Commit ec6c9638 authored by Jeff Skirvin's avatar Jeff Skirvin Committed by Dan Williams
Browse files

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: default avatarJeff Skirvin <jeffrey.d.skirvin@intel.com>
Signed-off-by: default avatarJacek Danecki <Jacek.Danecki@intel.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent a5fde225
Loading
Loading
Loading
Loading
+0 −11
Original line number Diff line number Diff line
@@ -290,17 +290,6 @@ static void isci_host_completion_routine(unsigned long data)
	list_splice_init(&isci_host->requests_to_complete,
			 &completed_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);
+6 −3
Original line number Diff line number Diff line
@@ -790,10 +790,10 @@ static void isci_task_save_for_upper_layer_completion(
{
	struct sas_task *task = isci_request_access_task(request);

	isci_task_set_completion_status(task, response, status,
	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.
	 */
@@ -811,6 +811,9 @@ static void isci_task_save_for_upper_layer_completion(
		/* Add to the completed list. */
		list_add(&request->completed_node,
			 &host->requests_to_complete);

		/* Take the request off the device's pending request list. */
		list_del_init(&request->dev_node);
		break;

	case isci_perform_aborted_io_completion:
+40 −13
Original line number Diff line number Diff line
@@ -280,9 +280,10 @@ static inline void isci_task_all_done(
 * @response: This parameter is the response code for the completed task.
 * @status: This parameter is the status code for the completed task.
 *
 * none.
* @return The new notification mode for the request.
*/
static inline void isci_task_set_completion_status(
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 @@ static inline void isci_task_set_completion_status(
	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 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.
			*/
	if ((task_notification_selection != isci_perform_error_io_completion)
	    && !(task->task_state_flags & SAS_TASK_NEED_DEV_RESET))
			/* 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,10 +349,10 @@ static inline void isci_task_complete_for_upper_layer(
	enum exec_status status,
	enum isci_completion_selection task_notification_selection)
{
	isci_task_set_completion_status(task, response, status,
	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.
	 */