isci: Any reset indicated on an I/O completion escalates it to the error path.
If there is a pending device reset, the I/O is used to accomplish the reset by setting the RESET bit in the task status, and then putting the task into the error handler path using sas abort task. Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com> Signed-off-by: Jacek Danecki <Jacek.Danecki@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
parent
a5fde22536
commit
ec6c9638b0
3 changed files with 46 additions and 27 deletions
|
@ -290,17 +290,6 @@ static void isci_host_completion_routine(unsigned long data)
|
|||
list_splice_init(&isci_host->requests_to_complete,
|
||||
&completed_request_list);
|
||||
|
||||
/* While holding the scic_lock take all of the normally completed
|
||||
* I/Os off of the device's pending lists.
|
||||
*/
|
||||
list_for_each_entry(request, &completed_request_list, completed_node) {
|
||||
|
||||
/* Remove the request from the remote device's list
|
||||
* of pending requests.
|
||||
*/
|
||||
list_del_init(&request->dev_node);
|
||||
}
|
||||
|
||||
/* Take the list of errored I/Os from the host. */
|
||||
list_splice_init(&isci_host->requests_to_errorback,
|
||||
&errored_request_list);
|
||||
|
|
|
@ -790,9 +790,9 @@ static void isci_task_save_for_upper_layer_completion(
|
|||
{
|
||||
struct sas_task *task = isci_request_access_task(request);
|
||||
|
||||
isci_task_set_completion_status(task, response, status,
|
||||
task_notification_selection);
|
||||
|
||||
task_notification_selection
|
||||
= isci_task_set_completion_status(task, response, status,
|
||||
task_notification_selection);
|
||||
|
||||
/* Tasks aborted specifically by a call to the lldd_abort_task
|
||||
* function should not be completed to the host in the regular path.
|
||||
|
@ -811,6 +811,9 @@ static void isci_task_save_for_upper_layer_completion(
|
|||
/* Add to the completed list. */
|
||||
list_add(&request->completed_node,
|
||||
&host->requests_to_complete);
|
||||
|
||||
/* Take the request off the device's pending request list. */
|
||||
list_del_init(&request->dev_node);
|
||||
break;
|
||||
|
||||
case isci_perform_aborted_io_completion:
|
||||
|
|
|
@ -280,9 +280,10 @@ static inline void isci_task_all_done(
|
|||
* @response: This parameter is the response code for the completed task.
|
||||
* @status: This parameter is the status code for the completed task.
|
||||
*
|
||||
* none.
|
||||
*/
|
||||
static inline void isci_task_set_completion_status(
|
||||
* @return The new notification mode for the request.
|
||||
*/
|
||||
static inline enum isci_completion_selection
|
||||
isci_task_set_completion_status(
|
||||
struct sas_task *task,
|
||||
enum service_response response,
|
||||
enum exec_status status,
|
||||
|
@ -295,15 +296,41 @@ static inline void isci_task_set_completion_status(
|
|||
task->task_status.resp = response;
|
||||
task->task_status.stat = status;
|
||||
|
||||
/* Don't set DONE (or clear AT_INITIATOR) for any task going into the
|
||||
* error path, because the EH interprets that as a handled error condition.
|
||||
* Also don't take action if there is a reset pending.
|
||||
*/
|
||||
if ((task_notification_selection != isci_perform_error_io_completion)
|
||||
&& !(task->task_state_flags & SAS_TASK_NEED_DEV_RESET))
|
||||
isci_set_task_doneflags(task);
|
||||
/* If a device reset is being indicated, make sure the I/O
|
||||
* is in the error path.
|
||||
*/
|
||||
if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET)
|
||||
task_notification_selection = isci_perform_error_io_completion;
|
||||
|
||||
switch (task_notification_selection) {
|
||||
|
||||
case isci_perform_aborted_io_completion:
|
||||
/* This path can occur with task-managed requests as well as
|
||||
* requests terminated because of LUN or device resets.
|
||||
*/
|
||||
/* Fall through to the normal case... */
|
||||
|
||||
case isci_perform_normal_io_completion:
|
||||
/* Normal notification (task_done) */
|
||||
isci_set_task_doneflags(task);
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN_ON(FALSE);
|
||||
/* Fall through to the error case... */
|
||||
|
||||
case isci_perform_error_io_completion:
|
||||
/* Use sas_task_abort */
|
||||
/* Leave SAS_TASK_STATE_DONE clear
|
||||
* Leave SAS_TASK_AT_INITIATOR set.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
|
||||
return task_notification_selection;
|
||||
|
||||
}
|
||||
/**
|
||||
* isci_task_complete_for_upper_layer() - This function completes the request
|
||||
|
@ -322,9 +349,9 @@ static inline void isci_task_complete_for_upper_layer(
|
|||
enum exec_status status,
|
||||
enum isci_completion_selection task_notification_selection)
|
||||
{
|
||||
isci_task_set_completion_status(task, response, status,
|
||||
task_notification_selection);
|
||||
|
||||
task_notification_selection
|
||||
= isci_task_set_completion_status(task, response, status,
|
||||
task_notification_selection);
|
||||
|
||||
/* Tasks aborted specifically by a call to the lldd_abort_task
|
||||
* function should not be completed to the host in the regular path.
|
||||
|
|
Loading…
Reference in a new issue