From: Sunil Kumar Kori <sk...@marvell.com> As a port can be configured to operate on specific mode and speed via struct rte_eth_conf::link_speeds in rte_eth_dev_configure() API.
Implement mentioned configuration passed by user. Signed-off-by: Sunil Kumar Kori <sk...@marvell.com> Signed-off-by: Nithin Dabilpuram <ndabilpu...@marvell.com> --- drivers/net/cnxk/cnxk_ethdev.c | 6 ++ drivers/net/cnxk/cnxk_ethdev.h | 1 + drivers/net/cnxk/cnxk_link.c | 132 +++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+) diff --git a/drivers/net/cnxk/cnxk_ethdev.c b/drivers/net/cnxk/cnxk_ethdev.c index 89d304be7e..34f391e755 100644 --- a/drivers/net/cnxk/cnxk_ethdev.c +++ b/drivers/net/cnxk/cnxk_ethdev.c @@ -3,6 +3,7 @@ */ #include <cnxk_ethdev.h> +#include <rte_bitops.h> #include <eal_export.h> #include <rte_eventdev.h> #include <rte_pmd_cnxk.h> @@ -1609,6 +1610,11 @@ cnxk_nix_configure(struct rte_eth_dev *eth_dev) eth_dev->data->port_id, ea_fmt, nb_rxq, nb_txq, dev->rx_offloads, dev->tx_offloads); + /* Configure link parameters */ + rc = cnxk_nix_link_info_configure(eth_dev); + if (rc) + plt_warn("Unable to configure requested link attributes, rc=%d continue...", rc); + /* All good */ dev->configured = 1; dev->nb_rxq = data->nb_rx_queues; diff --git a/drivers/net/cnxk/cnxk_ethdev.h b/drivers/net/cnxk/cnxk_ethdev.h index 1ced6dd65e..c11a3e6ce0 100644 --- a/drivers/net/cnxk/cnxk_ethdev.h +++ b/drivers/net/cnxk/cnxk_ethdev.h @@ -678,6 +678,7 @@ void cnxk_eth_dev_link_status_cb(struct roc_nix *nix, void cnxk_eth_dev_link_status_get_cb(struct roc_nix *nix, struct roc_nix_link_info *link); void cnxk_eth_dev_q_err_cb(struct roc_nix *nix, void *data); +int cnxk_nix_link_info_configure(struct rte_eth_dev *eth_dev); int cnxk_nix_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete); int cnxk_nix_queue_stats_mapping(struct rte_eth_dev *dev, uint16_t queue_id, uint8_t stat_idx, uint8_t is_rx); diff --git a/drivers/net/cnxk/cnxk_link.c b/drivers/net/cnxk/cnxk_link.c index 903b44de2c..0bc56fbb8c 100644 --- a/drivers/net/cnxk/cnxk_link.c +++ b/drivers/net/cnxk/cnxk_link.c @@ -4,6 +4,74 @@ #include "cnxk_ethdev.h" +const enum roc_nix_link_mode mac_to_ethtool_mode[CGX_LMAC_TYPE_MAX][2] = { + [CGX_LMAC_TYPE_SGMII][ROC_NIX_LINK_DUPLEX_HALF] = ROC_NIX_LINK_MODE_1000BASET_HD, + [CGX_LMAC_TYPE_SGMII][ROC_NIX_LINK_DUPLEX_FULL] = ROC_NIX_LINK_MODE_1000BASET_FD, + [CGX_LMAC_TYPE_10G_R][ROC_NIX_LINK_DUPLEX_FULL] = ROC_NIX_LINK_MODE_10000BASESR_FD, + [CGX_LMAC_TYPE_QSGMII][ROC_NIX_LINK_DUPLEX_HALF] = ROC_NIX_LINK_MODE_1000BASET_HD, + [CGX_LMAC_TYPE_QSGMII][ROC_NIX_LINK_DUPLEX_FULL] = ROC_NIX_LINK_MODE_10000BASET_FD, +}; + +const enum roc_nix_link_mode rte_to_ethtool_mode[ROC_NIX_LINK_SPEED_MAX] = { + 0, + ROC_NIX_LINK_MODE_10BASET_HD, + ROC_NIX_LINK_MODE_10BASET_FD, + ROC_NIX_LINK_MODE_100BASET_HD, + ROC_NIX_LINK_MODE_100BASET_FD, + ROC_NIX_LINK_MODE_1000BASET_FD, + ROC_NIX_LINK_MODE_2500BASEX_FD, + 0, + ROC_NIX_LINK_MODE_10000BASESR_FD, + 0, + ROC_NIX_LINK_MODE_25000BASESR_FD, + ROC_NIX_LINK_MODE_40000BASELR4_FD, + ROC_NIX_LINK_MODE_50000BASELR_ER_FR_FD, + 0, + ROC_NIX_LINK_MODE_100000BASELR4_ER4_FD, + 0, + 0, +}; + +static uint64_t +nix_link_advertising_get(struct cnxk_eth_dev *dev, struct roc_nix_link_info *link_info) +{ + struct roc_nix_mac_fwdata fwdata; + struct roc_nix_link_info linfo; + uint64_t advertise = 0; + int bit, rc; + + memset(&fwdata, 0, sizeof(fwdata)); + rc = roc_nix_mac_fwdata_get(&dev->nix, &fwdata); + if (rc) { + plt_err("Failed to get MAC firmware data"); + goto exit; + } + + memset(&linfo, 0, sizeof(linfo)); + rc = roc_nix_mac_link_info_get(&dev->nix, &linfo); + if (rc) { + plt_err("Failed to get MAC link info"); + goto exit; + } + + if (link_info->autoneg) { + if (!fwdata.supported_an) { + plt_err("Autoneg is not supported"); + goto exit; + } else { + for (bit = 0; bit < ROC_NIX_LINK_SPEED_MAX; bit++) { + if (link_info->speed_bitmask & BIT_ULL(bit)) + advertise |= rte_to_ethtool_mode[bit]; + } + goto exit; + } + } + + advertise |= mac_to_ethtool_mode[linfo.lmac_type_id][link_info->full_duplex]; +exit: + return advertise; +} + void cnxk_nix_toggle_flag_link_cfg(struct cnxk_eth_dev *dev, bool set) { @@ -146,3 +214,67 @@ cnxk_nix_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete) return rte_eth_linkstatus_set(eth_dev, &link); } + +int +cnxk_nix_link_info_configure(struct rte_eth_dev *eth_dev) +{ + uint32_t speed_map[] = { + RTE_ETH_SPEED_NUM_NONE, RTE_ETH_SPEED_NUM_10M, RTE_ETH_SPEED_NUM_10M, + RTE_ETH_SPEED_NUM_100M, RTE_ETH_SPEED_NUM_100M, RTE_ETH_SPEED_NUM_1G, + RTE_ETH_SPEED_NUM_2_5G, RTE_ETH_SPEED_NUM_5G, RTE_ETH_SPEED_NUM_10G, + RTE_ETH_SPEED_NUM_20G, RTE_ETH_SPEED_NUM_25G, RTE_ETH_SPEED_NUM_40G, + RTE_ETH_SPEED_NUM_50G, RTE_ETH_SPEED_NUM_56G, RTE_ETH_SPEED_NUM_100G, + RTE_ETH_SPEED_NUM_200G, RTE_ETH_SPEED_NUM_400G + }; + struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); + struct rte_eth_dev_data *data = eth_dev->data; + struct rte_eth_conf *conf = &data->dev_conf; + uint32_t link_speeds = conf->link_speeds; + struct roc_nix_link_info link_info = {0}; + struct roc_nix *nix = &dev->nix; + uint32_t speed = link_speeds; + bool fixed; + + plt_info("User passed link configuration: %x", link_speeds); + + if (!roc_nix_is_pf(nix) || link_speeds == RTE_ETH_LINK_SPEED_AUTONEG) + return 0; + + fixed = link_speeds & RTE_ETH_LINK_SPEED_FIXED ? true : false; + if (fixed) { + if (rte_popcount32(link_speeds) == 1) { + plt_err("Desired speed is not specified in FIXED mode"); + return -EINVAL; + } + + if (rte_popcount32(link_speeds) > 2) { + plt_err("Multiple speeds can't be configured in FIXED mode"); + return -EINVAL; + } + + link_info.autoneg = 0; + } else { + link_info.autoneg = 1; + } + + speed >>= 1; + link_info.speed = speed_map[rte_bsf32(speed) + 1]; + link_info.speed_bitmask = link_speeds & ~RTE_ETH_LINK_SPEED_FIXED; + link_info.full_duplex = ((link_speeds & RTE_ETH_LINK_SPEED_10M_HD) || + (link_speeds & RTE_ETH_LINK_SPEED_100M_HD)) ? + ROC_NIX_LINK_DUPLEX_HALF : + ROC_NIX_LINK_DUPLEX_FULL; + link_info.advertising = nix_link_advertising_get(dev, &link_info); + if (link_info.advertising == 0) { + plt_err("advertising bitmap is not set"); + return -EINVAL; + } + + plt_info("Following link settings are sent to firmware:"); + plt_info("Advertised modes: %lx", link_info.advertising); + plt_info("speed: %u", link_info.speed); + plt_info("duplex: %s", link_info.full_duplex == ROC_NIX_LINK_DUPLEX_HALF ? + "half-duplex" : "full-duplex"); + plt_info("autoneg: %s", link_info.autoneg ? "enabled" : "disabled"); + return roc_nix_mac_link_info_set(nix, &link_info); +} -- 2.43.0