1 /* 2 * CDDL HEADER START 3 * 4 * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. 5 * The contents of this file are subject to the terms of the 6 * Common Development and Distribution License (the "License"). 7 * You may not use this file except in compliance with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #include "ixgbe_sw.h" 29 30 /* 31 * Retrieve a value for one of the statistics. 32 */ 33 int 34 ixgbe_m_stat(void *arg, uint_t stat, uint64_t *val) 35 { 36 ixgbe_t *ixgbe = (ixgbe_t *)arg; 37 struct ixgbe_hw *hw = &ixgbe->hw; 38 ixgbe_stat_t *ixgbe_ks; 39 int i; 40 41 ixgbe_ks = (ixgbe_stat_t *)ixgbe->ixgbe_ks->ks_data; 42 43 mutex_enter(&ixgbe->gen_lock); 44 45 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 46 mutex_exit(&ixgbe->gen_lock); 47 return (ECANCELED); 48 } 49 50 switch (stat) { 51 case MAC_STAT_IFSPEED: 52 *val = ixgbe->link_speed * 1000000ull; 53 break; 54 55 case MAC_STAT_MULTIRCV: 56 ixgbe_ks->mprc.value.ui64 += 57 IXGBE_READ_REG(hw, IXGBE_MPRC); 58 *val = ixgbe_ks->mprc.value.ui64; 59 break; 60 61 case MAC_STAT_BRDCSTRCV: 62 ixgbe_ks->bprc.value.ui64 += 63 IXGBE_READ_REG(hw, IXGBE_BPRC); 64 *val = ixgbe_ks->bprc.value.ui64; 65 break; 66 67 case MAC_STAT_MULTIXMT: 68 ixgbe_ks->mptc.value.ui64 += 69 IXGBE_READ_REG(hw, IXGBE_MPTC); 70 *val = ixgbe_ks->mptc.value.ui64; 71 break; 72 73 case MAC_STAT_BRDCSTXMT: 74 ixgbe_ks->bptc.value.ui64 += 75 IXGBE_READ_REG(hw, IXGBE_BPTC); 76 *val = ixgbe_ks->bptc.value.ui64; 77 break; 78 79 case MAC_STAT_NORCVBUF: 80 for (i = 0; i < 8; i++) { 81 ixgbe_ks->rnbc.value.ui64 += 82 IXGBE_READ_REG(hw, IXGBE_RNBC(i)); 83 } 84 *val = ixgbe_ks->rnbc.value.ui64; 85 break; 86 87 case MAC_STAT_IERRORS: 88 ixgbe_ks->crcerrs.value.ui64 += 89 IXGBE_READ_REG(hw, IXGBE_CRCERRS); 90 ixgbe_ks->illerrc.value.ui64 += 91 IXGBE_READ_REG(hw, IXGBE_ILLERRC); 92 ixgbe_ks->errbc.value.ui64 += 93 IXGBE_READ_REG(hw, IXGBE_ERRBC); 94 ixgbe_ks->rlec.value.ui64 += 95 IXGBE_READ_REG(hw, IXGBE_RLEC); 96 *val = ixgbe_ks->crcerrs.value.ui64 + 97 ixgbe_ks->illerrc.value.ui64 + 98 ixgbe_ks->errbc.value.ui64 + 99 ixgbe_ks->rlec.value.ui64; 100 break; 101 102 case MAC_STAT_RBYTES: 103 ixgbe_ks->tor.value.ui64 = 0; 104 for (i = 0; i < 16; i++) { 105 ixgbe_ks->qbrc[i].value.ui64 += 106 IXGBE_READ_REG(hw, IXGBE_QBRC(i)); 107 ixgbe_ks->tor.value.ui64 += 108 ixgbe_ks->qbrc[i].value.ui64; 109 } 110 *val = ixgbe_ks->tor.value.ui64; 111 break; 112 113 case MAC_STAT_OBYTES: 114 ixgbe_ks->tot.value.ui64 = 0; 115 for (i = 0; i < 16; i++) { 116 if (hw->mac.type >= ixgbe_mac_82599EB) { 117 ixgbe_ks->qbtc[i].value.ui64 += 118 IXGBE_READ_REG(hw, IXGBE_QBTC_L(i)); 119 ixgbe_ks->qbtc[i].value.ui64 += ((uint64_t) 120 IXGBE_READ_REG(hw, IXGBE_QBTC_H(i))) << 32; 121 } else { 122 ixgbe_ks->qbtc[i].value.ui64 += 123 IXGBE_READ_REG(hw, IXGBE_QBTC(i)); 124 } 125 ixgbe_ks->tot.value.ui64 += 126 ixgbe_ks->qbtc[i].value.ui64; 127 } 128 *val = ixgbe_ks->tot.value.ui64; 129 break; 130 131 case MAC_STAT_IPACKETS: 132 ixgbe_ks->tpr.value.ui64 += 133 IXGBE_READ_REG(hw, IXGBE_TPR); 134 *val = ixgbe_ks->tpr.value.ui64; 135 break; 136 137 case MAC_STAT_OPACKETS: 138 ixgbe_ks->tpt.value.ui64 += 139 IXGBE_READ_REG(hw, IXGBE_TPT); 140 *val = ixgbe_ks->tpt.value.ui64; 141 break; 142 143 /* RFC 1643 stats */ 144 case ETHER_STAT_FCS_ERRORS: 145 ixgbe_ks->crcerrs.value.ui64 += 146 IXGBE_READ_REG(hw, IXGBE_CRCERRS); 147 *val = ixgbe_ks->crcerrs.value.ui64; 148 break; 149 150 case ETHER_STAT_TOOLONG_ERRORS: 151 ixgbe_ks->roc.value.ui64 += 152 IXGBE_READ_REG(hw, IXGBE_ROC); 153 *val = ixgbe_ks->roc.value.ui64; 154 break; 155 156 case ETHER_STAT_MACRCV_ERRORS: 157 ixgbe_ks->crcerrs.value.ui64 += 158 IXGBE_READ_REG(hw, IXGBE_CRCERRS); 159 ixgbe_ks->illerrc.value.ui64 += 160 IXGBE_READ_REG(hw, IXGBE_ILLERRC); 161 ixgbe_ks->errbc.value.ui64 += 162 IXGBE_READ_REG(hw, IXGBE_ERRBC); 163 ixgbe_ks->rlec.value.ui64 += 164 IXGBE_READ_REG(hw, IXGBE_RLEC); 165 *val = ixgbe_ks->crcerrs.value.ui64 + 166 ixgbe_ks->illerrc.value.ui64 + 167 ixgbe_ks->errbc.value.ui64 + 168 ixgbe_ks->rlec.value.ui64; 169 break; 170 171 /* MII/GMII stats */ 172 case ETHER_STAT_XCVR_ADDR: 173 /* The Internal PHY's MDI address for each MAC is 1 */ 174 *val = 1; 175 break; 176 177 case ETHER_STAT_XCVR_ID: 178 *val = hw->phy.id; 179 break; 180 181 case ETHER_STAT_XCVR_INUSE: 182 switch (ixgbe->link_speed) { 183 case IXGBE_LINK_SPEED_1GB_FULL: 184 *val = 185 (hw->phy.media_type == ixgbe_media_type_copper) ? 186 XCVR_1000T : XCVR_1000X; 187 break; 188 case IXGBE_LINK_SPEED_100_FULL: 189 *val = (hw->phy.media_type == ixgbe_media_type_copper) ? 190 XCVR_100T2 : XCVR_100X; 191 break; 192 default: 193 *val = XCVR_NONE; 194 break; 195 } 196 break; 197 198 case ETHER_STAT_CAP_10GFDX: 199 *val = 1; 200 break; 201 202 case ETHER_STAT_CAP_1000FDX: 203 *val = 1; 204 break; 205 206 case ETHER_STAT_CAP_100FDX: 207 *val = 1; 208 break; 209 210 case ETHER_STAT_CAP_ASMPAUSE: 211 *val = ixgbe->param_asym_pause_cap; 212 break; 213 214 case ETHER_STAT_CAP_PAUSE: 215 *val = ixgbe->param_pause_cap; 216 break; 217 218 case ETHER_STAT_CAP_AUTONEG: 219 *val = 1; 220 break; 221 222 case ETHER_STAT_ADV_CAP_10GFDX: 223 *val = ixgbe->param_adv_10000fdx_cap; 224 break; 225 226 case ETHER_STAT_ADV_CAP_1000FDX: 227 *val = ixgbe->param_adv_1000fdx_cap; 228 break; 229 230 case ETHER_STAT_ADV_CAP_100FDX: 231 *val = ixgbe->param_adv_100fdx_cap; 232 break; 233 234 case ETHER_STAT_ADV_CAP_ASMPAUSE: 235 *val = ixgbe->param_adv_asym_pause_cap; 236 break; 237 238 case ETHER_STAT_ADV_CAP_PAUSE: 239 *val = ixgbe->param_adv_pause_cap; 240 break; 241 242 case ETHER_STAT_ADV_CAP_AUTONEG: 243 *val = ixgbe->param_adv_autoneg_cap; 244 break; 245 246 case ETHER_STAT_LP_CAP_10GFDX: 247 *val = ixgbe->param_lp_10000fdx_cap; 248 break; 249 250 case ETHER_STAT_LP_CAP_1000FDX: 251 *val = ixgbe->param_lp_1000fdx_cap; 252 break; 253 254 case ETHER_STAT_LP_CAP_100FDX: 255 *val = ixgbe->param_lp_100fdx_cap; 256 break; 257 258 case ETHER_STAT_LP_CAP_ASMPAUSE: 259 *val = ixgbe->param_lp_asym_pause_cap; 260 break; 261 262 case ETHER_STAT_LP_CAP_PAUSE: 263 *val = ixgbe->param_lp_pause_cap; 264 break; 265 266 case ETHER_STAT_LP_CAP_AUTONEG: 267 *val = ixgbe->param_lp_autoneg_cap; 268 break; 269 270 case ETHER_STAT_LINK_ASMPAUSE: 271 *val = ixgbe->param_asym_pause_cap; 272 break; 273 274 case ETHER_STAT_LINK_PAUSE: 275 *val = ixgbe->param_pause_cap; 276 break; 277 278 case ETHER_STAT_LINK_AUTONEG: 279 *val = ixgbe->param_adv_autoneg_cap; 280 break; 281 282 case ETHER_STAT_LINK_DUPLEX: 283 *val = LINK_DUPLEX_FULL; 284 break; 285 286 case ETHER_STAT_TOOSHORT_ERRORS: 287 ixgbe_ks->ruc.value.ui64 += 288 IXGBE_READ_REG(hw, IXGBE_RUC); 289 *val = ixgbe_ks->ruc.value.ui64; 290 break; 291 292 case ETHER_STAT_CAP_REMFAULT: 293 *val = ixgbe->param_rem_fault; 294 break; 295 296 case ETHER_STAT_ADV_REMFAULT: 297 *val = ixgbe->param_adv_rem_fault; 298 break; 299 300 case ETHER_STAT_LP_REMFAULT: 301 *val = ixgbe->param_lp_rem_fault; 302 break; 303 304 case ETHER_STAT_JABBER_ERRORS: 305 ixgbe_ks->rjc.value.ui64 += 306 IXGBE_READ_REG(hw, IXGBE_RJC); 307 *val = ixgbe_ks->rjc.value.ui64; 308 break; 309 310 default: 311 mutex_exit(&ixgbe->gen_lock); 312 return (ENOTSUP); 313 } 314 315 mutex_exit(&ixgbe->gen_lock); 316 317 if (ixgbe_check_acc_handle(ixgbe->osdep.reg_handle) != DDI_FM_OK) 318 ddi_fm_service_impact(ixgbe->dip, DDI_SERVICE_UNAFFECTED); 319 320 return (0); 321 } 322 323 /* 324 * Bring the device out of the reset/quiesced state that it 325 * was in when the interface was registered. 326 */ 327 int 328 ixgbe_m_start(void *arg) 329 { 330 ixgbe_t *ixgbe = (ixgbe_t *)arg; 331 332 mutex_enter(&ixgbe->gen_lock); 333 334 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 335 mutex_exit(&ixgbe->gen_lock); 336 return (ECANCELED); 337 } 338 339 if (ixgbe_start(ixgbe, B_TRUE) != IXGBE_SUCCESS) { 340 mutex_exit(&ixgbe->gen_lock); 341 return (EIO); 342 } 343 344 ixgbe->ixgbe_state |= IXGBE_STARTED; 345 346 mutex_exit(&ixgbe->gen_lock); 347 348 /* 349 * Enable and start the watchdog timer 350 */ 351 ixgbe_enable_watchdog_timer(ixgbe); 352 353 return (0); 354 } 355 356 /* 357 * Stop the device and put it in a reset/quiesced state such 358 * that the interface can be unregistered. 359 */ 360 void 361 ixgbe_m_stop(void *arg) 362 { 363 ixgbe_t *ixgbe = (ixgbe_t *)arg; 364 365 mutex_enter(&ixgbe->gen_lock); 366 367 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 368 mutex_exit(&ixgbe->gen_lock); 369 return; 370 } 371 372 ixgbe->ixgbe_state &= ~IXGBE_STARTED; 373 374 ixgbe_stop(ixgbe, B_TRUE); 375 376 mutex_exit(&ixgbe->gen_lock); 377 378 /* 379 * Disable and stop the watchdog timer 380 */ 381 ixgbe_disable_watchdog_timer(ixgbe); 382 } 383 384 /* 385 * Set the promiscuity of the device. 386 */ 387 int 388 ixgbe_m_promisc(void *arg, boolean_t on) 389 { 390 ixgbe_t *ixgbe = (ixgbe_t *)arg; 391 uint32_t reg_val; 392 struct ixgbe_hw *hw = &ixgbe->hw; 393 394 mutex_enter(&ixgbe->gen_lock); 395 396 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 397 mutex_exit(&ixgbe->gen_lock); 398 return (ECANCELED); 399 } 400 reg_val = IXGBE_READ_REG(hw, IXGBE_FCTRL); 401 402 if (on) 403 reg_val |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 404 else 405 reg_val &= (~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE)); 406 407 IXGBE_WRITE_REG(&ixgbe->hw, IXGBE_FCTRL, reg_val); 408 409 mutex_exit(&ixgbe->gen_lock); 410 411 return (0); 412 } 413 414 /* 415 * Add/remove the addresses to/from the set of multicast 416 * addresses for which the device will receive packets. 417 */ 418 int 419 ixgbe_m_multicst(void *arg, boolean_t add, const uint8_t *mcst_addr) 420 { 421 ixgbe_t *ixgbe = (ixgbe_t *)arg; 422 int result; 423 424 mutex_enter(&ixgbe->gen_lock); 425 426 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 427 mutex_exit(&ixgbe->gen_lock); 428 return (ECANCELED); 429 } 430 431 result = (add) ? ixgbe_multicst_add(ixgbe, mcst_addr) 432 : ixgbe_multicst_remove(ixgbe, mcst_addr); 433 434 mutex_exit(&ixgbe->gen_lock); 435 436 return (result); 437 } 438 439 /* 440 * Pass on M_IOCTL messages passed to the DLD, and support 441 * private IOCTLs for debugging and ndd. 442 */ 443 void 444 ixgbe_m_ioctl(void *arg, queue_t *q, mblk_t *mp) 445 { 446 ixgbe_t *ixgbe = (ixgbe_t *)arg; 447 struct iocblk *iocp; 448 enum ioc_reply status; 449 450 iocp = (struct iocblk *)(uintptr_t)mp->b_rptr; 451 iocp->ioc_error = 0; 452 453 mutex_enter(&ixgbe->gen_lock); 454 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 455 mutex_exit(&ixgbe->gen_lock); 456 miocnak(q, mp, 0, EINVAL); 457 return; 458 } 459 mutex_exit(&ixgbe->gen_lock); 460 461 switch (iocp->ioc_cmd) { 462 case LB_GET_INFO_SIZE: 463 case LB_GET_INFO: 464 case LB_GET_MODE: 465 case LB_SET_MODE: 466 status = ixgbe_loopback_ioctl(ixgbe, iocp, mp); 467 break; 468 469 default: 470 status = IOC_INVAL; 471 break; 472 } 473 474 /* 475 * Decide how to reply 476 */ 477 switch (status) { 478 default: 479 case IOC_INVAL: 480 /* 481 * Error, reply with a NAK and EINVAL or the specified error 482 */ 483 miocnak(q, mp, 0, iocp->ioc_error == 0 ? 484 EINVAL : iocp->ioc_error); 485 break; 486 487 case IOC_DONE: 488 /* 489 * OK, reply already sent 490 */ 491 break; 492 493 case IOC_ACK: 494 /* 495 * OK, reply with an ACK 496 */ 497 miocack(q, mp, 0, 0); 498 break; 499 500 case IOC_REPLY: 501 /* 502 * OK, send prepared reply as ACK or NAK 503 */ 504 mp->b_datap->db_type = iocp->ioc_error == 0 ? 505 M_IOCACK : M_IOCNAK; 506 qreply(q, mp); 507 break; 508 } 509 } 510 511 /* 512 * Obtain the MAC's capabilities and associated data from 513 * the driver. 514 */ 515 boolean_t 516 ixgbe_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 517 { 518 ixgbe_t *ixgbe = (ixgbe_t *)arg; 519 520 switch (cap) { 521 case MAC_CAPAB_HCKSUM: { 522 uint32_t *tx_hcksum_flags = cap_data; 523 524 /* 525 * We advertise our capabilities only if tx hcksum offload is 526 * enabled. On receive, the stack will accept checksummed 527 * packets anyway, even if we haven't said we can deliver 528 * them. 529 */ 530 if (!ixgbe->tx_hcksum_enable) 531 return (B_FALSE); 532 533 *tx_hcksum_flags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM; 534 break; 535 } 536 case MAC_CAPAB_LSO: { 537 mac_capab_lso_t *cap_lso = cap_data; 538 539 if (ixgbe->lso_enable) { 540 cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 541 cap_lso->lso_basic_tcp_ipv4.lso_max = IXGBE_LSO_MAXLEN; 542 break; 543 } else { 544 return (B_FALSE); 545 } 546 } 547 case MAC_CAPAB_RINGS: { 548 mac_capab_rings_t *cap_rings = cap_data; 549 550 switch (cap_rings->mr_type) { 551 case MAC_RING_TYPE_RX: 552 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 553 cap_rings->mr_rnum = ixgbe->num_rx_rings; 554 cap_rings->mr_gnum = ixgbe->num_rx_groups; 555 cap_rings->mr_rget = ixgbe_fill_ring; 556 cap_rings->mr_gget = ixgbe_fill_group; 557 cap_rings->mr_gaddring = NULL; 558 cap_rings->mr_gremring = NULL; 559 break; 560 case MAC_RING_TYPE_TX: 561 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 562 cap_rings->mr_rnum = ixgbe->num_tx_rings; 563 cap_rings->mr_gnum = 0; 564 cap_rings->mr_rget = ixgbe_fill_ring; 565 cap_rings->mr_gget = NULL; 566 break; 567 default: 568 break; 569 } 570 break; 571 } 572 default: 573 return (B_FALSE); 574 } 575 return (B_TRUE); 576 } 577 578 int 579 ixgbe_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 580 uint_t pr_valsize, const void *pr_val) 581 { 582 ixgbe_t *ixgbe = (ixgbe_t *)arg; 583 struct ixgbe_hw *hw = &ixgbe->hw; 584 int err = 0; 585 uint32_t flow_control; 586 uint32_t cur_mtu, new_mtu; 587 uint32_t rx_size; 588 uint32_t tx_size; 589 590 mutex_enter(&ixgbe->gen_lock); 591 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 592 mutex_exit(&ixgbe->gen_lock); 593 return (ECANCELED); 594 } 595 596 if (ixgbe->loopback_mode != IXGBE_LB_NONE && 597 ixgbe_param_locked(pr_num)) { 598 /* 599 * All en_* parameters are locked (read-only) 600 * while the device is in any sort of loopback mode. 601 */ 602 mutex_exit(&ixgbe->gen_lock); 603 return (EBUSY); 604 } 605 606 switch (pr_num) { 607 case MAC_PROP_EN_10GFDX_CAP: 608 /* read/write on copper, read-only on serdes */ 609 if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) { 610 err = ENOTSUP; 611 break; 612 } else { 613 ixgbe->param_en_10000fdx_cap = *(uint8_t *)pr_val; 614 ixgbe->param_adv_10000fdx_cap = *(uint8_t *)pr_val; 615 goto setup_link; 616 } 617 case MAC_PROP_EN_1000FDX_CAP: 618 /* read/write on copper, read-only on serdes */ 619 if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) { 620 err = ENOTSUP; 621 break; 622 } else { 623 ixgbe->param_en_1000fdx_cap = *(uint8_t *)pr_val; 624 ixgbe->param_adv_1000fdx_cap = *(uint8_t *)pr_val; 625 goto setup_link; 626 } 627 case MAC_PROP_EN_100FDX_CAP: 628 /* read/write on copper, read-only on serdes */ 629 if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) { 630 err = ENOTSUP; 631 break; 632 } else { 633 ixgbe->param_en_100fdx_cap = *(uint8_t *)pr_val; 634 ixgbe->param_adv_100fdx_cap = *(uint8_t *)pr_val; 635 goto setup_link; 636 } 637 case MAC_PROP_AUTONEG: 638 /* read/write on copper, read-only on serdes */ 639 if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) { 640 err = ENOTSUP; 641 break; 642 } else { 643 ixgbe->param_adv_autoneg_cap = *(uint8_t *)pr_val; 644 goto setup_link; 645 } 646 case MAC_PROP_FLOWCTRL: 647 bcopy(pr_val, &flow_control, sizeof (flow_control)); 648 649 switch (flow_control) { 650 default: 651 err = EINVAL; 652 break; 653 case LINK_FLOWCTRL_NONE: 654 hw->fc.requested_mode = ixgbe_fc_none; 655 break; 656 case LINK_FLOWCTRL_RX: 657 hw->fc.requested_mode = ixgbe_fc_rx_pause; 658 break; 659 case LINK_FLOWCTRL_TX: 660 hw->fc.requested_mode = ixgbe_fc_tx_pause; 661 break; 662 case LINK_FLOWCTRL_BI: 663 hw->fc.requested_mode = ixgbe_fc_full; 664 break; 665 } 666 setup_link: 667 if (err == 0) { 668 if (ixgbe_driver_setup_link(ixgbe, B_TRUE) != 669 IXGBE_SUCCESS) 670 err = EINVAL; 671 } 672 break; 673 case MAC_PROP_ADV_10GFDX_CAP: 674 case MAC_PROP_ADV_1000FDX_CAP: 675 case MAC_PROP_ADV_100FDX_CAP: 676 case MAC_PROP_STATUS: 677 case MAC_PROP_SPEED: 678 case MAC_PROP_DUPLEX: 679 err = ENOTSUP; /* read-only prop. Can't set this. */ 680 break; 681 case MAC_PROP_MTU: 682 cur_mtu = ixgbe->default_mtu; 683 bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 684 if (new_mtu == cur_mtu) { 685 err = 0; 686 break; 687 } 688 689 if (new_mtu < DEFAULT_MTU || new_mtu > ixgbe->capab->max_mtu) { 690 err = EINVAL; 691 break; 692 } 693 694 if (ixgbe->ixgbe_state & IXGBE_STARTED) { 695 err = EBUSY; 696 break; 697 } 698 699 err = mac_maxsdu_update(ixgbe->mac_hdl, new_mtu); 700 if (err == 0) { 701 ixgbe->default_mtu = new_mtu; 702 ixgbe->max_frame_size = ixgbe->default_mtu + 703 sizeof (struct ether_vlan_header) + ETHERFCSL; 704 705 /* 706 * Set rx buffer size 707 */ 708 rx_size = ixgbe->max_frame_size + IPHDR_ALIGN_ROOM; 709 ixgbe->rx_buf_size = ((rx_size >> 10) + ((rx_size & 710 (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10; 711 712 /* 713 * Set tx buffer size 714 */ 715 tx_size = ixgbe->max_frame_size; 716 ixgbe->tx_buf_size = ((tx_size >> 10) + ((tx_size & 717 (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10; 718 } 719 break; 720 case MAC_PROP_PRIVATE: 721 err = ixgbe_set_priv_prop(ixgbe, pr_name, pr_valsize, pr_val); 722 break; 723 default: 724 err = EINVAL; 725 break; 726 } 727 mutex_exit(&ixgbe->gen_lock); 728 return (err); 729 } 730 731 int 732 ixgbe_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 733 uint_t pr_flags, uint_t pr_valsize, void *pr_val, uint_t *perm) 734 { 735 ixgbe_t *ixgbe = (ixgbe_t *)arg; 736 struct ixgbe_hw *hw = &ixgbe->hw; 737 int err = 0; 738 uint32_t flow_control; 739 uint64_t tmp = 0; 740 boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT); 741 mac_propval_range_t range; 742 743 if (pr_valsize == 0) 744 return (EINVAL); 745 746 *perm = MAC_PROP_PERM_READ; 747 748 bzero(pr_val, pr_valsize); 749 750 switch (pr_num) { 751 case MAC_PROP_DUPLEX: 752 if (pr_valsize >= sizeof (link_duplex_t)) { 753 bcopy(&ixgbe->link_duplex, pr_val, 754 sizeof (link_duplex_t)); 755 } else 756 err = EINVAL; 757 break; 758 case MAC_PROP_SPEED: 759 if (pr_valsize >= sizeof (uint64_t)) { 760 tmp = ixgbe->link_speed * 1000000ull; 761 bcopy(&tmp, pr_val, sizeof (tmp)); 762 } else 763 err = EINVAL; 764 break; 765 case MAC_PROP_AUTONEG: 766 if (ixgbe->hw.phy.media_type == ixgbe_media_type_copper) 767 *perm = MAC_PROP_PERM_RW; 768 *(uint8_t *)pr_val = 769 (is_default ? 1 : ixgbe->param_adv_autoneg_cap); 770 break; 771 case MAC_PROP_FLOWCTRL: 772 *perm = MAC_PROP_PERM_RW; 773 if (pr_valsize >= sizeof (uint32_t)) { 774 if (is_default) { 775 flow_control = LINK_FLOWCTRL_NONE; 776 bcopy(&flow_control, pr_val, 777 sizeof (flow_control)); 778 break; 779 } 780 switch (hw->fc.requested_mode) { 781 case ixgbe_fc_none: 782 flow_control = LINK_FLOWCTRL_NONE; 783 break; 784 case ixgbe_fc_rx_pause: 785 flow_control = LINK_FLOWCTRL_RX; 786 break; 787 case ixgbe_fc_tx_pause: 788 flow_control = LINK_FLOWCTRL_TX; 789 break; 790 case ixgbe_fc_full: 791 flow_control = LINK_FLOWCTRL_BI; 792 break; 793 } 794 bcopy(&flow_control, pr_val, sizeof (flow_control)); 795 } else 796 err = EINVAL; 797 break; 798 case MAC_PROP_ADV_10GFDX_CAP: 799 *(uint8_t *)pr_val = (is_default ? 1 : 800 ixgbe->param_adv_10000fdx_cap); 801 break; 802 case MAC_PROP_EN_10GFDX_CAP: 803 if (ixgbe->hw.phy.media_type == ixgbe_media_type_copper) 804 *perm = MAC_PROP_PERM_RW; 805 *(uint8_t *)pr_val = 806 (is_default ? 1 : ixgbe->param_en_10000fdx_cap); 807 break; 808 case MAC_PROP_ADV_1000FDX_CAP: 809 *(uint8_t *)pr_val = (is_default ? 1 : 810 ixgbe->param_adv_1000fdx_cap); 811 break; 812 case MAC_PROP_EN_1000FDX_CAP: 813 if (ixgbe->hw.phy.media_type == ixgbe_media_type_copper) 814 *perm = MAC_PROP_PERM_RW; 815 *(uint8_t *)pr_val = 816 (is_default ? 1 : ixgbe->param_en_1000fdx_cap); 817 break; 818 case MAC_PROP_ADV_100FDX_CAP: 819 *(uint8_t *)pr_val = 820 (is_default ? 1 : ixgbe->param_adv_100fdx_cap); 821 break; 822 case MAC_PROP_EN_100FDX_CAP: 823 if (ixgbe->hw.phy.media_type == ixgbe_media_type_copper) 824 *perm = MAC_PROP_PERM_RW; 825 *(uint8_t *)pr_val = 826 (is_default ? 1 : ixgbe->param_en_100fdx_cap); 827 break; 828 case MAC_PROP_PRIVATE: 829 err = ixgbe_get_priv_prop(ixgbe, pr_name, 830 pr_flags, pr_valsize, pr_val, perm); 831 break; 832 case MAC_PROP_MTU: 833 if (!(pr_flags & MAC_PROP_POSSIBLE)) 834 return (ENOTSUP); 835 if (pr_valsize < sizeof (mac_propval_range_t)) 836 return (EINVAL); 837 range.mpr_count = 1; 838 range.mpr_type = MAC_PROPVAL_UINT32; 839 range.range_uint32[0].mpur_min = DEFAULT_MTU; 840 range.range_uint32[0].mpur_max = ixgbe->capab->max_mtu; 841 bcopy(&range, pr_val, sizeof (range)); 842 break; 843 default: 844 err = EINVAL; 845 break; 846 } 847 return (err); 848 } 849 850 boolean_t 851 ixgbe_param_locked(mac_prop_id_t pr_num) 852 { 853 /* 854 * All en_* parameters are locked (read-only) while 855 * the device is in any sort of loopback mode ... 856 */ 857 switch (pr_num) { 858 case MAC_PROP_EN_10GFDX_CAP: 859 case MAC_PROP_EN_1000FDX_CAP: 860 case MAC_PROP_EN_100FDX_CAP: 861 case MAC_PROP_AUTONEG: 862 case MAC_PROP_FLOWCTRL: 863 return (B_TRUE); 864 } 865 return (B_FALSE); 866 } 867 868 /* ARGSUSED */ 869 int 870 ixgbe_set_priv_prop(ixgbe_t *ixgbe, const char *pr_name, 871 uint_t pr_valsize, const void *pr_val) 872 { 873 int err = 0; 874 long result; 875 struct ixgbe_hw *hw = &ixgbe->hw; 876 int i; 877 878 if (strcmp(pr_name, "_tx_copy_thresh") == 0) { 879 if (pr_val == NULL) { 880 err = EINVAL; 881 return (err); 882 } 883 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 884 if (result < MIN_TX_COPY_THRESHOLD || 885 result > MAX_TX_COPY_THRESHOLD) 886 err = EINVAL; 887 else { 888 ixgbe->tx_copy_thresh = (uint32_t)result; 889 } 890 return (err); 891 } 892 if (strcmp(pr_name, "_tx_recycle_thresh") == 0) { 893 if (pr_val == NULL) { 894 err = EINVAL; 895 return (err); 896 } 897 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 898 if (result < MIN_TX_RECYCLE_THRESHOLD || 899 result > MAX_TX_RECYCLE_THRESHOLD) 900 err = EINVAL; 901 else { 902 ixgbe->tx_recycle_thresh = (uint32_t)result; 903 } 904 return (err); 905 } 906 if (strcmp(pr_name, "_tx_overload_thresh") == 0) { 907 if (pr_val == NULL) { 908 err = EINVAL; 909 return (err); 910 } 911 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 912 if (result < MIN_TX_OVERLOAD_THRESHOLD || 913 result > MAX_TX_OVERLOAD_THRESHOLD) 914 err = EINVAL; 915 else { 916 ixgbe->tx_overload_thresh = (uint32_t)result; 917 } 918 return (err); 919 } 920 if (strcmp(pr_name, "_tx_resched_thresh") == 0) { 921 if (pr_val == NULL) { 922 err = EINVAL; 923 return (err); 924 } 925 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 926 if (result < MIN_TX_RESCHED_THRESHOLD || 927 result > MAX_TX_RESCHED_THRESHOLD) 928 err = EINVAL; 929 else { 930 ixgbe->tx_resched_thresh = (uint32_t)result; 931 } 932 return (err); 933 } 934 if (strcmp(pr_name, "_rx_copy_thresh") == 0) { 935 if (pr_val == NULL) { 936 err = EINVAL; 937 return (err); 938 } 939 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 940 if (result < MIN_RX_COPY_THRESHOLD || 941 result > MAX_RX_COPY_THRESHOLD) 942 err = EINVAL; 943 else { 944 ixgbe->rx_copy_thresh = (uint32_t)result; 945 } 946 return (err); 947 } 948 if (strcmp(pr_name, "_rx_limit_per_intr") == 0) { 949 if (pr_val == NULL) { 950 err = EINVAL; 951 return (err); 952 } 953 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 954 if (result < MIN_RX_LIMIT_PER_INTR || 955 result > MAX_RX_LIMIT_PER_INTR) 956 err = EINVAL; 957 else { 958 ixgbe->rx_limit_per_intr = (uint32_t)result; 959 } 960 return (err); 961 } 962 if (strcmp(pr_name, "_intr_throttling") == 0) { 963 if (pr_val == NULL) { 964 err = EINVAL; 965 return (err); 966 } 967 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 968 969 if (result < ixgbe->capab->min_intr_throttle || 970 result > ixgbe->capab->max_intr_throttle) 971 err = EINVAL; 972 else { 973 ixgbe->intr_throttling[0] = (uint32_t)result; 974 975 /* 976 * 82599 requires the interupt throttling rate is 977 * a multiple of 8. This is enforced by the register 978 * definiton. 979 */ 980 if (hw->mac.type == ixgbe_mac_82599EB) 981 ixgbe->intr_throttling[0] = 982 ixgbe->intr_throttling[0] & 0xFF8; 983 984 for (i = 0; i < MAX_INTR_VECTOR; i++) 985 ixgbe->intr_throttling[i] = 986 ixgbe->intr_throttling[0]; 987 988 /* Set interrupt throttling rate */ 989 for (i = 0; i < ixgbe->intr_cnt; i++) 990 IXGBE_WRITE_REG(hw, IXGBE_EITR(i), 991 ixgbe->intr_throttling[i]); 992 } 993 return (err); 994 } 995 return (ENOTSUP); 996 } 997 998 int 999 ixgbe_get_priv_prop(ixgbe_t *ixgbe, const char *pr_name, 1000 uint_t pr_flags, uint_t pr_valsize, void *pr_val, uint_t *perm) 1001 { 1002 int err = ENOTSUP; 1003 boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT); 1004 int value; 1005 1006 *perm = MAC_PROP_PERM_RW; 1007 1008 if (strcmp(pr_name, "_adv_pause_cap") == 0) { 1009 *perm = MAC_PROP_PERM_READ; 1010 value = (is_default ? 1 : ixgbe->param_adv_pause_cap); 1011 err = 0; 1012 goto done; 1013 } 1014 if (strcmp(pr_name, "_adv_asym_pause_cap") == 0) { 1015 *perm = MAC_PROP_PERM_READ; 1016 value = (is_default ? 1 : ixgbe->param_adv_asym_pause_cap); 1017 err = 0; 1018 goto done; 1019 } 1020 if (strcmp(pr_name, "_tx_copy_thresh") == 0) { 1021 value = (is_default ? DEFAULT_TX_COPY_THRESHOLD : 1022 ixgbe->tx_copy_thresh); 1023 err = 0; 1024 goto done; 1025 } 1026 if (strcmp(pr_name, "_tx_recycle_thresh") == 0) { 1027 value = (is_default ? DEFAULT_TX_RECYCLE_THRESHOLD : 1028 ixgbe->tx_recycle_thresh); 1029 err = 0; 1030 goto done; 1031 } 1032 if (strcmp(pr_name, "_tx_overload_thresh") == 0) { 1033 value = (is_default ? DEFAULT_TX_OVERLOAD_THRESHOLD : 1034 ixgbe->tx_overload_thresh); 1035 err = 0; 1036 goto done; 1037 } 1038 if (strcmp(pr_name, "_tx_resched_thresh") == 0) { 1039 value = (is_default ? DEFAULT_TX_RESCHED_THRESHOLD : 1040 ixgbe->tx_resched_thresh); 1041 err = 0; 1042 goto done; 1043 } 1044 if (strcmp(pr_name, "_rx_copy_thresh") == 0) { 1045 value = (is_default ? DEFAULT_RX_COPY_THRESHOLD : 1046 ixgbe->rx_copy_thresh); 1047 err = 0; 1048 goto done; 1049 } 1050 if (strcmp(pr_name, "_rx_limit_per_intr") == 0) { 1051 value = (is_default ? DEFAULT_RX_LIMIT_PER_INTR : 1052 ixgbe->rx_limit_per_intr); 1053 err = 0; 1054 goto done; 1055 } 1056 if (strcmp(pr_name, "_intr_throttling") == 0) { 1057 value = (is_default ? ixgbe->capab->def_intr_throttle : 1058 ixgbe->intr_throttling[0]); 1059 err = 0; 1060 goto done; 1061 } 1062 done: 1063 if (err == 0) { 1064 (void) snprintf(pr_val, pr_valsize, "%d", value); 1065 } 1066 return (err); 1067 } 1068