Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
[sfrench/cifs-2.6.git] / drivers / scsi / sd.c
index 20295774bf70c8c800ff0cd0eb1fe7b1488ec989..57d1e3e1bd4478548f89ef9f3a472ee4418c71b3 100644 (file)
@@ -1498,6 +1498,9 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
        unsigned long long lba;
        unsigned sector_size;
 
        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;
        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]);
 
        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 "
        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 "