aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sd.c
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2014-06-03 18:45:51 -0400
committerChristoph Hellwig <hch@lst.de>2014-07-17 16:07:33 -0400
commitbcdb247c6b6a1f3e72b9b787b73f47dd509d17ec (patch)
tree00131e8131aaeb1a94c61556dfb87ded905dd5e3 /drivers/scsi/sd.c
parent8d964478b2d124fcfde8017d02d4d70ae20802f2 (diff)
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>
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r--drivers/scsi/sd.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 5167b9678240..87566b51fcf7 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2236,7 +2236,11 @@ got_data:
2236 } 2236 }
2237 } 2237 }
2238 2238
2239 sdp->use_16_for_rw = (sdkp->capacity > 0xffffffff); 2239 if (sdkp->capacity > 0xffffffff) {
2240 sdp->use_16_for_rw = 1;
2241 sdkp->max_xfer_blocks = SD_MAX_XFER_BLOCKS;
2242 } else
2243 sdkp->max_xfer_blocks = SD_DEF_XFER_BLOCKS;
2240 2244
2241 /* Rescale capacity to 512-byte units */ 2245 /* Rescale capacity to 512-byte units */
2242 if (sector_size == 4096) 2246 if (sector_size == 4096)
@@ -2551,6 +2555,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
2551{ 2555{
2552 unsigned int sector_sz = sdkp->device->sector_size; 2556 unsigned int sector_sz = sdkp->device->sector_size;
2553 const int vpd_len = 64; 2557 const int vpd_len = 64;
2558 u32 max_xfer_length;
2554 unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL); 2559 unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL);
2555 2560
2556 if (!buffer || 2561 if (!buffer ||
@@ -2558,6 +2563,10 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
2558 scsi_get_vpd_page(sdkp->device, 0xb0, buffer, vpd_len)) 2563 scsi_get_vpd_page(sdkp->device, 0xb0, buffer, vpd_len))
2559 goto out; 2564 goto out;
2560 2565
2566 max_xfer_length = get_unaligned_be32(&buffer[8]);
2567 if (max_xfer_length)
2568 sdkp->max_xfer_blocks = max_xfer_length;
2569
2561 blk_queue_io_min(sdkp->disk->queue, 2570 blk_queue_io_min(sdkp->disk->queue,
2562 get_unaligned_be16(&buffer[6]) * sector_sz); 2571 get_unaligned_be16(&buffer[6]) * sector_sz);
2563 blk_queue_io_opt(sdkp->disk->queue, 2572 blk_queue_io_opt(sdkp->disk->queue,
@@ -2712,6 +2721,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
2712 struct scsi_disk *sdkp = scsi_disk(disk); 2721 struct scsi_disk *sdkp = scsi_disk(disk);
2713 struct scsi_device *sdp = sdkp->device; 2722 struct scsi_device *sdp = sdkp->device;
2714 unsigned char *buffer; 2723 unsigned char *buffer;
2724 unsigned int max_xfer;
2715 2725
2716 SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, 2726 SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
2717 "sd_revalidate_disk\n")); 2727 "sd_revalidate_disk\n"));
@@ -2759,6 +2769,10 @@ static int sd_revalidate_disk(struct gendisk *disk)
2759 */ 2769 */
2760 sd_set_flush_flag(sdkp); 2770 sd_set_flush_flag(sdkp);
2761 2771
2772 max_xfer = min_not_zero(queue_max_hw_sectors(sdkp->disk->queue),
2773 sdkp->max_xfer_blocks);
2774 max_xfer <<= ilog2(sdp->sector_size) - 9;
2775 blk_queue_max_hw_sectors(sdkp->disk->queue, max_xfer);
2762 set_capacity(disk, sdkp->capacity); 2776 set_capacity(disk, sdkp->capacity);
2763 sd_config_write_same(sdkp); 2777 sd_config_write_same(sdkp);
2764 kfree(buffer); 2778 kfree(buffer);