summaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2011-04-12 19:05:37 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2011-04-22 17:06:29 -0700
commit8497d6a21c4b17052e868bd53a74c82b557a6c46 (patch)
treef20b4098f8811a0dc7790a26150c969e5ae2ae80 /drivers/base
parentfc2711992b8601c20b7cc078f533e55c3106fbd4 (diff)
driver-core: fix race between device_register and driver_register
When a device is registered to a bus it will be a) added to the list of devices of the bus and b) bind to a driver (if one matches). As a result of a driver being registered at this bus between a) and b) this device could already be bound to a driver. This leads to a warning and incorrect refcounting. To fix this add a check to device_attach to identify an already bound device. Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/dd.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index da57ee9d63f..7e9219b0279 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -245,6 +245,10 @@ int device_attach(struct device *dev)
device_lock(dev);
if (dev->driver) {
+ if (klist_node_attached(&dev->p->knode_driver)) {
+ ret = 1;
+ goto out_unlock;
+ }
ret = device_bind_driver(dev);
if (ret == 0)
ret = 1;
@@ -257,6 +261,7 @@ int device_attach(struct device *dev)
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
pm_runtime_put_sync(dev);
}
+out_unlock:
device_unlock(dev);
return ret;
}