diff options
-rw-r--r-- | drivers/scsi/isci/host.c | 67 | ||||
-rw-r--r-- | drivers/scsi/isci/host.h | 3 | ||||
-rw-r--r-- | drivers/scsi/isci/port_config.c | 18 |
3 files changed, 50 insertions, 38 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 95c3da66ea4b..577a8369274c 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c | |||
@@ -816,7 +816,7 @@ static void sci_controller_initialize_unsolicited_frame_queue(struct isci_host * | |||
816 | &ihost->scu_registers->sdma.unsolicited_frame_put_pointer); | 816 | &ihost->scu_registers->sdma.unsolicited_frame_put_pointer); |
817 | } | 817 | } |
818 | 818 | ||
819 | static void sci_controller_transition_to_ready(struct isci_host *ihost, enum sci_status status) | 819 | void sci_controller_transition_to_ready(struct isci_host *ihost, enum sci_status status) |
820 | { | 820 | { |
821 | if (ihost->sm.current_state_id == SCIC_STARTING) { | 821 | if (ihost->sm.current_state_id == SCIC_STARTING) { |
822 | /* | 822 | /* |
@@ -843,6 +843,7 @@ static bool is_phy_starting(struct isci_phy *iphy) | |||
843 | case SCI_PHY_SUB_AWAIT_SATA_POWER: | 843 | case SCI_PHY_SUB_AWAIT_SATA_POWER: |
844 | case SCI_PHY_SUB_AWAIT_SATA_PHY_EN: | 844 | case SCI_PHY_SUB_AWAIT_SATA_PHY_EN: |
845 | case SCI_PHY_SUB_AWAIT_SATA_SPEED_EN: | 845 | case SCI_PHY_SUB_AWAIT_SATA_SPEED_EN: |
846 | case SCI_PHY_SUB_AWAIT_OSSP_EN: | ||
846 | case SCI_PHY_SUB_AWAIT_SIG_FIS_UF: | 847 | case SCI_PHY_SUB_AWAIT_SIG_FIS_UF: |
847 | case SCI_PHY_SUB_FINAL: | 848 | case SCI_PHY_SUB_FINAL: |
848 | return true; | 849 | return true; |
@@ -851,6 +852,39 @@ static bool is_phy_starting(struct isci_phy *iphy) | |||
851 | } | 852 | } |
852 | } | 853 | } |
853 | 854 | ||
855 | bool is_controller_start_complete(struct isci_host *ihost) | ||
856 | { | ||
857 | int i; | ||
858 | |||
859 | for (i = 0; i < SCI_MAX_PHYS; i++) { | ||
860 | struct isci_phy *iphy = &ihost->phys[i]; | ||
861 | u32 state = iphy->sm.current_state_id; | ||
862 | |||
863 | /* in apc mode we need to check every phy, in | ||
864 | * mpc mode we only need to check phys that have | ||
865 | * been configured into a port | ||
866 | */ | ||
867 | if (is_port_config_apc(ihost)) | ||
868 | /* pass */; | ||
869 | else if (!phy_get_non_dummy_port(iphy)) | ||
870 | continue; | ||
871 | |||
872 | /* The controller start operation is complete iff: | ||
873 | * - all links have been given an opportunity to start | ||
874 | * - have no indication of a connected device | ||
875 | * - have an indication of a connected device and it has | ||
876 | * finished the link training process. | ||
877 | */ | ||
878 | if ((iphy->is_in_link_training == false && state == SCI_PHY_INITIAL) || | ||
879 | (iphy->is_in_link_training == false && state == SCI_PHY_STOPPED) || | ||
880 | (iphy->is_in_link_training == true && is_phy_starting(iphy)) || | ||
881 | (ihost->port_agent.phy_ready_mask != ihost->port_agent.phy_configured_mask)) | ||
882 | return false; | ||
883 | } | ||
884 | |||
885 | return true; | ||
886 | } | ||
887 | |||
854 | /** | 888 | /** |
855 | * sci_controller_start_next_phy - start phy | 889 | * sci_controller_start_next_phy - start phy |
856 | * @scic: controller | 890 | * @scic: controller |
@@ -871,36 +905,7 @@ static enum sci_status sci_controller_start_next_phy(struct isci_host *ihost) | |||
871 | return status; | 905 | return status; |
872 | 906 | ||
873 | if (ihost->next_phy_to_start >= SCI_MAX_PHYS) { | 907 | if (ihost->next_phy_to_start >= SCI_MAX_PHYS) { |
874 | bool is_controller_start_complete = true; | 908 | if (is_controller_start_complete(ihost)) { |
875 | u32 state; | ||
876 | u8 index; | ||
877 | |||
878 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
879 | iphy = &ihost->phys[index]; | ||
880 | state = iphy->sm.current_state_id; | ||
881 | |||
882 | if (!phy_get_non_dummy_port(iphy)) | ||
883 | continue; | ||
884 | |||
885 | /* The controller start operation is complete iff: | ||
886 | * - all links have been given an opportunity to start | ||
887 | * - have no indication of a connected device | ||
888 | * - have an indication of a connected device and it has | ||
889 | * finished the link training process. | ||
890 | */ | ||
891 | if ((iphy->is_in_link_training == false && state == SCI_PHY_INITIAL) || | ||
892 | (iphy->is_in_link_training == false && state == SCI_PHY_STOPPED) || | ||
893 | (iphy->is_in_link_training == true && is_phy_starting(iphy)) || | ||
894 | (ihost->port_agent.phy_ready_mask != ihost->port_agent.phy_configured_mask)) { | ||
895 | is_controller_start_complete = false; | ||
896 | break; | ||
897 | } | ||
898 | } | ||
899 | |||
900 | /* | ||
901 | * The controller has successfully finished the start process. | ||
902 | * Inform the SCI Core user and transition to the READY state. */ | ||
903 | if (is_controller_start_complete == true) { | ||
904 | sci_controller_transition_to_ready(ihost, SCI_SUCCESS); | 909 | sci_controller_transition_to_ready(ihost, SCI_SUCCESS); |
905 | sci_del_timer(&ihost->phy_timer); | 910 | sci_del_timer(&ihost->phy_timer); |
906 | ihost->phy_startup_timer_pending = false; | 911 | ihost->phy_startup_timer_pending = false; |
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index a89c0e3c5a14..9dc910b9d921 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h | |||
@@ -109,6 +109,8 @@ struct sci_port_configuration_agent; | |||
109 | typedef void (*port_config_fn)(struct isci_host *, | 109 | typedef void (*port_config_fn)(struct isci_host *, |
110 | struct sci_port_configuration_agent *, | 110 | struct sci_port_configuration_agent *, |
111 | struct isci_port *, struct isci_phy *); | 111 | struct isci_port *, struct isci_phy *); |
112 | bool is_port_config_apc(struct isci_host *ihost); | ||
113 | bool is_controller_start_complete(struct isci_host *ihost); | ||
112 | 114 | ||
113 | struct sci_port_configuration_agent { | 115 | struct sci_port_configuration_agent { |
114 | u16 phy_configured_mask; | 116 | u16 phy_configured_mask; |
@@ -473,6 +475,7 @@ void isci_host_completion_routine(unsigned long data); | |||
473 | void isci_host_deinit(struct isci_host *); | 475 | void isci_host_deinit(struct isci_host *); |
474 | void sci_controller_disable_interrupts(struct isci_host *ihost); | 476 | void sci_controller_disable_interrupts(struct isci_host *ihost); |
475 | bool sci_controller_has_remote_devices_stopping(struct isci_host *ihost); | 477 | bool sci_controller_has_remote_devices_stopping(struct isci_host *ihost); |
478 | void sci_controller_transition_to_ready(struct isci_host *ihost, enum sci_status status); | ||
476 | 479 | ||
477 | enum sci_status sci_controller_start_io( | 480 | enum sci_status sci_controller_start_io( |
478 | struct isci_host *ihost, | 481 | struct isci_host *ihost, |
diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c index 6d1e9544cbe5..cd962da4a57a 100644 --- a/drivers/scsi/isci/port_config.c +++ b/drivers/scsi/isci/port_config.c | |||
@@ -57,7 +57,7 @@ | |||
57 | 57 | ||
58 | #define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT (10) | 58 | #define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT (10) |
59 | #define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT (10) | 59 | #define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT (10) |
60 | #define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (250) | 60 | #define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (1000) |
61 | 61 | ||
62 | enum SCIC_SDS_APC_ACTIVITY { | 62 | enum SCIC_SDS_APC_ACTIVITY { |
63 | SCIC_SDS_APC_SKIP_PHY, | 63 | SCIC_SDS_APC_SKIP_PHY, |
@@ -472,13 +472,9 @@ sci_apc_agent_validate_phy_configuration(struct isci_host *ihost, | |||
472 | * down event or a link up event where we can not yet tell to which a phy | 472 | * down event or a link up event where we can not yet tell to which a phy |
473 | * belongs. | 473 | * belongs. |
474 | */ | 474 | */ |
475 | static void sci_apc_agent_start_timer( | 475 | static void sci_apc_agent_start_timer(struct sci_port_configuration_agent *port_agent, |
476 | struct sci_port_configuration_agent *port_agent, | 476 | u32 timeout) |
477 | u32 timeout) | ||
478 | { | 477 | { |
479 | if (port_agent->timer_pending) | ||
480 | sci_del_timer(&port_agent->timer); | ||
481 | |||
482 | port_agent->timer_pending = true; | 478 | port_agent->timer_pending = true; |
483 | sci_mod_timer(&port_agent->timer, timeout); | 479 | sci_mod_timer(&port_agent->timer, timeout); |
484 | } | 480 | } |
@@ -697,6 +693,9 @@ static void apc_agent_timeout(unsigned long data) | |||
697 | &ihost->phys[index], false); | 693 | &ihost->phys[index], false); |
698 | } | 694 | } |
699 | 695 | ||
696 | if (is_controller_start_complete(ihost)) | ||
697 | sci_controller_transition_to_ready(ihost, SCI_SUCCESS); | ||
698 | |||
700 | done: | 699 | done: |
701 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | 700 | spin_unlock_irqrestore(&ihost->scic_lock, flags); |
702 | } | 701 | } |
@@ -732,6 +731,11 @@ void sci_port_configuration_agent_construct( | |||
732 | } | 731 | } |
733 | } | 732 | } |
734 | 733 | ||
734 | bool is_port_config_apc(struct isci_host *ihost) | ||
735 | { | ||
736 | return ihost->port_agent.link_up_handler == sci_apc_agent_link_up; | ||
737 | } | ||
738 | |||
735 | enum sci_status sci_port_configuration_agent_initialize( | 739 | enum sci_status sci_port_configuration_agent_initialize( |
736 | struct isci_host *ihost, | 740 | struct isci_host *ihost, |
737 | struct sci_port_configuration_agent *port_agent) | 741 | struct sci_port_configuration_agent *port_agent) |