[PATCH v2 3/7] drivers/base: Probe devices concurrently if requested by the driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Instead of probing devices sequentially in the PROBE_PREFER_ASYNCHRONOUS
mode, scan devices concurrently. This helps when the wall clock time for
a single probe is significantly above the CPU time needed for a single
probe, e.g. when scanning SCSI LUNs over a storage network.

Cc: Lee Duncan <lduncan@xxxxxxxx>
Cc: Hannes Reinecke <hare@xxxxxxxx>
Cc: Luis Chamberlain <mcgrof@xxxxxxxxxx>
Cc: Johannes Thumshirn <jthumshirn@xxxxxxx>
Cc: Christoph Hellwig <hch@xxxxxx>
Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
Cc: Dan Williams <dan.j.williams@xxxxxxxxx>
Signed-off-by: Bart Van Assche <bvanassche@xxxxxxx>
---
 drivers/base/bus.c |  3 +--
 drivers/base/dd.c  | 49 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 8bfd27ec73d6..18ca1178821f 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -696,8 +696,7 @@ int bus_add_driver(struct device_driver *drv)
 
 out_unregister:
 	kobject_put(&priv->kobj);
-	/* drv->p is freed in driver_release()  */
-	drv->p = NULL;
+
 out_put_bus:
 	bus_put(bus);
 	return error;
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 033382421351..f8d645aa09be 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -27,6 +27,7 @@
 #include <linux/async.h>
 #include <linux/pm_runtime.h>
 #include <linux/pinctrl/devinfo.h>
+#include <linux/slab.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -691,6 +692,49 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)
 	return ret;
 }
 
+struct driver_and_dev {
+	struct device_driver	*drv;
+	struct device		*dev;
+};
+
+static void __driver_probe_device_async(void *data, async_cookie_t cookie)
+{
+	struct driver_and_dev *dd = data;
+	struct device_driver *drv = dd->drv;
+	struct device *dev = dd->dev;
+
+	device_lock(dev);
+	driver_probe_device(drv, dev);
+	device_unlock(dev);
+	kobject_put(&drv->p->kobj);
+	module_put(drv->owner);
+	kfree(dd);
+}
+
+static void driver_probe_device_async(struct device_driver *drv,
+				      struct device *dev)
+{
+	struct driver_and_dev *dd;
+
+	if (!try_module_get(drv->owner))
+		return;
+	dd = kmalloc(sizeof(*dd), GFP_KERNEL);
+	if (!dd) {
+		/* If out of memory, scan synchronously. */
+		device_lock(dev);
+		driver_probe_device(drv, dev);
+		device_unlock(dev);
+		module_put(drv->owner);
+		return;
+	}
+	*dd = (struct driver_and_dev){
+		.drv = drv,
+		.dev = dev,
+	};
+	kobject_get(&drv->p->kobj);
+	async_schedule(__driver_probe_device_async, dd);
+}
+
 bool driver_allows_async_probing(struct device_driver *drv)
 {
 	switch (drv->probe_type) {
@@ -777,6 +821,11 @@ static int __device_attach_driver(struct device_driver *drv, void *_data)
 	if (data->check_async && async_allowed != data->want_async)
 		return 0;
 
+	if (data->check_async) {
+		driver_probe_device_async(drv, dev);
+		return 0;
+	}
+
 	return driver_probe_device(drv, dev);
 }
 
-- 
2.19.1.568.g152ad8e336-goog




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux