/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
*/
#include "ice_common.h"
#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;
}
/**
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 <<
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:
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:
} 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;
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
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;
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);
}
* 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)
INIT_LIST_HEAD(&sw->vsi_list_map_head);
- return ice_init_def_sw_recp(hw);
+ 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;
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
}
}
-/**
- * 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
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",
+ "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);
}
ice_clear_pxe_mode(hw);
-
status = ice_get_caps(hw);
if (status)
goto err_unroll_cqinit;
goto err_unroll_alloc;
hw->evb_veb = true;
-
/* Query the allocated resources for Tx scheduler */
status = ice_sched_query_res_alloc(hw);
if (status) {
"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);
/* 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;
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 */
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:
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);
*/
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.
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;
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;
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
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);
}
{
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);
}
{
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);
}
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);
}
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)
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;
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,
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;
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",
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);
}
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);
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;
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_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;
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;
+
+ hw = pi->hw;
+
pcaps = (struct ice_aqc_get_phy_caps_data *)
ice_malloc(hw, sizeof(*pcaps));
if (!pcaps)
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 */
- cfg.caps |= pause_mask;
+ /* 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;
+
+ goto out;
+ }
/* If the capabilities have changed, then set the new config */
if (cfg.caps != pcaps->caps) {
/* 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) {
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)
/**
* 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
*
* 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
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;
}
/**
/**
* 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;
* 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]);
* 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;
* 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.
*/
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;
}
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;
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)
+{
+ /* 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;
+ 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;
+}