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 38518b0880739a5d2dded941e5b6cfbdb85c131d..3d0a1e6e9c489cb79647c54e28865e79cc733d4c 100644 (file)
@@ -459,8 +459,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
        found_target->reap_ref++;
        spin_unlock_irqrestore(shost->host_lock, flags);
        if (found_target->state != STARGET_DEL) {
-               put_device(parent);
-               kfree(starget);
+               put_device(dev);
                return found_target;
        }
        /* Unfortunately, we found a dying target; need to
@@ -493,19 +492,20 @@ void scsi_target_reap(struct scsi_target *starget)
        struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
        unsigned long flags;
        enum scsi_target_state state;
-       int empty;
+       int empty = 0;
 
        spin_lock_irqsave(shost->host_lock, flags);
        state = starget->state;
-       empty = --starget->reap_ref == 0 &&
-               list_empty(&starget->devices) ? 1 : 0;
+       if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
+               empty = 1;
+               starget->state = STARGET_DEL;
+       }
        spin_unlock_irqrestore(shost->host_lock, flags);
 
        if (!empty)
                return;
 
        BUG_ON(state == STARGET_DEL);
-       starget->state = STARGET_DEL;
        if (state == STARGET_CREATED)
                scsi_target_destroy(starget);
        else
@@ -1221,7 +1221,7 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget,
 }
 
 /**
- * scsilun_to_int: convert a scsi_lun to an int
+ * scsilun_to_int - convert a scsi_lun to an int
  * @scsilun:   struct scsi_lun to be converted.
  *
  * Description:
@@ -1253,7 +1253,7 @@ int scsilun_to_int(struct scsi_lun *scsilun)
 EXPORT_SYMBOL(scsilun_to_int);
 
 /**
- * int_to_scsilun: reverts an int into a scsi_lun
+ * int_to_scsilun - reverts an int into a scsi_lun
  * @lun:        integer to be reverted
  * @scsilun:   struct scsi_lun to be set.
  *
@@ -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);
 
@@ -1877,12 +1893,9 @@ void scsi_forget_host(struct Scsi_Host *shost)
        spin_unlock_irqrestore(shost->host_lock, flags);
 }
 
-/*
- * Function:    scsi_get_host_dev()
- *
- * Purpose:     Create a scsi_device that points to the host adapter itself.
- *
- * Arguments:   SHpnt   - Host that needs a scsi_device
+/**
+ * scsi_get_host_dev - Create a scsi_device that points to the host adapter itself
+ * @shost: Host that needs a scsi_device
  *
  * Lock status: None assumed.
  *
@@ -1895,7 +1908,7 @@ void scsi_forget_host(struct Scsi_Host *shost)
  *
  *     Note - this device is not accessible from any high-level
  *     drivers (including generics), which is probably not
- *     optimal.  We can add hooks later to attach 
+ *     optimal.  We can add hooks later to attach.
  */
 struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
 {
@@ -1921,18 +1934,13 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
 }
 EXPORT_SYMBOL(scsi_get_host_dev);
 
-/*
- * Function:    scsi_free_host_dev()
- *
- * Purpose:     Free a scsi_device that points to the host adapter itself.
- *
- * Arguments:   SHpnt   - Host that needs a scsi_device
+/**
+ * scsi_free_host_dev - Free a scsi_device that points to the host adapter itself
+ * @sdev: Host device to be freed
  *
  * Lock status: None assumed.
  *
  * Returns:     Nothing
- *
- * Notes:
  */
 void scsi_free_host_dev(struct scsi_device *sdev)
 {