diff options
author | Jeff Skirvin <jeffrey.d.skirvin@intel.com> | 2011-06-20 17:09:06 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 07:04:50 -0400 |
commit | cde76fbf1f27551a08860227765ae8d5026ac0d9 (patch) | |
tree | 15b05ab39908e634cd633232025025d54a94a0ed | |
parent | 61aaff49e20fdb700f1300a49962bc76effc77fc (diff) |
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>
-rw-r--r-- | drivers/scsi/isci/request.c | 35 | ||||
-rw-r--r-- | drivers/scsi/isci/task.h | 27 |
2 files changed, 52 insertions, 10 deletions
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 8bd1f7dbad37..3a891d32c331 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c | |||
@@ -2508,9 +2508,16 @@ static void isci_request_handle_controller_specific_errors( | |||
2508 | /* Task in the target is not done. */ | 2508 | /* Task in the target is not done. */ |
2509 | *response_ptr = SAS_TASK_UNDELIVERED; | 2509 | *response_ptr = SAS_TASK_UNDELIVERED; |
2510 | *status_ptr = SAM_STAT_TASK_ABORTED; | 2510 | *status_ptr = SAM_STAT_TASK_ABORTED; |
2511 | request->complete_in_target = false; | ||
2512 | 2511 | ||
2513 | *complete_to_host_ptr = isci_perform_error_io_completion; | 2512 | if (task->task_proto == SAS_PROTOCOL_SMP) { |
2513 | request->complete_in_target = true; | ||
2514 | |||
2515 | *complete_to_host_ptr = isci_perform_normal_io_completion; | ||
2516 | } else { | ||
2517 | request->complete_in_target = false; | ||
2518 | |||
2519 | *complete_to_host_ptr = isci_perform_error_io_completion; | ||
2520 | } | ||
2514 | break; | 2521 | break; |
2515 | } | 2522 | } |
2516 | } | 2523 | } |
@@ -2882,6 +2889,21 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, | |||
2882 | request->complete_in_target = false; | 2889 | request->complete_in_target = false; |
2883 | break; | 2890 | break; |
2884 | 2891 | ||
2892 | case SCI_FAILURE_RETRY_REQUIRED: | ||
2893 | |||
2894 | /* Fail the I/O so it can be retried. */ | ||
2895 | response = SAS_TASK_UNDELIVERED; | ||
2896 | if ((isci_device->status == isci_stopping) || | ||
2897 | (isci_device->status == isci_stopped)) | ||
2898 | status = SAS_DEVICE_UNKNOWN; | ||
2899 | else | ||
2900 | status = SAS_ABORTED_TASK; | ||
2901 | |||
2902 | complete_to_host = isci_perform_normal_io_completion; | ||
2903 | request->complete_in_target = true; | ||
2904 | break; | ||
2905 | |||
2906 | |||
2885 | default: | 2907 | default: |
2886 | /* Catch any otherwise unhandled error codes here. */ | 2908 | /* Catch any otherwise unhandled error codes here. */ |
2887 | dev_warn(&isci_host->pdev->dev, | 2909 | dev_warn(&isci_host->pdev->dev, |
@@ -2901,8 +2923,13 @@ static void isci_request_io_request_complete(struct isci_host *isci_host, | |||
2901 | else | 2923 | else |
2902 | status = SAS_ABORTED_TASK; | 2924 | status = SAS_ABORTED_TASK; |
2903 | 2925 | ||
2904 | complete_to_host = isci_perform_error_io_completion; | 2926 | if (SAS_PROTOCOL_SMP == task->task_proto) { |
2905 | request->complete_in_target = false; | 2927 | request->complete_in_target = true; |
2928 | complete_to_host = isci_perform_normal_io_completion; | ||
2929 | } else { | ||
2930 | request->complete_in_target = false; | ||
2931 | complete_to_host = isci_perform_error_io_completion; | ||
2932 | } | ||
2906 | break; | 2933 | break; |
2907 | } | 2934 | } |
2908 | break; | 2935 | break; |
diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index 432b81aecd47..c8dd075d2be2 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h | |||
@@ -301,6 +301,27 @@ isci_task_set_completion_status( | |||
301 | task->task_status.stat = status; | 301 | task->task_status.stat = status; |
302 | 302 | ||
303 | switch (task_notification_selection) { | 303 | switch (task_notification_selection) { |
304 | |||
305 | case isci_perform_error_io_completion: | ||
306 | |||
307 | if (task->task_proto == SAS_PROTOCOL_SMP) { | ||
308 | /* There is no error escalation in the SMP case. | ||
309 | * Convert to a normal completion to avoid the | ||
310 | * timeout in the discovery path and to let the | ||
311 | * next action take place quickly. | ||
312 | */ | ||
313 | task_notification_selection | ||
314 | = isci_perform_normal_io_completion; | ||
315 | |||
316 | /* Fall through to the normal case... */ | ||
317 | } else { | ||
318 | /* Use sas_task_abort */ | ||
319 | /* Leave SAS_TASK_STATE_DONE clear | ||
320 | * Leave SAS_TASK_AT_INITIATOR set. | ||
321 | */ | ||
322 | break; | ||
323 | } | ||
324 | |||
304 | case isci_perform_aborted_io_completion: | 325 | case isci_perform_aborted_io_completion: |
305 | /* This path can occur with task-managed requests as well as | 326 | /* This path can occur with task-managed requests as well as |
306 | * requests terminated because of LUN or device resets. | 327 | * requests terminated because of LUN or device resets. |
@@ -313,12 +334,6 @@ isci_task_set_completion_status( | |||
313 | default: | 334 | default: |
314 | WARN_ONCE(1, "unknown task_notification_selection: %d\n", | 335 | WARN_ONCE(1, "unknown task_notification_selection: %d\n", |
315 | task_notification_selection); | 336 | task_notification_selection); |
316 | /* Fall through to the error case... */ | ||
317 | case isci_perform_error_io_completion: | ||
318 | /* Use sas_task_abort */ | ||
319 | /* Leave SAS_TASK_STATE_DONE clear | ||
320 | * Leave SAS_TASK_AT_INITIATOR set. | ||
321 | */ | ||
322 | break; | 337 | break; |
323 | } | 338 | } |
324 | 339 | ||