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 = ixgbe->link_duplex; 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_DEGRADED); 319 return (EIO); 320 } 321 322 return (0); 323 } 324 325 /* 326 * Bring the device out of the reset/quiesced state that it 327 * was in when the interface was registered. 328 */ 329 int 330 ixgbe_m_start(void *arg) 331 { 332 ixgbe_t *ixgbe = (ixgbe_t *)arg; 333 334 mutex_enter(&ixgbe->gen_lock); 335 336 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 337 mutex_exit(&ixgbe->gen_lock); 338 return (ECANCELED); 339 } 340 341 if (ixgbe_start(ixgbe, B_TRUE) != IXGBE_SUCCESS) { 342 mutex_exit(&ixgbe->gen_lock); 343 return (EIO); 344 } 345 346 atomic_or_32(&ixgbe->ixgbe_state, IXGBE_STARTED); 347 348 mutex_exit(&ixgbe->gen_lock); 349 350 /* 351 * Enable and start the watchdog timer 352 */ 353 ixgbe_enable_watchdog_timer(ixgbe); 354 355 return (0); 356 } 357 358 /* 359 * Stop the device and put it in a reset/quiesced state such 360 * that the interface can be unregistered. 361 */ 362 void 363 ixgbe_m_stop(void *arg) 364 { 365 ixgbe_t *ixgbe = (ixgbe_t *)arg; 366 367 mutex_enter(&ixgbe->gen_lock); 368 369 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 370 mutex_exit(&ixgbe->gen_lock); 371 return; 372 } 373 374 atomic_and_32(&ixgbe->ixgbe_state, ~IXGBE_STARTED); 375 376 ixgbe_stop(ixgbe, B_TRUE); 377 378 mutex_exit(&ixgbe->gen_lock); 379 380 /* 381 * Disable and stop the watchdog timer 382 */ 383 ixgbe_disable_watchdog_timer(ixgbe); 384 } 385 386 /* 387 * Set the promiscuity of the device. 388 */ 389 int 390 ixgbe_m_promisc(void *arg, boolean_t on) 391 { 392 ixgbe_t *ixgbe = (ixgbe_t *)arg; 393 uint32_t reg_val; 394 struct ixgbe_hw *hw = &ixgbe->hw; 395 396 mutex_enter(&ixgbe->gen_lock); 397 398 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 399 mutex_exit(&ixgbe->gen_lock); 400 return (ECANCELED); 401 } 402 reg_val = IXGBE_READ_REG(hw, IXGBE_FCTRL); 403 404 if (on) 405 reg_val |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 406 else 407 reg_val &= (~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE)); 408 409 IXGBE_WRITE_REG(&ixgbe->hw, IXGBE_FCTRL, reg_val); 410 411 mutex_exit(&ixgbe->gen_lock); 412 413 return (0); 414 } 415 416 /* 417 * Add/remove the addresses to/from the set of multicast 418 * addresses for which the device will receive packets. 419 */ 420 int 421 ixgbe_m_multicst(void *arg, boolean_t add, const uint8_t *mcst_addr) 422 { 423 ixgbe_t *ixgbe = (ixgbe_t *)arg; 424 int result; 425 426 mutex_enter(&ixgbe->gen_lock); 427 428 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 429 mutex_exit(&ixgbe->gen_lock); 430 return (ECANCELED); 431 } 432 433 result = (add) ? ixgbe_multicst_add(ixgbe, mcst_addr) 434 : ixgbe_multicst_remove(ixgbe, mcst_addr); 435 436 mutex_exit(&ixgbe->gen_lock); 437 438 return (result); 439 } 440 441 /* 442 * Pass on M_IOCTL messages passed to the DLD, and support 443 * private IOCTLs for debugging and ndd. 444 */ 445 void 446 ixgbe_m_ioctl(void *arg, queue_t *q, mblk_t *mp) 447 { 448 ixgbe_t *ixgbe = (ixgbe_t *)arg; 449 struct iocblk *iocp; 450 enum ioc_reply status; 451 452 iocp = (struct iocblk *)(uintptr_t)mp->b_rptr; 453 iocp->ioc_error = 0; 454 455 mutex_enter(&ixgbe->gen_lock); 456 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 457 mutex_exit(&ixgbe->gen_lock); 458 miocnak(q, mp, 0, EINVAL); 459 return; 460 } 461 mutex_exit(&ixgbe->gen_lock); 462 463 switch (iocp->ioc_cmd) { 464 case LB_GET_INFO_SIZE: 465 case LB_GET_INFO: 466 case LB_GET_MODE: 467 case LB_SET_MODE: 468 status = ixgbe_loopback_ioctl(ixgbe, iocp, mp); 469 break; 470 471 default: 472 status = IOC_INVAL; 473 break; 474 } 475 476 /* 477 * Decide how to reply 478 */ 479 switch (status) { 480 default: 481 case IOC_INVAL: 482 /* 483 * Error, reply with a NAK and EINVAL or the specified error 484 */ 485 miocnak(q, mp, 0, iocp->ioc_error == 0 ? 486 EINVAL : iocp->ioc_error); 487 break; 488 489 case IOC_DONE: 490 /* 491 * OK, reply already sent 492 */ 493 break; 494 495 case IOC_ACK: 496 /* 497 * OK, reply with an ACK 498 */ 499 miocack(q, mp, 0, 0); 500 break; 501 502 case IOC_REPLY: 503 /* 504 * OK, send prepared reply as ACK or NAK 505 */ 506 mp->b_datap->db_type = iocp->ioc_error == 0 ? 507 M_IOCACK : M_IOCNAK; 508 qreply(q, mp); 509 break; 510 } 511 } 512 513 /* 514 * Obtain the MAC's capabilities and associated data from 515 * the driver. 516 */ 517 boolean_t 518 ixgbe_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 519 { 520 ixgbe_t *ixgbe = (ixgbe_t *)arg; 521 522 switch (cap) { 523 case MAC_CAPAB_HCKSUM: { 524 uint32_t *tx_hcksum_flags = cap_data; 525 526 /* 527 * We advertise our capabilities only if tx hcksum offload is 528 * enabled. On receive, the stack will accept checksummed 529 * packets anyway, even if we haven't said we can deliver 530 * them. 531 */ 532 if (!ixgbe->tx_hcksum_enable) 533 return (B_FALSE); 534 535 *tx_hcksum_flags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM; 536 break; 537 } 538 case MAC_CAPAB_LSO: { 539 mac_capab_lso_t *cap_lso = cap_data; 540 541 if (ixgbe->lso_enable) { 542 cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 543 cap_lso->lso_basic_tcp_ipv4.lso_max = IXGBE_LSO_MAXLEN; 544 break; 545 } else { 546 return (B_FALSE); 547 } 548 } 549 case MAC_CAPAB_RINGS: { 550 mac_capab_rings_t *cap_rings = cap_data; 551 552 switch (cap_rings->mr_type) { 553 case MAC_RING_TYPE_RX: 554 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 555 cap_rings->mr_rnum = ixgbe->num_rx_rings; 556 cap_rings->mr_gnum = ixgbe->num_rx_groups; 557 cap_rings->mr_rget = ixgbe_fill_ring; 558 cap_rings->mr_gget = ixgbe_fill_group; 559 cap_rings->mr_gaddring = NULL; 560 cap_rings->mr_gremring = NULL; 561 break; 562 case MAC_RING_TYPE_TX: 563 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 564 cap_rings->mr_rnum = ixgbe->num_tx_rings; 565 cap_rings->mr_gnum = 0; 566 cap_rings->mr_rget = ixgbe_fill_ring; 567 cap_rings->mr_gget = NULL; 568 break; 569 default: 570 break; 571 } 572 break; 573 } 574 default: 575 return (B_FALSE); 576 } 577 return (B_TRUE); 578 } 579 580 int 581 ixgbe_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 582 uint_t pr_valsize, const void *pr_val) 583 { 584 ixgbe_t *ixgbe = (ixgbe_t *)arg; 585 struct ixgbe_hw *hw = &ixgbe->hw; 586 int err = 0; 587 uint32_t flow_control; 588 uint32_t cur_mtu, new_mtu; 589 uint32_t rx_size; 590 uint32_t tx_size; 591 592 mutex_enter(&ixgbe->gen_lock); 593 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 594 mutex_exit(&ixgbe->gen_lock); 595 return (ECANCELED); 596 } 597 598 if (ixgbe->loopback_mode != IXGBE_LB_NONE && 599 ixgbe_param_locked(pr_num)) { 600 /* 601 * All en_* parameters are locked (read-only) 602 * while the device is in any sort of loopback mode. 603 */ 604 mutex_exit(&ixgbe->gen_lock); 605 return (EBUSY); 606 } 607 608 switch (pr_num) { 609 case MAC_PROP_EN_10GFDX_CAP: 610 /* read/write on copper, read-only on serdes */ 611 if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) { 612 err = ENOTSUP; 613 break; 614 } else { 615 ixgbe->param_en_10000fdx_cap = *(uint8_t *)pr_val; 616 ixgbe->param_adv_10000fdx_cap = *(uint8_t *)pr_val; 617 goto setup_link; 618 } 619 case MAC_PROP_EN_1000FDX_CAP: 620 /* read/write on copper, read-only on serdes */ 621 if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) { 622 err = ENOTSUP; 623 break; 624 } else { 625 ixgbe->param_en_1000fdx_cap = *(uint8_t *)pr_val; 626 ixgbe->param_adv_1000fdx_cap = *(uint8_t *)pr_val; 627 goto setup_link; 628 } 629 case MAC_PROP_EN_100FDX_CAP: 630 /* read/write on copper, read-only on serdes */ 631 if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) { 632 err = ENOTSUP; 633 break; 634 } else { 635 ixgbe->param_en_100fdx_cap = *(uint8_t *)pr_val; 636 ixgbe->param_adv_100fdx_cap = *(uint8_t *)pr_val; 637 goto setup_link; 638 } 639 case MAC_PROP_AUTONEG: 640 /* read/write on copper, read-only on serdes */ 641 if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) { 642 err = ENOTSUP; 643 break; 644 } else { 645 ixgbe->param_adv_autoneg_cap = *(uint8_t *)pr_val; 646 goto setup_link; 647 } 648 case MAC_PROP_FLOWCTRL: 649 bcopy(pr_val, &flow_control, sizeof (flow_control)); 650 651 switch (flow_control) { 652 default: 653 err = EINVAL; 654 break; 655 case LINK_FLOWCTRL_NONE: 656 hw->fc.requested_mode = ixgbe_fc_none; 657 break; 658 case LINK_FLOWCTRL_RX: 659 hw->fc.requested_mode = ixgbe_fc_rx_pause; 660 break; 661 case LINK_FLOWCTRL_TX: 662 hw->fc.requested_mode = ixgbe_fc_tx_pause; 663 break; 664 case LINK_FLOWCTRL_BI: 665 hw->fc.requested_mode = ixgbe_fc_full; 666 break; 667 } 668 setup_link: 669 if (err == 0) { 670 if (ixgbe_driver_setup_link(ixgbe, B_TRUE) != 671 IXGBE_SUCCESS) 672 err = EINVAL; 673 } 674 break; 675 case MAC_PROP_ADV_10GFDX_CAP: 676 case MAC_PROP_ADV_1000FDX_CAP: 677 case MAC_PROP_ADV_100FDX_CAP: 678 case MAC_PROP_STATUS: 679 case MAC_PROP_SPEED: 680 case MAC_PROP_DUPLEX: 681 err = ENOTSUP; /* read-only prop. Can't set this. */ 682 break; 683 case MAC_PROP_MTU: 684 cur_mtu = ixgbe->default_mtu; 685 bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 686 if (new_mtu == cur_mtu) { 687 err = 0; 688 break; 689 } 690 691 if (new_mtu < DEFAULT_MTU || new_mtu > ixgbe->capab->max_mtu) { 692 err = EINVAL; 693 break; 694 } 695 696 if (ixgbe->ixgbe_state & IXGBE_STARTED) { 697 err = EBUSY; 698 break; 699 } 700 701 err = mac_maxsdu_update(ixgbe->mac_hdl, new_mtu); 702 if (err == 0) { 703 ixgbe->default_mtu = new_mtu; 704 ixgbe->max_frame_size = ixgbe->default_mtu + 705 sizeof (struct ether_vlan_header) + ETHERFCSL; 706 707 /* 708 * Set rx buffer size 709 */ 710 rx_size = ixgbe->max_frame_size + IPHDR_ALIGN_ROOM; 711 ixgbe->rx_buf_size = ((rx_size >> 10) + ((rx_size & 712 (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10; 713 714 /* 715 * Set tx buffer size 716 */ 717 tx_size = ixgbe->max_frame_size; 718 ixgbe->tx_buf_size = ((tx_size >> 10) + ((tx_size & 719 (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10; 720 } 721 break; 722 case MAC_PROP_PRIVATE: 723 err = ixgbe_set_priv_prop(ixgbe, pr_name, pr_valsize, pr_val); 724 break; 725 default: 726 err = EINVAL; 727 break; 728 } 729 mutex_exit(&ixgbe->gen_lock); 730 return (err); 731 } 732 733 int 734 ixgbe_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 735 uint_t pr_flags, uint_t pr_valsize, void *pr_val, uint_t *perm) 736 { 737 ixgbe_t *ixgbe = (ixgbe_t *)arg; 738 struct ixgbe_hw *hw = &ixgbe->hw; 739 int err = 0; 740 uint32_t flow_control; 741 uint64_t tmp = 0; 742 boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT); 743 mac_propval_range_t range; 744 745 if (pr_valsize == 0) 746 return (EINVAL); 747 748 *perm = MAC_PROP_PERM_READ; 749 750 bzero(pr_val, pr_valsize); 751 752 switch (pr_num) { 753 case MAC_PROP_DUPLEX: 754 if (pr_valsize >= sizeof (link_duplex_t)) { 755 bcopy(&ixgbe->link_duplex, pr_val, 756 sizeof (link_duplex_t)); 757 } else 758 err = EINVAL; 759 break; 760 case MAC_PROP_SPEED: 761 if (pr_valsize >= sizeof (uint64_t)) { 762 tmp = ixgbe->link_speed * 1000000ull; 763 bcopy(&tmp, pr_val, sizeof (tmp)); 764 } else 765 err = EINVAL; 766 break; 767 case MAC_PROP_AUTONEG: 768 if (ixgbe->hw.phy.media_type == ixgbe_media_type_copper) 769 *perm = MAC_PROP_PERM_RW; 770 *(uint8_t *)pr_val = 771 (is_default ? 1 : ixgbe->param_adv_autoneg_cap); 772 break; 773 case MAC_PROP_FLOWCTRL: 774 *perm = MAC_PROP_PERM_RW; 775 if (pr_valsize >= sizeof (uint32_t)) { 776 if (is_default) { 777 flow_control = LINK_FLOWCTRL_NONE; 778 bcopy(&flow_control, pr_val, 779 sizeof (flow_control)); 780 break; 781 } 782 switch (hw->fc.requested_mode) { 783 case ixgbe_fc_none: 784 flow_control = LINK_FLOWCTRL_NONE; 785 break; 786 case ixgbe_fc_rx_pause: 787 flow_control = LINK_FLOWCTRL_RX; 788 break; 789 case ixgbe_fc_tx_pause: 790 flow_control = LINK_FLOWCTRL_TX; 791 break; 792 case ixgbe_fc_full: 793 flow_control = LINK_FLOWCTRL_BI; 794 break; 795 } 796 bcopy(&flow_control, pr_val, sizeof (flow_control)); 797 } else 798 err = EINVAL; 799 break; 800 case MAC_PROP_ADV_10GFDX_CAP: 801 *(uint8_t *)pr_val = (is_default ? 1 : 802 ixgbe->param_adv_10000fdx_cap); 803 break; 804 case MAC_PROP_EN_10GFDX_CAP: 805 if (ixgbe->hw.phy.media_type == ixgbe_media_type_copper) 806 *perm = MAC_PROP_PERM_RW; 807 *(uint8_t *)pr_val = 808 (is_default ? 1 : ixgbe->param_en_10000fdx_cap); 809 break; 810 case MAC_PROP_ADV_1000FDX_CAP: 811 *(uint8_t *)pr_val = (is_default ? 1 : 812 ixgbe->param_adv_1000fdx_cap); 813 break; 814 case MAC_PROP_EN_1000FDX_CAP: 815 if (ixgbe->hw.phy.media_type == ixgbe_media_type_copper) 816 *perm = MAC_PROP_PERM_RW; 817 *(uint8_t *)pr_val = 818 (is_default ? 1 : ixgbe->param_en_1000fdx_cap); 819 break; 820 case MAC_PROP_ADV_100FDX_CAP: 821 *(uint8_t *)pr_val = 822 (is_default ? 1 : ixgbe->param_adv_100fdx_cap); 823 break; 824 case MAC_PROP_EN_100FDX_CAP: 825 if (ixgbe->hw.phy.media_type == ixgbe_media_type_copper) 826 *perm = MAC_PROP_PERM_RW; 827 *(uint8_t *)pr_val = 828 (is_default ? 1 : ixgbe->param_en_100fdx_cap); 829 break; 830 case MAC_PROP_PRIVATE: 831 err = ixgbe_get_priv_prop(ixgbe, pr_name, 832 pr_flags, pr_valsize, pr_val, perm); 833 break; 834 case MAC_PROP_MTU: 835 if (!(pr_flags & MAC_PROP_POSSIBLE)) 836 return (ENOTSUP); 837 if (pr_valsize < sizeof (mac_propval_range_t)) 838 return (EINVAL); 839 range.mpr_count = 1; 840 range.mpr_type = MAC_PROPVAL_UINT32; 841 range.range_uint32[0].mpur_min = DEFAULT_MTU; 842 range.range_uint32[0].mpur_max = ixgbe->capab->max_mtu; 843 bcopy(&range, pr_val, sizeof (range)); 844 break; 845 default: 846 err = EINVAL; 847 break; 848 } 849 return (err); 850 } 851 852 boolean_t 853 ixgbe_param_locked(mac_prop_id_t pr_num) 854 { 855 /* 856 * All en_* parameters are locked (read-only) while 857 * the device is in any sort of loopback mode ... 858 */ 859 switch (pr_num) { 860 case MAC_PROP_EN_10GFDX_CAP: 861 case MAC_PROP_EN_1000FDX_CAP: 862 case MAC_PROP_EN_100FDX_CAP: 863 case MAC_PROP_AUTONEG: 864 case MAC_PROP_FLOWCTRL: 865 return (B_TRUE); 866 } 867 return (B_FALSE); 868 } 869 870 /* ARGSUSED */ 871 int 872 ixgbe_set_priv_prop(ixgbe_t *ixgbe, const char *pr_name, 873 uint_t pr_valsize, const void *pr_val) 874 { 875 int err = 0; 876 long result; 877 struct ixgbe_hw *hw = &ixgbe->hw; 878 int i; 879 880 if (strcmp(pr_name, "_tx_copy_thresh") == 0) { 881 if (pr_val == NULL) { 882 err = EINVAL; 883 return (err); 884 } 885 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 886 if (result < MIN_TX_COPY_THRESHOLD || 887 result > MAX_TX_COPY_THRESHOLD) 888 err = EINVAL; 889 else { 890 ixgbe->tx_copy_thresh = (uint32_t)result; 891 } 892 return (err); 893 } 894 if (strcmp(pr_name, "_tx_recycle_thresh") == 0) { 895 if (pr_val == NULL) { 896 err = EINVAL; 897 return (err); 898 } 899 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 900 if (result < MIN_TX_RECYCLE_THRESHOLD || 901 result > MAX_TX_RECYCLE_THRESHOLD) 902 err = EINVAL; 903 else { 904 ixgbe->tx_recycle_thresh = (uint32_t)result; 905 } 906 return (err); 907 } 908 if (strcmp(pr_name, "_tx_overload_thresh") == 0) { 909 if (pr_val == NULL) { 910 err = EINVAL; 911 return (err); 912 } 913 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 914 if (result < MIN_TX_OVERLOAD_THRESHOLD || 915 result > MAX_TX_OVERLOAD_THRESHOLD) 916 err = EINVAL; 917 else { 918 ixgbe->tx_overload_thresh = (uint32_t)result; 919 } 920 return (err); 921 } 922 if (strcmp(pr_name, "_tx_resched_thresh") == 0) { 923 if (pr_val == NULL) { 924 err = EINVAL; 925 return (err); 926 } 927 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 928 if (result < MIN_TX_RESCHED_THRESHOLD || 929 result > MAX_TX_RESCHED_THRESHOLD) 930 err = EINVAL; 931 else { 932 ixgbe->tx_resched_thresh = (uint32_t)result; 933 } 934 return (err); 935 } 936 if (strcmp(pr_name, "_rx_copy_thresh") == 0) { 937 if (pr_val == NULL) { 938 err = EINVAL; 939 return (err); 940 } 941 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 942 if (result < MIN_RX_COPY_THRESHOLD || 943 result > MAX_RX_COPY_THRESHOLD) 944 err = EINVAL; 945 else { 946 ixgbe->rx_copy_thresh = (uint32_t)result; 947 } 948 return (err); 949 } 950 if (strcmp(pr_name, "_rx_limit_per_intr") == 0) { 951 if (pr_val == NULL) { 952 err = EINVAL; 953 return (err); 954 } 955 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 956 if (result < MIN_RX_LIMIT_PER_INTR || 957 result > MAX_RX_LIMIT_PER_INTR) 958 err = EINVAL; 959 else { 960 ixgbe->rx_limit_per_intr = (uint32_t)result; 961 } 962 return (err); 963 } 964 if (strcmp(pr_name, "_intr_throttling") == 0) { 965 if (pr_val == NULL) { 966 err = EINVAL; 967 return (err); 968 } 969 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 970 971 if (result < ixgbe->capab->min_intr_throttle || 972 result > ixgbe->capab->max_intr_throttle) 973 err = EINVAL; 974 else { 975 ixgbe->intr_throttling[0] = (uint32_t)result; 976 977 /* 978 * 82599 requires the interupt throttling rate is 979 * a multiple of 8. This is enforced by the register 980 * definiton. 981 */ 982 if (hw->mac.type == ixgbe_mac_82599EB) 983 ixgbe->intr_throttling[0] = 984 ixgbe->intr_throttling[0] & 0xFF8; 985 986 for (i = 0; i < MAX_INTR_VECTOR; i++) 987 ixgbe->intr_throttling[i] = 988 ixgbe->intr_throttling[0]; 989 990 /* Set interrupt throttling rate */ 991 for (i = 0; i < ixgbe->intr_cnt; i++) 992 IXGBE_WRITE_REG(hw, IXGBE_EITR(i), 993 ixgbe->intr_throttling[i]); 994 } 995 return (err); 996 } 997 return (ENOTSUP); 998 } 999 1000 int 1001 ixgbe_get_priv_prop(ixgbe_t *ixgbe, const char *pr_name, 1002 uint_t pr_flags, uint_t pr_valsize, void *pr_val, uint_t *perm) 1003 { 1004 int err = ENOTSUP; 1005 boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT); 1006 int value; 1007 1008 *perm = MAC_PROP_PERM_RW; 1009 1010 if (strcmp(pr_name, "_adv_pause_cap") == 0) { 1011 *perm = MAC_PROP_PERM_READ; 1012 value = (is_default ? 1 : ixgbe->param_adv_pause_cap); 1013 err = 0; 1014 goto done; 1015 } 1016 if (strcmp(pr_name, "_adv_asym_pause_cap") == 0) { 1017 *perm = MAC_PROP_PERM_READ; 1018 value = (is_default ? 1 : ixgbe->param_adv_asym_pause_cap); 1019 err = 0; 1020 goto done; 1021 } 1022 if (strcmp(pr_name, "_tx_copy_thresh") == 0) { 1023 value = (is_default ? DEFAULT_TX_COPY_THRESHOLD : 1024 ixgbe->tx_copy_thresh); 1025 err = 0; 1026 goto done; 1027 } 1028 if (strcmp(pr_name, "_tx_recycle_thresh") == 0) { 1029 value = (is_default ? DEFAULT_TX_RECYCLE_THRESHOLD : 1030 ixgbe->tx_recycle_thresh); 1031 err = 0; 1032 goto done; 1033 } 1034 if (strcmp(pr_name, "_tx_overload_thresh") == 0) { 1035 value = (is_default ? DEFAULT_TX_OVERLOAD_THRESHOLD : 1036 ixgbe->tx_overload_thresh); 1037 err = 0; 1038 goto done; 1039 } 1040 if (strcmp(pr_name, "_tx_resched_thresh") == 0) { 1041 value = (is_default ? DEFAULT_TX_RESCHED_THRESHOLD : 1042 ixgbe->tx_resched_thresh); 1043 err = 0; 1044 goto done; 1045 } 1046 if (strcmp(pr_name, "_rx_copy_thresh") == 0) { 1047 value = (is_default ? DEFAULT_RX_COPY_THRESHOLD : 1048 ixgbe->rx_copy_thresh); 1049 err = 0; 1050 goto done; 1051 } 1052 if (strcmp(pr_name, "_rx_limit_per_intr") == 0) { 1053 value = (is_default ? DEFAULT_RX_LIMIT_PER_INTR : 1054 ixgbe->rx_limit_per_intr); 1055 err = 0; 1056 goto done; 1057 } 1058 if (strcmp(pr_name, "_intr_throttling") == 0) { 1059 value = (is_default ? ixgbe->capab->def_intr_throttle : 1060 ixgbe->intr_throttling[0]); 1061 err = 0; 1062 goto done; 1063 } 1064 done: 1065 if (err == 0) { 1066 (void) snprintf(pr_val, pr_valsize, "%d", value); 1067 } 1068 return (err); 1069 } 1070