On Wed, Oct 17, 2018 at 4:41 PM Bart Van Assche <bvanass...@acm.org> 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 <ldun...@suse.com>
> Cc: Hannes Reinecke <h...@suse.com>
> Cc: Luis Chamberlain <mcg...@kernel.org>
> Cc: Johannes Thumshirn <jthumsh...@suse.de>
> Cc: Christoph Hellwig <h...@lst.de>
> Cc: Greg Kroah-Hartman <gre...@linuxfoundation.org>
> Cc: Dan Williams <dan.j.willi...@intel.com>
> Signed-off-by: Bart Van Assche <bvanass...@acm.org>
> ---
>  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
>

Reply via email to