net/ice/base: support link default override
authorQi Zhang <qi.z.zhang@intel.com>
Mon, 23 Mar 2020 07:17:36 +0000 (15:17 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 21 Apr 2020 11:57:04 +0000 (13:57 +0200)
Adds functions to check for link override firmware support and get
the override settings for a port. Link override allows a user to force
link settings that are not normally supported.

Firmware support is version dependent so a function to check support has
been added.

The link FC settings will use the override if available.

Signed-off-by: Evan Swanson <evan.swanson@intel.com>
Signed-off-by: Paul M Stillwell Jr <paul.m.stillwell.jr@intel.com>
Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
Acked-by: Qiming Yang <qiming.yang@intel.com>
drivers/net/ice/base/ice_adminq_cmd.h
drivers/net/ice/base/ice_common.c
drivers/net/ice/base/ice_common.h
drivers/net/ice/base/ice_type.h

index bcb2dd7..34c0581 100644 (file)
@@ -1363,7 +1363,8 @@ struct ice_aqc_get_phy_caps_data {
 #define ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN             BIT(6)
 #define ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN             BIT(7)
 #define ICE_AQC_PHY_FEC_MASK                           MAKEMASK(0xdf, 0)
-       u8 rsvd1;       /* Byte 35 reserved */
+       u8 module_compliance_enforcement;
+#define ICE_AQC_MOD_ENFORCE_STRICT_MODE                        BIT(0)
        u8 extended_compliance_code;
 #define ICE_MODULE_TYPE_TOTAL_BYTE                     3
        u8 module_type[ICE_MODULE_TYPE_TOTAL_BYTE];
@@ -1416,7 +1417,7 @@ struct ice_aqc_set_phy_cfg_data {
        __le16 eee_cap; /* Value from ice_aqc_get_phy_caps */
        __le16 eeer_value;
        u8 link_fec_opt; /* Use defines from ice_aqc_get_phy_caps */
-       u8 rsvd1;
+       u8 module_compliance_enforcement;
 };
 
 /* Set MAC Config command data structure (direct 0x0603) */
index 4b1b310..3fae6e7 100644 (file)
@@ -2526,6 +2526,7 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
 {
        struct ice_aqc_set_phy_cfg_data cfg = { 0 };
        struct ice_phy_cache_mode_data cache_data;
+       struct ice_link_default_override_tlv tlv;
        struct ice_aqc_get_phy_caps_data *pcaps;
        enum ice_status status;
        u8 pause_mask = 0x0;
@@ -2573,7 +2574,18 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
                                   ICE_AQC_PHY_EN_RX_LINK_PAUSE);
 
        /* set the new capabilities */
-       cfg.caps |= pause_mask;
+       if (pi->fc.req_mode == ICE_FC_AUTO &&
+           ice_fw_supports_link_override(hw)) {
+               status = ice_get_link_default_override(&tlv, pi);
+               if (status)
+                       return status;
+
+               if (!(tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) &&
+                   (tlv.options & ICE_LINK_OVERRIDE_EN))
+                       cfg.caps |= tlv.phy_config & ICE_LINK_OVERRIDE_PAUSE_M;
+       } else {
+               cfg.caps |= pause_mask;
+       }
 
        /* If the capabilities have changed, then set the new config */
        if (cfg.caps != pcaps->caps) {
@@ -4269,3 +4281,102 @@ enum ice_fw_modes ice_get_fw_mode(struct ice_hw *hw)
        else
                return ICE_FW_MODE_NORMAL;
 }
+
+/**
+ * ice_fw_supports_link_override
+ * @hw: pointer to the hardware structure
+ *
+ * Checks if the firmware supports link override
+ */
+bool ice_fw_supports_link_override(struct ice_hw *hw)
+{
+       if (hw->api_maj_ver == ICE_FW_API_LINK_OVERRIDE_MAJ) {
+               if (hw->api_min_ver > ICE_FW_API_LINK_OVERRIDE_MIN)
+                       return true;
+               if (hw->api_min_ver == ICE_FW_API_LINK_OVERRIDE_MIN &&
+                   hw->api_patch >= ICE_FW_API_LINK_OVERRIDE_PATCH)
+                       return true;
+       } else if (hw->api_maj_ver > ICE_FW_API_LINK_OVERRIDE_MAJ) {
+               return true;
+       }
+
+       return false;
+}
+
+/**
+ * ice_get_link_default_override
+ * @ldo: pointer to the link default override struct
+ * @pi: pointer to the port info struct
+ *
+ * Gets the link default override for a port
+ */
+enum ice_status
+ice_get_link_default_override(struct ice_link_default_override_tlv *ldo,
+                             struct ice_port_info *pi)
+{
+       u16 i, tlv, tlv_len, tlv_start, buf, offset;
+       struct ice_hw *hw = pi->hw;
+       enum ice_status status;
+
+       status = ice_get_pfa_module_tlv(hw, &tlv, &tlv_len,
+                                       ICE_SR_LINK_DEFAULT_OVERRIDE_PTR);
+       if (status) {
+               ice_debug(hw, ICE_DBG_INIT,
+                         "Failed to read link override TLV.\n");
+               return status;
+       }
+
+       /* Each port has its own config; calculate for our port */
+       tlv_start = tlv + pi->lport * ICE_SR_PFA_LINK_OVERRIDE_WORDS +
+               ICE_SR_PFA_LINK_OVERRIDE_OFFSET;
+
+       /* link options first */
+       status = ice_read_sr_word(hw, tlv_start, &buf);
+       if (status) {
+               ice_debug(hw, ICE_DBG_INIT,
+                         "Failed to read override link options.\n");
+               return status;
+       }
+       ldo->options = buf & ICE_LINK_OVERRIDE_OPT_M;
+       ldo->phy_config = (buf & ICE_LINK_OVERRIDE_PHY_CFG_M) >>
+               ICE_LINK_OVERRIDE_PHY_CFG_S;
+
+       /* link PHY config */
+       offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_FEC_OFFSET;
+       status = ice_read_sr_word(hw, offset, &buf);
+       if (status) {
+               ice_debug(hw, ICE_DBG_INIT,
+                         "Failed to read override phy config.\n");
+               return status;
+       }
+       ldo->fec_options = buf & ICE_LINK_OVERRIDE_FEC_OPT_M;
+
+       /* PHY types low */
+       offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET;
+       for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) {
+               status = ice_read_sr_word(hw, (offset + i), &buf);
+               if (status) {
+                       ice_debug(hw, ICE_DBG_INIT,
+                                 "Failed to read override link options.\n");
+                       return status;
+               }
+               /* shift 16 bits at a time to fill 64 bits */
+               ldo->phy_type_low |= ((u64)buf << (i * 16));
+       }
+
+       /* PHY types high */
+       offset = tlv_start + ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET +
+               ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS;
+       for (i = 0; i < ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS; i++) {
+               status = ice_read_sr_word(hw, (offset + i), &buf);
+               if (status) {
+                       ice_debug(hw, ICE_DBG_INIT,
+                                 "Failed to read override link options.\n");
+                       return status;
+               }
+               /* shift 16 bits at a time to fill 64 bits */
+               ldo->phy_type_high |= ((u64)buf << (i * 16));
+       }
+
+       return status;
+}
index c731844..bbff175 100644 (file)
@@ -140,6 +140,11 @@ enum ice_status ice_clear_pf_cfg(struct ice_hw *hw);
 enum ice_status
 ice_aq_set_phy_cfg(struct ice_hw *hw, struct ice_port_info *pi,
                   struct ice_aqc_set_phy_cfg_data *cfg, struct ice_sq_cd *cd);
+bool ice_fw_supports_link_override(struct ice_hw *hw);
+enum ice_status
+ice_get_link_default_override(struct ice_link_default_override_tlv *ldo,
+                             struct ice_port_info *pi);
+
 enum ice_fc_mode ice_caps_to_fc_mode(u8 caps);
 enum ice_fec_mode ice_caps_to_fec_mode(u8 caps, u8 fec_options);
 enum ice_status
index 59dce32..29fa34f 100644 (file)
@@ -168,6 +168,7 @@ enum ice_fc_mode {
        ICE_FC_RX_PAUSE,
        ICE_FC_TX_PAUSE,
        ICE_FC_FULL,
+       ICE_FC_AUTO,
        ICE_FC_PFC,
        ICE_FC_DFLT
 };
@@ -483,6 +484,28 @@ struct ice_nvm_info {
        u8 blank_nvm_mode;              /* is NVM empty (no FW present)*/
 };
 
+struct ice_link_default_override_tlv {
+       u8 options;
+#define ICE_LINK_OVERRIDE_OPT_M                0x3F
+#define ICE_LINK_OVERRIDE_STRICT_MODE  BIT(0)
+#define ICE_LINK_OVERRIDE_EPCT_DIS     BIT(1)
+#define ICE_LINK_OVERRIDE_PORT_DIS     BIT(2)
+#define ICE_LINK_OVERRIDE_EN           BIT(3)
+#define ICE_LINK_OVERRIDE_AUTO_LINK_DIS        BIT(4)
+#define ICE_LINK_OVERRIDE_EEE_EN       BIT(5)
+       u8 phy_config;
+#define ICE_LINK_OVERRIDE_PHY_CFG_S    8
+#define ICE_LINK_OVERRIDE_PHY_CFG_M    (0xC3 << ICE_LINK_OVERRIDE_PHY_CFG_S)
+#define ICE_LINK_OVERRIDE_PAUSE_M      0x3
+#define ICE_LINK_OVERRIDE_LESM_EN      BIT(6)
+#define ICE_LINK_OVERRIDE_AUTO_FEC_EN  BIT(7)
+       u8 fec_options;
+#define ICE_LINK_OVERRIDE_FEC_OPT_M    0xFF
+       u8 rsvd1;
+       u64 phy_type_low;
+       u64 phy_type_high;
+};
+
 #define ICE_NVM_VER_LEN        32
 
 /* Max number of port to queue branches w.r.t topology */
@@ -1003,6 +1026,7 @@ enum ice_sw_fwd_act_type {
 #define ICE_SR_EMP_SR_SETTINGS_PTR             0x48
 #define ICE_SR_CONFIGURATION_METADATA_PTR      0x4D
 #define ICE_SR_IMMEDIATE_VALUES_PTR            0x4E
+#define ICE_SR_LINK_DEFAULT_OVERRIDE_PTR       0x134
 #define ICE_SR_POR_REGISTERS_AUTOLOAD_PTR      0x118
 
 /* Auxiliary field, mask and shift definition for Shadow RAM and NVM Flash */
@@ -1020,6 +1044,16 @@ enum ice_sw_fwd_act_type {
  */
 #define ICE_SR_SW_CHECKSUM_BASE                0xBABA
 
+/* Link override related */
+#define ICE_SR_PFA_LINK_OVERRIDE_WORDS         10
+#define ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS     4
+#define ICE_SR_PFA_LINK_OVERRIDE_OFFSET                2
+#define ICE_SR_PFA_LINK_OVERRIDE_FEC_OFFSET    1
+#define ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET    2
+#define ICE_FW_API_LINK_OVERRIDE_MAJ           1
+#define ICE_FW_API_LINK_OVERRIDE_MIN           5
+#define ICE_FW_API_LINK_OVERRIDE_PATCH         2
+
 #define ICE_PBA_FLAG_DFLT              0xFAFA
 /* Hash redirection LUT for VSI - maximum array size */
 #define ICE_VSIQF_HLUT_ARRAY_SIZE      ((VSIQF_HLUT_MAX_INDEX + 1) * 4)