diff options
Diffstat (limited to 'drivers/scsi/isci/task.h')
-rw-r--r-- | drivers/scsi/isci/task.h | 53 |
1 files changed, 40 insertions, 13 deletions
diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index ced6a8be1b31..68d8e5e65a73 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -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. |