aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Neukum <oneukum@suse.de>2007-02-08 03:04:48 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2007-02-16 18:32:19 -0500
commit61bf54b71d5abf767ee46284be19965d7253ddbf (patch)
tree04bda12e495bc19be2712dff9da35f5e3271691a
parent5b06470816fb5e658e81db2a55b530ff2ba711c9 (diff)
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 <oneukum@suse.de> Acked-by: Alan Stern <stern@rowland.harvard.edu> Acked-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/scsi/sd.c11
-rw-r--r--drivers/usb/storage/scsiglue.c6
-rw-r--r--drivers/usb/storage/unusual_devs.h2
-rw-r--r--include/linux/usb_usual.h4
-rw-r--r--include/scsi/scsi_device.h1
5 files changed, 21 insertions, 3 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 3f048bd6326d..5a8f55fea5ff 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1269,9 +1269,18 @@ repeat:
1269 1269
1270 /* Some devices return the total number of sectors, not the 1270 /* Some devices return the total number of sectors, not the
1271 * highest sector number. Make the necessary adjustment. */ 1271 * highest sector number. Make the necessary adjustment. */
1272 if (sdp->fix_capacity) 1272 if (sdp->fix_capacity) {
1273 --sdkp->capacity; 1273 --sdkp->capacity;
1274 1274
1275 /* Some devices have version which report the correct sizes
1276 * and others which do not. We guess size according to a heuristic
1277 * and err on the side of lowering the capacity. */
1278 } else {
1279 if (sdp->guess_capacity)
1280 if (sdkp->capacity & 0x01) /* odd sizes are odd */
1281 --sdkp->capacity;
1282 }
1283
1275got_data: 1284got_data:
1276 if (sector_size == 0) { 1285 if (sector_size == 0) {
1277 sector_size = 512; 1286 sector_size = 512;
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 70234f5dbeeb..e227f64d5641 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)
153 if (us->flags & US_FL_FIX_CAPACITY) 153 if (us->flags & US_FL_FIX_CAPACITY)
154 sdev->fix_capacity = 1; 154 sdev->fix_capacity = 1;
155 155
156 /* A few disks have two indistinguishable version, one of
157 * which reports the correct capacity and the other does not.
158 * The sd driver has to guess which is the case. */
159 if (us->flags & US_FL_CAPACITY_HEURISTICS)
160 sdev->guess_capacity = 1;
161
156 /* Some devices report a SCSI revision level above 2 but are 162 /* Some devices report a SCSI revision level above 2 but are
157 * unable to handle the REPORT LUNS command (for which 163 * unable to handle the REPORT LUNS command (for which
158 * support is mandatory at level 3). Since we already have 164 * 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 bab054b8d94f..568366569769 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,
1434 "DataStor", 1434 "DataStor",
1435 "USB4500 FW1.04", 1435 "USB4500 FW1.04",
1436 US_SC_DEVICE, US_PR_DEVICE, NULL, 1436 US_SC_DEVICE, US_PR_DEVICE, NULL,
1437 US_FL_FIX_CAPACITY), 1437 US_FL_CAPACITY_HEURISTICS),
1438 1438
1439/* Control/Bulk transport for all SubClass values */ 1439/* Control/Bulk transport for all SubClass values */
1440USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR), 1440USUAL_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 2ae76fe52ff7..1b792b9286ba 100644
--- a/include/linux/usb_usual.h
+++ b/include/linux/usb_usual.h
@@ -46,7 +46,9 @@
46 US_FLAG(MAX_SECTORS_64, 0x00000400) \ 46 US_FLAG(MAX_SECTORS_64, 0x00000400) \
47 /* Sets max_sectors to 64 */ \ 47 /* Sets max_sectors to 64 */ \
48 US_FLAG(IGNORE_DEVICE, 0x00000800) \ 48 US_FLAG(IGNORE_DEVICE, 0x00000800) \
49 /* Don't claim device */ 49 /* Don't claim device */ \
50 US_FLAG(CAPACITY_HEURISTICS, 0x00001000) \
51 /* sometimes sizes is too big */
50 52
51#define US_FLAG(name, value) US_FL_##name = value , 53#define US_FLAG(name, value) US_FL_##name = value ,
52enum { US_DO_ALL_FLAGS }; 54enum { US_DO_ALL_FLAGS };
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index ebf31b16dc49..9dd37e2f5a84 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -122,6 +122,7 @@ struct scsi_device {
122 unsigned no_uld_attach:1; /* disable connecting to upper level drivers */ 122 unsigned no_uld_attach:1; /* disable connecting to upper level drivers */
123 unsigned select_no_atn:1; 123 unsigned select_no_atn:1;
124 unsigned fix_capacity:1; /* READ_CAPACITY is too high by 1 */ 124 unsigned fix_capacity:1; /* READ_CAPACITY is too high by 1 */
125 unsigned guess_capacity:1; /* READ_CAPACITY might be too high by 1 */
125 unsigned retry_hwerror:1; /* Retry HARDWARE_ERROR */ 126 unsigned retry_hwerror:1; /* Retry HARDWARE_ERROR */
126 127
127 unsigned int device_blocked; /* Device returned QUEUE_FULL. */ 128 unsigned int device_blocked; /* Device returned QUEUE_FULL. */