/* 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)
nvm_str, hw->fw_maj_ver, hw->fw_min_ver);
}
+/**
+ * ice_set_umac_shared
+ * @hw: pointer to the hw struct
+ *
+ * Set boolean flag to allow unicast MAC sharing
+ */
+void ice_set_umac_shared(struct ice_hw *hw)
+{
+ hw->umac_shared = true;
+}
+
/**
* ice_init_hw - main hardware initialization routine
* @hw: pointer to the hardware structure
/* 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, "Get PHY capabilities failed, continuing anyway\n");
+ 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)
goto err_unroll_fltr_mgmt_struct;
ice_init_lock(&hw->tnl_lock);
- ice_init_vlan_mode_ops(hw);
-
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);
}
/**
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;
func_p->guar_num_vsi);
}
+/**
+ * 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_1588.
+ */
+static void
+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
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);
break;
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
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;
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);
}
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)
/* 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;
/**
* 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
+ * @caps: PHY ability structure to copy data from
* @cfg: PHY configuration structure to copy data to
*
* Helper function to copy AQC PHY get ability data to PHY set configuration
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))
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
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
}
/**
- * 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;
+}