@@ -655,6 +655,8 @@ struct ice_pf {
struct ice_agg_node vf_agg_node[ICE_MAX_VF_AGG_NODES];
struct ice_dplls dplls;
struct device *hwmon_dev;
+
+ int split_cnt;
};
extern struct workqueue_struct *ice_lag_wq;
@@ -1497,6 +1497,10 @@ struct ice_aqc_link_topo_addr {
struct ice_aqc_get_link_topo {
struct ice_aqc_link_topo_addr addr;
u8 node_part_num;
+#define ICE_AQC_GET_LINK_TOPO_NODE_NR_SFP_PLUS 0x11
+#define ICE_AQC_GET_LINK_TOPO_NODE_NR_SFP28 0x12
+#define ICE_AQC_GET_LINK_TOPO_NODE_NR_QSFP_PLUS 0x13
+#define ICE_AQC_GET_LINK_TOPO_NODE_NR_QSFP28 0x14
#define ICE_AQC_GET_LINK_TOPO_NODE_NR_PCA9575 0x21
#define ICE_AQC_GET_LINK_TOPO_NODE_NR_ZL30632_80032 0x24
#define ICE_AQC_GET_LINK_TOPO_NODE_NR_SI5383_5384 0x25
@@ -1664,6 +1668,23 @@ struct ice_aqc_nvm {
__le32 addr_low;
};
+#define ICE_AQC_NVM_CMPO_MOD_ID 0x153
+#define ICE_AQC_NVM_EMP_SETTINGS_MOD_ID 0x0F
+#define ICE_AQC_NVM_MAX_PWR_LIMIT_OFFSET 0x1A
+#define ICE_AQC_NVM_DFLT_MAX_PWR_MASK GENMASK(7, 0)
+#define ICE_AQC_NVM_BOARD_MAX_PWR_MASK GENMASK(15, 8)
+
+#define ICE_NUM_OF_CAGES 8
+
+#define ICE_AQC_NVM_CMPO_ENABLE BIT(8)
+#define ICE_AQC_NVM_CMPO_POWER_MASK GENMASK(7, 0)
+
+/* Cage Max Power override NVM module */
+struct ice_aqc_nvm_cmpo {
+ __le16 length;
+ __le16 cages_cfg[ICE_NUM_OF_CAGES];
+};
+
#define ICE_AQC_NVM_START_POINT 0
/* NVM Checksum Command (direct, 0x0706) */
@@ -571,6 +571,23 @@ static bool ice_is_media_cage_present(struct ice_port_info *pi)
NULL);
}
+int ice_get_port_cage_node(struct ice_hw *hw, u8 index,
+ u16 *node_handle, u8 *node_part_number)
+{
+ struct ice_aqc_get_link_topo cmd = {};
+
+ cmd.addr.topo_params.node_type_ctx =
+ FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_TYPE_M,
+ ICE_AQC_LINK_TOPO_NODE_TYPE_CAGE);
+ cmd.addr.topo_params.node_type_ctx |=
+ FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_CTX_M,
+ ICE_AQC_LINK_TOPO_NODE_CTX_GLOBAL);
+ cmd.addr.topo_params.index = index;
+
+ return ice_aq_get_netlist_node(hw, &cmd, node_part_number,
+ node_handle);
+}
+
/**
* ice_get_media_type - Gets media type
* @pi: port information structure
@@ -5723,6 +5740,29 @@ static bool ice_is_fw_api_min_ver(struct ice_hw *hw, u8 maj, u8 min, u8 patch)
return false;
}
+/**
+ * ice_is_fw_min_ver
+ * @hw: pointer to the hardware structure
+ * @maj: major version
+ * @min: minor version
+ * @patch: patch version
+ *
+ * Checks if the firmware is minimum version
+ */
+static bool ice_is_fw_min_ver(struct ice_hw *hw, u8 maj, u8 min, u8 patch)
+{
+ if (hw->fw_maj_ver > maj)
+ return true;
+ if (hw->fw_maj_ver == maj) {
+ if (hw->fw_min_ver > min)
+ return true;
+ if (hw->fw_min_ver == min && hw->fw_patch >= patch)
+ return true;
+ }
+
+ return false;
+}
+
/**
* ice_fw_supports_link_override
* @hw: pointer to the hardware structure
@@ -5736,6 +5776,12 @@ bool ice_fw_supports_link_override(struct ice_hw *hw)
ICE_FW_API_LINK_OVERRIDE_PATCH);
}
+bool ice_fw_supports_cmpo(struct ice_hw *hw)
+{
+ return ice_is_fw_min_ver(hw, ICE_FW_CMPO_MAJ, ICE_FW_CMPO_MIN,
+ ICE_FW_CMPO_PATCH);
+}
+
/**
* ice_get_link_default_override
* @ldo: pointer to the link default override struct
@@ -96,6 +96,8 @@ bool ice_is_phy_rclk_in_netlist(struct ice_hw *hw);
bool ice_is_clock_mux_in_netlist(struct ice_hw *hw);
bool ice_is_cgu_in_netlist(struct ice_hw *hw);
bool ice_is_gps_in_netlist(struct ice_hw *hw);
+int ice_get_port_cage_node(struct ice_hw *hw, u8 index,
+ u16 *node_handle, u8 *node_part_number);
int
ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd,
u8 *node_part_number, u16 *node_handle);
@@ -117,6 +119,7 @@ int
ice_aq_set_phy_cfg(struct ice_hw *hw, struct ice_port_info *pi,
struct ice_aqc_set_phy_cfg_data *cfg, struct ice_sq_cd *cd);
bool ice_fw_supports_link_override(struct ice_hw *hw);
+bool ice_fw_supports_cmpo(struct ice_hw *hw);
int
ice_get_link_default_override(struct ice_link_default_override_tlv *ldo,
struct ice_port_info *pi);
@@ -1604,6 +1604,14 @@ ice_devlink_set_port_split_options(struct ice_pf *pf,
return;
}
+ pf->split_cnt = options[active_idx].pmd;
+
+ /* As FW supports only port split options for whole device,
+ * set port split options only for first PF.
+ */
+ if (pf->hw.pf_id != 0)
+ return;
+
/* find the biggest available port split count */
for (i = 0; i < option_count; i++)
attrs->lanes = max_t(int, attrs->lanes, options[i].pmd);
@@ -1648,11 +1656,7 @@ int ice_devlink_create_pf_port(struct ice_pf *pf)
attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
attrs.phys.port_number = pf->hw.bus.func;
- /* As FW supports only port split options for whole device,
- * set port split options only for first PF.
- */
- if (pf->hw.pf_id == 0)
- ice_devlink_set_port_split_options(pf, &attrs);
+ ice_devlink_set_port_split_options(pf, &attrs);
ice_devlink_set_switch_id(pf, &attrs.switch_id);
@@ -4297,6 +4297,465 @@ ice_get_module_eeprom(struct net_device *netdev,
return 0;
}
+/**
+ * ice_get_min_pwr_allowed - Get min power allowed
+ * @hw: pointer to the hardware structure
+ * @extack: extended ACK from the Netlink message
+ *
+ * Values are constant based on the cage type.
+ * Return value in mW.
+ */
+static int ice_get_min_pwr_allowed(struct ice_hw *hw,
+ struct netlink_ext_ack *extack)
+{
+ u8 node_part_number;
+ u16 node_handle;
+ int err;
+
+ err = ice_get_port_cage_node(hw, 0, &node_handle, &node_part_number);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack, "Failed to get cage node handle");
+ return err;
+ }
+
+ switch (node_part_number) {
+ case ICE_AQC_GET_LINK_TOPO_NODE_NR_SFP_PLUS:
+ case ICE_AQC_GET_LINK_TOPO_NODE_NR_SFP28:
+ return 1000;
+ case ICE_AQC_GET_LINK_TOPO_NODE_NR_QSFP_PLUS:
+ case ICE_AQC_GET_LINK_TOPO_NODE_NR_QSFP28:
+ return 1500;
+ default:
+ return -EINVAL;
+ }
+}
+
+/**
+ * ice_pwr_nvm_to_ethtool - Convert NVM values to ethtool
+ * @pwr: power from NVM
+ */
+static u32 ice_pwr_nvm_to_ethtool(u32 pwr)
+{
+ /* ethtool takes power values in mW */
+ pwr *= 1000;
+ /* 0.5 W resolution */
+ pwr /= 2;
+
+ return pwr;
+}
+
+/**
+ * ice_pwr_ethtool_to_nvm - Convert ethtool values to NVM
+ * @pwr: power from ethtool, in mW
+ */
+static u32 ice_pwr_ethtool_to_nvm(u32 pwr)
+{
+ /* 0.5 W resolution */
+ pwr *= 2;
+ /* ethtool takes power values in mW */
+ pwr /= 1000;
+
+ return pwr;
+}
+
+/**
+ * ice_get_num_of_cages - Get number of cages in the board
+ * @hw: pointer to the hardware structure
+ *
+ * We have as many cages as netlist nodes of cage type.
+ */
+static int ice_get_num_of_cages(struct ice_hw *hw)
+{
+ int i, err, cage_count = 0;
+ u8 node_part_number;
+ u16 node_handle;
+
+ for (i = 0; i < ICE_NUM_OF_CAGES; i++) {
+ err = ice_get_port_cage_node(hw, i, &node_handle,
+ &node_part_number);
+ if (!err && node_handle)
+ cage_count++;
+ }
+
+ return cage_count;
+}
+
+/**
+ * ice_get_board_max_pwr - Get max power allowed per board
+ * @hw: pointer to the hardware structure
+ *
+ * Board maximum power is stored in EMP settings NVM module
+ */
+static int ice_get_board_max_pwr(struct ice_hw *hw)
+{
+ u16 board_max_pwr;
+ __le16 data;
+ int err;
+
+ err = ice_acquire_nvm(hw, ICE_RES_READ);
+ if (err)
+ return err;
+
+ err = ice_aq_read_nvm(hw, ICE_AQC_NVM_EMP_SETTINGS_MOD_ID,
+ ICE_AQC_NVM_MAX_PWR_LIMIT_OFFSET,
+ sizeof(data), &data,
+ true, false, NULL);
+ if (err) {
+ ice_release_nvm(hw);
+ return err;
+ }
+
+ ice_release_nvm(hw);
+
+ board_max_pwr = __le16_to_cpu(data);
+ board_max_pwr = FIELD_GET(ICE_AQC_NVM_BOARD_MAX_PWR_MASK,
+ board_max_pwr);
+
+ return ice_pwr_nvm_to_ethtool(board_max_pwr);
+}
+
+/**
+ * ice_get_max_pwr_allowed - Get max power allowed per cage
+ * @hw: pointer to the hardware structure
+ * @min_pwr_allowed: min allowed power
+ * @cage_count: number of cages in the board
+ */
+static int ice_get_max_pwr_allowed(struct ice_hw *hw, u32 min_pwr_allowed,
+ int cage_count)
+{
+ int board_max_pwr;
+
+ board_max_pwr = ice_get_board_max_pwr(hw);
+ if (board_max_pwr < 0)
+ return board_max_pwr;
+
+ return board_max_pwr - (cage_count - 1) * min_pwr_allowed;
+}
+
+/**
+ * ice_get_cage_idx - Get index to the cage
+ * @pf: pointer to the PF structure
+ * @cage_count: number of cages in the board
+ * @extack: extended ACK from the Netlink message
+ *
+ * Get index to the cage and validate if the given PF
+ * is associated with the cage.
+ */
+static int ice_get_cage_idx(struct ice_pf *pf, int cage_count,
+ struct netlink_ext_ack *extack)
+{
+ /* if there is only on cage, PF 0 is responsoble for it */
+ if (cage_count == 1) {
+ if (pf->hw.pf_id == 0)
+ return 0;
+ goto err;
+ } else if (cage_count == 4) {
+ /* if there are 4 cages, than port split is not supported
+ * so each PF is responsoble for its cage
+ */
+ return pf->hw.pf_id;
+ } else if (cage_count == 2) {
+ /* We have 2 cages, PF 0 always takes care of the first one.
+ * If the split_cnt is 2 than PF 1 takes care of the second cage.
+ * If the split_cnt is 4 than PF 2 takes care of the second cage.
+ * If the split_cnt is 8 than PF 4 takes care of the second cage.
+ * So, the formula for the second cage is pf_id * 2 == split_cnt
+ */
+ if (pf->hw.pf_id == 0 || pf->hw.pf_id * 2 == pf->split_cnt)
+ return pf->hw.pf_id;
+ }
+
+err:
+ NL_SET_ERR_MSG_MOD(extack, "Cage maximum power cannot be requested for selected port");
+
+ return -EPERM;
+}
+
+/**
+ * ice_get_dflt_max_pwr - Get dflt max power
+ * @hw: pointer to the hardware structure
+ *
+ * Default max power is stored in EMP settings NVM module
+ */
+static int ice_get_dflt_max_pwr(struct ice_hw *hw)
+{
+ __le16 data;
+ u16 pwr;
+ int ret;
+
+ ret = ice_acquire_nvm(hw, ICE_RES_READ);
+ if (ret)
+ return ret;
+
+ ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_EMP_SETTINGS_MOD_ID,
+ ICE_AQC_NVM_MAX_PWR_LIMIT_OFFSET, sizeof(data),
+ &data, true, false, NULL);
+ if (ret) {
+ ice_release_nvm(hw);
+ return ret;
+ }
+
+ ice_release_nvm(hw);
+
+ pwr = __le16_to_cpu(data);
+ pwr = FIELD_GET(ICE_AQC_NVM_DFLT_MAX_PWR_MASK, pwr);
+
+ return ice_pwr_nvm_to_ethtool(pwr);
+}
+
+/**
+ * ice_get_max_pwr_set - Get currently set max power
+ * @hw: pointer to the hardware structure
+ * @idx: index of the cage
+ *
+ * If cmpo enable bit is set, use the value from
+ * CMPO module otherwise use default value.
+ */
+static int ice_get_max_pwr_set(struct ice_hw *hw, int idx)
+{
+ struct ice_aqc_nvm_cmpo data;
+ int max_pwr_set;
+ u16 temp;
+ int ret;
+
+ ret = ice_acquire_nvm(hw, ICE_RES_READ);
+ if (ret)
+ return ret;
+
+ ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_CMPO_MOD_ID, 0, sizeof(data),
+ &data, true, false, NULL);
+ if (ret) {
+ ice_release_nvm(hw);
+ return ret;
+ }
+
+ ice_release_nvm(hw);
+
+ temp = le16_to_cpu(data.cages_cfg[idx]);
+
+ if (FIELD_GET(ICE_AQC_NVM_CMPO_ENABLE, temp)) {
+ max_pwr_set = FIELD_GET(ICE_AQC_NVM_CMPO_POWER_MASK, temp);
+ return ice_pwr_nvm_to_ethtool(max_pwr_set);
+ } else {
+ return ice_get_dflt_max_pwr(hw);
+ }
+}
+
+/**
+ * ice_get_module_power_cfg - Get device's power setting
+ * @dev: network device
+ * @params: output parameters
+ * @extack: extended ACK from the Netlink message
+ *
+ * We care only about min_pwr_allowed, max_pwr_allowed and max_pwr_set params.
+ */
+static int
+ice_get_module_power_cfg(struct net_device *dev,
+ struct ethtool_module_power_params *params,
+ struct netlink_ext_ack *extack)
+{
+ int min_pwr_allowed, max_pwr_allowed, max_pwr_set, cage_count;
+ struct ice_netdev_priv *np = netdev_priv(dev);
+ struct ice_vsi *vsi = np->vsi;
+ struct ice_pf *pf = vsi->back;
+ struct ice_hw *hw = &pf->hw;
+ int idx;
+
+ if (!ice_fw_supports_cmpo(hw)) {
+ NL_SET_ERR_MSG_MOD(extack, "Cage maximum power request is unsupported by the current firmware");
+ return -EOPNOTSUPP;
+ }
+
+ cage_count = ice_get_num_of_cages(hw);
+
+ idx = ice_get_cage_idx(pf, cage_count, extack);
+ if (idx < 0)
+ return idx;
+
+ min_pwr_allowed = ice_get_min_pwr_allowed(hw, extack);
+ if (min_pwr_allowed < 0) {
+ NL_SET_ERR_MSG_MOD(extack, "Unable to get min power limit");
+ return min_pwr_allowed;
+ }
+
+ max_pwr_allowed = ice_get_max_pwr_allowed(hw, min_pwr_allowed,
+ cage_count);
+ if (max_pwr_allowed < 0) {
+ NL_SET_ERR_MSG_MOD(extack, "Unable to get max power limit");
+ return max_pwr_allowed;
+ }
+
+ max_pwr_set = ice_get_max_pwr_set(hw, idx);
+ if (max_pwr_set < 0) {
+ NL_SET_ERR_MSG_MOD(extack, "Unable to get max power currently set");
+ return max_pwr_set;
+ }
+
+ params->min_pwr_allowed = min_pwr_allowed;
+ params->max_pwr_allowed = max_pwr_allowed;
+ params->max_pwr_set = max_pwr_set;
+
+ return 0;
+}
+
+/**
+ * ice_check_board_pwr_sum - Check if the new sum exceeds the board maximum.
+ * @hw: pointer to the hardware structure
+ * @data: current power config from NVM
+ * @idx: index of the cage we want to update
+ * @power: new power value from ethtool
+ * @cage_count: number of cages in the board
+ * @extack: extended ACK from the Netlink message
+ *
+ * Get number of cages, board maximum and default power value.
+ * Add up all values. If cmpo enable bit is set, use the value from
+ * CMPO module otherwise use default value.
+ */
+static int
+ice_check_board_pwr_sum(struct ice_hw *hw, struct ice_aqc_nvm_cmpo *data,
+ int idx, u32 power, int cage_count,
+ struct netlink_ext_ack *extack)
+{
+ int board_max_pwr, dflt_pwr, max_pwr_set, sum = 0;
+ u16 temp;
+ int i;
+
+ board_max_pwr = ice_get_board_max_pwr(hw);
+ if (board_max_pwr < 0)
+ return board_max_pwr;
+
+ dflt_pwr = ice_get_dflt_max_pwr(hw);
+ if (dflt_pwr < 0)
+ return dflt_pwr;
+
+ for (i = 0; i < cage_count; i++) {
+ temp = le16_to_cpu(data->cages_cfg[i]);
+
+ /* skipping the cage we want to update with the new value, we
+ * want to add the new power, not the value from NVM
+ */
+ if (i == idx)
+ continue;
+
+ if (FIELD_GET(ICE_AQC_NVM_CMPO_ENABLE, temp)) {
+ max_pwr_set = FIELD_GET(ICE_AQC_NVM_CMPO_POWER_MASK,
+ temp);
+ sum += ice_pwr_nvm_to_ethtool(max_pwr_set);
+ } else {
+ sum += dflt_pwr;
+ }
+ }
+
+ sum += power;
+
+ if (sum > board_max_pwr) {
+ NL_SET_ERR_MSG_MOD(extack, "Sum of power values is out of range: overbudgeting board level.");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * ice_set_module_power_cfg - Update device's power setting
+ * @dev: network device
+ * @params: new power config
+ * @extack: extended ACK from the Netlink message
+ *
+ * We care only about max_pwr_set and max_pwr_reset params.
+ */
+static int
+ice_set_module_power_cfg(struct net_device *dev,
+ const struct ethtool_module_power_params *params,
+ struct netlink_ext_ack *extack)
+{
+ struct ice_netdev_priv *np = netdev_priv(dev);
+ struct ice_vsi *vsi = np->vsi;
+ struct ice_pf *pf = vsi->back;
+ struct ice_aqc_nvm_cmpo data;
+ struct ice_hw *hw = &pf->hw;
+ int idx, ret, cage_count;
+ u16 power;
+
+ if (params->policy) {
+ NL_SET_ERR_MSG_MOD(extack, "Unsupported power parameter.");
+ return -EOPNOTSUPP;
+ }
+
+ if (!ice_fw_supports_cmpo(hw)) {
+ NL_SET_ERR_MSG_MOD(extack, "Cage maximum power request is unsupported by the current firmware.");
+ return -EOPNOTSUPP;
+ }
+
+ if (params->max_pwr_set % 500) {
+ NL_SET_ERR_MSG_MOD(extack, "Unsupported power resolution, use 500 mW resolution.");
+ return -EOPNOTSUPP;
+ }
+
+ cage_count = ice_get_num_of_cages(hw);
+
+ idx = ice_get_cage_idx(pf, cage_count, extack);
+ if (idx < 0)
+ return idx;
+
+ ret = ice_acquire_nvm(hw, ICE_RES_READ);
+ if (ret)
+ return ret;
+
+ ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_CMPO_MOD_ID, 0, sizeof(data),
+ &data, true, false, NULL);
+ if (ret) {
+ ice_release_nvm(hw);
+ NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM power config.");
+ return ret;
+ }
+
+ ice_release_nvm(hw);
+
+ power = ice_pwr_ethtool_to_nvm(params->max_pwr_set);
+
+ if (power) {
+ ret = ice_check_board_pwr_sum(hw, &data, idx,
+ params->max_pwr_set, cage_count,
+ extack);
+ if (ret)
+ return ret;
+
+ data.cages_cfg[idx] =
+ cpu_to_le16(power & ICE_AQC_NVM_CMPO_POWER_MASK);
+ data.cages_cfg[idx] |= cpu_to_le16(ICE_AQC_NVM_CMPO_ENABLE);
+ } else {
+ data.cages_cfg[idx] &= ~cpu_to_le16(ICE_AQC_NVM_CMPO_ENABLE);
+ }
+
+ ret = ice_acquire_nvm(hw, ICE_RES_WRITE);
+ if (ret)
+ return ret;
+
+ ret = ice_aq_update_nvm(hw, ICE_AQC_NVM_CMPO_MOD_ID, 2,
+ sizeof(data.cages_cfg), data.cages_cfg,
+ false, 0, NULL);
+ if (ret) {
+ ice_release_nvm(hw);
+ NL_SET_ERR_MSG_MOD(extack, "Failed to update NVM power config.");
+ return ret;
+ }
+
+ ret = ice_nvm_write_activate(&pf->hw, ICE_AQC_NVM_ACTIV_REQ_EMPR,
+ NULL);
+ if (ret) {
+ ice_release_nvm(hw);
+ NL_SET_ERR_MSG_MOD(extack, "Failed to save NVM power config.");
+ return ret;
+ }
+
+ ice_release_nvm(hw);
+
+ dev_info(ice_pf_to_dev(pf), "Reboot is required to complete power change.");
+
+ return 0;
+}
+
static const struct ethtool_ops ice_ethtool_ops = {
.cap_rss_ctx_supported = true,
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
@@ -4344,6 +4803,8 @@ static const struct ethtool_ops ice_ethtool_ops = {
.set_fecparam = ice_set_fecparam,
.get_module_info = ice_get_module_info,
.get_module_eeprom = ice_get_module_eeprom,
+ .get_module_power_cfg = ice_get_module_power_cfg,
+ .set_module_power_cfg = ice_set_module_power_cfg,
};
static const struct ethtool_ops ice_ethtool_safe_mode_ops = {
@@ -18,7 +18,7 @@
*
* Read the NVM using the admin queue commands (0x0701)
*/
-static int
+int
ice_aq_read_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset, u16 length,
void *data, bool last_command, bool read_shadow_ram,
struct ice_sq_cd *cd)
@@ -14,6 +14,9 @@ struct ice_orom_civd_info {
int ice_acquire_nvm(struct ice_hw *hw, enum ice_aq_res_access_type access);
void ice_release_nvm(struct ice_hw *hw);
+int ice_aq_read_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset,
+ u16 length, void *data, bool last_command,
+ bool read_shadow_ram, struct ice_sq_cd *cd);
int
ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data,
bool read_shadow_ram);
@@ -1152,6 +1152,10 @@ struct ice_aq_get_set_rss_lut_params {
#define ICE_FW_API_LINK_OVERRIDE_MIN 5
#define ICE_FW_API_LINK_OVERRIDE_PATCH 2
+#define ICE_FW_CMPO_MAJ 7
+#define ICE_FW_CMPO_MIN 4
+#define ICE_FW_CMPO_PATCH 1
+
#define ICE_SR_WORDS_IN_1KB 512
/* AQ API version for LLDP_FILTER_CONTROL */