[PATCH v2 40/45] net/sfc: query link status on link change events on new NICs

Ivan Malov ivan.malov at arknetworks.am
Wed Apr 23 17:59:57 CEST 2025


Link events signaled on new adaptors (Medford4 and later) do
not carry any specifics, so query the link status separately.

Signed-off-by: Ivan Malov <ivan.malov at arknetworks.am>
Reviewed-by: Andy Moreton <andy.moreton at amd.com>
Reviewed-by: Pieter Jansen Van Vuuren <pieter.jansen-van-vuuren at amd.com>
---
 drivers/net/sfc/sfc.h        |  2 ++
 drivers/net/sfc/sfc_ethdev.c |  2 ++
 drivers/net/sfc/sfc_ev.c     | 51 +++++++++++++++++++++++++++++++++++-
 3 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 2432a2307e..819ce52529 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -309,6 +309,8 @@ struct sfc_adapter {
 	uint32_t			rxd_wait_timeout_ns;
 
 	bool				switchdev;
+
+	bool				link_ev_need_poll;
 };
 
 static inline struct sfc_adapter_shared *
diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index bd0061f557..05933b1d39 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -3252,6 +3252,8 @@ sfc_eth_dev_init(struct rte_eth_dev *dev, void *init_params)
 	if (rc != 0)
 		goto fail_nic_dma_attach;
 
+	sa->link_ev_need_poll = encp->enc_link_ev_need_poll;
+
 	sfc_adapter_unlock(sa);
 
 	sfc_log_init(sa, "done");
diff --git a/drivers/net/sfc/sfc_ev.c b/drivers/net/sfc/sfc_ev.c
index c0d58c9554..1d1ee0671f 100644
--- a/drivers/net/sfc/sfc_ev.c
+++ b/drivers/net/sfc/sfc_ev.c
@@ -467,9 +467,58 @@ sfc_ev_link_change(void *arg, efx_link_mode_t link_mode)
 {
 	struct sfc_evq *evq = arg;
 	struct sfc_adapter *sa = evq->sa;
-	struct rte_eth_link new_link;
+	struct rte_eth_link new_link = {0};
 
+	if (sa->link_ev_need_poll) {
+		efx_link_mode_t new_mode;
+		bool poll_done = false;
+
+		/*
+		 * The event provides only the general status. When the link is
+		 * up, poll the port to get the speed, but it is not compulsory.
+		 */
+		if (link_mode != EFX_LINK_DOWN) {
+			int ret = 0;
+
+			if (sfc_adapter_trylock(sa)) {
+				/* Never poll when the adaptor is going down. */
+				if (sa->state == SFC_ETHDEV_STARTED) {
+					ret = efx_port_poll(sa->nic, &new_mode);
+					poll_done = true;
+				}
+
+				sfc_adapter_unlock(sa);
+			}
+
+			if (ret != 0) {
+				sfc_warn(sa, "port poll failed on link event");
+				poll_done = false;
+			}
+		}
+
+		if (poll_done) {
+			link_mode = new_mode;
+			goto decode_comprehensive;
+		}
+
+		new_link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
+		new_link.link_autoneg = RTE_ETH_LINK_AUTONEG;
+
+		if (link_mode == EFX_LINK_DOWN) {
+			new_link.link_speed  = RTE_ETH_SPEED_NUM_NONE;
+			new_link.link_status = RTE_ETH_LINK_DOWN;
+		} else {
+			new_link.link_speed  = RTE_ETH_SPEED_NUM_UNKNOWN;
+			new_link.link_status = RTE_ETH_LINK_UP;
+		}
+
+		goto set;
+	}
+
+decode_comprehensive:
 	sfc_port_link_mode_to_info(link_mode, &new_link);
+
+set:
 	if (rte_eth_linkstatus_set(sa->eth_dev, &new_link) == 0)
 		evq->sa->port.lsc_seq++;
 
-- 
2.39.5



More information about the dev mailing list