mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 14:42:24 +00:00
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>
This commit is contained in:
parent
5b06470816
commit
61bf54b71d
@ -1269,9 +1269,18 @@ repeat:
|
|||||||
|
|
||||||
/* Some devices return the total number of sectors, not the
|
/* Some devices return the total number of sectors, not the
|
||||||
* highest sector number. Make the necessary adjustment. */
|
* highest sector number. Make the necessary adjustment. */
|
||||||
if (sdp->fix_capacity)
|
if (sdp->fix_capacity) {
|
||||||
--sdkp->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:
|
got_data:
|
||||||
if (sector_size == 0) {
|
if (sector_size == 0) {
|
||||||
sector_size = 512;
|
sector_size = 512;
|
||||||
|
@ -153,6 +153,12 @@ static int slave_configure(struct scsi_device *sdev)
|
|||||||
if (us->flags & US_FL_FIX_CAPACITY)
|
if (us->flags & US_FL_FIX_CAPACITY)
|
||||||
sdev->fix_capacity = 1;
|
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
|
/* Some devices report a SCSI revision level above 2 but are
|
||||||
* unable to handle the REPORT LUNS command (for which
|
* unable to handle the REPORT LUNS command (for which
|
||||||
* support is mandatory at level 3). Since we already have
|
* support is mandatory at level 3). Since we already have
|
||||||
|
@ -1434,7 +1434,7 @@ UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001,
|
|||||||
"DataStor",
|
"DataStor",
|
||||||
"USB4500 FW1.04",
|
"USB4500 FW1.04",
|
||||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||||
US_FL_FIX_CAPACITY),
|
US_FL_CAPACITY_HEURISTICS),
|
||||||
|
|
||||||
/* Control/Bulk transport for all SubClass values */
|
/* Control/Bulk transport for all SubClass values */
|
||||||
USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
|
USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
|
||||||
|
@ -46,7 +46,9 @@
|
|||||||
US_FLAG(MAX_SECTORS_64, 0x00000400) \
|
US_FLAG(MAX_SECTORS_64, 0x00000400) \
|
||||||
/* Sets max_sectors to 64 */ \
|
/* Sets max_sectors to 64 */ \
|
||||||
US_FLAG(IGNORE_DEVICE, 0x00000800) \
|
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 ,
|
#define US_FLAG(name, value) US_FL_##name = value ,
|
||||||
enum { US_DO_ALL_FLAGS };
|
enum { US_DO_ALL_FLAGS };
|
||||||
|
@ -122,6 +122,7 @@ struct scsi_device {
|
|||||||
unsigned no_uld_attach:1; /* disable connecting to upper level drivers */
|
unsigned no_uld_attach:1; /* disable connecting to upper level drivers */
|
||||||
unsigned select_no_atn:1;
|
unsigned select_no_atn:1;
|
||||||
unsigned fix_capacity:1; /* READ_CAPACITY is too high by 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 retry_hwerror:1; /* Retry HARDWARE_ERROR */
|
||||||
|
|
||||||
unsigned int device_blocked; /* Device returned QUEUE_FULL. */
|
unsigned int device_blocked; /* Device returned QUEUE_FULL. */
|
||||||
|
Loading…
Reference in New Issue
Block a user