|
4 | 4 |
|
5 | 5 | #include "cnxk_ethdev.h" |
6 | 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 | +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 | + rc = roc_nix_mac_fwdata_get(&dev->nix, &fwdata); |
| 45 | + if (rc) { |
| 46 | + plt_err("Failed to get MAC firmware data"); |
| 47 | + goto exit; |
| 48 | + } |
| 49 | + |
| 50 | + memset(&linfo, 0, sizeof(linfo)); |
| 51 | + rc = roc_nix_mac_link_info_get(&dev->nix, &linfo); |
| 52 | + if (rc) { |
| 53 | + plt_err("Failed to get MAC link info"); |
| 54 | + goto exit; |
| 55 | + } |
| 56 | + |
| 57 | + if (link_info->autoneg) { |
| 58 | + if (!fwdata.supported_an) { |
| 59 | + plt_err("Autoneg is not supported"); |
| 60 | + goto exit; |
| 61 | + } else { |
| 62 | + for (bit = 0; bit < ROC_NIX_LINK_SPEED_MAX; bit++) { |
| 63 | + if (link_info->speed_bitmask & BIT_ULL(bit)) |
| 64 | + advertise |= rte_to_ethtool_mode[bit]; |
| 65 | + } |
| 66 | + goto exit; |
| 67 | + } |
| 68 | + } |
| 69 | + |
| 70 | + advertise |= mac_to_ethtool_mode[linfo.lmac_type_id][link_info->full_duplex]; |
| 71 | +exit: |
| 72 | + return advertise; |
| 73 | +} |
| 74 | + |
7 | 75 | void |
8 | 76 | cnxk_nix_toggle_flag_link_cfg(struct cnxk_eth_dev *dev, bool set) |
9 | 77 | { |
@@ -146,3 +214,67 @@ cnxk_nix_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete) |
146 | 214 |
|
147 | 215 | return rte_eth_linkstatus_set(eth_dev, &link); |
148 | 216 | } |
| 217 | + |
| 218 | +int |
| 219 | +cnxk_nix_link_info_configure(struct rte_eth_dev *eth_dev) |
| 220 | +{ |
| 221 | + uint32_t speed_map[] = { |
| 222 | + RTE_ETH_SPEED_NUM_NONE, RTE_ETH_SPEED_NUM_10M, RTE_ETH_SPEED_NUM_10M, |
| 223 | + RTE_ETH_SPEED_NUM_100M, RTE_ETH_SPEED_NUM_100M, RTE_ETH_SPEED_NUM_1G, |
| 224 | + RTE_ETH_SPEED_NUM_2_5G, RTE_ETH_SPEED_NUM_5G, RTE_ETH_SPEED_NUM_10G, |
| 225 | + RTE_ETH_SPEED_NUM_20G, RTE_ETH_SPEED_NUM_25G, RTE_ETH_SPEED_NUM_40G, |
| 226 | + RTE_ETH_SPEED_NUM_50G, RTE_ETH_SPEED_NUM_56G, RTE_ETH_SPEED_NUM_100G, |
| 227 | + RTE_ETH_SPEED_NUM_200G, RTE_ETH_SPEED_NUM_400G |
| 228 | + }; |
| 229 | + struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); |
| 230 | + struct rte_eth_dev_data *data = eth_dev->data; |
| 231 | + struct rte_eth_conf *conf = &data->dev_conf; |
| 232 | + uint32_t link_speeds = conf->link_speeds; |
| 233 | + struct roc_nix_link_info link_info = {0}; |
| 234 | + struct roc_nix *nix = &dev->nix; |
| 235 | + uint32_t speed = link_speeds; |
| 236 | + bool fixed; |
| 237 | + |
| 238 | + plt_info("User passed link configuration: %x", link_speeds); |
| 239 | + |
| 240 | + if (!roc_nix_is_pf(nix) || link_speeds == RTE_ETH_LINK_SPEED_AUTONEG) |
| 241 | + return 0; |
| 242 | + |
| 243 | + fixed = link_speeds & RTE_ETH_LINK_SPEED_FIXED ? true : false; |
| 244 | + if (fixed) { |
| 245 | + if (rte_popcount32(link_speeds) == 1) { |
| 246 | + plt_err("Desired speed is not specified in FIXED mode"); |
| 247 | + return -EINVAL; |
| 248 | + } |
| 249 | + |
| 250 | + if (rte_popcount32(link_speeds) > 2) { |
| 251 | + plt_err("Multiple speeds can't be configured in FIXED mode"); |
| 252 | + return -EINVAL; |
| 253 | + } |
| 254 | + |
| 255 | + link_info.autoneg = 0; |
| 256 | + } else { |
| 257 | + link_info.autoneg = 1; |
| 258 | + } |
| 259 | + |
| 260 | + speed >>= 1; |
| 261 | + link_info.speed = speed_map[rte_bsf32(speed) + 1]; |
| 262 | + link_info.speed_bitmask = link_speeds & ~RTE_ETH_LINK_SPEED_FIXED; |
| 263 | + link_info.full_duplex = ((link_speeds & RTE_ETH_LINK_SPEED_10M_HD) || |
| 264 | + (link_speeds & RTE_ETH_LINK_SPEED_100M_HD)) ? |
| 265 | + ROC_NIX_LINK_DUPLEX_HALF : |
| 266 | + ROC_NIX_LINK_DUPLEX_FULL; |
| 267 | + link_info.advertising = nix_link_advertising_get(dev, &link_info); |
| 268 | + if (link_info.advertising == 0) { |
| 269 | + plt_err("advertising bitmap is not set"); |
| 270 | + return -EINVAL; |
| 271 | + } |
| 272 | + |
| 273 | + plt_info("Following link settings are sent to firmware:"); |
| 274 | + plt_info("Advertised modes: %" PRIX64, link_info.advertising); |
| 275 | + plt_info("speed: %u", link_info.speed); |
| 276 | + plt_info("duplex: %s", link_info.full_duplex == ROC_NIX_LINK_DUPLEX_HALF ? |
| 277 | + "half-duplex" : "full-duplex"); |
| 278 | + plt_info("autoneg: %s", link_info.autoneg ? "enabled" : "disabled"); |
| 279 | + return roc_nix_mac_link_info_set(nix, &link_info); |
| 280 | +} |
0 commit comments