diff options
Diffstat (limited to 'drivers/scsi/isci/task.c')
-rw-r--r-- | drivers/scsi/isci/task.c | 231 |
1 files changed, 91 insertions, 140 deletions
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index ded81cd1a781..dd5e9de1ffb5 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c | |||
@@ -146,7 +146,7 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task, | |||
146 | int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) | 146 | int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) |
147 | { | 147 | { |
148 | struct isci_host *ihost = dev_to_ihost(task->dev); | 148 | struct isci_host *ihost = dev_to_ihost(task->dev); |
149 | struct isci_remote_device *device; | 149 | struct isci_remote_device *idev; |
150 | unsigned long flags; | 150 | unsigned long flags; |
151 | int ret; | 151 | int ret; |
152 | enum sci_status status; | 152 | enum sci_status status; |
@@ -166,11 +166,12 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) | |||
166 | dev_dbg(&ihost->pdev->dev, | 166 | dev_dbg(&ihost->pdev->dev, |
167 | "task = %p, num = %d; dev = %p; cmd = %p\n", | 167 | "task = %p, num = %d; dev = %p; cmd = %p\n", |
168 | task, num, task->dev, task->uldd_task); | 168 | task, num, task->dev, task->uldd_task); |
169 | spin_lock_irqsave(&ihost->scic_lock, flags); | ||
170 | idev = isci_lookup_device(task->dev); | ||
171 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | ||
169 | 172 | ||
170 | device = task->dev->lldd_dev; | 173 | if (idev) |
171 | 174 | device_status = idev->status; | |
172 | if (device) | ||
173 | device_status = device->status; | ||
174 | else | 175 | else |
175 | device_status = isci_freed; | 176 | device_status = isci_freed; |
176 | 177 | ||
@@ -188,7 +189,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) | |||
188 | __func__, | 189 | __func__, |
189 | task, | 190 | task, |
190 | isci_host_get_state(ihost), | 191 | isci_host_get_state(ihost), |
191 | device, | 192 | idev, |
192 | device_status); | 193 | device_status); |
193 | 194 | ||
194 | if (device_status == isci_ready) { | 195 | if (device_status == isci_ready) { |
@@ -225,7 +226,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) | |||
225 | spin_unlock_irqrestore(&task->task_state_lock, flags); | 226 | spin_unlock_irqrestore(&task->task_state_lock, flags); |
226 | 227 | ||
227 | /* build and send the request. */ | 228 | /* build and send the request. */ |
228 | status = isci_request_execute(ihost, task, gfp_flags); | 229 | status = isci_request_execute(ihost, idev, task, gfp_flags); |
229 | 230 | ||
230 | if (status != SCI_SUCCESS) { | 231 | if (status != SCI_SUCCESS) { |
231 | 232 | ||
@@ -248,33 +249,31 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) | |||
248 | } | 249 | } |
249 | } | 250 | } |
250 | } | 251 | } |
252 | isci_put_device(idev); | ||
251 | } | 253 | } |
252 | return 0; | 254 | return 0; |
253 | } | 255 | } |
254 | 256 | ||
255 | static struct isci_request *isci_task_request_build(struct isci_host *ihost, | 257 | static struct isci_request *isci_task_request_build(struct isci_host *ihost, |
258 | struct isci_remote_device *idev, | ||
256 | struct isci_tmf *isci_tmf) | 259 | struct isci_tmf *isci_tmf) |
257 | { | 260 | { |
258 | struct scic_sds_remote_device *sci_dev; | ||
259 | enum sci_status status = SCI_FAILURE; | 261 | enum sci_status status = SCI_FAILURE; |
260 | struct isci_request *ireq = NULL; | 262 | struct isci_request *ireq = NULL; |
261 | struct isci_remote_device *idev; | ||
262 | struct domain_device *dev; | 263 | struct domain_device *dev; |
263 | 264 | ||
264 | dev_dbg(&ihost->pdev->dev, | 265 | dev_dbg(&ihost->pdev->dev, |
265 | "%s: isci_tmf = %p\n", __func__, isci_tmf); | 266 | "%s: isci_tmf = %p\n", __func__, isci_tmf); |
266 | 267 | ||
267 | idev = isci_tmf->device; | ||
268 | sci_dev = &idev->sci; | ||
269 | dev = idev->domain_dev; | 268 | dev = idev->domain_dev; |
270 | 269 | ||
271 | /* do common allocation and init of request object. */ | 270 | /* do common allocation and init of request object. */ |
272 | ireq = isci_request_alloc_tmf(ihost, isci_tmf, idev, GFP_ATOMIC); | 271 | ireq = isci_request_alloc_tmf(ihost, isci_tmf, GFP_ATOMIC); |
273 | if (!ireq) | 272 | if (!ireq) |
274 | return NULL; | 273 | return NULL; |
275 | 274 | ||
276 | /* let the core do it's construct. */ | 275 | /* let the core do it's construct. */ |
277 | status = scic_task_request_construct(&ihost->sci, sci_dev, | 276 | status = scic_task_request_construct(&ihost->sci, &idev->sci, |
278 | SCI_CONTROLLER_INVALID_IO_TAG, | 277 | SCI_CONTROLLER_INVALID_IO_TAG, |
279 | &ireq->sci); | 278 | &ireq->sci); |
280 | 279 | ||
@@ -309,25 +308,13 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, | |||
309 | return ireq; | 308 | return ireq; |
310 | } | 309 | } |
311 | 310 | ||
312 | /** | 311 | int isci_task_execute_tmf(struct isci_host *ihost, |
313 | * isci_task_execute_tmf() - This function builds and sends a task request, | 312 | struct isci_remote_device *isci_device, |
314 | * then waits for the completion. | 313 | struct isci_tmf *tmf, unsigned long timeout_ms) |
315 | * @isci_host: This parameter specifies the ISCI host object | ||
316 | * @tmf: This parameter is the pointer to the task management structure for | ||
317 | * this request. | ||
318 | * @timeout_ms: This parameter specifies the timeout period for the task | ||
319 | * management request. | ||
320 | * | ||
321 | * TMF_RESP_FUNC_COMPLETE on successful completion of the TMF (this includes | ||
322 | * error conditions reported in the IU status), or TMF_RESP_FUNC_FAILED. | ||
323 | */ | ||
324 | int isci_task_execute_tmf(struct isci_host *ihost, struct isci_tmf *tmf, | ||
325 | unsigned long timeout_ms) | ||
326 | { | 314 | { |
327 | DECLARE_COMPLETION_ONSTACK(completion); | 315 | DECLARE_COMPLETION_ONSTACK(completion); |
328 | enum sci_task_status status = SCI_TASK_FAILURE; | 316 | enum sci_task_status status = SCI_TASK_FAILURE; |
329 | struct scic_sds_remote_device *sci_device; | 317 | struct scic_sds_remote_device *sci_device; |
330 | struct isci_remote_device *isci_device = tmf->device; | ||
331 | struct isci_request *ireq; | 318 | struct isci_request *ireq; |
332 | int ret = TMF_RESP_FUNC_FAILED; | 319 | int ret = TMF_RESP_FUNC_FAILED; |
333 | unsigned long flags; | 320 | unsigned long flags; |
@@ -352,7 +339,7 @@ int isci_task_execute_tmf(struct isci_host *ihost, struct isci_tmf *tmf, | |||
352 | /* Assign the pointer to the TMF's completion kernel wait structure. */ | 339 | /* Assign the pointer to the TMF's completion kernel wait structure. */ |
353 | tmf->complete = &completion; | 340 | tmf->complete = &completion; |
354 | 341 | ||
355 | ireq = isci_task_request_build(ihost, tmf); | 342 | ireq = isci_task_request_build(ihost, isci_device, tmf); |
356 | if (!ireq) { | 343 | if (!ireq) { |
357 | dev_warn(&ihost->pdev->dev, | 344 | dev_warn(&ihost->pdev->dev, |
358 | "%s: isci_task_request_build failed\n", | 345 | "%s: isci_task_request_build failed\n", |
@@ -399,10 +386,9 @@ int isci_task_execute_tmf(struct isci_host *ihost, struct isci_tmf *tmf, | |||
399 | if (tmf->cb_state_func != NULL) | 386 | if (tmf->cb_state_func != NULL) |
400 | tmf->cb_state_func(isci_tmf_timed_out, tmf, tmf->cb_data); | 387 | tmf->cb_state_func(isci_tmf_timed_out, tmf, tmf->cb_data); |
401 | 388 | ||
402 | status = scic_controller_terminate_request( | 389 | status = scic_controller_terminate_request(&ihost->sci, |
403 | &ireq->isci_host->sci, | 390 | &isci_device->sci, |
404 | &ireq->isci_device->sci, | 391 | &ireq->sci); |
405 | &ireq->sci); | ||
406 | 392 | ||
407 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | 393 | spin_unlock_irqrestore(&ihost->scic_lock, flags); |
408 | } | 394 | } |
@@ -437,65 +423,32 @@ int isci_task_execute_tmf(struct isci_host *ihost, struct isci_tmf *tmf, | |||
437 | 423 | ||
438 | void isci_task_build_tmf( | 424 | void isci_task_build_tmf( |
439 | struct isci_tmf *tmf, | 425 | struct isci_tmf *tmf, |
440 | struct isci_remote_device *isci_device, | ||
441 | enum isci_tmf_function_codes code, | 426 | enum isci_tmf_function_codes code, |
442 | void (*tmf_sent_cb)(enum isci_tmf_cb_state, | 427 | void (*tmf_sent_cb)(enum isci_tmf_cb_state, |
443 | struct isci_tmf *, | 428 | struct isci_tmf *, |
444 | void *), | 429 | void *), |
445 | void *cb_data) | 430 | void *cb_data) |
446 | { | 431 | { |
447 | dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, | ||
448 | "%s: isci_device = %p\n", __func__, isci_device); | ||
449 | |||
450 | memset(tmf, 0, sizeof(*tmf)); | 432 | memset(tmf, 0, sizeof(*tmf)); |
451 | 433 | ||
452 | tmf->device = isci_device; | ||
453 | tmf->tmf_code = code; | 434 | tmf->tmf_code = code; |
454 | |||
455 | tmf->cb_state_func = tmf_sent_cb; | 435 | tmf->cb_state_func = tmf_sent_cb; |
456 | tmf->cb_data = cb_data; | 436 | tmf->cb_data = cb_data; |
457 | } | 437 | } |
458 | 438 | ||
459 | static void isci_task_build_abort_task_tmf( | 439 | static void isci_task_build_abort_task_tmf( |
460 | struct isci_tmf *tmf, | 440 | struct isci_tmf *tmf, |
461 | struct isci_remote_device *isci_device, | ||
462 | enum isci_tmf_function_codes code, | 441 | enum isci_tmf_function_codes code, |
463 | void (*tmf_sent_cb)(enum isci_tmf_cb_state, | 442 | void (*tmf_sent_cb)(enum isci_tmf_cb_state, |
464 | struct isci_tmf *, | 443 | struct isci_tmf *, |
465 | void *), | 444 | void *), |
466 | struct isci_request *old_request) | 445 | struct isci_request *old_request) |
467 | { | 446 | { |
468 | isci_task_build_tmf(tmf, isci_device, code, tmf_sent_cb, | 447 | isci_task_build_tmf(tmf, code, tmf_sent_cb, |
469 | (void *)old_request); | 448 | (void *)old_request); |
470 | tmf->io_tag = old_request->io_tag; | 449 | tmf->io_tag = old_request->io_tag; |
471 | } | 450 | } |
472 | 451 | ||
473 | static struct isci_request *isci_task_get_request_from_task( | ||
474 | struct sas_task *task, | ||
475 | struct isci_remote_device **isci_device) | ||
476 | { | ||
477 | |||
478 | struct isci_request *request = NULL; | ||
479 | unsigned long flags; | ||
480 | |||
481 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
482 | |||
483 | request = task->lldd_task; | ||
484 | |||
485 | /* If task is already done, the request isn't valid */ | ||
486 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE) && | ||
487 | (task->task_state_flags & SAS_TASK_AT_INITIATOR) && | ||
488 | (request != NULL)) { | ||
489 | |||
490 | if (isci_device != NULL) | ||
491 | *isci_device = request->isci_device; | ||
492 | } | ||
493 | |||
494 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
495 | |||
496 | return request; | ||
497 | } | ||
498 | |||
499 | /** | 452 | /** |
500 | * isci_task_validate_request_to_abort() - This function checks the given I/O | 453 | * isci_task_validate_request_to_abort() - This function checks the given I/O |
501 | * against the "started" state. If the request is still "started", it's | 454 | * against the "started" state. If the request is still "started", it's |
@@ -858,11 +811,10 @@ static int isci_task_send_lu_reset_sas( | |||
858 | * value is "TMF_RESP_FUNC_COMPLETE", or the request timed-out (or | 811 | * value is "TMF_RESP_FUNC_COMPLETE", or the request timed-out (or |
859 | * was otherwise unable to be executed ("TMF_RESP_FUNC_FAILED"). | 812 | * was otherwise unable to be executed ("TMF_RESP_FUNC_FAILED"). |
860 | */ | 813 | */ |
861 | isci_task_build_tmf(&tmf, isci_device, isci_tmf_ssp_lun_reset, NULL, | 814 | isci_task_build_tmf(&tmf, isci_tmf_ssp_lun_reset, NULL, NULL); |
862 | NULL); | ||
863 | 815 | ||
864 | #define ISCI_LU_RESET_TIMEOUT_MS 2000 /* 2 second timeout. */ | 816 | #define ISCI_LU_RESET_TIMEOUT_MS 2000 /* 2 second timeout. */ |
865 | ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_LU_RESET_TIMEOUT_MS); | 817 | ret = isci_task_execute_tmf(isci_host, isci_device, &tmf, ISCI_LU_RESET_TIMEOUT_MS); |
866 | 818 | ||
867 | if (ret == TMF_RESP_FUNC_COMPLETE) | 819 | if (ret == TMF_RESP_FUNC_COMPLETE) |
868 | dev_dbg(&isci_host->pdev->dev, | 820 | dev_dbg(&isci_host->pdev->dev, |
@@ -888,33 +840,33 @@ static int isci_task_send_lu_reset_sas( | |||
888 | int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun) | 840 | int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun) |
889 | { | 841 | { |
890 | struct isci_host *isci_host = dev_to_ihost(domain_device); | 842 | struct isci_host *isci_host = dev_to_ihost(domain_device); |
891 | struct isci_remote_device *isci_device = NULL; | 843 | struct isci_remote_device *isci_device; |
844 | unsigned long flags; | ||
892 | int ret; | 845 | int ret; |
893 | bool device_stopping = false; | ||
894 | 846 | ||
895 | isci_device = domain_device->lldd_dev; | 847 | spin_lock_irqsave(&isci_host->scic_lock, flags); |
848 | isci_device = isci_lookup_device(domain_device); | ||
849 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
896 | 850 | ||
897 | dev_dbg(&isci_host->pdev->dev, | 851 | dev_dbg(&isci_host->pdev->dev, |
898 | "%s: domain_device=%p, isci_host=%p; isci_device=%p\n", | 852 | "%s: domain_device=%p, isci_host=%p; isci_device=%p\n", |
899 | __func__, domain_device, isci_host, isci_device); | 853 | __func__, domain_device, isci_host, isci_device); |
900 | 854 | ||
901 | if (isci_device != NULL) { | 855 | if (isci_device) |
902 | device_stopping = (isci_device->status == isci_stopping) | ||
903 | || (isci_device->status == isci_stopped); | ||
904 | set_bit(IDEV_EH, &isci_device->flags); | 856 | set_bit(IDEV_EH, &isci_device->flags); |
905 | } | ||
906 | 857 | ||
907 | /* If there is a device reset pending on any request in the | 858 | /* If there is a device reset pending on any request in the |
908 | * device's list, fail this LUN reset request in order to | 859 | * device's list, fail this LUN reset request in order to |
909 | * escalate to the device reset. | 860 | * escalate to the device reset. |
910 | */ | 861 | */ |
911 | if (!isci_device || device_stopping || | 862 | if (!isci_device || |
912 | isci_device_is_reset_pending(isci_host, isci_device)) { | 863 | isci_device_is_reset_pending(isci_host, isci_device)) { |
913 | dev_warn(&isci_host->pdev->dev, | 864 | dev_warn(&isci_host->pdev->dev, |
914 | "%s: No dev (%p), or " | 865 | "%s: No dev (%p), or " |
915 | "RESET PENDING: domain_device=%p\n", | 866 | "RESET PENDING: domain_device=%p\n", |
916 | __func__, isci_device, domain_device); | 867 | __func__, isci_device, domain_device); |
917 | return TMF_RESP_FUNC_FAILED; | 868 | ret = TMF_RESP_FUNC_FAILED; |
869 | goto out; | ||
918 | } | 870 | } |
919 | 871 | ||
920 | /* Send the task management part of the reset. */ | 872 | /* Send the task management part of the reset. */ |
@@ -929,6 +881,8 @@ int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun) | |||
929 | isci_terminate_pending_requests(isci_host, | 881 | isci_terminate_pending_requests(isci_host, |
930 | isci_device); | 882 | isci_device); |
931 | 883 | ||
884 | out: | ||
885 | isci_put_device(isci_device); | ||
932 | return ret; | 886 | return ret; |
933 | } | 887 | } |
934 | 888 | ||
@@ -1023,60 +977,54 @@ int isci_task_abort_task(struct sas_task *task) | |||
1023 | int ret = TMF_RESP_FUNC_FAILED; | 977 | int ret = TMF_RESP_FUNC_FAILED; |
1024 | unsigned long flags; | 978 | unsigned long flags; |
1025 | bool any_dev_reset = false; | 979 | bool any_dev_reset = false; |
1026 | bool device_stopping; | ||
1027 | 980 | ||
1028 | /* Get the isci_request reference from the task. Note that | 981 | /* Get the isci_request reference from the task. Note that |
1029 | * this check does not depend on the pending request list | 982 | * this check does not depend on the pending request list |
1030 | * in the device, because tasks driving resets may land here | 983 | * in the device, because tasks driving resets may land here |
1031 | * after completion in the core. | 984 | * after completion in the core. |
1032 | */ | 985 | */ |
1033 | old_request = isci_task_get_request_from_task(task, &isci_device); | 986 | spin_lock_irqsave(&isci_host->scic_lock, flags); |
987 | spin_lock(&task->task_state_lock); | ||
988 | |||
989 | old_request = task->lldd_task; | ||
990 | |||
991 | /* If task is already done, the request isn't valid */ | ||
992 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE) && | ||
993 | (task->task_state_flags & SAS_TASK_AT_INITIATOR) && | ||
994 | old_request) | ||
995 | isci_device = isci_lookup_device(task->dev); | ||
996 | |||
997 | spin_unlock(&task->task_state_lock); | ||
998 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
1034 | 999 | ||
1035 | dev_dbg(&isci_host->pdev->dev, | 1000 | dev_dbg(&isci_host->pdev->dev, |
1036 | "%s: task = %p\n", __func__, task); | 1001 | "%s: task = %p\n", __func__, task); |
1037 | 1002 | ||
1038 | /* Check if the device has been / is currently being removed. | 1003 | if (!isci_device || !old_request) |
1039 | * If so, no task management will be done, and the I/O will | 1004 | goto out; |
1040 | * be terminated. | ||
1041 | */ | ||
1042 | device_stopping = (isci_device->status == isci_stopping) | ||
1043 | || (isci_device->status == isci_stopped); | ||
1044 | 1005 | ||
1045 | /* XXX need to fix device lookup lifetime (needs to be done | ||
1046 | * under scic_lock, among other things...), but for now assume | ||
1047 | * the device is available like the above code | ||
1048 | */ | ||
1049 | set_bit(IDEV_EH, &isci_device->flags); | 1006 | set_bit(IDEV_EH, &isci_device->flags); |
1050 | 1007 | ||
1051 | /* This version of the driver will fail abort requests for | 1008 | /* This version of the driver will fail abort requests for |
1052 | * SATA/STP. Failing the abort request this way will cause the | 1009 | * SATA/STP. Failing the abort request this way will cause the |
1053 | * SCSI error handler thread to escalate to LUN reset | 1010 | * SCSI error handler thread to escalate to LUN reset |
1054 | */ | 1011 | */ |
1055 | if (sas_protocol_ata(task->task_proto) && !device_stopping) { | 1012 | if (sas_protocol_ata(task->task_proto)) { |
1056 | dev_warn(&isci_host->pdev->dev, | 1013 | dev_warn(&isci_host->pdev->dev, |
1057 | " task %p is for a STP/SATA device;" | 1014 | " task %p is for a STP/SATA device;" |
1058 | " returning TMF_RESP_FUNC_FAILED\n" | 1015 | " returning TMF_RESP_FUNC_FAILED\n" |
1059 | " to cause a LUN reset...\n", task); | 1016 | " to cause a LUN reset...\n", task); |
1060 | return TMF_RESP_FUNC_FAILED; | 1017 | goto out; |
1061 | } | 1018 | } |
1062 | 1019 | ||
1063 | dev_dbg(&isci_host->pdev->dev, | 1020 | dev_dbg(&isci_host->pdev->dev, |
1064 | "%s: old_request == %p\n", __func__, old_request); | 1021 | "%s: old_request == %p\n", __func__, old_request); |
1065 | 1022 | ||
1066 | if (!device_stopping) | 1023 | any_dev_reset = isci_device_is_reset_pending(isci_host,isci_device); |
1067 | any_dev_reset = isci_device_is_reset_pending(isci_host,isci_device); | ||
1068 | 1024 | ||
1069 | spin_lock_irqsave(&task->task_state_lock, flags); | 1025 | spin_lock_irqsave(&task->task_state_lock, flags); |
1070 | 1026 | ||
1071 | /* Don't do resets to stopping devices. */ | 1027 | any_dev_reset = any_dev_reset || (task->task_state_flags & SAS_TASK_NEED_DEV_RESET); |
1072 | if (device_stopping) { | ||
1073 | |||
1074 | task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET; | ||
1075 | any_dev_reset = false; | ||
1076 | |||
1077 | } else /* See if there is a pending device reset for this device. */ | ||
1078 | any_dev_reset = any_dev_reset | ||
1079 | || (task->task_state_flags & SAS_TASK_NEED_DEV_RESET); | ||
1080 | 1028 | ||
1081 | /* If the extraction of the request reference from the task | 1029 | /* If the extraction of the request reference from the task |
1082 | * failed, then the request has been completed (or if there is a | 1030 | * failed, then the request has been completed (or if there is a |
@@ -1130,8 +1078,7 @@ int isci_task_abort_task(struct sas_task *task) | |||
1130 | "%s: abort task not needed for %p\n", | 1078 | "%s: abort task not needed for %p\n", |
1131 | __func__, task); | 1079 | __func__, task); |
1132 | } | 1080 | } |
1133 | 1081 | goto out; | |
1134 | return ret; | ||
1135 | } | 1082 | } |
1136 | else | 1083 | else |
1137 | spin_unlock_irqrestore(&task->task_state_lock, flags); | 1084 | spin_unlock_irqrestore(&task->task_state_lock, flags); |
@@ -1158,11 +1105,10 @@ int isci_task_abort_task(struct sas_task *task) | |||
1158 | "%s: device = %p; old_request %p already being aborted\n", | 1105 | "%s: device = %p; old_request %p already being aborted\n", |
1159 | __func__, | 1106 | __func__, |
1160 | isci_device, old_request); | 1107 | isci_device, old_request); |
1161 | 1108 | ret = TMF_RESP_FUNC_COMPLETE; | |
1162 | return TMF_RESP_FUNC_COMPLETE; | 1109 | goto out; |
1163 | } | 1110 | } |
1164 | if ((task->task_proto == SAS_PROTOCOL_SMP) | 1111 | if ((task->task_proto == SAS_PROTOCOL_SMP) |
1165 | || device_stopping | ||
1166 | || old_request->complete_in_target | 1112 | || old_request->complete_in_target |
1167 | ) { | 1113 | ) { |
1168 | 1114 | ||
@@ -1170,10 +1116,9 @@ int isci_task_abort_task(struct sas_task *task) | |||
1170 | 1116 | ||
1171 | dev_dbg(&isci_host->pdev->dev, | 1117 | dev_dbg(&isci_host->pdev->dev, |
1172 | "%s: SMP request (%d)" | 1118 | "%s: SMP request (%d)" |
1173 | " or device is stopping (%d)" | ||
1174 | " or complete_in_target (%d), thus no TMF\n", | 1119 | " or complete_in_target (%d), thus no TMF\n", |
1175 | __func__, (task->task_proto == SAS_PROTOCOL_SMP), | 1120 | __func__, (task->task_proto == SAS_PROTOCOL_SMP), |
1176 | device_stopping, old_request->complete_in_target); | 1121 | old_request->complete_in_target); |
1177 | 1122 | ||
1178 | /* Set the state on the task. */ | 1123 | /* Set the state on the task. */ |
1179 | isci_task_all_done(task); | 1124 | isci_task_all_done(task); |
@@ -1185,15 +1130,14 @@ int isci_task_abort_task(struct sas_task *task) | |||
1185 | */ | 1130 | */ |
1186 | } else { | 1131 | } else { |
1187 | /* Fill in the tmf stucture */ | 1132 | /* Fill in the tmf stucture */ |
1188 | isci_task_build_abort_task_tmf(&tmf, isci_device, | 1133 | isci_task_build_abort_task_tmf(&tmf, isci_tmf_ssp_task_abort, |
1189 | isci_tmf_ssp_task_abort, | ||
1190 | isci_abort_task_process_cb, | 1134 | isci_abort_task_process_cb, |
1191 | old_request); | 1135 | old_request); |
1192 | 1136 | ||
1193 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | 1137 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); |
1194 | 1138 | ||
1195 | #define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* half second timeout. */ | 1139 | #define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* half second timeout. */ |
1196 | ret = isci_task_execute_tmf(isci_host, &tmf, | 1140 | ret = isci_task_execute_tmf(isci_host, isci_device, &tmf, |
1197 | ISCI_ABORT_TASK_TIMEOUT_MS); | 1141 | ISCI_ABORT_TASK_TIMEOUT_MS); |
1198 | 1142 | ||
1199 | if (ret != TMF_RESP_FUNC_COMPLETE) | 1143 | if (ret != TMF_RESP_FUNC_COMPLETE) |
@@ -1212,6 +1156,8 @@ int isci_task_abort_task(struct sas_task *task) | |||
1212 | 1156 | ||
1213 | /* Make sure we do not leave a reference to aborted_io_completion */ | 1157 | /* Make sure we do not leave a reference to aborted_io_completion */ |
1214 | old_request->io_request_completion = NULL; | 1158 | old_request->io_request_completion = NULL; |
1159 | out: | ||
1160 | isci_put_device(isci_device); | ||
1215 | return ret; | 1161 | return ret; |
1216 | } | 1162 | } |
1217 | 1163 | ||
@@ -1305,7 +1251,6 @@ isci_task_request_complete(struct isci_host *ihost, | |||
1305 | struct isci_request *ireq, | 1251 | struct isci_request *ireq, |
1306 | enum sci_task_status completion_status) | 1252 | enum sci_task_status completion_status) |
1307 | { | 1253 | { |
1308 | struct isci_remote_device *idev = ireq->isci_device; | ||
1309 | struct isci_tmf *tmf = isci_request_access_tmf(ireq); | 1254 | struct isci_tmf *tmf = isci_request_access_tmf(ireq); |
1310 | struct completion *tmf_complete; | 1255 | struct completion *tmf_complete; |
1311 | struct scic_sds_request *sci_req = &ireq->sci; | 1256 | struct scic_sds_request *sci_req = &ireq->sci; |
@@ -1332,7 +1277,7 @@ isci_task_request_complete(struct isci_host *ihost, | |||
1332 | /* PRINT_TMF( ((struct isci_tmf *)request->task)); */ | 1277 | /* PRINT_TMF( ((struct isci_tmf *)request->task)); */ |
1333 | tmf_complete = tmf->complete; | 1278 | tmf_complete = tmf->complete; |
1334 | 1279 | ||
1335 | scic_controller_complete_io(&ihost->sci, &idev->sci, &ireq->sci); | 1280 | scic_controller_complete_io(&ihost->sci, ireq->sci.target_device, &ireq->sci); |
1336 | /* set the 'terminated' flag handle to make sure it cannot be terminated | 1281 | /* set the 'terminated' flag handle to make sure it cannot be terminated |
1337 | * or completed again. | 1282 | * or completed again. |
1338 | */ | 1283 | */ |
@@ -1583,11 +1528,10 @@ static void isci_wait_for_smp_phy_reset(struct isci_remote_device *idev, int phy | |||
1583 | dev_dbg(&ihost->pdev->dev, "%s: done\n", __func__); | 1528 | dev_dbg(&ihost->pdev->dev, "%s: done\n", __func__); |
1584 | } | 1529 | } |
1585 | 1530 | ||
1586 | static int isci_reset_device(struct domain_device *dev, int hard_reset) | 1531 | static int isci_reset_device(struct isci_host *ihost, |
1532 | struct isci_remote_device *idev, int hard_reset) | ||
1587 | { | 1533 | { |
1588 | struct isci_remote_device *idev = dev->lldd_dev; | 1534 | struct sas_phy *phy = sas_find_local_phy(idev->domain_dev); |
1589 | struct sas_phy *phy = sas_find_local_phy(dev); | ||
1590 | struct isci_host *ihost = dev_to_ihost(dev); | ||
1591 | struct isci_port *iport = idev->isci_port; | 1535 | struct isci_port *iport = idev->isci_port; |
1592 | enum sci_status status; | 1536 | enum sci_status status; |
1593 | unsigned long flags; | 1537 | unsigned long flags; |
@@ -1595,14 +1539,6 @@ static int isci_reset_device(struct domain_device *dev, int hard_reset) | |||
1595 | 1539 | ||
1596 | dev_dbg(&ihost->pdev->dev, "%s: idev %p\n", __func__, idev); | 1540 | dev_dbg(&ihost->pdev->dev, "%s: idev %p\n", __func__, idev); |
1597 | 1541 | ||
1598 | if (!idev) { | ||
1599 | dev_warn(&ihost->pdev->dev, | ||
1600 | "%s: idev is GONE!\n", | ||
1601 | __func__); | ||
1602 | |||
1603 | return TMF_RESP_FUNC_COMPLETE; /* Nothing to reset. */ | ||
1604 | } | ||
1605 | |||
1606 | spin_lock_irqsave(&ihost->scic_lock, flags); | 1542 | spin_lock_irqsave(&ihost->scic_lock, flags); |
1607 | status = scic_remote_device_reset(&idev->sci); | 1543 | status = scic_remote_device_reset(&idev->sci); |
1608 | if (status != SCI_SUCCESS) { | 1544 | if (status != SCI_SUCCESS) { |
@@ -1662,35 +1598,50 @@ static int isci_reset_device(struct domain_device *dev, int hard_reset) | |||
1662 | int isci_task_I_T_nexus_reset(struct domain_device *dev) | 1598 | int isci_task_I_T_nexus_reset(struct domain_device *dev) |
1663 | { | 1599 | { |
1664 | struct isci_host *ihost = dev_to_ihost(dev); | 1600 | struct isci_host *ihost = dev_to_ihost(dev); |
1665 | int ret = TMF_RESP_FUNC_FAILED, hard_reset = 1; | ||
1666 | struct isci_remote_device *idev; | 1601 | struct isci_remote_device *idev; |
1602 | int ret, hard_reset = 1; | ||
1667 | unsigned long flags; | 1603 | unsigned long flags; |
1668 | 1604 | ||
1669 | /* XXX mvsas is not protecting against ->lldd_dev_gone(), are we | ||
1670 | * being too paranoid, or is mvsas busted?! | ||
1671 | */ | ||
1672 | spin_lock_irqsave(&ihost->scic_lock, flags); | 1605 | spin_lock_irqsave(&ihost->scic_lock, flags); |
1673 | idev = dev->lldd_dev; | 1606 | idev = isci_lookup_device(dev); |
1674 | if (!idev || !test_bit(IDEV_EH, &idev->flags)) | ||
1675 | ret = TMF_RESP_FUNC_COMPLETE; | ||
1676 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | 1607 | spin_unlock_irqrestore(&ihost->scic_lock, flags); |
1677 | 1608 | ||
1678 | if (ret == TMF_RESP_FUNC_COMPLETE) | 1609 | if (!idev || !test_bit(IDEV_EH, &idev->flags)) { |
1679 | return ret; | 1610 | ret = TMF_RESP_FUNC_COMPLETE; |
1611 | goto out; | ||
1612 | } | ||
1680 | 1613 | ||
1681 | if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) | 1614 | if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) |
1682 | hard_reset = 0; | 1615 | hard_reset = 0; |
1683 | 1616 | ||
1684 | return isci_reset_device(dev, hard_reset); | 1617 | ret = isci_reset_device(ihost, idev, hard_reset); |
1618 | out: | ||
1619 | isci_put_device(idev); | ||
1620 | return ret; | ||
1685 | } | 1621 | } |
1686 | 1622 | ||
1687 | int isci_bus_reset_handler(struct scsi_cmnd *cmd) | 1623 | int isci_bus_reset_handler(struct scsi_cmnd *cmd) |
1688 | { | 1624 | { |
1689 | struct domain_device *dev = sdev_to_domain_dev(cmd->device); | 1625 | struct domain_device *dev = sdev_to_domain_dev(cmd->device); |
1690 | int hard_reset = 1; | 1626 | struct isci_host *ihost = dev_to_ihost(dev); |
1627 | struct isci_remote_device *idev; | ||
1628 | int ret, hard_reset = 1; | ||
1629 | unsigned long flags; | ||
1691 | 1630 | ||
1692 | if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) | 1631 | if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) |
1693 | hard_reset = 0; | 1632 | hard_reset = 0; |
1694 | 1633 | ||
1695 | return isci_reset_device(dev, hard_reset); | 1634 | spin_lock_irqsave(&ihost->scic_lock, flags); |
1635 | idev = isci_lookup_device(dev); | ||
1636 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | ||
1637 | |||
1638 | if (!idev) { | ||
1639 | ret = TMF_RESP_FUNC_COMPLETE; | ||
1640 | goto out; | ||
1641 | } | ||
1642 | |||
1643 | ret = isci_reset_device(ihost, idev, hard_reset); | ||
1644 | out: | ||
1645 | isci_put_device(idev); | ||
1646 | return ret; | ||
1696 | } | 1647 | } |