1 /* 2 * Copyright (c) 2008-2015 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 /* Wait for any pending DMAed stats to complete */ 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 SFXGE_OBJ_CHECK(smp, sfxge_mac_t); 472 473 return (rc); 474 } 475 476 static int 477 sfxge_mac_filter_apply(sfxge_t *sp) 478 { 479 efx_nic_t *enp = sp->s_enp; 480 sfxge_mac_t *smp = &(sp->s_mac); 481 int rc; 482 483 ASSERT(mutex_owned(&(smp->sm_lock))); 484 485 if (smp->sm_state == SFXGE_MAC_STARTED) { 486 boolean_t all_unicst; 487 boolean_t mulcst; 488 boolean_t all_mulcst; 489 boolean_t brdcst; 490 491 all_unicst = (smp->sm_promisc == SFXGE_PROMISC_ALL_PHYS); 492 mulcst = (smp->sm_mcast_count > 0); 493 all_mulcst = (smp->sm_promisc >= SFXGE_PROMISC_ALL_MULTI); 494 brdcst = B_TRUE; 495 496 if ((rc = efx_mac_filter_set(enp, all_unicst, mulcst, 497 all_mulcst, brdcst)) != 0) { 498 goto fail1; 499 } 500 if ((rc = efx_mac_multicast_list_set(enp, 501 smp->sm_mcast_addr, smp->sm_mcast_count)) != 0) 502 goto fail2; 503 } 504 505 return (0); 506 507 fail2: 508 DTRACE_PROBE(fail2); 509 fail1: 510 DTRACE_PROBE1(fail1, int, rc); 511 512 return (rc); 513 } 514 515 int 516 sfxge_mac_start(sfxge_t *sp, boolean_t restart) 517 { 518 sfxge_mac_t *smp = &(sp->s_mac); 519 efsys_mem_t *esmp = &(smp->sm_mem); 520 efx_nic_t *enp = sp->s_enp; 521 size_t pdu; 522 int rc; 523 524 mutex_enter(&(smp->sm_lock)); 525 526 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_INITIALIZED); 527 528 if ((rc = efx_port_init(enp)) != 0) 529 goto fail1; 530 531 /* 532 * Set up the advertised capabilities that may have been asked for 533 * before the call to efx_port_init(). 534 */ 535 if ((rc = sfxge_phy_cap_apply(sp, !restart)) != 0) 536 goto fail2; 537 538 /* Set the SDU */ 539 pdu = EFX_MAC_PDU(sp->s_mtu); 540 if ((rc = efx_mac_pdu_set(enp, pdu)) != 0) 541 goto fail3; 542 543 if ((rc = efx_mac_fcntl_set(enp, smp->sm_fcntl, B_TRUE)) != 0) 544 goto fail4; 545 546 /* Set the unicast address */ 547 if ((rc = efx_mac_addr_set(enp, (smp->sm_laa_valid) ? 548 smp->sm_laa : smp->sm_bia)) != 0) 549 goto fail5; 550 551 if ((rc = sfxge_mac_filter_apply(sp)) != 0) 552 goto fail6; 553 554 if (!smp->sm_mac_stats_timer_reqd) { 555 if ((rc = efx_mac_stats_periodic(enp, esmp, 556 SFXGE_MAC_POLL_PERIOD_MS, B_FALSE)) != 0) 557 goto fail7; 558 } 559 560 if ((rc = efx_mac_drain(enp, B_FALSE)) != 0) 561 goto fail8; 562 563 smp->sm_state = SFXGE_MAC_STARTED; 564 565 /* 566 * Start link state polling. For hardware that reports link change 567 * events we still poll once to update the initial link state. 568 */ 569 sfxge_mac_poll_start(sp); 570 571 mutex_exit(&(smp->sm_lock)); 572 return (0); 573 574 fail8: 575 DTRACE_PROBE(fail8); 576 (void) efx_mac_stats_periodic(enp, esmp, 0, B_FALSE); 577 fail7: 578 DTRACE_PROBE(fail7); 579 fail6: 580 DTRACE_PROBE(fail6); 581 fail5: 582 DTRACE_PROBE(fail5); 583 fail4: 584 DTRACE_PROBE(fail4); 585 fail3: 586 DTRACE_PROBE(fail3); 587 fail2: 588 DTRACE_PROBE(fail2); 589 efx_port_fini(enp); 590 fail1: 591 DTRACE_PROBE1(fail1, int, rc); 592 593 mutex_exit(&(smp->sm_lock)); 594 595 return (rc); 596 } 597 598 599 static void 600 sfxge_mac_link_update_locked(sfxge_t *sp, efx_link_mode_t mode) 601 { 602 sfxge_mac_t *smp = &(sp->s_mac); 603 const char *change, *duplex; 604 char info[sizeof (": now 10000Mbps FULL duplex")]; 605 606 ASSERT(mutex_owned(&(smp->sm_lock))); 607 if (smp->sm_state != SFXGE_MAC_STARTED) 608 return; 609 610 if (smp->sm_link_mode == mode) 611 return; 612 613 smp->sm_link_mode = mode; 614 smp->sm_link_up = B_TRUE; 615 616 switch (smp->sm_link_mode) { 617 case EFX_LINK_UNKNOWN: 618 case EFX_LINK_DOWN: 619 smp->sm_link_speed = 0; 620 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_UNKNOWN; 621 smp->sm_link_up = B_FALSE; 622 break; 623 624 case EFX_LINK_10HDX: 625 case EFX_LINK_10FDX: 626 smp->sm_link_speed = 10; 627 smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_10HDX) ? 628 SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL; 629 break; 630 631 case EFX_LINK_100HDX: 632 case EFX_LINK_100FDX: 633 smp->sm_link_speed = 100; 634 smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_100HDX) ? 635 SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL; 636 break; 637 638 case EFX_LINK_1000HDX: 639 case EFX_LINK_1000FDX: 640 smp->sm_link_speed = 1000; 641 smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_1000HDX) ? 642 SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL; 643 break; 644 645 case EFX_LINK_10000FDX: 646 smp->sm_link_speed = 10000; 647 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_FULL; 648 break; 649 650 case EFX_LINK_40000FDX: 651 smp->sm_link_speed = 40000; 652 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_FULL; 653 break; 654 655 default: 656 ASSERT(B_FALSE); 657 break; 658 } 659 660 duplex = (smp->sm_link_duplex == SFXGE_LINK_DUPLEX_FULL) ? 661 "full" : "half"; 662 change = (smp->sm_link_up) ? "UP" : "DOWN"; 663 (void) snprintf(info, sizeof (info), ": now %dMbps %s duplex", 664 smp->sm_link_speed, duplex); 665 666 dev_err(sp->s_dip, CE_NOTE, SFXGE_CMN_ERR "Link %s%s", 667 change, smp->sm_link_up ? info : ""); 668 669 /* Push link state update to the OS */ 670 sfxge_gld_link_update(sp); 671 } 672 673 void 674 sfxge_mac_link_update(sfxge_t *sp, efx_link_mode_t mode) 675 { 676 sfxge_mac_t *smp = &(sp->s_mac); 677 678 mutex_enter(&(smp->sm_lock)); 679 sfxge_mac_link_update_locked(sp, mode); 680 mutex_exit(&(smp->sm_lock)); 681 } 682 683 void 684 sfxge_mac_link_check(sfxge_t *sp, boolean_t *upp) 685 { 686 sfxge_mac_t *smp = &(sp->s_mac); 687 688 mutex_enter(&(smp->sm_lock)); 689 *upp = smp->sm_link_up; 690 mutex_exit(&(smp->sm_lock)); 691 } 692 693 void 694 sfxge_mac_link_speed_get(sfxge_t *sp, unsigned int *speedp) 695 { 696 sfxge_mac_t *smp = &(sp->s_mac); 697 698 mutex_enter(&(smp->sm_lock)); 699 *speedp = smp->sm_link_speed; 700 mutex_exit(&(smp->sm_lock)); 701 } 702 703 void 704 sfxge_mac_link_duplex_get(sfxge_t *sp, sfxge_link_duplex_t *duplexp) 705 { 706 sfxge_mac_t *smp = &(sp->s_mac); 707 708 mutex_enter(&(smp->sm_lock)); 709 *duplexp = smp->sm_link_duplex; 710 mutex_exit(&(smp->sm_lock)); 711 } 712 713 void 714 sfxge_mac_fcntl_get(sfxge_t *sp, unsigned int *fcntlp) 715 { 716 sfxge_mac_t *smp = &(sp->s_mac); 717 718 mutex_enter(&(smp->sm_lock)); 719 *fcntlp = smp->sm_fcntl; 720 mutex_exit(&(smp->sm_lock)); 721 } 722 723 int 724 sfxge_mac_fcntl_set(sfxge_t *sp, unsigned int fcntl) 725 { 726 sfxge_mac_t *smp = &(sp->s_mac); 727 int rc; 728 729 mutex_enter(&(smp->sm_lock)); 730 731 if (smp->sm_fcntl == fcntl) 732 goto done; 733 734 smp->sm_fcntl = fcntl; 735 736 if (smp->sm_state != SFXGE_MAC_STARTED) 737 goto done; 738 739 if ((rc = efx_mac_fcntl_set(sp->s_enp, smp->sm_fcntl, B_TRUE)) != 0) 740 goto fail1; 741 742 done: 743 mutex_exit(&(smp->sm_lock)); 744 745 return (0); 746 747 fail1: 748 DTRACE_PROBE1(fail1, int, rc); 749 750 mutex_exit(&(smp->sm_lock)); 751 752 return (rc); 753 } 754 755 int 756 sfxge_mac_unicst_get(sfxge_t *sp, sfxge_unicst_type_t type, uint8_t *addr) 757 { 758 sfxge_mac_t *smp = &(sp->s_mac); 759 int rc; 760 761 if (type >= SFXGE_UNICST_NTYPES) { 762 rc = EINVAL; 763 goto fail1; 764 } 765 766 mutex_enter(&(smp->sm_lock)); 767 768 if (smp->sm_state != SFXGE_MAC_INITIALIZED && 769 smp->sm_state != SFXGE_MAC_STARTED) { 770 rc = EFAULT; 771 goto fail2; 772 } 773 774 switch (type) { 775 case SFXGE_UNICST_BIA: 776 bcopy(smp->sm_bia, addr, ETHERADDRL); 777 break; 778 779 case SFXGE_UNICST_LAA: 780 if (!(smp->sm_laa_valid)) { 781 rc = ENOENT; 782 goto fail3; 783 } 784 785 bcopy(smp->sm_laa, addr, ETHERADDRL); 786 break; 787 788 default: 789 ASSERT(B_FALSE); 790 break; 791 } 792 793 mutex_exit(&(smp->sm_lock)); 794 795 return (0); 796 797 798 fail3: 799 DTRACE_PROBE(fail3); 800 fail2: 801 DTRACE_PROBE(fail2); 802 803 mutex_exit(&(smp->sm_lock)); 804 805 fail1: 806 DTRACE_PROBE1(fail1, int, rc); 807 808 return (rc); 809 } 810 811 int 812 sfxge_mac_unicst_set(sfxge_t *sp, uint8_t *addr) 813 { 814 sfxge_mac_t *smp = &(sp->s_mac); 815 efx_nic_t *enp = sp->s_enp; 816 int rc; 817 818 mutex_enter(&(smp->sm_lock)); 819 820 bcopy(addr, smp->sm_laa, ETHERADDRL); 821 smp->sm_laa_valid = B_TRUE; 822 823 if (smp->sm_state != SFXGE_MAC_STARTED) 824 goto done; 825 826 if ((rc = efx_mac_addr_set(enp, smp->sm_laa)) != 0) 827 goto fail1; 828 829 done: 830 mutex_exit(&(smp->sm_lock)); 831 832 return (0); 833 834 fail1: 835 DTRACE_PROBE1(fail1, int, rc); 836 837 mutex_exit(&(smp->sm_lock)); 838 839 return (rc); 840 } 841 842 int 843 sfxge_mac_promisc_set(sfxge_t *sp, sfxge_promisc_type_t promisc) 844 { 845 sfxge_mac_t *smp = &(sp->s_mac); 846 int rc; 847 848 mutex_enter(&(smp->sm_lock)); 849 850 if (smp->sm_promisc == promisc) 851 goto done; 852 853 smp->sm_promisc = promisc; 854 855 if ((rc = sfxge_mac_filter_apply(sp)) != 0) 856 goto fail1; 857 858 done: 859 mutex_exit(&(smp->sm_lock)); 860 return (0); 861 862 fail1: 863 DTRACE_PROBE1(fail1, int, rc); 864 mutex_exit(&(smp->sm_lock)); 865 866 return (rc); 867 } 868 869 int 870 sfxge_mac_multicst_add(sfxge_t *sp, const uint8_t *addr) 871 { 872 sfxge_mac_t *smp = &(sp->s_mac); 873 int i; 874 int rc; 875 876 mutex_enter(&(smp->sm_lock)); 877 878 /* Check if the address is already in the list */ 879 i = 0; 880 while (i < smp->sm_mcast_count) { 881 if (bcmp(smp->sm_mcast_addr + (i * ETHERADDRL), 882 addr, ETHERADDRL) == 0) 883 goto done; 884 else 885 i++; 886 } 887 888 /* Add to the list */ 889 bcopy(addr, smp->sm_mcast_addr + (smp->sm_mcast_count++ * ETHERADDRL), 890 ETHERADDRL); 891 892 if ((rc = sfxge_mac_filter_apply(sp)) != 0) 893 goto fail1; 894 895 done: 896 mutex_exit(&(smp->sm_lock)); 897 return (0); 898 899 fail1: 900 DTRACE_PROBE1(fail1, int, rc); 901 mutex_exit(&(smp->sm_lock)); 902 903 return (rc); 904 } 905 906 int 907 sfxge_mac_multicst_remove(sfxge_t *sp, const uint8_t *addr) 908 { 909 sfxge_mac_t *smp = &(sp->s_mac); 910 int i; 911 int rc; 912 913 mutex_enter(&(smp->sm_lock)); 914 915 i = 0; 916 while (i < smp->sm_mcast_count) { 917 if (bcmp(smp->sm_mcast_addr + (i * ETHERADDRL), 918 addr, ETHERADDRL) == 0) { 919 (void) memmove(smp->sm_mcast_addr + (i * ETHERADDRL), 920 smp->sm_mcast_addr + ((i + 1) * ETHERADDRL), 921 (smp->sm_mcast_count - (i + 1)) * ETHERADDRL); 922 smp->sm_mcast_count--; 923 } else 924 i++; 925 } 926 927 if ((rc = sfxge_mac_filter_apply(sp)) != 0) 928 goto fail1; 929 930 mutex_exit(&(smp->sm_lock)); 931 return (0); 932 933 fail1: 934 DTRACE_PROBE1(fail1, int, rc); 935 mutex_exit(&(smp->sm_lock)); 936 937 return (rc); 938 } 939 940 void 941 sfxge_mac_stop(sfxge_t *sp) 942 { 943 sfxge_mac_t *smp = &(sp->s_mac); 944 efx_nic_t *enp = sp->s_enp; 945 efsys_mem_t *esmp = &(smp->sm_mem); 946 947 mutex_enter(&(smp->sm_lock)); 948 949 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_STARTED); 950 ASSERT3P(smp->sm_sp, ==, sp); 951 smp->sm_state = SFXGE_MAC_INITIALIZED; 952 953 /* If stopping in response to an MC reboot this may fail */ 954 if (!smp->sm_mac_stats_timer_reqd) 955 (void) efx_mac_stats_periodic(enp, esmp, 0, B_FALSE); 956 957 sfxge_mac_poll_stop(sp); 958 959 smp->sm_lbolt = 0; 960 961 smp->sm_link_up = B_FALSE; 962 smp->sm_link_speed = 0; 963 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_UNKNOWN; 964 965 /* This may call MCDI */ 966 (void) efx_mac_drain(enp, B_TRUE); 967 968 smp->sm_link_mode = EFX_LINK_UNKNOWN; 969 970 efx_port_fini(enp); 971 972 mutex_exit(&(smp->sm_lock)); 973 } 974 975 void 976 sfxge_mac_fini(sfxge_t *sp) 977 { 978 sfxge_mac_t *smp = &(sp->s_mac); 979 efsys_mem_t *esmp = &(smp->sm_mem); 980 981 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_INITIALIZED); 982 ASSERT3P(smp->sm_sp, ==, sp); 983 984 /* Tear down the statistics */ 985 sfxge_phy_kstat_fini(sp); 986 sfxge_mac_kstat_fini(sp); 987 988 smp->sm_state = SFXGE_MAC_UNINITIALIZED; 989 smp->sm_link_mode = EFX_LINK_UNKNOWN; 990 smp->sm_promisc = SFXGE_PROMISC_OFF; 991 992 bzero(smp->sm_mcast_addr, SFXGE_MCAST_LIST_MAX * ETHERADDRL); 993 smp->sm_mcast_count = 0; 994 995 bzero(smp->sm_laa, ETHERADDRL); 996 smp->sm_laa_valid = B_FALSE; 997 998 bzero(smp->sm_bia, ETHERADDRL); 999 1000 smp->sm_fcntl = 0; 1001 1002 /* Finish with PHY DMA memory */ 1003 sfxge_phy_fini(sp); 1004 1005 /* Teardown the DMA */ 1006 sfxge_dma_buffer_destroy(esmp); 1007 1008 /* Destroy the link poll taskq */ 1009 ddi_taskq_destroy(smp->sm_tqp); 1010 smp->sm_tqp = NULL; 1011 1012 mutex_destroy(&(smp->sm_lock)); 1013 1014 smp->sm_sp = NULL; 1015 1016 SFXGE_OBJ_CHECK(smp, sfxge_mac_t); 1017 }