Commit d7768998 authored by Alan Stern's avatar Alan Stern Committed by James Bottomley

[PATCH] sd.c: adjust READ_CAPACITY for broken devices

A number of USB mass storage devices return the wrong value in response to
READ CAPACITY: They give the total number of blocks rather than the
highest block number.  Currently the usb-storage driver tries to adjust
for this by altering the contents of the reply buffer.  That's not a very
good idea because it prevents users from seeing what the device actually
has to say; it violates the principle that a transport should do nothing
more than transfer data.

This patch moves the responsibility for adjusting the capacity to the sd
driver instead, by adding a new device flag.  After this has been merged
the corresponding change (to set the flag) will be made to the usb-storage
driver.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 39f07a0a
...@@ -1104,6 +1104,11 @@ sd_read_capacity(struct scsi_disk *sdkp, char *diskname, ...@@ -1104,6 +1104,11 @@ sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
(buffer[9] << 16) | (buffer[10] << 8) | buffer[11]; (buffer[9] << 16) | (buffer[10] << 8) | buffer[11];
} }
/* Some devices return the total number of sectors, not the
* highest sector number. Make the necessary adjustment. */
if (sdp->fix_capacity)
--sdkp->capacity;
got_data: got_data:
if (sector_size == 0) { if (sector_size == 0) {
sector_size = 512; sector_size = 512;
......
...@@ -111,6 +111,7 @@ struct scsi_device { ...@@ -111,6 +111,7 @@ struct scsi_device {
unsigned allow_restart:1; /* issue START_UNIT in error handler */ unsigned allow_restart:1; /* issue START_UNIT in error handler */
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 int device_blocked; /* Device returned QUEUE_FULL. */ unsigned int device_blocked; /* Device returned QUEUE_FULL. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment