DPDK patches and discussions
 help / color / mirror / Atom feed
From: "Medvedkin, Vladimir" <vladimir.medvedkin@intel.com>
To: Zhichao Zeng <zhichaox.zeng@intel.com>, <dev@dpdk.org>
Cc: <kaixinx.cui@intel.com>, Qiming Yang <qiming.yang@intel.com>,
	Yuying Zhang <Yuying.Zhang@intel.com>
Subject: Re: [PATCH v4] net/i40e: support FEC feature
Date: Mon, 11 Mar 2024 15:59:21 +0000	[thread overview]
Message-ID: <a0a3b102-31ff-413d-beef-a6213067f550@intel.com> (raw)
In-Reply-To: <20240306104135.2805774-1-zhichaox.zeng@intel.com>

[-- Attachment #1: Type: text/plain, Size: 12153 bytes --]

Hi Zhicha,

It would be good to reflect FEC feature here:

https://doc.dpdk.org/guides/nics/overview.html

in "/Table 1.1 //Features availability in networking drivers/"

please find the rest comments inline

On 06/03/2024 10:41, Zhichao Zeng wrote:
> This patch enabled querying Forward Error Correction(FEC) capabilities,
> set FEC mode and get current FEC mode functions.
>
> Signed-off-by: Qiming Yang<qiming.yang@intel.com>
> Signed-off-by: Zhichao Zeng<zhichaox.zeng@intel.com>
>
> ---
> v4: fix some logic
> v3: optimize code details
> v2: update NIC feature document
> ---
>   doc/guides/nics/features/i40e.ini      |   1 +
>   doc/guides/rel_notes/release_24_03.rst |   5 +
>   drivers/net/i40e/i40e_ethdev.c         | 192 +++++++++++++++++++++++++
>   3 files changed, 198 insertions(+)
>
> diff --git a/doc/guides/nics/features/i40e.ini b/doc/guides/nics/features/i40e.ini
> index e241dad047..aac2c1a6a1 100644
> --- a/doc/guides/nics/features/i40e.ini
> +++ b/doc/guides/nics/features/i40e.ini
> @@ -30,6 +30,7 @@ Flow control         = Y
>   CRC offload          = Y
>   VLAN offload         = Y
>   QinQ offload         = P
> +FEC                  = Y
>   L3 checksum offload  = P
>   L4 checksum offload  = P
>   Inner L3 checksum    = P
> diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
> index 161f77112b..862a5f8fb8 100644
> --- a/doc/guides/rel_notes/release_24_03.rst
> +++ b/doc/guides/rel_notes/release_24_03.rst
> @@ -110,6 +110,11 @@ New Features
>   
>     * Added support for 5760X device family.
>   
> +* **Updated Intel i40e driver.**
> +
> +  * Added support for configuring the Forward Error Correction(FEC) mode, querying
> +  * FEC capabilities and current FEC mode from a device.
> +
>   * **Updated Marvell cnxk net driver.**
>   
>     * Added support for port representors.
> diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
> index 380ce1a720..2bc6675a04 100644
> --- a/drivers/net/i40e/i40e_ethdev.c
> +++ b/drivers/net/i40e/i40e_ethdev.c
> @@ -406,6 +406,10 @@ 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,
> @@ -521,6 +525,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 */
> @@ -12297,6 +12304,191 @@ 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, __rte_unused unsigned int num)
> +{
> +	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
> +
> +	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;
> +	}
> +
> +	if (hw->device_id == I40E_DEV_ID_25G_SFP28 ||
> +	    hw->device_id == I40E_DEV_ID_25G_B) {
> +		if (speed_fec_capa) {
> +			speed_fec_capa->speed = RTE_ETH_SPEED_NUM_25G;
> +			speed_fec_capa->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);
> +		}
> +
> +		/* since HW only supports 25G */
> +		return 1;
> +	} else if (hw->device_id == I40E_DEV_ID_KX_X722) {
> +		if (speed_fec_capa) {
> +			speed_fec_capa->speed = RTE_ETH_SPEED_NUM_25G;
> +			speed_fec_capa->capa = RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
> +					     RTE_ETH_FEC_MODE_CAPA_MASK(RS);
> +		}
> +		return 1;
> +	}
> +
> +	return -ENOTSUP;
> +}
> +
> +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_link_status link_status = {0};
> +	uint8_t configured_fec_cfg = 0, current_fec_cfg;
> +	uint32_t temp_fec_capa = 0;
> +	bool link_up, enable_lse;
> +	int ret = 0;
> +
> +	enable_lse = dev->data->dev_conf.intr_conf.lsc ? true : false;
> +	/* Get FEC info */
> +	ret = i40e_aq_get_link_info(hw, enable_lse, &link_status, NULL);
> +	if (ret != I40E_SUCCESS) {
> +		PMD_DRV_LOG(ERR, "Failed to get link information");
> +		return -ENOTSUP;
> +	}
> +
> +	link_up = link_status.link_info & I40E_AQ_LINK_UP;
> +
> +	/**
> +	 * If link is down and AUTO is enabled, AUTO is returned,
> +	 * otherwise, configured FEC mode is returned.
> +	 * If link is up, current FEC mode is returned.
> +	 */
> +	configured_fec_cfg = link_status.req_fec_info;

here we need to better understand the difference between [FC,RS]-FEC 
ability bit (aka I40E_AQ_ENABLE_FEC_[KR,RS]) from [FC,RS]-FEC Request 
bit (aka I40E_AQ_REQUEST_FEC_[KR,RS]), since link_status.req_fec_info 
has only "Request" bits for each FEC algo (see i40e_update_link_info()).

 From what I found on the internet, it seems that we don't need to use 
them at all, because, for example for FC-FEC (aka Clause 74), from:

https://www.ieee802.org/3/25GSG/public/Nov14/baden_25GE_02_1114.pdf

Key phrase: "If both LPs advertise the FEC Ability, and EITHER LP 
requests the FEC, it is enabled."

So I'd suggest not to use these "Request" bits here.
For configured fec (case when link is DOWN) please use struct 
i40e_aq_get_phy_abilities_resp abilities.

> +	current_fec_cfg = link_status.fec_info;
> +
> +	if (!link_up) {
This section should be rewritten according to bit flags from 
abilities.fec_cfg_curr_mod_ext_info.
> +		if (current_fec_cfg & (I40E_AQ_ENABLE_FEC_KR | I40E_AQ_ENABLE_FEC_RS)) {
> +			temp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
> +		} else {
> +			if (configured_fec_cfg == (I40E_AQ_REQUEST_FEC_KR | I40E_AQ_REQUEST_FEC_RS))
> +				temp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
> +			else if (configured_fec_cfg & I40E_AQ_REQUEST_FEC_KR)
> +				temp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
> +			else if (configured_fec_cfg & I40E_AQ_REQUEST_FEC_RS)
> +				temp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(RS);
> +			else
> +				temp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
> +		}
> +	} else {
> +		if (current_fec_cfg & (I40E_AQ_ENABLE_FEC_KR | I40E_AQ_ENABLE_FEC_RS))
> +			temp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
In case when FEC was successfully negotiated current_fec_cfg is 
containing only single bit (since 2 algos can not be enabled at the same 
time), so this part is meaningless. Also here and below in this else 
section (i.e. in section if link is UP), for consistency please use 
corresponding macros defined for struct i40e_aqc_get_link_status - 
I40E_AQ_CONFIG_FEC_KR_ENA and I40E_AQ_CONFIG_FEC_RS_ENA instead of 
I40E_AQ_ENABLE_FEC_ .
> +		else if (current_fec_cfg & I40E_AQ_ENABLE_FEC_KR)
> +			temp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
> +		else if (current_fec_cfg & I40E_AQ_ENABLE_FEC_RS)
> +			temp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(RS);
> +		else
> +			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 = {0};
> +	struct i40e_aq_set_phy_config config = {0};
> +	enum i40e_status_code status;
> +	uint8_t req_fec = 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) {
> +		return -ENOTSUP;
> +	}
> +
> +	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.
> +	 */
> +	if (fec_capa != 0)
> +		return -EINVAL;
Did you mean if (fec_capa == 0)?
> +
> +	if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(AUTO)) {
> +		if (hw->mac.type == I40E_MAC_X722) {
> +			PMD_DRV_LOG(ERR, "X722 Unsupported FEC mode: AUTO");
> +			return -EINVAL;
> +		}
> +		req_fec = I40E_AQ_SET_FEC_AUTO;
> +		goto set_fec;
> +	}
> +
> +	if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC))
> +		req_fec = 0;
> +
> +	if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(BASER))
> +		req_fec |= I40E_AQ_SET_FEC_REQUEST_KR;
> +
> +	if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(RS)) {
> +		if (hw->mac.type == I40E_MAC_X722) {
> +			PMD_DRV_LOG(ERR, "X722 Unsupported FEC mode: RS");
> +			return -EINVAL;
> +		}
> +		req_fec |= I40E_AQ_SET_FEC_REQUEST_RS;
> +	}

This part is not looking correct to me:

- only I40E_AQ_SET_FEC_AUTO bit is set w/o enabling specific protocols

- "if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC))" makes no sense if 
other bitfields are set

- only I40E_AQ_SET_FEC_REQUEST_* is set without I40E_AQ_SET_FEC_ABILITY_*

  According to API : "If only the AUTO bit is set, the decision on which 
FEC mode to use will be made by HW/FW or driver. If the AUTO bit is set 
with some FEC modes, only specified FEC modes can be set. If AUTO bit is 
clear, specify FEC mode to be used (only one valid mode per speed may be 
set)." I'd suggest:

- In case when AUTO bit is set we need to check for other bit flags. In 
case of absence let's decide to  add all supported by mac type 
algorithms (i.e. set corresponding _enable_ and _request_ bit fields for 
each supported algo).

- In case if there are more bits apart from AUTO - check for their 
validity and support and specify corresponding _enable_ and _request_ flags.

- In case if AUTO is not set check that only single mode was specified, 
check its validity + support and so on.

> +
> +set_fec:
> +	/* 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);
> +		return -ENOTSUP;
> +	}
> +
> +	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);
> +			return -ENOTSUP;
> +		}
> +	}
> +
> +	status = i40e_update_link_info(hw);
> +	if (status) {
> +		PMD_DRV_LOG(ERR, "Failed to set PHY capabilities: %d\n",
> +			status);
> +		return -EAGAIN;
This is a new return status of this API. It needs to be added in doxygen 
documentation for this function and be reflected in release notes
> +	}
> +
> +	return 0;
> +}
> +
>   RTE_LOG_REGISTER_SUFFIX(i40e_logtype_init, init, NOTICE);
>   RTE_LOG_REGISTER_SUFFIX(i40e_logtype_driver, driver, NOTICE);
>   #ifdef RTE_ETHDEV_DEBUG_RX

-- 
Regards,
Vladimir

[-- Attachment #2: Type: text/html, Size: 85889 bytes --]

  reply	other threads:[~2024-03-11 15:59 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-20  8:47 [PATCH] " Qiming Yang
2024-03-06 10:41 ` [PATCH v4] " Zhichao Zeng
2024-03-11 15:59   ` Medvedkin, Vladimir [this message]
2024-03-12  8:44     ` Zeng, ZhichaoX
2024-03-14 21:41       ` Medvedkin, Vladimir
2024-04-11  8:18   ` [PATCH v5] " Zhichao Zeng
2024-04-11  9:29   ` Zhichao Zeng
2024-06-18  3:08     ` Zeng, ZhichaoX
2024-07-01  9:52     ` Medvedkin, Vladimir
2024-07-02  7:59     ` [PATCH v6] " Zhichao Zeng
2024-07-02  8:40     ` Zhichao Zeng
2024-07-03 17:37       ` Medvedkin, Vladimir
2024-07-04 11:29         ` Bruce Richardson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=a0a3b102-31ff-413d-beef-a6213067f550@intel.com \
    --to=vladimir.medvedkin@intel.com \
    --cc=Yuying.Zhang@intel.com \
    --cc=dev@dpdk.org \
    --cc=kaixinx.cui@intel.com \
    --cc=qiming.yang@intel.com \
    --cc=zhichaox.zeng@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).