On Wed, Oct 17, 2018 at 4:41 PM Bart Van Assche <bvanassche@xxxxxxx> wrote: > > 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. Alex had a similar patch here [1] that I don't think has been accepted yet, in any event some collaboration is needed: [1]: https://lkml.org/lkml/2018/9/27/14 > > 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 >