aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>2011-03-04 17:06:44 -0500
committerDan Williams <dan.j.williams@intel.com>2011-07-03 06:55:29 -0400
commitec6c9638b0d0537430f78a3e20503b5e68a537b6 (patch)
treeb6d05437adb1c8bc40a02e2fa82ff67df57aef6d
parenta5fde225364df30507ba1a5aafeec85e595000d3 (diff)
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>
-rw-r--r--drivers/scsi/isci/host.c11
-rw-r--r--drivers/scsi/isci/request.c9
-rw-r--r--drivers/scsi/isci/task.h53
3 files changed, 46 insertions, 27 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index 153f419f1618..dc231c22ea93 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -290,17 +290,6 @@ static void isci_host_completion_routine(unsigned long data)
290 list_splice_init(&isci_host->requests_to_complete, 290 list_splice_init(&isci_host->requests_to_complete,
291 &completed_request_list); 291 &completed_request_list);
292 292
293 /* While holding the scic_lock take all of the normally completed
294 * I/Os off of the device's pending lists.
295 */
296 list_for_each_entry(request, &completed_request_list, completed_node) {
297
298 /* Remove the request from the remote device's list
299 * of pending requests.
300 */
301 list_del_init(&request->dev_node);
302 }
303
304 /* Take the list of errored I/Os from the host. */ 293 /* Take the list of errored I/Os from the host. */
305 list_splice_init(&isci_host->requests_to_errorback, 294 list_splice_init(&isci_host->requests_to_errorback,
306 &errored_request_list); 295 &errored_request_list);
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index c88e270b2b40..6cd80bbdae15 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -790,9 +790,9 @@ static void isci_task_save_for_upper_layer_completion(
790{ 790{
791 struct sas_task *task = isci_request_access_task(request); 791 struct sas_task *task = isci_request_access_task(request);
792 792
793 isci_task_set_completion_status(task, response, status, 793 task_notification_selection
794 task_notification_selection); 794 = isci_task_set_completion_status(task, response, status,
795 795 task_notification_selection);
796 796
797 /* Tasks aborted specifically by a call to the lldd_abort_task 797 /* Tasks aborted specifically by a call to the lldd_abort_task
798 * function should not be completed to the host in the regular path. 798 * 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(
811 /* Add to the completed list. */ 811 /* Add to the completed list. */
812 list_add(&request->completed_node, 812 list_add(&request->completed_node,
813 &host->requests_to_complete); 813 &host->requests_to_complete);
814
815 /* Take the request off the device's pending request list. */
816 list_del_init(&request->dev_node);
814 break; 817 break;
815 818
816 case isci_perform_aborted_io_completion: 819 case isci_perform_aborted_io_completion:
diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h
index ced6a8be1b31..68d8e5e65a73 100644
--- a/drivers/scsi/isci/task.h
+++ b/drivers/scsi/isci/task.h
@@ -280,9 +280,10 @@ static inline void isci_task_all_done(
280 * @response: This parameter is the response code for the completed task. 280 * @response: This parameter is the response code for the completed task.
281 * @status: This parameter is the status code for the completed task. 281 * @status: This parameter is the status code for the completed task.
282 * 282 *
283 * none. 283* @return The new notification mode for the request.
284 */ 284*/
285static inline void isci_task_set_completion_status( 285static inline enum isci_completion_selection
286isci_task_set_completion_status(
286 struct sas_task *task, 287 struct sas_task *task,
287 enum service_response response, 288 enum service_response response,
288 enum exec_status status, 289 enum exec_status status,
@@ -295,15 +296,41 @@ static inline void isci_task_set_completion_status(
295 task->task_status.resp = response; 296 task->task_status.resp = response;
296 task->task_status.stat = status; 297 task->task_status.stat = status;
297 298
298 /* Don't set DONE (or clear AT_INITIATOR) for any task going into the 299 /* If a device reset is being indicated, make sure the I/O
299 * error path, because the EH interprets that as a handled error condition. 300 * is in the error path.
300 * Also don't take action if there is a reset pending. 301 */
301 */ 302 if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET)
302 if ((task_notification_selection != isci_perform_error_io_completion) 303 task_notification_selection = isci_perform_error_io_completion;
303 && !(task->task_state_flags & SAS_TASK_NEED_DEV_RESET)) 304
304 isci_set_task_doneflags(task); 305 switch (task_notification_selection) {
306
307 case isci_perform_aborted_io_completion:
308 /* This path can occur with task-managed requests as well as
309 * requests terminated because of LUN or device resets.
310 */
311 /* Fall through to the normal case... */
312
313 case isci_perform_normal_io_completion:
314 /* Normal notification (task_done) */
315 isci_set_task_doneflags(task);
316 break;
317
318 default:
319 WARN_ON(FALSE);
320 /* Fall through to the error case... */
321
322 case isci_perform_error_io_completion:
323 /* Use sas_task_abort */
324 /* Leave SAS_TASK_STATE_DONE clear
325 * Leave SAS_TASK_AT_INITIATOR set.
326 */
327 break;
328 }
305 329
306 spin_unlock_irqrestore(&task->task_state_lock, flags); 330 spin_unlock_irqrestore(&task->task_state_lock, flags);
331
332 return task_notification_selection;
333
307} 334}
308/** 335/**
309 * isci_task_complete_for_upper_layer() - This function completes the request 336 * isci_task_complete_for_upper_layer() - This function completes the request
@@ -322,9 +349,9 @@ static inline void isci_task_complete_for_upper_layer(
322 enum exec_status status, 349 enum exec_status status,
323 enum isci_completion_selection task_notification_selection) 350 enum isci_completion_selection task_notification_selection)
324{ 351{
325 isci_task_set_completion_status(task, response, status, 352 task_notification_selection
326 task_notification_selection); 353 = isci_task_set_completion_status(task, response, status,
327 354 task_notification_selection);
328 355
329 /* Tasks aborted specifically by a call to the lldd_abort_task 356 /* Tasks aborted specifically by a call to the lldd_abort_task
330 * function should not be completed to the host in the regular path. 357 * function should not be completed to the host in the regular path.