1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright (c) 2016-2018 Solarflare Communications Inc. 4 * All rights reserved. 5 * 6 * This software was jointly developed between OKTET Labs (under contract 7 * for Solarflare) and Solarflare Communications, Inc. 8 */ 9 10 #include "efx.h" 11 12 #include "sfc.h" 13 #include "sfc_log.h" 14 #include "sfc_kvargs.h" 15 16 /** Default MAC statistics update period is 1 second */ 17 #define SFC_MAC_STATS_UPDATE_PERIOD_MS_DEF MS_PER_S 18 19 /** The number of microseconds to sleep on attempt to get statistics update */ 20 #define SFC_MAC_STATS_UPDATE_RETRY_INTERVAL_US 10 21 22 /** The number of attempts to await arrival of freshly generated statistics */ 23 #define SFC_MAC_STATS_UPDATE_NB_ATTEMPTS 50 24 25 /** 26 * Update MAC statistics in the buffer. 27 * 28 * @param sa Adapter 29 * 30 * @return Status code 31 * @retval 0 Success 32 * @retval EAGAIN Try again 33 * @retval ENOMEM Memory allocation failure 34 */ 35 int 36 sfc_port_update_mac_stats(struct sfc_adapter *sa) 37 { 38 struct sfc_port *port = &sa->port; 39 efsys_mem_t *esmp = &port->mac_stats_dma_mem; 40 uint32_t *genp = NULL; 41 uint32_t gen_old; 42 unsigned int nb_attempts = 0; 43 int rc; 44 45 SFC_ASSERT(rte_spinlock_is_locked(&port->mac_stats_lock)); 46 47 if (sa->state != SFC_ADAPTER_STARTED) 48 return EINVAL; 49 50 /* 51 * If periodic statistics DMA'ing is off or if not supported, 52 * make a manual request and keep an eye on timer if need be 53 */ 54 if (!port->mac_stats_periodic_dma_supported || 55 (port->mac_stats_update_period_ms == 0)) { 56 if (port->mac_stats_update_period_ms != 0) { 57 uint64_t timestamp = sfc_get_system_msecs(); 58 59 if ((timestamp - 60 port->mac_stats_last_request_timestamp) < 61 port->mac_stats_update_period_ms) 62 return 0; 63 64 port->mac_stats_last_request_timestamp = timestamp; 65 } 66 67 rc = efx_mac_stats_upload(sa->nic, esmp); 68 if (rc != 0) 69 return rc; 70 71 genp = &port->mac_stats_update_generation; 72 gen_old = *genp; 73 } 74 75 do { 76 if (nb_attempts > 0) 77 rte_delay_us(SFC_MAC_STATS_UPDATE_RETRY_INTERVAL_US); 78 79 rc = efx_mac_stats_update(sa->nic, esmp, 80 port->mac_stats_buf, genp); 81 if (rc != 0) 82 return rc; 83 84 } while ((genp != NULL) && (*genp == gen_old) && 85 (++nb_attempts < SFC_MAC_STATS_UPDATE_NB_ATTEMPTS)); 86 87 return 0; 88 } 89 90 static void 91 sfc_port_reset_sw_stats(struct sfc_adapter *sa) 92 { 93 struct sfc_port *port = &sa->port; 94 95 /* 96 * Reset diff stats explicitly since check which does not allow 97 * the statistics to grow backward could deny it. 98 */ 99 port->ipackets = 0; 100 } 101 102 int 103 sfc_port_reset_mac_stats(struct sfc_adapter *sa) 104 { 105 struct sfc_port *port = &sa->port; 106 int rc; 107 108 rte_spinlock_lock(&port->mac_stats_lock); 109 rc = efx_mac_stats_clear(sa->nic); 110 if (rc == 0) 111 sfc_port_reset_sw_stats(sa); 112 rte_spinlock_unlock(&port->mac_stats_lock); 113 114 return rc; 115 } 116 117 static int 118 sfc_port_init_dev_link(struct sfc_adapter *sa) 119 { 120 struct rte_eth_link *dev_link = &sa->eth_dev->data->dev_link; 121 int rc; 122 efx_link_mode_t link_mode; 123 struct rte_eth_link current_link; 124 125 rc = efx_port_poll(sa->nic, &link_mode); 126 if (rc != 0) 127 return rc; 128 129 sfc_port_link_mode_to_info(link_mode, ¤t_link); 130 131 EFX_STATIC_ASSERT(sizeof(*dev_link) == sizeof(rte_atomic64_t)); 132 rte_atomic64_set((rte_atomic64_t *)dev_link, 133 *(uint64_t *)¤t_link); 134 135 return 0; 136 } 137 138 #if EFSYS_OPT_LOOPBACK 139 140 static efx_link_mode_t 141 sfc_port_phy_caps_to_max_link_speed(uint32_t phy_caps) 142 { 143 if (phy_caps & (1u << EFX_PHY_CAP_100000FDX)) 144 return EFX_LINK_100000FDX; 145 if (phy_caps & (1u << EFX_PHY_CAP_50000FDX)) 146 return EFX_LINK_50000FDX; 147 if (phy_caps & (1u << EFX_PHY_CAP_40000FDX)) 148 return EFX_LINK_40000FDX; 149 if (phy_caps & (1u << EFX_PHY_CAP_25000FDX)) 150 return EFX_LINK_25000FDX; 151 if (phy_caps & (1u << EFX_PHY_CAP_10000FDX)) 152 return EFX_LINK_10000FDX; 153 if (phy_caps & (1u << EFX_PHY_CAP_1000FDX)) 154 return EFX_LINK_1000FDX; 155 return EFX_LINK_UNKNOWN; 156 } 157 158 #endif 159 160 int 161 sfc_port_start(struct sfc_adapter *sa) 162 { 163 struct sfc_port *port = &sa->port; 164 int rc; 165 uint32_t phy_adv_cap; 166 const uint32_t phy_pause_caps = 167 ((1u << EFX_PHY_CAP_PAUSE) | (1u << EFX_PHY_CAP_ASYM)); 168 unsigned int i; 169 170 sfc_log_init(sa, "entry"); 171 172 sfc_log_init(sa, "init filters"); 173 rc = efx_filter_init(sa->nic); 174 if (rc != 0) 175 goto fail_filter_init; 176 177 sfc_log_init(sa, "init port"); 178 rc = efx_port_init(sa->nic); 179 if (rc != 0) 180 goto fail_port_init; 181 182 #if EFSYS_OPT_LOOPBACK 183 if (sa->eth_dev->data->dev_conf.lpbk_mode != 0) { 184 efx_link_mode_t link_mode; 185 186 link_mode = 187 sfc_port_phy_caps_to_max_link_speed(port->phy_adv_cap); 188 sfc_log_init(sa, "set loopback link_mode=%u type=%u", link_mode, 189 sa->eth_dev->data->dev_conf.lpbk_mode); 190 rc = efx_port_loopback_set(sa->nic, link_mode, 191 sa->eth_dev->data->dev_conf.lpbk_mode); 192 if (rc != 0) 193 goto fail_loopback_set; 194 } 195 #endif 196 197 sfc_log_init(sa, "set flow control to %#x autoneg=%u", 198 port->flow_ctrl, port->flow_ctrl_autoneg); 199 rc = efx_mac_fcntl_set(sa->nic, port->flow_ctrl, 200 port->flow_ctrl_autoneg); 201 if (rc != 0) 202 goto fail_mac_fcntl_set; 203 204 /* Preserve pause capabilities set by above efx_mac_fcntl_set() */ 205 efx_phy_adv_cap_get(sa->nic, EFX_PHY_CAP_CURRENT, &phy_adv_cap); 206 SFC_ASSERT((port->phy_adv_cap & phy_pause_caps) == 0); 207 phy_adv_cap = port->phy_adv_cap | (phy_adv_cap & phy_pause_caps); 208 209 /* 210 * No controls for FEC yet. Use default FEC mode. 211 * I.e. advertise everything supported (*_FEC=1), but do not request 212 * anything explicitly (*_FEC_REQUESTED=0). 213 */ 214 phy_adv_cap |= port->phy_adv_cap_mask & 215 (1u << EFX_PHY_CAP_BASER_FEC | 216 1u << EFX_PHY_CAP_RS_FEC | 217 1u << EFX_PHY_CAP_25G_BASER_FEC); 218 219 sfc_log_init(sa, "set phy adv caps to %#x", phy_adv_cap); 220 rc = efx_phy_adv_cap_set(sa->nic, phy_adv_cap); 221 if (rc != 0) 222 goto fail_phy_adv_cap_set; 223 224 sfc_log_init(sa, "set MAC PDU %u", (unsigned int)port->pdu); 225 rc = efx_mac_pdu_set(sa->nic, port->pdu); 226 if (rc != 0) 227 goto fail_mac_pdu_set; 228 229 if (!port->isolated) { 230 struct ether_addr *addr = &port->default_mac_addr; 231 232 sfc_log_init(sa, "set MAC address"); 233 rc = efx_mac_addr_set(sa->nic, addr->addr_bytes); 234 if (rc != 0) 235 goto fail_mac_addr_set; 236 237 sfc_log_init(sa, "set MAC filters"); 238 port->promisc = (sa->eth_dev->data->promiscuous != 0) ? 239 B_TRUE : B_FALSE; 240 port->allmulti = (sa->eth_dev->data->all_multicast != 0) ? 241 B_TRUE : B_FALSE; 242 rc = sfc_set_rx_mode(sa); 243 if (rc != 0) 244 goto fail_mac_filter_set; 245 246 sfc_log_init(sa, "set multicast address list"); 247 rc = efx_mac_multicast_list_set(sa->nic, port->mcast_addrs, 248 port->nb_mcast_addrs); 249 if (rc != 0) 250 goto fail_mcast_address_list_set; 251 } 252 253 if (port->mac_stats_reset_pending) { 254 rc = sfc_port_reset_mac_stats(sa); 255 if (rc != 0) 256 sfc_err(sa, "statistics reset failed (requested " 257 "before the port was started)"); 258 259 port->mac_stats_reset_pending = B_FALSE; 260 } 261 262 efx_mac_stats_get_mask(sa->nic, port->mac_stats_mask, 263 sizeof(port->mac_stats_mask)); 264 265 for (i = 0, port->mac_stats_nb_supported = 0; i < EFX_MAC_NSTATS; ++i) 266 if (EFX_MAC_STAT_SUPPORTED(port->mac_stats_mask, i)) 267 port->mac_stats_nb_supported++; 268 269 port->mac_stats_update_generation = 0; 270 271 if (port->mac_stats_update_period_ms != 0) { 272 /* 273 * Update MAC stats using periodic DMA; 274 * any positive update interval different from 275 * 1000 ms can be set only on SFN8xxx provided 276 * that FW version is 6.2.1.1033 or higher 277 */ 278 sfc_log_init(sa, "request MAC stats DMA'ing"); 279 rc = efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem, 280 port->mac_stats_update_period_ms, 281 B_FALSE); 282 if (rc == 0) { 283 port->mac_stats_periodic_dma_supported = B_TRUE; 284 } else if (rc == EOPNOTSUPP) { 285 port->mac_stats_periodic_dma_supported = B_FALSE; 286 port->mac_stats_last_request_timestamp = 0; 287 } else { 288 goto fail_mac_stats_periodic; 289 } 290 } 291 292 if ((port->mac_stats_update_period_ms != 0) && 293 port->mac_stats_periodic_dma_supported) { 294 /* 295 * Request an explicit MAC stats upload immediately to 296 * preclude bogus figures readback if the user decides 297 * to read stats before periodic DMA is really started 298 */ 299 rc = efx_mac_stats_upload(sa->nic, &port->mac_stats_dma_mem); 300 if (rc != 0) 301 goto fail_mac_stats_upload; 302 } 303 304 sfc_log_init(sa, "disable MAC drain"); 305 rc = efx_mac_drain(sa->nic, B_FALSE); 306 if (rc != 0) 307 goto fail_mac_drain; 308 309 /* Synchronize link status knowledge */ 310 rc = sfc_port_init_dev_link(sa); 311 if (rc != 0) 312 goto fail_port_init_dev_link; 313 314 sfc_log_init(sa, "done"); 315 return 0; 316 317 fail_port_init_dev_link: 318 (void)efx_mac_drain(sa->nic, B_TRUE); 319 320 fail_mac_drain: 321 fail_mac_stats_upload: 322 (void)efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem, 323 0, B_FALSE); 324 325 fail_mac_stats_periodic: 326 fail_mcast_address_list_set: 327 fail_mac_filter_set: 328 fail_mac_addr_set: 329 fail_mac_pdu_set: 330 fail_phy_adv_cap_set: 331 fail_mac_fcntl_set: 332 #if EFSYS_OPT_LOOPBACK 333 fail_loopback_set: 334 #endif 335 efx_port_fini(sa->nic); 336 337 fail_port_init: 338 efx_filter_fini(sa->nic); 339 340 fail_filter_init: 341 sfc_log_init(sa, "failed %d", rc); 342 return rc; 343 } 344 345 void 346 sfc_port_stop(struct sfc_adapter *sa) 347 { 348 sfc_log_init(sa, "entry"); 349 350 efx_mac_drain(sa->nic, B_TRUE); 351 352 (void)efx_mac_stats_periodic(sa->nic, &sa->port.mac_stats_dma_mem, 353 0, B_FALSE); 354 355 efx_port_fini(sa->nic); 356 efx_filter_fini(sa->nic); 357 358 sfc_log_init(sa, "done"); 359 } 360 361 int 362 sfc_port_configure(struct sfc_adapter *sa) 363 { 364 const struct rte_eth_dev_data *dev_data = sa->eth_dev->data; 365 struct sfc_port *port = &sa->port; 366 const struct rte_eth_rxmode *rxmode = &dev_data->dev_conf.rxmode; 367 368 sfc_log_init(sa, "entry"); 369 370 if (rxmode->offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) 371 port->pdu = rxmode->max_rx_pkt_len; 372 else 373 port->pdu = EFX_MAC_PDU(dev_data->mtu); 374 375 return 0; 376 } 377 378 void 379 sfc_port_close(struct sfc_adapter *sa) 380 { 381 sfc_log_init(sa, "entry"); 382 } 383 384 int 385 sfc_port_attach(struct sfc_adapter *sa) 386 { 387 struct sfc_port *port = &sa->port; 388 const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic); 389 const struct ether_addr *from; 390 uint32_t mac_nstats; 391 size_t mac_stats_size; 392 long kvarg_stats_update_period_ms; 393 int rc; 394 395 sfc_log_init(sa, "entry"); 396 397 efx_phy_adv_cap_get(sa->nic, EFX_PHY_CAP_PERM, &port->phy_adv_cap_mask); 398 399 /* Enable flow control by default */ 400 port->flow_ctrl = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE; 401 port->flow_ctrl_autoneg = B_TRUE; 402 403 RTE_BUILD_BUG_ON(sizeof(encp->enc_mac_addr) != sizeof(*from)); 404 from = (const struct ether_addr *)(encp->enc_mac_addr); 405 ether_addr_copy(from, &port->default_mac_addr); 406 407 port->max_mcast_addrs = EFX_MAC_MULTICAST_LIST_MAX; 408 port->nb_mcast_addrs = 0; 409 port->mcast_addrs = rte_calloc_socket("mcast_addr_list_buf", 410 port->max_mcast_addrs, 411 EFX_MAC_ADDR_LEN, 0, 412 sa->socket_id); 413 if (port->mcast_addrs == NULL) { 414 rc = ENOMEM; 415 goto fail_mcast_addr_list_buf_alloc; 416 } 417 418 rte_spinlock_init(&port->mac_stats_lock); 419 420 rc = ENOMEM; 421 port->mac_stats_buf = rte_calloc_socket("mac_stats_buf", EFX_MAC_NSTATS, 422 sizeof(uint64_t), 0, 423 sa->socket_id); 424 if (port->mac_stats_buf == NULL) 425 goto fail_mac_stats_buf_alloc; 426 427 mac_nstats = efx_nic_cfg_get(sa->nic)->enc_mac_stats_nstats; 428 mac_stats_size = RTE_ALIGN(mac_nstats * sizeof(uint64_t), EFX_BUF_SIZE); 429 rc = sfc_dma_alloc(sa, "mac_stats", 0, mac_stats_size, 430 sa->socket_id, &port->mac_stats_dma_mem); 431 if (rc != 0) 432 goto fail_mac_stats_dma_alloc; 433 434 port->mac_stats_reset_pending = B_FALSE; 435 436 kvarg_stats_update_period_ms = SFC_MAC_STATS_UPDATE_PERIOD_MS_DEF; 437 438 rc = sfc_kvargs_process(sa, SFC_KVARG_STATS_UPDATE_PERIOD_MS, 439 sfc_kvarg_long_handler, 440 &kvarg_stats_update_period_ms); 441 if ((rc == 0) && 442 ((kvarg_stats_update_period_ms < 0) || 443 (kvarg_stats_update_period_ms > UINT16_MAX))) { 444 sfc_err(sa, "wrong '" SFC_KVARG_STATS_UPDATE_PERIOD_MS "' " 445 "was set (%ld);", kvarg_stats_update_period_ms); 446 sfc_err(sa, "it must not be less than 0 " 447 "or greater than %" PRIu16, UINT16_MAX); 448 rc = EINVAL; 449 goto fail_kvarg_stats_update_period_ms; 450 } else if (rc != 0) { 451 goto fail_kvarg_stats_update_period_ms; 452 } 453 454 port->mac_stats_update_period_ms = kvarg_stats_update_period_ms; 455 456 sfc_log_init(sa, "done"); 457 return 0; 458 459 fail_kvarg_stats_update_period_ms: 460 sfc_dma_free(sa, &port->mac_stats_dma_mem); 461 462 fail_mac_stats_dma_alloc: 463 rte_free(port->mac_stats_buf); 464 465 fail_mac_stats_buf_alloc: 466 rte_free(port->mcast_addrs); 467 468 fail_mcast_addr_list_buf_alloc: 469 sfc_log_init(sa, "failed %d", rc); 470 return rc; 471 } 472 473 void 474 sfc_port_detach(struct sfc_adapter *sa) 475 { 476 struct sfc_port *port = &sa->port; 477 478 sfc_log_init(sa, "entry"); 479 480 sfc_dma_free(sa, &port->mac_stats_dma_mem); 481 rte_free(port->mac_stats_buf); 482 483 rte_free(port->mcast_addrs); 484 485 sfc_log_init(sa, "done"); 486 } 487 488 int 489 sfc_set_rx_mode(struct sfc_adapter *sa) 490 { 491 struct sfc_port *port = &sa->port; 492 int rc; 493 494 rc = efx_mac_filter_set(sa->nic, port->promisc, B_TRUE, 495 port->promisc || port->allmulti, B_TRUE); 496 497 return rc; 498 } 499 500 void 501 sfc_port_link_mode_to_info(efx_link_mode_t link_mode, 502 struct rte_eth_link *link_info) 503 { 504 SFC_ASSERT(link_mode < EFX_LINK_NMODES); 505 506 memset(link_info, 0, sizeof(*link_info)); 507 if ((link_mode == EFX_LINK_DOWN) || (link_mode == EFX_LINK_UNKNOWN)) 508 link_info->link_status = ETH_LINK_DOWN; 509 else 510 link_info->link_status = ETH_LINK_UP; 511 512 switch (link_mode) { 513 case EFX_LINK_10HDX: 514 link_info->link_speed = ETH_SPEED_NUM_10M; 515 link_info->link_duplex = ETH_LINK_HALF_DUPLEX; 516 break; 517 case EFX_LINK_10FDX: 518 link_info->link_speed = ETH_SPEED_NUM_10M; 519 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 520 break; 521 case EFX_LINK_100HDX: 522 link_info->link_speed = ETH_SPEED_NUM_100M; 523 link_info->link_duplex = ETH_LINK_HALF_DUPLEX; 524 break; 525 case EFX_LINK_100FDX: 526 link_info->link_speed = ETH_SPEED_NUM_100M; 527 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 528 break; 529 case EFX_LINK_1000HDX: 530 link_info->link_speed = ETH_SPEED_NUM_1G; 531 link_info->link_duplex = ETH_LINK_HALF_DUPLEX; 532 break; 533 case EFX_LINK_1000FDX: 534 link_info->link_speed = ETH_SPEED_NUM_1G; 535 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 536 break; 537 case EFX_LINK_10000FDX: 538 link_info->link_speed = ETH_SPEED_NUM_10G; 539 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 540 break; 541 case EFX_LINK_25000FDX: 542 link_info->link_speed = ETH_SPEED_NUM_25G; 543 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 544 break; 545 case EFX_LINK_40000FDX: 546 link_info->link_speed = ETH_SPEED_NUM_40G; 547 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 548 break; 549 case EFX_LINK_50000FDX: 550 link_info->link_speed = ETH_SPEED_NUM_50G; 551 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 552 break; 553 case EFX_LINK_100000FDX: 554 link_info->link_speed = ETH_SPEED_NUM_100G; 555 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 556 break; 557 default: 558 SFC_ASSERT(B_FALSE); 559 /* FALLTHROUGH */ 560 case EFX_LINK_UNKNOWN: 561 case EFX_LINK_DOWN: 562 link_info->link_speed = ETH_SPEED_NUM_NONE; 563 link_info->link_duplex = 0; 564 break; 565 } 566 567 link_info->link_autoneg = ETH_LINK_AUTONEG; 568 } 569