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.ma...@arknetworks.am> Reviewed-by: Andy Moreton <andy.more...@amd.com> Reviewed-by: Pieter Jansen Van Vuuren <pieter.jansen-van-vuu...@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