isci: Changes in isci_host_completion_routine
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>
Fri, 4 Mar 2011 22:06:40 +0000 (14:06 -0800)
committerDan Williams <dan.j.williams@intel.com>
Sun, 3 Jul 2011 10:55:29 +0000 (03:55 -0700)
Changes to move management of the reqs_in_process entry for the request here.
Made changes to note when the task is already in the abort path and
cannot be completed through callbacks.

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/host.h
drivers/scsi/isci/request.c

index ae5d460..153f419 100644 (file)
@@ -270,27 +270,40 @@ static int isci_host_mdl_allocate_coherent(
 static void isci_host_completion_routine(unsigned long data)
 {
        struct isci_host *isci_host = (struct isci_host *)data;
-       struct list_head completed_request_list;
-       struct list_head aborted_request_list;
-       struct list_head *current_position;
-       struct list_head *next_position;
+       struct list_head    completed_request_list;
+       struct list_head    errored_request_list;
+       struct list_head    *current_position;
+       struct list_head    *next_position;
        struct isci_request *request;
        struct isci_request *next_request;
-       struct sas_task *task;
+       struct sas_task     *task;
 
        INIT_LIST_HEAD(&completed_request_list);
-       INIT_LIST_HEAD(&aborted_request_list);
+       INIT_LIST_HEAD(&errored_request_list);
 
        spin_lock_irq(&isci_host->scic_lock);
 
        scic_sds_controller_completion_handler(isci_host->core_controller);
 
        /* Take the lists of completed I/Os from the host. */
+
        list_splice_init(&isci_host->requests_to_complete,
                         &completed_request_list);
 
-       list_splice_init(&isci_host->requests_to_abort,
-                        &aborted_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);
 
        spin_unlock_irq(&isci_host->scic_lock);
 
@@ -309,13 +322,22 @@ static void isci_host_completion_routine(unsigned long data)
                        request,
                        task);
 
-               task->task_done(task);
-               task->lldd_task = NULL;
+               /* Return the task to libsas */
+               if (task != NULL) {
+
+                       task->lldd_task = NULL;
+                       if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
 
+                               /* If the task is already in the abort path,
+                               * the task_done callback cannot be called.
+                               */
+                               task->task_done(task);
+                       }
+               }
                /* Free the request object. */
                isci_request_free(isci_host, request);
        }
-       list_for_each_entry_safe(request, next_request, &aborted_request_list,
+       list_for_each_entry_safe(request, next_request, &errored_request_list,
                                 completed_node) {
 
                task = isci_request_access_task(request);
@@ -327,8 +349,33 @@ static void isci_host_completion_routine(unsigned long data)
                         request,
                         task);
 
-               /* Put the task into the abort path. */
-               sas_task_abort(task);
+               if (task != NULL) {
+
+                       /* Put the task into the abort path if it's not there
+                        * already.
+                        */
+                       if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED))
+                               sas_task_abort(task);
+
+               } else {
+                       /* This is a case where the request has completed with a
+                        * status such that it needed further target servicing,
+                        * but the sas_task reference has already been removed
+                        * from the request.  Since it was errored, it was not
+                        * being aborted, so there is nothing to do except free
+                        * it.
+                        */
+
+                       spin_lock_irq(&isci_host->scic_lock);
+                       /* Remove the request from the remote device's list
+                       * of pending requests.
+                       */
+                       list_del_init(&request->dev_node);
+                       spin_unlock_irq(&isci_host->scic_lock);
+
+                       /* Free the request object. */
+                       isci_request_free(isci_host, request);
+               }
        }
 
 }
@@ -477,7 +524,7 @@ int isci_host_init(struct isci_host *isci_host)
        INIT_LIST_HEAD(&(isci_host->mdl_struct_list));
 
        INIT_LIST_HEAD(&isci_host->requests_to_complete);
-       INIT_LIST_HEAD(&isci_host->requests_to_abort);
+       INIT_LIST_HEAD(&isci_host->requests_to_errorback);
 
        spin_lock_irq(&isci_host->scic_lock);
        status = scic_controller_initialize(isci_host->core_controller);
index 3c69f1f..889a785 100644 (file)
@@ -116,7 +116,7 @@ struct isci_host {
        struct tasklet_struct completion_tasklet;
        struct list_head mdl_struct_list;
        struct list_head requests_to_complete;
-       struct list_head requests_to_abort;
+       struct list_head requests_to_errorback;
        spinlock_t scic_lock;
 
        /* careful only access this via idev_by_id */
index 6b0863e..8039f1c 100644 (file)
@@ -836,7 +836,7 @@ static void isci_task_save_for_upper_layer_completion(
                         status);
                /* Add to the aborted list. */
                list_add(&request->completed_node,
-                        &host->requests_to_abort);
+                        &host->requests_to_errorback);
                break;
 
        default:
@@ -849,7 +849,7 @@ static void isci_task_save_for_upper_layer_completion(
 
                /* Add to the aborted list. */
                list_add(&request->completed_node,
-                        &host->requests_to_abort);
+                        &host->requests_to_errorback);
                break;
        }
 }
@@ -1185,14 +1185,6 @@ void isci_request_io_request_complete(
         */
        request->sci_request_handle = NULL;
 
-       /* Only remove the request from the remote device list
-        * of pending requests if we have not requested error
-        * handling on this request.
-        */
-       if (complete_to_host != isci_perform_error_io_completion)
-               list_del_init(&request->dev_node);
-
-
        /* Save possible completion ptr. */
        io_request_completion = request->io_request_completion;