diff options
Diffstat (limited to 'drivers/scsi/isci')
-rw-r--r-- | drivers/scsi/isci/host.c | 22 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_device.c | 106 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_device.h | 10 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_node_context.c | 56 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_node_context.h | 2 | ||||
-rw-r--r-- | drivers/scsi/isci/request.c | 22 | ||||
-rw-r--r-- | drivers/scsi/isci/request.h | 2 |
7 files changed, 188 insertions, 32 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 5832b13e7b07..d241b5722eb3 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c | |||
@@ -2696,18 +2696,18 @@ enum sci_status sci_controller_terminate_request(struct isci_host *ihost, | |||
2696 | __func__, ihost->sm.current_state_id); | 2696 | __func__, ihost->sm.current_state_id); |
2697 | return SCI_FAILURE_INVALID_STATE; | 2697 | return SCI_FAILURE_INVALID_STATE; |
2698 | } | 2698 | } |
2699 | |||
2700 | status = sci_io_request_terminate(ireq); | 2699 | status = sci_io_request_terminate(ireq); |
2701 | if (status != SCI_SUCCESS) | 2700 | if ((status == SCI_SUCCESS) && |
2702 | return status; | 2701 | !test_bit(IREQ_PENDING_ABORT, &ireq->flags) && |
2703 | 2702 | !test_and_set_bit(IREQ_TC_ABORT_POSTED, &ireq->flags)) { | |
2704 | /* | 2703 | /* Utilize the original post context command and or in the |
2705 | * Utilize the original post context command and or in the POST_TC_ABORT | 2704 | * POST_TC_ABORT request sub-type. |
2706 | * request sub-type. | 2705 | */ |
2707 | */ | 2706 | sci_controller_post_request( |
2708 | sci_controller_post_request(ihost, | 2707 | ihost, ireq->post_context | |
2709 | ireq->post_context | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT); | 2708 | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT); |
2710 | return SCI_SUCCESS; | 2709 | } |
2710 | return status; | ||
2711 | } | 2711 | } |
2712 | 2712 | ||
2713 | /** | 2713 | /** |
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index b1a8000a5ef8..9f03877534d2 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c | |||
@@ -133,6 +133,50 @@ static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote | |||
133 | wake_up(&ihost->eventq); | 133 | wake_up(&ihost->eventq); |
134 | } | 134 | } |
135 | 135 | ||
136 | static enum sci_status sci_remote_device_suspend( | ||
137 | struct isci_remote_device *idev) | ||
138 | { | ||
139 | return sci_remote_node_context_suspend( | ||
140 | &idev->rnc, | ||
141 | SCI_SOFTWARE_SUSPENSION, | ||
142 | SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT, | ||
143 | NULL, NULL); | ||
144 | } | ||
145 | |||
146 | enum sci_status isci_remote_device_suspend( | ||
147 | struct isci_host *ihost, | ||
148 | struct isci_remote_device *idev) | ||
149 | { | ||
150 | enum sci_status status; | ||
151 | unsigned long flags; | ||
152 | |||
153 | spin_lock_irqsave(&ihost->scic_lock, flags); | ||
154 | |||
155 | if (isci_lookup_device(idev->domain_dev) == NULL) { | ||
156 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | ||
157 | status = SCI_FAILURE; | ||
158 | } else { | ||
159 | status = sci_remote_device_suspend(idev); | ||
160 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | ||
161 | if (status == SCI_SUCCESS) { | ||
162 | wait_event(ihost->eventq, | ||
163 | test_bit(IDEV_TXRX_SUSPENDED, &idev->flags) | ||
164 | || !test_bit(IDEV_ALLOCATED, &idev->flags)); | ||
165 | |||
166 | status = test_bit(IDEV_TXRX_SUSPENDED, &idev->flags) | ||
167 | ? SCI_SUCCESS : SCI_FAILURE; | ||
168 | dev_dbg(&ihost->pdev->dev, | ||
169 | "%s: idev=%p, wait done, device is %s\n", | ||
170 | __func__, idev, | ||
171 | test_bit(IDEV_TXRX_SUSPENDED, &idev->flags) | ||
172 | ? "<suspended>" : "<deallocated!>"); | ||
173 | |||
174 | } | ||
175 | isci_put_device(idev); | ||
176 | } | ||
177 | return status; | ||
178 | } | ||
179 | |||
136 | /* called once the remote node context is ready to be freed. | 180 | /* called once the remote node context is ready to be freed. |
137 | * The remote device can now report that its stop operation is complete. none | 181 | * The remote device can now report that its stop operation is complete. none |
138 | */ | 182 | */ |
@@ -144,7 +188,9 @@ static void rnc_destruct_done(void *_dev) | |||
144 | sci_change_state(&idev->sm, SCI_DEV_STOPPED); | 188 | sci_change_state(&idev->sm, SCI_DEV_STOPPED); |
145 | } | 189 | } |
146 | 190 | ||
147 | static enum sci_status sci_remote_device_terminate_requests(struct isci_remote_device *idev) | 191 | static enum sci_status sci_remote_device_terminate_requests_checkabort( |
192 | struct isci_remote_device *idev, | ||
193 | int check_abort_pending) | ||
148 | { | 194 | { |
149 | struct isci_host *ihost = idev->owning_port->owning_controller; | 195 | struct isci_host *ihost = idev->owning_port->owning_controller; |
150 | enum sci_status status = SCI_SUCCESS; | 196 | enum sci_status status = SCI_SUCCESS; |
@@ -155,7 +201,9 @@ static enum sci_status sci_remote_device_terminate_requests(struct isci_remote_d | |||
155 | enum sci_status s; | 201 | enum sci_status s; |
156 | 202 | ||
157 | if (!test_bit(IREQ_ACTIVE, &ireq->flags) || | 203 | if (!test_bit(IREQ_ACTIVE, &ireq->flags) || |
158 | ireq->target_device != idev) | 204 | (ireq->target_device != idev) || |
205 | (check_abort_pending && !test_bit(IREQ_PENDING_ABORT, | ||
206 | &ireq->flags))) | ||
159 | continue; | 207 | continue; |
160 | 208 | ||
161 | s = sci_controller_terminate_request(ihost, idev, ireq); | 209 | s = sci_controller_terminate_request(ihost, idev, ireq); |
@@ -166,6 +214,12 @@ static enum sci_status sci_remote_device_terminate_requests(struct isci_remote_d | |||
166 | return status; | 214 | return status; |
167 | } | 215 | } |
168 | 216 | ||
217 | enum sci_status sci_remote_device_terminate_requests( | ||
218 | struct isci_remote_device *idev) | ||
219 | { | ||
220 | return sci_remote_device_terminate_requests_checkabort(idev, 0); | ||
221 | } | ||
222 | |||
169 | enum sci_status sci_remote_device_stop(struct isci_remote_device *idev, | 223 | enum sci_status sci_remote_device_stop(struct isci_remote_device *idev, |
170 | u32 timeout) | 224 | u32 timeout) |
171 | { | 225 | { |
@@ -265,14 +319,6 @@ enum sci_status sci_remote_device_reset_complete(struct isci_remote_device *idev | |||
265 | return SCI_SUCCESS; | 319 | return SCI_SUCCESS; |
266 | } | 320 | } |
267 | 321 | ||
268 | enum sci_status sci_remote_device_suspend(struct isci_remote_device *idev) | ||
269 | { | ||
270 | return sci_remote_node_context_suspend(&idev->rnc, | ||
271 | SCI_SOFTWARE_SUSPENSION, | ||
272 | SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT, | ||
273 | NULL, NULL); | ||
274 | } | ||
275 | |||
276 | enum sci_status sci_remote_device_frame_handler(struct isci_remote_device *idev, | 322 | enum sci_status sci_remote_device_frame_handler(struct isci_remote_device *idev, |
277 | u32 frame_index) | 323 | u32 frame_index) |
278 | { | 324 | { |
@@ -1186,7 +1232,7 @@ static enum sci_status sci_remote_device_ea_construct(struct isci_port *iport, | |||
1186 | * the device when there have been no phys added to it. | 1232 | * the device when there have been no phys added to it. |
1187 | */ | 1233 | */ |
1188 | static enum sci_status sci_remote_device_start(struct isci_remote_device *idev, | 1234 | static enum sci_status sci_remote_device_start(struct isci_remote_device *idev, |
1189 | u32 timeout) | 1235 | u32 timeout) |
1190 | { | 1236 | { |
1191 | struct sci_base_state_machine *sm = &idev->sm; | 1237 | struct sci_base_state_machine *sm = &idev->sm; |
1192 | enum sci_remote_device_states state = sm->current_state_id; | 1238 | enum sci_remote_device_states state = sm->current_state_id; |
@@ -1413,3 +1459,41 @@ int isci_remote_device_found(struct domain_device *dev) | |||
1413 | 1459 | ||
1414 | return status == SCI_SUCCESS ? 0 : -ENODEV; | 1460 | return status == SCI_SUCCESS ? 0 : -ENODEV; |
1415 | } | 1461 | } |
1462 | |||
1463 | enum sci_status isci_remote_device_reset( | ||
1464 | struct isci_remote_device *idev) | ||
1465 | { | ||
1466 | struct isci_host *ihost = dev_to_ihost(idev->domain_dev); | ||
1467 | unsigned long flags; | ||
1468 | enum sci_status status; | ||
1469 | |||
1470 | /* Wait for the device suspend. */ | ||
1471 | status = isci_remote_device_suspend(ihost, idev); | ||
1472 | if (status != SCI_SUCCESS) { | ||
1473 | dev_dbg(&ihost->pdev->dev, | ||
1474 | "%s: isci_remote_device_suspend(%p) returned %d!\n", | ||
1475 | __func__, idev, status); | ||
1476 | return status; | ||
1477 | } | ||
1478 | spin_lock_irqsave(&ihost->scic_lock, flags); | ||
1479 | status = sci_remote_device_reset(idev); | ||
1480 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | ||
1481 | if (status != SCI_SUCCESS) { | ||
1482 | dev_dbg(&ihost->pdev->dev, | ||
1483 | "%s: sci_remote_device_reset(%p) returned %d!\n", | ||
1484 | __func__, idev, status); | ||
1485 | } | ||
1486 | return status; | ||
1487 | } | ||
1488 | |||
1489 | int isci_remote_device_is_safe_to_abort( | ||
1490 | struct isci_remote_device *idev) | ||
1491 | { | ||
1492 | return sci_remote_node_context_is_safe_to_abort(&idev->rnc); | ||
1493 | } | ||
1494 | |||
1495 | enum sci_status sci_remote_device_abort_requests_pending_abort( | ||
1496 | struct isci_remote_device *idev) | ||
1497 | { | ||
1498 | return sci_remote_device_terminate_requests_checkabort(idev, 1); | ||
1499 | } | ||
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 39159053b7ff..ae508ee33664 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h | |||
@@ -85,6 +85,7 @@ struct isci_remote_device { | |||
85 | #define IDEV_GONE 3 | 85 | #define IDEV_GONE 3 |
86 | #define IDEV_IO_READY 4 | 86 | #define IDEV_IO_READY 4 |
87 | #define IDEV_IO_NCQERROR 5 | 87 | #define IDEV_IO_NCQERROR 5 |
88 | #define IDEV_TXRX_SUSPENDED 6 | ||
88 | unsigned long flags; | 89 | unsigned long flags; |
89 | struct kref kref; | 90 | struct kref kref; |
90 | struct isci_port *isci_port; | 91 | struct isci_port *isci_port; |
@@ -335,4 +336,13 @@ void sci_remote_device_post_request( | |||
335 | struct isci_remote_device *idev, | 336 | struct isci_remote_device *idev, |
336 | u32 request); | 337 | u32 request); |
337 | 338 | ||
339 | enum sci_status sci_remote_device_terminate_requests( | ||
340 | struct isci_remote_device *idev); | ||
341 | |||
342 | int isci_remote_device_is_safe_to_abort( | ||
343 | struct isci_remote_device *idev); | ||
344 | |||
345 | enum sci_status | ||
346 | sci_remote_device_abort_requests_pending_abort( | ||
347 | struct isci_remote_device *idev); | ||
338 | #endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */ | 348 | #endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */ |
diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index f180c726c5bb..7a8347e51767 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c | |||
@@ -268,6 +268,8 @@ static void sci_remote_node_context_invalidating_state_enter(struct sci_base_sta | |||
268 | { | 268 | { |
269 | struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); | 269 | struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); |
270 | 270 | ||
271 | /* Terminate outstanding requests pending abort. */ | ||
272 | sci_remote_device_abort_requests_pending_abort(rnc_to_dev(rnc)); | ||
271 | sci_remote_node_context_invalidate_context_buffer(rnc); | 273 | sci_remote_node_context_invalidate_context_buffer(rnc); |
272 | } | 274 | } |
273 | 275 | ||
@@ -312,10 +314,28 @@ static void sci_remote_node_context_tx_suspended_state_enter(struct sci_base_sta | |||
312 | static void sci_remote_node_context_tx_rx_suspended_state_enter(struct sci_base_state_machine *sm) | 314 | static void sci_remote_node_context_tx_rx_suspended_state_enter(struct sci_base_state_machine *sm) |
313 | { | 315 | { |
314 | struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); | 316 | struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); |
317 | struct isci_remote_device *idev = rnc_to_dev(rnc); | ||
318 | struct isci_host *ihost = idev->owning_port->owning_controller; | ||
319 | |||
320 | set_bit(IDEV_TXRX_SUSPENDED, &idev->flags); | ||
315 | 321 | ||
322 | /* Terminate outstanding requests pending abort. */ | ||
323 | sci_remote_device_abort_requests_pending_abort(idev); | ||
324 | |||
325 | wake_up(&ihost->eventq); | ||
316 | sci_remote_node_context_continue_state_transitions(rnc); | 326 | sci_remote_node_context_continue_state_transitions(rnc); |
317 | } | 327 | } |
318 | 328 | ||
329 | static void sci_remote_node_context_tx_rx_suspended_state_exit( | ||
330 | struct sci_base_state_machine *sm) | ||
331 | { | ||
332 | struct sci_remote_node_context *rnc | ||
333 | = container_of(sm, typeof(*rnc), sm); | ||
334 | struct isci_remote_device *idev = rnc_to_dev(rnc); | ||
335 | |||
336 | clear_bit(IDEV_TXRX_SUSPENDED, &idev->flags); | ||
337 | } | ||
338 | |||
319 | static void sci_remote_node_context_await_suspend_state_exit( | 339 | static void sci_remote_node_context_await_suspend_state_exit( |
320 | struct sci_base_state_machine *sm) | 340 | struct sci_base_state_machine *sm) |
321 | { | 341 | { |
@@ -346,6 +366,8 @@ static const struct sci_base_state sci_remote_node_context_state_table[] = { | |||
346 | }, | 366 | }, |
347 | [SCI_RNC_TX_RX_SUSPENDED] = { | 367 | [SCI_RNC_TX_RX_SUSPENDED] = { |
348 | .enter_state = sci_remote_node_context_tx_rx_suspended_state_enter, | 368 | .enter_state = sci_remote_node_context_tx_rx_suspended_state_enter, |
369 | .exit_state | ||
370 | = sci_remote_node_context_tx_rx_suspended_state_exit, | ||
349 | }, | 371 | }, |
350 | [SCI_RNC_AWAIT_SUSPENSION] = { | 372 | [SCI_RNC_AWAIT_SUSPENSION] = { |
351 | .exit_state = sci_remote_node_context_await_suspend_state_exit, | 373 | .exit_state = sci_remote_node_context_await_suspend_state_exit, |
@@ -515,6 +537,13 @@ enum sci_status sci_remote_node_context_suspend( | |||
515 | struct isci_remote_device *idev = rnc_to_dev(sci_rnc); | 537 | struct isci_remote_device *idev = rnc_to_dev(sci_rnc); |
516 | enum sci_status status = SCI_FAILURE_INVALID_STATE; | 538 | enum sci_status status = SCI_FAILURE_INVALID_STATE; |
517 | 539 | ||
540 | dev_dbg(scirdev_to_dev(idev), | ||
541 | "%s: current state %d, current suspend_type %x dest state %d," | ||
542 | " arg suspend_reason %d, arg suspend_type %x", | ||
543 | __func__, state, sci_rnc->suspend_type, | ||
544 | sci_rnc->destination_state, suspend_reason, | ||
545 | suspend_type); | ||
546 | |||
518 | /* Disable automatic state continuations if explicitly suspending. */ | 547 | /* Disable automatic state continuations if explicitly suspending. */ |
519 | if (suspend_reason == SCI_SOFTWARE_SUSPENSION) | 548 | if (suspend_reason == SCI_SOFTWARE_SUSPENSION) |
520 | sci_rnc->destination_state | 549 | sci_rnc->destination_state |
@@ -546,7 +575,10 @@ enum sci_status sci_remote_node_context_suspend( | |||
546 | sci_rnc->suspend_type = suspend_type; | 575 | sci_rnc->suspend_type = suspend_type; |
547 | 576 | ||
548 | if (status == SCI_SUCCESS) { /* Already in the destination state? */ | 577 | if (status == SCI_SUCCESS) { /* Already in the destination state? */ |
578 | struct isci_host *ihost = idev->owning_port->owning_controller; | ||
579 | |||
549 | sci_remote_node_context_notify_user(sci_rnc); | 580 | sci_remote_node_context_notify_user(sci_rnc); |
581 | wake_up_all(&ihost->eventq); /* Let observers look. */ | ||
550 | return SCI_SUCCESS; | 582 | return SCI_SUCCESS; |
551 | } | 583 | } |
552 | if (suspend_reason == SCI_SOFTWARE_SUSPENSION) { | 584 | if (suspend_reason == SCI_SOFTWARE_SUSPENSION) { |
@@ -661,3 +693,27 @@ enum sci_status sci_remote_node_context_start_task(struct sci_remote_node_contex | |||
661 | return SCI_FAILURE_INVALID_STATE; | 693 | return SCI_FAILURE_INVALID_STATE; |
662 | } | 694 | } |
663 | } | 695 | } |
696 | |||
697 | int sci_remote_node_context_is_safe_to_abort( | ||
698 | struct sci_remote_node_context *sci_rnc) | ||
699 | { | ||
700 | enum scis_sds_remote_node_context_states state; | ||
701 | |||
702 | state = sci_rnc->sm.current_state_id; | ||
703 | switch (state) { | ||
704 | case SCI_RNC_INVALIDATING: | ||
705 | case SCI_RNC_TX_RX_SUSPENDED: | ||
706 | return 1; | ||
707 | case SCI_RNC_POSTING: | ||
708 | case SCI_RNC_RESUMING: | ||
709 | case SCI_RNC_READY: | ||
710 | case SCI_RNC_TX_SUSPENDED: | ||
711 | case SCI_RNC_AWAIT_SUSPENSION: | ||
712 | case SCI_RNC_INITIAL: | ||
713 | return 0; | ||
714 | default: | ||
715 | dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), | ||
716 | "%s: invalid state %d\n", __func__, state); | ||
717 | return 0; | ||
718 | } | ||
719 | } | ||
diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h index 276fc491e8f9..5ddf88b53133 100644 --- a/drivers/scsi/isci/remote_node_context.h +++ b/drivers/scsi/isci/remote_node_context.h | |||
@@ -214,5 +214,7 @@ enum sci_status sci_remote_node_context_start_task(struct sci_remote_node_contex | |||
214 | struct isci_request *ireq); | 214 | struct isci_request *ireq); |
215 | enum sci_status sci_remote_node_context_start_io(struct sci_remote_node_context *sci_rnc, | 215 | enum sci_status sci_remote_node_context_start_io(struct sci_remote_node_context *sci_rnc, |
216 | struct isci_request *ireq); | 216 | struct isci_request *ireq); |
217 | int sci_remote_node_context_is_safe_to_abort( | ||
218 | struct sci_remote_node_context *sci_rnc); | ||
217 | 219 | ||
218 | #endif /* _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ */ | 220 | #endif /* _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ */ |
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 605dc68cbf79..1f314d0d71d5 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c | |||
@@ -863,6 +863,8 @@ sci_io_request_terminate(struct isci_request *ireq) | |||
863 | 863 | ||
864 | switch (state) { | 864 | switch (state) { |
865 | case SCI_REQ_CONSTRUCTED: | 865 | case SCI_REQ_CONSTRUCTED: |
866 | /* Set to make sure no HW terminate posting is done: */ | ||
867 | set_bit(IREQ_TC_ABORT_POSTED, &ireq->flags); | ||
866 | ireq->scu_status = SCU_TASK_DONE_TASK_ABORT; | 868 | ireq->scu_status = SCU_TASK_DONE_TASK_ABORT; |
867 | ireq->sci_status = SCI_FAILURE_IO_TERMINATED; | 869 | ireq->sci_status = SCI_FAILURE_IO_TERMINATED; |
868 | sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); | 870 | sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); |
@@ -883,8 +885,7 @@ sci_io_request_terminate(struct isci_request *ireq) | |||
883 | case SCI_REQ_ATAPI_WAIT_PIO_SETUP: | 885 | case SCI_REQ_ATAPI_WAIT_PIO_SETUP: |
884 | case SCI_REQ_ATAPI_WAIT_D2H: | 886 | case SCI_REQ_ATAPI_WAIT_D2H: |
885 | case SCI_REQ_ATAPI_WAIT_TC_COMP: | 887 | case SCI_REQ_ATAPI_WAIT_TC_COMP: |
886 | sci_change_state(&ireq->sm, SCI_REQ_ABORTING); | 888 | /* Fall through and change state to ABORTING... */ |
887 | return SCI_SUCCESS; | ||
888 | case SCI_REQ_TASK_WAIT_TC_RESP: | 889 | case SCI_REQ_TASK_WAIT_TC_RESP: |
889 | /* The task frame was already confirmed to have been | 890 | /* The task frame was already confirmed to have been |
890 | * sent by the SCU HW. Since the state machine is | 891 | * sent by the SCU HW. Since the state machine is |
@@ -893,20 +894,21 @@ sci_io_request_terminate(struct isci_request *ireq) | |||
893 | * and don't wait for the task response. | 894 | * and don't wait for the task response. |
894 | */ | 895 | */ |
895 | sci_change_state(&ireq->sm, SCI_REQ_ABORTING); | 896 | sci_change_state(&ireq->sm, SCI_REQ_ABORTING); |
896 | sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); | 897 | /* Fall through and handle like ABORTING... */ |
897 | return SCI_SUCCESS; | ||
898 | case SCI_REQ_ABORTING: | 898 | case SCI_REQ_ABORTING: |
899 | /* If a request has a termination requested twice, return | 899 | if (!isci_remote_device_is_safe_to_abort(ireq->target_device)) |
900 | * a failure indication, since HW confirmation of the first | 900 | set_bit(IREQ_PENDING_ABORT, &ireq->flags); |
901 | * abort is still outstanding. | 901 | else |
902 | clear_bit(IREQ_PENDING_ABORT, &ireq->flags); | ||
903 | /* If the request is only waiting on the remote device | ||
904 | * suspension, return SUCCESS so the caller will wait too. | ||
902 | */ | 905 | */ |
906 | return SCI_SUCCESS; | ||
903 | case SCI_REQ_COMPLETED: | 907 | case SCI_REQ_COMPLETED: |
904 | default: | 908 | default: |
905 | dev_warn(&ireq->owning_controller->pdev->dev, | 909 | dev_warn(&ireq->owning_controller->pdev->dev, |
906 | "%s: SCIC IO Request requested to abort while in wrong " | 910 | "%s: SCIC IO Request requested to abort while in wrong " |
907 | "state %d\n", | 911 | "state %d\n", __func__, ireq->sm.current_state_id); |
908 | __func__, | ||
909 | ireq->sm.current_state_id); | ||
910 | break; | 912 | break; |
911 | } | 913 | } |
912 | 914 | ||
diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index e845a31ecebb..8d55f78010aa 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h | |||
@@ -102,6 +102,8 @@ struct isci_request { | |||
102 | #define IREQ_TERMINATED 1 | 102 | #define IREQ_TERMINATED 1 |
103 | #define IREQ_TMF 2 | 103 | #define IREQ_TMF 2 |
104 | #define IREQ_ACTIVE 3 | 104 | #define IREQ_ACTIVE 3 |
105 | #define IREQ_PENDING_ABORT 4 /* Set == device was not suspended yet */ | ||
106 | #define IREQ_TC_ABORT_POSTED 5 | ||
105 | unsigned long flags; | 107 | unsigned long flags; |
106 | /* XXX kill ttype and ttype_ptr, allocate full sas_task */ | 108 | /* XXX kill ttype and ttype_ptr, allocate full sas_task */ |
107 | union ttype_ptr_union { | 109 | union ttype_ptr_union { |