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 int 91 sfc_port_reset_mac_stats(struct sfc_adapter *sa) 92 { 93 struct sfc_port *port = &sa->port; 94 int rc; 95 96 rte_spinlock_lock(&port->mac_stats_lock); 97 rc = efx_mac_stats_clear(sa->nic); 98 rte_spinlock_unlock(&port->mac_stats_lock); 99 100 return rc; 101 } 102 103 static int 104 sfc_port_init_dev_link(struct sfc_adapter *sa) 105 { 106 struct rte_eth_link *dev_link = &sa->eth_dev->data->dev_link; 107 int rc; 108 efx_link_mode_t link_mode; 109 struct rte_eth_link current_link; 110 111 rc = efx_port_poll(sa->nic, &link_mode); 112 if (rc != 0) 113 return rc; 114 115 sfc_port_link_mode_to_info(link_mode, ¤t_link); 116 117 EFX_STATIC_ASSERT(sizeof(*dev_link) == sizeof(rte_atomic64_t)); 118 rte_atomic64_set((rte_atomic64_t *)dev_link, 119 *(uint64_t *)¤t_link); 120 121 return 0; 122 } 123 124 #if EFSYS_OPT_LOOPBACK 125 126 static efx_link_mode_t 127 sfc_port_phy_caps_to_max_link_speed(uint32_t phy_caps) 128 { 129 if (phy_caps & (1u << EFX_PHY_CAP_100000FDX)) 130 return EFX_LINK_100000FDX; 131 if (phy_caps & (1u << EFX_PHY_CAP_50000FDX)) 132 return EFX_LINK_50000FDX; 133 if (phy_caps & (1u << EFX_PHY_CAP_40000FDX)) 134 return EFX_LINK_40000FDX; 135 if (phy_caps & (1u << EFX_PHY_CAP_25000FDX)) 136 return EFX_LINK_25000FDX; 137 if (phy_caps & (1u << EFX_PHY_CAP_10000FDX)) 138 return EFX_LINK_10000FDX; 139 if (phy_caps & (1u << EFX_PHY_CAP_1000FDX)) 140 return EFX_LINK_1000FDX; 141 return EFX_LINK_UNKNOWN; 142 } 143 144 #endif 145 146 int 147 sfc_port_start(struct sfc_adapter *sa) 148 { 149 struct sfc_port *port = &sa->port; 150 int rc; 151 uint32_t phy_adv_cap; 152 const uint32_t phy_pause_caps = 153 ((1u << EFX_PHY_CAP_PAUSE) | (1u << EFX_PHY_CAP_ASYM)); 154 unsigned int i; 155 156 sfc_log_init(sa, "entry"); 157 158 sfc_log_init(sa, "init filters"); 159 rc = efx_filter_init(sa->nic); 160 if (rc != 0) 161 goto fail_filter_init; 162 163 sfc_log_init(sa, "init port"); 164 rc = efx_port_init(sa->nic); 165 if (rc != 0) 166 goto fail_port_init; 167 168 #if EFSYS_OPT_LOOPBACK 169 if (sa->eth_dev->data->dev_conf.lpbk_mode != 0) { 170 efx_link_mode_t link_mode; 171 172 link_mode = 173 sfc_port_phy_caps_to_max_link_speed(port->phy_adv_cap); 174 sfc_log_init(sa, "set loopback link_mode=%u type=%u", link_mode, 175 sa->eth_dev->data->dev_conf.lpbk_mode); 176 rc = efx_port_loopback_set(sa->nic, link_mode, 177 sa->eth_dev->data->dev_conf.lpbk_mode); 178 if (rc != 0) 179 goto fail_loopback_set; 180 } 181 #endif 182 183 sfc_log_init(sa, "set flow control to %#x autoneg=%u", 184 port->flow_ctrl, port->flow_ctrl_autoneg); 185 rc = efx_mac_fcntl_set(sa->nic, port->flow_ctrl, 186 port->flow_ctrl_autoneg); 187 if (rc != 0) 188 goto fail_mac_fcntl_set; 189 190 /* Preserve pause capabilities set by above efx_mac_fcntl_set() */ 191 efx_phy_adv_cap_get(sa->nic, EFX_PHY_CAP_CURRENT, &phy_adv_cap); 192 SFC_ASSERT((port->phy_adv_cap & phy_pause_caps) == 0); 193 phy_adv_cap = port->phy_adv_cap | (phy_adv_cap & phy_pause_caps); 194 195 /* 196 * No controls for FEC yet. Use default FEC mode. 197 * I.e. advertise everything supported (*_FEC=1), but do not request 198 * anything explicitly (*_FEC_REQUESTED=0). 199 */ 200 phy_adv_cap |= port->phy_adv_cap_mask & 201 (1u << EFX_PHY_CAP_BASER_FEC | 202 1u << EFX_PHY_CAP_RS_FEC | 203 1u << EFX_PHY_CAP_25G_BASER_FEC); 204 205 sfc_log_init(sa, "set phy adv caps to %#x", phy_adv_cap); 206 rc = efx_phy_adv_cap_set(sa->nic, phy_adv_cap); 207 if (rc != 0) 208 goto fail_phy_adv_cap_set; 209 210 sfc_log_init(sa, "set MAC PDU %u", (unsigned int)port->pdu); 211 rc = efx_mac_pdu_set(sa->nic, port->pdu); 212 if (rc != 0) 213 goto fail_mac_pdu_set; 214 215 if (!port->isolated) { 216 struct ether_addr *addr = &port->default_mac_addr; 217 218 sfc_log_init(sa, "set MAC address"); 219 rc = efx_mac_addr_set(sa->nic, addr->addr_bytes); 220 if (rc != 0) 221 goto fail_mac_addr_set; 222 223 sfc_log_init(sa, "set MAC filters"); 224 port->promisc = (sa->eth_dev->data->promiscuous != 0) ? 225 B_TRUE : B_FALSE; 226 port->allmulti = (sa->eth_dev->data->all_multicast != 0) ? 227 B_TRUE : B_FALSE; 228 rc = sfc_set_rx_mode(sa); 229 if (rc != 0) 230 goto fail_mac_filter_set; 231 232 sfc_log_init(sa, "set multicast address list"); 233 rc = efx_mac_multicast_list_set(sa->nic, port->mcast_addrs, 234 port->nb_mcast_addrs); 235 if (rc != 0) 236 goto fail_mcast_address_list_set; 237 } 238 239 if (port->mac_stats_reset_pending) { 240 rc = sfc_port_reset_mac_stats(sa); 241 if (rc != 0) 242 sfc_err(sa, "statistics reset failed (requested " 243 "before the port was started)"); 244 245 port->mac_stats_reset_pending = B_FALSE; 246 } 247 248 efx_mac_stats_get_mask(sa->nic, port->mac_stats_mask, 249 sizeof(port->mac_stats_mask)); 250 251 for (i = 0, port->mac_stats_nb_supported = 0; i < EFX_MAC_NSTATS; ++i) 252 if (EFX_MAC_STAT_SUPPORTED(port->mac_stats_mask, i)) 253 port->mac_stats_nb_supported++; 254 255 port->mac_stats_update_generation = 0; 256 257 if (port->mac_stats_update_period_ms != 0) { 258 /* 259 * Update MAC stats using periodic DMA; 260 * any positive update interval different from 261 * 1000 ms can be set only on SFN8xxx provided 262 * that FW version is 6.2.1.1033 or higher 263 */ 264 sfc_log_init(sa, "request MAC stats DMA'ing"); 265 rc = efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem, 266 port->mac_stats_update_period_ms, 267 B_FALSE); 268 if (rc == 0) { 269 port->mac_stats_periodic_dma_supported = B_TRUE; 270 } else if (rc == EOPNOTSUPP) { 271 port->mac_stats_periodic_dma_supported = B_FALSE; 272 port->mac_stats_last_request_timestamp = 0; 273 } else { 274 goto fail_mac_stats_periodic; 275 } 276 } 277 278 if ((port->mac_stats_update_period_ms != 0) && 279 port->mac_stats_periodic_dma_supported) { 280 /* 281 * Request an explicit MAC stats upload immediately to 282 * preclude bogus figures readback if the user decides 283 * to read stats before periodic DMA is really started 284 */ 285 rc = efx_mac_stats_upload(sa->nic, &port->mac_stats_dma_mem); 286 if (rc != 0) 287 goto fail_mac_stats_upload; 288 } 289 290 sfc_log_init(sa, "disable MAC drain"); 291 rc = efx_mac_drain(sa->nic, B_FALSE); 292 if (rc != 0) 293 goto fail_mac_drain; 294 295 /* Synchronize link status knowledge */ 296 rc = sfc_port_init_dev_link(sa); 297 if (rc != 0) 298 goto fail_port_init_dev_link; 299 300 sfc_log_init(sa, "done"); 301 return 0; 302 303 fail_port_init_dev_link: 304 (void)efx_mac_drain(sa->nic, B_TRUE); 305 306 fail_mac_drain: 307 fail_mac_stats_upload: 308 (void)efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem, 309 0, B_FALSE); 310 311 fail_mac_stats_periodic: 312 fail_mcast_address_list_set: 313 fail_mac_filter_set: 314 fail_mac_addr_set: 315 fail_mac_pdu_set: 316 fail_phy_adv_cap_set: 317 fail_mac_fcntl_set: 318 #if EFSYS_OPT_LOOPBACK 319 fail_loopback_set: 320 #endif 321 efx_port_fini(sa->nic); 322 323 fail_port_init: 324 efx_filter_fini(sa->nic); 325 326 fail_filter_init: 327 sfc_log_init(sa, "failed %d", rc); 328 return rc; 329 } 330 331 void 332 sfc_port_stop(struct sfc_adapter *sa) 333 { 334 sfc_log_init(sa, "entry"); 335 336 efx_mac_drain(sa->nic, B_TRUE); 337 338 (void)efx_mac_stats_periodic(sa->nic, &sa->port.mac_stats_dma_mem, 339 0, B_FALSE); 340 341 efx_port_fini(sa->nic); 342 efx_filter_fini(sa->nic); 343 344 sfc_log_init(sa, "done"); 345 } 346 347 int 348 sfc_port_configure(struct sfc_adapter *sa) 349 { 350 const struct rte_eth_dev_data *dev_data = sa->eth_dev->data; 351 struct sfc_port *port = &sa->port; 352 const struct rte_eth_rxmode *rxmode = &dev_data->dev_conf.rxmode; 353 354 sfc_log_init(sa, "entry"); 355 356 if (rxmode->offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) 357 port->pdu = rxmode->max_rx_pkt_len; 358 else 359 port->pdu = EFX_MAC_PDU(dev_data->mtu); 360 361 return 0; 362 } 363 364 void 365 sfc_port_close(struct sfc_adapter *sa) 366 { 367 sfc_log_init(sa, "entry"); 368 } 369 370 int 371 sfc_port_attach(struct sfc_adapter *sa) 372 { 373 struct sfc_port *port = &sa->port; 374 const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic); 375 const struct ether_addr *from; 376 uint32_t mac_nstats; 377 size_t mac_stats_size; 378 long kvarg_stats_update_period_ms; 379 int rc; 380 381 sfc_log_init(sa, "entry"); 382 383 efx_phy_adv_cap_get(sa->nic, EFX_PHY_CAP_PERM, &port->phy_adv_cap_mask); 384 385 /* Enable flow control by default */ 386 port->flow_ctrl = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE; 387 port->flow_ctrl_autoneg = B_TRUE; 388 389 RTE_BUILD_BUG_ON(sizeof(encp->enc_mac_addr) != sizeof(*from)); 390 from = (const struct ether_addr *)(encp->enc_mac_addr); 391 ether_addr_copy(from, &port->default_mac_addr); 392 393 port->max_mcast_addrs = EFX_MAC_MULTICAST_LIST_MAX; 394 port->nb_mcast_addrs = 0; 395 port->mcast_addrs = rte_calloc_socket("mcast_addr_list_buf", 396 port->max_mcast_addrs, 397 EFX_MAC_ADDR_LEN, 0, 398 sa->socket_id); 399 if (port->mcast_addrs == NULL) { 400 rc = ENOMEM; 401 goto fail_mcast_addr_list_buf_alloc; 402 } 403 404 rte_spinlock_init(&port->mac_stats_lock); 405 406 rc = ENOMEM; 407 port->mac_stats_buf = rte_calloc_socket("mac_stats_buf", EFX_MAC_NSTATS, 408 sizeof(uint64_t), 0, 409 sa->socket_id); 410 if (port->mac_stats_buf == NULL) 411 goto fail_mac_stats_buf_alloc; 412 413 mac_nstats = efx_nic_cfg_get(sa->nic)->enc_mac_stats_nstats; 414 mac_stats_size = RTE_ALIGN(mac_nstats * sizeof(uint64_t), EFX_BUF_SIZE); 415 rc = sfc_dma_alloc(sa, "mac_stats", 0, mac_stats_size, 416 sa->socket_id, &port->mac_stats_dma_mem); 417 if (rc != 0) 418 goto fail_mac_stats_dma_alloc; 419 420 port->mac_stats_reset_pending = B_FALSE; 421 422 kvarg_stats_update_period_ms = SFC_MAC_STATS_UPDATE_PERIOD_MS_DEF; 423 424 rc = sfc_kvargs_process(sa, SFC_KVARG_STATS_UPDATE_PERIOD_MS, 425 sfc_kvarg_long_handler, 426 &kvarg_stats_update_period_ms); 427 if ((rc == 0) && 428 ((kvarg_stats_update_period_ms < 0) || 429 (kvarg_stats_update_period_ms > UINT16_MAX))) { 430 sfc_err(sa, "wrong '" SFC_KVARG_STATS_UPDATE_PERIOD_MS "' " 431 "was set (%ld);", kvarg_stats_update_period_ms); 432 sfc_err(sa, "it must not be less than 0 " 433 "or greater than %" PRIu16, UINT16_MAX); 434 rc = EINVAL; 435 goto fail_kvarg_stats_update_period_ms; 436 } else if (rc != 0) { 437 goto fail_kvarg_stats_update_period_ms; 438 } 439 440 port->mac_stats_update_period_ms = kvarg_stats_update_period_ms; 441 442 sfc_log_init(sa, "done"); 443 return 0; 444 445 fail_kvarg_stats_update_period_ms: 446 sfc_dma_free(sa, &port->mac_stats_dma_mem); 447 448 fail_mac_stats_dma_alloc: 449 rte_free(port->mac_stats_buf); 450 451 fail_mac_stats_buf_alloc: 452 rte_free(port->mcast_addrs); 453 454 fail_mcast_addr_list_buf_alloc: 455 sfc_log_init(sa, "failed %d", rc); 456 return rc; 457 } 458 459 void 460 sfc_port_detach(struct sfc_adapter *sa) 461 { 462 struct sfc_port *port = &sa->port; 463 464 sfc_log_init(sa, "entry"); 465 466 sfc_dma_free(sa, &port->mac_stats_dma_mem); 467 rte_free(port->mac_stats_buf); 468 469 rte_free(port->mcast_addrs); 470 471 sfc_log_init(sa, "done"); 472 } 473 474 int 475 sfc_set_rx_mode(struct sfc_adapter *sa) 476 { 477 struct sfc_port *port = &sa->port; 478 int rc; 479 480 rc = efx_mac_filter_set(sa->nic, port->promisc, B_TRUE, 481 port->promisc || port->allmulti, B_TRUE); 482 483 return rc; 484 } 485 486 void 487 sfc_port_link_mode_to_info(efx_link_mode_t link_mode, 488 struct rte_eth_link *link_info) 489 { 490 SFC_ASSERT(link_mode < EFX_LINK_NMODES); 491 492 memset(link_info, 0, sizeof(*link_info)); 493 if ((link_mode == EFX_LINK_DOWN) || (link_mode == EFX_LINK_UNKNOWN)) 494 link_info->link_status = ETH_LINK_DOWN; 495 else 496 link_info->link_status = ETH_LINK_UP; 497 498 switch (link_mode) { 499 case EFX_LINK_10HDX: 500 link_info->link_speed = ETH_SPEED_NUM_10M; 501 link_info->link_duplex = ETH_LINK_HALF_DUPLEX; 502 break; 503 case EFX_LINK_10FDX: 504 link_info->link_speed = ETH_SPEED_NUM_10M; 505 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 506 break; 507 case EFX_LINK_100HDX: 508 link_info->link_speed = ETH_SPEED_NUM_100M; 509 link_info->link_duplex = ETH_LINK_HALF_DUPLEX; 510 break; 511 case EFX_LINK_100FDX: 512 link_info->link_speed = ETH_SPEED_NUM_100M; 513 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 514 break; 515 case EFX_LINK_1000HDX: 516 link_info->link_speed = ETH_SPEED_NUM_1G; 517 link_info->link_duplex = ETH_LINK_HALF_DUPLEX; 518 break; 519 case EFX_LINK_1000FDX: 520 link_info->link_speed = ETH_SPEED_NUM_1G; 521 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 522 break; 523 case EFX_LINK_10000FDX: 524 link_info->link_speed = ETH_SPEED_NUM_10G; 525 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 526 break; 527 case EFX_LINK_25000FDX: 528 link_info->link_speed = ETH_SPEED_NUM_25G; 529 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 530 break; 531 case EFX_LINK_40000FDX: 532 link_info->link_speed = ETH_SPEED_NUM_40G; 533 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 534 break; 535 case EFX_LINK_50000FDX: 536 link_info->link_speed = ETH_SPEED_NUM_50G; 537 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 538 break; 539 case EFX_LINK_100000FDX: 540 link_info->link_speed = ETH_SPEED_NUM_100G; 541 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 542 break; 543 default: 544 SFC_ASSERT(B_FALSE); 545 /* FALLTHROUGH */ 546 case EFX_LINK_UNKNOWN: 547 case EFX_LINK_DOWN: 548 link_info->link_speed = ETH_SPEED_NUM_NONE; 549 link_info->link_duplex = 0; 550 break; 551 } 552 553 link_info->link_autoneg = ETH_LINK_AUTONEG; 554 } 555