diff options
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
| -rw-r--r-- | drivers/scsi/scsi_lib.c | 79 | 
1 files changed, 43 insertions, 36 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 9ed1ebcb7443..b7c569a42aa4 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -185,39 +185,37 @@ void scsi_queue_insert(struct scsi_cmnd *cmd, int reason)  	__scsi_queue_insert(cmd, reason, true);  } -  /** - * __scsi_execute - insert request and wait for the result - * @sdev:	scsi device + * scsi_execute_cmd - insert request and wait for the result + * @sdev:	scsi_device   * @cmd:	scsi command - * @data_direction: data direction + * @opf:	block layer request cmd_flags   * @buffer:	data buffer   * @bufflen:	len of buffer - * @sense:	optional sense buffer - * @sshdr:	optional decoded sense header   * @timeout:	request timeout in HZ   * @retries:	number of times to retry request - * @flags:	flags for ->cmd_flags - * @rq_flags:	flags for ->rq_flags - * @resid:	optional residual length + * @args:	Optional args. See struct definition for field descriptions   *   * Returns the scsi_cmnd result field if a command was executed, or a negative   * Linux error code if we didn't get that far.   */ -int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, -		 int data_direction, void *buffer, unsigned bufflen, -		 unsigned char *sense, struct scsi_sense_hdr *sshdr, -		 int timeout, int retries, blk_opf_t flags, -		 req_flags_t rq_flags, int *resid) +int scsi_execute_cmd(struct scsi_device *sdev, const unsigned char *cmd, +		     blk_opf_t opf, void *buffer, unsigned int bufflen, +		     int timeout, int retries, +		     const struct scsi_exec_args *args)  { +	static const struct scsi_exec_args default_args;  	struct request *req;  	struct scsi_cmnd *scmd;  	int ret; -	req = scsi_alloc_request(sdev->request_queue, -			data_direction == DMA_TO_DEVICE ? -			REQ_OP_DRV_OUT : REQ_OP_DRV_IN, -			rq_flags & RQF_PM ? BLK_MQ_REQ_PM : 0); +	if (!args) +		args = &default_args; +	else if (WARN_ON_ONCE(args->sense && +			      args->sense_len != SCSI_SENSE_BUFFERSIZE)) +		return -EINVAL; + +	req = scsi_alloc_request(sdev->request_queue, opf, args->req_flags);  	if (IS_ERR(req))  		return PTR_ERR(req); @@ -231,9 +229,9 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,  	scmd->cmd_len = COMMAND_SIZE(cmd[0]);  	memcpy(scmd->cmnd, cmd, scmd->cmd_len);  	scmd->allowed = retries; +	scmd->flags |= args->scmd_flags;  	req->timeout = timeout; -	req->cmd_flags |= flags; -	req->rq_flags |= rq_flags | RQF_QUIET; +	req->rq_flags |= RQF_QUIET;  	/*  	 * head injection *required* here otherwise quiesce won't work @@ -249,20 +247,21 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,  	if (unlikely(scmd->resid_len > 0 && scmd->resid_len <= bufflen))  		memset(buffer + bufflen - scmd->resid_len, 0, scmd->resid_len); -	if (resid) -		*resid = scmd->resid_len; -	if (sense && scmd->sense_len) -		memcpy(sense, scmd->sense_buffer, SCSI_SENSE_BUFFERSIZE); -	if (sshdr) +	if (args->resid) +		*args->resid = scmd->resid_len; +	if (args->sense) +		memcpy(args->sense, scmd->sense_buffer, SCSI_SENSE_BUFFERSIZE); +	if (args->sshdr)  		scsi_normalize_sense(scmd->sense_buffer, scmd->sense_len, -				     sshdr); +				     args->sshdr); +  	ret = scmd->result;   out:  	blk_mq_free_request(req);  	return ret;  } -EXPORT_SYMBOL(__scsi_execute); +EXPORT_SYMBOL(scsi_execute_cmd);  /*   * Wake up the error handler if necessary. Avoid as follows that the error @@ -2086,6 +2085,9 @@ int scsi_mode_select(struct scsi_device *sdev, int pf, int sp,  {  	unsigned char cmd[10];  	unsigned char *real_buffer; +	const struct scsi_exec_args exec_args = { +		.sshdr = sshdr, +	};  	int ret;  	memset(cmd, 0, sizeof(cmd)); @@ -2135,8 +2137,8 @@ int scsi_mode_select(struct scsi_device *sdev, int pf, int sp,  		cmd[4] = len;  	} -	ret = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, real_buffer, len, -			       sshdr, timeout, retries, NULL); +	ret = scsi_execute_cmd(sdev, cmd, REQ_OP_DRV_OUT, real_buffer, len, +			       timeout, retries, &exec_args);  	kfree(real_buffer);  	return ret;  } @@ -2167,6 +2169,10 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,  	int header_length;  	int result, retry_count = retries;  	struct scsi_sense_hdr my_sshdr; +	const struct scsi_exec_args exec_args = { +		/* caller might not be interested in sense, but we need it */ +		.sshdr = sshdr ? : &my_sshdr, +	};  	memset(data, 0, sizeof(*data));  	memset(&cmd[0], 0, 12); @@ -2175,9 +2181,7 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,  	cmd[1] = dbd & 0x18;	/* allows DBD and LLBA bits */  	cmd[2] = modepage; -	/* caller might not be interested in sense, but we need it */ -	if (!sshdr) -		sshdr = &my_sshdr; +	sshdr = exec_args.sshdr;   retry:  	use_10_for_ms = sdev->use_10_for_ms || len > 255; @@ -2200,8 +2204,8 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,  	memset(buffer, 0, len); -	result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len, -				  sshdr, timeout, retries, NULL); +	result = scsi_execute_cmd(sdev, cmd, REQ_OP_DRV_IN, buffer, len, +				  timeout, retries, &exec_args);  	if (result < 0)  		return result; @@ -2281,12 +2285,15 @@ scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries,  	char cmd[] = {  		TEST_UNIT_READY, 0, 0, 0, 0, 0,  	}; +	const struct scsi_exec_args exec_args = { +		.sshdr = sshdr, +	};  	int result;  	/* try to eat the UNIT_ATTENTION if there are enough retries */  	do { -		result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, sshdr, -					  timeout, 1, NULL); +		result = scsi_execute_cmd(sdev, cmd, REQ_OP_DRV_IN, NULL, 0, +					  timeout, 1, &exec_args);  		if (sdev->removable && scsi_sense_valid(sshdr) &&  		    sshdr->sense_key == UNIT_ATTENTION)  			sdev->changed = 1;  |