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) 2017, 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                 }       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 }