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>
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index 8bd1f7d..3a891d3 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -2508,9 +2508,16 @@
 		/* 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 @@
 			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 @@
 			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;