isci: Any reset indicated on an I/O completion escalates it to the error path.

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>
diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h
index ced6a8b..68d8e5e 100644
--- a/drivers/scsi/isci/task.h
+++ b/drivers/scsi/isci/task.h
@@ -280,9 +280,10 @@
  * @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 @@
 	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 @@
 	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.