1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) 2016-2017 Solarflare Communications Inc. 5 * All rights reserved. 6 * 7 * This software was jointly developed between OKTET Labs (under contract 8 * for Solarflare) and Solarflare Communications, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright notice, 14 * this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 29 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "efx.h" 33 34 #include "sfc.h" 35 #include "sfc_log.h" 36 #include "sfc_kvargs.h" 37 38 /** Default MAC statistics update period is 1 second */ 39 #define SFC_MAC_STATS_UPDATE_PERIOD_MS_DEF MS_PER_S 40 41 /** The number of microseconds to sleep on attempt to get statistics update */ 42 #define SFC_MAC_STATS_UPDATE_RETRY_INTERVAL_US 10 43 44 /** The number of attempts to await arrival of freshly generated statistics */ 45 #define SFC_MAC_STATS_UPDATE_NB_ATTEMPTS 50 46 47 /** 48 * Update MAC statistics in the buffer. 49 * 50 * @param sa Adapter 51 * 52 * @return Status code 53 * @retval 0 Success 54 * @retval EAGAIN Try again 55 * @retval ENOMEM Memory allocation failure 56 */ 57 int 58 sfc_port_update_mac_stats(struct sfc_adapter *sa) 59 { 60 struct sfc_port *port = &sa->port; 61 efsys_mem_t *esmp = &port->mac_stats_dma_mem; 62 uint32_t *genp = NULL; 63 uint32_t gen_old; 64 unsigned int nb_attempts = 0; 65 int rc; 66 67 SFC_ASSERT(rte_spinlock_is_locked(&port->mac_stats_lock)); 68 69 if (sa->state != SFC_ADAPTER_STARTED) 70 return EINVAL; 71 72 /* 73 * If periodic statistics DMA'ing is off or if not supported, 74 * make a manual request and keep an eye on timer if need be 75 */ 76 if (!port->mac_stats_periodic_dma_supported || 77 (port->mac_stats_update_period_ms == 0)) { 78 if (port->mac_stats_update_period_ms != 0) { 79 uint64_t timestamp = sfc_get_system_msecs(); 80 81 if ((timestamp - 82 port->mac_stats_last_request_timestamp) < 83 port->mac_stats_update_period_ms) 84 return 0; 85 86 port->mac_stats_last_request_timestamp = timestamp; 87 } 88 89 rc = efx_mac_stats_upload(sa->nic, esmp); 90 if (rc != 0) 91 return rc; 92 93 genp = &port->mac_stats_update_generation; 94 gen_old = *genp; 95 } 96 97 do { 98 if (nb_attempts > 0) 99 rte_delay_us(SFC_MAC_STATS_UPDATE_RETRY_INTERVAL_US); 100 101 rc = efx_mac_stats_update(sa->nic, esmp, 102 port->mac_stats_buf, genp); 103 if (rc != 0) 104 return rc; 105 106 } while ((genp != NULL) && (*genp == gen_old) && 107 (++nb_attempts < SFC_MAC_STATS_UPDATE_NB_ATTEMPTS)); 108 109 return 0; 110 } 111 112 int 113 sfc_port_reset_mac_stats(struct sfc_adapter *sa) 114 { 115 struct sfc_port *port = &sa->port; 116 int rc; 117 118 rte_spinlock_lock(&port->mac_stats_lock); 119 rc = efx_mac_stats_clear(sa->nic); 120 rte_spinlock_unlock(&port->mac_stats_lock); 121 122 return rc; 123 } 124 125 static int 126 sfc_port_init_dev_link(struct sfc_adapter *sa) 127 { 128 struct rte_eth_link *dev_link = &sa->eth_dev->data->dev_link; 129 int rc; 130 efx_link_mode_t link_mode; 131 struct rte_eth_link current_link; 132 133 rc = efx_port_poll(sa->nic, &link_mode); 134 if (rc != 0) 135 return rc; 136 137 sfc_port_link_mode_to_info(link_mode, ¤t_link); 138 139 EFX_STATIC_ASSERT(sizeof(*dev_link) == sizeof(rte_atomic64_t)); 140 rte_atomic64_set((rte_atomic64_t *)dev_link, 141 *(uint64_t *)¤t_link); 142 143 return 0; 144 } 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 sfc_log_init(sa, "set flow control to %#x autoneg=%u", 169 port->flow_ctrl, port->flow_ctrl_autoneg); 170 rc = efx_mac_fcntl_set(sa->nic, port->flow_ctrl, 171 port->flow_ctrl_autoneg); 172 if (rc != 0) 173 goto fail_mac_fcntl_set; 174 175 /* Preserve pause capabilities set by above efx_mac_fcntl_set() */ 176 efx_phy_adv_cap_get(sa->nic, EFX_PHY_CAP_CURRENT, &phy_adv_cap); 177 SFC_ASSERT((port->phy_adv_cap & phy_pause_caps) == 0); 178 phy_adv_cap = port->phy_adv_cap | (phy_adv_cap & phy_pause_caps); 179 180 sfc_log_init(sa, "set phy adv caps to %#x", phy_adv_cap); 181 rc = efx_phy_adv_cap_set(sa->nic, phy_adv_cap); 182 if (rc != 0) 183 goto fail_phy_adv_cap_set; 184 185 sfc_log_init(sa, "set MAC PDU %u", (unsigned int)port->pdu); 186 rc = efx_mac_pdu_set(sa->nic, port->pdu); 187 if (rc != 0) 188 goto fail_mac_pdu_set; 189 190 if (!port->isolated) { 191 struct ether_addr *addr = &port->default_mac_addr; 192 193 sfc_log_init(sa, "set MAC address"); 194 rc = efx_mac_addr_set(sa->nic, addr->addr_bytes); 195 if (rc != 0) 196 goto fail_mac_addr_set; 197 198 sfc_log_init(sa, "set MAC filters"); 199 port->promisc = (sa->eth_dev->data->promiscuous != 0) ? 200 B_TRUE : B_FALSE; 201 port->allmulti = (sa->eth_dev->data->all_multicast != 0) ? 202 B_TRUE : B_FALSE; 203 rc = sfc_set_rx_mode(sa); 204 if (rc != 0) 205 goto fail_mac_filter_set; 206 207 sfc_log_init(sa, "set multicast address list"); 208 rc = efx_mac_multicast_list_set(sa->nic, port->mcast_addrs, 209 port->nb_mcast_addrs); 210 if (rc != 0) 211 goto fail_mcast_address_list_set; 212 } 213 214 if (port->mac_stats_reset_pending) { 215 rc = sfc_port_reset_mac_stats(sa); 216 if (rc != 0) 217 sfc_err(sa, "statistics reset failed (requested " 218 "before the port was started)"); 219 220 port->mac_stats_reset_pending = B_FALSE; 221 } 222 223 efx_mac_stats_get_mask(sa->nic, port->mac_stats_mask, 224 sizeof(port->mac_stats_mask)); 225 226 for (i = 0, port->mac_stats_nb_supported = 0; i < EFX_MAC_NSTATS; ++i) 227 if (EFX_MAC_STAT_SUPPORTED(port->mac_stats_mask, i)) 228 port->mac_stats_nb_supported++; 229 230 port->mac_stats_update_generation = 0; 231 232 if (port->mac_stats_update_period_ms != 0) { 233 /* 234 * Update MAC stats using periodic DMA; 235 * any positive update interval different from 236 * 1000 ms can be set only on SFN8xxx provided 237 * that FW version is 6.2.1.1033 or higher 238 */ 239 sfc_log_init(sa, "request MAC stats DMA'ing"); 240 rc = efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem, 241 port->mac_stats_update_period_ms, 242 B_FALSE); 243 if (rc == 0) { 244 port->mac_stats_periodic_dma_supported = B_TRUE; 245 } else if (rc == EOPNOTSUPP) { 246 port->mac_stats_periodic_dma_supported = B_FALSE; 247 port->mac_stats_last_request_timestamp = 0; 248 } else { 249 goto fail_mac_stats_periodic; 250 } 251 } 252 253 if ((port->mac_stats_update_period_ms != 0) && 254 port->mac_stats_periodic_dma_supported) { 255 /* 256 * Request an explicit MAC stats upload immediately to 257 * preclude bogus figures readback if the user decides 258 * to read stats before periodic DMA is really started 259 */ 260 rc = efx_mac_stats_upload(sa->nic, &port->mac_stats_dma_mem); 261 if (rc != 0) 262 goto fail_mac_stats_upload; 263 } 264 265 sfc_log_init(sa, "disable MAC drain"); 266 rc = efx_mac_drain(sa->nic, B_FALSE); 267 if (rc != 0) 268 goto fail_mac_drain; 269 270 /* Synchronize link status knowledge */ 271 rc = sfc_port_init_dev_link(sa); 272 if (rc != 0) 273 goto fail_port_init_dev_link; 274 275 sfc_log_init(sa, "done"); 276 return 0; 277 278 fail_port_init_dev_link: 279 (void)efx_mac_drain(sa->nic, B_TRUE); 280 281 fail_mac_drain: 282 fail_mac_stats_upload: 283 (void)efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem, 284 0, B_FALSE); 285 286 fail_mac_stats_periodic: 287 fail_mcast_address_list_set: 288 fail_mac_filter_set: 289 fail_mac_addr_set: 290 fail_mac_pdu_set: 291 fail_phy_adv_cap_set: 292 fail_mac_fcntl_set: 293 efx_port_fini(sa->nic); 294 295 fail_port_init: 296 efx_filter_fini(sa->nic); 297 298 fail_filter_init: 299 sfc_log_init(sa, "failed %d", rc); 300 return rc; 301 } 302 303 void 304 sfc_port_stop(struct sfc_adapter *sa) 305 { 306 sfc_log_init(sa, "entry"); 307 308 efx_mac_drain(sa->nic, B_TRUE); 309 310 (void)efx_mac_stats_periodic(sa->nic, &sa->port.mac_stats_dma_mem, 311 0, B_FALSE); 312 313 efx_port_fini(sa->nic); 314 efx_filter_fini(sa->nic); 315 316 sfc_log_init(sa, "done"); 317 } 318 319 int 320 sfc_port_configure(struct sfc_adapter *sa) 321 { 322 const struct rte_eth_dev_data *dev_data = sa->eth_dev->data; 323 struct sfc_port *port = &sa->port; 324 325 sfc_log_init(sa, "entry"); 326 327 if (dev_data->dev_conf.rxmode.jumbo_frame) 328 port->pdu = dev_data->dev_conf.rxmode.max_rx_pkt_len; 329 else 330 port->pdu = EFX_MAC_PDU(dev_data->mtu); 331 332 return 0; 333 } 334 335 void 336 sfc_port_close(struct sfc_adapter *sa) 337 { 338 sfc_log_init(sa, "entry"); 339 } 340 341 int 342 sfc_port_attach(struct sfc_adapter *sa) 343 { 344 struct sfc_port *port = &sa->port; 345 const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic); 346 const struct ether_addr *from; 347 long kvarg_stats_update_period_ms; 348 int rc; 349 350 sfc_log_init(sa, "entry"); 351 352 efx_phy_adv_cap_get(sa->nic, EFX_PHY_CAP_PERM, &port->phy_adv_cap_mask); 353 354 /* Enable flow control by default */ 355 port->flow_ctrl = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE; 356 port->flow_ctrl_autoneg = B_TRUE; 357 358 RTE_BUILD_BUG_ON(sizeof(encp->enc_mac_addr) != sizeof(*from)); 359 from = (const struct ether_addr *)(encp->enc_mac_addr); 360 ether_addr_copy(from, &port->default_mac_addr); 361 362 port->max_mcast_addrs = EFX_MAC_MULTICAST_LIST_MAX; 363 port->nb_mcast_addrs = 0; 364 port->mcast_addrs = rte_calloc_socket("mcast_addr_list_buf", 365 port->max_mcast_addrs, 366 EFX_MAC_ADDR_LEN, 0, 367 sa->socket_id); 368 if (port->mcast_addrs == NULL) { 369 rc = ENOMEM; 370 goto fail_mcast_addr_list_buf_alloc; 371 } 372 373 rte_spinlock_init(&port->mac_stats_lock); 374 375 rc = ENOMEM; 376 port->mac_stats_buf = rte_calloc_socket("mac_stats_buf", EFX_MAC_NSTATS, 377 sizeof(uint64_t), 0, 378 sa->socket_id); 379 if (port->mac_stats_buf == NULL) 380 goto fail_mac_stats_buf_alloc; 381 382 rc = sfc_dma_alloc(sa, "mac_stats", 0, EFX_MAC_STATS_SIZE, 383 sa->socket_id, &port->mac_stats_dma_mem); 384 if (rc != 0) 385 goto fail_mac_stats_dma_alloc; 386 387 port->mac_stats_reset_pending = B_FALSE; 388 389 kvarg_stats_update_period_ms = SFC_MAC_STATS_UPDATE_PERIOD_MS_DEF; 390 391 rc = sfc_kvargs_process(sa, SFC_KVARG_STATS_UPDATE_PERIOD_MS, 392 sfc_kvarg_long_handler, 393 &kvarg_stats_update_period_ms); 394 if ((rc == 0) && 395 ((kvarg_stats_update_period_ms < 0) || 396 (kvarg_stats_update_period_ms > UINT16_MAX))) { 397 sfc_err(sa, "wrong '" SFC_KVARG_STATS_UPDATE_PERIOD_MS "' " 398 "was set (%ld);", kvarg_stats_update_period_ms); 399 sfc_err(sa, "it must not be less than 0 " 400 "or greater than %" PRIu16, UINT16_MAX); 401 rc = EINVAL; 402 goto fail_kvarg_stats_update_period_ms; 403 } else if (rc != 0) { 404 goto fail_kvarg_stats_update_period_ms; 405 } 406 407 port->mac_stats_update_period_ms = kvarg_stats_update_period_ms; 408 409 sfc_log_init(sa, "done"); 410 return 0; 411 412 fail_kvarg_stats_update_period_ms: 413 sfc_dma_free(sa, &port->mac_stats_dma_mem); 414 415 fail_mac_stats_dma_alloc: 416 rte_free(port->mac_stats_buf); 417 418 fail_mac_stats_buf_alloc: 419 rte_free(port->mcast_addrs); 420 421 fail_mcast_addr_list_buf_alloc: 422 sfc_log_init(sa, "failed %d", rc); 423 return rc; 424 } 425 426 void 427 sfc_port_detach(struct sfc_adapter *sa) 428 { 429 struct sfc_port *port = &sa->port; 430 431 sfc_log_init(sa, "entry"); 432 433 sfc_dma_free(sa, &port->mac_stats_dma_mem); 434 rte_free(port->mac_stats_buf); 435 436 rte_free(port->mcast_addrs); 437 438 sfc_log_init(sa, "done"); 439 } 440 441 int 442 sfc_set_rx_mode(struct sfc_adapter *sa) 443 { 444 struct sfc_port *port = &sa->port; 445 int rc; 446 447 rc = efx_mac_filter_set(sa->nic, port->promisc, B_TRUE, 448 port->promisc || port->allmulti, B_TRUE); 449 450 return rc; 451 } 452 453 void 454 sfc_port_link_mode_to_info(efx_link_mode_t link_mode, 455 struct rte_eth_link *link_info) 456 { 457 SFC_ASSERT(link_mode < EFX_LINK_NMODES); 458 459 memset(link_info, 0, sizeof(*link_info)); 460 if ((link_mode == EFX_LINK_DOWN) || (link_mode == EFX_LINK_UNKNOWN)) 461 link_info->link_status = ETH_LINK_DOWN; 462 else 463 link_info->link_status = ETH_LINK_UP; 464 465 switch (link_mode) { 466 case EFX_LINK_10HDX: 467 link_info->link_speed = ETH_SPEED_NUM_10M; 468 link_info->link_duplex = ETH_LINK_HALF_DUPLEX; 469 break; 470 case EFX_LINK_10FDX: 471 link_info->link_speed = ETH_SPEED_NUM_10M; 472 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 473 break; 474 case EFX_LINK_100HDX: 475 link_info->link_speed = ETH_SPEED_NUM_100M; 476 link_info->link_duplex = ETH_LINK_HALF_DUPLEX; 477 break; 478 case EFX_LINK_100FDX: 479 link_info->link_speed = ETH_SPEED_NUM_100M; 480 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 481 break; 482 case EFX_LINK_1000HDX: 483 link_info->link_speed = ETH_SPEED_NUM_1G; 484 link_info->link_duplex = ETH_LINK_HALF_DUPLEX; 485 break; 486 case EFX_LINK_1000FDX: 487 link_info->link_speed = ETH_SPEED_NUM_1G; 488 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 489 break; 490 case EFX_LINK_10000FDX: 491 link_info->link_speed = ETH_SPEED_NUM_10G; 492 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 493 break; 494 case EFX_LINK_40000FDX: 495 link_info->link_speed = ETH_SPEED_NUM_40G; 496 link_info->link_duplex = ETH_LINK_FULL_DUPLEX; 497 break; 498 default: 499 SFC_ASSERT(B_FALSE); 500 /* FALLTHROUGH */ 501 case EFX_LINK_UNKNOWN: 502 case EFX_LINK_DOWN: 503 link_info->link_speed = ETH_SPEED_NUM_NONE; 504 link_info->link_duplex = 0; 505 break; 506 } 507 508 link_info->link_autoneg = ETH_LINK_AUTONEG; 509 } 510