Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / drivers / scsi / scsi_scan.c
index 1c027a97d8b9ea570d0a48d254908a71cfe84377..3d0a1e6e9c489cb79647c54e28865e79cc733d4c 100644 (file)
@@ -1513,14 +1513,18 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
        starget = scsi_alloc_target(parent, channel, id);
        if (!starget)
                return ERR_PTR(-ENOMEM);
+       scsi_autopm_get_target(starget);
 
        mutex_lock(&shost->scan_mutex);
        if (!shost->async_scan)
                scsi_complete_async_scans();
 
-       if (scsi_host_scan_allowed(shost))
+       if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) {
                scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
+               scsi_autopm_put_host(shost);
+       }
        mutex_unlock(&shost->scan_mutex);
+       scsi_autopm_put_target(starget);
        scsi_target_reap(starget);
        put_device(&starget->dev);
 
@@ -1574,6 +1578,7 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel,
        starget = scsi_alloc_target(parent, channel, id);
        if (!starget)
                return;
+       scsi_autopm_get_target(starget);
 
        if (lun != SCAN_WILD_CARD) {
                /*
@@ -1599,6 +1604,7 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel,
        }
 
  out_reap:
+       scsi_autopm_put_target(starget);
        /* now determine if the target has any children at all
         * and if not, nuke it */
        scsi_target_reap(starget);
@@ -1633,8 +1639,10 @@ void scsi_scan_target(struct device *parent, unsigned int channel,
        if (!shost->async_scan)
                scsi_complete_async_scans();
 
-       if (scsi_host_scan_allowed(shost))
+       if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) {
                __scsi_scan_target(parent, channel, id, lun, rescan);
+               scsi_autopm_put_host(shost);
+       }
        mutex_unlock(&shost->scan_mutex);
 }
 EXPORT_SYMBOL(scsi_scan_target);
@@ -1686,7 +1694,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
        if (!shost->async_scan)
                scsi_complete_async_scans();
 
-       if (scsi_host_scan_allowed(shost)) {
+       if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) {
                if (channel == SCAN_WILD_CARD)
                        for (channel = 0; channel <= shost->max_channel;
                             channel++)
@@ -1694,6 +1702,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
                                                  rescan);
                else
                        scsi_scan_channel(shost, channel, id, lun, rescan);
+               scsi_autopm_put_host(shost);
        }
        mutex_unlock(&shost->scan_mutex);
 
@@ -1831,8 +1840,11 @@ static void do_scsi_scan_host(struct Scsi_Host *shost)
 static int do_scan_async(void *_data)
 {
        struct async_scan_data *data = _data;
-       do_scsi_scan_host(data->shost);
+       struct Scsi_Host *shost = data->shost;
+
+       do_scsi_scan_host(shost);
        scsi_finish_async_scan(data);
+       scsi_autopm_put_host(shost);
        return 0;
 }
 
@@ -1847,16 +1859,20 @@ void scsi_scan_host(struct Scsi_Host *shost)
 
        if (strncmp(scsi_scan_type, "none", 4) == 0)
                return;
+       if (scsi_autopm_get_host(shost) < 0)
+               return;
 
        data = scsi_prep_async_scan(shost);
        if (!data) {
                do_scsi_scan_host(shost);
+               scsi_autopm_put_host(shost);
                return;
        }
 
        p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no);
        if (IS_ERR(p))
                do_scan_async(data);
+       /* scsi_autopm_put_host(shost) is called in do_scan_async() */
 }
 EXPORT_SYMBOL(scsi_scan_host);