diff options
author | Jeff Skirvin <jeffrey.d.skirvin@intel.com> | 2011-03-04 17:06:44 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 06:55:29 -0400 |
commit | ec6c9638b0d0537430f78a3e20503b5e68a537b6 (patch) | |
tree | b6d05437adb1c8bc40a02e2fa82ff67df57aef6d | |
parent | a5fde225364df30507ba1a5aafeec85e595000d3 (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.c | 11 | ||||
-rw-r--r-- | drivers/scsi/isci/request.c | 9 | ||||
-rw-r--r-- | drivers/scsi/isci/task.h | 53 |
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 | */ |
285 | static inline void isci_task_set_completion_status( | 285 | static inline enum isci_completion_selection |
286 | isci_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. |