Skip to content

Commit

Permalink
sd: Physical block size and alignment support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Martin K. Petersen authored and James Bottomley committed Jun 21, 2009
1 parent c277331 commit ea09bcc
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 2 deletions.
23 changes: 21 additions & 2 deletions drivers/scsi/sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1307,6 +1307,7 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
int sense_valid = 0;
int the_result;
int retries = 3;
unsigned int alignment;
unsigned long long lba;
unsigned sector_size;

Expand Down Expand Up @@ -1358,6 +1359,16 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
return -EOVERFLOW;
}

/* Logical blocks per physical block exponent */
sdkp->hw_sector_size = (1 << (buffer[13] & 0xf)) * sector_size;

/* Lowest aligned logical block */
alignment = ((buffer[14] & 0x3f) << 8 | buffer[15]) * sector_size;
blk_queue_alignment_offset(sdp->request_queue, alignment);
if (alignment && sdkp->first_scan)
sd_printk(KERN_NOTICE, sdkp,
"physical block alignment offset: %u\n", alignment);

sdkp->capacity = lba + 1;
return sector_size;
}
Expand Down Expand Up @@ -1409,6 +1420,7 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
}

sdkp->capacity = lba + 1;
sdkp->hw_sector_size = sector_size;
return sector_size;
}

Expand Down Expand Up @@ -1521,11 +1533,17 @@ sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer)
string_get_size(sz, STRING_UNITS_10, cap_str_10,
sizeof(cap_str_10));

if (sdkp->first_scan || old_capacity != sdkp->capacity)
if (sdkp->first_scan || old_capacity != sdkp->capacity) {
sd_printk(KERN_NOTICE, sdkp,
"%llu %d-byte hardware sectors: (%s/%s)\n",
"%llu %d-byte logical blocks: (%s/%s)\n",
(unsigned long long)sdkp->capacity,
sector_size, cap_str_10, cap_str_2);

if (sdkp->hw_sector_size != sector_size)
sd_printk(KERN_NOTICE, sdkp,
"%u-byte physical blocks\n",
sdkp->hw_sector_size);
}
}

/* Rescale capacity to 512-byte units */
Expand All @@ -1538,6 +1556,7 @@ sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer)
else if (sector_size == 256)
sdkp->capacity >>= 1;

blk_queue_physical_block_size(sdp->request_queue, sdkp->hw_sector_size);
sdkp->device->sector_size = sector_size;
}

Expand Down
1 change: 1 addition & 0 deletions drivers/scsi/sd.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct scsi_disk {
unsigned int openers; /* protected by BKL for now, yuck */
sector_t capacity; /* size in 512-byte sectors */
u32 index;
unsigned short hw_sector_size;
u8 media_present;
u8 write_prot;
u8 protection_type;/* Data Integrity Field */
Expand Down

0 comments on commit ea09bcc

Please sign in to comment.