Home | History | Annotate | Download | only in ixgbe
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * Copyright(c) 2007-2009 Intel Corporation. All rights reserved.
      5  * The contents of this file are subject to the terms of the
      6  * Common Development and Distribution License (the "License").
      7  * You may not use this file except in compliance with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 
     23 /*
     24  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     25  * Use is subject to license terms.
     26  */
     27 
     28 #include "ixgbe_sw.h"
     29 
     30 /*
     31  * Retrieve a value for one of the statistics.
     32  */
     33 int
     34 ixgbe_m_stat(void *arg, uint_t stat, uint64_t *val)
     35 {
     36 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
     37 	struct ixgbe_hw *hw = &ixgbe->hw;
     38 	ixgbe_stat_t *ixgbe_ks;
     39 	int i;
     40 
     41 	ixgbe_ks = (ixgbe_stat_t *)ixgbe->ixgbe_ks->ks_data;
     42 
     43 	mutex_enter(&ixgbe->gen_lock);
     44 
     45 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
     46 		mutex_exit(&ixgbe->gen_lock);
     47 		return (ECANCELED);
     48 	}
     49 
     50 	switch (stat) {
     51 	case MAC_STAT_IFSPEED:
     52 		*val = ixgbe->link_speed * 1000000ull;
     53 		break;
     54 
     55 	case MAC_STAT_MULTIRCV:
     56 		ixgbe_ks->mprc.value.ui64 +=
     57 		    IXGBE_READ_REG(hw, IXGBE_MPRC);
     58 		*val = ixgbe_ks->mprc.value.ui64;
     59 		break;
     60 
     61 	case MAC_STAT_BRDCSTRCV:
     62 		ixgbe_ks->bprc.value.ui64 +=
     63 		    IXGBE_READ_REG(hw, IXGBE_BPRC);
     64 		*val = ixgbe_ks->bprc.value.ui64;
     65 		break;
     66 
     67 	case MAC_STAT_MULTIXMT:
     68 		ixgbe_ks->mptc.value.ui64 +=
     69 		    IXGBE_READ_REG(hw, IXGBE_MPTC);
     70 		*val = ixgbe_ks->mptc.value.ui64;
     71 		break;
     72 
     73 	case MAC_STAT_BRDCSTXMT:
     74 		ixgbe_ks->bptc.value.ui64 +=
     75 		    IXGBE_READ_REG(hw, IXGBE_BPTC);
     76 		*val = ixgbe_ks->bptc.value.ui64;
     77 		break;
     78 
     79 	case MAC_STAT_NORCVBUF:
     80 		for (i = 0; i < 8; i++) {
     81 			ixgbe_ks->rnbc.value.ui64 +=
     82 			    IXGBE_READ_REG(hw, IXGBE_RNBC(i));
     83 		}
     84 		*val = ixgbe_ks->rnbc.value.ui64;
     85 		break;
     86 
     87 	case MAC_STAT_IERRORS:
     88 		ixgbe_ks->crcerrs.value.ui64 +=
     89 		    IXGBE_READ_REG(hw, IXGBE_CRCERRS);
     90 		ixgbe_ks->illerrc.value.ui64 +=
     91 		    IXGBE_READ_REG(hw, IXGBE_ILLERRC);
     92 		ixgbe_ks->errbc.value.ui64 +=
     93 		    IXGBE_READ_REG(hw, IXGBE_ERRBC);
     94 		ixgbe_ks->rlec.value.ui64 +=
     95 		    IXGBE_READ_REG(hw, IXGBE_RLEC);
     96 		*val = ixgbe_ks->crcerrs.value.ui64 +
     97 		    ixgbe_ks->illerrc.value.ui64 +
     98 		    ixgbe_ks->errbc.value.ui64 +
     99 		    ixgbe_ks->rlec.value.ui64;
    100 		break;
    101 
    102 	case MAC_STAT_RBYTES:
    103 		ixgbe_ks->tor.value.ui64 = 0;
    104 		for (i = 0; i < 16; i++) {
    105 			ixgbe_ks->qbrc[i].value.ui64 +=
    106 			    IXGBE_READ_REG(hw, IXGBE_QBRC(i));
    107 			ixgbe_ks->tor.value.ui64 +=
    108 			    ixgbe_ks->qbrc[i].value.ui64;
    109 		}
    110 		*val = ixgbe_ks->tor.value.ui64;
    111 		break;
    112 
    113 	case MAC_STAT_OBYTES:
    114 		ixgbe_ks->tot.value.ui64 = 0;
    115 		for (i = 0; i < 16; i++) {
    116 			if (hw->mac.type >= ixgbe_mac_82599EB) {
    117 				ixgbe_ks->qbtc[i].value.ui64 +=
    118 				    IXGBE_READ_REG(hw, IXGBE_QBTC_L(i));
    119 				ixgbe_ks->qbtc[i].value.ui64 += ((uint64_t)
    120 				    IXGBE_READ_REG(hw, IXGBE_QBTC_H(i))) << 32;
    121 			} else {
    122 				ixgbe_ks->qbtc[i].value.ui64 +=
    123 				    IXGBE_READ_REG(hw, IXGBE_QBTC(i));
    124 			}
    125 			ixgbe_ks->tot.value.ui64 +=
    126 			    ixgbe_ks->qbtc[i].value.ui64;
    127 		}
    128 		*val = ixgbe_ks->tot.value.ui64;
    129 		break;
    130 
    131 	case MAC_STAT_IPACKETS:
    132 		ixgbe_ks->tpr.value.ui64 +=
    133 		    IXGBE_READ_REG(hw, IXGBE_TPR);
    134 		*val = ixgbe_ks->tpr.value.ui64;
    135 		break;
    136 
    137 	case MAC_STAT_OPACKETS:
    138 		ixgbe_ks->tpt.value.ui64 +=
    139 		    IXGBE_READ_REG(hw, IXGBE_TPT);
    140 		*val = ixgbe_ks->tpt.value.ui64;
    141 		break;
    142 
    143 	/* RFC 1643 stats */
    144 	case ETHER_STAT_FCS_ERRORS:
    145 		ixgbe_ks->crcerrs.value.ui64 +=
    146 		    IXGBE_READ_REG(hw, IXGBE_CRCERRS);
    147 		*val = ixgbe_ks->crcerrs.value.ui64;
    148 		break;
    149 
    150 	case ETHER_STAT_TOOLONG_ERRORS:
    151 		ixgbe_ks->roc.value.ui64 +=
    152 		    IXGBE_READ_REG(hw, IXGBE_ROC);
    153 		*val = ixgbe_ks->roc.value.ui64;
    154 		break;
    155 
    156 	case ETHER_STAT_MACRCV_ERRORS:
    157 		ixgbe_ks->crcerrs.value.ui64 +=
    158 		    IXGBE_READ_REG(hw, IXGBE_CRCERRS);
    159 		ixgbe_ks->illerrc.value.ui64 +=
    160 		    IXGBE_READ_REG(hw, IXGBE_ILLERRC);
    161 		ixgbe_ks->errbc.value.ui64 +=
    162 		    IXGBE_READ_REG(hw, IXGBE_ERRBC);
    163 		ixgbe_ks->rlec.value.ui64 +=
    164 		    IXGBE_READ_REG(hw, IXGBE_RLEC);
    165 		*val = ixgbe_ks->crcerrs.value.ui64 +
    166 		    ixgbe_ks->illerrc.value.ui64 +
    167 		    ixgbe_ks->errbc.value.ui64 +
    168 		    ixgbe_ks->rlec.value.ui64;
    169 		break;
    170 
    171 	/* MII/GMII stats */
    172 	case ETHER_STAT_XCVR_ADDR:
    173 		/* The Internal PHY's MDI address for each MAC is 1 */
    174 		*val = 1;
    175 		break;
    176 
    177 	case ETHER_STAT_XCVR_ID:
    178 		*val = hw->phy.id;
    179 		break;
    180 
    181 	case ETHER_STAT_XCVR_INUSE:
    182 		switch (ixgbe->link_speed) {
    183 		case IXGBE_LINK_SPEED_1GB_FULL:
    184 			*val =
    185 			    (hw->phy.media_type == ixgbe_media_type_copper) ?
    186 			    XCVR_1000T : XCVR_1000X;
    187 			break;
    188 		case IXGBE_LINK_SPEED_100_FULL:
    189 			*val = (hw->phy.media_type == ixgbe_media_type_copper) ?
    190 			    XCVR_100T2 : XCVR_100X;
    191 			break;
    192 		default:
    193 			*val = XCVR_NONE;
    194 			break;
    195 		}
    196 		break;
    197 
    198 	case ETHER_STAT_CAP_10GFDX:
    199 		*val = 1;
    200 		break;
    201 
    202 	case ETHER_STAT_CAP_1000FDX:
    203 		*val = 1;
    204 		break;
    205 
    206 	case ETHER_STAT_CAP_100FDX:
    207 		*val = 1;
    208 		break;
    209 
    210 	case ETHER_STAT_CAP_ASMPAUSE:
    211 		*val = ixgbe->param_asym_pause_cap;
    212 		break;
    213 
    214 	case ETHER_STAT_CAP_PAUSE:
    215 		*val = ixgbe->param_pause_cap;
    216 		break;
    217 
    218 	case ETHER_STAT_CAP_AUTONEG:
    219 		*val = 1;
    220 		break;
    221 
    222 	case ETHER_STAT_ADV_CAP_10GFDX:
    223 		*val = ixgbe->param_adv_10000fdx_cap;
    224 		break;
    225 
    226 	case ETHER_STAT_ADV_CAP_1000FDX:
    227 		*val = ixgbe->param_adv_1000fdx_cap;
    228 		break;
    229 
    230 	case ETHER_STAT_ADV_CAP_100FDX:
    231 		*val = ixgbe->param_adv_100fdx_cap;
    232 		break;
    233 
    234 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
    235 		*val = ixgbe->param_adv_asym_pause_cap;
    236 		break;
    237 
    238 	case ETHER_STAT_ADV_CAP_PAUSE:
    239 		*val = ixgbe->param_adv_pause_cap;
    240 		break;
    241 
    242 	case ETHER_STAT_ADV_CAP_AUTONEG:
    243 		*val = ixgbe->param_adv_autoneg_cap;
    244 		break;
    245 
    246 	case ETHER_STAT_LP_CAP_10GFDX:
    247 		*val = ixgbe->param_lp_10000fdx_cap;
    248 		break;
    249 
    250 	case ETHER_STAT_LP_CAP_1000FDX:
    251 		*val = ixgbe->param_lp_1000fdx_cap;
    252 		break;
    253 
    254 	case ETHER_STAT_LP_CAP_100FDX:
    255 		*val = ixgbe->param_lp_100fdx_cap;
    256 		break;
    257 
    258 	case ETHER_STAT_LP_CAP_ASMPAUSE:
    259 		*val = ixgbe->param_lp_asym_pause_cap;
    260 		break;
    261 
    262 	case ETHER_STAT_LP_CAP_PAUSE:
    263 		*val = ixgbe->param_lp_pause_cap;
    264 		break;
    265 
    266 	case ETHER_STAT_LP_CAP_AUTONEG:
    267 		*val = ixgbe->param_lp_autoneg_cap;
    268 		break;
    269 
    270 	case ETHER_STAT_LINK_ASMPAUSE:
    271 		*val = ixgbe->param_asym_pause_cap;
    272 		break;
    273 
    274 	case ETHER_STAT_LINK_PAUSE:
    275 		*val = ixgbe->param_pause_cap;
    276 		break;
    277 
    278 	case ETHER_STAT_LINK_AUTONEG:
    279 		*val = ixgbe->param_adv_autoneg_cap;
    280 		break;
    281 
    282 	case ETHER_STAT_LINK_DUPLEX:
    283 		*val = LINK_DUPLEX_FULL;
    284 		break;
    285 
    286 	case ETHER_STAT_TOOSHORT_ERRORS:
    287 		ixgbe_ks->ruc.value.ui64 +=
    288 		    IXGBE_READ_REG(hw, IXGBE_RUC);
    289 		*val = ixgbe_ks->ruc.value.ui64;
    290 		break;
    291 
    292 	case ETHER_STAT_CAP_REMFAULT:
    293 		*val = ixgbe->param_rem_fault;
    294 		break;
    295 
    296 	case ETHER_STAT_ADV_REMFAULT:
    297 		*val = ixgbe->param_adv_rem_fault;
    298 		break;
    299 
    300 	case ETHER_STAT_LP_REMFAULT:
    301 		*val = ixgbe->param_lp_rem_fault;
    302 		break;
    303 
    304 	case ETHER_STAT_JABBER_ERRORS:
    305 		ixgbe_ks->rjc.value.ui64 +=
    306 		    IXGBE_READ_REG(hw, IXGBE_RJC);
    307 		*val = ixgbe_ks->rjc.value.ui64;
    308 		break;
    309 
    310 	default:
    311 		mutex_exit(&ixgbe->gen_lock);
    312 		return (ENOTSUP);
    313 	}
    314 
    315 	mutex_exit(&ixgbe->gen_lock);
    316 
    317 	if (ixgbe_check_acc_handle(ixgbe->osdep.reg_handle) != DDI_FM_OK)
    318 		ddi_fm_service_impact(ixgbe->dip, DDI_SERVICE_UNAFFECTED);
    319 
    320 	return (0);
    321 }
    322 
    323 /*
    324  * Bring the device out of the reset/quiesced state that it
    325  * was in when the interface was registered.
    326  */
    327 int
    328 ixgbe_m_start(void *arg)
    329 {
    330 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
    331 
    332 	mutex_enter(&ixgbe->gen_lock);
    333 
    334 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
    335 		mutex_exit(&ixgbe->gen_lock);
    336 		return (ECANCELED);
    337 	}
    338 
    339 	if (ixgbe_start(ixgbe, B_TRUE) != IXGBE_SUCCESS) {
    340 		mutex_exit(&ixgbe->gen_lock);
    341 		return (EIO);
    342 	}
    343 
    344 	ixgbe->ixgbe_state |= IXGBE_STARTED;
    345 
    346 	mutex_exit(&ixgbe->gen_lock);
    347 
    348 	/*
    349 	 * Enable and start the watchdog timer
    350 	 */
    351 	ixgbe_enable_watchdog_timer(ixgbe);
    352 
    353 	return (0);
    354 }
    355 
    356 /*
    357  * Stop the device and put it in a reset/quiesced state such
    358  * that the interface can be unregistered.
    359  */
    360 void
    361 ixgbe_m_stop(void *arg)
    362 {
    363 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
    364 
    365 	mutex_enter(&ixgbe->gen_lock);
    366 
    367 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
    368 		mutex_exit(&ixgbe->gen_lock);
    369 		return;
    370 	}
    371 
    372 	ixgbe->ixgbe_state &= ~IXGBE_STARTED;
    373 
    374 	ixgbe_stop(ixgbe, B_TRUE);
    375 
    376 	mutex_exit(&ixgbe->gen_lock);
    377 
    378 	/*
    379 	 * Disable and stop the watchdog timer
    380 	 */
    381 	ixgbe_disable_watchdog_timer(ixgbe);
    382 }
    383 
    384 /*
    385  * Set the promiscuity of the device.
    386  */
    387 int
    388 ixgbe_m_promisc(void *arg, boolean_t on)
    389 {
    390 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
    391 	uint32_t reg_val;
    392 	struct ixgbe_hw *hw = &ixgbe->hw;
    393 
    394 	mutex_enter(&ixgbe->gen_lock);
    395 
    396 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
    397 		mutex_exit(&ixgbe->gen_lock);
    398 		return (ECANCELED);
    399 	}
    400 	reg_val = IXGBE_READ_REG(hw, IXGBE_FCTRL);
    401 
    402 	if (on)
    403 		reg_val |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
    404 	else
    405 		reg_val &= (~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE));
    406 
    407 	IXGBE_WRITE_REG(&ixgbe->hw, IXGBE_FCTRL, reg_val);
    408 
    409 	mutex_exit(&ixgbe->gen_lock);
    410 
    411 	return (0);
    412 }
    413 
    414 /*
    415  * Add/remove the addresses to/from the set of multicast
    416  * addresses for which the device will receive packets.
    417  */
    418 int
    419 ixgbe_m_multicst(void *arg, boolean_t add, const uint8_t *mcst_addr)
    420 {
    421 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
    422 	int result;
    423 
    424 	mutex_enter(&ixgbe->gen_lock);
    425 
    426 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
    427 		mutex_exit(&ixgbe->gen_lock);
    428 		return (ECANCELED);
    429 	}
    430 
    431 	result = (add) ? ixgbe_multicst_add(ixgbe, mcst_addr)
    432 	    : ixgbe_multicst_remove(ixgbe, mcst_addr);
    433 
    434 	mutex_exit(&ixgbe->gen_lock);
    435 
    436 	return (result);
    437 }
    438 
    439 /*
    440  * Pass on M_IOCTL messages passed to the DLD, and support
    441  * private IOCTLs for debugging and ndd.
    442  */
    443 void
    444 ixgbe_m_ioctl(void *arg, queue_t *q, mblk_t *mp)
    445 {
    446 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
    447 	struct iocblk *iocp;
    448 	enum ioc_reply status;
    449 
    450 	iocp = (struct iocblk *)(uintptr_t)mp->b_rptr;
    451 	iocp->ioc_error = 0;
    452 
    453 	mutex_enter(&ixgbe->gen_lock);
    454 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
    455 		mutex_exit(&ixgbe->gen_lock);
    456 		miocnak(q, mp, 0, EINVAL);
    457 		return;
    458 	}
    459 	mutex_exit(&ixgbe->gen_lock);
    460 
    461 	switch (iocp->ioc_cmd) {
    462 	case LB_GET_INFO_SIZE:
    463 	case LB_GET_INFO:
    464 	case LB_GET_MODE:
    465 	case LB_SET_MODE:
    466 		status = ixgbe_loopback_ioctl(ixgbe, iocp, mp);
    467 		break;
    468 
    469 	default:
    470 		status = IOC_INVAL;
    471 		break;
    472 	}
    473 
    474 	/*
    475 	 * Decide how to reply
    476 	 */
    477 	switch (status) {
    478 	default:
    479 	case IOC_INVAL:
    480 		/*
    481 		 * Error, reply with a NAK and EINVAL or the specified error
    482 		 */
    483 		miocnak(q, mp, 0, iocp->ioc_error == 0 ?
    484 		    EINVAL : iocp->ioc_error);
    485 		break;
    486 
    487 	case IOC_DONE:
    488 		/*
    489 		 * OK, reply already sent
    490 		 */
    491 		break;
    492 
    493 	case IOC_ACK:
    494 		/*
    495 		 * OK, reply with an ACK
    496 		 */
    497 		miocack(q, mp, 0, 0);
    498 		break;
    499 
    500 	case IOC_REPLY:
    501 		/*
    502 		 * OK, send prepared reply as ACK or NAK
    503 		 */
    504 		mp->b_datap->db_type = iocp->ioc_error == 0 ?
    505 		    M_IOCACK : M_IOCNAK;
    506 		qreply(q, mp);
    507 		break;
    508 	}
    509 }
    510 
    511 /*
    512  * Obtain the MAC's capabilities and associated data from
    513  * the driver.
    514  */
    515 boolean_t
    516 ixgbe_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
    517 {
    518 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
    519 
    520 	switch (cap) {
    521 	case MAC_CAPAB_HCKSUM: {
    522 		uint32_t *tx_hcksum_flags = cap_data;
    523 
    524 		/*
    525 		 * We advertise our capabilities only if tx hcksum offload is
    526 		 * enabled.  On receive, the stack will accept checksummed
    527 		 * packets anyway, even if we haven't said we can deliver
    528 		 * them.
    529 		 */
    530 		if (!ixgbe->tx_hcksum_enable)
    531 			return (B_FALSE);
    532 
    533 		*tx_hcksum_flags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM;
    534 		break;
    535 	}
    536 	case MAC_CAPAB_LSO: {
    537 		mac_capab_lso_t *cap_lso = cap_data;
    538 
    539 		if (ixgbe->lso_enable) {
    540 			cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
    541 			cap_lso->lso_basic_tcp_ipv4.lso_max = IXGBE_LSO_MAXLEN;
    542 			break;
    543 		} else {
    544 			return (B_FALSE);
    545 		}
    546 	}
    547 	case MAC_CAPAB_RINGS: {
    548 		mac_capab_rings_t *cap_rings = cap_data;
    549 
    550 		switch (cap_rings->mr_type) {
    551 		case MAC_RING_TYPE_RX:
    552 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
    553 			cap_rings->mr_rnum = ixgbe->num_rx_rings;
    554 			cap_rings->mr_gnum = ixgbe->num_rx_groups;
    555 			cap_rings->mr_rget = ixgbe_fill_ring;
    556 			cap_rings->mr_gget = ixgbe_fill_group;
    557 			cap_rings->mr_gaddring = NULL;
    558 			cap_rings->mr_gremring = NULL;
    559 			break;
    560 		case MAC_RING_TYPE_TX:
    561 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
    562 			cap_rings->mr_rnum = ixgbe->num_tx_rings;
    563 			cap_rings->mr_gnum = 0;
    564 			cap_rings->mr_rget = ixgbe_fill_ring;
    565 			cap_rings->mr_gget = NULL;
    566 			break;
    567 		default:
    568 			break;
    569 		}
    570 		break;
    571 	}
    572 	default:
    573 		return (B_FALSE);
    574 	}
    575 	return (B_TRUE);
    576 }
    577 
    578 int
    579 ixgbe_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
    580     uint_t pr_valsize, const void *pr_val)
    581 {
    582 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
    583 	struct ixgbe_hw *hw = &ixgbe->hw;
    584 	int err = 0;
    585 	uint32_t flow_control;
    586 	uint32_t cur_mtu, new_mtu;
    587 	uint32_t rx_size;
    588 	uint32_t tx_size;
    589 
    590 	mutex_enter(&ixgbe->gen_lock);
    591 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
    592 		mutex_exit(&ixgbe->gen_lock);
    593 		return (ECANCELED);
    594 	}
    595 
    596 	if (ixgbe->loopback_mode != IXGBE_LB_NONE &&
    597 	    ixgbe_param_locked(pr_num)) {
    598 		/*
    599 		 * All en_* parameters are locked (read-only)
    600 		 * while the device is in any sort of loopback mode.
    601 		 */
    602 		mutex_exit(&ixgbe->gen_lock);
    603 		return (EBUSY);
    604 	}
    605 
    606 	switch (pr_num) {
    607 	case MAC_PROP_EN_10GFDX_CAP:
    608 		/* read/write on copper, read-only on serdes */
    609 		if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) {
    610 			err = ENOTSUP;
    611 			break;
    612 		} else {
    613 			ixgbe->param_en_10000fdx_cap = *(uint8_t *)pr_val;
    614 			ixgbe->param_adv_10000fdx_cap = *(uint8_t *)pr_val;
    615 			goto setup_link;
    616 		}
    617 	case MAC_PROP_EN_1000FDX_CAP:
    618 		/* read/write on copper, read-only on serdes */
    619 		if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) {
    620 			err = ENOTSUP;
    621 			break;
    622 		} else {
    623 			ixgbe->param_en_1000fdx_cap = *(uint8_t *)pr_val;
    624 			ixgbe->param_adv_1000fdx_cap = *(uint8_t *)pr_val;
    625 			goto setup_link;
    626 		}
    627 	case MAC_PROP_EN_100FDX_CAP:
    628 		/* read/write on copper, read-only on serdes */
    629 		if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) {
    630 			err = ENOTSUP;
    631 			break;
    632 		} else {
    633 			ixgbe->param_en_100fdx_cap = *(uint8_t *)pr_val;
    634 			ixgbe->param_adv_100fdx_cap = *(uint8_t *)pr_val;
    635 			goto setup_link;
    636 		}
    637 	case MAC_PROP_AUTONEG:
    638 		/* read/write on copper, read-only on serdes */
    639 		if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) {
    640 			err = ENOTSUP;
    641 			break;
    642 		} else {
    643 			ixgbe->param_adv_autoneg_cap = *(uint8_t *)pr_val;
    644 			goto setup_link;
    645 		}
    646 	case MAC_PROP_FLOWCTRL:
    647 		bcopy(pr_val, &flow_control, sizeof (flow_control));
    648 
    649 		switch (flow_control) {
    650 		default:
    651 			err = EINVAL;
    652 			break;
    653 		case LINK_FLOWCTRL_NONE:
    654 			hw->fc.requested_mode = ixgbe_fc_none;
    655 			break;
    656 		case LINK_FLOWCTRL_RX:
    657 			hw->fc.requested_mode = ixgbe_fc_rx_pause;
    658 			break;
    659 		case LINK_FLOWCTRL_TX:
    660 			hw->fc.requested_mode = ixgbe_fc_tx_pause;
    661 			break;
    662 		case LINK_FLOWCTRL_BI:
    663 			hw->fc.requested_mode = ixgbe_fc_full;
    664 			break;
    665 		}
    666 setup_link:
    667 		if (err == 0) {
    668 			if (ixgbe_driver_setup_link(ixgbe, B_TRUE) !=
    669 			    IXGBE_SUCCESS)
    670 				err = EINVAL;
    671 		}
    672 		break;
    673 	case MAC_PROP_ADV_10GFDX_CAP:
    674 	case MAC_PROP_ADV_1000FDX_CAP:
    675 	case MAC_PROP_ADV_100FDX_CAP:
    676 	case MAC_PROP_STATUS:
    677 	case MAC_PROP_SPEED:
    678 	case MAC_PROP_DUPLEX:
    679 		err = ENOTSUP; /* read-only prop. Can't set this. */
    680 		break;
    681 	case MAC_PROP_MTU:
    682 		cur_mtu = ixgbe->default_mtu;
    683 		bcopy(pr_val, &new_mtu, sizeof (new_mtu));
    684 		if (new_mtu == cur_mtu) {
    685 			err = 0;
    686 			break;
    687 		}
    688 
    689 		if (new_mtu < DEFAULT_MTU || new_mtu > ixgbe->capab->max_mtu) {
    690 			err = EINVAL;
    691 			break;
    692 		}
    693 
    694 		if (ixgbe->ixgbe_state & IXGBE_STARTED) {
    695 			err = EBUSY;
    696 			break;
    697 		}
    698 
    699 		err = mac_maxsdu_update(ixgbe->mac_hdl, new_mtu);
    700 		if (err == 0) {
    701 			ixgbe->default_mtu = new_mtu;
    702 			ixgbe->max_frame_size = ixgbe->default_mtu +
    703 			    sizeof (struct ether_vlan_header) + ETHERFCSL;
    704 
    705 			/*
    706 			 * Set rx buffer size
    707 			 */
    708 			rx_size = ixgbe->max_frame_size + IPHDR_ALIGN_ROOM;
    709 			ixgbe->rx_buf_size = ((rx_size >> 10) + ((rx_size &
    710 			    (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
    711 
    712 			/*
    713 			 * Set tx buffer size
    714 			 */
    715 			tx_size = ixgbe->max_frame_size;
    716 			ixgbe->tx_buf_size = ((tx_size >> 10) + ((tx_size &
    717 			    (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
    718 		}
    719 		break;
    720 	case MAC_PROP_PRIVATE:
    721 		err = ixgbe_set_priv_prop(ixgbe, pr_name, pr_valsize, pr_val);
    722 		break;
    723 	default:
    724 		err = EINVAL;
    725 		break;
    726 	}
    727 	mutex_exit(&ixgbe->gen_lock);
    728 	return (err);
    729 }
    730 
    731 int
    732 ixgbe_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
    733     uint_t pr_flags, uint_t pr_valsize, void *pr_val, uint_t *perm)
    734 {
    735 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
    736 	struct ixgbe_hw *hw = &ixgbe->hw;
    737 	int err = 0;
    738 	uint32_t flow_control;
    739 	uint64_t tmp = 0;
    740 	boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT);
    741 	mac_propval_range_t range;
    742 
    743 	if (pr_valsize == 0)
    744 		return (EINVAL);
    745 
    746 	*perm = MAC_PROP_PERM_READ;
    747 
    748 	bzero(pr_val, pr_valsize);
    749 
    750 	switch (pr_num) {
    751 	case MAC_PROP_DUPLEX:
    752 		if (pr_valsize >= sizeof (link_duplex_t)) {
    753 			bcopy(&ixgbe->link_duplex, pr_val,
    754 			    sizeof (link_duplex_t));
    755 		} else
    756 			err = EINVAL;
    757 		break;
    758 	case MAC_PROP_SPEED:
    759 		if (pr_valsize >= sizeof (uint64_t)) {
    760 			tmp = ixgbe->link_speed * 1000000ull;
    761 			bcopy(&tmp, pr_val, sizeof (tmp));
    762 		} else
    763 			err = EINVAL;
    764 		break;
    765 	case MAC_PROP_AUTONEG:
    766 		if (ixgbe->hw.phy.media_type == ixgbe_media_type_copper)
    767 			*perm = MAC_PROP_PERM_RW;
    768 		*(uint8_t *)pr_val =
    769 		    (is_default ? 1 : ixgbe->param_adv_autoneg_cap);
    770 		break;
    771 	case MAC_PROP_FLOWCTRL:
    772 		*perm = MAC_PROP_PERM_RW;
    773 		if (pr_valsize >= sizeof (uint32_t)) {
    774 			if (is_default) {
    775 				flow_control = LINK_FLOWCTRL_NONE;
    776 				bcopy(&flow_control, pr_val,
    777 				    sizeof (flow_control));
    778 				break;
    779 			}
    780 			switch (hw->fc.requested_mode) {
    781 				case ixgbe_fc_none:
    782 					flow_control = LINK_FLOWCTRL_NONE;
    783 					break;
    784 				case ixgbe_fc_rx_pause:
    785 					flow_control = LINK_FLOWCTRL_RX;
    786 					break;
    787 				case ixgbe_fc_tx_pause:
    788 					flow_control = LINK_FLOWCTRL_TX;
    789 					break;
    790 				case ixgbe_fc_full:
    791 					flow_control = LINK_FLOWCTRL_BI;
    792 					break;
    793 			}
    794 			bcopy(&flow_control, pr_val, sizeof (flow_control));
    795 		} else
    796 			err = EINVAL;
    797 		break;
    798 	case MAC_PROP_ADV_10GFDX_CAP:
    799 		*(uint8_t *)pr_val = (is_default ? 1 :
    800 		    ixgbe->param_adv_10000fdx_cap);
    801 		break;
    802 	case MAC_PROP_EN_10GFDX_CAP:
    803 		if (ixgbe->hw.phy.media_type == ixgbe_media_type_copper)
    804 			*perm = MAC_PROP_PERM_RW;
    805 		*(uint8_t *)pr_val =
    806 		    (is_default ? 1 : ixgbe->param_en_10000fdx_cap);
    807 		break;
    808 	case MAC_PROP_ADV_1000FDX_CAP:
    809 		*(uint8_t *)pr_val = (is_default ? 1 :
    810 		    ixgbe->param_adv_1000fdx_cap);
    811 		break;
    812 	case MAC_PROP_EN_1000FDX_CAP:
    813 		if (ixgbe->hw.phy.media_type == ixgbe_media_type_copper)
    814 			*perm = MAC_PROP_PERM_RW;
    815 		*(uint8_t *)pr_val =
    816 		    (is_default ? 1 : ixgbe->param_en_1000fdx_cap);
    817 		break;
    818 	case MAC_PROP_ADV_100FDX_CAP:
    819 		*(uint8_t *)pr_val =
    820 		    (is_default ? 1 : ixgbe->param_adv_100fdx_cap);
    821 		break;
    822 	case MAC_PROP_EN_100FDX_CAP:
    823 		if (ixgbe->hw.phy.media_type == ixgbe_media_type_copper)
    824 			*perm = MAC_PROP_PERM_RW;
    825 		*(uint8_t *)pr_val =
    826 		    (is_default ? 1 : ixgbe->param_en_100fdx_cap);
    827 		break;
    828 	case MAC_PROP_PRIVATE:
    829 		err = ixgbe_get_priv_prop(ixgbe, pr_name,
    830 		    pr_flags, pr_valsize, pr_val, perm);
    831 		break;
    832 	case MAC_PROP_MTU:
    833 		if (!(pr_flags & MAC_PROP_POSSIBLE))
    834 			return (ENOTSUP);
    835 		if (pr_valsize < sizeof (mac_propval_range_t))
    836 			return (EINVAL);
    837 		range.mpr_count = 1;
    838 		range.mpr_type = MAC_PROPVAL_UINT32;
    839 		range.range_uint32[0].mpur_min = DEFAULT_MTU;
    840 		range.range_uint32[0].mpur_max = ixgbe->capab->max_mtu;
    841 		bcopy(&range, pr_val, sizeof (range));
    842 		break;
    843 	default:
    844 		err = EINVAL;
    845 		break;
    846 	}
    847 	return (err);
    848 }
    849 
    850 boolean_t
    851 ixgbe_param_locked(mac_prop_id_t pr_num)
    852 {
    853 	/*
    854 	 * All en_* parameters are locked (read-only) while
    855 	 * the device is in any sort of loopback mode ...
    856 	 */
    857 	switch (pr_num) {
    858 		case MAC_PROP_EN_10GFDX_CAP:
    859 		case MAC_PROP_EN_1000FDX_CAP:
    860 		case MAC_PROP_EN_100FDX_CAP:
    861 		case MAC_PROP_AUTONEG:
    862 		case MAC_PROP_FLOWCTRL:
    863 			return (B_TRUE);
    864 	}
    865 	return (B_FALSE);
    866 }
    867 
    868 /* ARGSUSED */
    869 int
    870 ixgbe_set_priv_prop(ixgbe_t *ixgbe, const char *pr_name,
    871     uint_t pr_valsize, const void *pr_val)
    872 {
    873 	int err = 0;
    874 	long result;
    875 	struct ixgbe_hw *hw = &ixgbe->hw;
    876 	int i;
    877 
    878 	if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
    879 		if (pr_val == NULL) {
    880 			err = EINVAL;
    881 			return (err);
    882 		}
    883 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
    884 		if (result < MIN_TX_COPY_THRESHOLD ||
    885 		    result > MAX_TX_COPY_THRESHOLD)
    886 			err = EINVAL;
    887 		else {
    888 			ixgbe->tx_copy_thresh = (uint32_t)result;
    889 		}
    890 		return (err);
    891 	}
    892 	if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
    893 		if (pr_val == NULL) {
    894 			err = EINVAL;
    895 			return (err);
    896 		}
    897 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
    898 		if (result < MIN_TX_RECYCLE_THRESHOLD ||
    899 		    result > MAX_TX_RECYCLE_THRESHOLD)
    900 			err = EINVAL;
    901 		else {
    902 			ixgbe->tx_recycle_thresh = (uint32_t)result;
    903 		}
    904 		return (err);
    905 	}
    906 	if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
    907 		if (pr_val == NULL) {
    908 			err = EINVAL;
    909 			return (err);
    910 		}
    911 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
    912 		if (result < MIN_TX_OVERLOAD_THRESHOLD ||
    913 		    result > MAX_TX_OVERLOAD_THRESHOLD)
    914 			err = EINVAL;
    915 		else {
    916 			ixgbe->tx_overload_thresh = (uint32_t)result;
    917 		}
    918 		return (err);
    919 	}
    920 	if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
    921 		if (pr_val == NULL) {
    922 			err = EINVAL;
    923 			return (err);
    924 		}
    925 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
    926 		if (result < MIN_TX_RESCHED_THRESHOLD ||
    927 		    result > MAX_TX_RESCHED_THRESHOLD)
    928 			err = EINVAL;
    929 		else {
    930 			ixgbe->tx_resched_thresh = (uint32_t)result;
    931 		}
    932 		return (err);
    933 	}
    934 	if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
    935 		if (pr_val == NULL) {
    936 			err = EINVAL;
    937 			return (err);
    938 		}
    939 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
    940 		if (result < MIN_RX_COPY_THRESHOLD ||
    941 		    result > MAX_RX_COPY_THRESHOLD)
    942 			err = EINVAL;
    943 		else {
    944 			ixgbe->rx_copy_thresh = (uint32_t)result;
    945 		}
    946 		return (err);
    947 	}
    948 	if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
    949 		if (pr_val == NULL) {
    950 			err = EINVAL;
    951 			return (err);
    952 		}
    953 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
    954 		if (result < MIN_RX_LIMIT_PER_INTR ||
    955 		    result > MAX_RX_LIMIT_PER_INTR)
    956 			err = EINVAL;
    957 		else {
    958 			ixgbe->rx_limit_per_intr = (uint32_t)result;
    959 		}
    960 		return (err);
    961 	}
    962 	if (strcmp(pr_name, "_intr_throttling") == 0) {
    963 		if (pr_val == NULL) {
    964 			err = EINVAL;
    965 			return (err);
    966 		}
    967 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
    968 
    969 		if (result < ixgbe->capab->min_intr_throttle ||
    970 		    result > ixgbe->capab->max_intr_throttle)
    971 			err = EINVAL;
    972 		else {
    973 			ixgbe->intr_throttling[0] = (uint32_t)result;
    974 
    975 			/*
    976 			 * 82599 requires the interupt throttling rate is
    977 			 * a multiple of 8. This is enforced by the register
    978 			 * definiton.
    979 			 */
    980 			if (hw->mac.type == ixgbe_mac_82599EB)
    981 				ixgbe->intr_throttling[0] =
    982 				    ixgbe->intr_throttling[0] & 0xFF8;
    983 
    984 			for (i = 0; i < MAX_INTR_VECTOR; i++)
    985 				ixgbe->intr_throttling[i] =
    986 				    ixgbe->intr_throttling[0];
    987 
    988 			/* Set interrupt throttling rate */
    989 			for (i = 0; i < ixgbe->intr_cnt; i++)
    990 				IXGBE_WRITE_REG(hw, IXGBE_EITR(i),
    991 				    ixgbe->intr_throttling[i]);
    992 		}
    993 		return (err);
    994 	}
    995 	return (ENOTSUP);
    996 }
    997 
    998 int
    999 ixgbe_get_priv_prop(ixgbe_t *ixgbe, const char *pr_name,
   1000     uint_t pr_flags, uint_t pr_valsize, void *pr_val, uint_t *perm)
   1001 {
   1002 	int err = ENOTSUP;
   1003 	boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT);
   1004 	int value;
   1005 
   1006 	*perm = MAC_PROP_PERM_RW;
   1007 
   1008 	if (strcmp(pr_name, "_adv_pause_cap") == 0) {
   1009 		*perm = MAC_PROP_PERM_READ;
   1010 		value = (is_default ? 1 : ixgbe->param_adv_pause_cap);
   1011 		err = 0;
   1012 		goto done;
   1013 	}
   1014 	if (strcmp(pr_name, "_adv_asym_pause_cap") == 0) {
   1015 		*perm = MAC_PROP_PERM_READ;
   1016 		value = (is_default ? 1 : ixgbe->param_adv_asym_pause_cap);
   1017 		err = 0;
   1018 		goto done;
   1019 	}
   1020 	if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
   1021 		value = (is_default ? DEFAULT_TX_COPY_THRESHOLD :
   1022 		    ixgbe->tx_copy_thresh);
   1023 		err = 0;
   1024 		goto done;
   1025 	}
   1026 	if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
   1027 		value = (is_default ? DEFAULT_TX_RECYCLE_THRESHOLD :
   1028 		    ixgbe->tx_recycle_thresh);
   1029 		err = 0;
   1030 		goto done;
   1031 	}
   1032 	if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
   1033 		value = (is_default ? DEFAULT_TX_OVERLOAD_THRESHOLD :
   1034 		    ixgbe->tx_overload_thresh);
   1035 		err = 0;
   1036 		goto done;
   1037 	}
   1038 	if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
   1039 		value = (is_default ? DEFAULT_TX_RESCHED_THRESHOLD :
   1040 		    ixgbe->tx_resched_thresh);
   1041 		err = 0;
   1042 		goto done;
   1043 	}
   1044 	if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
   1045 		value = (is_default ? DEFAULT_RX_COPY_THRESHOLD :
   1046 		    ixgbe->rx_copy_thresh);
   1047 		err = 0;
   1048 		goto done;
   1049 	}
   1050 	if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
   1051 		value = (is_default ? DEFAULT_RX_LIMIT_PER_INTR :
   1052 		    ixgbe->rx_limit_per_intr);
   1053 		err = 0;
   1054 		goto done;
   1055 	}
   1056 	if (strcmp(pr_name, "_intr_throttling") == 0) {
   1057 		value = (is_default ? ixgbe->capab->def_intr_throttle :
   1058 		    ixgbe->intr_throttling[0]);
   1059 		err = 0;
   1060 		goto done;
   1061 	}
   1062 done:
   1063 	if (err == 0) {
   1064 		(void) snprintf(pr_val, pr_valsize, "%d", value);
   1065 	}
   1066 	return (err);
   1067 }
   1068