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 #include <sys/types.h> 28 #include <sys/ddi.h> 29 #include <sys/sunddi.h> 30 #include <sys/gld.h> 31 32 #include <inet/nd.h> 33 #include <inet/mi.h> 34 35 #include "sfxge.h" 36 37 38 typedef enum sfxge_prop_e { 39 SFXGE_RX_COALESCE_MODE = 0, 40 SFXGE_RX_SCALE_COUNT, 41 SFXGE_FCNTL_RESPOND, 42 SFXGE_FCNTL_GENERATE, 43 SFXGE_INTR_MODERATION, 44 SFXGE_ADV_AUTONEG, 45 SFXGE_ADV_10GFDX, 46 SFXGE_ADV_1000FDX, 47 SFXGE_ADV_1000HDX, 48 SFXGE_ADV_100FDX, 49 SFXGE_ADV_100HDX, 50 SFXGE_ADV_10FDX, 51 SFXGE_ADV_10HDX, 52 SFXGE_ADV_PAUSE, 53 SFXGE_ADV_ASM_PAUSE, 54 SFXGE_LP_AUTONEG, 55 SFXGE_LP_10GFDX, 56 SFXGE_LP_1000FDX, 57 SFXGE_LP_1000HDX, 58 SFXGE_LP_100FDX, 59 SFXGE_LP_100HDX, 60 SFXGE_LP_10FDX, 61 SFXGE_LP_10HDX, 62 SFXGE_LP_PAUSE, 63 SFXGE_LP_ASM_PAUSE, 64 SFXGE_CAP_AUTONEG, 65 SFXGE_CAP_10GFDX, 66 SFXGE_CAP_1000FDX, 67 SFXGE_CAP_1000HDX, 68 SFXGE_CAP_100FDX, 69 SFXGE_CAP_100HDX, 70 SFXGE_CAP_10FDX, 71 SFXGE_CAP_10HDX, 72 SFXGE_CAP_PAUSE, 73 SFXGE_CAP_ASM_PAUSE, 74 SFXGE_NPROPS 75 } sfxge_prop_t; 76 77 78 static int 79 sfxge_gld_nd_get(sfxge_t *sp, unsigned int id, uint32_t *valp) 80 { 81 efx_nic_t *enp = sp->s_enp; 82 unsigned int nprops; 83 int rc; 84 85 nprops = efx_nic_cfg_get(enp)->enc_phy_nprops; 86 87 if (sp->s_mac.sm_state != SFXGE_MAC_STARTED) { 88 rc = ENODEV; 89 goto fail1; 90 } 91 92 ASSERT3U(id, <, nprops + SFXGE_NPROPS); 93 94 if (id < nprops) { 95 if ((rc = efx_phy_prop_get(enp, id, 0, valp)) != 0) 96 goto fail2; 97 } else { 98 id -= nprops; 99 100 switch (id) { 101 case SFXGE_RX_COALESCE_MODE: { 102 sfxge_rx_coalesce_mode_t mode; 103 104 sfxge_rx_coalesce_mode_get(sp, &mode); 105 106 *valp = mode; 107 break; 108 } 109 case SFXGE_RX_SCALE_COUNT: { 110 unsigned int count; 111 112 if (sfxge_rx_scale_count_get(sp, &count) != 0) 113 count = 0; 114 115 *valp = count; 116 break; 117 } 118 case SFXGE_FCNTL_RESPOND: { 119 unsigned int fcntl; 120 121 sfxge_mac_fcntl_get(sp, &fcntl); 122 123 *valp = (fcntl & EFX_FCNTL_RESPOND) ? 1 : 0; 124 break; 125 } 126 case SFXGE_FCNTL_GENERATE: { 127 unsigned int fcntl; 128 129 sfxge_mac_fcntl_get(sp, &fcntl); 130 131 *valp = (fcntl & EFX_FCNTL_GENERATE) ? 1 : 0; 132 break; 133 } 134 case SFXGE_INTR_MODERATION: { 135 unsigned int us; 136 137 sfxge_ev_moderation_get(sp, &us); 138 139 *valp = (long)us; 140 break; 141 } 142 case SFXGE_ADV_AUTONEG: { 143 uint32_t mask; 144 145 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 146 147 *valp = (mask & (1 << EFX_PHY_CAP_AN)) ? 1 : 0; 148 break; 149 } 150 case SFXGE_ADV_10GFDX: { 151 uint32_t mask; 152 153 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 154 155 *valp = (mask & (1 << EFX_PHY_CAP_10000FDX)) ? 1 : 0; 156 break; 157 } 158 case SFXGE_ADV_1000FDX: { 159 uint32_t mask; 160 161 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 162 163 *valp = (mask & (1 << EFX_PHY_CAP_1000FDX)) ? 1 : 0; 164 break; 165 } 166 case SFXGE_ADV_1000HDX: { 167 uint32_t mask; 168 169 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 170 171 *valp = (mask & (1 << EFX_PHY_CAP_1000HDX)) ? 1 : 0; 172 break; 173 } 174 case SFXGE_ADV_100FDX: { 175 uint32_t mask; 176 177 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 178 179 *valp = (mask & (1 << EFX_PHY_CAP_100FDX)) ? 1 : 0; 180 break; 181 } 182 case SFXGE_ADV_100HDX: { 183 uint32_t mask; 184 185 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 186 187 *valp = (mask & (1 << EFX_PHY_CAP_100HDX)) ? 1 : 0; 188 break; 189 } 190 case SFXGE_ADV_10FDX: { 191 uint32_t mask; 192 193 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 194 195 *valp = (mask & (1 << EFX_PHY_CAP_10FDX)) ? 1 : 0; 196 break; 197 } 198 case SFXGE_ADV_10HDX: { 199 uint32_t mask; 200 201 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 202 203 *valp = (mask & (1 << EFX_PHY_CAP_10HDX)) ? 1 : 0; 204 break; 205 } 206 case SFXGE_ADV_PAUSE: { 207 uint32_t mask; 208 209 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 210 211 *valp = (mask & (1 << EFX_PHY_CAP_PAUSE)) ? 1 : 0; 212 break; 213 } 214 case SFXGE_ADV_ASM_PAUSE: { 215 uint32_t mask; 216 217 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 218 219 *valp = (mask & (1 << EFX_PHY_CAP_ASYM)) ? 1 : 0; 220 break; 221 } 222 case SFXGE_LP_AUTONEG: { 223 uint32_t mask; 224 225 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 226 227 *valp = (mask & (1 << EFX_PHY_CAP_AN)) ? 1 : 0; 228 break; 229 } 230 case SFXGE_LP_10GFDX: { 231 uint32_t mask; 232 233 efx_phy_lp_cap_get(enp, &mask); 234 235 *valp = (mask & (1 << EFX_PHY_CAP_10000FDX)) ? 1 : 0; 236 break; 237 } 238 case SFXGE_LP_1000FDX: { 239 uint32_t mask; 240 241 efx_phy_lp_cap_get(enp, &mask); 242 243 *valp = (mask & (1 << EFX_PHY_CAP_1000FDX)) ? 1 : 0; 244 break; 245 } 246 case SFXGE_LP_1000HDX: { 247 uint32_t mask; 248 249 efx_phy_lp_cap_get(enp, &mask); 250 251 *valp = (mask & (1 << EFX_PHY_CAP_1000HDX)) ? 1 : 0; 252 break; 253 } 254 case SFXGE_LP_100FDX: { 255 uint32_t mask; 256 257 efx_phy_lp_cap_get(enp, &mask); 258 259 *valp = (mask & (1 << EFX_PHY_CAP_100FDX)) ? 1 : 0; 260 break; 261 } 262 case SFXGE_LP_100HDX: { 263 uint32_t mask; 264 265 efx_phy_lp_cap_get(enp, &mask); 266 267 *valp = (mask & (1 << EFX_PHY_CAP_100HDX)) ? 1 : 0; 268 break; 269 } 270 case SFXGE_LP_10FDX: { 271 uint32_t mask; 272 273 efx_phy_lp_cap_get(enp, &mask); 274 275 *valp = (mask & (1 << EFX_PHY_CAP_10FDX)) ? 1 : 0; 276 break; 277 } 278 case SFXGE_LP_10HDX: { 279 uint32_t mask; 280 281 efx_phy_lp_cap_get(enp, &mask); 282 283 *valp = (mask & (1 << EFX_PHY_CAP_10HDX)) ? 1 : 0; 284 break; 285 } 286 case SFXGE_LP_PAUSE: { 287 uint32_t mask; 288 289 efx_phy_lp_cap_get(enp, &mask); 290 291 *valp = (mask & (1 << EFX_PHY_CAP_PAUSE)) ? 1 : 0; 292 break; 293 } 294 case SFXGE_LP_ASM_PAUSE: { 295 uint32_t mask; 296 297 efx_phy_lp_cap_get(enp, &mask); 298 299 *valp = (mask & (1 << EFX_PHY_CAP_ASYM)) ? 1 : 0; 300 break; 301 } 302 case SFXGE_CAP_AUTONEG: { 303 uint32_t mask; 304 305 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask); 306 307 *valp = (mask & (1 << EFX_PHY_CAP_AN)) ? 1 : 0; 308 break; 309 } 310 case SFXGE_CAP_10GFDX: { 311 uint32_t mask; 312 313 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask); 314 315 *valp = (mask & (1 << EFX_PHY_CAP_10000FDX)) ? 1 : 0; 316 break; 317 } 318 case SFXGE_CAP_1000FDX: { 319 uint32_t mask; 320 321 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask); 322 323 *valp = (mask & (1 << EFX_PHY_CAP_1000FDX)) ? 1 : 0; 324 break; 325 } 326 case SFXGE_CAP_1000HDX: { 327 uint32_t mask; 328 329 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask); 330 331 *valp = (mask & (1 << EFX_PHY_CAP_1000HDX)) ? 1 : 0; 332 break; 333 } 334 case SFXGE_CAP_100FDX: { 335 uint32_t mask; 336 337 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask); 338 339 *valp = (mask & (1 << EFX_PHY_CAP_100FDX)) ? 1 : 0; 340 break; 341 } 342 case SFXGE_CAP_100HDX: { 343 uint32_t mask; 344 345 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask); 346 347 *valp = (mask & (1 << EFX_PHY_CAP_100HDX)) ? 1 : 0; 348 break; 349 } 350 case SFXGE_CAP_10FDX: { 351 uint32_t mask; 352 353 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask); 354 355 *valp = (mask & (1 << EFX_PHY_CAP_10FDX)) ? 1 : 0; 356 break; 357 } 358 case SFXGE_CAP_10HDX: { 359 uint32_t mask; 360 361 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask); 362 363 *valp = (mask & (1 << EFX_PHY_CAP_10HDX)) ? 1 : 0; 364 break; 365 } 366 case SFXGE_CAP_PAUSE: { 367 uint32_t mask; 368 369 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask); 370 371 *valp = (mask & (1 << EFX_PHY_CAP_PAUSE)) ? 1 : 0; 372 break; 373 } 374 case SFXGE_CAP_ASM_PAUSE: { 375 uint32_t mask; 376 377 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask); 378 379 *valp = (mask & (1 << EFX_PHY_CAP_ASYM)) ? 1 : 0; 380 break; 381 } 382 default: 383 ASSERT(B_FALSE); 384 break; 385 } 386 } 387 388 return (0); 389 fail2: 390 DTRACE_PROBE(fail2); 391 fail1: 392 DTRACE_PROBE1(fail1, int, rc); 393 394 return (rc); 395 } 396 397 #ifdef _USE_NDD_PROPS 398 static int 399 sfxge_gld_nd_get_ioctl(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *credp) 400 { 401 sfxge_ndd_param_t *snpp = (sfxge_ndd_param_t *)arg; 402 sfxge_t *sp = snpp->snp_sp; 403 unsigned int id = snpp->snp_id; 404 uint32_t val; 405 int rc; 406 407 _NOTE(ARGUNUSED(q, credp)) 408 409 if ((rc = sfxge_gld_nd_get(sp, id, &val)) != 0) 410 goto fail1; 411 412 (void) mi_mpprintf(mp, "%d", val); 413 414 return (0); 415 416 fail1: 417 DTRACE_PROBE1(fail1, int, rc); 418 419 return (rc); 420 } 421 #else 422 static int 423 sfxge_gld_nd_get_ioctl(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *credp) 424 { 425 ASSERT(B_FALSE); 426 return (-ENODEV); 427 } 428 #endif 429 430 431 static int 432 sfxge_gld_nd_set(sfxge_t *sp, unsigned int id, uint32_t val) 433 { 434 efx_nic_t *enp = sp->s_enp; 435 unsigned int nprops; 436 int rc; 437 438 nprops = efx_nic_cfg_get(enp)->enc_phy_nprops; 439 440 ASSERT3U(id, <, nprops + SFXGE_NPROPS); 441 442 if (id < nprops) { 443 if ((rc = efx_phy_prop_set(enp, id, val)) != 0) 444 goto fail1; 445 } else { 446 id -= nprops; 447 448 switch (id) { 449 case SFXGE_RX_COALESCE_MODE: { 450 sfxge_rx_coalesce_mode_t mode = 451 (sfxge_rx_coalesce_mode_t)val; 452 453 if ((rc = sfxge_rx_coalesce_mode_set(sp, mode)) != 0) 454 goto fail1; 455 456 break; 457 } 458 case SFXGE_RX_SCALE_COUNT: { 459 unsigned int count = (unsigned int)val; 460 461 if ((rc = sfxge_rx_scale_count_set(sp, count)) != 0) 462 goto fail1; 463 464 break; 465 } 466 case SFXGE_FCNTL_RESPOND: { 467 unsigned int fcntl; 468 469 sfxge_mac_fcntl_get(sp, &fcntl); 470 471 if (val != 0) 472 fcntl |= EFX_FCNTL_RESPOND; 473 else 474 fcntl &= ~EFX_FCNTL_RESPOND; 475 476 if ((rc = sfxge_mac_fcntl_set(sp, fcntl)) != 0) 477 goto fail1; 478 479 break; 480 } 481 case SFXGE_FCNTL_GENERATE: { 482 unsigned int fcntl; 483 484 sfxge_mac_fcntl_get(sp, &fcntl); 485 486 if (val != 0) 487 fcntl |= EFX_FCNTL_GENERATE; 488 else 489 fcntl &= ~EFX_FCNTL_GENERATE; 490 491 if ((rc = sfxge_mac_fcntl_set(sp, fcntl)) != 0) 492 goto fail1; 493 494 break; 495 } 496 case SFXGE_INTR_MODERATION: { 497 unsigned int us = (unsigned int)val; 498 499 if ((rc = sfxge_ev_moderation_set(sp, us)) != 0) 500 goto fail1; 501 break; 502 } 503 case SFXGE_ADV_AUTONEG: { 504 uint32_t mask; 505 506 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 507 508 if (val != 0) 509 mask |= (1 << EFX_PHY_CAP_AN); 510 else 511 mask &= ~(1 << EFX_PHY_CAP_AN); 512 513 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0) 514 goto fail1; 515 516 break; 517 } 518 case SFXGE_ADV_10GFDX: { 519 uint32_t mask; 520 521 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 522 523 if (val != 0) 524 mask |= (1 << EFX_PHY_CAP_10000FDX); 525 else 526 mask &= ~(1 << EFX_PHY_CAP_10000FDX); 527 528 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0) 529 goto fail1; 530 531 break; 532 } 533 case SFXGE_ADV_1000FDX: { 534 uint32_t mask; 535 536 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 537 538 if (val != 0) 539 mask |= (1 << EFX_PHY_CAP_1000FDX); 540 else 541 mask &= ~(1 << EFX_PHY_CAP_1000FDX); 542 543 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0) 544 goto fail1; 545 546 break; 547 } 548 case SFXGE_ADV_1000HDX: { 549 uint32_t mask; 550 551 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 552 553 if (val != 0) 554 mask |= (1 << EFX_PHY_CAP_1000HDX); 555 else 556 mask &= ~(1 << EFX_PHY_CAP_1000HDX); 557 558 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0) 559 goto fail1; 560 561 break; 562 } 563 case SFXGE_ADV_100FDX: { 564 uint32_t mask; 565 566 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 567 568 if (val != 0) 569 mask |= (1 << EFX_PHY_CAP_100FDX); 570 else 571 mask &= ~(1 << EFX_PHY_CAP_100FDX); 572 573 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0) 574 goto fail1; 575 576 break; 577 } 578 case SFXGE_ADV_100HDX: { 579 uint32_t mask; 580 581 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 582 583 if (val != 0) 584 mask |= (1 << EFX_PHY_CAP_100HDX); 585 else 586 mask &= ~(1 << EFX_PHY_CAP_100HDX); 587 588 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0) 589 goto fail1; 590 591 break; 592 } 593 case SFXGE_ADV_10FDX: { 594 uint32_t mask; 595 596 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 597 598 if (val != 0) 599 mask |= (1 << EFX_PHY_CAP_10FDX); 600 else 601 mask &= ~(1 << EFX_PHY_CAP_10FDX); 602 603 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0) 604 goto fail1; 605 606 break; 607 } 608 case SFXGE_ADV_10HDX: { 609 uint32_t mask; 610 611 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 612 613 if (val != 0) 614 mask |= (1 << EFX_PHY_CAP_10HDX); 615 else 616 mask &= ~(1 << EFX_PHY_CAP_10HDX); 617 618 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0) 619 goto fail1; 620 621 break; 622 } 623 case SFXGE_ADV_PAUSE: { 624 uint32_t mask; 625 626 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 627 628 if (val != 0) 629 mask |= (1 << EFX_PHY_CAP_PAUSE); 630 else 631 mask &= ~(1 << EFX_PHY_CAP_PAUSE); 632 633 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0) 634 goto fail1; 635 636 break; 637 } 638 case SFXGE_ADV_ASM_PAUSE: { 639 uint32_t mask; 640 641 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask); 642 643 if (val != 0) 644 mask |= (1 << EFX_PHY_CAP_ASYM); 645 else 646 mask &= ~(1 << EFX_PHY_CAP_ASYM); 647 648 if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0) 649 goto fail1; 650 651 break; 652 } 653 /* Ignore other kstat writes. Might be for the link partner */ 654 default: 655 DTRACE_PROBE1(ignore_kstat_write, int, id); 656 } 657 } 658 659 return (0); 660 661 fail1: 662 DTRACE_PROBE1(fail1, int, rc); 663 664 return (rc); 665 } 666 667 668 #ifdef _USE_NDD_PROPS 669 static int 670 sfxge_gld_nd_set_ioctl(queue_t *q, mblk_t *mp, char *valp, caddr_t arg, 671 cred_t *credp) 672 { 673 sfxge_ndd_param_t *snpp = (sfxge_ndd_param_t *)arg; 674 sfxge_t *sp = snpp->snp_sp; 675 unsigned int id = snpp->snp_id; 676 long val; 677 int rc; 678 679 _NOTE(ARGUNUSED(q, mp, credp)) 680 681 (void) ddi_strtol(valp, (char **)NULL, 0, &val); 682 683 if ((rc = sfxge_gld_nd_set(sp, id, (uint32_t)val)) != 0) 684 goto fail1; 685 686 return (0); 687 688 fail1: 689 DTRACE_PROBE1(fail1, int, rc); 690 691 return (rc); 692 } 693 #else 694 static int 695 sfxge_gld_nd_set_ioctl(queue_t *q, mblk_t *mp, char *valp, caddr_t arg, 696 cred_t *credp) 697 { 698 ASSERT(B_FALSE); 699 return (-ENODEV); 700 } 701 #endif 702 703 704 static int 705 sfxge_gld_nd_update(kstat_t *ksp, int rw) 706 { 707 sfxge_t *sp = ksp->ks_private; 708 efx_nic_t *enp = sp->s_enp; 709 unsigned int nprops; 710 unsigned int id; 711 int rc = 0; 712 713 nprops = efx_nic_cfg_get(enp)->enc_phy_nprops; 714 715 for (id = 0; id < nprops + SFXGE_NPROPS; id++) { 716 kstat_named_t *knp = &(sp->s_nd_stat[id]); 717 718 if (rw == KSTAT_READ) 719 rc = sfxge_gld_nd_get(sp, id, &(knp->value.ui32)); 720 else if (rw == KSTAT_WRITE) 721 rc = sfxge_gld_nd_set(sp, id, knp->value.ui32); 722 else 723 rc = EACCES; 724 725 if (rc != 0) 726 goto fail1; 727 } 728 729 return (0); 730 731 fail1: 732 DTRACE_PROBE1(fail1, int, rc); 733 return (rc); 734 } 735 736 737 static sfxge_ndd_param_t sfxge_ndd_param[] = { 738 { 739 NULL, 740 SFXGE_RX_COALESCE_MODE, 741 "rx_coalesce_mode", 742 sfxge_gld_nd_get_ioctl, 743 sfxge_gld_nd_set_ioctl 744 }, 745 { 746 NULL, 747 SFXGE_RX_SCALE_COUNT, 748 "rx_scale_count", 749 sfxge_gld_nd_get_ioctl, 750 sfxge_gld_nd_set_ioctl 751 }, 752 { 753 NULL, 754 SFXGE_FCNTL_RESPOND, 755 "fcntl_respond", 756 sfxge_gld_nd_get_ioctl, 757 sfxge_gld_nd_set_ioctl 758 }, 759 { 760 NULL, 761 SFXGE_FCNTL_GENERATE, 762 "fcntl_generate", 763 sfxge_gld_nd_get_ioctl, 764 sfxge_gld_nd_set_ioctl 765 }, 766 { 767 NULL, 768 SFXGE_INTR_MODERATION, 769 "intr_moderation", 770 sfxge_gld_nd_get_ioctl, 771 sfxge_gld_nd_set_ioctl 772 }, 773 { 774 NULL, 775 SFXGE_ADV_AUTONEG, 776 "adv_cap_autoneg", 777 sfxge_gld_nd_get_ioctl, 778 sfxge_gld_nd_set_ioctl 779 }, 780 { 781 NULL, 782 SFXGE_ADV_10GFDX, 783 "adv_cap_10gfdx", 784 sfxge_gld_nd_get_ioctl, 785 sfxge_gld_nd_set_ioctl 786 }, 787 { 788 NULL, 789 SFXGE_ADV_1000FDX, 790 "adv_cap_1000fdx", 791 sfxge_gld_nd_get_ioctl, 792 sfxge_gld_nd_set_ioctl 793 }, 794 { 795 NULL, 796 SFXGE_ADV_1000HDX, 797 "adv_cap_1000hdx", 798 sfxge_gld_nd_get_ioctl, 799 sfxge_gld_nd_set_ioctl 800 }, 801 { 802 NULL, 803 SFXGE_ADV_100FDX, 804 "adv_cap_100fdx", 805 sfxge_gld_nd_get_ioctl, 806 sfxge_gld_nd_set_ioctl 807 }, 808 { 809 NULL, 810 SFXGE_ADV_100HDX, 811 "adv_cap_100hdx", 812 sfxge_gld_nd_get_ioctl, 813 sfxge_gld_nd_set_ioctl 814 }, 815 { 816 NULL, 817 SFXGE_ADV_10FDX, 818 "adv_cap_10fdx", 819 sfxge_gld_nd_get_ioctl, 820 sfxge_gld_nd_set_ioctl 821 }, 822 { 823 NULL, 824 SFXGE_ADV_10HDX, 825 "adv_cap_10hdx", 826 sfxge_gld_nd_get_ioctl, 827 sfxge_gld_nd_set_ioctl 828 }, 829 { 830 NULL, 831 SFXGE_ADV_PAUSE, 832 "adv_cap_pause", 833 sfxge_gld_nd_get_ioctl, 834 sfxge_gld_nd_set_ioctl 835 }, 836 { 837 NULL, 838 SFXGE_ADV_ASM_PAUSE, 839 "adv_cap_asm_pause", 840 sfxge_gld_nd_get_ioctl, 841 sfxge_gld_nd_set_ioctl 842 }, 843 { 844 NULL, 845 SFXGE_LP_AUTONEG, 846 "lp_cap_autoneg", 847 sfxge_gld_nd_get_ioctl, 848 NULL 849 }, 850 { 851 NULL, 852 SFXGE_LP_10GFDX, 853 "lp_cap_10gfdx", 854 sfxge_gld_nd_get_ioctl, 855 NULL 856 }, 857 { 858 NULL, 859 SFXGE_LP_1000FDX, 860 "lp_cap_1000fdx", 861 sfxge_gld_nd_get_ioctl, 862 NULL 863 }, 864 { 865 NULL, 866 SFXGE_LP_1000HDX, 867 "lp_cap_1000hdx", 868 sfxge_gld_nd_get_ioctl, 869 NULL 870 }, 871 { 872 NULL, 873 SFXGE_LP_100FDX, 874 "lp_cap_100fdx", 875 sfxge_gld_nd_get_ioctl, 876 NULL 877 }, 878 { 879 NULL, 880 SFXGE_LP_100HDX, 881 "lp_cap_100hdx", 882 sfxge_gld_nd_get_ioctl, 883 NULL 884 }, 885 { 886 NULL, 887 SFXGE_LP_10FDX, 888 "lp_cap_10fdx", 889 sfxge_gld_nd_get_ioctl, 890 NULL 891 }, 892 { 893 NULL, 894 SFXGE_LP_10HDX, 895 "lp_cap_10hdx", 896 sfxge_gld_nd_get_ioctl, 897 NULL 898 }, 899 { 900 NULL, 901 SFXGE_LP_PAUSE, 902 "lp_cap_pause", 903 sfxge_gld_nd_get_ioctl, 904 NULL 905 }, 906 { 907 NULL, 908 SFXGE_LP_ASM_PAUSE, 909 "lp_cap_asm_pause", 910 sfxge_gld_nd_get_ioctl, 911 NULL 912 }, 913 { 914 NULL, 915 SFXGE_CAP_AUTONEG, 916 "cap_autoneg", 917 sfxge_gld_nd_get_ioctl, 918 NULL 919 }, 920 { 921 NULL, 922 SFXGE_CAP_10GFDX, 923 "cap_10gfdx", 924 sfxge_gld_nd_get_ioctl, 925 NULL 926 }, 927 { 928 NULL, 929 SFXGE_CAP_1000FDX, 930 "cap_1000fdx", 931 sfxge_gld_nd_get_ioctl, 932 NULL 933 }, 934 { 935 NULL, 936 SFXGE_CAP_1000HDX, 937 "cap_1000hdx", 938 sfxge_gld_nd_get_ioctl, 939 NULL 940 }, 941 { 942 NULL, 943 SFXGE_CAP_100FDX, 944 "cap_100fdx", 945 sfxge_gld_nd_get_ioctl, 946 NULL 947 }, 948 { 949 NULL, 950 SFXGE_CAP_100HDX, 951 "cap_100hdx", 952 sfxge_gld_nd_get_ioctl, 953 NULL 954 }, 955 { 956 NULL, 957 SFXGE_CAP_10FDX, 958 "cap_10fdx", 959 sfxge_gld_nd_get_ioctl, 960 NULL 961 }, 962 { 963 NULL, 964 SFXGE_CAP_10HDX, 965 "cap_10hdx", 966 sfxge_gld_nd_get_ioctl, 967 NULL 968 }, 969 { 970 NULL, 971 SFXGE_CAP_PAUSE, 972 "cap_pause", 973 sfxge_gld_nd_get_ioctl, 974 NULL 975 }, 976 { 977 NULL, 978 SFXGE_CAP_ASM_PAUSE, 979 "cap_asm_pause", 980 sfxge_gld_nd_get_ioctl, 981 NULL 982 } 983 }; 984 985 986 int 987 sfxge_gld_nd_register(sfxge_t *sp) 988 { 989 #ifdef _USE_NDD_PROPS 990 caddr_t *ndhp = &(sp->s_ndh); 991 #endif 992 efx_nic_t *enp = sp->s_enp; 993 unsigned int nprops; 994 unsigned int id; 995 char name[MAXNAMELEN]; 996 kstat_t *ksp; 997 int rc; 998 999 ASSERT3P(sp->s_ndh, ==, NULL); 1000 1001 nprops = efx_nic_cfg_get(enp)->enc_phy_nprops; 1002 1003 #ifdef _USE_NDD_PROPS 1004 /* Register with the NDD framework */ 1005 if ((sp->s_ndp = kmem_zalloc(sizeof (sfxge_ndd_param_t) * 1006 (nprops + SFXGE_NPROPS), KM_NOSLEEP)) == NULL) { 1007 rc = ENOMEM; 1008 goto fail1; 1009 } 1010 1011 for (id = 0; id < nprops; id++) { 1012 sfxge_ndd_param_t *snpp = &(sp->s_ndp[id]); 1013 1014 snpp->snp_sp = sp; 1015 snpp->snp_id = id; 1016 snpp->snp_name = efx_phy_prop_name(enp, id); 1017 snpp->snp_get = sfxge_gld_nd_get_ioctl; 1018 snpp->snp_set = sfxge_gld_nd_set_ioctl; 1019 1020 ASSERT(snpp->snp_name != NULL); 1021 1022 (void) nd_load(ndhp, (char *)(snpp->snp_name), 1023 snpp->snp_get, snpp->snp_set, (caddr_t)snpp); 1024 } 1025 1026 for (id = 0; id < SFXGE_NPROPS; id++) { 1027 sfxge_ndd_param_t *snpp = &(sp->s_ndp[id + nprops]); 1028 1029 *snpp = sfxge_ndd_param[id]; 1030 ASSERT3U(snpp->snp_id, ==, id); 1031 1032 snpp->snp_sp = sp; 1033 snpp->snp_id += nprops; 1034 1035 (void) nd_load(ndhp, (char *)(snpp->snp_name), 1036 snpp->snp_get, snpp->snp_set, (caddr_t)snpp); 1037 } 1038 #endif 1039 1040 /* Also create a kstat set */ 1041 (void) snprintf(name, MAXNAMELEN - 1, "%s_ndd", 1042 ddi_driver_name(sp->s_dip)); 1043 1044 if ((ksp = kstat_create((char *)ddi_driver_name(sp->s_dip), 1045 ddi_get_instance(sp->s_dip), name, "ndd", KSTAT_TYPE_NAMED, 1046 (nprops + SFXGE_NPROPS), KSTAT_FLAG_WRITABLE)) == NULL) { 1047 rc = ENOMEM; 1048 goto fail2; 1049 } 1050 1051 sp->s_nd_ksp = ksp; 1052 1053 ksp->ks_update = sfxge_gld_nd_update; 1054 ksp->ks_private = sp; 1055 1056 sp->s_nd_stat = ksp->ks_data; 1057 1058 for (id = 0; id < nprops; id++) { 1059 kstat_named_t *knp = &(sp->s_nd_stat[id]); 1060 1061 kstat_named_init(knp, (char *)efx_phy_prop_name(enp, id), 1062 KSTAT_DATA_UINT32); 1063 } 1064 1065 for (id = 0; id < SFXGE_NPROPS; id++) { 1066 kstat_named_t *knp = &(sp->s_nd_stat[id + nprops]); 1067 sfxge_ndd_param_t *snpp = &sfxge_ndd_param[id]; 1068 1069 kstat_named_init(knp, (char *)(snpp->snp_name), 1070 KSTAT_DATA_UINT32); 1071 } 1072 1073 kstat_install(ksp); 1074 1075 return (0); 1076 1077 fail2: 1078 DTRACE_PROBE(fail2); 1079 1080 #ifdef _USE_NDD_PROPS 1081 nd_free(ndhp); 1082 sp->s_ndh = NULL; 1083 1084 kmem_free(sp->s_ndp, sizeof (sfxge_ndd_param_t) * 1085 (nprops + SFXGE_NPROPS)); 1086 sp->s_ndp = NULL; 1087 1088 fail1: 1089 DTRACE_PROBE1(fail1, int, rc); 1090 #endif 1091 1092 return (rc); 1093 } 1094 1095 1096 void 1097 sfxge_gld_nd_unregister(sfxge_t *sp) 1098 { 1099 #ifdef _USE_NDD_PROPS 1100 caddr_t *ndhp = &(sp->s_ndh); 1101 #endif 1102 efx_nic_t *enp = sp->s_enp; 1103 unsigned int nprops; 1104 1105 nprops = efx_nic_cfg_get(enp)->enc_phy_nprops; 1106 1107 /* Destroy the kstat set */ 1108 kstat_delete(sp->s_nd_ksp); 1109 sp->s_nd_ksp = NULL; 1110 sp->s_nd_stat = NULL; 1111 1112 /* Unregister from the NDD framework */ 1113 #ifdef _USE_NDD_PROPS 1114 nd_free(ndhp); 1115 1116 sp->s_ndh = NULL; 1117 1118 kmem_free(sp->s_ndp, sizeof (sfxge_ndd_param_t) * 1119 (nprops + SFXGE_NPROPS)); 1120 sp->s_ndp = NULL; 1121 #endif 1122 }