diff options
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 20295774bf70..57d1e3e1bd44 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1498,6 +1498,9 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, unsigned long long lba; unsigned sector_size; + if (sdp->no_read_capacity_16) + return -EINVAL; + do { memset(cmd, 0, 16); cmd[0] = SERVICE_ACTION_IN; @@ -1626,6 +1629,15 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp, sector_size = get_unaligned_be32(&buffer[4]); lba = get_unaligned_be32(&buffer[0]); + if (sdp->no_read_capacity_16 && (lba == 0xffffffff)) { + /* Some buggy (usb cardreader) devices return an lba of + 0xffffffff when the want to report a size of 0 (with + which they really mean no media is present) */ + sdkp->capacity = 0; + sdkp->physical_block_size = sector_size; + return sector_size; + } + if ((sizeof(sdkp->capacity) == 4) && (lba == 0xffffffff)) { sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a " "kernel compiled with support for large block " |