Commit 07373a5caa29e4159ef1ea5e72985ddaf013519a

Authored by Henryk Dembkowski
Committed by Dan Williams
1 parent 8db37aabac

isci: add support for 2 more oem parmeters

1/ add OEM paramater support for mode_type (MPC vs APC)
2/ add OEM parameter support for max_number_concurrent_device_spin_up
3/ cleanup scic_sds_controller_start_next_phy

todo: hook up the amp control afe parameters into the afe init code

Signed-off-by: Henryk Dembkowski <henryk.dembkowski@intel.com>
Signed-off-by: Jacek Danecki <Jacek.Danecki@intel.com>
[cleaned up scic_sds_controller_start_next_phy]
Signed-off-by: Dan Williams <dan.j.williams@intel.com>

Showing 7 changed files with 176 additions and 155 deletions Side-by-side Diff

drivers/scsi/isci/core/scic_config_parameters.h
... ... @@ -224,6 +224,8 @@
224 224 */
225 225 #define SCIC_SDS_PARM_PHY_MASK_MAX 0xF
226 226  
  227 +#define MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT 4
  228 +
227 229 /**
228 230 * This structure/union specifies the various different OEM parameter sets
229 231 * available. Each type is specific to a hardware controller version.
... ... @@ -237,7 +239,6 @@
237 239 * 1.
238 240 */
239 241 struct scic_sds_oem_params sds1;
240   -
241 242 };
242 243  
243 244 /**
drivers/scsi/isci/core/scic_sds_controller.c
... ... @@ -293,6 +293,7 @@
293 293 );
294 294  
295 295 this_controller->power_control.phys_waiting = 0;
  296 + this_controller->power_control.phys_granted_power = 0;
296 297 }
297 298  
298 299 /* --------------------------------------------------------------------------- */
... ... @@ -770,31 +771,6 @@
770 771 __func__);
771 772 }
772 773  
773   -/**
774   - * scic_sds_controller_get_port_configuration_mode
775   - * @this_controller: This is the controller to use to determine if we are using
776   - * manual or automatic port configuration.
777   - *
778   - * SCIC_PORT_CONFIGURATION_MODE
779   - */
780   -enum SCIC_PORT_CONFIGURATION_MODE scic_sds_controller_get_port_configuration_mode(
781   - struct scic_sds_controller *this_controller)
782   -{
783   - u32 index;
784   - enum SCIC_PORT_CONFIGURATION_MODE mode;
785   -
786   - mode = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
787   -
788   - for (index = 0; index < SCI_MAX_PORTS; index++) {
789   - if (this_controller->oem_parameters.sds1.ports[index].phy_mask != 0) {
790   - mode = SCIC_PORT_MANUAL_CONFIGURATION_MODE;
791   - break;
792   - }
793   - }
794   -
795   - return mode;
796   -}
797   -
798 774 enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic)
799 775 {
800 776 u32 index;
... ... @@ -859,7 +835,7 @@
859 835  
860 836 /**
861 837 * This method is called internally by the controller object to start the next
862   - * phy on the controller. If all the phys have been starte, then this
  838 + * phy on the controller. If all the phys have been started, then this
863 839 * method will attempt to transition the controller to the READY state and
864 840 * inform the user (scic_cb_controller_start_complete()).
865 841 * @this_controller: This parameter specifies the controller object for which
866 842  
867 843  
868 844  
869 845  
870 846  
871 847  
872 848  
873 849  
874 850  
875 851  
876 852  
877 853  
878 854  
... ... @@ -867,101 +843,88 @@
867 843 *
868 844 * enum sci_status
869 845 */
870   -enum sci_status scic_sds_controller_start_next_phy(
871   - struct scic_sds_controller *this_controller)
  846 +enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_controller *scic)
872 847 {
  848 + struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1;
  849 + struct scic_sds_phy *sci_phy;
873 850 enum sci_status status;
874 851  
875 852 status = SCI_SUCCESS;
876 853  
877   - if (this_controller->phy_startup_timer_pending == false) {
878   - if (this_controller->next_phy_to_start == SCI_MAX_PHYS) {
879   - bool is_controller_start_complete = true;
880   - struct scic_sds_phy *the_phy;
881   - u8 index;
  854 + if (scic->phy_startup_timer_pending)
  855 + return status;
882 856  
883   - for (index = 0; index < SCI_MAX_PHYS; index++) {
884   - the_phy = &this_controller->phy_table[index];
  857 + if (scic->next_phy_to_start >= SCI_MAX_PHYS) {
  858 + bool is_controller_start_complete = true;
  859 + u32 state;
  860 + u8 index;
885 861  
886   - if (scic_sds_phy_get_port(the_phy) != NULL) {
887   - /**
888   - * The controller start operation is complete if and only
889   - * if:
890   - * - all links have been given an opportunity to start
891   - * - have no indication of a connected device
892   - * - have an indication of a connected device and it has
893   - * finished the link training process.
894   - */
895   - if (
896   - (
897   - (the_phy->is_in_link_training == false)
898   - && (the_phy->parent.state_machine.current_state_id
899   - == SCI_BASE_PHY_STATE_INITIAL)
900   - )
901   - || (
902   - (the_phy->is_in_link_training == false)
903   - && (the_phy->parent.state_machine.current_state_id
904   - == SCI_BASE_PHY_STATE_STOPPED)
905   - )
906   - || (
907   - (the_phy->is_in_link_training == true)
908   - && (the_phy->parent.state_machine.current_state_id
909   - == SCI_BASE_PHY_STATE_STARTING)
910   - )
911   - ) {
912   - is_controller_start_complete = false;
913   - break;
914   - }
915   - }
916   - }
  862 + for (index = 0; index < SCI_MAX_PHYS; index++) {
  863 + sci_phy = &scic->phy_table[index];
  864 + state = sci_phy->parent.state_machine.current_state_id;
917 865  
918   - /*
919   - * The controller has successfully finished the start process.
920   - * Inform the SCI Core user and transition to the READY state. */
921   - if (is_controller_start_complete == true) {
922   - scic_sds_controller_transition_to_ready(
923   - this_controller, SCI_SUCCESS
924   - );
925   - scic_sds_controller_phy_timer_stop(this_controller);
  866 + if (!scic_sds_phy_get_port(sci_phy))
  867 + continue;
  868 +
  869 + /* The controller start operation is complete iff:
  870 + * - all links have been given an opportunity to start
  871 + * - have no indication of a connected device
  872 + * - have an indication of a connected device and it has
  873 + * finished the link training process.
  874 + */
  875 + if ((sci_phy->is_in_link_training == false &&
  876 + state == SCI_BASE_PHY_STATE_INITIAL) ||
  877 + (sci_phy->is_in_link_training == false &&
  878 + state == SCI_BASE_PHY_STATE_STOPPED) ||
  879 + (sci_phy->is_in_link_training == true &&
  880 + state == SCI_BASE_PHY_STATE_STARTING)) {
  881 + is_controller_start_complete = false;
  882 + break;
926 883 }
927   - } else {
928   - struct scic_sds_phy *the_phy;
  884 + }
929 885  
930   - the_phy = &this_controller->phy_table[this_controller->next_phy_to_start];
  886 + /*
  887 + * The controller has successfully finished the start process.
  888 + * Inform the SCI Core user and transition to the READY state. */
  889 + if (is_controller_start_complete == true) {
  890 + scic_sds_controller_transition_to_ready(scic, SCI_SUCCESS);
  891 + scic_sds_controller_phy_timer_stop(scic);
  892 + }
  893 + } else {
  894 + sci_phy = &scic->phy_table[scic->next_phy_to_start];
931 895  
932   - if (
933   - scic_sds_controller_get_port_configuration_mode(this_controller)
934   - == SCIC_PORT_MANUAL_CONFIGURATION_MODE
935   - ) {
936   - if (scic_sds_phy_get_port(the_phy) == NULL) {
937   - this_controller->next_phy_to_start++;
  896 + if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) {
  897 + if (scic_sds_phy_get_port(sci_phy) == NULL) {
  898 + scic->next_phy_to_start++;
938 899  
939   - /*
940   - * Caution recursion ahead be forwarned
941   - *
942   - * The PHY was never added to a PORT in MPC mode so start the next phy in sequence
943   - * This phy will never go link up and will not draw power the OEM parameters either
944   - * configured the phy incorrectly for the PORT or it was never assigned to a PORT */
945   - return scic_sds_controller_start_next_phy(this_controller);
946   - }
  900 + /* Caution recursion ahead be forwarned
  901 + *
  902 + * The PHY was never added to a PORT in MPC mode
  903 + * so start the next phy in sequence This phy
  904 + * will never go link up and will not draw power
  905 + * the OEM parameters either configured the phy
  906 + * incorrectly for the PORT or it was never
  907 + * assigned to a PORT
  908 + */
  909 + return scic_sds_controller_start_next_phy(scic);
947 910 }
  911 + }
948 912  
949   - status = scic_sds_phy_start(the_phy);
  913 + status = scic_sds_phy_start(sci_phy);
950 914  
951   - if (status == SCI_SUCCESS) {
952   - scic_sds_controller_phy_timer_start(this_controller);
953   - } else {
954   - dev_warn(scic_to_dev(this_controller),
955   - "%s: Controller stop operation failed "
956   - "to stop phy %d because of status "
957   - "%d.\n",
958   - __func__,
959   - this_controller->phy_table[this_controller->next_phy_to_start].phy_index,
960   - status);
961   - }
962   -
963   - this_controller->next_phy_to_start++;
  915 + if (status == SCI_SUCCESS) {
  916 + scic_sds_controller_phy_timer_start(scic);
  917 + } else {
  918 + dev_warn(scic_to_dev(scic),
  919 + "%s: Controller stop operation failed "
  920 + "to stop phy %d because of status "
  921 + "%d.\n",
  922 + __func__,
  923 + scic->phy_table[scic->next_phy_to_start].phy_index,
  924 + status);
964 925 }
  926 +
  927 + scic->next_phy_to_start++;
965 928 }
966 929  
967 930 return status;
968 931  
969 932  
970 933  
... ... @@ -1059,9 +1022,34 @@
1059 1022 }
1060 1023  
1061 1024 /**
  1025 + * This method stops the power control timer for this controller object.
1062 1026 *
  1027 + * @param scic
  1028 + */
  1029 +void scic_sds_controller_power_control_timer_stop(struct scic_sds_controller *scic)
  1030 +{
  1031 + if (scic->power_control.timer_started) {
  1032 + isci_event_timer_stop(scic, scic->power_control.timer);
  1033 + scic->power_control.timer_started = false;
  1034 + }
  1035 +}
  1036 +
  1037 +/**
  1038 + * This method stops and starts the power control timer for this controller object.
1063 1039 *
  1040 + * @param scic
  1041 + */
  1042 +void scic_sds_controller_power_control_timer_restart(
  1043 + struct scic_sds_controller *scic)
  1044 +{
  1045 + scic_sds_controller_power_control_timer_stop(scic);
  1046 + scic_sds_controller_power_control_timer_start(scic);
  1047 +}
  1048 +
  1049 +/**
1064 1050 *
  1051 + *
  1052 + *
1065 1053 */
1066 1054 static void scic_sds_controller_power_control_timer_handler(
1067 1055 void *controller)
... ... @@ -1070,6 +1058,8 @@
1070 1058  
1071 1059 this_controller = (struct scic_sds_controller *)controller;
1072 1060  
  1061 + this_controller->power_control.phys_granted_power = 0;
  1062 +
1073 1063 if (this_controller->power_control.phys_waiting == 0) {
1074 1064 this_controller->power_control.timer_started = false;
1075 1065 } else {
1076 1066  
1077 1067  
... ... @@ -1081,19 +1071,24 @@
1081 1071 && (this_controller->power_control.phys_waiting != 0);
1082 1072 i++) {
1083 1073 if (this_controller->power_control.requesters[i] != NULL) {
1084   - the_phy = this_controller->power_control.requesters[i];
1085   - this_controller->power_control.requesters[i] = NULL;
1086   - this_controller->power_control.phys_waiting--;
1087   - break;
  1074 + if (this_controller->power_control.phys_granted_power <
  1075 + this_controller->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) {
  1076 + the_phy = this_controller->power_control.requesters[i];
  1077 + this_controller->power_control.requesters[i] = NULL;
  1078 + this_controller->power_control.phys_waiting--;
  1079 + this_controller->power_control.phys_granted_power++;
  1080 + scic_sds_phy_consume_power_handler(the_phy);
  1081 + } else {
  1082 + break;
  1083 + }
1088 1084 }
1089 1085 }
1090 1086  
1091 1087 /*
1092 1088 * It doesn't matter if the power list is empty, we need to start the
1093   - * timer in case another phy becomes ready. */
  1089 + * timer in case another phy becomes ready.
  1090 + */
1094 1091 scic_sds_controller_power_control_timer_start(this_controller);
1095   -
1096   - scic_sds_phy_consume_power_handler(the_phy);
1097 1092 }
1098 1093 }
1099 1094  
1100 1095  
... ... @@ -1109,15 +1104,20 @@
1109 1104 {
1110 1105 BUG_ON(the_phy == NULL);
1111 1106  
1112   - if (
1113   - (this_controller->power_control.timer_started)
1114   - && (this_controller->power_control.requesters[the_phy->phy_index] == NULL)
1115   - ) {
  1107 + if (this_controller->power_control.phys_granted_power <
  1108 + this_controller->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) {
  1109 + this_controller->power_control.phys_granted_power++;
  1110 + scic_sds_phy_consume_power_handler(the_phy);
  1111 +
  1112 + /*
  1113 + * stop and start the power_control timer. When the timer fires, the
  1114 + * no_of_phys_granted_power will be set to 0
  1115 + */
  1116 + scic_sds_controller_power_control_timer_restart(this_controller);
  1117 + } else {
  1118 + /* Add the phy in the waiting list */
1116 1119 this_controller->power_control.requesters[the_phy->phy_index] = the_phy;
1117 1120 this_controller->power_control.phys_waiting++;
1118   - } else {
1119   - scic_sds_controller_power_control_timer_start(this_controller);
1120   - scic_sds_phy_consume_power_handler(the_phy);
1121 1121 }
1122 1122 }
1123 1123  
... ... @@ -2021,7 +2021,7 @@
2021 2021 * This method sets user parameters and OEM parameters to default values.
2022 2022 * Users can override these values utilizing the scic_user_parameters_set()
2023 2023 * and scic_oem_parameters_set() methods.
2024   - * @controller: This parameter specifies the controller for which to set the
  2024 + * @scic: This parameter specifies the controller for which to set the
2025 2025 * configuration parameters to their default values.
2026 2026 *
2027 2027 */
... ... @@ -2029,6 +2029,12 @@
2029 2029 {
2030 2030 u16 index;
2031 2031  
  2032 + /* Default to APC mode. */
  2033 + scic->oem_parameters.sds1.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
  2034 +
  2035 + /* Default to APC mode. */
  2036 + scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up = 1;
  2037 +
2032 2038 /* Default to no SSC operation. */
2033 2039 scic->oem_parameters.sds1.controller.do_enable_ssc = false;
2034 2040  
... ... @@ -2607,6 +2613,7 @@
2607 2613 == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
2608 2614 ) {
2609 2615 u16 index;
  2616 + u8 combined_phy_mask = 0;
2610 2617  
2611 2618 /*
2612 2619 * Validate the oem parameters. If they are not legal, then
... ... @@ -2625,6 +2632,24 @@
2625 2632 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
2626 2633 }
2627 2634 }
  2635 +
  2636 + if (scic_parms->sds1.controller.mode_type == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE) {
  2637 + for (index = 0; index < SCI_MAX_PHYS; index++) {
  2638 + if (scic_parms->sds1.ports[index].phy_mask != 0)
  2639 + return SCI_FAILURE_INVALID_PARAMETER_VALUE;
  2640 + }
  2641 + } else if (scic_parms->sds1.controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) {
  2642 + for (index = 0; index < SCI_MAX_PHYS; index++)
  2643 + combined_phy_mask |= scic_parms->sds1.ports[index].phy_mask;
  2644 +
  2645 + if (combined_phy_mask == 0)
  2646 + return SCI_FAILURE_INVALID_PARAMETER_VALUE;
  2647 + } else {
  2648 + return SCI_FAILURE_INVALID_PARAMETER_VALUE;
  2649 + }
  2650 +
  2651 + if (scic_parms->sds1.controller.max_concurrent_dev_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT)
  2652 + return SCI_FAILURE_INVALID_PARAMETER_VALUE;
2628 2653  
2629 2654 memcpy(&scic->oem_parameters, scic_parms, sizeof(*scic_parms));
2630 2655 return SCI_SUCCESS;
drivers/scsi/isci/core/scic_sds_controller.h
... ... @@ -122,23 +122,6 @@
122 122  
123 123  
124 124 /**
125   - *
126   - *
127   - * Allowed PORT configuration modes APC Automatic PORT configuration mode is
128   - * defined by the OEM configuration parameters providing no PHY_MASK parameters
129   - * for any PORT. i.e. There are no phys assigned to any of the ports at start.
130   - * MPC Manual PORT configuration mode is defined by the OEM configuration
131   - * parameters providing a PHY_MASK value for any PORT. It is assumed that any
132   - * PORT with no PHY_MASK is an invalid port and not all PHYs must be assigned.
133   - * A PORT_PHY mask that assigns just a single PHY to a port and no other PHYs
134   - * being assigned is sufficient to declare manual PORT configuration.
135   - */
136   -enum SCIC_PORT_CONFIGURATION_MODE {
137   - SCIC_PORT_MANUAL_CONFIGURATION_MODE,
138   - SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE
139   -};
140   -
141   -/**
142 125 * struct scic_power_control -
143 126 *
144 127 * This structure defines the fields for managing power control for direct
... ... @@ -164,6 +147,11 @@
164 147 u8 phys_waiting;
165 148  
166 149 /**
  150 + * This field is used to keep track of how many phys have been granted to consume power
  151 + */
  152 + u8 phys_granted_power;
  153 +
  154 + /**
167 155 * This field is an array of phys that we are waiting on. The phys are direct
168 156 * mapped into requesters via struct scic_sds_phy.phy_index
169 157 */
... ... @@ -557,14 +545,6 @@
557 545 /* --------------------------------------------------------------------------- */
558 546  
559 547 u32 scic_sds_controller_get_object_size(void);
560   -
561   -/* --------------------------------------------------------------------------- */
562   -
563   -
564   -/* --------------------------------------------------------------------------- */
565   -
566   -enum SCIC_PORT_CONFIGURATION_MODE scic_sds_controller_get_port_configuration_mode(
567   - struct scic_sds_controller *this_controller);
568 548  
569 549 /* --------------------------------------------------------------------------- */
570 550  
drivers/scsi/isci/core/scic_sds_port_configuration_agent.c
... ... @@ -822,7 +822,7 @@
822 822 enum sci_status status = SCI_SUCCESS;
823 823 enum SCIC_PORT_CONFIGURATION_MODE mode;
824 824  
825   - mode = scic_sds_controller_get_port_configuration_mode(controller);
  825 + mode = controller->oem_parameters.sds1.controller.mode_type;
826 826  
827 827 if (mode == SCIC_PORT_MANUAL_CONFIGURATION_MODE) {
828 828 status = scic_sds_mpc_agent_validate_phy_configuration(controller, port_agent);
drivers/scsi/isci/firmware/create_fw.h
1 1 #ifndef _CREATE_FW_H_
2 2 #define _CREATE_FW_H_
  3 +#include "../probe_roms.h"
3 4  
4 5  
5 6 /* we are configuring for 2 SCUs */
6 7  
7 8  
8 9  
... ... @@ -24,15 +25,15 @@
24 25 * if there is a port/phy on which you do not wish to override the default
25 26 * values, use the value assigned to UNINIT_PARAM (255).
26 27 */
  28 +/* discovery mode type (port auto config mode by default ) */
27 29 #ifdef MPC
  30 +static const int mode_type = SCIC_PORT_MANUAL_CONFIGURATION_MODE;
28 31 static const __u8 phy_mask[2][4] = { {1, 2, 4, 8},
29 32 {1, 2, 4, 8} };
30 33 #else /* APC (default) */
  34 +static const int mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
31 35 static const __u8 phy_mask[2][4];
32 36 #endif
33   -
34   -/* discovery mode type (port auto config mode by default ) */
35   -static const int mode_type;
36 37  
37 38 /* Maximum number of concurrent device spin up */
38 39 static const int max_num_concurrent_dev_spin_up = 1;
drivers/scsi/isci/probe_roms.h
... ... @@ -86,6 +86,20 @@
86 86 #define ISCI_EFI_ATTRIBUTES 0
87 87 #define ISCI_EFI_VAR_NAME "isci_oemb"
88 88  
  89 +/* Allowed PORT configuration modes APC Automatic PORT configuration mode is
  90 + * defined by the OEM configuration parameters providing no PHY_MASK parameters
  91 + * for any PORT. i.e. There are no phys assigned to any of the ports at start.
  92 + * MPC Manual PORT configuration mode is defined by the OEM configuration
  93 + * parameters providing a PHY_MASK value for any PORT. It is assumed that any
  94 + * PORT with no PHY_MASK is an invalid port and not all PHYs must be assigned.
  95 + * A PORT_PHY mask that assigns just a single PHY to a port and no other PHYs
  96 + * being assigned is sufficient to declare manual PORT configuration.
  97 + */
  98 +enum SCIC_PORT_CONFIGURATION_MODE {
  99 + SCIC_PORT_MANUAL_CONFIGURATION_MODE = 0,
  100 + SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE = 1
  101 +};
  102 +
89 103 struct sci_bios_oem_param_block_hdr {
90 104 uint8_t signature[ISCI_ROM_SIG_SIZE];
91 105 uint16_t total_block_length;
firmware/isci/isci_firmware.bin.ihex
1 1 :10000000495343554F454D42E70017100002000089
2   -:10001000000000000000000001000000000000FFE0
  2 +:10001000000000000000000101000000000000FFDF
3 3 :10002000FFCF5F000000F0000000000000000000B3
4 4 :1000300000000000000000FFFFCF5F000000F100A3
5 5 :10004000000000000000000000000000000000FFB1
6 6 :10005000FFCF5F000000F200000000000000000081
7 7 :1000600000000000000000FFFFCF5F000000F30071
8   -:100070000000000000000000000000000000000080
  8 +:10007000000000000000000000000000000000017F
9 9 :1000800001000000000000FFFFCF5F000000F4004F
10 10 :10009000000000000000000000000000000000FF61
11 11 :1000A000FFCF5F000000F50000000000000000002E