aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/dd.c
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@novell.com>2006-10-07 15:55:55 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-12-01 17:51:58 -0500
commit1901fb2604fbcd53201f38725182ea807581159e (patch)
treef75e83294a9b4b4ba405e7ed39e941095f8729cf /drivers/base/dd.c
parent116af378201ef793424cd10508ccf18b06d8a021 (diff)
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>
Diffstat (limited to 'drivers/base/dd.c')
-rw-r--r--drivers/base/dd.c82
1 files changed, 52 insertions, 30 deletions
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 9c88b1e34bc..510e7884975 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -26,28 +26,12 @@
26#define to_drv(node) container_of(node, struct device_driver, kobj.entry) 26#define to_drv(node) container_of(node, struct device_driver, kobj.entry)
27 27
28 28
29/** 29static void driver_bound(struct device *dev)
30 * device_bind_driver - bind a driver to one device.
31 * @dev: device.
32 *
33 * Allow manual attachment of a driver to a device.
34 * Caller must have already set @dev->driver.
35 *
36 * Note that this does not modify the bus reference count
37 * nor take the bus's rwsem. Please verify those are accounted
38 * for before calling this. (It is ok to call with no other effort
39 * from a driver's probe() method.)
40 *
41 * This function must be called with @dev->sem held.
42 */
43int device_bind_driver(struct device *dev)
44{ 30{
45 int ret;
46
47 if (klist_node_attached(&dev->knode_driver)) { 31 if (klist_node_attached(&dev->knode_driver)) {
48 printk(KERN_WARNING "%s: device %s already bound\n", 32 printk(KERN_WARNING "%s: device %s already bound\n",
49 __FUNCTION__, kobject_name(&dev->kobj)); 33 __FUNCTION__, kobject_name(&dev->kobj));
50 return 0; 34 return;
51 } 35 }
52 36
53 pr_debug("bound device '%s' to driver '%s'\n", 37 pr_debug("bound device '%s' to driver '%s'\n",
@@ -58,6 +42,12 @@ int device_bind_driver(struct device *dev)
58 BUS_NOTIFY_BOUND_DRIVER, dev); 42 BUS_NOTIFY_BOUND_DRIVER, dev);
59 43
60 klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices); 44 klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
45}
46
47static int driver_sysfs_add(struct device *dev)
48{
49 int ret;
50
61 ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj, 51 ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj,
62 kobject_name(&dev->kobj)); 52 kobject_name(&dev->kobj));
63 if (ret == 0) { 53 if (ret == 0) {
@@ -70,6 +60,36 @@ int device_bind_driver(struct device *dev)
70 return ret; 60 return ret;
71} 61}
72 62
63static 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
73/**
74 * device_bind_driver - bind a driver to one device.
75 * @dev: device.
76 *
77 * Allow manual attachment of a driver to a device.
78 * Caller must have already set @dev->driver.
79 *
80 * Note that this does not modify the bus reference count
81 * nor take the bus's rwsem. Please verify those are accounted
82 * for before calling this. (It is ok to call with no other effort
83 * from a driver's probe() method.)
84 *
85 * This function must be called with @dev->sem held.
86 */
87int device_bind_driver(struct device *dev)
88{
89 driver_bound(dev);
90 return driver_sysfs_add(dev);
91}
92
73struct stupid_thread_structure { 93struct stupid_thread_structure {
74 struct device_driver *drv; 94 struct device_driver *drv;
75 struct device *dev; 95 struct device *dev;
@@ -90,30 +110,32 @@ static int really_probe(void *void_data)
90 drv->bus->name, drv->name, dev->bus_id); 110 drv->bus->name, drv->name, dev->bus_id);
91 111
92 dev->driver = drv; 112 dev->driver = drv;
113 if (driver_sysfs_add(dev)) {
114 printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
115 __FUNCTION__, dev->bus_id);
116 goto probe_failed;
117 }
118
93 if (dev->bus->probe) { 119 if (dev->bus->probe) {
94 ret = dev->bus->probe(dev); 120 ret = dev->bus->probe(dev);
95 if (ret) { 121 if (ret)
96 dev->driver = NULL;
97 goto probe_failed; 122 goto probe_failed;
98 }
99 } else if (drv->probe) { 123 } else if (drv->probe) {
100 ret = drv->probe(dev); 124 ret = drv->probe(dev);
101 if (ret) { 125 if (ret)
102 dev->driver = NULL;
103 goto probe_failed; 126 goto probe_failed;
104 }
105 }
106 if (device_bind_driver(dev)) {
107 printk(KERN_ERR "%s: device_bind_driver(%s) failed\n",
108 __FUNCTION__, dev->bus_id);
109 /* How does undo a ->probe? We're screwed. */
110 } 127 }
128
129 driver_bound(dev);
111 ret = 1; 130 ret = 1;
112 pr_debug("%s: Bound Device %s to Driver %s\n", 131 pr_debug("%s: Bound Device %s to Driver %s\n",
113 drv->bus->name, dev->bus_id, drv->name); 132 drv->bus->name, dev->bus_id, drv->name);
114 goto done; 133 goto done;
115 134
116probe_failed: 135probe_failed:
136 driver_sysfs_remove(dev);
137 dev->driver = NULL;
138
117 if (ret == -ENODEV || ret == -ENXIO) { 139 if (ret == -ENODEV || ret == -ENXIO) {
118 /* Driver matched, but didn't support device 140 /* Driver matched, but didn't support device
119 * or device not found. 141 * or device not found.
@@ -289,7 +311,7 @@ static void __device_release_driver(struct device * dev)
289 drv = dev->driver; 311 drv = dev->driver;
290 if (drv) { 312 if (drv) {
291 get_driver(drv); 313 get_driver(drv);
292 sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj)); 314 driver_sysfs_remove(dev);
293 sysfs_remove_link(&dev->kobj, "driver"); 315 sysfs_remove_link(&dev->kobj, "driver");
294 klist_remove(&dev->knode_driver); 316 klist_remove(&dev->knode_driver);
295 317