diff options
-rw-r--r-- | arch/sparc/include/asm/mdesc.h | 7 | ||||
-rw-r--r-- | arch/sparc/include/asm/vio.h | 2 | ||||
-rw-r--r-- | arch/sparc/kernel/mdesc.c | 88 | ||||
-rw-r--r-- | arch/sparc/kernel/vio.c | 22 |
4 files changed, 68 insertions, 51 deletions
diff --git a/arch/sparc/include/asm/mdesc.h b/arch/sparc/include/asm/mdesc.h index 68d19909d1cd..e8a4c413a1c7 100644 --- a/arch/sparc/include/asm/mdesc.h +++ b/arch/sparc/include/asm/mdesc.h | |||
@@ -63,9 +63,10 @@ u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc); | |||
63 | void mdesc_update(void); | 63 | void mdesc_update(void); |
64 | 64 | ||
65 | struct mdesc_notifier_client { | 65 | struct mdesc_notifier_client { |
66 | void (*add)(struct mdesc_handle *handle, u64 node); | 66 | void (*add)(struct mdesc_handle *handle, u64 node, |
67 | void (*remove)(struct mdesc_handle *handle, u64 node); | 67 | const char *node_name); |
68 | 68 | void (*remove)(struct mdesc_handle *handle, u64 node, | |
69 | const char *node_name); | ||
69 | const char *node_name; | 70 | const char *node_name; |
70 | struct mdesc_notifier_client *next; | 71 | struct mdesc_notifier_client *next; |
71 | }; | 72 | }; |
diff --git a/arch/sparc/include/asm/vio.h b/arch/sparc/include/asm/vio.h index 9dca7a892978..69cb3a5ff8cf 100644 --- a/arch/sparc/include/asm/vio.h +++ b/arch/sparc/include/asm/vio.h | |||
@@ -316,12 +316,14 @@ static inline u32 vio_dring_prev(struct vio_dring_state *dr, u32 index) | |||
316 | } | 316 | } |
317 | 317 | ||
318 | #define VIO_MAX_TYPE_LEN 32 | 318 | #define VIO_MAX_TYPE_LEN 32 |
319 | #define VIO_MAX_NAME_LEN 32 | ||
319 | #define VIO_MAX_COMPAT_LEN 64 | 320 | #define VIO_MAX_COMPAT_LEN 64 |
320 | 321 | ||
321 | struct vio_dev { | 322 | struct vio_dev { |
322 | u64 mp; | 323 | u64 mp; |
323 | struct device_node *dp; | 324 | struct device_node *dp; |
324 | 325 | ||
326 | char node_name[VIO_MAX_NAME_LEN]; | ||
325 | char type[VIO_MAX_TYPE_LEN]; | 327 | char type[VIO_MAX_TYPE_LEN]; |
326 | char compat[VIO_MAX_COMPAT_LEN]; | 328 | char compat[VIO_MAX_COMPAT_LEN]; |
327 | int compat_len; | 329 | int compat_len; |
diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index f0249691d000..04b76267ddfa 100644 --- a/arch/sparc/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c | |||
@@ -291,7 +291,7 @@ void mdesc_register_notifier(struct mdesc_notifier_client *client) | |||
291 | client_list = client; | 291 | client_list = client; |
292 | 292 | ||
293 | mdesc_for_each_node_by_name(cur_mdesc, node, client->node_name) | 293 | mdesc_for_each_node_by_name(cur_mdesc, node, client->node_name) |
294 | client->add(cur_mdesc, node); | 294 | client->add(cur_mdesc, node, client->node_name); |
295 | 295 | ||
296 | mutex_unlock(&mdesc_mutex); | 296 | mutex_unlock(&mdesc_mutex); |
297 | } | 297 | } |
@@ -399,55 +399,61 @@ static bool ds_port_node_match(union md_node_info *a_node_info, | |||
399 | static void invoke_on_missing(const char *name, | 399 | static void invoke_on_missing(const char *name, |
400 | struct mdesc_handle *a, | 400 | struct mdesc_handle *a, |
401 | struct mdesc_handle *b, | 401 | struct mdesc_handle *b, |
402 | void (*func)(struct mdesc_handle *, u64)) | 402 | void (*func)(struct mdesc_handle *, u64, |
403 | const char *node_name)) | ||
403 | { | 404 | { |
404 | u64 node; | 405 | mdesc_node_info_get_f get_info_func; |
406 | mdesc_node_info_rel_f rel_info_func; | ||
407 | mdesc_node_match_f node_match_func; | ||
408 | union md_node_info a_node_info; | ||
409 | union md_node_info b_node_info; | ||
410 | bool found; | ||
411 | u64 a_node; | ||
412 | u64 b_node; | ||
413 | int rv; | ||
405 | 414 | ||
406 | mdesc_for_each_node_by_name(a, node, name) { | 415 | /* |
407 | int found = 0, is_vdc_port = 0; | 416 | * Find the get_info, rel_info and node_match ops for the given |
408 | const char *name_prop; | 417 | * node name |
409 | const u64 *id; | 418 | */ |
410 | u64 fnode; | 419 | mdesc_get_node_ops(name, &get_info_func, &rel_info_func, |
411 | 420 | &node_match_func); | |
412 | name_prop = mdesc_get_property(a, node, "name", NULL); | 421 | |
413 | if (name_prop && !strcmp(name_prop, "vdc-port")) { | 422 | /* If we didn't find a match, the node type is not supported */ |
414 | is_vdc_port = 1; | 423 | if (!get_info_func || !rel_info_func || !node_match_func) { |
415 | id = parent_cfg_handle(a, node); | 424 | pr_err("MD: %s node type is not supported\n", name); |
416 | } else | 425 | return; |
417 | id = mdesc_get_property(a, node, "id", NULL); | 426 | } |
418 | 427 | ||
419 | if (!id) { | 428 | mdesc_for_each_node_by_name(a, a_node, name) { |
420 | printk(KERN_ERR "MD: Cannot find ID for %s node.\n", | 429 | found = false; |
421 | (name_prop ? name_prop : name)); | 430 | |
431 | rv = get_info_func(a, a_node, &a_node_info); | ||
432 | if (rv != 0) { | ||
433 | pr_err("MD: Cannot find 1 or more required match properties for %s node.\n", | ||
434 | name); | ||
422 | continue; | 435 | continue; |
423 | } | 436 | } |
424 | 437 | ||
425 | mdesc_for_each_node_by_name(b, fnode, name) { | 438 | /* Check each node in B for node matching a_node */ |
426 | const u64 *fid; | 439 | mdesc_for_each_node_by_name(b, b_node, name) { |
427 | 440 | rv = get_info_func(b, b_node, &b_node_info); | |
428 | if (is_vdc_port) { | 441 | if (rv != 0) |
429 | name_prop = mdesc_get_property(b, fnode, | 442 | continue; |
430 | "name", NULL); | 443 | |
431 | if (!name_prop || | 444 | if (node_match_func(&a_node_info, &b_node_info)) { |
432 | strcmp(name_prop, "vdc-port")) | 445 | found = true; |
433 | continue; | 446 | rel_info_func(&b_node_info); |
434 | fid = parent_cfg_handle(b, fnode); | ||
435 | if (!fid) { | ||
436 | printk(KERN_ERR "MD: Cannot find ID " | ||
437 | "for vdc-port node.\n"); | ||
438 | continue; | ||
439 | } | ||
440 | } else | ||
441 | fid = mdesc_get_property(b, fnode, | ||
442 | "id", NULL); | ||
443 | |||
444 | if (*id == *fid) { | ||
445 | found = 1; | ||
446 | break; | 447 | break; |
447 | } | 448 | } |
449 | |||
450 | rel_info_func(&b_node_info); | ||
448 | } | 451 | } |
452 | |||
453 | rel_info_func(&a_node_info); | ||
454 | |||
449 | if (!found) | 455 | if (!found) |
450 | func(a, node); | 456 | func(a, a_node, name); |
451 | } | 457 | } |
452 | } | 458 | } |
453 | 459 | ||
diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c index 075d38980dee..f37937b95dbf 100644 --- a/arch/sparc/kernel/vio.c +++ b/arch/sparc/kernel/vio.c | |||
@@ -219,6 +219,7 @@ int vio_set_intr(unsigned long dev_ino, int state) | |||
219 | EXPORT_SYMBOL(vio_set_intr); | 219 | EXPORT_SYMBOL(vio_set_intr); |
220 | 220 | ||
221 | static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, | 221 | static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, |
222 | const char *node_name, | ||
222 | struct device *parent) | 223 | struct device *parent) |
223 | { | 224 | { |
224 | const char *type, *compat, *bus_id_name; | 225 | const char *type, *compat, *bus_id_name; |
@@ -236,7 +237,7 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, | |||
236 | tlen = strlen(type) + 1; | 237 | tlen = strlen(type) + 1; |
237 | } | 238 | } |
238 | } | 239 | } |
239 | if (tlen > VIO_MAX_TYPE_LEN) { | 240 | if (tlen > VIO_MAX_TYPE_LEN || strlen(type) >= VIO_MAX_TYPE_LEN) { |
240 | printk(KERN_ERR "VIO: Type string [%s] is too long.\n", | 241 | printk(KERN_ERR "VIO: Type string [%s] is too long.\n", |
241 | type); | 242 | type); |
242 | return NULL; | 243 | return NULL; |
@@ -335,6 +336,11 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, | |||
335 | 336 | ||
336 | printk(KERN_INFO "VIO: Adding device %s\n", dev_name(&vdev->dev)); | 337 | printk(KERN_INFO "VIO: Adding device %s\n", dev_name(&vdev->dev)); |
337 | 338 | ||
339 | /* node_name is NULL for the parent/channel-devices node */ | ||
340 | if (node_name != NULL) | ||
341 | (void) snprintf(vdev->node_name, VIO_MAX_NAME_LEN, "%s", | ||
342 | node_name); | ||
343 | |||
338 | err = device_register(&vdev->dev); | 344 | err = device_register(&vdev->dev); |
339 | if (err) { | 345 | if (err) { |
340 | printk(KERN_ERR "VIO: Could not register device %s, err=%d\n", | 346 | printk(KERN_ERR "VIO: Could not register device %s, err=%d\n", |
@@ -349,9 +355,10 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, | |||
349 | return vdev; | 355 | return vdev; |
350 | } | 356 | } |
351 | 357 | ||
352 | static void vio_add(struct mdesc_handle *hp, u64 node) | 358 | static void vio_add(struct mdesc_handle *hp, u64 node, |
359 | const char *node_name) | ||
353 | { | 360 | { |
354 | (void) vio_create_one(hp, node, &root_vdev->dev); | 361 | (void) vio_create_one(hp, node, node_name, &root_vdev->dev); |
355 | } | 362 | } |
356 | 363 | ||
357 | struct vio_md_node_query { | 364 | struct vio_md_node_query { |
@@ -375,7 +382,7 @@ static int vio_md_node_match(struct device *dev, void *arg) | |||
375 | return 1; | 382 | return 1; |
376 | } | 383 | } |
377 | 384 | ||
378 | static void vio_remove(struct mdesc_handle *hp, u64 node) | 385 | static void vio_remove(struct mdesc_handle *hp, u64 node, const char *node_name) |
379 | { | 386 | { |
380 | const char *type; | 387 | const char *type; |
381 | const u64 *id, *cfg_handle; | 388 | const u64 *id, *cfg_handle; |
@@ -446,7 +453,8 @@ static struct mdesc_notifier_client vio_device_notifier = { | |||
446 | * under "openboot" that we should not mess with as aparently that is | 453 | * under "openboot" that we should not mess with as aparently that is |
447 | * reserved exclusively for OBP use. | 454 | * reserved exclusively for OBP use. |
448 | */ | 455 | */ |
449 | static void vio_add_ds(struct mdesc_handle *hp, u64 node) | 456 | static void vio_add_ds(struct mdesc_handle *hp, u64 node, |
457 | const char *node_name) | ||
450 | { | 458 | { |
451 | int found; | 459 | int found; |
452 | u64 a; | 460 | u64 a; |
@@ -463,7 +471,7 @@ static void vio_add_ds(struct mdesc_handle *hp, u64 node) | |||
463 | } | 471 | } |
464 | 472 | ||
465 | if (found) | 473 | if (found) |
466 | (void) vio_create_one(hp, node, &root_vdev->dev); | 474 | (void) vio_create_one(hp, node, node_name, &root_vdev->dev); |
467 | } | 475 | } |
468 | 476 | ||
469 | static struct mdesc_notifier_client vio_ds_notifier = { | 477 | static struct mdesc_notifier_client vio_ds_notifier = { |
@@ -530,7 +538,7 @@ static int __init vio_init(void) | |||
530 | 538 | ||
531 | cdev_cfg_handle = *cfg_handle; | 539 | cdev_cfg_handle = *cfg_handle; |
532 | 540 | ||
533 | root_vdev = vio_create_one(hp, root, NULL); | 541 | root_vdev = vio_create_one(hp, root, NULL, NULL); |
534 | err = -ENODEV; | 542 | err = -ENODEV; |
535 | if (!root_vdev) { | 543 | if (!root_vdev) { |
536 | printk(KERN_ERR "VIO: Could not create root device.\n"); | 544 | printk(KERN_ERR "VIO: Could not create root device.\n"); |