mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-30 13:38:40 +00:00
sd: Limit transfer length
Until now the per-command transfer length has exclusively been gated by the max_sectors parameter in the scsi_host template. Given that the size of this parameter has been bumped to an unsigned int we have to be careful not to exceed the target device's capabilities. If the if the device specifies a Maximum Transfer Length in the Block Limits VPD we'll use that value. Otherwise we'll use 0xffffffff for devices that have use_16_for_rw set and 0xffff for the rest. We then combine the chosen disk limit with max_sectors in the host template. The smaller of the two will be used to set the max_hw_sectors queue limit. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Reviewed-by: Ewan D. Milne <emilne@redhat.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
8d964478b2
commit
bcdb247c6b
@ -2236,7 +2236,11 @@ got_data:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sdp->use_16_for_rw = (sdkp->capacity > 0xffffffff);
|
if (sdkp->capacity > 0xffffffff) {
|
||||||
|
sdp->use_16_for_rw = 1;
|
||||||
|
sdkp->max_xfer_blocks = SD_MAX_XFER_BLOCKS;
|
||||||
|
} else
|
||||||
|
sdkp->max_xfer_blocks = SD_DEF_XFER_BLOCKS;
|
||||||
|
|
||||||
/* Rescale capacity to 512-byte units */
|
/* Rescale capacity to 512-byte units */
|
||||||
if (sector_size == 4096)
|
if (sector_size == 4096)
|
||||||
@ -2551,6 +2555,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
|
|||||||
{
|
{
|
||||||
unsigned int sector_sz = sdkp->device->sector_size;
|
unsigned int sector_sz = sdkp->device->sector_size;
|
||||||
const int vpd_len = 64;
|
const int vpd_len = 64;
|
||||||
|
u32 max_xfer_length;
|
||||||
unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL);
|
unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL);
|
||||||
|
|
||||||
if (!buffer ||
|
if (!buffer ||
|
||||||
@ -2558,6 +2563,10 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
|
|||||||
scsi_get_vpd_page(sdkp->device, 0xb0, buffer, vpd_len))
|
scsi_get_vpd_page(sdkp->device, 0xb0, buffer, vpd_len))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
max_xfer_length = get_unaligned_be32(&buffer[8]);
|
||||||
|
if (max_xfer_length)
|
||||||
|
sdkp->max_xfer_blocks = max_xfer_length;
|
||||||
|
|
||||||
blk_queue_io_min(sdkp->disk->queue,
|
blk_queue_io_min(sdkp->disk->queue,
|
||||||
get_unaligned_be16(&buffer[6]) * sector_sz);
|
get_unaligned_be16(&buffer[6]) * sector_sz);
|
||||||
blk_queue_io_opt(sdkp->disk->queue,
|
blk_queue_io_opt(sdkp->disk->queue,
|
||||||
@ -2712,6 +2721,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
|
|||||||
struct scsi_disk *sdkp = scsi_disk(disk);
|
struct scsi_disk *sdkp = scsi_disk(disk);
|
||||||
struct scsi_device *sdp = sdkp->device;
|
struct scsi_device *sdp = sdkp->device;
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
|
unsigned int max_xfer;
|
||||||
|
|
||||||
SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
|
SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
|
||||||
"sd_revalidate_disk\n"));
|
"sd_revalidate_disk\n"));
|
||||||
@ -2759,6 +2769,10 @@ static int sd_revalidate_disk(struct gendisk *disk)
|
|||||||
*/
|
*/
|
||||||
sd_set_flush_flag(sdkp);
|
sd_set_flush_flag(sdkp);
|
||||||
|
|
||||||
|
max_xfer = min_not_zero(queue_max_hw_sectors(sdkp->disk->queue),
|
||||||
|
sdkp->max_xfer_blocks);
|
||||||
|
max_xfer <<= ilog2(sdp->sector_size) - 9;
|
||||||
|
blk_queue_max_hw_sectors(sdkp->disk->queue, max_xfer);
|
||||||
set_capacity(disk, sdkp->capacity);
|
set_capacity(disk, sdkp->capacity);
|
||||||
sd_config_write_same(sdkp);
|
sd_config_write_same(sdkp);
|
||||||
kfree(buffer);
|
kfree(buffer);
|
||||||
|
@ -44,6 +44,8 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
SD_DEF_XFER_BLOCKS = 0xffff,
|
||||||
|
SD_MAX_XFER_BLOCKS = 0xffffffff,
|
||||||
SD_MAX_WS10_BLOCKS = 0xffff,
|
SD_MAX_WS10_BLOCKS = 0xffff,
|
||||||
SD_MAX_WS16_BLOCKS = 0x7fffff,
|
SD_MAX_WS16_BLOCKS = 0x7fffff,
|
||||||
};
|
};
|
||||||
@ -64,6 +66,7 @@ struct scsi_disk {
|
|||||||
struct gendisk *disk;
|
struct gendisk *disk;
|
||||||
atomic_t openers;
|
atomic_t openers;
|
||||||
sector_t capacity; /* size in 512-byte sectors */
|
sector_t capacity; /* size in 512-byte sectors */
|
||||||
|
u32 max_xfer_blocks;
|
||||||
u32 max_ws_blocks;
|
u32 max_ws_blocks;
|
||||||
u32 max_unmap_blocks;
|
u32 max_unmap_blocks;
|
||||||
u32 unmap_granularity;
|
u32 unmap_granularity;
|
||||||
|
Loading…
Reference in New Issue
Block a user