[PATCH 2/36] Driver core: fix "driver" symlink timing
- From: Greg KH <greg@xxxxxxxxx>
- Date: Fri, 1 Dec 2006 15:21:32 -0800
From: Kay Sievers <kay.sievers@xxxxxxxxxx>
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@xxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>
---
drivers/base/dd.c | 82 +++++++++++++++++++++++++++++++++-------------------
1 files changed, 52 insertions(+), 30 deletions(-)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 9c88b1e..510e788 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -26,28 +26,12 @@
#define to_drv(node) container_of(node, struct device_driver, kobj.entry)
-/**
- * device_bind_driver - bind a driver to one device.
- * @dev: device.
- *
- * Allow manual attachment of a driver to a device.
- * Caller must have already set @dev->driver.
- *
- * Note that this does not modify the bus reference count
- * nor take the bus's rwsem. Please verify those are accounted
- * for before calling this. (It is ok to call with no other effort
- * from a driver's probe() method.)
- *
- * This function must be called with @dev->sem held.
- */
-int device_bind_driver(struct device *dev)
+static void driver_bound(struct device *dev)
{
- int ret;
-
if (klist_node_attached(&dev->knode_driver)) {
printk(KERN_WARNING "%s: device %s already bound\n",
__FUNCTION__, kobject_name(&dev->kobj));
- return 0;
+ return;
}
pr_debug("bound device '%s' to driver '%s'\n",
@@ -58,6 +42,12 @@ int device_bind_driver(struct device *de
BUS_NOTIFY_BOUND_DRIVER, dev);
klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
+}
+
+static int driver_sysfs_add(struct device *dev)
+{
+ int ret;
+
ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj,
kobject_name(&dev->kobj));
if (ret == 0) {
@@ -70,6 +60,36 @@ int device_bind_driver(struct device *de
return ret;
}
+static void driver_sysfs_remove(struct device *dev)
+{
+ struct device_driver *drv = dev->driver;
+
+ if (drv) {
+ sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
+ sysfs_remove_link(&dev->kobj, "driver");
+ }
+}
+
+/**
+ * device_bind_driver - bind a driver to one device.
+ * @dev: device.
+ *
+ * Allow manual attachment of a driver to a device.
+ * Caller must have already set @dev->driver.
+ *
+ * Note that this does not modify the bus reference count
+ * nor take the bus's rwsem. Please verify those are accounted
+ * for before calling this. (It is ok to call with no other effort
+ * from a driver's probe() method.)
+ *
+ * This function must be called with @dev->sem held.
+ */
+int device_bind_driver(struct device *dev)
+{
+ driver_bound(dev);
+ return driver_sysfs_add(dev);
+}
+
struct stupid_thread_structure {
struct device_driver *drv;
struct device *dev;
@@ -90,30 +110,32 @@ static int really_probe(void *void_data)
drv->bus->name, drv->name, dev->bus_id);
dev->driver = drv;
+ if (driver_sysfs_add(dev)) {
+ printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
+ __FUNCTION__, dev->bus_id);
+ goto probe_failed;
+ }
+
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
- if (ret) {
- dev->driver = NULL;
+ if (ret)
goto probe_failed;
- }
} else if (drv->probe) {
ret = drv->probe(dev);
- if (ret) {
- dev->driver = NULL;
+ if (ret)
goto probe_failed;
- }
- }
- if (device_bind_driver(dev)) {
- printk(KERN_ERR "%s: device_bind_driver(%s) failed\n",
- __FUNCTION__, dev->bus_id);
- /* How does undo a ->probe? We're screwed. */
}
+
+ driver_bound(dev);
ret = 1;
pr_debug("%s: Bound Device %s to Driver %s\n",
drv->bus->name, dev->bus_id, drv->name);
goto done;
probe_failed:
+ driver_sysfs_remove(dev);
+ dev->driver = NULL;
+
if (ret == -ENODEV || ret == -ENXIO) {
/* Driver matched, but didn't support device
* or device not found.
@@ -289,7 +311,7 @@ static void __device_release_driver(stru
drv = dev->driver;
if (drv) {
get_driver(drv);
- sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
+ driver_sysfs_remove(dev);
sysfs_remove_link(&dev->kobj, "driver");
klist_remove(&dev->knode_driver);
--
1.4.4.1
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
- Follow-Ups:
- References:
- [GIT PATCH] Driver core patches for 2.6.19
- From: Greg KH
- [PATCH 1/36] Driver core: add notification of bus events
- From: Greg KH
- [GIT PATCH] Driver core patches for 2.6.19
- Prev by Date: [PATCH 28/36] cpu topology: consider sysfs_create_group return value
- Next by Date: [PATCH 32/36] driver core: Introduce device_move(): move a device to a new parent.
- Previous by thread: [PATCH 1/36] Driver core: add notification of bus events
- Next by thread: [PATCH 3/36] Driver Core: Move virtual_device_parent() to core.c
- Index(es):
Relevant Pages
|