aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew@wil.cx>2009-03-12 14:20:30 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-03-17 21:43:29 -0400
commit2b301307f63dbecf06d91f58f003c7fb7addee24 (patch)
treee6dee7552a0c52124a537e6db74ddce940443554 /drivers/scsi
parent0da205e01bc58cfad660659e3c901223d3596c57 (diff)
[SCSI] sd: Try READ CAPACITY 16 first for SBC-2 devices
New features are being added to the READ CAPACITY 16 results, so we want to issue it in preference to READ CAPACITY 10. Unfortunately, some devices misbehave when they see a READ CAPACITY 16, so we restrict this command to devices which claim conformance to SPC-3 (aka SBC-2), or claim they have features which are only reported in the READ CAPACITY 16 data. The READ CAPACITY 16 command is optional, even for SBC-2 devices, so we fall back to READ CAPACITY 10 if READ CAPACITY 16 fails. [jejb: don't error if device supports SBC-2 but doesn't support RC16] Signed-off-by: Matthew Wilcox <willy@linux.intel.com> Tested-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/sd.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index dcff84abcdee..8eebaa8c6f52 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1329,8 +1329,17 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
1329 if (media_not_present(sdkp, &sshdr)) 1329 if (media_not_present(sdkp, &sshdr))
1330 return -ENODEV; 1330 return -ENODEV;
1331 1331
1332 if (the_result) 1332 if (the_result) {
1333 sense_valid = scsi_sense_valid(&sshdr); 1333 sense_valid = scsi_sense_valid(&sshdr);
1334 if (sense_valid &&
1335 sshdr.sense_key == ILLEGAL_REQUEST &&
1336 (sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
1337 sshdr.ascq == 0x00)
1338 /* Invalid Command Operation Code or
1339 * Invalid Field in CDB, just retry
1340 * silently with RC10 */
1341 return -EINVAL;
1342 }
1334 retries--; 1343 retries--;
1335 1344
1336 } while (the_result && retries); 1345 } while (the_result && retries);
@@ -1414,6 +1423,15 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
1414 return sector_size; 1423 return sector_size;
1415} 1424}
1416 1425
1426static int sd_try_rc16_first(struct scsi_device *sdp)
1427{
1428 if (sdp->scsi_level > SCSI_SPC_2)
1429 return 1;
1430 if (scsi_device_protection(sdp))
1431 return 1;
1432 return 0;
1433}
1434
1417/* 1435/*
1418 * read disk capacity 1436 * read disk capacity
1419 */ 1437 */
@@ -1423,11 +1441,14 @@ sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer)
1423 int sector_size; 1441 int sector_size;
1424 struct scsi_device *sdp = sdkp->device; 1442 struct scsi_device *sdp = sdkp->device;
1425 1443
1426 /* Force READ CAPACITY(16) when PROTECT=1 */ 1444 if (sd_try_rc16_first(sdp)) {
1427 if (scsi_device_protection(sdp)) {
1428 sector_size = read_capacity_16(sdkp, sdp, buffer); 1445 sector_size = read_capacity_16(sdkp, sdp, buffer);
1429 if (sector_size == -EOVERFLOW) 1446 if (sector_size == -EOVERFLOW)
1430 goto got_data; 1447 goto got_data;
1448 if (sector_size == -ENODEV)
1449 return;
1450 if (sector_size < 0)
1451 sector_size = read_capacity_10(sdkp, sdp, buffer);
1431 if (sector_size < 0) 1452 if (sector_size < 0)
1432 return; 1453 return;
1433 } else { 1454 } else {