aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>2011-10-27 18:05:16 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-10-31 05:17:48 -0400
commit98145cb722b51ccc3ba27166c9803545accba950 (patch)
tree714aaae27bd45da93793729f3321c6409aad45ae /drivers/scsi
parentdb49c2d037d50dfc67b29a4e013d6250ca97c3aa (diff)
[SCSI] isci: Fix task management for SMP, SATA and on dev remove.
libsas uses the LLDD abort task interface to handle I/O timeouts in the SATA/STP and SMP discovery paths, so this change will terminate STP/SMP requests. Also, if the device is gone, the lldd will prevent libsas from further escalations in the error handler. Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/isci/remote_device.c47
-rw-r--r--drivers/scsi/isci/remote_device.h2
-rw-r--r--drivers/scsi/isci/task.c169
-rw-r--r--drivers/scsi/isci/task.h33
4 files changed, 67 insertions, 184 deletions
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index fbf9ce28c3f5..20c77edd4711 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -1438,53 +1438,6 @@ int isci_remote_device_found(struct domain_device *domain_dev)
1438 1438
1439 return status == SCI_SUCCESS ? 0 : -ENODEV; 1439 return status == SCI_SUCCESS ? 0 : -ENODEV;
1440} 1440}
1441/**
1442 * isci_device_is_reset_pending() - This function will check if there is any
1443 * pending reset condition on the device.
1444 * @request: This parameter is the isci_device object.
1445 *
1446 * true if there is a reset pending for the device.
1447 */
1448bool isci_device_is_reset_pending(
1449 struct isci_host *isci_host,
1450 struct isci_remote_device *isci_device)
1451{
1452 struct isci_request *isci_request;
1453 struct isci_request *tmp_req;
1454 bool reset_is_pending = false;
1455 unsigned long flags;
1456
1457 dev_dbg(&isci_host->pdev->dev,
1458 "%s: isci_device = %p\n", __func__, isci_device);
1459
1460 spin_lock_irqsave(&isci_host->scic_lock, flags);
1461
1462 /* Check for reset on all pending requests. */
1463 list_for_each_entry_safe(isci_request, tmp_req,
1464 &isci_device->reqs_in_process, dev_node) {
1465 dev_dbg(&isci_host->pdev->dev,
1466 "%s: isci_device = %p request = %p\n",
1467 __func__, isci_device, isci_request);
1468
1469 if (isci_request->ttype == io_task) {
1470 struct sas_task *task = isci_request_access_task(
1471 isci_request);
1472
1473 spin_lock(&task->task_state_lock);
1474 if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET)
1475 reset_is_pending = true;
1476 spin_unlock(&task->task_state_lock);
1477 }
1478 }
1479
1480 spin_unlock_irqrestore(&isci_host->scic_lock, flags);
1481
1482 dev_dbg(&isci_host->pdev->dev,
1483 "%s: isci_device = %p reset_is_pending = %d\n",
1484 __func__, isci_device, reset_is_pending);
1485
1486 return reset_is_pending;
1487}
1488 1441
1489/** 1442/**
1490 * isci_device_clear_reset_pending() - This function will clear if any pending 1443 * isci_device_clear_reset_pending() - This function will clear if any pending
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h
index e1747ea0d0ea..bee6dd2d0fe7 100644
--- a/drivers/scsi/isci/remote_device.h
+++ b/drivers/scsi/isci/remote_device.h
@@ -132,8 +132,6 @@ void isci_remote_device_nuke_requests(struct isci_host *ihost,
132 struct isci_remote_device *idev); 132 struct isci_remote_device *idev);
133void isci_remote_device_gone(struct domain_device *domain_dev); 133void isci_remote_device_gone(struct domain_device *domain_dev);
134int isci_remote_device_found(struct domain_device *domain_dev); 134int isci_remote_device_found(struct domain_device *domain_dev);
135bool isci_device_is_reset_pending(struct isci_host *ihost,
136 struct isci_remote_device *idev);
137void isci_device_clear_reset_pending(struct isci_host *ihost, 135void isci_device_clear_reset_pending(struct isci_host *ihost,
138 struct isci_remote_device *idev); 136 struct isci_remote_device *idev);
139/** 137/**
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index c1f439bed717..ec85beb1f979 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -920,22 +920,14 @@ int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun)
920 "%s: domain_device=%p, isci_host=%p; isci_device=%p\n", 920 "%s: domain_device=%p, isci_host=%p; isci_device=%p\n",
921 __func__, domain_device, isci_host, isci_device); 921 __func__, domain_device, isci_host, isci_device);
922 922
923 if (isci_device) 923 if (!isci_device) {
924 set_bit(IDEV_EH, &isci_device->flags); 924 /* If the device is gone, stop the escalations. */
925 dev_dbg(&isci_host->pdev->dev, "%s: No dev\n", __func__);
925 926
926 /* If there is a device reset pending on any request in the 927 ret = TMF_RESP_FUNC_COMPLETE;
927 * device's list, fail this LUN reset request in order to
928 * escalate to the device reset.
929 */
930 if (!isci_device ||
931 isci_device_is_reset_pending(isci_host, isci_device)) {
932 dev_dbg(&isci_host->pdev->dev,
933 "%s: No dev (%p), or "
934 "RESET PENDING: domain_device=%p\n",
935 __func__, isci_device, domain_device);
936 ret = TMF_RESP_FUNC_FAILED;
937 goto out; 928 goto out;
938 } 929 }
930 set_bit(IDEV_EH, &isci_device->flags);
939 931
940 /* Send the task management part of the reset. */ 932 /* Send the task management part of the reset. */
941 if (sas_protocol_ata(domain_device->tproto)) { 933 if (sas_protocol_ata(domain_device->tproto)) {
@@ -1044,7 +1036,7 @@ int isci_task_abort_task(struct sas_task *task)
1044 struct isci_tmf tmf; 1036 struct isci_tmf tmf;
1045 int ret = TMF_RESP_FUNC_FAILED; 1037 int ret = TMF_RESP_FUNC_FAILED;
1046 unsigned long flags; 1038 unsigned long flags;
1047 bool any_dev_reset = false; 1039 int perform_termination = 0;
1048 1040
1049 /* Get the isci_request reference from the task. Note that 1041 /* Get the isci_request reference from the task. Note that
1050 * this check does not depend on the pending request list 1042 * this check does not depend on the pending request list
@@ -1066,89 +1058,34 @@ int isci_task_abort_task(struct sas_task *task)
1066 spin_unlock_irqrestore(&isci_host->scic_lock, flags); 1058 spin_unlock_irqrestore(&isci_host->scic_lock, flags);
1067 1059
1068 dev_dbg(&isci_host->pdev->dev, 1060 dev_dbg(&isci_host->pdev->dev,
1069 "%s: task = %p\n", __func__, task); 1061 "%s: dev = %p, task = %p, old_request == %p\n",
1070 1062 __func__, isci_device, task, old_request);
1071 if (!isci_device || !old_request)
1072 goto out;
1073 1063
1074 set_bit(IDEV_EH, &isci_device->flags); 1064 if (isci_device)
1075 1065 set_bit(IDEV_EH, &isci_device->flags);
1076 /* This version of the driver will fail abort requests for
1077 * SATA/STP. Failing the abort request this way will cause the
1078 * SCSI error handler thread to escalate to LUN reset
1079 */
1080 if (sas_protocol_ata(task->task_proto)) {
1081 dev_dbg(&isci_host->pdev->dev,
1082 " task %p is for a STP/SATA device;"
1083 " returning TMF_RESP_FUNC_FAILED\n"
1084 " to cause a LUN reset...\n", task);
1085 goto out;
1086 }
1087
1088 dev_dbg(&isci_host->pdev->dev,
1089 "%s: old_request == %p\n", __func__, old_request);
1090
1091 any_dev_reset = isci_device_is_reset_pending(isci_host, isci_device);
1092
1093 spin_lock_irqsave(&task->task_state_lock, flags);
1094
1095 any_dev_reset = any_dev_reset || (task->task_state_flags & SAS_TASK_NEED_DEV_RESET);
1096 1066
1097 /* If the extraction of the request reference from the task 1067 /* Device reset conditions signalled in task_state_flags are the
1098 * failed, then the request has been completed (or if there is a 1068 * responsbility of libsas to observe at the start of the error
1099 * pending reset then this abort request function must be failed 1069 * handler thread.
1100 * in order to escalate to the target reset).
1101 */ 1070 */
1102 if ((old_request == NULL) || any_dev_reset) { 1071 if (!isci_device || !old_request) {
1103 1072 /* The request has already completed and there
1104 /* If the device reset task flag is set, fail the task 1073 * is nothing to do here other than to set the task
1105 * management request. Otherwise, the original request 1074 * done bit, and indicate that the task abort function
1106 * has completed. 1075 * was sucessful.
1107 */ 1076 */
1108 if (any_dev_reset) { 1077 spin_lock_irqsave(&task->task_state_lock, flags);
1109 1078 task->task_state_flags |= SAS_TASK_STATE_DONE;
1110 /* Turn off the task's DONE to make sure this 1079 task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
1111 * task is escalated to a target reset. 1080 SAS_TASK_STATE_PENDING);
1112 */ 1081 spin_unlock_irqrestore(&task->task_state_lock, flags);
1113 task->task_state_flags &= ~SAS_TASK_STATE_DONE;
1114
1115 /* Make the reset happen as soon as possible. */
1116 task->task_state_flags |= SAS_TASK_NEED_DEV_RESET;
1117
1118 spin_unlock_irqrestore(&task->task_state_lock, flags);
1119
1120 /* Fail the task management request in order to
1121 * escalate to the target reset.
1122 */
1123 ret = TMF_RESP_FUNC_FAILED;
1124
1125 dev_dbg(&isci_host->pdev->dev,
1126 "%s: Failing task abort in order to "
1127 "escalate to target reset because\n"
1128 "SAS_TASK_NEED_DEV_RESET is set for "
1129 "task %p on dev %p\n",
1130 __func__, task, isci_device);
1131
1132
1133 } else {
1134 /* The request has already completed and there
1135 * is nothing to do here other than to set the task
1136 * done bit, and indicate that the task abort function
1137 * was sucessful.
1138 */
1139 isci_set_task_doneflags(task);
1140
1141 spin_unlock_irqrestore(&task->task_state_lock, flags);
1142 1082
1143 ret = TMF_RESP_FUNC_COMPLETE; 1083 ret = TMF_RESP_FUNC_COMPLETE;
1144 1084
1145 dev_dbg(&isci_host->pdev->dev, 1085 dev_dbg(&isci_host->pdev->dev,
1146 "%s: abort task not needed for %p\n", 1086 "%s: abort task not needed for %p\n",
1147 __func__, task); 1087 __func__, task);
1148 }
1149 goto out; 1088 goto out;
1150 } else {
1151 spin_unlock_irqrestore(&task->task_state_lock, flags);
1152 } 1089 }
1153 1090
1154 spin_lock_irqsave(&isci_host->scic_lock, flags); 1091 spin_lock_irqsave(&isci_host->scic_lock, flags);
@@ -1177,24 +1114,44 @@ int isci_task_abort_task(struct sas_task *task)
1177 goto out; 1114 goto out;
1178 } 1115 }
1179 if (task->task_proto == SAS_PROTOCOL_SMP || 1116 if (task->task_proto == SAS_PROTOCOL_SMP ||
1117 sas_protocol_ata(task->task_proto) ||
1180 test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags)) { 1118 test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags)) {
1181 1119
1182 spin_unlock_irqrestore(&isci_host->scic_lock, flags); 1120 spin_unlock_irqrestore(&isci_host->scic_lock, flags);
1183 1121
1184 dev_dbg(&isci_host->pdev->dev, 1122 dev_dbg(&isci_host->pdev->dev,
1185 "%s: SMP request (%d)" 1123 "%s: %s request"
1186 " or complete_in_target (%d), thus no TMF\n", 1124 " or complete_in_target (%d), thus no TMF\n",
1187 __func__, (task->task_proto == SAS_PROTOCOL_SMP), 1125 __func__,
1126 ((task->task_proto == SAS_PROTOCOL_SMP)
1127 ? "SMP"
1128 : (sas_protocol_ata(task->task_proto)
1129 ? "SATA/STP"
1130 : "<other>")
1131 ),
1188 test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags)); 1132 test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags));
1189 1133
1190 /* Set the state on the task. */ 1134 if (test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags)) {
1191 isci_task_all_done(task); 1135 spin_lock_irqsave(&task->task_state_lock, flags);
1192 1136 task->task_state_flags |= SAS_TASK_STATE_DONE;
1193 ret = TMF_RESP_FUNC_COMPLETE; 1137 task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
1138 SAS_TASK_STATE_PENDING);
1139 spin_unlock_irqrestore(&task->task_state_lock, flags);
1140 ret = TMF_RESP_FUNC_COMPLETE;
1141 } else {
1142 spin_lock_irqsave(&task->task_state_lock, flags);
1143 task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
1144 SAS_TASK_STATE_PENDING);
1145 spin_unlock_irqrestore(&task->task_state_lock, flags);
1146 }
1194 1147
1195 /* Stopping and SMP devices are not sent a TMF, and are not 1148 /* STP and SMP devices are not sent a TMF, but the
1196 * reset, but the outstanding I/O request is terminated below. 1149 * outstanding I/O request is terminated below. This is
1150 * because SATA/STP and SMP discovery path timeouts directly
1151 * call the abort task interface for cleanup.
1197 */ 1152 */
1153 perform_termination = 1;
1154
1198 } else { 1155 } else {
1199 /* Fill in the tmf stucture */ 1156 /* Fill in the tmf stucture */
1200 isci_task_build_abort_task_tmf(&tmf, isci_tmf_ssp_task_abort, 1157 isci_task_build_abort_task_tmf(&tmf, isci_tmf_ssp_task_abort,
@@ -1203,22 +1160,24 @@ int isci_task_abort_task(struct sas_task *task)
1203 1160
1204 spin_unlock_irqrestore(&isci_host->scic_lock, flags); 1161 spin_unlock_irqrestore(&isci_host->scic_lock, flags);
1205 1162
1206 #define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* half second timeout. */ 1163 #define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* 1/2 second timeout */
1207 ret = isci_task_execute_tmf(isci_host, isci_device, &tmf, 1164 ret = isci_task_execute_tmf(isci_host, isci_device, &tmf,
1208 ISCI_ABORT_TASK_TIMEOUT_MS); 1165 ISCI_ABORT_TASK_TIMEOUT_MS);
1209 1166
1210 if (ret != TMF_RESP_FUNC_COMPLETE) 1167 if (ret == TMF_RESP_FUNC_COMPLETE)
1168 perform_termination = 1;
1169 else
1211 dev_dbg(&isci_host->pdev->dev, 1170 dev_dbg(&isci_host->pdev->dev,
1212 "%s: isci_task_send_tmf failed\n", 1171 "%s: isci_task_send_tmf failed\n", __func__);
1213 __func__);
1214 } 1172 }
1215 if (ret == TMF_RESP_FUNC_COMPLETE) { 1173 if (perform_termination) {
1216 set_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags); 1174 set_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags);
1217 1175
1218 /* Clean up the request on our side, and wait for the aborted 1176 /* Clean up the request on our side, and wait for the aborted
1219 * I/O to complete. 1177 * I/O to complete.
1220 */ 1178 */
1221 isci_terminate_request_core(isci_host, isci_device, old_request); 1179 isci_terminate_request_core(isci_host, isci_device,
1180 old_request);
1222 } 1181 }
1223 1182
1224 /* Make sure we do not leave a reference to aborted_io_completion */ 1183 /* Make sure we do not leave a reference to aborted_io_completion */
diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h
index c9ccd0b5ff53..bc78c0a41d5c 100644
--- a/drivers/scsi/isci/task.h
+++ b/drivers/scsi/isci/task.h
@@ -226,35 +226,6 @@ enum isci_completion_selection {
226 isci_perform_error_io_completion /* Use sas_task_abort */ 226 isci_perform_error_io_completion /* Use sas_task_abort */
227}; 227};
228 228
229static inline void isci_set_task_doneflags(
230 struct sas_task *task)
231{
232 /* Since no futher action will be taken on this task,
233 * make sure to mark it complete from the lldd perspective.
234 */
235 task->task_state_flags |= SAS_TASK_STATE_DONE;
236 task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
237 task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
238}
239/**
240 * isci_task_all_done() - This function clears the task bits to indicate the
241 * LLDD is done with the task.
242 *
243 *
244 */
245static inline void isci_task_all_done(
246 struct sas_task *task)
247{
248 unsigned long flags;
249
250 /* Since no futher action will be taken on this task,
251 * make sure to mark it complete from the lldd perspective.
252 */
253 spin_lock_irqsave(&task->task_state_lock, flags);
254 isci_set_task_doneflags(task);
255 spin_unlock_irqrestore(&task->task_state_lock, flags);
256}
257
258/** 229/**
259 * isci_task_set_completion_status() - This function sets the completion status 230 * isci_task_set_completion_status() - This function sets the completion status
260 * for the request. 231 * for the request.
@@ -336,7 +307,9 @@ isci_task_set_completion_status(
336 /* Fall through to the normal case... */ 307 /* Fall through to the normal case... */
337 case isci_perform_normal_io_completion: 308 case isci_perform_normal_io_completion:
338 /* Normal notification (task_done) */ 309 /* Normal notification (task_done) */
339 isci_set_task_doneflags(task); 310 task->task_state_flags |= SAS_TASK_STATE_DONE;
311 task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
312 SAS_TASK_STATE_PENDING);
340 break; 313 break;
341 default: 314 default:
342 WARN_ONCE(1, "unknown task_notification_selection: %d\n", 315 WARN_ONCE(1, "unknown task_notification_selection: %d\n",