From: Martin Spinler <[email protected]> Read link speed capabilities and actual link speed from the MDIO registers.
Signed-off-by: Martin Spinler <[email protected]> --- drivers/net/nfb/meson.build | 1 + drivers/net/nfb/nfb.h | 7 ++++ drivers/net/nfb/nfb_ethdev.c | 78 +++++++++++++++++++++++++++--------- drivers/net/nfb/nfb_mdio.c | 42 +++++++++++++++++++ drivers/net/nfb/nfb_mdio.h | 34 ++++++++++++++++ 5 files changed, 142 insertions(+), 20 deletions(-) create mode 100644 drivers/net/nfb/nfb_mdio.c create mode 100644 drivers/net/nfb/nfb_mdio.h diff --git a/drivers/net/nfb/meson.build b/drivers/net/nfb/meson.build index 9e458dfb4a..b57d1d48fa 100644 --- a/drivers/net/nfb/meson.build +++ b/drivers/net/nfb/meson.build @@ -21,6 +21,7 @@ sources = files( 'nfb_rxmode.c', 'nfb_stats.c', 'nfb_tx.c', + 'nfb_mdio.c', ) cflags += no_wvla_cflag diff --git a/drivers/net/nfb/nfb.h b/drivers/net/nfb/nfb.h index 2bce71ac89..6ffb940c6d 100644 --- a/drivers/net/nfb/nfb.h +++ b/drivers/net/nfb/nfb.h @@ -11,6 +11,7 @@ #include <nfb/ndp.h> #include <netcope/rxmac.h> #include <netcope/txmac.h> +#include <netcope/mdio_if_info.h> #include <netcope/info.h> extern int nfb_logtype; @@ -50,6 +51,10 @@ extern int nfb_logtype; NFB_ARG_PORT "=<number>" \ "" +struct eth_node { + struct mdio_if_info if_info; /**< MDIO interface handles */ +}; + /* * Handles obtained from the libnfb: each process must use own instance. * Stored inside dev->process_private. @@ -57,8 +62,10 @@ extern int nfb_logtype; struct pmd_internals { uint16_t max_rxmac; /**< Count of valid rxmac items */ uint16_t max_txmac; /**< Count of valid txmac items */ + uint16_t max_eth; /**< Count of valid eth nodes */ struct nc_rxmac **rxmac; /**< Array of Rx MAC handles */ struct nc_txmac **txmac; /**< Array of Tx MAC handles */ + struct eth_node *eth_node; /**< Array of Eth nodes */ struct nfb_device *nfb; TAILQ_ENTRY(pmd_internals) eth_dev_list; /**< Item in list of all devices */ diff --git a/drivers/net/nfb/nfb_ethdev.c b/drivers/net/nfb/nfb_ethdev.c index ca3dbad879..437aed9ae7 100644 --- a/drivers/net/nfb/nfb_ethdev.c +++ b/drivers/net/nfb/nfb_ethdev.c @@ -14,6 +14,8 @@ #include <netcope/eth.h> #include <netcope/rxmac.h> #include <netcope/txmac.h> +#include <netcope/mdio.h> +#include <netcope/ieee802_3.h> #include <ethdev_pci.h> #include <rte_kvargs.h> @@ -24,6 +26,8 @@ #include "nfb_rxmode.h" #include "nfb.h" +#include "nfb_mdio.h" + static const char * const VALID_KEYS[] = { NFB_ARG_PORT, NULL @@ -46,6 +50,18 @@ static struct nfb_pmd_internals_head nfb_eth_dev_list = static int nfb_eth_dev_uninit(struct rte_eth_dev *dev); +static int +nfb_mdio_read(void *priv, int prtad, int devad, uint16_t addr) +{ + return nc_mdio_read((struct nc_mdio *)priv, prtad, devad, addr); +} + +static int +nfb_mdio_write(void *priv, int prtad, int devad, uint16_t addr, uint16_t val) +{ + return nc_mdio_write((struct nc_mdio *)priv, prtad, devad, addr, val); +} + /** * Default MAC addr */ @@ -65,10 +81,17 @@ static int nfb_nc_eth_init(struct pmd_internals *intl, struct nfb_ifc_create_params *params) { int ret; - int i, rxm, txm; + int i, rxm, txm, eth; struct nc_ifc_info *ifc = params->ifc_info; struct nc_ifc_map_info *mi = ¶ms->map_info; + int node, node_cp; + const int32_t *prop32; + int proplen; + const void *fdt; + + fdt = nfb_get_fdt(intl->nfb); + ret = -ENOMEM; if (ifc->eth_cnt == 0) return 0; @@ -81,9 +104,14 @@ nfb_nc_eth_init(struct pmd_internals *intl, struct nfb_ifc_create_params *params if (intl->txmac == NULL) goto err_alloc_txmac; + intl->eth_node = calloc(ifc->eth_cnt, sizeof(*intl->eth_node)); + if (intl->eth_node == NULL) + goto err_alloc_ethnode; + /* Some eths may not have assigned MAC nodes, hence use separate var for indexing */ rxm = 0; txm = 0; + eth = 0; for (i = 0; i < mi->eth_cnt; i++) { if (mi->eth[i].ifc != ifc->id) continue; @@ -95,12 +123,30 @@ nfb_nc_eth_init(struct pmd_internals *intl, struct nfb_ifc_create_params *params intl->txmac[txm] = nc_txmac_open(intl->nfb, mi->eth[i].node_txmac); if (intl->txmac[txm]) txm++; + + node = nc_eth_get_pcspma_control_node(fdt, mi->eth[i].node_eth, &node_cp); + + intl->eth_node[eth].if_info.dev = nc_mdio_open(intl->nfb, node, node_cp); + if (intl->eth_node[eth].if_info.dev) { + intl->eth_node[eth].if_info.prtad = 0; + intl->eth_node[eth].if_info.mdio_read = nfb_mdio_read; + intl->eth_node[eth].if_info.mdio_write = nfb_mdio_write; + + prop32 = fdt_getprop(fdt, node_cp, "dev", &proplen); + if (proplen == sizeof(*prop32)) + intl->eth_node[eth].if_info.prtad = fdt32_to_cpu(*prop32); + + eth++; + } } intl->max_rxmac = rxm; intl->max_txmac = txm; + intl->max_eth = eth; return 0; +err_alloc_ethnode: + free(intl->txmac); err_alloc_txmac: free(intl->rxmac); err_alloc_rxmac: @@ -116,6 +162,8 @@ static void nfb_nc_eth_deinit(struct pmd_internals *intl) { uint16_t i; + for (i = 0; i < intl->max_eth; i++) + nc_mdio_close(intl->eth_node[i].if_info.dev); for (i = 0; i < intl->max_txmac; i++) nc_txmac_close(intl->txmac[i]); for (i = 0; i < intl->max_rxmac; i++) @@ -262,16 +310,22 @@ nfb_eth_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct pmd_priv *priv = dev->data->dev_private; + struct pmd_internals *intl = dev->process_private; dev_info->max_mac_addrs = nfb_eth_get_max_mac_address_count(dev); dev_info->max_rx_pktlen = (uint32_t)-1; dev_info->max_rx_queues = priv->max_rx_queues; dev_info->max_tx_queues = priv->max_tx_queues; - dev_info->speed_capa = RTE_ETH_LINK_SPEED_100G; + dev_info->speed_capa = RTE_ETH_LINK_SPEED_FIXED; dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_TIMESTAMP; + if (intl->max_eth) { + nfb_mdio_cl45_pma_get_speed_capa(&intl->eth_node[0].if_info, + &dev_info->speed_capa); + } + return 0; } @@ -339,24 +393,8 @@ nfb_eth_link_update(struct rte_eth_dev *dev, link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX; link.link_autoneg = RTE_ETH_LINK_SPEED_FIXED; - if (internals->max_rxmac) { - nc_rxmac_read_status(internals->rxmac[0], &status); - - switch (status.speed) { - case MAC_SPEED_10G: - link.link_speed = RTE_ETH_SPEED_NUM_10G; - break; - case MAC_SPEED_40G: - link.link_speed = RTE_ETH_SPEED_NUM_40G; - break; - case MAC_SPEED_100G: - link.link_speed = RTE_ETH_SPEED_NUM_100G; - break; - default: - link.link_speed = RTE_ETH_SPEED_NUM_NONE; - break; - } - } + if (internals->max_eth) + link.link_speed = ieee802_3_get_pma_speed_value(&internals->eth_node->if_info); for (i = 0; i < internals->max_rxmac; ++i) { nc_rxmac_read_status(internals->rxmac[i], &status); diff --git a/drivers/net/nfb/nfb_mdio.c b/drivers/net/nfb/nfb_mdio.c new file mode 100644 index 0000000000..19a433635b --- /dev/null +++ b/drivers/net/nfb/nfb_mdio.c @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2026 CESNET, z.s.p.o. + */ + +#include <eal_export.h> +#include <rte_ethdev.h> + +#include "nfb_mdio.h" + +RTE_EXPORT_INTERNAL_SYMBOL(nfb_mdio_cl45_pma_get_speed_capa) +void +nfb_mdio_cl45_pma_get_speed_capa(struct mdio_if_info *info, uint32_t *capa) +{ + int i; + int reg; + + const int speed_ability[NFB_MDIO_WIDTH] = { + RTE_ETH_LINK_SPEED_10G, + 0, + 0, + RTE_ETH_LINK_SPEED_50G, + RTE_ETH_LINK_SPEED_1G, + RTE_ETH_LINK_SPEED_100M, + RTE_ETH_LINK_SPEED_10M, + 0, + RTE_ETH_LINK_SPEED_40G, + RTE_ETH_LINK_SPEED_100G, + 0, + RTE_ETH_LINK_SPEED_25G, + RTE_ETH_LINK_SPEED_200G, + RTE_ETH_LINK_SPEED_2_5G, + RTE_ETH_LINK_SPEED_5G, + RTE_ETH_LINK_SPEED_400G, + }; + + reg = nfb_mdio_if_read_pma(info, NFB_MDIO_PMA_SPEED_ABILITY); + + for (i = 0; i < NFB_MDIO_WIDTH; i++) { + if (reg & NFB_MDIO_BIT(i)) + *capa |= speed_ability[i]; + } +} diff --git a/drivers/net/nfb/nfb_mdio.h b/drivers/net/nfb/nfb_mdio.h new file mode 100644 index 0000000000..f783e71c4b --- /dev/null +++ b/drivers/net/nfb/nfb_mdio.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2026 CESNET, z.s.p.o. + */ + +#include <stdint.h> +#include <rte_bitops.h> +#include <netcope/mdio_if_info.h> + + +#define NFB_MDIO_WIDTH (UINT16_WIDTH) +#define NFB_MDIO_BIT(nr) (UINT16_C(1) << (nr)) + +#define NFB_MDIO_DEV_PMA 1 + +#define NFB_MDIO_PMA_CTRL 0 +#define NFB_MDIO_PMA_CTRL_RESET NFB_MDIO_BIT(15) + +#define NFB_MDIO_PMA_SPEED_ABILITY 4 + +#define NFB_MDIO_PMA_RSFEC_CR 200 +#define NFB_MDIO_PMA_RSFEC_CR_ENABLE NFB_MDIO_BIT(2) + +static inline int nfb_mdio_if_read_pma(struct mdio_if_info *if_info, uint16_t addr) +{ + return if_info->mdio_read(if_info->dev, if_info->prtad, NFB_MDIO_DEV_PMA, addr); +} + +static inline int nfb_mdio_if_write_pma(struct mdio_if_info *if_info, uint16_t addr, uint16_t val) +{ + return if_info->mdio_write(if_info->dev, if_info->prtad, NFB_MDIO_DEV_PMA, addr, val); +} + +__rte_internal +void nfb_mdio_cl45_pma_get_speed_capa(struct mdio_if_info *if_info, uint32_t *capa); -- 2.53.0

