Browse Source

isci: Add decode for SMP request retry error condition

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>
Jeff Skirvin 14 years ago
parent
commit
cde76fbf1f
2 changed files with 52 additions and 10 deletions
  1. 31 4
      drivers/scsi/isci/request.c
  2. 21 6
      drivers/scsi/isci/task.h

+ 31 - 4
drivers/scsi/isci/request.c

@@ -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;

+ 21 - 6
drivers/scsi/isci/task.h

@@ -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;
 	}