aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/isci/remote_device.c86
-rw-r--r--drivers/scsi/isci/remote_device.h4
-rw-r--r--drivers/scsi/isci/remote_node_context.c74
-rw-r--r--drivers/scsi/isci/remote_node_context.h13
-rw-r--r--drivers/scsi/isci/request.c149
-rw-r--r--drivers/scsi/isci/request.h1
-rw-r--r--drivers/scsi/isci/scu_completion_codes.h2
7 files changed, 242 insertions, 87 deletions
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index 71f509064737..b1a8000a5ef8 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -265,20 +265,12 @@ enum sci_status sci_remote_device_reset_complete(struct isci_remote_device *idev
265 return SCI_SUCCESS; 265 return SCI_SUCCESS;
266} 266}
267 267
268enum sci_status sci_remote_device_suspend(struct isci_remote_device *idev, 268enum sci_status sci_remote_device_suspend(struct isci_remote_device *idev)
269 u32 suspend_type)
270{ 269{
271 struct sci_base_state_machine *sm = &idev->sm;
272 enum sci_remote_device_states state = sm->current_state_id;
273
274 if (state != SCI_STP_DEV_CMD) {
275 dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %s\n",
276 __func__, dev_state_name(state));
277 return SCI_FAILURE_INVALID_STATE;
278 }
279
280 return sci_remote_node_context_suspend(&idev->rnc, 270 return sci_remote_node_context_suspend(&idev->rnc,
281 suspend_type, NULL, NULL); 271 SCI_SOFTWARE_SUSPENSION,
272 SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT,
273 NULL, NULL);
282} 274}
283 275
284enum sci_status sci_remote_device_frame_handler(struct isci_remote_device *idev, 276enum sci_status sci_remote_device_frame_handler(struct isci_remote_device *idev,
@@ -412,8 +404,6 @@ static void atapi_remote_device_resume_done(void *_dev)
412enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev, 404enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
413 u32 event_code) 405 u32 event_code)
414{ 406{
415 struct sci_base_state_machine *sm = &idev->sm;
416 enum sci_remote_device_states state = sm->current_state_id;
417 enum sci_status status; 407 enum sci_status status;
418 408
419 switch (scu_get_event_type(event_code)) { 409 switch (scu_get_event_type(event_code)) {
@@ -427,9 +417,11 @@ enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
427 status = SCI_SUCCESS; 417 status = SCI_SUCCESS;
428 418
429 /* Suspend the associated RNC */ 419 /* Suspend the associated RNC */
430 sci_remote_node_context_suspend(&idev->rnc, 420 sci_remote_node_context_suspend(
431 SCI_SOFTWARE_SUSPENSION, 421 &idev->rnc,
432 NULL, NULL); 422 SCI_SOFTWARE_SUSPENSION,
423 SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT,
424 NULL, NULL);
433 425
434 dev_dbg(scirdev_to_dev(idev), 426 dev_dbg(scirdev_to_dev(idev),
435 "%s: device: %p event code: %x: %s\n", 427 "%s: device: %p event code: %x: %s\n",
@@ -455,26 +447,6 @@ enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
455 if (status != SCI_SUCCESS) 447 if (status != SCI_SUCCESS)
456 return status; 448 return status;
457 449
458 if (state == SCI_STP_DEV_ATAPI_ERROR) {
459 /* For ATAPI error state resume the RNC right away. */
460 if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX ||
461 scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) {
462 return sci_remote_node_context_resume(&idev->rnc,
463 atapi_remote_device_resume_done,
464 idev);
465 }
466 }
467
468 if (state == SCI_STP_DEV_IDLE) {
469
470 /* We pick up suspension events to handle specifically to this
471 * state. We resume the RNC right away.
472 */
473 if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX ||
474 scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX)
475 status = sci_remote_node_context_resume(&idev->rnc, NULL, NULL);
476 }
477
478 return status; 450 return status;
479} 451}
480 452
@@ -765,11 +737,11 @@ enum sci_status sci_remote_device_start_task(struct isci_host *ihost,
765 * the correct action when the remote node context is suspended 737 * the correct action when the remote node context is suspended
766 * and later resumed. 738 * and later resumed.
767 */ 739 */
768 sci_remote_node_context_suspend(&idev->rnc, 740 sci_remote_node_context_suspend(
769 SCI_SOFTWARE_SUSPENSION, NULL, NULL); 741 &idev->rnc, SCI_SOFTWARE_SUSPENSION,
770 sci_remote_node_context_resume(&idev->rnc, 742 SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT, NULL, NULL);
771 sci_remote_device_continue_request, 743 sci_remote_node_context_resume(
772 idev); 744 &idev->rnc, sci_remote_device_continue_request, idev);
773 745
774 out: 746 out:
775 sci_remote_device_start_request(idev, ireq, status); 747 sci_remote_device_start_request(idev, ireq, status);
@@ -954,14 +926,23 @@ static void sci_remote_device_ready_state_exit(struct sci_base_state_machine *sm
954static void sci_remote_device_resetting_state_enter(struct sci_base_state_machine *sm) 926static void sci_remote_device_resetting_state_enter(struct sci_base_state_machine *sm)
955{ 927{
956 struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); 928 struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
929 struct isci_host *ihost = idev->owning_port->owning_controller;
930
931 dev_dbg(&ihost->pdev->dev,
932 "%s: isci_device = %p\n", __func__, idev);
957 933
958 sci_remote_node_context_suspend( 934 sci_remote_node_context_suspend(
959 &idev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); 935 &idev->rnc, SCI_SOFTWARE_SUSPENSION,
936 SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT, NULL, NULL);
960} 937}
961 938
962static void sci_remote_device_resetting_state_exit(struct sci_base_state_machine *sm) 939static void sci_remote_device_resetting_state_exit(struct sci_base_state_machine *sm)
963{ 940{
964 struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); 941 struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
942 struct isci_host *ihost = idev->owning_port->owning_controller;
943
944 dev_dbg(&ihost->pdev->dev,
945 "%s: isci_device = %p\n", __func__, idev);
965 946
966 sci_remote_node_context_resume(&idev->rnc, NULL, NULL); 947 sci_remote_node_context_resume(&idev->rnc, NULL, NULL);
967} 948}
@@ -1004,6 +985,21 @@ static void sci_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base
1004 idev->not_ready_reason); 985 idev->not_ready_reason);
1005} 986}
1006 987
988static void sci_stp_remote_device_atapi_error_substate_enter(
989 struct sci_base_state_machine *sm)
990{
991 struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
992
993 /* This state is entered when an I/O is decoded with an error
994 * condition. By this point the RNC expected suspension state is set.
995 * The error conditions suspend the device, so unsuspend here if
996 * possible.
997 */
998 sci_remote_node_context_resume(&idev->rnc,
999 atapi_remote_device_resume_done,
1000 idev);
1001}
1002
1007static void sci_smp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm) 1003static void sci_smp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm)
1008{ 1004{
1009 struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); 1005 struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
@@ -1054,7 +1050,9 @@ static const struct sci_base_state sci_remote_device_state_table[] = {
1054 [SCI_STP_DEV_NCQ_ERROR] = { 1050 [SCI_STP_DEV_NCQ_ERROR] = {
1055 .enter_state = sci_stp_remote_device_ready_ncq_error_substate_enter, 1051 .enter_state = sci_stp_remote_device_ready_ncq_error_substate_enter,
1056 }, 1052 },
1057 [SCI_STP_DEV_ATAPI_ERROR] = { }, 1053 [SCI_STP_DEV_ATAPI_ERROR] = {
1054 .enter_state = sci_stp_remote_device_atapi_error_substate_enter,
1055 },
1058 [SCI_STP_DEV_AWAIT_RESET] = { }, 1056 [SCI_STP_DEV_AWAIT_RESET] = { },
1059 [SCI_SMP_DEV_IDLE] = { 1057 [SCI_SMP_DEV_IDLE] = {
1060 .enter_state = sci_smp_remote_device_ready_idle_substate_enter, 1058 .enter_state = sci_smp_remote_device_ready_idle_substate_enter,
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h
index 4850b58edbe6..39159053b7ff 100644
--- a/drivers/scsi/isci/remote_device.h
+++ b/drivers/scsi/isci/remote_device.h
@@ -331,10 +331,6 @@ enum sci_status sci_remote_device_complete_io(
331 struct isci_remote_device *idev, 331 struct isci_remote_device *idev,
332 struct isci_request *ireq); 332 struct isci_request *ireq);
333 333
334enum sci_status sci_remote_device_suspend(
335 struct isci_remote_device *idev,
336 u32 suspend_type);
337
338void sci_remote_device_post_request( 334void sci_remote_device_post_request(
339 struct isci_remote_device *idev, 335 struct isci_remote_device *idev,
340 u32 request); 336 u32 request);
diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c
index 3e849752bffa..f180c726c5bb 100644
--- a/drivers/scsi/isci/remote_node_context.c
+++ b/drivers/scsi/isci/remote_node_context.c
@@ -367,6 +367,7 @@ enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_con
367 u32 event_code) 367 u32 event_code)
368{ 368{
369 enum scis_sds_remote_node_context_states state; 369 enum scis_sds_remote_node_context_states state;
370 u32 next_state;
370 371
371 state = sci_rnc->sm.current_state_id; 372 state = sci_rnc->sm.current_state_id;
372 switch (state) { 373 switch (state) {
@@ -425,11 +426,11 @@ enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_con
425 switch (scu_get_event_type(event_code)) { 426 switch (scu_get_event_type(event_code)) {
426 case SCU_EVENT_TL_RNC_SUSPEND_TX: 427 case SCU_EVENT_TL_RNC_SUSPEND_TX:
427 sci_change_state(&sci_rnc->sm, SCI_RNC_TX_SUSPENDED); 428 sci_change_state(&sci_rnc->sm, SCI_RNC_TX_SUSPENDED);
428 sci_rnc->suspension_code = scu_get_event_specifier(event_code); 429 sci_rnc->suspend_type = scu_get_event_type(event_code);
429 break; 430 break;
430 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: 431 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
431 sci_change_state(&sci_rnc->sm, SCI_RNC_TX_RX_SUSPENDED); 432 sci_change_state(&sci_rnc->sm, SCI_RNC_TX_RX_SUSPENDED);
432 sci_rnc->suspension_code = scu_get_event_specifier(event_code); 433 sci_rnc->suspend_type = scu_get_event_type(event_code);
433 break; 434 break;
434 default: 435 default:
435 goto out; 436 goto out;
@@ -438,16 +439,16 @@ enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_con
438 case SCI_RNC_AWAIT_SUSPENSION: 439 case SCI_RNC_AWAIT_SUSPENSION:
439 switch (scu_get_event_type(event_code)) { 440 switch (scu_get_event_type(event_code)) {
440 case SCU_EVENT_TL_RNC_SUSPEND_TX: 441 case SCU_EVENT_TL_RNC_SUSPEND_TX:
441 sci_change_state(&sci_rnc->sm, SCI_RNC_TX_SUSPENDED); 442 next_state = SCI_RNC_TX_SUSPENDED;
442 sci_rnc->suspension_code = scu_get_event_specifier(event_code);
443 break; 443 break;
444 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: 444 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
445 sci_change_state(&sci_rnc->sm, SCI_RNC_TX_RX_SUSPENDED); 445 next_state = SCI_RNC_TX_RX_SUSPENDED;
446 sci_rnc->suspension_code = scu_get_event_specifier(event_code);
447 break; 446 break;
448 default: 447 default:
449 goto out; 448 goto out;
450 } 449 }
450 if (sci_rnc->suspend_type == scu_get_event_type(event_code))
451 sci_change_state(&sci_rnc->sm, next_state);
451 break; 452 break;
452 default: 453 default:
453 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), 454 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
@@ -502,33 +503,60 @@ enum sci_status sci_remote_node_context_destruct(struct sci_remote_node_context
502 } 503 }
503} 504}
504 505
505enum sci_status sci_remote_node_context_suspend(struct sci_remote_node_context *sci_rnc, 506enum sci_status sci_remote_node_context_suspend(
506 u32 suspend_type, 507 struct sci_remote_node_context *sci_rnc,
507 scics_sds_remote_node_context_callback cb_fn, 508 enum sci_remote_node_suspension_reasons suspend_reason,
508 void *cb_p) 509 u32 suspend_type,
510 scics_sds_remote_node_context_callback cb_fn,
511 void *cb_p)
509{ 512{
510 enum scis_sds_remote_node_context_states state; 513 enum scis_sds_remote_node_context_states state
514 = sci_rnc->sm.current_state_id;
515 struct isci_remote_device *idev = rnc_to_dev(sci_rnc);
516 enum sci_status status = SCI_FAILURE_INVALID_STATE;
511 517
512 state = sci_rnc->sm.current_state_id; 518 /* Disable automatic state continuations if explicitly suspending. */
513 if (state != SCI_RNC_READY) { 519 if (suspend_reason == SCI_SOFTWARE_SUSPENSION)
520 sci_rnc->destination_state
521 = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
522 switch (state) {
523 case SCI_RNC_READY:
524 break;
525 case SCI_RNC_TX_SUSPENDED:
526 if (suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX)
527 status = SCI_SUCCESS;
528 break;
529 case SCI_RNC_TX_RX_SUSPENDED:
530 if (suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX_RX)
531 status = SCI_SUCCESS;
532 break;
533 case SCI_RNC_AWAIT_SUSPENSION:
534 if ((sci_rnc->suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX_RX)
535 || (suspend_type == sci_rnc->suspend_type))
536 return SCI_SUCCESS;
537 break;
538 default:
514 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), 539 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
515 "%s: invalid state %s\n", __func__, 540 "%s: invalid state %s\n", __func__,
516 rnc_state_name(state)); 541 rnc_state_name(state));
517 return SCI_FAILURE_INVALID_STATE; 542 return SCI_FAILURE_INVALID_STATE;
518 } 543 }
544 sci_rnc->user_callback = cb_fn;
545 sci_rnc->user_cookie = cb_p;
546 sci_rnc->suspend_type = suspend_type;
519 547
520 sci_rnc->user_callback = cb_fn; 548 if (status == SCI_SUCCESS) { /* Already in the destination state? */
521 sci_rnc->user_cookie = cb_p; 549 sci_remote_node_context_notify_user(sci_rnc);
522 sci_rnc->suspension_code = suspend_type; 550 return SCI_SUCCESS;
523 551 }
524 if (suspend_type == SCI_SOFTWARE_SUSPENSION) { 552 if (suspend_reason == SCI_SOFTWARE_SUSPENSION) {
525 sci_remote_device_post_request(rnc_to_dev(sci_rnc), 553 isci_dev_set_hang_detection_timeout(idev, 0x00000001);
526 SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX); 554 sci_remote_device_post_request(
527 isci_dev_set_hang_detection_timeout(rnc_to_dev(sci_rnc), 555 idev, SCI_SOFTWARE_SUSPEND_CMD);
528 0x00000001);
529 } 556 }
557 if (state != SCI_RNC_AWAIT_SUSPENSION)
558 sci_change_state(&sci_rnc->sm, SCI_RNC_AWAIT_SUSPENSION);
530 559
531 sci_change_state(&sci_rnc->sm, SCI_RNC_AWAIT_SUSPENSION);
532 return SCI_SUCCESS; 560 return SCI_SUCCESS;
533} 561}
534 562
diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h
index a241e0f4c865..276fc491e8f9 100644
--- a/drivers/scsi/isci/remote_node_context.h
+++ b/drivers/scsi/isci/remote_node_context.h
@@ -75,8 +75,12 @@
75 */ 75 */
76#define SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX 0x0FFF 76#define SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX 0x0FFF
77 77
78#define SCU_HARDWARE_SUSPENSION (0) 78enum sci_remote_node_suspension_reasons {
79#define SCI_SOFTWARE_SUSPENSION (1) 79 SCU_HARDWARE_SUSPENSION,
80 SCI_SOFTWARE_SUSPENSION
81};
82#define SCI_SOFTWARE_SUSPEND_CMD SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX
83#define SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT SCU_EVENT_TL_RNC_SUSPEND_TX_RX
80 84
81struct isci_request; 85struct isci_request;
82struct isci_remote_device; 86struct isci_remote_device;
@@ -156,10 +160,10 @@ struct sci_remote_node_context {
156 u16 remote_node_index; 160 u16 remote_node_index;
157 161
158 /** 162 /**
159 * This field is the recored suspension code or the reason for the remote node 163 * This field is the recored suspension type of the remote node
160 * context suspension. 164 * context suspension.
161 */ 165 */
162 u32 suspension_code; 166 u32 suspend_type;
163 167
164 /** 168 /**
165 * This field is true if the remote node context is resuming from its current 169 * This field is true if the remote node context is resuming from its current
@@ -200,6 +204,7 @@ enum sci_status sci_remote_node_context_destruct(struct sci_remote_node_context
200 void *callback_parameter); 204 void *callback_parameter);
201enum sci_status sci_remote_node_context_suspend(struct sci_remote_node_context *sci_rnc, 205enum sci_status sci_remote_node_context_suspend(struct sci_remote_node_context *sci_rnc,
202 u32 suspend_type, 206 u32 suspend_type,
207 u32 suspension_code,
203 scics_sds_remote_node_context_callback cb_fn, 208 scics_sds_remote_node_context_callback cb_fn,
204 void *cb_p); 209 void *cb_p);
205enum sci_status sci_remote_node_context_resume(struct sci_remote_node_context *sci_rnc, 210enum sci_status sci_remote_node_context_resume(struct sci_remote_node_context *sci_rnc,
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index dcd26eadf867..605dc68cbf79 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -2116,9 +2116,6 @@ static enum sci_status stp_request_udma_await_tc_event(struct isci_request *ireq
2116 * completion. 2116 * completion.
2117 */ 2117 */
2118 if (ireq->stp.rsp.fis_type == FIS_REGD2H) { 2118 if (ireq->stp.rsp.fis_type == FIS_REGD2H) {
2119 sci_remote_device_suspend(ireq->target_device,
2120 SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)));
2121
2122 ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE; 2119 ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE;
2123 ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID; 2120 ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
2124 sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); 2121 sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
@@ -2138,13 +2135,6 @@ static enum sci_status stp_request_udma_await_tc_event(struct isci_request *ireq
2138 /* TODO We can retry the command for SCU_TASK_DONE_CMD_LL_R_ERR 2135 /* TODO We can retry the command for SCU_TASK_DONE_CMD_LL_R_ERR
2139 * - this comes only for B0 2136 * - this comes only for B0
2140 */ 2137 */
2141 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_INV_FIS_LEN):
2142 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR):
2143 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR):
2144 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR):
2145 sci_remote_device_suspend(ireq->target_device,
2146 SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)));
2147 /* Fall through to the default case */
2148 default: 2138 default:
2149 /* All other completion status cause the IO to be complete. */ 2139 /* All other completion status cause the IO to be complete. */
2150 ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code); 2140 ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code);
@@ -2262,15 +2252,152 @@ static enum sci_status atapi_data_tc_completion_handler(struct isci_request *ire
2262 return status; 2252 return status;
2263} 2253}
2264 2254
2255static int sci_request_smp_completion_status_is_tx_suspend(
2256 unsigned int completion_status)
2257{
2258 switch (completion_status) {
2259 case SCU_TASK_OPEN_REJECT_WRONG_DESTINATION:
2260 case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1:
2261 case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2:
2262 case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3:
2263 case SCU_TASK_OPEN_REJECT_BAD_DESTINATION:
2264 case SCU_TASK_OPEN_REJECT_ZONE_VIOLATION:
2265 return 1;
2266 }
2267 return 0;
2268}
2269
2270static int sci_request_smp_completion_status_is_tx_rx_suspend(
2271 unsigned int completion_status)
2272{
2273 return 0; /* There are no Tx/Rx SMP suspend conditions. */
2274}
2275
2276static int sci_request_ssp_completion_status_is_tx_suspend(
2277 unsigned int completion_status)
2278{
2279 switch (completion_status) {
2280 case SCU_TASK_DONE_TX_RAW_CMD_ERR:
2281 case SCU_TASK_DONE_LF_ERR:
2282 case SCU_TASK_OPEN_REJECT_WRONG_DESTINATION:
2283 case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1:
2284 case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2:
2285 case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3:
2286 case SCU_TASK_OPEN_REJECT_BAD_DESTINATION:
2287 case SCU_TASK_OPEN_REJECT_ZONE_VIOLATION:
2288 case SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY:
2289 case SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED:
2290 case SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED:
2291 return 1;
2292 }
2293 return 0;
2294}
2295
2296static int sci_request_ssp_completion_status_is_tx_rx_suspend(
2297 unsigned int completion_status)
2298{
2299 return 0; /* There are no Tx/Rx SSP suspend conditions. */
2300}
2301
2302static int sci_request_stpsata_completion_status_is_tx_suspend(
2303 unsigned int completion_status)
2304{
2305 switch (completion_status) {
2306 case SCU_TASK_DONE_TX_RAW_CMD_ERR:
2307 case SCU_TASK_DONE_LL_R_ERR:
2308 case SCU_TASK_DONE_LL_PERR:
2309 case SCU_TASK_DONE_REG_ERR:
2310 case SCU_TASK_DONE_SDB_ERR:
2311 case SCU_TASK_OPEN_REJECT_WRONG_DESTINATION:
2312 case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1:
2313 case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2:
2314 case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3:
2315 case SCU_TASK_OPEN_REJECT_BAD_DESTINATION:
2316 case SCU_TASK_OPEN_REJECT_ZONE_VIOLATION:
2317 case SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY:
2318 case SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED:
2319 case SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED:
2320 return 1;
2321 }
2322 return 0;
2323}
2324
2325
2326static int sci_request_stpsata_completion_status_is_tx_rx_suspend(
2327 unsigned int completion_status)
2328{
2329 switch (completion_status) {
2330 case SCU_TASK_DONE_LF_ERR:
2331 case SCU_TASK_DONE_LL_SY_TERM:
2332 case SCU_TASK_DONE_LL_LF_TERM:
2333 case SCU_TASK_DONE_BREAK_RCVD:
2334 case SCU_TASK_DONE_INV_FIS_LEN:
2335 case SCU_TASK_DONE_UNEXP_FIS:
2336 case SCU_TASK_DONE_UNEXP_SDBFIS:
2337 case SCU_TASK_DONE_MAX_PLD_ERR:
2338 return 1;
2339 }
2340 return 0;
2341}
2342
2343static void sci_request_handle_suspending_completions(
2344 struct isci_request *ireq,
2345 u32 completion_code)
2346{
2347 int is_tx = 0;
2348 int is_tx_rx = 0;
2349
2350 switch (ireq->protocol) {
2351 case SAS_PROTOCOL_SMP:
2352 is_tx = sci_request_smp_completion_status_is_tx_suspend(
2353 completion_code);
2354 is_tx_rx = sci_request_smp_completion_status_is_tx_rx_suspend(
2355 completion_code);
2356 break;
2357 case SAS_PROTOCOL_SSP:
2358 is_tx = sci_request_ssp_completion_status_is_tx_suspend(
2359 completion_code);
2360 is_tx_rx = sci_request_ssp_completion_status_is_tx_rx_suspend(
2361 completion_code);
2362 break;
2363 case SAS_PROTOCOL_STP:
2364 is_tx = sci_request_stpsata_completion_status_is_tx_suspend(
2365 completion_code);
2366 is_tx_rx =
2367 sci_request_stpsata_completion_status_is_tx_rx_suspend(
2368 completion_code);
2369 break;
2370 default:
2371 dev_warn(&ireq->isci_host->pdev->dev,
2372 "%s: request %p has no valid protocol\n",
2373 __func__, ireq);
2374 break;
2375 }
2376 if (is_tx || is_tx_rx) {
2377 BUG_ON(is_tx && is_tx_rx);
2378
2379 sci_remote_node_context_suspend(
2380 &ireq->target_device->rnc,
2381 SCU_HARDWARE_SUSPENSION,
2382 (is_tx_rx) ? SCU_EVENT_TL_RNC_SUSPEND_TX_RX
2383 : SCU_EVENT_TL_RNC_SUSPEND_TX,
2384 NULL, NULL);
2385 }
2386}
2387
2265enum sci_status 2388enum sci_status
2266sci_io_request_tc_completion(struct isci_request *ireq, 2389sci_io_request_tc_completion(struct isci_request *ireq,
2267 u32 completion_code) 2390 u32 completion_code)
2268{ 2391{
2269 enum sci_base_request_states state; 2392 enum sci_base_request_states state;
2270 struct isci_host *ihost = ireq->owning_controller; 2393 struct isci_host *ihost = ireq->owning_controller;
2271 2394
2272 state = ireq->sm.current_state_id; 2395 state = ireq->sm.current_state_id;
2273 2396
2397 /* Decode those completions that signal upcoming suspension events. */
2398 sci_request_handle_suspending_completions(
2399 ireq, SCU_GET_COMPLETION_TL_STATUS(completion_code));
2400
2274 switch (state) { 2401 switch (state) {
2275 case SCI_REQ_STARTED: 2402 case SCI_REQ_STARTED:
2276 return request_started_state_tc_event(ireq, completion_code); 2403 return request_started_state_tc_event(ireq, completion_code);
diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h
index 4961f9fbf70f..e845a31ecebb 100644
--- a/drivers/scsi/isci/request.h
+++ b/drivers/scsi/isci/request.h
@@ -414,5 +414,4 @@ static inline int isci_task_is_ncq_recovery(struct sas_task *task)
414 task->ata_task.fis.lbal == ATA_LOG_SATA_NCQ); 414 task->ata_task.fis.lbal == ATA_LOG_SATA_NCQ);
415 415
416} 416}
417
418#endif /* !defined(_ISCI_REQUEST_H_) */ 417#endif /* !defined(_ISCI_REQUEST_H_) */
diff --git a/drivers/scsi/isci/scu_completion_codes.h b/drivers/scsi/isci/scu_completion_codes.h
index c8b329c695f9..071cb74a211c 100644
--- a/drivers/scsi/isci/scu_completion_codes.h
+++ b/drivers/scsi/isci/scu_completion_codes.h
@@ -224,6 +224,7 @@
224 * 32-bit value like we want, each immediate value must be cast to a u32. 224 * 32-bit value like we want, each immediate value must be cast to a u32.
225 */ 225 */
226#define SCU_TASK_DONE_GOOD ((u32)0x00) 226#define SCU_TASK_DONE_GOOD ((u32)0x00)
227#define SCU_TASK_DONE_TX_RAW_CMD_ERR ((u32)0x08)
227#define SCU_TASK_DONE_CRC_ERR ((u32)0x14) 228#define SCU_TASK_DONE_CRC_ERR ((u32)0x14)
228#define SCU_TASK_DONE_CHECK_RESPONSE ((u32)0x14) 229#define SCU_TASK_DONE_CHECK_RESPONSE ((u32)0x14)
229#define SCU_TASK_DONE_GEN_RESPONSE ((u32)0x15) 230#define SCU_TASK_DONE_GEN_RESPONSE ((u32)0x15)
@@ -237,6 +238,7 @@
237#define SCU_TASK_DONE_LL_LF_TERM ((u32)0x1A) 238#define SCU_TASK_DONE_LL_LF_TERM ((u32)0x1A)
238#define SCU_TASK_DONE_DATA_LEN_ERR ((u32)0x1A) 239#define SCU_TASK_DONE_DATA_LEN_ERR ((u32)0x1A)
239#define SCU_TASK_DONE_LL_CL_TERM ((u32)0x1B) 240#define SCU_TASK_DONE_LL_CL_TERM ((u32)0x1B)
241#define SCU_TASK_DONE_BREAK_RCVD ((u32)0x1B)
240#define SCU_TASK_DONE_LL_ABORT_ERR ((u32)0x1B) 242#define SCU_TASK_DONE_LL_ABORT_ERR ((u32)0x1B)
241#define SCU_TASK_DONE_SEQ_INV_TYPE ((u32)0x1C) 243#define SCU_TASK_DONE_SEQ_INV_TYPE ((u32)0x1C)
242#define SCU_TASK_DONE_UNEXP_XR ((u32)0x1C) 244#define SCU_TASK_DONE_UNEXP_XR ((u32)0x1C)