isci: Any reset indicated on an I/O completion escalates it to the error path.
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>
Fri, 4 Mar 2011 22:06:44 +0000 (14:06 -0800)
committerDan Williams <dan.j.williams@intel.com>
Sun, 3 Jul 2011 10:55:29 +0000 (03:55 -0700)
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>
drivers/scsi/isci/host.c
drivers/scsi/isci/request.c
drivers/scsi/isci/task.h

index 153f419..dc231c2 100644 (file)
@@ -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);
index c88e270..6cd80bb 100644 (file)
@@ -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:
index ced6a8b..68d8e5e 100644 (file)
@@ -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.