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(c) 2007-2010 Intel Corporation. All rights reserved. 24 */ 25 26 /* 27 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 28 */ 29 30 #include "ixgbe_sw.h" 31 32 /* 33 * Bring the device out of the reset/quiesced state that it 34 * was in when the interface was registered. 35 */ 36 int 37 ixgbe_m_start(void *arg) 38 { 39 ixgbe_t *ixgbe = (ixgbe_t *)arg; 40 41 mutex_enter(&ixgbe->gen_lock); 42 43 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 44 mutex_exit(&ixgbe->gen_lock); 45 return (ECANCELED); 46 } 47 48 if (ixgbe_start(ixgbe, B_TRUE) != IXGBE_SUCCESS) { 49 mutex_exit(&ixgbe->gen_lock); 50 return (EIO); 51 } 52 53 atomic_or_32(&ixgbe->ixgbe_state, IXGBE_STARTED); 54 55 mutex_exit(&ixgbe->gen_lock); 56 57 /* 58 * Enable and start the watchdog timer 59 */ 60 ixgbe_enable_watchdog_timer(ixgbe); 61 62 return (0); 63 } 64 65 /* 66 * Stop the device and put it in a reset/quiesced state such 67 * that the interface can be unregistered. 68 */ 69 void 70 ixgbe_m_stop(void *arg) 71 { 72 ixgbe_t *ixgbe = (ixgbe_t *)arg; 73 74 mutex_enter(&ixgbe->gen_lock); 75 76 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 77 mutex_exit(&ixgbe->gen_lock); 78 return; 79 } 80 81 atomic_and_32(&ixgbe->ixgbe_state, ~IXGBE_STARTED); 82 83 ixgbe_stop(ixgbe, B_TRUE); 84 85 mutex_exit(&ixgbe->gen_lock); 86 87 /* 88 * Disable and stop the watchdog timer 89 */ 90 ixgbe_disable_watchdog_timer(ixgbe); 91 } 92 93 /* 94 * Set the promiscuity of the device. 95 */ 96 int 97 ixgbe_m_promisc(void *arg, boolean_t on) 98 { 99 ixgbe_t *ixgbe = (ixgbe_t *)arg; 100 uint32_t reg_val; 101 struct ixgbe_hw *hw = &ixgbe->hw; 102 103 mutex_enter(&ixgbe->gen_lock); 104 105 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 106 mutex_exit(&ixgbe->gen_lock); 107 return (ECANCELED); 108 } 109 reg_val = IXGBE_READ_REG(hw, IXGBE_FCTRL); 110 111 if (on) 112 reg_val |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 113 else 114 reg_val &= (~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE)); 115 116 IXGBE_WRITE_REG(&ixgbe->hw, IXGBE_FCTRL, reg_val); 117 118 mutex_exit(&ixgbe->gen_lock); 119 120 return (0); 121 } 122 123 /* 124 * Add/remove the addresses to/from the set of multicast 125 * addresses for which the device will receive packets. 126 */ 127 int 128 ixgbe_m_multicst(void *arg, boolean_t add, const uint8_t *mcst_addr) 129 { 130 ixgbe_t *ixgbe = (ixgbe_t *)arg; 131 int result; 132 133 mutex_enter(&ixgbe->gen_lock); 134 135 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 136 mutex_exit(&ixgbe->gen_lock); 137 return (ECANCELED); 138 } 139 140 result = (add) ? ixgbe_multicst_add(ixgbe, mcst_addr) 141 : ixgbe_multicst_remove(ixgbe, mcst_addr); 142 143 mutex_exit(&ixgbe->gen_lock); 144 145 return (result); 146 } 147 148 /* 149 * Pass on M_IOCTL messages passed to the DLD, and support 150 * private IOCTLs for debugging and ndd. 151 */ 152 void 153 ixgbe_m_ioctl(void *arg, queue_t *q, mblk_t *mp) 154 { 155 ixgbe_t *ixgbe = (ixgbe_t *)arg; 156 struct iocblk *iocp; 157 enum ioc_reply status; 158 159 iocp = (struct iocblk *)(uintptr_t)mp->b_rptr; 160 iocp->ioc_error = 0; 161 162 mutex_enter(&ixgbe->gen_lock); 163 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 164 mutex_exit(&ixgbe->gen_lock); 165 miocnak(q, mp, 0, EINVAL); 166 return; 167 } 168 mutex_exit(&ixgbe->gen_lock); 169 170 switch (iocp->ioc_cmd) { 171 case LB_GET_INFO_SIZE: 172 case LB_GET_INFO: 173 case LB_GET_MODE: 174 case LB_SET_MODE: 175 status = ixgbe_loopback_ioctl(ixgbe, iocp, mp); 176 break; 177 178 default: 179 status = IOC_INVAL; 180 break; 181 } 182 183 /* 184 * Decide how to reply 185 */ 186 switch (status) { 187 default: 188 case IOC_INVAL: 189 /* 190 * Error, reply with a NAK and EINVAL or the specified error 191 */ 192 miocnak(q, mp, 0, iocp->ioc_error == 0 ? 193 EINVAL : iocp->ioc_error); 194 break; 195 196 case IOC_DONE: 197 /* 198 * OK, reply already sent 199 */ 200 break; 201 202 case IOC_ACK: 203 /* 204 * OK, reply with an ACK 205 */ 206 miocack(q, mp, 0, 0); 207 break; 208 209 case IOC_REPLY: 210 /* 211 * OK, send prepared reply as ACK or NAK 212 */ 213 mp->b_datap->db_type = iocp->ioc_error == 0 ? 214 M_IOCACK : M_IOCNAK; 215 qreply(q, mp); 216 break; 217 } 218 } 219 220 /* 221 * Obtain the MAC's capabilities and associated data from 222 * the driver. 223 */ 224 boolean_t 225 ixgbe_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 226 { 227 ixgbe_t *ixgbe = (ixgbe_t *)arg; 228 229 switch (cap) { 230 case MAC_CAPAB_HCKSUM: { 231 uint32_t *tx_hcksum_flags = cap_data; 232 233 /* 234 * We advertise our capabilities only if tx hcksum offload is 235 * enabled. On receive, the stack will accept checksummed 236 * packets anyway, even if we haven't said we can deliver 237 * them. 238 */ 239 if (!ixgbe->tx_hcksum_enable) 240 return (B_FALSE); 241 242 *tx_hcksum_flags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM; 243 break; 244 } 245 case MAC_CAPAB_LSO: { 246 mac_capab_lso_t *cap_lso = cap_data; 247 248 if (ixgbe->lso_enable) { 249 cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 250 cap_lso->lso_basic_tcp_ipv4.lso_max = IXGBE_LSO_MAXLEN; 251 break; 252 } else { 253 return (B_FALSE); 254 } 255 } 256 case MAC_CAPAB_RINGS: { 257 mac_capab_rings_t *cap_rings = cap_data; 258 259 switch (cap_rings->mr_type) { 260 case MAC_RING_TYPE_RX: 261 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 262 cap_rings->mr_rnum = ixgbe->num_rx_rings; 263 cap_rings->mr_gnum = ixgbe->num_rx_groups; 264 cap_rings->mr_rget = ixgbe_fill_ring; 265 cap_rings->mr_gget = ixgbe_fill_group; 266 cap_rings->mr_gaddring = NULL; 267 cap_rings->mr_gremring = NULL; 268 break; 269 case MAC_RING_TYPE_TX: 270 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 271 cap_rings->mr_rnum = ixgbe->num_tx_rings; 272 cap_rings->mr_gnum = 0; 273 cap_rings->mr_rget = ixgbe_fill_ring; 274 cap_rings->mr_gget = NULL; 275 break; 276 default: 277 break; 278 } 279 break; 280 } 281 default: 282 return (B_FALSE); 283 } 284 return (B_TRUE); 285 } 286 287 int 288 ixgbe_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 289 uint_t pr_valsize, const void *pr_val) 290 { 291 ixgbe_t *ixgbe = (ixgbe_t *)arg; 292 struct ixgbe_hw *hw = &ixgbe->hw; 293 int err = 0; 294 uint32_t flow_control; 295 uint32_t cur_mtu, new_mtu; 296 uint32_t rx_size; 297 uint32_t tx_size; 298 299 mutex_enter(&ixgbe->gen_lock); 300 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 301 mutex_exit(&ixgbe->gen_lock); 302 return (ECANCELED); 303 } 304 305 if (ixgbe->loopback_mode != IXGBE_LB_NONE && 306 ixgbe_param_locked(pr_num)) { 307 /* 308 * All en_* parameters are locked (read-only) 309 * while the device is in any sort of loopback mode. 310 */ 311 mutex_exit(&ixgbe->gen_lock); 312 return (EBUSY); 313 } 314 315 switch (pr_num) { 316 case MAC_PROP_EN_10GFDX_CAP: 317 /* read/write on copper, read-only on serdes */ 318 if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) { 319 err = ENOTSUP; 320 break; 321 } else { 322 ixgbe->param_en_10000fdx_cap = *(uint8_t *)pr_val; 323 ixgbe->param_adv_10000fdx_cap = *(uint8_t *)pr_val; 324 goto setup_link; 325 } 326 case MAC_PROP_EN_1000FDX_CAP: 327 /* read/write on copper, read-only on serdes */ 328 if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) { 329 err = ENOTSUP; 330 break; 331 } else { 332 ixgbe->param_en_1000fdx_cap = *(uint8_t *)pr_val; 333 ixgbe->param_adv_1000fdx_cap = *(uint8_t *)pr_val; 334 goto setup_link; 335 } 336 case MAC_PROP_EN_100FDX_CAP: 337 /* read/write on copper, read-only on serdes */ 338 if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) { 339 err = ENOTSUP; 340 break; 341 } else { 342 ixgbe->param_en_100fdx_cap = *(uint8_t *)pr_val; 343 ixgbe->param_adv_100fdx_cap = *(uint8_t *)pr_val; 344 goto setup_link; 345 } 346 case MAC_PROP_AUTONEG: 347 /* read/write on copper, read-only on serdes */ 348 if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) { 349 err = ENOTSUP; 350 break; 351 } else { 352 ixgbe->param_adv_autoneg_cap = *(uint8_t *)pr_val; 353 goto setup_link; 354 } 355 case MAC_PROP_FLOWCTRL: 356 bcopy(pr_val, &flow_control, sizeof (flow_control)); 357 358 switch (flow_control) { 359 default: 360 err = EINVAL; 361 break; 362 case LINK_FLOWCTRL_NONE: 363 hw->fc.requested_mode = ixgbe_fc_none; 364 break; 365 case LINK_FLOWCTRL_RX: 366 hw->fc.requested_mode = ixgbe_fc_rx_pause; 367 break; 368 case LINK_FLOWCTRL_TX: 369 hw->fc.requested_mode = ixgbe_fc_tx_pause; 370 break; 371 case LINK_FLOWCTRL_BI: 372 hw->fc.requested_mode = ixgbe_fc_full; 373 break; 374 } 375 setup_link: 376 if (err == 0) { 377 if (ixgbe_driver_setup_link(ixgbe, B_TRUE) != 378 IXGBE_SUCCESS) 379 err = EINVAL; 380 } 381 break; 382 case MAC_PROP_ADV_10GFDX_CAP: 383 case MAC_PROP_ADV_1000FDX_CAP: 384 case MAC_PROP_ADV_100FDX_CAP: 385 case MAC_PROP_STATUS: 386 case MAC_PROP_SPEED: 387 case MAC_PROP_DUPLEX: 388 err = ENOTSUP; /* read-only prop. Can't set this. */ 389 break; 390 case MAC_PROP_MTU: 391 cur_mtu = ixgbe->default_mtu; 392 bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 393 if (new_mtu == cur_mtu) { 394 err = 0; 395 break; 396 } 397 398 if (new_mtu < DEFAULT_MTU || new_mtu > ixgbe->capab->max_mtu) { 399 err = EINVAL; 400 break; 401 } 402 403 if (ixgbe->ixgbe_state & IXGBE_STARTED) { 404 err = EBUSY; 405 break; 406 } 407 408 err = mac_maxsdu_update(ixgbe->mac_hdl, new_mtu); 409 if (err == 0) { 410 ixgbe->default_mtu = new_mtu; 411 ixgbe->max_frame_size = ixgbe->default_mtu + 412 sizeof (struct ether_vlan_header) + ETHERFCSL; 413 414 /* 415 * Set rx buffer size 416 */ 417 rx_size = ixgbe->max_frame_size + IPHDR_ALIGN_ROOM; 418 ixgbe->rx_buf_size = ((rx_size >> 10) + ((rx_size & 419 (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10; 420 421 /* 422 * Set tx buffer size 423 */ 424 tx_size = ixgbe->max_frame_size; 425 ixgbe->tx_buf_size = ((tx_size >> 10) + ((tx_size & 426 (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10; 427 } 428 break; 429 case MAC_PROP_PRIVATE: 430 err = ixgbe_set_priv_prop(ixgbe, pr_name, pr_valsize, pr_val); 431 break; 432 default: 433 err = EINVAL; 434 break; 435 } 436 mutex_exit(&ixgbe->gen_lock); 437 return (err); 438 } 439 440 int 441 ixgbe_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 442 uint_t pr_valsize, void *pr_val) 443 { 444 ixgbe_t *ixgbe = (ixgbe_t *)arg; 445 struct ixgbe_hw *hw = &ixgbe->hw; 446 int err = 0; 447 uint32_t flow_control; 448 uint64_t tmp = 0; 449 450 switch (pr_num) { 451 case MAC_PROP_DUPLEX: 452 ASSERT(pr_valsize >= sizeof (link_duplex_t)); 453 bcopy(&ixgbe->link_duplex, pr_val, 454 sizeof (link_duplex_t)); 455 break; 456 case MAC_PROP_SPEED: 457 ASSERT(pr_valsize >= sizeof (uint64_t)); 458 tmp = ixgbe->link_speed * 1000000ull; 459 bcopy(&tmp, pr_val, sizeof (tmp)); 460 break; 461 case MAC_PROP_AUTONEG: 462 *(uint8_t *)pr_val = ixgbe->param_adv_autoneg_cap; 463 break; 464 case MAC_PROP_FLOWCTRL: 465 ASSERT(pr_valsize >= sizeof (uint32_t)); 466 467 switch (hw->fc.requested_mode) { 468 case ixgbe_fc_none: 469 flow_control = LINK_FLOWCTRL_NONE; 470 break; 471 case ixgbe_fc_rx_pause: 472 flow_control = LINK_FLOWCTRL_RX; 473 break; 474 case ixgbe_fc_tx_pause: 475 flow_control = LINK_FLOWCTRL_TX; 476 break; 477 case ixgbe_fc_full: 478 flow_control = LINK_FLOWCTRL_BI; 479 break; 480 } 481 bcopy(&flow_control, pr_val, sizeof (flow_control)); 482 break; 483 case MAC_PROP_ADV_10GFDX_CAP: 484 *(uint8_t *)pr_val = ixgbe->param_adv_10000fdx_cap; 485 break; 486 case MAC_PROP_EN_10GFDX_CAP: 487 *(uint8_t *)pr_val = ixgbe->param_en_10000fdx_cap; 488 break; 489 case MAC_PROP_ADV_1000FDX_CAP: 490 *(uint8_t *)pr_val = ixgbe->param_adv_1000fdx_cap; 491 break; 492 case MAC_PROP_EN_1000FDX_CAP: 493 *(uint8_t *)pr_val = ixgbe->param_en_1000fdx_cap; 494 break; 495 case MAC_PROP_ADV_100FDX_CAP: 496 *(uint8_t *)pr_val = ixgbe->param_adv_100fdx_cap; 497 break; 498 case MAC_PROP_EN_100FDX_CAP: 499 *(uint8_t *)pr_val = ixgbe->param_en_100fdx_cap; 500 break; 501 case MAC_PROP_PRIVATE: 502 err = ixgbe_get_priv_prop(ixgbe, pr_name, 503 pr_valsize, pr_val); 504 break; 505 default: 506 err = EINVAL; 507 break; 508 } 509 return (err); 510 } 511 512 void 513 ixgbe_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num, 514 mac_prop_info_handle_t prh) 515 { 516 ixgbe_t *ixgbe = (ixgbe_t *)arg; 517 uint_t perm; 518 519 switch (pr_num) { 520 case MAC_PROP_DUPLEX: 521 case MAC_PROP_SPEED: 522 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 523 break; 524 525 case MAC_PROP_ADV_100FDX_CAP: 526 case MAC_PROP_ADV_1000FDX_CAP: 527 case MAC_PROP_ADV_10GFDX_CAP: 528 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 529 mac_prop_info_set_default_uint8(prh, 1); 530 break; 531 532 case MAC_PROP_AUTONEG: 533 case MAC_PROP_EN_10GFDX_CAP: 534 case MAC_PROP_EN_1000FDX_CAP: 535 case MAC_PROP_EN_100FDX_CAP: 536 perm = (ixgbe->hw.phy.media_type == ixgbe_media_type_copper) ? 537 MAC_PROP_PERM_RW : MAC_PROP_PERM_READ; 538 mac_prop_info_set_perm(prh, perm); 539 mac_prop_info_set_default_uint8(prh, 1); 540 break; 541 542 case MAC_PROP_FLOWCTRL: 543 mac_prop_info_set_default_link_flowctrl(prh, 544 LINK_FLOWCTRL_NONE); 545 break; 546 547 case MAC_PROP_MTU: 548 mac_prop_info_set_range_uint32(prh, 549 DEFAULT_MTU, ixgbe->capab->max_mtu); 550 break; 551 552 case MAC_PROP_PRIVATE: { 553 char valstr[64]; 554 int value; 555 556 bzero(valstr, sizeof (valstr)); 557 558 if (strcmp(pr_name, "_adv_pause_cap") == 0 || 559 strcmp(pr_name, "_adv_asym_pause_cap") == 0) { 560 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 561 return; 562 } 563 564 if (strcmp(pr_name, "_tx_copy_thresh") == 0) { 565 value = DEFAULT_TX_COPY_THRESHOLD; 566 } else if (strcmp(pr_name, "_tx_recycle_thresh") == 0) { 567 value = DEFAULT_TX_RECYCLE_THRESHOLD; 568 } else if (strcmp(pr_name, "_tx_overload_thresh") == 0) { 569 value = DEFAULT_TX_OVERLOAD_THRESHOLD; 570 } else if (strcmp(pr_name, "_tx_resched_thresh") == 0) { 571 value = DEFAULT_TX_RESCHED_THRESHOLD; 572 } else if (strcmp(pr_name, "_rx_copy_thresh") == 0) { 573 value = DEFAULT_RX_COPY_THRESHOLD; 574 } else if (strcmp(pr_name, "_rx_limit_per_intr") == 0) { 575 value = DEFAULT_RX_LIMIT_PER_INTR; 576 } if (strcmp(pr_name, "_intr_throttling") == 0) { 577 value = ixgbe->capab->def_intr_throttle; 578 } else { 579 return; 580 } 581 582 (void) snprintf(valstr, sizeof (valstr), "%x", value); 583 } 584 } 585 } 586 587 boolean_t 588 ixgbe_param_locked(mac_prop_id_t pr_num) 589 { 590 /* 591 * All en_* parameters are locked (read-only) while 592 * the device is in any sort of loopback mode ... 593 */ 594 switch (pr_num) { 595 case MAC_PROP_EN_10GFDX_CAP: 596 case MAC_PROP_EN_1000FDX_CAP: 597 case MAC_PROP_EN_100FDX_CAP: 598 case MAC_PROP_AUTONEG: 599 case MAC_PROP_FLOWCTRL: 600 return (B_TRUE); 601 } 602 return (B_FALSE); 603 } 604 605 /* ARGSUSED */ 606 int 607 ixgbe_set_priv_prop(ixgbe_t *ixgbe, const char *pr_name, 608 uint_t pr_valsize, const void *pr_val) 609 { 610 int err = 0; 611 long result; 612 struct ixgbe_hw *hw = &ixgbe->hw; 613 int i; 614 615 if (strcmp(pr_name, "_tx_copy_thresh") == 0) { 616 if (pr_val == NULL) { 617 err = EINVAL; 618 return (err); 619 } 620 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 621 if (result < MIN_TX_COPY_THRESHOLD || 622 result > MAX_TX_COPY_THRESHOLD) 623 err = EINVAL; 624 else { 625 ixgbe->tx_copy_thresh = (uint32_t)result; 626 } 627 return (err); 628 } 629 if (strcmp(pr_name, "_tx_recycle_thresh") == 0) { 630 if (pr_val == NULL) { 631 err = EINVAL; 632 return (err); 633 } 634 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 635 if (result < MIN_TX_RECYCLE_THRESHOLD || 636 result > MAX_TX_RECYCLE_THRESHOLD) 637 err = EINVAL; 638 else { 639 ixgbe->tx_recycle_thresh = (uint32_t)result; 640 } 641 return (err); 642 } 643 if (strcmp(pr_name, "_tx_overload_thresh") == 0) { 644 if (pr_val == NULL) { 645 err = EINVAL; 646 return (err); 647 } 648 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 649 if (result < MIN_TX_OVERLOAD_THRESHOLD || 650 result > MAX_TX_OVERLOAD_THRESHOLD) 651 err = EINVAL; 652 else { 653 ixgbe->tx_overload_thresh = (uint32_t)result; 654 } 655 return (err); 656 } 657 if (strcmp(pr_name, "_tx_resched_thresh") == 0) { 658 if (pr_val == NULL) { 659 err = EINVAL; 660 return (err); 661 } 662 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 663 if (result < MIN_TX_RESCHED_THRESHOLD || 664 result > MAX_TX_RESCHED_THRESHOLD) 665 err = EINVAL; 666 else { 667 ixgbe->tx_resched_thresh = (uint32_t)result; 668 } 669 return (err); 670 } 671 if (strcmp(pr_name, "_rx_copy_thresh") == 0) { 672 if (pr_val == NULL) { 673 err = EINVAL; 674 return (err); 675 } 676 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 677 if (result < MIN_RX_COPY_THRESHOLD || 678 result > MAX_RX_COPY_THRESHOLD) 679 err = EINVAL; 680 else { 681 ixgbe->rx_copy_thresh = (uint32_t)result; 682 } 683 return (err); 684 } 685 if (strcmp(pr_name, "_rx_limit_per_intr") == 0) { 686 if (pr_val == NULL) { 687 err = EINVAL; 688 return (err); 689 } 690 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 691 if (result < MIN_RX_LIMIT_PER_INTR || 692 result > MAX_RX_LIMIT_PER_INTR) 693 err = EINVAL; 694 else { 695 ixgbe->rx_limit_per_intr = (uint32_t)result; 696 } 697 return (err); 698 } 699 if (strcmp(pr_name, "_intr_throttling") == 0) { 700 if (pr_val == NULL) { 701 err = EINVAL; 702 return (err); 703 } 704 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 705 706 if (result < ixgbe->capab->min_intr_throttle || 707 result > ixgbe->capab->max_intr_throttle) 708 err = EINVAL; 709 else { 710 ixgbe->intr_throttling[0] = (uint32_t)result; 711 712 /* 713 * 82599 requires the interupt throttling rate is 714 * a multiple of 8. This is enforced by the register 715 * definiton. 716 */ 717 if (hw->mac.type == ixgbe_mac_82599EB) 718 ixgbe->intr_throttling[0] = 719 ixgbe->intr_throttling[0] & 0xFF8; 720 721 for (i = 0; i < MAX_INTR_VECTOR; i++) 722 ixgbe->intr_throttling[i] = 723 ixgbe->intr_throttling[0]; 724 725 /* Set interrupt throttling rate */ 726 for (i = 0; i < ixgbe->intr_cnt; i++) 727 IXGBE_WRITE_REG(hw, IXGBE_EITR(i), 728 ixgbe->intr_throttling[i]); 729 } 730 return (err); 731 } 732 return (ENOTSUP); 733 } 734 735 int 736 ixgbe_get_priv_prop(ixgbe_t *ixgbe, const char *pr_name, 737 uint_t pr_valsize, void *pr_val) 738 { 739 int err = ENOTSUP; 740 int value; 741 742 if (strcmp(pr_name, "_adv_pause_cap") == 0) { 743 value = ixgbe->param_adv_pause_cap; 744 err = 0; 745 goto done; 746 } 747 if (strcmp(pr_name, "_adv_asym_pause_cap") == 0) { 748 value = ixgbe->param_adv_asym_pause_cap; 749 err = 0; 750 goto done; 751 } 752 if (strcmp(pr_name, "_tx_copy_thresh") == 0) { 753 value = ixgbe->tx_copy_thresh; 754 err = 0; 755 goto done; 756 } 757 if (strcmp(pr_name, "_tx_recycle_thresh") == 0) { 758 value = ixgbe->tx_recycle_thresh; 759 err = 0; 760 goto done; 761 } 762 if (strcmp(pr_name, "_tx_overload_thresh") == 0) { 763 value = ixgbe->tx_overload_thresh; 764 err = 0; 765 goto done; 766 } 767 if (strcmp(pr_name, "_tx_resched_thresh") == 0) { 768 value = ixgbe->tx_resched_thresh; 769 err = 0; 770 goto done; 771 } 772 if (strcmp(pr_name, "_rx_copy_thresh") == 0) { 773 value = ixgbe->rx_copy_thresh; 774 err = 0; 775 goto done; 776 } 777 if (strcmp(pr_name, "_rx_limit_per_intr") == 0) { 778 value = ixgbe->rx_limit_per_intr; 779 err = 0; 780 goto done; 781 } 782 if (strcmp(pr_name, "_intr_throttling") == 0) { 783 value = ixgbe->intr_throttling[0]; 784 err = 0; 785 goto done; 786 } 787 done: 788 if (err == 0) { 789 (void) snprintf(pr_val, pr_valsize, "%d", value); 790 } 791 return (err); 792 } 793