mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	[SCSI] sd: Implement support for WRITE SAME
Implement support for WRITE SAME(10) and WRITE SAME(16) in the SCSI disk driver. - We set the default maximum to 0xFFFF because there are several devices out there that only support two-byte block counts even with WRITE SAME(16). We only enable transfers bigger than 0xFFFF if the device explicitly reports MAXIMUM WRITE SAME LENGTH in the BLOCK LIMITS VPD. - max_write_same_blocks can be overriden per-device basis in sysfs. - The UNMAP discovery heuristics remain unchanged but the discard limits are tweaked to match the "real" WRITE SAME commands. - In the error handling logic we now distinguish between WRITE SAME with and without UNMAP set. The discovery process heuristics are: - If the device reports a SCSI level of SPC-3 or greater we'll issue READ SUPPORTED OPERATION CODES to find out whether WRITE SAME(16) is supported. If that's the case we will use it. - If the device supports the block limits VPD and reports a MAXIMUM WRITE SAME LENGTH bigger than 0xFFFF we will use WRITE SAME(16). - Otherwise we will use WRITE SAME(10) unless the target LBA is beyond 0xFFFFFFFF or the block count exceeds 0xFFFF. - no_write_same is set for ATA, FireWire and USB. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Reviewed-by: Mike Snitzer <snitzer@redhat.com> Reviewed-by: Jeff Garzik <jgarzik@redhat.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
		
							parent
							
								
									26e85fcd15
								
							
						
					
					
						commit
						5db44863b6
					
				
					 7 changed files with 191 additions and 16 deletions
				
			
		| 
						 | 
					@ -1053,6 +1053,7 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev)
 | 
				
			||||||
	sdev->use_10_for_rw = 1;
 | 
						sdev->use_10_for_rw = 1;
 | 
				
			||||||
	sdev->use_10_for_ms = 1;
 | 
						sdev->use_10_for_ms = 1;
 | 
				
			||||||
	sdev->no_report_opcodes = 1;
 | 
						sdev->no_report_opcodes = 1;
 | 
				
			||||||
 | 
						sdev->no_write_same = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Schedule policy is determined by ->qc_defer() callback and
 | 
						/* Schedule policy is determined by ->qc_defer() callback and
 | 
				
			||||||
	 * it needs to see every deferred qc.  Set dev_blocked to 1 to
 | 
						 * it needs to see every deferred qc.  Set dev_blocked to 1 to
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1547,6 +1547,7 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sdev->use_10_for_rw = 1;
 | 
						sdev->use_10_for_rw = 1;
 | 
				
			||||||
	sdev->no_report_opcodes = 1;
 | 
						sdev->no_report_opcodes = 1;
 | 
				
			||||||
 | 
						sdev->no_write_same = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sbp2_param_exclusive_login)
 | 
						if (sbp2_param_exclusive_login)
 | 
				
			||||||
		sdev->manage_start_stop = 1;
 | 
							sdev->manage_start_stop = 1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -900,11 +900,23 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 | 
				
			||||||
				action = ACTION_FAIL;
 | 
									action = ACTION_FAIL;
 | 
				
			||||||
				error = -EILSEQ;
 | 
									error = -EILSEQ;
 | 
				
			||||||
			/* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
 | 
								/* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
 | 
				
			||||||
			} else if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
 | 
								} else if (sshdr.asc == 0x20 || sshdr.asc == 0x24) {
 | 
				
			||||||
				   (cmd->cmnd[0] == UNMAP ||
 | 
									switch (cmd->cmnd[0]) {
 | 
				
			||||||
				    cmd->cmnd[0] == WRITE_SAME_16 ||
 | 
									case UNMAP:
 | 
				
			||||||
				    cmd->cmnd[0] == WRITE_SAME)) {
 | 
					 | 
				
			||||||
					description = "Discard failure";
 | 
										description = "Discard failure";
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									case WRITE_SAME:
 | 
				
			||||||
 | 
									case WRITE_SAME_16:
 | 
				
			||||||
 | 
										if (cmd->cmnd[1] & 0x8)
 | 
				
			||||||
 | 
											description = "Discard failure";
 | 
				
			||||||
 | 
										else
 | 
				
			||||||
 | 
											description =
 | 
				
			||||||
 | 
												"Write same failure";
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									default:
 | 
				
			||||||
 | 
										description = "Invalid command failure";
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				action = ACTION_FAIL;
 | 
									action = ACTION_FAIL;
 | 
				
			||||||
				error = -EREMOTEIO;
 | 
									error = -EREMOTEIO;
 | 
				
			||||||
			} else
 | 
								} else
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,6 +99,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void sd_config_discard(struct scsi_disk *, unsigned int);
 | 
					static void sd_config_discard(struct scsi_disk *, unsigned int);
 | 
				
			||||||
 | 
					static void sd_config_write_same(struct scsi_disk *);
 | 
				
			||||||
static int  sd_revalidate_disk(struct gendisk *);
 | 
					static int  sd_revalidate_disk(struct gendisk *);
 | 
				
			||||||
static void sd_unlock_native_capacity(struct gendisk *disk);
 | 
					static void sd_unlock_native_capacity(struct gendisk *disk);
 | 
				
			||||||
static int  sd_probe(struct device *);
 | 
					static int  sd_probe(struct device *);
 | 
				
			||||||
| 
						 | 
					@ -395,6 +396,45 @@ sd_store_max_medium_access_timeouts(struct device *dev,
 | 
				
			||||||
	return err ? err : count;
 | 
						return err ? err : count;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ssize_t
 | 
				
			||||||
 | 
					sd_show_write_same_blocks(struct device *dev, struct device_attribute *attr,
 | 
				
			||||||
 | 
								  char *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scsi_disk *sdkp = to_scsi_disk(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return snprintf(buf, 20, "%u\n", sdkp->max_ws_blocks);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ssize_t
 | 
				
			||||||
 | 
					sd_store_write_same_blocks(struct device *dev, struct device_attribute *attr,
 | 
				
			||||||
 | 
								   const char *buf, size_t count)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scsi_disk *sdkp = to_scsi_disk(dev);
 | 
				
			||||||
 | 
						struct scsi_device *sdp = sdkp->device;
 | 
				
			||||||
 | 
						unsigned long max;
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!capable(CAP_SYS_ADMIN))
 | 
				
			||||||
 | 
							return -EACCES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sdp->type != TYPE_DISK)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = kstrtoul(buf, 10, &max);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (err)
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (max == 0)
 | 
				
			||||||
 | 
							sdp->no_write_same = 1;
 | 
				
			||||||
 | 
						else if (max <= SD_MAX_WS16_BLOCKS)
 | 
				
			||||||
 | 
							sdkp->max_ws_blocks = max;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sd_config_write_same(sdkp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return count;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct device_attribute sd_disk_attrs[] = {
 | 
					static struct device_attribute sd_disk_attrs[] = {
 | 
				
			||||||
	__ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type,
 | 
						__ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type,
 | 
				
			||||||
	       sd_store_cache_type),
 | 
						       sd_store_cache_type),
 | 
				
			||||||
| 
						 | 
					@ -410,6 +450,8 @@ static struct device_attribute sd_disk_attrs[] = {
 | 
				
			||||||
	__ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL),
 | 
						__ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL),
 | 
				
			||||||
	__ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode,
 | 
						__ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode,
 | 
				
			||||||
	       sd_store_provisioning_mode),
 | 
						       sd_store_provisioning_mode),
 | 
				
			||||||
 | 
						__ATTR(max_write_same_blocks, S_IRUGO|S_IWUSR,
 | 
				
			||||||
 | 
						       sd_show_write_same_blocks, sd_store_write_same_blocks),
 | 
				
			||||||
	__ATTR(max_medium_access_timeouts, S_IRUGO|S_IWUSR,
 | 
						__ATTR(max_medium_access_timeouts, S_IRUGO|S_IWUSR,
 | 
				
			||||||
	       sd_show_max_medium_access_timeouts,
 | 
						       sd_show_max_medium_access_timeouts,
 | 
				
			||||||
	       sd_store_max_medium_access_timeouts),
 | 
						       sd_store_max_medium_access_timeouts),
 | 
				
			||||||
| 
						 | 
					@ -561,19 +603,23 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case SD_LBP_UNMAP:
 | 
						case SD_LBP_UNMAP:
 | 
				
			||||||
		max_blocks = min_not_zero(sdkp->max_unmap_blocks, 0xffffffff);
 | 
							max_blocks = min_not_zero(sdkp->max_unmap_blocks,
 | 
				
			||||||
 | 
										  (u32)SD_MAX_WS16_BLOCKS);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case SD_LBP_WS16:
 | 
						case SD_LBP_WS16:
 | 
				
			||||||
		max_blocks = min_not_zero(sdkp->max_ws_blocks, 0xffffffff);
 | 
							max_blocks = min_not_zero(sdkp->max_ws_blocks,
 | 
				
			||||||
 | 
										  (u32)SD_MAX_WS16_BLOCKS);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case SD_LBP_WS10:
 | 
						case SD_LBP_WS10:
 | 
				
			||||||
		max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff);
 | 
							max_blocks = min_not_zero(sdkp->max_ws_blocks,
 | 
				
			||||||
 | 
										  (u32)SD_MAX_WS10_BLOCKS);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case SD_LBP_ZERO:
 | 
						case SD_LBP_ZERO:
 | 
				
			||||||
		max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff);
 | 
							max_blocks = min_not_zero(sdkp->max_ws_blocks,
 | 
				
			||||||
 | 
										  (u32)SD_MAX_WS10_BLOCKS);
 | 
				
			||||||
		q->limits.discard_zeroes_data = 1;
 | 
							q->limits.discard_zeroes_data = 1;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -667,6 +713,83 @@ static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Some devices can not handle block counts above 0xffff despite
 | 
				
			||||||
 | 
						 * supporting WRITE SAME(16). Consequently we default to 64k
 | 
				
			||||||
 | 
						 * 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						blk_queue_max_write_same_sectors(q, blocks * (logical_block_size >> 9));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * sd_setup_write_same_cmnd - write the same data to multiple blocks
 | 
				
			||||||
 | 
					 * @sdp: scsi device to operate one
 | 
				
			||||||
 | 
					 * @rq: Request to prepare
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Will issue either WRITE SAME(10) or WRITE SAME(16) depending on
 | 
				
			||||||
 | 
					 * preference indicated by target device.
 | 
				
			||||||
 | 
					 **/
 | 
				
			||||||
 | 
					static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
 | 
				
			||||||
 | 
						struct bio *bio = rq->bio;
 | 
				
			||||||
 | 
						sector_t sector = blk_rq_pos(rq);
 | 
				
			||||||
 | 
						unsigned int nr_sectors = blk_rq_sectors(rq);
 | 
				
			||||||
 | 
						unsigned int nr_bytes = blk_rq_bytes(rq);
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sdkp->device->no_write_same)
 | 
				
			||||||
 | 
							return BLKPREP_KILL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BUG_ON(bio_offset(bio) || bio_iovec(bio)->bv_len != sdp->sector_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sector >>= ilog2(sdp->sector_size) - 9;
 | 
				
			||||||
 | 
						nr_sectors >>= ilog2(sdp->sector_size) - 9;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rq->__data_len = sdp->sector_size;
 | 
				
			||||||
 | 
						rq->timeout = SD_WRITE_SAME_TIMEOUT;
 | 
				
			||||||
 | 
						memset(rq->cmd, 0, rq->cmd_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff) {
 | 
				
			||||||
 | 
							rq->cmd_len = 16;
 | 
				
			||||||
 | 
							rq->cmd[0] = WRITE_SAME_16;
 | 
				
			||||||
 | 
							put_unaligned_be64(sector, &rq->cmd[2]);
 | 
				
			||||||
 | 
							put_unaligned_be32(nr_sectors, &rq->cmd[10]);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							rq->cmd_len = 10;
 | 
				
			||||||
 | 
							rq->cmd[0] = WRITE_SAME;
 | 
				
			||||||
 | 
							put_unaligned_be32(sector, &rq->cmd[2]);
 | 
				
			||||||
 | 
							put_unaligned_be16(nr_sectors, &rq->cmd[7]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = scsi_setup_blk_pc_cmnd(sdp, rq);
 | 
				
			||||||
 | 
						rq->__data_len = nr_bytes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq)
 | 
					static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	rq->timeout = SD_FLUSH_TIMEOUT;
 | 
						rq->timeout = SD_FLUSH_TIMEOUT;
 | 
				
			||||||
| 
						 | 
					@ -712,6 +835,9 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
 | 
				
			||||||
	if (rq->cmd_flags & REQ_DISCARD) {
 | 
						if (rq->cmd_flags & REQ_DISCARD) {
 | 
				
			||||||
		ret = sd_setup_discard_cmnd(sdp, rq);
 | 
							ret = sd_setup_discard_cmnd(sdp, rq);
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
						} else if (rq->cmd_flags & REQ_WRITE_SAME) {
 | 
				
			||||||
 | 
							ret = sd_setup_write_same_cmnd(sdp, rq);
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
	} else if (rq->cmd_flags & REQ_FLUSH) {
 | 
						} else if (rq->cmd_flags & REQ_FLUSH) {
 | 
				
			||||||
		ret = scsi_setup_flush_cmnd(sdp, rq);
 | 
							ret = scsi_setup_flush_cmnd(sdp, rq);
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
| 
						 | 
					@ -1484,8 +1610,9 @@ static int sd_done(struct scsi_cmnd *SCpnt)
 | 
				
			||||||
	int sense_valid = 0;
 | 
						int sense_valid = 0;
 | 
				
			||||||
	int sense_deferred = 0;
 | 
						int sense_deferred = 0;
 | 
				
			||||||
	unsigned char op = SCpnt->cmnd[0];
 | 
						unsigned char op = SCpnt->cmnd[0];
 | 
				
			||||||
 | 
						unsigned char unmap = SCpnt->cmnd[1] & 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (req->cmd_flags & REQ_DISCARD) {
 | 
						if (req->cmd_flags & REQ_DISCARD || req->cmd_flags & REQ_WRITE_SAME) {
 | 
				
			||||||
		if (!result) {
 | 
							if (!result) {
 | 
				
			||||||
			good_bytes = blk_rq_bytes(req);
 | 
								good_bytes = blk_rq_bytes(req);
 | 
				
			||||||
			scsi_set_resid(SCpnt, 0);
 | 
								scsi_set_resid(SCpnt, 0);
 | 
				
			||||||
| 
						 | 
					@ -1542,10 +1669,26 @@ static int sd_done(struct scsi_cmnd *SCpnt)
 | 
				
			||||||
		if (sshdr.asc == 0x10)  /* DIX: Host detected corruption */
 | 
							if (sshdr.asc == 0x10)  /* DIX: Host detected corruption */
 | 
				
			||||||
			good_bytes = sd_completed_bytes(SCpnt);
 | 
								good_bytes = sd_completed_bytes(SCpnt);
 | 
				
			||||||
		/* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
 | 
							/* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
 | 
				
			||||||
		if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
 | 
							if (sshdr.asc == 0x20 || sshdr.asc == 0x24) {
 | 
				
			||||||
		    (op == UNMAP || op == WRITE_SAME_16 || op == WRITE_SAME))
 | 
								switch (op) {
 | 
				
			||||||
 | 
								case UNMAP:
 | 
				
			||||||
				sd_config_discard(sdkp, SD_LBP_DISABLE);
 | 
									sd_config_discard(sdkp, SD_LBP_DISABLE);
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
 | 
								case WRITE_SAME_16:
 | 
				
			||||||
 | 
								case WRITE_SAME:
 | 
				
			||||||
 | 
									if (unmap)
 | 
				
			||||||
 | 
										sd_config_discard(sdkp, SD_LBP_DISABLE);
 | 
				
			||||||
 | 
									else {
 | 
				
			||||||
 | 
										sdkp->device->no_write_same = 1;
 | 
				
			||||||
 | 
										sd_config_write_same(sdkp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										good_bytes = 0;
 | 
				
			||||||
 | 
										req->__data_len = blk_rq_bytes(req);
 | 
				
			||||||
 | 
										req->cmd_flags |= REQ_QUIET;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -2380,9 +2523,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
 | 
				
			||||||
	if (buffer[3] == 0x3c) {
 | 
						if (buffer[3] == 0x3c) {
 | 
				
			||||||
		unsigned int lba_count, desc_count;
 | 
							unsigned int lba_count, desc_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		sdkp->max_ws_blocks =
 | 
							sdkp->max_ws_blocks = (u32)get_unaligned_be64(&buffer[36]);
 | 
				
			||||||
			(u32) min_not_zero(get_unaligned_be64(&buffer[36]),
 | 
					 | 
				
			||||||
					   (u64)0xffffffff);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!sdkp->lbpme)
 | 
							if (!sdkp->lbpme)
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
| 
						 | 
					@ -2475,6 +2616,13 @@ static void sd_read_block_provisioning(struct scsi_disk *sdkp)
 | 
				
			||||||
	kfree(buffer);
 | 
						kfree(buffer);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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))
 | 
				
			||||||
 | 
							sdkp->ws16 = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int sd_try_extended_inquiry(struct scsi_device *sdp)
 | 
					static int sd_try_extended_inquiry(struct scsi_device *sdp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -2534,6 +2682,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
 | 
				
			||||||
		sd_read_write_protect_flag(sdkp, buffer);
 | 
							sd_read_write_protect_flag(sdkp, buffer);
 | 
				
			||||||
		sd_read_cache_type(sdkp, buffer);
 | 
							sd_read_cache_type(sdkp, buffer);
 | 
				
			||||||
		sd_read_app_tag_own(sdkp, buffer);
 | 
							sd_read_app_tag_own(sdkp, buffer);
 | 
				
			||||||
 | 
							sd_read_write_same(sdkp, buffer);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sdkp->first_scan = 0;
 | 
						sdkp->first_scan = 0;
 | 
				
			||||||
| 
						 | 
					@ -2551,6 +2700,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
 | 
				
			||||||
	blk_queue_flush(sdkp->disk->queue, flush);
 | 
						blk_queue_flush(sdkp->disk->queue, flush);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	set_capacity(disk, sdkp->capacity);
 | 
						set_capacity(disk, sdkp->capacity);
 | 
				
			||||||
 | 
						sd_config_write_same(sdkp);
 | 
				
			||||||
	kfree(buffer);
 | 
						kfree(buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 out:
 | 
					 out:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,7 @@
 | 
				
			||||||
#define SD_TIMEOUT		(30 * HZ)
 | 
					#define SD_TIMEOUT		(30 * HZ)
 | 
				
			||||||
#define SD_MOD_TIMEOUT		(75 * HZ)
 | 
					#define SD_MOD_TIMEOUT		(75 * HZ)
 | 
				
			||||||
#define SD_FLUSH_TIMEOUT	(60 * HZ)
 | 
					#define SD_FLUSH_TIMEOUT	(60 * HZ)
 | 
				
			||||||
 | 
					#define SD_WRITE_SAME_TIMEOUT	(120 * HZ)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Number of allowed retries
 | 
					 * Number of allowed retries
 | 
				
			||||||
| 
						 | 
					@ -38,6 +39,11 @@ enum {
 | 
				
			||||||
	SD_MEMPOOL_SIZE = 2,	/* CDB pool size */
 | 
						SD_MEMPOOL_SIZE = 2,	/* CDB pool size */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						SD_MAX_WS10_BLOCKS = 0xffff,
 | 
				
			||||||
 | 
						SD_MAX_WS16_BLOCKS = 0x7fffff,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
	SD_LBP_FULL = 0,	/* Full logical block provisioning */
 | 
						SD_LBP_FULL = 0,	/* Full logical block provisioning */
 | 
				
			||||||
	SD_LBP_UNMAP,		/* Use UNMAP command */
 | 
						SD_LBP_UNMAP,		/* Use UNMAP command */
 | 
				
			||||||
| 
						 | 
					@ -77,6 +83,7 @@ struct scsi_disk {
 | 
				
			||||||
	unsigned	lbpws : 1;
 | 
						unsigned	lbpws : 1;
 | 
				
			||||||
	unsigned	lbpws10 : 1;
 | 
						unsigned	lbpws10 : 1;
 | 
				
			||||||
	unsigned	lbpvpd : 1;
 | 
						unsigned	lbpvpd : 1;
 | 
				
			||||||
 | 
						unsigned	ws16 : 1;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
 | 
					#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -189,6 +189,9 @@ static int slave_configure(struct scsi_device *sdev)
 | 
				
			||||||
		/* Do not attempt to use REPORT SUPPORTED OPERATION CODES */
 | 
							/* Do not attempt to use REPORT SUPPORTED OPERATION CODES */
 | 
				
			||||||
		sdev->no_report_opcodes = 1;
 | 
							sdev->no_report_opcodes = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Do not attempt to use WRITE SAME */
 | 
				
			||||||
 | 
							sdev->no_write_same = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Some disks return the total number of blocks in response
 | 
							/* Some disks return the total number of blocks in response
 | 
				
			||||||
		 * to READ CAPACITY rather than the highest block number.
 | 
							 * to READ CAPACITY rather than the highest block number.
 | 
				
			||||||
		 * If this device makes that mistake, tell the sd driver. */
 | 
							 * If this device makes that mistake, tell the sd driver. */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -136,6 +136,7 @@ struct scsi_device {
 | 
				
			||||||
	unsigned use_10_for_rw:1; /* first try 10-byte read / write */
 | 
						unsigned use_10_for_rw:1; /* first try 10-byte read / write */
 | 
				
			||||||
	unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
 | 
						unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
 | 
				
			||||||
	unsigned no_report_opcodes:1;	/* no REPORT SUPPORTED OPERATION CODES */
 | 
						unsigned no_report_opcodes:1;	/* no REPORT SUPPORTED OPERATION CODES */
 | 
				
			||||||
 | 
						unsigned no_write_same:1;	/* no WRITE SAME command */
 | 
				
			||||||
	unsigned skip_ms_page_8:1;	/* do not use MODE SENSE page 0x08 */
 | 
						unsigned skip_ms_page_8:1;	/* do not use MODE SENSE page 0x08 */
 | 
				
			||||||
	unsigned skip_ms_page_3f:1;	/* do not use MODE SENSE page 0x3f */
 | 
						unsigned skip_ms_page_3f:1;	/* do not use MODE SENSE page 0x3f */
 | 
				
			||||||
	unsigned skip_vpd_pages:1;	/* do not read VPD pages */
 | 
						unsigned skip_vpd_pages:1;	/* do not read VPD pages */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue