DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [RFC] ethdev: add Forward Error Correction support
@ 2020-08-28 11:32 Min Hu(Connor)
  2020-08-30 12:43 ` Andrew Rybchenko
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
  0 siblings, 2 replies; 118+ messages in thread
From: Min Hu(Connor) @ 2020-08-28 11:32 UTC (permalink / raw)
  To: dev; +Cc: thomas, arybchenko, ferruh.yigit, linuxarm

Hi All,

I would like to add FEC support of ethdev for DPDK.
I am planning to add this support in v20.11 release.

This RFC attempts to get feedback from the community.

In current DPDK version, Forward Error Correction(FEC) is not
supported.

Forward error correction (FEC) is a bit error correction mode.
It adds error correction information to data packets at the
transmit end, and uses the error correction information to correct
the bit errors generated during data packet transmission at the
receive end. This improves signal quality but also brings a delay
to signals. You can enable or disable this function as required.

To enable FEC support in DPDK, following items need to work out:
a) Add three API:
	rte_eth_fec_get_capability
	rte_eth_fec_get
	rte_eth_fec_set

b) Add new data structure:
	enum rte_fec_mode {
		ETH_FEC_NOFEC,
		ETH_FEC_BASER,
		ETH_FEC_RS,
		ETH_FEC_AUTO
	};

c) Add items in "struct eth_dev_ops":
	struct eth_dev_ops {
	+	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; */
 };

The details are as follows:
---
 lib/librte_ethdev/rte_ethdev.c      | 33 +++++++++++++++++++
 lib/librte_ethdev/rte_ethdev.h      | 52 +++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_core.h | 65 +++++++++++++++++++++++++++++++++++++
 3 files changed, 150 insertions(+)

diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 7858ad5..0a96718 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -3642,6 +3642,39 @@ rte_eth_led_off(uint16_t port_id)
 	return eth_err(port_id, (*dev->dev_ops->dev_led_off)(dev));
 }
 
+void
+rte_eth_fec_get_capability(uint16_t port_id, int *mode_mask)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_RET(port_id);
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_RET(*dev->dev_ops->fec_get_capability);
+	(*dev->dev_ops->fec_get_capability)(dev, mode_mask);
+}
+
+int
+rte_eth_fec_get(uint16_t port_id, enum rte_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_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_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..ff82771 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1511,6 +1511,17 @@ struct rte_eth_dcb_info {
 	struct rte_eth_dcb_tc_queue_mapping tc_queue;
 };
 
+/**
+ * This enum indicates the possible FEC modes
+ * of an ethdev port.
+ */
+enum rte_fec_mode {
+	ETH_FEC_NOFEC,
+	ETH_FEC_BASER,
+	ETH_FEC_RS,
+	ETH_FEC_AUTO
+};
+
 #define RTE_ETH_ALL RTE_MAX_ETHPORTS
 
 /* Macros to check for valid port */
@@ -3328,6 +3339,47 @@ int  rte_eth_led_on(uint16_t port_id);
 int  rte_eth_led_off(uint16_t port_id);
 
 /**
+ * Get Forward Error Correction(FEC) capability.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param mode_mask
+ *   returns the FEC capability from the device.
+ */
+void rte_eth_fec_get_capability(uint16_t port_id, int *mode_mask);
+
+/**
+ * Get 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.
+ *   - (-EBUSY) if device is in resetting.
+ *   - (-ENOMEM) if device unable to allocate resources.
+ */
+int rte_eth_fec_get(uint16_t port_id, enum rte_fec_mode *mode);
+
+/**
+ * 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.
+ *   - (-EBUSY) if device is in resetting.
+ *   - (-ENOMEM) if device unable to allocate resources.
+ */
+int rte_eth_fec_set(uint16_t port_id, enum rte_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..1f2c414 100644
--- a/lib/librte_ethdev/rte_ethdev_core.h
+++ b/lib/librte_ethdev/rte_ethdev_core.h
@@ -604,6 +604,64 @@ 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 mode_mask
+ *   returns the FEC capability from the device.
+ */
+typedef void (*eth_fec_get_capability_t)(struct rte_eth_dev *dev,
+					   int *mode_mask);
+
+/**
+ * @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 -EOPNOTSUPP
+ *   opreation is not supported.
+ * @retval -EBUSY
+ *   detect device is in resetting
+ * @retval -ENOMEM
+ *   Unable to allocate resources.
+ */
+typedef int (*eth_fec_get_t)(struct rte_eth_dev *dev, enum rte_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 -EINVAL
+ *   the FEC mode is not valid.
+ * @retval -EBUSY
+ *   detect device is in resetting
+ * @retval -ENOMEM
+ *   Unable to allocate resources.
+ */
+typedef int (*eth_fec_set_t)(struct rte_eth_dev *dev, enum rte_fec_mode mode);
+
+/**
  * @internal A structure containing the functions exported by an Ethernet driver.
  */
 struct eth_dev_ops {
@@ -752,6 +810,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; */
 };
 
 /**
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [RFC] ethdev: add Forward Error Correction support
  2020-08-28 11:32 [dpdk-dev] [RFC] ethdev: add Forward Error Correction support Min Hu(Connor)
@ 2020-08-30 12:43 ` Andrew Rybchenko
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
  1 sibling, 0 replies; 118+ messages in thread
From: Andrew Rybchenko @ 2020-08-30 12:43 UTC (permalink / raw)
  To: Min Hu(Connor), dev; +Cc: thomas, ferruh.yigit, linuxarm

On 8/28/20 2:32 PM, Min Hu(Connor) wrote:
> Hi All,
> 
> I would like to add FEC support of ethdev for DPDK.
> I am planning to add this support in v20.11 release.
> 
> This RFC attempts to get feedback from the community.
> 
> In current DPDK version, Forward Error Correction(FEC) is not
> supported.
> 
> Forward error correction (FEC) is a bit error correction mode.
> It adds error correction information to data packets at the
> transmit end, and uses the error correction information to correct
> the bit errors generated during data packet transmission at the
> receive end. This improves signal quality but also brings a delay
> to signals. You can enable or disable this function as required.
> 
> To enable FEC support in DPDK, following items need to work out:
> a) Add three API:
> 	rte_eth_fec_get_capability
> 	rte_eth_fec_get
> 	rte_eth_fec_set
> 
> b) Add new data structure:
> 	enum rte_fec_mode {
> 		ETH_FEC_NOFEC,
> 		ETH_FEC_BASER,
> 		ETH_FEC_RS,
> 		ETH_FEC_AUTO
> 	};
> 
> c) Add items in "struct eth_dev_ops":
> 	struct eth_dev_ops {
> 	+	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; */
>  };
> 
> The details are as follows:

1. New API should be experimental with corresponding markup.

2. FEC capabilities may depend on link speed if I'm not
   mistaken and it should be properly reported in capabilities.

3. Hopefully Ferruh's patches will make the dev_ops structure
   ethdev internal and these additions could be done in 20.11.

4. Format in mode_mask is not defined below.

^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH 0/3] add FEC support
  2020-08-28 11:32 [dpdk-dev] [RFC] ethdev: add Forward Error Correction support Min Hu(Connor)
  2020-08-30 12:43 ` Andrew Rybchenko
@ 2020-09-08  3:05 ` Min Hu (Connor)
  2020-09-08  3:05   ` [dpdk-dev] [PATCH 1/3] ethdev: introduce FEC API Min Hu (Connor)
                     ` (16 more replies)
  1 sibling, 17 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-08  3:05 UTC (permalink / raw)
  To: dev; +Cc: thomas, arybchenko, ferruh.yigit, linuxarm

This series add FEC support for ethdev.

Min Hu (Connor) (3):
  ethdev: introduce FEC API
  net/hns3: support FEC
  app/testpmd: add FEC command

 app/test-pmd/cmdline.c                   | 206 +++++++++++++++++++++++++++++++
 app/test-pmd/config.c                    |  54 ++++++++
 app/test-pmd/testpmd.h                   |   2 +
 drivers/net/hns3/hns3_cmd.h              |  19 ++-
 drivers/net/hns3/hns3_ethdev.c           | 154 +++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h           |   1 +
 lib/librte_ethdev/rte_ethdev.c           |  50 ++++++++
 lib/librte_ethdev/rte_ethdev.h           |  74 +++++++++++
 lib/librte_ethdev/rte_ethdev_core.h      |  77 ++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |   5 +
 10 files changed, 641 insertions(+), 1 deletion(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH 1/3] ethdev: introduce FEC API
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
@ 2020-09-08  3:05   ` Min Hu (Connor)
  2020-09-09  2:42     ` [dpdk-dev] [PATCH V2 0/3] add FEC support Min Hu (Connor)
  2020-09-08  3:05   ` [dpdk-dev] [PATCH 2/3] net/hns3: support FEC Min Hu (Connor)
                     ` (15 subsequent siblings)
  16 siblings, 1 reply; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-08  3:05 UTC (permalink / raw)
  To: dev; +Cc: thomas, arybchenko, ferruh.yigit, linuxarm

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>
---
 lib/librte_ethdev/rte_ethdev.c           | 50 +++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev.h           | 74 ++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_core.h      | 77 ++++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |  5 +++
 4 files changed, 206 insertions(+)

diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 7858ad5..b7ac791 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -3642,6 +3642,56 @@ 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, uint8_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_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_fec_mode mode)
+{
+	struct rte_eth_dev *dev;
+	uint8_t fec_mode_mask;
+	int ret;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	ret = rte_eth_fec_get_capability(port_id, &fec_mode_mask);
+	if (ret)
+		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 & (1U << (uint8_t)mode))) {
+		RTE_ETHDEV_LOG(ERR, "unsupported fec mode=%d\n", mode);
+		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..23e069a 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1511,6 +1511,17 @@ 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_fec_mode {
+	ETH_FEC_NOFEC = 0,      /**< FEC is off */
+	ETH_FEC_BASER,          /**< FEC using common algorithm */
+	ETH_FEC_RS,             /**< FEC using RS algorithm */
+	ETH_FEC_AUTO            /**< FEC autonegotiation modes */
+};
+
 #define RTE_ETH_ALL RTE_MAX_ETHPORTS
 
 /* Macros to check for valid port */
@@ -3328,6 +3339,69 @@ 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:
+ *   bit0: nofec
+ *   bit1: baser
+ *   bit2: rs
+ *   bit3: auto
+ * @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, uint8_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_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.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ */
+__rte_experimental
+int rte_eth_fec_set(uint16_t port_id, enum rte_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..efd9dc5 100644
--- a/lib/librte_ethdev/rte_ethdev_core.h
+++ b/lib/librte_ethdev/rte_ethdev_core.h
@@ -604,6 +604,76 @@ 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 -EOPNOTSUPP
+ *   opreation 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,
+					uint8_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 -EOPNOTSUPP
+ *   opreation 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_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 -EOPNOTSUPP
+ *   opreation 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_fec_mode mode);
+
+/**
  * @internal A structure containing the functions exported by an Ethernet driver.
  */
 struct eth_dev_ops {
@@ -752,6 +822,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 1212a17..33cf5e4 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -241,6 +241,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 {
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH 2/3] net/hns3: support FEC
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
  2020-09-08  3:05   ` [dpdk-dev] [PATCH 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-08  3:05   ` Min Hu (Connor)
  2020-09-08  3:05   ` [dpdk-dev] [PATCH 3/3] app/testpmd: add FEC command Min Hu (Connor)
                     ` (14 subsequent siblings)
  16 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-08  3:05 UTC (permalink / raw)
  To: dev; +Cc: thomas, arybchenko, ferruh.yigit, linuxarm

Forward error correction (FEC) is a bit error correction mode.
It adds error correction information to data packets at the
transmit end, and uses the error correction information to correct
the bit errors generated during data packet transmission at the
receive end. This improves signal quality but also brings a delay
to signals. This function can be enabled or disabled as required.

This patch adds FEC support for ethdev.Introduce ethdev
operations 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>
---
 drivers/net/hns3/hns3_cmd.h    |  19 ++++-
 drivers/net/hns3/hns3_ethdev.c | 154 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h |   1 +
 3 files changed, 173 insertions(+), 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index d70f42e..8b80353 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -99,6 +99,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_CONFIG_MAX_FRM_SIZE    = 0x0308,
 	HNS3_OPC_CONFIG_SPEED_DUP       = 0x0309,
 	HNS3_MAC_COMMON_INT_EN          = 0x030E,
+	HNS3_OPC_CONFIG_FEC_MODE        = 0x031A,
 
 	/* PFC/Pause commands */
 	HNS3_OPC_CFG_MAC_PAUSE_EN       = 0x0701,
@@ -653,9 +654,25 @@ struct hns3_config_auto_neg_cmd {
 	uint8_t   rsv[20];
 };
 
+#define HNS3_MAC_CFG_FEC_AUTO_EN_B	0
+#define HNS3_MAC_CFG_FEC_MODE_S		1
+#define HNS3_MAC_CFG_FEC_MODE_M	GENMASK(3, 1)
+#define HNS3_MAC_FEC_OFF		0
+#define HNS3_MAC_FEC_BASER		1
+#define HNS3_MAC_FEC_RS			2
+
 struct hns3_sfp_speed_cmd {
 	uint32_t  sfp_speed;
-	uint32_t  rsv[5];
+	uint8_t   query_type; /* 0: sfp speed, 1: active fec */
+	uint8_t   active_fec; /* current FEC mode */
+	uint16_t  rsv1;
+	uint32_t  rsv2[4];
+};
+
+/* Configure FEC mode, opcode:0x031A */
+struct hns3_config_fec_cmd {
+	uint8_t fec_mode;
+	uint8_t rsv[23];
 };
 
 #define HNS3_MAC_MGR_MASK_VLAN_B		BIT(0)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 81e7730..bbaff54 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -78,6 +78,8 @@ static int hns3_add_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
 static int hns3_remove_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
+static int hns3_restore_fec(struct hns3_hw *hw);
+static int hns3_query_dev_fec_info(struct rte_eth_dev *dev);
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -2819,6 +2821,13 @@ hns3_get_capability(struct hns3_hw *hw)
 	    device_id == HNS3_DEV_ID_200G_RDMA)
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_DCB_B, 1);
 
+	ret = hns3_query_dev_fec_info(eth_dev);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			     "failed to query FEC information, ret = %d", ret);
+		return ret;
+	}
+
 	/* Get PCI revision id */
 	ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN,
 				  HNS3_PCI_REVISION_ID);
@@ -5311,6 +5320,10 @@ hns3_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_promisc;
 
+	ret = hns3_restore_fec(hw);
+	if (ret)
+		goto err_promisc;
+
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED) {
 		ret = hns3_do_start(hns, false);
 		if (ret)
@@ -5389,6 +5402,144 @@ hns3_reset_service(void *param)
 		hns3_msix_process(hns, reset_level);
 }
 
+static int
+hns3_fec_get_capability(struct rte_eth_dev *dev, uint8_t *fec_cap)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_mac *mac = &hw->mac;
+	uint8_t mode;
+
+	switch (mac->link_speed) {
+	case ETH_SPEED_NUM_10G:
+	case ETH_SPEED_NUM_40G:
+		mode = BIT(ETH_FEC_NOFEC) | BIT(ETH_FEC_BASER) |
+			BIT(ETH_FEC_AUTO);
+		break;
+	case ETH_SPEED_NUM_25G:
+	case ETH_SPEED_NUM_50G:
+		mode = BIT(ETH_FEC_NOFEC) | BIT(ETH_FEC_BASER) |
+			BIT(ETH_FEC_RS) | BIT(ETH_FEC_AUTO);
+		break;
+	case ETH_SPEED_NUM_100G:
+	case ETH_SPEED_NUM_200G:
+		mode = BIT(ETH_FEC_NOFEC) | BIT(ETH_FEC_RS) | BIT(ETH_FEC_AUTO);
+		break;
+	default:
+		mode = 0;
+		break;
+	}
+
+	*fec_cap = mode;
+	return 0;
+}
+
+static int
+hns3_fec_get(struct rte_eth_dev *dev, enum rte_fec_mode *mode)
+{
+#define QUERY_ACTIVE_SPEED	1
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_sfp_speed_cmd *resp;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_SFP_GET_SPEED, true);
+	resp = (struct hns3_sfp_speed_cmd *)desc.data;
+	resp->query_type = QUERY_ACTIVE_SPEED;
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret == -EOPNOTSUPP) {
+		hns3_err(hw, "IMP do not support get FEC, ret = %d", ret);
+		return ret;
+	} else if (ret) {
+		hns3_err(hw, "get FEC failed, ret = %d", ret);
+		return ret;
+	}
+
+	*mode = resp->active_fec;
+	return 0;
+}
+
+static int
+hns3_set_fec_hw(struct hns3_hw *hw, enum rte_fec_mode mode)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, false);
+
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	switch (mode) {
+	case ETH_FEC_NOFEC:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_OFF);
+		break;
+	case ETH_FEC_BASER:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_BASER);
+		break;
+	case ETH_FEC_RS:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_RS);
+		break;
+	case ETH_FEC_AUTO:
+		hns3_set_bit(req->fec_mode, HNS3_MAC_CFG_FEC_AUTO_EN_B, 1);
+		break;
+	default:
+		return 0;
+	}
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw, "set fec mode failed, ret = %d", ret);
+
+	return 0;
+}
+
+static int
+hns3_fec_set(struct rte_eth_dev *dev, enum rte_fec_mode mode)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		return ret;
+
+	pf->fec_mode = mode;
+	return 0;
+}
+
+static int
+hns3_restore_fec(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+	enum rte_fec_mode mode = pf->fec_mode;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		hns3_err(hw, "restore fec mode(%d) failed, ret = %d",
+			 mode, ret);
+
+	return ret;
+}
+
+static int
+hns3_query_dev_fec_info(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_fec_get(dev, &pf->fec_mode);
+	if (ret)
+		return ret;
+
+	return 0;
+}
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_start          = hns3_dev_start,
 	.dev_stop           = hns3_dev_stop,
@@ -5434,6 +5585,9 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.get_reg                = hns3_get_regs,
 	.get_dcb_info           = hns3_get_dcb_info,
 	.dev_supported_ptypes_get = hns3_dev_supported_ptypes_get,
+	.fec_get_capability     = hns3_fec_get_capability,
+	.fec_get                = hns3_fec_get,
+	.fec_set                = hns3_fec_set,
 };
 
 static const struct hns3_reset_ops hns3_reset_ops = {
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 0e665e5..daf723e 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -510,6 +510,7 @@ struct hns3_pf {
 	struct hns3_err_msix_intr_stats abn_int_stats;
 
 	bool support_sfp_query;
+	enum rte_fec_mode fec_mode; /* current FEC mode for ethdev */
 
 	struct hns3_vtag_cfg vtag_config;
 	LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH 3/3] app/testpmd: add FEC command
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
  2020-09-08  3:05   ` [dpdk-dev] [PATCH 1/3] ethdev: introduce FEC API Min Hu (Connor)
  2020-09-08  3:05   ` [dpdk-dev] [PATCH 2/3] net/hns3: support FEC Min Hu (Connor)
@ 2020-09-08  3:05   ` Min Hu (Connor)
  2020-09-10  7:24   ` [dpdk-dev] [PATCH V4 0/3] add FEC support Min Hu (Connor)
                     ` (13 subsequent siblings)
  16 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-08  3:05 UTC (permalink / raw)
  To: dev; +Cc: thomas, arybchenko, ferruh.yigit, linuxarm

This commit adds testpmd capability to query and config FEC
function of device. This includes:
- show FEC capabilities, example:
	testpmd> show port 0 fec capabilities
- show FEC mode, example:
	testpmd> show port 0 fec_mode
- config FEC mode, example:
	testpmd> set port <port_id> 0 <auto|off|rs|baser>

	where:

	auto|off|rs|baser are four kinds of FEC mode which dev
	support according to MAC link speed.

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>
---
 app/test-pmd/cmdline.c | 206 +++++++++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c  |  54 +++++++++++++
 app/test-pmd/testpmd.h |   2 +
 3 files changed, 262 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0a6ed85..71b2711 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -19054,6 +19054,209 @@ cmdline_parse_inst_t cmd_show_tx_metadata = {
 	},
 };
 
+/* *** show fec capability per port configuration *** */
+struct cmd_show_fec_capability_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_fec;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_capability_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+	struct cmd_show_fec_capability_result *res = parsed_result;
+	uint8_t fec_cap;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_fec_get_capability(res->cmd_pid, &fec_cap);
+	if (ret < 0)
+		return;
+
+	show_fec_capability(fec_cap);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_capability_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_capability_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_capability_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_capability_fec =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_fec, "fec");
+cmdline_parse_token_string_t cmd_show_fec_capability_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_keyword, "capabilities");
+
+cmdline_parse_inst_t cmd_show_capability = {
+	.f = cmd_show_fec_capability_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec capabilities",
+	.tokens = {
+		(void *)&cmd_show_fec_capability_show,
+		(void *)&cmd_show_fec_capability_port,
+		(void *)&cmd_show_fec_capability_pid,
+		(void *)&cmd_show_fec_capability_fec,
+		(void *)&cmd_show_fec_capability_keyword,
+		NULL,
+	},
+};
+
+/* *** show fec mode per port configuration *** */
+struct cmd_show_fec_metadata_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_mode_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_NAME_SIZE 16
+	struct cmd_show_fec_metadata_result *res = parsed_result;
+	enum rte_fec_mode mode;
+	char buf[FEC_NAME_SIZE];
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+	ret = rte_eth_fec_get(res->cmd_pid, &mode);
+	if (ret < 0)
+		return;
+
+	switch (mode) {
+	case ETH_FEC_NOFEC:
+		strlcpy(buf, "off", sizeof(buf));
+		break;
+	case ETH_FEC_BASER:
+		strlcpy(buf, "baser", sizeof(buf));
+		break;
+	case ETH_FEC_RS:
+		strlcpy(buf, "rs", sizeof(buf));
+		break;
+	case ETH_FEC_AUTO:
+		strlcpy(buf, "auto", sizeof(buf));
+		break;
+	default:
+		return;
+	}
+
+	printf("%s\n", buf);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_mode_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_mode_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_mode_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_mode_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_keyword, "fec_mode");
+
+cmdline_parse_inst_t cmd_show_fec_mode = {
+	.f = cmd_show_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec_mode",
+	.tokens = {
+		(void *)&cmd_show_fec_mode_show,
+		(void *)&cmd_show_fec_mode_port,
+		(void *)&cmd_show_fec_mode_pid,
+		(void *)&cmd_show_fec_mode_keyword,
+		NULL,
+	},
+};
+
+/* *** set fec mode per port configuration *** */
+struct cmd_set_port_fec_mode {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t fec_mode;
+	cmdline_fixed_string_t fec_value;
+};
+
+/* Common CLI fields for set fec mode */
+cmdline_parse_token_string_t cmd_set_port_fec_mode_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port, "port");
+cmdline_parse_token_num_t cmd_set_port_fec_mode_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_port_fec_mode_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_mode, "fec_mode");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_value =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_value, NULL);
+
+static void
+cmd_set_port_fec_mode_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	__rte_unused void *data)
+{
+	struct cmd_set_port_fec_mode *res = parsed_result;
+	uint16_t port_id = res->port_id;
+	enum rte_fec_mode mode;
+	int ret;
+
+	ret = parse_fec_mode(res->fec_value, &mode);
+	if (ret < 0) {
+		printf("Unknown fec mode: %s for Port %d", res->fec_value,
+			port_id);
+		return;
+	}
+
+	ret = rte_eth_fec_set(port_id, mode);
+	if (ret < 0) {
+		printf("Set fec mode for Port %d failed\n", port_id);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_fec_mode = {
+	.f = cmd_set_port_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> fec_mode <auto|off|rs|baser>",
+	.tokens = {
+		(void *)&cmd_set_port_fec_mode_set,
+		(void *)&cmd_set_port_fec_mode_port,
+		(void *)&cmd_set_port_fec_mode_port_id,
+		(void *)&cmd_set_port_fec_mode_str,
+		(void *)&cmd_set_port_fec_mode_value,
+		NULL,
+	},
+};
+
 /* show port supported ptypes */
 
 /* Common result structure for show port ptypes */
@@ -19685,6 +19888,9 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_set_raw,
 	(cmdline_parse_inst_t *)&cmd_show_set_raw_all,
 	(cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
+	(cmdline_parse_inst_t *)&cmd_show_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_set_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_show_capability,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 30bee33..8f996af 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -138,6 +138,28 @@ const struct rss_type_info rss_type_table[] = {
 	{ NULL, 0 },
 };
 
+static const struct {
+	enum rte_fec_mode mode;
+	const char *name;
+} fec_mode_name[] = {
+	{
+		.mode = ETH_FEC_NOFEC,
+		.name = "off",
+	},
+	{
+		.mode = ETH_FEC_BASER,
+		.name = "baser",
+	},
+	{
+		.mode = ETH_FEC_RS,
+		.name = "rs",
+	},
+	{
+		.mode = ETH_FEC_AUTO,
+		.name = "auto",
+	},
+};
+
 static void
 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
 {
@@ -2967,6 +2989,38 @@ set_tx_pkt_split(const char *name)
 	printf("unknown value: \"%s\"\n", name);
 }
 
+int
+parse_fec_mode(const char *name, enum rte_fec_mode *mode)
+{
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(fec_mode_name); i++) {
+		if (strcmp(fec_mode_name[i].name, name) == 0) {
+			*mode = fec_mode_name[i].mode;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void
+show_fec_capability(uint8_t fec_cap)
+{
+	uint8_t i;
+
+	if (fec_cap == 0) {
+		printf("FEC is not supported\n");
+		return;
+	}
+
+	printf("FEC capabilities:\n");
+	for (i = ETH_FEC_BASER; i <= ETH_FEC_AUTO; i++) {
+		if (fec_cap & 1U << i)
+			printf("%s ", fec_mode_name[i].name);
+	}
+	printf("\n");
+}
+
 void
 show_tx_pkt_segments(void)
 {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 25a12b1..7ab91ad 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -778,6 +778,8 @@ void show_tx_pkt_segments(void);
 void set_tx_pkt_times(unsigned int *tx_times);
 void show_tx_pkt_times(void);
 void set_tx_pkt_split(const char *name);
+int parse_fec_mode(const char *name, enum rte_fec_mode *mode);
+void show_fec_capability(uint8_t fec_cap);
 void set_nb_pkt_per_burst(uint16_t pkt_burst);
 char *list_pkt_forwarding_modes(void);
 char *list_pkt_forwarding_retry_modes(void);
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V2 0/3] add FEC support
  2020-09-08  3:05   ` [dpdk-dev] [PATCH 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-09  2:42     ` Min Hu (Connor)
  2020-09-09  2:42       ` [dpdk-dev] [PATCH V2 1/3] ethdev: introduce FEC API Min Hu (Connor)
                         ` (2 more replies)
  0 siblings, 3 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-09  2:42 UTC (permalink / raw)
  To: dev; +Cc: thomas, arybchenko, ferruh.yigit, linuxarm

This series add FEC support for ethdev.

Min Hu (Connor) (3):
  ethdev: introduce FEC API
  net/hns3: support FEC
  app/testpmd: add FEC command

 app/test-pmd/cmdline.c                   | 219 +++++++++++++++++++++++++++++++
 app/test-pmd/config.c                    |  54 ++++++++
 app/test-pmd/testpmd.h                   |   2 +
 drivers/net/hns3/hns3_cmd.h              |  19 ++-
 drivers/net/hns3/hns3_ethdev.c           | 154 ++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h           |   1 +
 lib/librte_ethdev/rte_ethdev.c           |  50 +++++++
 lib/librte_ethdev/rte_ethdev.h           |  74 +++++++++++
 lib/librte_ethdev/rte_ethdev_core.h      |  77 +++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |   5 +
 10 files changed, 654 insertions(+), 1 deletion(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V2 1/3] ethdev: introduce FEC API
  2020-09-09  2:42     ` [dpdk-dev] [PATCH V2 0/3] add FEC support Min Hu (Connor)
@ 2020-09-09  2:42       ` Min Hu (Connor)
  2020-09-09  2:43       ` [dpdk-dev] [PATCH V2 2/3] net/hns3: support FEC Min Hu (Connor)
  2020-09-09  2:43       ` [dpdk-dev] [PATCH V2 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-09  2:42 UTC (permalink / raw)
  To: dev; +Cc: thomas, arybchenko, ferruh.yigit, linuxarm

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>
---
 lib/librte_ethdev/rte_ethdev.c           | 50 +++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev.h           | 74 ++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_core.h      | 77 ++++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |  5 +++
 4 files changed, 206 insertions(+)

diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 7858ad5..b7ac791 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -3642,6 +3642,56 @@ 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, uint8_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_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_fec_mode mode)
+{
+	struct rte_eth_dev *dev;
+	uint8_t fec_mode_mask;
+	int ret;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	ret = rte_eth_fec_get_capability(port_id, &fec_mode_mask);
+	if (ret)
+		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 & (1U << (uint8_t)mode))) {
+		RTE_ETHDEV_LOG(ERR, "unsupported fec mode=%d\n", mode);
+		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..23e069a 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1511,6 +1511,17 @@ 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_fec_mode {
+	ETH_FEC_NOFEC = 0,      /**< FEC is off */
+	ETH_FEC_BASER,          /**< FEC using common algorithm */
+	ETH_FEC_RS,             /**< FEC using RS algorithm */
+	ETH_FEC_AUTO            /**< FEC autonegotiation modes */
+};
+
 #define RTE_ETH_ALL RTE_MAX_ETHPORTS
 
 /* Macros to check for valid port */
@@ -3328,6 +3339,69 @@ 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:
+ *   bit0: nofec
+ *   bit1: baser
+ *   bit2: rs
+ *   bit3: auto
+ * @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, uint8_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_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.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ */
+__rte_experimental
+int rte_eth_fec_set(uint16_t port_id, enum rte_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..efd9dc5 100644
--- a/lib/librte_ethdev/rte_ethdev_core.h
+++ b/lib/librte_ethdev/rte_ethdev_core.h
@@ -604,6 +604,76 @@ 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 -EOPNOTSUPP
+ *   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,
+					uint8_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 -EOPNOTSUPP
+ *   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_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 -EOPNOTSUPP
+ *   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_fec_mode mode);
+
+/**
  * @internal A structure containing the functions exported by an Ethernet driver.
  */
 struct eth_dev_ops {
@@ -752,6 +822,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 1212a17..33cf5e4 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -241,6 +241,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 {
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V2 2/3] net/hns3: support FEC
  2020-09-09  2:42     ` [dpdk-dev] [PATCH V2 0/3] add FEC support Min Hu (Connor)
  2020-09-09  2:42       ` [dpdk-dev] [PATCH V2 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-09  2:43       ` Min Hu (Connor)
  2020-09-09  2:43       ` [dpdk-dev] [PATCH V2 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-09  2:43 UTC (permalink / raw)
  To: dev; +Cc: thomas, arybchenko, ferruh.yigit, linuxarm

Forward error correction (FEC) is a bit error correction mode.
It adds error correction information to data packets at the
transmit end, and uses the error correction information to correct
the bit errors generated during data packet transmission at the
receive end. This improves signal quality but also brings a delay
to signals. This function can be enabled or disabled as required.

This patch adds FEC support for ethdev.Introduce ethdev
operations 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>
---
 drivers/net/hns3/hns3_cmd.h    |  19 ++++-
 drivers/net/hns3/hns3_ethdev.c | 154 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h |   1 +
 3 files changed, 173 insertions(+), 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index d70f42e..8b80353 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -99,6 +99,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_CONFIG_MAX_FRM_SIZE    = 0x0308,
 	HNS3_OPC_CONFIG_SPEED_DUP       = 0x0309,
 	HNS3_MAC_COMMON_INT_EN          = 0x030E,
+	HNS3_OPC_CONFIG_FEC_MODE        = 0x031A,
 
 	/* PFC/Pause commands */
 	HNS3_OPC_CFG_MAC_PAUSE_EN       = 0x0701,
@@ -653,9 +654,25 @@ struct hns3_config_auto_neg_cmd {
 	uint8_t   rsv[20];
 };
 
+#define HNS3_MAC_CFG_FEC_AUTO_EN_B	0
+#define HNS3_MAC_CFG_FEC_MODE_S		1
+#define HNS3_MAC_CFG_FEC_MODE_M	GENMASK(3, 1)
+#define HNS3_MAC_FEC_OFF		0
+#define HNS3_MAC_FEC_BASER		1
+#define HNS3_MAC_FEC_RS			2
+
 struct hns3_sfp_speed_cmd {
 	uint32_t  sfp_speed;
-	uint32_t  rsv[5];
+	uint8_t   query_type; /* 0: sfp speed, 1: active fec */
+	uint8_t   active_fec; /* current FEC mode */
+	uint16_t  rsv1;
+	uint32_t  rsv2[4];
+};
+
+/* Configure FEC mode, opcode:0x031A */
+struct hns3_config_fec_cmd {
+	uint8_t fec_mode;
+	uint8_t rsv[23];
 };
 
 #define HNS3_MAC_MGR_MASK_VLAN_B		BIT(0)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 81e7730..bbaff54 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -78,6 +78,8 @@ static int hns3_add_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
 static int hns3_remove_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
+static int hns3_restore_fec(struct hns3_hw *hw);
+static int hns3_query_dev_fec_info(struct rte_eth_dev *dev);
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -2819,6 +2821,13 @@ hns3_get_capability(struct hns3_hw *hw)
 	    device_id == HNS3_DEV_ID_200G_RDMA)
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_DCB_B, 1);
 
+	ret = hns3_query_dev_fec_info(eth_dev);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			     "failed to query FEC information, ret = %d", ret);
+		return ret;
+	}
+
 	/* Get PCI revision id */
 	ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN,
 				  HNS3_PCI_REVISION_ID);
@@ -5311,6 +5320,10 @@ hns3_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_promisc;
 
+	ret = hns3_restore_fec(hw);
+	if (ret)
+		goto err_promisc;
+
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED) {
 		ret = hns3_do_start(hns, false);
 		if (ret)
@@ -5389,6 +5402,144 @@ hns3_reset_service(void *param)
 		hns3_msix_process(hns, reset_level);
 }
 
+static int
+hns3_fec_get_capability(struct rte_eth_dev *dev, uint8_t *fec_cap)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_mac *mac = &hw->mac;
+	uint8_t mode;
+
+	switch (mac->link_speed) {
+	case ETH_SPEED_NUM_10G:
+	case ETH_SPEED_NUM_40G:
+		mode = BIT(ETH_FEC_NOFEC) | BIT(ETH_FEC_BASER) |
+			BIT(ETH_FEC_AUTO);
+		break;
+	case ETH_SPEED_NUM_25G:
+	case ETH_SPEED_NUM_50G:
+		mode = BIT(ETH_FEC_NOFEC) | BIT(ETH_FEC_BASER) |
+			BIT(ETH_FEC_RS) | BIT(ETH_FEC_AUTO);
+		break;
+	case ETH_SPEED_NUM_100G:
+	case ETH_SPEED_NUM_200G:
+		mode = BIT(ETH_FEC_NOFEC) | BIT(ETH_FEC_RS) | BIT(ETH_FEC_AUTO);
+		break;
+	default:
+		mode = 0;
+		break;
+	}
+
+	*fec_cap = mode;
+	return 0;
+}
+
+static int
+hns3_fec_get(struct rte_eth_dev *dev, enum rte_fec_mode *mode)
+{
+#define QUERY_ACTIVE_SPEED	1
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_sfp_speed_cmd *resp;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_SFP_GET_SPEED, true);
+	resp = (struct hns3_sfp_speed_cmd *)desc.data;
+	resp->query_type = QUERY_ACTIVE_SPEED;
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret == -EOPNOTSUPP) {
+		hns3_err(hw, "IMP do not support get FEC, ret = %d", ret);
+		return ret;
+	} else if (ret) {
+		hns3_err(hw, "get FEC failed, ret = %d", ret);
+		return ret;
+	}
+
+	*mode = resp->active_fec;
+	return 0;
+}
+
+static int
+hns3_set_fec_hw(struct hns3_hw *hw, enum rte_fec_mode mode)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, false);
+
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	switch (mode) {
+	case ETH_FEC_NOFEC:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_OFF);
+		break;
+	case ETH_FEC_BASER:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_BASER);
+		break;
+	case ETH_FEC_RS:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_RS);
+		break;
+	case ETH_FEC_AUTO:
+		hns3_set_bit(req->fec_mode, HNS3_MAC_CFG_FEC_AUTO_EN_B, 1);
+		break;
+	default:
+		return 0;
+	}
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw, "set fec mode failed, ret = %d", ret);
+
+	return 0;
+}
+
+static int
+hns3_fec_set(struct rte_eth_dev *dev, enum rte_fec_mode mode)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		return ret;
+
+	pf->fec_mode = mode;
+	return 0;
+}
+
+static int
+hns3_restore_fec(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+	enum rte_fec_mode mode = pf->fec_mode;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		hns3_err(hw, "restore fec mode(%d) failed, ret = %d",
+			 mode, ret);
+
+	return ret;
+}
+
+static int
+hns3_query_dev_fec_info(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_fec_get(dev, &pf->fec_mode);
+	if (ret)
+		return ret;
+
+	return 0;
+}
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_start          = hns3_dev_start,
 	.dev_stop           = hns3_dev_stop,
@@ -5434,6 +5585,9 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.get_reg                = hns3_get_regs,
 	.get_dcb_info           = hns3_get_dcb_info,
 	.dev_supported_ptypes_get = hns3_dev_supported_ptypes_get,
+	.fec_get_capability     = hns3_fec_get_capability,
+	.fec_get                = hns3_fec_get,
+	.fec_set                = hns3_fec_set,
 };
 
 static const struct hns3_reset_ops hns3_reset_ops = {
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 0e665e5..daf723e 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -510,6 +510,7 @@ struct hns3_pf {
 	struct hns3_err_msix_intr_stats abn_int_stats;
 
 	bool support_sfp_query;
+	enum rte_fec_mode fec_mode; /* current FEC mode for ethdev */
 
 	struct hns3_vtag_cfg vtag_config;
 	LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V2 3/3] app/testpmd: add FEC command
  2020-09-09  2:42     ` [dpdk-dev] [PATCH V2 0/3] add FEC support Min Hu (Connor)
  2020-09-09  2:42       ` [dpdk-dev] [PATCH V2 1/3] ethdev: introduce FEC API Min Hu (Connor)
  2020-09-09  2:43       ` [dpdk-dev] [PATCH V2 2/3] net/hns3: support FEC Min Hu (Connor)
@ 2020-09-09  2:43       ` Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-09  2:43 UTC (permalink / raw)
  To: dev; +Cc: thomas, arybchenko, ferruh.yigit, linuxarm

This commit adds testpmd capability to query and config FEC
function of device. This includes:
- show FEC capabilities, example:
	testpmd> show port 0 fec capabilities
- show FEC mode, example:
	testpmd> show port 0 fec_mode
- config FEC mode, example:
	testpmd> set port <port_id> 0 <auto|off|rs|baser>

	where:

	auto|off|rs|baser are four kinds of FEC mode which dev
	support according to MAC link speed.

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>
---
 app/test-pmd/cmdline.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c  |  54 ++++++++++++
 app/test-pmd/testpmd.h |   2 +
 3 files changed, 275 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0a6ed85..072f390 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -19054,6 +19054,222 @@ cmdline_parse_inst_t cmd_show_tx_metadata = {
 	},
 };
 
+/* *** show fec capability per port configuration *** */
+struct cmd_show_fec_capability_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_fec;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_capability_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+	struct cmd_show_fec_capability_result *res = parsed_result;
+	uint8_t fec_cap;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_fec_get_capability(res->cmd_pid, &fec_cap);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC capability failed\n");
+		return;
+	}
+
+	show_fec_capability(fec_cap);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_capability_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_capability_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_capability_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_capability_fec =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_fec, "fec");
+cmdline_parse_token_string_t cmd_show_fec_capability_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_keyword, "capabilities");
+
+cmdline_parse_inst_t cmd_show_capability = {
+	.f = cmd_show_fec_capability_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec capabilities",
+	.tokens = {
+		(void *)&cmd_show_fec_capability_show,
+		(void *)&cmd_show_fec_capability_port,
+		(void *)&cmd_show_fec_capability_pid,
+		(void *)&cmd_show_fec_capability_fec,
+		(void *)&cmd_show_fec_capability_keyword,
+		NULL,
+	},
+};
+
+/* *** show fec mode per port configuration *** */
+struct cmd_show_fec_metadata_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_mode_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_NAME_SIZE 16
+	struct cmd_show_fec_metadata_result *res = parsed_result;
+	enum rte_fec_mode mode;
+	char buf[FEC_NAME_SIZE];
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+	ret = rte_eth_fec_get(res->cmd_pid, &mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC mode failed\n");
+		return;
+	}
+
+	switch (mode) {
+	case ETH_FEC_NOFEC:
+		strlcpy(buf, "off", sizeof(buf));
+		break;
+	case ETH_FEC_BASER:
+		strlcpy(buf, "baser", sizeof(buf));
+		break;
+	case ETH_FEC_RS:
+		strlcpy(buf, "rs", sizeof(buf));
+		break;
+	case ETH_FEC_AUTO:
+		strlcpy(buf, "auto", sizeof(buf));
+		break;
+	default:
+		return;
+	}
+
+	printf("%s\n", buf);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_mode_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_mode_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_mode_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_mode_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_keyword, "fec_mode");
+
+cmdline_parse_inst_t cmd_show_fec_mode = {
+	.f = cmd_show_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec_mode",
+	.tokens = {
+		(void *)&cmd_show_fec_mode_show,
+		(void *)&cmd_show_fec_mode_port,
+		(void *)&cmd_show_fec_mode_pid,
+		(void *)&cmd_show_fec_mode_keyword,
+		NULL,
+	},
+};
+
+/* *** set fec mode per port configuration *** */
+struct cmd_set_port_fec_mode {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t fec_mode;
+	cmdline_fixed_string_t fec_value;
+};
+
+/* Common CLI fields for set fec mode */
+cmdline_parse_token_string_t cmd_set_port_fec_mode_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port, "port");
+cmdline_parse_token_num_t cmd_set_port_fec_mode_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_port_fec_mode_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_mode, "fec_mode");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_value =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_value, NULL);
+
+static void
+cmd_set_port_fec_mode_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	__rte_unused void *data)
+{
+	struct cmd_set_port_fec_mode *res = parsed_result;
+	uint16_t port_id = res->port_id;
+	enum rte_fec_mode mode;
+	int ret;
+
+	ret = parse_fec_mode(res->fec_value, &mode);
+	if (ret < 0) {
+		printf("Unknown fec mode: %s for Port %d", res->fec_value,
+			port_id);
+		return;
+	}
+
+	ret = rte_eth_fec_set(port_id, mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Set FEC mode failed\n");
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_fec_mode = {
+	.f = cmd_set_port_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> fec_mode <auto|off|rs|baser>",
+	.tokens = {
+		(void *)&cmd_set_port_fec_mode_set,
+		(void *)&cmd_set_port_fec_mode_port,
+		(void *)&cmd_set_port_fec_mode_port_id,
+		(void *)&cmd_set_port_fec_mode_str,
+		(void *)&cmd_set_port_fec_mode_value,
+		NULL,
+	},
+};
+
 /* show port supported ptypes */
 
 /* Common result structure for show port ptypes */
@@ -19685,6 +19901,9 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_set_raw,
 	(cmdline_parse_inst_t *)&cmd_show_set_raw_all,
 	(cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
+	(cmdline_parse_inst_t *)&cmd_show_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_set_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_show_capability,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 30bee33..8f996af 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -138,6 +138,28 @@ const struct rss_type_info rss_type_table[] = {
 	{ NULL, 0 },
 };
 
+static const struct {
+	enum rte_fec_mode mode;
+	const char *name;
+} fec_mode_name[] = {
+	{
+		.mode = ETH_FEC_NOFEC,
+		.name = "off",
+	},
+	{
+		.mode = ETH_FEC_BASER,
+		.name = "baser",
+	},
+	{
+		.mode = ETH_FEC_RS,
+		.name = "rs",
+	},
+	{
+		.mode = ETH_FEC_AUTO,
+		.name = "auto",
+	},
+};
+
 static void
 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
 {
@@ -2967,6 +2989,38 @@ set_tx_pkt_split(const char *name)
 	printf("unknown value: \"%s\"\n", name);
 }
 
+int
+parse_fec_mode(const char *name, enum rte_fec_mode *mode)
+{
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(fec_mode_name); i++) {
+		if (strcmp(fec_mode_name[i].name, name) == 0) {
+			*mode = fec_mode_name[i].mode;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void
+show_fec_capability(uint8_t fec_cap)
+{
+	uint8_t i;
+
+	if (fec_cap == 0) {
+		printf("FEC is not supported\n");
+		return;
+	}
+
+	printf("FEC capabilities:\n");
+	for (i = ETH_FEC_BASER; i <= ETH_FEC_AUTO; i++) {
+		if (fec_cap & 1U << i)
+			printf("%s ", fec_mode_name[i].name);
+	}
+	printf("\n");
+}
+
 void
 show_tx_pkt_segments(void)
 {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 25a12b1..7ab91ad 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -778,6 +778,8 @@ void show_tx_pkt_segments(void);
 void set_tx_pkt_times(unsigned int *tx_times);
 void show_tx_pkt_times(void);
 void set_tx_pkt_split(const char *name);
+int parse_fec_mode(const char *name, enum rte_fec_mode *mode);
+void show_fec_capability(uint8_t fec_cap);
 void set_nb_pkt_per_burst(uint16_t pkt_burst);
 char *list_pkt_forwarding_modes(void);
 char *list_pkt_forwarding_retry_modes(void);
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V4  0/3] add FEC support
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
                     ` (2 preceding siblings ...)
  2020-09-08  3:05   ` [dpdk-dev] [PATCH 3/3] app/testpmd: add FEC command Min Hu (Connor)
@ 2020-09-10  7:24   ` Min Hu (Connor)
  2020-09-10  7:24     ` [dpdk-dev] [PATCH V4 1/3] ethdev: introduce FEC API Min Hu (Connor)
                       ` (4 more replies)
  2020-09-17  8:23   ` [dpdk-dev] [V5 " Min Hu (Connor)
                     ` (12 subsequent siblings)
  16 siblings, 5 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-10  7:24 UTC (permalink / raw)
  To: dev; +Cc: thomas, arybchenko, ferruh.yigit, linuxarm

This series add FEC support for ethdev.

Min Hu (Connor) (3):
  ethdev: introduce FEC API
  net/hns3: support FEC
  app/testpmd: add FEC command

 app/test-pmd/cmdline.c                   | 219 +++++++++++++++++++++++++++++++
 app/test-pmd/config.c                    |  54 ++++++++
 app/test-pmd/testpmd.h                   |   2 +
 drivers/net/hns3/hns3_cmd.h              |  19 ++-
 drivers/net/hns3/hns3_ethdev.c           | 156 ++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h           |   1 +
 lib/librte_ethdev/rte_ethdev.c           |  50 +++++++
 lib/librte_ethdev/rte_ethdev.h           |  75 +++++++++++
 lib/librte_ethdev/rte_ethdev_core.h      |  77 +++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |   5 +
 10 files changed, 657 insertions(+), 1 deletion(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V4  1/3] ethdev: introduce FEC API
  2020-09-10  7:24   ` [dpdk-dev] [PATCH V4 0/3] add FEC support Min Hu (Connor)
@ 2020-09-10  7:24     ` Min Hu (Connor)
  2020-09-12  4:53       ` Ajit Khaparde
  2020-09-16 14:10       ` Ananyev, Konstantin
  2020-09-10  7:24     ` [dpdk-dev] [PATCH V4 2/3] net/hns3: support FEC Min Hu (Connor)
                       ` (3 subsequent siblings)
  4 siblings, 2 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-10  7:24 UTC (permalink / raw)
  To: dev; +Cc: thomas, arybchenko, ferruh.yigit, linuxarm

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>

---
v2->v3:
add function return value "-ENOTSUP" for API
---
 lib/librte_ethdev/rte_ethdev.c           | 50 +++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev.h           | 75 +++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_core.h      | 77 ++++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |  5 +++
 4 files changed, 207 insertions(+)

diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 7858ad5..b7ac791 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -3642,6 +3642,56 @@ 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, uint8_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_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_fec_mode mode)
+{
+	struct rte_eth_dev *dev;
+	uint8_t fec_mode_mask;
+	int ret;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	ret = rte_eth_fec_get_capability(port_id, &fec_mode_mask);
+	if (ret)
+		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 & (1U << (uint8_t)mode))) {
+		RTE_ETHDEV_LOG(ERR, "unsupported fec mode=%d\n", mode);
+		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..c353480 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1511,6 +1511,17 @@ 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_fec_mode {
+	ETH_FEC_NOFEC = 0,      /**< FEC is off */
+	ETH_FEC_BASER,          /**< FEC using common algorithm */
+	ETH_FEC_RS,             /**< FEC using RS algorithm */
+	ETH_FEC_AUTO            /**< FEC autonegotiation modes */
+};
+
 #define RTE_ETH_ALL RTE_MAX_ETHPORTS
 
 /* Macros to check for valid port */
@@ -3328,6 +3339,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:
+ *   bit0: nofec
+ *   bit1: baser
+ *   bit2: rs
+ *   bit3: auto
+ * @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, uint8_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_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_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..df9e18a 100644
--- a/lib/librte_ethdev/rte_ethdev_core.h
+++ b/lib/librte_ethdev/rte_ethdev_core.h
@@ -604,6 +604,76 @@ 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,
+					uint8_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_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_fec_mode mode);
+
+/**
  * @internal A structure containing the functions exported by an Ethernet driver.
  */
 struct eth_dev_ops {
@@ -752,6 +822,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 1212a17..33cf5e4 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -241,6 +241,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 {
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V4  2/3] net/hns3: support FEC
  2020-09-10  7:24   ` [dpdk-dev] [PATCH V4 0/3] add FEC support Min Hu (Connor)
  2020-09-10  7:24     ` [dpdk-dev] [PATCH V4 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-10  7:24     ` Min Hu (Connor)
  2020-09-10  7:24     ` [dpdk-dev] [PATCH V4 3/3] app/testpmd: add FEC command Min Hu (Connor)
                       ` (2 subsequent siblings)
  4 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-10  7:24 UTC (permalink / raw)
  To: dev; +Cc: thomas, arybchenko, ferruh.yigit, linuxarm

Forward error correction (FEC) is a bit error correction mode.
It adds error correction information to data packets at the
transmit end, and uses the error correction information to correct
the bit errors generated during data packet transmission at the
receive end. This improves signal quality but also brings a delay
to signals. This function can be enabled or disabled as required.

This patch adds FEC support for ethdev.Introduce ethdev
operations 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>

---
v2->v3:
adjust the return value of function.
---
 drivers/net/hns3/hns3_cmd.h    |  19 ++++-
 drivers/net/hns3/hns3_ethdev.c | 156 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h |   1 +
 3 files changed, 175 insertions(+), 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index d70f42e..8b80353 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -99,6 +99,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_CONFIG_MAX_FRM_SIZE    = 0x0308,
 	HNS3_OPC_CONFIG_SPEED_DUP       = 0x0309,
 	HNS3_MAC_COMMON_INT_EN          = 0x030E,
+	HNS3_OPC_CONFIG_FEC_MODE        = 0x031A,
 
 	/* PFC/Pause commands */
 	HNS3_OPC_CFG_MAC_PAUSE_EN       = 0x0701,
@@ -653,9 +654,25 @@ struct hns3_config_auto_neg_cmd {
 	uint8_t   rsv[20];
 };
 
+#define HNS3_MAC_CFG_FEC_AUTO_EN_B	0
+#define HNS3_MAC_CFG_FEC_MODE_S		1
+#define HNS3_MAC_CFG_FEC_MODE_M	GENMASK(3, 1)
+#define HNS3_MAC_FEC_OFF		0
+#define HNS3_MAC_FEC_BASER		1
+#define HNS3_MAC_FEC_RS			2
+
 struct hns3_sfp_speed_cmd {
 	uint32_t  sfp_speed;
-	uint32_t  rsv[5];
+	uint8_t   query_type; /* 0: sfp speed, 1: active fec */
+	uint8_t   active_fec; /* current FEC mode */
+	uint16_t  rsv1;
+	uint32_t  rsv2[4];
+};
+
+/* Configure FEC mode, opcode:0x031A */
+struct hns3_config_fec_cmd {
+	uint8_t fec_mode;
+	uint8_t rsv[23];
 };
 
 #define HNS3_MAC_MGR_MASK_VLAN_B		BIT(0)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 81e7730..9b5a7c8 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -78,6 +78,8 @@ static int hns3_add_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
 static int hns3_remove_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
+static int hns3_restore_fec(struct hns3_hw *hw);
+static int hns3_query_dev_fec_info(struct rte_eth_dev *dev);
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -2819,6 +2821,13 @@ hns3_get_capability(struct hns3_hw *hw)
 	    device_id == HNS3_DEV_ID_200G_RDMA)
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_DCB_B, 1);
 
+	ret = hns3_query_dev_fec_info(eth_dev);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			     "failed to query FEC information, ret = %d", ret);
+		return ret;
+	}
+
 	/* Get PCI revision id */
 	ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN,
 				  HNS3_PCI_REVISION_ID);
@@ -5311,6 +5320,10 @@ hns3_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_promisc;
 
+	ret = hns3_restore_fec(hw);
+	if (ret)
+		goto err_promisc;
+
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED) {
 		ret = hns3_do_start(hns, false);
 		if (ret)
@@ -5389,6 +5402,146 @@ hns3_reset_service(void *param)
 		hns3_msix_process(hns, reset_level);
 }
 
+static int
+hns3_fec_get_capability(struct rte_eth_dev *dev, uint8_t *fec_cap)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_mac *mac = &hw->mac;
+	uint8_t mode;
+
+	switch (mac->link_speed) {
+	case ETH_SPEED_NUM_10G:
+	case ETH_SPEED_NUM_40G:
+		mode = BIT(ETH_FEC_NOFEC) | BIT(ETH_FEC_BASER) |
+			BIT(ETH_FEC_AUTO);
+		break;
+	case ETH_SPEED_NUM_25G:
+	case ETH_SPEED_NUM_50G:
+		mode = BIT(ETH_FEC_NOFEC) | BIT(ETH_FEC_BASER) |
+			BIT(ETH_FEC_RS) | BIT(ETH_FEC_AUTO);
+		break;
+	case ETH_SPEED_NUM_100G:
+	case ETH_SPEED_NUM_200G:
+		mode = BIT(ETH_FEC_NOFEC) | BIT(ETH_FEC_RS) | BIT(ETH_FEC_AUTO);
+		break;
+	default:
+		mode = 0;
+		break;
+	}
+
+	*fec_cap = mode;
+	return 0;
+}
+
+static int
+hns3_fec_get(struct rte_eth_dev *dev, enum rte_fec_mode *mode)
+{
+#define QUERY_ACTIVE_SPEED	1
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_sfp_speed_cmd *resp;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_SFP_GET_SPEED, true);
+	resp = (struct hns3_sfp_speed_cmd *)desc.data;
+	resp->query_type = QUERY_ACTIVE_SPEED;
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret == -EOPNOTSUPP) {
+		hns3_err(hw, "IMP do not support get FEC, ret = %d", ret);
+		return ret;
+	} else if (ret) {
+		hns3_err(hw, "get FEC failed, ret = %d", ret);
+		return ret;
+	}
+
+	*mode = resp->active_fec;
+	return 0;
+}
+
+static int
+hns3_set_fec_hw(struct hns3_hw *hw, enum rte_fec_mode mode)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, false);
+
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	switch (mode) {
+	case ETH_FEC_NOFEC:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_OFF);
+		break;
+	case ETH_FEC_BASER:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_BASER);
+		break;
+	case ETH_FEC_RS:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_RS);
+		break;
+	case ETH_FEC_AUTO:
+		hns3_set_bit(req->fec_mode, HNS3_MAC_CFG_FEC_AUTO_EN_B, 1);
+		break;
+	default:
+		return 0;
+	}
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw, "set fec mode failed, ret = %d", ret);
+
+	return ret;
+}
+
+static int
+hns3_fec_set(struct rte_eth_dev *dev, enum rte_fec_mode mode)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		return ret;
+
+	pf->fec_mode = mode;
+	return 0;
+}
+
+static int
+hns3_restore_fec(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+	enum rte_fec_mode mode = pf->fec_mode;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		hns3_err(hw, "restore fec mode(%d) failed, ret = %d",
+			 mode, ret);
+
+	return ret;
+}
+
+static int
+hns3_query_dev_fec_info(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_fec_get(dev, &pf->fec_mode);
+	if (ret)
+		hns3_err(hw, "query device FEC info failed, ret = %d", ret);
+
+	return ret;
+}
+
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_start          = hns3_dev_start,
 	.dev_stop           = hns3_dev_stop,
@@ -5434,6 +5587,9 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.get_reg                = hns3_get_regs,
 	.get_dcb_info           = hns3_get_dcb_info,
 	.dev_supported_ptypes_get = hns3_dev_supported_ptypes_get,
+	.fec_get_capability     = hns3_fec_get_capability,
+	.fec_get                = hns3_fec_get,
+	.fec_set                = hns3_fec_set,
 };
 
 static const struct hns3_reset_ops hns3_reset_ops = {
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 0e665e5..daf723e 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -510,6 +510,7 @@ struct hns3_pf {
 	struct hns3_err_msix_intr_stats abn_int_stats;
 
 	bool support_sfp_query;
+	enum rte_fec_mode fec_mode; /* current FEC mode for ethdev */
 
 	struct hns3_vtag_cfg vtag_config;
 	LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V4  3/3] app/testpmd: add FEC command
  2020-09-10  7:24   ` [dpdk-dev] [PATCH V4 0/3] add FEC support Min Hu (Connor)
  2020-09-10  7:24     ` [dpdk-dev] [PATCH V4 1/3] ethdev: introduce FEC API Min Hu (Connor)
  2020-09-10  7:24     ` [dpdk-dev] [PATCH V4 2/3] net/hns3: support FEC Min Hu (Connor)
@ 2020-09-10  7:24     ` Min Hu (Connor)
  2020-09-10 21:02     ` [dpdk-dev] [PATCH V4 0/3] add FEC support Ajit Khaparde
  2020-09-16 12:37     ` humin (Connor)
  4 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-10  7:24 UTC (permalink / raw)
  To: dev; +Cc: thomas, arybchenko, ferruh.yigit, linuxarm

This commit adds testpmd capability to query and config FEC
function of device. This includes:
- show FEC capabilities, example:
	testpmd> show port 0 fec capabilities
- show FEC mode, example:
	testpmd> show port 0 fec_mode
- config FEC mode, example:
	testpmd> set port <port_id> 0 <auto|off|rs|baser>

	where:

	auto|off|rs|baser are four kinds of FEC mode which dev
	support according to MAC link speed.

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>

---
v3->v4:
adjust the display format of FEC mode

---
v2->v3:
adjust the display format of FEC capability.
---
 app/test-pmd/cmdline.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c  |  54 ++++++++++++
 app/test-pmd/testpmd.h |   2 +
 3 files changed, 275 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0a6ed85..072f390 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -19054,6 +19054,222 @@ cmdline_parse_inst_t cmd_show_tx_metadata = {
 	},
 };
 
+/* *** show fec capability per port configuration *** */
+struct cmd_show_fec_capability_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_fec;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_capability_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+	struct cmd_show_fec_capability_result *res = parsed_result;
+	uint8_t fec_cap;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_fec_get_capability(res->cmd_pid, &fec_cap);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC capability failed\n");
+		return;
+	}
+
+	show_fec_capability(fec_cap);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_capability_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_capability_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_capability_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_capability_fec =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_fec, "fec");
+cmdline_parse_token_string_t cmd_show_fec_capability_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_keyword, "capabilities");
+
+cmdline_parse_inst_t cmd_show_capability = {
+	.f = cmd_show_fec_capability_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec capabilities",
+	.tokens = {
+		(void *)&cmd_show_fec_capability_show,
+		(void *)&cmd_show_fec_capability_port,
+		(void *)&cmd_show_fec_capability_pid,
+		(void *)&cmd_show_fec_capability_fec,
+		(void *)&cmd_show_fec_capability_keyword,
+		NULL,
+	},
+};
+
+/* *** show fec mode per port configuration *** */
+struct cmd_show_fec_metadata_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_mode_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_NAME_SIZE 16
+	struct cmd_show_fec_metadata_result *res = parsed_result;
+	enum rte_fec_mode mode;
+	char buf[FEC_NAME_SIZE];
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+	ret = rte_eth_fec_get(res->cmd_pid, &mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC mode failed\n");
+		return;
+	}
+
+	switch (mode) {
+	case ETH_FEC_NOFEC:
+		strlcpy(buf, "off", sizeof(buf));
+		break;
+	case ETH_FEC_BASER:
+		strlcpy(buf, "baser", sizeof(buf));
+		break;
+	case ETH_FEC_RS:
+		strlcpy(buf, "rs", sizeof(buf));
+		break;
+	case ETH_FEC_AUTO:
+		strlcpy(buf, "auto", sizeof(buf));
+		break;
+	default:
+		return;
+	}
+
+	printf("%s\n", buf);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_mode_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_mode_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_mode_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_mode_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_keyword, "fec_mode");
+
+cmdline_parse_inst_t cmd_show_fec_mode = {
+	.f = cmd_show_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec_mode",
+	.tokens = {
+		(void *)&cmd_show_fec_mode_show,
+		(void *)&cmd_show_fec_mode_port,
+		(void *)&cmd_show_fec_mode_pid,
+		(void *)&cmd_show_fec_mode_keyword,
+		NULL,
+	},
+};
+
+/* *** set fec mode per port configuration *** */
+struct cmd_set_port_fec_mode {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t fec_mode;
+	cmdline_fixed_string_t fec_value;
+};
+
+/* Common CLI fields for set fec mode */
+cmdline_parse_token_string_t cmd_set_port_fec_mode_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port, "port");
+cmdline_parse_token_num_t cmd_set_port_fec_mode_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_port_fec_mode_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_mode, "fec_mode");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_value =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_value, NULL);
+
+static void
+cmd_set_port_fec_mode_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	__rte_unused void *data)
+{
+	struct cmd_set_port_fec_mode *res = parsed_result;
+	uint16_t port_id = res->port_id;
+	enum rte_fec_mode mode;
+	int ret;
+
+	ret = parse_fec_mode(res->fec_value, &mode);
+	if (ret < 0) {
+		printf("Unknown fec mode: %s for Port %d\n", res->fec_value,
+			port_id);
+		return;
+	}
+
+	ret = rte_eth_fec_set(port_id, mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Set FEC mode failed\n");
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_fec_mode = {
+	.f = cmd_set_port_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> fec_mode <auto|off|rs|baser>",
+	.tokens = {
+		(void *)&cmd_set_port_fec_mode_set,
+		(void *)&cmd_set_port_fec_mode_port,
+		(void *)&cmd_set_port_fec_mode_port_id,
+		(void *)&cmd_set_port_fec_mode_str,
+		(void *)&cmd_set_port_fec_mode_value,
+		NULL,
+	},
+};
+
 /* show port supported ptypes */
 
 /* Common result structure for show port ptypes */
@@ -19685,6 +19901,9 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_set_raw,
 	(cmdline_parse_inst_t *)&cmd_show_set_raw_all,
 	(cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
+	(cmdline_parse_inst_t *)&cmd_show_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_set_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_show_capability,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 30bee33..6048f19 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -138,6 +138,28 @@ const struct rss_type_info rss_type_table[] = {
 	{ NULL, 0 },
 };
 
+static const struct {
+	enum rte_fec_mode mode;
+	const char *name;
+} fec_mode_name[] = {
+	{
+		.mode = ETH_FEC_NOFEC,
+		.name = "off",
+	},
+	{
+		.mode = ETH_FEC_BASER,
+		.name = "baser",
+	},
+	{
+		.mode = ETH_FEC_RS,
+		.name = "rs",
+	},
+	{
+		.mode = ETH_FEC_AUTO,
+		.name = "auto",
+	},
+};
+
 static void
 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
 {
@@ -2967,6 +2989,38 @@ set_tx_pkt_split(const char *name)
 	printf("unknown value: \"%s\"\n", name);
 }
 
+int
+parse_fec_mode(const char *name, enum rte_fec_mode *mode)
+{
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(fec_mode_name); i++) {
+		if (strcmp(fec_mode_name[i].name, name) == 0) {
+			*mode = fec_mode_name[i].mode;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void
+show_fec_capability(uint8_t fec_cap)
+{
+	uint8_t i;
+
+	if (fec_cap == 0) {
+		printf("FEC is not supported\n");
+		return;
+	}
+
+	printf("FEC capabilities: ");
+	for (i = ETH_FEC_BASER; i <= ETH_FEC_AUTO; i++) {
+		if (fec_cap & 1U << i)
+			printf("%s ", fec_mode_name[i].name);
+	}
+	printf("\n");
+}
+
 void
 show_tx_pkt_segments(void)
 {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 25a12b1..7ab91ad 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -778,6 +778,8 @@ void show_tx_pkt_segments(void);
 void set_tx_pkt_times(unsigned int *tx_times);
 void show_tx_pkt_times(void);
 void set_tx_pkt_split(const char *name);
+int parse_fec_mode(const char *name, enum rte_fec_mode *mode);
+void show_fec_capability(uint8_t fec_cap);
 void set_nb_pkt_per_burst(uint16_t pkt_burst);
 char *list_pkt_forwarding_modes(void);
 char *list_pkt_forwarding_retry_modes(void);
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V4 0/3] add FEC support
  2020-09-10  7:24   ` [dpdk-dev] [PATCH V4 0/3] add FEC support Min Hu (Connor)
                       ` (2 preceding siblings ...)
  2020-09-10  7:24     ` [dpdk-dev] [PATCH V4 3/3] app/testpmd: add FEC command Min Hu (Connor)
@ 2020-09-10 21:02     ` Ajit Khaparde
  2020-09-11  8:39       ` humin (Connor)
  2020-09-16 12:37     ` humin (Connor)
  4 siblings, 1 reply; 118+ messages in thread
From: Ajit Khaparde @ 2020-09-10 21:02 UTC (permalink / raw)
  To: Min Hu (Connor)
  Cc: dpdk-dev, Thomas Monjalon, Andrew Rybchenko, Ferruh Yigit, linuxarm

On Thu, Sep 10, 2020 at 12:26 AM Min Hu (Connor) <humin29@huawei.com> wrote:

> This series add FEC support for ethdev.
>
Can you tell why DPDK applications need this info?


>
> Min Hu (Connor) (3):
>   ethdev: introduce FEC API
>   net/hns3: support FEC
>   app/testpmd: add FEC command
>
>  app/test-pmd/cmdline.c                   | 219
> +++++++++++++++++++++++++++++++
>  app/test-pmd/config.c                    |  54 ++++++++
>  app/test-pmd/testpmd.h                   |   2 +
>  drivers/net/hns3/hns3_cmd.h              |  19 ++-
>  drivers/net/hns3/hns3_ethdev.c           | 156 ++++++++++++++++++++++
>  drivers/net/hns3/hns3_ethdev.h           |   1 +
>  lib/librte_ethdev/rte_ethdev.c           |  50 +++++++
>  lib/librte_ethdev/rte_ethdev.h           |  75 +++++++++++
>  lib/librte_ethdev/rte_ethdev_core.h      |  77 +++++++++++
>  lib/librte_ethdev/rte_ethdev_version.map |   5 +
>  10 files changed, 657 insertions(+), 1 deletion(-)
>
> --
> 2.7.4
>
>

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V4 0/3] add FEC support
  2020-09-10 21:02     ` [dpdk-dev] [PATCH V4 0/3] add FEC support Ajit Khaparde
@ 2020-09-11  8:39       ` humin (Connor)
  0 siblings, 0 replies; 118+ messages in thread
From: humin (Connor) @ 2020-09-11  8:39 UTC (permalink / raw)
  To: Ajit Khaparde
  Cc: dpdk-dev, Thomas Monjalon, Andrew Rybchenko, Ferruh Yigit, linuxarm

Hi, Ajit Khaparde:

Forward error correction (FEC) is a bit error correction mode.
It adds error correction information to data packets at the
transmit end, and uses the error correction information to correct
the bit errors generated during data packet transmission at the
receive end. This improves signal quality.

FEC ensures signal transmission quality in high-speed networks.
DPDK application needs FEC information from device if user want to
set FEC mode to ensures signal transmission quality.

For example, if user wants to set FEC mode for device by 
"rte_eth_fec_set",FEC capability of device getting from 
"rte_eth_fec_get_capability" is needed by user. AS FEC mode should be 
within the limits of FEC capability of device.

在 2020/9/11 5:02, Ajit Khaparde 写道:
> 
> On Thu, Sep 10, 2020 at 12:26 AM Min Hu (Connor) <humin29@huawei.com 
> <mailto:humin29@huawei.com>> wrote:
> 
>     This series add FEC support for ethdev.
> 
> Can you tell why DPDK applications need this info?
> 
> 
>     Min Hu (Connor) (3):
>        ethdev: introduce FEC API
>        net/hns3: support FEC
>        app/testpmd: add FEC command
> 
>       app/test-pmd/cmdline.c                   | 219
>     +++++++++++++++++++++++++++++++
>       app/test-pmd/config.c                    |  54 ++++++++
>       app/test-pmd/testpmd.h                   |   2 +
>       drivers/net/hns3/hns3_cmd.h              |  19 ++-
>       drivers/net/hns3/hns3_ethdev.c           | 156 ++++++++++++++++++++++
>       drivers/net/hns3/hns3_ethdev.h           |   1 +
>       lib/librte_ethdev/rte_ethdev.c           |  50 +++++++
>       lib/librte_ethdev/rte_ethdev.h           |  75 +++++++++++
>       lib/librte_ethdev/rte_ethdev_core.h      |  77 +++++++++++
>       lib/librte_ethdev/rte_ethdev_version.map |   5 +
>       10 files changed, 657 insertions(+), 1 deletion(-)
> 
>     -- 
>     2.7.4
> 


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V4 1/3] ethdev: introduce FEC API
  2020-09-10  7:24     ` [dpdk-dev] [PATCH V4 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-12  4:53       ` Ajit Khaparde
  2020-09-16 14:10       ` Ananyev, Konstantin
  1 sibling, 0 replies; 118+ messages in thread
From: Ajit Khaparde @ 2020-09-12  4:53 UTC (permalink / raw)
  To: Min Hu (Connor)
  Cc: dpdk-dev, Thomas Monjalon, Andrew Rybchenko, Ferruh Yigit, linuxarm

On Thu, Sep 10, 2020 at 12:26 AM Min Hu (Connor) <humin29@huawei.com> 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>


>
> ---
> v2->v3:
> add function return value "-ENOTSUP" for API
> ---
>  lib/librte_ethdev/rte_ethdev.c           | 50 +++++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev.h           | 75
> +++++++++++++++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev_core.h      | 77
> ++++++++++++++++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev_version.map |  5 +++
>  4 files changed, 207 insertions(+)
>
> diff --git a/lib/librte_ethdev/rte_ethdev.c
> b/lib/librte_ethdev/rte_ethdev.c
> index 7858ad5..b7ac791 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -3642,6 +3642,56 @@ 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, uint8_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_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_fec_mode mode)
> +{
> +       struct rte_eth_dev *dev;
> +       uint8_t fec_mode_mask;
> +       int ret;
> +
> +       RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +       ret = rte_eth_fec_get_capability(port_id, &fec_mode_mask);
> +       if (ret)
> +               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 & (1U << (uint8_t)mode))) {
> +               RTE_ETHDEV_LOG(ERR, "unsupported fec mode=%d\n", mode);
> +               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..c353480 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -1511,6 +1511,17 @@ 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_fec_mode {
> +       ETH_FEC_NOFEC = 0,      /**< FEC is off */
> +       ETH_FEC_BASER,          /**< FEC using common algorithm */
> +       ETH_FEC_RS,             /**< FEC using RS algorithm */
> +       ETH_FEC_AUTO            /**< FEC autonegotiation modes */
> +};
> +
>  #define RTE_ETH_ALL RTE_MAX_ETHPORTS
>
>  /* Macros to check for valid port */
> @@ -3328,6 +3339,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:
> + *   bit0: nofec
> + *   bit1: baser
> + *   bit2: rs
> + *   bit3: auto
> + * @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, uint8_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_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_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..df9e18a 100644
> --- a/lib/librte_ethdev/rte_ethdev_core.h
> +++ b/lib/librte_ethdev/rte_ethdev_core.h
> @@ -604,6 +604,76 @@ 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,
> +                                       uint8_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_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_fec_mode
> mode);
> +
> +/**
>   * @internal A structure containing the functions exported by an Ethernet
> driver.
>   */
>  struct eth_dev_ops {
> @@ -752,6 +822,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 1212a17..33cf5e4 100644
> --- a/lib/librte_ethdev/rte_ethdev_version.map
> +++ b/lib/librte_ethdev/rte_ethdev_version.map
> @@ -241,6 +241,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 {
> --
> 2.7.4
>
>

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V4 0/3] add FEC support
  2020-09-10  7:24   ` [dpdk-dev] [PATCH V4 0/3] add FEC support Min Hu (Connor)
                       ` (3 preceding siblings ...)
  2020-09-10 21:02     ` [dpdk-dev] [PATCH V4 0/3] add FEC support Ajit Khaparde
@ 2020-09-16 12:37     ` humin (Connor)
  4 siblings, 0 replies; 118+ messages in thread
From: humin (Connor) @ 2020-09-16 12:37 UTC (permalink / raw)
  To: dev; +Cc: thomas, ferruh.yigit, linuxarm, arybchenko

Hi, all
	Are there any comment?

Thanks
Connor

在 2020/9/10 15:24, Min Hu (Connor) 写道:
> This series add FEC support for ethdev.
> 
> Min Hu (Connor) (3):
>    ethdev: introduce FEC API
>    net/hns3: support FEC
>    app/testpmd: add FEC command
> 
>   app/test-pmd/cmdline.c                   | 219 +++++++++++++++++++++++++++++++
>   app/test-pmd/config.c                    |  54 ++++++++
>   app/test-pmd/testpmd.h                   |   2 +
>   drivers/net/hns3/hns3_cmd.h              |  19 ++-
>   drivers/net/hns3/hns3_ethdev.c           | 156 ++++++++++++++++++++++
>   drivers/net/hns3/hns3_ethdev.h           |   1 +
>   lib/librte_ethdev/rte_ethdev.c           |  50 +++++++
>   lib/librte_ethdev/rte_ethdev.h           |  75 +++++++++++
>   lib/librte_ethdev/rte_ethdev_core.h      |  77 +++++++++++
>   lib/librte_ethdev/rte_ethdev_version.map |   5 +
>   10 files changed, 657 insertions(+), 1 deletion(-)
> 

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V4  1/3] ethdev: introduce FEC API
  2020-09-10  7:24     ` [dpdk-dev] [PATCH V4 1/3] ethdev: introduce FEC API Min Hu (Connor)
  2020-09-12  4:53       ` Ajit Khaparde
@ 2020-09-16 14:10       ` Ananyev, Konstantin
  1 sibling, 0 replies; 118+ messages in thread
From: Ananyev, Konstantin @ 2020-09-16 14:10 UTC (permalink / raw)
  To: Min Hu (Connor), dev; +Cc: thomas, arybchenko, Yigit, Ferruh, linuxarm

Seems ok in general, few nits below.

> 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>
> 
> ---
> v2->v3:
> add function return value "-ENOTSUP" for API
> ---
>  lib/librte_ethdev/rte_ethdev.c           | 50 +++++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev.h           | 75 +++++++++++++++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev_core.h      | 77 ++++++++++++++++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev_version.map |  5 +++

This is a wew feature, probably worth to update release notes. 

>  4 files changed, 207 insertions(+)
> 
> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> index 7858ad5..b7ac791 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -3642,6 +3642,56 @@ 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, uint8_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_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_fec_mode mode)
> +{
> +	struct rte_eth_dev *dev;
> +	uint8_t fec_mode_mask;
> +	int ret;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	ret = rte_eth_fec_get_capability(port_id, &fec_mode_mask);
> +	if (ret)
> +		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 & (1U << (uint8_t)mode))) {
> +		RTE_ETHDEV_LOG(ERR, "unsupported fec mode=%d\n", mode);
> +		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..c353480 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -1511,6 +1511,17 @@ 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_fec_mode {
> +	ETH_FEC_NOFEC = 0,      /**< FEC is off */

As it is a public enum, RTE_ prefix is needed for each value.

> +	ETH_FEC_BASER,          /**< FEC using common algorithm */
> +	ETH_FEC_RS,             /**< FEC using RS algorithm */
> +	ETH_FEC_AUTO            /**< FEC autonegotiation modes */
> +};
> +
>  #define RTE_ETH_ALL RTE_MAX_ETHPORTS
> 
>  /* Macros to check for valid port */
> @@ -3328,6 +3339,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:
> + *   bit0: nofec
> + *   bit1: baser
> + *   bit2: rs
> + *   bit3: auto

Instead of putting bit description into the comment, I think it is better to define
them explicitly. Something like: 

#define RTE_ETH_FEC_CAPA_XXX	(1 << RTE_ETH_FEC_XXX)

> + * @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, uint8_t *fec_cap);

Probably make sense to have uint32_t  bit value for fec_cap (for possible future expansion)?

> +
> +/**
> + * @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_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_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..df9e18a 100644
> --- a/lib/librte_ethdev/rte_ethdev_core.h
> +++ b/lib/librte_ethdev/rte_ethdev_core.h
> @@ -604,6 +604,76 @@ 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,
> +					uint8_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_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_fec_mode mode);
> +
> +/**
>   * @internal A structure containing the functions exported by an Ethernet driver.
>   */
>  struct eth_dev_ops {
> @@ -752,6 +822,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 1212a17..33cf5e4 100644
> --- a/lib/librte_ethdev/rte_ethdev_version.map
> +++ b/lib/librte_ethdev/rte_ethdev_version.map
> @@ -241,6 +241,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 {
> --
> 2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [V5 0/3] add FEC support
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
                     ` (3 preceding siblings ...)
  2020-09-10  7:24   ` [dpdk-dev] [PATCH V4 0/3] add FEC support Min Hu (Connor)
@ 2020-09-17  8:23   ` Min Hu (Connor)
  2020-09-17  8:23     ` [dpdk-dev] [V5 1/3] ethdev: introduce FEC API Min Hu (Connor)
                       ` (2 more replies)
  2020-09-17  8:52   ` [dpdk-dev] [V5 0/3] add FEC support Min Hu (Connor)
                     ` (11 subsequent siblings)
  16 siblings, 3 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-17  8:23 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This series add FEC support for ethdev.

Min Hu (Connor) (3):
  ethdev: introduce FEC API
  net/hns3: support FEC
  app/testpmd: add FEC command

 app/test-pmd/cmdline.c                   | 219 +++++++++++++++++++++++++++++++
 app/test-pmd/config.c                    |  54 ++++++++
 app/test-pmd/testpmd.h                   |   2 +
 doc/guides/rel_notes/release_20_11.rst   |  13 ++
 drivers/net/hns3/hns3_cmd.h              |  19 ++-
 drivers/net/hns3/hns3_ethdev.c           | 157 ++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h           |   1 +
 lib/librte_ethdev/rte_ethdev.c           |  50 +++++++
 lib/librte_ethdev/rte_ethdev.h           |  83 ++++++++++++
 lib/librte_ethdev/rte_ethdev_core.h      |  77 +++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |   5 +
 11 files changed, 679 insertions(+), 1 deletion(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [V5 1/3] ethdev: introduce FEC API
  2020-09-17  8:23   ` [dpdk-dev] [V5 " Min Hu (Connor)
@ 2020-09-17  8:23     ` Min Hu (Connor)
  2020-09-17  8:23     ` [dpdk-dev] [V5 2/3] net/hns3: support FEC Min Hu (Connor)
  2020-09-17  8:23     ` [dpdk-dev] [V5 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-17  8:23 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

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>
---
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   | 13 +++++
 lib/librte_ethdev/rte_ethdev.c           | 50 +++++++++++++++++++
 lib/librte_ethdev/rte_ethdev.h           | 83 ++++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_core.h      | 77 +++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |  5 ++
 5 files changed, 228 insertions(+)

diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index cc72609..e4f0587 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -55,6 +55,19 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Added the FEC Library, a generic FEC query and config library.**
+
+  Added the FEC library which provides an API for query FEC capabilities and
+  FEC mode from device. Also, API for configuring FEC mode is also provided.
+
+  Added hns3 FEC PMD, for suppporting query and config FEC mode.
+
+* **Updated testpmd with a command for FEC.**
+
+  Added a FEC command to testpmd app,
+  ``show port <port_id> fec capabilities`` which queries FEC capabilities device supports.
+  ``show port <port_id> fec_mode`` which queries FEC mode from device.
+  ``set port <port_id> fec_mode <auto|off|rs|baser>`` which configures FEC mode to device.
 
 Removed Items
 -------------
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 7858ad5..fde77c1 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -3642,6 +3642,56 @@ 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_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_fec_mode mode)
+{
+	struct rte_eth_dev *dev;
+	uint32_t fec_mode_mask;
+	int ret;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	ret = rte_eth_fec_get_capability(port_id, &fec_mode_mask);
+	if (ret)
+		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 & (1U << (uint32_t)mode))) {
+		RTE_ETHDEV_LOG(ERR, "unsupported fec mode=%d\n", mode);
+		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..aa79326 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1511,6 +1511,25 @@ 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_fec_mode {
+	RTE_ETH_FEC_NOFEC = 0,      /**< FEC is off */
+	RTE_ETH_FEC_BASER,          /**< FEC using common algorithm */
+	RTE_ETH_FEC_RS,             /**< FEC using RS algorithm */
+	RTE_ETH_FEC_AUTO,           /**< FEC autonegotiation modes */
+	RTE_ETH_FEC_NUM
+};
+
+/* This indicates FEC capabilities */
+#define RTE_ETH_FEC_CAPA_NOFEC  (1U << RTE_ETH_FEC_NOFEC)
+#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_FEC_CAPA_AUTO   (1U << RTE_ETH_FEC_AUTO)
+
+
 #define RTE_ETH_ALL RTE_MAX_ETHPORTS
 
 /* Macros to check for valid port */
@@ -3328,6 +3347,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_BASER
+ *   RTE_ETH_FEC_CAPA_RS
+ *   RTE_ETH_FEC_CAPA_AUTO
+ * @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_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_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..cd1acf1 100644
--- a/lib/librte_ethdev/rte_ethdev_core.h
+++ b/lib/librte_ethdev/rte_ethdev_core.h
@@ -604,6 +604,76 @@ 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_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_fec_mode mode);
+
+/**
  * @internal A structure containing the functions exported by an Ethernet driver.
  */
 struct eth_dev_ops {
@@ -752,6 +822,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 {
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [V5 2/3] net/hns3: support FEC
  2020-09-17  8:23   ` [dpdk-dev] [V5 " Min Hu (Connor)
  2020-09-17  8:23     ` [dpdk-dev] [V5 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-17  8:23     ` Min Hu (Connor)
  2020-09-17  8:23     ` [dpdk-dev] [V5 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-17  8:23 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

Forward error correction (FEC) is a bit error correction mode.
It adds error correction information to data packets at the
transmit end, and uses the error correction information to correct
the bit errors generated during data packet transmission at the
receive end. This improves signal quality but also brings a delay
to signals. This function can be enabled or disabled as required.

This patch adds FEC support for ethdev.Introduce ethdev
operations 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>
---
v4->v5:
Data type for fec_cap is changed from uint8_t
to uint32_t for possible future expansion.

---
v2->v3:
adjust the return value of function.

---
 drivers/net/hns3/hns3_cmd.h    |  19 ++++-
 drivers/net/hns3/hns3_ethdev.c | 157 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h |   1 +
 3 files changed, 176 insertions(+), 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index d70f42e..8b80353 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -99,6 +99,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_CONFIG_MAX_FRM_SIZE    = 0x0308,
 	HNS3_OPC_CONFIG_SPEED_DUP       = 0x0309,
 	HNS3_MAC_COMMON_INT_EN          = 0x030E,
+	HNS3_OPC_CONFIG_FEC_MODE        = 0x031A,
 
 	/* PFC/Pause commands */
 	HNS3_OPC_CFG_MAC_PAUSE_EN       = 0x0701,
@@ -653,9 +654,25 @@ struct hns3_config_auto_neg_cmd {
 	uint8_t   rsv[20];
 };
 
+#define HNS3_MAC_CFG_FEC_AUTO_EN_B	0
+#define HNS3_MAC_CFG_FEC_MODE_S		1
+#define HNS3_MAC_CFG_FEC_MODE_M	GENMASK(3, 1)
+#define HNS3_MAC_FEC_OFF		0
+#define HNS3_MAC_FEC_BASER		1
+#define HNS3_MAC_FEC_RS			2
+
 struct hns3_sfp_speed_cmd {
 	uint32_t  sfp_speed;
-	uint32_t  rsv[5];
+	uint8_t   query_type; /* 0: sfp speed, 1: active fec */
+	uint8_t   active_fec; /* current FEC mode */
+	uint16_t  rsv1;
+	uint32_t  rsv2[4];
+};
+
+/* Configure FEC mode, opcode:0x031A */
+struct hns3_config_fec_cmd {
+	uint8_t fec_mode;
+	uint8_t rsv[23];
 };
 
 #define HNS3_MAC_MGR_MASK_VLAN_B		BIT(0)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 81e7730..abe01e1 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -78,6 +78,8 @@ static int hns3_add_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
 static int hns3_remove_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
+static int hns3_restore_fec(struct hns3_hw *hw);
+static int hns3_query_dev_fec_info(struct rte_eth_dev *dev);
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -2819,6 +2821,13 @@ hns3_get_capability(struct hns3_hw *hw)
 	    device_id == HNS3_DEV_ID_200G_RDMA)
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_DCB_B, 1);
 
+	ret = hns3_query_dev_fec_info(eth_dev);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			     "failed to query FEC information, ret = %d", ret);
+		return ret;
+	}
+
 	/* Get PCI revision id */
 	ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN,
 				  HNS3_PCI_REVISION_ID);
@@ -5311,6 +5320,10 @@ hns3_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_promisc;
 
+	ret = hns3_restore_fec(hw);
+	if (ret)
+		goto err_promisc;
+
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED) {
 		ret = hns3_do_start(hns, false);
 		if (ret)
@@ -5389,6 +5402,147 @@ hns3_reset_service(void *param)
 		hns3_msix_process(hns, reset_level);
 }
 
+static int
+hns3_fec_get_capability(struct rte_eth_dev *dev, uint32_t *fec_cap)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_mac *mac = &hw->mac;
+	uint32_t mode;
+
+	switch (mac->link_speed) {
+	case ETH_SPEED_NUM_10G:
+	case ETH_SPEED_NUM_40G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
+			RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	case ETH_SPEED_NUM_25G:
+	case ETH_SPEED_NUM_50G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
+			RTE_ETH_FEC_CAPA_RS | RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	case ETH_SPEED_NUM_100G:
+	case ETH_SPEED_NUM_200G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_RS |
+			RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	default:
+		mode = 0;
+		break;
+	}
+
+	*fec_cap = mode;
+	return 0;
+}
+
+static int
+hns3_fec_get(struct rte_eth_dev *dev, enum rte_fec_mode *mode)
+{
+#define QUERY_ACTIVE_SPEED	1
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_sfp_speed_cmd *resp;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_SFP_GET_SPEED, true);
+	resp = (struct hns3_sfp_speed_cmd *)desc.data;
+	resp->query_type = QUERY_ACTIVE_SPEED;
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret == -EOPNOTSUPP) {
+		hns3_err(hw, "IMP do not support get FEC, ret = %d", ret);
+		return ret;
+	} else if (ret) {
+		hns3_err(hw, "get FEC failed, ret = %d", ret);
+		return ret;
+	}
+
+	*mode = resp->active_fec;
+	return 0;
+}
+
+static int
+hns3_set_fec_hw(struct hns3_hw *hw, enum rte_fec_mode mode)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, false);
+
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	switch (mode) {
+	case RTE_ETH_FEC_NOFEC:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_OFF);
+		break;
+	case RTE_ETH_FEC_BASER:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_BASER);
+		break;
+	case RTE_ETH_FEC_RS:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_RS);
+		break;
+	case RTE_ETH_FEC_AUTO:
+		hns3_set_bit(req->fec_mode, HNS3_MAC_CFG_FEC_AUTO_EN_B, 1);
+		break;
+	default:
+		return 0;
+	}
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw, "set fec mode failed, ret = %d", ret);
+
+	return ret;
+}
+
+static int
+hns3_fec_set(struct rte_eth_dev *dev, enum rte_fec_mode mode)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		return ret;
+
+	pf->fec_mode = mode;
+	return 0;
+}
+
+static int
+hns3_restore_fec(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+	enum rte_fec_mode mode = pf->fec_mode;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		hns3_err(hw, "restore fec mode(%d) failed, ret = %d",
+			 mode, ret);
+
+	return ret;
+}
+
+static int
+hns3_query_dev_fec_info(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_fec_get(dev, &pf->fec_mode);
+	if (ret)
+		hns3_err(hw, "query device FEC info failed, ret = %d", ret);
+
+	return ret;
+}
+
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_start          = hns3_dev_start,
 	.dev_stop           = hns3_dev_stop,
@@ -5434,6 +5588,9 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.get_reg                = hns3_get_regs,
 	.get_dcb_info           = hns3_get_dcb_info,
 	.dev_supported_ptypes_get = hns3_dev_supported_ptypes_get,
+	.fec_get_capability     = hns3_fec_get_capability,
+	.fec_get                = hns3_fec_get,
+	.fec_set                = hns3_fec_set,
 };
 
 static const struct hns3_reset_ops hns3_reset_ops = {
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 0e665e5..daf723e 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -510,6 +510,7 @@ struct hns3_pf {
 	struct hns3_err_msix_intr_stats abn_int_stats;
 
 	bool support_sfp_query;
+	enum rte_fec_mode fec_mode; /* current FEC mode for ethdev */
 
 	struct hns3_vtag_cfg vtag_config;
 	LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [V5 3/3] app/testpmd: add FEC command
  2020-09-17  8:23   ` [dpdk-dev] [V5 " Min Hu (Connor)
  2020-09-17  8:23     ` [dpdk-dev] [V5 1/3] ethdev: introduce FEC API Min Hu (Connor)
  2020-09-17  8:23     ` [dpdk-dev] [V5 2/3] net/hns3: support FEC Min Hu (Connor)
@ 2020-09-17  8:23     ` Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-17  8:23 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This commit adds testpmd capability to query and config FEC
function of device. This includes:
- show FEC capabilities, example:
	testpmd> show port 0 fec capabilities
- show FEC mode, example:
	testpmd> show port 0 fec_mode
- config FEC mode, example:
	testpmd> set port <port_id> 0 <auto|off|rs|baser>

	where:

	auto|off|rs|baser are four kinds of FEC mode which dev
	support according to MAC link speed.

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>
---
v4->v5:
Add RTE_ prefix for public FEC mode enum.

---
v3->v4:
adjust the display format of FEC mode

---
v2->v3:
adjust the display format of FEC capability.

---
 app/test-pmd/cmdline.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c  |  54 ++++++++++++
 app/test-pmd/testpmd.h |   2 +
 3 files changed, 275 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0a6ed85..c8fb616 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -19054,6 +19054,222 @@ cmdline_parse_inst_t cmd_show_tx_metadata = {
 	},
 };
 
+/* *** show fec capability per port configuration *** */
+struct cmd_show_fec_capability_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_fec;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_capability_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+	struct cmd_show_fec_capability_result *res = parsed_result;
+	uint32_t fec_cap;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_fec_get_capability(res->cmd_pid, &fec_cap);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC capability failed\n");
+		return;
+	}
+
+	show_fec_capability(fec_cap);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_capability_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_capability_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_capability_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_capability_fec =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_fec, "fec");
+cmdline_parse_token_string_t cmd_show_fec_capability_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_keyword, "capabilities");
+
+cmdline_parse_inst_t cmd_show_capability = {
+	.f = cmd_show_fec_capability_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec capabilities",
+	.tokens = {
+		(void *)&cmd_show_fec_capability_show,
+		(void *)&cmd_show_fec_capability_port,
+		(void *)&cmd_show_fec_capability_pid,
+		(void *)&cmd_show_fec_capability_fec,
+		(void *)&cmd_show_fec_capability_keyword,
+		NULL,
+	},
+};
+
+/* *** show fec mode per port configuration *** */
+struct cmd_show_fec_metadata_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_mode_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_NAME_SIZE 16
+	struct cmd_show_fec_metadata_result *res = parsed_result;
+	enum rte_fec_mode mode;
+	char buf[FEC_NAME_SIZE];
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+	ret = rte_eth_fec_get(res->cmd_pid, &mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC mode failed\n");
+		return;
+	}
+
+	switch (mode) {
+	case RTE_ETH_FEC_NOFEC:
+		strlcpy(buf, "off", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_BASER:
+		strlcpy(buf, "baser", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_RS:
+		strlcpy(buf, "rs", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_AUTO:
+		strlcpy(buf, "auto", sizeof(buf));
+		break;
+	default:
+		return;
+	}
+
+	printf("%s\n", buf);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_mode_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_mode_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_mode_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_mode_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_keyword, "fec_mode");
+
+cmdline_parse_inst_t cmd_show_fec_mode = {
+	.f = cmd_show_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec_mode",
+	.tokens = {
+		(void *)&cmd_show_fec_mode_show,
+		(void *)&cmd_show_fec_mode_port,
+		(void *)&cmd_show_fec_mode_pid,
+		(void *)&cmd_show_fec_mode_keyword,
+		NULL,
+	},
+};
+
+/* *** set fec mode per port configuration *** */
+struct cmd_set_port_fec_mode {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t fec_mode;
+	cmdline_fixed_string_t fec_value;
+};
+
+/* Common CLI fields for set fec mode */
+cmdline_parse_token_string_t cmd_set_port_fec_mode_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port, "port");
+cmdline_parse_token_num_t cmd_set_port_fec_mode_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_port_fec_mode_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_mode, "fec_mode");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_value =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_value, NULL);
+
+static void
+cmd_set_port_fec_mode_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	__rte_unused void *data)
+{
+	struct cmd_set_port_fec_mode *res = parsed_result;
+	uint16_t port_id = res->port_id;
+	enum rte_fec_mode mode;
+	int ret;
+
+	ret = parse_fec_mode(res->fec_value, &mode);
+	if (ret < 0) {
+		printf("Unknown fec mode: %s for Port %d\n", res->fec_value,
+			port_id);
+		return;
+	}
+
+	ret = rte_eth_fec_set(port_id, mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Set FEC mode failed\n");
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_fec_mode = {
+	.f = cmd_set_port_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> fec_mode <auto|off|rs|baser>",
+	.tokens = {
+		(void *)&cmd_set_port_fec_mode_set,
+		(void *)&cmd_set_port_fec_mode_port,
+		(void *)&cmd_set_port_fec_mode_port_id,
+		(void *)&cmd_set_port_fec_mode_str,
+		(void *)&cmd_set_port_fec_mode_value,
+		NULL,
+	},
+};
+
 /* show port supported ptypes */
 
 /* Common result structure for show port ptypes */
@@ -19685,6 +19901,9 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_set_raw,
 	(cmdline_parse_inst_t *)&cmd_show_set_raw_all,
 	(cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
+	(cmdline_parse_inst_t *)&cmd_show_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_set_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_show_capability,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 30bee33..4ed277a 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -138,6 +138,28 @@ const struct rss_type_info rss_type_table[] = {
 	{ NULL, 0 },
 };
 
+static const struct {
+	enum rte_fec_mode mode;
+	const char *name;
+} fec_mode_name[] = {
+	{
+		.mode = RTE_ETH_FEC_NOFEC,
+		.name = "off",
+	},
+	{
+		.mode = RTE_ETH_FEC_BASER,
+		.name = "baser",
+	},
+	{
+		.mode = RTE_ETH_FEC_RS,
+		.name = "rs",
+	},
+	{
+		.mode = RTE_ETH_FEC_AUTO,
+		.name = "auto",
+	},
+};
+
 static void
 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
 {
@@ -2967,6 +2989,38 @@ set_tx_pkt_split(const char *name)
 	printf("unknown value: \"%s\"\n", name);
 }
 
+int
+parse_fec_mode(const char *name, enum rte_fec_mode *mode)
+{
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(fec_mode_name); i++) {
+		if (strcmp(fec_mode_name[i].name, name) == 0) {
+			*mode = fec_mode_name[i].mode;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void
+show_fec_capability(uint32_t fec_cap)
+{
+	uint32_t i;
+
+	if (fec_cap == 0) {
+		printf("FEC is not supported\n");
+		return;
+	}
+
+	printf("FEC capabilities: ");
+	for (i = RTE_ETH_FEC_BASER; i < RTE_ETH_FEC_NUM; i++) {
+		if (fec_cap & 1U << i)
+			printf("%s ", fec_mode_name[i].name);
+	}
+	printf("\n");
+}
+
 void
 show_tx_pkt_segments(void)
 {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 25a12b1..8cc4728 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -778,6 +778,8 @@ void show_tx_pkt_segments(void);
 void set_tx_pkt_times(unsigned int *tx_times);
 void show_tx_pkt_times(void);
 void set_tx_pkt_split(const char *name);
+int parse_fec_mode(const char *name, enum rte_fec_mode *mode);
+void show_fec_capability(uint32_t fec_cap);
 void set_nb_pkt_per_burst(uint16_t pkt_burst);
 char *list_pkt_forwarding_modes(void);
 char *list_pkt_forwarding_retry_modes(void);
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [V5 0/3] add FEC support
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
                     ` (4 preceding siblings ...)
  2020-09-17  8:23   ` [dpdk-dev] [V5 " Min Hu (Connor)
@ 2020-09-17  8:52   ` Min Hu (Connor)
  2020-09-17  8:52     ` [dpdk-dev] [V5 1/3] ethdev: introduce FEC API Min Hu (Connor)
                       ` (2 more replies)
  2020-09-18  9:04   ` [dpdk-dev] [PATCH V6 0/3] add FEC support Min Hu (Connor)
                     ` (10 subsequent siblings)
  16 siblings, 3 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-17  8:52 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This series add FEC support for ethdev.

Min Hu (Connor) (3):
  ethdev: introduce FEC API
  net/hns3: support FEC
  app/testpmd: add FEC command

 app/test-pmd/cmdline.c                   | 219 +++++++++++++++++++++++++++++++
 app/test-pmd/config.c                    |  54 ++++++++
 app/test-pmd/testpmd.h                   |   2 +
 doc/guides/rel_notes/release_20_11.rst   |  13 ++
 drivers/net/hns3/hns3_cmd.h              |  19 ++-
 drivers/net/hns3/hns3_ethdev.c           | 157 ++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h           |   1 +
 lib/librte_ethdev/rte_ethdev.c           |  50 +++++++
 lib/librte_ethdev/rte_ethdev.h           |  83 ++++++++++++
 lib/librte_ethdev/rte_ethdev_core.h      |  77 +++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |   5 +
 11 files changed, 679 insertions(+), 1 deletion(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [V5 1/3] ethdev: introduce FEC API
  2020-09-17  8:52   ` [dpdk-dev] [V5 0/3] add FEC support Min Hu (Connor)
@ 2020-09-17  8:52     ` Min Hu (Connor)
  2020-09-17  9:58       ` Andrew Rybchenko
  2020-09-17 12:49       ` Ananyev, Konstantin
  2020-09-17  8:52     ` [dpdk-dev] [V5 2/3] net/hns3: support FEC Min Hu (Connor)
  2020-09-17  8:52     ` [dpdk-dev] [V5 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 2 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-17  8:52 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

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>
---
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   | 13 +++++
 lib/librte_ethdev/rte_ethdev.c           | 50 +++++++++++++++++++
 lib/librte_ethdev/rte_ethdev.h           | 83 ++++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_core.h      | 77 +++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |  5 ++
 5 files changed, 228 insertions(+)

diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index cc72609..e4f0587 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -55,6 +55,19 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Added the FEC Library, a generic FEC query and config library.**
+
+  Added the FEC library which provides an API for query FEC capabilities and
+  FEC mode from device. Also, API for configuring FEC mode is also provided.
+
+  Added hns3 FEC PMD, for supporting query and config FEC mode.
+
+* **Updated testpmd with a command for FEC.**
+
+  Added a FEC command to testpmd app,
+  ``show port <port_id> fec capabilities`` which queries FEC capabilities device supports.
+  ``show port <port_id> fec_mode`` which queries FEC mode from device.
+  ``set port <port_id> fec_mode <auto|off|rs|baser>`` which configures FEC mode to device.
 
 Removed Items
 -------------
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 7858ad5..fde77c1 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -3642,6 +3642,56 @@ 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_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_fec_mode mode)
+{
+	struct rte_eth_dev *dev;
+	uint32_t fec_mode_mask;
+	int ret;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	ret = rte_eth_fec_get_capability(port_id, &fec_mode_mask);
+	if (ret)
+		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 & (1U << (uint32_t)mode))) {
+		RTE_ETHDEV_LOG(ERR, "unsupported fec mode=%d\n", mode);
+		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..aa79326 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1511,6 +1511,25 @@ 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_fec_mode {
+	RTE_ETH_FEC_NOFEC = 0,      /**< FEC is off */
+	RTE_ETH_FEC_BASER,          /**< FEC using common algorithm */
+	RTE_ETH_FEC_RS,             /**< FEC using RS algorithm */
+	RTE_ETH_FEC_AUTO,           /**< FEC autonegotiation modes */
+	RTE_ETH_FEC_NUM
+};
+
+/* This indicates FEC capabilities */
+#define RTE_ETH_FEC_CAPA_NOFEC  (1U << RTE_ETH_FEC_NOFEC)
+#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_FEC_CAPA_AUTO   (1U << RTE_ETH_FEC_AUTO)
+
+
 #define RTE_ETH_ALL RTE_MAX_ETHPORTS
 
 /* Macros to check for valid port */
@@ -3328,6 +3347,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_BASER
+ *   RTE_ETH_FEC_CAPA_RS
+ *   RTE_ETH_FEC_CAPA_AUTO
+ * @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_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_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..cd1acf1 100644
--- a/lib/librte_ethdev/rte_ethdev_core.h
+++ b/lib/librte_ethdev/rte_ethdev_core.h
@@ -604,6 +604,76 @@ 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_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_fec_mode mode);
+
+/**
  * @internal A structure containing the functions exported by an Ethernet driver.
  */
 struct eth_dev_ops {
@@ -752,6 +822,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 {
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [V5 2/3] net/hns3: support FEC
  2020-09-17  8:52   ` [dpdk-dev] [V5 0/3] add FEC support Min Hu (Connor)
  2020-09-17  8:52     ` [dpdk-dev] [V5 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-17  8:52     ` Min Hu (Connor)
  2020-09-17  8:52     ` [dpdk-dev] [V5 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-17  8:52 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

Forward error correction (FEC) is a bit error correction mode.
It adds error correction information to data packets at the
transmit end, and uses the error correction information to correct
the bit errors generated during data packet transmission at the
receive end. This improves signal quality but also brings a delay
to signals. This function can be enabled or disabled as required.

This patch adds FEC support for ethdev.Introduce ethdev
operations 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>
---
v4->v5:
Data type for fec_cap is changed from uint8_t
to uint32_t for possible future expansion.

---
v2->v3:
adjust the return value of function.

---
 drivers/net/hns3/hns3_cmd.h    |  19 ++++-
 drivers/net/hns3/hns3_ethdev.c | 157 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h |   1 +
 3 files changed, 176 insertions(+), 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index d70f42e..8b80353 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -99,6 +99,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_CONFIG_MAX_FRM_SIZE    = 0x0308,
 	HNS3_OPC_CONFIG_SPEED_DUP       = 0x0309,
 	HNS3_MAC_COMMON_INT_EN          = 0x030E,
+	HNS3_OPC_CONFIG_FEC_MODE        = 0x031A,
 
 	/* PFC/Pause commands */
 	HNS3_OPC_CFG_MAC_PAUSE_EN       = 0x0701,
@@ -653,9 +654,25 @@ struct hns3_config_auto_neg_cmd {
 	uint8_t   rsv[20];
 };
 
+#define HNS3_MAC_CFG_FEC_AUTO_EN_B	0
+#define HNS3_MAC_CFG_FEC_MODE_S		1
+#define HNS3_MAC_CFG_FEC_MODE_M	GENMASK(3, 1)
+#define HNS3_MAC_FEC_OFF		0
+#define HNS3_MAC_FEC_BASER		1
+#define HNS3_MAC_FEC_RS			2
+
 struct hns3_sfp_speed_cmd {
 	uint32_t  sfp_speed;
-	uint32_t  rsv[5];
+	uint8_t   query_type; /* 0: sfp speed, 1: active fec */
+	uint8_t   active_fec; /* current FEC mode */
+	uint16_t  rsv1;
+	uint32_t  rsv2[4];
+};
+
+/* Configure FEC mode, opcode:0x031A */
+struct hns3_config_fec_cmd {
+	uint8_t fec_mode;
+	uint8_t rsv[23];
 };
 
 #define HNS3_MAC_MGR_MASK_VLAN_B		BIT(0)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 81e7730..abe01e1 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -78,6 +78,8 @@ static int hns3_add_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
 static int hns3_remove_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
+static int hns3_restore_fec(struct hns3_hw *hw);
+static int hns3_query_dev_fec_info(struct rte_eth_dev *dev);
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -2819,6 +2821,13 @@ hns3_get_capability(struct hns3_hw *hw)
 	    device_id == HNS3_DEV_ID_200G_RDMA)
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_DCB_B, 1);
 
+	ret = hns3_query_dev_fec_info(eth_dev);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			     "failed to query FEC information, ret = %d", ret);
+		return ret;
+	}
+
 	/* Get PCI revision id */
 	ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN,
 				  HNS3_PCI_REVISION_ID);
@@ -5311,6 +5320,10 @@ hns3_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_promisc;
 
+	ret = hns3_restore_fec(hw);
+	if (ret)
+		goto err_promisc;
+
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED) {
 		ret = hns3_do_start(hns, false);
 		if (ret)
@@ -5389,6 +5402,147 @@ hns3_reset_service(void *param)
 		hns3_msix_process(hns, reset_level);
 }
 
+static int
+hns3_fec_get_capability(struct rte_eth_dev *dev, uint32_t *fec_cap)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_mac *mac = &hw->mac;
+	uint32_t mode;
+
+	switch (mac->link_speed) {
+	case ETH_SPEED_NUM_10G:
+	case ETH_SPEED_NUM_40G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
+			RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	case ETH_SPEED_NUM_25G:
+	case ETH_SPEED_NUM_50G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
+			RTE_ETH_FEC_CAPA_RS | RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	case ETH_SPEED_NUM_100G:
+	case ETH_SPEED_NUM_200G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_RS |
+			RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	default:
+		mode = 0;
+		break;
+	}
+
+	*fec_cap = mode;
+	return 0;
+}
+
+static int
+hns3_fec_get(struct rte_eth_dev *dev, enum rte_fec_mode *mode)
+{
+#define QUERY_ACTIVE_SPEED	1
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_sfp_speed_cmd *resp;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_SFP_GET_SPEED, true);
+	resp = (struct hns3_sfp_speed_cmd *)desc.data;
+	resp->query_type = QUERY_ACTIVE_SPEED;
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret == -EOPNOTSUPP) {
+		hns3_err(hw, "IMP do not support get FEC, ret = %d", ret);
+		return ret;
+	} else if (ret) {
+		hns3_err(hw, "get FEC failed, ret = %d", ret);
+		return ret;
+	}
+
+	*mode = resp->active_fec;
+	return 0;
+}
+
+static int
+hns3_set_fec_hw(struct hns3_hw *hw, enum rte_fec_mode mode)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, false);
+
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	switch (mode) {
+	case RTE_ETH_FEC_NOFEC:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_OFF);
+		break;
+	case RTE_ETH_FEC_BASER:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_BASER);
+		break;
+	case RTE_ETH_FEC_RS:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_RS);
+		break;
+	case RTE_ETH_FEC_AUTO:
+		hns3_set_bit(req->fec_mode, HNS3_MAC_CFG_FEC_AUTO_EN_B, 1);
+		break;
+	default:
+		return 0;
+	}
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw, "set fec mode failed, ret = %d", ret);
+
+	return ret;
+}
+
+static int
+hns3_fec_set(struct rte_eth_dev *dev, enum rte_fec_mode mode)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		return ret;
+
+	pf->fec_mode = mode;
+	return 0;
+}
+
+static int
+hns3_restore_fec(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+	enum rte_fec_mode mode = pf->fec_mode;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		hns3_err(hw, "restore fec mode(%d) failed, ret = %d",
+			 mode, ret);
+
+	return ret;
+}
+
+static int
+hns3_query_dev_fec_info(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_fec_get(dev, &pf->fec_mode);
+	if (ret)
+		hns3_err(hw, "query device FEC info failed, ret = %d", ret);
+
+	return ret;
+}
+
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_start          = hns3_dev_start,
 	.dev_stop           = hns3_dev_stop,
@@ -5434,6 +5588,9 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.get_reg                = hns3_get_regs,
 	.get_dcb_info           = hns3_get_dcb_info,
 	.dev_supported_ptypes_get = hns3_dev_supported_ptypes_get,
+	.fec_get_capability     = hns3_fec_get_capability,
+	.fec_get                = hns3_fec_get,
+	.fec_set                = hns3_fec_set,
 };
 
 static const struct hns3_reset_ops hns3_reset_ops = {
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 0e665e5..daf723e 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -510,6 +510,7 @@ struct hns3_pf {
 	struct hns3_err_msix_intr_stats abn_int_stats;
 
 	bool support_sfp_query;
+	enum rte_fec_mode fec_mode; /* current FEC mode for ethdev */
 
 	struct hns3_vtag_cfg vtag_config;
 	LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [V5 3/3] app/testpmd: add FEC command
  2020-09-17  8:52   ` [dpdk-dev] [V5 0/3] add FEC support Min Hu (Connor)
  2020-09-17  8:52     ` [dpdk-dev] [V5 1/3] ethdev: introduce FEC API Min Hu (Connor)
  2020-09-17  8:52     ` [dpdk-dev] [V5 2/3] net/hns3: support FEC Min Hu (Connor)
@ 2020-09-17  8:52     ` Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-17  8:52 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This commit adds testpmd capability to query and config FEC
function of device. This includes:
- show FEC capabilities, example:
	testpmd> show port 0 fec capabilities
- show FEC mode, example:
	testpmd> show port 0 fec_mode
- config FEC mode, example:
	testpmd> set port <port_id> 0 <auto|off|rs|baser>

	where:

	auto|off|rs|baser are four kinds of FEC mode which dev
	support according to MAC link speed.

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>
---
v4->v5:
Add RTE_ prefix for public FEC mode enum.

---
v3->v4:
adjust the display format of FEC mode

---
v2->v3:
adjust the display format of FEC capability.

---
 app/test-pmd/cmdline.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c  |  54 ++++++++++++
 app/test-pmd/testpmd.h |   2 +
 3 files changed, 275 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0a6ed85..c8fb616 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -19054,6 +19054,222 @@ cmdline_parse_inst_t cmd_show_tx_metadata = {
 	},
 };
 
+/* *** show fec capability per port configuration *** */
+struct cmd_show_fec_capability_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_fec;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_capability_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+	struct cmd_show_fec_capability_result *res = parsed_result;
+	uint32_t fec_cap;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_fec_get_capability(res->cmd_pid, &fec_cap);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC capability failed\n");
+		return;
+	}
+
+	show_fec_capability(fec_cap);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_capability_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_capability_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_capability_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_capability_fec =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_fec, "fec");
+cmdline_parse_token_string_t cmd_show_fec_capability_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_keyword, "capabilities");
+
+cmdline_parse_inst_t cmd_show_capability = {
+	.f = cmd_show_fec_capability_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec capabilities",
+	.tokens = {
+		(void *)&cmd_show_fec_capability_show,
+		(void *)&cmd_show_fec_capability_port,
+		(void *)&cmd_show_fec_capability_pid,
+		(void *)&cmd_show_fec_capability_fec,
+		(void *)&cmd_show_fec_capability_keyword,
+		NULL,
+	},
+};
+
+/* *** show fec mode per port configuration *** */
+struct cmd_show_fec_metadata_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_mode_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_NAME_SIZE 16
+	struct cmd_show_fec_metadata_result *res = parsed_result;
+	enum rte_fec_mode mode;
+	char buf[FEC_NAME_SIZE];
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+	ret = rte_eth_fec_get(res->cmd_pid, &mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC mode failed\n");
+		return;
+	}
+
+	switch (mode) {
+	case RTE_ETH_FEC_NOFEC:
+		strlcpy(buf, "off", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_BASER:
+		strlcpy(buf, "baser", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_RS:
+		strlcpy(buf, "rs", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_AUTO:
+		strlcpy(buf, "auto", sizeof(buf));
+		break;
+	default:
+		return;
+	}
+
+	printf("%s\n", buf);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_mode_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_mode_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_mode_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_mode_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_keyword, "fec_mode");
+
+cmdline_parse_inst_t cmd_show_fec_mode = {
+	.f = cmd_show_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec_mode",
+	.tokens = {
+		(void *)&cmd_show_fec_mode_show,
+		(void *)&cmd_show_fec_mode_port,
+		(void *)&cmd_show_fec_mode_pid,
+		(void *)&cmd_show_fec_mode_keyword,
+		NULL,
+	},
+};
+
+/* *** set fec mode per port configuration *** */
+struct cmd_set_port_fec_mode {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t fec_mode;
+	cmdline_fixed_string_t fec_value;
+};
+
+/* Common CLI fields for set fec mode */
+cmdline_parse_token_string_t cmd_set_port_fec_mode_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port, "port");
+cmdline_parse_token_num_t cmd_set_port_fec_mode_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_port_fec_mode_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_mode, "fec_mode");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_value =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_value, NULL);
+
+static void
+cmd_set_port_fec_mode_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	__rte_unused void *data)
+{
+	struct cmd_set_port_fec_mode *res = parsed_result;
+	uint16_t port_id = res->port_id;
+	enum rte_fec_mode mode;
+	int ret;
+
+	ret = parse_fec_mode(res->fec_value, &mode);
+	if (ret < 0) {
+		printf("Unknown fec mode: %s for Port %d\n", res->fec_value,
+			port_id);
+		return;
+	}
+
+	ret = rte_eth_fec_set(port_id, mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Set FEC mode failed\n");
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_fec_mode = {
+	.f = cmd_set_port_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> fec_mode <auto|off|rs|baser>",
+	.tokens = {
+		(void *)&cmd_set_port_fec_mode_set,
+		(void *)&cmd_set_port_fec_mode_port,
+		(void *)&cmd_set_port_fec_mode_port_id,
+		(void *)&cmd_set_port_fec_mode_str,
+		(void *)&cmd_set_port_fec_mode_value,
+		NULL,
+	},
+};
+
 /* show port supported ptypes */
 
 /* Common result structure for show port ptypes */
@@ -19685,6 +19901,9 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_set_raw,
 	(cmdline_parse_inst_t *)&cmd_show_set_raw_all,
 	(cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
+	(cmdline_parse_inst_t *)&cmd_show_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_set_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_show_capability,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 30bee33..4ed277a 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -138,6 +138,28 @@ const struct rss_type_info rss_type_table[] = {
 	{ NULL, 0 },
 };
 
+static const struct {
+	enum rte_fec_mode mode;
+	const char *name;
+} fec_mode_name[] = {
+	{
+		.mode = RTE_ETH_FEC_NOFEC,
+		.name = "off",
+	},
+	{
+		.mode = RTE_ETH_FEC_BASER,
+		.name = "baser",
+	},
+	{
+		.mode = RTE_ETH_FEC_RS,
+		.name = "rs",
+	},
+	{
+		.mode = RTE_ETH_FEC_AUTO,
+		.name = "auto",
+	},
+};
+
 static void
 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
 {
@@ -2967,6 +2989,38 @@ set_tx_pkt_split(const char *name)
 	printf("unknown value: \"%s\"\n", name);
 }
 
+int
+parse_fec_mode(const char *name, enum rte_fec_mode *mode)
+{
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(fec_mode_name); i++) {
+		if (strcmp(fec_mode_name[i].name, name) == 0) {
+			*mode = fec_mode_name[i].mode;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void
+show_fec_capability(uint32_t fec_cap)
+{
+	uint32_t i;
+
+	if (fec_cap == 0) {
+		printf("FEC is not supported\n");
+		return;
+	}
+
+	printf("FEC capabilities: ");
+	for (i = RTE_ETH_FEC_BASER; i < RTE_ETH_FEC_NUM; i++) {
+		if (fec_cap & 1U << i)
+			printf("%s ", fec_mode_name[i].name);
+	}
+	printf("\n");
+}
+
 void
 show_tx_pkt_segments(void)
 {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 25a12b1..8cc4728 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -778,6 +778,8 @@ void show_tx_pkt_segments(void);
 void set_tx_pkt_times(unsigned int *tx_times);
 void show_tx_pkt_times(void);
 void set_tx_pkt_split(const char *name);
+int parse_fec_mode(const char *name, enum rte_fec_mode *mode);
+void show_fec_capability(uint32_t fec_cap);
 void set_nb_pkt_per_burst(uint16_t pkt_burst);
 char *list_pkt_forwarding_modes(void);
 char *list_pkt_forwarding_retry_modes(void);
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [V5 1/3] ethdev: introduce FEC API
  2020-09-17  8:52     ` [dpdk-dev] [V5 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-17  9:58       ` Andrew Rybchenko
  2020-09-18  9:28         ` Min Hu (Connor)
  2020-09-17 12:49       ` Ananyev, Konstantin
  1 sibling, 1 reply; 118+ messages in thread
From: Andrew Rybchenko @ 2020-09-17  9:58 UTC (permalink / raw)
  To: Min Hu (Connor), dev; +Cc: konstantin.ananyev, thomas, ferruh.yigit, linuxarm

On 9/17/20 11:52 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>
> ---
> 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   | 13 +++++
>  lib/librte_ethdev/rte_ethdev.c           | 50 +++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev.h           | 83 ++++++++++++++++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev_core.h      | 77 +++++++++++++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev_version.map |  5 ++
>  5 files changed, 228 insertions(+)
> 
> diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
> index cc72609..e4f0587 100644
> --- a/doc/guides/rel_notes/release_20_11.rst
> +++ b/doc/guides/rel_notes/release_20_11.rst
> @@ -55,6 +55,19 @@ New Features
>       Also, make sure to start the actual text at the margin.
>       =======================================================
>  
> +* **Added the FEC Library, a generic FEC query and config library.**
> +
> +  Added the FEC library which provides an API for query FEC capabilities and
> +  FEC mode from device. Also, API for configuring FEC mode is also provided.

The patch does not add a library. It adds an API get FEC
capabilities, get current configuration and allows to set
a new configuration.

> +
> +  Added hns3 FEC PMD, for supporting query and config FEC mode.

If required, it should be later in release notes in accordance
with defined order.

> +
> +* **Updated testpmd with a command for FEC.**
> +
> +  Added a FEC command to testpmd app,
> +  ``show port <port_id> fec capabilities`` which queries FEC capabilities device supports.
> +  ``show port <port_id> fec_mode`` which queries FEC mode from device.
> +  ``set port <port_id> fec_mode <auto|off|rs|baser>`` which configures FEC mode to device.

IMHO, it is not much details for release notes.
As I understand it is assumed that testpmd must be
updated for any new ethdev feature, so, the information
about testpmd is not really required.

>  
>  Removed Items
>  -------------
> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> index 7858ad5..fde77c1 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -3642,6 +3642,56 @@ 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_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_fec_mode mode)
> +{
> +	struct rte_eth_dev *dev;
> +	uint32_t fec_mode_mask;
> +	int ret;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);

Basically the check is duplicated since get_capabilities
does it. However, there is no much harm to keep. If so,
I'd move it below just before port_id usage as an index
in rte_eth_devices array.

> +
> +	ret = rte_eth_fec_get_capability(port_id, &fec_mode_mask);
> +	if (ret)

Please, compare with 0 explicitly as specified in DPDK coding
style.

> +		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 & (1U << (uint32_t)mode))) {
> +		RTE_ETHDEV_LOG(ERR, "unsupported fec mode=%d\n", mode);

I'd use "FEC" (in capitals) in log message as well.
Also I think it would be useful to log 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..aa79326 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -1511,6 +1511,25 @@ 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_fec_mode {

enum rte_eth_fec_mode
to be consistent with other enums and to have library prefix.

> +	RTE_ETH_FEC_NOFEC = 0,      /**< FEC is off */
> +	RTE_ETH_FEC_BASER,          /**< FEC using common algorithm */
> +	RTE_ETH_FEC_RS,             /**< FEC using RS algorithm */
> +	RTE_ETH_FEC_AUTO,           /**< FEC autonegotiation modes */

May I suggest to put AUTO just after NOFEC. It would look move
logical in the future when more FEC modes are added. It would
look strange with AUTO in the middle of the list.

> +	RTE_ETH_FEC_NUM

I'm not about about current policy for such items. Is it really
required? Addition of more FEC modes will be ABI breakage.

> +};
> +
> +/* This indicates FEC capabilities */
> +#define RTE_ETH_FEC_CAPA_NOFEC  (1U << RTE_ETH_FEC_NOFEC)
> +#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_FEC_CAPA_AUTO   (1U << RTE_ETH_FEC_AUTO)
> +
> +
>  #define RTE_ETH_ALL RTE_MAX_ETHPORTS
>  
>  /* Macros to check for valid port */
> @@ -3328,6 +3347,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_BASER
> + *   RTE_ETH_FEC_CAPA_RS
> + *   RTE_ETH_FEC_CAPA_AUTO

I'd like to see thoughts about different FEC modes for
different link speed. How to report it?
(sorry if I missed it before)

> + * @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);

[snip]

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [V5 1/3] ethdev: introduce FEC API
  2020-09-17  8:52     ` [dpdk-dev] [V5 1/3] ethdev: introduce FEC API Min Hu (Connor)
  2020-09-17  9:58       ` Andrew Rybchenko
@ 2020-09-17 12:49       ` Ananyev, Konstantin
  2020-09-18  1:57         ` humin (Connor)
  1 sibling, 1 reply; 118+ messages in thread
From: Ananyev, Konstantin @ 2020-09-17 12:49 UTC (permalink / raw)
  To: Min Hu (Connor), dev; +Cc: thomas, arybchenko, Yigit, Ferruh, linuxarm


> 
> 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>
> ---
> 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   | 13 +++++
>  lib/librte_ethdev/rte_ethdev.c           | 50 +++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev.h           | 83 ++++++++++++++++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev_core.h      | 77 +++++++++++++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev_version.map |  5 ++
>  5 files changed, 228 insertions(+)
> 
> diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
> index cc72609..e4f0587 100644
> --- a/doc/guides/rel_notes/release_20_11.rst
> +++ b/doc/guides/rel_notes/release_20_11.rst
> @@ -55,6 +55,19 @@ New Features
>       Also, make sure to start the actual text at the margin.
>       =======================================================
> 
> +* **Added the FEC Library, a generic FEC query and config library.**
> +
> +  Added the FEC library which provides an API for query FEC capabilities and
> +  FEC mode from device. Also, API for configuring FEC mode is also provided.
> +
> +  Added hns3 FEC PMD, for supporting query and config FEC mode.
> +
> +* **Updated testpmd with a command for FEC.**
> +
> +  Added a FEC command to testpmd app,
> +  ``show port <port_id> fec capabilities`` which queries FEC capabilities device supports.
> +  ``show port <port_id> fec_mode`` which queries FEC mode from device.
> +  ``set port <port_id> fec_mode <auto|off|rs|baser>`` which configures FEC mode to device.
> 
>  Removed Items
>  -------------
> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> index 7858ad5..fde77c1 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -3642,6 +3642,56 @@ 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_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_fec_mode mode)
> +{
> +	struct rte_eth_dev *dev;
> +	uint32_t fec_mode_mask;
> +	int ret;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	ret = rte_eth_fec_get_capability(port_id, &fec_mode_mask);
> +	if (ret)
> +		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 & (1U << (uint32_t)mode))) {
> +		RTE_ETHDEV_LOG(ERR, "unsupported fec mode=%d\n", mode);
> +		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..aa79326 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -1511,6 +1511,25 @@ 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_fec_mode {
> +	RTE_ETH_FEC_NOFEC = 0,      /**< FEC is off */
> +	RTE_ETH_FEC_BASER,          /**< FEC using common algorithm */
> +	RTE_ETH_FEC_RS,             /**< FEC using RS algorithm */
> +	RTE_ETH_FEC_AUTO,           /**< FEC autonegotiation modes */
> +	RTE_ETH_FEC_NUM

It is better not to have RTE_ETH_FEC_NUM here:
Any future additions to that enum would overwrite _NUM values and would
considered as ABI breakage.
Aprart from that:
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>

> +};
> +
> +/* This indicates FEC capabilities */
> +#define RTE_ETH_FEC_CAPA_NOFEC  (1U << RTE_ETH_FEC_NOFEC)
> +#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_FEC_CAPA_AUTO   (1U << RTE_ETH_FEC_AUTO)
> +
> +
>  #define RTE_ETH_ALL RTE_MAX_ETHPORTS
> 
>  /* Macros to check for valid port */
> @@ -3328,6 +3347,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_BASER
> + *   RTE_ETH_FEC_CAPA_RS
> + *   RTE_ETH_FEC_CAPA_AUTO
> + * @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_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_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..cd1acf1 100644
> --- a/lib/librte_ethdev/rte_ethdev_core.h
> +++ b/lib/librte_ethdev/rte_ethdev_core.h
> @@ -604,6 +604,76 @@ 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_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_fec_mode mode);
> +
> +/**
>   * @internal A structure containing the functions exported by an Ethernet driver.
>   */
>  struct eth_dev_ops {
> @@ -752,6 +822,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 {
> --
> 2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [V5 1/3] ethdev: introduce FEC API
  2020-09-17 12:49       ` Ananyev, Konstantin
@ 2020-09-18  1:57         ` humin (Connor)
  2020-09-18 10:46           ` Ananyev, Konstantin
  0 siblings, 1 reply; 118+ messages in thread
From: humin (Connor) @ 2020-09-18  1:57 UTC (permalink / raw)
  To: Ananyev, Konstantin, dev; +Cc: thomas, arybchenko, Yigit, Ferruh, linuxarm



在 2020/9/17 20:49, Ananyev, Konstantin 写道:
> 
>>
>> 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>
>> ---
>> 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   | 13 +++++
>>   lib/librte_ethdev/rte_ethdev.c           | 50 +++++++++++++++++++
>>   lib/librte_ethdev/rte_ethdev.h           | 83 ++++++++++++++++++++++++++++++++
>>   lib/librte_ethdev/rte_ethdev_core.h      | 77 +++++++++++++++++++++++++++++
>>   lib/librte_ethdev/rte_ethdev_version.map |  5 ++
>>   5 files changed, 228 insertions(+)
>>
>> diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
>> index cc72609..e4f0587 100644
>> --- a/doc/guides/rel_notes/release_20_11.rst
>> +++ b/doc/guides/rel_notes/release_20_11.rst
>> @@ -55,6 +55,19 @@ New Features
>>        Also, make sure to start the actual text at the margin.
>>        =======================================================
>>
>> +* **Added the FEC Library, a generic FEC query and config library.**
>> +
>> +  Added the FEC library which provides an API for query FEC capabilities and
>> +  FEC mode from device. Also, API for configuring FEC mode is also provided.
>> +
>> +  Added hns3 FEC PMD, for supporting query and config FEC mode.
>> +
>> +* **Updated testpmd with a command for FEC.**
>> +
>> +  Added a FEC command to testpmd app,
>> +  ``show port <port_id> fec capabilities`` which queries FEC capabilities device supports.
>> +  ``show port <port_id> fec_mode`` which queries FEC mode from device.
>> +  ``set port <port_id> fec_mode <auto|off|rs|baser>`` which configures FEC mode to device.
>>
>>   Removed Items
>>   -------------
>> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
>> index 7858ad5..fde77c1 100644
>> --- a/lib/librte_ethdev/rte_ethdev.c
>> +++ b/lib/librte_ethdev/rte_ethdev.c
>> @@ -3642,6 +3642,56 @@ 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_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_fec_mode mode)
>> +{
>> +	struct rte_eth_dev *dev;
>> +	uint32_t fec_mode_mask;
>> +	int ret;
>> +
>> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
>> +
>> +	ret = rte_eth_fec_get_capability(port_id, &fec_mode_mask);
>> +	if (ret)
>> +		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 & (1U << (uint32_t)mode))) {
>> +		RTE_ETHDEV_LOG(ERR, "unsupported fec mode=%d\n", mode);
>> +		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..aa79326 100644
>> --- a/lib/librte_ethdev/rte_ethdev.h
>> +++ b/lib/librte_ethdev/rte_ethdev.h
>> @@ -1511,6 +1511,25 @@ 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_fec_mode {
>> +	RTE_ETH_FEC_NOFEC = 0,      /**< FEC is off */
>> +	RTE_ETH_FEC_BASER,          /**< FEC using common algorithm */
>> +	RTE_ETH_FEC_RS,             /**< FEC using RS algorithm */
>> +	RTE_ETH_FEC_AUTO,           /**< FEC autonegotiation modes */
>> +	RTE_ETH_FEC_NUM
> 
> It is better not to have RTE_ETH_FEC_NUM here:
> Any future additions to that enum would overwrite _NUM values and would
> considered as ABI breakage.
> Aprart from that:
> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> 
HI,
       it does not matter even though RTE_ETH_FEC_NUM value is changed 
when adding new element to that enum. RTE_ETH_FEC_NUM is used as the MAX 
vlaue of FEC modes, not one FEC mode itself.
       One of the application scenarios is as follows,set "testpmd" as 
an example:
show_fec_capability(uint32_t fec_cap)
{
	uint32_t i;

	if (fec_cap == 0) {
		printf("FEC is not supported\n");
		return;
	}

	printf("FEC capabilities: ");
	for (i = RTE_ETH_FEC_BASER; i < RTE_ETH_FEC_NUM; i++) {
		if (fec_cap & 1U << i)
			printf("%s ", fec_mode_name[i].name);
	}
	printf("\n");
}

Hope for your reply.

>> +};
>> +
>> +/* This indicates FEC capabilities */
>> +#define RTE_ETH_FEC_CAPA_NOFEC  (1U << RTE_ETH_FEC_NOFEC)
>> +#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_FEC_CAPA_AUTO   (1U << RTE_ETH_FEC_AUTO)
>> +
>> +
>>   #define RTE_ETH_ALL RTE_MAX_ETHPORTS
>>
>>   /* Macros to check for valid port */
>> @@ -3328,6 +3347,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_BASER
>> + *   RTE_ETH_FEC_CAPA_RS
>> + *   RTE_ETH_FEC_CAPA_AUTO
>> + * @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_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_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..cd1acf1 100644
>> --- a/lib/librte_ethdev/rte_ethdev_core.h
>> +++ b/lib/librte_ethdev/rte_ethdev_core.h
>> @@ -604,6 +604,76 @@ 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_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_fec_mode mode);
>> +
>> +/**
>>    * @internal A structure containing the functions exported by an Ethernet driver.
>>    */
>>   struct eth_dev_ops {
>> @@ -752,6 +822,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 {
>> --
>> 2.7.4
> 
> .
> 

^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V6 0/3] add FEC support
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
                     ` (5 preceding siblings ...)
  2020-09-17  8:52   ` [dpdk-dev] [V5 0/3] add FEC support Min Hu (Connor)
@ 2020-09-18  9:04   ` Min Hu (Connor)
  2020-09-18  9:04     ` [dpdk-dev] [PATCH V6 1/3] ethdev: introduce FEC API Min Hu (Connor)
                       ` (2 more replies)
  2020-09-18 11:48   ` [dpdk-dev] [PATCH V7 0/3] add FEC support Min Hu (Connor)
                     ` (9 subsequent siblings)
  16 siblings, 3 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-18  9:04 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This series add FEC support for ethdev.

Min Hu (Connor) (3):
  ethdev: introduce FEC API
  net/hns3: support FEC
  app/testpmd: add FEC command

 app/test-pmd/cmdline.c                   | 219 +++++++++++++++++++++++++++++++
 app/test-pmd/config.c                    |  54 ++++++++
 app/test-pmd/testpmd.h                   |   2 +
 doc/guides/rel_notes/release_20_11.rst   |  10 ++
 drivers/net/hns3/hns3_cmd.h              |  19 ++-
 drivers/net/hns3/hns3_ethdev.c           | 157 ++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h           |   1 +
 lib/librte_ethdev/rte_ethdev.c           |  49 +++++++
 lib/librte_ethdev/rte_ethdev.h           |  83 ++++++++++++
 lib/librte_ethdev/rte_ethdev_core.h      |  78 +++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |   5 +
 11 files changed, 676 insertions(+), 1 deletion(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V6 1/3] ethdev: introduce FEC API
  2020-09-18  9:04   ` [dpdk-dev] [PATCH V6 0/3] add FEC support Min Hu (Connor)
@ 2020-09-18  9:04     ` Min Hu (Connor)
  2020-09-18  9:04     ` [dpdk-dev] [PATCH V6 2/3] net/hns3: support FEC Min Hu (Connor)
  2020-09-18  9:04     ` [dpdk-dev] [PATCH V6 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-18  9:04 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

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>
---
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           | 83 ++++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_core.h      | 78 ++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |  5 ++
 5 files changed, 225 insertions(+)

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..b15ed33 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 & (1U << (uint32_t)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..cc22cf7 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1511,6 +1511,25 @@ 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_BASER,          /**< FEC using common algorithm */
+	RTE_ETH_FEC_RS,             /**< FEC using RS algorithm */
+	RTE_ETH_FEC_AUTO,           /**< FEC autonegotiation modes */
+	RTE_ETH_FEC_NUM
+};
+
+/* This indicates FEC capabilities */
+#define RTE_ETH_FEC_CAPA_NOFEC  (1U << RTE_ETH_FEC_NOFEC)
+#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_FEC_CAPA_AUTO   (1U << RTE_ETH_FEC_AUTO)
+
+
 #define RTE_ETH_ALL RTE_MAX_ETHPORTS
 
 /* Macros to check for valid port */
@@ -3328,6 +3347,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_BASER
+ *   RTE_ETH_FEC_CAPA_RS
+ *   RTE_ETH_FEC_CAPA_AUTO
+ * @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..885632f 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 +823,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 {
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V6 2/3] net/hns3: support FEC
  2020-09-18  9:04   ` [dpdk-dev] [PATCH V6 0/3] add FEC support Min Hu (Connor)
  2020-09-18  9:04     ` [dpdk-dev] [PATCH V6 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-18  9:04     ` Min Hu (Connor)
  2020-09-18  9:04     ` [dpdk-dev] [PATCH V6 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-18  9:04 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

Forward error correction (FEC) is a bit error correction mode.
It adds error correction information to data packets at the
transmit end, and uses the error correction information to correct
the bit errors generated during data packet transmission at the
receive end. This improves signal quality but also brings a delay
to signals. This function can be enabled or disabled as required.

This patch adds FEC support for ethdev.Introduce ethdev
operations 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>
---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Data type for fec_cap is changed from uint8_t
to uint32_t for possible future expansion.

---
v2->v3:
adjust the return value of function.

---
 drivers/net/hns3/hns3_cmd.h    |  19 ++++-
 drivers/net/hns3/hns3_ethdev.c | 157 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h |   1 +
 3 files changed, 176 insertions(+), 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index d70f42e..8b80353 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -99,6 +99,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_CONFIG_MAX_FRM_SIZE    = 0x0308,
 	HNS3_OPC_CONFIG_SPEED_DUP       = 0x0309,
 	HNS3_MAC_COMMON_INT_EN          = 0x030E,
+	HNS3_OPC_CONFIG_FEC_MODE        = 0x031A,
 
 	/* PFC/Pause commands */
 	HNS3_OPC_CFG_MAC_PAUSE_EN       = 0x0701,
@@ -653,9 +654,25 @@ struct hns3_config_auto_neg_cmd {
 	uint8_t   rsv[20];
 };
 
+#define HNS3_MAC_CFG_FEC_AUTO_EN_B	0
+#define HNS3_MAC_CFG_FEC_MODE_S		1
+#define HNS3_MAC_CFG_FEC_MODE_M	GENMASK(3, 1)
+#define HNS3_MAC_FEC_OFF		0
+#define HNS3_MAC_FEC_BASER		1
+#define HNS3_MAC_FEC_RS			2
+
 struct hns3_sfp_speed_cmd {
 	uint32_t  sfp_speed;
-	uint32_t  rsv[5];
+	uint8_t   query_type; /* 0: sfp speed, 1: active fec */
+	uint8_t   active_fec; /* current FEC mode */
+	uint16_t  rsv1;
+	uint32_t  rsv2[4];
+};
+
+/* Configure FEC mode, opcode:0x031A */
+struct hns3_config_fec_cmd {
+	uint8_t fec_mode;
+	uint8_t rsv[23];
 };
 
 #define HNS3_MAC_MGR_MASK_VLAN_B		BIT(0)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 81e7730..e39a3b9 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -78,6 +78,8 @@ static int hns3_add_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
 static int hns3_remove_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
+static int hns3_restore_fec(struct hns3_hw *hw);
+static int hns3_query_dev_fec_info(struct rte_eth_dev *dev);
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -2819,6 +2821,13 @@ hns3_get_capability(struct hns3_hw *hw)
 	    device_id == HNS3_DEV_ID_200G_RDMA)
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_DCB_B, 1);
 
+	ret = hns3_query_dev_fec_info(eth_dev);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			     "failed to query FEC information, ret = %d", ret);
+		return ret;
+	}
+
 	/* Get PCI revision id */
 	ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN,
 				  HNS3_PCI_REVISION_ID);
@@ -5311,6 +5320,10 @@ hns3_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_promisc;
 
+	ret = hns3_restore_fec(hw);
+	if (ret)
+		goto err_promisc;
+
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED) {
 		ret = hns3_do_start(hns, false);
 		if (ret)
@@ -5389,6 +5402,147 @@ hns3_reset_service(void *param)
 		hns3_msix_process(hns, reset_level);
 }
 
+static int
+hns3_fec_get_capability(struct rte_eth_dev *dev, uint32_t *fec_cap)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_mac *mac = &hw->mac;
+	uint32_t mode;
+
+	switch (mac->link_speed) {
+	case ETH_SPEED_NUM_10G:
+	case ETH_SPEED_NUM_40G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
+			RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	case ETH_SPEED_NUM_25G:
+	case ETH_SPEED_NUM_50G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
+			RTE_ETH_FEC_CAPA_RS | RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	case ETH_SPEED_NUM_100G:
+	case ETH_SPEED_NUM_200G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_RS |
+			RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	default:
+		mode = 0;
+		break;
+	}
+
+	*fec_cap = mode;
+	return 0;
+}
+
+static int
+hns3_fec_get(struct rte_eth_dev *dev, enum rte_eth_fec_mode *mode)
+{
+#define QUERY_ACTIVE_SPEED	1
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_sfp_speed_cmd *resp;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_SFP_GET_SPEED, true);
+	resp = (struct hns3_sfp_speed_cmd *)desc.data;
+	resp->query_type = QUERY_ACTIVE_SPEED;
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret == -EOPNOTSUPP) {
+		hns3_err(hw, "IMP do not support get FEC, ret = %d", ret);
+		return ret;
+	} else if (ret) {
+		hns3_err(hw, "get FEC failed, ret = %d", ret);
+		return ret;
+	}
+
+	*mode = resp->active_fec;
+	return 0;
+}
+
+static int
+hns3_set_fec_hw(struct hns3_hw *hw, enum rte_eth_fec_mode mode)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, false);
+
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	switch (mode) {
+	case RTE_ETH_FEC_NOFEC:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_OFF);
+		break;
+	case RTE_ETH_FEC_BASER:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_BASER);
+		break;
+	case RTE_ETH_FEC_RS:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_RS);
+		break;
+	case RTE_ETH_FEC_AUTO:
+		hns3_set_bit(req->fec_mode, HNS3_MAC_CFG_FEC_AUTO_EN_B, 1);
+		break;
+	default:
+		return 0;
+	}
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw, "set fec mode failed, ret = %d", ret);
+
+	return ret;
+}
+
+static int
+hns3_fec_set(struct rte_eth_dev *dev, enum rte_eth_fec_mode mode)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		return ret;
+
+	pf->fec_mode = mode;
+	return 0;
+}
+
+static int
+hns3_restore_fec(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+	enum rte_eth_fec_mode mode = pf->fec_mode;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		hns3_err(hw, "restore fec mode(%d) failed, ret = %d",
+			 mode, ret);
+
+	return ret;
+}
+
+static int
+hns3_query_dev_fec_info(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_fec_get(dev, &pf->fec_mode);
+	if (ret)
+		hns3_err(hw, "query device FEC info failed, ret = %d", ret);
+
+	return ret;
+}
+
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_start          = hns3_dev_start,
 	.dev_stop           = hns3_dev_stop,
@@ -5434,6 +5588,9 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.get_reg                = hns3_get_regs,
 	.get_dcb_info           = hns3_get_dcb_info,
 	.dev_supported_ptypes_get = hns3_dev_supported_ptypes_get,
+	.fec_get_capability     = hns3_fec_get_capability,
+	.fec_get                = hns3_fec_get,
+	.fec_set                = hns3_fec_set,
 };
 
 static const struct hns3_reset_ops hns3_reset_ops = {
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 0e665e5..2435668 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -510,6 +510,7 @@ struct hns3_pf {
 	struct hns3_err_msix_intr_stats abn_int_stats;
 
 	bool support_sfp_query;
+	enum rte_eth_fec_mode fec_mode; /* current FEC mode for ethdev */
 
 	struct hns3_vtag_cfg vtag_config;
 	LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V6 3/3] app/testpmd: add FEC command
  2020-09-18  9:04   ` [dpdk-dev] [PATCH V6 0/3] add FEC support Min Hu (Connor)
  2020-09-18  9:04     ` [dpdk-dev] [PATCH V6 1/3] ethdev: introduce FEC API Min Hu (Connor)
  2020-09-18  9:04     ` [dpdk-dev] [PATCH V6 2/3] net/hns3: support FEC Min Hu (Connor)
@ 2020-09-18  9:04     ` Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-18  9:04 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This commit adds testpmd capability to query and config FEC
function of device. This includes:
- show FEC capabilities, example:
	testpmd> show port 0 fec capabilities
- show FEC mode, example:
	testpmd> show port 0 fec_mode
- config FEC mode, example:
	testpmd> set port <port_id> 0 <auto|off|rs|baser>

	where:

	auto|off|rs|baser are four kinds of FEC mode which dev
	support according to MAC link speed.

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>
---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Add RTE_ prefix for public FEC mode enum.

---
v3->v4:
adjust the display format of FEC mode

---
v2->v3:
adjust the display format of FEC capability.

---
 app/test-pmd/cmdline.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c  |  54 ++++++++++++
 app/test-pmd/testpmd.h |   2 +
 3 files changed, 275 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0a6ed85..96da9aa 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -19054,6 +19054,222 @@ cmdline_parse_inst_t cmd_show_tx_metadata = {
 	},
 };
 
+/* *** show fec capability per port configuration *** */
+struct cmd_show_fec_capability_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_fec;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_capability_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+	struct cmd_show_fec_capability_result *res = parsed_result;
+	uint32_t fec_cap;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_fec_get_capability(res->cmd_pid, &fec_cap);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC capability failed\n");
+		return;
+	}
+
+	show_fec_capability(fec_cap);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_capability_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_capability_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_capability_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_capability_fec =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_fec, "fec");
+cmdline_parse_token_string_t cmd_show_fec_capability_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_keyword, "capabilities");
+
+cmdline_parse_inst_t cmd_show_capability = {
+	.f = cmd_show_fec_capability_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec capabilities",
+	.tokens = {
+		(void *)&cmd_show_fec_capability_show,
+		(void *)&cmd_show_fec_capability_port,
+		(void *)&cmd_show_fec_capability_pid,
+		(void *)&cmd_show_fec_capability_fec,
+		(void *)&cmd_show_fec_capability_keyword,
+		NULL,
+	},
+};
+
+/* *** show fec mode per port configuration *** */
+struct cmd_show_fec_metadata_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_mode_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_NAME_SIZE 16
+	struct cmd_show_fec_metadata_result *res = parsed_result;
+	enum rte_eth_fec_mode mode;
+	char buf[FEC_NAME_SIZE];
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+	ret = rte_eth_fec_get(res->cmd_pid, &mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC mode failed\n");
+		return;
+	}
+
+	switch (mode) {
+	case RTE_ETH_FEC_NOFEC:
+		strlcpy(buf, "off", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_BASER:
+		strlcpy(buf, "baser", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_RS:
+		strlcpy(buf, "rs", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_AUTO:
+		strlcpy(buf, "auto", sizeof(buf));
+		break;
+	default:
+		return;
+	}
+
+	printf("%s\n", buf);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_mode_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_mode_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_mode_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_mode_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_keyword, "fec_mode");
+
+cmdline_parse_inst_t cmd_show_fec_mode = {
+	.f = cmd_show_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec_mode",
+	.tokens = {
+		(void *)&cmd_show_fec_mode_show,
+		(void *)&cmd_show_fec_mode_port,
+		(void *)&cmd_show_fec_mode_pid,
+		(void *)&cmd_show_fec_mode_keyword,
+		NULL,
+	},
+};
+
+/* *** set fec mode per port configuration *** */
+struct cmd_set_port_fec_mode {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t fec_mode;
+	cmdline_fixed_string_t fec_value;
+};
+
+/* Common CLI fields for set fec mode */
+cmdline_parse_token_string_t cmd_set_port_fec_mode_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port, "port");
+cmdline_parse_token_num_t cmd_set_port_fec_mode_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_port_fec_mode_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_mode, "fec_mode");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_value =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_value, NULL);
+
+static void
+cmd_set_port_fec_mode_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	__rte_unused void *data)
+{
+	struct cmd_set_port_fec_mode *res = parsed_result;
+	uint16_t port_id = res->port_id;
+	enum rte_eth_fec_mode mode;
+	int ret;
+
+	ret = parse_fec_mode(res->fec_value, &mode);
+	if (ret < 0) {
+		printf("Unknown fec mode: %s for Port %d\n", res->fec_value,
+			port_id);
+		return;
+	}
+
+	ret = rte_eth_fec_set(port_id, mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Set FEC mode failed\n");
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_fec_mode = {
+	.f = cmd_set_port_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> fec_mode <auto|off|rs|baser>",
+	.tokens = {
+		(void *)&cmd_set_port_fec_mode_set,
+		(void *)&cmd_set_port_fec_mode_port,
+		(void *)&cmd_set_port_fec_mode_port_id,
+		(void *)&cmd_set_port_fec_mode_str,
+		(void *)&cmd_set_port_fec_mode_value,
+		NULL,
+	},
+};
+
 /* show port supported ptypes */
 
 /* Common result structure for show port ptypes */
@@ -19685,6 +19901,9 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_set_raw,
 	(cmdline_parse_inst_t *)&cmd_show_set_raw_all,
 	(cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
+	(cmdline_parse_inst_t *)&cmd_show_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_set_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_show_capability,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 30bee33..db973db 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -138,6 +138,28 @@ const struct rss_type_info rss_type_table[] = {
 	{ NULL, 0 },
 };
 
+static const struct {
+	enum rte_eth_fec_mode mode;
+	const char *name;
+} fec_mode_name[] = {
+	{
+		.mode = RTE_ETH_FEC_NOFEC,
+		.name = "off",
+	},
+	{
+		.mode = RTE_ETH_FEC_BASER,
+		.name = "baser",
+	},
+	{
+		.mode = RTE_ETH_FEC_RS,
+		.name = "rs",
+	},
+	{
+		.mode = RTE_ETH_FEC_AUTO,
+		.name = "auto",
+	},
+};
+
 static void
 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
 {
@@ -2967,6 +2989,38 @@ set_tx_pkt_split(const char *name)
 	printf("unknown value: \"%s\"\n", name);
 }
 
+int
+parse_fec_mode(const char *name, enum rte_eth_fec_mode *mode)
+{
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(fec_mode_name); i++) {
+		if (strcmp(fec_mode_name[i].name, name) == 0) {
+			*mode = fec_mode_name[i].mode;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void
+show_fec_capability(uint32_t fec_cap)
+{
+	uint32_t i;
+
+	if (fec_cap == 0) {
+		printf("FEC is not supported\n");
+		return;
+	}
+
+	printf("FEC capabilities: ");
+	for (i = RTE_ETH_FEC_BASER; i < RTE_ETH_FEC_NUM; i++) {
+		if (fec_cap & 1U << i)
+			printf("%s ", fec_mode_name[i].name);
+	}
+	printf("\n");
+}
+
 void
 show_tx_pkt_segments(void)
 {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 25a12b1..3be56e8 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -778,6 +778,8 @@ void show_tx_pkt_segments(void);
 void set_tx_pkt_times(unsigned int *tx_times);
 void show_tx_pkt_times(void);
 void set_tx_pkt_split(const char *name);
+int parse_fec_mode(const char *name, enum rte_eth_fec_mode *mode);
+void show_fec_capability(uint32_t fec_cap);
 void set_nb_pkt_per_burst(uint16_t pkt_burst);
 char *list_pkt_forwarding_modes(void);
 char *list_pkt_forwarding_retry_modes(void);
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [V5 1/3] ethdev: introduce FEC API
  2020-09-17  9:58       ` Andrew Rybchenko
@ 2020-09-18  9:28         ` Min Hu (Connor)
  2020-09-19  8:42           ` Andrew Rybchenko
  0 siblings, 1 reply; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-18  9:28 UTC (permalink / raw)
  To: Andrew Rybchenko, dev; +Cc: konstantin.ananyev, thomas, ferruh.yigit, linuxarm



在 2020/9/17 17:58, Andrew Rybchenko 写道:
> On 9/17/20 11:52 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>
>> ---
>> 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   | 13 +++++
>>   lib/librte_ethdev/rte_ethdev.c           | 50 +++++++++++++++++++
>>   lib/librte_ethdev/rte_ethdev.h           | 83 ++++++++++++++++++++++++++++++++
>>   lib/librte_ethdev/rte_ethdev_core.h      | 77 +++++++++++++++++++++++++++++
>>   lib/librte_ethdev/rte_ethdev_version.map |  5 ++
>>   5 files changed, 228 insertions(+)
>>
>> diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
>> index cc72609..e4f0587 100644
>> --- a/doc/guides/rel_notes/release_20_11.rst
>> +++ b/doc/guides/rel_notes/release_20_11.rst
>> @@ -55,6 +55,19 @@ New Features
>>        Also, make sure to start the actual text at the margin.
>>        =======================================================
>>   
>> +* **Added the FEC Library, a generic FEC query and config library.**
>> +
>> +  Added the FEC library which provides an API for query FEC capabilities and
>> +  FEC mode from device. Also, API for configuring FEC mode is also provided.
> 
> The patch does not add a library. It adds an API get FEC
> capabilities, get current configuration and allows to set
> a new configuration.
I fixed it in V6,thanks.

> 
>> +
>> +  Added hns3 FEC PMD, for supporting query and config FEC mode.
> 
> If required, it should be later in release notes in accordance
> with defined order.
> 
I fixed it in V6,thanks.

>> +
>> +* **Updated testpmd with a command for FEC.**
>> +
>> +  Added a FEC command to testpmd app,
>> +  ``show port <port_id> fec capabilities`` which queries FEC capabilities device supports.
>> +  ``show port <port_id> fec_mode`` which queries FEC mode from device.
>> +  ``set port <port_id> fec_mode <auto|off|rs|baser>`` which configures FEC mode to device.
> 
> IMHO, it is not much details for release notes.
> As I understand it is assumed that testpmd must be
> updated for any new ethdev feature, so, the information
> about testpmd is not really required.
> 
I fixed it in V6,thanks.
>>   
>>   Removed Items
>>   -------------
>> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
>> index 7858ad5..fde77c1 100644
>> --- a/lib/librte_ethdev/rte_ethdev.c
>> +++ b/lib/librte_ethdev/rte_ethdev.c
>> @@ -3642,6 +3642,56 @@ 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_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_fec_mode mode)
>> +{
>> +	struct rte_eth_dev *dev;
>> +	uint32_t fec_mode_mask;
>> +	int ret;
>> +
>> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> 
> Basically the check is duplicated since get_capabilities
> does it. However, there is no much harm to keep. If so,
> I'd move it below just before port_id usage as an index
> in rte_eth_devices array.
> 
I fixed it in V6,just delete the duplicated check, thanks.
>> +
>> +	ret = rte_eth_fec_get_capability(port_id, &fec_mode_mask);
>> +	if (ret)
> 
> Please, compare with 0 explicitly as specified in DPDK coding
> style.
> 
I fixed it in V6,thanks.

>> +		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 & (1U << (uint32_t)mode))) {
>> +		RTE_ETHDEV_LOG(ERR, "unsupported fec mode=%d\n", mode);
> 
> I'd use "FEC" (in capitals) in log message as well.
> Also I think it would be useful to log port_id.
I fixed it in V6,thanks.

> .
>> +		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..aa79326 100644
>> --- a/lib/librte_ethdev/rte_ethdev.h
>> +++ b/lib/librte_ethdev/rte_ethdev.h
>> @@ -1511,6 +1511,25 @@ 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_fec_mode {
> 
> enum rte_eth_fec_mode
> to be consistent with other enums and to have library prefix.
> 
I fixed it in V6,thanks.
>> +	RTE_ETH_FEC_NOFEC = 0,      /**< FEC is off */
>> +	RTE_ETH_FEC_BASER,          /**< FEC using common algorithm */
>> +	RTE_ETH_FEC_RS,             /**< FEC using RS algorithm */
>> +	RTE_ETH_FEC_AUTO,           /**< FEC autonegotiation modes */
> 
> May I suggest to put AUTO just after NOFEC. It would look move
> logical in the future when more FEC modes are added. It would
> look strange with AUTO in the middle of the list.
> 
  hns3 PMD is the first to implement FEC function. The FEC mode order
  is in accordance with the bit definition in hardware FEC module.
  in other ways, AUTO is flexible mode, which should not be differently 
    treated,the location in last item of enum is ok.

>> +	RTE_ETH_FEC_NUM
> 
> I'm not about about current policy for such items. Is it really
> required? Addition of more FEC modes will be ABI breakage.

  it does not matter even though RTE_ETH_FEC_NUM value is changed when 
adding new element to that enum.
  RTE_ETH_FEC_NUM is used as the MAX vlaue of FEC modes, not one FEC 
mode itself.
  One of the application scenarios is as follows,set "testpmd" as an 
example:
show_fec_capability(uint32_t fec_cap)
{
     uint32_t i;

     if (fec_cap == 0) {
         printf("FEC is not supported\n");
         return;
     }

     printf("FEC capabilities: ");
     for (i = RTE_ETH_FEC_BASER; i < RTE_ETH_FEC_NUM; i++) {
         if (fec_cap & 1U << i)
             printf("%s ", fec_mode_name[i].name);
     }
     printf("\n");
}
>> +};
>> +
>> +/* This indicates FEC capabilities */
>> +#define RTE_ETH_FEC_CAPA_NOFEC  (1U << RTE_ETH_FEC_NOFEC)
>> +#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_FEC_CAPA_AUTO   (1U << RTE_ETH_FEC_AUTO)
>> +
>> +
>>   #define RTE_ETH_ALL RTE_MAX_ETHPORTS
>>   
>>   /* Macros to check for valid port */
>> @@ -3328,6 +3347,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_BASER
>> + *   RTE_ETH_FEC_CAPA_RS
>> + *   RTE_ETH_FEC_CAPA_AUTO
> 
> I'd like to see thoughts about different FEC modes for
> different link speed. How to report it?
> (sorry if I missed it before)
the relation between FEC mode and link speed, we can refer to
hns3 PMD code, as follows:

	switch (mac->link_speed) {
	case ETH_SPEED_NUM_10G:
	case ETH_SPEED_NUM_40G:
		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
			RTE_ETH_FEC_CAPA_AUTO;
		break;
	case ETH_SPEED_NUM_25G:
	case ETH_SPEED_NUM_50G:
		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
			RTE_ETH_FEC_CAPA_RS | RTE_ETH_FEC_CAPA_AUTO;
		break;
	case ETH_SPEED_NUM_100G:
	case ETH_SPEED_NUM_200G:
		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_RS |
			RTE_ETH_FEC_CAPA_AUTO;
		break;
	default:
		mode = 0;
		break;
	}

> 
>> + * @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);
> 
> [snip]
> .
> 

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [V5 1/3] ethdev: introduce FEC API
  2020-09-18  1:57         ` humin (Connor)
@ 2020-09-18 10:46           ` Ananyev, Konstantin
  0 siblings, 0 replies; 118+ messages in thread
From: Ananyev, Konstantin @ 2020-09-18 10:46 UTC (permalink / raw)
  To: humin (Connor), dev; +Cc: thomas, arybchenko, Yigit, Ferruh, linuxarm

> >>
> >> +/**
> >> + * This enum indicates the possible (forward error correction)FEC modes
> >> + * of an ethdev port.
> >> + */
> >> +enum rte_fec_mode {
> >> +	RTE_ETH_FEC_NOFEC = 0,      /**< FEC is off */
> >> +	RTE_ETH_FEC_BASER,          /**< FEC using common algorithm */
> >> +	RTE_ETH_FEC_RS,             /**< FEC using RS algorithm */
> >> +	RTE_ETH_FEC_AUTO,           /**< FEC autonegotiation modes */
> >> +	RTE_ETH_FEC_NUM
> >
> > It is better not to have RTE_ETH_FEC_NUM here:
> > Any future additions to that enum would overwrite _NUM values and would
> > considered as ABI breakage.
> > Aprart from that:
> > Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> >
> HI,
>        it does not matter even though RTE_ETH_FEC_NUM value is changed
> when adding new element to that enum. RTE_ETH_FEC_NUM is used as the MAX
> vlaue of FEC modes, not one FEC mode itself.

I understand that, but when in future you'll try to add some new mode,
it will cause a change of RTE_ETH_FEC_NUM value.
As I remember, abicheck will report it as ABI breakage.
So adding new values to that enum will be really problematic.

>        One of the application scenarios is as follows,set "testpmd" as
> an example:
> show_fec_capability(uint32_t fec_cap)
> {
> 	uint32_t i;
> 
> 	if (fec_cap == 0) {
> 		printf("FEC is not supported\n");
> 		return;
> 	}
> 
> 	printf("FEC capabilities: ");
> 	for (i = RTE_ETH_FEC_BASER; i < RTE_ETH_FEC_NUM; i++) {

I think you can use RTE_DIM(fec_mode_name) here instead of RTE_ETH_FEC_NUM.

> 		if (fec_cap & 1U << i)

BTW, one more thing - as you translate from mode to capa all over the place,
I think it deserves a separate macro for it.
Something like:
#define RTE_ETH_FEC_MODE_TO_CAPA(x)	(1U << (x))

> 			printf("%s ", fec_mode_name[i].name);
> 	}
> 	printf("\n");
> }
> 
> Hope for your reply.
> 
> >> +};
> >> +
> >> +/* This indicates FEC capabilities */
> >> +#define RTE_ETH_FEC_CAPA_NOFEC  (1U << RTE_ETH_FEC_NOFEC)
> >> +#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_FEC_CAPA_AUTO   (1U << RTE_ETH_FEC_AUTO)
> >> +
> >> +

^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V7 0/3] add FEC support
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
                     ` (6 preceding siblings ...)
  2020-09-18  9:04   ` [dpdk-dev] [PATCH V6 0/3] add FEC support Min Hu (Connor)
@ 2020-09-18 11:48   ` Min Hu (Connor)
  2020-09-18 11:48     ` [dpdk-dev] [PATCH V7 1/3] ethdev: introduce FEC API Min Hu (Connor)
                       ` (2 more replies)
  2020-09-21  2:59   ` [dpdk-dev] [PATCH V8 0/3] add FEC support Min Hu (Connor)
                     ` (8 subsequent siblings)
  16 siblings, 3 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-18 11:48 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This series add FEC support for ethdev.

Min Hu (Connor) (3):
  ethdev: introduce FEC API
  net/hns3: support FEC
  app/testpmd: add FEC command

 app/test-pmd/cmdline.c                   | 219 +++++++++++++++++++++++++++++++
 app/test-pmd/config.c                    |  54 ++++++++
 app/test-pmd/testpmd.h                   |   2 +
 doc/guides/rel_notes/release_20_11.rst   |  10 ++
 drivers/net/hns3/hns3_cmd.h              |  19 ++-
 drivers/net/hns3/hns3_ethdev.c           | 157 ++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h           |   1 +
 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 +
 11 files changed, 679 insertions(+), 1 deletion(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V7 1/3] ethdev: introduce FEC API
  2020-09-18 11:48   ` [dpdk-dev] [PATCH V7 0/3] add FEC support Min Hu (Connor)
@ 2020-09-18 11:48     ` Min Hu (Connor)
  2020-09-18 12:13       ` Ananyev, Konstantin
  2020-09-18 11:48     ` [dpdk-dev] [PATCH V7 2/3] net/hns3: support FEC Min Hu (Connor)
  2020-09-18 11:48     ` [dpdk-dev] [PATCH V7 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 1 reply; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-18 11:48 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

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>
---
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(+)

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..1835fb9 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_BASER,          /**< FEC using common algorithm */
+	RTE_ETH_FEC_RS,             /**< FEC using RS algorithm */
+	RTE_ETH_FEC_AUTO,           /**< FEC autonegotiation modes */
+};
+
+/* This indicates FEC capabilities */
+#define RTE_ETH_FEC_CAPA_NOFEC  (1U << RTE_ETH_FEC_NOFEC)
+#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_FEC_CAPA_AUTO   (1U << RTE_ETH_FEC_AUTO)
+
+
 #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_BASER
+ *   RTE_ETH_FEC_CAPA_RS
+ *   RTE_ETH_FEC_CAPA_AUTO
+ * @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 {
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V7 2/3] net/hns3: support FEC
  2020-09-18 11:48   ` [dpdk-dev] [PATCH V7 0/3] add FEC support Min Hu (Connor)
  2020-09-18 11:48     ` [dpdk-dev] [PATCH V7 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-18 11:48     ` Min Hu (Connor)
  2020-09-18 11:48     ` [dpdk-dev] [PATCH V7 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-18 11:48 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

Forward error correction (FEC) is a bit error correction mode.
It adds error correction information to data packets at the
transmit end, and uses the error correction information to correct
the bit errors generated during data packet transmission at the
receive end. This improves signal quality but also brings a delay
to signals. This function can be enabled or disabled as required.

This patch adds FEC support for ethdev.Introduce ethdev
operations 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>
---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Data type for fec_cap is changed from uint8_t
to uint32_t for possible future expansion.

---
v2->v3:
adjust the return value of function.

---
 drivers/net/hns3/hns3_cmd.h    |  19 ++++-
 drivers/net/hns3/hns3_ethdev.c | 157 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h |   1 +
 3 files changed, 176 insertions(+), 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index d70f42e..8b80353 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -99,6 +99,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_CONFIG_MAX_FRM_SIZE    = 0x0308,
 	HNS3_OPC_CONFIG_SPEED_DUP       = 0x0309,
 	HNS3_MAC_COMMON_INT_EN          = 0x030E,
+	HNS3_OPC_CONFIG_FEC_MODE        = 0x031A,
 
 	/* PFC/Pause commands */
 	HNS3_OPC_CFG_MAC_PAUSE_EN       = 0x0701,
@@ -653,9 +654,25 @@ struct hns3_config_auto_neg_cmd {
 	uint8_t   rsv[20];
 };
 
+#define HNS3_MAC_CFG_FEC_AUTO_EN_B	0
+#define HNS3_MAC_CFG_FEC_MODE_S		1
+#define HNS3_MAC_CFG_FEC_MODE_M	GENMASK(3, 1)
+#define HNS3_MAC_FEC_OFF		0
+#define HNS3_MAC_FEC_BASER		1
+#define HNS3_MAC_FEC_RS			2
+
 struct hns3_sfp_speed_cmd {
 	uint32_t  sfp_speed;
-	uint32_t  rsv[5];
+	uint8_t   query_type; /* 0: sfp speed, 1: active fec */
+	uint8_t   active_fec; /* current FEC mode */
+	uint16_t  rsv1;
+	uint32_t  rsv2[4];
+};
+
+/* Configure FEC mode, opcode:0x031A */
+struct hns3_config_fec_cmd {
+	uint8_t fec_mode;
+	uint8_t rsv[23];
 };
 
 #define HNS3_MAC_MGR_MASK_VLAN_B		BIT(0)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 81e7730..e39a3b9 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -78,6 +78,8 @@ static int hns3_add_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
 static int hns3_remove_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
+static int hns3_restore_fec(struct hns3_hw *hw);
+static int hns3_query_dev_fec_info(struct rte_eth_dev *dev);
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -2819,6 +2821,13 @@ hns3_get_capability(struct hns3_hw *hw)
 	    device_id == HNS3_DEV_ID_200G_RDMA)
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_DCB_B, 1);
 
+	ret = hns3_query_dev_fec_info(eth_dev);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			     "failed to query FEC information, ret = %d", ret);
+		return ret;
+	}
+
 	/* Get PCI revision id */
 	ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN,
 				  HNS3_PCI_REVISION_ID);
@@ -5311,6 +5320,10 @@ hns3_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_promisc;
 
+	ret = hns3_restore_fec(hw);
+	if (ret)
+		goto err_promisc;
+
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED) {
 		ret = hns3_do_start(hns, false);
 		if (ret)
@@ -5389,6 +5402,147 @@ hns3_reset_service(void *param)
 		hns3_msix_process(hns, reset_level);
 }
 
+static int
+hns3_fec_get_capability(struct rte_eth_dev *dev, uint32_t *fec_cap)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_mac *mac = &hw->mac;
+	uint32_t mode;
+
+	switch (mac->link_speed) {
+	case ETH_SPEED_NUM_10G:
+	case ETH_SPEED_NUM_40G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
+			RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	case ETH_SPEED_NUM_25G:
+	case ETH_SPEED_NUM_50G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
+			RTE_ETH_FEC_CAPA_RS | RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	case ETH_SPEED_NUM_100G:
+	case ETH_SPEED_NUM_200G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_RS |
+			RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	default:
+		mode = 0;
+		break;
+	}
+
+	*fec_cap = mode;
+	return 0;
+}
+
+static int
+hns3_fec_get(struct rte_eth_dev *dev, enum rte_eth_fec_mode *mode)
+{
+#define QUERY_ACTIVE_SPEED	1
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_sfp_speed_cmd *resp;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_SFP_GET_SPEED, true);
+	resp = (struct hns3_sfp_speed_cmd *)desc.data;
+	resp->query_type = QUERY_ACTIVE_SPEED;
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret == -EOPNOTSUPP) {
+		hns3_err(hw, "IMP do not support get FEC, ret = %d", ret);
+		return ret;
+	} else if (ret) {
+		hns3_err(hw, "get FEC failed, ret = %d", ret);
+		return ret;
+	}
+
+	*mode = resp->active_fec;
+	return 0;
+}
+
+static int
+hns3_set_fec_hw(struct hns3_hw *hw, enum rte_eth_fec_mode mode)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, false);
+
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	switch (mode) {
+	case RTE_ETH_FEC_NOFEC:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_OFF);
+		break;
+	case RTE_ETH_FEC_BASER:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_BASER);
+		break;
+	case RTE_ETH_FEC_RS:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_RS);
+		break;
+	case RTE_ETH_FEC_AUTO:
+		hns3_set_bit(req->fec_mode, HNS3_MAC_CFG_FEC_AUTO_EN_B, 1);
+		break;
+	default:
+		return 0;
+	}
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw, "set fec mode failed, ret = %d", ret);
+
+	return ret;
+}
+
+static int
+hns3_fec_set(struct rte_eth_dev *dev, enum rte_eth_fec_mode mode)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		return ret;
+
+	pf->fec_mode = mode;
+	return 0;
+}
+
+static int
+hns3_restore_fec(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+	enum rte_eth_fec_mode mode = pf->fec_mode;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		hns3_err(hw, "restore fec mode(%d) failed, ret = %d",
+			 mode, ret);
+
+	return ret;
+}
+
+static int
+hns3_query_dev_fec_info(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_fec_get(dev, &pf->fec_mode);
+	if (ret)
+		hns3_err(hw, "query device FEC info failed, ret = %d", ret);
+
+	return ret;
+}
+
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_start          = hns3_dev_start,
 	.dev_stop           = hns3_dev_stop,
@@ -5434,6 +5588,9 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.get_reg                = hns3_get_regs,
 	.get_dcb_info           = hns3_get_dcb_info,
 	.dev_supported_ptypes_get = hns3_dev_supported_ptypes_get,
+	.fec_get_capability     = hns3_fec_get_capability,
+	.fec_get                = hns3_fec_get,
+	.fec_set                = hns3_fec_set,
 };
 
 static const struct hns3_reset_ops hns3_reset_ops = {
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 0e665e5..2435668 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -510,6 +510,7 @@ struct hns3_pf {
 	struct hns3_err_msix_intr_stats abn_int_stats;
 
 	bool support_sfp_query;
+	enum rte_eth_fec_mode fec_mode; /* current FEC mode for ethdev */
 
 	struct hns3_vtag_cfg vtag_config;
 	LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V7 3/3] app/testpmd: add FEC command
  2020-09-18 11:48   ` [dpdk-dev] [PATCH V7 0/3] add FEC support Min Hu (Connor)
  2020-09-18 11:48     ` [dpdk-dev] [PATCH V7 1/3] ethdev: introduce FEC API Min Hu (Connor)
  2020-09-18 11:48     ` [dpdk-dev] [PATCH V7 2/3] net/hns3: support FEC Min Hu (Connor)
@ 2020-09-18 11:48     ` Min Hu (Connor)
  2020-09-18 20:35       ` Ajit Khaparde
  2 siblings, 1 reply; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-18 11:48 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This commit adds testpmd capability to query and config FEC
function of device. This includes:
- show FEC capabilities, example:
	testpmd> show port 0 fec capabilities
- show FEC mode, example:
	testpmd> show port 0 fec_mode
- config FEC mode, example:
	testpmd> set port <port_id> 0 <auto|off|rs|baser>

	where:

	auto|off|rs|baser are four kinds of FEC mode which dev
	support according to MAC link speed.

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>
---
v6->v7:
used RTE_DIM(fec_mode_name) instead of RTE_ETH_FEC_NUM

---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Add RTE_ prefix for public FEC mode enum.

---
v3->v4:
adjust the display format of FEC mode

---
v2->v3:
adjust the display format of FEC capability.

---
 app/test-pmd/cmdline.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c  |  54 ++++++++++++
 app/test-pmd/testpmd.h |   2 +
 3 files changed, 275 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0a6ed85..96da9aa 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -19054,6 +19054,222 @@ cmdline_parse_inst_t cmd_show_tx_metadata = {
 	},
 };
 
+/* *** show fec capability per port configuration *** */
+struct cmd_show_fec_capability_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_fec;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_capability_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+	struct cmd_show_fec_capability_result *res = parsed_result;
+	uint32_t fec_cap;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_fec_get_capability(res->cmd_pid, &fec_cap);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC capability failed\n");
+		return;
+	}
+
+	show_fec_capability(fec_cap);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_capability_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_capability_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_capability_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_capability_fec =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_fec, "fec");
+cmdline_parse_token_string_t cmd_show_fec_capability_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_keyword, "capabilities");
+
+cmdline_parse_inst_t cmd_show_capability = {
+	.f = cmd_show_fec_capability_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec capabilities",
+	.tokens = {
+		(void *)&cmd_show_fec_capability_show,
+		(void *)&cmd_show_fec_capability_port,
+		(void *)&cmd_show_fec_capability_pid,
+		(void *)&cmd_show_fec_capability_fec,
+		(void *)&cmd_show_fec_capability_keyword,
+		NULL,
+	},
+};
+
+/* *** show fec mode per port configuration *** */
+struct cmd_show_fec_metadata_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_mode_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_NAME_SIZE 16
+	struct cmd_show_fec_metadata_result *res = parsed_result;
+	enum rte_eth_fec_mode mode;
+	char buf[FEC_NAME_SIZE];
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+	ret = rte_eth_fec_get(res->cmd_pid, &mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC mode failed\n");
+		return;
+	}
+
+	switch (mode) {
+	case RTE_ETH_FEC_NOFEC:
+		strlcpy(buf, "off", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_BASER:
+		strlcpy(buf, "baser", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_RS:
+		strlcpy(buf, "rs", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_AUTO:
+		strlcpy(buf, "auto", sizeof(buf));
+		break;
+	default:
+		return;
+	}
+
+	printf("%s\n", buf);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_mode_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_mode_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_mode_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_mode_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_keyword, "fec_mode");
+
+cmdline_parse_inst_t cmd_show_fec_mode = {
+	.f = cmd_show_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec_mode",
+	.tokens = {
+		(void *)&cmd_show_fec_mode_show,
+		(void *)&cmd_show_fec_mode_port,
+		(void *)&cmd_show_fec_mode_pid,
+		(void *)&cmd_show_fec_mode_keyword,
+		NULL,
+	},
+};
+
+/* *** set fec mode per port configuration *** */
+struct cmd_set_port_fec_mode {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t fec_mode;
+	cmdline_fixed_string_t fec_value;
+};
+
+/* Common CLI fields for set fec mode */
+cmdline_parse_token_string_t cmd_set_port_fec_mode_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port, "port");
+cmdline_parse_token_num_t cmd_set_port_fec_mode_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_port_fec_mode_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_mode, "fec_mode");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_value =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_value, NULL);
+
+static void
+cmd_set_port_fec_mode_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	__rte_unused void *data)
+{
+	struct cmd_set_port_fec_mode *res = parsed_result;
+	uint16_t port_id = res->port_id;
+	enum rte_eth_fec_mode mode;
+	int ret;
+
+	ret = parse_fec_mode(res->fec_value, &mode);
+	if (ret < 0) {
+		printf("Unknown fec mode: %s for Port %d\n", res->fec_value,
+			port_id);
+		return;
+	}
+
+	ret = rte_eth_fec_set(port_id, mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Set FEC mode failed\n");
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_fec_mode = {
+	.f = cmd_set_port_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> fec_mode <auto|off|rs|baser>",
+	.tokens = {
+		(void *)&cmd_set_port_fec_mode_set,
+		(void *)&cmd_set_port_fec_mode_port,
+		(void *)&cmd_set_port_fec_mode_port_id,
+		(void *)&cmd_set_port_fec_mode_str,
+		(void *)&cmd_set_port_fec_mode_value,
+		NULL,
+	},
+};
+
 /* show port supported ptypes */
 
 /* Common result structure for show port ptypes */
@@ -19685,6 +19901,9 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_set_raw,
 	(cmdline_parse_inst_t *)&cmd_show_set_raw_all,
 	(cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
+	(cmdline_parse_inst_t *)&cmd_show_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_set_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_show_capability,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 30bee33..e35d61a 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -138,6 +138,28 @@ const struct rss_type_info rss_type_table[] = {
 	{ NULL, 0 },
 };
 
+static const struct {
+	enum rte_eth_fec_mode mode;
+	const char *name;
+} fec_mode_name[] = {
+	{
+		.mode = RTE_ETH_FEC_NOFEC,
+		.name = "off",
+	},
+	{
+		.mode = RTE_ETH_FEC_BASER,
+		.name = "baser",
+	},
+	{
+		.mode = RTE_ETH_FEC_RS,
+		.name = "rs",
+	},
+	{
+		.mode = RTE_ETH_FEC_AUTO,
+		.name = "auto",
+	},
+};
+
 static void
 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
 {
@@ -2967,6 +2989,38 @@ set_tx_pkt_split(const char *name)
 	printf("unknown value: \"%s\"\n", name);
 }
 
+int
+parse_fec_mode(const char *name, enum rte_eth_fec_mode *mode)
+{
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(fec_mode_name); i++) {
+		if (strcmp(fec_mode_name[i].name, name) == 0) {
+			*mode = fec_mode_name[i].mode;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void
+show_fec_capability(uint32_t fec_cap)
+{
+	uint32_t i;
+
+	if (fec_cap == 0) {
+		printf("FEC is not supported\n");
+		return;
+	}
+
+	printf("FEC capabilities: ");
+	for (i = RTE_ETH_FEC_BASER; i < RTE_DIM(fec_mode_name); i++) {
+		if (fec_cap & RTE_ETH_FEC_MODE_TO_CAPA(i))
+			printf("%s ", fec_mode_name[i].name);
+	}
+	printf("\n");
+}
+
 void
 show_tx_pkt_segments(void)
 {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 25a12b1..3be56e8 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -778,6 +778,8 @@ void show_tx_pkt_segments(void);
 void set_tx_pkt_times(unsigned int *tx_times);
 void show_tx_pkt_times(void);
 void set_tx_pkt_split(const char *name);
+int parse_fec_mode(const char *name, enum rte_eth_fec_mode *mode);
+void show_fec_capability(uint32_t fec_cap);
 void set_nb_pkt_per_burst(uint16_t pkt_burst);
 char *list_pkt_forwarding_modes(void);
 char *list_pkt_forwarding_retry_modes(void);
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V7 1/3] ethdev: introduce FEC API
  2020-09-18 11:48     ` [dpdk-dev] [PATCH V7 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-18 12:13       ` Ananyev, Konstantin
  2020-09-18 18:10         ` Ajit Khaparde
  0 siblings, 1 reply; 118+ messages in thread
From: Ananyev, Konstantin @ 2020-09-18 12:13 UTC (permalink / raw)
  To: Min Hu (Connor), dev; +Cc: thomas, arybchenko, Yigit, Ferruh, linuxarm


> 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>
> ---
> 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
> 
> ---

Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>

> 2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V7 1/3] ethdev: introduce FEC API
  2020-09-18 12:13       ` Ananyev, Konstantin
@ 2020-09-18 18:10         ` Ajit Khaparde
  2020-09-19  8:44           ` Andrew Rybchenko
  0 siblings, 1 reply; 118+ messages in thread
From: Ajit Khaparde @ 2020-09-18 18:10 UTC (permalink / raw)
  To: Ananyev, Konstantin
  Cc: Min Hu (Connor), dev, thomas, arybchenko, Yigit, Ferruh, linuxarm

On Fri, Sep 18, 2020 at 5:13 AM Ananyev, Konstantin
<konstantin.ananyev@intel.com> 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>
> > ---
> > 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
> >
> > ---
>
> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>

>
> > 2.7.4
>

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V7 3/3] app/testpmd: add FEC command
  2020-09-18 11:48     ` [dpdk-dev] [PATCH V7 3/3] app/testpmd: add FEC command Min Hu (Connor)
@ 2020-09-18 20:35       ` Ajit Khaparde
  0 siblings, 0 replies; 118+ messages in thread
From: Ajit Khaparde @ 2020-09-18 20:35 UTC (permalink / raw)
  To: Min Hu (Connor)
  Cc: dpdk-dev, Ananyev, Konstantin, Thomas Monjalon, Andrew Rybchenko,
	Ferruh Yigit, linuxarm

On Fri, Sep 18, 2020 at 4:51 AM Min Hu (Connor) <humin29@huawei.com> wrote:
>
> This commit adds testpmd capability to query and config FEC
> function of device. This includes:
> - show FEC capabilities, example:
>         testpmd> show port 0 fec capabilities
> - show FEC mode, example:
>         testpmd> show port 0 fec_mode
> - config FEC mode, example:
>         testpmd> set port <port_id> 0 <auto|off|rs|baser>
>
>         where:
>
>         auto|off|rs|baser are four kinds of FEC mode which dev
>         support according to MAC link speed.
>
> 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>

Acked-by: Ajit Khaparde <ajit.khaparde@broadcom.com>

> ---
> v6->v7:
> used RTE_DIM(fec_mode_name) instead of RTE_ETH_FEC_NUM
>
> ---
> v5->v6:
> fixed code styles according to DPDK coding style.
> added _eth prefix.
>
> ---
> v4->v5:
> Add RTE_ prefix for public FEC mode enum.
>
> ---
> v3->v4:
> adjust the display format of FEC mode
>
> ---
> v2->v3:
> adjust the display format of FEC capability.
>
> ---
>  app/test-pmd/cmdline.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++
>  app/test-pmd/config.c  |  54 ++++++++++++
>  app/test-pmd/testpmd.h |   2 +
>  3 files changed, 275 insertions(+)
>
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> index 0a6ed85..96da9aa 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -19054,6 +19054,222 @@ cmdline_parse_inst_t cmd_show_tx_metadata = {
>         },
>  };
>
> +/* *** show fec capability per port configuration *** */
> +struct cmd_show_fec_capability_result {
> +       cmdline_fixed_string_t cmd_show;
> +       cmdline_fixed_string_t cmd_port;
> +       cmdline_fixed_string_t cmd_fec;
> +       cmdline_fixed_string_t cmd_keyword;
> +       portid_t cmd_pid;
> +};
> +
> +static void
> +cmd_show_fec_capability_parsed(void *parsed_result,
> +               __rte_unused struct cmdline *cl,
> +               __rte_unused void *data)
> +{
> +       struct cmd_show_fec_capability_result *res = parsed_result;
> +       uint32_t fec_cap;
> +       int ret;
> +
> +       if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
> +               printf("Invalid port id %u\n", res->cmd_pid);
> +               return;
> +       }
> +
> +       ret = rte_eth_fec_get_capability(res->cmd_pid, &fec_cap);
> +       if (ret == -ENOTSUP) {
> +               printf("Function not implemented\n");
> +               return;
> +       } else if (ret < 0) {
> +               printf("Get FEC capability failed\n");
> +               return;
> +       }
> +
> +       show_fec_capability(fec_cap);
> +}
> +
> +cmdline_parse_token_string_t cmd_show_fec_capability_show =
> +       TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
> +                       cmd_show, "show");
> +cmdline_parse_token_string_t cmd_show_fec_capability_port =
> +       TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
> +                       cmd_port, "port");
> +cmdline_parse_token_num_t cmd_show_fec_capability_pid =
> +       TOKEN_NUM_INITIALIZER(struct cmd_show_fec_capability_result,
> +                       cmd_pid, UINT16);
> +cmdline_parse_token_string_t cmd_show_fec_capability_fec =
> +       TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
> +                       cmd_fec, "fec");
> +cmdline_parse_token_string_t cmd_show_fec_capability_keyword =
> +       TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
> +                       cmd_keyword, "capabilities");
> +
> +cmdline_parse_inst_t cmd_show_capability = {
> +       .f = cmd_show_fec_capability_parsed,
> +       .data = NULL,
> +       .help_str = "show port <port_id> fec capabilities",
> +       .tokens = {
> +               (void *)&cmd_show_fec_capability_show,
> +               (void *)&cmd_show_fec_capability_port,
> +               (void *)&cmd_show_fec_capability_pid,
> +               (void *)&cmd_show_fec_capability_fec,
> +               (void *)&cmd_show_fec_capability_keyword,
> +               NULL,
> +       },
> +};
> +
> +/* *** show fec mode per port configuration *** */
> +struct cmd_show_fec_metadata_result {
> +       cmdline_fixed_string_t cmd_show;
> +       cmdline_fixed_string_t cmd_port;
> +       cmdline_fixed_string_t cmd_keyword;
> +       portid_t cmd_pid;
> +};
> +
> +static void
> +cmd_show_fec_mode_parsed(void *parsed_result,
> +               __rte_unused struct cmdline *cl,
> +               __rte_unused void *data)
> +{
> +#define FEC_NAME_SIZE 16
> +       struct cmd_show_fec_metadata_result *res = parsed_result;
> +       enum rte_eth_fec_mode mode;
> +       char buf[FEC_NAME_SIZE];
> +       int ret;
> +
> +       if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
> +               printf("Invalid port id %u\n", res->cmd_pid);
> +               return;
> +       }
> +       ret = rte_eth_fec_get(res->cmd_pid, &mode);
> +       if (ret == -ENOTSUP) {
> +               printf("Function not implemented\n");
> +               return;
> +       } else if (ret < 0) {
> +               printf("Get FEC mode failed\n");
> +               return;
> +       }
> +
> +       switch (mode) {
> +       case RTE_ETH_FEC_NOFEC:
> +               strlcpy(buf, "off", sizeof(buf));
> +               break;
> +       case RTE_ETH_FEC_BASER:
> +               strlcpy(buf, "baser", sizeof(buf));
> +               break;
> +       case RTE_ETH_FEC_RS:
> +               strlcpy(buf, "rs", sizeof(buf));
> +               break;
> +       case RTE_ETH_FEC_AUTO:
> +               strlcpy(buf, "auto", sizeof(buf));
> +               break;
> +       default:
> +               return;
> +       }
> +
> +       printf("%s\n", buf);
> +}
> +
> +cmdline_parse_token_string_t cmd_show_fec_mode_show =
> +       TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
> +                       cmd_show, "show");
> +cmdline_parse_token_string_t cmd_show_fec_mode_port =
> +       TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
> +                       cmd_port, "port");
> +cmdline_parse_token_num_t cmd_show_fec_mode_pid =
> +       TOKEN_NUM_INITIALIZER(struct cmd_show_fec_metadata_result,
> +                       cmd_pid, UINT16);
> +cmdline_parse_token_string_t cmd_show_fec_mode_keyword =
> +       TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
> +                       cmd_keyword, "fec_mode");
> +
> +cmdline_parse_inst_t cmd_show_fec_mode = {
> +       .f = cmd_show_fec_mode_parsed,
> +       .data = NULL,
> +       .help_str = "show port <port_id> fec_mode",
> +       .tokens = {
> +               (void *)&cmd_show_fec_mode_show,
> +               (void *)&cmd_show_fec_mode_port,
> +               (void *)&cmd_show_fec_mode_pid,
> +               (void *)&cmd_show_fec_mode_keyword,
> +               NULL,
> +       },
> +};
> +
> +/* *** set fec mode per port configuration *** */
> +struct cmd_set_port_fec_mode {
> +       cmdline_fixed_string_t set;
> +       cmdline_fixed_string_t port;
> +       portid_t port_id;
> +       cmdline_fixed_string_t fec_mode;
> +       cmdline_fixed_string_t fec_value;
> +};
> +
> +/* Common CLI fields for set fec mode */
> +cmdline_parse_token_string_t cmd_set_port_fec_mode_set =
> +       TOKEN_STRING_INITIALIZER
> +               (struct cmd_set_port_fec_mode,
> +                set, "set");
> +cmdline_parse_token_string_t cmd_set_port_fec_mode_port =
> +       TOKEN_STRING_INITIALIZER
> +               (struct cmd_set_port_fec_mode,
> +                port, "port");
> +cmdline_parse_token_num_t cmd_set_port_fec_mode_port_id =
> +       TOKEN_NUM_INITIALIZER
> +               (struct cmd_set_port_fec_mode,
> +                port_id, UINT16);
> +cmdline_parse_token_string_t cmd_set_port_fec_mode_str =
> +       TOKEN_STRING_INITIALIZER
> +               (struct cmd_set_port_fec_mode,
> +                fec_mode, "fec_mode");
> +cmdline_parse_token_string_t cmd_set_port_fec_mode_value =
> +       TOKEN_STRING_INITIALIZER
> +               (struct cmd_set_port_fec_mode,
> +                fec_value, NULL);
> +
> +static void
> +cmd_set_port_fec_mode_parsed(
> +       void *parsed_result,
> +       __rte_unused struct cmdline *cl,
> +       __rte_unused void *data)
> +{
> +       struct cmd_set_port_fec_mode *res = parsed_result;
> +       uint16_t port_id = res->port_id;
> +       enum rte_eth_fec_mode mode;
> +       int ret;
> +
> +       ret = parse_fec_mode(res->fec_value, &mode);
> +       if (ret < 0) {
> +               printf("Unknown fec mode: %s for Port %d\n", res->fec_value,
> +                       port_id);
> +               return;
> +       }
> +
> +       ret = rte_eth_fec_set(port_id, mode);
> +       if (ret == -ENOTSUP) {
> +               printf("Function not implemented\n");
> +               return;
> +       } else if (ret < 0) {
> +               printf("Set FEC mode failed\n");
> +               return;
> +       }
> +}
> +
> +cmdline_parse_inst_t cmd_set_fec_mode = {
> +       .f = cmd_set_port_fec_mode_parsed,
> +       .data = NULL,
> +       .help_str = "set port <port_id> fec_mode <auto|off|rs|baser>",
> +       .tokens = {
> +               (void *)&cmd_set_port_fec_mode_set,
> +               (void *)&cmd_set_port_fec_mode_port,
> +               (void *)&cmd_set_port_fec_mode_port_id,
> +               (void *)&cmd_set_port_fec_mode_str,
> +               (void *)&cmd_set_port_fec_mode_value,
> +               NULL,
> +       },
> +};
> +
>  /* show port supported ptypes */
>
>  /* Common result structure for show port ptypes */
> @@ -19685,6 +19901,9 @@ cmdline_parse_ctx_t main_ctx[] = {
>         (cmdline_parse_inst_t *)&cmd_show_set_raw,
>         (cmdline_parse_inst_t *)&cmd_show_set_raw_all,
>         (cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
> +       (cmdline_parse_inst_t *)&cmd_show_fec_mode,
> +       (cmdline_parse_inst_t *)&cmd_set_fec_mode,
> +       (cmdline_parse_inst_t *)&cmd_show_capability,
>         NULL,
>  };
>
> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
> index 30bee33..e35d61a 100644
> --- a/app/test-pmd/config.c
> +++ b/app/test-pmd/config.c
> @@ -138,6 +138,28 @@ const struct rss_type_info rss_type_table[] = {
>         { NULL, 0 },
>  };
>
> +static const struct {
> +       enum rte_eth_fec_mode mode;
> +       const char *name;
> +} fec_mode_name[] = {
> +       {
> +               .mode = RTE_ETH_FEC_NOFEC,
> +               .name = "off",
> +       },
> +       {
> +               .mode = RTE_ETH_FEC_BASER,
> +               .name = "baser",
> +       },
> +       {
> +               .mode = RTE_ETH_FEC_RS,
> +               .name = "rs",
> +       },
> +       {
> +               .mode = RTE_ETH_FEC_AUTO,
> +               .name = "auto",
> +       },
> +};
> +
>  static void
>  print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
>  {
> @@ -2967,6 +2989,38 @@ set_tx_pkt_split(const char *name)
>         printf("unknown value: \"%s\"\n", name);
>  }
>
> +int
> +parse_fec_mode(const char *name, enum rte_eth_fec_mode *mode)
> +{
> +       uint8_t i;
> +
> +       for (i = 0; i < RTE_DIM(fec_mode_name); i++) {
> +               if (strcmp(fec_mode_name[i].name, name) == 0) {
> +                       *mode = fec_mode_name[i].mode;
> +                       return 0;
> +               }
> +       }
> +       return -1;
> +}
> +
> +void
> +show_fec_capability(uint32_t fec_cap)
> +{
> +       uint32_t i;
> +
> +       if (fec_cap == 0) {
> +               printf("FEC is not supported\n");
> +               return;
> +       }
> +
> +       printf("FEC capabilities: ");
> +       for (i = RTE_ETH_FEC_BASER; i < RTE_DIM(fec_mode_name); i++) {
> +               if (fec_cap & RTE_ETH_FEC_MODE_TO_CAPA(i))
> +                       printf("%s ", fec_mode_name[i].name);
> +       }
> +       printf("\n");
> +}
> +
>  void
>  show_tx_pkt_segments(void)
>  {
> diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
> index 25a12b1..3be56e8 100644
> --- a/app/test-pmd/testpmd.h
> +++ b/app/test-pmd/testpmd.h
> @@ -778,6 +778,8 @@ void show_tx_pkt_segments(void);
>  void set_tx_pkt_times(unsigned int *tx_times);
>  void show_tx_pkt_times(void);
>  void set_tx_pkt_split(const char *name);
> +int parse_fec_mode(const char *name, enum rte_eth_fec_mode *mode);
> +void show_fec_capability(uint32_t fec_cap);
>  void set_nb_pkt_per_burst(uint16_t pkt_burst);
>  char *list_pkt_forwarding_modes(void);
>  char *list_pkt_forwarding_retry_modes(void);
> --
> 2.7.4
>

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [V5 1/3] ethdev: introduce FEC API
  2020-09-18  9:28         ` Min Hu (Connor)
@ 2020-09-19  8:42           ` Andrew Rybchenko
  2020-09-19 12:06             ` Min Hu (Connor)
  0 siblings, 1 reply; 118+ messages in thread
From: Andrew Rybchenko @ 2020-09-19  8:42 UTC (permalink / raw)
  To: Min Hu (Connor), dev; +Cc: konstantin.ananyev, thomas, ferruh.yigit, linuxarm

On 9/18/20 12:28 PM, Min Hu (Connor) wrote:
> 
> 
> 在 2020/9/17 17:58, Andrew Rybchenko 写道:
>> On 9/17/20 11:52 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>
>>> ---
>>> 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

[snip]

>>> diff --git a/lib/librte_ethdev/rte_ethdev.h 
>>> b/lib/librte_ethdev/rte_ethdev.h
>>> index 70295d7..aa79326 100644
>>> --- a/lib/librte_ethdev/rte_ethdev.h
>>> +++ b/lib/librte_ethdev/rte_ethdev.h
>>> @@ -1511,6 +1511,25 @@ 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_fec_mode {
>>
>> enum rte_eth_fec_mode
>> to be consistent with other enums and to have library prefix.
>>
> I fixed it in V6,thanks.
>>> +    RTE_ETH_FEC_NOFEC = 0,      /**< FEC is off */
>>> +    RTE_ETH_FEC_BASER,          /**< FEC using common algorithm */
>>> +    RTE_ETH_FEC_RS,             /**< FEC using RS algorithm */
>>> +    RTE_ETH_FEC_AUTO,           /**< FEC autonegotiation modes */
>>
>> May I suggest to put AUTO just after NOFEC. It would look move
>> logical in the future when more FEC modes are added. It would
>> look strange with AUTO in the middle of the list.
>>
>   hns3 PMD is the first to implement FEC function. The FEC mode order
>   is in accordance with the bit definition in hardware FEC module.

Sorry, it is not a good justification.
It does not matter who is the first and who will be the last.

>   in other ways, AUTO is flexible mode, which should not be differently 
>     treated,the location in last item of enum is ok.

I still disagree. If it is OK for other ethdev maintainer - no problem,
but I'd like to see explicit confirmation.

[snip]

>>> @@ -3328,6 +3347,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_BASER
>>> + *   RTE_ETH_FEC_CAPA_RS
>>> + *   RTE_ETH_FEC_CAPA_AUTO
>>
>> I'd like to see thoughts about different FEC modes for
>> different link speed. How to report it?
>> (sorry if I missed it before)
> the relation between FEC mode and link speed, we can refer to
> hns3 PMD code, as follows:
> 
>      switch (mac->link_speed) {
>      case ETH_SPEED_NUM_10G:
>      case ETH_SPEED_NUM_40G:
>          mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
>              RTE_ETH_FEC_CAPA_AUTO;
>          break;
>      case ETH_SPEED_NUM_25G:
>      case ETH_SPEED_NUM_50G:
>          mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
>              RTE_ETH_FEC_CAPA_RS | RTE_ETH_FEC_CAPA_AUTO;
>          break;
>      case ETH_SPEED_NUM_100G:
>      case ETH_SPEED_NUM_200G:
>          mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_RS |
>              RTE_ETH_FEC_CAPA_AUTO;
>          break;
>      default:
>          mode = 0;
>          break;
>      }

I'm sorry, but it does not answer my question.
I think we should change the API to report supported FEC modes per
supported link speed.

>>> + * @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);
>>
>> [snip]
>> .
>>


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V7 1/3] ethdev: introduce FEC API
  2020-09-18 18:10         ` Ajit Khaparde
@ 2020-09-19  8:44           ` Andrew Rybchenko
  0 siblings, 0 replies; 118+ messages in thread
From: Andrew Rybchenko @ 2020-09-19  8:44 UTC (permalink / raw)
  To: Ajit Khaparde, Ananyev, Konstantin
  Cc: Min Hu (Connor), dev, thomas, Yigit, Ferruh, linuxarm

On 9/18/20 9:10 PM, Ajit Khaparde wrote:
> On Fri, Sep 18, 2020 at 5:13 AM Ananyev, Konstantin
> <konstantin.ananyev@intel.com> 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>
>>> ---
>>> 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
>>>
>>> ---
>> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>

I'm sorry, but I'm still unhappy with enum members order and
get capabilities API. See v5 notes.


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [V5 1/3] ethdev: introduce FEC API
  2020-09-19  8:42           ` Andrew Rybchenko
@ 2020-09-19 12:06             ` Min Hu (Connor)
  0 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-19 12:06 UTC (permalink / raw)
  To: Andrew Rybchenko, dev; +Cc: konstantin.ananyev, thomas, ferruh.yigit, linuxarm



在 2020/9/19 16:42, Andrew Rybchenko 写道:
> On 9/18/20 12:28 PM, Min Hu (Connor) wrote:
>>
>>
>> 在 2020/9/17 17:58, Andrew Rybchenko 写道:
>>> On 9/17/20 11:52 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>
>>>> ---
>>>> 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
> 
> [snip]
> 
>>>> diff --git a/lib/librte_ethdev/rte_ethdev.h 
>>>> b/lib/librte_ethdev/rte_ethdev.h
>>>> index 70295d7..aa79326 100644
>>>> --- a/lib/librte_ethdev/rte_ethdev.h
>>>> +++ b/lib/librte_ethdev/rte_ethdev.h
>>>> @@ -1511,6 +1511,25 @@ 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_fec_mode {
>>>
>>> enum rte_eth_fec_mode
>>> to be consistent with other enums and to have library prefix.
>>>
>> I fixed it in V6,thanks.
>>>> +    RTE_ETH_FEC_NOFEC = 0,      /**< FEC is off */
>>>> +    RTE_ETH_FEC_BASER,          /**< FEC using common algorithm */
>>>> +    RTE_ETH_FEC_RS,             /**< FEC using RS algorithm */
>>>> +    RTE_ETH_FEC_AUTO,           /**< FEC autonegotiation modes */
>>>
>>> May I suggest to put AUTO just after NOFEC. It would look move
>>> logical in the future when more FEC modes are added. It would
>>> look strange with AUTO in the middle of the list.
>>>
>>   hns3 PMD is the first to implement FEC function. The FEC mode order
>>   is in accordance with the bit definition in hardware FEC module.
> 
> Sorry, it is not a good justification.
> It does not matter who is the first and who will be the last.
> 
>>   in other ways, AUTO is flexible mode, which should not be 
>> differently     treated,the location in last item of enum is ok.
> 
> I still disagree. If it is OK for other ethdev maintainer - no problem,
> but I'd like to see explicit confirmation.
  OK,thanks, I will try to fix it as you suggested.

> 
> [snip]
> 
>>>> @@ -3328,6 +3347,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_BASER
>>>> + *   RTE_ETH_FEC_CAPA_RS
>>>> + *   RTE_ETH_FEC_CAPA_AUTO
>>>
>>> I'd like to see thoughts about different FEC modes for
>>> different link speed. How to report it?
>>> (sorry if I missed it before)
>> the relation between FEC mode and link speed, we can refer to
>> hns3 PMD code, as follows:
>>
>>      switch (mac->link_speed) {
>>      case ETH_SPEED_NUM_10G:
>>      case ETH_SPEED_NUM_40G:
>>          mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
>>              RTE_ETH_FEC_CAPA_AUTO;
>>          break;
>>      case ETH_SPEED_NUM_25G:
>>      case ETH_SPEED_NUM_50G:
>>          mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
>>              RTE_ETH_FEC_CAPA_RS | RTE_ETH_FEC_CAPA_AUTO;
>>          break;
>>      case ETH_SPEED_NUM_100G:
>>      case ETH_SPEED_NUM_200G:
>>          mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_RS |
>>              RTE_ETH_FEC_CAPA_AUTO;
>>          break;
>>      default:
>>          mode = 0;
>>          break;
>>      }
> 
> I'm sorry, but it does not answer my question.
> I think we should change the API to report supported FEC modes per
> supported link speed.
  Sorry, maybe I do not get your meaning. By this API 
(rte_eth_fec_get_capability),we can get FEC capabilityes from device.
we (as user )do not care about the link speed, because this is done in PMD.
  So, how to change the API. Could your make it more clearer?
  Hope for your reply.

> 
>>>> + * @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);
>>>
>>> [snip]
>>> .
>>>
> 
> .

^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V8 0/3] add FEC support
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
                     ` (7 preceding siblings ...)
  2020-09-18 11:48   ` [dpdk-dev] [PATCH V7 0/3] add FEC support Min Hu (Connor)
@ 2020-09-21  2:59   ` Min Hu (Connor)
  2020-09-21  2:59     ` [dpdk-dev] [PATCH V8 1/3] ethdev: introduce FEC API Min Hu (Connor)
                       ` (2 more replies)
  2020-09-21  6:13   ` [dpdk-dev] [PATCH V9 0/3] add FEC support Min Hu (Connor)
                     ` (7 subsequent siblings)
  16 siblings, 3 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-21  2:59 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This series add FEC support for ethdev.

Min Hu (Connor) (3):
  ethdev: introduce FEC API
  net/hns3: support FEC
  app/testpmd: add FEC command

 app/test-pmd/cmdline.c                   | 219 +++++++++++++++++++++++++++++++
 app/test-pmd/config.c                    |  54 ++++++++
 app/test-pmd/testpmd.h                   |   2 +
 doc/guides/rel_notes/release_20_11.rst   |  10 ++
 drivers/net/hns3/hns3_cmd.h              |  19 ++-
 drivers/net/hns3/hns3_ethdev.c           | 183 ++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h           |   1 +
 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 +
 11 files changed, 705 insertions(+), 1 deletion(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V8 1/3] ethdev: introduce FEC API
  2020-09-21  2:59   ` [dpdk-dev] [PATCH V8 0/3] add FEC support Min Hu (Connor)
@ 2020-09-21  2:59     ` Min Hu (Connor)
  2020-09-21  2:59     ` [dpdk-dev] [PATCH V8 2/3] net/hns3: support FEC Min Hu (Connor)
  2020-09-21  2:59     ` [dpdk-dev] [PATCH V8 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-21  2:59 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

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>
---
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(+)

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 {
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V8 2/3] net/hns3: support FEC
  2020-09-21  2:59   ` [dpdk-dev] [PATCH V8 0/3] add FEC support Min Hu (Connor)
  2020-09-21  2:59     ` [dpdk-dev] [PATCH V8 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-21  2:59     ` Min Hu (Connor)
  2020-09-21  2:59     ` [dpdk-dev] [PATCH V8 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-21  2:59 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

Forward error correction (FEC) is a bit error correction mode.
It adds error correction information to data packets at the
transmit end, and uses the error correction information to correct
the bit errors generated during data packet transmission at the
receive end. This improves signal quality but also brings a delay
to signals. This function can be enabled or disabled as required.

This patch adds FEC support for ethdev.Introduce ethdev
operations 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>
---
v7->v8:
FEC mode order defined in hns3 hardware is inconsistend with
that defined in the ethdev library. So the sequence needs
to be converted.

---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Data type for fec_cap is changed from uint8_t
to uint32_t for possible future expansion.

---
v2->v3:
adjust the return value of function.

---
 drivers/net/hns3/hns3_cmd.h    |  19 ++++-
 drivers/net/hns3/hns3_ethdev.c | 183 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h |   1 +
 3 files changed, 202 insertions(+), 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index d70f42e..8b80353 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -99,6 +99,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_CONFIG_MAX_FRM_SIZE    = 0x0308,
 	HNS3_OPC_CONFIG_SPEED_DUP       = 0x0309,
 	HNS3_MAC_COMMON_INT_EN          = 0x030E,
+	HNS3_OPC_CONFIG_FEC_MODE        = 0x031A,
 
 	/* PFC/Pause commands */
 	HNS3_OPC_CFG_MAC_PAUSE_EN       = 0x0701,
@@ -653,9 +654,25 @@ struct hns3_config_auto_neg_cmd {
 	uint8_t   rsv[20];
 };
 
+#define HNS3_MAC_CFG_FEC_AUTO_EN_B	0
+#define HNS3_MAC_CFG_FEC_MODE_S		1
+#define HNS3_MAC_CFG_FEC_MODE_M	GENMASK(3, 1)
+#define HNS3_MAC_FEC_OFF		0
+#define HNS3_MAC_FEC_BASER		1
+#define HNS3_MAC_FEC_RS			2
+
 struct hns3_sfp_speed_cmd {
 	uint32_t  sfp_speed;
-	uint32_t  rsv[5];
+	uint8_t   query_type; /* 0: sfp speed, 1: active fec */
+	uint8_t   active_fec; /* current FEC mode */
+	uint16_t  rsv1;
+	uint32_t  rsv2[4];
+};
+
+/* Configure FEC mode, opcode:0x031A */
+struct hns3_config_fec_cmd {
+	uint8_t fec_mode;
+	uint8_t rsv[23];
 };
 
 #define HNS3_MAC_MGR_MASK_VLAN_B		BIT(0)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 81e7730..3fc2525 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -60,6 +60,11 @@
 #define HNS3_RESET_WAIT_MS	100
 #define HNS3_RESET_WAIT_CNT	200
 
+/* FEC mode order defined in HNS3 hardware */
+#define HNS3_HW_FEC_MODE_NOFEC  0
+#define HNS3_HW_FEC_MODE_BASER  1
+#define HNS3_HW_FEC_MODE_RS     2
+
 enum hns3_evt_cause {
 	HNS3_VECTOR0_EVENT_RST,
 	HNS3_VECTOR0_EVENT_MBX,
@@ -78,6 +83,8 @@ static int hns3_add_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
 static int hns3_remove_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
+static int hns3_restore_fec(struct hns3_hw *hw);
+static int hns3_query_dev_fec_info(struct rte_eth_dev *dev);
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -2819,6 +2826,13 @@ hns3_get_capability(struct hns3_hw *hw)
 	    device_id == HNS3_DEV_ID_200G_RDMA)
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_DCB_B, 1);
 
+	ret = hns3_query_dev_fec_info(eth_dev);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			     "failed to query FEC information, ret = %d", ret);
+		return ret;
+	}
+
 	/* Get PCI revision id */
 	ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN,
 				  HNS3_PCI_REVISION_ID);
@@ -5311,6 +5325,10 @@ hns3_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_promisc;
 
+	ret = hns3_restore_fec(hw);
+	if (ret)
+		goto err_promisc;
+
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED) {
 		ret = hns3_do_start(hns, false);
 		if (ret)
@@ -5389,6 +5407,168 @@ hns3_reset_service(void *param)
 		hns3_msix_process(hns, reset_level);
 }
 
+static int
+hns3_fec_get_capability(struct rte_eth_dev *dev, uint32_t *fec_cap)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_mac *mac = &hw->mac;
+	uint32_t mode;
+
+	switch (mac->link_speed) {
+	case ETH_SPEED_NUM_10G:
+	case ETH_SPEED_NUM_40G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
+			RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	case ETH_SPEED_NUM_25G:
+	case ETH_SPEED_NUM_50G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
+			RTE_ETH_FEC_CAPA_RS | RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	case ETH_SPEED_NUM_100G:
+	case ETH_SPEED_NUM_200G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_RS |
+			RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	default:
+		mode = 0;
+		break;
+	}
+
+	*fec_cap = mode;
+	return 0;
+}
+
+static int
+hns3_fec_get(struct rte_eth_dev *dev, enum rte_eth_fec_mode *mode)
+{
+#define QUERY_ACTIVE_SPEED	1
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_sfp_speed_cmd *resp;
+	enum rte_eth_fec_mode tmp_mode;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_SFP_GET_SPEED, true);
+	resp = (struct hns3_sfp_speed_cmd *)desc.data;
+	resp->query_type = QUERY_ACTIVE_SPEED;
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret == -EOPNOTSUPP) {
+		hns3_err(hw, "IMP do not support get FEC, ret = %d", ret);
+		return ret;
+	} else if (ret) {
+		hns3_err(hw, "get FEC failed, ret = %d", ret);
+		return ret;
+	}
+
+	/*
+	 * FEC mode order defined in hns3 hardware is inconsistend with
+	 * that defined in the ethdev library. So the sequence needs
+	 * to be converted.
+	 */
+	switch (resp->active_fec) {
+	case HNS3_HW_FEC_MODE_NOFEC:
+		tmp_mode = RTE_ETH_FEC_NOFEC;
+		break;
+	case HNS3_HW_FEC_MODE_BASER:
+		tmp_mode = RTE_ETH_FEC_BASER;
+		break;
+	case HNS3_HW_FEC_MODE_RS:
+		tmp_mode = RTE_ETH_FEC_RS;
+		break;
+	default:
+		tmp_mode = RTE_ETH_FEC_NOFEC;
+		break;
+	}
+
+	*mode = tmp_mode;
+	return 0;
+}
+
+static int
+hns3_set_fec_hw(struct hns3_hw *hw, enum rte_eth_fec_mode mode)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, false);
+
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	switch (mode) {
+	case RTE_ETH_FEC_NOFEC:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_OFF);
+		break;
+	case RTE_ETH_FEC_BASER:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_BASER);
+		break;
+	case RTE_ETH_FEC_RS:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_RS);
+		break;
+	case RTE_ETH_FEC_AUTO:
+		hns3_set_bit(req->fec_mode, HNS3_MAC_CFG_FEC_AUTO_EN_B, 1);
+		break;
+	default:
+		return 0;
+	}
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw, "set fec mode failed, ret = %d", ret);
+
+	return ret;
+}
+
+static int
+hns3_fec_set(struct rte_eth_dev *dev, enum rte_eth_fec_mode mode)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		return ret;
+
+	pf->fec_mode = mode;
+	return 0;
+}
+
+static int
+hns3_restore_fec(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+	enum rte_eth_fec_mode mode = pf->fec_mode;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		hns3_err(hw, "restore fec mode(%d) failed, ret = %d",
+			 mode, ret);
+
+	return ret;
+}
+
+static int
+hns3_query_dev_fec_info(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_fec_get(dev, &pf->fec_mode);
+	if (ret)
+		hns3_err(hw, "query device FEC info failed, ret = %d", ret);
+
+	return ret;
+}
+
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_start          = hns3_dev_start,
 	.dev_stop           = hns3_dev_stop,
@@ -5434,6 +5614,9 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.get_reg                = hns3_get_regs,
 	.get_dcb_info           = hns3_get_dcb_info,
 	.dev_supported_ptypes_get = hns3_dev_supported_ptypes_get,
+	.fec_get_capability     = hns3_fec_get_capability,
+	.fec_get                = hns3_fec_get,
+	.fec_set                = hns3_fec_set,
 };
 
 static const struct hns3_reset_ops hns3_reset_ops = {
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 0e665e5..2435668 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -510,6 +510,7 @@ struct hns3_pf {
 	struct hns3_err_msix_intr_stats abn_int_stats;
 
 	bool support_sfp_query;
+	enum rte_eth_fec_mode fec_mode; /* current FEC mode for ethdev */
 
 	struct hns3_vtag_cfg vtag_config;
 	LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V8 3/3] app/testpmd: add FEC command
  2020-09-21  2:59   ` [dpdk-dev] [PATCH V8 0/3] add FEC support Min Hu (Connor)
  2020-09-21  2:59     ` [dpdk-dev] [PATCH V8 1/3] ethdev: introduce FEC API Min Hu (Connor)
  2020-09-21  2:59     ` [dpdk-dev] [PATCH V8 2/3] net/hns3: support FEC Min Hu (Connor)
@ 2020-09-21  2:59     ` Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-21  2:59 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This commit adds testpmd capability to query and config FEC
function of device. This includes:
- show FEC capabilities, example:
	testpmd> show port 0 fec capabilities
- show FEC mode, example:
	testpmd> show port 0 fec_mode
- config FEC mode, example:
	testpmd> set port <port_id> 0 <auto|off|rs|baser>

	where:

	auto|off|rs|baser are four kinds of FEC mode which dev
	support according to MAC link speed.

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>
---
v6->v7:
used RTE_DIM(fec_mode_name) instead of RTE_ETH_FEC_NUM

---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Add RTE_ prefix for public FEC mode enum.

---
v3->v4:
adjust the display format of FEC mode

---
v2->v3:
adjust the display format of FEC capability.

---
 app/test-pmd/cmdline.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c  |  54 ++++++++++++
 app/test-pmd/testpmd.h |   2 +
 3 files changed, 275 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0a6ed85..3394bea 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -19054,6 +19054,222 @@ cmdline_parse_inst_t cmd_show_tx_metadata = {
 	},
 };
 
+/* *** show fec capability per port configuration *** */
+struct cmd_show_fec_capability_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_fec;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_capability_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+	struct cmd_show_fec_capability_result *res = parsed_result;
+	uint32_t fec_cap;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_fec_get_capability(res->cmd_pid, &fec_cap);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC capability failed\n");
+		return;
+	}
+
+	show_fec_capability(fec_cap);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_capability_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_capability_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_capability_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_capability_fec =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_fec, "fec");
+cmdline_parse_token_string_t cmd_show_fec_capability_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_keyword, "capabilities");
+
+cmdline_parse_inst_t cmd_show_capability = {
+	.f = cmd_show_fec_capability_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec capabilities",
+	.tokens = {
+		(void *)&cmd_show_fec_capability_show,
+		(void *)&cmd_show_fec_capability_port,
+		(void *)&cmd_show_fec_capability_pid,
+		(void *)&cmd_show_fec_capability_fec,
+		(void *)&cmd_show_fec_capability_keyword,
+		NULL,
+	},
+};
+
+/* *** show fec mode per port configuration *** */
+struct cmd_show_fec_metadata_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_mode_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_NAME_SIZE 16
+	struct cmd_show_fec_metadata_result *res = parsed_result;
+	enum rte_eth_fec_mode mode;
+	char buf[FEC_NAME_SIZE];
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+	ret = rte_eth_fec_get(res->cmd_pid, &mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC mode failed\n");
+		return;
+	}
+
+	switch (mode) {
+	case RTE_ETH_FEC_NOFEC:
+		strlcpy(buf, "off", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_AUTO:
+		strlcpy(buf, "auto", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_BASER:
+		strlcpy(buf, "baser", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_RS:
+		strlcpy(buf, "rs", sizeof(buf));
+		break;
+	default:
+		return;
+	}
+
+	printf("%s\n", buf);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_mode_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_mode_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_mode_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_mode_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_keyword, "fec_mode");
+
+cmdline_parse_inst_t cmd_show_fec_mode = {
+	.f = cmd_show_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec_mode",
+	.tokens = {
+		(void *)&cmd_show_fec_mode_show,
+		(void *)&cmd_show_fec_mode_port,
+		(void *)&cmd_show_fec_mode_pid,
+		(void *)&cmd_show_fec_mode_keyword,
+		NULL,
+	},
+};
+
+/* *** set fec mode per port configuration *** */
+struct cmd_set_port_fec_mode {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t fec_mode;
+	cmdline_fixed_string_t fec_value;
+};
+
+/* Common CLI fields for set fec mode */
+cmdline_parse_token_string_t cmd_set_port_fec_mode_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port, "port");
+cmdline_parse_token_num_t cmd_set_port_fec_mode_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_port_fec_mode_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_mode, "fec_mode");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_value =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_value, NULL);
+
+static void
+cmd_set_port_fec_mode_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	__rte_unused void *data)
+{
+	struct cmd_set_port_fec_mode *res = parsed_result;
+	uint16_t port_id = res->port_id;
+	enum rte_eth_fec_mode mode;
+	int ret;
+
+	ret = parse_fec_mode(res->fec_value, &mode);
+	if (ret < 0) {
+		printf("Unknown fec mode: %s for Port %d\n", res->fec_value,
+			port_id);
+		return;
+	}
+
+	ret = rte_eth_fec_set(port_id, mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Set FEC mode failed\n");
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_fec_mode = {
+	.f = cmd_set_port_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> fec_mode <auto|off|rs|baser>",
+	.tokens = {
+		(void *)&cmd_set_port_fec_mode_set,
+		(void *)&cmd_set_port_fec_mode_port,
+		(void *)&cmd_set_port_fec_mode_port_id,
+		(void *)&cmd_set_port_fec_mode_str,
+		(void *)&cmd_set_port_fec_mode_value,
+		NULL,
+	},
+};
+
 /* show port supported ptypes */
 
 /* Common result structure for show port ptypes */
@@ -19685,6 +19901,9 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_set_raw,
 	(cmdline_parse_inst_t *)&cmd_show_set_raw_all,
 	(cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
+	(cmdline_parse_inst_t *)&cmd_show_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_set_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_show_capability,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 30bee33..ba752ea 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -138,6 +138,28 @@ const struct rss_type_info rss_type_table[] = {
 	{ NULL, 0 },
 };
 
+static const struct {
+	enum rte_eth_fec_mode mode;
+	const char *name;
+} fec_mode_name[] = {
+	{
+		.mode = RTE_ETH_FEC_NOFEC,
+		.name = "off",
+	},
+	{
+		.mode = RTE_ETH_FEC_AUTO,
+		.name = "auto",
+	},
+	{
+		.mode = RTE_ETH_FEC_BASER,
+		.name = "baser",
+	},
+	{
+		.mode = RTE_ETH_FEC_RS,
+		.name = "rs",
+	},
+};
+
 static void
 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
 {
@@ -2967,6 +2989,38 @@ set_tx_pkt_split(const char *name)
 	printf("unknown value: \"%s\"\n", name);
 }
 
+int
+parse_fec_mode(const char *name, enum rte_eth_fec_mode *mode)
+{
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(fec_mode_name); i++) {
+		if (strcmp(fec_mode_name[i].name, name) == 0) {
+			*mode = fec_mode_name[i].mode;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void
+show_fec_capability(uint32_t fec_cap)
+{
+	uint32_t i;
+
+	if (fec_cap == 0) {
+		printf("FEC is not supported\n");
+		return;
+	}
+
+	printf("FEC capabilities: ");
+	for (i = RTE_ETH_FEC_AUTO; i < RTE_DIM(fec_mode_name); i++) {
+		if (fec_cap & RTE_ETH_FEC_MODE_TO_CAPA(i))
+			printf("%s ", fec_mode_name[i].name);
+	}
+	printf("\n");
+}
+
 void
 show_tx_pkt_segments(void)
 {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 25a12b1..3be56e8 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -778,6 +778,8 @@ void show_tx_pkt_segments(void);
 void set_tx_pkt_times(unsigned int *tx_times);
 void show_tx_pkt_times(void);
 void set_tx_pkt_split(const char *name);
+int parse_fec_mode(const char *name, enum rte_eth_fec_mode *mode);
+void show_fec_capability(uint32_t fec_cap);
 void set_nb_pkt_per_burst(uint16_t pkt_burst);
 char *list_pkt_forwarding_modes(void);
 char *list_pkt_forwarding_retry_modes(void);
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V9 0/3] add FEC support
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
                     ` (8 preceding siblings ...)
  2020-09-21  2:59   ` [dpdk-dev] [PATCH V8 0/3] add FEC support Min Hu (Connor)
@ 2020-09-21  6:13   ` Min Hu (Connor)
  2020-09-21  6:13     ` [dpdk-dev] [PATCH V9 1/3] ethdev: introduce FEC API Min Hu (Connor)
                       ` (2 more replies)
  2020-09-22  7:26   ` [dpdk-dev] [PATCH V10 0/3] add FEC support Min Hu (Connor)
                     ` (6 subsequent siblings)
  16 siblings, 3 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-21  6:13 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This series add FEC support for ethdev.

Min Hu (Connor) (3):
  ethdev: introduce FEC API
  net/hns3: support FEC
  app/testpmd: add FEC command

 app/test-pmd/cmdline.c                   | 219 +++++++++++++++++++++++++++++++
 app/test-pmd/config.c                    |  54 ++++++++
 app/test-pmd/testpmd.h                   |   2 +
 doc/guides/rel_notes/release_20_11.rst   |  10 ++
 drivers/net/hns3/hns3_cmd.h              |  19 ++-
 drivers/net/hns3/hns3_ethdev.c           | 183 ++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h           |   1 +
 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 +
 11 files changed, 705 insertions(+), 1 deletion(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V9 1/3] ethdev: introduce FEC API
  2020-09-21  6:13   ` [dpdk-dev] [PATCH V9 0/3] add FEC support Min Hu (Connor)
@ 2020-09-21  6:13     ` Min Hu (Connor)
  2020-09-21 13:39       ` Andrew Rybchenko
  2020-09-21  6:13     ` [dpdk-dev] [PATCH V9 2/3] net/hns3: support FEC Min Hu (Connor)
  2020-09-21  6:13     ` [dpdk-dev] [PATCH V9 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 1 reply; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-21  6:13 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

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(+)

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 {
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V9 2/3] net/hns3: support FEC
  2020-09-21  6:13   ` [dpdk-dev] [PATCH V9 0/3] add FEC support Min Hu (Connor)
  2020-09-21  6:13     ` [dpdk-dev] [PATCH V9 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-21  6:13     ` Min Hu (Connor)
  2020-09-21  6:13     ` [dpdk-dev] [PATCH V9 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-21  6:13 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

Forward error correction (FEC) is a bit error correction mode.
It adds error correction information to data packets at the
transmit end, and uses the error correction information to correct
the bit errors generated during data packet transmission at the
receive end. This improves signal quality but also brings a delay
to signals. This function can be enabled or disabled as required.

This patch adds FEC support for ethdev.Introduce ethdev
operations 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>
---
v7->v8:
FEC mode order defined in hns3 hardware is inconsistend with
that defined in the ethdev library. So the sequence needs
to be converted.

---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Data type for fec_cap is changed from uint8_t
to uint32_t for possible future expansion.

---
v2->v3:
adjust the return value of function.

---
 drivers/net/hns3/hns3_cmd.h    |  19 ++++-
 drivers/net/hns3/hns3_ethdev.c | 183 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h |   1 +
 3 files changed, 202 insertions(+), 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index d70f42e..8b80353 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -99,6 +99,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_CONFIG_MAX_FRM_SIZE    = 0x0308,
 	HNS3_OPC_CONFIG_SPEED_DUP       = 0x0309,
 	HNS3_MAC_COMMON_INT_EN          = 0x030E,
+	HNS3_OPC_CONFIG_FEC_MODE        = 0x031A,
 
 	/* PFC/Pause commands */
 	HNS3_OPC_CFG_MAC_PAUSE_EN       = 0x0701,
@@ -653,9 +654,25 @@ struct hns3_config_auto_neg_cmd {
 	uint8_t   rsv[20];
 };
 
+#define HNS3_MAC_CFG_FEC_AUTO_EN_B	0
+#define HNS3_MAC_CFG_FEC_MODE_S		1
+#define HNS3_MAC_CFG_FEC_MODE_M	GENMASK(3, 1)
+#define HNS3_MAC_FEC_OFF		0
+#define HNS3_MAC_FEC_BASER		1
+#define HNS3_MAC_FEC_RS			2
+
 struct hns3_sfp_speed_cmd {
 	uint32_t  sfp_speed;
-	uint32_t  rsv[5];
+	uint8_t   query_type; /* 0: sfp speed, 1: active fec */
+	uint8_t   active_fec; /* current FEC mode */
+	uint16_t  rsv1;
+	uint32_t  rsv2[4];
+};
+
+/* Configure FEC mode, opcode:0x031A */
+struct hns3_config_fec_cmd {
+	uint8_t fec_mode;
+	uint8_t rsv[23];
 };
 
 #define HNS3_MAC_MGR_MASK_VLAN_B		BIT(0)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 81e7730..3fc2525 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -60,6 +60,11 @@
 #define HNS3_RESET_WAIT_MS	100
 #define HNS3_RESET_WAIT_CNT	200
 
+/* FEC mode order defined in HNS3 hardware */
+#define HNS3_HW_FEC_MODE_NOFEC  0
+#define HNS3_HW_FEC_MODE_BASER  1
+#define HNS3_HW_FEC_MODE_RS     2
+
 enum hns3_evt_cause {
 	HNS3_VECTOR0_EVENT_RST,
 	HNS3_VECTOR0_EVENT_MBX,
@@ -78,6 +83,8 @@ static int hns3_add_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
 static int hns3_remove_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
+static int hns3_restore_fec(struct hns3_hw *hw);
+static int hns3_query_dev_fec_info(struct rte_eth_dev *dev);
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -2819,6 +2826,13 @@ hns3_get_capability(struct hns3_hw *hw)
 	    device_id == HNS3_DEV_ID_200G_RDMA)
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_DCB_B, 1);
 
+	ret = hns3_query_dev_fec_info(eth_dev);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			     "failed to query FEC information, ret = %d", ret);
+		return ret;
+	}
+
 	/* Get PCI revision id */
 	ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN,
 				  HNS3_PCI_REVISION_ID);
@@ -5311,6 +5325,10 @@ hns3_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_promisc;
 
+	ret = hns3_restore_fec(hw);
+	if (ret)
+		goto err_promisc;
+
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED) {
 		ret = hns3_do_start(hns, false);
 		if (ret)
@@ -5389,6 +5407,168 @@ hns3_reset_service(void *param)
 		hns3_msix_process(hns, reset_level);
 }
 
+static int
+hns3_fec_get_capability(struct rte_eth_dev *dev, uint32_t *fec_cap)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_mac *mac = &hw->mac;
+	uint32_t mode;
+
+	switch (mac->link_speed) {
+	case ETH_SPEED_NUM_10G:
+	case ETH_SPEED_NUM_40G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
+			RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	case ETH_SPEED_NUM_25G:
+	case ETH_SPEED_NUM_50G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_BASER |
+			RTE_ETH_FEC_CAPA_RS | RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	case ETH_SPEED_NUM_100G:
+	case ETH_SPEED_NUM_200G:
+		mode = RTE_ETH_FEC_CAPA_NOFEC | RTE_ETH_FEC_CAPA_RS |
+			RTE_ETH_FEC_CAPA_AUTO;
+		break;
+	default:
+		mode = 0;
+		break;
+	}
+
+	*fec_cap = mode;
+	return 0;
+}
+
+static int
+hns3_fec_get(struct rte_eth_dev *dev, enum rte_eth_fec_mode *mode)
+{
+#define QUERY_ACTIVE_SPEED	1
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_sfp_speed_cmd *resp;
+	enum rte_eth_fec_mode tmp_mode;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_SFP_GET_SPEED, true);
+	resp = (struct hns3_sfp_speed_cmd *)desc.data;
+	resp->query_type = QUERY_ACTIVE_SPEED;
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret == -EOPNOTSUPP) {
+		hns3_err(hw, "IMP do not support get FEC, ret = %d", ret);
+		return ret;
+	} else if (ret) {
+		hns3_err(hw, "get FEC failed, ret = %d", ret);
+		return ret;
+	}
+
+	/*
+	 * FEC mode order defined in hns3 hardware is inconsistend with
+	 * that defined in the ethdev library. So the sequence needs
+	 * to be converted.
+	 */
+	switch (resp->active_fec) {
+	case HNS3_HW_FEC_MODE_NOFEC:
+		tmp_mode = RTE_ETH_FEC_NOFEC;
+		break;
+	case HNS3_HW_FEC_MODE_BASER:
+		tmp_mode = RTE_ETH_FEC_BASER;
+		break;
+	case HNS3_HW_FEC_MODE_RS:
+		tmp_mode = RTE_ETH_FEC_RS;
+		break;
+	default:
+		tmp_mode = RTE_ETH_FEC_NOFEC;
+		break;
+	}
+
+	*mode = tmp_mode;
+	return 0;
+}
+
+static int
+hns3_set_fec_hw(struct hns3_hw *hw, enum rte_eth_fec_mode mode)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, false);
+
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	switch (mode) {
+	case RTE_ETH_FEC_NOFEC:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_OFF);
+		break;
+	case RTE_ETH_FEC_BASER:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_BASER);
+		break;
+	case RTE_ETH_FEC_RS:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_RS);
+		break;
+	case RTE_ETH_FEC_AUTO:
+		hns3_set_bit(req->fec_mode, HNS3_MAC_CFG_FEC_AUTO_EN_B, 1);
+		break;
+	default:
+		return 0;
+	}
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw, "set fec mode failed, ret = %d", ret);
+
+	return ret;
+}
+
+static int
+hns3_fec_set(struct rte_eth_dev *dev, enum rte_eth_fec_mode mode)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		return ret;
+
+	pf->fec_mode = mode;
+	return 0;
+}
+
+static int
+hns3_restore_fec(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+	enum rte_eth_fec_mode mode = pf->fec_mode;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		hns3_err(hw, "restore fec mode(%d) failed, ret = %d",
+			 mode, ret);
+
+	return ret;
+}
+
+static int
+hns3_query_dev_fec_info(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_fec_get(dev, &pf->fec_mode);
+	if (ret)
+		hns3_err(hw, "query device FEC info failed, ret = %d", ret);
+
+	return ret;
+}
+
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_start          = hns3_dev_start,
 	.dev_stop           = hns3_dev_stop,
@@ -5434,6 +5614,9 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.get_reg                = hns3_get_regs,
 	.get_dcb_info           = hns3_get_dcb_info,
 	.dev_supported_ptypes_get = hns3_dev_supported_ptypes_get,
+	.fec_get_capability     = hns3_fec_get_capability,
+	.fec_get                = hns3_fec_get,
+	.fec_set                = hns3_fec_set,
 };
 
 static const struct hns3_reset_ops hns3_reset_ops = {
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 0e665e5..2435668 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -510,6 +510,7 @@ struct hns3_pf {
 	struct hns3_err_msix_intr_stats abn_int_stats;
 
 	bool support_sfp_query;
+	enum rte_eth_fec_mode fec_mode; /* current FEC mode for ethdev */
 
 	struct hns3_vtag_cfg vtag_config;
 	LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V9 3/3] app/testpmd: add FEC command
  2020-09-21  6:13   ` [dpdk-dev] [PATCH V9 0/3] add FEC support Min Hu (Connor)
  2020-09-21  6:13     ` [dpdk-dev] [PATCH V9 1/3] ethdev: introduce FEC API Min Hu (Connor)
  2020-09-21  6:13     ` [dpdk-dev] [PATCH V9 2/3] net/hns3: support FEC Min Hu (Connor)
@ 2020-09-21  6:13     ` Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-21  6:13 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This commit adds testpmd capability to query and config FEC
function of device. This includes:
- show FEC capabilities, example:
	testpmd> show port 0 fec capabilities
- show FEC mode, example:
	testpmd> show port 0 fec_mode
- config FEC mode, example:
	testpmd> set port <port_id> 0 <auto|off|rs|baser>

	where:

	auto|off|rs|baser are four kinds of FEC mode which dev
	support according to MAC link speed.

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>
Acked-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
---
v8->v9:
added acked-by.

---
v6->v7:
used RTE_DIM(fec_mode_name) instead of RTE_ETH_FEC_NUM

---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Add RTE_ prefix for public FEC mode enum.

---
v3->v4:
adjust the display format of FEC mode

---
v2->v3:
adjust the display format of FEC capability.

---
 app/test-pmd/cmdline.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c  |  54 ++++++++++++
 app/test-pmd/testpmd.h |   2 +
 3 files changed, 275 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0a6ed85..3394bea 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -19054,6 +19054,222 @@ cmdline_parse_inst_t cmd_show_tx_metadata = {
 	},
 };
 
+/* *** show fec capability per port configuration *** */
+struct cmd_show_fec_capability_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_fec;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_capability_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+	struct cmd_show_fec_capability_result *res = parsed_result;
+	uint32_t fec_cap;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_fec_get_capability(res->cmd_pid, &fec_cap);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC capability failed\n");
+		return;
+	}
+
+	show_fec_capability(fec_cap);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_capability_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_capability_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_capability_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_capability_fec =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_fec, "fec");
+cmdline_parse_token_string_t cmd_show_fec_capability_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_keyword, "capabilities");
+
+cmdline_parse_inst_t cmd_show_capability = {
+	.f = cmd_show_fec_capability_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec capabilities",
+	.tokens = {
+		(void *)&cmd_show_fec_capability_show,
+		(void *)&cmd_show_fec_capability_port,
+		(void *)&cmd_show_fec_capability_pid,
+		(void *)&cmd_show_fec_capability_fec,
+		(void *)&cmd_show_fec_capability_keyword,
+		NULL,
+	},
+};
+
+/* *** show fec mode per port configuration *** */
+struct cmd_show_fec_metadata_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_mode_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_NAME_SIZE 16
+	struct cmd_show_fec_metadata_result *res = parsed_result;
+	enum rte_eth_fec_mode mode;
+	char buf[FEC_NAME_SIZE];
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+	ret = rte_eth_fec_get(res->cmd_pid, &mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC mode failed\n");
+		return;
+	}
+
+	switch (mode) {
+	case RTE_ETH_FEC_NOFEC:
+		strlcpy(buf, "off", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_AUTO:
+		strlcpy(buf, "auto", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_BASER:
+		strlcpy(buf, "baser", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_RS:
+		strlcpy(buf, "rs", sizeof(buf));
+		break;
+	default:
+		return;
+	}
+
+	printf("%s\n", buf);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_mode_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_mode_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_mode_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_mode_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_keyword, "fec_mode");
+
+cmdline_parse_inst_t cmd_show_fec_mode = {
+	.f = cmd_show_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec_mode",
+	.tokens = {
+		(void *)&cmd_show_fec_mode_show,
+		(void *)&cmd_show_fec_mode_port,
+		(void *)&cmd_show_fec_mode_pid,
+		(void *)&cmd_show_fec_mode_keyword,
+		NULL,
+	},
+};
+
+/* *** set fec mode per port configuration *** */
+struct cmd_set_port_fec_mode {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t fec_mode;
+	cmdline_fixed_string_t fec_value;
+};
+
+/* Common CLI fields for set fec mode */
+cmdline_parse_token_string_t cmd_set_port_fec_mode_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port, "port");
+cmdline_parse_token_num_t cmd_set_port_fec_mode_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_port_fec_mode_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_mode, "fec_mode");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_value =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_value, NULL);
+
+static void
+cmd_set_port_fec_mode_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	__rte_unused void *data)
+{
+	struct cmd_set_port_fec_mode *res = parsed_result;
+	uint16_t port_id = res->port_id;
+	enum rte_eth_fec_mode mode;
+	int ret;
+
+	ret = parse_fec_mode(res->fec_value, &mode);
+	if (ret < 0) {
+		printf("Unknown fec mode: %s for Port %d\n", res->fec_value,
+			port_id);
+		return;
+	}
+
+	ret = rte_eth_fec_set(port_id, mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Set FEC mode failed\n");
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_fec_mode = {
+	.f = cmd_set_port_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> fec_mode <auto|off|rs|baser>",
+	.tokens = {
+		(void *)&cmd_set_port_fec_mode_set,
+		(void *)&cmd_set_port_fec_mode_port,
+		(void *)&cmd_set_port_fec_mode_port_id,
+		(void *)&cmd_set_port_fec_mode_str,
+		(void *)&cmd_set_port_fec_mode_value,
+		NULL,
+	},
+};
+
 /* show port supported ptypes */
 
 /* Common result structure for show port ptypes */
@@ -19685,6 +19901,9 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_set_raw,
 	(cmdline_parse_inst_t *)&cmd_show_set_raw_all,
 	(cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
+	(cmdline_parse_inst_t *)&cmd_show_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_set_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_show_capability,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 30bee33..ba752ea 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -138,6 +138,28 @@ const struct rss_type_info rss_type_table[] = {
 	{ NULL, 0 },
 };
 
+static const struct {
+	enum rte_eth_fec_mode mode;
+	const char *name;
+} fec_mode_name[] = {
+	{
+		.mode = RTE_ETH_FEC_NOFEC,
+		.name = "off",
+	},
+	{
+		.mode = RTE_ETH_FEC_AUTO,
+		.name = "auto",
+	},
+	{
+		.mode = RTE_ETH_FEC_BASER,
+		.name = "baser",
+	},
+	{
+		.mode = RTE_ETH_FEC_RS,
+		.name = "rs",
+	},
+};
+
 static void
 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
 {
@@ -2967,6 +2989,38 @@ set_tx_pkt_split(const char *name)
 	printf("unknown value: \"%s\"\n", name);
 }
 
+int
+parse_fec_mode(const char *name, enum rte_eth_fec_mode *mode)
+{
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(fec_mode_name); i++) {
+		if (strcmp(fec_mode_name[i].name, name) == 0) {
+			*mode = fec_mode_name[i].mode;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void
+show_fec_capability(uint32_t fec_cap)
+{
+	uint32_t i;
+
+	if (fec_cap == 0) {
+		printf("FEC is not supported\n");
+		return;
+	}
+
+	printf("FEC capabilities: ");
+	for (i = RTE_ETH_FEC_AUTO; i < RTE_DIM(fec_mode_name); i++) {
+		if (fec_cap & RTE_ETH_FEC_MODE_TO_CAPA(i))
+			printf("%s ", fec_mode_name[i].name);
+	}
+	printf("\n");
+}
+
 void
 show_tx_pkt_segments(void)
 {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 25a12b1..3be56e8 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -778,6 +778,8 @@ void show_tx_pkt_segments(void);
 void set_tx_pkt_times(unsigned int *tx_times);
 void show_tx_pkt_times(void);
 void set_tx_pkt_split(const char *name);
+int parse_fec_mode(const char *name, enum rte_eth_fec_mode *mode);
+void show_fec_capability(uint32_t fec_cap);
 void set_nb_pkt_per_burst(uint16_t pkt_burst);
 char *list_pkt_forwarding_modes(void);
 char *list_pkt_forwarding_retry_modes(void);
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V9 1/3] ethdev: introduce FEC API
  2020-09-21  6:13     ` [dpdk-dev] [PATCH V9 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-21 13:39       ` Andrew Rybchenko
  2020-09-22  4:58         ` Min Hu (Connor)
  0 siblings, 1 reply; 118+ messages in thread
From: Andrew Rybchenko @ 2020-09-21 13:39 UTC (permalink / raw)
  To: Min Hu (Connor), dev; +Cc: konstantin.ananyev, thomas, ferruh.yigit, linuxarm

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]


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V9 1/3] ethdev: introduce FEC API
  2020-09-21 13:39       ` Andrew Rybchenko
@ 2020-09-22  4:58         ` Min Hu (Connor)
  2020-09-22  8:02           ` Andrew Rybchenko
  0 siblings, 1 reply; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-22  4:58 UTC (permalink / raw)
  To: Andrew Rybchenko, dev; +Cc: konstantin.ananyev, thomas, ferruh.yigit, linuxarm



在 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]
> 
> .
> 

^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V10 0/3] add FEC support
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
                     ` (9 preceding siblings ...)
  2020-09-21  6:13   ` [dpdk-dev] [PATCH V9 0/3] add FEC support Min Hu (Connor)
@ 2020-09-22  7:26   ` Min Hu (Connor)
  2020-09-22  7:26     ` [dpdk-dev] [PATCH V10 1/3] ethdev: introduce FEC API Min Hu (Connor)
                       ` (2 more replies)
  2020-09-24 11:01   ` [dpdk-dev] [PATCH V11 0/4] add FEC support Min Hu (Connor)
                     ` (5 subsequent siblings)
  16 siblings, 3 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-22  7:26 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This series add FEC support for ethdev.

Min Hu (Connor) (3):
  ethdev: introduce FEC API
  net/hns3: support FEC
  app/testpmd: add FEC command

 app/test-pmd/cmdline.c                   | 219 +++++++++++++++++++++++++++++++
 app/test-pmd/config.c                    |  54 ++++++++
 app/test-pmd/testpmd.h                   |   2 +
 doc/guides/rel_notes/release_20_11.rst   |  10 ++
 drivers/net/hns3/hns3_cmd.h              |  19 ++-
 drivers/net/hns3/hns3_ethdev.c           | 187 ++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h           |   1 +
 lib/librte_ethdev/rte_ethdev.c           |  49 +++++++
 lib/librte_ethdev/rte_ethdev.h           |  81 ++++++++++++
 lib/librte_ethdev/rte_ethdev_core.h      |  79 +++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |   5 +
 11 files changed, 705 insertions(+), 1 deletion(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V10 1/3] ethdev: introduce FEC API
  2020-09-22  7:26   ` [dpdk-dev] [PATCH V10 0/3] add FEC support Min Hu (Connor)
@ 2020-09-22  7:26     ` Min Hu (Connor)
  2020-09-22  7:26     ` [dpdk-dev] [PATCH V10 2/3] net/hns3: support FEC Min Hu (Connor)
  2020-09-22  7:26     ` [dpdk-dev] [PATCH V10 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-22  7:26 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

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>
---
v9->v10:
add macro RTE_ETH_FEC_MODE_CAPA_MASK(x) to indicate
different FEC mode capa.

---
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           | 81 ++++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_core.h      | 79 +++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |  5 ++
 5 files changed, 224 insertions(+)

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..3f5c960 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1511,6 +1511,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 */
+};
+
+/* Translate from FEC mode to FEC capa */
+#define RTE_ETH_FEC_MODE_TO_CAPA(x)	(1U << (x))
+
+/* This macro indicates FEC capa mask*/
+#define RTE_ETH_FEC_MODE_CAPA_MASK(x)	(1U << (RTE_ETH_FEC_ ## x))
+
+
 #define RTE_ETH_ALL RTE_MAX_ETHPORTS
 
 /* Macros to check for valid port */
@@ -3328,6 +3346,69 @@ 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, referring to:
+ *   RTE_ETH_FEC_MODE_CAPA_MASK(x)
+ * @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.
+ * 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 querying the 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 {
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V10 2/3] net/hns3: support FEC
  2020-09-22  7:26   ` [dpdk-dev] [PATCH V10 0/3] add FEC support Min Hu (Connor)
  2020-09-22  7:26     ` [dpdk-dev] [PATCH V10 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-22  7:26     ` Min Hu (Connor)
  2020-09-22  7:26     ` [dpdk-dev] [PATCH V10 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-22  7:26 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

Forward error correction (FEC) is a bit error correction mode.
It adds error correction information to data packets at the
transmit end, and uses the error correction information to correct
the bit errors generated during data packet transmission at the
receive end. This improves signal quality but also brings a delay
to signals. This function can be enabled or disabled as required.

This patch adds FEC support for ethdev.Introduce ethdev
operations 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>
---
v9->v10:
use RTE_ETH_FEC_MODE_CAPA_MASK(x) which is just defined.

---
v7->v8:
FEC mode order defined in hns3 hardware is inconsistend with
that defined in the ethdev library. So the sequence needs
to be converted.

---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Data type for fec_cap is changed from uint8_t
to uint32_t for possible future expansion.

---
v2->v3:
adjust the return value of function.

---
 drivers/net/hns3/hns3_cmd.h    |  19 ++++-
 drivers/net/hns3/hns3_ethdev.c | 187 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h |   1 +
 3 files changed, 206 insertions(+), 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index d70f42e..8b80353 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -99,6 +99,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_CONFIG_MAX_FRM_SIZE    = 0x0308,
 	HNS3_OPC_CONFIG_SPEED_DUP       = 0x0309,
 	HNS3_MAC_COMMON_INT_EN          = 0x030E,
+	HNS3_OPC_CONFIG_FEC_MODE        = 0x031A,
 
 	/* PFC/Pause commands */
 	HNS3_OPC_CFG_MAC_PAUSE_EN       = 0x0701,
@@ -653,9 +654,25 @@ struct hns3_config_auto_neg_cmd {
 	uint8_t   rsv[20];
 };
 
+#define HNS3_MAC_CFG_FEC_AUTO_EN_B	0
+#define HNS3_MAC_CFG_FEC_MODE_S		1
+#define HNS3_MAC_CFG_FEC_MODE_M	GENMASK(3, 1)
+#define HNS3_MAC_FEC_OFF		0
+#define HNS3_MAC_FEC_BASER		1
+#define HNS3_MAC_FEC_RS			2
+
 struct hns3_sfp_speed_cmd {
 	uint32_t  sfp_speed;
-	uint32_t  rsv[5];
+	uint8_t   query_type; /* 0: sfp speed, 1: active fec */
+	uint8_t   active_fec; /* current FEC mode */
+	uint16_t  rsv1;
+	uint32_t  rsv2[4];
+};
+
+/* Configure FEC mode, opcode:0x031A */
+struct hns3_config_fec_cmd {
+	uint8_t fec_mode;
+	uint8_t rsv[23];
 };
 
 #define HNS3_MAC_MGR_MASK_VLAN_B		BIT(0)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 81e7730..e53ae4e 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -60,6 +60,11 @@
 #define HNS3_RESET_WAIT_MS	100
 #define HNS3_RESET_WAIT_CNT	200
 
+/* FEC mode order defined in HNS3 hardware */
+#define HNS3_HW_FEC_MODE_NOFEC  0
+#define HNS3_HW_FEC_MODE_BASER  1
+#define HNS3_HW_FEC_MODE_RS     2
+
 enum hns3_evt_cause {
 	HNS3_VECTOR0_EVENT_RST,
 	HNS3_VECTOR0_EVENT_MBX,
@@ -78,6 +83,8 @@ static int hns3_add_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
 static int hns3_remove_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
+static int hns3_restore_fec(struct hns3_hw *hw);
+static int hns3_query_dev_fec_info(struct rte_eth_dev *dev);
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -2819,6 +2826,13 @@ hns3_get_capability(struct hns3_hw *hw)
 	    device_id == HNS3_DEV_ID_200G_RDMA)
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_DCB_B, 1);
 
+	ret = hns3_query_dev_fec_info(eth_dev);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			     "failed to query FEC information, ret = %d", ret);
+		return ret;
+	}
+
 	/* Get PCI revision id */
 	ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN,
 				  HNS3_PCI_REVISION_ID);
@@ -5311,6 +5325,10 @@ hns3_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_promisc;
 
+	ret = hns3_restore_fec(hw);
+	if (ret)
+		goto err_promisc;
+
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED) {
 		ret = hns3_do_start(hns, false);
 		if (ret)
@@ -5389,6 +5407,172 @@ hns3_reset_service(void *param)
 		hns3_msix_process(hns, reset_level);
 }
 
+static int
+hns3_fec_get_capability(struct rte_eth_dev *dev, uint32_t *fec_cap)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_mac *mac = &hw->mac;
+	uint32_t mode;
+
+	switch (mac->link_speed) {
+	case ETH_SPEED_NUM_10G:
+	case ETH_SPEED_NUM_40G:
+		mode = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+		       RTE_ETH_FEC_MODE_CAPA_MASK(BASER) |
+		       RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
+		break;
+	case ETH_SPEED_NUM_25G:
+	case ETH_SPEED_NUM_50G:
+		mode = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+		       RTE_ETH_FEC_MODE_CAPA_MASK(BASER) |
+		       RTE_ETH_FEC_MODE_CAPA_MASK(RS) |
+		       RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
+		break;
+	case ETH_SPEED_NUM_100G:
+	case ETH_SPEED_NUM_200G:
+		mode = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+		       RTE_ETH_FEC_MODE_CAPA_MASK(RS) |
+		       RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
+		break;
+	default:
+		mode = 0;
+		break;
+	}
+
+	*fec_cap = mode;
+	return 0;
+}
+
+static int
+hns3_fec_get(struct rte_eth_dev *dev, enum rte_eth_fec_mode *mode)
+{
+#define QUERY_ACTIVE_SPEED	1
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_sfp_speed_cmd *resp;
+	enum rte_eth_fec_mode tmp_mode;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_SFP_GET_SPEED, true);
+	resp = (struct hns3_sfp_speed_cmd *)desc.data;
+	resp->query_type = QUERY_ACTIVE_SPEED;
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret == -EOPNOTSUPP) {
+		hns3_err(hw, "IMP do not support get FEC, ret = %d", ret);
+		return ret;
+	} else if (ret) {
+		hns3_err(hw, "get FEC failed, ret = %d", ret);
+		return ret;
+	}
+
+	/*
+	 * FEC mode order defined in hns3 hardware is inconsistend with
+	 * that defined in the ethdev library. So the sequence needs
+	 * to be converted.
+	 */
+	switch (resp->active_fec) {
+	case HNS3_HW_FEC_MODE_NOFEC:
+		tmp_mode = RTE_ETH_FEC_NOFEC;
+		break;
+	case HNS3_HW_FEC_MODE_BASER:
+		tmp_mode = RTE_ETH_FEC_BASER;
+		break;
+	case HNS3_HW_FEC_MODE_RS:
+		tmp_mode = RTE_ETH_FEC_RS;
+		break;
+	default:
+		tmp_mode = RTE_ETH_FEC_NOFEC;
+		break;
+	}
+
+	*mode = tmp_mode;
+	return 0;
+}
+
+static int
+hns3_set_fec_hw(struct hns3_hw *hw, enum rte_eth_fec_mode mode)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, false);
+
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	switch (mode) {
+	case RTE_ETH_FEC_NOFEC:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_OFF);
+		break;
+	case RTE_ETH_FEC_BASER:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_BASER);
+		break;
+	case RTE_ETH_FEC_RS:
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_RS);
+		break;
+	case RTE_ETH_FEC_AUTO:
+		hns3_set_bit(req->fec_mode, HNS3_MAC_CFG_FEC_AUTO_EN_B, 1);
+		break;
+	default:
+		return 0;
+	}
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw, "set fec mode failed, ret = %d", ret);
+
+	return ret;
+}
+
+static int
+hns3_fec_set(struct rte_eth_dev *dev, enum rte_eth_fec_mode mode)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		return ret;
+
+	pf->fec_mode = mode;
+	return 0;
+}
+
+static int
+hns3_restore_fec(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+	enum rte_eth_fec_mode mode = pf->fec_mode;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		hns3_err(hw, "restore fec mode(%d) failed, ret = %d",
+			 mode, ret);
+
+	return ret;
+}
+
+static int
+hns3_query_dev_fec_info(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_fec_get(dev, &pf->fec_mode);
+	if (ret)
+		hns3_err(hw, "query device FEC info failed, ret = %d", ret);
+
+	return ret;
+}
+
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_start          = hns3_dev_start,
 	.dev_stop           = hns3_dev_stop,
@@ -5434,6 +5618,9 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.get_reg                = hns3_get_regs,
 	.get_dcb_info           = hns3_get_dcb_info,
 	.dev_supported_ptypes_get = hns3_dev_supported_ptypes_get,
+	.fec_get_capability     = hns3_fec_get_capability,
+	.fec_get                = hns3_fec_get,
+	.fec_set                = hns3_fec_set,
 };
 
 static const struct hns3_reset_ops hns3_reset_ops = {
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 0e665e5..2435668 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -510,6 +510,7 @@ struct hns3_pf {
 	struct hns3_err_msix_intr_stats abn_int_stats;
 
 	bool support_sfp_query;
+	enum rte_eth_fec_mode fec_mode; /* current FEC mode for ethdev */
 
 	struct hns3_vtag_cfg vtag_config;
 	LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V10 3/3] app/testpmd: add FEC command
  2020-09-22  7:26   ` [dpdk-dev] [PATCH V10 0/3] add FEC support Min Hu (Connor)
  2020-09-22  7:26     ` [dpdk-dev] [PATCH V10 1/3] ethdev: introduce FEC API Min Hu (Connor)
  2020-09-22  7:26     ` [dpdk-dev] [PATCH V10 2/3] net/hns3: support FEC Min Hu (Connor)
@ 2020-09-22  7:26     ` Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-22  7:26 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This commit adds testpmd capability to query and config FEC
function of device. This includes:
- show FEC capabilities, example:
	testpmd> show port 0 fec capabilities
- show FEC mode, example:
	testpmd> show port 0 fec_mode
- config FEC mode, example:
	testpmd> set port <port_id> 0 <auto|off|rs|baser>

	where:

	auto|off|rs|baser are four kinds of FEC mode which dev
	support according to MAC link speed.

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>
Acked-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
---
v8->v9:
added acked-by.

---
v6->v7:
used RTE_DIM(fec_mode_name) instead of RTE_ETH_FEC_NUM

---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Add RTE_ prefix for public FEC mode enum.

---
v3->v4:
adjust the display format of FEC mode

---
v2->v3:
adjust the display format of FEC capability.

---
 app/test-pmd/cmdline.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c  |  54 ++++++++++++
 app/test-pmd/testpmd.h |   2 +
 3 files changed, 275 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0a6ed85..3394bea 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -19054,6 +19054,222 @@ cmdline_parse_inst_t cmd_show_tx_metadata = {
 	},
 };
 
+/* *** show fec capability per port configuration *** */
+struct cmd_show_fec_capability_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_fec;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_capability_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+	struct cmd_show_fec_capability_result *res = parsed_result;
+	uint32_t fec_cap;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_fec_get_capability(res->cmd_pid, &fec_cap);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC capability failed\n");
+		return;
+	}
+
+	show_fec_capability(fec_cap);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_capability_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_capability_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_capability_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_capability_fec =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_fec, "fec");
+cmdline_parse_token_string_t cmd_show_fec_capability_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_keyword, "capabilities");
+
+cmdline_parse_inst_t cmd_show_capability = {
+	.f = cmd_show_fec_capability_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec capabilities",
+	.tokens = {
+		(void *)&cmd_show_fec_capability_show,
+		(void *)&cmd_show_fec_capability_port,
+		(void *)&cmd_show_fec_capability_pid,
+		(void *)&cmd_show_fec_capability_fec,
+		(void *)&cmd_show_fec_capability_keyword,
+		NULL,
+	},
+};
+
+/* *** show fec mode per port configuration *** */
+struct cmd_show_fec_metadata_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_mode_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_NAME_SIZE 16
+	struct cmd_show_fec_metadata_result *res = parsed_result;
+	enum rte_eth_fec_mode mode;
+	char buf[FEC_NAME_SIZE];
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+	ret = rte_eth_fec_get(res->cmd_pid, &mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC mode failed\n");
+		return;
+	}
+
+	switch (mode) {
+	case RTE_ETH_FEC_NOFEC:
+		strlcpy(buf, "off", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_AUTO:
+		strlcpy(buf, "auto", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_BASER:
+		strlcpy(buf, "baser", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_RS:
+		strlcpy(buf, "rs", sizeof(buf));
+		break;
+	default:
+		return;
+	}
+
+	printf("%s\n", buf);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_mode_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_mode_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_mode_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_mode_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_keyword, "fec_mode");
+
+cmdline_parse_inst_t cmd_show_fec_mode = {
+	.f = cmd_show_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec_mode",
+	.tokens = {
+		(void *)&cmd_show_fec_mode_show,
+		(void *)&cmd_show_fec_mode_port,
+		(void *)&cmd_show_fec_mode_pid,
+		(void *)&cmd_show_fec_mode_keyword,
+		NULL,
+	},
+};
+
+/* *** set fec mode per port configuration *** */
+struct cmd_set_port_fec_mode {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t fec_mode;
+	cmdline_fixed_string_t fec_value;
+};
+
+/* Common CLI fields for set fec mode */
+cmdline_parse_token_string_t cmd_set_port_fec_mode_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port, "port");
+cmdline_parse_token_num_t cmd_set_port_fec_mode_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_port_fec_mode_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_mode, "fec_mode");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_value =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_value, NULL);
+
+static void
+cmd_set_port_fec_mode_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	__rte_unused void *data)
+{
+	struct cmd_set_port_fec_mode *res = parsed_result;
+	uint16_t port_id = res->port_id;
+	enum rte_eth_fec_mode mode;
+	int ret;
+
+	ret = parse_fec_mode(res->fec_value, &mode);
+	if (ret < 0) {
+		printf("Unknown fec mode: %s for Port %d\n", res->fec_value,
+			port_id);
+		return;
+	}
+
+	ret = rte_eth_fec_set(port_id, mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Set FEC mode failed\n");
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_fec_mode = {
+	.f = cmd_set_port_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> fec_mode <auto|off|rs|baser>",
+	.tokens = {
+		(void *)&cmd_set_port_fec_mode_set,
+		(void *)&cmd_set_port_fec_mode_port,
+		(void *)&cmd_set_port_fec_mode_port_id,
+		(void *)&cmd_set_port_fec_mode_str,
+		(void *)&cmd_set_port_fec_mode_value,
+		NULL,
+	},
+};
+
 /* show port supported ptypes */
 
 /* Common result structure for show port ptypes */
@@ -19685,6 +19901,9 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_set_raw,
 	(cmdline_parse_inst_t *)&cmd_show_set_raw_all,
 	(cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
+	(cmdline_parse_inst_t *)&cmd_show_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_set_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_show_capability,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 30bee33..ba752ea 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -138,6 +138,28 @@ const struct rss_type_info rss_type_table[] = {
 	{ NULL, 0 },
 };
 
+static const struct {
+	enum rte_eth_fec_mode mode;
+	const char *name;
+} fec_mode_name[] = {
+	{
+		.mode = RTE_ETH_FEC_NOFEC,
+		.name = "off",
+	},
+	{
+		.mode = RTE_ETH_FEC_AUTO,
+		.name = "auto",
+	},
+	{
+		.mode = RTE_ETH_FEC_BASER,
+		.name = "baser",
+	},
+	{
+		.mode = RTE_ETH_FEC_RS,
+		.name = "rs",
+	},
+};
+
 static void
 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
 {
@@ -2967,6 +2989,38 @@ set_tx_pkt_split(const char *name)
 	printf("unknown value: \"%s\"\n", name);
 }
 
+int
+parse_fec_mode(const char *name, enum rte_eth_fec_mode *mode)
+{
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(fec_mode_name); i++) {
+		if (strcmp(fec_mode_name[i].name, name) == 0) {
+			*mode = fec_mode_name[i].mode;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void
+show_fec_capability(uint32_t fec_cap)
+{
+	uint32_t i;
+
+	if (fec_cap == 0) {
+		printf("FEC is not supported\n");
+		return;
+	}
+
+	printf("FEC capabilities: ");
+	for (i = RTE_ETH_FEC_AUTO; i < RTE_DIM(fec_mode_name); i++) {
+		if (fec_cap & RTE_ETH_FEC_MODE_TO_CAPA(i))
+			printf("%s ", fec_mode_name[i].name);
+	}
+	printf("\n");
+}
+
 void
 show_tx_pkt_segments(void)
 {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 25a12b1..3be56e8 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -778,6 +778,8 @@ void show_tx_pkt_segments(void);
 void set_tx_pkt_times(unsigned int *tx_times);
 void show_tx_pkt_times(void);
 void set_tx_pkt_split(const char *name);
+int parse_fec_mode(const char *name, enum rte_eth_fec_mode *mode);
+void show_fec_capability(uint32_t fec_cap);
 void set_nb_pkt_per_burst(uint16_t pkt_burst);
 char *list_pkt_forwarding_modes(void);
 char *list_pkt_forwarding_retry_modes(void);
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V9 1/3] ethdev: introduce FEC API
  2020-09-22  4:58         ` Min Hu (Connor)
@ 2020-09-22  8:02           ` Andrew Rybchenko
  2020-09-22 11:06             ` Min Hu (Connor)
  0 siblings, 1 reply; 118+ messages in thread
From: Andrew Rybchenko @ 2020-09-22  8:02 UTC (permalink / raw)
  To: Min Hu (Connor), dev; +Cc: konstantin.ananyev, thomas, ferruh.yigit, linuxarm

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]
>>
>> .
>>


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V9 1/3] ethdev: introduce FEC API
  2020-09-22  8:02           ` Andrew Rybchenko
@ 2020-09-22 11:06             ` Min Hu (Connor)
  2020-09-22 12:18               ` Andrew Rybchenko
  0 siblings, 1 reply; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-22 11:06 UTC (permalink / raw)
  To: Andrew Rybchenko, dev; +Cc: konstantin.ananyev, thomas, ferruh.yigit, linuxarm



在 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]
>>>
>>> .
>>>
> 
> .
> 

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V9 1/3] ethdev: introduce FEC API
  2020-09-22 11:06             ` Min Hu (Connor)
@ 2020-09-22 12:18               ` Andrew Rybchenko
  2020-09-24 11:07                 ` Min Hu (Connor)
  0 siblings, 1 reply; 118+ messages in thread
From: Andrew Rybchenko @ 2020-09-22 12:18 UTC (permalink / raw)
  To: Min Hu (Connor), dev; +Cc: konstantin.ananyev, thomas, ferruh.yigit, linuxarm

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]
>>>>
>>>> .
>>>>
>>
>> .
>>


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V11 0/4] add FEC support
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
                     ` (10 preceding siblings ...)
  2020-09-22  7:26   ` [dpdk-dev] [PATCH V10 0/3] add FEC support Min Hu (Connor)
@ 2020-09-24 11:01   ` Min Hu (Connor)
  2020-09-24 11:01     ` [dpdk-dev] [PATCH V11 1/4] ethdev: introduce FEC API Min Hu (Connor)
                       ` (3 more replies)
  2020-09-24 13:05   ` [dpdk-dev] [PATCH V12 0/4] add FEC support Min Hu (Connor)
                     ` (4 subsequent siblings)
  16 siblings, 4 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-24 11:01 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This series add FEC support for ethdev.

Min Hu (Connor) (4):
  ethdev: introduce FEC API
  net/hns3: support FEC
  app/testpmd: add FEC command
  doc: add FEC API and PMD information

 app/test-pmd/cmdline.c                   | 221 +++++++++++++++++++
 app/test-pmd/config.c                    |  91 ++++++++
 app/test-pmd/testpmd.h                   |   2 +
 doc/guides/rel_notes/release_20_11.rst   |   9 +
 drivers/net/hns3/hns3_cmd.h              |  19 +-
 drivers/net/hns3/hns3_ethdev.c           | 357 +++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h           |   1 +
 lib/librte_ethdev/rte_ethdev.c           |  37 ++++
 lib/librte_ethdev/rte_ethdev.h           |  91 ++++++++
 lib/librte_ethdev/rte_ethdev_driver.h    |  82 +++++++
 lib/librte_ethdev/rte_ethdev_version.map |   3 +
 11 files changed, 912 insertions(+), 1 deletion(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V11 1/4] ethdev: introduce FEC API
  2020-09-24 11:01   ` [dpdk-dev] [PATCH V11 0/4] add FEC support Min Hu (Connor)
@ 2020-09-24 11:01     ` Min Hu (Connor)
  2020-09-24 11:01     ` [dpdk-dev] [PATCH V11 2/4] net/hns3: support FEC Min Hu (Connor)
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-24 11:01 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

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>
---
v10->v11:
allow to report capabilities per link speed.
specify what should be reported if link is down
when get FEC.
change mode to capa bitmask.

---
v9->v10:
add macro RTE_ETH_FEC_MODE_CAPA_MASK(x) to indicate
different FEC mode capa.

---
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.

---
 lib/librte_ethdev/rte_ethdev.c           | 37 +++++++++++++
 lib/librte_ethdev/rte_ethdev.h           | 91 ++++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_driver.h    | 82 ++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |  3 ++
 4 files changed, 213 insertions(+)

diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index dfe5c1b..b614bfc 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -3679,6 +3679,43 @@ 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 *num,
+			   struct rte_eth_fec_capa *speed_fec_capa)
+{
+	struct rte_eth_dev *dev;
+
+	if (num == NULL || speed_fec_capa == NULL)
+		return -EINVAL;
+
+	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, num,
+							speed_fec_capa));
+}
+
+int
+rte_eth_fec_get(uint16_t port_id, uint32_t *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, uint32_t mode)
+{
+	struct rte_eth_dev *dev;
+
+	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 645a186..104181d 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1544,6 +1544,29 @@ 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 */
+};
+
+/* Translate from FEC mode to FEC capa */
+#define RTE_ETH_FEC_MODE_TO_CAPA(x)	(1U << (x))
+
+/* This macro indicates FEC capa mask*/
+#define RTE_ETH_FEC_MODE_CAPA_MASK(x)	(1U << (RTE_ETH_FEC_ ## x))
+
+/* A structure used to get capabilities per link speed */
+struct rte_eth_fec_capa {
+	uint32_t speed; /**< Link speed (see ETH_SPEED_NUM_*) */
+	uint32_t capa;  /**< FEC capabilities bitmask (see RTE_FEC_CAPA_*) */
+};
+
 #define RTE_ETH_ALL RTE_MAX_ETHPORTS
 
 /* Macros to check for valid port */
@@ -3397,6 +3420,74 @@ 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 num
+ *   the num is in/out with a number of elements in an array.
+ * @param speed_fec_capa
+ *   speed_fec_capa is out only with per-speed capabilities.
+ *
+ * @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.
+ *   - (-EINVAL)  if *num* or *speed_fec_capa* invalid
+ */
+__rte_experimental
+int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *num,
+			struct rte_eth_fec_capa *speed_fec_capa);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get current Forward Error Correction(FEC) mode.
+ * 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.
+ *
+ * @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, uint32_t *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, uint32_t mode);
+
+/**
  * Get current status of the Ethernet link flow control for Ethernet device
  *
  * @param port_id
diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
index 23cc1e0..625b8c5 100644
--- a/lib/librte_ethdev/rte_ethdev_driver.h
+++ b/lib/librte_ethdev/rte_ethdev_driver.h
@@ -575,6 +575,81 @@ 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 num
+ *   the num is in/out with a number of elements in an array.
+ * @param speed_fec_capa
+ *   speed_fec_capa is out only with per-speed capabilities.
+ *
+ * @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.
+ * @retval -EINVAL
+ *   *num* or *speed_fec_capa* invalid.
+ */
+typedef int (*eth_fec_get_capability_t)(struct rte_eth_dev *dev, uint32_t *num,
+				struct rte_eth_fec_capa *speed_fec_capa);
+
+/**
+ * @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,
+			     uint32_t *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, uint32_t mode);
+
+/**
  * @internal A structure containing the functions exported by an Ethernet driver.
  */
 struct eth_dev_ops {
@@ -713,6 +788,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 c95ef51..b9ace3a 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -229,6 +229,9 @@ EXPERIMENTAL {
 	# added in 20.11
 	rte_eth_link_speed_to_str;
 	rte_eth_link_to_str;
+	rte_eth_fec_get_capability;
+	rte_eth_fec_get;
+	rte_eth_fec_set;
 };
 
 INTERNAL {
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V11 2/4] net/hns3: support FEC
  2020-09-24 11:01   ` [dpdk-dev] [PATCH V11 0/4] add FEC support Min Hu (Connor)
  2020-09-24 11:01     ` [dpdk-dev] [PATCH V11 1/4] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-24 11:01     ` Min Hu (Connor)
  2020-09-24 11:01     ` [dpdk-dev] [PATCH V11 3/4] app/testpmd: add FEC command Min Hu (Connor)
  2020-09-24 11:01     ` [dpdk-dev] [PATCH V11 4/4] doc: add FEC API and PMD information Min Hu (Connor)
  3 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-24 11:01 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

Forward error correction (FEC) is a bit error correction mode.
It adds error correction information to data packets at the
transmit end, and uses the error correction information to correct
the bit errors generated during data packet transmission at the
receive end. This improves signal quality but also brings a delay
to signals. This function can be enabled or disabled as required.

This patch adds FEC support for ethdev.Introduce ethdev
operations 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>
---
v10->v11:
allow to report capabilities per link speed.
specify what should be reported if link is down
when get FEC.
change mode to capa bitmask.

---
v9->v10:
use RTE_ETH_FEC_MODE_CAPA_MASK(x) which is just defined.

---
v7->v8:
FEC mode order defined in hns3 hardware is inconsistend with
that defined in the ethdev library. So the sequence needs
to be converted.

---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Data type for fec_cap is changed from uint8_t
to uint32_t for possible future expansion.

---
v2->v3:
adjust the return value of function.

---
 drivers/net/hns3/hns3_cmd.h    |  19 ++-
 drivers/net/hns3/hns3_ethdev.c | 357 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h |   1 +
 3 files changed, 376 insertions(+), 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index 87d6053..a1e9604 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -100,6 +100,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_QUERY_LINK_STATUS      = 0x0307,
 	HNS3_OPC_CONFIG_MAX_FRM_SIZE    = 0x0308,
 	HNS3_OPC_CONFIG_SPEED_DUP       = 0x0309,
+	HNS3_OPC_CONFIG_FEC_MODE        = 0x031A,
 
 	/* PFC/Pause commands */
 	HNS3_OPC_CFG_MAC_PAUSE_EN       = 0x0701,
@@ -684,9 +685,25 @@ struct hns3_config_auto_neg_cmd {
 	uint8_t   rsv[20];
 };
 
+#define HNS3_MAC_CFG_FEC_AUTO_EN_B	0
+#define HNS3_MAC_CFG_FEC_MODE_S		1
+#define HNS3_MAC_CFG_FEC_MODE_M	GENMASK(3, 1)
+#define HNS3_MAC_FEC_OFF		0
+#define HNS3_MAC_FEC_BASER		1
+#define HNS3_MAC_FEC_RS			2
+
 struct hns3_sfp_speed_cmd {
 	uint32_t  sfp_speed;
-	uint32_t  rsv[5];
+	uint8_t   query_type; /* 0: sfp speed, 1: active fec */
+	uint8_t   active_fec; /* current FEC mode */
+	uint16_t  rsv1;
+	uint32_t  rsv2[4];
+};
+
+/* Configure FEC mode, opcode:0x031A */
+struct hns3_config_fec_cmd {
+	uint8_t fec_mode;
+	uint8_t rsv[23];
 };
 
 #define HNS3_MAC_MGR_MASK_VLAN_B		BIT(0)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 73d5042..f06b5b1 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -63,6 +63,11 @@
 #define HNS3_RESET_WAIT_MS	100
 #define HNS3_RESET_WAIT_CNT	200
 
+/* FEC mode order defined in HNS3 hardware */
+#define HNS3_HW_FEC_MODE_NOFEC  0
+#define HNS3_HW_FEC_MODE_BASER  1
+#define HNS3_HW_FEC_MODE_RS     2
+
 enum hns3_evt_cause {
 	HNS3_VECTOR0_EVENT_RST,
 	HNS3_VECTOR0_EVENT_MBX,
@@ -70,6 +75,34 @@ enum hns3_evt_cause {
 	HNS3_VECTOR0_EVENT_OTHER,
 };
 
+static const struct rte_eth_fec_capa speed_fec_capa_tbl[] = {
+	{ ETH_SPEED_NUM_10G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(BASER) },
+
+	{ ETH_SPEED_NUM_25G, 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) },
+
+	{ ETH_SPEED_NUM_40G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(BASER) },
+
+	{ ETH_SPEED_NUM_50G, 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) },
+
+	{ ETH_SPEED_NUM_100G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(RS) },
+
+	{ ETH_SPEED_NUM_200G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(RS) }
+};
+
 static enum hns3_reset_level hns3_get_reset_level(struct hns3_adapter *hns,
 						 uint64_t *levels);
 static int hns3_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
@@ -81,6 +114,8 @@ static int hns3_add_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
 static int hns3_remove_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
+static int hns3_restore_fec(struct hns3_hw *hw);
+static int hns3_query_dev_fec_info(struct rte_eth_dev *dev);
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -2889,6 +2924,13 @@ hns3_get_capability(struct hns3_hw *hw)
 	    device_id == HNS3_DEV_ID_200G_RDMA)
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_DCB_B, 1);
 
+	ret = hns3_query_dev_fec_info(eth_dev);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			     "failed to query FEC information, ret = %d", ret);
+		return ret;
+	}
+
 	/* Get PCI revision id */
 	ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN,
 				  HNS3_PCI_REVISION_ID);
@@ -5446,6 +5488,10 @@ hns3_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_promisc;
 
+	ret = hns3_restore_fec(hw);
+	if (ret)
+		goto err_promisc;
+
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED) {
 		ret = hns3_do_start(hns, false);
 		if (ret)
@@ -5524,6 +5570,314 @@ hns3_reset_service(void *param)
 		hns3_msix_process(hns, reset_level);
 }
 
+static int
+hns3_get_speed_capa_num(uint16_t device_id)
+{
+	uint32_t num;
+
+	switch (device_id) {
+	case HNS3_DEV_ID_25GE:
+	case HNS3_DEV_ID_25GE_RDMA:
+		num = 2;
+		break;
+	case HNS3_DEV_ID_100G_RDMA_MACSEC:
+	case HNS3_DEV_ID_200G_RDMA:
+		num = 1;
+		break;
+	default:
+		num = 0;
+		break;
+	}
+
+	return num;
+}
+
+static int
+hns3_get_speed_fec_capa(struct rte_eth_fec_capa *speed_fec_capa,
+			uint16_t device_id)
+{
+	switch (device_id) {
+	case HNS3_DEV_ID_25GE:
+	/* falls through - to 25GE_RDMA */
+	case HNS3_DEV_ID_25GE_RDMA:
+		speed_fec_capa[0].speed = speed_fec_capa_tbl[1].speed;
+		speed_fec_capa[0].capa = speed_fec_capa_tbl[1].capa;
+
+		/* In HNS3 device, the 25G NIC is compatible with 10G rate */
+		speed_fec_capa[1].speed = speed_fec_capa_tbl[0].speed;
+		speed_fec_capa[1].capa = speed_fec_capa_tbl[0].capa;
+		break;
+	case HNS3_DEV_ID_100G_RDMA_MACSEC:
+		speed_fec_capa[0].speed = speed_fec_capa_tbl[4].speed;
+		speed_fec_capa[0].capa = speed_fec_capa_tbl[4].capa;
+		break;
+	case HNS3_DEV_ID_200G_RDMA:
+		speed_fec_capa[0].speed = speed_fec_capa_tbl[5].speed;
+		speed_fec_capa[0].capa = speed_fec_capa_tbl[5].capa;
+		break;
+	default:
+		return -ENOTSUP;
+	}
+
+	return 0;
+}
+
+static int
+hns3_fec_get_capability(struct rte_eth_dev *dev, uint32_t *num,
+			struct rte_eth_fec_capa *speed_fec_capa)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	uint16_t device_id = pci_dev->id.device_id;
+	uint32_t capa_num;
+	int ret;
+
+	capa_num = hns3_get_speed_capa_num(device_id);
+	if (capa_num == 0) {
+		hns3_err(hw, "device(0x%x) is not supported by hns3 PMD",
+			 device_id);
+		return -ENOTSUP;
+	} else if (*num < capa_num) {
+		hns3_err(hw, "insufficient num, num should be no less than %u",
+			 capa_num);
+		return -EINVAL;
+	}
+
+	ret = hns3_get_speed_fec_capa(speed_fec_capa, device_id);
+	if (ret)
+		return -ENOTSUP;
+
+	*num = capa_num;
+	return 0;
+}
+
+static int
+get_current_fec_auto_state(struct hns3_hw *hw, uint8_t *state)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, true);
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret) {
+		hns3_err(hw, "get current fec auto state failed, ret = %d",
+			 ret);
+		return ret;
+	}
+
+	*state = req->fec_mode & (1U << HNS3_MAC_CFG_FEC_AUTO_EN_B);
+	return 0;
+}
+
+static int
+hns3_fec_get(struct rte_eth_dev *dev, uint32_t *mode)
+{
+#define QUERY_ACTIVE_SPEED	1
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_sfp_speed_cmd *resp;
+	uint32_t tmp_mode;
+	uint8_t auto_state;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	/*
+	 * 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.
+	 */
+	if (hw->mac.link_status == ETH_LINK_DOWN) {
+		ret = get_current_fec_auto_state(hw, &auto_state);
+		if (ret)
+			return ret;
+
+		if (auto_state == 0x1) {
+			*mode = RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
+			return 0;
+		}
+	}
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_SFP_GET_SPEED, true);
+	resp = (struct hns3_sfp_speed_cmd *)desc.data;
+	resp->query_type = QUERY_ACTIVE_SPEED;
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret == -EOPNOTSUPP) {
+		hns3_err(hw, "IMP do not support get FEC, ret = %d", ret);
+		return ret;
+	} else if (ret) {
+		hns3_err(hw, "get FEC failed, ret = %d", ret);
+		return ret;
+	}
+
+	/*
+	 * FEC mode order defined in hns3 hardware is inconsistend with
+	 * that defined in the ethdev library. So the sequence needs
+	 * to be converted.
+	 */
+	switch (resp->active_fec) {
+	case HNS3_HW_FEC_MODE_NOFEC:
+		tmp_mode = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
+		break;
+	case HNS3_HW_FEC_MODE_BASER:
+		tmp_mode = RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
+		break;
+	case HNS3_HW_FEC_MODE_RS:
+		tmp_mode = RTE_ETH_FEC_MODE_CAPA_MASK(RS);
+		break;
+	default:
+		tmp_mode = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
+		break;
+	}
+
+	*mode = tmp_mode;
+	return 0;
+}
+
+static int
+hns3_set_fec_hw(struct hns3_hw *hw, uint32_t mode)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, false);
+
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	switch (mode) {
+	case RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC):
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_OFF);
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(BASER):
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_BASER);
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(RS):
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_RS);
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(AUTO):
+		hns3_set_bit(req->fec_mode, HNS3_MAC_CFG_FEC_AUTO_EN_B, 1);
+		break;
+	default:
+		return 0;
+	}
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw, "set fec mode failed, ret = %d", ret);
+
+	return ret;
+}
+
+static uint32_t
+get_current_speed_fec_cap(struct hns3_hw *hw, struct rte_eth_fec_capa *fec_capa)
+{
+	struct hns3_mac *mac = &hw->mac;
+	uint32_t cur_capa;
+
+	switch (mac->link_speed) {
+	case ETH_SPEED_NUM_10G:
+		cur_capa = fec_capa[1].capa;
+		break;
+	case ETH_SPEED_NUM_25G:
+	case ETH_SPEED_NUM_100G:
+	case ETH_SPEED_NUM_200G:
+		cur_capa = fec_capa[0].capa;
+		break;
+	default:
+		cur_capa = 0;
+		break;
+	}
+
+	return cur_capa;
+}
+
+static bool
+is_fec_mode_one_bit_set(uint32_t mode)
+{
+	int cnt = 0;
+	uint8_t i;
+
+	for (i = 0; i < sizeof(mode); i++)
+		if (mode >> i & 0x1)
+			cnt++;
+
+	return cnt == 1 ? true : false;
+}
+
+static int
+hns3_fec_set(struct rte_eth_dev *dev, uint32_t mode)
+{
+#define FEC_CAPA_NUM 2
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+
+	struct rte_eth_fec_capa fec_capa[FEC_CAPA_NUM];
+	uint32_t cur_capa;
+	uint32_t num = FEC_CAPA_NUM;
+	int ret;
+
+	ret = hns3_fec_get_capability(dev, &num, fec_capa);
+	if (ret != 0)
+		return ret;
+
+	/* HNS3 PMD driver only support one bit set mode, e.g. 0x1, 0x4 */
+	if (!is_fec_mode_one_bit_set(mode))
+		hns3_err(hw, "FEC mode(0x%x) not supported in HNS3 PMD,"
+			     "FEC mode should be only one bit set", mode);
+
+	/*
+	 * Check whether the configured mode is within the FEC capability.
+	 * If not, the configured mode will not be supported.
+	 */
+	cur_capa = get_current_speed_fec_cap(hw, fec_capa);
+	if (!(cur_capa & mode)) {
+		hns3_err(hw, "unsupported FEC mode = 0x%x", mode);
+		return -EINVAL;
+	}
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		return ret;
+
+	pf->fec_mode = mode;
+	return 0;
+}
+
+static int
+hns3_restore_fec(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+	uint32_t mode = pf->fec_mode;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		hns3_err(hw, "restore fec mode(0x%x) failed, ret = %d",
+			 mode, ret);
+
+	return ret;
+}
+
+static int
+hns3_query_dev_fec_info(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_fec_get(dev, &pf->fec_mode);
+	if (ret)
+		hns3_err(hw, "query device FEC info failed, ret = %d", ret);
+
+	return ret;
+}
+
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_configure      = hns3_dev_configure,
 	.dev_start          = hns3_dev_start,
@@ -5573,6 +5927,9 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.get_reg                = hns3_get_regs,
 	.get_dcb_info           = hns3_get_dcb_info,
 	.dev_supported_ptypes_get = hns3_dev_supported_ptypes_get,
+	.fec_get_capability     = hns3_fec_get_capability,
+	.fec_get                = hns3_fec_get,
+	.fec_set                = hns3_fec_set,
 };
 
 static const struct hns3_reset_ops hns3_reset_ops = {
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index fd6a9f9..393b91f 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -620,6 +620,7 @@ struct hns3_pf {
 	struct hns3_err_msix_intr_stats abn_int_stats;
 
 	bool support_sfp_query;
+	uint32_t fec_mode; /* current FEC mode for ethdev */
 
 	struct hns3_vtag_cfg vtag_config;
 	LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V11 3/4] app/testpmd: add FEC command
  2020-09-24 11:01   ` [dpdk-dev] [PATCH V11 0/4] add FEC support Min Hu (Connor)
  2020-09-24 11:01     ` [dpdk-dev] [PATCH V11 1/4] ethdev: introduce FEC API Min Hu (Connor)
  2020-09-24 11:01     ` [dpdk-dev] [PATCH V11 2/4] net/hns3: support FEC Min Hu (Connor)
@ 2020-09-24 11:01     ` Min Hu (Connor)
  2020-09-24 11:01     ` [dpdk-dev] [PATCH V11 4/4] doc: add FEC API and PMD information Min Hu (Connor)
  3 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-24 11:01 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This commit adds testpmd capability to query and config FEC
function of device. This includes:
- show FEC capabilities, example:
	testpmd> show port 0 fec capabilities
- show FEC mode, example:
	testpmd> show port 0 fec_mode
- config FEC mode, example:
	testpmd> set port <port_id> 0 <auto|off|rs|baser>

	where:

	auto|off|rs|baser are four kinds of FEC mode which dev
	support according to MAC link speed.

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>
Acked-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
---
v10->v11:
change mode to capa bitmask.

---
v8->v9:
added acked-by.

---
v6->v7:
used RTE_DIM(fec_mode_name) instead of RTE_ETH_FEC_NUM

---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Add RTE_ prefix for public FEC mode enum.

---
v3->v4:
adjust the display format of FEC mode

---
v2->v3:
adjust the display format of FEC capability.

---
 app/test-pmd/cmdline.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c  |  91 ++++++++++++++++++++
 app/test-pmd/testpmd.h |   2 +
 3 files changed, 314 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 5f93409..445726f 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -19161,6 +19161,224 @@ cmdline_parse_inst_t cmd_show_tx_metadata = {
 	},
 };
 
+/* *** show fec capability per port configuration *** */
+struct cmd_show_fec_capability_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_fec;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_capability_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_CAP_NUM 2
+	struct cmd_show_fec_capability_result *res = parsed_result;
+	struct rte_eth_fec_capa speed_fec_capa[FEC_CAP_NUM];
+	uint32_t num = FEC_CAP_NUM;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_fec_get_capability(res->cmd_pid, &num, speed_fec_capa);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC capability failed\n");
+		return;
+	}
+
+	show_fec_capability(num, speed_fec_capa);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_capability_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_capability_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_capability_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_capability_fec =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_fec, "fec");
+cmdline_parse_token_string_t cmd_show_fec_capability_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_keyword, "capabilities");
+
+cmdline_parse_inst_t cmd_show_capability = {
+	.f = cmd_show_fec_capability_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec capabilities",
+	.tokens = {
+		(void *)&cmd_show_fec_capability_show,
+		(void *)&cmd_show_fec_capability_port,
+		(void *)&cmd_show_fec_capability_pid,
+		(void *)&cmd_show_fec_capability_fec,
+		(void *)&cmd_show_fec_capability_keyword,
+		NULL,
+	},
+};
+
+/* *** show fec mode per port configuration *** */
+struct cmd_show_fec_metadata_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_mode_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_NAME_SIZE 16
+	struct cmd_show_fec_metadata_result *res = parsed_result;
+	uint32_t mode;
+	char buf[FEC_NAME_SIZE];
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+	ret = rte_eth_fec_get(res->cmd_pid, &mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC mode failed\n");
+		return;
+	}
+
+	switch (mode) {
+	case RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC):
+		strlcpy(buf, "off", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(AUTO):
+		strlcpy(buf, "auto", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(BASER):
+		strlcpy(buf, "baser", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(RS):
+		strlcpy(buf, "rs", sizeof(buf));
+		break;
+	default:
+		return;
+	}
+
+	printf("%s\n", buf);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_mode_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_mode_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_mode_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_mode_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_keyword, "fec_mode");
+
+cmdline_parse_inst_t cmd_show_fec_mode = {
+	.f = cmd_show_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec_mode",
+	.tokens = {
+		(void *)&cmd_show_fec_mode_show,
+		(void *)&cmd_show_fec_mode_port,
+		(void *)&cmd_show_fec_mode_pid,
+		(void *)&cmd_show_fec_mode_keyword,
+		NULL,
+	},
+};
+
+/* *** set fec mode per port configuration *** */
+struct cmd_set_port_fec_mode {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t fec_mode;
+	cmdline_fixed_string_t fec_value;
+};
+
+/* Common CLI fields for set fec mode */
+cmdline_parse_token_string_t cmd_set_port_fec_mode_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port, "port");
+cmdline_parse_token_num_t cmd_set_port_fec_mode_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_port_fec_mode_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_mode, "fec_mode");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_value =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_value, NULL);
+
+static void
+cmd_set_port_fec_mode_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	__rte_unused void *data)
+{
+	struct cmd_set_port_fec_mode *res = parsed_result;
+	uint16_t port_id = res->port_id;
+	uint32_t mode;
+	int ret;
+
+	ret = parse_fec_mode(res->fec_value, &mode);
+	if (ret < 0) {
+		printf("Unknown fec mode: %s for Port %d\n", res->fec_value,
+			port_id);
+		return;
+	}
+
+	ret = rte_eth_fec_set(port_id, mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Set FEC mode failed\n");
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_fec_mode = {
+	.f = cmd_set_port_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> fec_mode <auto|off|rs|baser>",
+	.tokens = {
+		(void *)&cmd_set_port_fec_mode_set,
+		(void *)&cmd_set_port_fec_mode_port,
+		(void *)&cmd_set_port_fec_mode_port_id,
+		(void *)&cmd_set_port_fec_mode_str,
+		(void *)&cmd_set_port_fec_mode_value,
+		NULL,
+	},
+};
+
 /* show port supported ptypes */
 
 /* Common result structure for show port ptypes */
@@ -19795,6 +20013,9 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_set_raw,
 	(cmdline_parse_inst_t *)&cmd_show_set_raw_all,
 	(cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
+	(cmdline_parse_inst_t *)&cmd_show_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_set_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_show_capability,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 2d9a456..a6269c1 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -138,6 +138,58 @@ const struct rss_type_info rss_type_table[] = {
 	{ NULL, 0 },
 };
 
+static const struct {
+	enum rte_eth_fec_mode mode;
+	const char *name;
+} fec_mode_name[] = {
+	{
+		.mode = RTE_ETH_FEC_NOFEC,
+		.name = "off",
+	},
+	{
+		.mode = RTE_ETH_FEC_AUTO,
+		.name = "auto",
+	},
+	{
+		.mode = RTE_ETH_FEC_BASER,
+		.name = "baser",
+	},
+	{
+		.mode = RTE_ETH_FEC_RS,
+		.name = "rs",
+	},
+};
+
+static const struct {
+	uint32_t speed;
+	const char *name;
+} eth_speed_name[] = {
+	{
+		.speed = ETH_SPEED_NUM_10G,
+		.name = "Speed 10G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_25G,
+		.name = "Speed 25G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_40G,
+		.name = "Speed 40G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_50G,
+		.name = "Speed 50G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_100G,
+		.name = "Speed 100G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_200G,
+		.name = "Speed 200G",
+	},
+};
+
 static void
 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
 {
@@ -2969,6 +3021,45 @@ set_tx_pkt_split(const char *name)
 	printf("unknown value: \"%s\"\n", name);
 }
 
+int
+parse_fec_mode(const char *name, uint32_t *mode)
+{
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(fec_mode_name); i++) {
+		if (strcmp(fec_mode_name[i].name, name) == 0) {
+			*mode = RTE_ETH_FEC_MODE_TO_CAPA(fec_mode_name[i].mode);
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void
+show_fec_capability(uint32_t num, struct rte_eth_fec_capa *speed_fec_capa)
+{
+	uint32_t i, j, k;
+
+	printf("FEC capabilities:\n");
+
+	for (i = 0; i < num; i++) {
+		for (j = 0; j < RTE_DIM(eth_speed_name); j++) {
+			if (eth_speed_name[j].speed ==
+						speed_fec_capa[i].speed) {
+				printf("%s : ", eth_speed_name[j].name);
+				break;
+			}
+		}
+
+		for (k = RTE_ETH_FEC_AUTO; k < RTE_DIM(fec_mode_name); k++) {
+			if (RTE_ETH_FEC_MODE_TO_CAPA(k) &
+						speed_fec_capa[i].capa)
+				printf("%s ", fec_mode_name[k].name);
+		}
+		printf("\n");
+	}
+}
+
 void
 show_tx_pkt_segments(void)
 {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index f139fe7..85ea030 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -804,6 +804,8 @@ void show_tx_pkt_segments(void);
 void set_tx_pkt_times(unsigned int *tx_times);
 void show_tx_pkt_times(void);
 void set_tx_pkt_split(const char *name);
+int parse_fec_mode(const char *name, enum rte_eth_fec_mode *mode);
+void show_fec_capability(uint32_t num, struct rte_eth_fec_capa *speed_fec_capa);
 void set_nb_pkt_per_burst(uint16_t pkt_burst);
 char *list_pkt_forwarding_modes(void);
 char *list_pkt_forwarding_retry_modes(void);
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V11 4/4] doc: add FEC API and PMD information
  2020-09-24 11:01   ` [dpdk-dev] [PATCH V11 0/4] add FEC support Min Hu (Connor)
                       ` (2 preceding siblings ...)
  2020-09-24 11:01     ` [dpdk-dev] [PATCH V11 3/4] app/testpmd: add FEC command Min Hu (Connor)
@ 2020-09-24 11:01     ` Min Hu (Connor)
  3 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-24 11:01 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

Added the FEC API, and hns3 FEC PMD information in
release 20.11.rst file.

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>
---
 doc/guides/rel_notes/release_20_11.rst | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index c6642f5..de2c8e4 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -78,6 +78,15 @@ New Features
     ``--portmask=N``
     where N represents the hexadecimal bitmask of ports used.
 
+* **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
 -------------
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V9 1/3] ethdev: introduce FEC API
  2020-09-22 12:18               ` Andrew Rybchenko
@ 2020-09-24 11:07                 ` Min Hu (Connor)
  0 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-24 11:07 UTC (permalink / raw)
  To: Andrew Rybchenko, dev; +Cc: konstantin.ananyev, thomas, ferruh.yigit, linuxarm

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]
>>>>>
>>>>> .
>>>>>
>>>
>>> .
>>>
> 
> .
> 

^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V12 0/4] add FEC support
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
                     ` (11 preceding siblings ...)
  2020-09-24 11:01   ` [dpdk-dev] [PATCH V11 0/4] add FEC support Min Hu (Connor)
@ 2020-09-24 13:05   ` Min Hu (Connor)
  2020-09-24 13:05     ` [dpdk-dev] [PATCH V12 1/4] ethdev: introduce FEC API Min Hu (Connor)
                       ` (3 more replies)
  2020-09-25  8:39   ` [dpdk-dev] [PATCH V13 0/3] add FEC support Min Hu (Connor)
                     ` (3 subsequent siblings)
  16 siblings, 4 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-24 13:05 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This series add FEC support for ethdev.

Min Hu (Connor) (4):
  ethdev: introduce FEC API
  net/hns3: support FEC
  app/testpmd: add FEC command
  doc: add FEC API and PMD information

 app/test-pmd/cmdline.c                   | 221 +++++++++++++++++++
 app/test-pmd/config.c                    |  91 ++++++++
 app/test-pmd/testpmd.h                   |   2 +
 doc/guides/rel_notes/release_20_11.rst   |   9 +
 drivers/net/hns3/hns3_cmd.h              |  19 +-
 drivers/net/hns3/hns3_ethdev.c           | 357 +++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h           |   1 +
 lib/librte_ethdev/rte_ethdev.c           |  37 ++++
 lib/librte_ethdev/rte_ethdev.h           |  91 ++++++++
 lib/librte_ethdev/rte_ethdev_driver.h    |  82 +++++++
 lib/librte_ethdev/rte_ethdev_version.map |   3 +
 11 files changed, 912 insertions(+), 1 deletion(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V12 1/4] ethdev: introduce FEC API
  2020-09-24 13:05   ` [dpdk-dev] [PATCH V12 0/4] add FEC support Min Hu (Connor)
@ 2020-09-24 13:05     ` Min Hu (Connor)
  2020-09-24 14:46       ` Andrew Rybchenko
  2020-09-24 13:05     ` [dpdk-dev] [PATCH V12 2/4] net/hns3: support FEC Min Hu (Connor)
                       ` (2 subsequent siblings)
  3 siblings, 1 reply; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-24 13:05 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

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>
---
v10->v11:
allow to report capabilities per link speed.
specify what should be reported if link is down
when get FEC.
change mode to capa bitmask.

---
v9->v10:
add macro RTE_ETH_FEC_MODE_CAPA_MASK(x) to indicate
different FEC mode capa.

---
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.

---
 lib/librte_ethdev/rte_ethdev.c           | 37 +++++++++++++
 lib/librte_ethdev/rte_ethdev.h           | 91 ++++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_driver.h    | 82 ++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |  3 ++
 4 files changed, 213 insertions(+)

diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index dfe5c1b..b614bfc 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -3679,6 +3679,43 @@ 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 *num,
+			   struct rte_eth_fec_capa *speed_fec_capa)
+{
+	struct rte_eth_dev *dev;
+
+	if (num == NULL || speed_fec_capa == NULL)
+		return -EINVAL;
+
+	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, num,
+							speed_fec_capa));
+}
+
+int
+rte_eth_fec_get(uint16_t port_id, uint32_t *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, uint32_t mode)
+{
+	struct rte_eth_dev *dev;
+
+	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 645a186..104181d 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1544,6 +1544,29 @@ 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 */
+};
+
+/* Translate from FEC mode to FEC capa */
+#define RTE_ETH_FEC_MODE_TO_CAPA(x)	(1U << (x))
+
+/* This macro indicates FEC capa mask*/
+#define RTE_ETH_FEC_MODE_CAPA_MASK(x)	(1U << (RTE_ETH_FEC_ ## x))
+
+/* A structure used to get capabilities per link speed */
+struct rte_eth_fec_capa {
+	uint32_t speed; /**< Link speed (see ETH_SPEED_NUM_*) */
+	uint32_t capa;  /**< FEC capabilities bitmask (see RTE_FEC_CAPA_*) */
+};
+
 #define RTE_ETH_ALL RTE_MAX_ETHPORTS
 
 /* Macros to check for valid port */
@@ -3397,6 +3420,74 @@ 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 num
+ *   the num is in/out with a number of elements in an array.
+ * @param speed_fec_capa
+ *   speed_fec_capa is out only with per-speed capabilities.
+ *
+ * @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.
+ *   - (-EINVAL)  if *num* or *speed_fec_capa* invalid
+ */
+__rte_experimental
+int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *num,
+			struct rte_eth_fec_capa *speed_fec_capa);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get current Forward Error Correction(FEC) mode.
+ * 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.
+ *
+ * @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, uint32_t *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, uint32_t mode);
+
+/**
  * Get current status of the Ethernet link flow control for Ethernet device
  *
  * @param port_id
diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
index 23cc1e0..625b8c5 100644
--- a/lib/librte_ethdev/rte_ethdev_driver.h
+++ b/lib/librte_ethdev/rte_ethdev_driver.h
@@ -575,6 +575,81 @@ 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 num
+ *   the num is in/out with a number of elements in an array.
+ * @param speed_fec_capa
+ *   speed_fec_capa is out only with per-speed capabilities.
+ *
+ * @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.
+ * @retval -EINVAL
+ *   *num* or *speed_fec_capa* invalid.
+ */
+typedef int (*eth_fec_get_capability_t)(struct rte_eth_dev *dev, uint32_t *num,
+				struct rte_eth_fec_capa *speed_fec_capa);
+
+/**
+ * @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,
+			     uint32_t *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, uint32_t mode);
+
+/**
  * @internal A structure containing the functions exported by an Ethernet driver.
  */
 struct eth_dev_ops {
@@ -713,6 +788,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 c95ef51..b9ace3a 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -229,6 +229,9 @@ EXPERIMENTAL {
 	# added in 20.11
 	rte_eth_link_speed_to_str;
 	rte_eth_link_to_str;
+	rte_eth_fec_get_capability;
+	rte_eth_fec_get;
+	rte_eth_fec_set;
 };
 
 INTERNAL {
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V12 2/4] net/hns3: support FEC
  2020-09-24 13:05   ` [dpdk-dev] [PATCH V12 0/4] add FEC support Min Hu (Connor)
  2020-09-24 13:05     ` [dpdk-dev] [PATCH V12 1/4] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-24 13:05     ` Min Hu (Connor)
  2020-09-24 13:05     ` [dpdk-dev] [PATCH V12 3/4] app/testpmd: add FEC command Min Hu (Connor)
  2020-09-24 13:05     ` [dpdk-dev] [PATCH V12 4/4] doc: add FEC API and PMD information Min Hu (Connor)
  3 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-24 13:05 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

Forward error correction (FEC) is a bit error correction mode.
It adds error correction information to data packets at the
transmit end, and uses the error correction information to correct
the bit errors generated during data packet transmission at the
receive end. This improves signal quality but also brings a delay
to signals. This function can be enabled or disabled as required.

This patch adds FEC support for ethdev.Introduce ethdev
operations 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>
---
v11->v12:
fix coding warning.

v10->v11:
allow to report capabilities per link speed.
specify what should be reported if link is down
when get FEC.
change mode to capa bitmask.

---
v9->v10:
use RTE_ETH_FEC_MODE_CAPA_MASK(x) which is just defined.

---
v7->v8:
FEC mode order defined in hns3 hardware is inconsistend with
that defined in the ethdev library. So the sequence needs
to be converted.

---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Data type for fec_cap is changed from uint8_t
to uint32_t for possible future expansion.

---
v2->v3:
adjust the return value of function.

---
 drivers/net/hns3/hns3_cmd.h    |  19 ++-
 drivers/net/hns3/hns3_ethdev.c | 357 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h |   1 +
 3 files changed, 376 insertions(+), 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index 87d6053..a1e9604 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -100,6 +100,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_QUERY_LINK_STATUS      = 0x0307,
 	HNS3_OPC_CONFIG_MAX_FRM_SIZE    = 0x0308,
 	HNS3_OPC_CONFIG_SPEED_DUP       = 0x0309,
+	HNS3_OPC_CONFIG_FEC_MODE        = 0x031A,
 
 	/* PFC/Pause commands */
 	HNS3_OPC_CFG_MAC_PAUSE_EN       = 0x0701,
@@ -684,9 +685,25 @@ struct hns3_config_auto_neg_cmd {
 	uint8_t   rsv[20];
 };
 
+#define HNS3_MAC_CFG_FEC_AUTO_EN_B	0
+#define HNS3_MAC_CFG_FEC_MODE_S		1
+#define HNS3_MAC_CFG_FEC_MODE_M	GENMASK(3, 1)
+#define HNS3_MAC_FEC_OFF		0
+#define HNS3_MAC_FEC_BASER		1
+#define HNS3_MAC_FEC_RS			2
+
 struct hns3_sfp_speed_cmd {
 	uint32_t  sfp_speed;
-	uint32_t  rsv[5];
+	uint8_t   query_type; /* 0: sfp speed, 1: active fec */
+	uint8_t   active_fec; /* current FEC mode */
+	uint16_t  rsv1;
+	uint32_t  rsv2[4];
+};
+
+/* Configure FEC mode, opcode:0x031A */
+struct hns3_config_fec_cmd {
+	uint8_t fec_mode;
+	uint8_t rsv[23];
 };
 
 #define HNS3_MAC_MGR_MASK_VLAN_B		BIT(0)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 73d5042..f06b5b1 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -63,6 +63,11 @@
 #define HNS3_RESET_WAIT_MS	100
 #define HNS3_RESET_WAIT_CNT	200
 
+/* FEC mode order defined in HNS3 hardware */
+#define HNS3_HW_FEC_MODE_NOFEC  0
+#define HNS3_HW_FEC_MODE_BASER  1
+#define HNS3_HW_FEC_MODE_RS     2
+
 enum hns3_evt_cause {
 	HNS3_VECTOR0_EVENT_RST,
 	HNS3_VECTOR0_EVENT_MBX,
@@ -70,6 +75,34 @@ enum hns3_evt_cause {
 	HNS3_VECTOR0_EVENT_OTHER,
 };
 
+static const struct rte_eth_fec_capa speed_fec_capa_tbl[] = {
+	{ ETH_SPEED_NUM_10G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(BASER) },
+
+	{ ETH_SPEED_NUM_25G, 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) },
+
+	{ ETH_SPEED_NUM_40G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(BASER) },
+
+	{ ETH_SPEED_NUM_50G, 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) },
+
+	{ ETH_SPEED_NUM_100G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(RS) },
+
+	{ ETH_SPEED_NUM_200G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(RS) }
+};
+
 static enum hns3_reset_level hns3_get_reset_level(struct hns3_adapter *hns,
 						 uint64_t *levels);
 static int hns3_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
@@ -81,6 +114,8 @@ static int hns3_add_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
 static int hns3_remove_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
+static int hns3_restore_fec(struct hns3_hw *hw);
+static int hns3_query_dev_fec_info(struct rte_eth_dev *dev);
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -2889,6 +2924,13 @@ hns3_get_capability(struct hns3_hw *hw)
 	    device_id == HNS3_DEV_ID_200G_RDMA)
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_DCB_B, 1);
 
+	ret = hns3_query_dev_fec_info(eth_dev);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			     "failed to query FEC information, ret = %d", ret);
+		return ret;
+	}
+
 	/* Get PCI revision id */
 	ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN,
 				  HNS3_PCI_REVISION_ID);
@@ -5446,6 +5488,10 @@ hns3_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_promisc;
 
+	ret = hns3_restore_fec(hw);
+	if (ret)
+		goto err_promisc;
+
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED) {
 		ret = hns3_do_start(hns, false);
 		if (ret)
@@ -5524,6 +5570,314 @@ hns3_reset_service(void *param)
 		hns3_msix_process(hns, reset_level);
 }
 
+static int
+hns3_get_speed_capa_num(uint16_t device_id)
+{
+	uint32_t num;
+
+	switch (device_id) {
+	case HNS3_DEV_ID_25GE:
+	case HNS3_DEV_ID_25GE_RDMA:
+		num = 2;
+		break;
+	case HNS3_DEV_ID_100G_RDMA_MACSEC:
+	case HNS3_DEV_ID_200G_RDMA:
+		num = 1;
+		break;
+	default:
+		num = 0;
+		break;
+	}
+
+	return num;
+}
+
+static int
+hns3_get_speed_fec_capa(struct rte_eth_fec_capa *speed_fec_capa,
+			uint16_t device_id)
+{
+	switch (device_id) {
+	case HNS3_DEV_ID_25GE:
+	/* fallthrough */
+	case HNS3_DEV_ID_25GE_RDMA:
+		speed_fec_capa[0].speed = speed_fec_capa_tbl[1].speed;
+		speed_fec_capa[0].capa = speed_fec_capa_tbl[1].capa;
+
+		/* In HNS3 device, the 25G NIC is compatible with 10G rate */
+		speed_fec_capa[1].speed = speed_fec_capa_tbl[0].speed;
+		speed_fec_capa[1].capa = speed_fec_capa_tbl[0].capa;
+		break;
+	case HNS3_DEV_ID_100G_RDMA_MACSEC:
+		speed_fec_capa[0].speed = speed_fec_capa_tbl[4].speed;
+		speed_fec_capa[0].capa = speed_fec_capa_tbl[4].capa;
+		break;
+	case HNS3_DEV_ID_200G_RDMA:
+		speed_fec_capa[0].speed = speed_fec_capa_tbl[5].speed;
+		speed_fec_capa[0].capa = speed_fec_capa_tbl[5].capa;
+		break;
+	default:
+		return -ENOTSUP;
+	}
+
+	return 0;
+}
+
+static int
+hns3_fec_get_capability(struct rte_eth_dev *dev, uint32_t *num,
+			struct rte_eth_fec_capa *speed_fec_capa)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	uint16_t device_id = pci_dev->id.device_id;
+	uint32_t capa_num;
+	int ret;
+
+	capa_num = hns3_get_speed_capa_num(device_id);
+	if (capa_num == 0) {
+		hns3_err(hw, "device(0x%x) is not supported by hns3 PMD",
+			 device_id);
+		return -ENOTSUP;
+	} else if (*num < capa_num) {
+		hns3_err(hw, "insufficient num, num should be no less than %u",
+			 capa_num);
+		return -EINVAL;
+	}
+
+	ret = hns3_get_speed_fec_capa(speed_fec_capa, device_id);
+	if (ret)
+		return -ENOTSUP;
+
+	*num = capa_num;
+	return 0;
+}
+
+static int
+get_current_fec_auto_state(struct hns3_hw *hw, uint8_t *state)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, true);
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret) {
+		hns3_err(hw, "get current fec auto state failed, ret = %d",
+			 ret);
+		return ret;
+	}
+
+	*state = req->fec_mode & (1U << HNS3_MAC_CFG_FEC_AUTO_EN_B);
+	return 0;
+}
+
+static int
+hns3_fec_get(struct rte_eth_dev *dev, uint32_t *mode)
+{
+#define QUERY_ACTIVE_SPEED	1
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_sfp_speed_cmd *resp;
+	uint32_t tmp_mode;
+	uint8_t auto_state;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	/*
+	 * 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.
+	 */
+	if (hw->mac.link_status == ETH_LINK_DOWN) {
+		ret = get_current_fec_auto_state(hw, &auto_state);
+		if (ret)
+			return ret;
+
+		if (auto_state == 0x1) {
+			*mode = RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
+			return 0;
+		}
+	}
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_SFP_GET_SPEED, true);
+	resp = (struct hns3_sfp_speed_cmd *)desc.data;
+	resp->query_type = QUERY_ACTIVE_SPEED;
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret == -EOPNOTSUPP) {
+		hns3_err(hw, "IMP do not support get FEC, ret = %d", ret);
+		return ret;
+	} else if (ret) {
+		hns3_err(hw, "get FEC failed, ret = %d", ret);
+		return ret;
+	}
+
+	/*
+	 * FEC mode order defined in hns3 hardware is inconsistend with
+	 * that defined in the ethdev library. So the sequence needs
+	 * to be converted.
+	 */
+	switch (resp->active_fec) {
+	case HNS3_HW_FEC_MODE_NOFEC:
+		tmp_mode = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
+		break;
+	case HNS3_HW_FEC_MODE_BASER:
+		tmp_mode = RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
+		break;
+	case HNS3_HW_FEC_MODE_RS:
+		tmp_mode = RTE_ETH_FEC_MODE_CAPA_MASK(RS);
+		break;
+	default:
+		tmp_mode = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
+		break;
+	}
+
+	*mode = tmp_mode;
+	return 0;
+}
+
+static int
+hns3_set_fec_hw(struct hns3_hw *hw, uint32_t mode)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, false);
+
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	switch (mode) {
+	case RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC):
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_OFF);
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(BASER):
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_BASER);
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(RS):
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_RS);
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(AUTO):
+		hns3_set_bit(req->fec_mode, HNS3_MAC_CFG_FEC_AUTO_EN_B, 1);
+		break;
+	default:
+		return 0;
+	}
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw, "set fec mode failed, ret = %d", ret);
+
+	return ret;
+}
+
+static uint32_t
+get_current_speed_fec_cap(struct hns3_hw *hw, struct rte_eth_fec_capa *fec_capa)
+{
+	struct hns3_mac *mac = &hw->mac;
+	uint32_t cur_capa;
+
+	switch (mac->link_speed) {
+	case ETH_SPEED_NUM_10G:
+		cur_capa = fec_capa[1].capa;
+		break;
+	case ETH_SPEED_NUM_25G:
+	case ETH_SPEED_NUM_100G:
+	case ETH_SPEED_NUM_200G:
+		cur_capa = fec_capa[0].capa;
+		break;
+	default:
+		cur_capa = 0;
+		break;
+	}
+
+	return cur_capa;
+}
+
+static bool
+is_fec_mode_one_bit_set(uint32_t mode)
+{
+	int cnt = 0;
+	uint8_t i;
+
+	for (i = 0; i < sizeof(mode); i++)
+		if (mode >> i & 0x1)
+			cnt++;
+
+	return cnt == 1 ? true : false;
+}
+
+static int
+hns3_fec_set(struct rte_eth_dev *dev, uint32_t mode)
+{
+#define FEC_CAPA_NUM 2
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+
+	struct rte_eth_fec_capa fec_capa[FEC_CAPA_NUM];
+	uint32_t cur_capa;
+	uint32_t num = FEC_CAPA_NUM;
+	int ret;
+
+	ret = hns3_fec_get_capability(dev, &num, fec_capa);
+	if (ret != 0)
+		return ret;
+
+	/* HNS3 PMD driver only support one bit set mode, e.g. 0x1, 0x4 */
+	if (!is_fec_mode_one_bit_set(mode))
+		hns3_err(hw, "FEC mode(0x%x) not supported in HNS3 PMD,"
+			     "FEC mode should be only one bit set", mode);
+
+	/*
+	 * Check whether the configured mode is within the FEC capability.
+	 * If not, the configured mode will not be supported.
+	 */
+	cur_capa = get_current_speed_fec_cap(hw, fec_capa);
+	if (!(cur_capa & mode)) {
+		hns3_err(hw, "unsupported FEC mode = 0x%x", mode);
+		return -EINVAL;
+	}
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		return ret;
+
+	pf->fec_mode = mode;
+	return 0;
+}
+
+static int
+hns3_restore_fec(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+	uint32_t mode = pf->fec_mode;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		hns3_err(hw, "restore fec mode(0x%x) failed, ret = %d",
+			 mode, ret);
+
+	return ret;
+}
+
+static int
+hns3_query_dev_fec_info(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_fec_get(dev, &pf->fec_mode);
+	if (ret)
+		hns3_err(hw, "query device FEC info failed, ret = %d", ret);
+
+	return ret;
+}
+
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_configure      = hns3_dev_configure,
 	.dev_start          = hns3_dev_start,
@@ -5573,6 +5927,9 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.get_reg                = hns3_get_regs,
 	.get_dcb_info           = hns3_get_dcb_info,
 	.dev_supported_ptypes_get = hns3_dev_supported_ptypes_get,
+	.fec_get_capability     = hns3_fec_get_capability,
+	.fec_get                = hns3_fec_get,
+	.fec_set                = hns3_fec_set,
 };
 
 static const struct hns3_reset_ops hns3_reset_ops = {
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index fd6a9f9..393b91f 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -620,6 +620,7 @@ struct hns3_pf {
 	struct hns3_err_msix_intr_stats abn_int_stats;
 
 	bool support_sfp_query;
+	uint32_t fec_mode; /* current FEC mode for ethdev */
 
 	struct hns3_vtag_cfg vtag_config;
 	LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V12 3/4] app/testpmd: add FEC command
  2020-09-24 13:05   ` [dpdk-dev] [PATCH V12 0/4] add FEC support Min Hu (Connor)
  2020-09-24 13:05     ` [dpdk-dev] [PATCH V12 1/4] ethdev: introduce FEC API Min Hu (Connor)
  2020-09-24 13:05     ` [dpdk-dev] [PATCH V12 2/4] net/hns3: support FEC Min Hu (Connor)
@ 2020-09-24 13:05     ` Min Hu (Connor)
  2020-09-24 13:05     ` [dpdk-dev] [PATCH V12 4/4] doc: add FEC API and PMD information Min Hu (Connor)
  3 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-24 13:05 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This commit adds testpmd capability to query and config FEC
function of device. This includes:
- show FEC capabilities, example:
	testpmd> show port 0 fec capabilities
- show FEC mode, example:
	testpmd> show port 0 fec_mode
- config FEC mode, example:
	testpmd> set port <port_id> 0 <auto|off|rs|baser>

	where:

	auto|off|rs|baser are four kinds of FEC mode which dev
	support according to MAC link speed.

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>
Acked-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
---
v10->v11:
change mode to capa bitmask.

---
v8->v9:
added acked-by.

---
v6->v7:
used RTE_DIM(fec_mode_name) instead of RTE_ETH_FEC_NUM

---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Add RTE_ prefix for public FEC mode enum.

---
v3->v4:
adjust the display format of FEC mode

---
v2->v3:
adjust the display format of FEC capability.

---
 app/test-pmd/cmdline.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c  |  91 ++++++++++++++++++++
 app/test-pmd/testpmd.h |   2 +
 3 files changed, 314 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 5f93409..445726f 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -19161,6 +19161,224 @@ cmdline_parse_inst_t cmd_show_tx_metadata = {
 	},
 };
 
+/* *** show fec capability per port configuration *** */
+struct cmd_show_fec_capability_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_fec;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_capability_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_CAP_NUM 2
+	struct cmd_show_fec_capability_result *res = parsed_result;
+	struct rte_eth_fec_capa speed_fec_capa[FEC_CAP_NUM];
+	uint32_t num = FEC_CAP_NUM;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_fec_get_capability(res->cmd_pid, &num, speed_fec_capa);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC capability failed\n");
+		return;
+	}
+
+	show_fec_capability(num, speed_fec_capa);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_capability_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_capability_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_capability_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_capability_fec =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_fec, "fec");
+cmdline_parse_token_string_t cmd_show_fec_capability_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_keyword, "capabilities");
+
+cmdline_parse_inst_t cmd_show_capability = {
+	.f = cmd_show_fec_capability_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec capabilities",
+	.tokens = {
+		(void *)&cmd_show_fec_capability_show,
+		(void *)&cmd_show_fec_capability_port,
+		(void *)&cmd_show_fec_capability_pid,
+		(void *)&cmd_show_fec_capability_fec,
+		(void *)&cmd_show_fec_capability_keyword,
+		NULL,
+	},
+};
+
+/* *** show fec mode per port configuration *** */
+struct cmd_show_fec_metadata_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_mode_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_NAME_SIZE 16
+	struct cmd_show_fec_metadata_result *res = parsed_result;
+	uint32_t mode;
+	char buf[FEC_NAME_SIZE];
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+	ret = rte_eth_fec_get(res->cmd_pid, &mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC mode failed\n");
+		return;
+	}
+
+	switch (mode) {
+	case RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC):
+		strlcpy(buf, "off", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(AUTO):
+		strlcpy(buf, "auto", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(BASER):
+		strlcpy(buf, "baser", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(RS):
+		strlcpy(buf, "rs", sizeof(buf));
+		break;
+	default:
+		return;
+	}
+
+	printf("%s\n", buf);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_mode_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_mode_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_mode_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_mode_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_keyword, "fec_mode");
+
+cmdline_parse_inst_t cmd_show_fec_mode = {
+	.f = cmd_show_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec_mode",
+	.tokens = {
+		(void *)&cmd_show_fec_mode_show,
+		(void *)&cmd_show_fec_mode_port,
+		(void *)&cmd_show_fec_mode_pid,
+		(void *)&cmd_show_fec_mode_keyword,
+		NULL,
+	},
+};
+
+/* *** set fec mode per port configuration *** */
+struct cmd_set_port_fec_mode {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t fec_mode;
+	cmdline_fixed_string_t fec_value;
+};
+
+/* Common CLI fields for set fec mode */
+cmdline_parse_token_string_t cmd_set_port_fec_mode_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port, "port");
+cmdline_parse_token_num_t cmd_set_port_fec_mode_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_port_fec_mode_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_mode, "fec_mode");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_value =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_value, NULL);
+
+static void
+cmd_set_port_fec_mode_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	__rte_unused void *data)
+{
+	struct cmd_set_port_fec_mode *res = parsed_result;
+	uint16_t port_id = res->port_id;
+	uint32_t mode;
+	int ret;
+
+	ret = parse_fec_mode(res->fec_value, &mode);
+	if (ret < 0) {
+		printf("Unknown fec mode: %s for Port %d\n", res->fec_value,
+			port_id);
+		return;
+	}
+
+	ret = rte_eth_fec_set(port_id, mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Set FEC mode failed\n");
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_fec_mode = {
+	.f = cmd_set_port_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> fec_mode <auto|off|rs|baser>",
+	.tokens = {
+		(void *)&cmd_set_port_fec_mode_set,
+		(void *)&cmd_set_port_fec_mode_port,
+		(void *)&cmd_set_port_fec_mode_port_id,
+		(void *)&cmd_set_port_fec_mode_str,
+		(void *)&cmd_set_port_fec_mode_value,
+		NULL,
+	},
+};
+
 /* show port supported ptypes */
 
 /* Common result structure for show port ptypes */
@@ -19795,6 +20013,9 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_set_raw,
 	(cmdline_parse_inst_t *)&cmd_show_set_raw_all,
 	(cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
+	(cmdline_parse_inst_t *)&cmd_show_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_set_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_show_capability,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 2d9a456..a6269c1 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -138,6 +138,58 @@ const struct rss_type_info rss_type_table[] = {
 	{ NULL, 0 },
 };
 
+static const struct {
+	enum rte_eth_fec_mode mode;
+	const char *name;
+} fec_mode_name[] = {
+	{
+		.mode = RTE_ETH_FEC_NOFEC,
+		.name = "off",
+	},
+	{
+		.mode = RTE_ETH_FEC_AUTO,
+		.name = "auto",
+	},
+	{
+		.mode = RTE_ETH_FEC_BASER,
+		.name = "baser",
+	},
+	{
+		.mode = RTE_ETH_FEC_RS,
+		.name = "rs",
+	},
+};
+
+static const struct {
+	uint32_t speed;
+	const char *name;
+} eth_speed_name[] = {
+	{
+		.speed = ETH_SPEED_NUM_10G,
+		.name = "Speed 10G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_25G,
+		.name = "Speed 25G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_40G,
+		.name = "Speed 40G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_50G,
+		.name = "Speed 50G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_100G,
+		.name = "Speed 100G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_200G,
+		.name = "Speed 200G",
+	},
+};
+
 static void
 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
 {
@@ -2969,6 +3021,45 @@ set_tx_pkt_split(const char *name)
 	printf("unknown value: \"%s\"\n", name);
 }
 
+int
+parse_fec_mode(const char *name, uint32_t *mode)
+{
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(fec_mode_name); i++) {
+		if (strcmp(fec_mode_name[i].name, name) == 0) {
+			*mode = RTE_ETH_FEC_MODE_TO_CAPA(fec_mode_name[i].mode);
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void
+show_fec_capability(uint32_t num, struct rte_eth_fec_capa *speed_fec_capa)
+{
+	uint32_t i, j, k;
+
+	printf("FEC capabilities:\n");
+
+	for (i = 0; i < num; i++) {
+		for (j = 0; j < RTE_DIM(eth_speed_name); j++) {
+			if (eth_speed_name[j].speed ==
+						speed_fec_capa[i].speed) {
+				printf("%s : ", eth_speed_name[j].name);
+				break;
+			}
+		}
+
+		for (k = RTE_ETH_FEC_AUTO; k < RTE_DIM(fec_mode_name); k++) {
+			if (RTE_ETH_FEC_MODE_TO_CAPA(k) &
+						speed_fec_capa[i].capa)
+				printf("%s ", fec_mode_name[k].name);
+		}
+		printf("\n");
+	}
+}
+
 void
 show_tx_pkt_segments(void)
 {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index f139fe7..85ea030 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -804,6 +804,8 @@ void show_tx_pkt_segments(void);
 void set_tx_pkt_times(unsigned int *tx_times);
 void show_tx_pkt_times(void);
 void set_tx_pkt_split(const char *name);
+int parse_fec_mode(const char *name, enum rte_eth_fec_mode *mode);
+void show_fec_capability(uint32_t num, struct rte_eth_fec_capa *speed_fec_capa);
 void set_nb_pkt_per_burst(uint16_t pkt_burst);
 char *list_pkt_forwarding_modes(void);
 char *list_pkt_forwarding_retry_modes(void);
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V12 4/4] doc: add FEC API and PMD information
  2020-09-24 13:05   ` [dpdk-dev] [PATCH V12 0/4] add FEC support Min Hu (Connor)
                       ` (2 preceding siblings ...)
  2020-09-24 13:05     ` [dpdk-dev] [PATCH V12 3/4] app/testpmd: add FEC command Min Hu (Connor)
@ 2020-09-24 13:05     ` Min Hu (Connor)
  2020-09-24 13:52       ` Andrew Rybchenko
  3 siblings, 1 reply; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-24 13:05 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

Added the FEC API, and hns3 FEC PMD information in
release 20.11.rst file.

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>
---
 doc/guides/rel_notes/release_20_11.rst | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index c6642f5..de2c8e4 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -78,6 +78,15 @@ New Features
     ``--portmask=N``
     where N represents the hexadecimal bitmask of ports used.
 
+* **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
 -------------
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V12 4/4] doc: add FEC API and PMD information
  2020-09-24 13:05     ` [dpdk-dev] [PATCH V12 4/4] doc: add FEC API and PMD information Min Hu (Connor)
@ 2020-09-24 13:52       ` Andrew Rybchenko
  0 siblings, 0 replies; 118+ messages in thread
From: Andrew Rybchenko @ 2020-09-24 13:52 UTC (permalink / raw)
  To: Min Hu (Connor), dev; +Cc: konstantin.ananyev, thomas, ferruh.yigit, linuxarm

On 9/24/20 4:05 PM, Min Hu (Connor) wrote:
> Added the FEC API, and hns3 FEC PMD information in
> release 20.11.rst file.
> 
> 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>
> ---
>  doc/guides/rel_notes/release_20_11.rst | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
> index c6642f5..de2c8e4 100644
> --- a/doc/guides/rel_notes/release_20_11.rst
> +++ b/doc/guides/rel_notes/release_20_11.rst
> @@ -78,6 +78,15 @@ New Features
>      ``--portmask=N``
>      where N represents the hexadecimal bitmask of ports used.
>  
> +* **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.
> +

Release notes should be updated when corresponding functionality is
added. So above lines belong to 1/4.

> +* **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.

These lines belong to 2/4 and don't forget to add extra empty
line since it must be two empty lines the next section.

>  
>  Removed Items
>  -------------
> 


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V12 1/4] ethdev: introduce FEC API
  2020-09-24 13:05     ` [dpdk-dev] [PATCH V12 1/4] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-24 14:46       ` Andrew Rybchenko
  2020-09-25  8:47         ` Min Hu (Connor)
  0 siblings, 1 reply; 118+ messages in thread
From: Andrew Rybchenko @ 2020-09-24 14:46 UTC (permalink / raw)
  To: Min Hu (Connor), dev; +Cc: konstantin.ananyev, thomas, ferruh.yigit, linuxarm

On 9/24/20 4:05 PM, 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.

Almost good now. See my notes below.
Many thanks for hard work and patience.

> 
> 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>

I think that tags for Ajit and Konstantin should be
dropped, since API changes significantly after their review.

> ---
> v10->v11:
> allow to report capabilities per link speed.
> specify what should be reported if link is down
> when get FEC.
> change mode to capa bitmask.
> 
> ---
> v9->v10:
> add macro RTE_ETH_FEC_MODE_CAPA_MASK(x) to indicate
> different FEC mode capa.
> 
> ---
> 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.
> 
> ---
>  lib/librte_ethdev/rte_ethdev.c           | 37 +++++++++++++
>  lib/librte_ethdev/rte_ethdev.h           | 91 ++++++++++++++++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev_driver.h    | 82 ++++++++++++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev_version.map |  3 ++
>  4 files changed, 213 insertions(+)
> 
> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> index dfe5c1b..b614bfc 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -3679,6 +3679,43 @@ 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 *num,
> +			   struct rte_eth_fec_capa *speed_fec_capa)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	if (num == NULL || speed_fec_capa == NULL)
> +		return -EINVAL;

I think it is OK to have speed_fec_cap==NULL if *num is 0.
I.e. a request to get number of required array entries.

> +
> +	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, num,
> +							speed_fec_capa));
> +}
> +
> +int
> +rte_eth_fec_get(uint16_t port_id, uint32_t *mode)
> +{
> +	struct rte_eth_dev *dev;

I think it would be good to check that mode is not NULL here.

> +
> +	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, uint32_t mode)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	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 645a186..104181d 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -1544,6 +1544,29 @@ struct rte_eth_dcb_info {
>  	struct rte_eth_dcb_tc_queue_mapping tc_queue;
>  };
>  
> +/**
> + * This enum indicates the possible (forward error correction)FEC modes

(forward error correction)FEC -> Forward Error Correction (FEC)

> + * 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 */
> +};
> +
> +/* Translate from FEC mode to FEC capa */
> +#define RTE_ETH_FEC_MODE_TO_CAPA(x)	(1U << (x))
> +
> +/* This macro indicates FEC capa mask*/

Add missing space before */

> +#define RTE_ETH_FEC_MODE_CAPA_MASK(x)	(1U << (RTE_ETH_FEC_ ## x))
> +
> +/* A structure used to get capabilities per link speed */
> +struct rte_eth_fec_capa {
> +	uint32_t speed; /**< Link speed (see ETH_SPEED_NUM_*) */
> +	uint32_t capa;  /**< FEC capabilities bitmask (see RTE_FEC_CAPA_*) */
> +};
> +
>  #define RTE_ETH_ALL RTE_MAX_ETHPORTS
>  
>  /* Macros to check for valid port */
> @@ -3397,6 +3420,74 @@ 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 num
> + *   the num is in/out with a number of elements in an array.

Please, see below my notes on callback description.

> + * @param speed_fec_capa
> + *   speed_fec_capa is out only with per-speed capabilities.
> + *
> + * @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.
> + *   - (-EINVAL)  if *num* or *speed_fec_capa* invalid
> + */
> +__rte_experimental
> +int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *num,
> +			struct rte_eth_fec_capa *speed_fec_capa);
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get current Forward Error Correction(FEC) mode.
> + * 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.
> + *
> + * @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, uint32_t *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.

See below.

> + * @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, uint32_t mode);
> +
> +/**
>   * Get current status of the Ethernet link flow control for Ethernet device
>   *
>   * @param port_id
> diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
> index 23cc1e0..625b8c5 100644
> --- a/lib/librte_ethdev/rte_ethdev_driver.h
> +++ b/lib/librte_ethdev/rte_ethdev_driver.h
> @@ -575,6 +575,81 @@ 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 num
> + *   the num is in/out with a number of elements in an array.

I'm sorry, I should do it before my previous suggestion, but:
Looking at rte_eth_xstats_get_names() and trying to be
consistent I'd like to suggest to put the argument after
speed_fec_capa and make it input only with a number of
array elements.
Positive return values should be used to provide number of
filled in array elements. If the returned value is greater
than 'num', just provided elements are filled in, but
it is indication as well, that num is too small.

> + * @param speed_fec_capa
> + *   speed_fec_capa is out only with per-speed capabilities.
> + *
> + * @return
> + *   Negative errno value on error, 0 on success.
> + *
> + * @retval 0
> + *   Success, get FEC success.

See above.

> + * @retval -ENOTSUP
> + *   operation is not supported.

Should start from upper case letter

> + * @retval -EIO
> + *   device is removed.

Should start from upper case letter

> + * @retval -ENODEV
> + *   Device is gone.

What's the difference between "device is remove" and
"Device is gone"

> + * @retval -EINVAL
> + *   *num* or *speed_fec_capa* invalid.
> + */
> +typedef int (*eth_fec_get_capability_t)(struct rte_eth_dev *dev, uint32_t *num,
> +				struct rte_eth_fec_capa *speed_fec_capa);
> +
> +/**
> + * @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.

Should start from upper case letter

> + * @retval -EIO
> + *   device is removed.

Should start from upper case letter

> + * @retval -ENODEV
> + *   Device is gone.
> + */
> +typedef int (*eth_fec_get_t)(struct rte_eth_dev *dev,
> +			     uint32_t *mode);
> +
> +/**
> + * @internal
> + *   Set Forward Error Correction(FEC) mode.

Remove extra spaces before "Set"

> + *
> + * @param dev
> + *   ethdev handle of port.
> + * @param mode
> + *   the FEC mode.

The description is insufficient and misleading.
It should be fec_capa and described as:
Bitmask of allowed FEC modes. If must be only one
if AUTO is disabled. If AUTO is enabled, other
bits specify FEC modes which may be negotiated.

> + *
> + * @return
> + *   Negative errno value on error, 0 on success.
> + *
> + * @retval 0
> + *   Success, set FEC success.
> + * @retval -ENOTSUP
> + *   operation is not supported.

Should start from upper case letter

What about -EINVAL in the case of unsupported FEC mode
requested? It is listed above in API function but
missing here.

> + * @retval -EIO
> + *   device is removed.

Should start from upper case letter

> + * @retval -ENODEV
> + *   Device is gone.

What's the difference between "device is remove" and
"Device is gone"

> + */
> +typedef int (*eth_fec_set_t)(struct rte_eth_dev *dev, uint32_t mode);
> +
> +/**
>   * @internal A structure containing the functions exported by an Ethernet driver.
>   */
>  struct eth_dev_ops {
> @@ -713,6 +788,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; */

It should be a dot (.) at the end, not semicolon (;).

> +	eth_fec_get_t fec_get;
> +	/**< Get Forward Error Correction(FEC) mode; */

same

> +	eth_fec_set_t fec_set;
> +	/**< Set Forward Error Correction(FEC) mode; */

same

>  };
>  
>  /**
> diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
> index c95ef51..b9ace3a 100644
> --- a/lib/librte_ethdev/rte_ethdev_version.map
> +++ b/lib/librte_ethdev/rte_ethdev_version.map
> @@ -229,6 +229,9 @@ EXPERIMENTAL {
>  	# added in 20.11
>  	rte_eth_link_speed_to_str;
>  	rte_eth_link_to_str;
> +	rte_eth_fec_get_capability;
> +	rte_eth_fec_get;
> +	rte_eth_fec_set;
>  };
>  
>  INTERNAL {
> 


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V13 0/3] add FEC support
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
                     ` (12 preceding siblings ...)
  2020-09-24 13:05   ` [dpdk-dev] [PATCH V12 0/4] add FEC support Min Hu (Connor)
@ 2020-09-25  8:39   ` Min Hu (Connor)
  2020-09-25  8:39     ` [dpdk-dev] [PATCH V13 1/3] ethdev: introduce FEC API Min Hu (Connor)
                       ` (3 more replies)
  2020-09-28 11:08   ` [dpdk-dev] [PATCH V14 " Min Hu (Connor)
                     ` (2 subsequent siblings)
  16 siblings, 4 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-25  8:39 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This series add FEC support for ethdev.

Min Hu (Connor) (3):
  ethdev: introduce FEC API
  net/hns3: support FEC
  app/testpmd: add FEC command

 app/test-pmd/cmdline.c                   | 223 +++++++++++++++++++
 app/test-pmd/config.c                    |  91 ++++++++
 app/test-pmd/testpmd.h                   |   2 +
 doc/guides/rel_notes/release_20_11.rst   |  10 +
 drivers/net/hns3/hns3_cmd.h              |  19 +-
 drivers/net/hns3/hns3_ethdev.c           | 356 +++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h           |   1 +
 lib/librte_ethdev/rte_ethdev.c           |  43 ++++
 lib/librte_ethdev/rte_ethdev.h           |  94 ++++++++
 lib/librte_ethdev/rte_ethdev_driver.h    |  80 +++++++
 lib/librte_ethdev/rte_ethdev_version.map |   3 +
 11 files changed, 921 insertions(+), 1 deletion(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V13 1/3] ethdev: introduce FEC API
  2020-09-25  8:39   ` [dpdk-dev] [PATCH V13 0/3] add FEC support Min Hu (Connor)
@ 2020-09-25  8:39     ` Min Hu (Connor)
  2020-09-28  7:35       ` Andrew Rybchenko
  2020-09-25  8:39     ` [dpdk-dev] [PATCH V13 2/3] net/hns3: support FEC Min Hu (Connor)
                       ` (2 subsequent siblings)
  3 siblings, 1 reply; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-25  8:39 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

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>
---
v12->v13:
change fec get capa API.
fix comment styles.

---
v10->v11:
allow to report capabilities per link speed.
specify what should be reported if link is down
when get FEC.
change mode to capa bitmask.

---
v9->v10:
add macro RTE_ETH_FEC_MODE_CAPA_MASK(x) to indicate
different FEC mode capa.

---
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   |  5 ++
 lib/librte_ethdev/rte_ethdev.c           | 43 +++++++++++++++
 lib/librte_ethdev/rte_ethdev.h           | 94 ++++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_driver.h    | 80 +++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |  3 +
 5 files changed, 225 insertions(+)

diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index c6642f5..1f04bd5 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -78,6 +78,11 @@ New Features
     ``--portmask=N``
     where N represents the hexadecimal bitmask of ports used.
 
+* **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.
+
 
 Removed Items
 -------------
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index dfe5c1b..86ead87 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -3679,6 +3679,49 @@ 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,
+			   struct rte_eth_fec_capa *speed_fec_capa,
+			   unsigned int num)
+{
+	struct rte_eth_dev *dev;
+	int ret;
+
+	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);
+	ret = (*dev->dev_ops->fec_get_capability)(dev, speed_fec_capa, num);
+	if (ret > (int)num)
+		RTE_ETHDEV_LOG(ERR, "Insufficient num, num should be no less than %d\n",
+			       ret);
+
+	return ret;
+}
+
+int
+rte_eth_fec_get(uint16_t port_id, uint32_t *mode)
+{
+	struct rte_eth_dev *dev;
+
+	if (mode == NULL)
+		return -EINVAL;
+
+	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, uint32_t mode)
+{
+	struct rte_eth_dev *dev;
+
+	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 645a186..04525a8 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1544,6 +1544,29 @@ 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 */
+};
+
+/* Translate from FEC mode to FEC capa */
+#define RTE_ETH_FEC_MODE_TO_CAPA(x)	(1U << (x))
+
+/* This macro indicates FEC capa mask */
+#define RTE_ETH_FEC_MODE_CAPA_MASK(x)	(1U << (RTE_ETH_FEC_ ## x))
+
+/* A structure used to get capabilities per link speed */
+struct rte_eth_fec_capa {
+	uint32_t speed; /**< Link speed (see ETH_SPEED_NUM_*) */
+	uint32_t capa;  /**< FEC capabilities bitmask (see RTE_FEC_CAPA_*) */
+};
+
 #define RTE_ETH_ALL RTE_MAX_ETHPORTS
 
 /* Macros to check for valid port */
@@ -3397,6 +3420,77 @@ 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 speed_fec_capa
+ *   speed_fec_capa is out only with per-speed capabilities.
+ *   If set to NULL, the function returns the required number
+ *   of required array entries.
+ * @param num
+ *   the num is in/out with a number of elements in an array.
+ *
+ * @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.
+ *   - (-EINVAL)  if *num* or *speed_fec_capa* invalid
+ */
+__rte_experimental
+int rte_eth_fec_get_capability(uint16_t port_id,
+			       struct rte_eth_fec_capa *speed_fec_capa,
+			       unsigned int num);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get current Forward Error Correction(FEC) mode.
+ * 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.
+ *
+ * @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, uint32_t *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, uint32_t mode);
+
+/**
  * Get current status of the Ethernet link flow control for Ethernet device
  *
  * @param port_id
diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
index 23cc1e0..306f3a6 100644
--- a/lib/librte_ethdev/rte_ethdev_driver.h
+++ b/lib/librte_ethdev/rte_ethdev_driver.h
@@ -575,6 +575,79 @@ 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 speed_fec_capa
+ *   speed_fec_capa is out only with per-speed capabilities.
+ * @param num
+ *   the num is in/out with a number of elements in an array.
+ *
+ * @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 -EINVAL
+ *   *num* or *speed_fec_capa* invalid.
+ */
+typedef int (*eth_fec_get_capability_t)(struct rte_eth_dev *dev,
+		struct rte_eth_fec_capa *speed_fec_capa, unsigned int num);
+
+/**
+ * @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.
+ */
+typedef int (*eth_fec_get_t)(struct rte_eth_dev *dev,
+			     uint32_t *mode);
+
+/**
+ * @internal
+ * Set Forward Error Correction(FEC) mode.
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param mode
+ *   bitmask of allowed FEC modes. It must be only one
+ *   if AUTO is disabled. If AUTO is enabled, other
+ *   bits specify FEC modes which may be negotiated.
+ *
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success, set FEC success.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EINVAL
+ *   Unsupported FEC mode requested.
+ * @retval -EIO
+ *   Device is removed.
+ */
+typedef int (*eth_fec_set_t)(struct rte_eth_dev *dev, uint32_t mode);
+
+/**
  * @internal A structure containing the functions exported by an Ethernet driver.
  */
 struct eth_dev_ops {
@@ -713,6 +786,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 c95ef51..b9ace3a 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -229,6 +229,9 @@ EXPERIMENTAL {
 	# added in 20.11
 	rte_eth_link_speed_to_str;
 	rte_eth_link_to_str;
+	rte_eth_fec_get_capability;
+	rte_eth_fec_get;
+	rte_eth_fec_set;
 };
 
 INTERNAL {
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V13 2/3] net/hns3: support FEC
  2020-09-25  8:39   ` [dpdk-dev] [PATCH V13 0/3] add FEC support Min Hu (Connor)
  2020-09-25  8:39     ` [dpdk-dev] [PATCH V13 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-25  8:39     ` Min Hu (Connor)
  2020-09-25  8:39     ` [dpdk-dev] [PATCH V13 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2020-09-27  7:08     ` [dpdk-dev] [PATCH V13 0/3] add FEC support Min Hu (Connor)
  3 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-25  8:39 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

Forward error correction (FEC) is a bit error correction mode.
It adds error correction information to data packets at the
transmit end, and uses the error correction information to correct
the bit errors generated during data packet transmission at the
receive end. This improves signal quality but also brings a delay
to signals. This function can be enabled or disabled as required.

This patch adds FEC support for ethdev.Introduce ethdev
operations 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>
---
v12->v13:
change fec get capa interface.

---
v11->v12:
fix coding warning.

v10->v11:
allow to report capabilities per link speed.
specify what should be reported if link is down
when get FEC.
change mode to capa bitmask.

---
v9->v10:
use RTE_ETH_FEC_MODE_CAPA_MASK(x) which is just defined.

---
v7->v8:
FEC mode order defined in hns3 hardware is inconsistend with
that defined in the ethdev library. So the sequence needs
to be converted.

---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Data type for fec_cap is changed from uint8_t
to uint32_t for possible future expansion.

---
v2->v3:
adjust the return value of function.

---
 doc/guides/rel_notes/release_20_11.rst |   5 +
 drivers/net/hns3/hns3_cmd.h            |  19 +-
 drivers/net/hns3/hns3_ethdev.c         | 356 +++++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h         |   1 +
 4 files changed, 380 insertions(+), 1 deletion(-)

diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index 1f04bd5..eec6930 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -83,6 +83,11 @@ New Features
   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/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index 87d6053..a1e9604 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -100,6 +100,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_QUERY_LINK_STATUS      = 0x0307,
 	HNS3_OPC_CONFIG_MAX_FRM_SIZE    = 0x0308,
 	HNS3_OPC_CONFIG_SPEED_DUP       = 0x0309,
+	HNS3_OPC_CONFIG_FEC_MODE        = 0x031A,
 
 	/* PFC/Pause commands */
 	HNS3_OPC_CFG_MAC_PAUSE_EN       = 0x0701,
@@ -684,9 +685,25 @@ struct hns3_config_auto_neg_cmd {
 	uint8_t   rsv[20];
 };
 
+#define HNS3_MAC_CFG_FEC_AUTO_EN_B	0
+#define HNS3_MAC_CFG_FEC_MODE_S		1
+#define HNS3_MAC_CFG_FEC_MODE_M	GENMASK(3, 1)
+#define HNS3_MAC_FEC_OFF		0
+#define HNS3_MAC_FEC_BASER		1
+#define HNS3_MAC_FEC_RS			2
+
 struct hns3_sfp_speed_cmd {
 	uint32_t  sfp_speed;
-	uint32_t  rsv[5];
+	uint8_t   query_type; /* 0: sfp speed, 1: active fec */
+	uint8_t   active_fec; /* current FEC mode */
+	uint16_t  rsv1;
+	uint32_t  rsv2[4];
+};
+
+/* Configure FEC mode, opcode:0x031A */
+struct hns3_config_fec_cmd {
+	uint8_t fec_mode;
+	uint8_t rsv[23];
 };
 
 #define HNS3_MAC_MGR_MASK_VLAN_B		BIT(0)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 73d5042..d3650bc 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -63,6 +63,11 @@
 #define HNS3_RESET_WAIT_MS	100
 #define HNS3_RESET_WAIT_CNT	200
 
+/* FEC mode order defined in HNS3 hardware */
+#define HNS3_HW_FEC_MODE_NOFEC  0
+#define HNS3_HW_FEC_MODE_BASER  1
+#define HNS3_HW_FEC_MODE_RS     2
+
 enum hns3_evt_cause {
 	HNS3_VECTOR0_EVENT_RST,
 	HNS3_VECTOR0_EVENT_MBX,
@@ -70,6 +75,34 @@ enum hns3_evt_cause {
 	HNS3_VECTOR0_EVENT_OTHER,
 };
 
+static const struct rte_eth_fec_capa speed_fec_capa_tbl[] = {
+	{ ETH_SPEED_NUM_10G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(BASER) },
+
+	{ ETH_SPEED_NUM_25G, 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) },
+
+	{ ETH_SPEED_NUM_40G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(BASER) },
+
+	{ ETH_SPEED_NUM_50G, 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) },
+
+	{ ETH_SPEED_NUM_100G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(RS) },
+
+	{ ETH_SPEED_NUM_200G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(RS) }
+};
+
 static enum hns3_reset_level hns3_get_reset_level(struct hns3_adapter *hns,
 						 uint64_t *levels);
 static int hns3_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
@@ -81,6 +114,8 @@ static int hns3_add_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
 static int hns3_remove_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
+static int hns3_restore_fec(struct hns3_hw *hw);
+static int hns3_query_dev_fec_info(struct rte_eth_dev *dev);
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -2889,6 +2924,13 @@ hns3_get_capability(struct hns3_hw *hw)
 	    device_id == HNS3_DEV_ID_200G_RDMA)
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_DCB_B, 1);
 
+	ret = hns3_query_dev_fec_info(eth_dev);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			     "failed to query FEC information, ret = %d", ret);
+		return ret;
+	}
+
 	/* Get PCI revision id */
 	ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN,
 				  HNS3_PCI_REVISION_ID);
@@ -5446,6 +5488,10 @@ hns3_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_promisc;
 
+	ret = hns3_restore_fec(hw);
+	if (ret)
+		goto err_promisc;
+
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED) {
 		ret = hns3_do_start(hns, false);
 		if (ret)
@@ -5524,6 +5570,313 @@ hns3_reset_service(void *param)
 		hns3_msix_process(hns, reset_level);
 }
 
+static unsigned int
+hns3_get_speed_capa_num(uint16_t device_id)
+{
+	unsigned int num;
+
+	switch (device_id) {
+	case HNS3_DEV_ID_25GE:
+	case HNS3_DEV_ID_25GE_RDMA:
+		num = 2;
+		break;
+	case HNS3_DEV_ID_100G_RDMA_MACSEC:
+	case HNS3_DEV_ID_200G_RDMA:
+		num = 1;
+		break;
+	default:
+		num = 0;
+		break;
+	}
+
+	return num;
+}
+
+static int
+hns3_get_speed_fec_capa(struct rte_eth_fec_capa *speed_fec_capa,
+			uint16_t device_id)
+{
+	switch (device_id) {
+	case HNS3_DEV_ID_25GE:
+	/* fallthrough */
+	case HNS3_DEV_ID_25GE_RDMA:
+		speed_fec_capa[0].speed = speed_fec_capa_tbl[1].speed;
+		speed_fec_capa[0].capa = speed_fec_capa_tbl[1].capa;
+
+		/* In HNS3 device, the 25G NIC is compatible with 10G rate */
+		speed_fec_capa[1].speed = speed_fec_capa_tbl[0].speed;
+		speed_fec_capa[1].capa = speed_fec_capa_tbl[0].capa;
+		break;
+	case HNS3_DEV_ID_100G_RDMA_MACSEC:
+		speed_fec_capa[0].speed = speed_fec_capa_tbl[4].speed;
+		speed_fec_capa[0].capa = speed_fec_capa_tbl[4].capa;
+		break;
+	case HNS3_DEV_ID_200G_RDMA:
+		speed_fec_capa[0].speed = speed_fec_capa_tbl[5].speed;
+		speed_fec_capa[0].capa = speed_fec_capa_tbl[5].capa;
+		break;
+	default:
+		return -ENOTSUP;
+	}
+
+	return 0;
+}
+
+static int
+hns3_fec_get_capability(struct rte_eth_dev *dev,
+			struct rte_eth_fec_capa *speed_fec_capa,
+			unsigned int num)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	uint16_t device_id = pci_dev->id.device_id;
+	unsigned int capa_num;
+	int ret;
+
+	capa_num = hns3_get_speed_capa_num(device_id);
+	if (capa_num == 0) {
+		hns3_err(hw, "device(0x%x) is not supported by hns3 PMD",
+			 device_id);
+		return -ENOTSUP;
+	}
+
+	if (speed_fec_capa == NULL || num < capa_num)
+		return capa_num;
+
+	ret = hns3_get_speed_fec_capa(speed_fec_capa, device_id);
+	if (ret)
+		return -ENOTSUP;
+
+	return capa_num;
+}
+
+static int
+get_current_fec_auto_state(struct hns3_hw *hw, uint8_t *state)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, true);
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret) {
+		hns3_err(hw, "get current fec auto state failed, ret = %d",
+			 ret);
+		return ret;
+	}
+
+	*state = req->fec_mode & (1U << HNS3_MAC_CFG_FEC_AUTO_EN_B);
+	return 0;
+}
+
+static int
+hns3_fec_get(struct rte_eth_dev *dev, uint32_t *mode)
+{
+#define QUERY_ACTIVE_SPEED	1
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_sfp_speed_cmd *resp;
+	uint32_t tmp_mode;
+	uint8_t auto_state;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	/*
+	 * 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.
+	 */
+	if (hw->mac.link_status == ETH_LINK_DOWN) {
+		ret = get_current_fec_auto_state(hw, &auto_state);
+		if (ret)
+			return ret;
+
+		if (auto_state == 0x1) {
+			*mode = RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
+			return 0;
+		}
+	}
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_SFP_GET_SPEED, true);
+	resp = (struct hns3_sfp_speed_cmd *)desc.data;
+	resp->query_type = QUERY_ACTIVE_SPEED;
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret == -EOPNOTSUPP) {
+		hns3_err(hw, "IMP do not support get FEC, ret = %d", ret);
+		return ret;
+	} else if (ret) {
+		hns3_err(hw, "get FEC failed, ret = %d", ret);
+		return ret;
+	}
+
+	/*
+	 * FEC mode order defined in hns3 hardware is inconsistend with
+	 * that defined in the ethdev library. So the sequence needs
+	 * to be converted.
+	 */
+	switch (resp->active_fec) {
+	case HNS3_HW_FEC_MODE_NOFEC:
+		tmp_mode = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
+		break;
+	case HNS3_HW_FEC_MODE_BASER:
+		tmp_mode = RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
+		break;
+	case HNS3_HW_FEC_MODE_RS:
+		tmp_mode = RTE_ETH_FEC_MODE_CAPA_MASK(RS);
+		break;
+	default:
+		tmp_mode = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
+		break;
+	}
+
+	*mode = tmp_mode;
+	return 0;
+}
+
+static int
+hns3_set_fec_hw(struct hns3_hw *hw, uint32_t mode)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, false);
+
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	switch (mode) {
+	case RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC):
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_OFF);
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(BASER):
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_BASER);
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(RS):
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_RS);
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(AUTO):
+		hns3_set_bit(req->fec_mode, HNS3_MAC_CFG_FEC_AUTO_EN_B, 1);
+		break;
+	default:
+		return 0;
+	}
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw, "set fec mode failed, ret = %d", ret);
+
+	return ret;
+}
+
+static uint32_t
+get_current_speed_fec_cap(struct hns3_hw *hw, struct rte_eth_fec_capa *fec_capa)
+{
+	struct hns3_mac *mac = &hw->mac;
+	uint32_t cur_capa;
+
+	switch (mac->link_speed) {
+	case ETH_SPEED_NUM_10G:
+		cur_capa = fec_capa[1].capa;
+		break;
+	case ETH_SPEED_NUM_25G:
+	case ETH_SPEED_NUM_100G:
+	case ETH_SPEED_NUM_200G:
+		cur_capa = fec_capa[0].capa;
+		break;
+	default:
+		cur_capa = 0;
+		break;
+	}
+
+	return cur_capa;
+}
+
+static bool
+is_fec_mode_one_bit_set(uint32_t mode)
+{
+	int cnt = 0;
+	uint8_t i;
+
+	for (i = 0; i < sizeof(mode); i++)
+		if (mode >> i & 0x1)
+			cnt++;
+
+	return cnt == 1 ? true : false;
+}
+
+static int
+hns3_fec_set(struct rte_eth_dev *dev, uint32_t mode)
+{
+#define FEC_CAPA_NUM 2
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+
+	struct rte_eth_fec_capa fec_capa[FEC_CAPA_NUM];
+	uint32_t cur_capa;
+	uint32_t num = FEC_CAPA_NUM;
+	int ret;
+
+	ret = hns3_fec_get_capability(dev, fec_capa, num);
+	if (ret < 0)
+		return ret;
+
+	/* HNS3 PMD driver only support one bit set mode, e.g. 0x1, 0x4 */
+	if (!is_fec_mode_one_bit_set(mode))
+		hns3_err(hw, "FEC mode(0x%x) not supported in HNS3 PMD,"
+			     "FEC mode should be only one bit set", mode);
+
+	/*
+	 * Check whether the configured mode is within the FEC capability.
+	 * If not, the configured mode will not be supported.
+	 */
+	cur_capa = get_current_speed_fec_cap(hw, fec_capa);
+	if (!(cur_capa & mode)) {
+		hns3_err(hw, "unsupported FEC mode = 0x%x", mode);
+		return -EINVAL;
+	}
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		return ret;
+
+	pf->fec_mode = mode;
+	return 0;
+}
+
+static int
+hns3_restore_fec(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+	uint32_t mode = pf->fec_mode;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		hns3_err(hw, "restore fec mode(0x%x) failed, ret = %d",
+			 mode, ret);
+
+	return ret;
+}
+
+static int
+hns3_query_dev_fec_info(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_fec_get(dev, &pf->fec_mode);
+	if (ret)
+		hns3_err(hw, "query device FEC info failed, ret = %d", ret);
+
+	return ret;
+}
+
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_configure      = hns3_dev_configure,
 	.dev_start          = hns3_dev_start,
@@ -5573,6 +5926,9 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.get_reg                = hns3_get_regs,
 	.get_dcb_info           = hns3_get_dcb_info,
 	.dev_supported_ptypes_get = hns3_dev_supported_ptypes_get,
+	.fec_get_capability     = hns3_fec_get_capability,
+	.fec_get                = hns3_fec_get,
+	.fec_set                = hns3_fec_set,
 };
 
 static const struct hns3_reset_ops hns3_reset_ops = {
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index fd6a9f9..393b91f 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -620,6 +620,7 @@ struct hns3_pf {
 	struct hns3_err_msix_intr_stats abn_int_stats;
 
 	bool support_sfp_query;
+	uint32_t fec_mode; /* current FEC mode for ethdev */
 
 	struct hns3_vtag_cfg vtag_config;
 	LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V13 3/3] app/testpmd: add FEC command
  2020-09-25  8:39   ` [dpdk-dev] [PATCH V13 0/3] add FEC support Min Hu (Connor)
  2020-09-25  8:39     ` [dpdk-dev] [PATCH V13 1/3] ethdev: introduce FEC API Min Hu (Connor)
  2020-09-25  8:39     ` [dpdk-dev] [PATCH V13 2/3] net/hns3: support FEC Min Hu (Connor)
@ 2020-09-25  8:39     ` Min Hu (Connor)
  2020-09-27  7:08     ` [dpdk-dev] [PATCH V13 0/3] add FEC support Min Hu (Connor)
  3 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-25  8:39 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This commit adds testpmd capability to query and config FEC
function of device. This includes:
- show FEC capabilities, example:
	testpmd> show port 0 fec capabilities
- show FEC mode, example:
	testpmd> show port 0 fec_mode
- config FEC mode, example:
	testpmd> set port <port_id> 0 <auto|off|rs|baser>

	where:

	auto|off|rs|baser are four kinds of FEC mode which dev
	support according to MAC link speed.

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>
---
v12->v13:
change fec get capa interface.

---
v10->v11:
change mode to capa bitmask.

---
v8->v9:
added acked-by.

---
v6->v7:
used RTE_DIM(fec_mode_name) instead of RTE_ETH_FEC_NUM

---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Add RTE_ prefix for public FEC mode enum.

---
v3->v4:
adjust the display format of FEC mode

---
v2->v3:
adjust the display format of FEC capability.

---
 app/test-pmd/cmdline.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c  |  91 ++++++++++++++++++++
 app/test-pmd/testpmd.h |   2 +
 3 files changed, 316 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 5f93409..407513c 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -19161,6 +19161,226 @@ cmdline_parse_inst_t cmd_show_tx_metadata = {
 	},
 };
 
+/* *** show fec capability per port configuration *** */
+struct cmd_show_fec_capability_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_fec;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_capability_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_CAP_NUM 2
+	struct cmd_show_fec_capability_result *res = parsed_result;
+	struct rte_eth_fec_capa speed_fec_capa[FEC_CAP_NUM];
+	unsigned int num = FEC_CAP_NUM;
+	unsigned int ret_num;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_fec_get_capability(res->cmd_pid, speed_fec_capa, num);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC capability failed\n");
+		return;
+	}
+
+	ret_num = (unsigned int)ret;
+	show_fec_capability(ret_num, speed_fec_capa);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_capability_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_capability_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_capability_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_capability_fec =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_fec, "fec");
+cmdline_parse_token_string_t cmd_show_fec_capability_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_keyword, "capabilities");
+
+cmdline_parse_inst_t cmd_show_capability = {
+	.f = cmd_show_fec_capability_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec capabilities",
+	.tokens = {
+		(void *)&cmd_show_fec_capability_show,
+		(void *)&cmd_show_fec_capability_port,
+		(void *)&cmd_show_fec_capability_pid,
+		(void *)&cmd_show_fec_capability_fec,
+		(void *)&cmd_show_fec_capability_keyword,
+		NULL,
+	},
+};
+
+/* *** show fec mode per port configuration *** */
+struct cmd_show_fec_metadata_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_mode_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_NAME_SIZE 16
+	struct cmd_show_fec_metadata_result *res = parsed_result;
+	uint32_t mode;
+	char buf[FEC_NAME_SIZE];
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+	ret = rte_eth_fec_get(res->cmd_pid, &mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC mode failed\n");
+		return;
+	}
+
+	switch (mode) {
+	case RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC):
+		strlcpy(buf, "off", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(AUTO):
+		strlcpy(buf, "auto", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(BASER):
+		strlcpy(buf, "baser", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(RS):
+		strlcpy(buf, "rs", sizeof(buf));
+		break;
+	default:
+		return;
+	}
+
+	printf("%s\n", buf);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_mode_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_mode_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_mode_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_mode_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_keyword, "fec_mode");
+
+cmdline_parse_inst_t cmd_show_fec_mode = {
+	.f = cmd_show_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec_mode",
+	.tokens = {
+		(void *)&cmd_show_fec_mode_show,
+		(void *)&cmd_show_fec_mode_port,
+		(void *)&cmd_show_fec_mode_pid,
+		(void *)&cmd_show_fec_mode_keyword,
+		NULL,
+	},
+};
+
+/* *** set fec mode per port configuration *** */
+struct cmd_set_port_fec_mode {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t fec_mode;
+	cmdline_fixed_string_t fec_value;
+};
+
+/* Common CLI fields for set fec mode */
+cmdline_parse_token_string_t cmd_set_port_fec_mode_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port, "port");
+cmdline_parse_token_num_t cmd_set_port_fec_mode_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_port_fec_mode_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_mode, "fec_mode");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_value =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_value, NULL);
+
+static void
+cmd_set_port_fec_mode_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	__rte_unused void *data)
+{
+	struct cmd_set_port_fec_mode *res = parsed_result;
+	uint16_t port_id = res->port_id;
+	uint32_t mode;
+	int ret;
+
+	ret = parse_fec_mode(res->fec_value, &mode);
+	if (ret < 0) {
+		printf("Unknown fec mode: %s for Port %d\n", res->fec_value,
+			port_id);
+		return;
+	}
+
+	ret = rte_eth_fec_set(port_id, mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Set FEC mode failed\n");
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_fec_mode = {
+	.f = cmd_set_port_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> fec_mode <auto|off|rs|baser>",
+	.tokens = {
+		(void *)&cmd_set_port_fec_mode_set,
+		(void *)&cmd_set_port_fec_mode_port,
+		(void *)&cmd_set_port_fec_mode_port_id,
+		(void *)&cmd_set_port_fec_mode_str,
+		(void *)&cmd_set_port_fec_mode_value,
+		NULL,
+	},
+};
+
 /* show port supported ptypes */
 
 /* Common result structure for show port ptypes */
@@ -19795,6 +20015,9 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_set_raw,
 	(cmdline_parse_inst_t *)&cmd_show_set_raw_all,
 	(cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
+	(cmdline_parse_inst_t *)&cmd_show_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_set_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_show_capability,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 2d9a456..897ceaf 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -138,6 +138,58 @@ const struct rss_type_info rss_type_table[] = {
 	{ NULL, 0 },
 };
 
+static const struct {
+	enum rte_eth_fec_mode mode;
+	const char *name;
+} fec_mode_name[] = {
+	{
+		.mode = RTE_ETH_FEC_NOFEC,
+		.name = "off",
+	},
+	{
+		.mode = RTE_ETH_FEC_AUTO,
+		.name = "auto",
+	},
+	{
+		.mode = RTE_ETH_FEC_BASER,
+		.name = "baser",
+	},
+	{
+		.mode = RTE_ETH_FEC_RS,
+		.name = "rs",
+	},
+};
+
+static const struct {
+	uint32_t speed;
+	const char *name;
+} eth_speed_name[] = {
+	{
+		.speed = ETH_SPEED_NUM_10G,
+		.name = "Speed 10G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_25G,
+		.name = "Speed 25G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_40G,
+		.name = "Speed 40G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_50G,
+		.name = "Speed 50G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_100G,
+		.name = "Speed 100G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_200G,
+		.name = "Speed 200G",
+	},
+};
+
 static void
 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
 {
@@ -2969,6 +3021,45 @@ set_tx_pkt_split(const char *name)
 	printf("unknown value: \"%s\"\n", name);
 }
 
+int
+parse_fec_mode(const char *name, uint32_t *mode)
+{
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(fec_mode_name); i++) {
+		if (strcmp(fec_mode_name[i].name, name) == 0) {
+			*mode = RTE_ETH_FEC_MODE_TO_CAPA(fec_mode_name[i].mode);
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void
+show_fec_capability(unsigned int num, struct rte_eth_fec_capa *speed_fec_capa)
+{
+	unsigned int i, j, k;
+
+	printf("FEC capabilities:\n");
+
+	for (i = 0; i < num; i++) {
+		for (j = 0; j < RTE_DIM(eth_speed_name); j++) {
+			if (eth_speed_name[j].speed ==
+						speed_fec_capa[i].speed) {
+				printf("%s : ", eth_speed_name[j].name);
+				break;
+			}
+		}
+
+		for (k = RTE_ETH_FEC_AUTO; k < RTE_DIM(fec_mode_name); k++) {
+			if (RTE_ETH_FEC_MODE_TO_CAPA(k) &
+						speed_fec_capa[i].capa)
+				printf("%s ", fec_mode_name[k].name);
+		}
+		printf("\n");
+	}
+}
+
 void
 show_tx_pkt_segments(void)
 {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index f139fe7..85ea030 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -804,6 +804,8 @@ void show_tx_pkt_segments(void);
 void set_tx_pkt_times(unsigned int *tx_times);
 void show_tx_pkt_times(void);
 void set_tx_pkt_split(const char *name);
+int parse_fec_mode(const char *name, enum rte_eth_fec_mode *mode);
+void show_fec_capability(uint32_t num, struct rte_eth_fec_capa *speed_fec_capa);
 void set_nb_pkt_per_burst(uint16_t pkt_burst);
 char *list_pkt_forwarding_modes(void);
 char *list_pkt_forwarding_retry_modes(void);
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V12 1/4] ethdev: introduce FEC API
  2020-09-24 14:46       ` Andrew Rybchenko
@ 2020-09-25  8:47         ` Min Hu (Connor)
  2020-09-25 15:36           ` Ajit Khaparde
  0 siblings, 1 reply; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-25  8:47 UTC (permalink / raw)
  To: Andrew Rybchenko, dev; +Cc: konstantin.ananyev, thomas, ferruh.yigit, linuxarm

HI,Andrew,
	I fix it in V13 according to your advice.
	Thanks for  your patient review. Please check it out again.

By the way, there is always a coding check warning, like this:

WARNING:PREFER_FALLTHROUGH: Prefer 'fallthrough;' over fallthrough comment
#264: FILE: drivers/net/hns3/hns3_ethdev.c:5601:
+	/* fallthrough */

total: 0 errors, 1 warnings, 0 checks, 439 lines checked.

I have tried some ways, but it does not help.
Could you giver some advice?
	thanks.


在 2020/9/24 22:46, Andrew Rybchenko 写道:
> On 9/24/20 4:05 PM, 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.
> 
> Almost good now. See my notes below.
> Many thanks for hard work and patience.
> 
>>
>> 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>
> 
> I think that tags for Ajit and Konstantin should be
> dropped, since API changes significantly after their review.
> 
>> ---
>> v10->v11:
>> allow to report capabilities per link speed.
>> specify what should be reported if link is down
>> when get FEC.
>> change mode to capa bitmask.
>>
>> ---
>> v9->v10:
>> add macro RTE_ETH_FEC_MODE_CAPA_MASK(x) to indicate
>> different FEC mode capa.
>>
>> ---
>> 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.
>>
>> ---
>>   lib/librte_ethdev/rte_ethdev.c           | 37 +++++++++++++
>>   lib/librte_ethdev/rte_ethdev.h           | 91 ++++++++++++++++++++++++++++++++
>>   lib/librte_ethdev/rte_ethdev_driver.h    | 82 ++++++++++++++++++++++++++++
>>   lib/librte_ethdev/rte_ethdev_version.map |  3 ++
>>   4 files changed, 213 insertions(+)
>>
>> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
>> index dfe5c1b..b614bfc 100644
>> --- a/lib/librte_ethdev/rte_ethdev.c
>> +++ b/lib/librte_ethdev/rte_ethdev.c
>> @@ -3679,6 +3679,43 @@ 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 *num,
>> +			   struct rte_eth_fec_capa *speed_fec_capa)
>> +{
>> +	struct rte_eth_dev *dev;
>> +
>> +	if (num == NULL || speed_fec_capa == NULL)
>> +		return -EINVAL;
> 
> I think it is OK to have speed_fec_cap==NULL if *num is 0.
> I.e. a request to get number of required array entries.
> 
>> +
>> +	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, num,
>> +							speed_fec_capa));
>> +}
>> +
>> +int
>> +rte_eth_fec_get(uint16_t port_id, uint32_t *mode)
>> +{
>> +	struct rte_eth_dev *dev;
> 
> I think it would be good to check that mode is not NULL here.
> 
>> +
>> +	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, uint32_t mode)
>> +{
>> +	struct rte_eth_dev *dev;
>> +
>> +	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 645a186..104181d 100644
>> --- a/lib/librte_ethdev/rte_ethdev.h
>> +++ b/lib/librte_ethdev/rte_ethdev.h
>> @@ -1544,6 +1544,29 @@ struct rte_eth_dcb_info {
>>   	struct rte_eth_dcb_tc_queue_mapping tc_queue;
>>   };
>>   
>> +/**
>> + * This enum indicates the possible (forward error correction)FEC modes
> 
> (forward error correction)FEC -> Forward Error Correction (FEC)
> 
>> + * 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 */
>> +};
>> +
>> +/* Translate from FEC mode to FEC capa */
>> +#define RTE_ETH_FEC_MODE_TO_CAPA(x)	(1U << (x))
>> +
>> +/* This macro indicates FEC capa mask*/
> 
> Add missing space before */
> 
>> +#define RTE_ETH_FEC_MODE_CAPA_MASK(x)	(1U << (RTE_ETH_FEC_ ## x))
>> +
>> +/* A structure used to get capabilities per link speed */
>> +struct rte_eth_fec_capa {
>> +	uint32_t speed; /**< Link speed (see ETH_SPEED_NUM_*) */
>> +	uint32_t capa;  /**< FEC capabilities bitmask (see RTE_FEC_CAPA_*) */
>> +};
>> +
>>   #define RTE_ETH_ALL RTE_MAX_ETHPORTS
>>   
>>   /* Macros to check for valid port */
>> @@ -3397,6 +3420,74 @@ 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 num
>> + *   the num is in/out with a number of elements in an array.
> 
> Please, see below my notes on callback description.
> 
>> + * @param speed_fec_capa
>> + *   speed_fec_capa is out only with per-speed capabilities.
>> + *
>> + * @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.
>> + *   - (-EINVAL)  if *num* or *speed_fec_capa* invalid
>> + */
>> +__rte_experimental
>> +int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *num,
>> +			struct rte_eth_fec_capa *speed_fec_capa);
>> +
>> +/**
>> + * @warning
>> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
>> + *
>> + * Get current Forward Error Correction(FEC) mode.
>> + * 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.
>> + *
>> + * @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, uint32_t *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.
> 
> See below.
> 
>> + * @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, uint32_t mode);
>> +
>> +/**
>>    * Get current status of the Ethernet link flow control for Ethernet device
>>    *
>>    * @param port_id
>> diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
>> index 23cc1e0..625b8c5 100644
>> --- a/lib/librte_ethdev/rte_ethdev_driver.h
>> +++ b/lib/librte_ethdev/rte_ethdev_driver.h
>> @@ -575,6 +575,81 @@ 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 num
>> + *   the num is in/out with a number of elements in an array.
> 
> I'm sorry, I should do it before my previous suggestion, but:
> Looking at rte_eth_xstats_get_names() and trying to be
> consistent I'd like to suggest to put the argument after
> speed_fec_capa and make it input only with a number of
> array elements.
> Positive return values should be used to provide number of
> filled in array elements. If the returned value is greater
> than 'num', just provided elements are filled in, but
> it is indication as well, that num is too small.
> 
>> + * @param speed_fec_capa
>> + *   speed_fec_capa is out only with per-speed capabilities.
>> + *
>> + * @return
>> + *   Negative errno value on error, 0 on success.
>> + *
>> + * @retval 0
>> + *   Success, get FEC success.
> 
> See above.
> 
>> + * @retval -ENOTSUP
>> + *   operation is not supported.
> 
> Should start from upper case letter
> 
>> + * @retval -EIO
>> + *   device is removed.
> 
> Should start from upper case letter
> 
>> + * @retval -ENODEV
>> + *   Device is gone.
> 
> What's the difference between "device is remove" and
> "Device is gone"
> 
>> + * @retval -EINVAL
>> + *   *num* or *speed_fec_capa* invalid.
>> + */
>> +typedef int (*eth_fec_get_capability_t)(struct rte_eth_dev *dev, uint32_t *num,
>> +				struct rte_eth_fec_capa *speed_fec_capa);
>> +
>> +/**
>> + * @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.
> 
> Should start from upper case letter
> 
>> + * @retval -EIO
>> + *   device is removed.
> 
> Should start from upper case letter
> 
>> + * @retval -ENODEV
>> + *   Device is gone.
>> + */
>> +typedef int (*eth_fec_get_t)(struct rte_eth_dev *dev,
>> +			     uint32_t *mode);
>> +
>> +/**
>> + * @internal
>> + *   Set Forward Error Correction(FEC) mode.
> 
> Remove extra spaces before "Set"
> 
>> + *
>> + * @param dev
>> + *   ethdev handle of port.
>> + * @param mode
>> + *   the FEC mode.
> 
> The description is insufficient and misleading.
> It should be fec_capa and described as:
> Bitmask of allowed FEC modes. If must be only one
> if AUTO is disabled. If AUTO is enabled, other
> bits specify FEC modes which may be negotiated.
> 
>> + *
>> + * @return
>> + *   Negative errno value on error, 0 on success.
>> + *
>> + * @retval 0
>> + *   Success, set FEC success.
>> + * @retval -ENOTSUP
>> + *   operation is not supported.
> 
> Should start from upper case letter
> 
> What about -EINVAL in the case of unsupported FEC mode
> requested? It is listed above in API function but
> missing here.
> 
>> + * @retval -EIO
>> + *   device is removed.
> 
> Should start from upper case letter
> 
>> + * @retval -ENODEV
>> + *   Device is gone.
> 
> What's the difference between "device is remove" and
> "Device is gone"
> 
>> + */
>> +typedef int (*eth_fec_set_t)(struct rte_eth_dev *dev, uint32_t mode);
>> +
>> +/**
>>    * @internal A structure containing the functions exported by an Ethernet driver.
>>    */
>>   struct eth_dev_ops {
>> @@ -713,6 +788,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; */
> 
> It should be a dot (.) at the end, not semicolon (;).
> 
>> +	eth_fec_get_t fec_get;
>> +	/**< Get Forward Error Correction(FEC) mode; */
> 
> same
> 
>> +	eth_fec_set_t fec_set;
>> +	/**< Set Forward Error Correction(FEC) mode; */
> 
> same
> 
>>   };
>>   
>>   /**
>> diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
>> index c95ef51..b9ace3a 100644
>> --- a/lib/librte_ethdev/rte_ethdev_version.map
>> +++ b/lib/librte_ethdev/rte_ethdev_version.map
>> @@ -229,6 +229,9 @@ EXPERIMENTAL {
>>   	# added in 20.11
>>   	rte_eth_link_speed_to_str;
>>   	rte_eth_link_to_str;
>> +	rte_eth_fec_get_capability;
>> +	rte_eth_fec_get;
>> +	rte_eth_fec_set;
>>   };
>>   
>>   INTERNAL {
>>
> 
> .
> 

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V12 1/4] ethdev: introduce FEC API
  2020-09-25  8:47         ` Min Hu (Connor)
@ 2020-09-25 15:36           ` Ajit Khaparde
  2020-09-25 16:12             ` Stephen Hemminger
  0 siblings, 1 reply; 118+ messages in thread
From: Ajit Khaparde @ 2020-09-25 15:36 UTC (permalink / raw)
  To: Min Hu (Connor)
  Cc: Andrew Rybchenko, dpdk-dev, Ananyev, Konstantin, Thomas Monjalon,
	Ferruh Yigit, linuxarm

On Fri, Sep 25, 2020 at 1:47 AM Min Hu (Connor) <humin29@huawei.com> wrote:
>
> HI,Andrew,
>         I fix it in V13 according to your advice.
>         Thanks for  your patient review. Please check it out again.
>
> By the way, there is always a coding check warning, like this:
>
> WARNING:PREFER_FALLTHROUGH: Prefer 'fallthrough;' over fallthrough comment
> #264: FILE: drivers/net/hns3/hns3_ethdev.c:5601:
> +       /* fallthrough */
Try /* FALLTHROUGH */

>
> total: 0 errors, 1 warnings, 0 checks, 439 lines checked.
>
> I have tried some ways, but it does not help.
> Could you giver some advice?
>         thanks.
>
>
> 在 2020/9/24 22:46, Andrew Rybchenko 写道:
> > On 9/24/20 4:05 PM, 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.
> >
> > Almost good now. See my notes below.
> > Many thanks for hard work and patience.
> >
> >>
> >> 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>
> >
> > I think that tags for Ajit and Konstantin should be
> > dropped, since API changes significantly after their review.
> >
> >> ---
> >> v10->v11:
> >> allow to report capabilities per link speed.
> >> specify what should be reported if link is down
> >> when get FEC.
> >> change mode to capa bitmask.
> >>
> >> ---
> >> v9->v10:
> >> add macro RTE_ETH_FEC_MODE_CAPA_MASK(x) to indicate
> >> different FEC mode capa.
> >>
> >> ---
> >> 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.
> >>
> >> ---
> >>   lib/librte_ethdev/rte_ethdev.c           | 37 +++++++++++++
> >>   lib/librte_ethdev/rte_ethdev.h           | 91 ++++++++++++++++++++++++++++++++
> >>   lib/librte_ethdev/rte_ethdev_driver.h    | 82 ++++++++++++++++++++++++++++
> >>   lib/librte_ethdev/rte_ethdev_version.map |  3 ++
> >>   4 files changed, 213 insertions(+)
> >>
> >> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> >> index dfe5c1b..b614bfc 100644
> >> --- a/lib/librte_ethdev/rte_ethdev.c
> >> +++ b/lib/librte_ethdev/rte_ethdev.c
> >> @@ -3679,6 +3679,43 @@ 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 *num,
> >> +                       struct rte_eth_fec_capa *speed_fec_capa)
> >> +{
> >> +    struct rte_eth_dev *dev;
> >> +
> >> +    if (num == NULL || speed_fec_capa == NULL)
> >> +            return -EINVAL;
> >
> > I think it is OK to have speed_fec_cap==NULL if *num is 0.
> > I.e. a request to get number of required array entries.
> >
> >> +
> >> +    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, num,
> >> +                                                    speed_fec_capa));
> >> +}
> >> +
> >> +int
> >> +rte_eth_fec_get(uint16_t port_id, uint32_t *mode)
> >> +{
> >> +    struct rte_eth_dev *dev;
> >
> > I think it would be good to check that mode is not NULL here.
> >
> >> +
> >> +    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, uint32_t mode)
> >> +{
> >> +    struct rte_eth_dev *dev;
> >> +
> >> +    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 645a186..104181d 100644
> >> --- a/lib/librte_ethdev/rte_ethdev.h
> >> +++ b/lib/librte_ethdev/rte_ethdev.h
> >> @@ -1544,6 +1544,29 @@ struct rte_eth_dcb_info {
> >>      struct rte_eth_dcb_tc_queue_mapping tc_queue;
> >>   };
> >>
> >> +/**
> >> + * This enum indicates the possible (forward error correction)FEC modes
> >
> > (forward error correction)FEC -> Forward Error Correction (FEC)
> >
> >> + * 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 */
> >> +};
> >> +
> >> +/* Translate from FEC mode to FEC capa */
> >> +#define RTE_ETH_FEC_MODE_TO_CAPA(x) (1U << (x))
> >> +
> >> +/* This macro indicates FEC capa mask*/
> >
> > Add missing space before */
> >
> >> +#define RTE_ETH_FEC_MODE_CAPA_MASK(x)       (1U << (RTE_ETH_FEC_ ## x))
> >> +
> >> +/* A structure used to get capabilities per link speed */
> >> +struct rte_eth_fec_capa {
> >> +    uint32_t speed; /**< Link speed (see ETH_SPEED_NUM_*) */
> >> +    uint32_t capa;  /**< FEC capabilities bitmask (see RTE_FEC_CAPA_*) */
> >> +};
> >> +
> >>   #define RTE_ETH_ALL RTE_MAX_ETHPORTS
> >>
> >>   /* Macros to check for valid port */
> >> @@ -3397,6 +3420,74 @@ 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 num
> >> + *   the num is in/out with a number of elements in an array.
> >
> > Please, see below my notes on callback description.
> >
> >> + * @param speed_fec_capa
> >> + *   speed_fec_capa is out only with per-speed capabilities.
> >> + *
> >> + * @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.
> >> + *   - (-EINVAL)  if *num* or *speed_fec_capa* invalid
> >> + */
> >> +__rte_experimental
> >> +int rte_eth_fec_get_capability(uint16_t port_id, uint32_t *num,
> >> +                    struct rte_eth_fec_capa *speed_fec_capa);
> >> +
> >> +/**
> >> + * @warning
> >> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> >> + *
> >> + * Get current Forward Error Correction(FEC) mode.
> >> + * 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.
> >> + *
> >> + * @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, uint32_t *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.
> >
> > See below.
> >
> >> + * @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, uint32_t mode);
> >> +
> >> +/**
> >>    * Get current status of the Ethernet link flow control for Ethernet device
> >>    *
> >>    * @param port_id
> >> diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
> >> index 23cc1e0..625b8c5 100644
> >> --- a/lib/librte_ethdev/rte_ethdev_driver.h
> >> +++ b/lib/librte_ethdev/rte_ethdev_driver.h
> >> @@ -575,6 +575,81 @@ 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 num
> >> + *   the num is in/out with a number of elements in an array.
> >
> > I'm sorry, I should do it before my previous suggestion, but:
> > Looking at rte_eth_xstats_get_names() and trying to be
> > consistent I'd like to suggest to put the argument after
> > speed_fec_capa and make it input only with a number of
> > array elements.
> > Positive return values should be used to provide number of
> > filled in array elements. If the returned value is greater
> > than 'num', just provided elements are filled in, but
> > it is indication as well, that num is too small.
> >
> >> + * @param speed_fec_capa
> >> + *   speed_fec_capa is out only with per-speed capabilities.
> >> + *
> >> + * @return
> >> + *   Negative errno value on error, 0 on success.
> >> + *
> >> + * @retval 0
> >> + *   Success, get FEC success.
> >
> > See above.
> >
> >> + * @retval -ENOTSUP
> >> + *   operation is not supported.
> >
> > Should start from upper case letter
> >
> >> + * @retval -EIO
> >> + *   device is removed.
> >
> > Should start from upper case letter
> >
> >> + * @retval -ENODEV
> >> + *   Device is gone.
> >
> > What's the difference between "device is remove" and
> > "Device is gone"
> >
> >> + * @retval -EINVAL
> >> + *   *num* or *speed_fec_capa* invalid.
> >> + */
> >> +typedef int (*eth_fec_get_capability_t)(struct rte_eth_dev *dev, uint32_t *num,
> >> +                            struct rte_eth_fec_capa *speed_fec_capa);
> >> +
> >> +/**
> >> + * @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.
> >
> > Should start from upper case letter
> >
> >> + * @retval -EIO
> >> + *   device is removed.
> >
> > Should start from upper case letter
> >
> >> + * @retval -ENODEV
> >> + *   Device is gone.
> >> + */
> >> +typedef int (*eth_fec_get_t)(struct rte_eth_dev *dev,
> >> +                         uint32_t *mode);
> >> +
> >> +/**
> >> + * @internal
> >> + *   Set Forward Error Correction(FEC) mode.
> >
> > Remove extra spaces before "Set"
> >
> >> + *
> >> + * @param dev
> >> + *   ethdev handle of port.
> >> + * @param mode
> >> + *   the FEC mode.
> >
> > The description is insufficient and misleading.
> > It should be fec_capa and described as:
> > Bitmask of allowed FEC modes. If must be only one
> > if AUTO is disabled. If AUTO is enabled, other
> > bits specify FEC modes which may be negotiated.
> >
> >> + *
> >> + * @return
> >> + *   Negative errno value on error, 0 on success.
> >> + *
> >> + * @retval 0
> >> + *   Success, set FEC success.
> >> + * @retval -ENOTSUP
> >> + *   operation is not supported.
> >
> > Should start from upper case letter
> >
> > What about -EINVAL in the case of unsupported FEC mode
> > requested? It is listed above in API function but
> > missing here.
> >
> >> + * @retval -EIO
> >> + *   device is removed.
> >
> > Should start from upper case letter
> >
> >> + * @retval -ENODEV
> >> + *   Device is gone.
> >
> > What's the difference between "device is remove" and
> > "Device is gone"
> >
> >> + */
> >> +typedef int (*eth_fec_set_t)(struct rte_eth_dev *dev, uint32_t mode);
> >> +
> >> +/**
> >>    * @internal A structure containing the functions exported by an Ethernet driver.
> >>    */
> >>   struct eth_dev_ops {
> >> @@ -713,6 +788,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; */
> >
> > It should be a dot (.) at the end, not semicolon (;).
> >
> >> +    eth_fec_get_t fec_get;
> >> +    /**< Get Forward Error Correction(FEC) mode; */
> >
> > same
> >
> >> +    eth_fec_set_t fec_set;
> >> +    /**< Set Forward Error Correction(FEC) mode; */
> >
> > same
> >
> >>   };
> >>
> >>   /**
> >> diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
> >> index c95ef51..b9ace3a 100644
> >> --- a/lib/librte_ethdev/rte_ethdev_version.map
> >> +++ b/lib/librte_ethdev/rte_ethdev_version.map
> >> @@ -229,6 +229,9 @@ EXPERIMENTAL {
> >>      # added in 20.11
> >>      rte_eth_link_speed_to_str;
> >>      rte_eth_link_to_str;
> >> +    rte_eth_fec_get_capability;
> >> +    rte_eth_fec_get;
> >> +    rte_eth_fec_set;
> >>   };
> >>
> >>   INTERNAL {
> >>
> >
> > .
> >

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V12 1/4] ethdev: introduce FEC API
  2020-09-25 15:36           ` Ajit Khaparde
@ 2020-09-25 16:12             ` Stephen Hemminger
  2020-09-25 16:38               ` Ferruh Yigit
  0 siblings, 1 reply; 118+ messages in thread
From: Stephen Hemminger @ 2020-09-25 16:12 UTC (permalink / raw)
  To: Ajit Khaparde
  Cc: Min Hu (Connor),
	Andrew Rybchenko, dpdk-dev, Ananyev, Konstantin, Thomas Monjalon,
	Ferruh Yigit, linuxarm

On Fri, 25 Sep 2020 08:36:06 -0700
Ajit Khaparde <ajit.khaparde@broadcom.com> wrote:

> >
> > WARNING:PREFER_FALLTHROUGH: Prefer 'fallthrough;' over fallthrough comment
> > #264: FILE: drivers/net/hns3/hns3_ethdev.c:5601:
> > +       /* fallthrough */  
> Try /* FALLTHROUGH */

That won't work either.

This is a new warning from upstream Linux kernel checkpatch.
The Linux kernel has converted code to use a new macro.

The warning should be silenced by the DPDK checkpatch script.

diff --git a/devtools/checkpatches.sh b/devtools/checkpatches.sh
index 78a408ef9823..923ff6f7d9ee 100755
--- a/devtools/checkpatches.sh
+++ b/devtools/checkpatches.sh
@@ -33,7 +33,7 @@ VOLATILE,PREFER_PACKED,PREFER_ALIGNED,PREFER_PRINTF,\
 PREFER_KERNEL_TYPES,PREFER_FALLTHROUGH,BIT_MACRO,CONST_STRUCT,\
 SPLIT_STRING,LONG_LINE_STRING,C99_COMMENT_TOLERANCE,\
 LINE_SPACING,PARENTHESIS_ALIGNMENT,NETWORKING_BLOCK_COMMENT_STYLE,\
-NEW_TYPEDEFS,COMPARISON_TO_NULL"
+NEW_TYPEDEFS,COMPARISON_TO_NULL,PREFER_FALLTHROUGH"
 options="$options $DPDK_CHECKPATCH_OPTIONS"

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V12 1/4] ethdev: introduce FEC API
  2020-09-25 16:12             ` Stephen Hemminger
@ 2020-09-25 16:38               ` Ferruh Yigit
  0 siblings, 0 replies; 118+ messages in thread
From: Ferruh Yigit @ 2020-09-25 16:38 UTC (permalink / raw)
  To: Stephen Hemminger, Ajit Khaparde
  Cc: Min Hu (Connor),
	Andrew Rybchenko, dpdk-dev, Ananyev, Konstantin, Thomas Monjalon,
	linuxarm

On 9/25/2020 5:12 PM, Stephen Hemminger wrote:
> On Fri, 25 Sep 2020 08:36:06 -0700
> Ajit Khaparde <ajit.khaparde@broadcom.com> wrote:
> 
>>>
>>> WARNING:PREFER_FALLTHROUGH: Prefer 'fallthrough;' over fallthrough comment
>>> #264: FILE: drivers/net/hns3/hns3_ethdev.c:5601:
>>> +       /* fallthrough */
>> Try /* FALLTHROUGH */
> 
> That won't work either.
> 
> This is a new warning from upstream Linux kernel checkpatch.
> The Linux kernel has converted code to use a new macro.
> 
> The warning should be silenced by the DPDK checkpatch script.
> 
> diff --git a/devtools/checkpatches.sh b/devtools/checkpatches.sh
> index 78a408ef9823..923ff6f7d9ee 100755
> --- a/devtools/checkpatches.sh
> +++ b/devtools/checkpatches.sh
> @@ -33,7 +33,7 @@ VOLATILE,PREFER_PACKED,PREFER_ALIGNED,PREFER_PRINTF,\
>   PREFER_KERNEL_TYPES,PREFER_FALLTHROUGH,BIT_MACRO,CONST_STRUCT,\
>   SPLIT_STRING,LONG_LINE_STRING,C99_COMMENT_TOLERANCE,\
>   LINE_SPACING,PARENTHESIS_ALIGNMENT,NETWORKING_BLOCK_COMMENT_STYLE,\
> -NEW_TYPEDEFS,COMPARISON_TO_NULL"
> +NEW_TYPEDEFS,COMPARISON_TO_NULL,PREFER_FALLTHROUGH"
>   options="$options $DPDK_CHECKPATCH_OPTIONS"
> 

It should be already applied: https://patches.dpdk.org/patch/75173/
https://git.dpdk.org/dpdk/commit/?id=fcea4c8e29b6


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V13 0/3] add FEC support
  2020-09-25  8:39   ` [dpdk-dev] [PATCH V13 0/3] add FEC support Min Hu (Connor)
                       ` (2 preceding siblings ...)
  2020-09-25  8:39     ` [dpdk-dev] [PATCH V13 3/3] app/testpmd: add FEC command Min Hu (Connor)
@ 2020-09-27  7:08     ` Min Hu (Connor)
  2020-09-28 10:27       ` Ferruh Yigit
  3 siblings, 1 reply; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-27  7:08 UTC (permalink / raw)
  To: dev; +Cc: thomas, ferruh.yigit, linuxarm, konstantin.ananyev, arybchenko

Hello,
	Are there any suggustions for this set patches ?


在 2020/9/25 16:39, Min Hu (Connor) 写道:
> This series add FEC support for ethdev.
> 
> Min Hu (Connor) (3):
>    ethdev: introduce FEC API
>    net/hns3: support FEC
>    app/testpmd: add FEC command
> 
>   app/test-pmd/cmdline.c                   | 223 +++++++++++++++++++
>   app/test-pmd/config.c                    |  91 ++++++++
>   app/test-pmd/testpmd.h                   |   2 +
>   doc/guides/rel_notes/release_20_11.rst   |  10 +
>   drivers/net/hns3/hns3_cmd.h              |  19 +-
>   drivers/net/hns3/hns3_ethdev.c           | 356 +++++++++++++++++++++++++++++++
>   drivers/net/hns3/hns3_ethdev.h           |   1 +
>   lib/librte_ethdev/rte_ethdev.c           |  43 ++++
>   lib/librte_ethdev/rte_ethdev.h           |  94 ++++++++
>   lib/librte_ethdev/rte_ethdev_driver.h    |  80 +++++++
>   lib/librte_ethdev/rte_ethdev_version.map |   3 +
>   11 files changed, 921 insertions(+), 1 deletion(-)
> 

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V13 1/3] ethdev: introduce FEC API
  2020-09-25  8:39     ` [dpdk-dev] [PATCH V13 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-28  7:35       ` Andrew Rybchenko
  2020-09-28 11:13         ` Min Hu (Connor)
  0 siblings, 1 reply; 118+ messages in thread
From: Andrew Rybchenko @ 2020-09-28  7:35 UTC (permalink / raw)
  To: Min Hu (Connor), dev
  Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

On 9/25/20 11:39 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>

With few nits below:
Acked-by: Andrew Rybchenko <arybchenko@solarflare.com>

> ---
> v12->v13:
> change fec get capa API.
> fix comment styles.
> 
> ---
> v10->v11:
> allow to report capabilities per link speed.
> specify what should be reported if link is down
> when get FEC.
> change mode to capa bitmask.
> 
> ---
> v9->v10:
> add macro RTE_ETH_FEC_MODE_CAPA_MASK(x) to indicate
> different FEC mode capa.
> 
> ---
> 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   |  5 ++
>  lib/librte_ethdev/rte_ethdev.c           | 43 +++++++++++++++
>  lib/librte_ethdev/rte_ethdev.h           | 94 ++++++++++++++++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev_driver.h    | 80 +++++++++++++++++++++++++++
>  lib/librte_ethdev/rte_ethdev_version.map |  3 +
>  5 files changed, 225 insertions(+)
> 
> diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
> index c6642f5..1f04bd5 100644
> --- a/doc/guides/rel_notes/release_20_11.rst
> +++ b/doc/guides/rel_notes/release_20_11.rst
> @@ -78,6 +78,11 @@ New Features
>      ``--portmask=N``
>      where N represents the hexadecimal bitmask of ports used.
>  
> +* **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.
> +
>  
>  Removed Items
>  -------------
> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> index dfe5c1b..86ead87 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -3679,6 +3679,49 @@ 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,
> +			   struct rte_eth_fec_capa *speed_fec_capa,
> +			   unsigned int num)
> +{
> +	struct rte_eth_dev *dev;
> +	int ret;

if (speed_fec_capa == NULL && num > 0)
        return -EINVAL;

> +
> +	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);
> +	ret = (*dev->dev_ops->fec_get_capability)(dev, speed_fec_capa, num);
> +	if (ret > (int)num)
> +		RTE_ETHDEV_LOG(ERR, "Insufficient num, num should be no less than %d\n",
> +			       ret);

It is incorrect to log error, since
    num = rte_eth_fec_get_capability(port_id, NULL, 0);
may be used to obtain required number of array elements
(nothing bad is happening).

> +
> +	return ret;
> +}
> +
> +int
> +rte_eth_fec_get(uint16_t port_id, uint32_t *mode)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	if (mode == NULL)
> +		return -EINVAL;
> +
> +	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, uint32_t 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_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 645a186..04525a8 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -1544,6 +1544,29 @@ 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 */
> +};
> +
> +/* Translate from FEC mode to FEC capa */
> +#define RTE_ETH_FEC_MODE_TO_CAPA(x)	(1U << (x))
> +
> +/* This macro indicates FEC capa mask */
> +#define RTE_ETH_FEC_MODE_CAPA_MASK(x)	(1U << (RTE_ETH_FEC_ ## x))
> +
> +/* A structure used to get capabilities per link speed */
> +struct rte_eth_fec_capa {
> +	uint32_t speed; /**< Link speed (see ETH_SPEED_NUM_*) */
> +	uint32_t capa;  /**< FEC capabilities bitmask (see RTE_FEC_CAPA_*) */

Thre is no RTE_FEC_CAPA_* enum/defnes any more.
I'd just remove everything in parenthesis.

> +};
> +
>  #define RTE_ETH_ALL RTE_MAX_ETHPORTS
>  
>  /* Macros to check for valid port */
> @@ -3397,6 +3420,77 @@ 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 speed_fec_capa
> + *   speed_fec_capa is out only with per-speed capabilities.
> + *   If set to NULL, the function returns the required number
> + *   of required array entries.
> + * @param num
> + *   the num is in/out with a number of elements in an array.

Just (it it not in/out now):
   a number of elements in an speed_fec_capa array

> + *
> + * @return
> + *   - (0) if successful.

Wrong description. Any non-negative return value is success
(number of speed_fec_capa array elements filled in)

> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> + *     that operation.
> + *   - (-EIO) if device is removed.
> + *   - (-ENODEV)  if *port_id* invalid.
> + *   - (-EINVAL)  if *num* or *speed_fec_capa* invalid
> + */
> +__rte_experimental
> +int rte_eth_fec_get_capability(uint16_t port_id,
> +			       struct rte_eth_fec_capa *speed_fec_capa,
> +			       unsigned int num);
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get current Forward Error Correction(FEC) mode.
> + * 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.
> + *
> + * @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, uint32_t *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.

mode -> fec_capa
A bitmask of enabled FEC modes. If AUTO bit is set, other
bits specify FEC modes which may be negotiated. If AUTO
bit is clear, specify FEC modes to be used (only one valid
mode per speed may be set).

> + * @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, uint32_t mode);
> +
> +/**
>   * Get current status of the Ethernet link flow control for Ethernet device
>   *
>   * @param port_id
> diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
> index 23cc1e0..306f3a6 100644
> --- a/lib/librte_ethdev/rte_ethdev_driver.h
> +++ b/lib/librte_ethdev/rte_ethdev_driver.h
> @@ -575,6 +575,79 @@ 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 speed_fec_capa
> + *   speed_fec_capa is out only with per-speed capabilities.
> + * @param num
> + *   the num is in/out with a number of elements in an array.

same as above

> + *
> + * @return
> + *   Negative errno value on error, 0 on success.
> + *
> + * @retval 0
> + *   Success, get FEC success.

same as above

> + * @retval -ENOTSUP
> + *   Operation is not supported.
> + * @retval -EIO
> + *   Device is removed.
> + * @retval -EINVAL
> + *   *num* or *speed_fec_capa* invalid.
> + */
> +typedef int (*eth_fec_get_capability_t)(struct rte_eth_dev *dev,
> +		struct rte_eth_fec_capa *speed_fec_capa, unsigned int num);
> +
> +/**
> + * @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.
> + */
> +typedef int (*eth_fec_get_t)(struct rte_eth_dev *dev,
> +			     uint32_t *mode);
> +
> +/**
> + * @internal
> + * Set Forward Error Correction(FEC) mode.
> + *
> + * @param dev
> + *   ethdev handle of port.
> + * @param mode

similar as aboe I suggest to name it fec_capa,
since it is not a single mode

> + *   bitmask of allowed FEC modes. It must be only one
> + *   if AUTO is disabled. If AUTO is enabled, other
> + *   bits specify FEC modes which may be negotiated.
> + *
> + * @return
> + *   Negative errno value on error, 0 on success.
> + *
> + * @retval 0
> + *   Success, set FEC success.
> + * @retval -ENOTSUP
> + *   Operation is not supported.
> + * @retval -EINVAL
> + *   Unsupported FEC mode requested.
> + * @retval -EIO
> + *   Device is removed.
> + */
> +typedef int (*eth_fec_set_t)(struct rte_eth_dev *dev, uint32_t mode);
> +
> +/**
>   * @internal A structure containing the functions exported by an Ethernet driver.
>   */
>  struct eth_dev_ops {
> @@ -713,6 +786,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 c95ef51..b9ace3a 100644
> --- a/lib/librte_ethdev/rte_ethdev_version.map
> +++ b/lib/librte_ethdev/rte_ethdev_version.map
> @@ -229,6 +229,9 @@ EXPERIMENTAL {
>  	# added in 20.11
>  	rte_eth_link_speed_to_str;
>  	rte_eth_link_to_str;
> +	rte_eth_fec_get_capability;
> +	rte_eth_fec_get;
> +	rte_eth_fec_set;
>  };
>  
>  INTERNAL {
> 


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V13 0/3] add FEC support
  2020-09-27  7:08     ` [dpdk-dev] [PATCH V13 0/3] add FEC support Min Hu (Connor)
@ 2020-09-28 10:27       ` Ferruh Yigit
  2020-09-28 11:11         ` Min Hu (Connor)
  0 siblings, 1 reply; 118+ messages in thread
From: Ferruh Yigit @ 2020-09-28 10:27 UTC (permalink / raw)
  To: Min Hu (Connor), dev; +Cc: thomas, linuxarm, konstantin.ananyev, arybchenko

On 9/27/2020 8:08 AM, Min Hu (Connor) wrote:
> Hello,
>      Are there any suggustions for this set patches ?
> 
> 
> 在 2020/9/25 16:39, Min Hu (Connor) 写道:
>> This series add FEC support for ethdev.
>>
>> Min Hu (Connor) (3):
>>    ethdev: introduce FEC API
>>    net/hns3: support FEC
>>    app/testpmd: add FEC command
>>
>>   app/test-pmd/cmdline.c                   | 223 +++++++++++++++++++
>>   app/test-pmd/config.c                    |  91 ++++++++
>>   app/test-pmd/testpmd.h                   |   2 +
>>   doc/guides/rel_notes/release_20_11.rst   |  10 +
>>   drivers/net/hns3/hns3_cmd.h              |  19 +-
>>   drivers/net/hns3/hns3_ethdev.c           | 356 +++++++++++++++++++++++++++++++
>>   drivers/net/hns3/hns3_ethdev.h           |   1 +
>>   lib/librte_ethdev/rte_ethdev.c           |  43 ++++
>>   lib/librte_ethdev/rte_ethdev.h           |  94 ++++++++
>>   lib/librte_ethdev/rte_ethdev_driver.h    |  80 +++++++
>>   lib/librte_ethdev/rte_ethdev_version.map |   3 +
>>   11 files changed, 921 insertions(+), 1 deletion(-)
>>

Hi Connor,

Can you please make a new version addressing the minor issues Andrew highlighted 
and including his ack?

Thanks,
ferruh

^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V14 0/3] add FEC support
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
                     ` (13 preceding siblings ...)
  2020-09-25  8:39   ` [dpdk-dev] [PATCH V13 0/3] add FEC support Min Hu (Connor)
@ 2020-09-28 11:08   ` Min Hu (Connor)
  2020-09-28 11:08     ` [dpdk-dev] [PATCH V14 1/3] ethdev: introduce FEC API Min Hu (Connor)
                       ` (2 more replies)
  2020-09-29  1:03   ` [dpdk-dev] [PATCH V15 0/3] add FEC support Min Hu (Connor)
  2020-10-08 10:02   ` [dpdk-dev] [PATCH V16 0/3] add FEC support Min Hu (Connor)
  16 siblings, 3 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-28 11:08 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This series add FEC support for ethdev.

Min Hu (Connor) (3):
  ethdev: introduce FEC API
  net/hns3: support FEC
  app/testpmd: add FEC command

 app/test-pmd/cmdline.c                   | 223 +++++++++++++++++++
 app/test-pmd/config.c                    |  91 ++++++++
 app/test-pmd/testpmd.h                   |   2 +
 doc/guides/rel_notes/release_20_11.rst   |  10 +
 drivers/net/hns3/hns3_cmd.h              |  19 +-
 drivers/net/hns3/hns3_ethdev.c           | 356 +++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h           |   1 +
 lib/librte_ethdev/rte_ethdev.c           |  44 ++++
 lib/librte_ethdev/rte_ethdev.h           | 102 +++++++++
 lib/librte_ethdev/rte_ethdev_driver.h    |  88 ++++++++
 lib/librte_ethdev/rte_ethdev_version.map |   3 +
 11 files changed, 938 insertions(+), 1 deletion(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V14 1/3] ethdev: introduce FEC API
  2020-09-28 11:08   ` [dpdk-dev] [PATCH V14 " Min Hu (Connor)
@ 2020-09-28 11:08     ` Min Hu (Connor)
  2020-09-28 12:48       ` Andrew Rybchenko
  2020-09-28 11:08     ` [dpdk-dev] [PATCH V14 2/3] net/hns3: support FEC Min Hu (Connor)
  2020-09-28 11:08     ` [dpdk-dev] [PATCH V14 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 1 reply; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-28 11:08 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

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>
Acked-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
v13->v14:
change mode to fec_capa.
fix comment about API.

---
v12->v13:
change fec get capa API.
fix comment styles.

---
v10->v11:
allow to report capabilities per link speed.
specify what should be reported if link is down
when get FEC.
change mode to capa bitmask.

---
v9->v10:
add macro RTE_ETH_FEC_MODE_CAPA_MASK(x) to indicate
different FEC mode capa.

---
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   |   5 ++
 lib/librte_ethdev/rte_ethdev.c           |  44 +++++++++++++
 lib/librte_ethdev/rte_ethdev.h           | 102 +++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_driver.h    |  88 ++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |   3 +
 5 files changed, 242 insertions(+)

diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index c6642f5..1f04bd5 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -78,6 +78,11 @@ New Features
     ``--portmask=N``
     where N represents the hexadecimal bitmask of ports used.
 
+* **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.
+
 
 Removed Items
 -------------
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index dfe5c1b..996d230 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -3679,6 +3679,50 @@ 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,
+			   struct rte_eth_fec_capa *speed_fec_capa,
+			   unsigned int num)
+{
+	struct rte_eth_dev *dev;
+	int ret;
+
+	if (speed_fec_capa == NULL && num > 0)
+		return -EINVAL;
+
+	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);
+	ret = (*dev->dev_ops->fec_get_capability)(dev, speed_fec_capa, num);
+
+	return ret;
+}
+
+int
+rte_eth_fec_get(uint16_t port_id, uint32_t *fec_capa)
+{
+	struct rte_eth_dev *dev;
+
+	if (fec_capa == NULL)
+		return -EINVAL;
+
+	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, fec_capa));
+}
+
+int
+rte_eth_fec_set(uint16_t port_id, uint32_t 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_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 645a186..50c5280 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1544,6 +1544,29 @@ 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 */
+};
+
+/* Translate from FEC mode to FEC capa */
+#define RTE_ETH_FEC_MODE_TO_CAPA(x)	(1U << (x))
+
+/* This macro indicates FEC capa mask */
+#define RTE_ETH_FEC_MODE_CAPA_MASK(x)	(1U << (RTE_ETH_FEC_ ## x))
+
+/* A structure used to get capabilities per link speed */
+struct rte_eth_fec_capa {
+	uint32_t speed; /**< Link speed (see ETH_SPEED_NUM_*) */
+	uint32_t capa;  /**< FEC capabilities bitmask */
+};
+
 #define RTE_ETH_ALL RTE_MAX_ETHPORTS
 
 /* Macros to check for valid port */
@@ -3397,6 +3420,85 @@ 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 speed_fec_capa
+ *   speed_fec_capa is out only with per-speed capabilities.
+ *   If set to NULL, the function returns the required number
+ *   of required array entries.
+ * @param num
+ *   a number of elements in an speed_fec_capa array.
+ *
+ * @return
+ *   - A positive value lower or equal to num: success. The return value
+ *     is the number of entries filled in the fec capa array.
+ *   - A positive value higher than num: error, the given fec capa array
+ *     is too small. The return value corresponds to the num that should
+ *     be given to succeed. The entries in fec capa array are not valid and
+ *     shall not be used by the caller.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ *   - (-EINVAL)  if *num* or *speed_fec_capa* invalid
+ */
+__rte_experimental
+int rte_eth_fec_get_capability(uint16_t port_id,
+			       struct rte_eth_fec_capa *speed_fec_capa,
+			       unsigned int num);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get current Forward Error Correction(FEC) mode.
+ * 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.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param fec_capa
+ *   A bitmask of enabled FEC modes. If AUTO bit is set, other
+ *   bits specify FEC modes which may be negotiated. If AUTO
+ *   bit is clear, specify FEC modes to be used (only one valid
+ *   mode per speed may be set).
+ * @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, uint32_t *fec_capa);
+
+/**
+ * @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, uint32_t mode);
+
+/**
  * Get current status of the Ethernet link flow control for Ethernet device
  *
  * @param port_id
diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
index 23cc1e0..a1f10d6 100644
--- a/lib/librte_ethdev/rte_ethdev_driver.h
+++ b/lib/librte_ethdev/rte_ethdev_driver.h
@@ -575,6 +575,87 @@ 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 speed_fec_capa
+ *   speed_fec_capa is out only with per-speed capabilities.
+ * @param num
+ *   a number of elements in an speed_fec_capa array.
+ *
+ * @return
+ *   Negative errno value on error, positive value on success.
+ *
+ * @retval positive value
+ *   A positive value lower or equal to num: success. The return value
+ *   is the number of entries filled in the fec capa array.
+ *   A positive value higher than num: error, the given fec capa array
+ *   is too small. The return value corresponds to the num that should
+ *   be given to succeed. The entries in the fec capa array are not valid
+ *   and shall not be used by the caller.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EIO
+ *   Device is removed.
+ * @retval -EINVAL
+ *   *num* or *speed_fec_capa* invalid.
+ */
+typedef int (*eth_fec_get_capability_t)(struct rte_eth_dev *dev,
+		struct rte_eth_fec_capa *speed_fec_capa, unsigned int num);
+
+/**
+ * @internal
+ * Get Forward Error Correction(FEC) mode.
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param fec_capa
+ *   a bitmask of enabled FEC modes. If AUTO bit is set, other
+ *   bits specify FEC modes which may be negotiated. If AUTO
+ *   bit is clear, specify FEC modes to be used (only one valid
+ *   mode per speed may be set).
+ *
+ * @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.
+ */
+typedef int (*eth_fec_get_t)(struct rte_eth_dev *dev,
+			     uint32_t *fec_capa);
+
+/**
+ * @internal
+ * Set Forward Error Correction(FEC) mode.
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param mode
+ *   bitmask of allowed FEC modes. It must be only one
+ *   if AUTO is disabled. If AUTO is enabled, other
+ *   bits specify FEC modes which may be negotiated.
+ *
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success, set FEC success.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EINVAL
+ *   Unsupported FEC mode requested.
+ * @retval -EIO
+ *   Device is removed.
+ */
+typedef int (*eth_fec_set_t)(struct rte_eth_dev *dev, uint32_t mode);
+
+/**
  * @internal A structure containing the functions exported by an Ethernet driver.
  */
 struct eth_dev_ops {
@@ -713,6 +794,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 c95ef51..b9ace3a 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -229,6 +229,9 @@ EXPERIMENTAL {
 	# added in 20.11
 	rte_eth_link_speed_to_str;
 	rte_eth_link_to_str;
+	rte_eth_fec_get_capability;
+	rte_eth_fec_get;
+	rte_eth_fec_set;
 };
 
 INTERNAL {
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V14 2/3] net/hns3: support FEC
  2020-09-28 11:08   ` [dpdk-dev] [PATCH V14 " Min Hu (Connor)
  2020-09-28 11:08     ` [dpdk-dev] [PATCH V14 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-28 11:08     ` Min Hu (Connor)
  2020-09-28 11:08     ` [dpdk-dev] [PATCH V14 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-28 11:08 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

Forward error correction (FEC) is a bit error correction mode.
It adds error correction information to data packets at the
transmit end, and uses the error correction information to correct
the bit errors generated during data packet transmission at the
receive end. This improves signal quality but also brings a delay
to signals. This function can be enabled or disabled as required.

This patch adds FEC support for ethdev.Introduce ethdev
operations 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>
---
v13->v14:
change mode to fec_capa.

---
v12->v13:
change fec get capa interface.

---
v11->v12:
fix coding warning.

v10->v11:
allow to report capabilities per link speed.
specify what should be reported if link is down
when get FEC.
change mode to capa bitmask.

---
v9->v10:
use RTE_ETH_FEC_MODE_CAPA_MASK(x) which is just defined.

---
v7->v8:
FEC mode order defined in hns3 hardware is inconsistend with
that defined in the ethdev library. So the sequence needs
to be converted.

---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Data type for fec_cap is changed from uint8_t
to uint32_t for possible future expansion.

---
v2->v3:
adjust the return value of function.

---
 doc/guides/rel_notes/release_20_11.rst |   5 +
 drivers/net/hns3/hns3_cmd.h            |  19 +-
 drivers/net/hns3/hns3_ethdev.c         | 356 +++++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h         |   1 +
 4 files changed, 380 insertions(+), 1 deletion(-)

diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index 1f04bd5..eec6930 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -83,6 +83,11 @@ New Features
   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/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index 87d6053..a1e9604 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -100,6 +100,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_QUERY_LINK_STATUS      = 0x0307,
 	HNS3_OPC_CONFIG_MAX_FRM_SIZE    = 0x0308,
 	HNS3_OPC_CONFIG_SPEED_DUP       = 0x0309,
+	HNS3_OPC_CONFIG_FEC_MODE        = 0x031A,
 
 	/* PFC/Pause commands */
 	HNS3_OPC_CFG_MAC_PAUSE_EN       = 0x0701,
@@ -684,9 +685,25 @@ struct hns3_config_auto_neg_cmd {
 	uint8_t   rsv[20];
 };
 
+#define HNS3_MAC_CFG_FEC_AUTO_EN_B	0
+#define HNS3_MAC_CFG_FEC_MODE_S		1
+#define HNS3_MAC_CFG_FEC_MODE_M	GENMASK(3, 1)
+#define HNS3_MAC_FEC_OFF		0
+#define HNS3_MAC_FEC_BASER		1
+#define HNS3_MAC_FEC_RS			2
+
 struct hns3_sfp_speed_cmd {
 	uint32_t  sfp_speed;
-	uint32_t  rsv[5];
+	uint8_t   query_type; /* 0: sfp speed, 1: active fec */
+	uint8_t   active_fec; /* current FEC mode */
+	uint16_t  rsv1;
+	uint32_t  rsv2[4];
+};
+
+/* Configure FEC mode, opcode:0x031A */
+struct hns3_config_fec_cmd {
+	uint8_t fec_mode;
+	uint8_t rsv[23];
 };
 
 #define HNS3_MAC_MGR_MASK_VLAN_B		BIT(0)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 73d5042..2fa1aea 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -63,6 +63,11 @@
 #define HNS3_RESET_WAIT_MS	100
 #define HNS3_RESET_WAIT_CNT	200
 
+/* FEC mode order defined in HNS3 hardware */
+#define HNS3_HW_FEC_MODE_NOFEC  0
+#define HNS3_HW_FEC_MODE_BASER  1
+#define HNS3_HW_FEC_MODE_RS     2
+
 enum hns3_evt_cause {
 	HNS3_VECTOR0_EVENT_RST,
 	HNS3_VECTOR0_EVENT_MBX,
@@ -70,6 +75,34 @@ enum hns3_evt_cause {
 	HNS3_VECTOR0_EVENT_OTHER,
 };
 
+static const struct rte_eth_fec_capa speed_fec_capa_tbl[] = {
+	{ ETH_SPEED_NUM_10G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(BASER) },
+
+	{ ETH_SPEED_NUM_25G, 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) },
+
+	{ ETH_SPEED_NUM_40G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(BASER) },
+
+	{ ETH_SPEED_NUM_50G, 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) },
+
+	{ ETH_SPEED_NUM_100G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(RS) },
+
+	{ ETH_SPEED_NUM_200G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(RS) }
+};
+
 static enum hns3_reset_level hns3_get_reset_level(struct hns3_adapter *hns,
 						 uint64_t *levels);
 static int hns3_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
@@ -81,6 +114,8 @@ static int hns3_add_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
 static int hns3_remove_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
+static int hns3_restore_fec(struct hns3_hw *hw);
+static int hns3_query_dev_fec_info(struct rte_eth_dev *dev);
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -2889,6 +2924,13 @@ hns3_get_capability(struct hns3_hw *hw)
 	    device_id == HNS3_DEV_ID_200G_RDMA)
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_DCB_B, 1);
 
+	ret = hns3_query_dev_fec_info(eth_dev);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			     "failed to query FEC information, ret = %d", ret);
+		return ret;
+	}
+
 	/* Get PCI revision id */
 	ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN,
 				  HNS3_PCI_REVISION_ID);
@@ -5446,6 +5488,10 @@ hns3_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_promisc;
 
+	ret = hns3_restore_fec(hw);
+	if (ret)
+		goto err_promisc;
+
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED) {
 		ret = hns3_do_start(hns, false);
 		if (ret)
@@ -5524,6 +5570,313 @@ hns3_reset_service(void *param)
 		hns3_msix_process(hns, reset_level);
 }
 
+static unsigned int
+hns3_get_speed_capa_num(uint16_t device_id)
+{
+	unsigned int num;
+
+	switch (device_id) {
+	case HNS3_DEV_ID_25GE:
+	case HNS3_DEV_ID_25GE_RDMA:
+		num = 2;
+		break;
+	case HNS3_DEV_ID_100G_RDMA_MACSEC:
+	case HNS3_DEV_ID_200G_RDMA:
+		num = 1;
+		break;
+	default:
+		num = 0;
+		break;
+	}
+
+	return num;
+}
+
+static int
+hns3_get_speed_fec_capa(struct rte_eth_fec_capa *speed_fec_capa,
+			uint16_t device_id)
+{
+	switch (device_id) {
+	case HNS3_DEV_ID_25GE:
+	/* fallthrough */
+	case HNS3_DEV_ID_25GE_RDMA:
+		speed_fec_capa[0].speed = speed_fec_capa_tbl[1].speed;
+		speed_fec_capa[0].capa = speed_fec_capa_tbl[1].capa;
+
+		/* In HNS3 device, the 25G NIC is compatible with 10G rate */
+		speed_fec_capa[1].speed = speed_fec_capa_tbl[0].speed;
+		speed_fec_capa[1].capa = speed_fec_capa_tbl[0].capa;
+		break;
+	case HNS3_DEV_ID_100G_RDMA_MACSEC:
+		speed_fec_capa[0].speed = speed_fec_capa_tbl[4].speed;
+		speed_fec_capa[0].capa = speed_fec_capa_tbl[4].capa;
+		break;
+	case HNS3_DEV_ID_200G_RDMA:
+		speed_fec_capa[0].speed = speed_fec_capa_tbl[5].speed;
+		speed_fec_capa[0].capa = speed_fec_capa_tbl[5].capa;
+		break;
+	default:
+		return -ENOTSUP;
+	}
+
+	return 0;
+}
+
+static int
+hns3_fec_get_capability(struct rte_eth_dev *dev,
+			struct rte_eth_fec_capa *speed_fec_capa,
+			unsigned int num)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	uint16_t device_id = pci_dev->id.device_id;
+	unsigned int capa_num;
+	int ret;
+
+	capa_num = hns3_get_speed_capa_num(device_id);
+	if (capa_num == 0) {
+		hns3_err(hw, "device(0x%x) is not supported by hns3 PMD",
+			 device_id);
+		return -ENOTSUP;
+	}
+
+	if (speed_fec_capa == NULL || num < capa_num)
+		return capa_num;
+
+	ret = hns3_get_speed_fec_capa(speed_fec_capa, device_id);
+	if (ret)
+		return -ENOTSUP;
+
+	return capa_num;
+}
+
+static int
+get_current_fec_auto_state(struct hns3_hw *hw, uint8_t *state)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, true);
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret) {
+		hns3_err(hw, "get current fec auto state failed, ret = %d",
+			 ret);
+		return ret;
+	}
+
+	*state = req->fec_mode & (1U << HNS3_MAC_CFG_FEC_AUTO_EN_B);
+	return 0;
+}
+
+static int
+hns3_fec_get(struct rte_eth_dev *dev, uint32_t *fec_capa)
+{
+#define QUERY_ACTIVE_SPEED	1
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_sfp_speed_cmd *resp;
+	uint32_t tmp_fec_capa;
+	uint8_t auto_state;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	/*
+	 * 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.
+	 */
+	if (hw->mac.link_status == ETH_LINK_DOWN) {
+		ret = get_current_fec_auto_state(hw, &auto_state);
+		if (ret)
+			return ret;
+
+		if (auto_state == 0x1) {
+			*fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
+			return 0;
+		}
+	}
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_SFP_GET_SPEED, true);
+	resp = (struct hns3_sfp_speed_cmd *)desc.data;
+	resp->query_type = QUERY_ACTIVE_SPEED;
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret == -EOPNOTSUPP) {
+		hns3_err(hw, "IMP do not support get FEC, ret = %d", ret);
+		return ret;
+	} else if (ret) {
+		hns3_err(hw, "get FEC failed, ret = %d", ret);
+		return ret;
+	}
+
+	/*
+	 * FEC mode order defined in hns3 hardware is inconsistend with
+	 * that defined in the ethdev library. So the sequence needs
+	 * to be converted.
+	 */
+	switch (resp->active_fec) {
+	case HNS3_HW_FEC_MODE_NOFEC:
+		tmp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
+		break;
+	case HNS3_HW_FEC_MODE_BASER:
+		tmp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
+		break;
+	case HNS3_HW_FEC_MODE_RS:
+		tmp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(RS);
+		break;
+	default:
+		tmp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
+		break;
+	}
+
+	*fec_capa = tmp_fec_capa;
+	return 0;
+}
+
+static int
+hns3_set_fec_hw(struct hns3_hw *hw, uint32_t mode)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, false);
+
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	switch (mode) {
+	case RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC):
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_OFF);
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(BASER):
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_BASER);
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(RS):
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_RS);
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(AUTO):
+		hns3_set_bit(req->fec_mode, HNS3_MAC_CFG_FEC_AUTO_EN_B, 1);
+		break;
+	default:
+		return 0;
+	}
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw, "set fec mode failed, ret = %d", ret);
+
+	return ret;
+}
+
+static uint32_t
+get_current_speed_fec_cap(struct hns3_hw *hw, struct rte_eth_fec_capa *fec_capa)
+{
+	struct hns3_mac *mac = &hw->mac;
+	uint32_t cur_capa;
+
+	switch (mac->link_speed) {
+	case ETH_SPEED_NUM_10G:
+		cur_capa = fec_capa[1].capa;
+		break;
+	case ETH_SPEED_NUM_25G:
+	case ETH_SPEED_NUM_100G:
+	case ETH_SPEED_NUM_200G:
+		cur_capa = fec_capa[0].capa;
+		break;
+	default:
+		cur_capa = 0;
+		break;
+	}
+
+	return cur_capa;
+}
+
+static bool
+is_fec_mode_one_bit_set(uint32_t mode)
+{
+	int cnt = 0;
+	uint8_t i;
+
+	for (i = 0; i < sizeof(mode); i++)
+		if (mode >> i & 0x1)
+			cnt++;
+
+	return cnt == 1 ? true : false;
+}
+
+static int
+hns3_fec_set(struct rte_eth_dev *dev, uint32_t mode)
+{
+#define FEC_CAPA_NUM 2
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+
+	struct rte_eth_fec_capa fec_capa[FEC_CAPA_NUM];
+	uint32_t cur_capa;
+	uint32_t num = FEC_CAPA_NUM;
+	int ret;
+
+	ret = hns3_fec_get_capability(dev, fec_capa, num);
+	if (ret < 0)
+		return ret;
+
+	/* HNS3 PMD driver only support one bit set mode, e.g. 0x1, 0x4 */
+	if (!is_fec_mode_one_bit_set(mode))
+		hns3_err(hw, "FEC mode(0x%x) not supported in HNS3 PMD,"
+			     "FEC mode should be only one bit set", mode);
+
+	/*
+	 * Check whether the configured mode is within the FEC capability.
+	 * If not, the configured mode will not be supported.
+	 */
+	cur_capa = get_current_speed_fec_cap(hw, fec_capa);
+	if (!(cur_capa & mode)) {
+		hns3_err(hw, "unsupported FEC mode = 0x%x", mode);
+		return -EINVAL;
+	}
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		return ret;
+
+	pf->fec_mode = mode;
+	return 0;
+}
+
+static int
+hns3_restore_fec(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+	uint32_t mode = pf->fec_mode;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		hns3_err(hw, "restore fec mode(0x%x) failed, ret = %d",
+			 mode, ret);
+
+	return ret;
+}
+
+static int
+hns3_query_dev_fec_info(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_fec_get(dev, &pf->fec_mode);
+	if (ret)
+		hns3_err(hw, "query device FEC info failed, ret = %d", ret);
+
+	return ret;
+}
+
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_configure      = hns3_dev_configure,
 	.dev_start          = hns3_dev_start,
@@ -5573,6 +5926,9 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.get_reg                = hns3_get_regs,
 	.get_dcb_info           = hns3_get_dcb_info,
 	.dev_supported_ptypes_get = hns3_dev_supported_ptypes_get,
+	.fec_get_capability     = hns3_fec_get_capability,
+	.fec_get                = hns3_fec_get,
+	.fec_set                = hns3_fec_set,
 };
 
 static const struct hns3_reset_ops hns3_reset_ops = {
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index fd6a9f9..393b91f 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -620,6 +620,7 @@ struct hns3_pf {
 	struct hns3_err_msix_intr_stats abn_int_stats;
 
 	bool support_sfp_query;
+	uint32_t fec_mode; /* current FEC mode for ethdev */
 
 	struct hns3_vtag_cfg vtag_config;
 	LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V14 3/3] app/testpmd: add FEC command
  2020-09-28 11:08   ` [dpdk-dev] [PATCH V14 " Min Hu (Connor)
  2020-09-28 11:08     ` [dpdk-dev] [PATCH V14 1/3] ethdev: introduce FEC API Min Hu (Connor)
  2020-09-28 11:08     ` [dpdk-dev] [PATCH V14 2/3] net/hns3: support FEC Min Hu (Connor)
@ 2020-09-28 11:08     ` Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-28 11:08 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This commit adds testpmd capability to query and config FEC
function of device. This includes:
- show FEC capabilities, example:
	testpmd> show port 0 fec capabilities
- show FEC mode, example:
	testpmd> show port 0 fec_mode
- config FEC mode, example:
	testpmd> set port <port_id> 0 <auto|off|rs|baser>

	where:

	auto|off|rs|baser are four kinds of FEC mode which dev
	support according to MAC link speed.

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>
---
v12->v13:
change fec get capa interface.

---
v10->v11:
change mode to capa bitmask.

---
v8->v9:
added acked-by.

---
v6->v7:
used RTE_DIM(fec_mode_name) instead of RTE_ETH_FEC_NUM

---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Add RTE_ prefix for public FEC mode enum.

---
v3->v4:
adjust the display format of FEC mode

---
v2->v3:
adjust the display format of FEC capability.

---
 app/test-pmd/cmdline.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c  |  91 ++++++++++++++++++++
 app/test-pmd/testpmd.h |   2 +
 3 files changed, 316 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 5f93409..407513c 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -19161,6 +19161,226 @@ cmdline_parse_inst_t cmd_show_tx_metadata = {
 	},
 };
 
+/* *** show fec capability per port configuration *** */
+struct cmd_show_fec_capability_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_fec;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_capability_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_CAP_NUM 2
+	struct cmd_show_fec_capability_result *res = parsed_result;
+	struct rte_eth_fec_capa speed_fec_capa[FEC_CAP_NUM];
+	unsigned int num = FEC_CAP_NUM;
+	unsigned int ret_num;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_fec_get_capability(res->cmd_pid, speed_fec_capa, num);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC capability failed\n");
+		return;
+	}
+
+	ret_num = (unsigned int)ret;
+	show_fec_capability(ret_num, speed_fec_capa);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_capability_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_capability_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_capability_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_capability_fec =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_fec, "fec");
+cmdline_parse_token_string_t cmd_show_fec_capability_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_keyword, "capabilities");
+
+cmdline_parse_inst_t cmd_show_capability = {
+	.f = cmd_show_fec_capability_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec capabilities",
+	.tokens = {
+		(void *)&cmd_show_fec_capability_show,
+		(void *)&cmd_show_fec_capability_port,
+		(void *)&cmd_show_fec_capability_pid,
+		(void *)&cmd_show_fec_capability_fec,
+		(void *)&cmd_show_fec_capability_keyword,
+		NULL,
+	},
+};
+
+/* *** show fec mode per port configuration *** */
+struct cmd_show_fec_metadata_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_mode_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_NAME_SIZE 16
+	struct cmd_show_fec_metadata_result *res = parsed_result;
+	uint32_t mode;
+	char buf[FEC_NAME_SIZE];
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+	ret = rte_eth_fec_get(res->cmd_pid, &mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC mode failed\n");
+		return;
+	}
+
+	switch (mode) {
+	case RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC):
+		strlcpy(buf, "off", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(AUTO):
+		strlcpy(buf, "auto", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(BASER):
+		strlcpy(buf, "baser", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(RS):
+		strlcpy(buf, "rs", sizeof(buf));
+		break;
+	default:
+		return;
+	}
+
+	printf("%s\n", buf);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_mode_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_mode_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_mode_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_mode_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_keyword, "fec_mode");
+
+cmdline_parse_inst_t cmd_show_fec_mode = {
+	.f = cmd_show_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec_mode",
+	.tokens = {
+		(void *)&cmd_show_fec_mode_show,
+		(void *)&cmd_show_fec_mode_port,
+		(void *)&cmd_show_fec_mode_pid,
+		(void *)&cmd_show_fec_mode_keyword,
+		NULL,
+	},
+};
+
+/* *** set fec mode per port configuration *** */
+struct cmd_set_port_fec_mode {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t fec_mode;
+	cmdline_fixed_string_t fec_value;
+};
+
+/* Common CLI fields for set fec mode */
+cmdline_parse_token_string_t cmd_set_port_fec_mode_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port, "port");
+cmdline_parse_token_num_t cmd_set_port_fec_mode_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_port_fec_mode_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_mode, "fec_mode");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_value =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_value, NULL);
+
+static void
+cmd_set_port_fec_mode_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	__rte_unused void *data)
+{
+	struct cmd_set_port_fec_mode *res = parsed_result;
+	uint16_t port_id = res->port_id;
+	uint32_t mode;
+	int ret;
+
+	ret = parse_fec_mode(res->fec_value, &mode);
+	if (ret < 0) {
+		printf("Unknown fec mode: %s for Port %d\n", res->fec_value,
+			port_id);
+		return;
+	}
+
+	ret = rte_eth_fec_set(port_id, mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Set FEC mode failed\n");
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_fec_mode = {
+	.f = cmd_set_port_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> fec_mode <auto|off|rs|baser>",
+	.tokens = {
+		(void *)&cmd_set_port_fec_mode_set,
+		(void *)&cmd_set_port_fec_mode_port,
+		(void *)&cmd_set_port_fec_mode_port_id,
+		(void *)&cmd_set_port_fec_mode_str,
+		(void *)&cmd_set_port_fec_mode_value,
+		NULL,
+	},
+};
+
 /* show port supported ptypes */
 
 /* Common result structure for show port ptypes */
@@ -19795,6 +20015,9 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_set_raw,
 	(cmdline_parse_inst_t *)&cmd_show_set_raw_all,
 	(cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
+	(cmdline_parse_inst_t *)&cmd_show_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_set_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_show_capability,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 2d9a456..897ceaf 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -138,6 +138,58 @@ const struct rss_type_info rss_type_table[] = {
 	{ NULL, 0 },
 };
 
+static const struct {
+	enum rte_eth_fec_mode mode;
+	const char *name;
+} fec_mode_name[] = {
+	{
+		.mode = RTE_ETH_FEC_NOFEC,
+		.name = "off",
+	},
+	{
+		.mode = RTE_ETH_FEC_AUTO,
+		.name = "auto",
+	},
+	{
+		.mode = RTE_ETH_FEC_BASER,
+		.name = "baser",
+	},
+	{
+		.mode = RTE_ETH_FEC_RS,
+		.name = "rs",
+	},
+};
+
+static const struct {
+	uint32_t speed;
+	const char *name;
+} eth_speed_name[] = {
+	{
+		.speed = ETH_SPEED_NUM_10G,
+		.name = "Speed 10G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_25G,
+		.name = "Speed 25G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_40G,
+		.name = "Speed 40G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_50G,
+		.name = "Speed 50G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_100G,
+		.name = "Speed 100G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_200G,
+		.name = "Speed 200G",
+	},
+};
+
 static void
 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
 {
@@ -2969,6 +3021,45 @@ set_tx_pkt_split(const char *name)
 	printf("unknown value: \"%s\"\n", name);
 }
 
+int
+parse_fec_mode(const char *name, uint32_t *mode)
+{
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(fec_mode_name); i++) {
+		if (strcmp(fec_mode_name[i].name, name) == 0) {
+			*mode = RTE_ETH_FEC_MODE_TO_CAPA(fec_mode_name[i].mode);
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void
+show_fec_capability(unsigned int num, struct rte_eth_fec_capa *speed_fec_capa)
+{
+	unsigned int i, j, k;
+
+	printf("FEC capabilities:\n");
+
+	for (i = 0; i < num; i++) {
+		for (j = 0; j < RTE_DIM(eth_speed_name); j++) {
+			if (eth_speed_name[j].speed ==
+						speed_fec_capa[i].speed) {
+				printf("%s : ", eth_speed_name[j].name);
+				break;
+			}
+		}
+
+		for (k = RTE_ETH_FEC_AUTO; k < RTE_DIM(fec_mode_name); k++) {
+			if (RTE_ETH_FEC_MODE_TO_CAPA(k) &
+						speed_fec_capa[i].capa)
+				printf("%s ", fec_mode_name[k].name);
+		}
+		printf("\n");
+	}
+}
+
 void
 show_tx_pkt_segments(void)
 {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index f139fe7..85ea030 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -804,6 +804,8 @@ void show_tx_pkt_segments(void);
 void set_tx_pkt_times(unsigned int *tx_times);
 void show_tx_pkt_times(void);
 void set_tx_pkt_split(const char *name);
+int parse_fec_mode(const char *name, enum rte_eth_fec_mode *mode);
+void show_fec_capability(uint32_t num, struct rte_eth_fec_capa *speed_fec_capa);
 void set_nb_pkt_per_burst(uint16_t pkt_burst);
 char *list_pkt_forwarding_modes(void);
 char *list_pkt_forwarding_retry_modes(void);
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V13 0/3] add FEC support
  2020-09-28 10:27       ` Ferruh Yigit
@ 2020-09-28 11:11         ` Min Hu (Connor)
  0 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-28 11:11 UTC (permalink / raw)
  To: Ferruh Yigit, dev; +Cc: thomas, linuxarm, konstantin.ananyev, arybchenko

Hi, Ferruh,
	I've send a set of patches named V14, please check it ,thanks.

在 2020/9/28 18:27, Ferruh Yigit 写道:
> On 9/27/2020 8:08 AM, Min Hu (Connor) wrote:
>> Hello,
>>      Are there any suggustions for this set patches ?
>>
>>
>> 在 2020/9/25 16:39, Min Hu (Connor) 写道:
>>> This series add FEC support for ethdev.
>>>
>>> Min Hu (Connor) (3):
>>>    ethdev: introduce FEC API
>>>    net/hns3: support FEC
>>>    app/testpmd: add FEC command
>>>
>>>   app/test-pmd/cmdline.c                   | 223 +++++++++++++++++++
>>>   app/test-pmd/config.c                    |  91 ++++++++
>>>   app/test-pmd/testpmd.h                   |   2 +
>>>   doc/guides/rel_notes/release_20_11.rst   |  10 +
>>>   drivers/net/hns3/hns3_cmd.h              |  19 +-
>>>   drivers/net/hns3/hns3_ethdev.c           | 356 
>>> +++++++++++++++++++++++++++++++
>>>   drivers/net/hns3/hns3_ethdev.h           |   1 +
>>>   lib/librte_ethdev/rte_ethdev.c           |  43 ++++
>>>   lib/librte_ethdev/rte_ethdev.h           |  94 ++++++++
>>>   lib/librte_ethdev/rte_ethdev_driver.h    |  80 +++++++
>>>   lib/librte_ethdev/rte_ethdev_version.map |   3 +
>>>   11 files changed, 921 insertions(+), 1 deletion(-)
>>>
> 
> Hi Connor,
> 
> Can you please make a new version addressing the minor issues Andrew 
> highlighted and including his ack?
> 
> Thanks,
> ferruh
> .

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V13 1/3] ethdev: introduce FEC API
  2020-09-28  7:35       ` Andrew Rybchenko
@ 2020-09-28 11:13         ` Min Hu (Connor)
  0 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-28 11:13 UTC (permalink / raw)
  To: Andrew Rybchenko, dev; +Cc: konstantin.ananyev, thomas, ferruh.yigit, linuxarm

Hi, Andrew,
	I have sent V14, in which I fixed it as you suggested,
	please check it out,thank you.

在 2020/9/28 15:35, Andrew Rybchenko 写道:
> On 9/25/20 11:39 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>
> 
> With few nits below:
> Acked-by: Andrew Rybchenko <arybchenko@solarflare.com>
> 
>> ---
>> v12->v13:
>> change fec get capa API.
>> fix comment styles.
>>
>> ---
>> v10->v11:
>> allow to report capabilities per link speed.
>> specify what should be reported if link is down
>> when get FEC.
>> change mode to capa bitmask.
>>
>> ---
>> v9->v10:
>> add macro RTE_ETH_FEC_MODE_CAPA_MASK(x) to indicate
>> different FEC mode capa.
>>
>> ---
>> 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   |  5 ++
>>   lib/librte_ethdev/rte_ethdev.c           | 43 +++++++++++++++
>>   lib/librte_ethdev/rte_ethdev.h           | 94 ++++++++++++++++++++++++++++++++
>>   lib/librte_ethdev/rte_ethdev_driver.h    | 80 +++++++++++++++++++++++++++
>>   lib/librte_ethdev/rte_ethdev_version.map |  3 +
>>   5 files changed, 225 insertions(+)
>>
>> diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
>> index c6642f5..1f04bd5 100644
>> --- a/doc/guides/rel_notes/release_20_11.rst
>> +++ b/doc/guides/rel_notes/release_20_11.rst
>> @@ -78,6 +78,11 @@ New Features
>>       ``--portmask=N``
>>       where N represents the hexadecimal bitmask of ports used.
>>   
>> +* **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.
>> +
>>   
>>   Removed Items
>>   -------------
>> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
>> index dfe5c1b..86ead87 100644
>> --- a/lib/librte_ethdev/rte_ethdev.c
>> +++ b/lib/librte_ethdev/rte_ethdev.c
>> @@ -3679,6 +3679,49 @@ 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,
>> +			   struct rte_eth_fec_capa *speed_fec_capa,
>> +			   unsigned int num)
>> +{
>> +	struct rte_eth_dev *dev;
>> +	int ret;
> 
> if (speed_fec_capa == NULL && num > 0)
>          return -EINVAL;
> 
>> +
>> +	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);
>> +	ret = (*dev->dev_ops->fec_get_capability)(dev, speed_fec_capa, num);
>> +	if (ret > (int)num)
>> +		RTE_ETHDEV_LOG(ERR, "Insufficient num, num should be no less than %d\n",
>> +			       ret);
> 
> It is incorrect to log error, since
>      num = rte_eth_fec_get_capability(port_id, NULL, 0);
> may be used to obtain required number of array elements
> (nothing bad is happening).
> 
>> +
>> +	return ret;
>> +}
>> +
>> +int
>> +rte_eth_fec_get(uint16_t port_id, uint32_t *mode)
>> +{
>> +	struct rte_eth_dev *dev;
>> +
>> +	if (mode == NULL)
>> +		return -EINVAL;
>> +
>> +	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, uint32_t 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_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 645a186..04525a8 100644
>> --- a/lib/librte_ethdev/rte_ethdev.h
>> +++ b/lib/librte_ethdev/rte_ethdev.h
>> @@ -1544,6 +1544,29 @@ 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 */
>> +};
>> +
>> +/* Translate from FEC mode to FEC capa */
>> +#define RTE_ETH_FEC_MODE_TO_CAPA(x)	(1U << (x))
>> +
>> +/* This macro indicates FEC capa mask */
>> +#define RTE_ETH_FEC_MODE_CAPA_MASK(x)	(1U << (RTE_ETH_FEC_ ## x))
>> +
>> +/* A structure used to get capabilities per link speed */
>> +struct rte_eth_fec_capa {
>> +	uint32_t speed; /**< Link speed (see ETH_SPEED_NUM_*) */
>> +	uint32_t capa;  /**< FEC capabilities bitmask (see RTE_FEC_CAPA_*) */
> 
> Thre is no RTE_FEC_CAPA_* enum/defnes any more.
> I'd just remove everything in parenthesis.
> 
>> +};
>> +
>>   #define RTE_ETH_ALL RTE_MAX_ETHPORTS
>>   
>>   /* Macros to check for valid port */
>> @@ -3397,6 +3420,77 @@ 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 speed_fec_capa
>> + *   speed_fec_capa is out only with per-speed capabilities.
>> + *   If set to NULL, the function returns the required number
>> + *   of required array entries.
>> + * @param num
>> + *   the num is in/out with a number of elements in an array.
> 
> Just (it it not in/out now):
>     a number of elements in an speed_fec_capa array
> 
>> + *
>> + * @return
>> + *   - (0) if successful.
> 
> Wrong description. Any non-negative return value is success
> (number of speed_fec_capa array elements filled in)
> 
>> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
>> + *     that operation.
>> + *   - (-EIO) if device is removed.
>> + *   - (-ENODEV)  if *port_id* invalid.
>> + *   - (-EINVAL)  if *num* or *speed_fec_capa* invalid
>> + */
>> +__rte_experimental
>> +int rte_eth_fec_get_capability(uint16_t port_id,
>> +			       struct rte_eth_fec_capa *speed_fec_capa,
>> +			       unsigned int num);
>> +
>> +/**
>> + * @warning
>> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
>> + *
>> + * Get current Forward Error Correction(FEC) mode.
>> + * 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.
>> + *
>> + * @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, uint32_t *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.
> 
> mode -> fec_capa
> A bitmask of enabled FEC modes. If AUTO bit is set, other
> bits specify FEC modes which may be negotiated. If AUTO
> bit is clear, specify FEC modes to be used (only one valid
> mode per speed may be set).
> 
>> + * @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, uint32_t mode);
>> +
>> +/**
>>    * Get current status of the Ethernet link flow control for Ethernet device
>>    *
>>    * @param port_id
>> diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
>> index 23cc1e0..306f3a6 100644
>> --- a/lib/librte_ethdev/rte_ethdev_driver.h
>> +++ b/lib/librte_ethdev/rte_ethdev_driver.h
>> @@ -575,6 +575,79 @@ 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 speed_fec_capa
>> + *   speed_fec_capa is out only with per-speed capabilities.
>> + * @param num
>> + *   the num is in/out with a number of elements in an array.
> 
> same as above
> 
>> + *
>> + * @return
>> + *   Negative errno value on error, 0 on success.
>> + *
>> + * @retval 0
>> + *   Success, get FEC success.
> 
> same as above
> 
>> + * @retval -ENOTSUP
>> + *   Operation is not supported.
>> + * @retval -EIO
>> + *   Device is removed.
>> + * @retval -EINVAL
>> + *   *num* or *speed_fec_capa* invalid.
>> + */
>> +typedef int (*eth_fec_get_capability_t)(struct rte_eth_dev *dev,
>> +		struct rte_eth_fec_capa *speed_fec_capa, unsigned int num);
>> +
>> +/**
>> + * @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.
>> + */
>> +typedef int (*eth_fec_get_t)(struct rte_eth_dev *dev,
>> +			     uint32_t *mode);
>> +
>> +/**
>> + * @internal
>> + * Set Forward Error Correction(FEC) mode.
>> + *
>> + * @param dev
>> + *   ethdev handle of port.
>> + * @param mode
> 
> similar as aboe I suggest to name it fec_capa,
> since it is not a single mode
> 
>> + *   bitmask of allowed FEC modes. It must be only one
>> + *   if AUTO is disabled. If AUTO is enabled, other
>> + *   bits specify FEC modes which may be negotiated.
>> + *
>> + * @return
>> + *   Negative errno value on error, 0 on success.
>> + *
>> + * @retval 0
>> + *   Success, set FEC success.
>> + * @retval -ENOTSUP
>> + *   Operation is not supported.
>> + * @retval -EINVAL
>> + *   Unsupported FEC mode requested.
>> + * @retval -EIO
>> + *   Device is removed.
>> + */
>> +typedef int (*eth_fec_set_t)(struct rte_eth_dev *dev, uint32_t mode);
>> +
>> +/**
>>    * @internal A structure containing the functions exported by an Ethernet driver.
>>    */
>>   struct eth_dev_ops {
>> @@ -713,6 +786,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 c95ef51..b9ace3a 100644
>> --- a/lib/librte_ethdev/rte_ethdev_version.map
>> +++ b/lib/librte_ethdev/rte_ethdev_version.map
>> @@ -229,6 +229,9 @@ EXPERIMENTAL {
>>   	# added in 20.11
>>   	rte_eth_link_speed_to_str;
>>   	rte_eth_link_to_str;
>> +	rte_eth_fec_get_capability;
>> +	rte_eth_fec_get;
>> +	rte_eth_fec_set;
>>   };
>>   
>>   INTERNAL {
>>
> 
> .
> 

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V14 1/3] ethdev: introduce FEC API
  2020-09-28 11:08     ` [dpdk-dev] [PATCH V14 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-28 12:48       ` Andrew Rybchenko
  2020-09-29  2:09         ` Min Hu (Connor)
  0 siblings, 1 reply; 118+ messages in thread
From: Andrew Rybchenko @ 2020-09-28 12:48 UTC (permalink / raw)
  To: Min Hu (Connor), dev; +Cc: konstantin.ananyev, thomas, ferruh.yigit, linuxarm

On 9/28/20 2:08 PM, 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>
> Acked-by: Andrew Rybchenko <arybchenko@solarflare.com>

[snip]

> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> index dfe5c1b..996d230 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -3679,6 +3679,50 @@ 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,
> +			   struct rte_eth_fec_capa *speed_fec_capa,
> +			   unsigned int num)
> +{
> +	struct rte_eth_dev *dev;
> +	int ret;
> +
> +	if (speed_fec_capa == NULL && num > 0)
> +		return -EINVAL;
> +
> +	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);
> +	ret = (*dev->dev_ops->fec_get_capability)(dev, speed_fec_capa, num);
> +
> +	return ret;
> +}
> +
> +int
> +rte_eth_fec_get(uint16_t port_id, uint32_t *fec_capa)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	if (fec_capa == NULL)
> +		return -EINVAL;
> +
> +	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, fec_capa));
> +}
> +
> +int
> +rte_eth_fec_set(uint16_t port_id, uint32_t mode)

mode -> fec_capa, since it is not a single 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_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 645a186..50c5280 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h

[snip]

> @@ -3397,6 +3420,85 @@ 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 speed_fec_capa
> + *   speed_fec_capa is out only with per-speed capabilities.
> + *   If set to NULL, the function returns the required number
> + *   of required array entries.
> + * @param num
> + *   a number of elements in an speed_fec_capa array.
> + *
> + * @return
> + *   - A positive value lower or equal to num: success. The return value

positive -> non-negative
since 0 is OK if FEC is not applicable/supported

> + *     is the number of entries filled in the fec capa array.
> + *   - A positive value higher than num: error, the given fec capa array

same, positive -> non-negative

> + *     is too small. The return value corresponds to the num that should
> + *     be given to succeed. The entries in fec capa array are not valid and
> + *     shall not be used by the caller.

OK for me, possible option is to fill in just provided entries
(up to num)

> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> + *     that operation.
> + *   - (-EIO) if device is removed.
> + *   - (-ENODEV)  if *port_id* invalid.
> + *   - (-EINVAL)  if *num* or *speed_fec_capa* invalid
> + */
> +__rte_experimental
> +int rte_eth_fec_get_capability(uint16_t port_id,
> +			       struct rte_eth_fec_capa *speed_fec_capa,
> +			       unsigned int num);
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get current Forward Error Correction(FEC) mode.
> + * 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.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param fec_capa
> + *   A bitmask of enabled FEC modes. If AUTO bit is set, other
> + *   bits specify FEC modes which may be negotiated. If AUTO
> + *   bit is clear, specify FEC modes to be used (only one valid
> + *   mode per speed may be set).
> + * @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, uint32_t *fec_capa);
> +
> +/**
> + * @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.

mode -> fec_capa
with description from callback below

> + * @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, uint32_t mode);
> +
> +/**
>   * Get current status of the Ethernet link flow control for Ethernet device
>   *
>   * @param port_id
> diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
> index 23cc1e0..a1f10d6 100644
> --- a/lib/librte_ethdev/rte_ethdev_driver.h
> +++ b/lib/librte_ethdev/rte_ethdev_driver.h
> @@ -575,6 +575,87 @@ 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 speed_fec_capa
> + *   speed_fec_capa is out only with per-speed capabilities.
> + * @param num
> + *   a number of elements in an speed_fec_capa array.
> + *
> + * @return
> + *   Negative errno value on error, positive value on success.
> + *
> + * @retval positive value
> + *   A positive value lower or equal to num: success. The return value

same as above

> + *   is the number of entries filled in the fec capa array.
> + *   A positive value higher than num: error, the given fec capa array

same as above

> + *   is too small. The return value corresponds to the num that should
> + *   be given to succeed. The entries in the fec capa array are not valid
> + *   and shall not be used by the caller.
> + * @retval -ENOTSUP
> + *   Operation is not supported.
> + * @retval -EIO
> + *   Device is removed.
> + * @retval -EINVAL
> + *   *num* or *speed_fec_capa* invalid.
> + */
> +typedef int (*eth_fec_get_capability_t)(struct rte_eth_dev *dev,
> +		struct rte_eth_fec_capa *speed_fec_capa, unsigned int num);
> +
> +/**
> + * @internal
> + * Get Forward Error Correction(FEC) mode.
> + *
> + * @param dev
> + *   ethdev handle of port.
> + * @param fec_capa
> + *   a bitmask of enabled FEC modes. If AUTO bit is set, other
> + *   bits specify FEC modes which may be negotiated. If AUTO
> + *   bit is clear, specify FEC modes to be used (only one valid
> + *   mode per speed may be set).
> + *
> + * @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.
> + */
> +typedef int (*eth_fec_get_t)(struct rte_eth_dev *dev,
> +			     uint32_t *fec_capa);
> +
> +/**
> + * @internal
> + * Set Forward Error Correction(FEC) mode.
> + *
> + * @param dev
> + *   ethdev handle of port.
> + * @param mode

mode -> fec_capa

> + *   bitmask of allowed FEC modes. It must be only one
> + *   if AUTO is disabled. If AUTO is enabled, other
> + *   bits specify FEC modes which may be negotiated.
> + *
> + * @return
> + *   Negative errno value on error, 0 on success.
> + *
> + * @retval 0
> + *   Success, set FEC success.
> + * @retval -ENOTSUP
> + *   Operation is not supported.
> + * @retval -EINVAL
> + *   Unsupported FEC mode requested.
> + * @retval -EIO
> + *   Device is removed.
> + */
> +typedef int (*eth_fec_set_t)(struct rte_eth_dev *dev, uint32_t mode);
> +
> +/**
>   * @internal A structure containing the functions exported by an Ethernet driver.
>   */
>  struct eth_dev_ops {
> @@ -713,6 +794,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 c95ef51..b9ace3a 100644
> --- a/lib/librte_ethdev/rte_ethdev_version.map
> +++ b/lib/librte_ethdev/rte_ethdev_version.map
> @@ -229,6 +229,9 @@ EXPERIMENTAL {
>  	# added in 20.11
>  	rte_eth_link_speed_to_str;
>  	rte_eth_link_to_str;
> +	rte_eth_fec_get_capability;
> +	rte_eth_fec_get;
> +	rte_eth_fec_set;
>  };
>  
>  INTERNAL {
> 


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V15 0/3] add FEC support
  2020-09-08  3:05 ` [dpdk-dev] [PATCH 0/3] add FEC support Min Hu (Connor)
                     ` (14 preceding siblings ...)
  2020-09-28 11:08   ` [dpdk-dev] [PATCH V14 " Min Hu (Connor)
@ 2020-09-29  1:03   ` Min Hu (Connor)
  2020-09-29  1:03     ` [dpdk-dev] [PATCH V15 1/3] ethdev: introduce FEC API Min Hu (Connor)
                       ` (2 more replies)
  2020-10-08 10:02   ` [dpdk-dev] [PATCH V16 0/3] add FEC support Min Hu (Connor)
  16 siblings, 3 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-29  1:03 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This series add FEC support for ethdev.

Min Hu (Connor) (3):
  ethdev: introduce FEC API
  net/hns3: support FEC
  app/testpmd: add FEC command

 app/test-pmd/cmdline.c                   | 223 +++++++++++++++++++
 app/test-pmd/config.c                    |  91 ++++++++
 app/test-pmd/testpmd.h                   |   2 +
 doc/guides/rel_notes/release_20_11.rst   |  10 +
 drivers/net/hns3/hns3_cmd.h              |  19 +-
 drivers/net/hns3/hns3_ethdev.c           | 356 +++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h           |   1 +
 lib/librte_ethdev/rte_ethdev.c           |  44 ++++
 lib/librte_ethdev/rte_ethdev.h           | 105 +++++++++
 lib/librte_ethdev/rte_ethdev_driver.h    |  88 ++++++++
 lib/librte_ethdev/rte_ethdev_version.map |   3 +
 11 files changed, 941 insertions(+), 1 deletion(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V15 1/3] ethdev: introduce FEC API
  2020-09-29  1:03   ` [dpdk-dev] [PATCH V15 0/3] add FEC support Min Hu (Connor)
@ 2020-09-29  1:03     ` Min Hu (Connor)
  2020-09-29  4:18       ` Ajit Khaparde
  2020-09-30  9:45       ` Andrew Rybchenko
  2020-09-29  1:03     ` [dpdk-dev] [PATCH V15 2/3] net/hns3: support FEC Min Hu (Connor)
  2020-09-29  1:03     ` [dpdk-dev] [PATCH V15 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 2 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-29  1:03 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

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>
Acked-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
v14->v15:
change mode to fec_capa in fec set API.

---
v13->v14:
change mode to fec_capa.
fix comment about API.

---
v12->v13:
change fec get capa API.
fix comment styles.

---
v10->v11:
allow to report capabilities per link speed.
specify what should be reported if link is down
when get FEC.
change mode to capa bitmask.

---
v9->v10:
add macro RTE_ETH_FEC_MODE_CAPA_MASK(x) to indicate
different FEC mode capa.

---
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   |   5 ++
 lib/librte_ethdev/rte_ethdev.c           |  44 +++++++++++++
 lib/librte_ethdev/rte_ethdev.h           | 105 +++++++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_driver.h    |  88 ++++++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map |   3 +
 5 files changed, 245 insertions(+)

diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index c6642f5..1f04bd5 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -78,6 +78,11 @@ New Features
     ``--portmask=N``
     where N represents the hexadecimal bitmask of ports used.
 
+* **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.
+
 
 Removed Items
 -------------
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index dfe5c1b..ca596c1 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -3679,6 +3679,50 @@ 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,
+			   struct rte_eth_fec_capa *speed_fec_capa,
+			   unsigned int num)
+{
+	struct rte_eth_dev *dev;
+	int ret;
+
+	if (speed_fec_capa == NULL && num > 0)
+		return -EINVAL;
+
+	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);
+	ret = (*dev->dev_ops->fec_get_capability)(dev, speed_fec_capa, num);
+
+	return ret;
+}
+
+int
+rte_eth_fec_get(uint16_t port_id, uint32_t *fec_capa)
+{
+	struct rte_eth_dev *dev;
+
+	if (fec_capa == NULL)
+		return -EINVAL;
+
+	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, fec_capa));
+}
+
+int
+rte_eth_fec_set(uint16_t port_id, uint32_t fec_capa)
+{
+	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_set, -ENOTSUP);
+	return eth_err(port_id, (*dev->dev_ops->fec_set)(dev, fec_capa));
+}
+
 /*
  * 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 645a186..7938202 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1544,6 +1544,29 @@ 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 */
+};
+
+/* Translate from FEC mode to FEC capa */
+#define RTE_ETH_FEC_MODE_TO_CAPA(x)	(1U << (x))
+
+/* This macro indicates FEC capa mask */
+#define RTE_ETH_FEC_MODE_CAPA_MASK(x)	(1U << (RTE_ETH_FEC_ ## x))
+
+/* A structure used to get capabilities per link speed */
+struct rte_eth_fec_capa {
+	uint32_t speed; /**< Link speed (see ETH_SPEED_NUM_*) */
+	uint32_t capa;  /**< FEC capabilities bitmask */
+};
+
 #define RTE_ETH_ALL RTE_MAX_ETHPORTS
 
 /* Macros to check for valid port */
@@ -3397,6 +3420,88 @@ 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 speed_fec_capa
+ *   speed_fec_capa is out only with per-speed capabilities.
+ *   If set to NULL, the function returns the required number
+ *   of required array entries.
+ * @param num
+ *   a number of elements in an speed_fec_capa array.
+ *
+ * @return
+ *   - A non-negative value lower or equal to num: success. The return value
+ *     is the number of entries filled in the fec capa array.
+ *   - A non-negative value higher than num: error, the given fec capa array
+ *     is too small. The return value corresponds to the num that should
+ *     be given to succeed. The entries in fec capa array are not valid and
+ *     shall not be used by the caller.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ *   - (-EINVAL)  if *num* or *speed_fec_capa* invalid
+ */
+__rte_experimental
+int rte_eth_fec_get_capability(uint16_t port_id,
+			       struct rte_eth_fec_capa *speed_fec_capa,
+			       unsigned int num);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get current Forward Error Correction(FEC) mode.
+ * 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.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param fec_capa
+ *   A bitmask of enabled FEC modes. If AUTO bit is set, other
+ *   bits specify FEC modes which may be negotiated. If AUTO
+ *   bit is clear, specify FEC modes to be used (only one valid
+ *   mode per speed may be set).
+ * @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, uint32_t *fec_capa);
+
+/**
+ * @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 fec_capa
+ *   A bitmask of allowed FEC modes. If AUTO bit is set, other
+ *   bits specify FEC modes which may be negotiated. If AUTO
+ *   bit is clear, specify FEC modes to be used (only one valid
+ *   mode per speed may be set).
+ * @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, uint32_t fec_capa);
+
+/**
  * Get current status of the Ethernet link flow control for Ethernet device
  *
  * @param port_id
diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
index 23cc1e0..f147a67 100644
--- a/lib/librte_ethdev/rte_ethdev_driver.h
+++ b/lib/librte_ethdev/rte_ethdev_driver.h
@@ -575,6 +575,87 @@ 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 speed_fec_capa
+ *   speed_fec_capa is out only with per-speed capabilities.
+ * @param num
+ *   a number of elements in an speed_fec_capa array.
+ *
+ * @return
+ *   Negative errno value on error, positive value on success.
+ *
+ * @retval positive value
+ *   A non-negative value lower or equal to num: success. The return value
+ *   is the number of entries filled in the fec capa array.
+ *   A non-negative value higher than num: error, the given fec capa array
+ *   is too small. The return value corresponds to the num that should
+ *   be given to succeed. The entries in the fec capa array are not valid
+ *   and shall not be used by the caller.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EIO
+ *   Device is removed.
+ * @retval -EINVAL
+ *   *num* or *speed_fec_capa* invalid.
+ */
+typedef int (*eth_fec_get_capability_t)(struct rte_eth_dev *dev,
+		struct rte_eth_fec_capa *speed_fec_capa, unsigned int num);
+
+/**
+ * @internal
+ * Get Forward Error Correction(FEC) mode.
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param fec_capa
+ *   a bitmask of enabled FEC modes. If AUTO bit is set, other
+ *   bits specify FEC modes which may be negotiated. If AUTO
+ *   bit is clear, specify FEC modes to be used (only one valid
+ *   mode per speed may be set).
+ *
+ * @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.
+ */
+typedef int (*eth_fec_get_t)(struct rte_eth_dev *dev,
+			     uint32_t *fec_capa);
+
+/**
+ * @internal
+ * Set Forward Error Correction(FEC) mode.
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param fec_capa
+ *   bitmask of allowed FEC modes. It must be only one
+ *   if AUTO is disabled. If AUTO is enabled, other
+ *   bits specify FEC modes which may be negotiated.
+ *
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success, set FEC success.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EINVAL
+ *   Unsupported FEC mode requested.
+ * @retval -EIO
+ *   Device is removed.
+ */
+typedef int (*eth_fec_set_t)(struct rte_eth_dev *dev, uint32_t fec_capa);
+
+/**
  * @internal A structure containing the functions exported by an Ethernet driver.
  */
 struct eth_dev_ops {
@@ -713,6 +794,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 c95ef51..b9ace3a 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -229,6 +229,9 @@ EXPERIMENTAL {
 	# added in 20.11
 	rte_eth_link_speed_to_str;
 	rte_eth_link_to_str;
+	rte_eth_fec_get_capability;
+	rte_eth_fec_get;
+	rte_eth_fec_set;
 };
 
 INTERNAL {
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V15 2/3] net/hns3: support FEC
  2020-09-29  1:03   ` [dpdk-dev] [PATCH V15 0/3] add FEC support Min Hu (Connor)
  2020-09-29  1:03     ` [dpdk-dev] [PATCH V15 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-29  1:03     ` Min Hu (Connor)
  2020-09-29  1:03     ` [dpdk-dev] [PATCH V15 3/3] app/testpmd: add FEC command Min Hu (Connor)
  2 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-29  1:03 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

Forward error correction (FEC) is a bit error correction mode.
It adds error correction information to data packets at the
transmit end, and uses the error correction information to correct
the bit errors generated during data packet transmission at the
receive end. This improves signal quality but also brings a delay
to signals. This function can be enabled or disabled as required.

This patch adds FEC support for ethdev.Introduce ethdev
operations 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>
---
v13->v14:
change mode to fec_capa.

---
v12->v13:
change fec get capa interface.

---
v11->v12:
fix coding warning.

v10->v11:
allow to report capabilities per link speed.
specify what should be reported if link is down
when get FEC.
change mode to capa bitmask.

---
v9->v10:
use RTE_ETH_FEC_MODE_CAPA_MASK(x) which is just defined.

---
v7->v8:
FEC mode order defined in hns3 hardware is inconsistend with
that defined in the ethdev library. So the sequence needs
to be converted.

---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Data type for fec_cap is changed from uint8_t
to uint32_t for possible future expansion.

---
v2->v3:
adjust the return value of function.

---
 doc/guides/rel_notes/release_20_11.rst |   5 +
 drivers/net/hns3/hns3_cmd.h            |  19 +-
 drivers/net/hns3/hns3_ethdev.c         | 356 +++++++++++++++++++++++++++++++++
 drivers/net/hns3/hns3_ethdev.h         |   1 +
 4 files changed, 380 insertions(+), 1 deletion(-)

diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index 1f04bd5..eec6930 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -83,6 +83,11 @@ New Features
   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/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index 87d6053..a1e9604 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -100,6 +100,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_QUERY_LINK_STATUS      = 0x0307,
 	HNS3_OPC_CONFIG_MAX_FRM_SIZE    = 0x0308,
 	HNS3_OPC_CONFIG_SPEED_DUP       = 0x0309,
+	HNS3_OPC_CONFIG_FEC_MODE        = 0x031A,
 
 	/* PFC/Pause commands */
 	HNS3_OPC_CFG_MAC_PAUSE_EN       = 0x0701,
@@ -684,9 +685,25 @@ struct hns3_config_auto_neg_cmd {
 	uint8_t   rsv[20];
 };
 
+#define HNS3_MAC_CFG_FEC_AUTO_EN_B	0
+#define HNS3_MAC_CFG_FEC_MODE_S		1
+#define HNS3_MAC_CFG_FEC_MODE_M	GENMASK(3, 1)
+#define HNS3_MAC_FEC_OFF		0
+#define HNS3_MAC_FEC_BASER		1
+#define HNS3_MAC_FEC_RS			2
+
 struct hns3_sfp_speed_cmd {
 	uint32_t  sfp_speed;
-	uint32_t  rsv[5];
+	uint8_t   query_type; /* 0: sfp speed, 1: active fec */
+	uint8_t   active_fec; /* current FEC mode */
+	uint16_t  rsv1;
+	uint32_t  rsv2[4];
+};
+
+/* Configure FEC mode, opcode:0x031A */
+struct hns3_config_fec_cmd {
+	uint8_t fec_mode;
+	uint8_t rsv[23];
 };
 
 #define HNS3_MAC_MGR_MASK_VLAN_B		BIT(0)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 73d5042..2fa1aea 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -63,6 +63,11 @@
 #define HNS3_RESET_WAIT_MS	100
 #define HNS3_RESET_WAIT_CNT	200
 
+/* FEC mode order defined in HNS3 hardware */
+#define HNS3_HW_FEC_MODE_NOFEC  0
+#define HNS3_HW_FEC_MODE_BASER  1
+#define HNS3_HW_FEC_MODE_RS     2
+
 enum hns3_evt_cause {
 	HNS3_VECTOR0_EVENT_RST,
 	HNS3_VECTOR0_EVENT_MBX,
@@ -70,6 +75,34 @@ enum hns3_evt_cause {
 	HNS3_VECTOR0_EVENT_OTHER,
 };
 
+static const struct rte_eth_fec_capa speed_fec_capa_tbl[] = {
+	{ ETH_SPEED_NUM_10G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(BASER) },
+
+	{ ETH_SPEED_NUM_25G, 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) },
+
+	{ ETH_SPEED_NUM_40G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			     RTE_ETH_FEC_MODE_CAPA_MASK(BASER) },
+
+	{ ETH_SPEED_NUM_50G, 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) },
+
+	{ ETH_SPEED_NUM_100G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(RS) },
+
+	{ ETH_SPEED_NUM_200G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(AUTO) |
+			      RTE_ETH_FEC_MODE_CAPA_MASK(RS) }
+};
+
 static enum hns3_reset_level hns3_get_reset_level(struct hns3_adapter *hns,
 						 uint64_t *levels);
 static int hns3_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
@@ -81,6 +114,8 @@ static int hns3_add_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
 static int hns3_remove_mc_addr(struct hns3_hw *hw,
 			    struct rte_ether_addr *mac_addr);
+static int hns3_restore_fec(struct hns3_hw *hw);
+static int hns3_query_dev_fec_info(struct rte_eth_dev *dev);
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -2889,6 +2924,13 @@ hns3_get_capability(struct hns3_hw *hw)
 	    device_id == HNS3_DEV_ID_200G_RDMA)
 		hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_DCB_B, 1);
 
+	ret = hns3_query_dev_fec_info(eth_dev);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			     "failed to query FEC information, ret = %d", ret);
+		return ret;
+	}
+
 	/* Get PCI revision id */
 	ret = rte_pci_read_config(pci_dev, &revision, HNS3_PCI_REVISION_ID_LEN,
 				  HNS3_PCI_REVISION_ID);
@@ -5446,6 +5488,10 @@ hns3_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_promisc;
 
+	ret = hns3_restore_fec(hw);
+	if (ret)
+		goto err_promisc;
+
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED) {
 		ret = hns3_do_start(hns, false);
 		if (ret)
@@ -5524,6 +5570,313 @@ hns3_reset_service(void *param)
 		hns3_msix_process(hns, reset_level);
 }
 
+static unsigned int
+hns3_get_speed_capa_num(uint16_t device_id)
+{
+	unsigned int num;
+
+	switch (device_id) {
+	case HNS3_DEV_ID_25GE:
+	case HNS3_DEV_ID_25GE_RDMA:
+		num = 2;
+		break;
+	case HNS3_DEV_ID_100G_RDMA_MACSEC:
+	case HNS3_DEV_ID_200G_RDMA:
+		num = 1;
+		break;
+	default:
+		num = 0;
+		break;
+	}
+
+	return num;
+}
+
+static int
+hns3_get_speed_fec_capa(struct rte_eth_fec_capa *speed_fec_capa,
+			uint16_t device_id)
+{
+	switch (device_id) {
+	case HNS3_DEV_ID_25GE:
+	/* fallthrough */
+	case HNS3_DEV_ID_25GE_RDMA:
+		speed_fec_capa[0].speed = speed_fec_capa_tbl[1].speed;
+		speed_fec_capa[0].capa = speed_fec_capa_tbl[1].capa;
+
+		/* In HNS3 device, the 25G NIC is compatible with 10G rate */
+		speed_fec_capa[1].speed = speed_fec_capa_tbl[0].speed;
+		speed_fec_capa[1].capa = speed_fec_capa_tbl[0].capa;
+		break;
+	case HNS3_DEV_ID_100G_RDMA_MACSEC:
+		speed_fec_capa[0].speed = speed_fec_capa_tbl[4].speed;
+		speed_fec_capa[0].capa = speed_fec_capa_tbl[4].capa;
+		break;
+	case HNS3_DEV_ID_200G_RDMA:
+		speed_fec_capa[0].speed = speed_fec_capa_tbl[5].speed;
+		speed_fec_capa[0].capa = speed_fec_capa_tbl[5].capa;
+		break;
+	default:
+		return -ENOTSUP;
+	}
+
+	return 0;
+}
+
+static int
+hns3_fec_get_capability(struct rte_eth_dev *dev,
+			struct rte_eth_fec_capa *speed_fec_capa,
+			unsigned int num)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	uint16_t device_id = pci_dev->id.device_id;
+	unsigned int capa_num;
+	int ret;
+
+	capa_num = hns3_get_speed_capa_num(device_id);
+	if (capa_num == 0) {
+		hns3_err(hw, "device(0x%x) is not supported by hns3 PMD",
+			 device_id);
+		return -ENOTSUP;
+	}
+
+	if (speed_fec_capa == NULL || num < capa_num)
+		return capa_num;
+
+	ret = hns3_get_speed_fec_capa(speed_fec_capa, device_id);
+	if (ret)
+		return -ENOTSUP;
+
+	return capa_num;
+}
+
+static int
+get_current_fec_auto_state(struct hns3_hw *hw, uint8_t *state)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, true);
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret) {
+		hns3_err(hw, "get current fec auto state failed, ret = %d",
+			 ret);
+		return ret;
+	}
+
+	*state = req->fec_mode & (1U << HNS3_MAC_CFG_FEC_AUTO_EN_B);
+	return 0;
+}
+
+static int
+hns3_fec_get(struct rte_eth_dev *dev, uint32_t *fec_capa)
+{
+#define QUERY_ACTIVE_SPEED	1
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct hns3_sfp_speed_cmd *resp;
+	uint32_t tmp_fec_capa;
+	uint8_t auto_state;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	/*
+	 * 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.
+	 */
+	if (hw->mac.link_status == ETH_LINK_DOWN) {
+		ret = get_current_fec_auto_state(hw, &auto_state);
+		if (ret)
+			return ret;
+
+		if (auto_state == 0x1) {
+			*fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
+			return 0;
+		}
+	}
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_SFP_GET_SPEED, true);
+	resp = (struct hns3_sfp_speed_cmd *)desc.data;
+	resp->query_type = QUERY_ACTIVE_SPEED;
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret == -EOPNOTSUPP) {
+		hns3_err(hw, "IMP do not support get FEC, ret = %d", ret);
+		return ret;
+	} else if (ret) {
+		hns3_err(hw, "get FEC failed, ret = %d", ret);
+		return ret;
+	}
+
+	/*
+	 * FEC mode order defined in hns3 hardware is inconsistend with
+	 * that defined in the ethdev library. So the sequence needs
+	 * to be converted.
+	 */
+	switch (resp->active_fec) {
+	case HNS3_HW_FEC_MODE_NOFEC:
+		tmp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
+		break;
+	case HNS3_HW_FEC_MODE_BASER:
+		tmp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
+		break;
+	case HNS3_HW_FEC_MODE_RS:
+		tmp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(RS);
+		break;
+	default:
+		tmp_fec_capa = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
+		break;
+	}
+
+	*fec_capa = tmp_fec_capa;
+	return 0;
+}
+
+static int
+hns3_set_fec_hw(struct hns3_hw *hw, uint32_t mode)
+{
+	struct hns3_config_fec_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_FEC_MODE, false);
+
+	req = (struct hns3_config_fec_cmd *)desc.data;
+	switch (mode) {
+	case RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC):
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_OFF);
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(BASER):
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_BASER);
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(RS):
+		hns3_set_field(req->fec_mode, HNS3_MAC_CFG_FEC_MODE_M,
+				HNS3_MAC_CFG_FEC_MODE_S, HNS3_MAC_FEC_RS);
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(AUTO):
+		hns3_set_bit(req->fec_mode, HNS3_MAC_CFG_FEC_AUTO_EN_B, 1);
+		break;
+	default:
+		return 0;
+	}
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw, "set fec mode failed, ret = %d", ret);
+
+	return ret;
+}
+
+static uint32_t
+get_current_speed_fec_cap(struct hns3_hw *hw, struct rte_eth_fec_capa *fec_capa)
+{
+	struct hns3_mac *mac = &hw->mac;
+	uint32_t cur_capa;
+
+	switch (mac->link_speed) {
+	case ETH_SPEED_NUM_10G:
+		cur_capa = fec_capa[1].capa;
+		break;
+	case ETH_SPEED_NUM_25G:
+	case ETH_SPEED_NUM_100G:
+	case ETH_SPEED_NUM_200G:
+		cur_capa = fec_capa[0].capa;
+		break;
+	default:
+		cur_capa = 0;
+		break;
+	}
+
+	return cur_capa;
+}
+
+static bool
+is_fec_mode_one_bit_set(uint32_t mode)
+{
+	int cnt = 0;
+	uint8_t i;
+
+	for (i = 0; i < sizeof(mode); i++)
+		if (mode >> i & 0x1)
+			cnt++;
+
+	return cnt == 1 ? true : false;
+}
+
+static int
+hns3_fec_set(struct rte_eth_dev *dev, uint32_t mode)
+{
+#define FEC_CAPA_NUM 2
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+
+	struct rte_eth_fec_capa fec_capa[FEC_CAPA_NUM];
+	uint32_t cur_capa;
+	uint32_t num = FEC_CAPA_NUM;
+	int ret;
+
+	ret = hns3_fec_get_capability(dev, fec_capa, num);
+	if (ret < 0)
+		return ret;
+
+	/* HNS3 PMD driver only support one bit set mode, e.g. 0x1, 0x4 */
+	if (!is_fec_mode_one_bit_set(mode))
+		hns3_err(hw, "FEC mode(0x%x) not supported in HNS3 PMD,"
+			     "FEC mode should be only one bit set", mode);
+
+	/*
+	 * Check whether the configured mode is within the FEC capability.
+	 * If not, the configured mode will not be supported.
+	 */
+	cur_capa = get_current_speed_fec_cap(hw, fec_capa);
+	if (!(cur_capa & mode)) {
+		hns3_err(hw, "unsupported FEC mode = 0x%x", mode);
+		return -EINVAL;
+	}
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		return ret;
+
+	pf->fec_mode = mode;
+	return 0;
+}
+
+static int
+hns3_restore_fec(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+	uint32_t mode = pf->fec_mode;
+	int ret;
+
+	ret = hns3_set_fec_hw(hw, mode);
+	if (ret)
+		hns3_err(hw, "restore fec mode(0x%x) failed, ret = %d",
+			 mode, ret);
+
+	return ret;
+}
+
+static int
+hns3_query_dev_fec_info(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(hns);
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	ret = hns3_fec_get(dev, &pf->fec_mode);
+	if (ret)
+		hns3_err(hw, "query device FEC info failed, ret = %d", ret);
+
+	return ret;
+}
+
 static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.dev_configure      = hns3_dev_configure,
 	.dev_start          = hns3_dev_start,
@@ -5573,6 +5926,9 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.get_reg                = hns3_get_regs,
 	.get_dcb_info           = hns3_get_dcb_info,
 	.dev_supported_ptypes_get = hns3_dev_supported_ptypes_get,
+	.fec_get_capability     = hns3_fec_get_capability,
+	.fec_get                = hns3_fec_get,
+	.fec_set                = hns3_fec_set,
 };
 
 static const struct hns3_reset_ops hns3_reset_ops = {
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index fd6a9f9..393b91f 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -620,6 +620,7 @@ struct hns3_pf {
 	struct hns3_err_msix_intr_stats abn_int_stats;
 
 	bool support_sfp_query;
+	uint32_t fec_mode; /* current FEC mode for ethdev */
 
 	struct hns3_vtag_cfg vtag_config;
 	LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* [dpdk-dev] [PATCH V15 3/3] app/testpmd: add FEC command
  2020-09-29  1:03   ` [dpdk-dev] [PATCH V15 0/3] add FEC support Min Hu (Connor)
  2020-09-29  1:03     ` [dpdk-dev] [PATCH V15 1/3] ethdev: introduce FEC API Min Hu (Connor)
  2020-09-29  1:03     ` [dpdk-dev] [PATCH V15 2/3] net/hns3: support FEC Min Hu (Connor)
@ 2020-09-29  1:03     ` Min Hu (Connor)
  2020-09-30 16:52       ` Ferruh Yigit
  2 siblings, 1 reply; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-29  1:03 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, thomas, arybchenko, ferruh.yigit, linuxarm

This commit adds testpmd capability to query and config FEC
function of device. This includes:
- show FEC capabilities, example:
	testpmd> show port 0 fec capabilities
- show FEC mode, example:
	testpmd> show port 0 fec_mode
- config FEC mode, example:
	testpmd> set port <port_id> 0 <auto|off|rs|baser>

	where:

	auto|off|rs|baser are four kinds of FEC mode which dev
	support according to MAC link speed.

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>
---
v12->v13:
change fec get capa interface.

---
v10->v11:
change mode to capa bitmask.

---
v8->v9:
added acked-by.

---
v6->v7:
used RTE_DIM(fec_mode_name) instead of RTE_ETH_FEC_NUM

---
v5->v6:
fixed code styles according to DPDK coding style.
added _eth prefix.

---
v4->v5:
Add RTE_ prefix for public FEC mode enum.

---
v3->v4:
adjust the display format of FEC mode

---
v2->v3:
adjust the display format of FEC capability.

---
 app/test-pmd/cmdline.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c  |  91 ++++++++++++++++++++
 app/test-pmd/testpmd.h |   2 +
 3 files changed, 316 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 5f93409..407513c 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -19161,6 +19161,226 @@ cmdline_parse_inst_t cmd_show_tx_metadata = {
 	},
 };
 
+/* *** show fec capability per port configuration *** */
+struct cmd_show_fec_capability_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_fec;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_capability_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_CAP_NUM 2
+	struct cmd_show_fec_capability_result *res = parsed_result;
+	struct rte_eth_fec_capa speed_fec_capa[FEC_CAP_NUM];
+	unsigned int num = FEC_CAP_NUM;
+	unsigned int ret_num;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_fec_get_capability(res->cmd_pid, speed_fec_capa, num);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC capability failed\n");
+		return;
+	}
+
+	ret_num = (unsigned int)ret;
+	show_fec_capability(ret_num, speed_fec_capa);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_capability_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_capability_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_capability_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_capability_fec =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_fec, "fec");
+cmdline_parse_token_string_t cmd_show_fec_capability_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_capability_result,
+			cmd_keyword, "capabilities");
+
+cmdline_parse_inst_t cmd_show_capability = {
+	.f = cmd_show_fec_capability_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec capabilities",
+	.tokens = {
+		(void *)&cmd_show_fec_capability_show,
+		(void *)&cmd_show_fec_capability_port,
+		(void *)&cmd_show_fec_capability_pid,
+		(void *)&cmd_show_fec_capability_fec,
+		(void *)&cmd_show_fec_capability_keyword,
+		NULL,
+	},
+};
+
+/* *** show fec mode per port configuration *** */
+struct cmd_show_fec_metadata_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_fec_mode_parsed(void *parsed_result,
+		__rte_unused struct cmdline *cl,
+		__rte_unused void *data)
+{
+#define FEC_NAME_SIZE 16
+	struct cmd_show_fec_metadata_result *res = parsed_result;
+	uint32_t mode;
+	char buf[FEC_NAME_SIZE];
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		printf("Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+	ret = rte_eth_fec_get(res->cmd_pid, &mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Get FEC mode failed\n");
+		return;
+	}
+
+	switch (mode) {
+	case RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC):
+		strlcpy(buf, "off", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(AUTO):
+		strlcpy(buf, "auto", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(BASER):
+		strlcpy(buf, "baser", sizeof(buf));
+		break;
+	case RTE_ETH_FEC_MODE_CAPA_MASK(RS):
+		strlcpy(buf, "rs", sizeof(buf));
+		break;
+	default:
+		return;
+	}
+
+	printf("%s\n", buf);
+}
+
+cmdline_parse_token_string_t cmd_show_fec_mode_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_fec_mode_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_fec_mode_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_fec_mode_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_fec_metadata_result,
+			cmd_keyword, "fec_mode");
+
+cmdline_parse_inst_t cmd_show_fec_mode = {
+	.f = cmd_show_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> fec_mode",
+	.tokens = {
+		(void *)&cmd_show_fec_mode_show,
+		(void *)&cmd_show_fec_mode_port,
+		(void *)&cmd_show_fec_mode_pid,
+		(void *)&cmd_show_fec_mode_keyword,
+		NULL,
+	},
+};
+
+/* *** set fec mode per port configuration *** */
+struct cmd_set_port_fec_mode {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t fec_mode;
+	cmdline_fixed_string_t fec_value;
+};
+
+/* Common CLI fields for set fec mode */
+cmdline_parse_token_string_t cmd_set_port_fec_mode_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port, "port");
+cmdline_parse_token_num_t cmd_set_port_fec_mode_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_port_fec_mode_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_mode, "fec_mode");
+cmdline_parse_token_string_t cmd_set_port_fec_mode_value =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_port_fec_mode,
+		 fec_value, NULL);
+
+static void
+cmd_set_port_fec_mode_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	__rte_unused void *data)
+{
+	struct cmd_set_port_fec_mode *res = parsed_result;
+	uint16_t port_id = res->port_id;
+	uint32_t mode;
+	int ret;
+
+	ret = parse_fec_mode(res->fec_value, &mode);
+	if (ret < 0) {
+		printf("Unknown fec mode: %s for Port %d\n", res->fec_value,
+			port_id);
+		return;
+	}
+
+	ret = rte_eth_fec_set(port_id, mode);
+	if (ret == -ENOTSUP) {
+		printf("Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		printf("Set FEC mode failed\n");
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_fec_mode = {
+	.f = cmd_set_port_fec_mode_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> fec_mode <auto|off|rs|baser>",
+	.tokens = {
+		(void *)&cmd_set_port_fec_mode_set,
+		(void *)&cmd_set_port_fec_mode_port,
+		(void *)&cmd_set_port_fec_mode_port_id,
+		(void *)&cmd_set_port_fec_mode_str,
+		(void *)&cmd_set_port_fec_mode_value,
+		NULL,
+	},
+};
+
 /* show port supported ptypes */
 
 /* Common result structure for show port ptypes */
@@ -19795,6 +20015,9 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_set_raw,
 	(cmdline_parse_inst_t *)&cmd_show_set_raw_all,
 	(cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
+	(cmdline_parse_inst_t *)&cmd_show_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_set_fec_mode,
+	(cmdline_parse_inst_t *)&cmd_show_capability,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 2d9a456..897ceaf 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -138,6 +138,58 @@ const struct rss_type_info rss_type_table[] = {
 	{ NULL, 0 },
 };
 
+static const struct {
+	enum rte_eth_fec_mode mode;
+	const char *name;
+} fec_mode_name[] = {
+	{
+		.mode = RTE_ETH_FEC_NOFEC,
+		.name = "off",
+	},
+	{
+		.mode = RTE_ETH_FEC_AUTO,
+		.name = "auto",
+	},
+	{
+		.mode = RTE_ETH_FEC_BASER,
+		.name = "baser",
+	},
+	{
+		.mode = RTE_ETH_FEC_RS,
+		.name = "rs",
+	},
+};
+
+static const struct {
+	uint32_t speed;
+	const char *name;
+} eth_speed_name[] = {
+	{
+		.speed = ETH_SPEED_NUM_10G,
+		.name = "Speed 10G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_25G,
+		.name = "Speed 25G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_40G,
+		.name = "Speed 40G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_50G,
+		.name = "Speed 50G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_100G,
+		.name = "Speed 100G",
+	},
+	{
+		.speed = ETH_SPEED_NUM_200G,
+		.name = "Speed 200G",
+	},
+};
+
 static void
 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
 {
@@ -2969,6 +3021,45 @@ set_tx_pkt_split(const char *name)
 	printf("unknown value: \"%s\"\n", name);
 }
 
+int
+parse_fec_mode(const char *name, uint32_t *mode)
+{
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(fec_mode_name); i++) {
+		if (strcmp(fec_mode_name[i].name, name) == 0) {
+			*mode = RTE_ETH_FEC_MODE_TO_CAPA(fec_mode_name[i].mode);
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void
+show_fec_capability(unsigned int num, struct rte_eth_fec_capa *speed_fec_capa)
+{
+	unsigned int i, j, k;
+
+	printf("FEC capabilities:\n");
+
+	for (i = 0; i < num; i++) {
+		for (j = 0; j < RTE_DIM(eth_speed_name); j++) {
+			if (eth_speed_name[j].speed ==
+						speed_fec_capa[i].speed) {
+				printf("%s : ", eth_speed_name[j].name);
+				break;
+			}
+		}
+
+		for (k = RTE_ETH_FEC_AUTO; k < RTE_DIM(fec_mode_name); k++) {
+			if (RTE_ETH_FEC_MODE_TO_CAPA(k) &
+						speed_fec_capa[i].capa)
+				printf("%s ", fec_mode_name[k].name);
+		}
+		printf("\n");
+	}
+}
+
 void
 show_tx_pkt_segments(void)
 {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index f139fe7..85ea030 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -804,6 +804,8 @@ void show_tx_pkt_segments(void);
 void set_tx_pkt_times(unsigned int *tx_times);
 void show_tx_pkt_times(void);
 void set_tx_pkt_split(const char *name);
+int parse_fec_mode(const char *name, enum rte_eth_fec_mode *mode);
+void show_fec_capability(uint32_t num, struct rte_eth_fec_capa *speed_fec_capa);
 void set_nb_pkt_per_burst(uint16_t pkt_burst);
 char *list_pkt_forwarding_modes(void);
 char *list_pkt_forwarding_retry_modes(void);
-- 
2.7.4


^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V14 1/3] ethdev: introduce FEC API
  2020-09-28 12:48       ` Andrew Rybchenko
@ 2020-09-29  2:09         ` Min Hu (Connor)
  0 siblings, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-29  2:09 UTC (permalink / raw)
  To: Andrew Rybchenko, dev; +Cc: konstantin.ananyev, thomas, ferruh.yigit, linuxarm

Hi, Andrew, ALL,
	I have fixed it in V15. please check it out.
	By the way, I wish this patch will be merged into 20.11.
	Because if missed ,one more year will be waited.
	Please check it,thanks.

在 2020/9/28 20:48, Andrew Rybchenko 写道:
> On 9/28/20 2:08 PM, 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>
>> Acked-by: Andrew Rybchenko <arybchenko@solarflare.com>
> 
> [snip]
> 
>> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
>> index dfe5c1b..996d230 100644
>> --- a/lib/librte_ethdev/rte_ethdev.c
>> +++ b/lib/librte_ethdev/rte_ethdev.c
>> @@ -3679,6 +3679,50 @@ 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,
>> +			   struct rte_eth_fec_capa *speed_fec_capa,
>> +			   unsigned int num)
>> +{
>> +	struct rte_eth_dev *dev;
>> +	int ret;
>> +
>> +	if (speed_fec_capa == NULL && num > 0)
>> +		return -EINVAL;
>> +
>> +	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);
>> +	ret = (*dev->dev_ops->fec_get_capability)(dev, speed_fec_capa, num);
>> +
>> +	return ret;
>> +}
>> +
>> +int
>> +rte_eth_fec_get(uint16_t port_id, uint32_t *fec_capa)
>> +{
>> +	struct rte_eth_dev *dev;
>> +
>> +	if (fec_capa == NULL)
>> +		return -EINVAL;
>> +
>> +	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, fec_capa));
>> +}
>> +
>> +int
>> +rte_eth_fec_set(uint16_t port_id, uint32_t mode)
> 
> mode -> fec_capa, since it is not a single 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_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 645a186..50c5280 100644
>> --- a/lib/librte_ethdev/rte_ethdev.h
>> +++ b/lib/librte_ethdev/rte_ethdev.h
> 
> [snip]
> 
>> @@ -3397,6 +3420,85 @@ 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 speed_fec_capa
>> + *   speed_fec_capa is out only with per-speed capabilities.
>> + *   If set to NULL, the function returns the required number
>> + *   of required array entries.
>> + * @param num
>> + *   a number of elements in an speed_fec_capa array.
>> + *
>> + * @return
>> + *   - A positive value lower or equal to num: success. The return value
> 
> positive -> non-negative
> since 0 is OK if FEC is not applicable/supported
> 
>> + *     is the number of entries filled in the fec capa array.
>> + *   - A positive value higher than num: error, the given fec capa array
> 
> same, positive -> non-negative
> 
>> + *     is too small. The return value corresponds to the num that should
>> + *     be given to succeed. The entries in fec capa array are not valid and
>> + *     shall not be used by the caller.
> 
> OK for me, possible option is to fill in just provided entries
> (up to num)
> 
>> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
>> + *     that operation.
>> + *   - (-EIO) if device is removed.
>> + *   - (-ENODEV)  if *port_id* invalid.
>> + *   - (-EINVAL)  if *num* or *speed_fec_capa* invalid
>> + */
>> +__rte_experimental
>> +int rte_eth_fec_get_capability(uint16_t port_id,
>> +			       struct rte_eth_fec_capa *speed_fec_capa,
>> +			       unsigned int num);
>> +
>> +/**
>> + * @warning
>> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
>> + *
>> + * Get current Forward Error Correction(FEC) mode.
>> + * 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.
>> + *
>> + * @param port_id
>> + *   The port identifier of the Ethernet device.
>> + * @param fec_capa
>> + *   A bitmask of enabled FEC modes. If AUTO bit is set, other
>> + *   bits specify FEC modes which may be negotiated. If AUTO
>> + *   bit is clear, specify FEC modes to be used (only one valid
>> + *   mode per speed may be set).
>> + * @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, uint32_t *fec_capa);
>> +
>> +/**
>> + * @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.
> 
> mode -> fec_capa
> with description from callback below
> 
>> + * @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, uint32_t mode);
>> +
>> +/**
>>    * Get current status of the Ethernet link flow control for Ethernet device
>>    *
>>    * @param port_id
>> diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
>> index 23cc1e0..a1f10d6 100644
>> --- a/lib/librte_ethdev/rte_ethdev_driver.h
>> +++ b/lib/librte_ethdev/rte_ethdev_driver.h
>> @@ -575,6 +575,87 @@ 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 speed_fec_capa
>> + *   speed_fec_capa is out only with per-speed capabilities.
>> + * @param num
>> + *   a number of elements in an speed_fec_capa array.
>> + *
>> + * @return
>> + *   Negative errno value on error, positive value on success.
>> + *
>> + * @retval positive value
>> + *   A positive value lower or equal to num: success. The return value
> 
> same as above
> 
>> + *   is the number of entries filled in the fec capa array.
>> + *   A positive value higher than num: error, the given fec capa array
> 
> same as above
> 
>> + *   is too small. The return value corresponds to the num that should
>> + *   be given to succeed. The entries in the fec capa array are not valid
>> + *   and shall not be used by the caller.
>> + * @retval -ENOTSUP
>> + *   Operation is not supported.
>> + * @retval -EIO
>> + *   Device is removed.
>> + * @retval -EINVAL
>> + *   *num* or *speed_fec_capa* invalid.
>> + */
>> +typedef int (*eth_fec_get_capability_t)(struct rte_eth_dev *dev,
>> +		struct rte_eth_fec_capa *speed_fec_capa, unsigned int num);
>> +
>> +/**
>> + * @internal
>> + * Get Forward Error Correction(FEC) mode.
>> + *
>> + * @param dev
>> + *   ethdev handle of port.
>> + * @param fec_capa
>> + *   a bitmask of enabled FEC modes. If AUTO bit is set, other
>> + *   bits specify FEC modes which may be negotiated. If AUTO
>> + *   bit is clear, specify FEC modes to be used (only one valid
>> + *   mode per speed may be set).
>> + *
>> + * @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.
>> + */
>> +typedef int (*eth_fec_get_t)(struct rte_eth_dev *dev,
>> +			     uint32_t *fec_capa);
>> +
>> +/**
>> + * @internal
>> + * Set Forward Error Correction(FEC) mode.
>> + *
>> + * @param dev
>> + *   ethdev handle of port.
>> + * @param mode
> 
> mode -> fec_capa
> 
>> + *   bitmask of allowed FEC modes. It must be only one
>> + *   if AUTO is disabled. If AUTO is enabled, other
>> + *   bits specify FEC modes which may be negotiated.
>> + *
>> + * @return
>> + *   Negative errno value on error, 0 on success.
>> + *
>> + * @retval 0
>> + *   Success, set FEC success.
>> + * @retval -ENOTSUP
>> + *   Operation is not supported.
>> + * @retval -EINVAL
>> + *   Unsupported FEC mode requested.
>> + * @retval -EIO
>> + *   Device is removed.
>> + */
>> +typedef int (*eth_fec_set_t)(struct rte_eth_dev *dev, uint32_t mode);
>> +
>> +/**
>>    * @internal A structure containing the functions exported by an Ethernet driver.
>>    */
>>   struct eth_dev_ops {
>> @@ -713,6 +794,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 c95ef51..b9ace3a 100644
>> --- a/lib/librte_ethdev/rte_ethdev_version.map
>> +++ b/lib/librte_ethdev/rte_ethdev_version.map
>> @@ -229,6 +229,9 @@ EXPERIMENTAL {
>>   	# added in 20.11
>>   	rte_eth_link_speed_to_str;
>>   	rte_eth_link_to_str;
>> +	rte_eth_fec_get_capability;
>> +	rte_eth_fec_get;
>> +	rte_eth_fec_set;
>>   };
>>   
>>   INTERNAL {
>>
> 
> .
> 

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V15 1/3] ethdev: introduce FEC API
  2020-09-29  1:03     ` [dpdk-dev] [PATCH V15 1/3] ethdev: introduce FEC API Min Hu (Connor)
@ 2020-09-29  4:18       ` Ajit Khaparde
  2020-09-29  8:44         ` Min Hu (Connor)
  2020-09-30  9:45       ` Andrew Rybchenko
  1 sibling, 1 reply; 118+ messages in thread
From: Ajit Khaparde @ 2020-09-29  4:18 UTC (permalink / raw)
  To: Min Hu (Connor)
  Cc: dpdk-dev, Ananyev, Konstantin, Thomas Monjalon, Andrew Rybchenko,
	Ferruh Yigit, linuxarm

On Mon, Sep 28, 2020 at 6:06 PM Min Hu (Connor) <humin29@huawei.com> 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>
> Acked-by: Andrew Rybchenko <arybchenko@solarflare.com>
>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>


>
>

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V15 1/3] ethdev: introduce FEC API
  2020-09-29  4:18       ` Ajit Khaparde
@ 2020-09-29  8:44         ` Min Hu (Connor)
  2020-09-30  2:45           ` Min Hu (Connor)
  2020-09-30  8:15           ` Thomas Monjalon
  0 siblings, 2 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-29  8:44 UTC (permalink / raw)
  To: Ajit Khaparde
  Cc: dpdk-dev, Ananyev, Konstantin, Thomas Monjalon, Andrew Rybchenko,
	Ferruh Yigit, linuxarm


Thank Ajit.

Hi, all,
	Are there any suggestions for this set of patches?
	I wish this patch can be merged into 20.11,and this
	is urget. Please gives reply to me, thanks.

在 2020/9/29 12:18, Ajit Khaparde 写道:
> 
> 
> On Mon, Sep 28, 2020 at 6:06 PM Min Hu (Connor) <humin29@huawei.com 
> <mailto:humin29@huawei.com>> 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
>     <mailto:humin29@huawei.com>>
>     Reviewed-by: Wei Hu (Xavier) <xavier.huwei@huawei.com
>     <mailto:xavier.huwei@huawei.com>>
>     Reviewed-by: Chengwen Feng <fengchengwen@huawei.com
>     <mailto:fengchengwen@huawei.com>>
>     Reviewed-by: Chengchang Tang <tangchengchang@huawei.com
>     <mailto:tangchengchang@huawei.com>>
>     Acked-by: Andrew Rybchenko <arybchenko@solarflare.com
>     <mailto:arybchenko@solarflare.com>>
> 
> Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com 
> <mailto:ajit.khaparde@broadcom.com>>
> 
> 
> 

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: [dpdk-dev] [PATCH V15 1/3] ethdev: introduce FEC API
  2020-09-29  8:44         ` Min Hu (Connor)
@ 2020-09-30  2:45           ` Min Hu (Connor)
  2020-09-30  8:15           ` Thomas Monjalon
  1 sibling, 0 replies; 118+ messages in thread
From: Min Hu (Connor) @ 2020-09-30  2:45 UTC (permalink / raw)
  To: Ajit Khaparde
  Cc: dpdk-dev, linuxarm, Ferruh Yigit, Ananyev, Konstantin,
	Thomas Monjalon, Andrew Rybchenko

Hi, all,
       Are there any suggestions for this set of patches?
       I wish this patch can be merged into V20.11,and this
       is urgent. I only have one day to handle the patches,
       because from 10/1 to 10/8 we will be on holiday.

       Please give reply to me, thanks.

在 2020/9/29 16:44, Min Hu (Connor) 写道:
> 
> Thank Ajit.
> 
> Hi, all,
>      Are there any suggestions for this set of patches?
>      I wish this patch can be merged into 20.11,and this
>      is urget. Please gives reply to me, thanks.
> 
> 在 2020/9/29 12:18, Ajit Khaparde 写道:
>>
>>
>> On Mon, Sep 28, 2020 at 6:06 PM Min Hu (Connor) <humin29@huawei.com 
>> <mailto:humin29@huawei.com>> 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
>>     <mailto:humin29@huawei.com>>
>>     Reviewed-by: Wei Hu (Xavier) <xavier.huwei@huawei.com
>>     <mailto:xavier.huwei@huawei.com>>
>>     Reviewed-by: Chengwen Feng <fengchengwen@huawei.com
>>     <mailto:fengchengwen@huawei.com>>
>>     Reviewed-by: Chengchang Tang <tangchengchang@huawei.com
>>     <mailto:tangchengchang@huawei.com>>
>>     Acked-by: Andrew Rybchenko <arybchenko@solarflare.com
>>     <mailto:arybchenko@solarflare.com>>
>>
>> Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com 
>> <mailto:ajit.khaparde@broadcom.com>>
>>
>>
>>
> _______________________________________________
> Linuxarm mailing list
> Linuxarm@huawei.com
> http://hulk.huawei.com/mailman/listinfo/linuxarm

^ permalink raw reply	[flat|nested] 118+ messages in thread

* Re: