isci: Add decode for SMP request retry error condition
Jeff Skirvin [Mon, 20 Jun 2011 21:09:06 +0000 (14:09 -0700)]
There are situations with slow expanders in which a first attempt
to execute an SMP request will fail with a timeout.  Immediate
subsequent retries will generally succeed.  This change makes sure
SMP I/O failures are immediately failed to libsas so that retries
happen with no discovery process timeout delay.

Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>

drivers/scsi/isci/request.c
drivers/scsi/isci/task.h

index 8bd1f7d..3a891d3 100644 (file)
@@ -2508,9 +2508,16 @@ static void isci_request_handle_controller_specific_errors(
                /* Task in the target is not done. */
                *response_ptr = SAS_TASK_UNDELIVERED;
                *status_ptr = SAM_STAT_TASK_ABORTED;
-               request->complete_in_target = false;
 
-               *complete_to_host_ptr = isci_perform_error_io_completion;
+               if (task->task_proto == SAS_PROTOCOL_SMP) {
+                       request->complete_in_target = true;
+
+                       *complete_to_host_ptr = isci_perform_normal_io_completion;
+               } else {
+                       request->complete_in_target = false;
+
+                       *complete_to_host_ptr = isci_perform_error_io_completion;
+               }
                break;
        }
 }
@@ -2882,6 +2889,21 @@ static void isci_request_io_request_complete(struct isci_host *isci_host,
                        request->complete_in_target = false;
                        break;
 
+               case SCI_FAILURE_RETRY_REQUIRED:
+
+                       /* Fail the I/O so it can be retried. */
+                       response = SAS_TASK_UNDELIVERED;
+                       if ((isci_device->status == isci_stopping) ||
+                           (isci_device->status == isci_stopped))
+                               status = SAS_DEVICE_UNKNOWN;
+                       else
+                               status = SAS_ABORTED_TASK;
+
+                       complete_to_host = isci_perform_normal_io_completion;
+                       request->complete_in_target = true;
+                       break;
+
+
                default:
                        /* Catch any otherwise unhandled error codes here. */
                        dev_warn(&isci_host->pdev->dev,
@@ -2901,8 +2923,13 @@ static void isci_request_io_request_complete(struct isci_host *isci_host,
                        else
                                status = SAS_ABORTED_TASK;
 
-                       complete_to_host = isci_perform_error_io_completion;
-                       request->complete_in_target = false;
+                       if (SAS_PROTOCOL_SMP == task->task_proto) {
+                               request->complete_in_target = true;
+                               complete_to_host = isci_perform_normal_io_completion;
+                       } else {
+                               request->complete_in_target = false;
+                               complete_to_host = isci_perform_error_io_completion;
+                       }
                        break;
                }
                break;
index 432b81a..c8dd075 100644 (file)
@@ -301,6 +301,27 @@ isci_task_set_completion_status(
        task->task_status.stat = status;
 
        switch (task_notification_selection) {
+
+       case isci_perform_error_io_completion:
+
+               if (task->task_proto == SAS_PROTOCOL_SMP) {
+                       /* There is no error escalation in the SMP case.
+                        * Convert to a normal completion to avoid the
+                        * timeout in the discovery path and to let the
+                        * next action take place quickly.
+                        */
+                       task_notification_selection
+                               = isci_perform_normal_io_completion;
+
+                       /* Fall through to the normal case... */
+               } else {
+                       /* Use sas_task_abort */
+                       /* Leave SAS_TASK_STATE_DONE clear
+                        * Leave SAS_TASK_AT_INITIATOR set.
+                        */
+                       break;
+               }
+
        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.
@@ -313,12 +334,6 @@ isci_task_set_completion_status(
        default:
                WARN_ONCE(1, "unknown task_notification_selection: %d\n",
                         task_notification_selection);
-               /* 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;
        }