aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci/host.c
diff options
context:
space:
mode:
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>2012-03-09 01:41:54 -0500
committerDan Williams <dan.j.williams@intel.com>2012-05-17 17:33:38 -0400
commit14aaa9f0a318bd04cbb9d822524b817e95d8b343 (patch)
tree5f6292ec671d0993c1df51586dea4fb7750d1cd9 /drivers/scsi/isci/host.c
parentd80ecd5726ce49b5da457d562804b40f0183e8f7 (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.c86
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",