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 * Copyright 2012 Nexenta Systems, Inc. All rights reserved. 29 * Copyright 2016 OmniTI Computer Consulting, Inc. All rights reserved. 30 * Copyright (c) 2019, Joyent, Inc. 31 */ 32 33 #include "ixgbe_sw.h" 34 35 /* 36 * Bring the device out of the reset/quiesced state that it 37 * was in when the interface was registered. 38 */ 39 int 40 ixgbe_m_start(void *arg) 41 { 42 ixgbe_t *ixgbe = (ixgbe_t *)arg; 43 44 mutex_enter(&ixgbe->gen_lock); 45 46 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 47 mutex_exit(&ixgbe->gen_lock); 48 return (ECANCELED); 49 } 50 51 if (ixgbe_start(ixgbe, B_TRUE) != IXGBE_SUCCESS) { 52 mutex_exit(&ixgbe->gen_lock); 53 return (EIO); 54 } 55 56 atomic_or_32(&ixgbe->ixgbe_state, IXGBE_STARTED); 57 58 mutex_exit(&ixgbe->gen_lock); 59 60 /* 61 * Enable and start the watchdog timer 62 */ 63 ixgbe_enable_watchdog_timer(ixgbe); 64 65 return (0); 66 } 67 68 /* 69 * Stop the device and put it in a reset/quiesced state such 70 * that the interface can be unregistered. 71 */ 72 void 73 ixgbe_m_stop(void *arg) 74 { 75 ixgbe_t *ixgbe = (ixgbe_t *)arg; 76 77 mutex_enter(&ixgbe->gen_lock); 78 79 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 80 mutex_exit(&ixgbe->gen_lock); 81 return; 82 } 83 84 atomic_and_32(&ixgbe->ixgbe_state, ~IXGBE_STARTED); 85 86 ixgbe_stop(ixgbe, B_TRUE); 87 88 mutex_exit(&ixgbe->gen_lock); 89 90 /* 91 * Disable and stop the watchdog timer 92 */ 93 ixgbe_disable_watchdog_timer(ixgbe); 94 } 95 96 /* 97 * Set the promiscuity of the device. 98 */ 99 int 100 ixgbe_m_promisc(void *arg, boolean_t on) 101 { 102 ixgbe_t *ixgbe = (ixgbe_t *)arg; 103 uint32_t reg_val; 104 struct ixgbe_hw *hw = &ixgbe->hw; 105 106 mutex_enter(&ixgbe->gen_lock); 107 108 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 109 mutex_exit(&ixgbe->gen_lock); 110 return (ECANCELED); 111 } 112 reg_val = IXGBE_READ_REG(hw, IXGBE_FCTRL); 113 114 if (on) 115 reg_val |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 116 else 117 reg_val &= (~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE)); 118 119 IXGBE_WRITE_REG(&ixgbe->hw, IXGBE_FCTRL, reg_val); 120 121 mutex_exit(&ixgbe->gen_lock); 122 123 return (0); 124 } 125 126 /* 127 * Add/remove the addresses to/from the set of multicast 128 * addresses for which the device will receive packets. 129 */ 130 int 131 ixgbe_m_multicst(void *arg, boolean_t add, const uint8_t *mcst_addr) 132 { 133 ixgbe_t *ixgbe = (ixgbe_t *)arg; 134 int result; 135 136 mutex_enter(&ixgbe->gen_lock); 137 138 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 139 mutex_exit(&ixgbe->gen_lock); 140 return (ECANCELED); 141 } 142 143 result = (add) ? ixgbe_multicst_add(ixgbe, mcst_addr) 144 : ixgbe_multicst_remove(ixgbe, mcst_addr); 145 146 mutex_exit(&ixgbe->gen_lock); 147 148 return (result); 149 } 150 151 /* 152 * Pass on M_IOCTL messages passed to the DLD, and support 153 * private IOCTLs for debugging and ndd. 154 */ 155 void 156 ixgbe_m_ioctl(void *arg, queue_t *q, mblk_t *mp) 157 { 158 ixgbe_t *ixgbe = (ixgbe_t *)arg; 159 struct iocblk *iocp; 160 enum ioc_reply status; 161 162 iocp = (struct iocblk *)(uintptr_t)mp->b_rptr; 163 iocp->ioc_error = 0; 164 165 mutex_enter(&ixgbe->gen_lock); 166 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 167 mutex_exit(&ixgbe->gen_lock); 168 miocnak(q, mp, 0, EINVAL); 169 return; 170 } 171 mutex_exit(&ixgbe->gen_lock); 172 173 switch (iocp->ioc_cmd) { 174 case LB_GET_INFO_SIZE: 175 case LB_GET_INFO: 176 case LB_GET_MODE: 177 case LB_SET_MODE: 178 status = ixgbe_loopback_ioctl(ixgbe, iocp, mp); 179 break; 180 181 default: 182 status = IOC_INVAL; 183 break; 184 } 185 186 /* 187 * Decide how to reply 188 */ 189 switch (status) { 190 default: 191 case IOC_INVAL: 192 /* 193 * Error, reply with a NAK and EINVAL or the specified error 194 */ 195 miocnak(q, mp, 0, iocp->ioc_error == 0 ? 196 EINVAL : iocp->ioc_error); 197 break; 198 199 case IOC_DONE: 200 /* 201 * OK, reply already sent 202 */ 203 break; 204 205 case IOC_ACK: 206 /* 207 * OK, reply with an ACK 208 */ 209 miocack(q, mp, 0, 0); 210 break; 211 212 case IOC_REPLY: 213 /* 214 * OK, send prepared reply as ACK or NAK 215 */ 216 mp->b_datap->db_type = iocp->ioc_error == 0 ? 217 M_IOCACK : M_IOCNAK; 218 qreply(q, mp); 219 break; 220 } 221 } 222 223 static int 224 ixgbe_led_set(void *arg, mac_led_mode_t mode, uint_t flags) 225 { 226 ixgbe_t *ixgbe = arg; 227 struct ixgbe_hw *hw = &ixgbe->hw; 228 uint32_t lidx = ixgbe->ixgbe_led_index; 229 230 if (flags != 0) 231 return (EINVAL); 232 233 if (mode != MAC_LED_DEFAULT && 234 mode != MAC_LED_IDENT && 235 mode != MAC_LED_OFF && 236 mode != MAC_LED_ON) 237 return (ENOTSUP); 238 239 if (ixgbe->ixgbe_led_blink && mode != MAC_LED_IDENT) { 240 if (ixgbe_blink_led_stop(hw, lidx) != IXGBE_SUCCESS) { 241 return (EIO); 242 } 243 ixgbe->ixgbe_led_blink = B_FALSE; 244 } 245 246 if (mode != MAC_LED_DEFAULT && !ixgbe->ixgbe_led_active) { 247 ixgbe->ixgbe_led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 248 ixgbe->ixgbe_led_active = B_TRUE; 249 } 250 251 switch (mode) { 252 case MAC_LED_DEFAULT: 253 if (ixgbe->ixgbe_led_active) { 254 IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ixgbe->ixgbe_led_reg); 255 ixgbe->ixgbe_led_active = B_FALSE; 256 } 257 break; 258 case MAC_LED_IDENT: 259 if (ixgbe_blink_led_start(hw, lidx) != IXGBE_SUCCESS) 260 return (EIO); 261 ixgbe->ixgbe_led_blink = B_TRUE; 262 break; 263 case MAC_LED_OFF: 264 if (ixgbe_led_off(hw, lidx) != IXGBE_SUCCESS) 265 return (EIO); 266 break; 267 case MAC_LED_ON: 268 if (ixgbe_led_on(hw, lidx) != IXGBE_SUCCESS) 269 return (EIO); 270 break; 271 default: 272 return (ENOTSUP); 273 } 274 275 return (0); 276 } 277 278 /* 279 * Obtain the MAC's capabilities and associated data from 280 * the driver. 281 */ 282 boolean_t 283 ixgbe_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 284 { 285 ixgbe_t *ixgbe = (ixgbe_t *)arg; 286 287 switch (cap) { 288 case MAC_CAPAB_HCKSUM: { 289 uint32_t *tx_hcksum_flags = cap_data; 290 291 /* 292 * We advertise our capabilities only if tx hcksum offload is 293 * enabled. On receive, the stack will accept checksummed 294 * packets anyway, even if we haven't said we can deliver 295 * them. 296 */ 297 if (!ixgbe->tx_hcksum_enable) 298 return (B_FALSE); 299 300 *tx_hcksum_flags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM; 301 break; 302 } 303 case MAC_CAPAB_LSO: { 304 mac_capab_lso_t *cap_lso = cap_data; 305 306 if (ixgbe->lso_enable) { 307 cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 308 cap_lso->lso_basic_tcp_ipv4.lso_max = IXGBE_LSO_MAXLEN; 309 break; 310 } else { 311 return (B_FALSE); 312 } 313 } 314 case MAC_CAPAB_RINGS: { 315 mac_capab_rings_t *cap_rings = cap_data; 316 317 switch (cap_rings->mr_type) { 318 case MAC_RING_TYPE_RX: 319 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 320 cap_rings->mr_rnum = ixgbe->num_rx_rings; 321 cap_rings->mr_gnum = ixgbe->num_rx_groups; 322 cap_rings->mr_rget = ixgbe_fill_ring; 323 cap_rings->mr_gget = ixgbe_fill_group; 324 cap_rings->mr_gaddring = NULL; 325 cap_rings->mr_gremring = NULL; 326 break; 327 case MAC_RING_TYPE_TX: 328 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 329 cap_rings->mr_rnum = ixgbe->num_tx_rings; 330 cap_rings->mr_gnum = 0; 331 cap_rings->mr_rget = ixgbe_fill_ring; 332 cap_rings->mr_gget = NULL; 333 break; 334 default: 335 break; 336 } 337 break; 338 } 339 case MAC_CAPAB_TRANSCEIVER: { 340 mac_capab_transceiver_t *mct = cap_data; 341 342 /* 343 * Rather than try and guess based on the media type whether or 344 * not we have a transceiver we can read, we instead will let 345 * the actual function calls figure that out for us. 346 */ 347 mct->mct_flags = 0; 348 mct->mct_ntransceivers = 1; 349 mct->mct_info = ixgbe_transceiver_info; 350 mct->mct_read = ixgbe_transceiver_read; 351 return (B_TRUE); 352 } 353 case MAC_CAPAB_LED: { 354 mac_capab_led_t *mcl = cap_data; 355 356 mcl->mcl_flags = 0; 357 mcl->mcl_modes = MAC_LED_DEFAULT | MAC_LED_ON | MAC_LED_OFF | 358 MAC_LED_IDENT; 359 mcl->mcl_set = ixgbe_led_set; 360 break; 361 362 } 363 default: 364 return (B_FALSE); 365 } 366 return (B_TRUE); 367 } 368 369 int 370 ixgbe_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 371 uint_t pr_valsize, const void *pr_val) 372 { 373 ixgbe_t *ixgbe = (ixgbe_t *)arg; 374 struct ixgbe_hw *hw = &ixgbe->hw; 375 int err = 0; 376 uint32_t flow_control; 377 uint32_t cur_mtu, new_mtu; 378 uint32_t rx_size; 379 uint32_t tx_size; 380 ixgbe_link_speed speeds = 0; 381 382 mutex_enter(&ixgbe->gen_lock); 383 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 384 mutex_exit(&ixgbe->gen_lock); 385 return (ECANCELED); 386 } 387 388 /* 389 * We cannot always rely on the common code maintaining 390 * hw->phy.speeds_supported, therefore we fall back to use the recorded 391 * supported speeds which were obtained during instance init in 392 * ixgbe_init_params(). 393 */ 394 speeds = hw->phy.speeds_supported; 395 if (speeds == 0) 396 speeds = ixgbe->speeds_supported; 397 398 if (ixgbe->loopback_mode != IXGBE_LB_NONE && 399 ixgbe_param_locked(pr_num)) { 400 /* 401 * All en_* parameters are locked (read-only) 402 * while the device is in any sort of loopback mode. 403 */ 404 mutex_exit(&ixgbe->gen_lock); 405 return (EBUSY); 406 } 407 408 /* 409 * We allow speed changes only on baseT PHYs. MAC_PROP_EN_* are marked 410 * read-only on non-baseT PHYs. 411 */ 412 switch (pr_num) { 413 case MAC_PROP_EN_10GFDX_CAP: 414 if (hw->phy.media_type == ixgbe_media_type_copper && 415 speeds & IXGBE_LINK_SPEED_10GB_FULL) { 416 ixgbe->param_en_10000fdx_cap = *(uint8_t *)pr_val; 417 goto setup_link; 418 } else { 419 err = ENOTSUP; 420 break; 421 } 422 case MAC_PROP_EN_5000FDX_CAP: 423 if (hw->phy.media_type == ixgbe_media_type_copper && 424 speeds & IXGBE_LINK_SPEED_5GB_FULL) { 425 ixgbe->param_en_5000fdx_cap = *(uint8_t *)pr_val; 426 goto setup_link; 427 } else { 428 err = ENOTSUP; 429 break; 430 } 431 case MAC_PROP_EN_2500FDX_CAP: 432 if (hw->phy.media_type == ixgbe_media_type_copper && 433 speeds & IXGBE_LINK_SPEED_2_5GB_FULL) { 434 ixgbe->param_en_2500fdx_cap = *(uint8_t *)pr_val; 435 goto setup_link; 436 } else { 437 err = ENOTSUP; 438 break; 439 } 440 case MAC_PROP_EN_1000FDX_CAP: 441 if (hw->phy.media_type == ixgbe_media_type_copper && 442 speeds & IXGBE_LINK_SPEED_1GB_FULL) { 443 ixgbe->param_en_1000fdx_cap = *(uint8_t *)pr_val; 444 goto setup_link; 445 } else { 446 err = ENOTSUP; 447 break; 448 } 449 case MAC_PROP_EN_100FDX_CAP: 450 if (hw->phy.media_type == ixgbe_media_type_copper && 451 speeds & IXGBE_LINK_SPEED_100_FULL) { 452 ixgbe->param_en_100fdx_cap = *(uint8_t *)pr_val; 453 goto setup_link; 454 } else { 455 err = ENOTSUP; 456 break; 457 } 458 case MAC_PROP_AUTONEG: 459 if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) { 460 err = ENOTSUP; 461 break; 462 } else { 463 ixgbe->param_adv_autoneg_cap = *(uint8_t *)pr_val; 464 goto setup_link; 465 } 466 case MAC_PROP_FLOWCTRL: 467 bcopy(pr_val, &flow_control, sizeof (flow_control)); 468 469 switch (flow_control) { 470 default: 471 err = EINVAL; 472 break; 473 case LINK_FLOWCTRL_NONE: 474 hw->fc.requested_mode = ixgbe_fc_none; 475 break; 476 case LINK_FLOWCTRL_RX: 477 hw->fc.requested_mode = ixgbe_fc_rx_pause; 478 break; 479 case LINK_FLOWCTRL_TX: 480 hw->fc.requested_mode = ixgbe_fc_tx_pause; 481 break; 482 case LINK_FLOWCTRL_BI: 483 hw->fc.requested_mode = ixgbe_fc_full; 484 break; 485 } 486 setup_link: 487 if (err == 0) { 488 if (ixgbe_driver_setup_link(ixgbe, B_TRUE) != 489 IXGBE_SUCCESS) 490 err = EINVAL; 491 } 492 break; 493 case MAC_PROP_ADV_10GFDX_CAP: 494 case MAC_PROP_ADV_5000FDX_CAP: 495 case MAC_PROP_ADV_2500FDX_CAP: 496 case MAC_PROP_ADV_1000FDX_CAP: 497 case MAC_PROP_ADV_100FDX_CAP: 498 case MAC_PROP_STATUS: 499 case MAC_PROP_SPEED: 500 case MAC_PROP_DUPLEX: 501 err = ENOTSUP; /* read-only prop. Can't set this. */ 502 break; 503 case MAC_PROP_MTU: 504 cur_mtu = ixgbe->default_mtu; 505 bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 506 if (new_mtu == cur_mtu) { 507 err = 0; 508 break; 509 } 510 511 if (new_mtu < DEFAULT_MTU || new_mtu > ixgbe->capab->max_mtu) { 512 err = EINVAL; 513 break; 514 } 515 516 if (ixgbe->ixgbe_state & IXGBE_STARTED) { 517 err = EBUSY; 518 break; 519 } 520 521 err = mac_maxsdu_update(ixgbe->mac_hdl, new_mtu); 522 if (err == 0) { 523 ixgbe->default_mtu = new_mtu; 524 ixgbe->max_frame_size = ixgbe->default_mtu + 525 sizeof (struct ether_vlan_header) + ETHERFCSL; 526 527 /* 528 * Set rx buffer size 529 */ 530 rx_size = ixgbe->max_frame_size + IPHDR_ALIGN_ROOM; 531 ixgbe->rx_buf_size = ((rx_size >> 10) + ((rx_size & 532 (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10; 533 534 /* 535 * Set tx buffer size 536 */ 537 tx_size = ixgbe->max_frame_size; 538 ixgbe->tx_buf_size = ((tx_size >> 10) + ((tx_size & 539 (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10; 540 } 541 break; 542 case MAC_PROP_PRIVATE: 543 err = ixgbe_set_priv_prop(ixgbe, pr_name, pr_valsize, pr_val); 544 break; 545 default: 546 err = ENOTSUP; 547 break; 548 } 549 mutex_exit(&ixgbe->gen_lock); 550 return (err); 551 } 552 553 int 554 ixgbe_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 555 uint_t pr_valsize, void *pr_val) 556 { 557 ixgbe_t *ixgbe = (ixgbe_t *)arg; 558 struct ixgbe_hw *hw = &ixgbe->hw; 559 int err = 0; 560 uint32_t flow_control; 561 uint64_t tmp = 0; 562 ixgbe_link_speed speeds = 0; 563 564 /* 565 * We cannot always rely on the common code maintaining 566 * hw->phy.speeds_supported, therefore we fall back to use the recorded 567 * supported speeds which were obtained during instance init in 568 * ixgbe_init_params(). 569 */ 570 speeds = hw->phy.speeds_supported; 571 if (speeds == 0) 572 speeds = ixgbe->speeds_supported; 573 574 switch (pr_num) { 575 case MAC_PROP_DUPLEX: 576 ASSERT(pr_valsize >= sizeof (link_duplex_t)); 577 bcopy(&ixgbe->link_duplex, pr_val, 578 sizeof (link_duplex_t)); 579 break; 580 case MAC_PROP_SPEED: 581 ASSERT(pr_valsize >= sizeof (uint64_t)); 582 tmp = ixgbe->link_speed * 1000000ull; 583 bcopy(&tmp, pr_val, sizeof (tmp)); 584 break; 585 case MAC_PROP_AUTONEG: 586 *(uint8_t *)pr_val = ixgbe->param_adv_autoneg_cap; 587 break; 588 case MAC_PROP_FLOWCTRL: 589 ASSERT(pr_valsize >= sizeof (uint32_t)); 590 591 switch (hw->fc.requested_mode) { 592 case ixgbe_fc_none: 593 flow_control = LINK_FLOWCTRL_NONE; 594 break; 595 case ixgbe_fc_rx_pause: 596 flow_control = LINK_FLOWCTRL_RX; 597 break; 598 case ixgbe_fc_tx_pause: 599 flow_control = LINK_FLOWCTRL_TX; 600 break; 601 case ixgbe_fc_full: 602 flow_control = LINK_FLOWCTRL_BI; 603 break; 604 } 605 bcopy(&flow_control, pr_val, sizeof (flow_control)); 606 break; 607 case MAC_PROP_ADV_10GFDX_CAP: 608 if (speeds & IXGBE_LINK_SPEED_10GB_FULL) 609 *(uint8_t *)pr_val = ixgbe->param_adv_10000fdx_cap; 610 else 611 err = ENOTSUP; 612 break; 613 case MAC_PROP_EN_10GFDX_CAP: 614 if (speeds & IXGBE_LINK_SPEED_10GB_FULL) 615 *(uint8_t *)pr_val = ixgbe->param_en_10000fdx_cap; 616 else 617 err = ENOTSUP; 618 break; 619 case MAC_PROP_ADV_5000FDX_CAP: 620 if (speeds & IXGBE_LINK_SPEED_5GB_FULL) 621 *(uint8_t *)pr_val = ixgbe->param_adv_5000fdx_cap; 622 else 623 err = ENOTSUP; 624 break; 625 case MAC_PROP_EN_5000FDX_CAP: 626 if (speeds & IXGBE_LINK_SPEED_5GB_FULL) 627 *(uint8_t *)pr_val = ixgbe->param_en_5000fdx_cap; 628 else 629 err = ENOTSUP; 630 break; 631 case MAC_PROP_ADV_2500FDX_CAP: 632 if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL) 633 *(uint8_t *)pr_val = ixgbe->param_adv_2500fdx_cap; 634 else 635 err = ENOTSUP; 636 break; 637 case MAC_PROP_EN_2500FDX_CAP: 638 if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL) 639 *(uint8_t *)pr_val = ixgbe->param_en_2500fdx_cap; 640 else 641 err = ENOTSUP; 642 break; 643 case MAC_PROP_ADV_1000FDX_CAP: 644 if (speeds & IXGBE_LINK_SPEED_1GB_FULL) 645 *(uint8_t *)pr_val = ixgbe->param_adv_1000fdx_cap; 646 else 647 err = ENOTSUP; 648 break; 649 case MAC_PROP_EN_1000FDX_CAP: 650 if (speeds & IXGBE_LINK_SPEED_1GB_FULL) 651 *(uint8_t *)pr_val = ixgbe->param_en_1000fdx_cap; 652 else 653 err = ENOTSUP; 654 break; 655 case MAC_PROP_ADV_100FDX_CAP: 656 if (speeds & IXGBE_LINK_SPEED_100_FULL) 657 *(uint8_t *)pr_val = ixgbe->param_adv_100fdx_cap; 658 else 659 err = ENOTSUP; 660 break; 661 case MAC_PROP_EN_100FDX_CAP: 662 if (speeds & IXGBE_LINK_SPEED_100_FULL) 663 *(uint8_t *)pr_val = ixgbe->param_en_100fdx_cap; 664 else 665 err = ENOTSUP; 666 break; 667 case MAC_PROP_PRIVATE: 668 err = ixgbe_get_priv_prop(ixgbe, pr_name, 669 pr_valsize, pr_val); 670 break; 671 default: 672 err = ENOTSUP; 673 break; 674 } 675 return (err); 676 } 677 678 void 679 ixgbe_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num, 680 mac_prop_info_handle_t prh) 681 { 682 ixgbe_t *ixgbe = (ixgbe_t *)arg; 683 struct ixgbe_hw *hw = &ixgbe->hw; 684 uint_t perm; 685 uint8_t value; 686 ixgbe_link_speed speeds = 0; 687 688 /* 689 * We cannot always rely on the common code maintaining 690 * hw->phy.speeds_supported, therefore we fall back to use the 691 * recorded supported speeds which were obtained during instance init in 692 * ixgbe_init_params(). 693 */ 694 speeds = hw->phy.speeds_supported; 695 if (speeds == 0) 696 speeds = ixgbe->speeds_supported; 697 698 switch (pr_num) { 699 case MAC_PROP_DUPLEX: 700 case MAC_PROP_SPEED: 701 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 702 break; 703 704 case MAC_PROP_ADV_100FDX_CAP: 705 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 706 value = (speeds & IXGBE_LINK_SPEED_100_FULL) ? 1 : 0; 707 mac_prop_info_set_default_uint8(prh, value); 708 break; 709 710 case MAC_PROP_ADV_1000FDX_CAP: 711 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 712 value = (speeds & IXGBE_LINK_SPEED_1GB_FULL) ? 1 : 0; 713 mac_prop_info_set_default_uint8(prh, value); 714 break; 715 716 case MAC_PROP_ADV_2500FDX_CAP: 717 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 718 value = (speeds & IXGBE_LINK_SPEED_2_5GB_FULL) ? 1 : 0; 719 mac_prop_info_set_default_uint8(prh, value); 720 break; 721 722 case MAC_PROP_ADV_5000FDX_CAP: 723 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 724 value = (speeds & IXGBE_LINK_SPEED_5GB_FULL) ? 1 : 0; 725 mac_prop_info_set_default_uint8(prh, value); 726 break; 727 728 case MAC_PROP_ADV_10GFDX_CAP: 729 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 730 value = (speeds & IXGBE_LINK_SPEED_10GB_FULL) ? 1 : 0; 731 mac_prop_info_set_default_uint8(prh, value); 732 break; 733 734 /* 735 * We allow speed changes only on baseT PHYs. MAC_PROP_EN_* are marked 736 * read-only on non-baseT (SFP) PHYs. 737 */ 738 case MAC_PROP_AUTONEG: 739 perm = (hw->phy.media_type == ixgbe_media_type_copper) ? 740 MAC_PROP_PERM_RW : MAC_PROP_PERM_READ; 741 mac_prop_info_set_perm(prh, perm); 742 mac_prop_info_set_default_uint8(prh, 1); 743 break; 744 745 case MAC_PROP_EN_10GFDX_CAP: 746 if (speeds & IXGBE_LINK_SPEED_10GB_FULL) { 747 perm = (hw->phy.media_type == ixgbe_media_type_copper) ? 748 MAC_PROP_PERM_RW : MAC_PROP_PERM_READ; 749 mac_prop_info_set_perm(prh, perm); 750 mac_prop_info_set_default_uint8(prh, 1); 751 } 752 break; 753 754 case MAC_PROP_EN_5000FDX_CAP: 755 if (speeds & IXGBE_LINK_SPEED_5GB_FULL) { 756 perm = (hw->phy.media_type == ixgbe_media_type_copper) ? 757 MAC_PROP_PERM_RW : MAC_PROP_PERM_READ; 758 mac_prop_info_set_perm(prh, perm); 759 mac_prop_info_set_default_uint8(prh, 1); 760 } 761 break; 762 763 case MAC_PROP_EN_2500FDX_CAP: 764 if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL) { 765 perm = (hw->phy.media_type == ixgbe_media_type_copper) ? 766 MAC_PROP_PERM_RW : MAC_PROP_PERM_READ; 767 mac_prop_info_set_perm(prh, perm); 768 mac_prop_info_set_default_uint8(prh, 1); 769 } 770 break; 771 772 case MAC_PROP_EN_1000FDX_CAP: 773 if (speeds & IXGBE_LINK_SPEED_1GB_FULL) { 774 perm = (hw->phy.media_type == ixgbe_media_type_copper) ? 775 MAC_PROP_PERM_RW : MAC_PROP_PERM_READ; 776 mac_prop_info_set_perm(prh, perm); 777 mac_prop_info_set_default_uint8(prh, 1); 778 } 779 break; 780 781 case MAC_PROP_EN_100FDX_CAP: 782 if (speeds & IXGBE_LINK_SPEED_100_FULL) { 783 perm = (hw->phy.media_type == ixgbe_media_type_copper) ? 784 MAC_PROP_PERM_RW : MAC_PROP_PERM_READ; 785 mac_prop_info_set_perm(prh, perm); 786 mac_prop_info_set_default_uint8(prh, 1); 787 } 788 break; 789 790 case MAC_PROP_FLOWCTRL: 791 mac_prop_info_set_default_link_flowctrl(prh, 792 LINK_FLOWCTRL_NONE); 793 break; 794 795 case MAC_PROP_MTU: 796 mac_prop_info_set_range_uint32(prh, 797 DEFAULT_MTU, ixgbe->capab->max_mtu); 798 break; 799 800 case MAC_PROP_PRIVATE: { 801 char valstr[64]; 802 int value; 803 804 bzero(valstr, sizeof (valstr)); 805 806 if (strcmp(pr_name, "_adv_pause_cap") == 0 || 807 strcmp(pr_name, "_adv_asym_pause_cap") == 0) { 808 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 809 return; 810 } 811 812 if (strcmp(pr_name, "_tx_copy_thresh") == 0) { 813 value = DEFAULT_TX_COPY_THRESHOLD; 814 } else if (strcmp(pr_name, "_tx_recycle_thresh") == 0) { 815 value = DEFAULT_TX_RECYCLE_THRESHOLD; 816 } else if (strcmp(pr_name, "_tx_overload_thresh") == 0) { 817 value = DEFAULT_TX_OVERLOAD_THRESHOLD; 818 } else if (strcmp(pr_name, "_tx_resched_thresh") == 0) { 819 value = DEFAULT_TX_RESCHED_THRESHOLD; 820 } else if (strcmp(pr_name, "_rx_copy_thresh") == 0) { 821 value = DEFAULT_RX_COPY_THRESHOLD; 822 } else if (strcmp(pr_name, "_rx_limit_per_intr") == 0) { 823 value = DEFAULT_RX_LIMIT_PER_INTR; 824 } else if (strcmp(pr_name, "_intr_throttling") == 0) { 825 value = ixgbe->capab->def_intr_throttle; 826 } else { 827 return; 828 } 829 830 (void) snprintf(valstr, sizeof (valstr), "%x", value); 831 } 832 } 833 } 834 835 boolean_t 836 ixgbe_param_locked(mac_prop_id_t pr_num) 837 { 838 /* 839 * All en_* parameters are locked (read-only) while 840 * the device is in any sort of loopback mode ... 841 */ 842 switch (pr_num) { 843 case MAC_PROP_EN_10GFDX_CAP: 844 case MAC_PROP_EN_5000FDX_CAP: 845 case MAC_PROP_EN_2500FDX_CAP: 846 case MAC_PROP_EN_1000FDX_CAP: 847 case MAC_PROP_EN_100FDX_CAP: 848 case MAC_PROP_AUTONEG: 849 case MAC_PROP_FLOWCTRL: 850 return (B_TRUE); 851 } 852 return (B_FALSE); 853 } 854 855 /* ARGSUSED */ 856 int 857 ixgbe_set_priv_prop(ixgbe_t *ixgbe, const char *pr_name, 858 uint_t pr_valsize, const void *pr_val) 859 { 860 int err = 0; 861 long result; 862 struct ixgbe_hw *hw = &ixgbe->hw; 863 int i; 864 865 if (strcmp(pr_name, "_tx_copy_thresh") == 0) { 866 if (pr_val == NULL) { 867 err = EINVAL; 868 return (err); 869 } 870 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 871 if (result < MIN_TX_COPY_THRESHOLD || 872 result > MAX_TX_COPY_THRESHOLD) 873 err = EINVAL; 874 else { 875 ixgbe->tx_copy_thresh = (uint32_t)result; 876 } 877 return (err); 878 } 879 if (strcmp(pr_name, "_tx_recycle_thresh") == 0) { 880 if (pr_val == NULL) { 881 err = EINVAL; 882 return (err); 883 } 884 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 885 if (result < MIN_TX_RECYCLE_THRESHOLD || 886 result > MAX_TX_RECYCLE_THRESHOLD) 887 err = EINVAL; 888 else { 889 ixgbe->tx_recycle_thresh = (uint32_t)result; 890 } 891 return (err); 892 } 893 if (strcmp(pr_name, "_tx_overload_thresh") == 0) { 894 if (pr_val == NULL) { 895 err = EINVAL; 896 return (err); 897 } 898 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 899 if (result < MIN_TX_OVERLOAD_THRESHOLD || 900 result > MAX_TX_OVERLOAD_THRESHOLD) 901 err = EINVAL; 902 else { 903 ixgbe->tx_overload_thresh = (uint32_t)result; 904 } 905 return (err); 906 } 907 if (strcmp(pr_name, "_tx_resched_thresh") == 0) { 908 if (pr_val == NULL) { 909 err = EINVAL; 910 return (err); 911 } 912 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 913 if (result < MIN_TX_RESCHED_THRESHOLD || 914 result > MAX_TX_RESCHED_THRESHOLD) 915 err = EINVAL; 916 else { 917 ixgbe->tx_resched_thresh = (uint32_t)result; 918 } 919 return (err); 920 } 921 if (strcmp(pr_name, "_rx_copy_thresh") == 0) { 922 if (pr_val == NULL) { 923 err = EINVAL; 924 return (err); 925 } 926 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 927 if (result < MIN_RX_COPY_THRESHOLD || 928 result > MAX_RX_COPY_THRESHOLD) 929 err = EINVAL; 930 else { 931 ixgbe->rx_copy_thresh = (uint32_t)result; 932 } 933 return (err); 934 } 935 if (strcmp(pr_name, "_rx_limit_per_intr") == 0) { 936 if (pr_val == NULL) { 937 err = EINVAL; 938 return (err); 939 } 940 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 941 if (result < MIN_RX_LIMIT_PER_INTR || 942 result > MAX_RX_LIMIT_PER_INTR) 943 err = EINVAL; 944 else { 945 ixgbe->rx_limit_per_intr = (uint32_t)result; 946 } 947 return (err); 948 } 949 if (strcmp(pr_name, "_intr_throttling") == 0) { 950 if (pr_val == NULL) { 951 err = EINVAL; 952 return (err); 953 } 954 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 955 956 if (result < ixgbe->capab->min_intr_throttle || 957 result > ixgbe->capab->max_intr_throttle) 958 err = EINVAL; 959 else { 960 ixgbe->intr_throttling[0] = (uint32_t)result; 961 962 /* 963 * 82599, X540 and X550 require the interrupt throttling 964 * rate is a multiple of 8. This is enforced by the 965 * register definiton. 966 */ 967 if (hw->mac.type == ixgbe_mac_82599EB || 968 hw->mac.type == ixgbe_mac_X540 || 969 hw->mac.type == ixgbe_mac_X550 || 970 hw->mac.type == ixgbe_mac_X550EM_x) { 971 ixgbe->intr_throttling[0] = 972 ixgbe->intr_throttling[0] & 0xFF8; 973 } 974 975 for (i = 0; i < MAX_INTR_VECTOR; i++) 976 ixgbe->intr_throttling[i] = 977 ixgbe->intr_throttling[0]; 978 979 /* Set interrupt throttling rate */ 980 for (i = 0; i < ixgbe->intr_cnt; i++) 981 IXGBE_WRITE_REG(hw, IXGBE_EITR(i), 982 ixgbe->intr_throttling[i]); 983 } 984 return (err); 985 } 986 return (ENOTSUP); 987 } 988 989 int 990 ixgbe_get_priv_prop(ixgbe_t *ixgbe, const char *pr_name, 991 uint_t pr_valsize, void *pr_val) 992 { 993 int err = ENOTSUP; 994 int value; 995 996 if (strcmp(pr_name, "_adv_pause_cap") == 0) { 997 value = ixgbe->param_adv_pause_cap; 998 err = 0; 999 goto done; 1000 } 1001 if (strcmp(pr_name, "_adv_asym_pause_cap") == 0) { 1002 value = ixgbe->param_adv_asym_pause_cap; 1003 err = 0; 1004 goto done; 1005 } 1006 if (strcmp(pr_name, "_tx_copy_thresh") == 0) { 1007 value = ixgbe->tx_copy_thresh; 1008 err = 0; 1009 goto done; 1010 } 1011 if (strcmp(pr_name, "_tx_recycle_thresh") == 0) { 1012 value = ixgbe->tx_recycle_thresh; 1013 err = 0; 1014 goto done; 1015 } 1016 if (strcmp(pr_name, "_tx_overload_thresh") == 0) { 1017 value = ixgbe->tx_overload_thresh; 1018 err = 0; 1019 goto done; 1020 } 1021 if (strcmp(pr_name, "_tx_resched_thresh") == 0) { 1022 value = ixgbe->tx_resched_thresh; 1023 err = 0; 1024 goto done; 1025 } 1026 if (strcmp(pr_name, "_rx_copy_thresh") == 0) { 1027 value = ixgbe->rx_copy_thresh; 1028 err = 0; 1029 goto done; 1030 } 1031 if (strcmp(pr_name, "_rx_limit_per_intr") == 0) { 1032 value = ixgbe->rx_limit_per_intr; 1033 err = 0; 1034 goto done; 1035 } 1036 if (strcmp(pr_name, "_intr_throttling") == 0) { 1037 value = ixgbe->intr_throttling[0]; 1038 err = 0; 1039 goto done; 1040 } 1041 done: 1042 if (err == 0) { 1043 (void) snprintf(pr_val, pr_valsize, "%d", value); 1044 } 1045 return (err); 1046 } 1047