aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sparc/include/asm/mdesc.h7
-rw-r--r--arch/sparc/include/asm/vio.h2
-rw-r--r--arch/sparc/kernel/mdesc.c88
-rw-r--r--arch/sparc/kernel/vio.c22
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);
63void mdesc_update(void); 63void mdesc_update(void);
64 64
65struct mdesc_notifier_client { 65struct 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
321struct vio_dev { 322struct 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,
399static void invoke_on_missing(const char *name, 399static 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)
219EXPORT_SYMBOL(vio_set_intr); 219EXPORT_SYMBOL(vio_set_intr);
220 220
221static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, 221static 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
352static void vio_add(struct mdesc_handle *hp, u64 node) 358static 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
357struct vio_md_node_query { 364struct 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
378static void vio_remove(struct mdesc_handle *hp, u64 node) 385static 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 */
449static void vio_add_ds(struct mdesc_handle *hp, u64 node) 456static 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
469static struct mdesc_notifier_client vio_ds_notifier = { 477static 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");