Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Driver core: fix "driver" symlink timing

Create the "driver" link before the child device may be created by
the probing logic. This makes it possible for userspace (udev), to
determine the driver property of the parent device, at the time the
child device is created.

Signed-off-by: Kay Sievers <kay.sievers@novell.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Kay Sievers and committed by
Greg Kroah-Hartman
1901fb26 116af378

+60 -38
+60 -38
drivers/base/dd.c
··· 26 26 #define to_drv(node) container_of(node, struct device_driver, kobj.entry) 27 27 28 28 29 + static void driver_bound(struct device *dev) 30 + { 31 + if (klist_node_attached(&dev->knode_driver)) { 32 + printk(KERN_WARNING "%s: device %s already bound\n", 33 + __FUNCTION__, kobject_name(&dev->kobj)); 34 + return; 35 + } 36 + 37 + pr_debug("bound device '%s' to driver '%s'\n", 38 + dev->bus_id, dev->driver->name); 39 + 40 + if (dev->bus) 41 + blocking_notifier_call_chain(&dev->bus->bus_notifier, 42 + BUS_NOTIFY_BOUND_DRIVER, dev); 43 + 44 + klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices); 45 + } 46 + 47 + static int driver_sysfs_add(struct device *dev) 48 + { 49 + int ret; 50 + 51 + ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj, 52 + kobject_name(&dev->kobj)); 53 + if (ret == 0) { 54 + ret = sysfs_create_link(&dev->kobj, &dev->driver->kobj, 55 + "driver"); 56 + if (ret) 57 + sysfs_remove_link(&dev->driver->kobj, 58 + kobject_name(&dev->kobj)); 59 + } 60 + return ret; 61 + } 62 + 63 + static void driver_sysfs_remove(struct device *dev) 64 + { 65 + struct device_driver *drv = dev->driver; 66 + 67 + if (drv) { 68 + sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj)); 69 + sysfs_remove_link(&dev->kobj, "driver"); 70 + } 71 + } 72 + 29 73 /** 30 74 * device_bind_driver - bind a driver to one device. 31 75 * @dev: device. ··· 86 42 */ 87 43 int device_bind_driver(struct device *dev) 88 44 { 89 - int ret; 90 - 91 - if (klist_node_attached(&dev->knode_driver)) { 92 - printk(KERN_WARNING "%s: device %s already bound\n", 93 - __FUNCTION__, kobject_name(&dev->kobj)); 94 - return 0; 95 - } 96 - 97 - pr_debug("bound device '%s' to driver '%s'\n", 98 - dev->bus_id, dev->driver->name); 99 - 100 - if (dev->bus) 101 - blocking_notifier_call_chain(&dev->bus->bus_notifier, 102 - BUS_NOTIFY_BOUND_DRIVER, dev); 103 - 104 - klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices); 105 - ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj, 106 - kobject_name(&dev->kobj)); 107 - if (ret == 0) { 108 - ret = sysfs_create_link(&dev->kobj, &dev->driver->kobj, 109 - "driver"); 110 - if (ret) 111 - sysfs_remove_link(&dev->driver->kobj, 112 - kobject_name(&dev->kobj)); 113 - } 114 - return ret; 45 + driver_bound(dev); 46 + return driver_sysfs_add(dev); 115 47 } 116 48 117 49 struct stupid_thread_structure { ··· 110 90 drv->bus->name, drv->name, dev->bus_id); 111 91 112 92 dev->driver = drv; 93 + if (driver_sysfs_add(dev)) { 94 + printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n", 95 + __FUNCTION__, dev->bus_id); 96 + goto probe_failed; 97 + } 98 + 113 99 if (dev->bus->probe) { 114 100 ret = dev->bus->probe(dev); 115 - if (ret) { 116 - dev->driver = NULL; 101 + if (ret) 117 102 goto probe_failed; 118 - } 119 103 } else if (drv->probe) { 120 104 ret = drv->probe(dev); 121 - if (ret) { 122 - dev->driver = NULL; 105 + if (ret) 123 106 goto probe_failed; 124 - } 125 107 } 126 - if (device_bind_driver(dev)) { 127 - printk(KERN_ERR "%s: device_bind_driver(%s) failed\n", 128 - __FUNCTION__, dev->bus_id); 129 - /* How does undo a ->probe? We're screwed. */ 130 - } 108 + 109 + driver_bound(dev); 131 110 ret = 1; 132 111 pr_debug("%s: Bound Device %s to Driver %s\n", 133 112 drv->bus->name, dev->bus_id, drv->name); 134 113 goto done; 135 114 136 115 probe_failed: 116 + driver_sysfs_remove(dev); 117 + dev->driver = NULL; 118 + 137 119 if (ret == -ENODEV || ret == -ENXIO) { 138 120 /* Driver matched, but didn't support device 139 121 * or device not found. ··· 311 289 drv = dev->driver; 312 290 if (drv) { 313 291 get_driver(drv); 314 - sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj)); 292 + driver_sysfs_remove(dev); 315 293 sysfs_remove_link(&dev->kobj, "driver"); 316 294 klist_remove(&dev->knode_driver); 317 295