@@ -185,55 +185,39 @@ 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
- * @cmd: scsi command
- * @data_direction: data direction
- * @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
+ * __scsi_exec_req - insert request and wait for the result
+ * @scsi_exec_args: See struct definition for description of each field
*
* 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_exec_req(const struct scsi_exec_args *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);
+ req = scsi_alloc_request(args->sdev->request_queue,
+ args->data_dir == DMA_TO_DEVICE ?
+ REQ_OP_DRV_OUT : REQ_OP_DRV_IN,
+ args->req_flags & RQF_PM ? BLK_MQ_REQ_PM : 0);
if (IS_ERR(req))
return PTR_ERR(req);
- if (bufflen) {
- ret = blk_rq_map_kern(sdev->request_queue, req,
- buffer, bufflen, GFP_NOIO);
+ if (args->buf) {
+ ret = blk_rq_map_kern(args->sdev->request_queue, req, args->buf,
+ args->buf_len, GFP_NOIO);
if (ret)
goto out;
}
scmd = blk_mq_rq_to_pdu(req);
- scmd->cmd_len = COMMAND_SIZE(cmd[0]);
- memcpy(scmd->cmnd, cmd, scmd->cmd_len);
- scmd->allowed = retries;
- req->timeout = timeout;
- req->cmd_flags |= flags;
- req->rq_flags |= rq_flags | RQF_QUIET;
+ scmd->cmd_len = COMMAND_SIZE(args->cmd[0]);
+ memcpy(scmd->cmnd, args->cmd, scmd->cmd_len);
+ scmd->allowed = args->retries;
+ req->timeout = args->timeout;
+ req->cmd_flags |= args->op_flags;
+ req->rq_flags |= args->req_flags | RQF_QUIET;
/*
* head injection *required* here otherwise quiesce won't work
@@ -246,23 +230,24 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
* is invalid. Prevent the garbage from being misinterpreted
* and prevent security leaks by zeroing out the excess data.
*/
- 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 (unlikely(scmd->resid_len > 0 && scmd->resid_len <= args->buf_len))
+ memset(args->buf + args->buf_len - scmd->resid_len, 0,
+ scmd->resid_len);
+
+ if (args->resid)
+ *args->resid = scmd->resid_len;
+ if (args->sense && scmd->sense_len)
+ 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_exec_req);
/*
* Wake up the error handler if necessary. Avoid as follows that the error
@@ -454,28 +454,69 @@ 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(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);
+
+struct scsi_exec_args {
+ struct scsi_device *sdev; /* scsi device */
+ const unsigned char *cmd; /* scsi command */
+ int data_dir; /* DMA direction */
+ void *buf; /* data buffer */
+ unsigned int buf_len; /* len of buffer */
+ unsigned char *sense; /* optional sense buffer */
+ unsigned int sense_len; /* optional sense buffer len */
+ struct scsi_sense_hdr *sshdr; /* optional decoded sense header */
+ int timeout; /* request timeout in HZ */
+ int retries; /* number of times to retry request */
+ blk_opf_t op_flags; /* flags for ->cmd_flags */
+ req_flags_t req_flags; /* flags for ->rq_flags */
+ int *resid; /* optional residual length */
+};
+
+extern int __scsi_exec_req(const struct scsi_exec_args *args);
+/* Make sure any sense buffer is the correct size. */
+#define scsi_exec_req(args) \
+({ \
+ BUILD_BUG_ON(args.sense && \
+ args.sense_len != SCSI_SENSE_BUFFERSIZE); \
+ __scsi_exec_req(&args); \
+})
+
/* Make sure any sense buffer is the correct size. */
-#define scsi_execute(sdev, cmd, data_direction, buffer, bufflen, sense, \
- sshdr, timeout, retries, flags, rq_flags, resid) \
+#define scsi_execute(_sdev, _cmd, _data_dir, _buffer, _bufflen, _sense, \
+ _sshdr, _timeout, _retries, _flags, _rq_flags, \
+ _resid) \
({ \
- BUILD_BUG_ON((sense) != NULL && \
- sizeof(sense) != SCSI_SENSE_BUFFERSIZE); \
- __scsi_execute(sdev, cmd, data_direction, buffer, bufflen, \
- sense, sshdr, timeout, retries, flags, rq_flags, \
- resid); \
+ BUILD_BUG_ON((_sense) != NULL && \
+ sizeof(_sense) != SCSI_SENSE_BUFFERSIZE); \
+ __scsi_exec_req(&((struct scsi_exec_args) { \
+ .sdev = _sdev, \
+ .cmd = _cmd, \
+ .data_dir = _data_dir, \
+ .buf = _buffer, \
+ .buf_len = _bufflen, \
+ .sense = _sense, \
+ .sshdr = _sshdr, \
+ .timeout = _timeout, \
+ .retries = _retries, \
+ .op_flags = _flags, \
+ .req_flags = _rq_flags, \
+ .resid = _resid, })); \
})
+
static inline int scsi_execute_req(struct scsi_device *sdev,
const unsigned char *cmd, int data_direction, void *buffer,
unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout,
int retries, int *resid)
{
- return scsi_execute(sdev, cmd, data_direction, buffer,
- bufflen, NULL, sshdr, timeout, retries, 0, 0, resid);
+ return __scsi_exec_req(&(struct scsi_exec_args) {
+ .sdev = sdev,
+ .cmd = cmd,
+ .data_dir = data_direction,
+ .buf = buffer,
+ .buf_len = bufflen,
+ .sshdr = sshdr,
+ .timeout = timeout,
+ .retries = retries,
+ .resid = resid });
}
extern void sdev_disable_disk_events(struct scsi_device *sdev);
extern void sdev_enable_disk_events(struct scsi_device *sdev);