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 2013 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                         /* Don't autoneg if forcing a value */
 489                         ixgbe->hw.fc.disable_fc_autoneg = TRUE;
 490                         (void) ixgbe_fc_enable(hw);
 491 
 492                         if (ixgbe_driver_setup_link(ixgbe, B_TRUE) !=
 493                             IXGBE_SUCCESS)
 494                                 err = EINVAL;
 495                 }
 496                 break;
 497         case MAC_PROP_ADV_10GFDX_CAP:
 498         case MAC_PROP_ADV_5000FDX_CAP:
 499         case MAC_PROP_ADV_2500FDX_CAP:
 500         case MAC_PROP_ADV_1000FDX_CAP:
 501         case MAC_PROP_ADV_100FDX_CAP:
 502         case MAC_PROP_STATUS:
 503         case MAC_PROP_SPEED:
 504         case MAC_PROP_DUPLEX:
 505                 err = ENOTSUP; /* read-only prop. Can't set this. */
 506                 break;
 507         case MAC_PROP_MTU:
 508                 cur_mtu = ixgbe->default_mtu;
 509                 bcopy(pr_val, &new_mtu, sizeof (new_mtu));
 510                 if (new_mtu == cur_mtu) {
 511                         err = 0;
 512                         break;
 513                 }
 514 
 515                 if (new_mtu < DEFAULT_MTU || new_mtu > ixgbe->capab->max_mtu) {
 516                         err = EINVAL;
 517                         break;
 518                 }
 519 
 520                 if (ixgbe->ixgbe_state & IXGBE_STARTED) {
 521                         err = EBUSY;
 522                         break;
 523                 }
 524 
 525                 err = mac_maxsdu_update(ixgbe->mac_hdl, new_mtu);
 526                 if (err == 0) {
 527                         ixgbe->default_mtu = new_mtu;
 528                         ixgbe->max_frame_size = ixgbe->default_mtu +
 529                             sizeof (struct ether_vlan_header) + ETHERFCSL;
 530 
 531                         /*
 532                          * Set rx buffer size
 533                          */
 534                         rx_size = ixgbe->max_frame_size + IPHDR_ALIGN_ROOM;
 535                         ixgbe->rx_buf_size = ((rx_size >> 10) + ((rx_size &
 536                             (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
 537 
 538                         /*
 539                          * Set tx buffer size
 540                          */
 541                         tx_size = ixgbe->max_frame_size;
 542                         ixgbe->tx_buf_size = ((tx_size >> 10) + ((tx_size &
 543                             (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
 544                 }
 545                 break;
 546         case MAC_PROP_PRIVATE:
 547                 err = ixgbe_set_priv_prop(ixgbe, pr_name, pr_valsize, pr_val);
 548                 break;
 549         default:
 550                 err = ENOTSUP;
 551                 break;
 552         }
 553         mutex_exit(&ixgbe->gen_lock);
 554         return (err);
 555 }
 556 
 557 int
 558 ixgbe_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
 559     uint_t pr_valsize, void *pr_val)
 560 {
 561         ixgbe_t *ixgbe = (ixgbe_t *)arg;
 562         struct ixgbe_hw *hw = &ixgbe->hw;
 563         int err = 0;
 564         uint32_t flow_control;
 565         uint64_t tmp = 0;
 566         ixgbe_link_speed speeds = 0;
 567 
 568         /*
 569          * We cannot always rely on the common code maintaining
 570          * hw->phy.speeds_supported, therefore we fall back to use the recorded
 571          * supported speeds which were obtained during instance init in
 572          * ixgbe_init_params().
 573          */
 574         speeds = hw->phy.speeds_supported;
 575         if (speeds == 0)
 576                 speeds = ixgbe->speeds_supported;
 577 
 578         switch (pr_num) {
 579         case MAC_PROP_DUPLEX:
 580                 ASSERT(pr_valsize >= sizeof (link_duplex_t));
 581                 bcopy(&ixgbe->link_duplex, pr_val,
 582                     sizeof (link_duplex_t));
 583                 break;
 584         case MAC_PROP_SPEED:
 585                 ASSERT(pr_valsize >= sizeof (uint64_t));
 586                 tmp = ixgbe->link_speed * 1000000ull;
 587                 bcopy(&tmp, pr_val, sizeof (tmp));
 588                 break;
 589         case MAC_PROP_AUTONEG:
 590                 *(uint8_t *)pr_val = ixgbe->param_adv_autoneg_cap;
 591                 break;
 592         case MAC_PROP_FLOWCTRL:
 593                 ASSERT(pr_valsize >= sizeof (uint32_t));
 594 
 595                 switch (hw->fc.requested_mode) {
 596                         case ixgbe_fc_none:
 597                                 flow_control = LINK_FLOWCTRL_NONE;
 598                                 break;
 599                         case ixgbe_fc_rx_pause:
 600                                 flow_control = LINK_FLOWCTRL_RX;
 601                                 break;
 602                         case ixgbe_fc_tx_pause:
 603                                 flow_control = LINK_FLOWCTRL_TX;
 604                                 break;
 605                         case ixgbe_fc_full:
 606                                 flow_control = LINK_FLOWCTRL_BI;
 607                                 break;
 608                 }
 609                 bcopy(&flow_control, pr_val, sizeof (flow_control));
 610                 break;
 611         case MAC_PROP_ADV_10GFDX_CAP:
 612                 if (speeds & IXGBE_LINK_SPEED_10GB_FULL)
 613                         *(uint8_t *)pr_val = ixgbe->param_adv_10000fdx_cap;
 614                 else
 615                         err = ENOTSUP;
 616                 break;
 617         case MAC_PROP_EN_10GFDX_CAP:
 618                 if (speeds & IXGBE_LINK_SPEED_10GB_FULL)
 619                         *(uint8_t *)pr_val = ixgbe->param_en_10000fdx_cap;
 620                 else
 621                         err = ENOTSUP;
 622                 break;
 623         case MAC_PROP_ADV_5000FDX_CAP:
 624                 if (speeds & IXGBE_LINK_SPEED_5GB_FULL)
 625                         *(uint8_t *)pr_val = ixgbe->param_adv_5000fdx_cap;
 626                 else
 627                         err = ENOTSUP;
 628                 break;
 629         case MAC_PROP_EN_5000FDX_CAP:
 630                 if (speeds & IXGBE_LINK_SPEED_5GB_FULL)
 631                         *(uint8_t *)pr_val = ixgbe->param_en_5000fdx_cap;
 632                 else
 633                         err = ENOTSUP;
 634                 break;
 635         case MAC_PROP_ADV_2500FDX_CAP:
 636                 if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL)
 637                         *(uint8_t *)pr_val = ixgbe->param_adv_2500fdx_cap;
 638                 else
 639                         err = ENOTSUP;
 640                 break;
 641         case MAC_PROP_EN_2500FDX_CAP:
 642                 if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL)
 643                         *(uint8_t *)pr_val = ixgbe->param_en_2500fdx_cap;
 644                 else
 645                         err = ENOTSUP;
 646                 break;
 647         case MAC_PROP_ADV_1000FDX_CAP:
 648                 if (speeds & IXGBE_LINK_SPEED_1GB_FULL)
 649                         *(uint8_t *)pr_val = ixgbe->param_adv_1000fdx_cap;
 650                 else
 651                         err = ENOTSUP;
 652                 break;
 653         case MAC_PROP_EN_1000FDX_CAP:
 654                 if (speeds & IXGBE_LINK_SPEED_1GB_FULL)
 655                         *(uint8_t *)pr_val = ixgbe->param_en_1000fdx_cap;
 656                 else
 657                         err = ENOTSUP;
 658                 break;
 659         case MAC_PROP_ADV_100FDX_CAP:
 660                 if (speeds & IXGBE_LINK_SPEED_100_FULL)
 661                         *(uint8_t *)pr_val = ixgbe->param_adv_100fdx_cap;
 662                 else
 663                         err = ENOTSUP;
 664                 break;
 665         case MAC_PROP_EN_100FDX_CAP:
 666                 if (speeds & IXGBE_LINK_SPEED_100_FULL)
 667                         *(uint8_t *)pr_val = ixgbe->param_en_100fdx_cap;
 668                 else
 669                         err = ENOTSUP;
 670                 break;
 671         case MAC_PROP_PRIVATE:
 672                 err = ixgbe_get_priv_prop(ixgbe, pr_name,
 673                     pr_valsize, pr_val);
 674                 break;
 675         default:
 676                 err = ENOTSUP;
 677                 break;
 678         }
 679         return (err);
 680 }
 681 
 682 void
 683 ixgbe_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
 684     mac_prop_info_handle_t prh)
 685 {
 686         ixgbe_t *ixgbe = (ixgbe_t *)arg;
 687         struct ixgbe_hw *hw = &ixgbe->hw;
 688         uint_t perm;
 689         uint8_t value;
 690         ixgbe_link_speed speeds = 0;
 691 
 692         /*
 693          * We cannot always rely on the common code maintaining
 694          * hw->phy.speeds_supported, therefore we fall back to use the
 695          * recorded supported speeds which were obtained during instance init in
 696          * ixgbe_init_params().
 697          */
 698         speeds = hw->phy.speeds_supported;
 699         if (speeds == 0)
 700                 speeds = ixgbe->speeds_supported;
 701 
 702         switch (pr_num) {
 703         case MAC_PROP_DUPLEX:
 704         case MAC_PROP_SPEED:
 705                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
 706                 break;
 707 
 708         case MAC_PROP_ADV_100FDX_CAP:
 709                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
 710                 value = (speeds & IXGBE_LINK_SPEED_100_FULL) ? 1 : 0;
 711                 mac_prop_info_set_default_uint8(prh, value);
 712                 break;
 713 
 714         case MAC_PROP_ADV_1000FDX_CAP:
 715                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
 716                 value = (speeds & IXGBE_LINK_SPEED_1GB_FULL) ? 1 : 0;
 717                 mac_prop_info_set_default_uint8(prh, value);
 718                 break;
 719 
 720         case MAC_PROP_ADV_2500FDX_CAP:
 721                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
 722                 value = (speeds & IXGBE_LINK_SPEED_2_5GB_FULL) ? 1 : 0;
 723                 mac_prop_info_set_default_uint8(prh, value);
 724                 break;
 725 
 726         case MAC_PROP_ADV_5000FDX_CAP:
 727                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
 728                 value = (speeds & IXGBE_LINK_SPEED_5GB_FULL) ? 1 : 0;
 729                 mac_prop_info_set_default_uint8(prh, value);
 730                 break;
 731 
 732         case MAC_PROP_ADV_10GFDX_CAP:
 733                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
 734                 value = (speeds & IXGBE_LINK_SPEED_10GB_FULL) ? 1 : 0;
 735                 mac_prop_info_set_default_uint8(prh, value);
 736                 break;
 737 
 738         /*
 739          * We allow speed changes only on baseT PHYs. MAC_PROP_EN_* are marked
 740          * read-only on non-baseT (SFP) PHYs.
 741          */
 742         case MAC_PROP_AUTONEG:
 743                 perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
 744                     MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
 745                 mac_prop_info_set_perm(prh, perm);
 746                 mac_prop_info_set_default_uint8(prh, 1);
 747                 break;
 748 
 749         case MAC_PROP_EN_10GFDX_CAP:
 750                 if (speeds & IXGBE_LINK_SPEED_10GB_FULL) {
 751                         perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
 752                             MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
 753                         mac_prop_info_set_perm(prh, perm);
 754                         mac_prop_info_set_default_uint8(prh, 1);
 755                 }
 756                 break;
 757 
 758         case MAC_PROP_EN_5000FDX_CAP:
 759                 if (speeds & IXGBE_LINK_SPEED_5GB_FULL) {
 760                         perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
 761                             MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
 762                         mac_prop_info_set_perm(prh, perm);
 763                         mac_prop_info_set_default_uint8(prh, 1);
 764                 }
 765                 break;
 766 
 767         case MAC_PROP_EN_2500FDX_CAP:
 768                 if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL) {
 769                         perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
 770                             MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
 771                         mac_prop_info_set_perm(prh, perm);
 772                         mac_prop_info_set_default_uint8(prh, 1);
 773                 }
 774                 break;
 775 
 776         case MAC_PROP_EN_1000FDX_CAP:
 777                 if (speeds & IXGBE_LINK_SPEED_1GB_FULL) {
 778                         perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
 779                             MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
 780                         mac_prop_info_set_perm(prh, perm);
 781                         mac_prop_info_set_default_uint8(prh, 1);
 782                 }
 783                 break;
 784 
 785         case MAC_PROP_EN_100FDX_CAP:
 786                 if (speeds & IXGBE_LINK_SPEED_100_FULL) {
 787                         perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
 788                             MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
 789                         mac_prop_info_set_perm(prh, perm);
 790                         mac_prop_info_set_default_uint8(prh, 1);
 791                 }
 792                 break;
 793 
 794         case MAC_PROP_FLOWCTRL:
 795                 mac_prop_info_set_default_link_flowctrl(prh,
 796                     LINK_FLOWCTRL_NONE);
 797                 break;
 798 
 799         case MAC_PROP_MTU:
 800                 mac_prop_info_set_range_uint32(prh,
 801                     DEFAULT_MTU, ixgbe->capab->max_mtu);
 802                 break;
 803 
 804         case MAC_PROP_PRIVATE: {
 805                 char valstr[64];
 806                 int value;
 807 
 808                 bzero(valstr, sizeof (valstr));
 809 
 810                 if (strcmp(pr_name, "_adv_pause_cap") == 0 ||
 811                     strcmp(pr_name, "_adv_asym_pause_cap") == 0) {
 812                         mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
 813                         return;
 814                 }
 815 
 816                 if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
 817                         value = DEFAULT_TX_COPY_THRESHOLD;
 818                 } else if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
 819                         value = DEFAULT_TX_RECYCLE_THRESHOLD;
 820                 } else if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
 821                         value = DEFAULT_TX_OVERLOAD_THRESHOLD;
 822                 } else if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
 823                         value = DEFAULT_TX_RESCHED_THRESHOLD;
 824                 } else  if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
 825                         value = DEFAULT_RX_COPY_THRESHOLD;
 826                 } else  if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
 827                         value = DEFAULT_RX_LIMIT_PER_INTR;
 828                 }       if (strcmp(pr_name, "_intr_throttling") == 0) {
 829                         value = ixgbe->capab->def_intr_throttle;
 830                 } else {
 831                         return;
 832                 }
 833 
 834                 (void) snprintf(valstr, sizeof (valstr), "%x", value);
 835         }
 836         }
 837 }
 838 
 839 boolean_t
 840 ixgbe_param_locked(mac_prop_id_t pr_num)
 841 {
 842         /*
 843          * All en_* parameters are locked (read-only) while
 844          * the device is in any sort of loopback mode ...
 845          */
 846         switch (pr_num) {
 847                 case MAC_PROP_EN_10GFDX_CAP:
 848                 case MAC_PROP_EN_5000FDX_CAP:
 849                 case MAC_PROP_EN_2500FDX_CAP:
 850                 case MAC_PROP_EN_1000FDX_CAP:
 851                 case MAC_PROP_EN_100FDX_CAP:
 852                 case MAC_PROP_AUTONEG:
 853                 case MAC_PROP_FLOWCTRL:
 854                         return (B_TRUE);
 855         }
 856         return (B_FALSE);
 857 }
 858 
 859 /* ARGSUSED */
 860 int
 861 ixgbe_set_priv_prop(ixgbe_t *ixgbe, const char *pr_name,
 862     uint_t pr_valsize, const void *pr_val)
 863 {
 864         int err = 0;
 865         long result;
 866         struct ixgbe_hw *hw = &ixgbe->hw;
 867         int i;
 868 
 869         if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
 870                 if (pr_val == NULL) {
 871                         err = EINVAL;
 872                         return (err);
 873                 }
 874                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
 875                 if (result < MIN_TX_COPY_THRESHOLD ||
 876                     result > MAX_TX_COPY_THRESHOLD)
 877                         err = EINVAL;
 878                 else {
 879                         ixgbe->tx_copy_thresh = (uint32_t)result;
 880                 }
 881                 return (err);
 882         }
 883         if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
 884                 if (pr_val == NULL) {
 885                         err = EINVAL;
 886                         return (err);
 887                 }
 888                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
 889                 if (result < MIN_TX_RECYCLE_THRESHOLD ||
 890                     result > MAX_TX_RECYCLE_THRESHOLD)
 891                         err = EINVAL;
 892                 else {
 893                         ixgbe->tx_recycle_thresh = (uint32_t)result;
 894                 }
 895                 return (err);
 896         }
 897         if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
 898                 if (pr_val == NULL) {
 899                         err = EINVAL;
 900                         return (err);
 901                 }
 902                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
 903                 if (result < MIN_TX_OVERLOAD_THRESHOLD ||
 904                     result > MAX_TX_OVERLOAD_THRESHOLD)
 905                         err = EINVAL;
 906                 else {
 907                         ixgbe->tx_overload_thresh = (uint32_t)result;
 908                 }
 909                 return (err);
 910         }
 911         if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
 912                 if (pr_val == NULL) {
 913                         err = EINVAL;
 914                         return (err);
 915                 }
 916                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
 917                 if (result < MIN_TX_RESCHED_THRESHOLD ||
 918                     result > MAX_TX_RESCHED_THRESHOLD)
 919                         err = EINVAL;
 920                 else {
 921                         ixgbe->tx_resched_thresh = (uint32_t)result;
 922                 }
 923                 return (err);
 924         }
 925         if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
 926                 if (pr_val == NULL) {
 927                         err = EINVAL;
 928                         return (err);
 929                 }
 930                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
 931                 if (result < MIN_RX_COPY_THRESHOLD ||
 932                     result > MAX_RX_COPY_THRESHOLD)
 933                         err = EINVAL;
 934                 else {
 935                         ixgbe->rx_copy_thresh = (uint32_t)result;
 936                 }
 937                 return (err);
 938         }
 939         if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
 940                 if (pr_val == NULL) {
 941                         err = EINVAL;
 942                         return (err);
 943                 }
 944                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
 945                 if (result < MIN_RX_LIMIT_PER_INTR ||
 946                     result > MAX_RX_LIMIT_PER_INTR)
 947                         err = EINVAL;
 948                 else {
 949                         ixgbe->rx_limit_per_intr = (uint32_t)result;
 950                 }
 951                 return (err);
 952         }
 953         if (strcmp(pr_name, "_intr_throttling") == 0) {
 954                 if (pr_val == NULL) {
 955                         err = EINVAL;
 956                         return (err);
 957                 }
 958                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
 959 
 960                 if (result < ixgbe->capab->min_intr_throttle ||
 961                     result > ixgbe->capab->max_intr_throttle)
 962                         err = EINVAL;
 963                 else {
 964                         ixgbe->intr_throttling[0] = (uint32_t)result;
 965 
 966                         /*
 967                          * 82599, X540 and X550 require the interrupt throttling
 968                          * rate is a multiple of 8. This is enforced by the
 969                          * register definiton.
 970                          */
 971                         if (hw->mac.type == ixgbe_mac_82599EB ||
 972                             hw->mac.type == ixgbe_mac_X540 ||
 973                             hw->mac.type == ixgbe_mac_X550 ||
 974                             hw->mac.type == ixgbe_mac_X550EM_x) {
 975                                 ixgbe->intr_throttling[0] =
 976                                     ixgbe->intr_throttling[0] & 0xFF8;
 977                         }
 978 
 979                         for (i = 0; i < MAX_INTR_VECTOR; i++)
 980                                 ixgbe->intr_throttling[i] =
 981                                     ixgbe->intr_throttling[0];
 982 
 983                         /* Set interrupt throttling rate */
 984                         for (i = 0; i < ixgbe->intr_cnt; i++)
 985                                 IXGBE_WRITE_REG(hw, IXGBE_EITR(i),
 986                                     ixgbe->intr_throttling[i]);
 987                 }
 988                 return (err);
 989         }
 990         return (ENOTSUP);
 991 }
 992 
 993 int
 994 ixgbe_get_priv_prop(ixgbe_t *ixgbe, const char *pr_name,
 995     uint_t pr_valsize, void *pr_val)
 996 {
 997         int err = ENOTSUP;
 998         int value;
 999 
1000         if (strcmp(pr_name, "_adv_pause_cap") == 0) {
1001                 value = ixgbe->param_adv_pause_cap;
1002                 err = 0;
1003                 goto done;
1004         }
1005         if (strcmp(pr_name, "_adv_asym_pause_cap") == 0) {
1006                 value = ixgbe->param_adv_asym_pause_cap;
1007                 err = 0;
1008                 goto done;
1009         }
1010         if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
1011                 value = ixgbe->tx_copy_thresh;
1012                 err = 0;
1013                 goto done;
1014         }
1015         if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
1016                 value = ixgbe->tx_recycle_thresh;
1017                 err = 0;
1018                 goto done;
1019         }
1020         if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
1021                 value = ixgbe->tx_overload_thresh;
1022                 err = 0;
1023                 goto done;
1024         }
1025         if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
1026                 value = ixgbe->tx_resched_thresh;
1027                 err = 0;
1028                 goto done;
1029         }
1030         if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
1031                 value = ixgbe->rx_copy_thresh;
1032                 err = 0;
1033                 goto done;
1034         }
1035         if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
1036                 value = ixgbe->rx_limit_per_intr;
1037                 err = 0;
1038                 goto done;
1039         }
1040         if (strcmp(pr_name, "_intr_throttling") == 0) {
1041                 value = ixgbe->intr_throttling[0];
1042                 err = 0;
1043                 goto done;
1044         }
1045 done:
1046         if (err == 0) {
1047                 (void) snprintf(pr_val, pr_valsize, "%d", value);
1048         }
1049         return (err);
1050 }