Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=61bf54b71d5abf767ee46284be19965d7253ddbf
Commit:     61bf54b71d5abf767ee46284be19965d7253ddbf
Parent:     5b06470816fb5e658e81db2a55b530ff2ba711c9
Author:     Oliver Neukum <[EMAIL PROTECTED]>
AuthorDate: Thu Feb 8 09:04:48 2007 +0100
Committer:  Greg Kroah-Hartman <[EMAIL PROTECTED]>
CommitDate: Fri Feb 16 15:32:19 2007 -0800

    USB Storage: indistinguishable devices with broken and unbroken firmware
    
    there's a USB mass storage device which exists in two version. One
    reports the correct size and the other does not. Apart from that they
    are identical and cannot be told apart. Here's a heuristic based on the
    empirical finding that drives have even sizes.
    
    
    Signed-off-by: Oliver Neukum <[EMAIL PROTECTED]>
    Acked-by: Alan Stern <[EMAIL PROTECTED]>
    Acked-by: Matthew Dharm <[EMAIL PROTECTED]>
    Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/scsi/sd.c                  |   11 ++++++++++-
 drivers/usb/storage/scsiglue.c     |    6 ++++++
 drivers/usb/storage/unusual_devs.h |    2 +-
 include/linux/usb_usual.h          |    4 +++-
 include/scsi/scsi_device.h         |    1 +
 5 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 3f048bd..5a8f55f 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1269,9 +1269,18 @@ repeat:
 
        /* Some devices return the total number of sectors, not the
         * highest sector number.  Make the necessary adjustment. */
-       if (sdp->fix_capacity)
+       if (sdp->fix_capacity) {
                --sdkp->capacity;
 
+       /* Some devices have version which report the correct sizes
+        * and others which do not. We guess size according to a heuristic
+        * and err on the side of lowering the capacity. */
+       } else {
+               if (sdp->guess_capacity)
+                       if (sdkp->capacity & 0x01) /* odd sizes are odd */
+                               --sdkp->capacity;
+       }
+
 got_data:
        if (sector_size == 0) {
                sector_size = 512;
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 70234f5..e227f64 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -153,6 +153,12 @@ 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
diff --git a/drivers/usb/storage/unusual_devs.h 
b/drivers/usb/storage/unusual_devs.h
index bab054b..5683665 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1434,7 +1434,7 @@ UNUSUAL_DEV(  0xed06, 0x4500, 0x0001, 0x0001,
                "DataStor",
                "USB4500 FW1.04",
                US_SC_DEVICE, US_PR_DEVICE, NULL,
-               US_FL_FIX_CAPACITY),
+               US_FL_CAPACITY_HEURISTICS),
 
 /* Control/Bulk transport for all SubClass values */
 USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
index 2ae76fe..1b792b9 100644
--- a/include/linux/usb_usual.h
+++ b/include/linux/usb_usual.h
@@ -46,7 +46,9 @@
        US_FLAG(MAX_SECTORS_64, 0x00000400)                     \
                /* Sets max_sectors to 64    */                 \
        US_FLAG(IGNORE_DEVICE,  0x00000800)                     \
-               /* Don't claim device */
+               /* Don't claim device */                        \
+       US_FLAG(CAPACITY_HEURISTICS,    0x00001000)             \
+               /* sometimes sizes is too big */
 
 #define US_FLAG(name, value)   US_FL_##name = value ,
 enum { US_DO_ALL_FLAGS };
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index ebf31b1..9dd37e2 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -122,6 +122,7 @@ struct scsi_device {
        unsigned no_uld_attach:1; /* disable connecting to upper level drivers 
*/
        unsigned select_no_atn:1;
        unsigned fix_capacity:1;        /* READ_CAPACITY is too high by 1 */
+       unsigned guess_capacity:1;      /* READ_CAPACITY might be too high by 1 
*/
        unsigned retry_hwerror:1;       /* Retry HARDWARE_ERROR */
 
        unsigned int device_blocked;    /* Device returned QUEUE_FULL. */
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to