net/i40e: support FEC feature

Message ID 20231220084706.446508-1-qiming.yang@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Qi Zhang
Headers
Series net/i40e: support FEC feature |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS
ci/github-robot: build success github build: passed
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS
ci/intel-Functional success Functional PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-abi-testing success Testing PASS
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-compile-amd64-testing success Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/iol-unit-amd64-testing success Testing PASS
ci/iol-unit-arm64-testing success Testing PASS
ci/iol-compile-arm64-testing success Testing PASS
ci/iol-sample-apps-testing success Testing PASS

Commit Message

Qiming Yang Dec. 20, 2023, 8:47 a.m. UTC
  This patch enabled FEC set and get functions.

Signed-off-by: Qiming Yang <qiming.yang@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 183 +++++++++++++++++++++++++++++++++
 1 file changed, 183 insertions(+)
  

Patch

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 3ca226156b..1eb49176d1 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -405,6 +405,11 @@  static void i40e_ethertype_filter_restore(struct i40e_pf *pf);
 static void i40e_tunnel_filter_restore(struct i40e_pf *pf);
 static void i40e_filter_restore(struct i40e_pf *pf);
 static void i40e_notify_all_vfs_link_status(struct rte_eth_dev *dev);
+static int i40e_fec_get_capability(struct rte_eth_dev *dev, struct rte_eth_fec_capa *speed_fec_capa,
+			   unsigned int num);
+static int i40e_fec_get(struct rte_eth_dev *dev, uint32_t *fec_capa);
+static int i40e_fec_set(struct rte_eth_dev *dev, uint32_t fec_capa);
+
 
 static const char *const valid_keys[] = {
 	ETH_I40E_FLOATING_VEB_ARG,
@@ -519,6 +524,9 @@  static const struct eth_dev_ops i40e_eth_dev_ops = {
 	.tm_ops_get                   = i40e_tm_ops_get,
 	.tx_done_cleanup              = i40e_tx_done_cleanup,
 	.get_monitor_addr             = i40e_get_monitor_addr,
+	.fec_get_capability           = i40e_fec_get_capability,
+	.fec_get                      = i40e_fec_get,
+	.fec_set                      = i40e_fec_set,
 };
 
 /* store statistics names and its offset in stats structure */
@@ -12159,6 +12167,181 @@  i40e_cloud_filter_qinq_create(struct i40e_pf *pf)
 	return ret;
 }
 
+static int
+i40e_fec_get_capability(struct rte_eth_dev *dev, struct rte_eth_fec_capa *speed_fec_capa,
+			   unsigned int num)
+{
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	num = 0;
+
+	if (hw->mac.type == I40E_MAC_X722 &&
+	    !(hw->flags & I40E_HW_FLAG_X722_FEC_REQUEST_CAPABLE)) {
+		PMD_DRV_LOG(ERR, "Setting FEC encoding not supported by"
+			 " firmware. Please update the NVM image.\n");
+		return 0;
+	}
+
+	if (hw->device_id == I40E_DEV_ID_25G_SFP28 ||
+	    hw->device_id == I40E_DEV_ID_25G_B) {
+		if (speed_fec_capa) {
+			speed_fec_capa[num].speed = RTE_ETH_SPEED_NUM_25G;
+			speed_fec_capa[num].capa = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+					     RTE_ETH_FEC_MODE_CAPA_MASK(BASER) |
+					     RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+					     RTE_ETH_FEC_MODE_CAPA_MASK(RS);
+		}
+		num++;
+	}
+
+	if (hw->device_id == I40E_DEV_ID_KX_X722) {
+		if (speed_fec_capa) {
+			speed_fec_capa[num].speed = RTE_ETH_SPEED_NUM_25G;
+			speed_fec_capa[num].capa = RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+					     RTE_ETH_FEC_MODE_CAPA_MASK(RS);
+		}
+		num++;
+	}
+
+	return num;
+}
+
+static int
+i40e_fec_get(struct rte_eth_dev *dev, uint32_t *fec_capa)
+{
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct i40e_aq_get_phy_abilities_resp abilities;
+	u32 temp_fec_capa = 0;
+	u8 fec_cfg;
+	int ret = 0;
+
+	/* Get the current phy config */
+	memset(&abilities, 0, sizeof(abilities));
+	ret = i40e_aq_get_phy_capabilities(hw, false, false, &abilities,
+						  NULL);
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Failed to get PHY capabilities: %d\n",
+				ret);
+		return -ENOTSUP;
+	}
+
+	fec_cfg = abilities.fec_cfg_curr_mod_ext_info;
+	if (fec_cfg & I40E_AQ_SET_FEC_AUTO)
+		temp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
+
+	if (fec_cfg & I40E_AQ_SET_FEC_REQUEST_KR ||
+		fec_cfg & I40E_AQ_SET_FEC_ABILITY_KR)
+		temp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
+
+	if (fec_cfg & I40E_AQ_SET_FEC_REQUEST_RS ||
+		fec_cfg & I40E_AQ_SET_FEC_ABILITY_RS)
+		temp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(RS);
+
+	if (fec_cfg == 0)
+		temp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
+
+	*fec_capa = temp_fec_capa;
+
+	return 0;
+}
+
+static int
+i40e_fec_set(struct rte_eth_dev *dev, uint32_t fec_capa)
+{
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct i40e_aq_get_phy_abilities_resp abilities;
+	struct i40e_aq_set_phy_config config = { 0 };
+	enum i40e_status_code status;
+	u8 req_fec;
+	int ret = 0;
+
+	if (hw->device_id != I40E_DEV_ID_25G_SFP28 &&
+	    hw->device_id != I40E_DEV_ID_25G_B &&
+	    hw->device_id != I40E_DEV_ID_KX_X722) {
+		ret = -ENOTSUP;
+		goto done;
+	}
+
+	if (hw->mac.type == I40E_MAC_X722 &&
+	    !(hw->flags & I40E_HW_FLAG_X722_FEC_REQUEST_CAPABLE)) {
+		PMD_DRV_LOG(ERR, "Setting FEC encoding not supported by"
+			 " firmware. Please update the NVM image.\n");
+		return -ENOTSUP;
+	}
+
+	/* Copy the current user PHY configuration. The current user PHY
+	 * configuration is initialized during probe from PHY capabilities
+	 * software mode, and updated on set PHY configuration.
+	 */
+	switch (fec_capa) {
+	case RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC):
+		req_fec = 0;
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(AUTO):
+		if (hw->mac.type == I40E_MAC_X722) {
+			PMD_DRV_LOG(ERR, "X722 Unsupported FEC mode: AUTO");
+			ret = -EINVAL;
+			goto done;
+		} else {
+			req_fec = I40E_AQ_SET_FEC_AUTO;
+		}
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(BASER):
+		req_fec = (I40E_AQ_SET_FEC_REQUEST_KR |
+			     I40E_AQ_SET_FEC_ABILITY_KR);
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(RS):
+		if (hw->mac.type == I40E_MAC_X722) {
+			PMD_DRV_LOG(ERR, "X722 Unsupported FEC mode: RS");
+			ret = -EINVAL;
+			goto done;
+		} else {
+			req_fec = (I40E_AQ_SET_FEC_REQUEST_RS |
+				   I40E_AQ_SET_FEC_ABILITY_RS);
+		}
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Unsupported FEC mode: %d\n", fec_capa);
+		return -EINVAL;
+	}
+
+	/* Get the current phy config */
+	status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities,
+					      NULL);
+	if (status) {
+		PMD_DRV_LOG(ERR, "Failed to get PHY capabilities: %d\n",
+				status);
+		ret = -ENOTSUP;
+		goto done;
+	}
+
+	if (abilities.fec_cfg_curr_mod_ext_info != req_fec) {
+		config.phy_type = abilities.phy_type;
+		config.abilities = abilities.abilities |
+				   I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+		config.phy_type_ext = abilities.phy_type_ext;
+		config.link_speed = abilities.link_speed;
+		config.eee_capability = abilities.eee_capability;
+		config.eeer = abilities.eeer_val;
+		config.low_power_ctrl = abilities.d3_lpan;
+		config.fec_config = req_fec & I40E_AQ_PHY_FEC_CONFIG_MASK;
+		status = i40e_aq_set_phy_config(hw, &config, NULL);
+		if (status) {
+			PMD_DRV_LOG(ERR, "Failed to set PHY capabilities: %d\n",
+			status);
+			ret = -ENOTSUP;
+			goto done;
+		}
+	}
+
+	status = i40e_update_link_info(hw);
+	if (status)
+		PMD_DRV_LOG(ERR, "Failed to set PHY capabilities: %d\n",
+			status);
+
+done:
+	return ret;
+}
+
 RTE_LOG_REGISTER_SUFFIX(i40e_logtype_init, init, NOTICE);
 RTE_LOG_REGISTER_SUFFIX(i40e_logtype_driver, driver, NOTICE);
 #ifdef RTE_ETHDEV_DEBUG_RX