15779Sxy150489 /* 25779Sxy150489 * CDDL HEADER START 35779Sxy150489 * 45779Sxy150489 * The contents of this file are subject to the terms of the 55779Sxy150489 * Common Development and Distribution License (the "License"). 65779Sxy150489 * You may not use this file except in compliance with the License. 75779Sxy150489 * 88275SEric Cheng * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 98275SEric Cheng * or http://www.opensolaris.org/os/licensing. 105779Sxy150489 * See the License for the specific language governing permissions 115779Sxy150489 * and limitations under the License. 125779Sxy150489 * 138275SEric Cheng * When distributing Covered Code, include this CDDL HEADER in each 148275SEric Cheng * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155779Sxy150489 * If applicable, add the following below this CDDL HEADER, with the 165779Sxy150489 * fields enclosed by brackets "[]" replaced with your own identifying 175779Sxy150489 * information: Portions Copyright [yyyy] [name of copyright owner] 185779Sxy150489 * 195779Sxy150489 * CDDL HEADER END 205779Sxy150489 */ 215779Sxy150489 225779Sxy150489 /* 238275SEric Cheng * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. 245779Sxy150489 */ 255779Sxy150489 268275SEric Cheng /* 27*11502SChenlu.Chen@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 288275SEric Cheng * Use is subject to license terms. 298275SEric Cheng */ 305779Sxy150489 315779Sxy150489 #include "igb_sw.h" 325779Sxy150489 335779Sxy150489 int 345779Sxy150489 igb_m_stat(void *arg, uint_t stat, uint64_t *val) 355779Sxy150489 { 365779Sxy150489 igb_t *igb = (igb_t *)arg; 375779Sxy150489 struct e1000_hw *hw = &igb->hw; 385779Sxy150489 igb_stat_t *igb_ks; 395779Sxy150489 uint32_t low_val, high_val; 405779Sxy150489 415779Sxy150489 igb_ks = (igb_stat_t *)igb->igb_ks->ks_data; 425779Sxy150489 435779Sxy150489 mutex_enter(&igb->gen_lock); 445779Sxy150489 455779Sxy150489 if (igb->igb_state & IGB_SUSPENDED) { 465779Sxy150489 mutex_exit(&igb->gen_lock); 475779Sxy150489 return (ECANCELED); 485779Sxy150489 } 495779Sxy150489 505779Sxy150489 switch (stat) { 515779Sxy150489 case MAC_STAT_IFSPEED: 525779Sxy150489 *val = igb->link_speed * 1000000ull; 535779Sxy150489 break; 545779Sxy150489 555779Sxy150489 case MAC_STAT_MULTIRCV: 565779Sxy150489 igb_ks->mprc.value.ui64 += 575779Sxy150489 E1000_READ_REG(hw, E1000_MPRC); 585779Sxy150489 *val = igb_ks->mprc.value.ui64; 595779Sxy150489 break; 605779Sxy150489 615779Sxy150489 case MAC_STAT_BRDCSTRCV: 625779Sxy150489 igb_ks->bprc.value.ui64 += 635779Sxy150489 E1000_READ_REG(hw, E1000_BPRC); 645779Sxy150489 *val = igb_ks->bprc.value.ui64; 655779Sxy150489 break; 665779Sxy150489 675779Sxy150489 case MAC_STAT_MULTIXMT: 685779Sxy150489 igb_ks->mptc.value.ui64 += 695779Sxy150489 E1000_READ_REG(hw, E1000_MPTC); 705779Sxy150489 *val = igb_ks->mptc.value.ui64; 715779Sxy150489 break; 725779Sxy150489 735779Sxy150489 case MAC_STAT_BRDCSTXMT: 745779Sxy150489 igb_ks->bptc.value.ui64 += 755779Sxy150489 E1000_READ_REG(hw, E1000_BPTC); 765779Sxy150489 *val = igb_ks->bptc.value.ui64; 775779Sxy150489 break; 785779Sxy150489 795779Sxy150489 case MAC_STAT_NORCVBUF: 805779Sxy150489 igb_ks->rnbc.value.ui64 += 815779Sxy150489 E1000_READ_REG(hw, E1000_RNBC); 825779Sxy150489 *val = igb_ks->rnbc.value.ui64; 835779Sxy150489 break; 845779Sxy150489 855779Sxy150489 case MAC_STAT_IERRORS: 865779Sxy150489 igb_ks->rxerrc.value.ui64 += 875779Sxy150489 E1000_READ_REG(hw, E1000_RXERRC); 885779Sxy150489 igb_ks->algnerrc.value.ui64 += 895779Sxy150489 E1000_READ_REG(hw, E1000_ALGNERRC); 905779Sxy150489 igb_ks->rlec.value.ui64 += 915779Sxy150489 E1000_READ_REG(hw, E1000_RLEC); 925779Sxy150489 igb_ks->crcerrs.value.ui64 += 935779Sxy150489 E1000_READ_REG(hw, E1000_CRCERRS); 945779Sxy150489 igb_ks->cexterr.value.ui64 += 955779Sxy150489 E1000_READ_REG(hw, E1000_CEXTERR); 965779Sxy150489 *val = igb_ks->rxerrc.value.ui64 + 975779Sxy150489 igb_ks->algnerrc.value.ui64 + 985779Sxy150489 igb_ks->rlec.value.ui64 + 995779Sxy150489 igb_ks->crcerrs.value.ui64 + 1005779Sxy150489 igb_ks->cexterr.value.ui64; 1015779Sxy150489 break; 1025779Sxy150489 1035779Sxy150489 case MAC_STAT_NOXMTBUF: 1045779Sxy150489 *val = 0; 1055779Sxy150489 break; 1065779Sxy150489 1075779Sxy150489 case MAC_STAT_OERRORS: 1085779Sxy150489 igb_ks->ecol.value.ui64 += 1095779Sxy150489 E1000_READ_REG(hw, E1000_ECOL); 1105779Sxy150489 *val = igb_ks->ecol.value.ui64; 1115779Sxy150489 break; 1125779Sxy150489 1135779Sxy150489 case MAC_STAT_COLLISIONS: 1145779Sxy150489 igb_ks->colc.value.ui64 += 1155779Sxy150489 E1000_READ_REG(hw, E1000_COLC); 1165779Sxy150489 *val = igb_ks->colc.value.ui64; 1175779Sxy150489 break; 1185779Sxy150489 1195779Sxy150489 case MAC_STAT_RBYTES: 1205779Sxy150489 /* 1215779Sxy150489 * The 64-bit register will reset whenever the upper 1225779Sxy150489 * 32 bits are read. So we need to read the lower 1235779Sxy150489 * 32 bits first, then read the upper 32 bits. 1245779Sxy150489 */ 1255779Sxy150489 low_val = E1000_READ_REG(hw, E1000_TORL); 1265779Sxy150489 high_val = E1000_READ_REG(hw, E1000_TORH); 1275779Sxy150489 igb_ks->tor.value.ui64 += 1285779Sxy150489 (uint64_t)high_val << 32 | (uint64_t)low_val; 1295779Sxy150489 *val = igb_ks->tor.value.ui64; 1305779Sxy150489 break; 1315779Sxy150489 1325779Sxy150489 case MAC_STAT_IPACKETS: 1335779Sxy150489 igb_ks->tpr.value.ui64 += 1345779Sxy150489 E1000_READ_REG(hw, E1000_TPR); 1355779Sxy150489 *val = igb_ks->tpr.value.ui64; 1365779Sxy150489 break; 1375779Sxy150489 1385779Sxy150489 case MAC_STAT_OBYTES: 1395779Sxy150489 /* 1405779Sxy150489 * The 64-bit register will reset whenever the upper 1415779Sxy150489 * 32 bits are read. So we need to read the lower 1425779Sxy150489 * 32 bits first, then read the upper 32 bits. 1435779Sxy150489 */ 1445779Sxy150489 low_val = E1000_READ_REG(hw, E1000_TOTL); 1455779Sxy150489 high_val = E1000_READ_REG(hw, E1000_TOTH); 1465779Sxy150489 igb_ks->tot.value.ui64 += 1475779Sxy150489 (uint64_t)high_val << 32 | (uint64_t)low_val; 1485779Sxy150489 *val = igb_ks->tot.value.ui64; 1495779Sxy150489 break; 1505779Sxy150489 1515779Sxy150489 case MAC_STAT_OPACKETS: 1525779Sxy150489 igb_ks->tpt.value.ui64 += 1535779Sxy150489 E1000_READ_REG(hw, E1000_TPT); 1545779Sxy150489 *val = igb_ks->tpt.value.ui64; 1555779Sxy150489 break; 1565779Sxy150489 1575779Sxy150489 /* RFC 1643 stats */ 1585779Sxy150489 case ETHER_STAT_ALIGN_ERRORS: 1595779Sxy150489 igb_ks->algnerrc.value.ui64 += 1605779Sxy150489 E1000_READ_REG(hw, E1000_ALGNERRC); 1615779Sxy150489 *val = igb_ks->algnerrc.value.ui64; 1625779Sxy150489 break; 1635779Sxy150489 1645779Sxy150489 case ETHER_STAT_FCS_ERRORS: 1655779Sxy150489 igb_ks->crcerrs.value.ui64 += 1665779Sxy150489 E1000_READ_REG(hw, E1000_CRCERRS); 1675779Sxy150489 *val = igb_ks->crcerrs.value.ui64; 1685779Sxy150489 break; 1695779Sxy150489 1705779Sxy150489 case ETHER_STAT_FIRST_COLLISIONS: 1715779Sxy150489 igb_ks->scc.value.ui64 += 1725779Sxy150489 E1000_READ_REG(hw, E1000_SCC); 1735779Sxy150489 *val = igb_ks->scc.value.ui64; 1745779Sxy150489 break; 1755779Sxy150489 1765779Sxy150489 case ETHER_STAT_MULTI_COLLISIONS: 1775779Sxy150489 igb_ks->mcc.value.ui64 += 1785779Sxy150489 E1000_READ_REG(hw, E1000_MCC); 1795779Sxy150489 *val = igb_ks->mcc.value.ui64; 1805779Sxy150489 break; 1815779Sxy150489 1825779Sxy150489 case ETHER_STAT_SQE_ERRORS: 1835779Sxy150489 igb_ks->sec.value.ui64 += 1845779Sxy150489 E1000_READ_REG(hw, E1000_SEC); 1855779Sxy150489 *val = igb_ks->sec.value.ui64; 1865779Sxy150489 break; 1875779Sxy150489 1885779Sxy150489 case ETHER_STAT_DEFER_XMTS: 1895779Sxy150489 igb_ks->dc.value.ui64 += 1905779Sxy150489 E1000_READ_REG(hw, E1000_DC); 1915779Sxy150489 *val = igb_ks->dc.value.ui64; 1925779Sxy150489 break; 1935779Sxy150489 1945779Sxy150489 case ETHER_STAT_TX_LATE_COLLISIONS: 1955779Sxy150489 igb_ks->latecol.value.ui64 += 1965779Sxy150489 E1000_READ_REG(hw, E1000_LATECOL); 1975779Sxy150489 *val = igb_ks->latecol.value.ui64; 1985779Sxy150489 break; 1995779Sxy150489 2005779Sxy150489 case ETHER_STAT_EX_COLLISIONS: 2015779Sxy150489 igb_ks->ecol.value.ui64 += 2025779Sxy150489 E1000_READ_REG(hw, E1000_ECOL); 2035779Sxy150489 *val = igb_ks->ecol.value.ui64; 2045779Sxy150489 break; 2055779Sxy150489 2065779Sxy150489 case ETHER_STAT_MACXMT_ERRORS: 2075779Sxy150489 igb_ks->ecol.value.ui64 += 2085779Sxy150489 E1000_READ_REG(hw, E1000_ECOL); 2095779Sxy150489 *val = igb_ks->ecol.value.ui64; 2105779Sxy150489 break; 2115779Sxy150489 2125779Sxy150489 case ETHER_STAT_CARRIER_ERRORS: 2135779Sxy150489 igb_ks->cexterr.value.ui64 += 2145779Sxy150489 E1000_READ_REG(hw, E1000_CEXTERR); 2155779Sxy150489 *val = igb_ks->cexterr.value.ui64; 2165779Sxy150489 break; 2175779Sxy150489 2185779Sxy150489 case ETHER_STAT_TOOLONG_ERRORS: 2195779Sxy150489 igb_ks->roc.value.ui64 += 2205779Sxy150489 E1000_READ_REG(hw, E1000_ROC); 2215779Sxy150489 *val = igb_ks->roc.value.ui64; 2225779Sxy150489 break; 2235779Sxy150489 2245779Sxy150489 case ETHER_STAT_MACRCV_ERRORS: 2255779Sxy150489 igb_ks->rxerrc.value.ui64 += 2265779Sxy150489 E1000_READ_REG(hw, E1000_RXERRC); 2275779Sxy150489 *val = igb_ks->rxerrc.value.ui64; 2285779Sxy150489 break; 2295779Sxy150489 2305779Sxy150489 /* MII/GMII stats */ 2315779Sxy150489 case ETHER_STAT_XCVR_ADDR: 2325779Sxy150489 /* The Internal PHY's MDI address for each MAC is 1 */ 2335779Sxy150489 *val = 1; 2345779Sxy150489 break; 2355779Sxy150489 2365779Sxy150489 case ETHER_STAT_XCVR_ID: 2375779Sxy150489 *val = hw->phy.id | hw->phy.revision; 2385779Sxy150489 break; 2395779Sxy150489 2405779Sxy150489 case ETHER_STAT_XCVR_INUSE: 2415779Sxy150489 switch (igb->link_speed) { 2425779Sxy150489 case SPEED_1000: 2435779Sxy150489 *val = 2445779Sxy150489 (hw->phy.media_type == e1000_media_type_copper) ? 2455779Sxy150489 XCVR_1000T : XCVR_1000X; 2465779Sxy150489 break; 2475779Sxy150489 case SPEED_100: 2485779Sxy150489 *val = 2495779Sxy150489 (hw->phy.media_type == e1000_media_type_copper) ? 2505779Sxy150489 (igb->param_100t4_cap == 1) ? 2515779Sxy150489 XCVR_100T4 : XCVR_100T2 : XCVR_100X; 2525779Sxy150489 break; 2535779Sxy150489 case SPEED_10: 2545779Sxy150489 *val = XCVR_10; 2555779Sxy150489 break; 2565779Sxy150489 default: 2575779Sxy150489 *val = XCVR_NONE; 2585779Sxy150489 break; 2595779Sxy150489 } 2605779Sxy150489 break; 2615779Sxy150489 2625779Sxy150489 case ETHER_STAT_CAP_1000FDX: 2635779Sxy150489 *val = igb->param_1000fdx_cap; 2645779Sxy150489 break; 2655779Sxy150489 2665779Sxy150489 case ETHER_STAT_CAP_1000HDX: 2675779Sxy150489 *val = igb->param_1000hdx_cap; 2685779Sxy150489 break; 2695779Sxy150489 2705779Sxy150489 case ETHER_STAT_CAP_100FDX: 2715779Sxy150489 *val = igb->param_100fdx_cap; 2725779Sxy150489 break; 2735779Sxy150489 2745779Sxy150489 case ETHER_STAT_CAP_100HDX: 2755779Sxy150489 *val = igb->param_100hdx_cap; 2765779Sxy150489 break; 2775779Sxy150489 2785779Sxy150489 case ETHER_STAT_CAP_10FDX: 2795779Sxy150489 *val = igb->param_10fdx_cap; 2805779Sxy150489 break; 2815779Sxy150489 2825779Sxy150489 case ETHER_STAT_CAP_10HDX: 2835779Sxy150489 *val = igb->param_10hdx_cap; 2845779Sxy150489 break; 2855779Sxy150489 2865779Sxy150489 case ETHER_STAT_CAP_ASMPAUSE: 2875779Sxy150489 *val = igb->param_asym_pause_cap; 2885779Sxy150489 break; 2895779Sxy150489 2905779Sxy150489 case ETHER_STAT_CAP_PAUSE: 2915779Sxy150489 *val = igb->param_pause_cap; 2925779Sxy150489 break; 2935779Sxy150489 2945779Sxy150489 case ETHER_STAT_CAP_AUTONEG: 2955779Sxy150489 *val = igb->param_autoneg_cap; 2965779Sxy150489 break; 2975779Sxy150489 2985779Sxy150489 case ETHER_STAT_ADV_CAP_1000FDX: 2995779Sxy150489 *val = igb->param_adv_1000fdx_cap; 3005779Sxy150489 break; 3015779Sxy150489 3025779Sxy150489 case ETHER_STAT_ADV_CAP_1000HDX: 3035779Sxy150489 *val = igb->param_adv_1000hdx_cap; 3045779Sxy150489 break; 3055779Sxy150489 3065779Sxy150489 case ETHER_STAT_ADV_CAP_100FDX: 3075779Sxy150489 *val = igb->param_adv_100fdx_cap; 3085779Sxy150489 break; 3095779Sxy150489 3105779Sxy150489 case ETHER_STAT_ADV_CAP_100HDX: 3115779Sxy150489 *val = igb->param_adv_100hdx_cap; 3125779Sxy150489 break; 3135779Sxy150489 3145779Sxy150489 case ETHER_STAT_ADV_CAP_10FDX: 3155779Sxy150489 *val = igb->param_adv_10fdx_cap; 3165779Sxy150489 break; 3175779Sxy150489 3185779Sxy150489 case ETHER_STAT_ADV_CAP_10HDX: 3195779Sxy150489 *val = igb->param_adv_10hdx_cap; 3205779Sxy150489 break; 3215779Sxy150489 3225779Sxy150489 case ETHER_STAT_ADV_CAP_ASMPAUSE: 3235779Sxy150489 *val = igb->param_adv_asym_pause_cap; 3245779Sxy150489 break; 3255779Sxy150489 3265779Sxy150489 case ETHER_STAT_ADV_CAP_PAUSE: 3275779Sxy150489 *val = igb->param_adv_pause_cap; 3285779Sxy150489 break; 3295779Sxy150489 3305779Sxy150489 case ETHER_STAT_ADV_CAP_AUTONEG: 3315779Sxy150489 *val = hw->mac.autoneg; 3325779Sxy150489 break; 3335779Sxy150489 3345779Sxy150489 case ETHER_STAT_LP_CAP_1000FDX: 3355779Sxy150489 *val = igb->param_lp_1000fdx_cap; 3365779Sxy150489 break; 3375779Sxy150489 3385779Sxy150489 case ETHER_STAT_LP_CAP_1000HDX: 3395779Sxy150489 *val = igb->param_lp_1000hdx_cap; 3405779Sxy150489 break; 3415779Sxy150489 3425779Sxy150489 case ETHER_STAT_LP_CAP_100FDX: 3435779Sxy150489 *val = igb->param_lp_100fdx_cap; 3445779Sxy150489 break; 3455779Sxy150489 3465779Sxy150489 case ETHER_STAT_LP_CAP_100HDX: 3475779Sxy150489 *val = igb->param_lp_100hdx_cap; 3485779Sxy150489 break; 3495779Sxy150489 3505779Sxy150489 case ETHER_STAT_LP_CAP_10FDX: 3515779Sxy150489 *val = igb->param_lp_10fdx_cap; 3525779Sxy150489 break; 3535779Sxy150489 3545779Sxy150489 case ETHER_STAT_LP_CAP_10HDX: 3555779Sxy150489 *val = igb->param_lp_10hdx_cap; 3565779Sxy150489 break; 3575779Sxy150489 3585779Sxy150489 case ETHER_STAT_LP_CAP_ASMPAUSE: 3595779Sxy150489 *val = igb->param_lp_asym_pause_cap; 3605779Sxy150489 break; 3615779Sxy150489 3625779Sxy150489 case ETHER_STAT_LP_CAP_PAUSE: 3635779Sxy150489 *val = igb->param_lp_pause_cap; 3645779Sxy150489 break; 3655779Sxy150489 3665779Sxy150489 case ETHER_STAT_LP_CAP_AUTONEG: 3675779Sxy150489 *val = igb->param_lp_autoneg_cap; 3685779Sxy150489 break; 3695779Sxy150489 3705779Sxy150489 case ETHER_STAT_LINK_ASMPAUSE: 3715779Sxy150489 *val = igb->param_asym_pause_cap; 3725779Sxy150489 break; 3735779Sxy150489 3745779Sxy150489 case ETHER_STAT_LINK_PAUSE: 3755779Sxy150489 *val = igb->param_pause_cap; 3765779Sxy150489 break; 3775779Sxy150489 3785779Sxy150489 case ETHER_STAT_LINK_AUTONEG: 3795779Sxy150489 *val = hw->mac.autoneg; 3805779Sxy150489 break; 3815779Sxy150489 3825779Sxy150489 case ETHER_STAT_LINK_DUPLEX: 3835779Sxy150489 *val = (igb->link_duplex == FULL_DUPLEX) ? 3845779Sxy150489 LINK_DUPLEX_FULL : LINK_DUPLEX_HALF; 3855779Sxy150489 break; 3865779Sxy150489 3875779Sxy150489 case ETHER_STAT_TOOSHORT_ERRORS: 3885779Sxy150489 igb_ks->ruc.value.ui64 += 3895779Sxy150489 E1000_READ_REG(hw, E1000_RUC); 3905779Sxy150489 *val = igb_ks->ruc.value.ui64; 3915779Sxy150489 break; 3925779Sxy150489 3935779Sxy150489 case ETHER_STAT_CAP_REMFAULT: 3945779Sxy150489 *val = igb->param_rem_fault; 3955779Sxy150489 break; 3965779Sxy150489 3975779Sxy150489 case ETHER_STAT_ADV_REMFAULT: 3985779Sxy150489 *val = igb->param_adv_rem_fault; 3995779Sxy150489 break; 4005779Sxy150489 4015779Sxy150489 case ETHER_STAT_LP_REMFAULT: 4025779Sxy150489 *val = igb->param_lp_rem_fault; 4035779Sxy150489 break; 4045779Sxy150489 4055779Sxy150489 case ETHER_STAT_JABBER_ERRORS: 4065779Sxy150489 igb_ks->rjc.value.ui64 += 4075779Sxy150489 E1000_READ_REG(hw, E1000_RJC); 4085779Sxy150489 *val = igb_ks->rjc.value.ui64; 4095779Sxy150489 break; 4105779Sxy150489 4115779Sxy150489 case ETHER_STAT_CAP_100T4: 4125779Sxy150489 *val = igb->param_100t4_cap; 4135779Sxy150489 break; 4145779Sxy150489 4155779Sxy150489 case ETHER_STAT_ADV_CAP_100T4: 4165779Sxy150489 *val = igb->param_adv_100t4_cap; 4175779Sxy150489 break; 4185779Sxy150489 4195779Sxy150489 case ETHER_STAT_LP_CAP_100T4: 4205779Sxy150489 *val = igb->param_lp_100t4_cap; 4215779Sxy150489 break; 4225779Sxy150489 4235779Sxy150489 default: 4245779Sxy150489 mutex_exit(&igb->gen_lock); 4255779Sxy150489 return (ENOTSUP); 4265779Sxy150489 } 4275779Sxy150489 4285779Sxy150489 mutex_exit(&igb->gen_lock); 4295779Sxy150489 43011367SJason.Xu@Sun.COM if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) { 43111367SJason.Xu@Sun.COM ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); 43211367SJason.Xu@Sun.COM return (EIO); 43311367SJason.Xu@Sun.COM } 4346624Sgl147354 4355779Sxy150489 return (0); 4365779Sxy150489 } 4375779Sxy150489 4385779Sxy150489 /* 4395779Sxy150489 * Bring the device out of the reset/quiesced state that it 4405779Sxy150489 * was in when the interface was registered. 4415779Sxy150489 */ 4425779Sxy150489 int 4435779Sxy150489 igb_m_start(void *arg) 4445779Sxy150489 { 4455779Sxy150489 igb_t *igb = (igb_t *)arg; 4465779Sxy150489 4475779Sxy150489 mutex_enter(&igb->gen_lock); 4485779Sxy150489 4495779Sxy150489 if (igb->igb_state & IGB_SUSPENDED) { 4505779Sxy150489 mutex_exit(&igb->gen_lock); 4515779Sxy150489 return (ECANCELED); 4525779Sxy150489 } 4535779Sxy150489 454*11502SChenlu.Chen@Sun.COM if (igb_start(igb, B_TRUE) != IGB_SUCCESS) { 4555779Sxy150489 mutex_exit(&igb->gen_lock); 4565779Sxy150489 return (EIO); 4575779Sxy150489 } 4585779Sxy150489 45911367SJason.Xu@Sun.COM atomic_or_32(&igb->igb_state, IGB_STARTED); 4605779Sxy150489 4615779Sxy150489 mutex_exit(&igb->gen_lock); 4625779Sxy150489 4635779Sxy150489 /* 4645779Sxy150489 * Enable and start the watchdog timer 4655779Sxy150489 */ 4665779Sxy150489 igb_enable_watchdog_timer(igb); 4675779Sxy150489 4685779Sxy150489 return (0); 4695779Sxy150489 } 4705779Sxy150489 4715779Sxy150489 /* 4725779Sxy150489 * Stop the device and put it in a reset/quiesced state such 4735779Sxy150489 * that the interface can be unregistered. 4745779Sxy150489 */ 4755779Sxy150489 void 4765779Sxy150489 igb_m_stop(void *arg) 4775779Sxy150489 { 4785779Sxy150489 igb_t *igb = (igb_t *)arg; 4795779Sxy150489 4805779Sxy150489 mutex_enter(&igb->gen_lock); 4815779Sxy150489 4825779Sxy150489 if (igb->igb_state & IGB_SUSPENDED) { 4835779Sxy150489 mutex_exit(&igb->gen_lock); 4845779Sxy150489 return; 4855779Sxy150489 } 4865779Sxy150489 48711367SJason.Xu@Sun.COM atomic_and_32(&igb->igb_state, ~IGB_STARTED); 4885779Sxy150489 489*11502SChenlu.Chen@Sun.COM igb_stop(igb, B_TRUE); 4905779Sxy150489 4915779Sxy150489 mutex_exit(&igb->gen_lock); 4925779Sxy150489 4935779Sxy150489 /* 4945779Sxy150489 * Disable and stop the watchdog timer 4955779Sxy150489 */ 4965779Sxy150489 igb_disable_watchdog_timer(igb); 4975779Sxy150489 } 4985779Sxy150489 4995779Sxy150489 /* 5005779Sxy150489 * Set the promiscuity of the device. 5015779Sxy150489 */ 5025779Sxy150489 int 5035779Sxy150489 igb_m_promisc(void *arg, boolean_t on) 5045779Sxy150489 { 5055779Sxy150489 igb_t *igb = (igb_t *)arg; 5065779Sxy150489 uint32_t reg_val; 5075779Sxy150489 5085779Sxy150489 mutex_enter(&igb->gen_lock); 5095779Sxy150489 5105779Sxy150489 if (igb->igb_state & IGB_SUSPENDED) { 5115779Sxy150489 mutex_exit(&igb->gen_lock); 5125779Sxy150489 return (ECANCELED); 5135779Sxy150489 } 5145779Sxy150489 5155779Sxy150489 reg_val = E1000_READ_REG(&igb->hw, E1000_RCTL); 5165779Sxy150489 5175779Sxy150489 if (on) 5185779Sxy150489 reg_val |= (E1000_RCTL_UPE | E1000_RCTL_MPE); 5195779Sxy150489 else 5205779Sxy150489 reg_val &= (~(E1000_RCTL_UPE | E1000_RCTL_MPE)); 5215779Sxy150489 5225779Sxy150489 E1000_WRITE_REG(&igb->hw, E1000_RCTL, reg_val); 5235779Sxy150489 5245779Sxy150489 mutex_exit(&igb->gen_lock); 5255779Sxy150489 5266624Sgl147354 if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) { 5276624Sgl147354 ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); 5286624Sgl147354 return (EIO); 5296624Sgl147354 } 5306624Sgl147354 5315779Sxy150489 return (0); 5325779Sxy150489 } 5335779Sxy150489 5345779Sxy150489 /* 5355779Sxy150489 * Add/remove the addresses to/from the set of multicast 5365779Sxy150489 * addresses for which the device will receive packets. 5375779Sxy150489 */ 5385779Sxy150489 int 5395779Sxy150489 igb_m_multicst(void *arg, boolean_t add, const uint8_t *mcst_addr) 5405779Sxy150489 { 5415779Sxy150489 igb_t *igb = (igb_t *)arg; 5425779Sxy150489 int result; 5435779Sxy150489 5445779Sxy150489 mutex_enter(&igb->gen_lock); 5455779Sxy150489 5465779Sxy150489 if (igb->igb_state & IGB_SUSPENDED) { 5475779Sxy150489 mutex_exit(&igb->gen_lock); 5485779Sxy150489 return (ECANCELED); 5495779Sxy150489 } 5505779Sxy150489 5515779Sxy150489 result = (add) ? igb_multicst_add(igb, mcst_addr) 5525779Sxy150489 : igb_multicst_remove(igb, mcst_addr); 5535779Sxy150489 5545779Sxy150489 mutex_exit(&igb->gen_lock); 5555779Sxy150489 5565779Sxy150489 return (result); 5575779Sxy150489 } 5585779Sxy150489 5595779Sxy150489 /* 5605779Sxy150489 * Pass on M_IOCTL messages passed to the DLD, and support 5615779Sxy150489 * private IOCTLs for debugging and ndd. 5625779Sxy150489 */ 5635779Sxy150489 void 5645779Sxy150489 igb_m_ioctl(void *arg, queue_t *q, mblk_t *mp) 5655779Sxy150489 { 5665779Sxy150489 igb_t *igb = (igb_t *)arg; 5675779Sxy150489 struct iocblk *iocp; 5685779Sxy150489 enum ioc_reply status; 5695779Sxy150489 5705779Sxy150489 iocp = (struct iocblk *)(uintptr_t)mp->b_rptr; 5715779Sxy150489 iocp->ioc_error = 0; 5725779Sxy150489 573*11502SChenlu.Chen@Sun.COM mutex_enter(&igb->gen_lock); 574*11502SChenlu.Chen@Sun.COM if (igb->igb_state & IGB_SUSPENDED) { 575*11502SChenlu.Chen@Sun.COM mutex_exit(&igb->gen_lock); 576*11502SChenlu.Chen@Sun.COM miocnak(q, mp, 0, EINVAL); 577*11502SChenlu.Chen@Sun.COM return; 578*11502SChenlu.Chen@Sun.COM } 579*11502SChenlu.Chen@Sun.COM mutex_exit(&igb->gen_lock); 580*11502SChenlu.Chen@Sun.COM 5815779Sxy150489 switch (iocp->ioc_cmd) { 5825779Sxy150489 case LB_GET_INFO_SIZE: 5835779Sxy150489 case LB_GET_INFO: 5845779Sxy150489 case LB_GET_MODE: 5855779Sxy150489 case LB_SET_MODE: 5865779Sxy150489 status = igb_loopback_ioctl(igb, iocp, mp); 5875779Sxy150489 break; 5885779Sxy150489 5895779Sxy150489 default: 5905779Sxy150489 status = IOC_INVAL; 5915779Sxy150489 break; 5925779Sxy150489 } 5935779Sxy150489 5945779Sxy150489 /* 5955779Sxy150489 * Decide how to reply 5965779Sxy150489 */ 5975779Sxy150489 switch (status) { 5985779Sxy150489 default: 5995779Sxy150489 case IOC_INVAL: 6005779Sxy150489 /* 6015779Sxy150489 * Error, reply with a NAK and EINVAL or the specified error 6025779Sxy150489 */ 6035779Sxy150489 miocnak(q, mp, 0, iocp->ioc_error == 0 ? 6045779Sxy150489 EINVAL : iocp->ioc_error); 6055779Sxy150489 break; 6065779Sxy150489 6075779Sxy150489 case IOC_DONE: 6085779Sxy150489 /* 6095779Sxy150489 * OK, reply already sent 6105779Sxy150489 */ 6115779Sxy150489 break; 6125779Sxy150489 6135779Sxy150489 case IOC_ACK: 6145779Sxy150489 /* 6155779Sxy150489 * OK, reply with an ACK 6165779Sxy150489 */ 6175779Sxy150489 miocack(q, mp, 0, 0); 6185779Sxy150489 break; 6195779Sxy150489 6205779Sxy150489 case IOC_REPLY: 6215779Sxy150489 /* 6225779Sxy150489 * OK, send prepared reply as ACK or NAK 6235779Sxy150489 */ 6245779Sxy150489 mp->b_datap->db_type = iocp->ioc_error == 0 ? 6255779Sxy150489 M_IOCACK : M_IOCNAK; 6265779Sxy150489 qreply(q, mp); 6275779Sxy150489 break; 6285779Sxy150489 } 6295779Sxy150489 } 6305779Sxy150489 6315779Sxy150489 /* 6328275SEric Cheng * Add a MAC address to the target RX group. 6335779Sxy150489 */ 6348275SEric Cheng static int 6358275SEric Cheng igb_addmac(void *arg, const uint8_t *mac_addr) 6365779Sxy150489 { 6378275SEric Cheng igb_rx_group_t *rx_group = (igb_rx_group_t *)arg; 6388275SEric Cheng igb_t *igb = rx_group->igb; 6398275SEric Cheng struct e1000_hw *hw = &igb->hw; 6408275SEric Cheng int i, slot; 6415779Sxy150489 6425779Sxy150489 mutex_enter(&igb->gen_lock); 6435779Sxy150489 6445779Sxy150489 if (igb->igb_state & IGB_SUSPENDED) { 6455779Sxy150489 mutex_exit(&igb->gen_lock); 6465779Sxy150489 return (ECANCELED); 6475779Sxy150489 } 6485779Sxy150489 6495779Sxy150489 if (igb->unicst_avail == 0) { 6505779Sxy150489 /* no slots available */ 6515779Sxy150489 mutex_exit(&igb->gen_lock); 6525779Sxy150489 return (ENOSPC); 6535779Sxy150489 } 6545779Sxy150489 6555779Sxy150489 /* 6568275SEric Cheng * The slots from 0 to igb->num_rx_groups are reserved slots which 6578275SEric Cheng * are 1 to 1 mapped with group index directly. The other slots are 6588275SEric Cheng * shared between the all of groups. While adding a MAC address, 6598275SEric Cheng * it will try to set the reserved slots first, then the shared slots. 6605779Sxy150489 */ 6618275SEric Cheng slot = -1; 6628275SEric Cheng if (igb->unicst_addr[rx_group->index].mac.set == 1) { 6638275SEric Cheng /* 6648275SEric Cheng * The reserved slot for current group is used, find the free 6658275SEric Cheng * slots in the shared slots. 6668275SEric Cheng */ 6678275SEric Cheng for (i = igb->num_rx_groups; i < igb->unicst_total; i++) { 6688275SEric Cheng if (igb->unicst_addr[i].mac.set == 0) { 6698275SEric Cheng slot = i; 6708275SEric Cheng break; 6718275SEric Cheng } 6728275SEric Cheng } 6738275SEric Cheng } else 6748275SEric Cheng slot = rx_group->index; 6758275SEric Cheng 6768275SEric Cheng if (slot == -1) { 6778275SEric Cheng /* no slots available in the shared slots */ 6788275SEric Cheng mutex_exit(&igb->gen_lock); 6798275SEric Cheng return (ENOSPC); 6805779Sxy150489 } 6815779Sxy150489 6828275SEric Cheng /* Set VMDq according to the mode supported by hardware. */ 6838275SEric Cheng e1000_rar_set_vmdq(hw, mac_addr, slot, igb->vmdq_mode, rx_group->index); 6845779Sxy150489 6858275SEric Cheng bcopy(mac_addr, igb->unicst_addr[slot].mac.addr, ETHERADDRL); 6868275SEric Cheng igb->unicst_addr[slot].mac.group_index = rx_group->index; 6878275SEric Cheng igb->unicst_addr[slot].mac.set = 1; 6888275SEric Cheng igb->unicst_avail--; 6895779Sxy150489 6907072Sxy150489 mutex_exit(&igb->gen_lock); 6917072Sxy150489 6928275SEric Cheng return (0); 6935779Sxy150489 } 6945779Sxy150489 6955779Sxy150489 /* 6968275SEric Cheng * Remove a MAC address from the specified RX group. 6975779Sxy150489 */ 6988275SEric Cheng static int 6998275SEric Cheng igb_remmac(void *arg, const uint8_t *mac_addr) 7005779Sxy150489 { 7018275SEric Cheng igb_rx_group_t *rx_group = (igb_rx_group_t *)arg; 7028275SEric Cheng igb_t *igb = rx_group->igb; 7038275SEric Cheng struct e1000_hw *hw = &igb->hw; 7048275SEric Cheng int slot; 7055779Sxy150489 7065779Sxy150489 mutex_enter(&igb->gen_lock); 7075779Sxy150489 7085779Sxy150489 if (igb->igb_state & IGB_SUSPENDED) { 7095779Sxy150489 mutex_exit(&igb->gen_lock); 7105779Sxy150489 return (ECANCELED); 7115779Sxy150489 } 7125779Sxy150489 7138275SEric Cheng slot = igb_unicst_find(igb, mac_addr); 7148275SEric Cheng if (slot == -1) { 7155779Sxy150489 mutex_exit(&igb->gen_lock); 7165779Sxy150489 return (EINVAL); 7175779Sxy150489 } 7185779Sxy150489 7197072Sxy150489 if (igb->unicst_addr[slot].mac.set == 0) { 7207072Sxy150489 mutex_exit(&igb->gen_lock); 7217072Sxy150489 return (EINVAL); 7227072Sxy150489 } 7237072Sxy150489 7248275SEric Cheng /* Clear the MAC ddress in the slot */ 7258275SEric Cheng e1000_rar_clear(hw, slot); 7268275SEric Cheng igb->unicst_addr[slot].mac.set = 0; 7278275SEric Cheng igb->unicst_avail++; 7285779Sxy150489 7295779Sxy150489 mutex_exit(&igb->gen_lock); 7305779Sxy150489 7318275SEric Cheng return (0); 7328275SEric Cheng } 7338275SEric Cheng 7348275SEric Cheng /* 7358275SEric Cheng * Enable interrupt on the specificed rx ring. 7368275SEric Cheng */ 7378275SEric Cheng int 7388275SEric Cheng igb_rx_ring_intr_enable(mac_intr_handle_t intrh) 7398275SEric Cheng { 7408275SEric Cheng igb_rx_ring_t *rx_ring = (igb_rx_ring_t *)intrh; 7418275SEric Cheng igb_t *igb = rx_ring->igb; 7428275SEric Cheng struct e1000_hw *hw = &igb->hw; 7438275SEric Cheng uint32_t index = rx_ring->index; 7448275SEric Cheng 7458275SEric Cheng if (igb->intr_type == DDI_INTR_TYPE_MSIX) { 7468275SEric Cheng /* Interrupt enabling for MSI-X */ 7478275SEric Cheng igb->eims_mask |= (E1000_EICR_RX_QUEUE0 << index); 7488275SEric Cheng E1000_WRITE_REG(hw, E1000_EIMS, igb->eims_mask); 7498275SEric Cheng E1000_WRITE_REG(hw, E1000_EIAC, igb->eims_mask); 7508275SEric Cheng } else { 7518275SEric Cheng ASSERT(index == 0); 7528275SEric Cheng /* Interrupt enabling for MSI and legacy */ 7538275SEric Cheng igb->ims_mask |= E1000_IMS_RXT0; 7548275SEric Cheng E1000_WRITE_REG(hw, E1000_IMS, igb->ims_mask); 7558275SEric Cheng } 7568275SEric Cheng 7578275SEric Cheng E1000_WRITE_FLUSH(hw); 7588275SEric Cheng 7598275SEric Cheng return (0); 7608275SEric Cheng } 7618275SEric Cheng 7628275SEric Cheng /* 7638275SEric Cheng * Disable interrupt on the specificed rx ring. 7648275SEric Cheng */ 7658275SEric Cheng int 7668275SEric Cheng igb_rx_ring_intr_disable(mac_intr_handle_t intrh) 7678275SEric Cheng { 7688275SEric Cheng igb_rx_ring_t *rx_ring = (igb_rx_ring_t *)intrh; 7698275SEric Cheng igb_t *igb = rx_ring->igb; 7708275SEric Cheng struct e1000_hw *hw = &igb->hw; 7718275SEric Cheng uint32_t index = rx_ring->index; 7728275SEric Cheng 7738275SEric Cheng if (igb->intr_type == DDI_INTR_TYPE_MSIX) { 7748275SEric Cheng /* Interrupt disabling for MSI-X */ 7758275SEric Cheng igb->eims_mask &= ~(E1000_EICR_RX_QUEUE0 << index); 7768275SEric Cheng E1000_WRITE_REG(hw, E1000_EIMC, 7778275SEric Cheng (E1000_EICR_RX_QUEUE0 << index)); 7788275SEric Cheng E1000_WRITE_REG(hw, E1000_EIAC, igb->eims_mask); 7798275SEric Cheng } else { 7808275SEric Cheng ASSERT(index == 0); 7818275SEric Cheng /* Interrupt disabling for MSI and legacy */ 7828275SEric Cheng igb->ims_mask &= ~E1000_IMS_RXT0; 7838275SEric Cheng E1000_WRITE_REG(hw, E1000_IMC, E1000_IMS_RXT0); 7848275SEric Cheng } 7858275SEric Cheng 7868275SEric Cheng E1000_WRITE_FLUSH(hw); 7878275SEric Cheng 7888275SEric Cheng return (0); 7895779Sxy150489 } 7905779Sxy150489 7915779Sxy150489 /* 7928275SEric Cheng * Get the global ring index by a ring index within a group. 7935779Sxy150489 */ 7945779Sxy150489 int 7958275SEric Cheng igb_get_rx_ring_index(igb_t *igb, int gindex, int rindex) 7965779Sxy150489 { 7978275SEric Cheng igb_rx_ring_t *rx_ring; 7988275SEric Cheng int i; 7995779Sxy150489 8008275SEric Cheng for (i = 0; i < igb->num_rx_rings; i++) { 8018275SEric Cheng rx_ring = &igb->rx_rings[i]; 8028275SEric Cheng if (rx_ring->group_index == gindex) 8038275SEric Cheng rindex--; 8048275SEric Cheng if (rindex < 0) 8058275SEric Cheng return (i); 8065779Sxy150489 } 8075779Sxy150489 8088275SEric Cheng return (-1); 8098275SEric Cheng } 8105779Sxy150489 8118275SEric Cheng static int 8128275SEric Cheng igb_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num) 8138275SEric Cheng { 8148275SEric Cheng igb_rx_ring_t *rx_ring = (igb_rx_ring_t *)rh; 8155779Sxy150489 8168275SEric Cheng mutex_enter(&rx_ring->rx_lock); 8178275SEric Cheng rx_ring->ring_gen_num = mr_gen_num; 8188275SEric Cheng mutex_exit(&rx_ring->rx_lock); 8198275SEric Cheng return (0); 8205779Sxy150489 } 8215779Sxy150489 8225779Sxy150489 /* 8238275SEric Cheng * Callback funtion for MAC layer to register all rings. 8245779Sxy150489 */ 8258275SEric Cheng /* ARGSUSED */ 8268275SEric Cheng void 8278275SEric Cheng igb_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index, 8288275SEric Cheng const int index, mac_ring_info_t *infop, mac_ring_handle_t rh) 8295779Sxy150489 { 8305779Sxy150489 igb_t *igb = (igb_t *)arg; 8318275SEric Cheng mac_intr_t *mintr = &infop->mri_intr; 8328275SEric Cheng 8338275SEric Cheng switch (rtype) { 8348275SEric Cheng case MAC_RING_TYPE_RX: { 8358275SEric Cheng igb_rx_ring_t *rx_ring; 8368275SEric Cheng int global_index; 8375779Sxy150489 8388275SEric Cheng /* 8398275SEric Cheng * 'index' is the ring index within the group. 8408275SEric Cheng * We need the global ring index by searching in group. 8418275SEric Cheng */ 8428275SEric Cheng global_index = igb_get_rx_ring_index(igb, rg_index, index); 8438275SEric Cheng 8448275SEric Cheng ASSERT(global_index >= 0); 8455779Sxy150489 8468275SEric Cheng rx_ring = &igb->rx_rings[global_index]; 8478275SEric Cheng rx_ring->ring_handle = rh; 8488275SEric Cheng 8498275SEric Cheng infop->mri_driver = (mac_ring_driver_t)rx_ring; 8508275SEric Cheng infop->mri_start = igb_ring_start; 8518275SEric Cheng infop->mri_stop = NULL; 8528275SEric Cheng infop->mri_poll = (mac_ring_poll_t)igb_rx_ring_poll; 8538275SEric Cheng 8548275SEric Cheng mintr->mi_handle = (mac_intr_handle_t)rx_ring; 8558275SEric Cheng mintr->mi_enable = igb_rx_ring_intr_enable; 8568275SEric Cheng mintr->mi_disable = igb_rx_ring_intr_disable; 8578275SEric Cheng 8588275SEric Cheng break; 8595779Sxy150489 } 8608275SEric Cheng case MAC_RING_TYPE_TX: { 8618275SEric Cheng ASSERT(index < igb->num_tx_rings); 8625779Sxy150489 8638275SEric Cheng igb_tx_ring_t *tx_ring = &igb->tx_rings[index]; 8648275SEric Cheng tx_ring->ring_handle = rh; 8655779Sxy150489 8668275SEric Cheng infop->mri_driver = (mac_ring_driver_t)tx_ring; 8678275SEric Cheng infop->mri_start = NULL; 8688275SEric Cheng infop->mri_stop = NULL; 8698275SEric Cheng infop->mri_tx = igb_tx_ring_send; 8708275SEric Cheng 8718275SEric Cheng break; 8725779Sxy150489 } 8738275SEric Cheng default: 8748275SEric Cheng break; 8758275SEric Cheng } 8768275SEric Cheng } 8778275SEric Cheng 8788275SEric Cheng void 8798275SEric Cheng igb_fill_group(void *arg, mac_ring_type_t rtype, const int index, 8808275SEric Cheng mac_group_info_t *infop, mac_group_handle_t gh) 8818275SEric Cheng { 8828275SEric Cheng igb_t *igb = (igb_t *)arg; 8835779Sxy150489 8848275SEric Cheng switch (rtype) { 8858275SEric Cheng case MAC_RING_TYPE_RX: { 8868275SEric Cheng igb_rx_group_t *rx_group; 8878275SEric Cheng 8888275SEric Cheng ASSERT((index >= 0) && (index < igb->num_rx_groups)); 8898275SEric Cheng 8908275SEric Cheng rx_group = &igb->rx_groups[index]; 8918275SEric Cheng rx_group->group_handle = gh; 8928275SEric Cheng 8938275SEric Cheng infop->mgi_driver = (mac_group_driver_t)rx_group; 8948275SEric Cheng infop->mgi_start = NULL; 8958275SEric Cheng infop->mgi_stop = NULL; 8968275SEric Cheng infop->mgi_addmac = igb_addmac; 8978275SEric Cheng infop->mgi_remmac = igb_remmac; 8988275SEric Cheng infop->mgi_count = (igb->num_rx_rings / igb->num_rx_groups); 8998275SEric Cheng 9008275SEric Cheng break; 9015779Sxy150489 } 9028275SEric Cheng case MAC_RING_TYPE_TX: 9038275SEric Cheng break; 9048275SEric Cheng default: 9058275SEric Cheng break; 9068275SEric Cheng } 9075779Sxy150489 } 9085779Sxy150489 9095779Sxy150489 /* 9105779Sxy150489 * Obtain the MAC's capabilities and associated data from 9115779Sxy150489 * the driver. 9125779Sxy150489 */ 9135779Sxy150489 boolean_t 9145779Sxy150489 igb_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 9155779Sxy150489 { 9165779Sxy150489 igb_t *igb = (igb_t *)arg; 9175779Sxy150489 9185779Sxy150489 switch (cap) { 9195779Sxy150489 case MAC_CAPAB_HCKSUM: { 9205779Sxy150489 uint32_t *tx_hcksum_flags = cap_data; 9215779Sxy150489 9225779Sxy150489 /* 9235779Sxy150489 * We advertise our capabilities only if tx hcksum offload is 9245779Sxy150489 * enabled. On receive, the stack will accept checksummed 9255779Sxy150489 * packets anyway, even if we haven't said we can deliver 9265779Sxy150489 * them. 9275779Sxy150489 */ 9285779Sxy150489 if (!igb->tx_hcksum_enable) 9295779Sxy150489 return (B_FALSE); 9305779Sxy150489 9315779Sxy150489 *tx_hcksum_flags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM; 9325779Sxy150489 break; 9335779Sxy150489 } 9349188SPaul.Guo@Sun.COM case MAC_CAPAB_LSO: { 9359188SPaul.Guo@Sun.COM mac_capab_lso_t *cap_lso = cap_data; 9369188SPaul.Guo@Sun.COM 9379188SPaul.Guo@Sun.COM if (igb->lso_enable) { 9389188SPaul.Guo@Sun.COM cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 9399188SPaul.Guo@Sun.COM cap_lso->lso_basic_tcp_ipv4.lso_max = IGB_LSO_MAXLEN; 9409188SPaul.Guo@Sun.COM break; 9419188SPaul.Guo@Sun.COM } else { 9429188SPaul.Guo@Sun.COM return (B_FALSE); 9439188SPaul.Guo@Sun.COM } 9449188SPaul.Guo@Sun.COM } 9458275SEric Cheng case MAC_CAPAB_RINGS: { 9468275SEric Cheng mac_capab_rings_t *cap_rings = cap_data; 9478275SEric Cheng 9488275SEric Cheng switch (cap_rings->mr_type) { 9498275SEric Cheng case MAC_RING_TYPE_RX: 9508275SEric Cheng cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 9518275SEric Cheng cap_rings->mr_rnum = igb->num_rx_rings; 9528275SEric Cheng cap_rings->mr_gnum = igb->num_rx_groups; 9538275SEric Cheng cap_rings->mr_rget = igb_fill_ring; 9548275SEric Cheng cap_rings->mr_gget = igb_fill_group; 9558275SEric Cheng cap_rings->mr_gaddring = NULL; 9568275SEric Cheng cap_rings->mr_gremring = NULL; 9575779Sxy150489 9588275SEric Cheng break; 9598275SEric Cheng case MAC_RING_TYPE_TX: 9608275SEric Cheng cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 9618275SEric Cheng cap_rings->mr_rnum = igb->num_tx_rings; 9628275SEric Cheng cap_rings->mr_gnum = 0; 9638275SEric Cheng cap_rings->mr_rget = igb_fill_ring; 9648275SEric Cheng cap_rings->mr_gget = NULL; 9658275SEric Cheng 9668275SEric Cheng break; 9678275SEric Cheng default: 9688275SEric Cheng break; 9698275SEric Cheng } 9705779Sxy150489 break; 9715779Sxy150489 } 9728275SEric Cheng 9735779Sxy150489 default: 9745779Sxy150489 return (B_FALSE); 9755779Sxy150489 } 9765779Sxy150489 return (B_TRUE); 9775779Sxy150489 } 978*11502SChenlu.Chen@Sun.COM 979*11502SChenlu.Chen@Sun.COM int 980*11502SChenlu.Chen@Sun.COM igb_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 981*11502SChenlu.Chen@Sun.COM uint_t pr_valsize, const void *pr_val) 982*11502SChenlu.Chen@Sun.COM { 983*11502SChenlu.Chen@Sun.COM igb_t *igb = (igb_t *)arg; 984*11502SChenlu.Chen@Sun.COM struct e1000_hw *hw = &igb->hw; 985*11502SChenlu.Chen@Sun.COM int err = 0; 986*11502SChenlu.Chen@Sun.COM uint32_t flow_control; 987*11502SChenlu.Chen@Sun.COM uint32_t cur_mtu, new_mtu; 988*11502SChenlu.Chen@Sun.COM uint32_t rx_size; 989*11502SChenlu.Chen@Sun.COM uint32_t tx_size; 990*11502SChenlu.Chen@Sun.COM 991*11502SChenlu.Chen@Sun.COM mutex_enter(&igb->gen_lock); 992*11502SChenlu.Chen@Sun.COM if (igb->igb_state & IGB_SUSPENDED) { 993*11502SChenlu.Chen@Sun.COM mutex_exit(&igb->gen_lock); 994*11502SChenlu.Chen@Sun.COM return (ECANCELED); 995*11502SChenlu.Chen@Sun.COM } 996*11502SChenlu.Chen@Sun.COM 997*11502SChenlu.Chen@Sun.COM if (igb->loopback_mode != IGB_LB_NONE && igb_param_locked(pr_num)) { 998*11502SChenlu.Chen@Sun.COM /* 999*11502SChenlu.Chen@Sun.COM * All en_* parameters are locked (read-only) 1000*11502SChenlu.Chen@Sun.COM * while the device is in any sort of loopback mode. 1001*11502SChenlu.Chen@Sun.COM */ 1002*11502SChenlu.Chen@Sun.COM mutex_exit(&igb->gen_lock); 1003*11502SChenlu.Chen@Sun.COM return (EBUSY); 1004*11502SChenlu.Chen@Sun.COM } 1005*11502SChenlu.Chen@Sun.COM 1006*11502SChenlu.Chen@Sun.COM switch (pr_num) { 1007*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_1000FDX_CAP: 1008*11502SChenlu.Chen@Sun.COM /* read/write on copper, read-only on serdes */ 1009*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) { 1010*11502SChenlu.Chen@Sun.COM err = ENOTSUP; 1011*11502SChenlu.Chen@Sun.COM break; 1012*11502SChenlu.Chen@Sun.COM } 1013*11502SChenlu.Chen@Sun.COM igb->param_en_1000fdx_cap = *(uint8_t *)pr_val; 1014*11502SChenlu.Chen@Sun.COM igb->param_adv_1000fdx_cap = *(uint8_t *)pr_val; 1015*11502SChenlu.Chen@Sun.COM goto setup_link; 1016*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_100FDX_CAP: 1017*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) { 1018*11502SChenlu.Chen@Sun.COM err = ENOTSUP; 1019*11502SChenlu.Chen@Sun.COM break; 1020*11502SChenlu.Chen@Sun.COM } 1021*11502SChenlu.Chen@Sun.COM igb->param_en_100fdx_cap = *(uint8_t *)pr_val; 1022*11502SChenlu.Chen@Sun.COM igb->param_adv_100fdx_cap = *(uint8_t *)pr_val; 1023*11502SChenlu.Chen@Sun.COM goto setup_link; 1024*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_100HDX_CAP: 1025*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) { 1026*11502SChenlu.Chen@Sun.COM err = ENOTSUP; 1027*11502SChenlu.Chen@Sun.COM break; 1028*11502SChenlu.Chen@Sun.COM } 1029*11502SChenlu.Chen@Sun.COM igb->param_en_100hdx_cap = *(uint8_t *)pr_val; 1030*11502SChenlu.Chen@Sun.COM igb->param_adv_100hdx_cap = *(uint8_t *)pr_val; 1031*11502SChenlu.Chen@Sun.COM goto setup_link; 1032*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_10FDX_CAP: 1033*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) { 1034*11502SChenlu.Chen@Sun.COM err = ENOTSUP; 1035*11502SChenlu.Chen@Sun.COM break; 1036*11502SChenlu.Chen@Sun.COM } 1037*11502SChenlu.Chen@Sun.COM igb->param_en_10fdx_cap = *(uint8_t *)pr_val; 1038*11502SChenlu.Chen@Sun.COM igb->param_adv_10fdx_cap = *(uint8_t *)pr_val; 1039*11502SChenlu.Chen@Sun.COM goto setup_link; 1040*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_10HDX_CAP: 1041*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) { 1042*11502SChenlu.Chen@Sun.COM err = ENOTSUP; 1043*11502SChenlu.Chen@Sun.COM break; 1044*11502SChenlu.Chen@Sun.COM } 1045*11502SChenlu.Chen@Sun.COM igb->param_en_10hdx_cap = *(uint8_t *)pr_val; 1046*11502SChenlu.Chen@Sun.COM igb->param_adv_10hdx_cap = *(uint8_t *)pr_val; 1047*11502SChenlu.Chen@Sun.COM goto setup_link; 1048*11502SChenlu.Chen@Sun.COM case MAC_PROP_AUTONEG: 1049*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) { 1050*11502SChenlu.Chen@Sun.COM err = ENOTSUP; 1051*11502SChenlu.Chen@Sun.COM break; 1052*11502SChenlu.Chen@Sun.COM } 1053*11502SChenlu.Chen@Sun.COM igb->param_adv_autoneg_cap = *(uint8_t *)pr_val; 1054*11502SChenlu.Chen@Sun.COM goto setup_link; 1055*11502SChenlu.Chen@Sun.COM case MAC_PROP_FLOWCTRL: 1056*11502SChenlu.Chen@Sun.COM bcopy(pr_val, &flow_control, sizeof (flow_control)); 1057*11502SChenlu.Chen@Sun.COM 1058*11502SChenlu.Chen@Sun.COM switch (flow_control) { 1059*11502SChenlu.Chen@Sun.COM default: 1060*11502SChenlu.Chen@Sun.COM err = EINVAL; 1061*11502SChenlu.Chen@Sun.COM break; 1062*11502SChenlu.Chen@Sun.COM case LINK_FLOWCTRL_NONE: 1063*11502SChenlu.Chen@Sun.COM hw->fc.requested_mode = e1000_fc_none; 1064*11502SChenlu.Chen@Sun.COM break; 1065*11502SChenlu.Chen@Sun.COM case LINK_FLOWCTRL_RX: 1066*11502SChenlu.Chen@Sun.COM hw->fc.requested_mode = e1000_fc_rx_pause; 1067*11502SChenlu.Chen@Sun.COM break; 1068*11502SChenlu.Chen@Sun.COM case LINK_FLOWCTRL_TX: 1069*11502SChenlu.Chen@Sun.COM hw->fc.requested_mode = e1000_fc_tx_pause; 1070*11502SChenlu.Chen@Sun.COM break; 1071*11502SChenlu.Chen@Sun.COM case LINK_FLOWCTRL_BI: 1072*11502SChenlu.Chen@Sun.COM hw->fc.requested_mode = e1000_fc_full; 1073*11502SChenlu.Chen@Sun.COM break; 1074*11502SChenlu.Chen@Sun.COM } 1075*11502SChenlu.Chen@Sun.COM setup_link: 1076*11502SChenlu.Chen@Sun.COM if (err == 0) { 1077*11502SChenlu.Chen@Sun.COM if (igb_setup_link(igb, B_TRUE) != IGB_SUCCESS) 1078*11502SChenlu.Chen@Sun.COM err = EINVAL; 1079*11502SChenlu.Chen@Sun.COM } 1080*11502SChenlu.Chen@Sun.COM break; 1081*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_1000FDX_CAP: 1082*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_1000HDX_CAP: 1083*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_100T4_CAP: 1084*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_100FDX_CAP: 1085*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_100HDX_CAP: 1086*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_10FDX_CAP: 1087*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_10HDX_CAP: 1088*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_1000HDX_CAP: 1089*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_100T4_CAP: 1090*11502SChenlu.Chen@Sun.COM case MAC_PROP_STATUS: 1091*11502SChenlu.Chen@Sun.COM case MAC_PROP_SPEED: 1092*11502SChenlu.Chen@Sun.COM case MAC_PROP_DUPLEX: 1093*11502SChenlu.Chen@Sun.COM err = ENOTSUP; /* read-only prop. Can't set this. */ 1094*11502SChenlu.Chen@Sun.COM break; 1095*11502SChenlu.Chen@Sun.COM case MAC_PROP_MTU: 1096*11502SChenlu.Chen@Sun.COM /* adapter must be stopped for an MTU change */ 1097*11502SChenlu.Chen@Sun.COM if (igb->igb_state & IGB_STARTED) { 1098*11502SChenlu.Chen@Sun.COM err = EBUSY; 1099*11502SChenlu.Chen@Sun.COM break; 1100*11502SChenlu.Chen@Sun.COM } 1101*11502SChenlu.Chen@Sun.COM 1102*11502SChenlu.Chen@Sun.COM cur_mtu = igb->default_mtu; 1103*11502SChenlu.Chen@Sun.COM bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 1104*11502SChenlu.Chen@Sun.COM if (new_mtu == cur_mtu) { 1105*11502SChenlu.Chen@Sun.COM err = 0; 1106*11502SChenlu.Chen@Sun.COM break; 1107*11502SChenlu.Chen@Sun.COM } 1108*11502SChenlu.Chen@Sun.COM 1109*11502SChenlu.Chen@Sun.COM if (new_mtu < MIN_MTU || new_mtu > MAX_MTU) { 1110*11502SChenlu.Chen@Sun.COM err = EINVAL; 1111*11502SChenlu.Chen@Sun.COM break; 1112*11502SChenlu.Chen@Sun.COM } 1113*11502SChenlu.Chen@Sun.COM 1114*11502SChenlu.Chen@Sun.COM err = mac_maxsdu_update(igb->mac_hdl, new_mtu); 1115*11502SChenlu.Chen@Sun.COM if (err == 0) { 1116*11502SChenlu.Chen@Sun.COM igb->default_mtu = new_mtu; 1117*11502SChenlu.Chen@Sun.COM igb->max_frame_size = igb->default_mtu + 1118*11502SChenlu.Chen@Sun.COM sizeof (struct ether_vlan_header) + ETHERFCSL; 1119*11502SChenlu.Chen@Sun.COM 1120*11502SChenlu.Chen@Sun.COM /* 1121*11502SChenlu.Chen@Sun.COM * Set rx buffer size 1122*11502SChenlu.Chen@Sun.COM */ 1123*11502SChenlu.Chen@Sun.COM rx_size = igb->max_frame_size + IPHDR_ALIGN_ROOM; 1124*11502SChenlu.Chen@Sun.COM igb->rx_buf_size = ((rx_size >> 10) + ((rx_size & 1125*11502SChenlu.Chen@Sun.COM (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10; 1126*11502SChenlu.Chen@Sun.COM 1127*11502SChenlu.Chen@Sun.COM /* 1128*11502SChenlu.Chen@Sun.COM * Set tx buffer size 1129*11502SChenlu.Chen@Sun.COM */ 1130*11502SChenlu.Chen@Sun.COM tx_size = igb->max_frame_size; 1131*11502SChenlu.Chen@Sun.COM igb->tx_buf_size = ((tx_size >> 10) + ((tx_size & 1132*11502SChenlu.Chen@Sun.COM (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10; 1133*11502SChenlu.Chen@Sun.COM } 1134*11502SChenlu.Chen@Sun.COM break; 1135*11502SChenlu.Chen@Sun.COM case MAC_PROP_PRIVATE: 1136*11502SChenlu.Chen@Sun.COM err = igb_set_priv_prop(igb, pr_name, pr_valsize, pr_val); 1137*11502SChenlu.Chen@Sun.COM break; 1138*11502SChenlu.Chen@Sun.COM default: 1139*11502SChenlu.Chen@Sun.COM err = EINVAL; 1140*11502SChenlu.Chen@Sun.COM break; 1141*11502SChenlu.Chen@Sun.COM } 1142*11502SChenlu.Chen@Sun.COM 1143*11502SChenlu.Chen@Sun.COM mutex_exit(&igb->gen_lock); 1144*11502SChenlu.Chen@Sun.COM 1145*11502SChenlu.Chen@Sun.COM if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) { 1146*11502SChenlu.Chen@Sun.COM ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); 1147*11502SChenlu.Chen@Sun.COM return (EIO); 1148*11502SChenlu.Chen@Sun.COM } 1149*11502SChenlu.Chen@Sun.COM 1150*11502SChenlu.Chen@Sun.COM return (err); 1151*11502SChenlu.Chen@Sun.COM } 1152*11502SChenlu.Chen@Sun.COM 1153*11502SChenlu.Chen@Sun.COM int 1154*11502SChenlu.Chen@Sun.COM igb_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 1155*11502SChenlu.Chen@Sun.COM uint_t pr_flags, uint_t pr_valsize, void *pr_val, uint_t *perm) 1156*11502SChenlu.Chen@Sun.COM { 1157*11502SChenlu.Chen@Sun.COM igb_t *igb = (igb_t *)arg; 1158*11502SChenlu.Chen@Sun.COM struct e1000_hw *hw = &igb->hw; 1159*11502SChenlu.Chen@Sun.COM int err = 0; 1160*11502SChenlu.Chen@Sun.COM uint32_t flow_control; 1161*11502SChenlu.Chen@Sun.COM uint64_t tmp = 0; 1162*11502SChenlu.Chen@Sun.COM mac_propval_range_t range; 1163*11502SChenlu.Chen@Sun.COM 1164*11502SChenlu.Chen@Sun.COM if (pr_valsize == 0) 1165*11502SChenlu.Chen@Sun.COM return (EINVAL); 1166*11502SChenlu.Chen@Sun.COM 1167*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_RW; 1168*11502SChenlu.Chen@Sun.COM 1169*11502SChenlu.Chen@Sun.COM bzero(pr_val, pr_valsize); 1170*11502SChenlu.Chen@Sun.COM if ((pr_flags & MAC_PROP_DEFAULT) && (pr_num != MAC_PROP_PRIVATE)) 1171*11502SChenlu.Chen@Sun.COM return (igb_get_def_val(igb, pr_num, pr_valsize, pr_val)); 1172*11502SChenlu.Chen@Sun.COM 1173*11502SChenlu.Chen@Sun.COM switch (pr_num) { 1174*11502SChenlu.Chen@Sun.COM case MAC_PROP_DUPLEX: 1175*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1176*11502SChenlu.Chen@Sun.COM if (pr_valsize >= sizeof (link_duplex_t)) { 1177*11502SChenlu.Chen@Sun.COM bcopy(&igb->link_duplex, pr_val, 1178*11502SChenlu.Chen@Sun.COM sizeof (link_duplex_t)); 1179*11502SChenlu.Chen@Sun.COM } else 1180*11502SChenlu.Chen@Sun.COM err = EINVAL; 1181*11502SChenlu.Chen@Sun.COM break; 1182*11502SChenlu.Chen@Sun.COM case MAC_PROP_SPEED: 1183*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1184*11502SChenlu.Chen@Sun.COM if (pr_valsize >= sizeof (uint64_t)) { 1185*11502SChenlu.Chen@Sun.COM tmp = igb->link_speed * 1000000ull; 1186*11502SChenlu.Chen@Sun.COM bcopy(&tmp, pr_val, sizeof (tmp)); 1187*11502SChenlu.Chen@Sun.COM } else 1188*11502SChenlu.Chen@Sun.COM err = EINVAL; 1189*11502SChenlu.Chen@Sun.COM break; 1190*11502SChenlu.Chen@Sun.COM case MAC_PROP_AUTONEG: 1191*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) 1192*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1193*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = igb->param_adv_autoneg_cap; 1194*11502SChenlu.Chen@Sun.COM break; 1195*11502SChenlu.Chen@Sun.COM case MAC_PROP_FLOWCTRL: 1196*11502SChenlu.Chen@Sun.COM if (pr_valsize >= sizeof (uint32_t)) { 1197*11502SChenlu.Chen@Sun.COM switch (hw->fc.requested_mode) { 1198*11502SChenlu.Chen@Sun.COM case e1000_fc_none: 1199*11502SChenlu.Chen@Sun.COM flow_control = LINK_FLOWCTRL_NONE; 1200*11502SChenlu.Chen@Sun.COM break; 1201*11502SChenlu.Chen@Sun.COM case e1000_fc_rx_pause: 1202*11502SChenlu.Chen@Sun.COM flow_control = LINK_FLOWCTRL_RX; 1203*11502SChenlu.Chen@Sun.COM break; 1204*11502SChenlu.Chen@Sun.COM case e1000_fc_tx_pause: 1205*11502SChenlu.Chen@Sun.COM flow_control = LINK_FLOWCTRL_TX; 1206*11502SChenlu.Chen@Sun.COM break; 1207*11502SChenlu.Chen@Sun.COM case e1000_fc_full: 1208*11502SChenlu.Chen@Sun.COM flow_control = LINK_FLOWCTRL_BI; 1209*11502SChenlu.Chen@Sun.COM break; 1210*11502SChenlu.Chen@Sun.COM } 1211*11502SChenlu.Chen@Sun.COM bcopy(&flow_control, pr_val, sizeof (flow_control)); 1212*11502SChenlu.Chen@Sun.COM } else 1213*11502SChenlu.Chen@Sun.COM err = EINVAL; 1214*11502SChenlu.Chen@Sun.COM break; 1215*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_1000FDX_CAP: 1216*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1217*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = igb->param_adv_1000fdx_cap; 1218*11502SChenlu.Chen@Sun.COM break; 1219*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_1000FDX_CAP: 1220*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) 1221*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1222*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = igb->param_en_1000fdx_cap; 1223*11502SChenlu.Chen@Sun.COM break; 1224*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_1000HDX_CAP: 1225*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1226*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = igb->param_adv_1000hdx_cap; 1227*11502SChenlu.Chen@Sun.COM break; 1228*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_1000HDX_CAP: 1229*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1230*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = igb->param_en_1000hdx_cap; 1231*11502SChenlu.Chen@Sun.COM break; 1232*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_100T4_CAP: 1233*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1234*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = igb->param_adv_100t4_cap; 1235*11502SChenlu.Chen@Sun.COM break; 1236*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_100T4_CAP: 1237*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1238*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = igb->param_en_100t4_cap; 1239*11502SChenlu.Chen@Sun.COM break; 1240*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_100FDX_CAP: 1241*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1242*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = igb->param_adv_100fdx_cap; 1243*11502SChenlu.Chen@Sun.COM break; 1244*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_100FDX_CAP: 1245*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) 1246*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1247*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = igb->param_en_100fdx_cap; 1248*11502SChenlu.Chen@Sun.COM break; 1249*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_100HDX_CAP: 1250*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1251*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = igb->param_adv_100hdx_cap; 1252*11502SChenlu.Chen@Sun.COM break; 1253*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_100HDX_CAP: 1254*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) 1255*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1256*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = igb->param_en_100hdx_cap; 1257*11502SChenlu.Chen@Sun.COM break; 1258*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_10FDX_CAP: 1259*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1260*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = igb->param_adv_10fdx_cap; 1261*11502SChenlu.Chen@Sun.COM break; 1262*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_10FDX_CAP: 1263*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) 1264*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1265*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = igb->param_en_10fdx_cap; 1266*11502SChenlu.Chen@Sun.COM break; 1267*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_10HDX_CAP: 1268*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1269*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = igb->param_adv_10hdx_cap; 1270*11502SChenlu.Chen@Sun.COM break; 1271*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_10HDX_CAP: 1272*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) 1273*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1274*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = igb->param_en_10hdx_cap; 1275*11502SChenlu.Chen@Sun.COM break; 1276*11502SChenlu.Chen@Sun.COM case MAC_PROP_PRIVATE: 1277*11502SChenlu.Chen@Sun.COM err = igb_get_priv_prop(igb, pr_name, 1278*11502SChenlu.Chen@Sun.COM pr_flags, pr_valsize, pr_val, perm); 1279*11502SChenlu.Chen@Sun.COM break; 1280*11502SChenlu.Chen@Sun.COM case MAC_PROP_MTU: 1281*11502SChenlu.Chen@Sun.COM if (!(pr_flags & MAC_PROP_POSSIBLE)) 1282*11502SChenlu.Chen@Sun.COM return (ENOTSUP); 1283*11502SChenlu.Chen@Sun.COM if (pr_valsize < sizeof (mac_propval_range_t)) 1284*11502SChenlu.Chen@Sun.COM return (EINVAL); 1285*11502SChenlu.Chen@Sun.COM range.mpr_count = 1; 1286*11502SChenlu.Chen@Sun.COM range.mpr_type = MAC_PROPVAL_UINT32; 1287*11502SChenlu.Chen@Sun.COM range.range_uint32[0].mpur_min = MIN_MTU; 1288*11502SChenlu.Chen@Sun.COM range.range_uint32[0].mpur_max = MAX_MTU; 1289*11502SChenlu.Chen@Sun.COM bcopy(&range, pr_val, sizeof (range)); 1290*11502SChenlu.Chen@Sun.COM break; 1291*11502SChenlu.Chen@Sun.COM default: 1292*11502SChenlu.Chen@Sun.COM err = EINVAL; 1293*11502SChenlu.Chen@Sun.COM break; 1294*11502SChenlu.Chen@Sun.COM } 1295*11502SChenlu.Chen@Sun.COM return (err); 1296*11502SChenlu.Chen@Sun.COM } 1297*11502SChenlu.Chen@Sun.COM 1298*11502SChenlu.Chen@Sun.COM int 1299*11502SChenlu.Chen@Sun.COM igb_get_def_val(igb_t *igb, mac_prop_id_t pr_num, 1300*11502SChenlu.Chen@Sun.COM uint_t pr_valsize, void *pr_val) 1301*11502SChenlu.Chen@Sun.COM { 1302*11502SChenlu.Chen@Sun.COM uint32_t flow_control; 1303*11502SChenlu.Chen@Sun.COM struct e1000_hw *hw = &igb->hw; 1304*11502SChenlu.Chen@Sun.COM uint16_t phy_status; 1305*11502SChenlu.Chen@Sun.COM uint16_t phy_ext_status; 1306*11502SChenlu.Chen@Sun.COM int err = 0; 1307*11502SChenlu.Chen@Sun.COM 1308*11502SChenlu.Chen@Sun.COM ASSERT(pr_valsize > 0); 1309*11502SChenlu.Chen@Sun.COM switch (pr_num) { 1310*11502SChenlu.Chen@Sun.COM case MAC_PROP_AUTONEG: 1311*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) { 1312*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = 0; 1313*11502SChenlu.Chen@Sun.COM } else { 1314*11502SChenlu.Chen@Sun.COM (void) e1000_read_phy_reg(hw, PHY_STATUS, &phy_status); 1315*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = 1316*11502SChenlu.Chen@Sun.COM (phy_status & MII_SR_AUTONEG_CAPS) ? 1 : 0; 1317*11502SChenlu.Chen@Sun.COM } 1318*11502SChenlu.Chen@Sun.COM break; 1319*11502SChenlu.Chen@Sun.COM case MAC_PROP_FLOWCTRL: 1320*11502SChenlu.Chen@Sun.COM if (pr_valsize < sizeof (uint32_t)) 1321*11502SChenlu.Chen@Sun.COM return (EINVAL); 1322*11502SChenlu.Chen@Sun.COM flow_control = LINK_FLOWCTRL_BI; 1323*11502SChenlu.Chen@Sun.COM bcopy(&flow_control, pr_val, sizeof (flow_control)); 1324*11502SChenlu.Chen@Sun.COM break; 1325*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_1000FDX_CAP: 1326*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_1000FDX_CAP: 1327*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) { 1328*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = 1; 1329*11502SChenlu.Chen@Sun.COM } else { 1330*11502SChenlu.Chen@Sun.COM (void) e1000_read_phy_reg(hw, 1331*11502SChenlu.Chen@Sun.COM PHY_EXT_STATUS, &phy_ext_status); 1332*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = 1333*11502SChenlu.Chen@Sun.COM ((phy_ext_status & IEEE_ESR_1000T_FD_CAPS) || 1334*11502SChenlu.Chen@Sun.COM (phy_ext_status & IEEE_ESR_1000X_FD_CAPS)) ? 1 : 0; 1335*11502SChenlu.Chen@Sun.COM } 1336*11502SChenlu.Chen@Sun.COM break; 1337*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_1000HDX_CAP: 1338*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_1000HDX_CAP: 1339*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_100T4_CAP: 1340*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_100T4_CAP: 1341*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = 0; 1342*11502SChenlu.Chen@Sun.COM break; 1343*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_100FDX_CAP: 1344*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_100FDX_CAP: 1345*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) { 1346*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = 0; 1347*11502SChenlu.Chen@Sun.COM } else { 1348*11502SChenlu.Chen@Sun.COM (void) e1000_read_phy_reg(hw, PHY_STATUS, &phy_status); 1349*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = 1350*11502SChenlu.Chen@Sun.COM ((phy_status & MII_SR_100X_FD_CAPS) || 1351*11502SChenlu.Chen@Sun.COM (phy_status & MII_SR_100T2_FD_CAPS)) ? 1 : 0; 1352*11502SChenlu.Chen@Sun.COM } 1353*11502SChenlu.Chen@Sun.COM break; 1354*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_100HDX_CAP: 1355*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_100HDX_CAP: 1356*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) { 1357*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = 0; 1358*11502SChenlu.Chen@Sun.COM } else { 1359*11502SChenlu.Chen@Sun.COM (void) e1000_read_phy_reg(hw, PHY_STATUS, &phy_status); 1360*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = 1361*11502SChenlu.Chen@Sun.COM ((phy_status & MII_SR_100X_HD_CAPS) || 1362*11502SChenlu.Chen@Sun.COM (phy_status & MII_SR_100T2_HD_CAPS)) ? 1 : 0; 1363*11502SChenlu.Chen@Sun.COM } 1364*11502SChenlu.Chen@Sun.COM break; 1365*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_10FDX_CAP: 1366*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_10FDX_CAP: 1367*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) { 1368*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = 0; 1369*11502SChenlu.Chen@Sun.COM } else { 1370*11502SChenlu.Chen@Sun.COM (void) e1000_read_phy_reg(hw, PHY_STATUS, &phy_status); 1371*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = 1372*11502SChenlu.Chen@Sun.COM (phy_status & MII_SR_10T_FD_CAPS) ? 1 : 0; 1373*11502SChenlu.Chen@Sun.COM } 1374*11502SChenlu.Chen@Sun.COM break; 1375*11502SChenlu.Chen@Sun.COM case MAC_PROP_ADV_10HDX_CAP: 1376*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_10HDX_CAP: 1377*11502SChenlu.Chen@Sun.COM if (hw->phy.media_type != e1000_media_type_copper) { 1378*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = 0; 1379*11502SChenlu.Chen@Sun.COM } else { 1380*11502SChenlu.Chen@Sun.COM (void) e1000_read_phy_reg(hw, PHY_STATUS, &phy_status); 1381*11502SChenlu.Chen@Sun.COM *(uint8_t *)pr_val = 1382*11502SChenlu.Chen@Sun.COM (phy_status & MII_SR_10T_HD_CAPS) ? 1 : 0; 1383*11502SChenlu.Chen@Sun.COM } 1384*11502SChenlu.Chen@Sun.COM break; 1385*11502SChenlu.Chen@Sun.COM default: 1386*11502SChenlu.Chen@Sun.COM err = ENOTSUP; 1387*11502SChenlu.Chen@Sun.COM break; 1388*11502SChenlu.Chen@Sun.COM } 1389*11502SChenlu.Chen@Sun.COM return (err); 1390*11502SChenlu.Chen@Sun.COM } 1391*11502SChenlu.Chen@Sun.COM 1392*11502SChenlu.Chen@Sun.COM boolean_t 1393*11502SChenlu.Chen@Sun.COM igb_param_locked(mac_prop_id_t pr_num) 1394*11502SChenlu.Chen@Sun.COM { 1395*11502SChenlu.Chen@Sun.COM /* 1396*11502SChenlu.Chen@Sun.COM * All en_* parameters are locked (read-only) while 1397*11502SChenlu.Chen@Sun.COM * the device is in any sort of loopback mode ... 1398*11502SChenlu.Chen@Sun.COM */ 1399*11502SChenlu.Chen@Sun.COM switch (pr_num) { 1400*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_1000FDX_CAP: 1401*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_1000HDX_CAP: 1402*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_100T4_CAP: 1403*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_100FDX_CAP: 1404*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_100HDX_CAP: 1405*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_10FDX_CAP: 1406*11502SChenlu.Chen@Sun.COM case MAC_PROP_EN_10HDX_CAP: 1407*11502SChenlu.Chen@Sun.COM case MAC_PROP_AUTONEG: 1408*11502SChenlu.Chen@Sun.COM case MAC_PROP_FLOWCTRL: 1409*11502SChenlu.Chen@Sun.COM return (B_TRUE); 1410*11502SChenlu.Chen@Sun.COM } 1411*11502SChenlu.Chen@Sun.COM return (B_FALSE); 1412*11502SChenlu.Chen@Sun.COM } 1413*11502SChenlu.Chen@Sun.COM 1414*11502SChenlu.Chen@Sun.COM /* ARGSUSED */ 1415*11502SChenlu.Chen@Sun.COM int 1416*11502SChenlu.Chen@Sun.COM igb_set_priv_prop(igb_t *igb, const char *pr_name, 1417*11502SChenlu.Chen@Sun.COM uint_t pr_valsize, const void *pr_val) 1418*11502SChenlu.Chen@Sun.COM { 1419*11502SChenlu.Chen@Sun.COM int err = 0; 1420*11502SChenlu.Chen@Sun.COM long result; 1421*11502SChenlu.Chen@Sun.COM struct e1000_hw *hw = &igb->hw; 1422*11502SChenlu.Chen@Sun.COM int i; 1423*11502SChenlu.Chen@Sun.COM 1424*11502SChenlu.Chen@Sun.COM if (strcmp(pr_name, "_tx_copy_thresh") == 0) { 1425*11502SChenlu.Chen@Sun.COM if (pr_val == NULL) { 1426*11502SChenlu.Chen@Sun.COM err = EINVAL; 1427*11502SChenlu.Chen@Sun.COM return (err); 1428*11502SChenlu.Chen@Sun.COM } 1429*11502SChenlu.Chen@Sun.COM (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1430*11502SChenlu.Chen@Sun.COM if (result < MIN_TX_COPY_THRESHOLD || 1431*11502SChenlu.Chen@Sun.COM result > MAX_TX_COPY_THRESHOLD) 1432*11502SChenlu.Chen@Sun.COM err = EINVAL; 1433*11502SChenlu.Chen@Sun.COM else { 1434*11502SChenlu.Chen@Sun.COM igb->tx_copy_thresh = (uint32_t)result; 1435*11502SChenlu.Chen@Sun.COM } 1436*11502SChenlu.Chen@Sun.COM return (err); 1437*11502SChenlu.Chen@Sun.COM } 1438*11502SChenlu.Chen@Sun.COM if (strcmp(pr_name, "_tx_recycle_thresh") == 0) { 1439*11502SChenlu.Chen@Sun.COM if (pr_val == NULL) { 1440*11502SChenlu.Chen@Sun.COM err = EINVAL; 1441*11502SChenlu.Chen@Sun.COM return (err); 1442*11502SChenlu.Chen@Sun.COM } 1443*11502SChenlu.Chen@Sun.COM (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1444*11502SChenlu.Chen@Sun.COM if (result < MIN_TX_RECYCLE_THRESHOLD || 1445*11502SChenlu.Chen@Sun.COM result > MAX_TX_RECYCLE_THRESHOLD) 1446*11502SChenlu.Chen@Sun.COM err = EINVAL; 1447*11502SChenlu.Chen@Sun.COM else { 1448*11502SChenlu.Chen@Sun.COM igb->tx_recycle_thresh = (uint32_t)result; 1449*11502SChenlu.Chen@Sun.COM } 1450*11502SChenlu.Chen@Sun.COM return (err); 1451*11502SChenlu.Chen@Sun.COM } 1452*11502SChenlu.Chen@Sun.COM if (strcmp(pr_name, "_tx_overload_thresh") == 0) { 1453*11502SChenlu.Chen@Sun.COM if (pr_val == NULL) { 1454*11502SChenlu.Chen@Sun.COM err = EINVAL; 1455*11502SChenlu.Chen@Sun.COM return (err); 1456*11502SChenlu.Chen@Sun.COM } 1457*11502SChenlu.Chen@Sun.COM (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1458*11502SChenlu.Chen@Sun.COM if (result < MIN_TX_OVERLOAD_THRESHOLD || 1459*11502SChenlu.Chen@Sun.COM result > MAX_TX_OVERLOAD_THRESHOLD) 1460*11502SChenlu.Chen@Sun.COM err = EINVAL; 1461*11502SChenlu.Chen@Sun.COM else { 1462*11502SChenlu.Chen@Sun.COM igb->tx_overload_thresh = (uint32_t)result; 1463*11502SChenlu.Chen@Sun.COM } 1464*11502SChenlu.Chen@Sun.COM return (err); 1465*11502SChenlu.Chen@Sun.COM } 1466*11502SChenlu.Chen@Sun.COM if (strcmp(pr_name, "_tx_resched_thresh") == 0) { 1467*11502SChenlu.Chen@Sun.COM if (pr_val == NULL) { 1468*11502SChenlu.Chen@Sun.COM err = EINVAL; 1469*11502SChenlu.Chen@Sun.COM return (err); 1470*11502SChenlu.Chen@Sun.COM } 1471*11502SChenlu.Chen@Sun.COM (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1472*11502SChenlu.Chen@Sun.COM if (result < MIN_TX_RESCHED_THRESHOLD || 1473*11502SChenlu.Chen@Sun.COM result > MAX_TX_RESCHED_THRESHOLD) 1474*11502SChenlu.Chen@Sun.COM err = EINVAL; 1475*11502SChenlu.Chen@Sun.COM else { 1476*11502SChenlu.Chen@Sun.COM igb->tx_resched_thresh = (uint32_t)result; 1477*11502SChenlu.Chen@Sun.COM } 1478*11502SChenlu.Chen@Sun.COM return (err); 1479*11502SChenlu.Chen@Sun.COM } 1480*11502SChenlu.Chen@Sun.COM if (strcmp(pr_name, "_rx_copy_thresh") == 0) { 1481*11502SChenlu.Chen@Sun.COM if (pr_val == NULL) { 1482*11502SChenlu.Chen@Sun.COM err = EINVAL; 1483*11502SChenlu.Chen@Sun.COM return (err); 1484*11502SChenlu.Chen@Sun.COM } 1485*11502SChenlu.Chen@Sun.COM (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1486*11502SChenlu.Chen@Sun.COM if (result < MIN_RX_COPY_THRESHOLD || 1487*11502SChenlu.Chen@Sun.COM result > MAX_RX_COPY_THRESHOLD) 1488*11502SChenlu.Chen@Sun.COM err = EINVAL; 1489*11502SChenlu.Chen@Sun.COM else { 1490*11502SChenlu.Chen@Sun.COM igb->rx_copy_thresh = (uint32_t)result; 1491*11502SChenlu.Chen@Sun.COM } 1492*11502SChenlu.Chen@Sun.COM return (err); 1493*11502SChenlu.Chen@Sun.COM } 1494*11502SChenlu.Chen@Sun.COM if (strcmp(pr_name, "_rx_limit_per_intr") == 0) { 1495*11502SChenlu.Chen@Sun.COM if (pr_val == NULL) { 1496*11502SChenlu.Chen@Sun.COM err = EINVAL; 1497*11502SChenlu.Chen@Sun.COM return (err); 1498*11502SChenlu.Chen@Sun.COM } 1499*11502SChenlu.Chen@Sun.COM (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1500*11502SChenlu.Chen@Sun.COM if (result < MIN_RX_LIMIT_PER_INTR || 1501*11502SChenlu.Chen@Sun.COM result > MAX_RX_LIMIT_PER_INTR) 1502*11502SChenlu.Chen@Sun.COM err = EINVAL; 1503*11502SChenlu.Chen@Sun.COM else { 1504*11502SChenlu.Chen@Sun.COM igb->rx_limit_per_intr = (uint32_t)result; 1505*11502SChenlu.Chen@Sun.COM } 1506*11502SChenlu.Chen@Sun.COM return (err); 1507*11502SChenlu.Chen@Sun.COM } 1508*11502SChenlu.Chen@Sun.COM if (strcmp(pr_name, "_intr_throttling") == 0) { 1509*11502SChenlu.Chen@Sun.COM if (pr_val == NULL) { 1510*11502SChenlu.Chen@Sun.COM err = EINVAL; 1511*11502SChenlu.Chen@Sun.COM return (err); 1512*11502SChenlu.Chen@Sun.COM } 1513*11502SChenlu.Chen@Sun.COM (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1514*11502SChenlu.Chen@Sun.COM 1515*11502SChenlu.Chen@Sun.COM if (result < igb->capab->min_intr_throttle || 1516*11502SChenlu.Chen@Sun.COM result > igb->capab->max_intr_throttle) 1517*11502SChenlu.Chen@Sun.COM err = EINVAL; 1518*11502SChenlu.Chen@Sun.COM else { 1519*11502SChenlu.Chen@Sun.COM igb->intr_throttling[0] = (uint32_t)result; 1520*11502SChenlu.Chen@Sun.COM 1521*11502SChenlu.Chen@Sun.COM for (i = 0; i < MAX_NUM_EITR; i++) 1522*11502SChenlu.Chen@Sun.COM igb->intr_throttling[i] = 1523*11502SChenlu.Chen@Sun.COM igb->intr_throttling[0]; 1524*11502SChenlu.Chen@Sun.COM 1525*11502SChenlu.Chen@Sun.COM /* Set interrupt throttling rate */ 1526*11502SChenlu.Chen@Sun.COM for (i = 0; i < igb->intr_cnt; i++) 1527*11502SChenlu.Chen@Sun.COM E1000_WRITE_REG(hw, E1000_EITR(i), 1528*11502SChenlu.Chen@Sun.COM igb->intr_throttling[i]); 1529*11502SChenlu.Chen@Sun.COM } 1530*11502SChenlu.Chen@Sun.COM return (err); 1531*11502SChenlu.Chen@Sun.COM } 1532*11502SChenlu.Chen@Sun.COM return (ENOTSUP); 1533*11502SChenlu.Chen@Sun.COM } 1534*11502SChenlu.Chen@Sun.COM 1535*11502SChenlu.Chen@Sun.COM int 1536*11502SChenlu.Chen@Sun.COM igb_get_priv_prop(igb_t *igb, const char *pr_name, 1537*11502SChenlu.Chen@Sun.COM uint_t pr_flags, uint_t pr_valsize, void *pr_val, uint_t *perm) 1538*11502SChenlu.Chen@Sun.COM { 1539*11502SChenlu.Chen@Sun.COM int err = ENOTSUP; 1540*11502SChenlu.Chen@Sun.COM boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT); 1541*11502SChenlu.Chen@Sun.COM int value; 1542*11502SChenlu.Chen@Sun.COM 1543*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_RW; 1544*11502SChenlu.Chen@Sun.COM 1545*11502SChenlu.Chen@Sun.COM if (strcmp(pr_name, "_adv_pause_cap") == 0) { 1546*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1547*11502SChenlu.Chen@Sun.COM value = (is_default ? 1 : igb->param_adv_pause_cap); 1548*11502SChenlu.Chen@Sun.COM err = 0; 1549*11502SChenlu.Chen@Sun.COM goto done; 1550*11502SChenlu.Chen@Sun.COM } 1551*11502SChenlu.Chen@Sun.COM if (strcmp(pr_name, "_adv_asym_pause_cap") == 0) { 1552*11502SChenlu.Chen@Sun.COM *perm = MAC_PROP_PERM_READ; 1553*11502SChenlu.Chen@Sun.COM value = (is_default ? 1 : igb->param_adv_asym_pause_cap); 1554*11502SChenlu.Chen@Sun.COM err = 0; 1555*11502SChenlu.Chen@Sun.COM goto done; 1556*11502SChenlu.Chen@Sun.COM } 1557*11502SChenlu.Chen@Sun.COM if (strcmp(pr_name, "_tx_copy_thresh") == 0) { 1558*11502SChenlu.Chen@Sun.COM value = (is_default ? DEFAULT_TX_COPY_THRESHOLD : 1559*11502SChenlu.Chen@Sun.COM igb->tx_copy_thresh); 1560*11502SChenlu.Chen@Sun.COM err = 0; 1561*11502SChenlu.Chen@Sun.COM goto done; 1562*11502SChenlu.Chen@Sun.COM } 1563*11502SChenlu.Chen@Sun.COM if (strcmp(pr_name, "_tx_recycle_thresh") == 0) { 1564*11502SChenlu.Chen@Sun.COM value = (is_default ? DEFAULT_TX_RECYCLE_THRESHOLD : 1565*11502SChenlu.Chen@Sun.COM igb->tx_recycle_thresh); 1566*11502SChenlu.Chen@Sun.COM err = 0; 1567*11502SChenlu.Chen@Sun.COM goto done; 1568*11502SChenlu.Chen@Sun.COM } 1569*11502SChenlu.Chen@Sun.COM if (strcmp(pr_name, "_tx_overload_thresh") == 0) { 1570*11502SChenlu.Chen@Sun.COM value = (is_default ? DEFAULT_TX_OVERLOAD_THRESHOLD : 1571*11502SChenlu.Chen@Sun.COM igb->tx_overload_thresh); 1572*11502SChenlu.Chen@Sun.COM err = 0; 1573*11502SChenlu.Chen@Sun.COM goto done; 1574*11502SChenlu.Chen@Sun.COM } 1575*11502SChenlu.Chen@Sun.COM if (strcmp(pr_name, "_tx_resched_thresh") == 0) { 1576*11502SChenlu.Chen@Sun.COM value = (is_default ? DEFAULT_TX_RESCHED_THRESHOLD : 1577*11502SChenlu.Chen@Sun.COM igb->tx_resched_thresh); 1578*11502SChenlu.Chen@Sun.COM err = 0; 1579*11502SChenlu.Chen@Sun.COM goto done; 1580*11502SChenlu.Chen@Sun.COM } 1581*11502SChenlu.Chen@Sun.COM if (strcmp(pr_name, "_rx_copy_thresh") == 0) { 1582*11502SChenlu.Chen@Sun.COM value = (is_default ? DEFAULT_RX_COPY_THRESHOLD : 1583*11502SChenlu.Chen@Sun.COM igb->rx_copy_thresh); 1584*11502SChenlu.Chen@Sun.COM err = 0; 1585*11502SChenlu.Chen@Sun.COM goto done; 1586*11502SChenlu.Chen@Sun.COM } 1587*11502SChenlu.Chen@Sun.COM if (strcmp(pr_name, "_rx_limit_per_intr") == 0) { 1588*11502SChenlu.Chen@Sun.COM value = (is_default ? DEFAULT_RX_LIMIT_PER_INTR : 1589*11502SChenlu.Chen@Sun.COM igb->rx_limit_per_intr); 1590*11502SChenlu.Chen@Sun.COM err = 0; 1591*11502SChenlu.Chen@Sun.COM goto done; 1592*11502SChenlu.Chen@Sun.COM } 1593*11502SChenlu.Chen@Sun.COM if (strcmp(pr_name, "_intr_throttling") == 0) { 1594*11502SChenlu.Chen@Sun.COM value = (is_default ? igb->capab->def_intr_throttle : 1595*11502SChenlu.Chen@Sun.COM igb->intr_throttling[0]); 1596*11502SChenlu.Chen@Sun.COM err = 0; 1597*11502SChenlu.Chen@Sun.COM goto done; 1598*11502SChenlu.Chen@Sun.COM } 1599*11502SChenlu.Chen@Sun.COM done: 1600*11502SChenlu.Chen@Sun.COM if (err == 0) { 1601*11502SChenlu.Chen@Sun.COM (void) snprintf(pr_val, pr_valsize, "%d", value); 1602*11502SChenlu.Chen@Sun.COM } 1603*11502SChenlu.Chen@Sun.COM return (err); 1604*11502SChenlu.Chen@Sun.COM } 1605