As explained during the 2018 LSF/MM session about increasing SCSI disk
probing concurrency, the problems with the current probing approach are as
follows:
- The driver core is unaware of asynchronous SCSI LUN probing.
  wait_for_device_probe() waits for all asynchronous probes except
  asynchronous SCSI disk probes.
- There is unnecessary serialization between sd_probe() and sd_remove().
  This can lead to a deadlock.
Hence this patch that modifies the sd driver such that it uses the driver
core framework for asynchronous probing. The async domains and
get_device()/put_device() pairs that became superfluous due to this change
are removed.
This patch does not affect the time needed for loading the scsi_debug
kernel module with parameters delay=0 and max_luns=256.
This patch depends on commit 
ef0ff68351be ("driver core: Probe devices
asynchronously instead of the driver") that went upstream in kernel version
v5.1-rc1.
Cc: Lee Duncan <lduncan@suse.com>
Cc: Hannes Reinecke <hare@suse.com>
Cc: Luis Chamberlain <mcgrof@kernel.org>
Cc: Johannes Thumshirn <jthumshirn@suse.de>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
 EXPORT_SYMBOL(scsi_logging_level);
 #endif
 
-/* sd, scsi core and power management need to coordinate flushing async actions */
-ASYNC_DOMAIN(scsi_sd_probe_domain);
-EXPORT_SYMBOL(scsi_sd_probe_domain);
-
-/*
- * Separate domain (from scsi_sd_probe_domain) to maximize the benefit of
- * asynchronous system resume operations.  It is marked 'exclusive' to avoid
- * being included in the async_synchronize_full() that is invoked by
- * dpm_resume()
- */
-ASYNC_DOMAIN_EXCLUSIVE(scsi_sd_pm_domain);
-EXPORT_SYMBOL(scsi_sd_pm_domain);
-
 /**
  * scsi_put_command - Free a scsi command block
  * @cmd: command block to free
        scsi_exit_devinfo();
        scsi_exit_procfs();
        scsi_exit_queue();
-       async_unregister_domain(&scsi_sd_probe_domain);
 }
 
 subsys_initcall(init_scsi);
 
        const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
        int err;
 
-       /* flush pending in-flight resume operations, suspend is synchronous */
-       async_synchronize_full_domain(&scsi_sd_pm_domain);
-
        err = scsi_device_quiesce(to_scsi_device(dev));
        if (err == 0) {
                err = cb(dev, pm);
        else
                fn = NULL;
 
-       if (fn) {
-               async_schedule_domain(fn, dev, &scsi_sd_pm_domain);
-
-               /*
-                * If a user has disabled async probing a likely reason
-                * is due to a storage enclosure that does not inject
-                * staggered spin-ups.  For safety, make resume
-                * synchronous as well in that case.
-                */
-               if (strncmp(scsi_scan_type, "async", 5) != 0)
-                       async_synchronize_full_domain(&scsi_sd_pm_domain);
-       } else {
+       if (!fn) {
                pm_runtime_disable(dev);
                pm_runtime_set_active(dev);
                pm_runtime_enable(dev);
 
 static int scsi_bus_prepare(struct device *dev)
 {
-       if (scsi_is_sdev_device(dev)) {
-               /* sd probing uses async_schedule.  Wait until it finishes. */
-               async_synchronize_full_domain(&scsi_sd_probe_domain);
-
-       } else if (scsi_is_host_device(dev)) {
+       if (scsi_is_host_device(dev)) {
                /* Wait until async scanning is finished */
                scsi_complete_async_scans();
        }
 
 static inline void scsi_autopm_put_host(struct Scsi_Host *h) {}
 #endif /* CONFIG_PM */
 
-extern struct async_domain scsi_sd_pm_domain;
-extern struct async_domain scsi_sd_probe_domain;
-
 /* scsi_dh.c */
 #ifdef CONFIG_SCSI_DH
 void scsi_dh_add_device(struct scsi_device *sdev);
 
                .name           = "sd",
                .owner          = THIS_MODULE,
                .probe          = sd_probe,
+               .probe_type     = PROBE_PREFER_ASYNCHRONOUS,
                .remove         = sd_remove,
                .shutdown       = sd_shutdown,
                .pm             = &sd_pm_ops,
        return 0;
 }
 
-/*
- * The asynchronous part of sd_probe
- */
-static void sd_probe_async(void *data, async_cookie_t cookie)
+static void sd_probe_part2(struct scsi_disk *sdkp)
 {
-       struct scsi_disk *sdkp = data;
        struct scsi_device *sdp;
        struct gendisk *gd;
        u32 index;
        sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
                  sdp->removable ? "removable " : "");
        scsi_autopm_put_device(sdp);
-       put_device(&sdkp->dev);
 }
 
 /**
        get_device(dev);
        dev_set_drvdata(dev, sdkp);
 
-       get_device(&sdkp->dev); /* prevent release before async_schedule */
-       async_schedule_domain(sd_probe_async, sdkp, &scsi_sd_probe_domain);
+       sd_probe_part2(sdkp);
 
        return 0;
 
        devt = disk_devt(sdkp->disk);
        scsi_autopm_get_device(sdkp->device);
 
-       async_synchronize_full_domain(&scsi_sd_pm_domain);
-       async_synchronize_full_domain(&scsi_sd_probe_domain);
        device_del(&sdkp->dev);
        del_gendisk(sdkp->disk);
        sd_shutdown(dev);