Signed-off-by: Christoph Hellwig <[email protected]>
---
Documentation/scsi/scsi_eh.txt | 12 +++---
drivers/scsi/scsi.c | 58 -----------------------------
drivers/scsi/scsi_lib.c | 84 +++++++++++++++++++++++++++---------------
drivers/scsi/scsi_priv.h | 1 -
4 files changed, 59 insertions(+), 96 deletions(-)
diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.txt
index a0c8511..8a7ac48 100644
--- a/Documentation/scsi/scsi_eh.txt
+++ b/Documentation/scsi/scsi_eh.txt
@@ -57,13 +57,11 @@ looks at the scmd->result value and sense data to determine
what to do
with the command.
- SUCCESS
- scsi_finish_command() is invoked for the command. The
- function does some maintenance chores and then calls
- scsi_io_completion() to finish the I/O.
- scsi_io_completion() then notifies the block layer on
- the completed request by calling blk_end_request and
- friends or figures out what to do with the remainder
- of the data in case of an error.
+ scsi_finish_command() is invoked for the command. The function
+ does some maintenance chores and then notifies the block layer on
+ the completed request by calling blk_end_request / __blk_mq_end_io
+ or figures out what to do with the remainder of the data in case
+ of an error.
- NEEDS_RETRY
- ADD_TO_MLQUEUE
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index a86ccb7..cdc0686 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -626,64 +626,6 @@ void scsi_cmd_get_serial(struct Scsi_Host *host, struct
scsi_cmnd *cmd)
EXPORT_SYMBOL(scsi_cmd_get_serial);
/**
- * scsi_finish_command - cleanup and pass command back to upper layer
- * @cmd: the command
- *
- * Description: Pass command off to upper layer for finishing of I/O
- * request, waking processes that are waiting on results,
- * etc.
- */
-void scsi_finish_command(struct scsi_cmnd *cmd)
-{
- struct scsi_device *sdev = cmd->device;
- struct scsi_target *starget = scsi_target(sdev);
- struct Scsi_Host *shost = sdev->host;
- struct scsi_driver *drv;
- unsigned int good_bytes;
-
- scsi_device_unbusy(sdev);
-
- /*
- * Clear the flags that say that the device/target/host is no longer
- * capable of accepting new commands.
- */
- if (atomic_read(&shost->host_blocked))
- atomic_set(&shost->host_blocked, 0);
- if (atomic_read(&starget->target_blocked))
- atomic_set(&starget->target_blocked, 0);
- if (atomic_read(&sdev->device_blocked))
- atomic_set(&sdev->device_blocked, 0);
-
- /*
- * If we have valid sense information, then some kind of recovery
- * must have taken place. Make a note of this.
- */
- if (SCSI_SENSE_VALID(cmd))
- cmd->result |= (DRIVER_SENSE << 24);
-
- SCSI_LOG_MLCOMPLETE(4, sdev_printk(KERN_INFO, sdev,
- "Notifying upper driver of completion "
- "(result %x)\n", cmd->result));
-
- good_bytes = scsi_bufflen(cmd);
- if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
- int old_good_bytes = good_bytes;
- drv = scsi_cmd_to_driver(cmd);
- if (drv->done)
- good_bytes = drv->done(cmd);
- /*
- * USB may not give sense identifying bad sector and
- * simply return a residue instead, so subtract off the
- * residue if drv->done() error processing indicates no
- * change to the completion length.
- */
- if (good_bytes == old_good_bytes)
- good_bytes -= scsi_get_resid(cmd);
- }
- scsi_io_completion(cmd, good_bytes);
-}
-
-/**
* scsi_adjust_queue_depth - Let low level drivers change a device's queue
depth
* @sdev: SCSI Device in question
* @tagged: Do we use tagged queueing (non-0) or do we treat
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index cc5d404..e0eb809 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -868,44 +868,68 @@ scsi_handle_ioerror(struct scsi_cmnd *cmd, int result,
return true;
}
-/*
- * Function: scsi_io_completion()
- *
- * Purpose: Completion processing for block device I/O requests.
- *
- * Arguments: cmd - command that is finished.
- *
- * Lock status: Assumed that no lock is held upon entry.
- *
- * Returns: Nothing
- *
- * Notes: We will finish off the specified number of sectors. If we
- * are done, the command block will be released and the queue
- * function will be goosed. If we are not done then we have to
- * figure out what to do next:
- *
- * a) We can call scsi_requeue_command(). The request
- * will be unprepared and put back on the queue. Then
- * a new command will be created for it. This should
- * be used if we made forward progress, or if we want
- * to switch from READ(10) to READ(6) for example.
- *
- * b) We can call __scsi_queue_insert(). The request will
- * be put back on the queue and retried using the same
- * command as before, possibly after a delay.
+/**
+ * scsi_finish_command - handle I/O completion on a command
+ * @cmd: command to complete
*
- * c) We can call scsi_end_request() with -EIO to fail
- * the remainder of the request.
+ * Finish off the number of bytes returned by the driver. If the whole command
+ * has been completed return it to the block layer. If it hasn't figure out
+ * what to do based on the result from the driver and the sense code.
*/
-void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+void scsi_finish_command(struct scsi_cmnd *cmd)
{
- int result = cmd->result;
struct request *req = cmd->request;
- int error = 0;
+ struct scsi_device *sdev = cmd->device;
+ struct scsi_target *starget = scsi_target(sdev);
+ struct Scsi_Host *shost = sdev->host;
struct scsi_sense_hdr sshdr;
+ struct scsi_driver *drv;
+ unsigned int good_bytes;
int sense_valid = 0;
int sense_deferred = 0;
+ int error = 0, result;
+
+ scsi_device_unbusy(sdev);
+
+ /*
+ * Clear the flags that say that the device/target/host is no longer
+ * capable of accepting new commands.
+ */
+ if (atomic_read(&shost->host_blocked))
+ atomic_set(&shost->host_blocked, 0);
+ if (atomic_read(&starget->target_blocked))
+ atomic_set(&starget->target_blocked, 0);
+ if (atomic_read(&sdev->device_blocked))
+ atomic_set(&sdev->device_blocked, 0);
+
+ /*
+ * If we have valid sense information, then some kind of recovery
+ * must have taken place. Make a note of this.
+ */
+ if (SCSI_SENSE_VALID(cmd))
+ cmd->result |= (DRIVER_SENSE << 24);
+
+ SCSI_LOG_MLCOMPLETE(4, sdev_printk(KERN_INFO, sdev,
+ "Notifying upper driver of completion "
+ "(result %x)\n", cmd->result));
+
+ good_bytes = scsi_bufflen(cmd);
+ if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
+ int old_good_bytes = good_bytes;
+ drv = scsi_cmd_to_driver(cmd);
+ if (drv->done)
+ good_bytes = drv->done(cmd);
+ /*
+ * USB may not give sense identifying bad sector and
+ * simply return a residue instead, so subtract off the
+ * residue if drv->done() error processing indicates no
+ * change to the completion length.
+ */
+ if (good_bytes == old_good_bytes)
+ good_bytes -= scsi_get_resid(cmd);
+ }
+ result = cmd->result;
if (result) {
sense_valid = scsi_command_normalize_sense(cmd, &sshdr);
if (sense_valid)
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 2dc4a83..87c6c5a 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -83,7 +83,6 @@ int scsi_noretry_cmd(struct scsi_cmnd *scmd);
extern int scsi_maybe_unblock_host(struct scsi_device *sdev);
extern void scsi_device_unbusy(struct scsi_device *sdev);
extern void scsi_queue_insert(struct scsi_cmnd *cmd, int reason);
-extern void scsi_io_completion(struct scsi_cmnd *, unsigned int);
extern void scsi_run_host_queues(struct Scsi_Host *shost);
extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev);
extern struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev);
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html