net/ice/base: store NVM version in extracted format
[dpdk.git] / drivers / net / ice / base / ice_common.c
index 16b91dc..192cfdb 100644 (file)
@@ -9,7 +9,7 @@
 #include "ice_flow.h"
 #include "ice_switch.h"
 
-#define ICE_PF_RESET_WAIT_COUNT        200
+#define ICE_PF_RESET_WAIT_COUNT        300
 
 /**
  * ice_set_mac_type - Sets MAC type
  */
 static enum ice_status ice_set_mac_type(struct ice_hw *hw)
 {
-       enum ice_status status = ICE_SUCCESS;
-
        ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
 
-       if (hw->vendor_id == ICE_INTEL_VENDOR_ID) {
-               switch (hw->device_id) {
-               default:
-                       hw->mac_type = ICE_MAC_GENERIC;
-                       break;
-               }
-       } else {
-               status = ICE_ERR_DEVICE_NOT_SUPPORTED;
+       if (hw->vendor_id != ICE_INTEL_VENDOR_ID)
+               return ICE_ERR_DEVICE_NOT_SUPPORTED;
+
+       switch (hw->device_id) {
+       case ICE_DEV_ID_E810C_BACKPLANE:
+       case ICE_DEV_ID_E810C_QSFP:
+       case ICE_DEV_ID_E810C_SFP:
+       case ICE_DEV_ID_E810_XXV_BACKPLANE:
+       case ICE_DEV_ID_E810_XXV_QSFP:
+       case ICE_DEV_ID_E810_XXV_SFP:
+               hw->mac_type = ICE_MAC_E810;
+               break;
+       case ICE_DEV_ID_E822C_10G_BASE_T:
+       case ICE_DEV_ID_E822C_BACKPLANE:
+       case ICE_DEV_ID_E822C_QSFP:
+       case ICE_DEV_ID_E822C_SFP:
+       case ICE_DEV_ID_E822C_SGMII:
+       case ICE_DEV_ID_E822L_10G_BASE_T:
+       case ICE_DEV_ID_E822L_BACKPLANE:
+       case ICE_DEV_ID_E822L_SFP:
+       case ICE_DEV_ID_E822L_SGMII:
+               hw->mac_type = ICE_MAC_GENERIC;
+               break;
+       default:
+               hw->mac_type = ICE_MAC_UNKNOWN;
+               break;
        }
 
-       ice_debug(hw, ICE_DBG_INIT, "found mac_type: %d, status: %d\n",
-                 hw->mac_type, status);
-
-       return status;
+       ice_debug(hw, ICE_DBG_INIT, "mac_type: %d\n", hw->mac_type);
+       return ICE_SUCCESS;
 }
 
 /**
@@ -176,9 +190,6 @@ ice_aq_get_link_topo_handle(struct ice_port_info *pi, u8 node_type,
 
        cmd = &desc.params.get_link_topo;
 
-       if (!cmd)
-               return ICE_ERR_PARAM;
-
        ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo);
 
        cmd->addr.node_type_ctx = (ICE_AQC_LINK_TOPO_NODE_CTX_PORT <<
@@ -465,7 +476,7 @@ static enum ice_status ice_init_fltr_mgmt_struct(struct ice_hw *hw)
 
        INIT_LIST_HEAD(&sw->vsi_list_map_head);
 
-       return ice_init_def_sw_recp(hw);
+       return ice_init_def_sw_recp(hw, &hw->switch_info->recp_list);
 }
 
 /**
@@ -557,29 +568,6 @@ static void ice_get_itr_intrl_gran(struct ice_hw *hw)
        }
 }
 
-/**
- * ice_get_nvm_version - get cached NVM version data
- * @hw: pointer to the hardware structure
- * @oem_ver: 8 bit NVM version
- * @oem_build: 16 bit NVM build number
- * @oem_patch: 8 NVM patch number
- * @ver_hi: high 16 bits of the NVM version
- * @ver_lo: low 16 bits of the NVM version
- */
-void
-ice_get_nvm_version(struct ice_hw *hw, u8 *oem_ver, u16 *oem_build,
-                   u8 *oem_patch, u8 *ver_hi, u8 *ver_lo)
-{
-       struct ice_nvm_info *nvm = &hw->nvm;
-
-       *oem_ver = (u8)((nvm->oem_ver & ICE_OEM_VER_MASK) >> ICE_OEM_VER_SHIFT);
-       *oem_patch = (u8)(nvm->oem_ver & ICE_OEM_VER_PATCH_MASK);
-       *oem_build = (u16)((nvm->oem_ver & ICE_OEM_VER_BUILD_MASK) >>
-                          ICE_OEM_VER_BUILD_SHIFT);
-       *ver_hi = (nvm->ver & ICE_NVM_VER_HI_MASK) >> ICE_NVM_VER_HI_SHIFT;
-       *ver_lo = (nvm->ver & ICE_NVM_VER_LO_MASK) >> ICE_NVM_VER_LO_SHIFT;
-}
-
 /**
  * ice_print_rollback_msg - print FW rollback message
  * @hw: pointer to the hardware structure
@@ -587,15 +575,16 @@ ice_get_nvm_version(struct ice_hw *hw, u8 *oem_ver, u16 *oem_build,
 void ice_print_rollback_msg(struct ice_hw *hw)
 {
        char nvm_str[ICE_NVM_VER_LEN] = { 0 };
-       u8 oem_ver, oem_patch, ver_hi, ver_lo;
-       u16 oem_build;
+       struct ice_nvm_info *nvm = &hw->nvm;
+       struct ice_orom_info *orom;
 
-       ice_get_nvm_version(hw, &oem_ver, &oem_build, &oem_patch, &ver_hi,
-                           &ver_lo);
-       SNPRINTF(nvm_str, sizeof(nvm_str), "%x.%02x 0x%x %d.%d.%d", ver_hi,
-                ver_lo, hw->nvm.eetrack, oem_ver, oem_build, oem_patch);
+       orom = &nvm->orom;
+
+       SNPRINTF(nvm_str, sizeof(nvm_str), "%x.%02x 0x%x %d.%d.%d",
+                nvm->major_ver, nvm->minor_ver, nvm->eetrack, orom->major,
+                orom->build, orom->patch);
        ice_warn(hw,
-                "Firmware rollback mode detected. Current version is NVM: %s, FW: %d.%d. Device may exhibit limited functionality. Refer to the Intel(R) Ethernet Adapters and Devices User Guide for details on firmware rollback mode",
+                "Firmware rollback mode detected. Current version is NVM: %s, FW: %d.%d. Device may exhibit limited functionality. Refer to the Intel(R) Ethernet Adapters and Devices User Guide for details on firmware rollback mode\n",
                 nvm_str, hw->fw_maj_ver, hw->fw_min_ver);
 }
 
@@ -648,7 +637,6 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
 
        ice_clear_pxe_mode(hw);
 
-
        status = ice_get_caps(hw);
        if (status)
                goto err_unroll_cqinit;
@@ -669,7 +657,6 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
                goto err_unroll_alloc;
 
        hw->evb_veb = true;
-
        /* Query the allocated resources for Tx scheduler */
        status = ice_sched_query_res_alloc(hw);
        if (status) {
@@ -677,6 +664,7 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
                          "Failed to get scheduler allocated resources\n");
                goto err_unroll_alloc;
        }
+       ice_sched_get_psm_clk_freq(hw);
 
        /* Initialize port_info struct with scheduler data */
        status = ice_sched_init_port(hw->port_info);
@@ -788,7 +776,7 @@ void ice_deinit_hw(struct ice_hw *hw)
  */
 enum ice_status ice_check_reset(struct ice_hw *hw)
 {
-       u32 cnt, reg = 0, grst_delay;
+       u32 cnt, reg = 0, grst_delay, uld_mask;
 
        /* Poll for Device Active state in case a recent CORER, GLOBR,
         * or EMPR has occurred. The grst delay value is in 100ms units.
@@ -810,13 +798,20 @@ enum ice_status ice_check_reset(struct ice_hw *hw)
                return ICE_ERR_RESET_FAILED;
        }
 
-#define ICE_RESET_DONE_MASK    (GLNVM_ULD_CORER_DONE_M | \
-                                GLNVM_ULD_GLOBR_DONE_M)
+#define ICE_RESET_DONE_MASK    (GLNVM_ULD_PCIER_DONE_M |\
+                                GLNVM_ULD_PCIER_DONE_1_M |\
+                                GLNVM_ULD_CORER_DONE_M |\
+                                GLNVM_ULD_GLOBR_DONE_M |\
+                                GLNVM_ULD_POR_DONE_M |\
+                                GLNVM_ULD_POR_DONE_1_M |\
+                                GLNVM_ULD_PCIER_DONE_2_M)
+
+       uld_mask = ICE_RESET_DONE_MASK;
 
        /* Device is Active; check Global Reset processes are done */
        for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) {
-               reg = rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK;
-               if (reg == ICE_RESET_DONE_MASK) {
+               reg = rd32(hw, GLNVM_ULD) & uld_mask;
+               if (reg == uld_mask) {
                        ice_debug(hw, ICE_DBG_INIT,
                                  "Global reset processes done. %d\n", cnt);
                        break;
@@ -1068,7 +1063,6 @@ ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx,
        return ice_copy_rxq_ctx_to_hw(hw, ctx_buf, rxq_index);
 }
 
-#if !defined(NO_UNUSED_CTX_CODE) || defined(AE_DRIVER)
 /**
  * ice_clear_rxq_ctx
  * @hw: pointer to the hardware structure
@@ -1089,7 +1083,6 @@ enum ice_status ice_clear_rxq_ctx(struct ice_hw *hw, u32 rxq_index)
 
        return ICE_SUCCESS;
 }
-#endif /* !NO_UNUSED_CTX_CODE || AE_DRIVER */
 
 /* LAN Tx Queue Context */
 const struct ice_ctx_ele ice_tlan_ctx_info[] = {
@@ -1125,7 +1118,6 @@ const struct ice_ctx_ele ice_tlan_ctx_info[] = {
        { 0 }
 };
 
-#if !defined(NO_UNUSED_CTX_CODE) || defined(AE_DRIVER)
 /**
  * ice_copy_tx_cmpltnq_ctx_to_hw
  * @hw: pointer to the hardware structure
@@ -1306,7 +1298,6 @@ ice_clear_tx_drbell_q_ctx(struct ice_hw *hw, u32 tx_drbell_q_index)
 
        return ICE_SUCCESS;
 }
-#endif /* !NO_UNUSED_CTX_CODE || AE_DRIVER */
 
 /* FW Admin Queue command wrappers */
 
@@ -1681,7 +1672,7 @@ ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res)
        enum ice_status status;
        u16 buf_len;
 
-       buf_len = sizeof(*buf) + sizeof(buf->elem) * (num - 1);
+       buf_len = ice_struct_size(buf, elem, num - 1);
        buf = (struct ice_aqc_alloc_free_res_elem *)
                ice_malloc(hw, buf_len);
        if (!buf)
@@ -1721,7 +1712,7 @@ ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res)
        enum ice_status status;
        u16 buf_len;
 
-       buf_len = sizeof(*buf) + sizeof(buf->elem) * (num - 1);
+       buf_len = ice_struct_size(buf, elem, num - 1);
        buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
        if (!buf)
                return ICE_ERR_NO_MEMORY;
@@ -2380,8 +2371,8 @@ ice_aq_set_phy_cfg(struct ice_hw *hw, struct ice_port_info *pi,
        ice_debug(hw, ICE_DBG_LINK, "phy_type_high = 0x%llx\n",
                  (unsigned long long)LE64_TO_CPU(cfg->phy_type_high));
        ice_debug(hw, ICE_DBG_LINK, "caps = 0x%x\n", cfg->caps);
-       ice_debug(hw, ICE_DBG_LINK, "low_power_ctrl = 0x%x\n",
-                 cfg->low_power_ctrl);
+       ice_debug(hw, ICE_DBG_LINK, "low_power_ctrl_an = 0x%x\n",
+                 cfg->low_power_ctrl_an);
        ice_debug(hw, ICE_DBG_LINK, "eee_cap = 0x%x\n", cfg->eee_cap);
        ice_debug(hw, ICE_DBG_LINK, "eeer_value = 0x%x\n", cfg->eeer_value);
        ice_debug(hw, ICE_DBG_LINK, "link_fec_opt = 0x%x\n", cfg->link_fec_opt);
@@ -2532,8 +2523,9 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
        u8 pause_mask = 0x0;
        struct ice_hw *hw;
 
-       if (!pi)
+       if (!pi || !aq_failures)
                return ICE_ERR_PARAM;
+
        hw = pi->hw;
        *aq_failures = ICE_SET_FC_AQ_FAIL_NONE;
 
@@ -2541,7 +2533,26 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
        cache_data.data.curr_user_fc_req = pi->fc.req_mode;
        ice_cache_phy_user_req(pi, cache_data, ICE_FC_MODE);
 
+       pcaps = (struct ice_aqc_get_phy_caps_data *)
+               ice_malloc(hw, sizeof(*pcaps));
+       if (!pcaps)
+               return ICE_ERR_NO_MEMORY;
+
        switch (pi->fc.req_mode) {
+       case ICE_FC_AUTO:
+               /* Query the value of FC that both the NIC and attached media
+                * can do.
+                */
+               status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP,
+                                            pcaps, NULL);
+               if (status) {
+                       *aq_failures = ICE_SET_FC_AQ_FAIL_GET;
+                       goto out;
+               }
+
+               pause_mask |= pcaps->caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE;
+               pause_mask |= pcaps->caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE;
+               break;
        case ICE_FC_FULL:
                pause_mask |= ICE_AQC_PHY_EN_TX_LINK_PAUSE;
                pause_mask |= ICE_AQC_PHY_EN_RX_LINK_PAUSE;
@@ -2556,12 +2567,8 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
                break;
        }
 
-       pcaps = (struct ice_aqc_get_phy_caps_data *)
-               ice_malloc(hw, sizeof(*pcaps));
-       if (!pcaps)
-               return ICE_ERR_NO_MEMORY;
-
        /* Get the current PHY config */
+       ice_memset(pcaps, 0, sizeof(*pcaps), ICE_NONDMA_MEM);
        status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps,
                                     NULL);
        if (status) {
@@ -2569,9 +2576,11 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
                goto out;
        }
 
+       ice_copy_phy_caps_to_cfg(pi, pcaps, &cfg);
+
        /* clear the old pause settings */
-       cfg.caps = pcaps->caps & ~(ICE_AQC_PHY_EN_TX_LINK_PAUSE |
-                                  ICE_AQC_PHY_EN_RX_LINK_PAUSE);
+       cfg.caps &= ~(ICE_AQC_PHY_EN_TX_LINK_PAUSE |
+                     ICE_AQC_PHY_EN_RX_LINK_PAUSE);
 
        /* set the new capabilities */
        cfg.caps |= pause_mask;
@@ -2583,13 +2592,6 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
                /* Auto restart link so settings take effect */
                if (ena_auto_link_update)
                        cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
-               /* Copy over all the old settings */
-               cfg.phy_type_high = pcaps->phy_type_high;
-               cfg.phy_type_low = pcaps->phy_type_low;
-               cfg.low_power_ctrl = pcaps->low_power_ctrl;
-               cfg.eee_cap = pcaps->eee_cap;
-               cfg.eeer_value = pcaps->eeer_value;
-               cfg.link_fec_opt = pcaps->link_fec_options;
 
                status = ice_aq_set_phy_cfg(hw, pi, &cfg, NULL);
                if (status) {
@@ -2647,7 +2649,7 @@ ice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data *phy_caps,
        if (phy_caps->phy_type_low != phy_cfg->phy_type_low ||
            phy_caps->phy_type_high != phy_cfg->phy_type_high ||
            ((phy_caps->caps & caps_mask) != (phy_cfg->caps & cfg_mask)) ||
-           phy_caps->low_power_ctrl != phy_cfg->low_power_ctrl ||
+           phy_caps->low_power_ctrl_an != phy_cfg->low_power_ctrl_an ||
            phy_caps->eee_cap != phy_cfg->eee_cap ||
            phy_caps->eeer_value != phy_cfg->eeer_value ||
            phy_caps->link_fec_options != phy_cfg->link_fec_opt)
@@ -2658,6 +2660,7 @@ ice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data *phy_caps,
 
 /**
  * ice_copy_phy_caps_to_cfg - Copy PHY ability data to configuration data
+ * @pi: port information structure
  * @caps: PHY ability structure to copy date from
  * @cfg: PHY configuration structure to copy data to
  *
@@ -2665,33 +2668,65 @@ ice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data *phy_caps,
  * data structure
  */
 void
-ice_copy_phy_caps_to_cfg(struct ice_aqc_get_phy_caps_data *caps,
+ice_copy_phy_caps_to_cfg(struct ice_port_info *pi,
+                        struct ice_aqc_get_phy_caps_data *caps,
                         struct ice_aqc_set_phy_cfg_data *cfg)
 {
-       if (!caps || !cfg)
+       if (!pi || !caps || !cfg)
                return;
 
+       ice_memset(cfg, 0, sizeof(*cfg), ICE_NONDMA_MEM);
        cfg->phy_type_low = caps->phy_type_low;
        cfg->phy_type_high = caps->phy_type_high;
        cfg->caps = caps->caps;
-       cfg->low_power_ctrl = caps->low_power_ctrl;
+       cfg->low_power_ctrl_an = caps->low_power_ctrl_an;
        cfg->eee_cap = caps->eee_cap;
        cfg->eeer_value = caps->eeer_value;
        cfg->link_fec_opt = caps->link_fec_options;
+       cfg->module_compliance_enforcement =
+               caps->module_compliance_enforcement;
+
+       if (ice_fw_supports_link_override(pi->hw)) {
+               struct ice_link_default_override_tlv tlv;
+
+               if (ice_get_link_default_override(&tlv, pi))
+                       return;
+
+               if (tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE)
+                       cfg->module_compliance_enforcement |=
+                               ICE_LINK_OVERRIDE_STRICT_MODE;
+       }
 }
 
 /**
  * ice_cfg_phy_fec - Configure PHY FEC data based on FEC mode
+ * @pi: port information structure
  * @cfg: PHY configuration data to set FEC mode
  * @fec: FEC mode to configure
- *
- * Caller should copy ice_aqc_get_phy_caps_data.caps ICE_AQC_PHY_EN_AUTO_FEC
- * (bit 7) and ice_aqc_get_phy_caps_data.link_fec_options to cfg.caps
- * ICE_AQ_PHY_ENA_AUTO_FEC (bit 7) and cfg.link_fec_options before calling.
  */
-void
-ice_cfg_phy_fec(struct ice_aqc_set_phy_cfg_data *cfg, enum ice_fec_mode fec)
+enum ice_status
+ice_cfg_phy_fec(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
+               enum ice_fec_mode fec)
 {
+       struct ice_aqc_get_phy_caps_data *pcaps;
+       enum ice_status status = ICE_SUCCESS;
+       struct ice_hw *hw;
+
+       if (!pi || !cfg)
+               return ICE_ERR_BAD_PTR;
+
+       hw = pi->hw;
+
+       pcaps = (struct ice_aqc_get_phy_caps_data *)
+               ice_malloc(hw, sizeof(*pcaps));
+       if (!pcaps)
+               return ICE_ERR_NO_MEMORY;
+
+       status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, pcaps,
+                                    NULL);
+       if (status)
+               goto out;
+
        switch (fec) {
        case ICE_FEC_BASER:
                /* Clear RS bits, and AND BASE-R ability
@@ -2717,8 +2752,28 @@ ice_cfg_phy_fec(struct ice_aqc_set_phy_cfg_data *cfg, enum ice_fec_mode fec)
        case ICE_FEC_AUTO:
                /* AND auto FEC bit, and all caps bits. */
                cfg->caps &= ICE_AQC_PHY_CAPS_MASK;
+               cfg->link_fec_opt |= pcaps->link_fec_options;
                break;
+       default:
+               status = ICE_ERR_PARAM;
+               break;
+       }
+
+       if (fec == ICE_FEC_AUTO && ice_fw_supports_link_override(pi->hw)) {
+               struct ice_link_default_override_tlv tlv;
+
+               if (ice_get_link_default_override(&tlv, pi))
+                       goto out;
+
+               if (!(tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) &&
+                   (tlv.options & ICE_LINK_OVERRIDE_EN))
+                       cfg->link_fec_opt = tlv.fec_options;
        }
+
+out:
+       ice_free(hw, pcaps);
+
+       return status;
 }
 
 /**
@@ -3979,7 +4034,7 @@ ice_dis_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_queues,
  * This function adds/updates the VSI queues per TC.
  */
 static enum ice_status
-ice_cfg_vsi_qs(struct ice_port_info *pi, u16 vsi_handle, u8 tc_bitmap,
+ice_cfg_vsi_qs(struct ice_port_info *pi, u16 vsi_handle, u16 tc_bitmap,
               u16 *maxqs, u8 owner)
 {
        enum ice_status status = ICE_SUCCESS;
@@ -4018,7 +4073,7 @@ ice_cfg_vsi_qs(struct ice_port_info *pi, u16 vsi_handle, u8 tc_bitmap,
  * This function adds/updates the VSI LAN queues per TC.
  */
 enum ice_status
-ice_cfg_vsi_lan(struct ice_port_info *pi, u16 vsi_handle, u8 tc_bitmap,
+ice_cfg_vsi_lan(struct ice_port_info *pi, u16 vsi_handle, u16 tc_bitmap,
                u16 *max_lanqs)
 {
        return ice_cfg_vsi_qs(pi, vsi_handle, tc_bitmap, max_lanqs,
@@ -4270,3 +4325,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;
+}