LCOV - code coverage report
Current view: top level - drivers/net/cnxk - cnxk_link.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 114 0.0 %
Date: 2025-12-01 19:08:10 Functions: 0 8 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 74 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(C) 2021 Marvell.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include "cnxk_ethdev.h"
       6                 :            : 
       7                 :            : const enum roc_nix_link_mode mac_to_ethtool_mode[CGX_LMAC_TYPE_MAX][2] = {
       8                 :            :         [CGX_LMAC_TYPE_SGMII][ROC_NIX_LINK_DUPLEX_HALF] = ROC_NIX_LINK_MODE_1000BASET_HD,
       9                 :            :         [CGX_LMAC_TYPE_SGMII][ROC_NIX_LINK_DUPLEX_FULL] = ROC_NIX_LINK_MODE_1000BASET_FD,
      10                 :            :         [CGX_LMAC_TYPE_10G_R][ROC_NIX_LINK_DUPLEX_FULL] = ROC_NIX_LINK_MODE_10000BASESR_FD,
      11                 :            :         [CGX_LMAC_TYPE_QSGMII][ROC_NIX_LINK_DUPLEX_HALF] = ROC_NIX_LINK_MODE_1000BASET_HD,
      12                 :            :         [CGX_LMAC_TYPE_QSGMII][ROC_NIX_LINK_DUPLEX_FULL] = ROC_NIX_LINK_MODE_10000BASET_FD,
      13                 :            : };
      14                 :            : 
      15                 :            : const enum roc_nix_link_mode rte_to_ethtool_mode[ROC_NIX_LINK_SPEED_MAX] = {
      16                 :            :         0,
      17                 :            :         ROC_NIX_LINK_MODE_10BASET_HD,
      18                 :            :         ROC_NIX_LINK_MODE_10BASET_FD,
      19                 :            :         ROC_NIX_LINK_MODE_100BASET_HD,
      20                 :            :         ROC_NIX_LINK_MODE_100BASET_FD,
      21                 :            :         ROC_NIX_LINK_MODE_1000BASET_FD,
      22                 :            :         ROC_NIX_LINK_MODE_2500BASEX_FD,
      23                 :            :         0,
      24                 :            :         ROC_NIX_LINK_MODE_10000BASESR_FD,
      25                 :            :         0,
      26                 :            :         ROC_NIX_LINK_MODE_25000BASESR_FD,
      27                 :            :         ROC_NIX_LINK_MODE_40000BASELR4_FD,
      28                 :            :         ROC_NIX_LINK_MODE_50000BASELR_ER_FR_FD,
      29                 :            :         0,
      30                 :            :         ROC_NIX_LINK_MODE_100000BASELR4_ER4_FD,
      31                 :            :         0,
      32                 :            :         0,
      33                 :            : };
      34                 :            : 
      35                 :            : static uint64_t
      36                 :          0 : nix_link_advertising_get(struct cnxk_eth_dev *dev, struct roc_nix_link_info *link_info)
      37                 :            : {
      38                 :            :         struct roc_nix_mac_fwdata fwdata;
      39                 :            :         struct roc_nix_link_info linfo;
      40                 :            :         uint64_t advertise = 0;
      41                 :            :         int bit, rc;
      42                 :            : 
      43                 :            :         memset(&fwdata, 0, sizeof(fwdata));
      44                 :          0 :         rc = roc_nix_mac_fwdata_get(&dev->nix, &fwdata);
      45         [ #  # ]:          0 :         if (rc) {
      46                 :          0 :                 plt_err("Failed to get MAC firmware data");
      47                 :          0 :                 goto exit;
      48                 :            :         }
      49                 :            : 
      50                 :            :         memset(&linfo, 0, sizeof(linfo));
      51                 :          0 :         rc = roc_nix_mac_link_info_get(&dev->nix, &linfo);
      52         [ #  # ]:          0 :         if (rc) {
      53                 :          0 :                 plt_err("Failed to get MAC link info");
      54                 :          0 :                 goto exit;
      55                 :            :         }
      56                 :            : 
      57         [ #  # ]:          0 :         if (link_info->autoneg) {
      58         [ #  # ]:          0 :                 if (!fwdata.supported_an) {
      59                 :          0 :                         plt_err("Autoneg is not supported");
      60                 :          0 :                         goto exit;
      61                 :            :                 } else {
      62         [ #  # ]:          0 :                         for (bit = 0; bit < ROC_NIX_LINK_SPEED_MAX; bit++) {
      63         [ #  # ]:          0 :                                 if (link_info->speed_bitmask & BIT_ULL(bit))
      64                 :          0 :                                         advertise |= rte_to_ethtool_mode[bit];
      65                 :            :                         }
      66                 :          0 :                         goto exit;
      67                 :            :                 }
      68                 :            :         }
      69                 :            : 
      70                 :          0 :         advertise |= mac_to_ethtool_mode[linfo.lmac_type_id][link_info->full_duplex];
      71                 :          0 : exit:
      72                 :          0 :         return advertise;
      73                 :            : }
      74                 :            : 
      75                 :            : void
      76                 :          0 : cnxk_nix_toggle_flag_link_cfg(struct cnxk_eth_dev *dev, bool set)
      77                 :            : {
      78         [ #  # ]:          0 :         if (set)
      79                 :          0 :                 dev->flags |= CNXK_LINK_CFG_IN_PROGRESS_F;
      80                 :            :         else
      81                 :          0 :                 dev->flags &= ~CNXK_LINK_CFG_IN_PROGRESS_F;
      82                 :            : 
      83                 :            :         /* Update link info for LBK */
      84   [ #  #  #  # ]:          0 :         if (!set &&
      85   [ #  #  #  # ]:          0 :             (roc_nix_is_lbk(&dev->nix) || roc_nix_is_sdp(&dev->nix) || roc_nix_is_esw(&dev->nix))) {
      86                 :            :                 struct rte_eth_link link;
      87                 :            : 
      88                 :          0 :                 link.link_status = RTE_ETH_LINK_UP;
      89                 :          0 :                 link.link_speed = RTE_ETH_SPEED_NUM_100G;
      90                 :          0 :                 link.link_autoneg = RTE_ETH_LINK_FIXED;
      91                 :          0 :                 link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
      92                 :          0 :                 rte_eth_linkstatus_set(dev->eth_dev, &link);
      93                 :            :         }
      94                 :            : 
      95                 :            :         rte_wmb();
      96                 :          0 : }
      97                 :            : 
      98                 :            : static inline int
      99                 :          0 : nix_wait_for_link_cfg(struct cnxk_eth_dev *dev)
     100                 :            : {
     101                 :            :         uint16_t wait = 1000;
     102                 :            : 
     103                 :            :         do {
     104                 :            :                 rte_atomic_thread_fence(__ATOMIC_ACQUIRE);
     105         [ #  # ]:          0 :                 if (!(dev->flags & CNXK_LINK_CFG_IN_PROGRESS_F))
     106                 :            :                         break;
     107                 :          0 :                 wait--;
     108                 :            :                 rte_delay_ms(1);
     109         [ #  # ]:          0 :         } while (wait);
     110                 :            : 
     111         [ #  # ]:          0 :         return wait ? 0 : -1;
     112                 :            : }
     113                 :            : 
     114                 :            : static void
     115                 :          0 : nix_link_status_print(struct rte_eth_dev *eth_dev, struct rte_eth_link *link)
     116                 :            : {
     117   [ #  #  #  # ]:          0 :         if (link && link->link_status)
     118         [ #  # ]:          0 :                 plt_info("Port %d: Link Up - speed %u Mbps - %s - %s",
     119                 :            :                          (int)(eth_dev->data->port_id),
     120                 :            :                          (uint32_t)link->link_speed,
     121                 :            :                          link->link_duplex == RTE_ETH_LINK_FULL_DUPLEX
     122                 :            :                                  ? "full-duplex"
     123                 :            :                                  : "half-duplex",
     124                 :            :                                  rte_eth_link_connector_to_str(link->link_connector));
     125                 :            :         else
     126                 :          0 :                 plt_info("Port %d: Link Down - %s", (int)(eth_dev->data->port_id),
     127                 :            :                          rte_eth_link_connector_to_str(link->link_connector));
     128                 :          0 : }
     129                 :            : 
     130                 :            : void
     131                 :          0 : cnxk_eth_dev_link_status_get_cb(struct roc_nix *nix,
     132                 :            :                                 struct roc_nix_link_info *link)
     133                 :            : {
     134                 :            :         struct cnxk_eth_dev *dev = (struct cnxk_eth_dev *)nix;
     135                 :            :         struct rte_eth_link eth_link;
     136                 :            :         struct rte_eth_dev *eth_dev;
     137                 :            : 
     138         [ #  # ]:          0 :         if (!link || !nix)
     139                 :          0 :                 return;
     140                 :            : 
     141                 :          0 :         eth_dev = dev->eth_dev;
     142         [ #  # ]:          0 :         if (!eth_dev)
     143                 :            :                 return;
     144                 :            : 
     145                 :          0 :         rte_eth_linkstatus_get(eth_dev, &eth_link);
     146                 :            : 
     147                 :          0 :         link->status = eth_link.link_status;
     148                 :          0 :         link->speed = eth_link.link_speed;
     149                 :          0 :         link->autoneg = eth_link.link_autoneg;
     150                 :          0 :         link->full_duplex = eth_link.link_duplex;
     151                 :            : }
     152                 :            : 
     153                 :            : void
     154                 :          0 : cnxk_eth_dev_link_status_cb(struct roc_nix *nix, struct roc_nix_link_info *link)
     155                 :            : {
     156                 :            :         struct cnxk_eth_dev *dev = (struct cnxk_eth_dev *)nix;
     157                 :            :         struct rte_eth_link eth_link;
     158                 :            :         struct rte_eth_dev *eth_dev;
     159                 :            : 
     160         [ #  # ]:          0 :         if (!link || !nix)
     161                 :          0 :                 return;
     162                 :            : 
     163                 :          0 :         eth_dev = dev->eth_dev;
     164   [ #  #  #  # ]:          0 :         if (!eth_dev || !eth_dev->data->dev_conf.intr_conf.lsc)
     165                 :            :                 return;
     166                 :            : 
     167         [ #  # ]:          0 :         if (nix_wait_for_link_cfg(dev)) {
     168                 :          0 :                 plt_err("Timeout waiting for link_cfg to complete");
     169                 :          0 :                 return;
     170                 :            :         }
     171                 :            : 
     172                 :          0 :         eth_link.link_status = link->status;
     173                 :          0 :         eth_link.link_speed = link->speed;
     174                 :          0 :         eth_link.link_autoneg = link->autoneg ? RTE_ETH_LINK_AUTONEG : RTE_ETH_LINK_FIXED;
     175                 :          0 :         eth_link.link_duplex = link->full_duplex;
     176                 :          0 :         eth_link.link_connector = dev->link_type;
     177                 :            : 
     178                 :            :         /* Print link info */
     179                 :          0 :         nix_link_status_print(eth_dev, &eth_link);
     180                 :            : 
     181                 :            :         /* Update link info */
     182                 :          0 :         rte_eth_linkstatus_set(eth_dev, &eth_link);
     183                 :            : 
     184                 :            :         /* Set the flag and execute application callbacks */
     185                 :          0 :         rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_INTR_LSC, NULL);
     186                 :            : }
     187                 :            : 
     188                 :            : int
     189         [ #  # ]:          0 : cnxk_nix_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete)
     190                 :            : {
     191                 :            :         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
     192                 :            :         struct roc_nix_link_info info;
     193                 :            :         struct rte_eth_link link;
     194                 :            :         int rc;
     195                 :            : 
     196                 :            :         RTE_SET_USED(wait_to_complete);
     197                 :            :         memset(&link, 0, sizeof(struct rte_eth_link));
     198                 :            : 
     199         [ #  # ]:          0 :         if (!eth_dev->data->dev_started)
     200                 :            :                 return 0;
     201                 :            : 
     202   [ #  #  #  # ]:          0 :         if (roc_nix_is_lbk(&dev->nix) || roc_nix_is_sdp(&dev->nix)) {
     203                 :          0 :                 link.link_status = RTE_ETH_LINK_UP;
     204                 :          0 :                 link.link_speed = RTE_ETH_SPEED_NUM_100G;
     205                 :            :                 link.link_autoneg = RTE_ETH_LINK_FIXED;
     206                 :          0 :                 link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     207                 :            :         } else {
     208                 :          0 :                 rc = roc_nix_mac_link_info_get(&dev->nix, &info);
     209         [ #  # ]:          0 :                 if (rc)
     210                 :            :                         return rc;
     211                 :          0 :                 link.link_status = info.status;
     212                 :          0 :                 link.link_speed = info.speed;
     213                 :          0 :                 link.link_autoneg = info.autoneg ? RTE_ETH_LINK_AUTONEG : RTE_ETH_LINK_FIXED;
     214         [ #  # ]:          0 :                 if (info.full_duplex)
     215                 :          0 :                         link.link_duplex = info.full_duplex;
     216                 :          0 :                 link.link_connector = dev->link_type;
     217                 :            :         }
     218                 :            : 
     219                 :            :         return rte_eth_linkstatus_set(eth_dev, &link);
     220                 :            : }
     221                 :            : 
     222                 :            : int
     223                 :          0 : cnxk_nix_link_info_configure(struct rte_eth_dev *eth_dev)
     224                 :            : {
     225                 :          0 :         uint32_t speed_map[] = {
     226                 :            :                 RTE_ETH_SPEED_NUM_NONE, RTE_ETH_SPEED_NUM_10M,  RTE_ETH_SPEED_NUM_10M,
     227                 :            :                 RTE_ETH_SPEED_NUM_100M, RTE_ETH_SPEED_NUM_100M, RTE_ETH_SPEED_NUM_1G,
     228                 :            :                 RTE_ETH_SPEED_NUM_2_5G, RTE_ETH_SPEED_NUM_5G,   RTE_ETH_SPEED_NUM_10G,
     229                 :            :                 RTE_ETH_SPEED_NUM_20G,  RTE_ETH_SPEED_NUM_25G,  RTE_ETH_SPEED_NUM_40G,
     230                 :            :                 RTE_ETH_SPEED_NUM_50G,  RTE_ETH_SPEED_NUM_56G,  RTE_ETH_SPEED_NUM_100G,
     231                 :            :                 RTE_ETH_SPEED_NUM_200G, RTE_ETH_SPEED_NUM_400G
     232                 :            :         };
     233                 :            :         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
     234                 :            :         struct rte_eth_dev_data *data = eth_dev->data;
     235                 :            :         struct rte_eth_conf *conf = &data->dev_conf;
     236                 :          0 :         uint32_t link_speeds = conf->link_speeds;
     237                 :          0 :         struct roc_nix_link_info link_info = {0};
     238                 :          0 :         struct roc_nix *nix = &dev->nix;
     239                 :            :         uint32_t speed = link_speeds;
     240                 :            :         bool fixed;
     241                 :            : 
     242                 :          0 :         plt_info("User passed link configuration: %x", link_speeds);
     243                 :            : 
     244   [ #  #  #  # ]:          0 :         if (!roc_nix_is_pf(nix) || link_speeds == RTE_ETH_LINK_SPEED_AUTONEG)
     245                 :            :                 return 0;
     246                 :            : 
     247                 :          0 :         fixed = link_speeds & RTE_ETH_LINK_SPEED_FIXED ? true : false;
     248         [ #  # ]:          0 :         if (fixed) {
     249         [ #  # ]:          0 :                 if (rte_popcount32(link_speeds) == 1) {
     250                 :          0 :                         plt_err("Desired speed is not specified in FIXED mode");
     251                 :          0 :                         return -EINVAL;
     252                 :            :                 }
     253                 :            : 
     254         [ #  # ]:          0 :                 if (rte_popcount32(link_speeds) > 2) {
     255                 :          0 :                         plt_err("Multiple speeds can't be configured in FIXED mode");
     256                 :          0 :                         return -EINVAL;
     257                 :            :                 }
     258                 :            : 
     259                 :          0 :                 link_info.autoneg = 0;
     260                 :            :         } else {
     261                 :          0 :                 link_info.autoneg = 1;
     262                 :            :         }
     263                 :            : 
     264                 :          0 :         speed >>= 1;
     265                 :          0 :         link_info.speed = speed_map[rte_bsf32(speed) + 1];
     266                 :          0 :         link_info.speed_bitmask = link_speeds & ~RTE_ETH_LINK_SPEED_FIXED;
     267                 :          0 :         link_info.full_duplex = ((link_speeds & RTE_ETH_LINK_SPEED_10M_HD) ||
     268                 :            :                                  (link_speeds & RTE_ETH_LINK_SPEED_100M_HD)) ?
     269                 :          0 :                                   ROC_NIX_LINK_DUPLEX_HALF :
     270                 :            :                                   ROC_NIX_LINK_DUPLEX_FULL;
     271                 :          0 :         link_info.advertising = nix_link_advertising_get(dev, &link_info);
     272         [ #  # ]:          0 :         if (link_info.advertising == 0) {
     273                 :          0 :                 plt_err("advertising bitmap is not set");
     274                 :          0 :                 return -EINVAL;
     275                 :            :         }
     276                 :            : 
     277                 :          0 :         plt_info("Following link settings are sent to firmware:");
     278                 :          0 :         plt_info("Advertised modes: %" PRIX64, link_info.advertising);
     279                 :          0 :         plt_info("speed: %u", link_info.speed);
     280         [ #  # ]:          0 :         plt_info("duplex: %s", link_info.full_duplex == ROC_NIX_LINK_DUPLEX_HALF ?
     281                 :            :                                                 "half-duplex" : "full-duplex");
     282         [ #  # ]:          0 :         plt_info("autoneg: %s", link_info.autoneg ? "enabled" : "disabled");
     283                 :          0 :         return roc_nix_mac_link_info_set(nix, &link_info);
     284                 :            : }

Generated by: LCOV version 1.14