Move the code for submitting a SCSI command from scsi_execute() into scsi_build_rq(). Introduce scsi_execute_async(). This patch does not change any functionality.
Signed-off-by: Bart Van Assche <bart.vanass...@sandisk.com> Cc: Israel Rukshin <isra...@mellanox.com> Cc: Max Gurtovoy <m...@mellanox.com> Cc: Hannes Reinecke <h...@suse.de> --- drivers/scsi/scsi_lib.c | 89 +++++++++++++++++++++++++++++++++++++--------- include/scsi/scsi_device.h | 5 +++ 2 files changed, 77 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 4893f2908edf..dc87456b3f23 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -213,6 +213,73 @@ void scsi_queue_insert(struct scsi_cmnd *cmd, int reason) __scsi_queue_insert(cmd, reason, 1); } +static struct request *scsi_build_rq(const struct scsi_device *sdev, + const unsigned char *cmd, int data_direction, void *buffer, + unsigned bufflen, int timeout, int retries, u64 flags, + req_flags_t rq_flags) +{ + struct request *req; + struct scsi_request *rq; + int ret; + + req = blk_get_request(sdev->request_queue, + data_direction == DMA_TO_DEVICE ? + REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, __GFP_RECLAIM); + if (IS_ERR(req)) + return req; + rq = scsi_req(req); + scsi_req_init(req); + + if (bufflen) { + ret = blk_rq_map_kern(sdev->request_queue, req, + buffer, bufflen, __GFP_RECLAIM); + if (ret) { + blk_put_request(req); + return ERR_PTR(ret); + } + } + + rq->cmd_len = COMMAND_SIZE(cmd[0]); + memcpy(rq->cmd, cmd, rq->cmd_len); + req->retries = retries; + req->timeout = timeout; + req->cmd_flags |= flags; + req->rq_flags |= rq_flags | RQF_QUIET | RQF_PREEMPT; + + return req; +} + +/** + * scsi_execute_async - insert a SCSI request + * @sdev: scsi device + * @disk: gendisk pointer that will be stored in the request structure + * @cmd: scsi command + * @data_direction: data direction + * @buffer: data buffer + * @bufflen: length of buffer + * @timeout: request timeout in seconds + * @retries: number of times to retry request + * @flags: flags for ->cmd_flags + * @rq_flags: flags for ->rq_flags + * @done: I/O completion function + */ +int scsi_execute_async(const struct scsi_device *sdev, struct gendisk *disk, + const unsigned char *cmd, int data_direction, void *buffer, + unsigned bufflen, int timeout, int retries, u64 flags, + req_flags_t rq_flags, rq_end_io_fn *done) +{ + struct request *req; + + req = scsi_build_rq(sdev, cmd, data_direction, buffer, bufflen, timeout, + retries, flags, rq_flags); + if (IS_ERR(req)) + return PTR_ERR(req); + /* head injection *required* here otherwise quiesce won't work */ + blk_execute_rq_nowait(req->q, disk, req, 1, done); + + return 0; +} +EXPORT_SYMBOL(scsi_execute_async); /** * scsi_execute - insert request and wait for the result @@ -242,24 +309,12 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, struct scsi_request *rq; int ret = DRIVER_ERROR << 24; - req = blk_get_request(sdev->request_queue, - data_direction == DMA_TO_DEVICE ? - REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, __GFP_RECLAIM); + req = scsi_build_rq(sdev, cmd, data_direction, buffer, bufflen, + timeout, retries, flags, rq_flags); if (IS_ERR(req)) - return ret; - rq = scsi_req(req); - scsi_req_init(req); + return PTR_ERR(req); - if (bufflen && blk_rq_map_kern(sdev->request_queue, req, - buffer, bufflen, __GFP_RECLAIM)) - goto out; - - rq->cmd_len = COMMAND_SIZE(cmd[0]); - memcpy(rq->cmd, cmd, rq->cmd_len); - req->retries = retries; - req->timeout = timeout; - req->cmd_flags |= flags; - req->rq_flags |= rq_flags | RQF_QUIET | RQF_PREEMPT; + rq = scsi_req(req); /* * head injection *required* here otherwise quiesce won't work @@ -282,7 +337,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, if (sshdr) scsi_normalize_sense(rq->sense, rq->sense_len, sshdr); ret = req->errors; - out: + blk_put_request(req); return ret; diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 080c7ce9bae8..38c73ee0a929 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -408,6 +408,11 @@ extern const char *scsi_device_state_name(enum scsi_device_state); extern int scsi_is_sdev_device(const struct device *); extern int scsi_is_target_device(const struct device *); extern void scsi_sanitize_inquiry_string(unsigned char *s, int len); +extern int scsi_execute_async(const struct scsi_device *sdev, + struct gendisk *disk, const unsigned char *cmd, + int data_direction, void *buffer, unsigned bufflen, + int timeout, int retries, u64 flags, req_flags_t rq_flags, + rq_end_io_fn *done); extern 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, -- 2.12.2