[PATCH 2/36] Driver core: fix "driver" symlink timing



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/



Relevant Pages

  • [PATCH 37 of 39] IB/ipath - namespace cleanup: replace ips with ipath
    ... - * part of a QLogic release, or from the driver from OpenIB, kernel.org, ... +struct ipath_message_header { ... int ret; ... goto bail; ...
    (Linux-Kernel)
  • [PATCH v2] v4l2_device/v4l2_subdev: final (?) version
    ... +Overview of the V4L2 driver framework ... +1) A struct for each device instance containing the device state. ... +of which only a handful of ops are commonly implemented, ... +may be NULL if the subdev driver does not support anything from that category. ...
    (Linux-Kernel)
  • [PATCH 40/61] driver-core: make devt_attr and uevent_attr static
    ... embedded in device and class_device as they needed their owner field ... set to the module implementing the driver. ... immediate disconnect and owner field removed from struct attribute, ... goto out3; ...
    (Linux-Kernel)
  • [PATCH] [TRIVIAL] Fixing occurrences of "the the "
    ... Registering a driver using platform_driver_probeworks just like ... Free all pages associated with DMA buffers, the buffers and pages lists, and ... * hw - Struct containing variables accessed by shared code ... * This option is used to tune the the maximum retransmission attempts ...
    (Linux-Kernel)
  • Re: [PATCH] [TRIVIAL] Fixing occurrences of "the the "
    ... Registering a driver using platform_driver_probeworks just like ... Free all pages associated with DMA buffers, the buffers and pages lists, and ... * hw - Struct containing variables accessed by shared code ... * This option is used to tune the the maximum retransmission attempts ...
    (Linux-Kernel)