diff options
-rw-r--r-- | drivers/scsi/isci/remote_device.c | 86 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_device.h | 4 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_node_context.c | 74 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_node_context.h | 13 | ||||
-rw-r--r-- | drivers/scsi/isci/request.c | 149 | ||||
-rw-r--r-- | drivers/scsi/isci/request.h | 1 | ||||
-rw-r--r-- | drivers/scsi/isci/scu_completion_codes.h | 2 |
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 | ||
268 | enum sci_status sci_remote_device_suspend(struct isci_remote_device *idev, | 268 | enum 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 | ||
284 | enum sci_status sci_remote_device_frame_handler(struct isci_remote_device *idev, | 276 | enum 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) | |||
412 | enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev, | 404 | enum 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 | |||
954 | static void sci_remote_device_resetting_state_enter(struct sci_base_state_machine *sm) | 926 | static 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 | ||
962 | static void sci_remote_device_resetting_state_exit(struct sci_base_state_machine *sm) | 939 | static 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 | ||
988 | static 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 | |||
1007 | static void sci_smp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm) | 1003 | static 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 | ||
334 | enum sci_status sci_remote_device_suspend( | ||
335 | struct isci_remote_device *idev, | ||
336 | u32 suspend_type); | ||
337 | |||
338 | void sci_remote_device_post_request( | 334 | void 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 | ||
505 | enum sci_status sci_remote_node_context_suspend(struct sci_remote_node_context *sci_rnc, | 506 | enum 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) | 78 | enum 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 | ||
81 | struct isci_request; | 85 | struct isci_request; |
82 | struct isci_remote_device; | 86 | struct 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); |
201 | enum sci_status sci_remote_node_context_suspend(struct sci_remote_node_context *sci_rnc, | 205 | enum 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); |
205 | enum sci_status sci_remote_node_context_resume(struct sci_remote_node_context *sci_rnc, | 210 | enum 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 | ||
2255 | static 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 | |||
2270 | static 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 | |||
2276 | static 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 | |||
2296 | static 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 | |||
2302 | static 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 | |||
2326 | static 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 | |||
2343 | static 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 | |||
2265 | enum sci_status | 2388 | enum sci_status |
2266 | sci_io_request_tc_completion(struct isci_request *ireq, | 2389 | sci_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) |