diff options
author | Martin K. Petersen <martin.petersen@oracle.com> | 2009-05-23 11:43:37 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-06-21 11:52:37 -0400 |
commit | ea09bcc9c298d3057270abd78a973fc678d55c4c (patch) | |
tree | 35764eeb8325f03c29b2da115290c06c9f8303ab /drivers/scsi | |
parent | c277331d5fbaae5772ed19862feefa91f4e477d3 (diff) |
sd: Physical block size and alignment support
Extract physical block size and lowest aligned LBA from READ
CAPACITY(16) response and adjust queue parameters.
Report physical block size and alignment when applicable.
[jejb: fix up trailing whitespace]
Signed-off-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.c | 23 | ||||
-rw-r--r-- | drivers/scsi/sd.h | 1 |
2 files changed, 22 insertions, 2 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 878b17a9af30..a86064b6458d 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -1307,6 +1307,7 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, | |||
1307 | int sense_valid = 0; | 1307 | int sense_valid = 0; |
1308 | int the_result; | 1308 | int the_result; |
1309 | int retries = 3; | 1309 | int retries = 3; |
1310 | unsigned int alignment; | ||
1310 | unsigned long long lba; | 1311 | unsigned long long lba; |
1311 | unsigned sector_size; | 1312 | unsigned sector_size; |
1312 | 1313 | ||
@@ -1358,6 +1359,16 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, | |||
1358 | return -EOVERFLOW; | 1359 | return -EOVERFLOW; |
1359 | } | 1360 | } |
1360 | 1361 | ||
1362 | /* Logical blocks per physical block exponent */ | ||
1363 | sdkp->hw_sector_size = (1 << (buffer[13] & 0xf)) * sector_size; | ||
1364 | |||
1365 | /* Lowest aligned logical block */ | ||
1366 | alignment = ((buffer[14] & 0x3f) << 8 | buffer[15]) * sector_size; | ||
1367 | blk_queue_alignment_offset(sdp->request_queue, alignment); | ||
1368 | if (alignment && sdkp->first_scan) | ||
1369 | sd_printk(KERN_NOTICE, sdkp, | ||
1370 | "physical block alignment offset: %u\n", alignment); | ||
1371 | |||
1361 | sdkp->capacity = lba + 1; | 1372 | sdkp->capacity = lba + 1; |
1362 | return sector_size; | 1373 | return sector_size; |
1363 | } | 1374 | } |
@@ -1409,6 +1420,7 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp, | |||
1409 | } | 1420 | } |
1410 | 1421 | ||
1411 | sdkp->capacity = lba + 1; | 1422 | sdkp->capacity = lba + 1; |
1423 | sdkp->hw_sector_size = sector_size; | ||
1412 | return sector_size; | 1424 | return sector_size; |
1413 | } | 1425 | } |
1414 | 1426 | ||
@@ -1521,11 +1533,17 @@ got_data: | |||
1521 | string_get_size(sz, STRING_UNITS_10, cap_str_10, | 1533 | string_get_size(sz, STRING_UNITS_10, cap_str_10, |
1522 | sizeof(cap_str_10)); | 1534 | sizeof(cap_str_10)); |
1523 | 1535 | ||
1524 | if (sdkp->first_scan || old_capacity != sdkp->capacity) | 1536 | if (sdkp->first_scan || old_capacity != sdkp->capacity) { |
1525 | sd_printk(KERN_NOTICE, sdkp, | 1537 | sd_printk(KERN_NOTICE, sdkp, |
1526 | "%llu %d-byte hardware sectors: (%s/%s)\n", | 1538 | "%llu %d-byte logical blocks: (%s/%s)\n", |
1527 | (unsigned long long)sdkp->capacity, | 1539 | (unsigned long long)sdkp->capacity, |
1528 | sector_size, cap_str_10, cap_str_2); | 1540 | sector_size, cap_str_10, cap_str_2); |
1541 | |||
1542 | if (sdkp->hw_sector_size != sector_size) | ||
1543 | sd_printk(KERN_NOTICE, sdkp, | ||
1544 | "%u-byte physical blocks\n", | ||
1545 | sdkp->hw_sector_size); | ||
1546 | } | ||
1529 | } | 1547 | } |
1530 | 1548 | ||
1531 | /* Rescale capacity to 512-byte units */ | 1549 | /* Rescale capacity to 512-byte units */ |
@@ -1538,6 +1556,7 @@ got_data: | |||
1538 | else if (sector_size == 256) | 1556 | else if (sector_size == 256) |
1539 | sdkp->capacity >>= 1; | 1557 | sdkp->capacity >>= 1; |
1540 | 1558 | ||
1559 | blk_queue_physical_block_size(sdp->request_queue, sdkp->hw_sector_size); | ||
1541 | sdkp->device->sector_size = sector_size; | 1560 | sdkp->device->sector_size = sector_size; |
1542 | } | 1561 | } |
1543 | 1562 | ||
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 708778cf5f06..8474b5bad3fe 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h | |||
@@ -45,6 +45,7 @@ struct scsi_disk { | |||
45 | unsigned int openers; /* protected by BKL for now, yuck */ | 45 | unsigned int openers; /* protected by BKL for now, yuck */ |
46 | sector_t capacity; /* size in 512-byte sectors */ | 46 | sector_t capacity; /* size in 512-byte sectors */ |
47 | u32 index; | 47 | u32 index; |
48 | unsigned short hw_sector_size; | ||
48 | u8 media_present; | 49 | u8 media_present; |
49 | u8 write_prot; | 50 | u8 write_prot; |
50 | u8 protection_type;/* Data Integrity Field */ | 51 | u8 protection_type;/* Data Integrity Field */ |