diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2006-10-23 19:37:58 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-12-01 17:51:58 -0500 |
commit | 40fa54226f518a9bc97ed1d711c0016e416e3782 (patch) | |
tree | fd1a432e23b847e831564e13bb93956b07329b23 | |
parent | 88a22c985e3545c55c9779971007f0f29f912519 (diff) |
Driver core: make old versions of udev work properly
If CONFIG_SYSFS_DEPRECATED is enabled, old versions of udev will work
properly with devices that are associated with a class.
Cc: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/base/core.c | 59 |
1 files changed, 45 insertions, 14 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index dbcd40b987d2..8f8347b9197f 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -384,6 +384,19 @@ void device_initialize(struct device *dev) | |||
384 | device_init_wakeup(dev, 0); | 384 | device_init_wakeup(dev, 0); |
385 | } | 385 | } |
386 | 386 | ||
387 | #ifdef CONFIG_SYSFS_DEPRECATED | ||
388 | int setup_parent(struct device *dev, struct device *parent) | ||
389 | { | ||
390 | /* Set the parent to the class, not the parent device */ | ||
391 | /* this keeps sysfs from having a symlink to make old udevs happy */ | ||
392 | if (dev->class) | ||
393 | dev->kobj.parent = &dev->class->subsys.kset.kobj; | ||
394 | else if (parent) | ||
395 | dev->kobj.parent = &parent->kobj; | ||
396 | |||
397 | return 0; | ||
398 | } | ||
399 | #else | ||
387 | static int virtual_device_parent(struct device *dev) | 400 | static int virtual_device_parent(struct device *dev) |
388 | { | 401 | { |
389 | if (!dev->class) | 402 | if (!dev->class) |
@@ -401,6 +414,22 @@ static int virtual_device_parent(struct device *dev) | |||
401 | return 0; | 414 | return 0; |
402 | } | 415 | } |
403 | 416 | ||
417 | int setup_parent(struct device *dev, struct device *parent) | ||
418 | { | ||
419 | int error; | ||
420 | |||
421 | /* if this is a class device, and has no parent, create one */ | ||
422 | if ((dev->class) && (parent == NULL)) { | ||
423 | error = virtual_device_parent(dev); | ||
424 | if (error) | ||
425 | return error; | ||
426 | } else if (parent) | ||
427 | dev->kobj.parent = &parent->kobj; | ||
428 | |||
429 | return 0; | ||
430 | } | ||
431 | #endif | ||
432 | |||
404 | /** | 433 | /** |
405 | * device_add - add device to device hierarchy. | 434 | * device_add - add device to device hierarchy. |
406 | * @dev: device. | 435 | * @dev: device. |
@@ -423,23 +452,18 @@ int device_add(struct device *dev) | |||
423 | if (!dev || !strlen(dev->bus_id)) | 452 | if (!dev || !strlen(dev->bus_id)) |
424 | goto Error; | 453 | goto Error; |
425 | 454 | ||
426 | /* if this is a class device, and has no parent, create one */ | 455 | pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id); |
427 | if ((dev->class) && (dev->parent == NULL)) { | ||
428 | error = virtual_device_parent(dev); | ||
429 | if (error) | ||
430 | goto Error; | ||
431 | } | ||
432 | 456 | ||
433 | parent = get_device(dev->parent); | 457 | parent = get_device(dev->parent); |
434 | 458 | ||
435 | pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id); | 459 | error = setup_parent(dev, parent); |
460 | if (error) | ||
461 | goto Error; | ||
436 | 462 | ||
437 | /* first, register with generic layer. */ | 463 | /* first, register with generic layer. */ |
438 | kobject_set_name(&dev->kobj, "%s", dev->bus_id); | 464 | kobject_set_name(&dev->kobj, "%s", dev->bus_id); |
439 | if (parent) | 465 | error = kobject_add(&dev->kobj); |
440 | dev->kobj.parent = &parent->kobj; | 466 | if (error) |
441 | |||
442 | if ((error = kobject_add(&dev->kobj))) | ||
443 | goto Error; | 467 | goto Error; |
444 | 468 | ||
445 | /* notify platform of device entry */ | 469 | /* notify platform of device entry */ |
@@ -484,8 +508,11 @@ int device_add(struct device *dev) | |||
484 | if (dev->class) { | 508 | if (dev->class) { |
485 | sysfs_create_link(&dev->kobj, &dev->class->subsys.kset.kobj, | 509 | sysfs_create_link(&dev->kobj, &dev->class->subsys.kset.kobj, |
486 | "subsystem"); | 510 | "subsystem"); |
487 | sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj, | 511 | /* If this is not a "fake" compatible device, then create the |
488 | dev->bus_id); | 512 | * symlink from the class to the device. */ |
513 | if (dev->kobj.parent != &dev->class->subsys.kset.kobj) | ||
514 | sysfs_create_link(&dev->class->subsys.kset.kobj, | ||
515 | &dev->kobj, dev->bus_id); | ||
489 | if (parent) { | 516 | if (parent) { |
490 | sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device"); | 517 | sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device"); |
491 | class_name = make_class_name(dev->class->name, &dev->kobj); | 518 | class_name = make_class_name(dev->class->name, &dev->kobj); |
@@ -623,7 +650,11 @@ void device_del(struct device * dev) | |||
623 | } | 650 | } |
624 | if (dev->class) { | 651 | if (dev->class) { |
625 | sysfs_remove_link(&dev->kobj, "subsystem"); | 652 | sysfs_remove_link(&dev->kobj, "subsystem"); |
626 | sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id); | 653 | /* If this is not a "fake" compatible device, remove the |
654 | * symlink from the class to the device. */ | ||
655 | if (dev->kobj.parent != &dev->class->subsys.kset.kobj) | ||
656 | sysfs_remove_link(&dev->class->subsys.kset.kobj, | ||
657 | dev->bus_id); | ||
627 | class_name = make_class_name(dev->class->name, &dev->kobj); | 658 | class_name = make_class_name(dev->class->name, &dev->kobj); |
628 | if (parent) { | 659 | if (parent) { |
629 | sysfs_remove_link(&dev->kobj, "device"); | 660 | sysfs_remove_link(&dev->kobj, "device"); |