/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2020 Intel Corporation
+ * Copyright(c) 2001-2021 Intel Corporation
*/
#include "ice_common.h"
#define ICE_PF_RESET_WAIT_COUNT 300
+/**
+ * dump_phy_type - helper function that prints PHY type strings
+ * @hw: pointer to the HW structure
+ * @phy: 64 bit PHY type to decipher
+ * @i: bit index within phy
+ * @phy_string: string corresponding to bit i in phy
+ * @prefix: prefix string to differentiate multiple dumps
+ */
+static void
+dump_phy_type(struct ice_hw *hw, u64 phy, u8 i, const char *phy_string,
+ const char *prefix)
+{
+ if (phy & BIT_ULL(i))
+ ice_debug(hw, ICE_DBG_PHY, "%s: bit(%d): %s\n", prefix, i,
+ phy_string);
+}
+
+/**
+ * ice_dump_phy_type_low - helper function to dump phy_type_low
+ * @hw: pointer to the HW structure
+ * @low: 64 bit value for phy_type_low
+ * @prefix: prefix string to differentiate multiple dumps
+ */
+static void
+ice_dump_phy_type_low(struct ice_hw *hw, u64 low, const char *prefix)
+{
+ ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_low: 0x%016llx\n", prefix,
+ (unsigned long long)low);
+
+ dump_phy_type(hw, low, 0, "100BASE_TX", prefix);
+ dump_phy_type(hw, low, 1, "100M_SGMII", prefix);
+ dump_phy_type(hw, low, 2, "1000BASE_T", prefix);
+ dump_phy_type(hw, low, 3, "1000BASE_SX", prefix);
+ dump_phy_type(hw, low, 4, "1000BASE_LX", prefix);
+ dump_phy_type(hw, low, 5, "1000BASE_KX", prefix);
+ dump_phy_type(hw, low, 6, "1G_SGMII", prefix);
+ dump_phy_type(hw, low, 7, "2500BASE_T", prefix);
+ dump_phy_type(hw, low, 8, "2500BASE_X", prefix);
+ dump_phy_type(hw, low, 9, "2500BASE_KX", prefix);
+ dump_phy_type(hw, low, 10, "5GBASE_T", prefix);
+ dump_phy_type(hw, low, 11, "5GBASE_KR", prefix);
+ dump_phy_type(hw, low, 12, "10GBASE_T", prefix);
+ dump_phy_type(hw, low, 13, "10G_SFI_DA", prefix);
+ dump_phy_type(hw, low, 14, "10GBASE_SR", prefix);
+ dump_phy_type(hw, low, 15, "10GBASE_LR", prefix);
+ dump_phy_type(hw, low, 16, "10GBASE_KR_CR1", prefix);
+ dump_phy_type(hw, low, 17, "10G_SFI_AOC_ACC", prefix);
+ dump_phy_type(hw, low, 18, "10G_SFI_C2C", prefix);
+ dump_phy_type(hw, low, 19, "25GBASE_T", prefix);
+ dump_phy_type(hw, low, 20, "25GBASE_CR", prefix);
+ dump_phy_type(hw, low, 21, "25GBASE_CR_S", prefix);
+ dump_phy_type(hw, low, 22, "25GBASE_CR1", prefix);
+ dump_phy_type(hw, low, 23, "25GBASE_SR", prefix);
+ dump_phy_type(hw, low, 24, "25GBASE_LR", prefix);
+ dump_phy_type(hw, low, 25, "25GBASE_KR", prefix);
+ dump_phy_type(hw, low, 26, "25GBASE_KR_S", prefix);
+ dump_phy_type(hw, low, 27, "25GBASE_KR1", prefix);
+ dump_phy_type(hw, low, 28, "25G_AUI_AOC_ACC", prefix);
+ dump_phy_type(hw, low, 29, "25G_AUI_C2C", prefix);
+ dump_phy_type(hw, low, 30, "40GBASE_CR4", prefix);
+ dump_phy_type(hw, low, 31, "40GBASE_SR4", prefix);
+ dump_phy_type(hw, low, 32, "40GBASE_LR4", prefix);
+ dump_phy_type(hw, low, 33, "40GBASE_KR4", prefix);
+ dump_phy_type(hw, low, 34, "40G_XLAUI_AOC_ACC", prefix);
+ dump_phy_type(hw, low, 35, "40G_XLAUI", prefix);
+ dump_phy_type(hw, low, 36, "50GBASE_CR2", prefix);
+ dump_phy_type(hw, low, 37, "50GBASE_SR2", prefix);
+ dump_phy_type(hw, low, 38, "50GBASE_LR2", prefix);
+ dump_phy_type(hw, low, 39, "50GBASE_KR2", prefix);
+ dump_phy_type(hw, low, 40, "50G_LAUI2_AOC_ACC", prefix);
+ dump_phy_type(hw, low, 41, "50G_LAUI2", prefix);
+ dump_phy_type(hw, low, 42, "50G_AUI2_AOC_ACC", prefix);
+ dump_phy_type(hw, low, 43, "50G_AUI2", prefix);
+ dump_phy_type(hw, low, 44, "50GBASE_CP", prefix);
+ dump_phy_type(hw, low, 45, "50GBASE_SR", prefix);
+ dump_phy_type(hw, low, 46, "50GBASE_FR", prefix);
+ dump_phy_type(hw, low, 47, "50GBASE_LR", prefix);
+ dump_phy_type(hw, low, 48, "50GBASE_KR_PAM4", prefix);
+ dump_phy_type(hw, low, 49, "50G_AUI1_AOC_ACC", prefix);
+ dump_phy_type(hw, low, 50, "50G_AUI1", prefix);
+ dump_phy_type(hw, low, 51, "100GBASE_CR4", prefix);
+ dump_phy_type(hw, low, 52, "100GBASE_SR4", prefix);
+ dump_phy_type(hw, low, 53, "100GBASE_LR4", prefix);
+ dump_phy_type(hw, low, 54, "100GBASE_KR4", prefix);
+ dump_phy_type(hw, low, 55, "100G_CAUI4_AOC_ACC", prefix);
+ dump_phy_type(hw, low, 56, "100G_CAUI4", prefix);
+ dump_phy_type(hw, low, 57, "100G_AUI4_AOC_ACC", prefix);
+ dump_phy_type(hw, low, 58, "100G_AUI4", prefix);
+ dump_phy_type(hw, low, 59, "100GBASE_CR_PAM4", prefix);
+ dump_phy_type(hw, low, 60, "100GBASE_KR_PAM4", prefix);
+ dump_phy_type(hw, low, 61, "100GBASE_CP2", prefix);
+ dump_phy_type(hw, low, 62, "100GBASE_SR2", prefix);
+ dump_phy_type(hw, low, 63, "100GBASE_DR", prefix);
+}
+
+/**
+ * ice_dump_phy_type_high - helper function to dump phy_type_high
+ * @hw: pointer to the HW structure
+ * @high: 64 bit value for phy_type_high
+ * @prefix: prefix string to differentiate multiple dumps
+ */
+static void
+ice_dump_phy_type_high(struct ice_hw *hw, u64 high, const char *prefix)
+{
+ ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_high: 0x%016llx\n", prefix,
+ (unsigned long long)high);
+
+ dump_phy_type(hw, high, 0, "100GBASE_KR2_PAM4", prefix);
+ dump_phy_type(hw, high, 1, "100G_CAUI2_AOC_ACC", prefix);
+ dump_phy_type(hw, high, 2, "100G_CAUI2", prefix);
+ dump_phy_type(hw, high, 3, "100G_AUI2_AOC_ACC", prefix);
+ dump_phy_type(hw, high, 4, "100G_AUI2", prefix);
+}
+
/**
* ice_set_mac_type - Sets MAC type
* @hw: pointer to the HW structure
case ICE_DEV_ID_E823L_BACKPLANE:
case ICE_DEV_ID_E823L_QSFP:
case ICE_DEV_ID_E823L_SFP:
+ case ICE_DEV_ID_E823C_10G_BASE_T:
+ case ICE_DEV_ID_E823C_BACKPLANE:
+ case ICE_DEV_ID_E823C_QSFP:
+ case ICE_DEV_ID_E823C_SFP:
+ case ICE_DEV_ID_E823C_SGMII:
hw->mac_type = ICE_MAC_GENERIC;
break;
default:
return ICE_SUCCESS;
}
+/**
+ * ice_is_generic_mac
+ * @hw: pointer to the hardware structure
+ *
+ * returns true if mac_type is ICE_MAC_GENERIC, false if not
+ */
+bool ice_is_generic_mac(struct ice_hw *hw)
+{
+ return hw->mac_type == ICE_MAC_GENERIC;
+}
+
+/**
+ * ice_is_e810
+ * @hw: pointer to the hardware structure
+ *
+ * returns true if the device is E810 based, false if not.
+ */
+bool ice_is_e810(struct ice_hw *hw)
+{
+ return hw->mac_type == ICE_MAC_E810;
+}
+
+/**
+ * ice_is_e810t
+ * @hw: pointer to the hardware structure
+ *
+ * returns true if the device is E810T based, false if not.
+ */
+bool ice_is_e810t(struct ice_hw *hw)
+{
+ return (hw->device_id == ICE_DEV_ID_E810C_SFP &&
+ hw->subsystem_device_id == ICE_SUBDEV_ID_E810T);
+}
+
/**
* ice_clear_pf_cfg - Clear PF configuration
* @hw: pointer to the hardware structure
u16 pcaps_size = sizeof(*pcaps);
struct ice_aq_desc desc;
enum ice_status status;
+ const char *prefix;
struct ice_hw *hw;
cmd = &desc.params.get_phy;
return ICE_ERR_PARAM;
hw = pi->hw;
+ if (report_mode == ICE_AQC_REPORT_DFLT_CFG &&
+ !ice_fw_supports_report_dflt_cfg(hw))
+ return ICE_ERR_PARAM;
+
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_phy_caps);
if (qual_mods)
cmd->param0 |= CPU_TO_LE16(report_mode);
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",
+ ice_debug(hw, ICE_DBG_LINK, "get phy caps dump\n");
+
+ if (report_mode == ICE_AQC_REPORT_TOPO_CAP_MEDIA)
+ prefix = "phy_caps_media";
+ else if (report_mode == ICE_AQC_REPORT_TOPO_CAP_NO_MEDIA)
+ prefix = "phy_caps_no_media";
+ else if (report_mode == ICE_AQC_REPORT_ACTIVE_CFG)
+ prefix = "phy_caps_active";
+ else if (report_mode == ICE_AQC_REPORT_DFLT_CFG)
+ prefix = "phy_caps_default";
+ else
+ prefix = "phy_caps_invalid";
+
+ ice_dump_phy_type_low(hw, LE64_TO_CPU(pcaps->phy_type_low), prefix);
+ ice_dump_phy_type_high(hw, LE64_TO_CPU(pcaps->phy_type_high), prefix);
+
+ ice_debug(hw, ICE_DBG_LINK, "%s: report_mode = 0x%x\n",
+ prefix, report_mode);
+ ice_debug(hw, ICE_DBG_LINK, "%s: caps = 0x%x\n", prefix, pcaps->caps);
+ ice_debug(hw, ICE_DBG_LINK, "%s: low_power_ctrl_an = 0x%x\n", prefix,
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",
+ ice_debug(hw, ICE_DBG_LINK, "%s: eee_cap = 0x%x\n", prefix,
+ pcaps->eee_cap);
+ ice_debug(hw, ICE_DBG_LINK, "%s: eeer_value = 0x%x\n", prefix,
pcaps->eeer_value);
- ice_debug(hw, ICE_DBG_LINK, " link_fec_options = 0x%x\n",
+ ice_debug(hw, ICE_DBG_LINK, "%s: link_fec_options = 0x%x\n", prefix,
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",
+ ice_debug(hw, ICE_DBG_LINK, "%s: module_compliance_enforcement = 0x%x\n",
+ prefix, pcaps->module_compliance_enforcement);
+ ice_debug(hw, ICE_DBG_LINK, "%s: extended_compliance_code = 0x%x\n",
+ prefix, pcaps->extended_compliance_code);
+ ice_debug(hw, ICE_DBG_LINK, "%s: module_type[0] = 0x%x\n", prefix,
pcaps->module_type[0]);
- ice_debug(hw, ICE_DBG_LINK, " module_type[1] = 0x%x\n",
+ ice_debug(hw, ICE_DBG_LINK, "%s: module_type[1] = 0x%x\n", prefix,
pcaps->module_type[1]);
- ice_debug(hw, ICE_DBG_LINK, " module_type[2] = 0x%x\n",
+ ice_debug(hw, ICE_DBG_LINK, "%s: module_type[2] = 0x%x\n", prefix,
pcaps->module_type[2]);
- if (status == ICE_SUCCESS && report_mode == ICE_AQC_REPORT_TOPO_CAP) {
+ if (status == ICE_SUCCESS && report_mode == ICE_AQC_REPORT_TOPO_CAP_MEDIA) {
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,
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 <<
- ICE_AQC_LINK_TOPO_NODE_CTX_S);
+ cmd->addr.topo_params.node_type_ctx =
+ (ICE_AQC_LINK_TOPO_NODE_CTX_PORT <<
+ ICE_AQC_LINK_TOPO_NODE_CTX_S);
/* set node type */
- cmd->addr.node_type_ctx |= (ICE_AQC_LINK_TOPO_NODE_TYPE_M & node_type);
+ cmd->addr.topo_params.node_type_ctx |=
+ (ICE_AQC_LINK_TOPO_NODE_TYPE_M & node_type);
return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd);
}
li->phy_type_high = LE64_TO_CPU(link_data.phy_type_high);
*hw_media_type = ice_get_media_type(pi);
li->link_info = link_data.link_info;
+ li->link_cfg_err = link_data.link_cfg_err;
li->an_info = link_data.an_info;
li->ext_info = link_data.ext_info;
li->max_frame_size = LE16_TO_CPU(link_data.max_frame_size);
(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, " link_cfg_err = 0x%x\n", li->link_cfg_err);
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_cleanup_all_fltr_mgmt - cleanup filter management list and locks
+ * ice_cleanup_fltr_mgmt_struct - cleanup filter management list and locks
* @hw: pointer to the HW struct
*/
void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
void ice_print_rollback_msg(struct ice_hw *hw)
{
char nvm_str[ICE_NVM_VER_LEN] = { 0 };
- struct ice_nvm_info *nvm = &hw->nvm;
struct ice_orom_info *orom;
+ struct ice_nvm_info *nvm;
- orom = &nvm->orom;
+ orom = &hw->flash.orom;
+ nvm = &hw->flash.nvm;
SNPRINTF(nvm_str, sizeof(nvm_str), "%x.%02x 0x%x %d.%d.%d",
- nvm->major_ver, nvm->minor_ver, nvm->eetrack, orom->major,
+ nvm->major, nvm->minor, 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",
/* Initialize port_info struct with PHY capabilities */
status = ice_aq_get_phy_caps(hw->port_info, false,
- ICE_AQC_REPORT_TOPO_CAP, pcaps, NULL);
+ ICE_AQC_REPORT_TOPO_CAP_MEDIA, pcaps, NULL);
ice_free(hw, pcaps);
if (status)
- ice_debug(hw, ICE_DBG_PHY, "%s: Get PHY capabilities failed, continuing anyway\n",
- __func__);
+ ice_warn(hw, "Get PHY capabilities failed status = %d, continuing anyway\n",
+ status);
/* Initialize port_info struct with link information */
status = ice_aq_get_link_info(hw->port_info, false, NULL, NULL);
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_alloc_fd_res_cntr(hw, &hw->fd_ctr_base);
if (status)
if (status)
goto err_unroll_fltr_mgmt_struct;
ice_init_lock(&hw->tnl_lock);
+
return ICE_SUCCESS;
err_unroll_fltr_mgmt_struct:
return ICE_SUCCESS;
}
+/* Sideband Queue command wrappers */
+
+/**
+ * ice_get_sbq - returns the right control queue to use for sideband
+ * @hw: pointer to the hardware structure
+ */
+static struct ice_ctl_q_info *ice_get_sbq(struct ice_hw *hw)
+{
+ if (!ice_is_generic_mac(hw))
+ return &hw->adminq;
+ return &hw->sbq;
+}
+
+/**
+ * ice_sbq_send_cmd - send Sideband Queue command to Sideband Queue
+ * @hw: pointer to the HW struct
+ * @desc: descriptor describing the command
+ * @buf: buffer to use for indirect commands (NULL for direct commands)
+ * @buf_size: size of buffer for indirect commands (0 for direct commands)
+ * @cd: pointer to command details structure
+ */
+static enum ice_status
+ice_sbq_send_cmd(struct ice_hw *hw, struct ice_sbq_cmd_desc *desc,
+ void *buf, u16 buf_size, struct ice_sq_cd *cd)
+{
+ return ice_sq_send_cmd(hw, ice_get_sbq(hw), (struct ice_aq_desc *)desc,
+ buf, buf_size, cd);
+}
+
+/**
+ * ice_sbq_send_cmd_nolock - send Sideband Queue command to Sideband Queue
+ * but do not lock sq_lock
+ * @hw: pointer to the HW struct
+ * @desc: descriptor describing the command
+ * @buf: buffer to use for indirect commands (NULL for direct commands)
+ * @buf_size: size of buffer for indirect commands (0 for direct commands)
+ * @cd: pointer to command details structure
+ */
+static enum ice_status
+ice_sbq_send_cmd_nolock(struct ice_hw *hw, struct ice_sbq_cmd_desc *desc,
+ void *buf, u16 buf_size, struct ice_sq_cd *cd)
+{
+ return ice_sq_send_cmd_nolock(hw, ice_get_sbq(hw),
+ (struct ice_aq_desc *)desc, buf,
+ buf_size, cd);
+}
+
+/**
+ * ice_sbq_rw_reg_lp - Fill Sideband Queue command, with lock parameter
+ * @hw: pointer to the HW struct
+ * @in: message info to be filled in descriptor
+ * @lock: true to lock the sq_lock (the usual case); false if the sq_lock has
+ * already been locked at a higher level
+ */
+enum ice_status ice_sbq_rw_reg_lp(struct ice_hw *hw,
+ struct ice_sbq_msg_input *in, bool lock)
+{
+ struct ice_sbq_cmd_desc desc = {0};
+ struct ice_sbq_msg_req msg = {0};
+ enum ice_status status;
+ u16 msg_len;
+
+ msg_len = sizeof(msg);
+
+ msg.dest_dev = in->dest_dev;
+ msg.opcode = in->opcode;
+ msg.flags = ICE_SBQ_MSG_FLAGS;
+ msg.sbe_fbe = ICE_SBQ_MSG_SBE_FBE;
+ msg.msg_addr_low = CPU_TO_LE16(in->msg_addr_low);
+ msg.msg_addr_high = CPU_TO_LE32(in->msg_addr_high);
+
+ if (in->opcode)
+ msg.data = CPU_TO_LE32(in->data);
+ else
+ /* data read comes back in completion, so shorten the struct by
+ * sizeof(msg.data)
+ */
+ msg_len -= sizeof(msg.data);
+
+ desc.flags = CPU_TO_LE16(ICE_AQ_FLAG_RD);
+ desc.opcode = CPU_TO_LE16(ice_sbq_opc_neigh_dev_req);
+ desc.param0.cmd_len = CPU_TO_LE16(msg_len);
+ if (lock)
+ status = ice_sbq_send_cmd(hw, &desc, &msg, msg_len, NULL);
+ else
+ status = ice_sbq_send_cmd_nolock(hw, &desc, &msg, msg_len,
+ NULL);
+ if (!status && !in->opcode)
+ in->data = LE32_TO_CPU
+ (((struct ice_sbq_msg_cmpl *)&msg)->data);
+ return status;
+}
+
+/**
+ * ice_sbq_rw_reg - Fill Sideband Queue command
+ * @hw: pointer to the HW struct
+ * @in: message info to be filled in descriptor
+ */
+enum ice_status ice_sbq_rw_reg(struct ice_hw *hw, struct ice_sbq_msg_input *in)
+{
+ return ice_sbq_rw_reg_lp(hw, in, true);
+}
+
+/**
+ * ice_sbq_lock - Lock the sideband queue's sq_lock
+ * @hw: pointer to the HW struct
+ */
+void ice_sbq_lock(struct ice_hw *hw)
+{
+ ice_acquire_lock(&ice_get_sbq(hw)->sq_lock);
+}
+
+/**
+ * ice_sbq_unlock - Unlock the sideband queue's sq_lock
+ * @hw: pointer to the HW struct
+ */
+void ice_sbq_unlock(struct ice_hw *hw)
+{
+ ice_release_lock(&ice_get_sbq(hw)->sq_lock);
+}
+
/* FW Admin Queue command wrappers */
+/**
+ * ice_should_retry_sq_send_cmd
+ * @opcode: AQ opcode
+ *
+ * Decide if we should retry the send command routine for the ATQ, depending
+ * on the opcode.
+ */
+static bool ice_should_retry_sq_send_cmd(u16 opcode)
+{
+ switch (opcode) {
+ case ice_aqc_opc_get_link_topo:
+ case ice_aqc_opc_lldp_stop:
+ case ice_aqc_opc_lldp_start:
+ case ice_aqc_opc_lldp_filter_ctrl:
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * ice_sq_send_cmd_retry - send command to Control Queue (ATQ)
+ * @hw: pointer to the HW struct
+ * @cq: pointer to the specific Control queue
+ * @desc: prefilled descriptor describing the command
+ * @buf: buffer to use for indirect commands (or NULL for direct commands)
+ * @buf_size: size of buffer for indirect commands (or 0 for direct commands)
+ * @cd: pointer to command details structure
+ *
+ * Retry sending the FW Admin Queue command, multiple times, to the FW Admin
+ * Queue if the EBUSY AQ error is returned.
+ */
+static enum ice_status
+ice_sq_send_cmd_retry(struct ice_hw *hw, struct ice_ctl_q_info *cq,
+ struct ice_aq_desc *desc, void *buf, u16 buf_size,
+ struct ice_sq_cd *cd)
+{
+ struct ice_aq_desc desc_cpy;
+ enum ice_status status;
+ bool is_cmd_for_retry;
+ u8 *buf_cpy = NULL;
+ u8 idx = 0;
+ u16 opcode;
+
+ opcode = LE16_TO_CPU(desc->opcode);
+ is_cmd_for_retry = ice_should_retry_sq_send_cmd(opcode);
+ ice_memset(&desc_cpy, 0, sizeof(desc_cpy), ICE_NONDMA_MEM);
+
+ if (is_cmd_for_retry) {
+ if (buf) {
+ buf_cpy = (u8 *)ice_malloc(hw, buf_size);
+ if (!buf_cpy)
+ return ICE_ERR_NO_MEMORY;
+ }
+
+ ice_memcpy(&desc_cpy, desc, sizeof(desc_cpy),
+ ICE_NONDMA_TO_NONDMA);
+ }
+
+ do {
+ status = ice_sq_send_cmd(hw, cq, desc, buf, buf_size, cd);
+
+ if (!is_cmd_for_retry || status == ICE_SUCCESS ||
+ hw->adminq.sq_last_status != ICE_AQ_RC_EBUSY)
+ break;
+
+ if (buf_cpy)
+ ice_memcpy(buf, buf_cpy, buf_size,
+ ICE_NONDMA_TO_NONDMA);
+
+ ice_memcpy(desc, &desc_cpy, sizeof(desc_cpy),
+ ICE_NONDMA_TO_NONDMA);
+
+ ice_msec_delay(ICE_SQ_SEND_DELAY_TIME_MS, false);
+
+ } while (++idx < ICE_SQ_SEND_MAX_EXECUTE);
+
+ if (buf_cpy)
+ ice_free(hw, buf_cpy);
+
+ return status;
+}
+
/**
* ice_aq_send_cmd - send FW Admin Queue command to FW Admin Queue
* @hw: pointer to the HW struct
return status;
}
- return ice_sq_send_cmd(hw, &hw->adminq, desc, buf, buf_size, cd);
+ return ice_sq_send_cmd_retry(hw, &hw->adminq, desc, buf, buf_size, cd);
}
/**
if (!buf)
return ICE_ERR_PARAM;
- if (buf_size < (num_entries * sizeof(buf->elem[0])))
+ if (buf_size < FLEX_ARRAY_SIZE(buf, elem, num_entries))
return ICE_ERR_PARAM;
ice_fill_dflt_direct_cmd_desc(&desc, opc);
ice_debug(hw, ICE_DBG_INIT, "%s: msix_vector_first_id = %d\n", prefix,
caps->msix_vector_first_id);
break;
+ case ICE_AQC_CAPS_NVM_MGMT:
+ caps->sec_rev_disabled =
+ (number & ICE_NVM_MGMT_SEC_REV_DISABLED) ?
+ true : false;
+ ice_debug(hw, ICE_DBG_INIT, "%s: sec_rev_disabled = %d\n", prefix,
+ caps->sec_rev_disabled);
+ caps->update_disabled =
+ (number & ICE_NVM_MGMT_UPDATE_DISABLED) ?
+ true : false;
+ ice_debug(hw, ICE_DBG_INIT, "%s: update_disabled = %d\n", prefix,
+ caps->update_disabled);
+ caps->nvm_unified_update =
+ (number & ICE_NVM_MGMT_UNIFIED_UPD_SUPPORT) ?
+ true : false;
+ ice_debug(hw, ICE_DBG_INIT, "%s: nvm_unified_update = %d\n", prefix,
+ caps->nvm_unified_update);
+ break;
case ICE_AQC_CAPS_MAX_MTU:
caps->max_mtu = number;
ice_debug(hw, ICE_DBG_INIT, "%s: max_mtu = %d\n",
prefix, caps->max_mtu);
break;
+ case ICE_AQC_CAPS_PCIE_RESET_AVOIDANCE:
+ caps->pcie_reset_avoidance = (number > 0);
+ ice_debug(hw, ICE_DBG_INIT,
+ "%s: pcie_reset_avoidance = %d\n", prefix,
+ caps->pcie_reset_avoidance);
+ break;
+ case ICE_AQC_CAPS_POST_UPDATE_RESET_RESTRICT:
+ caps->reset_restrict_support = (number == 1);
+ ice_debug(hw, ICE_DBG_INIT,
+ "%s: reset_restrict_support = %d\n", prefix,
+ caps->reset_restrict_support);
+ break;
+ case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG0:
+ case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG1:
+ case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG2:
+ case ICE_AQC_CAPS_EXT_TOPO_DEV_IMG3:
+ {
+ u8 index = cap - ICE_AQC_CAPS_EXT_TOPO_DEV_IMG0;
+
+ caps->ext_topo_dev_img_ver_high[index] = number;
+ caps->ext_topo_dev_img_ver_low[index] = logical_id;
+ caps->ext_topo_dev_img_part_num[index] =
+ (phys_id & ICE_EXT_TOPO_DEV_IMG_PART_NUM_M) >>
+ ICE_EXT_TOPO_DEV_IMG_PART_NUM_S;
+ caps->ext_topo_dev_img_load_en[index] =
+ (phys_id & ICE_EXT_TOPO_DEV_IMG_LOAD_EN) != 0;
+ caps->ext_topo_dev_img_prog_en[index] =
+ (phys_id & ICE_EXT_TOPO_DEV_IMG_PROG_EN) != 0;
+ ice_debug(hw, ICE_DBG_INIT,
+ "%s: ext_topo_dev_img_ver_high[%d] = %d\n",
+ prefix, index,
+ caps->ext_topo_dev_img_ver_high[index]);
+ ice_debug(hw, ICE_DBG_INIT,
+ "%s: ext_topo_dev_img_ver_low[%d] = %d\n",
+ prefix, index,
+ caps->ext_topo_dev_img_ver_low[index]);
+ ice_debug(hw, ICE_DBG_INIT,
+ "%s: ext_topo_dev_img_part_num[%d] = %d\n",
+ prefix, index,
+ caps->ext_topo_dev_img_part_num[index]);
+ ice_debug(hw, ICE_DBG_INIT,
+ "%s: ext_topo_dev_img_load_en[%d] = %d\n",
+ prefix, index,
+ caps->ext_topo_dev_img_load_en[index]);
+ ice_debug(hw, ICE_DBG_INIT,
+ "%s: ext_topo_dev_img_prog_en[%d] = %d\n",
+ prefix, index,
+ caps->ext_topo_dev_img_prog_en[index]);
+ break;
+ }
default:
/* Not one of the recognized common capabilities */
found = false;
}
/**
- * ice_parse_fdir_func_caps - Parse ICE_AQC_CAPS_FD function caps
+ * ice_parse_1588_func_caps - Parse ICE_AQC_CAPS_1588 function caps
* @hw: pointer to the HW struct
* @func_p: pointer to function capabilities structure
* @cap: pointer to the capability element to parse
*
- * Extract function capabilities for ICE_AQC_CAPS_FD.
+ * Extract function capabilities for ICE_AQC_CAPS_1588.
*/
static void
-ice_parse_fdir_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
+ice_parse_1588_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p,
struct ice_aqc_list_caps_elem *cap)
+{
+ struct ice_ts_func_info *info = &func_p->ts_func_info;
+ u32 number = LE32_TO_CPU(cap->number);
+
+ info->ena = ((number & ICE_TS_FUNC_ENA_M) != 0);
+ func_p->common_cap.ieee_1588 = info->ena;
+
+ info->src_tmr_owned = ((number & ICE_TS_SRC_TMR_OWND_M) != 0);
+ info->tmr_ena = ((number & ICE_TS_TMR_ENA_M) != 0);
+ info->tmr_index_owned = ((number & ICE_TS_TMR_IDX_OWND_M) != 0);
+ info->tmr_index_assoc = ((number & ICE_TS_TMR_IDX_ASSOC_M) != 0);
+
+ info->clk_freq = (number & ICE_TS_CLK_FREQ_M) >> ICE_TS_CLK_FREQ_S;
+ info->clk_src = ((number & ICE_TS_CLK_SRC_M) != 0);
+
+ if (info->clk_freq < NUM_ICE_TIME_REF_FREQ) {
+ info->time_ref = (enum ice_time_ref_freq)info->clk_freq;
+ } else {
+ /* Unknown clock frequency, so assume a (probably incorrect)
+ * default to avoid out-of-bounds look ups of frequency
+ * related information.
+ */
+ ice_debug(hw, ICE_DBG_INIT, "1588 func caps: unknown clock frequency %u\n",
+ info->clk_freq);
+ info->time_ref = ICE_TIME_REF_FREQ_25_000;
+ }
+
+ ice_debug(hw, ICE_DBG_INIT, "func caps: ieee_1588 = %u\n",
+ func_p->common_cap.ieee_1588);
+ ice_debug(hw, ICE_DBG_INIT, "func caps: src_tmr_owned = %u\n",
+ info->src_tmr_owned);
+ ice_debug(hw, ICE_DBG_INIT, "func caps: tmr_ena = %u\n",
+ info->tmr_ena);
+ ice_debug(hw, ICE_DBG_INIT, "func caps: tmr_index_owned = %u\n",
+ info->tmr_index_owned);
+ ice_debug(hw, ICE_DBG_INIT, "func caps: tmr_index_assoc = %u\n",
+ info->tmr_index_assoc);
+ ice_debug(hw, ICE_DBG_INIT, "func caps: clk_freq = %u\n",
+ info->clk_freq);
+ ice_debug(hw, ICE_DBG_INIT, "func caps: clk_src = %u\n",
+ info->clk_src);
+}
+
+/**
+ * ice_parse_fdir_func_caps - Parse ICE_AQC_CAPS_FD function caps
+ * @hw: pointer to the HW struct
+ * @func_p: pointer to function capabilities structure
+ *
+ * Extract function capabilities for ICE_AQC_CAPS_FD.
+ */
+static void
+ice_parse_fdir_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p)
{
u32 reg_val, val;
case ICE_AQC_CAPS_VSI:
ice_parse_vsi_func_caps(hw, func_p, &cap_resp[i]);
break;
+ case ICE_AQC_CAPS_1588:
+ ice_parse_1588_func_caps(hw, func_p, &cap_resp[i]);
+ break;
case ICE_AQC_CAPS_FD:
- ice_parse_fdir_func_caps(hw, func_p, &cap_resp[i]);
+ ice_parse_fdir_func_caps(hw, func_p);
break;
default:
/* Don't list common capabilities as unknown */
dev_p->num_vsi_allocd_to_host);
}
+/**
+ * ice_parse_1588_dev_caps - Parse ICE_AQC_CAPS_1588 device caps
+ * @hw: pointer to the HW struct
+ * @dev_p: pointer to device capabilities structure
+ * @cap: capability element to parse
+ *
+ * Parse ICE_AQC_CAPS_1588 for device capabilities.
+ */
+static void
+ice_parse_1588_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
+ struct ice_aqc_list_caps_elem *cap)
+{
+ struct ice_ts_dev_info *info = &dev_p->ts_dev_info;
+ u32 logical_id = LE32_TO_CPU(cap->logical_id);
+ u32 phys_id = LE32_TO_CPU(cap->phys_id);
+ u32 number = LE32_TO_CPU(cap->number);
+
+ info->ena = ((number & ICE_TS_DEV_ENA_M) != 0);
+ dev_p->common_cap.ieee_1588 = info->ena;
+
+ info->tmr0_owner = number & ICE_TS_TMR0_OWNR_M;
+ info->tmr0_owned = ((number & ICE_TS_TMR0_OWND_M) != 0);
+ info->tmr0_ena = ((number & ICE_TS_TMR0_ENA_M) != 0);
+
+ info->tmr1_owner = (number & ICE_TS_TMR1_OWNR_M) >> ICE_TS_TMR1_OWNR_S;
+ info->tmr1_owned = ((number & ICE_TS_TMR1_OWND_M) != 0);
+ info->tmr1_ena = ((number & ICE_TS_TMR1_ENA_M) != 0);
+
+ info->ena_ports = logical_id;
+ info->tmr_own_map = phys_id;
+
+ ice_debug(hw, ICE_DBG_INIT, "dev caps: ieee_1588 = %u\n",
+ dev_p->common_cap.ieee_1588);
+ ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr0_owner = %u\n",
+ info->tmr0_owner);
+ ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr0_owned = %u\n",
+ info->tmr0_owned);
+ ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr0_ena = %u\n",
+ info->tmr0_ena);
+ ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr1_owner = %u\n",
+ info->tmr1_owner);
+ ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr1_owned = %u\n",
+ info->tmr1_owned);
+ ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr1_ena = %u\n",
+ info->tmr1_ena);
+ ice_debug(hw, ICE_DBG_INIT, "dev caps: ieee_1588 ena_ports = %u\n",
+ info->ena_ports);
+ ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr_own_map = %u\n",
+ info->tmr_own_map);
+}
+
/**
* ice_parse_fdir_dev_caps - Parse ICE_AQC_CAPS_FD device caps
* @hw: pointer to the HW struct
* @cap_count: the number of capabilities
*
* Helper device to parse device (0x000B) capabilities list. For
- * capabilities shared between device and device, this relies on
+ * capabilities shared between device and function, this relies on
* ice_parse_common_caps.
*
* Loop through the list of provided capabilities and extract the relevant
case ICE_AQC_CAPS_VSI:
ice_parse_vsi_dev_caps(hw, dev_p, &cap_resp[i]);
break;
+ case ICE_AQC_CAPS_1588:
+ ice_parse_1588_dev_caps(hw, dev_p, &cap_resp[i]);
+ break;
case ICE_AQC_CAPS_FD:
ice_parse_fdir_dev_caps(hw, dev_p, &cap_resp[i]);
break;
{
struct ice_hw_func_caps *func_caps = &hw->func_caps;
struct ice_hw_dev_caps *dev_caps = &hw->dev_caps;
- u32 valid_func, rxq_first_id, txq_first_id;
- u32 msix_vector_first_id, max_mtu;
+ struct ice_hw_common_caps cached_caps;
u32 num_funcs;
/* cache some func_caps values that should be restored after memset */
- valid_func = func_caps->common_cap.valid_functions;
- txq_first_id = func_caps->common_cap.txq_first_id;
- rxq_first_id = func_caps->common_cap.rxq_first_id;
- msix_vector_first_id = func_caps->common_cap.msix_vector_first_id;
- max_mtu = func_caps->common_cap.max_mtu;
+ cached_caps = func_caps->common_cap;
/* unset func capabilities */
memset(func_caps, 0, sizeof(*func_caps));
+#define ICE_RESTORE_FUNC_CAP(name) \
+ func_caps->common_cap.name = cached_caps.name
+
/* restore cached values */
- func_caps->common_cap.valid_functions = valid_func;
- func_caps->common_cap.txq_first_id = txq_first_id;
- func_caps->common_cap.rxq_first_id = rxq_first_id;
- func_caps->common_cap.msix_vector_first_id = msix_vector_first_id;
- func_caps->common_cap.max_mtu = max_mtu;
+ ICE_RESTORE_FUNC_CAP(valid_functions);
+ ICE_RESTORE_FUNC_CAP(txq_first_id);
+ ICE_RESTORE_FUNC_CAP(rxq_first_id);
+ ICE_RESTORE_FUNC_CAP(msix_vector_first_id);
+ ICE_RESTORE_FUNC_CAP(max_mtu);
+ ICE_RESTORE_FUNC_CAP(nvm_unified_update);
/* one Tx and one Rx queue in safe mode */
func_caps->common_cap.num_rxq = 1;
func_caps->guar_num_vsi = 1;
/* cache some dev_caps values that should be restored after memset */
- valid_func = dev_caps->common_cap.valid_functions;
- txq_first_id = dev_caps->common_cap.txq_first_id;
- rxq_first_id = dev_caps->common_cap.rxq_first_id;
- msix_vector_first_id = dev_caps->common_cap.msix_vector_first_id;
- max_mtu = dev_caps->common_cap.max_mtu;
+ cached_caps = dev_caps->common_cap;
num_funcs = dev_caps->num_funcs;
/* unset dev capabilities */
memset(dev_caps, 0, sizeof(*dev_caps));
+#define ICE_RESTORE_DEV_CAP(name) \
+ dev_caps->common_cap.name = cached_caps.name
+
/* restore cached values */
- dev_caps->common_cap.valid_functions = valid_func;
- dev_caps->common_cap.txq_first_id = txq_first_id;
- dev_caps->common_cap.rxq_first_id = rxq_first_id;
- dev_caps->common_cap.msix_vector_first_id = msix_vector_first_id;
- dev_caps->common_cap.max_mtu = max_mtu;
+ ICE_RESTORE_DEV_CAP(valid_functions);
+ ICE_RESTORE_DEV_CAP(txq_first_id);
+ ICE_RESTORE_DEV_CAP(rxq_first_id);
+ ICE_RESTORE_DEV_CAP(msix_vector_first_id);
+ ICE_RESTORE_DEV_CAP(max_mtu);
+ ICE_RESTORE_DEV_CAP(nvm_unified_update);
dev_caps->num_funcs = num_funcs;
/* one Tx and one Rx queue per function in safe mode */
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_write);
cmd->flags = flags;
- ice_memcpy(cmd->mac_addr, mac_addr, ETH_ALEN, ICE_NONDMA_TO_DMA);
+ ice_memcpy(cmd->mac_addr, mac_addr, ETH_ALEN, ICE_NONDMA_TO_NONDMA);
return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
}
ice_aq_clear_pxe_mode(hw);
}
+/**
+ * ice_aq_set_port_params - set physical port parameters.
+ * @pi: pointer to the port info struct
+ * @bad_frame_vsi: defines the VSI to which bad frames are forwarded
+ * @save_bad_pac: if set packets with errors are forwarded to the bad frames VSI
+ * @pad_short_pac: if set transmit packets smaller than 60 bytes are padded
+ * @double_vlan: if set double VLAN is enabled
+ * @cd: pointer to command details structure or NULL
+ *
+ * Set Physical port parameters (0x0203)
+ */
+enum ice_status
+ice_aq_set_port_params(struct ice_port_info *pi, u16 bad_frame_vsi,
+ bool save_bad_pac, bool pad_short_pac, bool double_vlan,
+ struct ice_sq_cd *cd)
+
+{
+ struct ice_aqc_set_port_params *cmd;
+ struct ice_hw *hw = pi->hw;
+ struct ice_aq_desc desc;
+ u16 cmd_flags = 0;
+
+ cmd = &desc.params.set_port_params;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_params);
+ cmd->bad_frame_vsi = CPU_TO_LE16(bad_frame_vsi);
+ if (save_bad_pac)
+ cmd_flags |= ICE_AQC_SET_P_PARAMS_SAVE_BAD_PACKETS;
+ if (pad_short_pac)
+ cmd_flags |= ICE_AQC_SET_P_PARAMS_PAD_SHORT_PACKETS;
+ if (double_vlan)
+ cmd_flags |= ICE_AQC_SET_P_PARAMS_DOUBLE_VLAN_ENA;
+ cmd->cmd_flags = CPU_TO_LE16(cmd_flags);
+
+ return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+}
+
/**
* ice_get_link_speed_based_on_phy_type - returns link speed
* @phy_type_low: lower part of phy_type
if (!pcaps)
return ICE_ERR_NO_MEMORY;
- status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP,
+ status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP_MEDIA,
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);
}
/* 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,
+ status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP_MEDIA,
pcaps, NULL);
if (status) {
ice_free(pi->hw, pcaps);
return ICE_ERR_NO_MEMORY;
/* Get the current PHY config */
- status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps,
- NULL);
+ status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_ACTIVE_CFG,
+ pcaps, NULL);
+
if (status) {
*aq_failures = ICE_SET_FC_AQ_FAIL_GET;
goto out;
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;
- }
}
/**
if (!pcaps)
return ICE_ERR_NO_MEMORY;
- status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, pcaps,
- NULL);
+ status = ice_aq_get_phy_caps(pi, false,
+ (ice_fw_supports_report_dflt_cfg(hw) ?
+ ICE_AQC_REPORT_DFLT_CFG :
+ ICE_AQC_REPORT_TOPO_CAP_MEDIA), pcaps, NULL);
+
if (status)
goto out;
break;
}
- if (fec == ICE_FEC_AUTO && ice_fw_supports_link_override(pi->hw)) {
+ if (fec == ICE_FEC_AUTO && ice_fw_supports_link_override(pi->hw) &&
+ !ice_fw_supports_report_dflt_cfg(pi->hw)) {
struct ice_link_default_override_tlv tlv;
if (ice_get_link_default_override(&tlv, pi))
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_sff_eeprom);
cmd = &desc.params.read_write_sff_param;
- desc.flags = CPU_TO_LE16(ICE_AQ_FLAG_RD | ICE_AQ_FLAG_BUF);
+ desc.flags = CPU_TO_LE16(ICE_AQ_FLAG_RD);
cmd->lport_num = (u8)(lport & 0xff);
cmd->lport_num_valid = (u8)((lport >> 8) & 0x01);
cmd->i2c_bus_addr = CPU_TO_LE16(((bus_addr >> 1) &
return status;
}
+/**
+ * ice_aq_prog_topo_dev_nvm
+ * @hw: pointer to the hardware structure
+ * @topo_params: pointer to structure storing topology parameters for a device
+ * @cd: pointer to command details structure or NULL
+ *
+ * Program Topology Device NVM (0x06F2)
+ *
+ */
+enum ice_status
+ice_aq_prog_topo_dev_nvm(struct ice_hw *hw,
+ struct ice_aqc_link_topo_params *topo_params,
+ struct ice_sq_cd *cd)
+{
+ struct ice_aqc_prog_topo_dev_nvm *cmd;
+ struct ice_aq_desc desc;
+
+ cmd = &desc.params.prog_topo_dev_nvm;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_prog_topo_dev_nvm);
+
+ ice_memcpy(&cmd->topo_params, topo_params, sizeof(*topo_params),
+ ICE_NONDMA_TO_NONDMA);
+
+ return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+}
+
+/**
+ * ice_aq_read_topo_dev_nvm
+ * @hw: pointer to the hardware structure
+ * @topo_params: pointer to structure storing topology parameters for a device
+ * @start_address: byte offset in the topology device NVM
+ * @data: pointer to data buffer
+ * @data_size: number of bytes to be read from the topology device NVM
+ * @cd: pointer to command details structure or NULL
+ * Read Topology Device NVM (0x06F3)
+ *
+ */
+enum ice_status
+ice_aq_read_topo_dev_nvm(struct ice_hw *hw,
+ struct ice_aqc_link_topo_params *topo_params,
+ u32 start_address, u8 *data, u8 data_size,
+ struct ice_sq_cd *cd)
+{
+ struct ice_aqc_read_topo_dev_nvm *cmd;
+ struct ice_aq_desc desc;
+ enum ice_status status;
+
+ if (!data || data_size == 0 ||
+ data_size > ICE_AQC_READ_TOPO_DEV_NVM_DATA_READ_SIZE)
+ return ICE_ERR_PARAM;
+
+ cmd = &desc.params.read_topo_dev_nvm;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_topo_dev_nvm);
+
+ desc.datalen = data_size;
+ ice_memcpy(&cmd->topo_params, topo_params, sizeof(*topo_params),
+ ICE_NONDMA_TO_NONDMA);
+ cmd->start_address = CPU_TO_LE32(start_address);
+
+ status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+ if (status)
+ return status;
+
+ ice_memcpy(data, cmd->data_read, data_size, ICE_NONDMA_TO_NONDMA);
+
+ return ICE_SUCCESS;
+}
+
/**
* __ice_aq_get_set_rss_lut
* @hw: pointer to the hardware structure
- * @vsi_id: VSI FW index
- * @lut_type: LUT table type
- * @lut: pointer to the LUT buffer provided by the caller
- * @lut_size: size of the LUT buffer
- * @glob_lut_idx: global LUT index
+ * @params: RSS LUT parameters
* @set: set true to set the table, false to get the table
*
* Internal function to get (0x0B05) or set (0x0B03) RSS look up table
*/
static enum ice_status
-__ice_aq_get_set_rss_lut(struct ice_hw *hw, u16 vsi_id, u8 lut_type, u8 *lut,
- u16 lut_size, u8 glob_lut_idx, bool set)
+__ice_aq_get_set_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *params, bool set)
{
+ u16 flags = 0, vsi_id, lut_type, lut_size, glob_lut_idx, vsi_handle;
struct ice_aqc_get_set_rss_lut *cmd_resp;
struct ice_aq_desc desc;
enum ice_status status;
- u16 flags = 0;
+ u8 *lut;
+
+ if (!params)
+ return ICE_ERR_PARAM;
+
+ vsi_handle = params->vsi_handle;
+ lut = params->lut;
+
+ if (!ice_is_vsi_valid(hw, vsi_handle) || !lut)
+ return ICE_ERR_PARAM;
+
+ lut_size = params->lut_size;
+ lut_type = params->lut_type;
+ glob_lut_idx = params->global_lut_id;
+ vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
cmd_resp = &desc.params.get_set_rss_lut;
/**
* ice_aq_get_rss_lut
* @hw: pointer to the hardware structure
- * @vsi_handle: software VSI handle
- * @lut_type: LUT table type
- * @lut: pointer to the LUT buffer provided by the caller
- * @lut_size: size of the LUT buffer
+ * @get_params: RSS LUT parameters used to specify which RSS LUT to get
*
* get the RSS lookup table, PF or VSI type
*/
enum ice_status
-ice_aq_get_rss_lut(struct ice_hw *hw, u16 vsi_handle, u8 lut_type,
- u8 *lut, u16 lut_size)
+ice_aq_get_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *get_params)
{
- if (!ice_is_vsi_valid(hw, vsi_handle) || !lut)
- return ICE_ERR_PARAM;
-
- return __ice_aq_get_set_rss_lut(hw, ice_get_hw_vsi_num(hw, vsi_handle),
- lut_type, lut, lut_size, 0, false);
+ return __ice_aq_get_set_rss_lut(hw, get_params, false);
}
/**
* ice_aq_set_rss_lut
* @hw: pointer to the hardware structure
- * @vsi_handle: software VSI handle
- * @lut_type: LUT table type
- * @lut: pointer to the LUT buffer provided by the caller
- * @lut_size: size of the LUT buffer
+ * @set_params: RSS LUT parameters used to specify how to set the RSS LUT
*
* set the RSS lookup table, PF or VSI type
*/
enum ice_status
-ice_aq_set_rss_lut(struct ice_hw *hw, u16 vsi_handle, u8 lut_type,
- u8 *lut, u16 lut_size)
+ice_aq_set_rss_lut(struct ice_hw *hw, struct ice_aq_get_set_rss_lut_params *set_params)
{
- if (!ice_is_vsi_valid(hw, vsi_handle) || !lut)
- return ICE_ERR_PARAM;
-
- return __ice_aq_get_set_rss_lut(hw, ice_get_hw_vsi_num(hw, vsi_handle),
- lut_type, lut, lut_size, 0, true);
+ return __ice_aq_get_set_rss_lut(hw, set_params, true);
}
/**
return ICE_SUCCESS;
}
+/**
+ * ice_aq_get_internal_data
+ * @hw: pointer to the hardware structure
+ * @cluster_id: specific cluster to dump
+ * @table_id: table ID within cluster
+ * @start: index of line in the block to read
+ * @buf: dump buffer
+ * @buf_size: dump buffer size
+ * @ret_buf_size: return buffer size (returned by FW)
+ * @ret_next_table: next block to read (returned by FW)
+ * @ret_next_index: next index to read (returned by FW)
+ * @cd: pointer to command details structure
+ *
+ * Get internal FW/HW data (0xFF08) for debug purposes.
+ */
+enum ice_status
+ice_aq_get_internal_data(struct ice_hw *hw, u8 cluster_id, u16 table_id,
+ u32 start, void *buf, u16 buf_size, u16 *ret_buf_size,
+ u16 *ret_next_table, u32 *ret_next_index,
+ struct ice_sq_cd *cd)
+{
+ struct ice_aqc_debug_dump_internals *cmd;
+ struct ice_aq_desc desc;
+ enum ice_status status;
+
+ cmd = &desc.params.debug_dump;
+
+ if (buf_size == 0 || !buf)
+ return ICE_ERR_PARAM;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_debug_dump_internals);
+
+ cmd->cluster_id = cluster_id;
+ cmd->table_id = CPU_TO_LE16(table_id);
+ cmd->idx = CPU_TO_LE32(start);
+
+ status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
+
+ if (!status) {
+ if (ret_buf_size)
+ *ret_buf_size = LE16_TO_CPU(desc.datalen);
+ if (ret_next_table)
+ *ret_next_table = LE16_TO_CPU(cmd->table_id);
+ if (ret_next_index)
+ *ret_next_index = LE32_TO_CPU(cmd->idx);
+ }
+
+ return status;
+}
+
/**
* ice_read_byte - read context byte into struct
* @src_ctx: the context structure to read from
*
* Initializes required config data for VSI, FD, ACL, and RSS before replay.
*/
-static enum ice_status
+enum ice_status
ice_replay_pre_init(struct ice_hw *hw, struct ice_switch_info *sw)
{
enum ice_status status;
return ICE_FW_MODE_NORMAL;
}
+/**
+ * ice_aq_read_i2c
+ * @hw: pointer to the hw struct
+ * @topo_addr: topology address for a device to communicate with
+ * @bus_addr: 7-bit I2C bus address
+ * @addr: I2C memory address (I2C offset) with up to 16 bits
+ * @params: I2C parameters: bit [7] - Repeated start, bits [6:5] data offset size,
+ * bit [4] - I2C address type, bits [3:0] - data size to read (0-16 bytes)
+ * @data: pointer to data (0 to 16 bytes) to be read from the I2C device
+ * @cd: pointer to command details structure or NULL
+ *
+ * Read I2C (0x06E2)
+ */
+enum ice_status
+ice_aq_read_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
+ u16 bus_addr, __le16 addr, u8 params, u8 *data,
+ struct ice_sq_cd *cd)
+{
+ struct ice_aq_desc desc = { 0 };
+ struct ice_aqc_i2c *cmd;
+ enum ice_status status;
+ u8 data_size;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_read_i2c);
+ cmd = &desc.params.read_write_i2c;
+
+ if (!data)
+ return ICE_ERR_PARAM;
+
+ data_size = (params & ICE_AQC_I2C_DATA_SIZE_M) >> ICE_AQC_I2C_DATA_SIZE_S;
+
+ cmd->i2c_bus_addr = CPU_TO_LE16(bus_addr);
+ cmd->topo_addr = topo_addr;
+ cmd->i2c_params = params;
+ cmd->i2c_addr = addr;
+
+ status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+ if (!status) {
+ struct ice_aqc_read_i2c_resp *resp;
+ u8 i;
+
+ resp = &desc.params.read_i2c_resp;
+ for (i = 0; i < data_size; i++) {
+ *data = resp->i2c_data[i];
+ data++;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * ice_aq_write_i2c
+ * @hw: pointer to the hw struct
+ * @topo_addr: topology address for a device to communicate with
+ * @bus_addr: 7-bit I2C bus address
+ * @addr: I2C memory address (I2C offset) with up to 16 bits
+ * @params: I2C parameters: bit [4] - I2C address type, bits [3:0] - data size to write (0-7 bytes)
+ * @data: pointer to data (0 to 4 bytes) to be written to the I2C device
+ * @cd: pointer to command details structure or NULL
+ *
+ * Write I2C (0x06E3)
+ */
+enum ice_status
+ice_aq_write_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr,
+ u16 bus_addr, __le16 addr, u8 params, u8 *data,
+ struct ice_sq_cd *cd)
+{
+ struct ice_aq_desc desc = { 0 };
+ struct ice_aqc_i2c *cmd;
+ u8 i, data_size;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_write_i2c);
+ cmd = &desc.params.read_write_i2c;
+
+ data_size = (params & ICE_AQC_I2C_DATA_SIZE_M) >> ICE_AQC_I2C_DATA_SIZE_S;
+
+ /* data_size limited to 4 */
+ if (data_size > 4)
+ return ICE_ERR_PARAM;
+
+ cmd->i2c_bus_addr = CPU_TO_LE16(bus_addr);
+ cmd->topo_addr = topo_addr;
+ cmd->i2c_params = params;
+ cmd->i2c_addr = addr;
+
+ for (i = 0; i < data_size; i++) {
+ cmd->i2c_data[i] = *data;
+ data++;
+ }
+
+ return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+}
+
+/**
+ * ice_aq_set_gpio
+ * @hw: pointer to the hw struct
+ * @gpio_ctrl_handle: GPIO controller node handle
+ * @pin_idx: IO Number of the GPIO that needs to be set
+ * @value: SW provide IO value to set in the LSB
+ * @cd: pointer to command details structure or NULL
+ *
+ * Sends 0x06EC AQ command to set the GPIO pin state that's part of the topology
+ */
+enum ice_status
+ice_aq_set_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx, bool value,
+ struct ice_sq_cd *cd)
+{
+ struct ice_aqc_gpio *cmd;
+ struct ice_aq_desc desc;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_gpio);
+ cmd = &desc.params.read_write_gpio;
+ cmd->gpio_ctrl_handle = gpio_ctrl_handle;
+ cmd->gpio_num = pin_idx;
+ cmd->gpio_val = value ? 1 : 0;
+
+ return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+}
+
+/**
+ * ice_aq_get_gpio
+ * @hw: pointer to the hw struct
+ * @gpio_ctrl_handle: GPIO controller node handle
+ * @pin_idx: IO Number of the GPIO that needs to be set
+ * @value: IO value read
+ * @cd: pointer to command details structure or NULL
+ *
+ * Sends 0x06ED AQ command to get the value of a GPIO signal which is part of
+ * the topology
+ */
+enum ice_status
+ice_aq_get_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx,
+ bool *value, struct ice_sq_cd *cd)
+{
+ struct ice_aqc_gpio *cmd;
+ struct ice_aq_desc desc;
+ enum ice_status status;
+
+ ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_gpio);
+ cmd = &desc.params.read_write_gpio;
+ cmd->gpio_ctrl_handle = gpio_ctrl_handle;
+ cmd->gpio_num = pin_idx;
+
+ status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+ if (status)
+ return status;
+
+ *value = !!cmd->gpio_val;
+ return ICE_SUCCESS;
+}
+
/**
* ice_fw_supports_link_override
* @hw: pointer to the hardware structure
*/
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;
}
/**
- * ice_fw_supports_lldp_fltr - check NVM version supports lldp_fltr_ctrl
+ * ice_fw_supports_lldp_fltr_ctrl - check NVM version supports lldp_fltr_ctrl
* @hw: pointer to HW struct
*/
bool ice_fw_supports_lldp_fltr_ctrl(struct ice_hw *hw)
return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
}
+
+/**
+ * ice_fw_supports_report_dflt_cfg
+ * @hw: pointer to the hardware structure
+ *
+ * Checks if the firmware supports report default configuration
+ */
+bool ice_fw_supports_report_dflt_cfg(struct ice_hw *hw)
+{
+ if (hw->api_maj_ver == ICE_FW_API_REPORT_DFLT_CFG_MAJ) {
+ if (hw->api_min_ver > ICE_FW_API_REPORT_DFLT_CFG_MIN)
+ return true;
+ if (hw->api_min_ver == ICE_FW_API_REPORT_DFLT_CFG_MIN &&
+ hw->api_patch >= ICE_FW_API_REPORT_DFLT_CFG_PATCH)
+ return true;
+ } else if (hw->api_maj_ver > ICE_FW_API_REPORT_DFLT_CFG_MAJ) {
+ return true;
+ }
+ return false;
+}