aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/dd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/dd.c')
-rw-r--r--drivers/base/dd.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 6f85280fef8d..7941a8fd2284 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -818,6 +818,11 @@ static int __device_attach_driver(struct device_driver *drv, void *_data)
} else if (ret == -EPROBE_DEFER) {
dev_dbg(dev, "Device match requests probe deferral\n");
driver_deferred_probe_add(dev);
+ /*
+ * Device can't match with a driver right now, so don't attempt
+ * to match or bind with other drivers on the bus.
+ */
+ return ret;
} else if (ret < 0) {
dev_dbg(dev, "Bus failed to match device: %d", ret);
return ret;
@@ -1037,6 +1042,7 @@ static void __driver_attach_async_helper(void *_dev, async_cookie_t cookie)
static int __driver_attach(struct device *dev, void *data)
{
struct device_driver *drv = data;
+ bool async = false;
int ret;
/*
@@ -1056,9 +1062,18 @@ static int __driver_attach(struct device *dev, void *data)
} else if (ret == -EPROBE_DEFER) {
dev_dbg(dev, "Device match requests probe deferral\n");
driver_deferred_probe_add(dev);
+ /*
+ * Driver could not match with device, but may match with
+ * another device on the bus.
+ */
+ return 0;
} else if (ret < 0) {
- dev_dbg(dev, "Bus failed to match device: %d", ret);
- return ret;
+ dev_dbg(dev, "Bus failed to match device: %d\n", ret);
+ /*
+ * Driver could not match with device, but may match with
+ * another device on the bus.
+ */
+ return 0;
} /* ret > 0 means positive match */
if (driver_allows_async_probing(drv)) {
@@ -1074,9 +1089,11 @@ static int __driver_attach(struct device *dev, void *data)
if (!dev->driver) {
get_device(dev);
dev->p->async_driver = drv;
- async_schedule_dev(__driver_attach_async_helper, dev);
+ async = true;
}
device_unlock(dev);
+ if (async)
+ async_schedule_dev(__driver_attach_async_helper, dev);
return 0;
}
@@ -1145,8 +1162,6 @@ static void __device_release_driver(struct device *dev, struct device *parent)
else if (drv->remove)
drv->remove(dev);
- device_links_driver_cleanup(dev);
-
devres_release_all(dev);
arch_teardown_dma_ops(dev);
dev->driver = NULL;
@@ -1156,6 +1171,8 @@ static void __device_release_driver(struct device *dev, struct device *parent)
pm_runtime_reinit(dev);
dev_pm_set_driver_flags(dev, 0);
+ device_links_driver_cleanup(dev);
+
klist_remove(&dev->p->knode_driver);
device_pm_check_callbacks(dev);
if (dev->bus)