From d4ad60d5b157d0fa88b5d12d0f6e268b87a976a7 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 8 Feb 2007 09:04:48 +0100 Subject: [PATCH] --- yaml --- r: 48743 b: refs/heads/master c: 61bf54b71d5abf767ee46284be19965d7253ddbf h: refs/heads/master i: 48741: 26bd065bbaddc8341bf61b40cc3f5e0431a0ecbe 48739: 012f5cc01d7bba63c04c44b367d905e7a5f0a48c 48735: 50bdc07228ad4d035b5681a245308f2589318da2 v: v3 --- [refs] | 2 +- trunk/drivers/scsi/sd.c | 11 ++++++++++- trunk/drivers/usb/storage/scsiglue.c | 6 ++++++ trunk/drivers/usb/storage/unusual_devs.h | 2 +- trunk/include/linux/usb_usual.h | 4 +++- trunk/include/scsi/scsi_device.h | 1 + 6 files changed, 22 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index e9f8e881414d..07f312226f38 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5b06470816fb5e658e81db2a55b530ff2ba711c9 +refs/heads/master: 61bf54b71d5abf767ee46284be19965d7253ddbf diff --git a/trunk/drivers/scsi/sd.c b/trunk/drivers/scsi/sd.c index 3f048bd6326d..5a8f55fea5ff 100644 --- a/trunk/drivers/scsi/sd.c +++ b/trunk/drivers/scsi/sd.c @@ -1269,9 +1269,18 @@ sd_read_capacity(struct scsi_disk *sdkp, char *diskname, /* 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/trunk/drivers/usb/storage/scsiglue.c b/trunk/drivers/usb/storage/scsiglue.c index 70234f5dbeeb..e227f64d5641 100644 --- a/trunk/drivers/usb/storage/scsiglue.c +++ b/trunk/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/trunk/drivers/usb/storage/unusual_devs.h b/trunk/drivers/usb/storage/unusual_devs.h index bab054b8d94f..568366569769 100644 --- a/trunk/drivers/usb/storage/unusual_devs.h +++ b/trunk/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/trunk/include/linux/usb_usual.h b/trunk/include/linux/usb_usual.h index 2ae76fe52ff7..1b792b9286ba 100644 --- a/trunk/include/linux/usb_usual.h +++ b/trunk/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/trunk/include/scsi/scsi_device.h b/trunk/include/scsi/scsi_device.h index ebf31b16dc49..9dd37e2f5a84 100644 --- a/trunk/include/scsi/scsi_device.h +++ b/trunk/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. */