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