Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ad55502 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by James Bottomley
Browse files

[SCSI] Update documentation



The documentation has gone out-of-sync, so update it to
the current status.

Signed-off-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent bb3b621a
Loading
Loading
Loading
Loading
+39 −30
Original line number Original line Diff line number Diff line
@@ -42,20 +42,14 @@ discussion.


 Once LLDD gets hold of a scmd, either the LLDD will complete the
 Once LLDD gets hold of a scmd, either the LLDD will complete the
command by calling scsi_done callback passed from midlayer when
command by calling scsi_done callback passed from midlayer when
invoking hostt->queuecommand() or SCSI midlayer will time it out.
invoking hostt->queuecommand() or the block layer will time it out.




[1-2-1] Completing a scmd w/ scsi_done
[1-2-1] Completing a scmd w/ scsi_done


 For all non-EH commands, scsi_done() is the completion callback.  It
 For all non-EH commands, scsi_done() is the completion callback.  It
does the following.
just calls blk_complete_request() to delete the block layer timer and

raise SCSI_SOFTIRQ
 1. Delete timeout timer.  If it fails, it means that timeout timer
    has expired and is going to finish the command.  Just return.

 2. Link scmd to per-cpu scsi_done_q using scmd->en_entry

 3. Raise SCSI_SOFTIRQ


 SCSI_SOFTIRQ handler scsi_softirq calls scsi_decide_disposition() to
 SCSI_SOFTIRQ handler scsi_softirq calls scsi_decide_disposition() to
determine what to do with the command.  scsi_decide_disposition()
determine what to do with the command.  scsi_decide_disposition()
@@ -64,10 +58,12 @@ with the command.


 - SUCCESS
 - SUCCESS
	scsi_finish_command() is invoked for the command.  The
	scsi_finish_command() is invoked for the command.  The
	function does some maintenance choirs and notify completion by
	function does some maintenance chores and then calls
	calling scmd->done() callback, which, for fs requests, would
	scsi_io_completion() to finish the I/O.
	be HLD completion callback - sd:sd_rw_intr, sr:rw_intr,
	scsi_io_completion() then notifies the block layer on
	st:st_intr.
	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.


 - NEEDS_RETRY
 - NEEDS_RETRY
 - ADD_TO_MLQUEUE
 - ADD_TO_MLQUEUE
@@ -86,33 +82,45 @@ function
 1. invokes optional hostt->eh_timed_out() callback.  Return value can
 1. invokes optional hostt->eh_timed_out() callback.  Return value can
    be one of
    be one of


    - EH_HANDLED
    - BLK_EH_HANDLED
	This indicates that eh_timed_out() dealt with the timeout.  The
	This indicates that eh_timed_out() dealt with the timeout.
	scmd is passed to __scsi_done() and thus linked into per-cpu
	The command is passed back to the block layer and completed
	scsi_done_q.  Normal command completion described in [1-2-1]
	via __blk_complete_requests().
	follows.

	*NOTE* After returning BLK_EH_HANDLED the SCSI layer is
	assumed to be finished with the command, and no other
	functions from the SCSI layer will be called. So this
	should typically only be returned if the eh_timed_out()
	handler raced with normal completion.


    - EH_RESET_TIMER
    - BLK_EH_RESET_TIMER
	This indicates that more time is required to finish the
	This indicates that more time is required to finish the
	command.  Timer is restarted.  This action is counted as a
	command.  Timer is restarted.  This action is counted as a
	retry and only allowed scmd->allowed + 1(!) times.  Once the
	retry and only allowed scmd->allowed + 1(!) times.  Once the
	limit is reached, action for EH_NOT_HANDLED is taken instead.
	limit is reached, action for BLK_EH_NOT_HANDLED is taken instead.


	*NOTE* This action is racy as the LLDD could finish the scmd
    - BLK_EH_NOT_HANDLED
	after the timeout has expired but before it's added back.  In
        eh_timed_out() callback did not handle the command.
	such cases, scsi_done() would think that timeout has occurred
	and return without doing anything.  We lose completion and the
	command will time out again.

    - EH_NOT_HANDLED
	This is the same as when eh_timed_out() callback doesn't exist.
	Step #2 is taken.
	Step #2 is taken.


 2. If the host supports asynchronous completion (as indicated by the
    no_async_abort setting in the host template) scsi_abort_command()
    is invoked to schedule an asynchrous abort. If that fails
    Step #3 is taken.

 2. scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD) is invoked for the
 2. scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD) is invoked for the
    command.  See [1-3] for more information.
    command.  See [1-3] for more information.


[1-3] Asynchronous command aborts


[1-3] How EH takes over
 After a timeout occurs a command abort is scheduled from
 scsi_abort_command(). If the abort is successful the command
 will either be retried (if the number of retries is not exhausted)
 or terminated with DID_TIME_OUT.
 Otherwise scsi_eh_scmd_add() is invoked for the command.
 See [1-4] for more information.

[1-4] How EH takes over


 scmds enter EH via scsi_eh_scmd_add(), which does the following.
 scmds enter EH via scsi_eh_scmd_add(), which does the following.


@@ -320,7 +328,8 @@ scmd->allowed.


    <<scsi_eh_abort_cmds>>
    <<scsi_eh_abort_cmds>>


	This action is taken for each timed out command.
	This action is taken for each timed out command when
	no_async_abort is enabled in the host template.
	hostt->eh_abort_handler() is invoked for each scmd.  The
	hostt->eh_abort_handler() is invoked for each scmd.  The
	handler returns SUCCESS if it has succeeded to make LLDD and
	handler returns SUCCESS if it has succeeded to make LLDD and
	all related hardware forget about the scmd.
	all related hardware forget about the scmd.
+7 −2
Original line number Original line Diff line number Diff line
@@ -882,8 +882,11 @@ Details:
 *
 *
 *      Calling context: kernel thread
 *      Calling context: kernel thread
 *
 *
 *      Notes: Invoked from scsi_eh thread. No other commands will be
 *      Notes: If 'no_async_abort' is defined this callback
 *      queued on current host during eh.
 *  	will be invoked from scsi_eh thread. No other commands
 *	will then be queued on current host during eh.
 *	Otherwise it will be called whenever scsi_times_out()
 *      is called due to a command timeout.
 *
 *
 *      Optionally defined in: LLD
 *      Optionally defined in: LLD
 **/
 **/
@@ -1257,6 +1260,8 @@ of interest:
                   address space
                   address space
    use_clustering - 1=>SCSI commands in mid level's queue can be merged,
    use_clustering - 1=>SCSI commands in mid level's queue can be merged,
                     0=>disallow SCSI command merging
                     0=>disallow SCSI command merging
    no_async_abort - 1=>Asynchronous aborts are not supported
                     0=>Timed-out commands will be aborted asynchronously
    hostt        - pointer to driver's struct scsi_host_template from which
    hostt        - pointer to driver's struct scsi_host_template from which
                   this struct Scsi_Host instance was spawned
                   this struct Scsi_Host instance was spawned
    hostt->proc_name  - name of LLD. This is the driver name that sysfs uses
    hostt->proc_name  - name of LLD. This is the driver name that sysfs uses
+2 −4
Original line number Original line Diff line number Diff line
@@ -745,15 +745,13 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
}
}


/**
/**
 * scsi_done - Enqueue the finished SCSI command into the done queue.
 * scsi_done - Invoke completion on finished SCSI command.
 * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives
 * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives
 * ownership back to SCSI Core -- i.e. the LLDD has finished with it.
 * ownership back to SCSI Core -- i.e. the LLDD has finished with it.
 *
 *
 * Description: This function is the mid-level's (SCSI Core) interrupt routine,
 * Description: This function is the mid-level's (SCSI Core) interrupt routine,
 * which regains ownership of the SCSI command (de facto) from a LLDD, and
 * which regains ownership of the SCSI command (de facto) from a LLDD, and
 * enqueues the command to the done queue for further processing.
 * calls blk_complete_request() for further processing.
 *
 * This is the producer of the done queue who enqueues at the tail.
 *
 *
 * This function is interrupt context safe.
 * This function is interrupt context safe.
 */
 */