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 /*
 224  * Obtain the MAC's capabilities and associated data from
 225  * the driver.
 226  */
 227 boolean_t
 228 ixgbe_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
 229 {
 230         ixgbe_t *ixgbe = (ixgbe_t *)arg;
 231 
 232         switch (cap) {
 233         case MAC_CAPAB_HCKSUM: {
 234                 uint32_t *tx_hcksum_flags = cap_data;
 235 
 236                 /*
 237                  * We advertise our capabilities only if tx hcksum offload is
 238                  * enabled.  On receive, the stack will accept checksummed
 239                  * packets anyway, even if we haven't said we can deliver
 240                  * them.
 241                  */
 242                 if (!ixgbe->tx_hcksum_enable)
 243                         return (B_FALSE);
 244 
 245                 *tx_hcksum_flags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM;
 246                 break;
 247         }
 248         case MAC_CAPAB_LSO: {
 249                 mac_capab_lso_t *cap_lso = cap_data;
 250 
 251                 if (ixgbe->lso_enable) {
 252                         cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
 253                         cap_lso->lso_basic_tcp_ipv4.lso_max = IXGBE_LSO_MAXLEN;
 254                         break;
 255                 } else {
 256                         return (B_FALSE);
 257                 }
 258         }
 259         case MAC_CAPAB_RINGS: {
 260                 mac_capab_rings_t *cap_rings = cap_data;
 261 
 262                 switch (cap_rings->mr_type) {
 263                 case MAC_RING_TYPE_RX:
 264                         cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
 265                         cap_rings->mr_rnum = ixgbe->num_rx_rings;
 266                         cap_rings->mr_gnum = ixgbe->num_rx_groups;
 267                         cap_rings->mr_rget = ixgbe_fill_ring;
 268                         cap_rings->mr_gget = ixgbe_fill_group;
 269                         cap_rings->mr_gaddring = NULL;
 270                         cap_rings->mr_gremring = NULL;
 271                         break;
 272                 case MAC_RING_TYPE_TX:
 273                         cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
 274                         cap_rings->mr_rnum = ixgbe->num_tx_rings;
 275                         cap_rings->mr_gnum = 0;
 276                         cap_rings->mr_rget = ixgbe_fill_ring;
 277                         cap_rings->mr_gget = NULL;
 278                         break;
 279                 default:
 280                         break;
 281                 }
 282                 break;
 283         }
 284         case MAC_CAPAB_TRANSCEIVER: {
 285                 mac_capab_transceiver_t *mct = cap_data;
 286 
 287                 /*
 288                  * Rather than try and guess based on the media type whether or
 289                  * not we have a transceiver we can read, we instead will let
 290                  * the actual function calls figure that out for us.
 291                  */
 292                 mct->mct_flags = 0;
 293                 mct->mct_ntransceivers = 1;
 294                 mct->mct_info = ixgbe_transceiver_info;
 295                 mct->mct_read = ixgbe_transceiver_read;
 296                 return (B_TRUE);
 297         }
 298         default:
 299                 return (B_FALSE);
 300         }
 301         return (B_TRUE);
 302 }
 303 
 304 int
 305 ixgbe_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
 306     uint_t pr_valsize, const void *pr_val)
 307 {
 308         ixgbe_t *ixgbe = (ixgbe_t *)arg;
 309         struct ixgbe_hw *hw = &ixgbe->hw;
 310         int err = 0;
 311         uint32_t flow_control;
 312         uint32_t cur_mtu, new_mtu;
 313         uint32_t rx_size;
 314         uint32_t tx_size;
 315         ixgbe_link_speed speeds = 0;
 316 
 317         mutex_enter(&ixgbe->gen_lock);
 318         if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
 319                 mutex_exit(&ixgbe->gen_lock);
 320                 return (ECANCELED);
 321         }
 322 
 323         /*
 324          * We cannot always rely on the common code maintaining
 325          * hw->phy.speeds_supported, therefore we fall back to use the recorded
 326          * supported speeds which were obtained during instance init in
 327          * ixgbe_init_params().
 328          */
 329         speeds = hw->phy.speeds_supported;
 330         if (speeds == 0)
 331                 speeds = ixgbe->speeds_supported;
 332 
 333         if (ixgbe->loopback_mode != IXGBE_LB_NONE &&
 334             ixgbe_param_locked(pr_num)) {
 335                 /*
 336                  * All en_* parameters are locked (read-only)
 337                  * while the device is in any sort of loopback mode.
 338                  */
 339                 mutex_exit(&ixgbe->gen_lock);
 340                 return (EBUSY);
 341         }
 342 
 343         /*
 344          * We allow speed changes only on baseT PHYs. MAC_PROP_EN_* are marked
 345          * read-only on non-baseT PHYs.
 346          */
 347         switch (pr_num) {
 348         case MAC_PROP_EN_10GFDX_CAP:
 349                 if (hw->phy.media_type == ixgbe_media_type_copper &&
 350                     speeds & IXGBE_LINK_SPEED_10GB_FULL) {
 351                         ixgbe->param_en_10000fdx_cap = *(uint8_t *)pr_val;
 352                         goto setup_link;
 353                 } else {
 354                         err = ENOTSUP;
 355                         break;
 356                 }
 357         case MAC_PROP_EN_5000FDX_CAP:
 358                 if (hw->phy.media_type == ixgbe_media_type_copper &&
 359                     speeds & IXGBE_LINK_SPEED_5GB_FULL) {
 360                         ixgbe->param_en_5000fdx_cap = *(uint8_t *)pr_val;
 361                         goto setup_link;
 362                 } else {
 363                         err = ENOTSUP;
 364                         break;
 365                 }
 366         case MAC_PROP_EN_2500FDX_CAP:
 367                 if (hw->phy.media_type == ixgbe_media_type_copper &&
 368                     speeds & IXGBE_LINK_SPEED_2_5GB_FULL) {
 369                         ixgbe->param_en_2500fdx_cap = *(uint8_t *)pr_val;
 370                         goto setup_link;
 371                 } else {
 372                         err = ENOTSUP;
 373                         break;
 374                 }
 375         case MAC_PROP_EN_1000FDX_CAP:
 376                 if (hw->phy.media_type == ixgbe_media_type_copper &&
 377                     speeds & IXGBE_LINK_SPEED_1GB_FULL) {
 378                         ixgbe->param_en_1000fdx_cap = *(uint8_t *)pr_val;
 379                         goto setup_link;
 380                 } else {
 381                         err = ENOTSUP;
 382                         break;
 383                 }
 384         case MAC_PROP_EN_100FDX_CAP:
 385                 if (hw->phy.media_type == ixgbe_media_type_copper &&
 386                     speeds & IXGBE_LINK_SPEED_100_FULL) {
 387                         ixgbe->param_en_100fdx_cap = *(uint8_t *)pr_val;
 388                         goto setup_link;
 389                 } else {
 390                         err = ENOTSUP;
 391                         break;
 392                 }
 393         case MAC_PROP_AUTONEG:
 394                 if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) {
 395                         err = ENOTSUP;
 396                         break;
 397                 } else {
 398                         ixgbe->param_adv_autoneg_cap = *(uint8_t *)pr_val;
 399                         goto setup_link;
 400                 }
 401         case MAC_PROP_FLOWCTRL:
 402                 bcopy(pr_val, &flow_control, sizeof (flow_control));
 403 
 404                 switch (flow_control) {
 405                 default:
 406                         err = EINVAL;
 407                         break;
 408                 case LINK_FLOWCTRL_NONE:
 409                         hw->fc.requested_mode = ixgbe_fc_none;
 410                         break;
 411                 case LINK_FLOWCTRL_RX:
 412                         hw->fc.requested_mode = ixgbe_fc_rx_pause;
 413                         break;
 414                 case LINK_FLOWCTRL_TX:
 415                         hw->fc.requested_mode = ixgbe_fc_tx_pause;
 416                         break;
 417                 case LINK_FLOWCTRL_BI:
 418                         hw->fc.requested_mode = ixgbe_fc_full;
 419                         break;
 420                 }
 421 setup_link:
 422                 if (err == 0) {
 423                         if (ixgbe_driver_setup_link(ixgbe, B_TRUE) !=
 424                             IXGBE_SUCCESS)
 425                                 err = EINVAL;
 426                 }
 427                 break;
 428         case MAC_PROP_ADV_10GFDX_CAP:
 429         case MAC_PROP_ADV_5000FDX_CAP:
 430         case MAC_PROP_ADV_2500FDX_CAP:
 431         case MAC_PROP_ADV_1000FDX_CAP:
 432         case MAC_PROP_ADV_100FDX_CAP:
 433         case MAC_PROP_STATUS:
 434         case MAC_PROP_SPEED:
 435         case MAC_PROP_DUPLEX:
 436                 err = ENOTSUP; /* read-only prop. Can't set this. */
 437                 break;
 438         case MAC_PROP_MTU:
 439                 cur_mtu = ixgbe->default_mtu;
 440                 bcopy(pr_val, &new_mtu, sizeof (new_mtu));
 441                 if (new_mtu == cur_mtu) {
 442                         err = 0;
 443                         break;
 444                 }
 445 
 446                 if (new_mtu < DEFAULT_MTU || new_mtu > ixgbe->capab->max_mtu) {
 447                         err = EINVAL;
 448                         break;
 449                 }
 450 
 451                 if (ixgbe->ixgbe_state & IXGBE_STARTED) {
 452                         err = EBUSY;
 453                         break;
 454                 }
 455 
 456                 err = mac_maxsdu_update(ixgbe->mac_hdl, new_mtu);
 457                 if (err == 0) {
 458                         ixgbe->default_mtu = new_mtu;
 459                         ixgbe->max_frame_size = ixgbe->default_mtu +
 460                             sizeof (struct ether_vlan_header) + ETHERFCSL;
 461 
 462                         /*
 463                          * Set rx buffer size
 464                          */
 465                         rx_size = ixgbe->max_frame_size + IPHDR_ALIGN_ROOM;
 466                         ixgbe->rx_buf_size = ((rx_size >> 10) + ((rx_size &
 467                             (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
 468 
 469                         /*
 470                          * Set tx buffer size
 471                          */
 472                         tx_size = ixgbe->max_frame_size;
 473                         ixgbe->tx_buf_size = ((tx_size >> 10) + ((tx_size &
 474                             (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
 475                 }
 476                 break;
 477         case MAC_PROP_PRIVATE:
 478                 err = ixgbe_set_priv_prop(ixgbe, pr_name, pr_valsize, pr_val);
 479                 break;
 480         default:
 481                 err = ENOTSUP;
 482                 break;
 483         }
 484         mutex_exit(&ixgbe->gen_lock);
 485         return (err);
 486 }
 487 
 488 int
 489 ixgbe_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
 490     uint_t pr_valsize, void *pr_val)
 491 {
 492         ixgbe_t *ixgbe = (ixgbe_t *)arg;
 493         struct ixgbe_hw *hw = &ixgbe->hw;
 494         int err = 0;
 495         uint32_t flow_control;
 496         uint64_t tmp = 0;
 497         ixgbe_link_speed speeds = 0;
 498 
 499         /*
 500          * We cannot always rely on the common code maintaining
 501          * hw->phy.speeds_supported, therefore we fall back to use the recorded
 502          * supported speeds which were obtained during instance init in
 503          * ixgbe_init_params().
 504          */
 505         speeds = hw->phy.speeds_supported;
 506         if (speeds == 0)
 507                 speeds = ixgbe->speeds_supported;
 508 
 509         switch (pr_num) {
 510         case MAC_PROP_DUPLEX:
 511                 ASSERT(pr_valsize >= sizeof (link_duplex_t));
 512                 bcopy(&ixgbe->link_duplex, pr_val,
 513                     sizeof (link_duplex_t));
 514                 break;
 515         case MAC_PROP_SPEED:
 516                 ASSERT(pr_valsize >= sizeof (uint64_t));
 517                 tmp = ixgbe->link_speed * 1000000ull;
 518                 bcopy(&tmp, pr_val, sizeof (tmp));
 519                 break;
 520         case MAC_PROP_AUTONEG:
 521                 *(uint8_t *)pr_val = ixgbe->param_adv_autoneg_cap;
 522                 break;
 523         case MAC_PROP_FLOWCTRL:
 524                 ASSERT(pr_valsize >= sizeof (uint32_t));
 525 
 526                 switch (hw->fc.requested_mode) {
 527                         case ixgbe_fc_none:
 528                                 flow_control = LINK_FLOWCTRL_NONE;
 529                                 break;
 530                         case ixgbe_fc_rx_pause:
 531                                 flow_control = LINK_FLOWCTRL_RX;
 532                                 break;
 533                         case ixgbe_fc_tx_pause:
 534                                 flow_control = LINK_FLOWCTRL_TX;
 535                                 break;
 536                         case ixgbe_fc_full:
 537                                 flow_control = LINK_FLOWCTRL_BI;
 538                                 break;
 539                 }
 540                 bcopy(&flow_control, pr_val, sizeof (flow_control));
 541                 break;
 542         case MAC_PROP_ADV_10GFDX_CAP:
 543                 if (speeds & IXGBE_LINK_SPEED_10GB_FULL)
 544                         *(uint8_t *)pr_val = ixgbe->param_adv_10000fdx_cap;
 545                 else
 546                         err = ENOTSUP;
 547                 break;
 548         case MAC_PROP_EN_10GFDX_CAP:
 549                 if (speeds & IXGBE_LINK_SPEED_10GB_FULL)
 550                         *(uint8_t *)pr_val = ixgbe->param_en_10000fdx_cap;
 551                 else
 552                         err = ENOTSUP;
 553                 break;
 554         case MAC_PROP_ADV_5000FDX_CAP:
 555                 if (speeds & IXGBE_LINK_SPEED_5GB_FULL)
 556                         *(uint8_t *)pr_val = ixgbe->param_adv_5000fdx_cap;
 557                 else
 558                         err = ENOTSUP;
 559                 break;
 560         case MAC_PROP_EN_5000FDX_CAP:
 561                 if (speeds & IXGBE_LINK_SPEED_5GB_FULL)
 562                         *(uint8_t *)pr_val = ixgbe->param_en_5000fdx_cap;
 563                 else
 564                         err = ENOTSUP;
 565                 break;
 566         case MAC_PROP_ADV_2500FDX_CAP:
 567                 if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL)
 568                         *(uint8_t *)pr_val = ixgbe->param_adv_2500fdx_cap;
 569                 else
 570                         err = ENOTSUP;
 571                 break;
 572         case MAC_PROP_EN_2500FDX_CAP:
 573                 if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL)
 574                         *(uint8_t *)pr_val = ixgbe->param_en_2500fdx_cap;
 575                 else
 576                         err = ENOTSUP;
 577                 break;
 578         case MAC_PROP_ADV_1000FDX_CAP:
 579                 if (speeds & IXGBE_LINK_SPEED_1GB_FULL)
 580                         *(uint8_t *)pr_val = ixgbe->param_adv_1000fdx_cap;
 581                 else
 582                         err = ENOTSUP;
 583                 break;
 584         case MAC_PROP_EN_1000FDX_CAP:
 585                 if (speeds & IXGBE_LINK_SPEED_1GB_FULL)
 586                         *(uint8_t *)pr_val = ixgbe->param_en_1000fdx_cap;
 587                 else
 588                         err = ENOTSUP;
 589                 break;
 590         case MAC_PROP_ADV_100FDX_CAP:
 591                 if (speeds & IXGBE_LINK_SPEED_100_FULL)
 592                         *(uint8_t *)pr_val = ixgbe->param_adv_100fdx_cap;
 593                 else
 594                         err = ENOTSUP;
 595                 break;
 596         case MAC_PROP_EN_100FDX_CAP:
 597                 if (speeds & IXGBE_LINK_SPEED_100_FULL)
 598                         *(uint8_t *)pr_val = ixgbe->param_en_100fdx_cap;
 599                 else
 600                         err = ENOTSUP;
 601                 break;
 602         case MAC_PROP_PRIVATE:
 603                 err = ixgbe_get_priv_prop(ixgbe, pr_name,
 604                     pr_valsize, pr_val);
 605                 break;
 606         default:
 607                 err = ENOTSUP;
 608                 break;
 609         }
 610         return (err);
 611 }
 612 
 613 void
 614 ixgbe_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
 615     mac_prop_info_handle_t prh)
 616 {
 617         ixgbe_t *ixgbe = (ixgbe_t *)arg;
 618         struct ixgbe_hw *hw = &ixgbe->hw;
 619         uint_t perm;
 620         uint8_t value;
 621         ixgbe_link_speed speeds = 0;
 622 
 623         /*
 624          * We cannot always rely on the common code maintaining
 625          * hw->phy.speeds_supported, therefore we fall back to use the
 626          * recorded supported speeds which were obtained during instance init in
 627          * ixgbe_init_params().
 628          */
 629         speeds = hw->phy.speeds_supported;
 630         if (speeds == 0)
 631                 speeds = ixgbe->speeds_supported;
 632 
 633         switch (pr_num) {
 634         case MAC_PROP_DUPLEX:
 635         case MAC_PROP_SPEED:
 636                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
 637                 break;
 638 
 639         case MAC_PROP_ADV_100FDX_CAP:
 640                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
 641                 value = (speeds & IXGBE_LINK_SPEED_100_FULL) ? 1 : 0;
 642                 mac_prop_info_set_default_uint8(prh, value);
 643                 break;
 644 
 645         case MAC_PROP_ADV_1000FDX_CAP:
 646                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
 647                 value = (speeds & IXGBE_LINK_SPEED_1GB_FULL) ? 1 : 0;
 648                 mac_prop_info_set_default_uint8(prh, value);
 649                 break;
 650 
 651         case MAC_PROP_ADV_2500FDX_CAP:
 652                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
 653                 value = (speeds & IXGBE_LINK_SPEED_2_5GB_FULL) ? 1 : 0;
 654                 mac_prop_info_set_default_uint8(prh, value);
 655                 break;
 656 
 657         case MAC_PROP_ADV_5000FDX_CAP:
 658                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
 659                 value = (speeds & IXGBE_LINK_SPEED_5GB_FULL) ? 1 : 0;
 660                 mac_prop_info_set_default_uint8(prh, value);
 661                 break;
 662 
 663         case MAC_PROP_ADV_10GFDX_CAP:
 664                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
 665                 value = (speeds & IXGBE_LINK_SPEED_10GB_FULL) ? 1 : 0;
 666                 mac_prop_info_set_default_uint8(prh, value);
 667                 break;
 668 
 669         /*
 670          * We allow speed changes only on baseT PHYs. MAC_PROP_EN_* are marked
 671          * read-only on non-baseT (SFP) PHYs.
 672          */
 673         case MAC_PROP_AUTONEG:
 674                 perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
 675                     MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
 676                 mac_prop_info_set_perm(prh, perm);
 677                 mac_prop_info_set_default_uint8(prh, 1);
 678                 break;
 679 
 680         case MAC_PROP_EN_10GFDX_CAP:
 681                 if (speeds & IXGBE_LINK_SPEED_10GB_FULL) {
 682                         perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
 683                             MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
 684                         mac_prop_info_set_perm(prh, perm);
 685                         mac_prop_info_set_default_uint8(prh, 1);
 686                 }
 687                 break;
 688 
 689         case MAC_PROP_EN_5000FDX_CAP:
 690                 if (speeds & IXGBE_LINK_SPEED_5GB_FULL) {
 691                         perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
 692                             MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
 693                         mac_prop_info_set_perm(prh, perm);
 694                         mac_prop_info_set_default_uint8(prh, 1);
 695                 }
 696                 break;
 697 
 698         case MAC_PROP_EN_2500FDX_CAP:
 699                 if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL) {
 700                         perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
 701                             MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
 702                         mac_prop_info_set_perm(prh, perm);
 703                         mac_prop_info_set_default_uint8(prh, 1);
 704                 }
 705                 break;
 706 
 707         case MAC_PROP_EN_1000FDX_CAP:
 708                 if (speeds & IXGBE_LINK_SPEED_1GB_FULL) {
 709                         perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
 710                             MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
 711                         mac_prop_info_set_perm(prh, perm);
 712                         mac_prop_info_set_default_uint8(prh, 1);
 713                 }
 714                 break;
 715 
 716         case MAC_PROP_EN_100FDX_CAP:
 717                 if (speeds & IXGBE_LINK_SPEED_100_FULL) {
 718                         perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
 719                             MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
 720                         mac_prop_info_set_perm(prh, perm);
 721                         mac_prop_info_set_default_uint8(prh, 1);
 722                 }
 723                 break;
 724 
 725         case MAC_PROP_FLOWCTRL:
 726                 mac_prop_info_set_default_link_flowctrl(prh,
 727                     LINK_FLOWCTRL_NONE);
 728                 break;
 729 
 730         case MAC_PROP_MTU:
 731                 mac_prop_info_set_range_uint32(prh,
 732                     DEFAULT_MTU, ixgbe->capab->max_mtu);
 733                 break;
 734 
 735         case MAC_PROP_PRIVATE: {
 736                 char valstr[64];
 737                 int value;
 738 
 739                 bzero(valstr, sizeof (valstr));
 740 
 741                 if (strcmp(pr_name, "_adv_pause_cap") == 0 ||
 742                     strcmp(pr_name, "_adv_asym_pause_cap") == 0) {
 743                         mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
 744                         return;
 745                 }
 746 
 747                 if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
 748                         value = DEFAULT_TX_COPY_THRESHOLD;
 749                 } else if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
 750                         value = DEFAULT_TX_RECYCLE_THRESHOLD;
 751                 } else if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
 752                         value = DEFAULT_TX_OVERLOAD_THRESHOLD;
 753                 } else if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
 754                         value = DEFAULT_TX_RESCHED_THRESHOLD;
 755                 } else  if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
 756                         value = DEFAULT_RX_COPY_THRESHOLD;
 757                 } else  if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
 758                         value = DEFAULT_RX_LIMIT_PER_INTR;
 759                 }       if (strcmp(pr_name, "_intr_throttling") == 0) {
 760                         value = ixgbe->capab->def_intr_throttle;
 761                 } else {
 762                         return;
 763                 }
 764 
 765                 (void) snprintf(valstr, sizeof (valstr), "%x", value);
 766         }
 767         }
 768 }
 769 
 770 boolean_t
 771 ixgbe_param_locked(mac_prop_id_t pr_num)
 772 {
 773         /*
 774          * All en_* parameters are locked (read-only) while
 775          * the device is in any sort of loopback mode ...
 776          */
 777         switch (pr_num) {
 778                 case MAC_PROP_EN_10GFDX_CAP:
 779                 case MAC_PROP_EN_5000FDX_CAP:
 780                 case MAC_PROP_EN_2500FDX_CAP:
 781                 case MAC_PROP_EN_1000FDX_CAP:
 782                 case MAC_PROP_EN_100FDX_CAP:
 783                 case MAC_PROP_AUTONEG:
 784                 case MAC_PROP_FLOWCTRL:
 785                         return (B_TRUE);
 786         }
 787         return (B_FALSE);
 788 }
 789 
 790 /* ARGSUSED */
 791 int
 792 ixgbe_set_priv_prop(ixgbe_t *ixgbe, const char *pr_name,
 793     uint_t pr_valsize, const void *pr_val)
 794 {
 795         int err = 0;
 796         long result;
 797         struct ixgbe_hw *hw = &ixgbe->hw;
 798         int i;
 799 
 800         if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
 801                 if (pr_val == NULL) {
 802                         err = EINVAL;
 803                         return (err);
 804                 }
 805                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
 806                 if (result < MIN_TX_COPY_THRESHOLD ||
 807                     result > MAX_TX_COPY_THRESHOLD)
 808                         err = EINVAL;
 809                 else {
 810                         ixgbe->tx_copy_thresh = (uint32_t)result;
 811                 }
 812                 return (err);
 813         }
 814         if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
 815                 if (pr_val == NULL) {
 816                         err = EINVAL;
 817                         return (err);
 818                 }
 819                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
 820                 if (result < MIN_TX_RECYCLE_THRESHOLD ||
 821                     result > MAX_TX_RECYCLE_THRESHOLD)
 822                         err = EINVAL;
 823                 else {
 824                         ixgbe->tx_recycle_thresh = (uint32_t)result;
 825                 }
 826                 return (err);
 827         }
 828         if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
 829                 if (pr_val == NULL) {
 830                         err = EINVAL;
 831                         return (err);
 832                 }
 833                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
 834                 if (result < MIN_TX_OVERLOAD_THRESHOLD ||
 835                     result > MAX_TX_OVERLOAD_THRESHOLD)
 836                         err = EINVAL;
 837                 else {
 838                         ixgbe->tx_overload_thresh = (uint32_t)result;
 839                 }
 840                 return (err);
 841         }
 842         if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
 843                 if (pr_val == NULL) {
 844                         err = EINVAL;
 845                         return (err);
 846                 }
 847                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
 848                 if (result < MIN_TX_RESCHED_THRESHOLD ||
 849                     result > MAX_TX_RESCHED_THRESHOLD)
 850                         err = EINVAL;
 851                 else {
 852                         ixgbe->tx_resched_thresh = (uint32_t)result;
 853                 }
 854                 return (err);
 855         }
 856         if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
 857                 if (pr_val == NULL) {
 858                         err = EINVAL;
 859                         return (err);
 860                 }
 861                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
 862                 if (result < MIN_RX_COPY_THRESHOLD ||
 863                     result > MAX_RX_COPY_THRESHOLD)
 864                         err = EINVAL;
 865                 else {
 866                         ixgbe->rx_copy_thresh = (uint32_t)result;
 867                 }
 868                 return (err);
 869         }
 870         if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
 871                 if (pr_val == NULL) {
 872                         err = EINVAL;
 873                         return (err);
 874                 }
 875                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
 876                 if (result < MIN_RX_LIMIT_PER_INTR ||
 877                     result > MAX_RX_LIMIT_PER_INTR)
 878                         err = EINVAL;
 879                 else {
 880                         ixgbe->rx_limit_per_intr = (uint32_t)result;
 881                 }
 882                 return (err);
 883         }
 884         if (strcmp(pr_name, "_intr_throttling") == 0) {
 885                 if (pr_val == NULL) {
 886                         err = EINVAL;
 887                         return (err);
 888                 }
 889                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
 890 
 891                 if (result < ixgbe->capab->min_intr_throttle ||
 892                     result > ixgbe->capab->max_intr_throttle)
 893                         err = EINVAL;
 894                 else {
 895                         ixgbe->intr_throttling[0] = (uint32_t)result;
 896 
 897                         /*
 898                          * 82599, X540 and X550 require the interrupt throttling
 899                          * rate is a multiple of 8. This is enforced by the
 900                          * register definiton.
 901                          */
 902                         if (hw->mac.type == ixgbe_mac_82599EB ||
 903                             hw->mac.type == ixgbe_mac_X540 ||
 904                             hw->mac.type == ixgbe_mac_X550 ||
 905                             hw->mac.type == ixgbe_mac_X550EM_x) {
 906                                 ixgbe->intr_throttling[0] =
 907                                     ixgbe->intr_throttling[0] & 0xFF8;
 908                         }
 909 
 910                         for (i = 0; i < MAX_INTR_VECTOR; i++)
 911                                 ixgbe->intr_throttling[i] =
 912                                     ixgbe->intr_throttling[0];
 913 
 914                         /* Set interrupt throttling rate */
 915                         for (i = 0; i < ixgbe->intr_cnt; i++)
 916                                 IXGBE_WRITE_REG(hw, IXGBE_EITR(i),
 917                                     ixgbe->intr_throttling[i]);
 918                 }
 919                 return (err);
 920         }
 921         return (ENOTSUP);
 922 }
 923 
 924 int
 925 ixgbe_get_priv_prop(ixgbe_t *ixgbe, const char *pr_name,
 926     uint_t pr_valsize, void *pr_val)
 927 {
 928         int err = ENOTSUP;
 929         int value;
 930 
 931         if (strcmp(pr_name, "_adv_pause_cap") == 0) {
 932                 value = ixgbe->param_adv_pause_cap;
 933                 err = 0;
 934                 goto done;
 935         }
 936         if (strcmp(pr_name, "_adv_asym_pause_cap") == 0) {
 937                 value = ixgbe->param_adv_asym_pause_cap;
 938                 err = 0;
 939                 goto done;
 940         }
 941         if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
 942                 value = ixgbe->tx_copy_thresh;
 943                 err = 0;
 944                 goto done;
 945         }
 946         if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
 947                 value = ixgbe->tx_recycle_thresh;
 948                 err = 0;
 949                 goto done;
 950         }
 951         if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
 952                 value = ixgbe->tx_overload_thresh;
 953                 err = 0;
 954                 goto done;
 955         }
 956         if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
 957                 value = ixgbe->tx_resched_thresh;
 958                 err = 0;
 959                 goto done;
 960         }
 961         if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
 962                 value = ixgbe->rx_copy_thresh;
 963                 err = 0;
 964                 goto done;
 965         }
 966         if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
 967                 value = ixgbe->rx_limit_per_intr;
 968                 err = 0;
 969                 goto done;
 970         }
 971         if (strcmp(pr_name, "_intr_throttling") == 0) {
 972                 value = ixgbe->intr_throttling[0];
 973                 err = 0;
 974                 goto done;
 975         }
 976 done:
 977         if (err == 0) {
 978                 (void) snprintf(pr_val, pr_valsize, "%d", value);
 979         }
 980         return (err);
 981 }