patch 'net/sfc: rework capability check that is done on FEC set' has been queued to stable release 24.11.5

luca.boccassi at gmail.com luca.boccassi at gmail.com
Fri Feb 20 15:55:33 CET 2026


Hi,

FYI, your patch has been queued to stable release 24.11.5

Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet.
It will be pushed if I get no objections before 02/22/26. So please
shout if anyone has objections.

Also note that after the patch there's a diff of the upstream commit vs the
patch applied to the branch. This will indicate if there was any rebasing
needed to apply to the stable branch. If there were code changes for rebasing
(ie: not only metadata diffs), please double check that the rebase was
correctly done.

Queued patches are on a temporary branch at:
https://github.com/bluca/dpdk-stable

This queued commit can be viewed at:
https://github.com/bluca/dpdk-stable/commit/85661291d85a576a7b1bc155f4b2ad5aaf16cdfe

Thanks.

Luca Boccassi

---
>From 85661291d85a576a7b1bc155f4b2ad5aaf16cdfe Mon Sep 17 00:00:00 2001
From: Ivan Malov <ivan.malov at arknetworks.am>
Date: Tue, 30 Dec 2025 01:35:25 +0400
Subject: [PATCH] net/sfc: rework capability check that is done on FEC set

[ upstream commit 2b57b2b654054fe918a74b888865f40214e66689 ]

The current code that sets new FEC mode does not consult capabilities when
the ethdev is not started. This leads to accepting FEC flags that the last
configured link speed cannot handle. This is shown in 'testpmd' as follows:

port stop all
port config 0 speed 10000 duplex full
port start 0
port stop 0
set port 0 fec_mode rs

In the case of X4 adaptors, RS FEC cannot be supported for such low speeds
and the last command should print 'Function not implemented' error message,
but it doesn't. To fix this, enforce the proper checks in every port state.

Fixes: 5efa8fc1cfc0 ("net/sfc: support FEC feature")

Signed-off-by: Ivan Malov <ivan.malov at arknetworks.am>
Reviewed-by: Andy Moreton <andy.moreton at amd.com>
---
 drivers/net/sfc/sfc_ethdev.c | 109 +++++++++++++++++++++--------------
 1 file changed, 65 insertions(+), 44 deletions(-)

diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index 89444f0b4a..52575c817a 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -7,6 +7,8 @@
  * for Solarflare) and Solarflare Communications, Inc.
  */
 
+#include <stdbool.h>
+
 #include <dev_driver.h>
 #include <ethdev_driver.h>
 #include <ethdev_pci.h>
@@ -14,6 +16,7 @@
 #include <bus_pci_driver.h>
 #include <rte_errno.h>
 #include <rte_string_fns.h>
+#include <rte_bitops.h>
 #include <rte_ether.h>
 
 #include "efx.h"
@@ -2347,6 +2350,10 @@ sfc_rx_metadata_negotiate(struct rte_eth_dev *dev, uint64_t *features)
 	return 0;
 }
 
+/*
+ * When adding support for new speeds/capabilities, make sure to adjust
+ * validity checks conducted by 'sfc_fec_capa_check' for user input.
+ */
 static unsigned int
 sfc_fec_get_capa_speed_to_fec(uint32_t supported_caps,
 			      struct rte_eth_fec_capa *speed_fec_capa)
@@ -2559,60 +2566,74 @@ adapter_unlock:
 	return -rc;
 }
 
+/*
+ * When adding checks for new speeds and/or capabilities, keep that consistent
+ * with capabilities that 'sfc_fec_get_capa_speed_to_fec' reports to the user.
+ */
 static int
 sfc_fec_capa_check(struct rte_eth_dev *dev, uint32_t fec_capa,
 		   uint32_t supported_caps)
 {
-	struct rte_eth_fec_capa *speed_fec_capa;
-	struct rte_eth_link current_link;
-	bool is_supported = false;
-	unsigned int num_entries;
-	bool auto_fec = false;
-	unsigned int i;
-
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
-
-	if (sa->state != SFC_ETHDEV_STARTED)
-		return 0;
+	unsigned int ncaps = rte_popcount32(fec_capa);
+	/* Set by 'sfc_phy_cap_from_link_speeds'. */
+	uint32_t speeds_cur = sa->port.phy_adv_cap;
+	uint32_t speeds_baser = 0;
+	uint32_t speeds_rs = 0;
 
 	if (fec_capa & RTE_ETH_FEC_MODE_TO_CAPA(RTE_ETH_FEC_AUTO)) {
-		auto_fec = true;
-		fec_capa &= ~RTE_ETH_FEC_MODE_TO_CAPA(RTE_ETH_FEC_AUTO);
-	}
-
-	/*
-	 * If only the AUTO bit is set, the decision on which FEC
-	 * mode to use will be made by HW/FW or driver.
-	 */
-	if (auto_fec && fec_capa == 0)
-		return 0;
-
-	sfc_dev_get_rte_link(dev, 1, &current_link);
-
-	num_entries = sfc_fec_get_capa_speed_to_fec(supported_caps, NULL);
-	if (num_entries == 0)
-		return ENOTSUP;
-
-	speed_fec_capa = rte_calloc("fec_capa", num_entries,
-				    sizeof(*speed_fec_capa), 0);
-	num_entries = sfc_fec_get_capa_speed_to_fec(supported_caps,
-						    speed_fec_capa);
-
-	for (i = 0; i < num_entries; i++) {
-		if (speed_fec_capa[i].speed == current_link.link_speed) {
-			if ((fec_capa & speed_fec_capa[i].capa) != 0)
-				is_supported = true;
-
-			break;
+		if (ncaps == 1) {
+			/* Let the FW choose a best-effort setting. */
+			return 0;
+		} else {
+			/*
+			 * Each requested FEC capability must be supported in
+			 * general and at least one speed that supports this
+			 * FEC mode must be currently advertised/configured.
+			 */
 		}
-	}
-
-	rte_free(speed_fec_capa);
-
-	if (is_supported)
+	} else if (ncaps != 1) {
+		/*
+		 * Fixed FEC mode does not allow for multiple capabilities.
+		 * Empty mask is invalid, as No-FEC has a capability bit.
+		 */
+		return EINVAL;
+	} else if (fec_capa & RTE_ETH_FEC_MODE_TO_CAPA(RTE_ETH_FEC_NOFEC)) {
+		/* No-FEC is assumed to be always acceptable. */
 		return 0;
+	}
 
-	return ENOTSUP;
+	/* 25G BASE-R is accounted for separately below. */
+	speeds_baser |= (1U << EFX_PHY_CAP_50000FDX);
+	speeds_baser |= (1U << EFX_PHY_CAP_40000FDX);
+	speeds_baser |= (1U << EFX_PHY_CAP_10000FDX);
+
+	speeds_rs |= (1U << EFX_PHY_CAP_100000FDX);
+	speeds_rs |= (1U << EFX_PHY_CAP_50000FDX);
+	speeds_rs |= (1U << EFX_PHY_CAP_25000FDX);
+
+	if (fec_capa & RTE_ETH_FEC_MODE_TO_CAPA(RTE_ETH_FEC_BASER)) {
+		bool supported = false;
+
+		if ((supported_caps & EFX_PHY_CAP_FEC_BIT(25G_BASER_FEC)) &&
+		    (speeds_cur & (1U << EFX_PHY_CAP_25000FDX)))
+			supported = true;
+
+		if ((supported_caps & EFX_PHY_CAP_FEC_BIT(BASER_FEC)) &&
+		    (speeds_cur & speeds_baser))
+			supported = true;
+
+		if (!supported)
+			return ENOTSUP;
+	}
+
+	if (fec_capa & RTE_ETH_FEC_MODE_TO_CAPA(RTE_ETH_FEC_RS)) {
+		if ((supported_caps & EFX_PHY_CAP_FEC_BIT(RS_FEC)) == 0 ||
+		    (speeds_cur & speeds_rs) == 0)
+			return ENOTSUP;
+	}
+
+	return 0;
 }
 
 static int
-- 
2.47.3

---
  Diff of the applied patch vs upstream commit (please double-check if non-empty:
---
--- -	2026-02-20 14:55:44.532504641 +0000
+++ 0031-net-sfc-rework-capability-check-that-is-done-on-FEC-.patch	2026-02-20 14:55:43.204191074 +0000
@@ -1 +1 @@
-From 2b57b2b654054fe918a74b888865f40214e66689 Mon Sep 17 00:00:00 2001
+From 85661291d85a576a7b1bc155f4b2ad5aaf16cdfe Mon Sep 17 00:00:00 2001
@@ -5,0 +6,2 @@
+[ upstream commit 2b57b2b654054fe918a74b888865f40214e66689 ]
+
@@ -21 +22,0 @@
-Cc: stable at dpdk.org
@@ -26,2 +27,2 @@
- drivers/net/sfc/sfc_ethdev.c | 110 +++++++++++++++++++++--------------
- 1 file changed, 66 insertions(+), 44 deletions(-)
+ drivers/net/sfc/sfc_ethdev.c | 109 +++++++++++++++++++++--------------
+ 1 file changed, 65 insertions(+), 44 deletions(-)
@@ -30 +31 @@
-index 6d2349a999..fc759f52fe 100644
+index 89444f0b4a..52575c817a 100644
@@ -50 +51 @@
-@@ -2496,6 +2499,10 @@ sfc_rx_metadata_negotiate(struct rte_eth_dev *dev, uint64_t *features)
+@@ -2347,6 +2350,10 @@ sfc_rx_metadata_negotiate(struct rte_eth_dev *dev, uint64_t *features)
@@ -61 +62 @@
-@@ -2721,60 +2728,75 @@ adapter_unlock:
+@@ -2559,60 +2566,74 @@ adapter_unlock:
@@ -151 +151,0 @@
-+	speeds_rs |= (1U << EFX_PHY_CAP_200000FDX);


More information about the stable mailing list