[PATCH 9/9] net/sfc: fix reporting status of autonegotiation to the user

Ivan Malov
2025-12-29T21:36:32Z

Currently, the driver always indicates speed autonegotiation to be enabled,
even when the user has disabled it. Fix the code to report the true status.

Fixes: 886f8d8a05bf ("net/sfc: retrieve link info")
Cc: stable@dpdk.org

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <andy.moreton@amd.com>
---
drivers/net/sfc/sfc.h | 2 +-
drivers/net/sfc/sfc_ethdev.c | 5 +++--
drivers/net/sfc/sfc_ev.c | 7 ++++++-
drivers/net/sfc/sfc_port.c | 8 +++++---
drivers/net/sfc/sfc_repr.c | 2 +-
5 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index af32ccfaa3..629578549f 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -417,7 +417,7 @@ int sfc_port_configure(struct sfc_adapter *sa);
void sfc_port_close(struct sfc_adapter *sa);
int sfc_port_start(struct sfc_adapter *sa);
void sfc_port_stop(struct sfc_adapter *sa);
-void sfc_port_link_mode_to_info(efx_link_mode_t link_mode,
+void sfc_port_link_mode_to_info(efx_link_mode_t link_mode, uint32_t phy_cap_req,
struct rte_eth_link *link_info);
int sfc_port_update_mac_stats(struct sfc_adapter *sa, boolean_t manual_update);
int sfc_port_get_mac_stats(struct sfc_adapter *sa, struct rte_eth_xstat *xstats,
diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index 7c2abaab6b..6be98c49d0 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -262,13 +262,14 @@ sfc_dev_get_rte_link(struct rte_eth_dev *dev, int wait_to_complete,
SFC_ASSERT(link != NULL);

if (sa->state != SFC_ETHDEV_STARTED) {
- sfc_port_link_mode_to_info(EFX_LINK_UNKNOWN, link);
+ sfc_port_link_mode_to_info(EFX_LINK_UNKNOWN, 0, link);
} else if (wait_to_complete) {
efx_link_mode_t link_mode;

if (efx_port_poll(sa->nic, &link_mode) != 0)
link_mode = EFX_LINK_UNKNOWN;
- sfc_port_link_mode_to_info(link_mode, link);
+ sfc_port_link_mode_to_info(link_mode, sa->port.phy_adv_cap,
+ link);
} else {
sfc_ev_mgmt_qpoll(sa);
rte_eth_linkstatus_get(dev, link);
diff --git a/drivers/net/sfc/sfc_ev.c b/drivers/net/sfc/sfc_ev.c
index 1d1ee0671f..f058b3cb9b 100644
--- a/drivers/net/sfc/sfc_ev.c
+++ b/drivers/net/sfc/sfc_ev.c
@@ -516,7 +516,12 @@ sfc_ev_link_change(void *arg, efx_link_mode_t link_mode)
}

decode_comprehensive:
- sfc_port_link_mode_to_info(link_mode, &new_link);
+ /*
+ * Reading 'sa->port.phy_adv_cap' without acquiring adaptor lock may
+ * render autonegotiation status inaccurate, but that's not critical,
+ * as it's unlikely to happen often and may be a practical trade-off.
+ */
+ sfc_port_link_mode_to_info(link_mode, sa->port.phy_adv_cap, &new_link);

set:
if (rte_eth_linkstatus_set(sa->eth_dev, &new_link) == 0)
diff --git a/drivers/net/sfc/sfc_port.c b/drivers/net/sfc/sfc_port.c
index e5a7b8358d..33b53f7ac8 100644
--- a/drivers/net/sfc/sfc_port.c
+++ b/drivers/net/sfc/sfc_port.c
@@ -130,7 +130,8 @@ sfc_port_init_dev_link(struct sfc_adapter *sa)
if (rc != 0)
return rc;

- sfc_port_link_mode_to_info(link_mode, &current_link);
+ sfc_port_link_mode_to_info(link_mode, sa->port.phy_adv_cap,
+ &current_link);

EFX_STATIC_ASSERT(sizeof(*dev_link) == sizeof(rte_atomic64_t));
rte_atomic64_set((rte_atomic64_t *)dev_link,
@@ -614,7 +615,7 @@ sfc_set_rx_mode(struct sfc_adapter *sa)
}

void
-sfc_port_link_mode_to_info(efx_link_mode_t link_mode,
+sfc_port_link_mode_to_info(efx_link_mode_t link_mode, uint32_t phy_cap_req,
struct rte_eth_link *link_info)
{
SFC_ASSERT(link_mode < EFX_LINK_NMODES);
@@ -684,7 +685,8 @@ sfc_port_link_mode_to_info(efx_link_mode_t link_mode,
break;
}

- link_info->link_autoneg = RTE_ETH_LINK_AUTONEG;
+ if ((phy_cap_req & (1U << EFX_PHY_CAP_AN)) != 0)
+ link_info->link_autoneg = RTE_ETH_LINK_AUTONEG;
}

int
diff --git a/drivers/net/sfc/sfc_repr.c b/drivers/net/sfc/sfc_repr.c
index 93da97387c..fbb5f58a8e 100644
--- a/drivers/net/sfc/sfc_repr.c
+++ b/drivers/net/sfc/sfc_repr.c
@@ -533,7 +533,7 @@ sfc_repr_dev_link_update(struct rte_eth_dev *dev,
struct rte_eth_link link;

if (sr->state != SFC_ETHDEV_STARTED) {
- sfc_port_link_mode_to_info(EFX_LINK_UNKNOWN, &link);
+ sfc_port_link_mode_to_info(EFX_LINK_UNKNOWN, 0, &link);
} else {
memset(&link, 0, sizeof(link));
link.link_status = RTE_ETH_LINK_UP;
--
2.47.3