1 /* 2 * Copyright (c) 2008-2016 Solarflare Communications Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * The views and conclusions contained in the software and documentation are 27 * those of the authors and should not be interpreted as representing official 28 * policies, either expressed or implied, of the FreeBSD Project. 29 */ 30 31 /* 32 * All efx_mac_*() must be after efx_port_init() 33 * LOCKING STRATEGY: Aquire sm_lock and test sm_state==SFXGE_MAC_STARTED 34 * to serialise against sfxge_restart() 35 */ 36 37 #include <sys/types.h> 38 #include <sys/sysmacros.h> 39 #include <sys/ddi.h> 40 #include <sys/sunddi.h> 41 42 #include "sfxge.h" 43 #include "efx.h" 44 45 #define SFXGE_MAC_POLL_PERIOD_MS 1000 46 47 static void sfxge_mac_link_update_locked(sfxge_t *sp, efx_link_mode_t mode); 48 49 50 /* MAC DMA attributes */ 51 static ddi_device_acc_attr_t sfxge_mac_devacc = { 52 53 DDI_DEVICE_ATTR_V0, /* devacc_attr_version */ 54 DDI_NEVERSWAP_ACC, /* devacc_attr_endian_flags */ 55 DDI_STRICTORDER_ACC /* devacc_attr_dataorder */ 56 }; 57 58 static ddi_dma_attr_t sfxge_mac_dma_attr = { 59 DMA_ATTR_V0, /* dma_attr_version */ 60 0, /* dma_attr_addr_lo */ 61 0xffffffffffffffffull, /* dma_attr_addr_hi */ 62 0xffffffffffffffffull, /* dma_attr_count_max */ 63 0x1000, /* dma_attr_align */ 64 0xffffffff, /* dma_attr_burstsizes */ 65 1, /* dma_attr_minxfer */ 66 0xffffffffffffffffull, /* dma_attr_maxxfer */ 67 0xffffffffffffffffull, /* dma_attr_seg */ 68 1, /* dma_attr_sgllen */ 69 1, /* dma_attr_granular */ 70 0 /* dma_attr_flags */ 71 }; 72 73 74 static void 75 _sfxge_mac_stat_update(sfxge_mac_t *smp, int tries, int delay_usec) 76 { 77 sfxge_t *sp = smp->sm_sp; 78 efsys_mem_t *esmp = &(smp->sm_mem); 79 int i; 80 81 ASSERT(mutex_owned(&(smp->sm_lock))); 82 ASSERT3U(smp->sm_state, !=, SFXGE_MAC_UNINITIALIZED); 83 84 /* if no stats pending then they are already freshly updated */ 85 if (smp->sm_mac_stats_timer_reqd && !smp->sm_mac_stats_pend) 86 return; 87 88 for (i = 0; i < tries; i++) { 89 /* Try to update the cached counters */ 90 if (efx_mac_stats_update(sp->s_enp, esmp, smp->sm_stat, 91 NULL) != EAGAIN) 92 goto done; 93 94 drv_usecwait(delay_usec); 95 } 96 97 DTRACE_PROBE(mac_stat_timeout); 98 dev_err(sp->s_dip, CE_NOTE, SFXGE_CMN_ERR "MAC stats timeout"); 99 return; 100 101 done: 102 smp->sm_mac_stats_pend = B_FALSE; 103 smp->sm_lbolt = ddi_get_lbolt(); 104 } 105 106 static void 107 sfxge_mac_stat_update_quick(sfxge_mac_t *smp) 108 { 109 /* 110 * Update the statistics from the most recent DMA. This might race 111 * with an inflight dma, so retry once. Otherwise get mac stat 112 * values from the last mac_poll() or MC periodic stats. 113 */ 114 _sfxge_mac_stat_update(smp, 2, 50); 115 } 116 117 static void 118 sfxge_mac_stat_update_wait(sfxge_mac_t *smp) 119 { 120 /* Wait a max of 20 * 500us = 10ms */ 121 _sfxge_mac_stat_update(smp, 20, 500); 122 } 123 124 static int 125 sfxge_mac_kstat_update(kstat_t *ksp, int rw) 126 { 127 sfxge_mac_t *smp = ksp->ks_private; 128 kstat_named_t *knp; 129 int rc; 130 unsigned int val; 131 sfxge_rx_coalesce_mode_t rxmode; 132 133 if (rw != KSTAT_READ) { 134 rc = EACCES; 135 goto fail1; 136 } 137 138 ASSERT(mutex_owned(&(smp->sm_lock))); 139 140 if (smp->sm_state != SFXGE_MAC_STARTED) 141 goto done; 142 143 sfxge_mac_stat_update_quick(smp); 144 145 knp = smp->sm_stat; 146 knp += EFX_MAC_NSTATS; 147 148 knp->value.ui64 = (smp->sm_link_up) ? 1 : 0; 149 knp++; 150 151 knp->value.ui64 = smp->sm_link_speed; 152 knp++; 153 154 knp->value.ui64 = smp->sm_link_duplex; 155 knp++; 156 157 knp->value.ui64 = (smp->sm_fcntl & EFX_FCNTL_GENERATE) ? 1 : 0; 158 knp++; 159 160 knp->value.ui64 = (smp->sm_fcntl & EFX_FCNTL_RESPOND) ? 1 : 0; 161 knp++; 162 163 sfxge_ev_moderation_get(smp->sm_sp, &val); 164 knp->value.ui64 = val; 165 knp++; 166 167 sfxge_rx_coalesce_mode_get(smp->sm_sp, &rxmode); 168 knp->value.ui64 = (uint64_t)rxmode; 169 knp++; 170 171 if (sfxge_rx_scale_count_get(smp->sm_sp, &val) != 0) 172 val = 0; 173 knp->value.ui64 = val; 174 knp++; 175 176 done: 177 return (0); 178 179 fail1: 180 DTRACE_PROBE1(fail1, int, rc); 181 182 return (rc); 183 } 184 185 static int 186 sfxge_mac_kstat_init(sfxge_t *sp) 187 { 188 sfxge_mac_t *smp = &(sp->s_mac); 189 dev_info_t *dip = sp->s_dip; 190 char name[MAXNAMELEN]; 191 kstat_t *ksp; 192 kstat_named_t *knp; 193 unsigned int id; 194 int rc; 195 196 /* Create the set */ 197 (void) snprintf(name, MAXNAMELEN - 1, "%s_mac", ddi_driver_name(dip)); 198 199 if ((ksp = kstat_create((char *)ddi_driver_name(dip), 200 ddi_get_instance(dip), name, "mac", KSTAT_TYPE_NAMED, 201 EFX_MAC_NSTATS + 8, 0)) == NULL) { 202 rc = ENOMEM; 203 goto fail1; 204 } 205 206 smp->sm_ksp = ksp; 207 208 ksp->ks_update = sfxge_mac_kstat_update; 209 ksp->ks_private = smp; 210 ksp->ks_lock = &(smp->sm_lock); 211 212 /* Initialise the named stats */ 213 smp->sm_stat = knp = ksp->ks_data; 214 for (id = 0; id < EFX_MAC_NSTATS; id++) { 215 kstat_named_init(knp, (char *)efx_mac_stat_name(sp->s_enp, id), 216 KSTAT_DATA_UINT64); 217 knp++; 218 } 219 220 kstat_named_init(knp++, "link_up", KSTAT_DATA_UINT64); 221 kstat_named_init(knp++, "link_speed", KSTAT_DATA_UINT64); 222 kstat_named_init(knp++, "link_duplex", KSTAT_DATA_UINT64); 223 kstat_named_init(knp++, "fcntl_generate", KSTAT_DATA_UINT64); 224 kstat_named_init(knp++, "fcntl_respond", KSTAT_DATA_UINT64); 225 kstat_named_init(knp++, "intr_moderation", KSTAT_DATA_UINT64); 226 kstat_named_init(knp++, "rx_coalesce_mode", KSTAT_DATA_UINT64); 227 kstat_named_init(knp++, "rx_scale_count", KSTAT_DATA_UINT64); 228 229 kstat_install(ksp); 230 231 return (0); 232 233 fail1: 234 DTRACE_PROBE1(fail1, int, rc); 235 236 return (rc); 237 } 238 239 static void 240 sfxge_mac_kstat_fini(sfxge_t *sp) 241 { 242 sfxge_mac_t *smp = &(sp->s_mac); 243 244 /* Destroy the set */ 245 kstat_delete(smp->sm_ksp); 246 smp->sm_ksp = NULL; 247 smp->sm_stat = NULL; 248 } 249 250 void 251 sfxge_mac_stat_get(sfxge_t *sp, unsigned int id, uint64_t *valp) 252 { 253 sfxge_mac_t *smp = &(sp->s_mac); 254 255 /* Make sure the cached counter values are recent */ 256 mutex_enter(&(smp->sm_lock)); 257 258 if (smp->sm_state != SFXGE_MAC_STARTED) 259 goto done; 260 261 sfxge_mac_stat_update_quick(smp); 262 263 *valp = smp->sm_stat[id].value.ui64; 264 265 done: 266 mutex_exit(&(smp->sm_lock)); 267 } 268 269 static void 270 sfxge_mac_poll(void *arg) 271 { 272 sfxge_t *sp = arg; 273 efx_nic_t *enp = sp->s_enp; 274 sfxge_mac_t *smp = &(sp->s_mac); 275 efsys_mem_t *esmp = &(smp->sm_mem); 276 efx_link_mode_t mode; 277 clock_t timeout; 278 279 mutex_enter(&(smp->sm_lock)); 280 while (smp->sm_state == SFXGE_MAC_STARTED) { 281 282 /* clears smp->sm_mac_stats_pend if appropriate */ 283 if (smp->sm_mac_stats_pend) 284 sfxge_mac_stat_update_wait(smp); 285 286 /* This may sleep waiting for MCDI completion */ 287 mode = EFX_LINK_UNKNOWN; 288 if (efx_port_poll(enp, &mode) == 0) 289 sfxge_mac_link_update_locked(sp, mode); 290 291 if ((smp->sm_link_poll_reqd == B_FALSE) && 292 (smp->sm_mac_stats_timer_reqd == B_FALSE)) 293 goto done; 294 295 /* Zero the memory */ 296 bzero(esmp->esm_base, EFX_MAC_STATS_SIZE); 297 298 /* Trigger upload the MAC statistics counters */ 299 if (smp->sm_link_up && 300 efx_mac_stats_upload(sp->s_enp, esmp) == 0) 301 smp->sm_mac_stats_pend = B_TRUE; 302 303 /* Wait for timeout or end of polling */ 304 timeout = ddi_get_lbolt() + drv_usectohz(1000 * 305 SFXGE_MAC_POLL_PERIOD_MS); 306 while (smp->sm_state == SFXGE_MAC_STARTED) { 307 if (cv_timedwait(&(smp->sm_link_poll_kv), 308 &(smp->sm_lock), timeout) < 0) { 309 /* Timeout - poll if polling still enabled */ 310 break; 311 } 312 } 313 } 314 done: 315 mutex_exit(&(smp->sm_lock)); 316 317 } 318 319 static void 320 sfxge_mac_poll_start(sfxge_t *sp) 321 { 322 sfxge_mac_t *smp = &(sp->s_mac); 323 324 ASSERT(mutex_owned(&(smp->sm_lock))); 325 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_STARTED); 326 327 /* Schedule a poll */ 328 (void) ddi_taskq_dispatch(smp->sm_tqp, sfxge_mac_poll, sp, DDI_SLEEP); 329 } 330 331 static void 332 sfxge_mac_poll_stop(sfxge_t *sp) 333 { 334 sfxge_mac_t *smp = &(sp->s_mac); 335 336 ASSERT(mutex_owned(&(smp->sm_lock))); 337 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_INITIALIZED); 338 339 cv_broadcast(&(smp->sm_link_poll_kv)); 340 341 /* Wait for link polling to cease */ 342 mutex_exit(&(smp->sm_lock)); 343 ddi_taskq_wait(smp->sm_tqp); 344 mutex_enter(&(smp->sm_lock)); 345 346 /* Collect the final statistics. */ 347 sfxge_mac_stat_update_wait(smp); 348 } 349 350 int 351 sfxge_mac_init(sfxge_t *sp) 352 { 353 sfxge_mac_t *smp = &(sp->s_mac); 354 efsys_mem_t *esmp = &(smp->sm_mem); 355 dev_info_t *dip = sp->s_dip; 356 sfxge_dma_buffer_attr_t dma_attr; 357 const efx_nic_cfg_t *encp; 358 unsigned char *bytes; 359 unsigned int n; 360 int err, rc; 361 362 SFXGE_OBJ_CHECK(smp, sfxge_mac_t); 363 364 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_UNINITIALIZED); 365 366 smp->sm_sp = sp; 367 encp = efx_nic_cfg_get(sp->s_enp); 368 smp->sm_link_poll_reqd = (~encp->enc_features & 369 EFX_FEATURE_LINK_EVENTS); 370 smp->sm_mac_stats_timer_reqd = (~encp->enc_features & 371 EFX_FEATURE_PERIODIC_MAC_STATS); 372 373 mutex_init(&(smp->sm_lock), NULL, MUTEX_DRIVER, 374 DDI_INTR_PRI(sp->s_intr.si_intr_pri)); 375 cv_init(&(smp->sm_link_poll_kv), NULL, CV_DRIVER, NULL); 376 377 /* Create link poll taskq */ 378 smp->sm_tqp = ddi_taskq_create(dip, "mac_tq", 1, TASKQ_DEFAULTPRI, 0); 379 if (smp->sm_tqp == NULL) { 380 rc = ENOMEM; 381 goto fail1; 382 } 383 384 if ((rc = sfxge_phy_init(sp)) != 0) 385 goto fail2; 386 387 dma_attr.sdba_dip = dip; 388 dma_attr.sdba_dattrp = &sfxge_mac_dma_attr; 389 dma_attr.sdba_callback = DDI_DMA_SLEEP; 390 dma_attr.sdba_length = EFX_MAC_STATS_SIZE; 391 dma_attr.sdba_memflags = DDI_DMA_CONSISTENT; 392 dma_attr.sdba_devaccp = &sfxge_mac_devacc; 393 dma_attr.sdba_bindflags = DDI_DMA_READ | DDI_DMA_CONSISTENT; 394 dma_attr.sdba_maxcookies = 1; 395 dma_attr.sdba_zeroinit = B_TRUE; 396 397 if ((rc = sfxge_dma_buffer_create(esmp, &dma_attr)) != 0) 398 goto fail3; 399 400 /* Set the initial flow control values */ 401 smp->sm_fcntl = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE; 402 403 /* 404 * Determine the 'burnt-in' MAC address: 405 * 406 * A: if the "mac-address" property is set on our device node use that. 407 * B: otherwise, use the value from NVRAM. 408 */ 409 410 /* A: property */ 411 err = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 412 "mac-address", &bytes, &n); 413 switch (err) { 414 case DDI_PROP_SUCCESS: 415 if (n == ETHERADDRL) { 416 bcopy(bytes, smp->sm_bia, ETHERADDRL); 417 goto done; 418 } 419 420 ddi_prop_free(bytes); 421 break; 422 423 default: 424 break; 425 } 426 427 /* B: NVRAM */ 428 bcopy(encp->enc_mac_addr, smp->sm_bia, ETHERADDRL); 429 430 done: 431 /* Initialize the statistics */ 432 if ((rc = sfxge_mac_kstat_init(sp)) != 0) 433 goto fail4; 434 435 if ((rc = sfxge_phy_kstat_init(sp)) != 0) 436 goto fail5; 437 438 smp->sm_state = SFXGE_MAC_INITIALIZED; 439 440 return (0); 441 442 fail5: 443 DTRACE_PROBE(fail5); 444 445 sfxge_mac_kstat_fini(sp); 446 fail4: 447 DTRACE_PROBE(fail4); 448 449 /* Tear down DMA setup */ 450 sfxge_dma_buffer_destroy(esmp); 451 fail3: 452 DTRACE_PROBE(fail3); 453 454 sfxge_phy_fini(sp); 455 fail2: 456 DTRACE_PROBE(fail2); 457 458 /* Destroy the link poll taskq */ 459 ddi_taskq_destroy(smp->sm_tqp); 460 smp->sm_tqp = NULL; 461 462 fail1: 463 DTRACE_PROBE1(fail1, int, rc); 464 465 cv_destroy(&(smp->sm_link_poll_kv)); 466 467 mutex_destroy(&(smp->sm_lock)); 468 469 smp->sm_sp = NULL; 470 471 return (rc); 472 } 473 474 static int 475 sfxge_mac_filter_apply(sfxge_t *sp) 476 { 477 efx_nic_t *enp = sp->s_enp; 478 sfxge_mac_t *smp = &(sp->s_mac); 479 int rc; 480 481 ASSERT(mutex_owned(&(smp->sm_lock))); 482 483 if (smp->sm_state == SFXGE_MAC_STARTED) { 484 boolean_t all_unicst; 485 boolean_t mulcst; 486 boolean_t all_mulcst; 487 boolean_t brdcst; 488 489 all_unicst = (smp->sm_promisc == SFXGE_PROMISC_ALL_PHYS); 490 mulcst = (smp->sm_mcast_count > 0); 491 all_mulcst = (smp->sm_promisc >= SFXGE_PROMISC_ALL_MULTI); 492 brdcst = B_TRUE; 493 494 if ((rc = efx_mac_filter_set(enp, all_unicst, mulcst, 495 all_mulcst, brdcst)) != 0) { 496 goto fail1; 497 } 498 if ((rc = efx_mac_multicast_list_set(enp, 499 smp->sm_mcast_addr, smp->sm_mcast_count)) != 0) 500 goto fail2; 501 } 502 503 return (0); 504 505 fail2: 506 DTRACE_PROBE(fail2); 507 fail1: 508 DTRACE_PROBE1(fail1, int, rc); 509 510 return (rc); 511 } 512 513 int 514 sfxge_mac_start(sfxge_t *sp, boolean_t restart) 515 { 516 sfxge_mac_t *smp = &(sp->s_mac); 517 efsys_mem_t *esmp = &(smp->sm_mem); 518 efx_nic_t *enp = sp->s_enp; 519 size_t pdu; 520 int rc; 521 522 mutex_enter(&(smp->sm_lock)); 523 524 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_INITIALIZED); 525 526 if ((rc = efx_port_init(enp)) != 0) 527 goto fail1; 528 529 /* 530 * Set up the advertised capabilities that may have been asked for 531 * before the call to efx_port_init(). 532 */ 533 if ((rc = sfxge_phy_cap_apply(sp, !restart)) != 0) 534 goto fail2; 535 536 /* Set the SDU */ 537 pdu = EFX_MAC_PDU(sp->s_mtu); 538 if ((rc = efx_mac_pdu_set(enp, pdu)) != 0) 539 goto fail3; 540 541 if ((rc = efx_mac_fcntl_set(enp, smp->sm_fcntl, B_TRUE)) != 0) 542 goto fail4; 543 544 /* Set the unicast address */ 545 if ((rc = efx_mac_addr_set(enp, (smp->sm_laa_valid) ? 546 smp->sm_laa : smp->sm_bia)) != 0) 547 goto fail5; 548 549 if ((rc = sfxge_mac_filter_apply(sp)) != 0) 550 goto fail6; 551 552 if (!smp->sm_mac_stats_timer_reqd) { 553 if ((rc = efx_mac_stats_periodic(enp, esmp, 554 SFXGE_MAC_POLL_PERIOD_MS, B_FALSE)) != 0) 555 goto fail7; 556 } 557 558 if ((rc = efx_mac_drain(enp, B_FALSE)) != 0) 559 goto fail8; 560 561 smp->sm_state = SFXGE_MAC_STARTED; 562 563 /* 564 * Start link state polling. For hardware that reports link change 565 * events we still poll once to update the initial link state. 566 */ 567 sfxge_mac_poll_start(sp); 568 569 mutex_exit(&(smp->sm_lock)); 570 return (0); 571 572 fail8: 573 DTRACE_PROBE(fail8); 574 (void) efx_mac_stats_periodic(enp, esmp, 0, B_FALSE); 575 fail7: 576 DTRACE_PROBE(fail7); 577 fail6: 578 DTRACE_PROBE(fail6); 579 fail5: 580 DTRACE_PROBE(fail5); 581 fail4: 582 DTRACE_PROBE(fail4); 583 fail3: 584 DTRACE_PROBE(fail3); 585 fail2: 586 DTRACE_PROBE(fail2); 587 efx_port_fini(enp); 588 fail1: 589 DTRACE_PROBE1(fail1, int, rc); 590 591 mutex_exit(&(smp->sm_lock)); 592 593 return (rc); 594 } 595 596 597 static void 598 sfxge_mac_link_update_locked(sfxge_t *sp, efx_link_mode_t mode) 599 { 600 sfxge_mac_t *smp = &(sp->s_mac); 601 const char *change, *duplex; 602 char info[sizeof (": now 10000Mbps FULL duplex")]; 603 604 ASSERT(mutex_owned(&(smp->sm_lock))); 605 if (smp->sm_state != SFXGE_MAC_STARTED) 606 return; 607 608 if (smp->sm_link_mode == mode) 609 return; 610 611 smp->sm_link_mode = mode; 612 smp->sm_link_up = B_TRUE; 613 614 switch (smp->sm_link_mode) { 615 case EFX_LINK_UNKNOWN: 616 case EFX_LINK_DOWN: 617 smp->sm_link_speed = 0; 618 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_UNKNOWN; 619 smp->sm_link_up = B_FALSE; 620 break; 621 622 case EFX_LINK_10HDX: 623 case EFX_LINK_10FDX: 624 smp->sm_link_speed = 10; 625 smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_10HDX) ? 626 SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL; 627 break; 628 629 case EFX_LINK_100HDX: 630 case EFX_LINK_100FDX: 631 smp->sm_link_speed = 100; 632 smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_100HDX) ? 633 SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL; 634 break; 635 636 case EFX_LINK_1000HDX: 637 case EFX_LINK_1000FDX: 638 smp->sm_link_speed = 1000; 639 smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_1000HDX) ? 640 SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL; 641 break; 642 643 case EFX_LINK_10000FDX: 644 smp->sm_link_speed = 10000; 645 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_FULL; 646 break; 647 648 case EFX_LINK_40000FDX: 649 smp->sm_link_speed = 40000; 650 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_FULL; 651 break; 652 653 default: 654 ASSERT(B_FALSE); 655 break; 656 } 657 658 duplex = (smp->sm_link_duplex == SFXGE_LINK_DUPLEX_FULL) ? 659 "full" : "half"; 660 change = (smp->sm_link_up) ? "UP" : "DOWN"; 661 (void) snprintf(info, sizeof (info), ": now %dMbps %s duplex", 662 smp->sm_link_speed, duplex); 663 664 dev_err(sp->s_dip, CE_NOTE, SFXGE_CMN_ERR "Link %s%s", 665 change, smp->sm_link_up ? info : ""); 666 667 /* Push link state update to the OS */ 668 sfxge_gld_link_update(sp); 669 } 670 671 void 672 sfxge_mac_link_update(sfxge_t *sp, efx_link_mode_t mode) 673 { 674 sfxge_mac_t *smp = &(sp->s_mac); 675 676 mutex_enter(&(smp->sm_lock)); 677 sfxge_mac_link_update_locked(sp, mode); 678 mutex_exit(&(smp->sm_lock)); 679 } 680 681 void 682 sfxge_mac_link_check(sfxge_t *sp, boolean_t *upp) 683 { 684 sfxge_mac_t *smp = &(sp->s_mac); 685 686 mutex_enter(&(smp->sm_lock)); 687 *upp = smp->sm_link_up; 688 mutex_exit(&(smp->sm_lock)); 689 } 690 691 void 692 sfxge_mac_link_speed_get(sfxge_t *sp, unsigned int *speedp) 693 { 694 sfxge_mac_t *smp = &(sp->s_mac); 695 696 mutex_enter(&(smp->sm_lock)); 697 *speedp = smp->sm_link_speed; 698 mutex_exit(&(smp->sm_lock)); 699 } 700 701 void 702 sfxge_mac_link_duplex_get(sfxge_t *sp, sfxge_link_duplex_t *duplexp) 703 { 704 sfxge_mac_t *smp = &(sp->s_mac); 705 706 mutex_enter(&(smp->sm_lock)); 707 *duplexp = smp->sm_link_duplex; 708 mutex_exit(&(smp->sm_lock)); 709 } 710 711 void 712 sfxge_mac_fcntl_get(sfxge_t *sp, unsigned int *fcntlp) 713 { 714 sfxge_mac_t *smp = &(sp->s_mac); 715 716 mutex_enter(&(smp->sm_lock)); 717 *fcntlp = smp->sm_fcntl; 718 mutex_exit(&(smp->sm_lock)); 719 } 720 721 int 722 sfxge_mac_fcntl_set(sfxge_t *sp, unsigned int fcntl) 723 { 724 sfxge_mac_t *smp = &(sp->s_mac); 725 int rc; 726 727 mutex_enter(&(smp->sm_lock)); 728 729 if (smp->sm_fcntl == fcntl) 730 goto done; 731 732 smp->sm_fcntl = fcntl; 733 734 if (smp->sm_state != SFXGE_MAC_STARTED) 735 goto done; 736 737 if ((rc = efx_mac_fcntl_set(sp->s_enp, smp->sm_fcntl, B_TRUE)) != 0) 738 goto fail1; 739 740 done: 741 mutex_exit(&(smp->sm_lock)); 742 743 return (0); 744 745 fail1: 746 DTRACE_PROBE1(fail1, int, rc); 747 748 mutex_exit(&(smp->sm_lock)); 749 750 return (rc); 751 } 752 753 int 754 sfxge_mac_unicst_get(sfxge_t *sp, sfxge_unicst_type_t type, uint8_t *addr) 755 { 756 sfxge_mac_t *smp = &(sp->s_mac); 757 int rc; 758 759 if (type >= SFXGE_UNICST_NTYPES) { 760 rc = EINVAL; 761 goto fail1; 762 } 763 764 mutex_enter(&(smp->sm_lock)); 765 766 if (smp->sm_state != SFXGE_MAC_INITIALIZED && 767 smp->sm_state != SFXGE_MAC_STARTED) { 768 rc = EFAULT; 769 goto fail2; 770 } 771 772 switch (type) { 773 case SFXGE_UNICST_BIA: 774 bcopy(smp->sm_bia, addr, ETHERADDRL); 775 break; 776 777 case SFXGE_UNICST_LAA: 778 if (!(smp->sm_laa_valid)) { 779 rc = ENOENT; 780 goto fail3; 781 } 782 783 bcopy(smp->sm_laa, addr, ETHERADDRL); 784 break; 785 786 default: 787 ASSERT(B_FALSE); 788 break; 789 } 790 791 mutex_exit(&(smp->sm_lock)); 792 793 return (0); 794 795 796 fail3: 797 DTRACE_PROBE(fail3); 798 fail2: 799 DTRACE_PROBE(fail2); 800 801 mutex_exit(&(smp->sm_lock)); 802 803 fail1: 804 DTRACE_PROBE1(fail1, int, rc); 805 806 return (rc); 807 } 808 809 int 810 sfxge_mac_unicst_set(sfxge_t *sp, uint8_t *addr) 811 { 812 sfxge_mac_t *smp = &(sp->s_mac); 813 efx_nic_t *enp = sp->s_enp; 814 boolean_t old_mac_valid; 815 uint8_t old_mac[ETHERADDRL]; 816 int rc; 817 818 mutex_enter(&(smp->sm_lock)); 819 820 old_mac_valid = smp->sm_laa_valid; 821 if (old_mac_valid) 822 bcopy(smp->sm_laa, old_mac, ETHERADDRL); 823 824 bcopy(addr, smp->sm_laa, ETHERADDRL); 825 smp->sm_laa_valid = B_TRUE; 826 827 if (smp->sm_state != SFXGE_MAC_STARTED) 828 goto done; 829 830 if (efx_nic_cfg_get(enp)->enc_allow_set_mac_with_installed_filters) { 831 if ((rc = efx_mac_addr_set(enp, smp->sm_laa)) != 0) { 832 dev_err(sp->s_dip, CE_NOTE, SFXGE_CMN_ERR 833 "unable to set unicast MAC filter"); 834 goto fail1; 835 } 836 } else { 837 /* Older EF10 firmware requires a device start */ 838 mutex_exit(&smp->sm_lock); 839 sfxge_stop(sp); 840 if ((rc = sfxge_start(sp, B_TRUE)) != 0) { 841 dev_err(sp->s_dip, CE_NOTE, SFXGE_CMN_ERR 842 "unable to restart with a new MAC"); 843 mutex_enter(&(smp->sm_lock)); 844 goto fail1; 845 } 846 mutex_enter(&smp->sm_lock); 847 } 848 849 if ((rc = efx_mac_addr_set(enp, smp->sm_laa)) != 0) 850 goto fail1; 851 852 done: 853 mutex_exit(&(smp->sm_lock)); 854 855 return (0); 856 857 fail1: 858 if (old_mac_valid) 859 bcopy(old_mac, smp->sm_laa, ETHERADDRL); 860 else 861 smp->sm_laa_valid = B_FALSE; 862 863 DTRACE_PROBE1(fail1, int, rc); 864 865 mutex_exit(&(smp->sm_lock)); 866 867 return (rc); 868 } 869 870 int 871 sfxge_mac_promisc_set(sfxge_t *sp, sfxge_promisc_type_t promisc) 872 { 873 sfxge_mac_t *smp = &(sp->s_mac); 874 int rc; 875 876 mutex_enter(&(smp->sm_lock)); 877 878 if (smp->sm_promisc == promisc) 879 goto done; 880 881 smp->sm_promisc = promisc; 882 883 if ((rc = sfxge_mac_filter_apply(sp)) != 0) 884 goto fail1; 885 886 done: 887 mutex_exit(&(smp->sm_lock)); 888 return (0); 889 890 fail1: 891 DTRACE_PROBE1(fail1, int, rc); 892 mutex_exit(&(smp->sm_lock)); 893 894 return (rc); 895 } 896 897 int 898 sfxge_mac_multicst_add(sfxge_t *sp, const uint8_t *addr) 899 { 900 sfxge_mac_t *smp = &(sp->s_mac); 901 int i; 902 int rc; 903 904 mutex_enter(&(smp->sm_lock)); 905 906 if ((addr[0] & 0x1) == 0) { 907 rc = EINVAL; 908 goto fail1; 909 } 910 911 /* Check if the address is already in the list */ 912 i = 0; 913 while (i < smp->sm_mcast_count) { 914 if (bcmp(smp->sm_mcast_addr + (i * ETHERADDRL), 915 addr, ETHERADDRL) == 0) 916 goto done; 917 else 918 i++; 919 } 920 921 if (smp->sm_mcast_count >= EFX_MAC_MULTICAST_LIST_MAX) { 922 rc = ENOENT; 923 goto fail1; 924 } 925 926 /* Add to the list */ 927 bcopy(addr, smp->sm_mcast_addr + (smp->sm_mcast_count++ * ETHERADDRL), 928 ETHERADDRL); 929 930 if ((rc = sfxge_mac_filter_apply(sp)) != 0) 931 goto fail2; 932 933 done: 934 mutex_exit(&(smp->sm_lock)); 935 return (0); 936 937 fail2: 938 DTRACE_PROBE(fail2); 939 smp->sm_mcast_count--; 940 fail1: 941 DTRACE_PROBE1(fail1, int, rc); 942 mutex_exit(&(smp->sm_lock)); 943 944 return (rc); 945 } 946 947 int 948 sfxge_mac_multicst_remove(sfxge_t *sp, const uint8_t *addr) 949 { 950 sfxge_mac_t *smp = &(sp->s_mac); 951 int i; 952 int rc; 953 954 mutex_enter(&(smp->sm_lock)); 955 956 i = 0; 957 while (i < smp->sm_mcast_count) { 958 if (bcmp(smp->sm_mcast_addr + (i * ETHERADDRL), 959 addr, ETHERADDRL) == 0) { 960 (void) memmove(smp->sm_mcast_addr + (i * ETHERADDRL), 961 smp->sm_mcast_addr + ((i + 1) * ETHERADDRL), 962 (smp->sm_mcast_count - (i + 1)) * ETHERADDRL); 963 smp->sm_mcast_count--; 964 } else 965 i++; 966 } 967 968 if ((rc = sfxge_mac_filter_apply(sp)) != 0) 969 goto fail1; 970 971 mutex_exit(&(smp->sm_lock)); 972 return (0); 973 974 fail1: 975 DTRACE_PROBE1(fail1, int, rc); 976 mutex_exit(&(smp->sm_lock)); 977 978 return (rc); 979 } 980 981 void 982 sfxge_mac_stop(sfxge_t *sp) 983 { 984 sfxge_mac_t *smp = &(sp->s_mac); 985 efx_nic_t *enp = sp->s_enp; 986 efsys_mem_t *esmp = &(smp->sm_mem); 987 988 mutex_enter(&(smp->sm_lock)); 989 990 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_STARTED); 991 ASSERT3P(smp->sm_sp, ==, sp); 992 smp->sm_state = SFXGE_MAC_INITIALIZED; 993 994 /* If stopping in response to an MC reboot this may fail */ 995 if (!smp->sm_mac_stats_timer_reqd) 996 (void) efx_mac_stats_periodic(enp, esmp, 0, B_FALSE); 997 998 sfxge_mac_poll_stop(sp); 999 1000 smp->sm_lbolt = 0; 1001 1002 smp->sm_link_up = B_FALSE; 1003 smp->sm_link_speed = 0; 1004 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_UNKNOWN; 1005 1006 /* This may call MCDI */ 1007 (void) efx_mac_drain(enp, B_TRUE); 1008 1009 smp->sm_link_mode = EFX_LINK_UNKNOWN; 1010 1011 efx_port_fini(enp); 1012 1013 mutex_exit(&(smp->sm_lock)); 1014 } 1015 1016 void 1017 sfxge_mac_fini(sfxge_t *sp) 1018 { 1019 sfxge_mac_t *smp = &(sp->s_mac); 1020 efsys_mem_t *esmp = &(smp->sm_mem); 1021 1022 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_INITIALIZED); 1023 ASSERT3P(smp->sm_sp, ==, sp); 1024 1025 /* Tear down the statistics */ 1026 sfxge_phy_kstat_fini(sp); 1027 sfxge_mac_kstat_fini(sp); 1028 1029 smp->sm_state = SFXGE_MAC_UNINITIALIZED; 1030 smp->sm_link_mode = EFX_LINK_UNKNOWN; 1031 smp->sm_promisc = SFXGE_PROMISC_OFF; 1032 1033 bzero(smp->sm_mcast_addr, sizeof (smp->sm_mcast_addr)); 1034 smp->sm_mcast_count = 0; 1035 1036 bzero(smp->sm_laa, ETHERADDRL); 1037 smp->sm_laa_valid = B_FALSE; 1038 1039 bzero(smp->sm_bia, ETHERADDRL); 1040 1041 smp->sm_fcntl = 0; 1042 1043 /* Finish with PHY DMA memory */ 1044 sfxge_phy_fini(sp); 1045 1046 /* Teardown the DMA */ 1047 sfxge_dma_buffer_destroy(esmp); 1048 1049 /* Destroy the link poll taskq */ 1050 ddi_taskq_destroy(smp->sm_tqp); 1051 smp->sm_tqp = NULL; 1052 1053 mutex_destroy(&(smp->sm_lock)); 1054 1055 smp->sm_sp = NULL; 1056 }