[V9,1/3] ethdev: introduce FEC API

Message ID 1600668838-31498-2-git-send-email-humin29@huawei.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series add FEC support |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

humin (Q) Sept. 21, 2020, 6:13 a.m. UTC
  This patch adds Forward error correction(FEC) support for ethdev.
Introduce APIs which support query and config FEC information in
hardware.

Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
Reviewed-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
Reviewed-by: Chengwen Feng <fengchengwen@huawei.com>
Reviewed-by: Chengchang Tang <tangchengchang@huawei.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---
v8->v9:
added reviewed-by and acked-by.

---
v7->v8:
put AUTO just after NOFEC in rte_fec_mode definition.

---
v6->v7:
deleted RTE_ETH_FEC_NUM to prevent ABI breakage.
add new macro to indicate translation from fec mode
to capa.

---
v5->v6:
modified release notes.
deleted check duplicated for FEC API
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Modifies FEC capa definitions using macros.
Add RTE_ prefix for public FEC mode enum.
add release notes about FEC for dpdk20_11.

---
v2->v3:
add function return value "-ENOTSUP" for API

---
 doc/guides/rel_notes/release_20_11.rst   | 10 ++++
 lib/librte_ethdev/rte_ethdev.c           | 49 ++++++++++++++++++
 lib/librte_ethdev/rte_ethdev.h           | 85 ++++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_core.h      | 79 +++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |  5 ++
 5 files changed, 228 insertions(+)
  

Comments

Andrew Rybchenko Sept. 21, 2020, 1:39 p.m. UTC | #1
On 9/21/20 9:13 AM, Min Hu (Connor) wrote:
> This patch adds Forward error correction(FEC) support for ethdev.
> Introduce APIs which support query and config FEC information in
> hardware.
> 
> Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
> Reviewed-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
> Reviewed-by: Chengwen Feng <fengchengwen@huawei.com>
> Reviewed-by: Chengchang Tang <tangchengchang@huawei.com>
> Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>

[snip]

> diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
> index 70295d7..7d5e81b 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -1310,6 +1310,9 @@ struct rte_eth_conf {
>  #define RTE_ETH_DEV_FALLBACK_RX_NBQUEUES 1
>  #define RTE_ETH_DEV_FALLBACK_TX_NBQUEUES 1
>  
> +/* Translate from FEC mode to FEC capa */
> +#define RTE_ETH_FEC_MODE_TO_CAPA(x)	(1U << (x))
> +

It should not be so far from rte_eth_fec_mode. Please, add just
after it.

May be it should be:
#define RTE_ETH_FEC_MODE_TO_CAPA(x) (1U << (RTE_ETH_FEC_ ## x))

>  /**
>   * Preferred Rx/Tx port parameters.
>   * There are separate instances of this structure for transmission
> @@ -1511,6 +1514,24 @@ struct rte_eth_dcb_info {
>  	struct rte_eth_dcb_tc_queue_mapping tc_queue;
>  };
>  
> +/**
> + * This enum indicates the possible (forward error correction)FEC modes
> + * of an ethdev port.
> + */
> +enum rte_eth_fec_mode {
> +	RTE_ETH_FEC_NOFEC = 0,      /**< FEC is off */
> +	RTE_ETH_FEC_AUTO,	    /**< FEC autonegotiation modes */
> +	RTE_ETH_FEC_BASER,          /**< FEC using common algorithm */
> +	RTE_ETH_FEC_RS,             /**< FEC using RS algorithm */
> +};
> +
> +/* This indicates FEC capabilities */
> +#define RTE_ETH_FEC_CAPA_NOFEC  (1U << RTE_ETH_FEC_NOFEC)
> +#define RTE_ETH_FEC_CAPA_AUTO   (1U << RTE_ETH_FEC_AUTO)
> +#define RTE_ETH_FEC_CAPA_BASER  (1U << RTE_ETH_FEC_BASER)
> +#define RTE_ETH_FEC_CAPA_RS     (1U << RTE_ETH_FEC_RS)

Shouldn't RTE_ETH_FEC_MODE_TO_CAPA be used as definition
values?

> +
> +
>  #define RTE_ETH_ALL RTE_MAX_ETHPORTS
>  
>  /* Macros to check for valid port */
> @@ -3328,6 +3349,70 @@ int  rte_eth_led_on(uint16_t port_id);
>  int  rte_eth_led_off(uint16_t port_id);
>  
>  /**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get Forward Error Correction(FEC) capability.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param fec_cap
> + *   returns the FEC capability from the device, as follows:
> + *   RTE_ETH_FEC_CAPA_NOFEC
> + *   RTE_ETH_FEC_CAPA_AUTO
> + *   RTE_ETH_FEC_CAPA_BASER
> + *   RTE_ETH_FEC_CAPA_RS
> + * @return
> + *   - (0) if successful.
> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> + *     that operation.
> + *   - (-EIO) if device is removed.
> + *   - (-ENODEV)  if *port_id* invalid.
> + */
> +__rte_experimental
> +int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *fec_cap);

The API does not allow to report capabilities per link speed:
which FEC mode is supported at which link speed?

What about something like:

struct rte_eth_fec_capa {
  uint32_t speed; /**< Link speed (see ETH_SPEED_NUM_*) */
  uint32_t capa;  /**< FEC capabilities bitmask (see RTE_FEC_CAPA_*) */
};

__rte_experimental
int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *num, struct
rte_eth_fec_capa *speed_capa);

where:
 - num is in/out with a number of elements in an array
 - speed_capa is out only with per-speed capabilities

> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get current Forward Error Correction(FEC) mode.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param mode
> + *   returns the FEC mode from the device.
> + * @return
> + *   - (0) if successful.
> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> + *     that operation.
> + *   - (-EIO) if device is removed.
> + *   - (-ENODEV)  if *port_id* invalid.
> + */
> +__rte_experimental
> +int rte_eth_fec_get(uint16_t port_id, enum rte_eth_fec_mode *mode);

Please, specify what should be reported if link is down.
E.g. if set to RS, but link is down.

Does AUTO make sense here?

> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Set Forward Error Correction(FEC) mode.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param mode
> + *   the FEC mode.
> + * @return
> + *   - (0) if successful.
> + *   - (-EINVAL) if the FEC mode is not valid.
> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> + *   - (-EIO) if device is removed.
> + *   - (-ENODEV)  if *port_id* invalid.
> + */
> +__rte_experimental
> +int rte_eth_fec_set(uint16_t port_id, enum rte_eth_fec_mode mode);

It does not allow to tweak autoneg facilities.
E.g. "I know that RS is buggy, so I want to exclude it from
auto-negotiation".
So, I suggest to change mode to capa bitmask.
If AUTO is set, other bits may be set and specify allowed
options. E.g. AUTO|RS|BASER will require FEC, i.e. NOFEC is
not allowed. If just RS, it means that auto-negotiation is
disabled and RS must be used.
If AUTO is unset, only one bit may be set in capabilities.
Since we don't do it per speed, I think it is safe to ignore
unsupported mode bits. I.e. do not return error if unsupported
capa is requested to together with AUTO, however it could be
a problem if no modes are allowed for negotiated link speed.
Thoughts are welcome.

> +
> +/**
>   * Get current status of the Ethernet link flow control for Ethernet device
>   *
>   * @param port_id

[snip]
  
humin (Q) Sept. 22, 2020, 4:58 a.m. UTC | #2
在 2020/9/21 21:39, Andrew Rybchenko 写道:
> On 9/21/20 9:13 AM, Min Hu (Connor) wrote:
>> This patch adds Forward error correction(FEC) support for ethdev.
>> Introduce APIs which support query and config FEC information in
>> hardware.
>>
>> Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
>> Reviewed-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
>> Reviewed-by: Chengwen Feng <fengchengwen@huawei.com>
>> Reviewed-by: Chengchang Tang <tangchengchang@huawei.com>
>> Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
>> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> 
> [snip]
> 
>> diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
>> index 70295d7..7d5e81b 100644
>> --- a/lib/librte_ethdev/rte_ethdev.h
>> +++ b/lib/librte_ethdev/rte_ethdev.h
>> @@ -1310,6 +1310,9 @@ struct rte_eth_conf {
>>   #define RTE_ETH_DEV_FALLBACK_RX_NBQUEUES 1
>>   #define RTE_ETH_DEV_FALLBACK_TX_NBQUEUES 1
>>   
>> +/* Translate from FEC mode to FEC capa */
>> +#define RTE_ETH_FEC_MODE_TO_CAPA(x)	(1U << (x))
>> +
> 
> It should not be so far from rte_eth_fec_mode. Please, add just
> after it.
I will fix it in V10, thanks.
> 
> May be it should be:
> #define RTE_ETH_FEC_MODE_TO_CAPA(x) (1U << (RTE_ETH_FEC_ ## x))
> 
This will be weird, as "x" should be one fec mode。examples
as follows:

rte_eth_fec_set(uint16_t port_id, enum rte_eth_fec_mode mode)
{
	struct rte_eth_dev *dev;
	uint32_t fec_mode_mask;
	int ret;

	ret = rte_eth_fec_get_capability(port_id, &fec_mode_mask);
	if (ret != 0)
		return ret;

	/*
	 * Check whether the configured mode is within the FEC capability.
	 * If not, the configured mode will not be supported.
	 */
	if (!(fec_mode_mask & RTE_ETH_FEC_MODE_TO_CAPA(mode))) {
		RTE_ETHDEV_LOG(ERR, "unsupported FEC mode = %d, port_id = %u\n",
			       mode, port_id);
		return -EINVAL;
	}
[snip]
>>   /**
>>    * Preferred Rx/Tx port parameters.
>>    * There are separate instances of this structure for transmission
>> @@ -1511,6 +1514,24 @@ struct rte_eth_dcb_info {
>>   	struct rte_eth_dcb_tc_queue_mapping tc_queue;
>>   };
>>   
>> +/**
>> + * This enum indicates the possible (forward error correction)FEC modes
>> + * of an ethdev port.
>> + */
>> +enum rte_eth_fec_mode {
>> +	RTE_ETH_FEC_NOFEC = 0,      /**< FEC is off */
>> +	RTE_ETH_FEC_AUTO,	    /**< FEC autonegotiation modes */
>> +	RTE_ETH_FEC_BASER,          /**< FEC using common algorithm */
>> +	RTE_ETH_FEC_RS,             /**< FEC using RS algorithm */
>> +};
>> +
>> +/* This indicates FEC capabilities */
>> +#define RTE_ETH_FEC_CAPA_NOFEC  (1U << RTE_ETH_FEC_NOFEC)
>> +#define RTE_ETH_FEC_CAPA_AUTO   (1U << RTE_ETH_FEC_AUTO)
>> +#define RTE_ETH_FEC_CAPA_BASER  (1U << RTE_ETH_FEC_BASER)
>> +#define RTE_ETH_FEC_CAPA_RS     (1U << RTE_ETH_FEC_RS)
> 
> Shouldn't RTE_ETH_FEC_MODE_TO_CAPA be used as definition
> values?
> I will define a new macro as you suggest in V10, like this:
/* This macro indicates FEC capa mask*/
#define RTE_ETH_FEC_MODE_CAPA_MASK(x)	(1U << (RTE_ETH_FEC_ ## x))

that macro will replace the follow macros:
#define RTE_ETH_FEC_CAPA_NOFEC  (1U << RTE_ETH_FEC_NOFEC)
#define RTE_ETH_FEC_CAPA_AUTO   (1U << RTE_ETH_FEC_AUTO)
#define RTE_ETH_FEC_CAPA_BASER  (1U << RTE_ETH_FEC_BASER)
#define RTE_ETH_FEC_CAPA_RS     (1U << RTE_ETH_FEC_RS)

i.e.:
RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC)
RTE_ETH_FEC_MODE_CAPA_MASK(AUTO)
RTE_ETH_FEC_MODE_CAPA_MASK(BASER)
RTE_ETH_FEC_MODE_CAPA_MASK(RS)

thanks for your suggestions.

>> +
>> +
>>   #define RTE_ETH_ALL RTE_MAX_ETHPORTS
>>   
>>   /* Macros to check for valid port */
>> @@ -3328,6 +3349,70 @@ int  rte_eth_led_on(uint16_t port_id);
>>   int  rte_eth_led_off(uint16_t port_id);
>>   
>>   /**
>> + * @warning
>> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
>> + *
>> + * Get Forward Error Correction(FEC) capability.
>> + *
>> + * @param port_id
>> + *   The port identifier of the Ethernet device.
>> + * @param fec_cap
>> + *   returns the FEC capability from the device, as follows:
>> + *   RTE_ETH_FEC_CAPA_NOFEC
>> + *   RTE_ETH_FEC_CAPA_AUTO
>> + *   RTE_ETH_FEC_CAPA_BASER
>> + *   RTE_ETH_FEC_CAPA_RS
>> + * @return
>> + *   - (0) if successful.
>> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
>> + *     that operation.
>> + *   - (-EIO) if device is removed.
>> + *   - (-ENODEV)  if *port_id* invalid.
>> + */
>> +__rte_experimental
>> +int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *fec_cap);
> 
> The API does not allow to report capabilities per link speed:
> which FEC mode is supported at which link speed?
> 
> What about something like:
> 
> struct rte_eth_fec_capa {
>    uint32_t speed; /**< Link speed (see ETH_SPEED_NUM_*) */
>    uint32_t capa;  /**< FEC capabilities bitmask (see RTE_FEC_CAPA_*) */
> };
> 
> __rte_experimental
> int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *num, struct
> rte_eth_fec_capa *speed_capa);
> 
> where:
>   - num is in/out with a number of elements in an array
>   - speed_capa is out only with per-speed capabilities
> 
There is no need to report capabilities per link speed, because 
relastionship between the link speed and fec mode is fixed. The 
infomations can be referred to in official documents or internet.

A ethernet port may have various link speed in diffrent situations(for 
example, optical module with different speed is used). But we do not
care about capabilities per link speed. We only care about FEC capa of 
the ethernet device at a specific moment, because set FEC mode also 
depend on the current FEC capa.

By the way, we can also get link speed of the device by API 
"rte_eth_link_get" in the same time.

thanks.

>> +
>> +/**
>> + * @warning
>> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
>> + *
>> + * Get current Forward Error Correction(FEC) mode.
>> + *
>> + * @param port_id
>> + *   The port identifier of the Ethernet device.
>> + * @param mode
>> + *   returns the FEC mode from the device.
>> + * @return
>> + *   - (0) if successful.
>> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
>> + *     that operation.
>> + *   - (-EIO) if device is removed.
>> + *   - (-ENODEV)  if *port_id* invalid.
>> + */
>> +__rte_experimental
>> +int rte_eth_fec_get(uint16_t port_id, enum rte_eth_fec_mode *mode);
> 
> Please, specify what should be reported if link is down.
> E.g. if set to RS, but link is down.
> 
> Does AUTO make sense here?
> 
OK, I will add the information in the function header comment:
when link down,None AUTO mode(RS, BASER. NOFEC) keep as it is when link 
up, AUTO mode will change from rs,baser to nofec when quering the mode.


>> +
>> +/**
>> + * @warning
>> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
>> + *
>> + * Set Forward Error Correction(FEC) mode.
>> + *
>> + * @param port_id
>> + *   The port identifier of the Ethernet device.
>> + * @param mode
>> + *   the FEC mode.
>> + * @return
>> + *   - (0) if successful.
>> + *   - (-EINVAL) if the FEC mode is not valid.
>> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
>> + *   - (-EIO) if device is removed.
>> + *   - (-ENODEV)  if *port_id* invalid.
>> + */
>> +__rte_experimental
>> +int rte_eth_fec_set(uint16_t port_id, enum rte_eth_fec_mode mode);
> 
> It does not allow to tweak autoneg facilities.
> E.g. "I know that RS is buggy, so I want to exclude it from
> auto-negotiation".
> So, I suggest to change mode to capa bitmask.
> If AUTO is set, other bits may be set and specify allowed
> options. E.g. AUTO|RS|BASER will require FEC, i.e. NOFEC is
The two FEC modes cannot be configured for hardware at the same time, 
including AUTO and other FEC modes. This is determined by Hardware itself.
Thanks.

> not allowed. If just RS, it means that auto-negotiation is
> disabled and RS must be used.
> If AUTO is unset, only one bit may be set in capabilities.
> Since we don't do it per speed, I think it is safe to ignore
> unsupported mode bits. I.e. do not return error if unsupported
> capa is requested to together with AUTO, however it could be
> a problem if no modes are allowed for negotiated link speed.
> Thoughts are welcome.
> 
>> +
>> +/**
>>    * Get current status of the Ethernet link flow control for Ethernet device
>>    *
>>    * @param port_id
> 
> [snip]
> 
> .
>
  
Andrew Rybchenko Sept. 22, 2020, 8:02 a.m. UTC | #3
On 9/22/20 7:58 AM, Min Hu (Connor) wrote:
> 
> 
> 在 2020/9/21 21:39, Andrew Rybchenko 写道:
>> On 9/21/20 9:13 AM, Min Hu (Connor) wrote:
>>> This patch adds Forward error correction(FEC) support for ethdev.
>>> Introduce APIs which support query and config FEC information in
>>> hardware.
>>>
>>> Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
>>> Reviewed-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
>>> Reviewed-by: Chengwen Feng <fengchengwen@huawei.com>
>>> Reviewed-by: Chengchang Tang <tangchengchang@huawei.com>
>>> Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
>>> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
>>
>> [snip]
>>
>>> diff --git a/lib/librte_ethdev/rte_ethdev.h
>>> b/lib/librte_ethdev/rte_ethdev.h
>>> index 70295d7..7d5e81b 100644
>>> --- a/lib/librte_ethdev/rte_ethdev.h
>>> +++ b/lib/librte_ethdev/rte_ethdev.h
>>> @@ -1310,6 +1310,9 @@ struct rte_eth_conf {
>>>   #define RTE_ETH_DEV_FALLBACK_RX_NBQUEUES 1
>>>   #define RTE_ETH_DEV_FALLBACK_TX_NBQUEUES 1
>>>   +/* Translate from FEC mode to FEC capa */
>>> +#define RTE_ETH_FEC_MODE_TO_CAPA(x)    (1U << (x))
>>> +
>>
>> It should not be so far from rte_eth_fec_mode. Please, add just
>> after it.
> I will fix it in V10, thanks.
>>
>> May be it should be:
>> #define RTE_ETH_FEC_MODE_TO_CAPA(x) (1U << (RTE_ETH_FEC_ ## x))
>>
> This will be weird, as "x" should be one fec mode。examples
> as follows:
> 
> rte_eth_fec_set(uint16_t port_id, enum rte_eth_fec_mode mode)
> {
>     struct rte_eth_dev *dev;
>     uint32_t fec_mode_mask;
>     int ret;
> 
>     ret = rte_eth_fec_get_capability(port_id, &fec_mode_mask);
>     if (ret != 0)
>         return ret;
> 
>     /*
>      * Check whether the configured mode is within the FEC capability.
>      * If not, the configured mode will not be supported.
>      */
>     if (!(fec_mode_mask & RTE_ETH_FEC_MODE_TO_CAPA(mode))) {
>         RTE_ETHDEV_LOG(ERR, "unsupported FEC mode = %d, port_id = %u\n",
>                    mode, port_id);
>         return -EINVAL;
>     }

Got it, makes sense.

> [snip]
>>>   /**
>>>    * Preferred Rx/Tx port parameters.
>>>    * There are separate instances of this structure for transmission
>>> @@ -1511,6 +1514,24 @@ struct rte_eth_dcb_info {
>>>       struct rte_eth_dcb_tc_queue_mapping tc_queue;
>>>   };
>>>   +/**
>>> + * This enum indicates the possible (forward error correction)FEC modes
>>> + * of an ethdev port.
>>> + */
>>> +enum rte_eth_fec_mode {
>>> +    RTE_ETH_FEC_NOFEC = 0,      /**< FEC is off */
>>> +    RTE_ETH_FEC_AUTO,        /**< FEC autonegotiation modes */
>>> +    RTE_ETH_FEC_BASER,          /**< FEC using common algorithm */
>>> +    RTE_ETH_FEC_RS,             /**< FEC using RS algorithm */
>>> +};
>>> +
>>> +/* This indicates FEC capabilities */
>>> +#define RTE_ETH_FEC_CAPA_NOFEC  (1U << RTE_ETH_FEC_NOFEC)
>>> +#define RTE_ETH_FEC_CAPA_AUTO   (1U << RTE_ETH_FEC_AUTO)
>>> +#define RTE_ETH_FEC_CAPA_BASER  (1U << RTE_ETH_FEC_BASER)
>>> +#define RTE_ETH_FEC_CAPA_RS     (1U << RTE_ETH_FEC_RS)
>>
>> Shouldn't RTE_ETH_FEC_MODE_TO_CAPA be used as definition
>> values?
>> I will define a new macro as you suggest in V10, like this:
> /* This macro indicates FEC capa mask*/
> #define RTE_ETH_FEC_MODE_CAPA_MASK(x)    (1U << (RTE_ETH_FEC_ ## x))
> 
> that macro will replace the follow macros:
> #define RTE_ETH_FEC_CAPA_NOFEC  (1U << RTE_ETH_FEC_NOFEC)
> #define RTE_ETH_FEC_CAPA_AUTO   (1U << RTE_ETH_FEC_AUTO)
> #define RTE_ETH_FEC_CAPA_BASER  (1U << RTE_ETH_FEC_BASER)
> #define RTE_ETH_FEC_CAPA_RS     (1U << RTE_ETH_FEC_RS)
> 
> i.e.:
> RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC)
> RTE_ETH_FEC_MODE_CAPA_MASK(AUTO)
> RTE_ETH_FEC_MODE_CAPA_MASK(BASER)
> RTE_ETH_FEC_MODE_CAPA_MASK(RS)
> 
> thanks for your suggestions.

Thanks for your work on the patchset.

> 
>>> +
>>> +
>>>   #define RTE_ETH_ALL RTE_MAX_ETHPORTS
>>>     /* Macros to check for valid port */
>>> @@ -3328,6 +3349,70 @@ int  rte_eth_led_on(uint16_t port_id);
>>>   int  rte_eth_led_off(uint16_t port_id);
>>>     /**
>>> + * @warning
>>> + * @b EXPERIMENTAL: this API may change, or be removed, without
>>> prior notice
>>> + *
>>> + * Get Forward Error Correction(FEC) capability.
>>> + *
>>> + * @param port_id
>>> + *   The port identifier of the Ethernet device.
>>> + * @param fec_cap
>>> + *   returns the FEC capability from the device, as follows:
>>> + *   RTE_ETH_FEC_CAPA_NOFEC
>>> + *   RTE_ETH_FEC_CAPA_AUTO
>>> + *   RTE_ETH_FEC_CAPA_BASER
>>> + *   RTE_ETH_FEC_CAPA_RS
>>> + * @return
>>> + *   - (0) if successful.
>>> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
>>> + *     that operation.
>>> + *   - (-EIO) if device is removed.
>>> + *   - (-ENODEV)  if *port_id* invalid.
>>> + */
>>> +__rte_experimental
>>> +int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *fec_cap);
>>
>> The API does not allow to report capabilities per link speed:
>> which FEC mode is supported at which link speed?
>>
>> What about something like:
>>
>> struct rte_eth_fec_capa {
>>    uint32_t speed; /**< Link speed (see ETH_SPEED_NUM_*) */
>>    uint32_t capa;  /**< FEC capabilities bitmask (see RTE_FEC_CAPA_*) */
>> };
>>
>> __rte_experimental
>> int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *num, struct
>> rte_eth_fec_capa *speed_capa);
>>
>> where:
>>   - num is in/out with a number of elements in an array
>>   - speed_capa is out only with per-speed capabilities
>>
> There is no need to report capabilities per link speed, because
> relastionship between the link speed and fec mode is fixed. The
> infomations can be referred to in official documents or internet.

Should an application download documents and search for it? :)

> 
> A ethernet port may have various link speed in diffrent situations(for
> example, optical module with different speed is used). But we do not
> care about capabilities per link speed. We only care about FEC capa of
> the ethernet device at a specific moment, because set FEC mode also
> depend on the current FEC capa.

Capabilities should not be for a specific moment. Capabilities
should be fixed and stable (if transceiver is not replaced).
Capabilities should not depend on a link speed or link status.
Otherwise an application can't use it in a reliable way.

> 
> By the way, we can also get link speed of the device by API
> "rte_eth_link_get" in the same time.
> 
> thanks.
> 
>>> +
>>> +/**
>>> + * @warning
>>> + * @b EXPERIMENTAL: this API may change, or be removed, without
>>> prior notice
>>> + *
>>> + * Get current Forward Error Correction(FEC) mode.
>>> + *
>>> + * @param port_id
>>> + *   The port identifier of the Ethernet device.
>>> + * @param mode
>>> + *   returns the FEC mode from the device.
>>> + * @return
>>> + *   - (0) if successful.
>>> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
>>> + *     that operation.
>>> + *   - (-EIO) if device is removed.
>>> + *   - (-ENODEV)  if *port_id* invalid.
>>> + */
>>> +__rte_experimental
>>> +int rte_eth_fec_get(uint16_t port_id, enum rte_eth_fec_mode *mode);
>>
>> Please, specify what should be reported if link is down.
>> E.g. if set to RS, but link is down.
>>
>> Does AUTO make sense here?
>>
> OK, I will add the information in the function header comment:
> when link down,None AUTO mode(RS, BASER. NOFEC) keep as it is when link
> up, AUTO mode will change from rs,baser to nofec when quering the mode.

I'll take a look at the patch, above text is hardly readable.

> 
> 
>>> +
>>> +/**
>>> + * @warning
>>> + * @b EXPERIMENTAL: this API may change, or be removed, without
>>> prior notice
>>> + *
>>> + * Set Forward Error Correction(FEC) mode.
>>> + *
>>> + * @param port_id
>>> + *   The port identifier of the Ethernet device.
>>> + * @param mode
>>> + *   the FEC mode.
>>> + * @return
>>> + *   - (0) if successful.
>>> + *   - (-EINVAL) if the FEC mode is not valid.
>>> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
>>> + *   - (-EIO) if device is removed.
>>> + *   - (-ENODEV)  if *port_id* invalid.
>>> + */
>>> +__rte_experimental
>>> +int rte_eth_fec_set(uint16_t port_id, enum rte_eth_fec_mode mode);
>>
>> It does not allow to tweak autoneg facilities.
>> E.g. "I know that RS is buggy, so I want to exclude it from
>> auto-negotiation".
>> So, I suggest to change mode to capa bitmask.
>> If AUTO is set, other bits may be set and specify allowed
>> options. E.g. AUTO|RS|BASER will require FEC, i.e. NOFEC is
> The two FEC modes cannot be configured for hardware at the same time,
> including AUTO and other FEC modes. This is determined by Hardware itself.

Which HW? Yours? If so, it does not matter. The patch adds
generic API. My comments are not abstract thoughts. There
are requirements and capabilities behind.

> Thanks.
> 
>> not allowed. If just RS, it means that auto-negotiation is
>> disabled and RS must be used.
>> If AUTO is unset, only one bit may be set in capabilities.
>> Since we don't do it per speed, I think it is safe to ignore
>> unsupported mode bits. I.e. do not return error if unsupported
>> capa is requested to together with AUTO, however it could be
>> a problem if no modes are allowed for negotiated link speed.
>> Thoughts are welcome.
>>
>>> +
>>> +/**
>>>    * Get current status of the Ethernet link flow control for
>>> Ethernet device
>>>    *
>>>    * @param port_id
>>
>> [snip]
>>
>> .
>>
  
humin (Q) Sept. 22, 2020, 11:06 a.m. UTC | #4
在 2020/9/22 16:02, Andrew Rybchenko 写道:
> On 9/22/20 7:58 AM, Min Hu (Connor) wrote:
>>
>>
>> 在 2020/9/21 21:39, Andrew Rybchenko 写道:
>>> On 9/21/20 9:13 AM, Min Hu (Connor) wrote:
>>>> This patch adds Forward error correction(FEC) support for ethdev.
>>>> Introduce APIs which support query and config FEC information in
>>>> hardware.
>>>>
>>>> Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
>>>> Reviewed-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
>>>> Reviewed-by: Chengwen Feng <fengchengwen@huawei.com>
>>>> Reviewed-by: Chengchang Tang <tangchengchang@huawei.com>
>>>> Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
>>>> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
>>>
>>> [snip]
>>>
>>>> diff --git a/lib/librte_ethdev/rte_ethdev.h
>>>> b/lib/librte_ethdev/rte_ethdev.h
>>>> index 70295d7..7d5e81b 100644
>>>> --- a/lib/librte_ethdev/rte_ethdev.h
>>>> +++ b/lib/librte_ethdev/rte_ethdev.h
>>>> @@ -1310,6 +1310,9 @@ struct rte_eth_conf {
>>>>    #define RTE_ETH_DEV_FALLBACK_RX_NBQUEUES 1
>>>>    #define RTE_ETH_DEV_FALLBACK_TX_NBQUEUES 1
>>>>    +/* Translate from FEC mode to FEC capa */
>>>> +#define RTE_ETH_FEC_MODE_TO_CAPA(x)    (1U << (x))
>>>> +
>>>
>>> It should not be so far from rte_eth_fec_mode. Please, add just
>>> after it.
>> I will fix it in V10, thanks.
>>>
>>> May be it should be:
>>> #define RTE_ETH_FEC_MODE_TO_CAPA(x) (1U << (RTE_ETH_FEC_ ## x))
>>>
>> This will be weird, as "x" should be one fec mode。examples
>> as follows:
>>
>> rte_eth_fec_set(uint16_t port_id, enum rte_eth_fec_mode mode)
>> {
>>      struct rte_eth_dev *dev;
>>      uint32_t fec_mode_mask;
>>      int ret;
>>
>>      ret = rte_eth_fec_get_capability(port_id, &fec_mode_mask);
>>      if (ret != 0)
>>          return ret;
>>
>>      /*
>>       * Check whether the configured mode is within the FEC capability.
>>       * If not, the configured mode will not be supported.
>>       */
>>      if (!(fec_mode_mask & RTE_ETH_FEC_MODE_TO_CAPA(mode))) {
>>          RTE_ETHDEV_LOG(ERR, "unsupported FEC mode = %d, port_id = %u\n",
>>                     mode, port_id);
>>          return -EINVAL;
>>      }
> 
> Got it, makes sense.
> 
>> [snip]
>>>>    /**
>>>>     * Preferred Rx/Tx port parameters.
>>>>     * There are separate instances of this structure for transmission
>>>> @@ -1511,6 +1514,24 @@ struct rte_eth_dcb_info {
>>>>        struct rte_eth_dcb_tc_queue_mapping tc_queue;
>>>>    };
>>>>    +/**
>>>> + * This enum indicates the possible (forward error correction)FEC modes
>>>> + * of an ethdev port.
>>>> + */
>>>> +enum rte_eth_fec_mode {
>>>> +    RTE_ETH_FEC_NOFEC = 0,      /**< FEC is off */
>>>> +    RTE_ETH_FEC_AUTO,        /**< FEC autonegotiation modes */
>>>> +    RTE_ETH_FEC_BASER,          /**< FEC using common algorithm */
>>>> +    RTE_ETH_FEC_RS,             /**< FEC using RS algorithm */
>>>> +};
>>>> +
>>>> +/* This indicates FEC capabilities */
>>>> +#define RTE_ETH_FEC_CAPA_NOFEC  (1U << RTE_ETH_FEC_NOFEC)
>>>> +#define RTE_ETH_FEC_CAPA_AUTO   (1U << RTE_ETH_FEC_AUTO)
>>>> +#define RTE_ETH_FEC_CAPA_BASER  (1U << RTE_ETH_FEC_BASER)
>>>> +#define RTE_ETH_FEC_CAPA_RS     (1U << RTE_ETH_FEC_RS)
>>>
>>> Shouldn't RTE_ETH_FEC_MODE_TO_CAPA be used as definition
>>> values?
>>> I will define a new macro as you suggest in V10, like this:
>> /* This macro indicates FEC capa mask*/
>> #define RTE_ETH_FEC_MODE_CAPA_MASK(x)    (1U << (RTE_ETH_FEC_ ## x))
>>
>> that macro will replace the follow macros:
>> #define RTE_ETH_FEC_CAPA_NOFEC  (1U << RTE_ETH_FEC_NOFEC)
>> #define RTE_ETH_FEC_CAPA_AUTO   (1U << RTE_ETH_FEC_AUTO)
>> #define RTE_ETH_FEC_CAPA_BASER  (1U << RTE_ETH_FEC_BASER)
>> #define RTE_ETH_FEC_CAPA_RS     (1U << RTE_ETH_FEC_RS)
>>
>> i.e.:
>> RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC)
>> RTE_ETH_FEC_MODE_CAPA_MASK(AUTO)
>> RTE_ETH_FEC_MODE_CAPA_MASK(BASER)
>> RTE_ETH_FEC_MODE_CAPA_MASK(RS)
>>
>> thanks for your suggestions.
> 
> Thanks for your work on the patchset.
> 
>>
>>>> +
>>>> +
>>>>    #define RTE_ETH_ALL RTE_MAX_ETHPORTS
>>>>      /* Macros to check for valid port */
>>>> @@ -3328,6 +3349,70 @@ int  rte_eth_led_on(uint16_t port_id);
>>>>    int  rte_eth_led_off(uint16_t port_id);
>>>>      /**
>>>> + * @warning
>>>> + * @b EXPERIMENTAL: this API may change, or be removed, without
>>>> prior notice
>>>> + *
>>>> + * Get Forward Error Correction(FEC) capability.
>>>> + *
>>>> + * @param port_id
>>>> + *   The port identifier of the Ethernet device.
>>>> + * @param fec_cap
>>>> + *   returns the FEC capability from the device, as follows:
>>>> + *   RTE_ETH_FEC_CAPA_NOFEC
>>>> + *   RTE_ETH_FEC_CAPA_AUTO
>>>> + *   RTE_ETH_FEC_CAPA_BASER
>>>> + *   RTE_ETH_FEC_CAPA_RS
>>>> + * @return
>>>> + *   - (0) if successful.
>>>> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
>>>> + *     that operation.
>>>> + *   - (-EIO) if device is removed.
>>>> + *   - (-ENODEV)  if *port_id* invalid.
>>>> + */
>>>> +__rte_experimental
>>>> +int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *fec_cap);
>>>
>>> The API does not allow to report capabilities per link speed:
>>> which FEC mode is supported at which link speed?
>>>
>>> What about something like:
>>>
>>> struct rte_eth_fec_capa {
>>>     uint32_t speed; /**< Link speed (see ETH_SPEED_NUM_*) */
>>>     uint32_t capa;  /**< FEC capabilities bitmask (see RTE_FEC_CAPA_*) */
>>> };
>>>
>>> __rte_experimental
>>> int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *num, struct
>>> rte_eth_fec_capa *speed_capa);
>>>
>>> where:
>>>    - num is in/out with a number of elements in an array
>>>    - speed_capa is out only with per-speed capabilities
>>>
>> There is no need to report capabilities per link speed, because
>> relastionship between the link speed and fec mode is fixed. The
>> infomations can be referred to in official documents or internet.
> 
> Should an application download documents and search for it? :)

OK, I will report capabilities per link speed in V11.
By the way,
 >>> where:
 >>>    - num is in/out with a number of elements in an array

could you describe "num" more detailedly, how to use this value?

> 
>>
>> A ethernet port may have various link speed in diffrent situations(for
>> example, optical module with different speed is used). But we do not
>> care about capabilities per link speed. We only care about FEC capa of
>> the ethernet device at a specific moment, because set FEC mode also
>> depend on the current FEC capa.
> 
> Capabilities should not be for a specific moment. Capabilities
> should be fixed and stable (if transceiver is not replaced).
> Capabilities should not depend on a link speed or link status.
> Otherwise an application can't use it in a reliable way.
> 
>>
>> By the way, we can also get link speed of the device by API
>> "rte_eth_link_get" in the same time.
>>
>> thanks.
>>
>>>> +
>>>> +/**
>>>> + * @warning
>>>> + * @b EXPERIMENTAL: this API may change, or be removed, without
>>>> prior notice
>>>> + *
>>>> + * Get current Forward Error Correction(FEC) mode.
>>>> + *
>>>> + * @param port_id
>>>> + *   The port identifier of the Ethernet device.
>>>> + * @param mode
>>>> + *   returns the FEC mode from the device.
>>>> + * @return
>>>> + *   - (0) if successful.
>>>> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
>>>> + *     that operation.
>>>> + *   - (-EIO) if device is removed.
>>>> + *   - (-ENODEV)  if *port_id* invalid.
>>>> + */
>>>> +__rte_experimental
>>>> +int rte_eth_fec_get(uint16_t port_id, enum rte_eth_fec_mode *mode);
>>>
>>> Please, specify what should be reported if link is down.
>>> E.g. if set to RS, but link is down.
>>>
>>> Does AUTO make sense here?
>>>
>> OK, I will add the information in the function header comment:
>> when link down,None AUTO mode(RS, BASER. NOFEC) keep as it is when link
>> up, AUTO mode will change from rs,baser to nofec when quering the mode.
> 
> I'll take a look at the patch, above text is hardly readable.(1). If the current mode of device is one of these modes:
RS, BASER. NOFEC.
when link up, for example, the mode is RS. when the device is linked
down, the mode is always RS.

(2). If the current mode of device is AUTO:
when the device is linked down, the mode varies in this order:
rs->baser->nofec, until Auto-negotiation success (link shoud be
up first).

But this is defined in our hardware. I think the first feature(1) are 
common and can be adopted.

>>
>>
>>>> +
>>>> +/**
>>>> + * @warning
>>>> + * @b EXPERIMENTAL: this API may change, or be removed, without
>>>> prior notice
>>>> + *
>>>> + * Set Forward Error Correction(FEC) mode.
>>>> + *
>>>> + * @param port_id
>>>> + *   The port identifier of the Ethernet device.
>>>> + * @param mode
>>>> + *   the FEC mode.
>>>> + * @return
>>>> + *   - (0) if successful.
>>>> + *   - (-EINVAL) if the FEC mode is not valid.
>>>> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
>>>> + *   - (-EIO) if device is removed.
>>>> + *   - (-ENODEV)  if *port_id* invalid.
>>>> + */
>>>> +__rte_experimental
>>>> +int rte_eth_fec_set(uint16_t port_id, enum rte_eth_fec_mode mode);
>>>
>>> It does not allow to tweak autoneg facilities.
>>> E.g. "I know that RS is buggy, so I want to exclude it from
>>> auto-negotiation".
>>> So, I suggest to change mode to capa bitmask.
>>> If AUTO is set, other bits may be set and specify allowed
>>> options. E.g. AUTO|RS|BASER will require FEC, i.e. NOFEC is
>> The two FEC modes cannot be configured for hardware at the same time,
>> including AUTO and other FEC modes. This is determined by Hardware itself.
> 
> Which HW? Yours? If so, it does not matter. The patch adds
> generic API. My comments are not abstract thoughts. There
> are requirements and capabilities behind.
yes, it is in my HW. But I think the feature of FEC will exist in other 
HW: the two FEC modes cannot be configured for hardware at the same time.
By the way, if set two FEC mode in our HW, the result will be unknown.
I also test X710 nic device, it does not support that feature.
I do not support that solutions. thanks.
>> Thanks.
>>
>>> not allowed. If just RS, it means that auto-negotiation is
>>> disabled and RS must be used.
>>> If AUTO is unset, only one bit may be set in capabilities.
>>> Since we don't do it per speed, I think it is safe to ignore
>>> unsupported mode bits. I.e. do not return error if unsupported
>>> capa is requested to together with AUTO, however it could be
Why? if the mode is unsupported (not in capa),why we can configure
the the mode to the device? Because this is unreaonable. Also,
the configure will not be ineffective, and the hardware will return
error back to the driver.

>>> a problem if no modes are allowed for negotiated link speed.
>>> Thoughts are welcome.
>>>
>>>> +
>>>> +/**
>>>>     * Get current status of the Ethernet link flow control for
>>>> Ethernet device
>>>>     *
>>>>     * @param port_id
>>>
>>> [snip]
>>>
>>> .
>>>
> 
> .
>
  
Andrew Rybchenko Sept. 22, 2020, 12:18 p.m. UTC | #5
On 9/22/20 2:06 PM, Min Hu (Connor) wrote:
> 
> 
> 在 2020/9/22 16:02, Andrew Rybchenko 写道:
>> On 9/22/20 7:58 AM, Min Hu (Connor) wrote:
>>>
>>>
>>> 在 2020/9/21 21:39, Andrew Rybchenko 写道:
>>>> On 9/21/20 9:13 AM, Min Hu (Connor) wrote:
>>>>> This patch adds Forward error correction(FEC) support for ethdev.
>>>>> Introduce APIs which support query and config FEC information in
>>>>> hardware.
>>>>>
>>>>> Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
>>>>> Reviewed-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
>>>>> Reviewed-by: Chengwen Feng <fengchengwen@huawei.com>
>>>>> Reviewed-by: Chengchang Tang <tangchengchang@huawei.com>
>>>>> Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
>>>>> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>

[snip]

>>>>> @@ -3328,6 +3349,70 @@ int  rte_eth_led_on(uint16_t port_id);
>>>>>    int  rte_eth_led_off(uint16_t port_id);
>>>>>      /**
>>>>> + * @warning
>>>>> + * @b EXPERIMENTAL: this API may change, or be removed, without
>>>>> prior notice
>>>>> + *
>>>>> + * Get Forward Error Correction(FEC) capability.
>>>>> + *
>>>>> + * @param port_id
>>>>> + *   The port identifier of the Ethernet device.
>>>>> + * @param fec_cap
>>>>> + *   returns the FEC capability from the device, as follows:
>>>>> + *   RTE_ETH_FEC_CAPA_NOFEC
>>>>> + *   RTE_ETH_FEC_CAPA_AUTO
>>>>> + *   RTE_ETH_FEC_CAPA_BASER
>>>>> + *   RTE_ETH_FEC_CAPA_RS
>>>>> + * @return
>>>>> + *   - (0) if successful.
>>>>> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
>>>>> + *     that operation.
>>>>> + *   - (-EIO) if device is removed.
>>>>> + *   - (-ENODEV)  if *port_id* invalid.
>>>>> + */
>>>>> +__rte_experimental
>>>>> +int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *fec_cap);
>>>>
>>>> The API does not allow to report capabilities per link speed:
>>>> which FEC mode is supported at which link speed?
>>>>
>>>> What about something like:
>>>>
>>>> struct rte_eth_fec_capa {
>>>>     uint32_t speed; /**< Link speed (see ETH_SPEED_NUM_*) */
>>>>     uint32_t capa;  /**< FEC capabilities bitmask (see
>>>> RTE_FEC_CAPA_*) */
>>>> };
>>>>
>>>> __rte_experimental
>>>> int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *num, struct
>>>> rte_eth_fec_capa *speed_capa);
>>>>
>>>> where:
>>>>    - num is in/out with a number of elements in an array
>>>>    - speed_capa is out only with per-speed capabilities
>>>>
>>> There is no need to report capabilities per link speed, because
>>> relastionship between the link speed and fec mode is fixed. The
>>> infomations can be referred to in official documents or internet.
>>
>> Should an application download documents and search for it? :)
> 
> OK, I will report capabilities per link speed in V11.
> By the way,
>>>> where:
>>>>    - num is in/out with a number of elements in an array
> 
> could you describe "num" more detailedly, how to use this value?

On input, num should specify a number of elements in speed_capa
array provided by the caller to get FEC capabilities.
If the number is insufficient to, error should be returned and
the number should contain required number of elements.
If sufficient, on output driver should return a number of
filled in array elements.

>>
>>>
>>> A ethernet port may have various link speed in diffrent situations(for
>>> example, optical module with different speed is used). But we do not
>>> care about capabilities per link speed. We only care about FEC capa of
>>> the ethernet device at a specific moment, because set FEC mode also
>>> depend on the current FEC capa.
>>
>> Capabilities should not be for a specific moment. Capabilities
>> should be fixed and stable (if transceiver is not replaced).
>> Capabilities should not depend on a link speed or link status.
>> Otherwise an application can't use it in a reliable way.
>>
>>>
>>> By the way, we can also get link speed of the device by API
>>> "rte_eth_link_get" in the same time.
>>>
>>> thanks.
>>>
>>>>> +
>>>>> +/**
>>>>> + * @warning
>>>>> + * @b EXPERIMENTAL: this API may change, or be removed, without
>>>>> prior notice
>>>>> + *
>>>>> + * Get current Forward Error Correction(FEC) mode.
>>>>> + *
>>>>> + * @param port_id
>>>>> + *   The port identifier of the Ethernet device.
>>>>> + * @param mode
>>>>> + *   returns the FEC mode from the device.
>>>>> + * @return
>>>>> + *   - (0) if successful.
>>>>> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
>>>>> + *     that operation.
>>>>> + *   - (-EIO) if device is removed.
>>>>> + *   - (-ENODEV)  if *port_id* invalid.
>>>>> + */
>>>>> +__rte_experimental
>>>>> +int rte_eth_fec_get(uint16_t port_id, enum rte_eth_fec_mode *mode);
>>>>
>>>> Please, specify what should be reported if link is down.
>>>> E.g. if set to RS, but link is down.
>>>>
>>>> Does AUTO make sense here?
>>>>
>>> OK, I will add the information in the function header comment:
>>> when link down,None AUTO mode(RS, BASER. NOFEC) keep as it is when link
>>> up, AUTO mode will change from rs,baser to nofec when quering the mode.
>>
>> I'll take a look at the patch, above text is hardly readable.

> (1). If the current mode of device is one of these modes:
> RS, BASER. NOFEC.
> when link up, for example, the mode is RS. when the device is linked
> down, the mode is always RS.

> (2). If the current mode of device is AUTO:
> when the device is linked down, the mode varies in this order:
> rs->baser->nofec, until Auto-negotiation success (link shoud be
> up first).
> 
> But this is defined in our hardware. I think the first feature(1) are
> common and can be adopted.

Sorry, I don't understand.
What abgot 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 (i.e. not AUTO,
either NOFEC, or RS, or BASER).

>>>>> +
>>>>> +/**
>>>>> + * @warning
>>>>> + * @b EXPERIMENTAL: this API may change, or be removed, without
>>>>> prior notice
>>>>> + *
>>>>> + * Set Forward Error Correction(FEC) mode.
>>>>> + *
>>>>> + * @param port_id
>>>>> + *   The port identifier of the Ethernet device.
>>>>> + * @param mode
>>>>> + *   the FEC mode.
>>>>> + * @return
>>>>> + *   - (0) if successful.
>>>>> + *   - (-EINVAL) if the FEC mode is not valid.
>>>>> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
>>>>> + *   - (-EIO) if device is removed.
>>>>> + *   - (-ENODEV)  if *port_id* invalid.
>>>>> + */
>>>>> +__rte_experimental
>>>>> +int rte_eth_fec_set(uint16_t port_id, enum rte_eth_fec_mode mode);
>>>>
>>>> It does not allow to tweak autoneg facilities.
>>>> E.g. "I know that RS is buggy, so I want to exclude it from
>>>> auto-negotiation".
>>>> So, I suggest to change mode to capa bitmask.
>>>> If AUTO is set, other bits may be set and specify allowed
>>>> options. E.g. AUTO|RS|BASER will require FEC, i.e. NOFEC is
>>> The two FEC modes cannot be configured for hardware at the same time,
>>> including AUTO and other FEC modes. This is determined by Hardware
>>> itself.
>>
>> Which HW? Yours? If so, it does not matter. The patch adds
>> generic API. My comments are not abstract thoughts. There
>> are requirements and capabilities behind.
>
> yes, it is in my HW. But I think the feature of FEC will exist in other
> HW: the two FEC modes cannot be configured for hardware at the same time.
> By the way, if set two FEC mode in our HW, the result will be unknown.
> I also test X710 nic device, it does not support that feature.
> I do not support that solutions. thanks.

I'm not trying to say that two FEC modes could be running
simultaneously. I'm trying to say that in the future a PHY
could support more than one FEC mode and autonegotiation
could make a choice which FEC mode to use.
E.g.
NOFEC, FOO and BAR modes supported
set (AUTO|FOO|BAR) will require either FOO or BAR to be
negotiated and does not allow NOFEC.

>>> Thanks.
>>>
>>>> not allowed. If just RS, it means that auto-negotiation is
>>>> disabled and RS must be used.
>>>> If AUTO is unset, only one bit may be set in capabilities.
>>>> Since we don't do it per speed, I think it is safe to ignore
>>>> unsupported mode bits. I.e. do not return error if unsupported
>>>> capa is requested to together with AUTO, however it could be
> Why? if the mode is unsupported (not in capa),why we can configure
> the the mode to the device? Because this is unreaonable. Also,
> the configure will not be ineffective, and the hardware will return
> error back to the driver.

I agree that requested mode should be in capabilities for at
least some speed, but not required to be applicable to
currently negotiated and running speed. May be it is obvious.
I.e. if I set AUTO|NOFEC|RS when capabilities are
25G(NOFEC,AUTO,BASER) and 100G(NOFEC,AUTO,RS), it will
enforce NOFEC for 25G (since BASER is disabled) and allow
either NOFEC or RS for 100G.

>>>> a problem if no modes are allowed for negotiated link speed.
>>>> Thoughts are welcome.
>>>>
>>>>> +
>>>>> +/**
>>>>>     * Get current status of the Ethernet link flow control for
>>>>> Ethernet device
>>>>>     *
>>>>>     * @param port_id
>>>>
>>>> [snip]
>>>>
>>>> .
>>>>
>>
>> .
>>
  
humin (Q) Sept. 24, 2020, 11:07 a.m. UTC | #6
Hi, Andrew,
	I have fixed it about FEC in V11 according to your suggestion.
	could your please check it out.

	thanks.

在 2020/9/22 20:18, Andrew Rybchenko 写道:
> On 9/22/20 2:06 PM, Min Hu (Connor) wrote:
>>
>>
>> 在 2020/9/22 16:02, Andrew Rybchenko 写道:
>>> On 9/22/20 7:58 AM, Min Hu (Connor) wrote:
>>>>
>>>>
>>>> 在 2020/9/21 21:39, Andrew Rybchenko 写道:
>>>>> On 9/21/20 9:13 AM, Min Hu (Connor) wrote:
>>>>>> This patch adds Forward error correction(FEC) support for ethdev.
>>>>>> Introduce APIs which support query and config FEC information in
>>>>>> hardware.
>>>>>>
>>>>>> Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
>>>>>> Reviewed-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
>>>>>> Reviewed-by: Chengwen Feng <fengchengwen@huawei.com>
>>>>>> Reviewed-by: Chengchang Tang <tangchengchang@huawei.com>
>>>>>> Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
>>>>>> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> 
> [snip]
> 
>>>>>> @@ -3328,6 +3349,70 @@ int  rte_eth_led_on(uint16_t port_id);
>>>>>>     int  rte_eth_led_off(uint16_t port_id);
>>>>>>       /**
>>>>>> + * @warning
>>>>>> + * @b EXPERIMENTAL: this API may change, or be removed, without
>>>>>> prior notice
>>>>>> + *
>>>>>> + * Get Forward Error Correction(FEC) capability.
>>>>>> + *
>>>>>> + * @param port_id
>>>>>> + *   The port identifier of the Ethernet device.
>>>>>> + * @param fec_cap
>>>>>> + *   returns the FEC capability from the device, as follows:
>>>>>> + *   RTE_ETH_FEC_CAPA_NOFEC
>>>>>> + *   RTE_ETH_FEC_CAPA_AUTO
>>>>>> + *   RTE_ETH_FEC_CAPA_BASER
>>>>>> + *   RTE_ETH_FEC_CAPA_RS
>>>>>> + * @return
>>>>>> + *   - (0) if successful.
>>>>>> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
>>>>>> + *     that operation.
>>>>>> + *   - (-EIO) if device is removed.
>>>>>> + *   - (-ENODEV)  if *port_id* invalid.
>>>>>> + */
>>>>>> +__rte_experimental
>>>>>> +int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *fec_cap);
>>>>>
>>>>> The API does not allow to report capabilities per link speed:
>>>>> which FEC mode is supported at which link speed?
>>>>>
>>>>> What about something like:
>>>>>
>>>>> struct rte_eth_fec_capa {
>>>>>      uint32_t speed; /**< Link speed (see ETH_SPEED_NUM_*) */
>>>>>      uint32_t capa;  /**< FEC capabilities bitmask (see
>>>>> RTE_FEC_CAPA_*) */
>>>>> };
>>>>>
>>>>> __rte_experimental
>>>>> int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *num, struct
>>>>> rte_eth_fec_capa *speed_capa);
>>>>>
>>>>> where:
>>>>>     - num is in/out with a number of elements in an array
>>>>>     - speed_capa is out only with per-speed capabilities
>>>>>
>>>> There is no need to report capabilities per link speed, because
>>>> relastionship between the link speed and fec mode is fixed. The
>>>> infomations can be referred to in official documents or internet.
>>>
>>> Should an application download documents and search for it? :)
>>
>> OK, I will report capabilities per link speed in V11.
>> By the way,
>>>>> where:
>>>>>      - num is in/out with a number of elements in an array
>>
>> could you describe "num" more detailedly, how to use this value?
> 
> On input, num should specify a number of elements in speed_capa
> array provided by the caller to get FEC capabilities.
> If the number is insufficient to, error should be returned and
> the number should contain required number of elements.
> If sufficient, on output driver should return a number of
> filled in array elements.
> 
>>>
>>>>
>>>> A ethernet port may have various link speed in diffrent situations(for
>>>> example, optical module with different speed is used). But we do not
>>>> care about capabilities per link speed. We only care about FEC capa of
>>>> the ethernet device at a specific moment, because set FEC mode also
>>>> depend on the current FEC capa.
>>>
>>> Capabilities should not be for a specific moment. Capabilities
>>> should be fixed and stable (if transceiver is not replaced).
>>> Capabilities should not depend on a link speed or link status.
>>> Otherwise an application can't use it in a reliable way.
>>>
>>>>
>>>> By the way, we can also get link speed of the device by API
>>>> "rte_eth_link_get" in the same time.
>>>>
>>>> thanks.
>>>>
>>>>>> +
>>>>>> +/**
>>>>>> + * @warning
>>>>>> + * @b EXPERIMENTAL: this API may change, or be removed, without
>>>>>> prior notice
>>>>>> + *
>>>>>> + * Get current Forward Error Correction(FEC) mode.
>>>>>> + *
>>>>>> + * @param port_id
>>>>>> + *   The port identifier of the Ethernet device.
>>>>>> + * @param mode
>>>>>> + *   returns the FEC mode from the device.
>>>>>> + * @return
>>>>>> + *   - (0) if successful.
>>>>>> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
>>>>>> + *     that operation.
>>>>>> + *   - (-EIO) if device is removed.
>>>>>> + *   - (-ENODEV)  if *port_id* invalid.
>>>>>> + */
>>>>>> +__rte_experimental
>>>>>> +int rte_eth_fec_get(uint16_t port_id, enum rte_eth_fec_mode *mode);
>>>>>
>>>>> Please, specify what should be reported if link is down.
>>>>> E.g. if set to RS, but link is down.
>>>>>
>>>>> Does AUTO make sense here?
>>>>>
>>>> OK, I will add the information in the function header comment:
>>>> when link down,None AUTO mode(RS, BASER. NOFEC) keep as it is when link
>>>> up, AUTO mode will change from rs,baser to nofec when quering the mode.
>>>
>>> I'll take a look at the patch, above text is hardly readable.
> 
>> (1). If the current mode of device is one of these modes:
>> RS, BASER. NOFEC.
>> when link up, for example, the mode is RS. when the device is linked
>> down, the mode is always RS.
> 
>> (2). If the current mode of device is AUTO:
>> when the device is linked down, the mode varies in this order:
>> rs->baser->nofec, until Auto-negotiation success (link shoud be
>> up first).
>>
>> But this is defined in our hardware. I think the first feature(1) are
>> common and can be adopted.
> 
> Sorry, I don't understand.
> What abgot 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 (i.e. not AUTO,
> either NOFEC, or RS, or BASER).
> 
>>>>>> +
>>>>>> +/**
>>>>>> + * @warning
>>>>>> + * @b EXPERIMENTAL: this API may change, or be removed, without
>>>>>> prior notice
>>>>>> + *
>>>>>> + * Set Forward Error Correction(FEC) mode.
>>>>>> + *
>>>>>> + * @param port_id
>>>>>> + *   The port identifier of the Ethernet device.
>>>>>> + * @param mode
>>>>>> + *   the FEC mode.
>>>>>> + * @return
>>>>>> + *   - (0) if successful.
>>>>>> + *   - (-EINVAL) if the FEC mode is not valid.
>>>>>> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
>>>>>> + *   - (-EIO) if device is removed.
>>>>>> + *   - (-ENODEV)  if *port_id* invalid.
>>>>>> + */
>>>>>> +__rte_experimental
>>>>>> +int rte_eth_fec_set(uint16_t port_id, enum rte_eth_fec_mode mode);
>>>>>
>>>>> It does not allow to tweak autoneg facilities.
>>>>> E.g. "I know that RS is buggy, so I want to exclude it from
>>>>> auto-negotiation".
>>>>> So, I suggest to change mode to capa bitmask.
>>>>> If AUTO is set, other bits may be set and specify allowed
>>>>> options. E.g. AUTO|RS|BASER will require FEC, i.e. NOFEC is
>>>> The two FEC modes cannot be configured for hardware at the same time,
>>>> including AUTO and other FEC modes. This is determined by Hardware
>>>> itself.
>>>
>>> Which HW? Yours? If so, it does not matter. The patch adds
>>> generic API. My comments are not abstract thoughts. There
>>> are requirements and capabilities behind.
>>
>> yes, it is in my HW. But I think the feature of FEC will exist in other
>> HW: the two FEC modes cannot be configured for hardware at the same time.
>> By the way, if set two FEC mode in our HW, the result will be unknown.
>> I also test X710 nic device, it does not support that feature.
>> I do not support that solutions. thanks.
> 
> I'm not trying to say that two FEC modes could be running
> simultaneously. I'm trying to say that in the future a PHY
> could support more than one FEC mode and autonegotiation
> could make a choice which FEC mode to use.
> E.g.
> NOFEC, FOO and BAR modes supported
> set (AUTO|FOO|BAR) will require either FOO or BAR to be
> negotiated and does not allow NOFEC.
> 
>>>> Thanks.
>>>>
>>>>> not allowed. If just RS, it means that auto-negotiation is
>>>>> disabled and RS must be used.
>>>>> If AUTO is unset, only one bit may be set in capabilities.
>>>>> Since we don't do it per speed, I think it is safe to ignore
>>>>> unsupported mode bits. I.e. do not return error if unsupported
>>>>> capa is requested to together with AUTO, however it could be
>> Why? if the mode is unsupported (not in capa),why we can configure
>> the the mode to the device? Because this is unreaonable. Also,
>> the configure will not be ineffective, and the hardware will return
>> error back to the driver.
> 
> I agree that requested mode should be in capabilities for at
> least some speed, but not required to be applicable to
> currently negotiated and running speed. May be it is obvious.
> I.e. if I set AUTO|NOFEC|RS when capabilities are
> 25G(NOFEC,AUTO,BASER) and 100G(NOFEC,AUTO,RS), it will
> enforce NOFEC for 25G (since BASER is disabled) and allow
> either NOFEC or RS for 100G.
> 
>>>>> a problem if no modes are allowed for negotiated link speed.
>>>>> Thoughts are welcome.
>>>>>
>>>>>> +
>>>>>> +/**
>>>>>>      * Get current status of the Ethernet link flow control for
>>>>>> Ethernet device
>>>>>>      *
>>>>>>      * @param port_id
>>>>>
>>>>> [snip]
>>>>>
>>>>> .
>>>>>
>>>
>>> .
>>>
> 
> .
>
  

Patch

diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index cc72609..e19b037 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -55,6 +55,16 @@  New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Added the FEC API, for a generic FEC query and config.**
+
+  Added the FEC API which provides functions for query FEC capabilities and
+  current FEC mode from device. Also, API for configuring FEC mode is also provided.
+
+* **Added hns3 FEC PMD, for supporting query and config FEC mode.**
+
+  Added the FEC PMD which provides functions for query FEC capabilities and
+  current FEC mode from device. Also, PMD for configuring FEC mode is also provided.
+
 
 Removed Items
 -------------
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 7858ad5..d7cd737 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -3642,6 +3642,55 @@  rte_eth_led_off(uint16_t port_id)
 	return eth_err(port_id, (*dev->dev_ops->dev_led_off)(dev));
 }
 
+int
+rte_eth_fec_get_capability(uint16_t port_id, uint32_t *fec_cap)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->fec_get_capability, -ENOTSUP);
+	return eth_err(port_id, (*dev->dev_ops->fec_get_capability)(dev,
+								fec_cap));
+}
+
+int
+rte_eth_fec_get(uint16_t port_id, enum rte_eth_fec_mode *mode)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->fec_get, -ENOTSUP);
+	return eth_err(port_id, (*dev->dev_ops->fec_get)(dev, mode));
+}
+
+int
+rte_eth_fec_set(uint16_t port_id, enum rte_eth_fec_mode mode)
+{
+	struct rte_eth_dev *dev;
+	uint32_t fec_mode_mask;
+	int ret;
+
+	ret = rte_eth_fec_get_capability(port_id, &fec_mode_mask);
+	if (ret != 0)
+		return ret;
+
+	/*
+	 * Check whether the configured mode is within the FEC capability.
+	 * If not, the configured mode will not be supported.
+	 */
+	if (!(fec_mode_mask & RTE_ETH_FEC_MODE_TO_CAPA(mode))) {
+		RTE_ETHDEV_LOG(ERR, "unsupported FEC mode = %d, port_id = %u\n",
+			       mode, port_id);
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->fec_set, -ENOTSUP);
+	return eth_err(port_id, (*dev->dev_ops->fec_set)(dev, mode));
+}
+
 /*
  * Returns index into MAC address array of addr. Use 00:00:00:00:00:00 to find
  * an empty spot.
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index 70295d7..7d5e81b 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1310,6 +1310,9 @@  struct rte_eth_conf {
 #define RTE_ETH_DEV_FALLBACK_RX_NBQUEUES 1
 #define RTE_ETH_DEV_FALLBACK_TX_NBQUEUES 1
 
+/* Translate from FEC mode to FEC capa */
+#define RTE_ETH_FEC_MODE_TO_CAPA(x)	(1U << (x))
+
 /**
  * Preferred Rx/Tx port parameters.
  * There are separate instances of this structure for transmission
@@ -1511,6 +1514,24 @@  struct rte_eth_dcb_info {
 	struct rte_eth_dcb_tc_queue_mapping tc_queue;
 };
 
+/**
+ * This enum indicates the possible (forward error correction)FEC modes
+ * of an ethdev port.
+ */
+enum rte_eth_fec_mode {
+	RTE_ETH_FEC_NOFEC = 0,      /**< FEC is off */
+	RTE_ETH_FEC_AUTO,	    /**< FEC autonegotiation modes */
+	RTE_ETH_FEC_BASER,          /**< FEC using common algorithm */
+	RTE_ETH_FEC_RS,             /**< FEC using RS algorithm */
+};
+
+/* This indicates FEC capabilities */
+#define RTE_ETH_FEC_CAPA_NOFEC  (1U << RTE_ETH_FEC_NOFEC)
+#define RTE_ETH_FEC_CAPA_AUTO   (1U << RTE_ETH_FEC_AUTO)
+#define RTE_ETH_FEC_CAPA_BASER  (1U << RTE_ETH_FEC_BASER)
+#define RTE_ETH_FEC_CAPA_RS     (1U << RTE_ETH_FEC_RS)
+
+
 #define RTE_ETH_ALL RTE_MAX_ETHPORTS
 
 /* Macros to check for valid port */
@@ -3328,6 +3349,70 @@  int  rte_eth_led_on(uint16_t port_id);
 int  rte_eth_led_off(uint16_t port_id);
 
 /**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get Forward Error Correction(FEC) capability.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param fec_cap
+ *   returns the FEC capability from the device, as follows:
+ *   RTE_ETH_FEC_CAPA_NOFEC
+ *   RTE_ETH_FEC_CAPA_AUTO
+ *   RTE_ETH_FEC_CAPA_BASER
+ *   RTE_ETH_FEC_CAPA_RS
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ */
+__rte_experimental
+int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *fec_cap);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get current Forward Error Correction(FEC) mode.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param mode
+ *   returns the FEC mode from the device.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ */
+__rte_experimental
+int rte_eth_fec_get(uint16_t port_id, enum rte_eth_fec_mode *mode);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Set Forward Error Correction(FEC) mode.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param mode
+ *   the FEC mode.
+ * @return
+ *   - (0) if successful.
+ *   - (-EINVAL) if the FEC mode is not valid.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ */
+__rte_experimental
+int rte_eth_fec_set(uint16_t port_id, enum rte_eth_fec_mode mode);
+
+/**
  * Get current status of the Ethernet link flow control for Ethernet device
  *
  * @param port_id
diff --git a/lib/librte_ethdev/rte_ethdev_core.h b/lib/librte_ethdev/rte_ethdev_core.h
index 32407dd..755a15a 100644
--- a/lib/librte_ethdev/rte_ethdev_core.h
+++ b/lib/librte_ethdev/rte_ethdev_core.h
@@ -604,6 +604,78 @@  typedef int (*eth_tx_hairpin_queue_setup_t)
 	 const struct rte_eth_hairpin_conf *hairpin_conf);
 
 /**
+ * @internal
+ * Get Forward Error Correction(FEC) capability.
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param fec_cap
+ *   returns the FEC capability from the device.
+ *
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success, get FEC success.
+ * @retval -ENOTSUP
+ *   operation is not supported.
+ * @retval -EIO
+ *   device is removed.
+ * @retval -ENODEV
+ *   Device is gone.
+ */
+typedef int (*eth_fec_get_capability_t)(struct rte_eth_dev *dev,
+					uint32_t *fec_cap);
+
+/**
+ * @internal
+ * Get Forward Error Correction(FEC) mode.
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param mode
+ *   returns the FEC mode from the device.
+ *
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success, get FEC success.
+ * @retval -ENOTSUP
+ *   operation is not supported.
+ * @retval -EIO
+ *   device is removed.
+ * @retval -ENODEV
+ *   Device is gone.
+ */
+typedef int (*eth_fec_get_t)(struct rte_eth_dev *dev,
+			     enum rte_eth_fec_mode *mode);
+
+/**
+ * @internal
+ *   Set Forward Error Correction(FEC) mode.
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param mode
+ *   the FEC mode.
+ *
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success, set FEC success.
+ * @retval -ENOTSUP
+ *   operation is not supported.
+ * @retval -EIO
+ *   device is removed.
+ * @retval -ENODEV
+ *   Device is gone.
+ */
+typedef int (*eth_fec_set_t)(struct rte_eth_dev *dev,
+			     enum rte_eth_fec_mode mode);
+
+/**
  * @internal A structure containing the functions exported by an Ethernet driver.
  */
 struct eth_dev_ops {
@@ -752,6 +824,13 @@  struct eth_dev_ops {
 	/**< Set up device RX hairpin queue. */
 	eth_tx_hairpin_queue_setup_t tx_hairpin_queue_setup;
 	/**< Set up device TX hairpin queue. */
+
+	eth_fec_get_capability_t fec_get_capability;
+	/**< Get Forward Error Correction(FEC) capability; */
+	eth_fec_get_t fec_get;
+	/**< Get Forward Error Correction(FEC) mode; */
+	eth_fec_set_t fec_set;
+	/**< Set Forward Error Correction(FEC) mode; */
 };
 
 /**
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index 02081d9..9f3fb8f 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -239,6 +239,11 @@  EXPERIMENTAL {
 	__rte_ethdev_trace_rx_burst;
 	__rte_ethdev_trace_tx_burst;
 	rte_flow_get_aged_flows;
+
+	# added in 20.11
+	rte_eth_fec_get_capability;
+	rte_eth_fec_get;
+	rte_eth_fec_set;
 };
 
 INTERNAL {