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 #ifdef _USE_GLD_V3 28 29 #include <sys/types.h> 30 #include <sys/ddi.h> 31 #include <sys/sunddi.h> 32 #include <sys/stream.h> 33 #include <sys/strsun.h> 34 #include <sys/strsubr.h> 35 #include <sys/dlpi.h> 36 #ifndef _USE_GLD_V3_SOL10 37 #include <sys/dld.h> 38 #endif 39 #include <sys/ksynch.h> 40 #include <sys/cpuvar.h> 41 #include <sys/cpu.h> 42 43 #include <inet/tcp.h> 44 45 #include "sfxge.h" 46 47 #ifndef MAC_VERSION_V1 48 /* GLDv3 interface version for sol10 (u8/u9) */ 49 #define MAC_VERSION_V1 MAC_VERSION 50 #endif 51 52 /* A vlan tag is 4 bytes */ 53 #define SFXGE_VLAN_TAGSZ 4 54 55 void 56 sfxge_gld_link_update(sfxge_t *sp) 57 { 58 sfxge_mac_t *smp = &(sp->s_mac); 59 link_state_t link; 60 61 switch (smp->sm_link_mode) { 62 case EFX_LINK_UNKNOWN: 63 link = LINK_STATE_UNKNOWN; 64 break; 65 case EFX_LINK_DOWN: 66 link = LINK_STATE_DOWN; 67 break; 68 default: 69 link = LINK_STATE_UP; 70 } 71 72 mac_link_update(sp->s_mh, link); 73 } 74 75 void 76 sfxge_gld_mtu_update(sfxge_t *sp) 77 { 78 #ifdef _USE_MTU_UPDATE 79 (void) mac_maxsdu_update(sp->s_mh, sp->s_mtu); 80 #endif 81 } 82 83 void 84 sfxge_gld_rx_post(sfxge_t *sp, unsigned int index, mblk_t *mp) 85 { 86 _NOTE(ARGUNUSED(index)) 87 88 mac_rx(sp->s_mh, NULL, mp); 89 } 90 91 92 void 93 sfxge_gld_rx_push(sfxge_t *sp) 94 { 95 _NOTE(ARGUNUSED(sp)) 96 } 97 98 99 static uint64_t 100 sfxge_phy_dfl_cap_test64(sfxge_t *sp, uint32_t field) 101 { 102 return (sfxge_phy_cap_test(sp, EFX_PHY_CAP_DEFAULT, field, NULL) ? 103 1ull : 0ull); 104 } 105 106 107 static uint64_t 108 sfxge_phy_cur_cap_test64(sfxge_t *sp, uint32_t field) 109 { 110 return (sfxge_phy_cap_test(sp, EFX_PHY_CAP_CURRENT, field, NULL) ? 111 1ull : 0ull); 112 } 113 114 static uint64_t 115 sfxge_phy_lp_cap_test64(sfxge_t *sp, uint32_t field) 116 { 117 return (sfxge_phy_lp_cap_test(sp, field) ? 1ull : 0ull); 118 } 119 120 static int 121 sfxge_gld_getstat(void *arg, unsigned int id, uint64_t *valp) 122 { 123 sfxge_t *sp = arg; 124 efx_nic_t *enp = sp->s_enp; 125 int rc; 126 127 if (sp->s_mac.sm_state != SFXGE_MAC_STARTED) { 128 rc = ENODEV; 129 goto fail1; 130 } 131 132 switch (id) { 133 case MAC_STAT_IFSPEED: { 134 unsigned int speed; 135 136 sfxge_mac_link_speed_get(sp, &speed); 137 138 *valp = (uint64_t)speed * 1000000ull; 139 break; 140 } 141 case ETHER_STAT_LINK_DUPLEX: { 142 sfxge_link_duplex_t duplex; 143 144 sfxge_mac_link_duplex_get(sp, &duplex); 145 146 switch (duplex) { 147 case SFXGE_LINK_DUPLEX_UNKNOWN: 148 *valp = LINK_DUPLEX_UNKNOWN; 149 break; 150 151 case SFXGE_LINK_DUPLEX_HALF: 152 *valp = LINK_DUPLEX_HALF; 153 break; 154 155 case SFXGE_LINK_DUPLEX_FULL: 156 *valp = LINK_DUPLEX_FULL; 157 break; 158 159 default: 160 ASSERT(B_FALSE); 161 break; 162 } 163 break; 164 } 165 166 #ifdef ETHER_STAT_CAP_10GFDX 167 case ETHER_STAT_CAP_10GFDX: 168 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_10000FDX); 169 break; 170 #endif 171 case ETHER_STAT_CAP_1000FDX: 172 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_1000FDX); 173 break; 174 case ETHER_STAT_CAP_1000HDX: 175 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_1000HDX); 176 break; 177 case ETHER_STAT_CAP_100FDX: 178 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_100FDX); 179 break; 180 case ETHER_STAT_CAP_100HDX: 181 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_100HDX); 182 break; 183 case ETHER_STAT_CAP_10FDX: 184 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_10FDX); 185 break; 186 case ETHER_STAT_CAP_10HDX: 187 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_10HDX); 188 break; 189 case ETHER_STAT_CAP_ASMPAUSE: 190 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_ASYM); 191 break; 192 case ETHER_STAT_CAP_PAUSE: 193 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_PAUSE); 194 break; 195 case ETHER_STAT_CAP_AUTONEG: 196 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_AN); 197 break; 198 199 #ifdef ETHER_STAT_ADV_CAP_10GFDX 200 case ETHER_STAT_ADV_CAP_10GFDX: 201 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_10000FDX); 202 break; 203 #endif 204 case ETHER_STAT_ADV_CAP_1000FDX: 205 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_1000FDX); 206 break; 207 case ETHER_STAT_ADV_CAP_1000HDX: 208 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_1000HDX); 209 break; 210 case ETHER_STAT_ADV_CAP_100FDX: 211 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_100FDX); 212 break; 213 case ETHER_STAT_ADV_CAP_100HDX: 214 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_100HDX); 215 break; 216 case ETHER_STAT_ADV_CAP_10FDX: 217 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_10FDX); 218 break; 219 case ETHER_STAT_ADV_CAP_10HDX: 220 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_10HDX); 221 break; 222 case ETHER_STAT_ADV_CAP_ASMPAUSE: 223 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_ASYM); 224 break; 225 case ETHER_STAT_ADV_CAP_PAUSE: 226 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_PAUSE); 227 break; 228 case ETHER_STAT_ADV_CAP_AUTONEG: 229 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_AN); 230 break; 231 232 #ifdef ETHER_STAT_LP_CAP_10GFDX 233 case ETHER_STAT_LP_CAP_10GFDX: 234 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_10000FDX); 235 break; 236 #endif 237 case ETHER_STAT_LP_CAP_1000FDX: 238 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_1000FDX); 239 break; 240 case ETHER_STAT_LP_CAP_1000HDX: 241 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_1000HDX); 242 break; 243 case ETHER_STAT_LP_CAP_100FDX: 244 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_100FDX); 245 break; 246 case ETHER_STAT_LP_CAP_100HDX: 247 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_100HDX); 248 break; 249 case ETHER_STAT_LP_CAP_10FDX: 250 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_10FDX); 251 break; 252 case ETHER_STAT_LP_CAP_10HDX: 253 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_10HDX); 254 break; 255 case ETHER_STAT_LP_CAP_ASMPAUSE: 256 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_ASYM); 257 break; 258 case ETHER_STAT_LP_CAP_PAUSE: 259 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_PAUSE); 260 break; 261 case ETHER_STAT_LP_CAP_AUTONEG: 262 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_AN); 263 break; 264 265 case ETHER_STAT_XCVR_ADDR: { 266 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 267 *valp = encp->enc_port; 268 break; 269 } 270 case ETHER_STAT_XCVR_ID: { 271 uint32_t oui; 272 273 if ((rc = efx_phy_oui_get(sp->s_enp, &oui)) != 0) 274 goto fail2; 275 *valp = oui; 276 break; 277 } 278 case MAC_STAT_MULTIRCV: 279 sfxge_mac_stat_get(sp, EFX_MAC_RX_MULTICST_PKTS, valp); 280 break; 281 282 case MAC_STAT_BRDCSTRCV: 283 sfxge_mac_stat_get(sp, EFX_MAC_RX_BRDCST_PKTS, valp); 284 break; 285 286 case MAC_STAT_MULTIXMT: 287 sfxge_mac_stat_get(sp, EFX_MAC_TX_MULTICST_PKTS, valp); 288 break; 289 290 case MAC_STAT_BRDCSTXMT: 291 sfxge_mac_stat_get(sp, EFX_MAC_TX_BRDCST_PKTS, valp); 292 break; 293 294 case MAC_STAT_IERRORS: 295 sfxge_mac_stat_get(sp, EFX_MAC_RX_ERRORS, valp); 296 break; 297 298 case MAC_STAT_OERRORS: 299 sfxge_mac_stat_get(sp, EFX_MAC_TX_ERRORS, valp); 300 break; 301 302 case MAC_STAT_RBYTES: 303 sfxge_mac_stat_get(sp, EFX_MAC_RX_OCTETS, valp); 304 break; 305 306 case MAC_STAT_IPACKETS: 307 sfxge_mac_stat_get(sp, EFX_MAC_RX_PKTS, valp); 308 break; 309 310 case MAC_STAT_OBYTES: 311 sfxge_mac_stat_get(sp, EFX_MAC_TX_OCTETS, valp); 312 break; 313 314 case MAC_STAT_OPACKETS: 315 sfxge_mac_stat_get(sp, EFX_MAC_TX_PKTS, valp); 316 break; 317 318 case MAC_STAT_NORCVBUF: 319 sfxge_mac_stat_get(sp, EFX_MAC_RX_DROP_EVENTS, valp); 320 break; 321 322 case ETHER_STAT_FCS_ERRORS: 323 sfxge_mac_stat_get(sp, EFX_MAC_RX_FCS_ERRORS, valp); 324 break; 325 326 default: 327 rc = ENOTSUP; 328 goto fail3; 329 } 330 331 return (0); 332 fail3: 333 DTRACE_PROBE(fail3); 334 fail2: 335 DTRACE_PROBE(fail2); 336 fail1: 337 DTRACE_PROBE1(fail1, int, rc); 338 339 return (rc); 340 } 341 342 static int 343 sfxge_gld_start(void *arg) 344 { 345 sfxge_t *sp = arg; 346 int rc; 347 348 if ((rc = sfxge_start(sp, B_FALSE)) != 0) 349 goto fail1; 350 351 return (0); 352 353 fail1: 354 DTRACE_PROBE1(fail1, int, rc); 355 356 return (rc); 357 } 358 359 static void 360 sfxge_gld_stop(void *arg) 361 { 362 sfxge_t *sp = arg; 363 364 sfxge_stop(sp); 365 } 366 367 static int 368 sfxge_gld_setpromisc(void *arg, boolean_t on) 369 { 370 sfxge_t *sp = arg; 371 372 return sfxge_mac_promisc_set(sp, 373 (on) ? SFXGE_PROMISC_ALL_PHYS : SFXGE_PROMISC_OFF); 374 } 375 376 static int 377 sfxge_gld_multicst(void *arg, boolean_t add, const uint8_t *addr) 378 { 379 sfxge_t *sp = arg; 380 int rc; 381 382 if (add) { 383 if ((rc = sfxge_mac_multicst_add(sp, (uint8_t *)addr)) != 0) 384 goto fail1; 385 } else { 386 if ((rc = sfxge_mac_multicst_remove(sp, (uint8_t *)addr)) != 0) 387 goto fail2; 388 } 389 390 return (0); 391 392 fail2: 393 DTRACE_PROBE(fail2); 394 fail1: 395 DTRACE_PROBE1(fail1, int, rc); 396 return (rc); 397 } 398 399 static int 400 sfxge_gld_unicst(void *arg, const uint8_t *addr) 401 { 402 sfxge_t *sp = arg; 403 int rc; 404 405 if ((rc = sfxge_mac_unicst_set(sp, (uint8_t *)addr)) != 0) 406 goto fail1; 407 408 return (0); 409 410 fail1: 411 DTRACE_PROBE1(fail1, int, rc); 412 413 return (rc); 414 } 415 416 static void 417 sfxge_gld_ioctl(void *arg, queue_t *wq, mblk_t *mp) 418 { 419 sfxge_t *sp = arg; 420 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 421 422 switch (iocp->ioc_cmd) { 423 #ifdef _USE_NDD_PROPS 424 case ND_GET: 425 case ND_SET: 426 if (!nd_getset(wq, sp->s_ndh, mp)) 427 miocnak(wq, mp, 0, EINVAL); 428 else 429 qreply(wq, mp); 430 break; 431 #endif 432 433 default: 434 sfxge_ioctl(sp, wq, mp); 435 break; 436 } 437 } 438 439 440 static mblk_t * 441 sfxge_gld_tx(void *arg, mblk_t *mp) 442 { 443 sfxge_t *sp = arg; 444 mblk_t *next; 445 446 /* Walk the packet chain */ 447 do { 448 /* Break the packet out of the chain */ 449 next = mp->b_next; 450 mp->b_next = NULL; 451 452 if (next != NULL) 453 prefetch_read_many(next); 454 455 /* Post the packet in the appropriate transmit queue */ 456 if (sfxge_tx_packet_add(sp, mp) == ENOSPC) { 457 mp->b_next = next; 458 return (mp); 459 } 460 461 mp = next; 462 } while (mp != NULL); 463 464 return (NULL); 465 } 466 467 static boolean_t sfxge_lso = B_TRUE; 468 469 static boolean_t 470 sfxge_gld_getcapab(void *arg, mac_capab_t cap, void *cap_arg) 471 { 472 int rc; 473 474 _NOTE(ARGUNUSED(arg)) 475 476 switch (cap) { 477 case MAC_CAPAB_LSO: { 478 mac_capab_lso_t *lsop = cap_arg; 479 480 /* Check whether LSO is disabled */ 481 if (!sfxge_lso) { 482 rc = ENOTSUP; 483 goto fail1; 484 } 485 486 DTRACE_PROBE(lso); 487 488 lsop->lso_flags = LSO_TX_BASIC_TCP_IPV4; 489 lsop->lso_basic_tcp_ipv4.lso_max = TCP_MAX_LSO_LENGTH; 490 break; 491 } 492 case MAC_CAPAB_HCKSUM: { 493 uint32_t *hcksump = cap_arg; 494 495 DTRACE_PROBE(cksum); 496 497 *hcksump = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM; 498 break; 499 } 500 default: 501 rc = ENOTSUP; 502 goto fail1; 503 } 504 505 return (B_TRUE); 506 507 fail1: 508 DTRACE_PROBE1(fail1, int, rc); 509 510 return (B_FALSE); 511 } 512 513 #ifdef _USE_MAC_PRIV_PROP 514 515 /* 516 * GLDv3 driver-private property names must be preceded by an underscore - see 517 * mc_getprop(9E). 518 */ 519 #define SFXGE_PRIV_PROP_NAME(s) ("_" #s) 520 521 /* Return the index of the named phy property. Return -1 if not found. */ 522 static int 523 sfxge_gld_priv_prop_phy_find(sfxge_t *sp, const char *name) 524 { 525 efx_nic_t *enp = sp->s_enp; 526 sfxge_mac_priv_prop_t *mac_priv_props; 527 unsigned int id; 528 unsigned int nprops; 529 530 mac_priv_props = sp->s_mac_priv_props; 531 nprops = efx_nic_cfg_get(enp)->enc_phy_nprops; 532 533 for (id = 0; id < nprops; id++) { 534 if (strncmp(name, *mac_priv_props, MAXLINKPROPNAME) == 0) 535 return (id); 536 mac_priv_props++; 537 } 538 return (-1); 539 } 540 541 #define SFXGE_XSTR(s) SFXGE_STR(s) 542 #define SFXGE_STR(s) #s 543 544 static void 545 sfxge_gld_priv_prop_info(sfxge_t *sp, const char *name, 546 mac_prop_info_handle_t handle) 547 { 548 /* 549 * Using mac_prop_info_set_default_str rather than the the corresponding 550 * mac_prop_info_set_default_uint32 etc as it gives readable output in 551 * "dladm show-linkprop" commands for private properties. Note this does 552 * not break "dladm reset-linkprop" as might have been expected. 553 */ 554 /* Treat all the phy properties the same */ 555 if (sfxge_gld_priv_prop_phy_find(sp, name) > 0) { 556 mac_prop_info_set_default_str(handle, "0"); 557 mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW); 558 return; 559 } 560 561 if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_coalesce_mode)) == 0) { 562 mac_prop_info_set_default_str(handle, 563 SFXGE_XSTR(SFXGE_RX_COALESCE_OFF)); 564 mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW); 565 return; 566 } 567 568 if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_scale_count)) == 0) { 569 mac_prop_info_set_default_str(handle, 570 SFXGE_XSTR(SFXGE_RX_SCALE_MAX)); 571 mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW); 572 return; 573 } 574 575 if (strcmp(name, SFXGE_PRIV_PROP_NAME(intr_moderation)) == 0) { 576 mac_prop_info_set_default_str(handle, 577 SFXGE_XSTR(SFXGE_DEFAULT_MODERATION)); 578 mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW); 579 return; 580 } 581 DTRACE_PROBE(unknown_priv_prop); 582 } 583 584 585 static int 586 sfxge_gld_priv_prop_get(sfxge_t *sp, const char *name, 587 unsigned int size, void *valp) 588 { 589 int id; 590 long val; 591 int rc; 592 593 if ((id = sfxge_gld_priv_prop_phy_find(sp, name)) > 0) { 594 if ((rc = sfxge_phy_prop_get(sp, id, 0, (uint32_t *)&val)) != 0) 595 goto fail1; 596 goto done; 597 } 598 599 if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_coalesce_mode)) == 0) { 600 sfxge_rx_coalesce_mode_t mode; 601 602 sfxge_rx_coalesce_mode_get(sp, &mode); 603 604 val = (long)mode; 605 goto done; 606 } 607 608 if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_scale_count)) == 0) { 609 unsigned int count; 610 611 if (sfxge_rx_scale_count_get(sp, &count) != 0) 612 count = 0; 613 614 val = (long)count; 615 goto done; 616 } 617 618 if (strcmp(name, SFXGE_PRIV_PROP_NAME(intr_moderation)) == 0) { 619 unsigned int us; 620 621 sfxge_ev_moderation_get(sp, &us); 622 623 val = (long)us; 624 goto done; 625 } 626 627 rc = ENOTSUP; 628 goto fail2; 629 630 done: 631 (void) snprintf(valp, size, "%ld", val); 632 633 return (0); 634 635 fail2: 636 DTRACE_PROBE(fail2); 637 638 fail1: 639 DTRACE_PROBE1(fail1, int, rc); 640 641 return (rc); 642 } 643 644 645 static int 646 sfxge_gld_priv_prop_set(sfxge_t *sp, const char *name, unsigned int size, 647 const void *valp) 648 { 649 int id; 650 long val; 651 int rc = 0; 652 653 _NOTE(ARGUNUSED(size)) 654 655 (void) ddi_strtol(valp, (char **)NULL, 0, &val); 656 657 if ((id = sfxge_gld_priv_prop_phy_find(sp, name)) > 0) { 658 if ((rc = sfxge_phy_prop_set(sp, id, (uint32_t)val)) != 0) 659 goto fail1; 660 goto done; 661 } 662 663 664 if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_coalesce_mode)) == 0) { 665 if ((rc = sfxge_rx_coalesce_mode_set(sp, 666 (sfxge_rx_coalesce_mode_t)val)) != 0) 667 goto fail1; 668 669 goto done; 670 } 671 672 if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_scale_count)) == 0) { 673 if ((rc = sfxge_rx_scale_count_set(sp, (unsigned int)val)) != 0) 674 goto fail1; 675 676 goto done; 677 } 678 679 if (strcmp(name, SFXGE_PRIV_PROP_NAME(intr_moderation)) == 0) { 680 if ((rc = sfxge_ev_moderation_set(sp, (unsigned int) val) != 0)) 681 goto fail1; 682 683 goto done; 684 } 685 686 rc = ENOTSUP; 687 goto fail1; 688 689 done: 690 return (0); 691 692 fail1: 693 DTRACE_PROBE1(fail1, int, rc); 694 695 return (rc); 696 } 697 698 /* 699 * The renaming of properties is necessary as efx_phy_prop_name needs to be 700 * called after efx_port_init(). See bug 18074 and sfxge_phy.c for notes on the 701 * locking strategy. 702 */ 703 void 704 sfxge_gld_priv_prop_rename(sfxge_t *sp) 705 { 706 sfxge_mac_t *smp = &(sp->s_mac); 707 sfxge_mac_priv_prop_t *mac_priv_props = sp->s_mac_priv_props; 708 efx_nic_t *enp = sp->s_enp; 709 unsigned int nprops; 710 int id; 711 712 ASSERT(mutex_owned(&(smp->sm_lock))); 713 714 nprops = efx_nic_cfg_get(enp)->enc_phy_nprops; 715 716 for (id = 0; id < nprops; id++) { 717 (void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1, "_%s", 718 efx_phy_prop_name(enp, id)); 719 mac_priv_props++; 720 } 721 } 722 723 724 static void 725 sfxge_gld_priv_prop_init(sfxge_t *sp) 726 { 727 efx_nic_t *enp = sp->s_enp; 728 sfxge_mac_priv_prop_t *mac_priv_props; 729 unsigned int nprops; 730 unsigned int id; 731 int nnamed_props = 3; 732 733 nprops = efx_nic_cfg_get(enp)->enc_phy_nprops; 734 735 /* 736 * We have nprops phy properties, nnamed_props (3) named properties and 737 * the structure must be finished by a NULL pointer. 738 */ 739 sp->s_mac_priv_props_alloc = nprops + nnamed_props + 1; 740 sp->s_mac_priv_props = kmem_zalloc(sizeof (sfxge_mac_priv_prop_t) * 741 sp->s_mac_priv_props_alloc, 742 KM_SLEEP); 743 744 /* 745 * Driver-private property names start with an underscore - see 746 * mc_getprop(9E). Phy property names are only available later - see 747 * bug 18074. Siena does not have these phy properties. 748 */ 749 750 mac_priv_props = sp->s_mac_priv_props; 751 for (id = 0; id < nprops; id++) { 752 *mac_priv_props = kmem_zalloc(MAXLINKPROPNAME, KM_SLEEP); 753 (void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1, 754 SFXGE_PRIV_PROP_NAME(phyprop%d), id); 755 mac_priv_props++; 756 } 757 758 *mac_priv_props = kmem_zalloc(MAXLINKPROPNAME, KM_SLEEP); 759 (void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1, 760 SFXGE_PRIV_PROP_NAME(rx_coalesce_mode)); 761 mac_priv_props++; 762 nprops++; 763 764 *mac_priv_props = kmem_zalloc(MAXLINKPROPNAME, KM_SLEEP); 765 (void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1, 766 SFXGE_PRIV_PROP_NAME(rx_scale_count)); 767 mac_priv_props++; 768 nprops++; 769 770 *mac_priv_props = kmem_zalloc(MAXLINKPROPNAME, KM_SLEEP); 771 (void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1, 772 SFXGE_PRIV_PROP_NAME(intr_moderation)); 773 mac_priv_props++; 774 nprops++; 775 776 ASSERT3U((nprops + 1), ==, sp->s_mac_priv_props_alloc); 777 778 /* Terminated by a NULL pointer */ 779 *mac_priv_props = NULL; 780 } 781 782 783 static void 784 sfxge_gld_priv_prop_fini(sfxge_t *sp) 785 { 786 efx_nic_t *enp = sp->s_enp; 787 unsigned int nprops; 788 char **mac_priv_props; 789 unsigned int id; 790 791 nprops = efx_nic_cfg_get(enp)->enc_phy_nprops; 792 mac_priv_props = sp->s_mac_priv_props; 793 794 for (id = 0; id < nprops + 3; id++) { 795 kmem_free(*mac_priv_props, MAXLINKPROPNAME); 796 mac_priv_props++; 797 } 798 799 kmem_free(sp->s_mac_priv_props, sizeof (sfxge_mac_priv_prop_t) * 800 sp->s_mac_priv_props_alloc); 801 sp->s_mac_priv_props = NULL; 802 } 803 #endif /* _USE_MAC_PRIV_PROP */ 804 805 806 #ifdef _USE_GLD_V3_PROPS 807 static int 808 sfxge_gld_getprop(void *arg, const char *name, mac_prop_id_t id, 809 unsigned int size, void *valp) 810 { 811 sfxge_t *sp = arg; 812 uint32_t flag = EFX_PHY_CAP_CURRENT; 813 uint8_t *v8 = ((uint8_t *)valp); 814 int rc; 815 816 /* check size */ 817 switch (id) { 818 case MAC_PROP_DUPLEX: 819 if (size < sizeof (link_duplex_t)) { 820 rc = EINVAL; 821 goto fail1; 822 } 823 break; 824 case MAC_PROP_FLOWCTRL: 825 if (size < sizeof (link_flowctrl_t)) { 826 rc = EINVAL; 827 goto fail1; 828 } 829 break; 830 case MAC_PROP_SPEED: 831 case MAC_PROP_STATUS: 832 if (size < sizeof (uint64_t)) { 833 rc = EINVAL; 834 goto fail1; 835 } 836 break; 837 case MAC_PROP_MTU: 838 if (size < sizeof (uint32_t)) { 839 rc = EINVAL; 840 goto fail1; 841 } 842 break; 843 case MAC_PROP_EN_AUTONEG: 844 case MAC_PROP_AUTONEG: 845 case MAC_PROP_EN_10GFDX_CAP: 846 case MAC_PROP_ADV_10GFDX_CAP: 847 case MAC_PROP_EN_1000FDX_CAP: 848 case MAC_PROP_ADV_1000FDX_CAP: 849 case MAC_PROP_EN_1000HDX_CAP: 850 case MAC_PROP_ADV_1000HDX_CAP: 851 case MAC_PROP_EN_100FDX_CAP: 852 case MAC_PROP_ADV_100FDX_CAP: 853 case MAC_PROP_EN_100HDX_CAP: 854 case MAC_PROP_ADV_100HDX_CAP: 855 case MAC_PROP_EN_10FDX_CAP: 856 case MAC_PROP_ADV_10FDX_CAP: 857 case MAC_PROP_EN_10HDX_CAP: 858 case MAC_PROP_ADV_10HDX_CAP: 859 if (size < sizeof (uint8_t)) { 860 rc = EINVAL; 861 goto fail1; 862 } 863 break; 864 #ifdef _USE_MAC_PRIV_PROP 865 case MAC_PROP_PRIVATE: 866 /* sfxge_gld_priv_prop_get should do any size checking */ 867 break; 868 #endif 869 default: 870 rc = ENOTSUP; 871 goto fail1; 872 break; 873 } 874 875 switch (id) { 876 case MAC_PROP_DUPLEX: { 877 sfxge_link_duplex_t duplex; 878 879 sfxge_mac_link_duplex_get(sp, &duplex); 880 881 switch (duplex) { 882 case SFXGE_LINK_DUPLEX_UNKNOWN: 883 *((link_duplex_t *)valp) = LINK_DUPLEX_UNKNOWN; 884 break; 885 886 case SFXGE_LINK_DUPLEX_HALF: 887 *((link_duplex_t *)valp) = LINK_DUPLEX_HALF; 888 break; 889 890 case SFXGE_LINK_DUPLEX_FULL: 891 *((link_duplex_t *)valp) = LINK_DUPLEX_FULL; 892 break; 893 894 default: 895 ASSERT(B_FALSE); 896 break; 897 } 898 899 break; 900 } 901 case MAC_PROP_SPEED: { 902 unsigned int speed; 903 904 sfxge_mac_link_speed_get(sp, &speed); 905 906 *((uint64_t *)valp) = (uint64_t)speed * 1000000ull; 907 908 break; 909 } 910 case MAC_PROP_STATUS: { 911 boolean_t up; 912 913 sfxge_mac_link_check(sp, &up); 914 915 *((link_state_t *)valp) = (up) ? 916 LINK_STATE_UP : LINK_STATE_DOWN; 917 918 break; 919 } 920 case MAC_PROP_EN_AUTONEG: 921 case MAC_PROP_AUTONEG: 922 *v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_AN, NULL); 923 break; 924 case MAC_PROP_EN_10GFDX_CAP: 925 case MAC_PROP_ADV_10GFDX_CAP: 926 *v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_10000FDX, NULL); 927 break; 928 case MAC_PROP_EN_1000FDX_CAP: 929 case MAC_PROP_ADV_1000FDX_CAP: 930 *v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_1000FDX, NULL); 931 break; 932 case MAC_PROP_EN_1000HDX_CAP: 933 case MAC_PROP_ADV_1000HDX_CAP: 934 *v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_1000HDX, NULL); 935 break; 936 case MAC_PROP_EN_100FDX_CAP: 937 case MAC_PROP_ADV_100FDX_CAP: 938 *v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_100FDX, NULL); 939 break; 940 case MAC_PROP_EN_100HDX_CAP: 941 case MAC_PROP_ADV_100HDX_CAP: 942 *v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_100HDX, NULL); 943 break; 944 case MAC_PROP_EN_10FDX_CAP: 945 case MAC_PROP_ADV_10FDX_CAP: 946 *v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_10FDX, NULL); 947 break; 948 case MAC_PROP_EN_10HDX_CAP: 949 case MAC_PROP_ADV_10HDX_CAP: 950 *v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_10HDX, NULL); 951 break; 952 case MAC_PROP_MTU: 953 *((uint32_t *)valp) = (uint32_t)(sp->s_mtu); 954 break; 955 956 case MAC_PROP_FLOWCTRL: { 957 unsigned int fcntl; 958 959 sfxge_mac_fcntl_get(sp, &fcntl); 960 961 switch (fcntl) { 962 case 0: 963 *((link_flowctrl_t *)valp) = LINK_FLOWCTRL_NONE; 964 break; 965 966 case EFX_FCNTL_GENERATE: 967 *((link_flowctrl_t *)valp) = LINK_FLOWCTRL_RX; 968 break; 969 970 case EFX_FCNTL_RESPOND: 971 *((link_flowctrl_t *)valp) = LINK_FLOWCTRL_TX; 972 break; 973 974 case (EFX_FCNTL_GENERATE | EFX_FCNTL_RESPOND): 975 *((link_flowctrl_t *)valp) = LINK_FLOWCTRL_BI; 976 break; 977 978 default: 979 ASSERT(B_FALSE); 980 break; 981 } 982 break; 983 } 984 #ifdef _USE_MAC_PRIV_PROP 985 case MAC_PROP_PRIVATE: 986 if ((rc = sfxge_gld_priv_prop_get(sp, name, size, valp)) != 0) 987 goto fail2; 988 break; 989 #endif 990 default: 991 rc = ENOTSUP; 992 goto fail3; 993 break; 994 } 995 996 return (0); 997 998 fail3: 999 DTRACE_PROBE(fail3); 1000 1001 #ifdef _USE_MAC_PRIV_PROP 1002 fail2: 1003 DTRACE_PROBE(fail2); 1004 #endif 1005 1006 fail1: 1007 DTRACE_PROBE1(fail1, int, rc); 1008 1009 return (rc); 1010 } 1011 #endif 1012 1013 1014 #ifdef _USE_GLD_V3_PROPS 1015 static int 1016 sfxge_gld_setprop(void *arg, const char *name, mac_prop_id_t id, 1017 unsigned int size, const void *valp) 1018 { 1019 sfxge_t *sp = arg; 1020 int v8 = *(uint8_t *)valp; 1021 int rc; 1022 1023 /* get size checks out fo the way */ 1024 switch (id) { 1025 /* 1026 * On Sol11 (no updates) dladm seems to be using MAC_PROP_AUTONEG to set 1027 * the autoneg parameter. This does not match the scheme suggested in 1028 * mac(9E) but as they both map to the same think in the driver and in 1029 * dladm it doesn't matter. 1030 */ 1031 case MAC_PROP_AUTONEG: 1032 case MAC_PROP_EN_AUTONEG: 1033 case MAC_PROP_EN_10GFDX_CAP: 1034 case MAC_PROP_EN_1000FDX_CAP: 1035 case MAC_PROP_EN_1000HDX_CAP: 1036 case MAC_PROP_EN_100FDX_CAP: 1037 case MAC_PROP_EN_100HDX_CAP: 1038 case MAC_PROP_EN_10FDX_CAP: 1039 case MAC_PROP_EN_10HDX_CAP: 1040 if (size < sizeof (uint8_t)) { 1041 rc = EINVAL; 1042 goto fail1; 1043 } 1044 break; 1045 case MAC_PROP_MTU: 1046 if (size < sizeof (uint32_t)) { 1047 rc = EINVAL; 1048 goto fail1; 1049 } 1050 break; 1051 case MAC_PROP_FLOWCTRL: 1052 if (size < sizeof (link_flowctrl_t)) { 1053 rc = EINVAL; 1054 goto fail1; 1055 } 1056 break; 1057 #ifdef _USE_MAC_PRIV_PROP 1058 case MAC_PROP_PRIVATE: 1059 /* sfxge_gld_priv_prop_set should do any size checking */ 1060 break; 1061 #endif 1062 default: 1063 rc = ENOTSUP; 1064 goto fail1; 1065 break; 1066 } 1067 1068 switch (id) { 1069 /* 1070 * It is unclear which of MAC_PROP_AUTONEG and MAC_PROP_EN_AUTONEG is 1071 * used. Try both. 1072 */ 1073 case MAC_PROP_AUTONEG: 1074 case MAC_PROP_EN_AUTONEG: 1075 if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_AN, v8)) != 0) 1076 goto fail2; 1077 break; 1078 case MAC_PROP_EN_10GFDX_CAP: { 1079 if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_10000FDX, v8)) != 0) 1080 goto fail2; 1081 break; 1082 } 1083 case MAC_PROP_EN_1000FDX_CAP: { 1084 if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_1000FDX, v8)) != 0) 1085 goto fail2; 1086 break; 1087 } 1088 case MAC_PROP_EN_1000HDX_CAP: { 1089 if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_1000HDX, v8)) != 0) 1090 goto fail2; 1091 break; 1092 } 1093 case MAC_PROP_EN_100FDX_CAP: { 1094 if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_100FDX, v8)) != 0) 1095 goto fail2; 1096 break; 1097 } 1098 case MAC_PROP_EN_100HDX_CAP: { 1099 if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_100HDX, v8)) != 0) 1100 goto fail2; 1101 break; 1102 } 1103 case MAC_PROP_EN_10FDX_CAP: { 1104 if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_10FDX, v8)) != 0) 1105 goto fail2; 1106 break; 1107 } 1108 case MAC_PROP_EN_10HDX_CAP: { 1109 if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_10HDX, v8)) != 0) 1110 goto fail2; 1111 break; 1112 } 1113 case MAC_PROP_MTU: { 1114 size_t mtu = (size_t)(*((uint32_t *)valp)); 1115 1116 if (mtu > EFX_MAC_SDU_MAX) { 1117 rc = EINVAL; 1118 goto fail2; 1119 } 1120 1121 sp->s_mtu = mtu; 1122 1123 DTRACE_PROBE(restart_mtu); 1124 (void) sfxge_restart_dispatch(sp, DDI_SLEEP, SFXGE_HW_OK, 1125 "MTU changing", (uint32_t)mtu); 1126 1127 break; 1128 } 1129 case MAC_PROP_FLOWCTRL: { 1130 unsigned int fcntl = 0; 1131 1132 switch (*((link_flowctrl_t *)valp)) { 1133 case LINK_FLOWCTRL_NONE: 1134 fcntl = 0; 1135 break; 1136 1137 case LINK_FLOWCTRL_RX: 1138 fcntl = EFX_FCNTL_GENERATE; 1139 break; 1140 1141 case LINK_FLOWCTRL_TX: 1142 fcntl = EFX_FCNTL_RESPOND; 1143 break; 1144 1145 case LINK_FLOWCTRL_BI: 1146 fcntl = EFX_FCNTL_GENERATE | EFX_FCNTL_RESPOND; 1147 break; 1148 1149 default: 1150 rc = EINVAL; 1151 goto fail2; 1152 break; 1153 } 1154 1155 if ((rc = sfxge_mac_fcntl_set(sp, fcntl)) != 0) 1156 goto fail3; 1157 1158 break; 1159 } 1160 #ifdef _USE_MAC_PRIV_PROP 1161 case MAC_PROP_PRIVATE: 1162 if ((rc = sfxge_gld_priv_prop_set(sp, name, size, valp)) != 0) 1163 goto fail4; 1164 1165 break; 1166 #endif 1167 default: 1168 rc = ENOTSUP; 1169 goto fail5; 1170 } 1171 1172 return (0); 1173 1174 fail5: 1175 DTRACE_PROBE(fail5); 1176 1177 #ifdef _USE_MAC_PRIV_PROP 1178 fail4: 1179 DTRACE_PROBE(fail4); 1180 #endif 1181 1182 fail3: 1183 DTRACE_PROBE(fail3); 1184 1185 fail2: 1186 DTRACE_PROBE(fail2); 1187 1188 fail1: 1189 DTRACE_PROBE1(fail1, int, rc); 1190 1191 return (rc); 1192 } 1193 #endif 1194 1195 #ifdef _USE_GLD_V3_PROPS 1196 static void 1197 sfxge_gld_propinfo(void *arg, const char *name, mac_prop_id_t id, 1198 mac_prop_info_handle_t handle) 1199 { 1200 sfxge_t *sp = arg; 1201 efx_phy_cap_type_t phy_cap = EFX_PHY_CAP_INVALID; 1202 switch (id) { 1203 case MAC_PROP_DUPLEX: 1204 mac_prop_info_set_perm(handle, MAC_PROP_PERM_READ); 1205 return; 1206 case MAC_PROP_FLOWCTRL: 1207 mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW); 1208 mac_prop_info_set_default_link_flowctrl(handle, 1209 LINK_FLOWCTRL_BI); 1210 return; 1211 case MAC_PROP_SPEED: 1212 mac_prop_info_set_perm(handle, MAC_PROP_PERM_READ); 1213 return; 1214 case MAC_PROP_STATUS: 1215 mac_prop_info_set_perm(handle, MAC_PROP_PERM_READ); 1216 return; 1217 case MAC_PROP_MTU: { 1218 uint32_t mtu_default; 1219 mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW); 1220 mtu_default = ddi_prop_get_int(DDI_DEV_T_ANY, 1221 sp->s_dip, DDI_PROP_DONTPASS, "mtu", ETHERMTU); 1222 mac_prop_info_set_default_uint32(handle, mtu_default); 1223 return; 1224 } 1225 #ifdef _USE_MAC_PRIV_PROP 1226 case MAC_PROP_PRIVATE: 1227 sfxge_gld_priv_prop_info(sp, name, handle); 1228 return; 1229 #endif 1230 case MAC_PROP_EN_AUTONEG: 1231 case MAC_PROP_AUTONEG: 1232 phy_cap = EFX_PHY_CAP_AN; 1233 break; 1234 case MAC_PROP_EN_10GFDX_CAP: 1235 case MAC_PROP_ADV_10GFDX_CAP: 1236 phy_cap = EFX_PHY_CAP_10000FDX; 1237 break; 1238 case MAC_PROP_EN_1000FDX_CAP: 1239 case MAC_PROP_ADV_1000FDX_CAP: 1240 phy_cap = EFX_PHY_CAP_1000FDX; 1241 break; 1242 case MAC_PROP_EN_1000HDX_CAP: 1243 case MAC_PROP_ADV_1000HDX_CAP: 1244 phy_cap = EFX_PHY_CAP_1000HDX; 1245 break; 1246 case MAC_PROP_EN_100FDX_CAP: 1247 case MAC_PROP_ADV_100FDX_CAP: 1248 phy_cap = EFX_PHY_CAP_100FDX; 1249 break; 1250 case MAC_PROP_EN_100HDX_CAP: 1251 case MAC_PROP_ADV_100HDX_CAP: 1252 phy_cap = EFX_PHY_CAP_100HDX; 1253 break; 1254 case MAC_PROP_EN_10FDX_CAP: 1255 case MAC_PROP_ADV_10FDX_CAP: 1256 phy_cap = EFX_PHY_CAP_10FDX; 1257 break; 1258 case MAC_PROP_EN_10HDX_CAP: 1259 case MAC_PROP_ADV_10HDX_CAP: 1260 phy_cap = EFX_PHY_CAP_10HDX; 1261 break; 1262 default: 1263 DTRACE_PROBE(unknown_prop); 1264 return; 1265 } 1266 if (phy_cap != EFX_PHY_CAP_INVALID) { 1267 boolean_t rw; 1268 uint8_t cap_default; 1269 cap_default = sfxge_phy_cap_test(sp, EFX_PHY_CAP_DEFAULT, 1270 phy_cap, &rw); 1271 if (rw == B_TRUE) 1272 mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW); 1273 else 1274 mac_prop_info_set_perm(handle, MAC_PROP_PERM_READ); 1275 mac_prop_info_set_default_uint8(handle, cap_default); 1276 } 1277 } 1278 #endif 1279 1280 int 1281 sfxge_gld_register(sfxge_t *sp) 1282 { 1283 mac_callbacks_t *mcp; 1284 mac_register_t *mrp; 1285 mac_handle_t mh; 1286 int rc; 1287 1288 #ifdef _USE_GLD_V3_SOL10 1289 if ((rc = sfxge_gld_nd_register(sp)) != 0) 1290 goto fail0; 1291 #endif 1292 1293 /* 1294 * NOTE: mac_register_t has additional fields in later kernels, 1295 * so the buffer returned by mac_alloc(9F) changes size. This 1296 * is not a problem for forward compatibility (a driver binary 1297 * built with older headers/libs running on a newer kernel). 1298 * 1299 * For Solaris 10, we build the sfxge driver on s10u9 to run on 1300 * s10u8, and later. This requries backward compatibility and 1301 * causes a problem. The mac_register_t in s10u8 is smaller than 1302 * the version in s10u9, so writing to the mc_margin field causes 1303 * a buffer overflow (and a hard-to-debug panic). 1304 * 1305 * Work around this problem by allocating mac_register_t using 1306 * kmem_alloc(9F) so it has the size expected by the driver. The 1307 * running kernel ignores the additional fields. 1308 * 1309 * Replace mac_alloc() with kmem_zalloc() and then set m_version. 1310 * Replace mac_free() with kmem_free(). 1311 * 1312 * See bug 33189 and bug33213 for details. 1313 */ 1314 if ((mrp = kmem_zalloc(sizeof (mac_register_t), KM_SLEEP)) == NULL) { 1315 rc = ENOMEM; 1316 goto fail1; 1317 } 1318 mrp->m_version = MAC_VERSION; 1319 1320 mrp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 1321 mrp->m_driver = sp; 1322 mrp->m_dip = sp->s_dip; 1323 1324 /* Set up the callbacks */ 1325 mcp = &(sp->s_mc); 1326 bzero(mcp, sizeof (mac_callbacks_t)); 1327 1328 mcp->mc_getstat = sfxge_gld_getstat; 1329 mcp->mc_start = sfxge_gld_start; 1330 mcp->mc_stop = sfxge_gld_stop; 1331 mcp->mc_setpromisc = sfxge_gld_setpromisc; 1332 mcp->mc_multicst = sfxge_gld_multicst; 1333 mcp->mc_unicst = sfxge_gld_unicst; 1334 mcp->mc_tx = sfxge_gld_tx; 1335 1336 mcp->mc_callbacks |= MC_IOCTL; 1337 mcp->mc_ioctl = sfxge_gld_ioctl; 1338 1339 mcp->mc_callbacks |= MC_GETCAPAB; 1340 mcp->mc_getcapab = sfxge_gld_getcapab; 1341 1342 #ifdef _USE_GLD_V3_PROPS 1343 /* NOTE: mc_setprop, mc_getprop, mc_propinfo added in s10u9 */ 1344 mcp->mc_callbacks |= MC_SETPROP; 1345 mcp->mc_setprop = sfxge_gld_setprop; 1346 1347 mcp->mc_callbacks |= MC_GETPROP; 1348 mcp->mc_getprop = sfxge_gld_getprop; 1349 1350 mcp->mc_callbacks |= MC_PROPINFO; 1351 mcp->mc_propinfo = sfxge_gld_propinfo; 1352 #endif 1353 1354 mrp->m_callbacks = mcp; 1355 1356 mrp->m_src_addr = kmem_alloc(ETHERADDRL, KM_SLEEP); 1357 1358 if ((rc = sfxge_mac_unicst_get(sp, SFXGE_UNICST_BIA, 1359 mrp->m_src_addr)) != 0) 1360 goto fail2; 1361 1362 mrp->m_min_sdu = 0; 1363 mrp->m_max_sdu = sp->s_mtu; 1364 1365 /* NOTE: m_margin added in s10u9 */ 1366 mrp->m_margin = SFXGE_VLAN_TAGSZ; 1367 1368 /* Set up the private properties */ 1369 #ifdef _USE_MAC_PRIV_PROP 1370 /* NOTE: m_priv_props added in s10u9 */ 1371 mrp->m_priv_props = sp->s_mac_priv_props; 1372 sfxge_gld_priv_prop_init(sp); 1373 #endif 1374 1375 /* NOTE: m_flags added in s11.0 */ 1376 /* NOTE: m_multicast_sdu added in s11.0 */ 1377 1378 /* Register the interface */ 1379 if ((rc = mac_register(mrp, &mh)) != 0) 1380 goto fail3; 1381 1382 kmem_free(mrp->m_src_addr, ETHERADDRL); 1383 1384 /* Free the stack registration object */ 1385 kmem_free(mrp, sizeof (mac_register_t)); 1386 1387 sp->s_mh = mh; 1388 1389 return (0); 1390 fail3: 1391 DTRACE_PROBE(fail3); 1392 fail2: 1393 DTRACE_PROBE(fail2); 1394 1395 kmem_free(mrp->m_src_addr, ETHERADDRL); 1396 1397 /* Free the stack registration object */ 1398 kmem_free(mrp, sizeof (mac_register_t)); 1399 1400 #ifdef _USE_MAC_PRIV_PROP 1401 /* Tear down the private properties */ 1402 sfxge_gld_priv_prop_fini(sp); 1403 #endif 1404 1405 /* Clear the callbacks */ 1406 bzero(&(sp->s_mc), sizeof (mac_callbacks_t)); 1407 1408 fail1: 1409 DTRACE_PROBE1(fail1, int, rc); 1410 #ifdef _USE_GLD_V3_SOL10 1411 sfxge_gld_nd_unregister(sp); 1412 1413 fail0: 1414 DTRACE_PROBE1(fail0, int, rc); 1415 #endif 1416 1417 return (rc); 1418 } 1419 1420 int 1421 sfxge_gld_unregister(sfxge_t *sp) 1422 { 1423 mac_handle_t mh = sp->s_mh; 1424 int rc; 1425 1426 if ((rc = mac_unregister(mh)) != 0) 1427 goto fail1; 1428 1429 sp->s_mh = NULL; 1430 1431 #ifdef _USE_MAC_PRIV_PROP 1432 /* Tear down the private properties */ 1433 sfxge_gld_priv_prop_fini(sp); 1434 #endif 1435 #ifdef _USE_GLD_V3_SOL10 1436 sfxge_gld_nd_unregister(sp); 1437 #endif 1438 1439 /* Clear the callbacks */ 1440 bzero(&(sp->s_mc), sizeof (mac_callbacks_t)); 1441 1442 return (0); 1443 1444 fail1: 1445 DTRACE_PROBE1(fail1, int, rc); 1446 1447 return (rc); 1448 } 1449 #endif /* _USE_GLD_V3 */