Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[pandora-kernel.git] / drivers / scsi / scsi_scan.c
index 327c5d7..05ebb9c 100644 (file)
@@ -9,7 +9,7 @@
  * global variable (boot or module load time) settings.
  *
  * A specific LUN is scanned via an INQUIRY command; if the LUN has a
- * device attached, a Scsi_Device is allocated and setup for it.
+ * device attached, a scsi_device is allocated and setup for it.
  *
  * For every id of every channel on the given host:
  *
@@ -17,7 +17,7 @@
  *     device or storage attached to LUN 0):
  *
  *             If LUN 0 has a device attached, allocate and setup a
- *             Scsi_Device for it.
+ *             scsi_device for it.
  *
  *             If target is SCSI-3 or up, issue a REPORT LUN, and scan
  *             all of the LUNs returned by the REPORT LUN; else,
@@ -74,7 +74,7 @@
 #define SCSI_SCAN_TARGET_PRESENT       1
 #define SCSI_SCAN_LUN_PRESENT          2
 
-static char *scsi_null_device_strs = "nullnullnullnull";
+static const char *scsi_null_device_strs = "nullnullnullnull";
 
 #define MAX_SCSI_LUNS  512
 
@@ -266,8 +266,6 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
                        /*
                         * if LLDD reports slave not present, don't clutter
                         * console with alloc failure messages
-
-
                         */
                        if (ret == -ENXIO)
                                display_failure_msg = 0;
@@ -279,7 +277,6 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
 
 out_device_destroy:
        transport_destroy_device(&sdev->sdev_gendev);
-       scsi_free_queue(sdev->request_queue);
        put_device(&sdev->sdev_gendev);
 out:
        if (display_failure_msg)
@@ -403,6 +400,36 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
        return found_target;
 }
 
+struct work_queue_wrapper {
+       struct work_struct      work;
+       struct scsi_target      *starget;
+};
+
+static void scsi_target_reap_work(void *data) {
+       struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
+       struct scsi_target *starget = wqw->starget;
+       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+       unsigned long flags;
+
+       kfree(wqw);
+
+       spin_lock_irqsave(shost->host_lock, flags);
+
+       if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
+               list_del_init(&starget->siblings);
+               spin_unlock_irqrestore(shost->host_lock, flags);
+               transport_remove_device(&starget->dev);
+               device_del(&starget->dev);
+               transport_destroy_device(&starget->dev);
+               put_device(&starget->dev);
+               return;
+
+       }
+       spin_unlock_irqrestore(shost->host_lock, flags);
+
+       return;
+}
+
 /**
  * scsi_target_reap - check to see if target is in use and destroy if not
  *
@@ -414,19 +441,18 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
  */
 void scsi_target_reap(struct scsi_target *starget)
 {
-       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-       unsigned long flags;
-       spin_lock_irqsave(shost->host_lock, flags);
+       struct work_queue_wrapper *wqw = 
+               kzalloc(sizeof(struct work_queue_wrapper), GFP_ATOMIC);
 
-       if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
-               list_del_init(&starget->siblings);
-               spin_unlock_irqrestore(shost->host_lock, flags);
-               device_del(&starget->dev);
-               transport_unregister_device(&starget->dev);
-               put_device(&starget->dev);
+       if (!wqw) {
+               starget_printk(KERN_ERR, starget,
+                              "Failed to allocate memory in scsi_reap_target()\n");
                return;
        }
-       spin_unlock_irqrestore(shost->host_lock, flags);
+
+       INIT_WORK(&wqw->work, scsi_target_reap_work, wqw);
+       wqw->starget = starget;
+       schedule_work(&wqw->work);
 }
 
 /**
@@ -441,7 +467,7 @@ void scsi_target_reap(struct scsi_target *starget)
  *
  *     If the INQUIRY is successful, zero is returned and the
  *     INQUIRY data is in @inq_result; the scsi_level and INQUIRY length
- *     are copied to the Scsi_Device any flags value is stored in *@bflags.
+ *     are copied to the scsi_device any flags value is stored in *@bflags.
  **/
 static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result,
                          int result_len, int *bflags)
@@ -462,10 +488,9 @@ static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result,
        pass = 1;
 
  next_pass:
-       SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY pass %d "
-                       "to host %d channel %d id %d lun %d, length %d\n",
-                       pass, sdev->host->host_no, sdev->channel,
-                       sdev->id, sdev->lun, try_inquiry_len));
+       SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev,
+                               "scsi scan: INQUIRY pass %d length %d\n",
+                               pass, try_inquiry_len));
 
        /* Each pass gets up to three chances to ignore Unit Attention */
        for (count = 0; count < 3; ++count) {
@@ -510,8 +535,8 @@ static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result,
                /*
                 * Get any flags for this device.
                 *
-                * XXX add a bflags to Scsi_Device, and replace the
-                * corresponding bit fields in Scsi_Device, so bflags
+                * XXX add a bflags to scsi_device, and replace the
+                * corresponding bit fields in scsi_device, so bflags
                 * need not be passed as an argument.
                 */
                *bflags = scsi_get_device_flags(sdev, &inq_result[8],
@@ -593,21 +618,21 @@ static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result,
 }
 
 /**
- * scsi_add_lun - allocate and fully initialze a Scsi_Device
- * @sdevscan:  holds information to be stored in the new Scsi_Device
- * @sdevnew:   store the address of the newly allocated Scsi_Device
+ * scsi_add_lun - allocate and fully initialze a scsi_device
+ * @sdevscan:  holds information to be stored in the new scsi_device
+ * @sdevnew:   store the address of the newly allocated scsi_device
  * @inq_result:        holds the result of a previous INQUIRY to the LUN
  * @bflags:    black/white list flag
  *
  * Description:
- *     Allocate and initialize a Scsi_Device matching sdevscan. Optionally
+ *     Allocate and initialize a scsi_device matching sdevscan. Optionally
  *     set fields based on values in *@bflags. If @sdevnew is not
- *     NULL, store the address of the new Scsi_Device in *@sdevnew (needed
+ *     NULL, store the address of the new scsi_device in *@sdevnew (needed
  *     when scanning a particular LUN).
  *
  * Return:
- *     SCSI_SCAN_NO_RESPONSE: could not allocate or setup a Scsi_Device
- *     SCSI_SCAN_LUN_PRESENT: a new Scsi_Device was allocated and initialized
+ *     SCSI_SCAN_NO_RESPONSE: could not allocate or setup a scsi_device
+ *     SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized
  **/
 static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
 {
@@ -675,7 +700,7 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
         *
         * The above is vague, as it implies that we could treat 001 and
         * 011 the same. Stay compatible with previous code, and create a
-        * Scsi_Device for a PQ of 1
+        * scsi_device for a PQ of 1
         *
         * Don't set the device offline here; rather let the upper
         * level drivers eval the PQ to decide whether they should
@@ -785,8 +810,8 @@ static inline void scsi_destroy_sdev(struct scsi_device *sdev)
  * scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it
  * @starget:   pointer to target device structure
  * @lun:       LUN of target device
- * @sdevscan:  probe the LUN corresponding to this Scsi_Device
- * @sdevnew:   store the value of any new Scsi_Device allocated
+ * @sdevscan:  probe the LUN corresponding to this scsi_device
+ * @sdevnew:   store the value of any new scsi_device allocated
  * @bflagsp:   store bflags here if not NULL
  *
  * Description:
@@ -794,10 +819,10 @@ static inline void scsi_destroy_sdev(struct scsi_device *sdev)
  *     allocate and set it up by calling scsi_add_lun.
  *
  * Return:
- *     SCSI_SCAN_NO_RESPONSE: could not allocate or setup a Scsi_Device
+ *     SCSI_SCAN_NO_RESPONSE: could not allocate or setup a scsi_device
  *     SCSI_SCAN_TARGET_PRESENT: target responded, but no device is
  *         attached at the LUN
- *     SCSI_SCAN_LUN_PRESENT: a new Scsi_Device was allocated and initialized
+ *     SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized
  **/
 static int scsi_probe_and_add_lun(struct scsi_target *starget,
                                  uint lun, int *bflagsp,
@@ -1047,7 +1072,7 @@ EXPORT_SYMBOL(int_to_scsilun);
 
 /**
  * scsi_report_lun_scan - Scan using SCSI REPORT LUN results
- * @sdevscan:  scan the host, channel, and id of this Scsi_Device
+ * @sdevscan:  scan the host, channel, and id of this scsi_device
  *
  * Description:
  *     If @sdevscan is for a SCSI-3 or up device, send a REPORT LUN
@@ -1075,6 +1100,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
        struct scsi_sense_hdr sshdr;
        struct scsi_device *sdev;
        struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+       int ret = 0;
 
        /*
         * Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set.
@@ -1170,8 +1196,8 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
                /*
                 * The device probably does not support a REPORT LUN command
                 */
-               kfree(lun_data);
-               return 1;
+               ret = 1;
+               goto out_err;
        }
 
        /*
@@ -1190,9 +1216,8 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
                num_luns = max_scsi_report_luns;
        }
 
-       SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUN scan of"
-                       " host %d channel %d id %d\n", sdev->host->host_no,
-                       sdev->channel, sdev->id));
+       SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev,
+               "scsi scan: REPORT LUN scan\n"));
 
        /*
         * Scan the luns in lun_data. The entry at offset 0 is really
@@ -1231,14 +1256,16 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
                                /*
                                 * Got some results, but now none, abort.
                                 */
-                               printk(KERN_ERR "scsi: Unexpected response"
-                                      " from %s lun %d while scanning, scan"
-                                      " aborted\n", devname, lun);
+                               sdev_printk(KERN_ERR, sdev,
+                                       "Unexpected response"
+                                       " from lun %d while scanning, scan"
+                                       " aborted\n", lun);
                                break;
                        }
                }
        }
 
+ out_err:
        kfree(lun_data);
  out:
        scsi_device_put(sdev);
@@ -1247,7 +1274,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
                 * the sdev we used didn't appear in the report luns scan
                 */
                scsi_destroy_sdev(sdev);
-       return 0;
+       return ret;
 }
 
 struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
@@ -1418,8 +1445,9 @@ static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel,
 int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
                            unsigned int id, unsigned int lun, int rescan)
 {
-       SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "%s: <%u:%u:%u:%u>\n",
-               __FUNCTION__, shost->host_no, channel, id, lun));
+       SCSI_LOG_SCAN_BUS(3, shost_printk (KERN_INFO, shost,
+               "%s: <%u:%u:%u>\n",
+               __FUNCTION__, channel, id, lun));
 
        if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||
            ((id != SCAN_WILD_CARD) && (id > shost->max_id)) ||
@@ -1452,19 +1480,6 @@ void scsi_scan_host(struct Scsi_Host *shost)
 }
 EXPORT_SYMBOL(scsi_scan_host);
 
-/**
- * scsi_scan_single_target - scan the given SCSI target
- * @shost:         adapter to scan
- * @chan:          channel to scan
- * @id:            target id to scan
- **/
-void scsi_scan_single_target(struct Scsi_Host *shost, 
-       unsigned int chan, unsigned int id)
-{
-       scsi_scan_host_selected(shost, chan, id, SCAN_WILD_CARD, 1);
-}
-EXPORT_SYMBOL(scsi_scan_single_target);
-
 void scsi_forget_host(struct Scsi_Host *shost)
 {
        struct scsi_device *sdev;
@@ -1485,16 +1500,16 @@ void scsi_forget_host(struct Scsi_Host *shost)
 /*
  * Function:    scsi_get_host_dev()
  *
- * Purpose:     Create a Scsi_Device that points to the host adapter itself.
+ * Purpose:     Create a scsi_device that points to the host adapter itself.
  *
- * Arguments:   SHpnt   - Host that needs a Scsi_Device
+ * Arguments:   SHpnt   - Host that needs a scsi_device
  *
  * Lock status: None assumed.
  *
- * Returns:     The Scsi_Device or NULL
+ * Returns:     The scsi_device or NULL
  *
  * Notes:
- *     Attach a single Scsi_Device to the Scsi_Host - this should
+ *     Attach a single scsi_device to the Scsi_Host - this should
  *     be made to look like a "pseudo-device" that points to the
  *     HA itself.
  *
@@ -1531,7 +1546,7 @@ EXPORT_SYMBOL(scsi_get_host_dev);
  *
  * Purpose:     Free a scsi_device that points to the host adapter itself.
  *
- * Arguments:   SHpnt   - Host that needs a Scsi_Device
+ * Arguments:   SHpnt   - Host that needs a scsi_device
  *
  * Lock status: None assumed.
  *