]> Git Repo - linux.git/blobdiff - drivers/usb/storage/scsiglue.c
USB: add reset_resume method
[linux.git] / drivers / usb / storage / scsiglue.c
index 5715291ba5400d784ccb59841ef956a881dfb1e0..1ba19eaa1970979faa450d71cf143282cc67e93a 100644 (file)
@@ -72,12 +72,27 @@ static const char* host_info(struct Scsi_Host *host)
 
 static int slave_alloc (struct scsi_device *sdev)
 {
+       struct us_data *us = host_to_us(sdev->host);
+
        /*
         * Set the INQUIRY transfer length to 36.  We don't use any of
         * the extra data and many devices choke if asked for more or
         * less than 36 bytes.
         */
        sdev->inquiry_len = 36;
+
+       /*
+        * The UFI spec treates the Peripheral Qualifier bits in an
+        * INQUIRY result as reserved and requires devices to set them
+        * to 0.  However the SCSI spec requires these bits to be set
+        * to 3 to indicate when a LUN is not present.
+        *
+        * Let the scanning code know if this target merely sets
+        * Peripheral Device Type to 0x1f to indicate no LUN.
+        */
+       if (us->subclass == US_SC_UFI)
+               sdev->sdev_target->pdt_1f_for_no_lun = 1;
+
        return 0;
 }
 
@@ -95,30 +110,11 @@ static int slave_configure(struct scsi_device *sdev)
         * the end, scatter-gather buffers follow page boundaries. */
        blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
 
-       /* Set the SCSI level to at least 2.  We'll leave it at 3 if that's
-        * what is originally reported.  We need this to avoid confusing
-        * the SCSI layer with devices that report 0 or 1, but need 10-byte
-        * commands (ala ATAPI devices behind certain bridges, or devices
-        * which simply have broken INQUIRY data).
-        *
-        * NOTE: This means /dev/sg programs (ala cdrecord) will get the
-        * actual information.  This seems to be the preference for
-        * programs like that.
-        *
-        * NOTE: This also means that /proc/scsi/scsi and sysfs may report
-        * the actual value or the modified one, depending on where the
-        * data comes from.
+       /* Many devices have trouble transfering more than 32KB at a time,
+        * while others have trouble with more than 64K. At this time we
+        * are limiting both to 32K (64 sectores).
         */
-       if (sdev->scsi_level < SCSI_2)
-               sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2;
-
-       /* According to the technical support people at Genesys Logic,
-        * devices using their chips have problems transferring more than
-        * 32 KB at a time.  In practice people have found that 64 KB
-        * works okay and that's what Windows does.  But we'll be
-        * conservative; people can always use the sysfs interface to
-        * increase max_sectors. */
-       if (le16_to_cpu(us->pusb_dev->descriptor.idVendor) == USB_VENDOR_ID_GENESYS &&
+       if ((us->flags & US_FL_MAX_SECTORS_64) &&
                        sdev->request_queue->max_sectors > 64)
                blk_queue_max_sectors(sdev->request_queue, 64);
 
@@ -157,13 +153,21 @@ static int slave_configure(struct scsi_device *sdev)
                if (us->flags & US_FL_FIX_CAPACITY)
                        sdev->fix_capacity = 1;
 
+               /* A few disks have two indistinguishable version, one of
+                * which reports the correct capacity and the other does not.
+                * The sd driver has to guess which is the case. */
+               if (us->flags & US_FL_CAPACITY_HEURISTICS)
+                       sdev->guess_capacity = 1;
+
                /* Some devices report a SCSI revision level above 2 but are
                 * unable to handle the REPORT LUNS command (for which
                 * support is mandatory at level 3).  Since we already have
                 * a Get-Max-LUN request, we won't lose much by setting the
                 * revision level down to 2.  The only devices that would be
                 * affected are those with sparse LUNs. */
-               sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2;
+               if (sdev->scsi_level > SCSI_2)
+                       sdev->sdev_target->scsi_level =
+                                       sdev->scsi_level = SCSI_2;
 
                /* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable
                 * Hardware Error) when any low-level error occurs,
@@ -181,6 +185,16 @@ static int slave_configure(struct scsi_device *sdev)
                sdev->use_10_for_ms = 1;
        }
 
+       /* The CB and CBI transports have no way to pass LUN values
+        * other than the bits in the second byte of a CDB.  But those
+        * bits don't get set to the LUN value if the device reports
+        * scsi_level == 0 (UNKNOWN).  Hence such devices must necessarily
+        * be single-LUN.
+        */
+       if ((us->protocol == US_PR_CB || us->protocol == US_PR_CBI) &&
+                       sdev->scsi_level == SCSI_UNKNOWN)
+               us->max_lun = 0;
+
        /* Some devices choke when they receive a PREVENT-ALLOW MEDIUM
         * REMOVAL command, so suppress those commands. */
        if (us->flags & US_FL_NOT_LOCKABLE)
@@ -307,10 +321,14 @@ void usb_stor_report_device_reset(struct us_data *us)
 
 /* Report a driver-initiated bus reset to the SCSI layer.
  * Calling this for a SCSI-initiated reset is unnecessary but harmless.
- * The caller must own the SCSI host lock. */
+ * The caller must not own the SCSI host lock. */
 void usb_stor_report_bus_reset(struct us_data *us)
 {
-       scsi_report_bus_reset(us_to_host(us), 0);
+       struct Scsi_Host *host = us_to_host(us);
+
+       scsi_lock(host);
+       scsi_report_bus_reset(host, 0);
+       scsi_unlock(host);
 }
 
 /***********************************************************************
This page took 0.034803 seconds and 4 git commands to generate.