diff options
author | Jeff Skirvin <jeffrey.d.skirvin@intel.com> | 2012-03-09 01:41:54 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2012-05-17 17:33:38 -0400 |
commit | 14aaa9f0a318bd04cbb9d822524b817e95d8b343 (patch) | |
tree | 5f6292ec671d0993c1df51586dea4fb7750d1cd9 /drivers/scsi/isci/host.c | |
parent | d80ecd5726ce49b5da457d562804b40f0183e8f7 (diff) |
isci: Redesign device suspension, abort, cleanup.
This commit changes the means by which outstanding I/Os are handled
for cleanup.
The likelihood is that this commit will be broken into smaller pieces,
however that will be a later revision. Among the changes:
- All completion structures have been removed from the tmf and
abort paths.
- Now using one completed I/O list, with the I/O completed in host bit being
used to select error or normal callback paths.
Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/scsi/isci/host.c')
-rw-r--r-- | drivers/scsi/isci/host.c | 86 |
1 files changed, 26 insertions, 60 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index d241b5722eb3..25d537e2f5c4 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c | |||
@@ -1089,33 +1089,25 @@ void isci_host_completion_routine(unsigned long data) | |||
1089 | { | 1089 | { |
1090 | struct isci_host *ihost = (struct isci_host *)data; | 1090 | struct isci_host *ihost = (struct isci_host *)data; |
1091 | struct list_head completed_request_list; | 1091 | struct list_head completed_request_list; |
1092 | struct list_head errored_request_list; | ||
1093 | struct list_head *current_position; | 1092 | struct list_head *current_position; |
1094 | struct list_head *next_position; | 1093 | struct list_head *next_position; |
1095 | struct isci_request *request; | 1094 | struct isci_request *request; |
1096 | struct isci_request *next_request; | ||
1097 | struct sas_task *task; | 1095 | struct sas_task *task; |
1098 | u16 active; | 1096 | u16 active; |
1099 | 1097 | ||
1100 | INIT_LIST_HEAD(&completed_request_list); | 1098 | INIT_LIST_HEAD(&completed_request_list); |
1101 | INIT_LIST_HEAD(&errored_request_list); | ||
1102 | 1099 | ||
1103 | spin_lock_irq(&ihost->scic_lock); | 1100 | spin_lock_irq(&ihost->scic_lock); |
1104 | 1101 | ||
1105 | sci_controller_completion_handler(ihost); | 1102 | sci_controller_completion_handler(ihost); |
1106 | 1103 | ||
1107 | /* Take the lists of completed I/Os from the host. */ | 1104 | /* Take the lists of completed I/Os from the host. */ |
1108 | |||
1109 | list_splice_init(&ihost->requests_to_complete, | 1105 | list_splice_init(&ihost->requests_to_complete, |
1110 | &completed_request_list); | 1106 | &completed_request_list); |
1111 | 1107 | ||
1112 | /* Take the list of errored I/Os from the host. */ | ||
1113 | list_splice_init(&ihost->requests_to_errorback, | ||
1114 | &errored_request_list); | ||
1115 | |||
1116 | spin_unlock_irq(&ihost->scic_lock); | 1108 | spin_unlock_irq(&ihost->scic_lock); |
1117 | 1109 | ||
1118 | /* Process any completions in the lists. */ | 1110 | /* Process any completions in the list. */ |
1119 | list_for_each_safe(current_position, next_position, | 1111 | list_for_each_safe(current_position, next_position, |
1120 | &completed_request_list) { | 1112 | &completed_request_list) { |
1121 | 1113 | ||
@@ -1123,23 +1115,30 @@ void isci_host_completion_routine(unsigned long data) | |||
1123 | completed_node); | 1115 | completed_node); |
1124 | task = isci_request_access_task(request); | 1116 | task = isci_request_access_task(request); |
1125 | 1117 | ||
1126 | /* Normal notification (task_done) */ | ||
1127 | dev_dbg(&ihost->pdev->dev, | ||
1128 | "%s: Normal - request/task = %p/%p\n", | ||
1129 | __func__, | ||
1130 | request, | ||
1131 | task); | ||
1132 | 1118 | ||
1133 | /* Return the task to libsas */ | 1119 | /* Return the task to libsas */ |
1134 | if (task != NULL) { | 1120 | if (task != NULL) { |
1135 | 1121 | ||
1136 | task->lldd_task = NULL; | 1122 | task->lldd_task = NULL; |
1137 | if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED)) { | 1123 | if (!test_bit(IREQ_ABORT_PATH_ACTIVE, &request->flags) && |
1138 | 1124 | !(task->task_state_flags & SAS_TASK_STATE_ABORTED)) { | |
1139 | /* If the task is already in the abort path, | 1125 | if (test_bit(IREQ_COMPLETE_IN_TARGET, |
1140 | * the task_done callback cannot be called. | 1126 | &request->flags)) { |
1141 | */ | 1127 | |
1142 | task->task_done(task); | 1128 | /* Normal notification (task_done) */ |
1129 | dev_dbg(&ihost->pdev->dev, "%s: Normal" | ||
1130 | " - request/task = %p/%p\n", | ||
1131 | __func__, request, task); | ||
1132 | |||
1133 | task->task_done(task); | ||
1134 | } else { | ||
1135 | dev_warn(&ihost->pdev->dev, | ||
1136 | "%s: Error - request/task" | ||
1137 | " = %p/%p\n", | ||
1138 | __func__, request, task); | ||
1139 | |||
1140 | sas_task_abort(task); | ||
1141 | } | ||
1143 | } | 1142 | } |
1144 | } | 1143 | } |
1145 | 1144 | ||
@@ -1147,44 +1146,6 @@ void isci_host_completion_routine(unsigned long data) | |||
1147 | isci_free_tag(ihost, request->io_tag); | 1146 | isci_free_tag(ihost, request->io_tag); |
1148 | spin_unlock_irq(&ihost->scic_lock); | 1147 | spin_unlock_irq(&ihost->scic_lock); |
1149 | } | 1148 | } |
1150 | list_for_each_entry_safe(request, next_request, &errored_request_list, | ||
1151 | completed_node) { | ||
1152 | |||
1153 | task = isci_request_access_task(request); | ||
1154 | |||
1155 | /* Use sas_task_abort */ | ||
1156 | dev_warn(&ihost->pdev->dev, | ||
1157 | "%s: Error - request/task = %p/%p\n", | ||
1158 | __func__, | ||
1159 | request, | ||
1160 | task); | ||
1161 | |||
1162 | if (task != NULL) { | ||
1163 | |||
1164 | /* Put the task into the abort path if it's not there | ||
1165 | * already. | ||
1166 | */ | ||
1167 | if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED)) | ||
1168 | sas_task_abort(task); | ||
1169 | |||
1170 | } else { | ||
1171 | /* This is a case where the request has completed with a | ||
1172 | * status such that it needed further target servicing, | ||
1173 | * but the sas_task reference has already been removed | ||
1174 | * from the request. Since it was errored, it was not | ||
1175 | * being aborted, so there is nothing to do except free | ||
1176 | * it. | ||
1177 | */ | ||
1178 | |||
1179 | spin_lock_irq(&ihost->scic_lock); | ||
1180 | /* Remove the request from the remote device's list | ||
1181 | * of pending requests. | ||
1182 | */ | ||
1183 | list_del_init(&request->dev_node); | ||
1184 | isci_free_tag(ihost, request->io_tag); | ||
1185 | spin_unlock_irq(&ihost->scic_lock); | ||
1186 | } | ||
1187 | } | ||
1188 | 1149 | ||
1189 | /* the coalesence timeout doubles at each encoding step, so | 1150 | /* the coalesence timeout doubles at each encoding step, so |
1190 | * update it based on the ilog2 value of the outstanding requests | 1151 | * update it based on the ilog2 value of the outstanding requests |
@@ -2345,7 +2306,6 @@ static int sci_controller_dma_alloc(struct isci_host *ihost) | |||
2345 | 2306 | ||
2346 | ireq->tc = &ihost->task_context_table[i]; | 2307 | ireq->tc = &ihost->task_context_table[i]; |
2347 | ireq->owning_controller = ihost; | 2308 | ireq->owning_controller = ihost; |
2348 | spin_lock_init(&ireq->state_lock); | ||
2349 | ireq->request_daddr = dma; | 2309 | ireq->request_daddr = dma; |
2350 | ireq->isci_host = ihost; | 2310 | ireq->isci_host = ihost; |
2351 | ihost->reqs[i] = ireq; | 2311 | ihost->reqs[i] = ireq; |
@@ -2697,6 +2657,10 @@ enum sci_status sci_controller_terminate_request(struct isci_host *ihost, | |||
2697 | return SCI_FAILURE_INVALID_STATE; | 2657 | return SCI_FAILURE_INVALID_STATE; |
2698 | } | 2658 | } |
2699 | status = sci_io_request_terminate(ireq); | 2659 | status = sci_io_request_terminate(ireq); |
2660 | |||
2661 | dev_dbg(&ihost->pdev->dev, "%s: status=%d; ireq=%p; flags=%lx\n", | ||
2662 | __func__, status, ireq, ireq->flags); | ||
2663 | |||
2700 | if ((status == SCI_SUCCESS) && | 2664 | if ((status == SCI_SUCCESS) && |
2701 | !test_bit(IREQ_PENDING_ABORT, &ireq->flags) && | 2665 | !test_bit(IREQ_PENDING_ABORT, &ireq->flags) && |
2702 | !test_and_set_bit(IREQ_TC_ABORT_POSTED, &ireq->flags)) { | 2666 | !test_and_set_bit(IREQ_TC_ABORT_POSTED, &ireq->flags)) { |
@@ -2739,6 +2703,8 @@ enum sci_status sci_controller_complete_io(struct isci_host *ihost, | |||
2739 | 2703 | ||
2740 | index = ISCI_TAG_TCI(ireq->io_tag); | 2704 | index = ISCI_TAG_TCI(ireq->io_tag); |
2741 | clear_bit(IREQ_ACTIVE, &ireq->flags); | 2705 | clear_bit(IREQ_ACTIVE, &ireq->flags); |
2706 | if (test_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags)) | ||
2707 | wake_up_all(&ihost->eventq); | ||
2742 | return SCI_SUCCESS; | 2708 | return SCI_SUCCESS; |
2743 | default: | 2709 | default: |
2744 | dev_warn(&ihost->pdev->dev, "%s invalid state: %d\n", | 2710 | dev_warn(&ihost->pdev->dev, "%s invalid state: %d\n", |