net/ice/base: support flow director for GTPU with outer IPv6
[dpdk.git] / drivers / net / ice / base / ice_common.c
index 3fae6e7..1683daf 100644 (file)
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ice_common.h"
  */
 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:
+       case ICE_DEV_ID_E823L_10G_BASE_T:
+       case ICE_DEV_ID_E823L_1GBE:
+       case ICE_DEV_ID_E823L_BACKPLANE:
+       case ICE_DEV_ID_E823L_QSFP:
+       case ICE_DEV_ID_E823L_SFP:
+               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;
 }
 
 /**
@@ -133,11 +152,13 @@ ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
        u16 pcaps_size = sizeof(*pcaps);
        struct ice_aq_desc desc;
        enum ice_status status;
+       struct ice_hw *hw;
 
        cmd = &desc.params.get_phy;
 
        if (!pcaps || (report_mode & ~ICE_AQC_REPORT_MODE_M) || !pi)
                return ICE_ERR_PARAM;
+       hw = pi->hw;
 
        ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_phy_caps);
 
@@ -145,11 +166,41 @@ ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
                cmd->param0 |= CPU_TO_LE16(ICE_AQC_GET_PHY_RQM);
 
        cmd->param0 |= CPU_TO_LE16(report_mode);
-       status = ice_aq_send_cmd(pi->hw, &desc, pcaps, pcaps_size, cd);
+       status = ice_aq_send_cmd(hw, &desc, pcaps, pcaps_size, cd);
+
+       ice_debug(hw, ICE_DBG_LINK, "get phy caps - report_mode = 0x%x\n",
+                 report_mode);
+       ice_debug(hw, ICE_DBG_LINK, "   phy_type_low = 0x%llx\n",
+                 (unsigned long long)LE64_TO_CPU(pcaps->phy_type_low));
+       ice_debug(hw, ICE_DBG_LINK, "   phy_type_high = 0x%llx\n",
+                 (unsigned long long)LE64_TO_CPU(pcaps->phy_type_high));
+       ice_debug(hw, ICE_DBG_LINK, "   caps = 0x%x\n", pcaps->caps);
+       ice_debug(hw, ICE_DBG_LINK, "   low_power_ctrl_an = 0x%x\n",
+                 pcaps->low_power_ctrl_an);
+       ice_debug(hw, ICE_DBG_LINK, "   eee_cap = 0x%x\n", pcaps->eee_cap);
+       ice_debug(hw, ICE_DBG_LINK, "   eeer_value = 0x%x\n",
+                 pcaps->eeer_value);
+       ice_debug(hw, ICE_DBG_LINK, "   link_fec_options = 0x%x\n",
+                 pcaps->link_fec_options);
+       ice_debug(hw, ICE_DBG_LINK, "   module_compliance_enforcement = 0x%x\n",
+                 pcaps->module_compliance_enforcement);
+       ice_debug(hw, ICE_DBG_LINK, "   extended_compliance_code = 0x%x\n",
+                 pcaps->extended_compliance_code);
+       ice_debug(hw, ICE_DBG_LINK, "   module_type[0] = 0x%x\n",
+                 pcaps->module_type[0]);
+       ice_debug(hw, ICE_DBG_LINK, "   module_type[1] = 0x%x\n",
+                 pcaps->module_type[1]);
+       ice_debug(hw, ICE_DBG_LINK, "   module_type[2] = 0x%x\n",
+                 pcaps->module_type[2]);
+
 
        if (status == ICE_SUCCESS && report_mode == ICE_AQC_REPORT_TOPO_CAP) {
                pi->phy.phy_type_low = LE64_TO_CPU(pcaps->phy_type_low);
                pi->phy.phy_type_high = LE64_TO_CPU(pcaps->phy_type_high);
+               ice_memcpy(pi->phy.link_info.module_type, &pcaps->module_type,
+                          sizeof(pi->phy.link_info.module_type),
+                          ICE_NONDMA_TO_NONDMA);
+
        }
 
        return status;
@@ -222,6 +273,18 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
                return ICE_MEDIA_UNKNOWN;
 
        if (hw_link_info->phy_type_low) {
+               /* 1G SGMII is a special case where some DA cable PHYs
+                * may show this as an option when it really shouldn't
+                * be since SGMII is meant to be between a MAC and a PHY
+                * in a backplane. Try to detect this case and handle it
+                */
+               if (hw_link_info->phy_type_low == ICE_PHY_TYPE_LOW_1G_SGMII &&
+                   (hw_link_info->module_type[ICE_AQC_MOD_TYPE_IDENT] ==
+                   ICE_AQC_MOD_TYPE_BYTE1_SFP_PLUS_CU_ACTIVE ||
+                   hw_link_info->module_type[ICE_AQC_MOD_TYPE_IDENT] ==
+                   ICE_AQC_MOD_TYPE_BYTE1_SFP_PLUS_CU_PASSIVE))
+                       return ICE_MEDIA_DA;
+
                switch (hw_link_info->phy_type_low) {
                case ICE_PHY_TYPE_LOW_1000BASE_SX:
                case ICE_PHY_TYPE_LOW_1000BASE_LX:
@@ -242,6 +305,15 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
                case ICE_PHY_TYPE_LOW_100GBASE_SR2:
                case ICE_PHY_TYPE_LOW_100GBASE_DR:
                        return ICE_MEDIA_FIBER;
+               case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC:
+               case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC:
+               case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC:
+               case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC:
+               case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC:
+               case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC:
+               case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC:
+               case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC:
+                       return ICE_MEDIA_FIBER;
                case ICE_PHY_TYPE_LOW_100BASE_TX:
                case ICE_PHY_TYPE_LOW_1000BASE_T:
                case ICE_PHY_TYPE_LOW_2500BASE_T:
@@ -268,7 +340,7 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
                case ICE_PHY_TYPE_LOW_100G_AUI4:
                case ICE_PHY_TYPE_LOW_100G_CAUI4:
                        if (ice_is_media_cage_present(pi))
-                               return ICE_MEDIA_DA;
+                               return ICE_MEDIA_AUI;
                        /* fall-through */
                case ICE_PHY_TYPE_LOW_1000BASE_KX:
                case ICE_PHY_TYPE_LOW_2500BASE_KX:
@@ -288,11 +360,15 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
        } else {
                switch (hw_link_info->phy_type_high) {
                case ICE_PHY_TYPE_HIGH_100G_AUI2:
+               case ICE_PHY_TYPE_HIGH_100G_CAUI2:
                        if (ice_is_media_cage_present(pi))
-                               return ICE_MEDIA_DA;
+                               return ICE_MEDIA_AUI;
                        /* fall-through */
                case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
                        return ICE_MEDIA_BACKPLANE;
+               case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC:
+               case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC:
+                       return ICE_MEDIA_FIBER;
                }
        }
        return ICE_MEDIA_UNKNOWN;
@@ -372,18 +448,21 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
 
        li->lse_ena = !!(resp->cmd_flags & CPU_TO_LE16(ICE_AQ_LSE_IS_ENABLED));
 
-       ice_debug(hw, ICE_DBG_LINK, "link_speed = 0x%x\n", li->link_speed);
-       ice_debug(hw, ICE_DBG_LINK, "phy_type_low = 0x%llx\n",
+       ice_debug(hw, ICE_DBG_LINK, "get link info\n");
+       ice_debug(hw, ICE_DBG_LINK, "   link_speed = 0x%x\n", li->link_speed);
+       ice_debug(hw, ICE_DBG_LINK, "   phy_type_low = 0x%llx\n",
                  (unsigned long long)li->phy_type_low);
-       ice_debug(hw, ICE_DBG_LINK, "phy_type_high = 0x%llx\n",
+       ice_debug(hw, ICE_DBG_LINK, "   phy_type_high = 0x%llx\n",
                  (unsigned long long)li->phy_type_high);
-       ice_debug(hw, ICE_DBG_LINK, "media_type = 0x%x\n", *hw_media_type);
-       ice_debug(hw, ICE_DBG_LINK, "link_info = 0x%x\n", li->link_info);
-       ice_debug(hw, ICE_DBG_LINK, "an_info = 0x%x\n", li->an_info);
-       ice_debug(hw, ICE_DBG_LINK, "ext_info = 0x%x\n", li->ext_info);
-       ice_debug(hw, ICE_DBG_LINK, "lse_ena = 0x%x\n", li->lse_ena);
-       ice_debug(hw, ICE_DBG_LINK, "max_frame = 0x%x\n", li->max_frame_size);
-       ice_debug(hw, ICE_DBG_LINK, "pacing = 0x%x\n", li->pacing);
+       ice_debug(hw, ICE_DBG_LINK, "   media_type = 0x%x\n", *hw_media_type);
+       ice_debug(hw, ICE_DBG_LINK, "   link_info = 0x%x\n", li->link_info);
+       ice_debug(hw, ICE_DBG_LINK, "   an_info = 0x%x\n", li->an_info);
+       ice_debug(hw, ICE_DBG_LINK, "   ext_info = 0x%x\n", li->ext_info);
+       ice_debug(hw, ICE_DBG_LINK, "   fec_info = 0x%x\n", li->fec_info);
+       ice_debug(hw, ICE_DBG_LINK, "   lse_ena = 0x%x\n", li->lse_ena);
+       ice_debug(hw, ICE_DBG_LINK, "   max_frame = 0x%x\n",
+                 li->max_frame_size);
+       ice_debug(hw, ICE_DBG_LINK, "   pacing = 0x%x\n", li->pacing);
 
        /* save link status information */
        if (link)
@@ -395,6 +474,43 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
        return ICE_SUCCESS;
 }
 
+/**
+ * ice_fill_tx_timer_and_fc_thresh
+ * @hw: pointer to the HW struct
+ * @cmd: pointer to MAC cfg structure
+ *
+ * Add Tx timer and FC refresh threshold info to Set MAC Config AQ command
+ * descriptor
+ */
+static void
+ice_fill_tx_timer_and_fc_thresh(struct ice_hw *hw,
+                               struct ice_aqc_set_mac_cfg *cmd)
+{
+       u16 fc_thres_val, tx_timer_val;
+       u32 val;
+
+       /* We read back the transmit timer and fc threshold value of
+        * LFC. Thus, we will use index =
+        * PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX.
+        *
+        * Also, because we are opearating on transmit timer and fc
+        * threshold of LFC, we don't turn on any bit in tx_tmr_priority
+        */
+#define IDX_OF_LFC PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX
+
+       /* Retrieve the transmit timer */
+       val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(IDX_OF_LFC));
+       tx_timer_val = val &
+               PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_M;
+       cmd->tx_tmr_value = CPU_TO_LE16(tx_timer_val);
+
+       /* Retrieve the fc threshold */
+       val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(IDX_OF_LFC));
+       fc_thres_val = val & PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_M;
+
+       cmd->fc_refresh_threshold = CPU_TO_LE16(fc_thres_val);
+}
+
 /**
  * ice_aq_set_mac_cfg
  * @hw: pointer to the HW struct
@@ -406,10 +522,8 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
 enum ice_status
 ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, struct ice_sq_cd *cd)
 {
-       u16 fc_threshold_val, tx_timer_val;
        struct ice_aqc_set_mac_cfg *cmd;
        struct ice_aq_desc desc;
-       u32 reg_val;
 
        cmd = &desc.params.set_mac_cfg;
 
@@ -420,27 +534,7 @@ ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, struct ice_sq_cd *cd)
 
        cmd->max_frame_size = CPU_TO_LE16(max_frame_size);
 
-       /* We read back the transmit timer and fc threshold value of
-        * LFC. Thus, we will use index =
-        * PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX.
-        *
-        * Also, because we are opearating on transmit timer and fc
-        * threshold of LFC, we don't turn on any bit in tx_tmr_priority
-        */
-#define IDX_OF_LFC PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX
-
-       /* Retrieve the transmit timer */
-       reg_val = rd32(hw,
-                      PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(IDX_OF_LFC));
-       tx_timer_val = reg_val &
-               PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_M;
-       cmd->tx_tmr_value = CPU_TO_LE16(tx_timer_val);
-
-       /* Retrieve the fc threshold */
-       reg_val = rd32(hw,
-                      PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(IDX_OF_LFC));
-       fc_threshold_val = reg_val & MAKEMASK(0xFFFF, 0);
-       cmd->fc_refresh_threshold = CPU_TO_LE16(fc_threshold_val);
+       ice_fill_tx_timer_and_fc_thresh(hw, cmd);
 
        return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
 }
@@ -449,40 +543,52 @@ ice_aq_set_mac_cfg(struct ice_hw *hw, u16 max_frame_size, struct ice_sq_cd *cd)
  * ice_init_fltr_mgmt_struct - initializes filter management list and locks
  * @hw: pointer to the HW struct
  */
-static enum ice_status ice_init_fltr_mgmt_struct(struct ice_hw *hw)
+enum ice_status ice_init_fltr_mgmt_struct(struct ice_hw *hw)
 {
        struct ice_switch_info *sw;
+       enum ice_status status;
 
        hw->switch_info = (struct ice_switch_info *)
                          ice_malloc(hw, sizeof(*hw->switch_info));
+
        sw = hw->switch_info;
 
        if (!sw)
                return ICE_ERR_NO_MEMORY;
 
        INIT_LIST_HEAD(&sw->vsi_list_map_head);
+       sw->prof_res_bm_init = 0;
 
-       return ice_init_def_sw_recp(hw, &hw->switch_info->recp_list);
+       status = ice_init_def_sw_recp(hw, &hw->switch_info->recp_list);
+       if (status) {
+               ice_free(hw, hw->switch_info);
+               return status;
+       }
+       return ICE_SUCCESS;
 }
 
 /**
- * ice_cleanup_fltr_mgmt_struct - cleanup filter management list and locks
+ * ice_cleanup_fltr_mgmt_single - clears single filter mngt struct
  * @hw: pointer to the HW struct
+ * @sw: pointer to switch info struct for which function clears filters
  */
-static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
+static void
+ice_cleanup_fltr_mgmt_single(struct ice_hw *hw, struct ice_switch_info *sw)
 {
-       struct ice_switch_info *sw = hw->switch_info;
        struct ice_vsi_list_map_info *v_pos_map;
        struct ice_vsi_list_map_info *v_tmp_map;
        struct ice_sw_recipe *recps;
        u8 i;
 
+       if (!sw)
+               return;
+
        LIST_FOR_EACH_ENTRY_SAFE(v_pos_map, v_tmp_map, &sw->vsi_list_map_head,
                                 ice_vsi_list_map_info, list_entry) {
                LIST_DEL(&v_pos_map->list_entry);
                ice_free(hw, v_pos_map);
        }
-       recps = hw->switch_info->recp_list;
+       recps = sw->recp_list;
        for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
                struct ice_recp_grp_entry *rg_entry, *tmprg_entry;
 
@@ -522,11 +628,20 @@ static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
                if (recps[i].root_buf)
                        ice_free(hw, recps[i].root_buf);
        }
-       ice_rm_all_sw_replay_rule_info(hw);
+       ice_rm_sw_replay_rule_info(hw, sw);
        ice_free(hw, sw->recp_list);
        ice_free(hw, sw);
 }
 
+/**
+ * ice_cleanup_all_fltr_mgmt - cleanup filter management list and locks
+ * @hw: pointer to the HW struct
+ */
+void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
+{
+       ice_cleanup_fltr_mgmt_single(hw, hw->switch_info);
+}
+
 /**
  * ice_get_itr_intrl_gran
  * @hw: pointer to the HW struct
@@ -554,29 +669,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
@@ -584,13 +676,14 @@ 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;
+
+       orom = &nvm->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);
+       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\n",
                 nvm_str, hw->fw_maj_ver, hw->fw_min_ver);
@@ -707,7 +800,6 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
        /* Initialize max burst size */
        if (!hw->max_burst_size)
                ice_cfg_rl_burst_size(hw, ICE_SCHED_DFLT_BURST_SIZE);
-
        status = ice_init_fltr_mgmt_struct(hw);
        if (status)
                goto err_unroll_sched;
@@ -726,6 +818,10 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
        status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL);
        ice_free(hw, mac_buf);
 
+       if (status)
+               goto err_unroll_fltr_mgmt_struct;
+       /* enable jumbo frame support at MAC level */
+       status = ice_aq_set_mac_cfg(hw, ICE_AQ_SET_MAC_FRAME_SIZE_MAX, NULL);
        if (status)
                goto err_unroll_fltr_mgmt_struct;
        /* Obtain counter base index which would be used by flow director */
@@ -735,6 +831,7 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
        status = ice_init_hw_tbls(hw);
        if (status)
                goto err_unroll_fltr_mgmt_struct;
+       ice_init_lock(&hw->tnl_lock);
        return ICE_SUCCESS;
 
 err_unroll_fltr_mgmt_struct:
@@ -766,6 +863,7 @@ void ice_deinit_hw(struct ice_hw *hw)
        ice_sched_clear_agg(hw);
        ice_free_seg(hw);
        ice_free_hw_tbls(hw);
+       ice_destroy_lock(&hw->tnl_lock);
 
        if (hw->port_info) {
                ice_free(hw, hw->port_info);
@@ -784,23 +882,23 @@ void ice_deinit_hw(struct ice_hw *hw)
  */
 enum ice_status ice_check_reset(struct ice_hw *hw)
 {
-       u32 cnt, reg = 0, grst_delay, uld_mask;
+       u32 cnt, reg = 0, grst_timeout, 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.
         * Add 1sec for outstanding AQ commands that can take a long time.
         */
-       grst_delay = ((rd32(hw, GLGEN_RSTCTL) & GLGEN_RSTCTL_GRSTDEL_M) >>
-                     GLGEN_RSTCTL_GRSTDEL_S) + 10;
+       grst_timeout = ((rd32(hw, GLGEN_RSTCTL) & GLGEN_RSTCTL_GRSTDEL_M) >>
+                       GLGEN_RSTCTL_GRSTDEL_S) + 10;
 
-       for (cnt = 0; cnt < grst_delay; cnt++) {
+       for (cnt = 0; cnt < grst_timeout; cnt++) {
                ice_msec_delay(100, true);
                reg = rd32(hw, GLGEN_RSTAT);
                if (!(reg & GLGEN_RSTAT_DEVSTATE_M))
                        break;
        }
 
-       if (cnt == grst_delay) {
+       if (cnt == grst_timeout) {
                ice_debug(hw, ICE_DBG_INIT,
                          "Global reset polling failed to complete.\n");
                return ICE_ERR_RESET_FAILED;
@@ -867,7 +965,12 @@ static enum ice_status ice_pf_reset(struct ice_hw *hw)
 
        wr32(hw, PFGEN_CTRL, (reg | PFGEN_CTRL_PFSWR_M));
 
-       for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) {
+       /* Wait for the PFR to complete. The wait time is the global config lock
+        * timeout plus the PFR timeout which will account for a possible reset
+        * that is occurring during a download package operation.
+        */
+       for (cnt = 0; cnt < ICE_GLOBAL_CFG_LOCK_TIMEOUT +
+            ICE_PF_RESET_WAIT_COUNT; cnt++) {
                reg = rd32(hw, PFGEN_CTRL);
                if (!(reg & PFGEN_CTRL_PFSWR_M))
                        break;
@@ -923,72 +1026,6 @@ enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req)
        return ice_check_reset(hw);
 }
 
-/**
- * ice_get_pfa_module_tlv - Reads sub module TLV from NVM PFA
- * @hw: pointer to hardware structure
- * @module_tlv: pointer to module TLV to return
- * @module_tlv_len: pointer to module TLV length to return
- * @module_type: module type requested
- *
- * Finds the requested sub module TLV type from the Preserved Field
- * Area (PFA) and returns the TLV pointer and length. The caller can
- * use these to read the variable length TLV value.
- */
-enum ice_status
-ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len,
-                      u16 module_type)
-{
-       enum ice_status status;
-       u16 pfa_len, pfa_ptr;
-       u16 next_tlv;
-
-       status = ice_read_sr_word(hw, ICE_SR_PFA_PTR, &pfa_ptr);
-       if (status != ICE_SUCCESS) {
-               ice_debug(hw, ICE_DBG_INIT, "Preserved Field Array pointer.\n");
-               return status;
-       }
-       status = ice_read_sr_word(hw, pfa_ptr, &pfa_len);
-       if (status != ICE_SUCCESS) {
-               ice_debug(hw, ICE_DBG_INIT, "Failed to read PFA length.\n");
-               return status;
-       }
-       /* Starting with first TLV after PFA length, iterate through the list
-        * of TLVs to find the requested one.
-        */
-       next_tlv = pfa_ptr + 1;
-       while (next_tlv < pfa_ptr + pfa_len) {
-               u16 tlv_sub_module_type;
-               u16 tlv_len;
-
-               /* Read TLV type */
-               status = ice_read_sr_word(hw, next_tlv, &tlv_sub_module_type);
-               if (status != ICE_SUCCESS) {
-                       ice_debug(hw, ICE_DBG_INIT, "Failed to read TLV type.\n");
-                       break;
-               }
-               /* Read TLV length */
-               status = ice_read_sr_word(hw, next_tlv + 1, &tlv_len);
-               if (status != ICE_SUCCESS) {
-                       ice_debug(hw, ICE_DBG_INIT, "Failed to read TLV length.\n");
-                       break;
-               }
-               if (tlv_sub_module_type == module_type) {
-                       if (tlv_len) {
-                               *module_tlv = next_tlv;
-                               *module_tlv_len = tlv_len;
-                               return ICE_SUCCESS;
-                       }
-                       return ICE_ERR_INVAL_SIZE;
-               }
-               /* Check next TLV, i.e. current TLV pointer + length + 2 words
-                * (for current TLV's type and length)
-                */
-               next_tlv = next_tlv + tlv_len + 2;
-       }
-       /* Module does not exist */
-       return ICE_ERR_DOES_NOT_EXIST;
-}
-
 /**
  * ice_copy_rxq_ctx_to_hw
  * @hw: pointer to the hardware structure
@@ -1067,7 +1104,7 @@ ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx,
 
        rlan_ctx->prefena = 1;
 
-       ice_set_ctx((u8 *)rlan_ctx, ctx_buf, ice_rlan_ctx_info);
+       ice_set_ctx(hw, (u8 *)rlan_ctx, ctx_buf, ice_rlan_ctx_info);
        return ice_copy_rxq_ctx_to_hw(hw, ctx_buf, rxq_index);
 }
 
@@ -1190,7 +1227,7 @@ ice_write_tx_cmpltnq_ctx(struct ice_hw *hw,
 {
        u8 ctx_buf[ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS * sizeof(u32)] = { 0 };
 
-       ice_set_ctx((u8 *)tx_cmpltnq_ctx, ctx_buf, ice_tx_cmpltnq_ctx_info);
+       ice_set_ctx(hw, (u8 *)tx_cmpltnq_ctx, ctx_buf, ice_tx_cmpltnq_ctx_info);
        return ice_copy_tx_cmpltnq_ctx_to_hw(hw, ctx_buf, tx_cmpltnq_index);
 }
 
@@ -1281,7 +1318,8 @@ ice_write_tx_drbell_q_ctx(struct ice_hw *hw,
 {
        u8 ctx_buf[ICE_TX_DRBELL_Q_CTX_SIZE_DWORDS * sizeof(u32)] = { 0 };
 
-       ice_set_ctx((u8 *)tx_drbell_q_ctx, ctx_buf, ice_tx_drbell_q_ctx_info);
+       ice_set_ctx(hw, (u8 *)tx_drbell_q_ctx, ctx_buf,
+                   ice_tx_drbell_q_ctx_info);
        return ice_copy_tx_drbell_q_ctx_to_hw(hw, ctx_buf, tx_drbell_q_index);
 }
 
@@ -1323,6 +1361,28 @@ enum ice_status
 ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf,
                u16 buf_size, struct ice_sq_cd *cd)
 {
+       if (hw->aq_send_cmd_fn) {
+               enum ice_status status = ICE_ERR_NOT_READY;
+               u16 retval = ICE_AQ_RC_OK;
+
+               ice_acquire_lock(&hw->adminq.sq_lock);
+               if (!hw->aq_send_cmd_fn(hw->aq_send_cmd_param, desc,
+                                       buf, buf_size)) {
+                       retval = LE16_TO_CPU(desc->retval);
+                       /* strip off FW internal code */
+                       if (retval)
+                               retval &= 0xff;
+                       if (retval == ICE_AQ_RC_OK)
+                               status = ICE_SUCCESS;
+                       else
+                               status = ICE_ERR_AQ_ERROR;
+               }
+
+               hw->adminq.sq_last_status = (enum ice_aq_err)retval;
+               ice_release_lock(&hw->adminq.sq_lock);
+
+               return status;
+       }
        return ice_sq_send_cmd(hw, &hw->adminq, desc, buf, buf_size, cd);
 }
 
@@ -1713,8 +1773,7 @@ ice_alloc_res_exit:
  * @num: number of resources
  * @res: pointer to array that contains the resources to free
  */
-enum ice_status
-ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res)
+enum ice_status ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res)
 {
        struct ice_aqc_alloc_free_res_elem *buf;
        enum ice_status status;
@@ -1791,10 +1850,16 @@ ice_parse_caps(struct ice_hw *hw, void *buf, u32 cap_count,
        if (opc == ice_aqc_opc_list_dev_caps) {
                dev_p = &hw->dev_caps;
                caps = &dev_p->common_cap;
+
+               ice_memset(dev_p, 0, sizeof(*dev_p), ICE_NONDMA_MEM);
+
                prefix = "dev cap";
        } else if (opc == ice_aqc_opc_list_func_caps) {
                func_p = &hw->func_caps;
                caps = &func_p->common_cap;
+
+               ice_memset(func_p, 0, sizeof(*func_p), ICE_NONDMA_MEM);
+
                prefix = "func cap";
        } else {
                ice_debug(hw, ICE_DBG_INIT, "wrong opcode\n");
@@ -1889,9 +1954,6 @@ ice_parse_caps(struct ice_hw *hw, void *buf, u32 cap_count,
                                  caps->msix_vector_first_id);
                        break;
                case ICE_AQC_CAPS_FD:
-               {
-                       u32 reg_val, val;
-
                        if (dev_p) {
                                dev_p->num_flow_director_fltr = number;
                                ice_debug(hw, ICE_DBG_INIT,
@@ -1900,6 +1962,10 @@ ice_parse_caps(struct ice_hw *hw, void *buf, u32 cap_count,
                                          dev_p->num_flow_director_fltr);
                        }
                        if (func_p) {
+                               u32 reg_val, val;
+
+                               if (hw->dcf_enabled)
+                                       break;
                                reg_val = rd32(hw, GLQF_FD_SIZE);
                                val = (reg_val & GLQF_FD_SIZE_FD_GSIZE_M) >>
                                      GLQF_FD_SIZE_FD_GSIZE_S;
@@ -1916,7 +1982,6 @@ ice_parse_caps(struct ice_hw *hw, void *buf, u32 cap_count,
                                          prefix, func_p->fd_fltr_best_effort);
                        }
                        break;
-               }
                case ICE_AQC_CAPS_MAX_MTU:
                        caps->max_mtu = number;
                        ice_debug(hw, ICE_DBG_INIT, "%s: max_mtu = %d\n",
@@ -1989,40 +2054,21 @@ ice_discover_caps(struct ice_hw *hw, enum ice_adminq_opc opc)
 {
        enum ice_status status;
        u32 cap_count;
-       u16 cbuf_len;
-       u8 retries;
-
-       /* The driver doesn't know how many capabilities the device will return
-        * so the buffer size required isn't known ahead of time. The driver
-        * starts with cbuf_len and if this turns out to be insufficient, the
-        * device returns ICE_AQ_RC_ENOMEM and also the cap_count it needs.
-        * The driver then allocates the buffer based on the count and retries
-        * the operation. So it follows that the retry count is 2.
-        */
-#define ICE_GET_CAP_BUF_COUNT  40
-#define ICE_GET_CAP_RETRY_COUNT        2
-
-       cap_count = ICE_GET_CAP_BUF_COUNT;
-       retries = ICE_GET_CAP_RETRY_COUNT;
+       void *cbuf;
 
-       do {
-               void *cbuf;
-
-               cbuf_len = (u16)(cap_count *
-                                sizeof(struct ice_aqc_list_caps_elem));
-               cbuf = ice_malloc(hw, cbuf_len);
-               if (!cbuf)
-                       return ICE_ERR_NO_MEMORY;
-
-               status = ice_aq_discover_caps(hw, cbuf, cbuf_len, &cap_count,
-                                             opc, NULL);
-               ice_free(hw, cbuf);
+       cbuf = ice_malloc(hw, ICE_AQ_MAX_BUF_LEN);
+       if (!cbuf)
+               return ICE_ERR_NO_MEMORY;
 
-               if (!status || hw->adminq.sq_last_status != ICE_AQ_RC_ENOMEM)
-                       break;
+       /* Although the driver doesn't know the number of capabilities the
+        * device will return, we can simply send a 4KB buffer, the maximum
+        * possible size that firmware can return.
+        */
+       cap_count = ICE_AQ_MAX_BUF_LEN / sizeof(struct ice_aqc_list_caps_elem);
 
-               /* If ENOMEM is returned, try again with bigger buffer */
-       } while (--retries);
+       status = ice_aq_discover_caps(hw, cbuf, ICE_AQ_MAX_BUF_LEN, &cap_count,
+                                     opc, NULL);
+       ice_free(hw, cbuf);
 
        return status;
 }
@@ -2126,10 +2172,7 @@ ice_aq_manage_mac_write(struct ice_hw *hw, const u8 *mac_addr, u8 flags,
        ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_write);
 
        cmd->flags = flags;
-
-       /* Prep values for flags, sah, sal */
-       cmd->sah = HTONS(*((const u16 *)mac_addr));
-       cmd->sal = HTONL(*((const u32 *)(mac_addr + 2)));
+       ice_memcpy(cmd->mac_addr, mac_addr, ETH_ALEN, ICE_NONDMA_TO_DMA);
 
        return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
 }
@@ -2374,19 +2417,24 @@ ice_aq_set_phy_cfg(struct ice_hw *hw, struct ice_port_info *pi,
        desc.params.set_phy.lport_num = pi->lport;
        desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
 
-       ice_debug(hw, ICE_DBG_LINK, "phy_type_low = 0x%llx\n",
+       ice_debug(hw, ICE_DBG_LINK, "set phy cfg\n");
+       ice_debug(hw, ICE_DBG_LINK, "   phy_type_low = 0x%llx\n",
                  (unsigned long long)LE64_TO_CPU(cfg->phy_type_low));
-       ice_debug(hw, ICE_DBG_LINK, "phy_type_high = 0x%llx\n",
+       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, "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);
+       ice_debug(hw, ICE_DBG_LINK, "   caps = 0x%x\n", cfg->caps);
+       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);
 
        status = ice_aq_send_cmd(hw, &desc, cfg, sizeof(*cfg), cd);
 
+       if (hw->adminq.sq_last_status == ICE_AQ_RC_EMODE)
+               status = ICE_SUCCESS;
+
        if (!status)
                pi->phy.curr_user_phy_cfg = *cfg;
 
@@ -2423,10 +2471,6 @@ enum ice_status ice_update_link_info(struct ice_port_info *pi)
 
                status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP,
                                             pcaps, NULL);
-               if (status == ICE_SUCCESS)
-                       ice_memcpy(li->module_type, &pcaps->module_type,
-                                  sizeof(li->module_type),
-                                  ICE_NONDMA_TO_NONDMA);
 
                ice_free(hw, pcaps);
        }
@@ -2513,35 +2557,40 @@ enum ice_fec_mode ice_caps_to_fec_mode(u8 caps, u8 fec_options)
        return ICE_FEC_NONE;
 }
 
-/**
- * ice_set_fc
- * @pi: port information structure
- * @aq_failures: pointer to status code, specific to ice_set_fc routine
- * @ena_auto_link_update: enable automatic link update
- *
- * Set the requested flow control mode.
- */
-enum ice_status
-ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
+static enum ice_status
+ice_cfg_phy_fc(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
+              enum ice_fc_mode req_mode)
 {
-       struct ice_aqc_set_phy_cfg_data cfg = { 0 };
+       struct ice_aqc_get_phy_caps_data *pcaps = NULL;
        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;
+       enum ice_status status = ICE_SUCCESS;
        u8 pause_mask = 0x0;
-       struct ice_hw *hw;
 
-       if (!pi)
-               return ICE_ERR_PARAM;
-       hw = pi->hw;
-       *aq_failures = ICE_SET_FC_AQ_FAIL_NONE;
+       if (!pi || !cfg)
+               return ICE_ERR_BAD_PTR;
+
+       pcaps = (struct ice_aqc_get_phy_caps_data *)
+               ice_malloc(pi->hw, sizeof(*pcaps));
+       if (!pcaps)
+               return ICE_ERR_NO_MEMORY;
 
        /* Cache user FC request */
-       cache_data.data.curr_user_fc_req = pi->fc.req_mode;
+       cache_data.data.curr_user_fc_req = req_mode;
        ice_cache_phy_user_req(pi, cache_data, ICE_FC_MODE);
 
-       switch (pi->fc.req_mode) {
+       switch (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)
+                       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,6 +2605,40 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
                break;
        }
 
+       /* clear the old pause settings */
+       cfg->caps &= ~(ICE_AQC_PHY_EN_TX_LINK_PAUSE |
+               ICE_AQC_PHY_EN_RX_LINK_PAUSE);
+
+       /* set the new capabilities */
+       cfg->caps |= pause_mask;
+
+out:
+       ice_free(pi->hw, pcaps);
+       return status;
+}
+
+/**
+ * ice_set_fc
+ * @pi: port information structure
+ * @aq_failures: pointer to status code, specific to ice_set_fc routine
+ * @ena_auto_link_update: enable automatic link update
+ *
+ * Set the requested flow control mode.
+ */
+enum ice_status
+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_aqc_get_phy_caps_data *pcaps;
+       enum ice_status status;
+       struct ice_hw *hw;
+
+       if (!pi || !aq_failures)
+               return ICE_ERR_BAD_PTR;
+
+       *aq_failures = 0;
+       hw = pi->hw;
+
        pcaps = (struct ice_aqc_get_phy_caps_data *)
                ice_malloc(hw, sizeof(*pcaps));
        if (!pcaps)
@@ -2569,22 +2652,15 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
                goto out;
        }
 
-       /* clear the old pause settings */
-       cfg.caps = pcaps->caps & ~(ICE_AQC_PHY_EN_TX_LINK_PAUSE |
-                                  ICE_AQC_PHY_EN_RX_LINK_PAUSE);
+       ice_copy_phy_caps_to_cfg(pi, pcaps, &cfg);
 
-       /* set the new capabilities */
-       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;
+       /* Configure the set PHY data */
+       status = ice_cfg_phy_fc(pi, &cfg, pi->fc.req_mode);
+       if (status) {
+               if (status != ICE_ERR_BAD_PTR)
+                       *aq_failures = ICE_SET_FC_AQ_FAIL_GET;
 
-               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;
+               goto out;
        }
 
        /* If the capabilities have changed, then set the new config */
@@ -2594,13 +2670,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) {
@@ -2658,7 +2727,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)
@@ -2669,6 +2738,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
  *
@@ -2676,33 +2746,68 @@ 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;
+
+       cfg->caps |= (pcaps->caps & ICE_AQC_PHY_EN_AUTO_FEC);
+       cfg->link_fec_opt = pcaps->link_fec_options;
+
        switch (fec) {
        case ICE_FEC_BASER:
                /* Clear RS bits, and AND BASE-R ability
@@ -2728,8 +2833,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;
 }
 
 /**
@@ -3538,12 +3663,14 @@ ice_write_qword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
 
 /**
  * ice_set_ctx - set context bits in packed structure
+ * @hw: pointer to the hardware structure
  * @src_ctx:  pointer to a generic non-packed context structure
  * @dest_ctx: pointer to memory for the packed structure
  * @ce_info:  a description of the structure to be transformed
  */
 enum ice_status
-ice_set_ctx(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
+ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx,
+           const struct ice_ctx_ele *ce_info)
 {
        int f;
 
@@ -3552,6 +3679,12 @@ ice_set_ctx(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
                 * using the correct size so that we are correct regardless
                 * of the endianness of the machine.
                 */
+               if (ce_info[f].width > (ce_info[f].size_of * BITS_PER_BYTE)) {
+                       ice_debug(hw, ICE_DBG_QCTX,
+                                 "Field %d width of %d bits larger than size of %d byte(s) ... skipping write\n",
+                                 f, ce_info[f].width, ce_info[f].size_of);
+                       continue;
+               }
                switch (ce_info[f].size_of) {
                case sizeof(u8):
                        ice_write_byte(src_ctx, dest_ctx, &ce_info[f]);
@@ -3878,7 +4011,18 @@ ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u16 q_handle,
         * Without setting the generic section as valid in valid_sections, the
         * Admin queue command will fail with error code ICE_AQ_RC_EINVAL.
         */
-       buf->txqs[0].info.valid_sections = ICE_AQC_ELEM_VALID_GENERIC;
+       buf->txqs[0].info.valid_sections =
+               ICE_AQC_ELEM_VALID_GENERIC | ICE_AQC_ELEM_VALID_CIR |
+               ICE_AQC_ELEM_VALID_EIR;
+       buf->txqs[0].info.generic = 0;
+       buf->txqs[0].info.cir_bw.bw_profile_idx =
+               CPU_TO_LE16(ICE_SCHED_DFLT_RL_PROF_ID);
+       buf->txqs[0].info.cir_bw.bw_alloc =
+               CPU_TO_LE16(ICE_SCHED_DFLT_BW_WT);
+       buf->txqs[0].info.eir_bw.bw_profile_idx =
+               CPU_TO_LE16(ICE_SCHED_DFLT_RL_PROF_ID);
+       buf->txqs[0].info.eir_bw.bw_alloc =
+               CPU_TO_LE16(ICE_SCHED_DFLT_BW_WT);
 
        /* add the LAN queue */
        status = ice_aq_add_lan_txq(hw, num_qgrps, buf, buf_size, cd);
@@ -3990,7 +4134,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;
@@ -4029,26 +4173,40 @@ 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,
                              ICE_SCHED_NODE_OWNER_LAN);
 }
 
+/**
+ * ice_is_main_vsi - checks whether the VSI is main VSI
+ * @hw: pointer to the HW struct
+ * @vsi_handle: VSI handle
+ *
+ * Checks whether the VSI is the main VSI (the first PF VSI created on
+ * given PF).
+ */
+static bool ice_is_main_vsi(struct ice_hw *hw, u16 vsi_handle)
+{
+       return vsi_handle == ICE_MAIN_VSI_HANDLE && hw->vsi_ctx[vsi_handle];
+}
+
 /**
  * ice_replay_pre_init - replay pre initialization
  * @hw: pointer to the HW struct
+ * @sw: pointer to switch info struct for which function initializes filters
  *
  * Initializes required config data for VSI, FD, ACL, and RSS before replay.
  */
-static enum ice_status ice_replay_pre_init(struct ice_hw *hw)
+static enum ice_status
+ice_replay_pre_init(struct ice_hw *hw, struct ice_switch_info *sw)
 {
-       struct ice_switch_info *sw = hw->switch_info;
        u8 i;
 
        /* Delete old entries from replay filter list head if there is any */
-       ice_rm_all_sw_replay_rule_info(hw);
+       ice_rm_sw_replay_rule_info(hw, sw);
        /* In start of replay, move entries into replay_rules list, it
         * will allow adding rules entries back to filt_rules list,
         * which is operational list.
@@ -4071,14 +4229,16 @@ static enum ice_status ice_replay_pre_init(struct ice_hw *hw)
  */
 enum ice_status ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle)
 {
+       struct ice_switch_info *sw = hw->switch_info;
+       struct ice_port_info *pi = hw->port_info;
        enum ice_status status;
 
        if (!ice_is_vsi_valid(hw, vsi_handle))
                return ICE_ERR_PARAM;
 
        /* Replay pre-initialization if there is any */
-       if (vsi_handle == ICE_MAIN_VSI_HANDLE) {
-               status = ice_replay_pre_init(hw);
+       if (ice_is_main_vsi(hw, vsi_handle)) {
+               status = ice_replay_pre_init(hw, sw);
                if (status)
                        return status;
        }
@@ -4087,7 +4247,7 @@ enum ice_status ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle)
        if (status)
                return status;
        /* Replay per VSI all filters */
-       status = ice_replay_vsi_all_fltr(hw, vsi_handle);
+       status = ice_replay_vsi_all_fltr(hw, pi, vsi_handle);
        if (!status)
                status = ice_replay_vsi_agg(hw, vsi_handle);
        return status;
@@ -4290,6 +4450,10 @@ enum ice_fw_modes ice_get_fw_mode(struct ice_hw *hw)
  */
 bool ice_fw_supports_link_override(struct ice_hw *hw)
 {
+       /* Currently, only supported for E810 devices */
+       if (hw->mac_type != ICE_MAC_E810)
+               return false;
+
        if (hw->api_maj_ver == ICE_FW_API_LINK_OVERRIDE_MAJ) {
                if (hw->api_min_ver > ICE_FW_API_LINK_OVERRIDE_MIN)
                        return true;
@@ -4380,3 +4544,18 @@ ice_get_link_default_override(struct ice_link_default_override_tlv *ldo,
 
        return status;
 }
+
+/**
+ * ice_is_phy_caps_an_enabled - check if PHY capabilities autoneg is enabled
+ * @caps: get PHY capability data
+ */
+bool ice_is_phy_caps_an_enabled(struct ice_aqc_get_phy_caps_data *caps)
+{
+       if (caps->caps & ICE_AQC_PHY_AN_MODE ||
+           caps->low_power_ctrl_an & (ICE_AQC_PHY_AN_EN_CLAUSE28 |
+                                      ICE_AQC_PHY_AN_EN_CLAUSE73 |
+                                      ICE_AQC_PHY_AN_EN_CLAUSE37))
+               return true;
+
+       return false;
+}