aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci
diff options
context:
space:
mode:
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>2012-03-09 01:41:50 -0500
committerDan Williams <dan.j.williams@intel.com>2012-05-17 17:33:37 -0400
commitac78ed0f78eae5c3c918e132b5e2029cdc4fdedc (patch)
treeac1e7cc2dc8fcffa22d8791baf265dd748594a1f /drivers/scsi/isci
parent56d7c013e714c6feab2ab5ac854808e29048b069 (diff)
isci: Handle all suspending TC completions
Add comprehensive decode for all TC completions that generate RNC suspensions. Note that this commit also removes unconditional resumptions of ATAPI devices when in the SCI_STP_DEV_ATAPI_ERROR state, and STP devices when in the SCI_STP_DEV_IDLE state. This is because the SCI_STP_DEV_IDLE and SCI_STP_DEV_ATAPI state entry functions manage the RNC resumption. Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/scsi/isci')
-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)