|
@@ -442,8 +442,10 @@ sd_store_write_same_blocks(struct device *dev, struct device_attribute *attr,
|
|
|
|
|
|
if (max == 0)
|
|
|
sdp->no_write_same = 1;
|
|
|
- else if (max <= SD_MAX_WS16_BLOCKS)
|
|
|
+ else if (max <= SD_MAX_WS16_BLOCKS) {
|
|
|
+ sdp->no_write_same = 0;
|
|
|
sdkp->max_ws_blocks = max;
|
|
|
+ }
|
|
|
|
|
|
sd_config_write_same(sdkp);
|
|
|
|
|
@@ -750,7 +752,6 @@ static void sd_config_write_same(struct scsi_disk *sdkp)
|
|
|
{
|
|
|
struct request_queue *q = sdkp->disk->queue;
|
|
|
unsigned int logical_block_size = sdkp->device->sector_size;
|
|
|
- unsigned int blocks = 0;
|
|
|
|
|
|
if (sdkp->device->no_write_same) {
|
|
|
sdkp->max_ws_blocks = 0;
|
|
@@ -762,18 +763,20 @@ static void sd_config_write_same(struct scsi_disk *sdkp)
|
|
|
* blocks per I/O unless the device explicitly advertises a
|
|
|
* bigger limit.
|
|
|
*/
|
|
|
- if (sdkp->max_ws_blocks == 0)
|
|
|
- sdkp->max_ws_blocks = SD_MAX_WS10_BLOCKS;
|
|
|
-
|
|
|
- if (sdkp->ws16 || sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS)
|
|
|
- blocks = min_not_zero(sdkp->max_ws_blocks,
|
|
|
- (u32)SD_MAX_WS16_BLOCKS);
|
|
|
- else
|
|
|
- blocks = min_not_zero(sdkp->max_ws_blocks,
|
|
|
- (u32)SD_MAX_WS10_BLOCKS);
|
|
|
+ if (sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS)
|
|
|
+ sdkp->max_ws_blocks = min_not_zero(sdkp->max_ws_blocks,
|
|
|
+ (u32)SD_MAX_WS16_BLOCKS);
|
|
|
+ else if (sdkp->ws16 || sdkp->ws10 || sdkp->device->no_report_opcodes)
|
|
|
+ sdkp->max_ws_blocks = min_not_zero(sdkp->max_ws_blocks,
|
|
|
+ (u32)SD_MAX_WS10_BLOCKS);
|
|
|
+ else {
|
|
|
+ sdkp->device->no_write_same = 1;
|
|
|
+ sdkp->max_ws_blocks = 0;
|
|
|
+ }
|
|
|
|
|
|
out:
|
|
|
- blk_queue_max_write_same_sectors(q, blocks * (logical_block_size >> 9));
|
|
|
+ blk_queue_max_write_same_sectors(q, sdkp->max_ws_blocks *
|
|
|
+ (logical_block_size >> 9));
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -2645,9 +2648,24 @@ static void sd_read_block_provisioning(struct scsi_disk *sdkp)
|
|
|
|
|
|
static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
|
|
|
{
|
|
|
- if (scsi_report_opcode(sdkp->device, buffer, SD_BUF_SIZE,
|
|
|
- WRITE_SAME_16))
|
|
|
+ struct scsi_device *sdev = sdkp->device;
|
|
|
+
|
|
|
+ if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) {
|
|
|
+ sdev->no_report_opcodes = 1;
|
|
|
+
|
|
|
+ /* Disable WRITE SAME if REPORT SUPPORTED OPERATION
|
|
|
+ * CODES is unsupported and the device has an ATA
|
|
|
+ * Information VPD page (SAT).
|
|
|
+ */
|
|
|
+ if (!scsi_get_vpd_page(sdev, 0x89, buffer, SD_BUF_SIZE))
|
|
|
+ sdev->no_write_same = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME_16) == 1)
|
|
|
sdkp->ws16 = 1;
|
|
|
+
|
|
|
+ if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME) == 1)
|
|
|
+ sdkp->ws10 = 1;
|
|
|
}
|
|
|
|
|
|
static int sd_try_extended_inquiry(struct scsi_device *sdp)
|