Home | History | Annotate | Download | only in nge
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 
     28 #include "nge.h"
     29 
     30 #undef	NGE_DBG
     31 #define	NGE_DBG		NGE_DBG_STATS	/* debug flag for this code	*/
     32 
     33 /*
     34  * Table of Hardware-defined Statistics Block Offsets and Names
     35  */
     36 #define	KS_NAME(s)			{ KS_ ## s, #s }
     37 
     38 const nge_ksindex_t nge_statistics[] = {
     39 
     40 	KS_NAME(ifHOutOctets),
     41 	KS_NAME(ifHOutZeroRetranCount),
     42 	KS_NAME(ifHOutOneRetranCount),
     43 	KS_NAME(ifHOutMoreRetranCount),
     44 	KS_NAME(ifHOutColCount),
     45 	KS_NAME(ifHOutFifoovCount),
     46 	KS_NAME(ifHOutLOCCount),
     47 	KS_NAME(ifHOutExDecCount),
     48 	KS_NAME(ifHOutRetryCount),
     49 	KS_NAME(ifHInFrameErrCount),
     50 	KS_NAME(ifHInExtraOctErrCount),
     51 	KS_NAME(ifHInLColErrCount),
     52 	KS_NAME(ifHInOversizeErrCount),
     53 	KS_NAME(ifHInFovErrCount),
     54 	KS_NAME(ifHInFCSErrCount),
     55 	KS_NAME(ifHInAlignErrCount),
     56 	KS_NAME(ifHInLenErrCount),
     57 	KS_NAME(ifHInUniPktsCount),
     58 	KS_NAME(ifHInBroadPksCount),
     59 	KS_NAME(ifHInMulPksCount),
     60 	{ KS_STATS_SIZE, NULL }
     61 };
     62 
     63 /*
     64  * Local datatype for defining tables of (Offset, Name) pairs
     65  */
     66 static int
     67 nge_statistics_update(kstat_t *ksp, int flag)
     68 {
     69 	uint32_t regno;
     70 	nge_t *ngep;
     71 	nge_statistics_t *istp;
     72 	nge_hw_statistics_t *hw_stp;
     73 	kstat_named_t *knp;
     74 	const nge_ksindex_t *ksip;
     75 
     76 	if (flag != KSTAT_READ)
     77 		return (EACCES);
     78 
     79 	ngep = ksp->ks_private;
     80 	istp = &ngep->statistics;
     81 	hw_stp = &istp->hw_statistics;
     82 	knp = ksp->ks_data;
     83 
     84 	/*
     85 	 * Transfer the statistics values from the hardware statistics regs
     86 	 */
     87 	for (ksip = nge_statistics; ksip->name != NULL; ++knp, ++ksip) {
     88 		regno = KS_BASE + ksip->index * sizeof (uint32_t);
     89 		hw_stp->a[ksip->index] += nge_reg_get32(ngep, regno);
     90 		knp->value.ui64 = hw_stp->a[ksip->index];
     91 	}
     92 
     93 	return (0);
     94 }
     95 
     96 
     97 static const nge_ksindex_t nge_chipinfo[] = {
     98 	{ 0,				"businfo"		},
     99 	{ 1,				"command"		},
    100 	{ 2,				"vendor_id"		},
    101 	{ 3,				"device_id"		},
    102 	{ 4,				"subsystem_vendor_id"	},
    103 	{ 5,				"subsystem_device_id"	},
    104 	{ 6,				"revision_id"		},
    105 	{ 7,				"cache_line_size"	},
    106 	{ 8,				"latency_timer"		},
    107 	{ 9,				"phy_mode"		},
    108 	{ 10,				"phy_id"		},
    109 	{ 11,				"hw_mac_addr"		},
    110 	{ 12,				"&bus_type"		},
    111 	{ 13,				"&bus_speed"		},
    112 	{ 14,				"&bus_size"		},
    113 	{ -1,				NULL 			}
    114 };
    115 
    116 static const nge_ksindex_t nge_debuginfo[] = {
    117 	{ 0,				"rx_realloc"		},
    118 	{ 1,				"rx_realloc_fails"	},
    119 	{ 2,				"rx_realloc_DMA_fails"	},
    120 	{ 3,				"rx_realloc_MP_fails"	},
    121 	{ 4,				"rx_rcfree"		},
    122 	{ 5,				"context_switch"	},
    123 	{ 6,				"ip_hsum_err"		},
    124 	{ 7,				"tcp_hsum_err"		},
    125 	{ 8,				"tc_next"		},
    126 	{ 9,				"tx_next"		},
    127 	{ 10,				"tx_free"		},
    128 	{ 11,				"tx_flow"		},
    129 	{ 12,				"rx_prod"		},
    130 	{ 13,				"rx_hold"		},
    131 	{ 14,				"rx_nobuf"		},
    132 	{ 15,				"rx_err"		},
    133 	{16,				"tx_err"		},
    134 	{17,				"tx_stall"		},
    135 	{ -1,				NULL 			}
    136 };
    137 
    138 static int
    139 nge_chipinfo_update(kstat_t *ksp, int flag)
    140 {
    141 	nge_t *ngep;
    142 	kstat_named_t *knp;
    143 	chip_info_t *infop;
    144 
    145 	if (flag != KSTAT_READ)
    146 		return (EACCES);
    147 
    148 	ngep = ksp->ks_private;
    149 	infop = &ngep->chipinfo;
    150 	knp = ksp->ks_data;
    151 
    152 	(knp++)->value.ui64 = infop->businfo;
    153 	(knp++)->value.ui64 = infop->command;
    154 	(knp++)->value.ui64 = infop->vendor;
    155 	(knp++)->value.ui64 = infop->device;
    156 	(knp++)->value.ui64 = infop->subven;
    157 	(knp++)->value.ui64 = infop->subdev;
    158 	(knp++)->value.ui64 = infop->revision;
    159 	(knp++)->value.ui64 = infop->clsize;
    160 	(knp++)->value.ui64 = infop->latency;
    161 	(knp++)->value.ui64 = ngep->phy_mode;
    162 	(knp++)->value.ui64 = ngep->phy_id;
    163 	(knp++)->value.ui64 = infop->hw_mac_addr;
    164 	return (0);
    165 }
    166 
    167 static int
    168 nge_debuginfo_update(kstat_t *ksp, int flag)
    169 {
    170 	nge_t *ngep;
    171 	kstat_named_t *knp;
    172 	nge_sw_statistics_t *sw_stp;
    173 
    174 	if (flag != KSTAT_READ)
    175 		return (EACCES);
    176 
    177 	ngep = ksp->ks_private;
    178 	sw_stp = &ngep->statistics.sw_statistics;
    179 	knp = ksp->ks_data;
    180 
    181 	(knp++)->value.ui64 = sw_stp->recv_realloc;
    182 	(knp++)->value.ui64 = sw_stp->kmem_alloc_err;
    183 	(knp++)->value.ui64 = sw_stp->dma_alloc_err;
    184 	(knp++)->value.ui64 = sw_stp->mp_alloc_err;
    185 	(knp++)->value.ui64 = sw_stp->recy_free;
    186 	(knp++)->value.ui64 = sw_stp->load_context;
    187 	(knp++)->value.ui64 = sw_stp->ip_hwsum_err;
    188 	(knp++)->value.ui64 = sw_stp->tcp_hwsum_err;
    189 	(knp++)->value.ui64 = ngep->send->tc_next;
    190 	(knp++)->value.ui64 = ngep->send->tx_next;
    191 	(knp++)->value.ui64 = ngep->send->tx_free;
    192 	(knp++)->value.ui64 = ngep->send->tx_flow;
    193 	(knp++)->value.ui64 = ngep->recv->prod_index;
    194 	(knp++)->value.ui64 = ngep->buff->rx_hold;
    195 	(knp++)->value.ui64 = sw_stp->rx_nobuffer;
    196 	(knp++)->value.ui64 = sw_stp->rx_err;
    197 	(knp++)->value.ui64 = sw_stp->tx_stop_err;
    198 	(knp++)->value.ui64 = sw_stp->tx_stall;
    199 	return (0);
    200 }
    201 
    202 static kstat_t *
    203 nge_setup_named_kstat(nge_t *ngep, int instance, char *name,
    204 	const nge_ksindex_t *ksip, size_t size, int (*update)(kstat_t *, int))
    205 {
    206 	kstat_t *ksp;
    207 	kstat_named_t *knp;
    208 	char *np;
    209 	int type;
    210 
    211 	size /= sizeof (nge_ksindex_t);
    212 	ksp = kstat_create(NGE_DRIVER_NAME, instance, name, "net",
    213 	    KSTAT_TYPE_NAMED, size-1, KSTAT_FLAG_PERSISTENT);
    214 	if (ksp == NULL)
    215 		return (NULL);
    216 
    217 	ksp->ks_private = ngep;
    218 	ksp->ks_update = update;
    219 	for (knp = ksp->ks_data; (np = ksip->name) != NULL; ++knp, ++ksip) {
    220 		switch (*np) {
    221 		default:
    222 			type = KSTAT_DATA_UINT64;
    223 			break;
    224 		case '%':
    225 			np += 1;
    226 			type = KSTAT_DATA_UINT32;
    227 			break;
    228 
    229 		case '$':
    230 			np ++;
    231 			type = KSTAT_DATA_STRING;
    232 			break;
    233 		case '&':
    234 			np ++;
    235 			type = KSTAT_DATA_CHAR;
    236 			break;
    237 		}
    238 		kstat_named_init(knp, np, type);
    239 	}
    240 	kstat_install(ksp);
    241 
    242 	return (ksp);
    243 }
    244 
    245 void
    246 nge_init_kstats(nge_t *ngep, int instance)
    247 {
    248 	NGE_TRACE(("nge_init_kstats($%p, %d)", (void *)ngep, instance));
    249 
    250 	ngep->nge_kstats[NGE_KSTAT_STATS] = nge_setup_named_kstat(ngep,
    251 	    instance, "statistics", nge_statistics,
    252 	    sizeof (nge_statistics), nge_statistics_update);
    253 
    254 	ngep->nge_kstats[NGE_KSTAT_CHIPID] = nge_setup_named_kstat(ngep,
    255 	    instance, "chipinfo", nge_chipinfo,
    256 	    sizeof (nge_chipinfo), nge_chipinfo_update);
    257 
    258 	ngep->nge_kstats[NGE_KSTAT_DEBUG] = nge_setup_named_kstat(ngep,
    259 	    instance, "driver-debug", nge_debuginfo,
    260 	    sizeof (nge_debuginfo), nge_debuginfo_update);
    261 
    262 }
    263 
    264 void
    265 nge_fini_kstats(nge_t *ngep)
    266 {
    267 	int i;
    268 
    269 	NGE_TRACE(("nge_fini_kstats($%p)", (void *)ngep));
    270 	for (i = NGE_KSTAT_COUNT;  --i >= 0; )
    271 		if (ngep->nge_kstats[i] != NULL)
    272 			kstat_delete(ngep->nge_kstats[i]);
    273 }
    274 
    275 int
    276 nge_m_stat(void *arg, uint_t stat, uint64_t *val)
    277 {
    278 	nge_t *ngep = arg;
    279 	uint32_t regno;
    280 	nge_statistics_t *nstp = &ngep->statistics;
    281 	nge_hw_statistics_t *hw_stp = &nstp->hw_statistics;
    282 	nge_sw_statistics_t *sw_stp = &nstp->sw_statistics;
    283 
    284 	switch (stat) {
    285 	case MAC_STAT_IFSPEED:
    286 		*val = ngep->param_link_speed * 1000000ull;
    287 		break;
    288 
    289 	case MAC_STAT_MULTIRCV:
    290 		regno = KS_BASE + KS_ifHInMulPksCount * sizeof (uint32_t);
    291 		hw_stp->s.InMulPksCount += nge_reg_get32(ngep, regno);
    292 		*val = hw_stp->s.InMulPksCount;
    293 		break;
    294 
    295 	case MAC_STAT_BRDCSTRCV:
    296 		regno = KS_BASE +  KS_ifHInBroadPksCount * sizeof (uint32_t);
    297 		hw_stp->s.InBroadPksCount += nge_reg_get32(ngep, regno);
    298 		*val = hw_stp->s.InBroadPksCount;
    299 		break;
    300 
    301 	case MAC_STAT_NORCVBUF:
    302 		*val = sw_stp->rx_nobuffer;
    303 		break;
    304 
    305 	case MAC_STAT_IERRORS:
    306 		regno = KS_BASE + KS_ifHInFrameErrCount * sizeof (uint32_t);
    307 		hw_stp->s.InFrameErrCount += nge_reg_get32(ngep, regno);
    308 		regno = KS_BASE + KS_ifHInExtraOctErrCount * sizeof (uint32_t);
    309 		hw_stp->s.InExtraOctErrCount += nge_reg_get32(ngep, regno);
    310 		regno = KS_BASE + KS_ifHInLColErrCount * sizeof (uint32_t);
    311 		hw_stp->s.InLColErrCount += nge_reg_get32(ngep, regno);
    312 		regno = KS_BASE + KS_ifHInOversizeErrCount * sizeof (uint32_t);
    313 		hw_stp->s.InOversizeErrCount += nge_reg_get32(ngep, regno);
    314 		regno = KS_BASE + KS_ifHInFovErrCount * sizeof (uint32_t);
    315 		hw_stp->s.InFovErrCount += nge_reg_get32(ngep, regno);
    316 		regno = KS_BASE + KS_ifHInFCSErrCount * sizeof (uint32_t);
    317 		hw_stp->s.InFCSErrCount += nge_reg_get32(ngep, regno);
    318 		regno = KS_BASE + KS_ifHInAlignErrCount * sizeof (uint32_t);
    319 		hw_stp->s.InAlignErrCount += nge_reg_get32(ngep, regno);
    320 		regno = KS_BASE + KS_ifHInLenErrCount * sizeof (uint32_t);
    321 		hw_stp->s.InLenErrCount += nge_reg_get32(ngep, regno);
    322 		*val = hw_stp->s.InFrameErrCount +
    323 		    hw_stp->s.InExtraOctErrCount +
    324 		    hw_stp->s.InLColErrCount +
    325 		    hw_stp->s.InOversizeErrCount +
    326 		    hw_stp->s.InFovErrCount +
    327 		    hw_stp->s.InFCSErrCount +
    328 		    hw_stp->s.InAlignErrCount +
    329 		    hw_stp->s.InLenErrCount;
    330 		break;
    331 
    332 	case MAC_STAT_OERRORS:
    333 		regno = KS_BASE + KS_ifHOutFifoovCount * sizeof (uint32_t);
    334 		hw_stp->s.OutFifoovCount += nge_reg_get32(ngep, regno);
    335 		regno = KS_BASE + KS_ifHOutLOCCount * sizeof (uint32_t);
    336 		hw_stp->s.OutLOCCount += nge_reg_get32(ngep, regno);
    337 		regno = KS_BASE + KS_ifHOutExDecCount * sizeof (uint32_t);
    338 		hw_stp->s.OutExDecCount += nge_reg_get32(ngep, regno);
    339 		regno = KS_BASE + KS_ifHOutRetryCount * sizeof (uint32_t);
    340 		hw_stp->s.OutRetryCount += nge_reg_get32(ngep, regno);
    341 		*val = hw_stp->s.OutFifoovCount +
    342 		    hw_stp->s.OutLOCCount +
    343 		    hw_stp->s.OutExDecCount +
    344 		    hw_stp->s.OutRetryCount;
    345 		break;
    346 
    347 	case MAC_STAT_COLLISIONS:
    348 		regno = KS_BASE + KS_ifHOutColCount * sizeof (uint32_t);
    349 		hw_stp->s.OutColCount += nge_reg_get32(ngep, regno);
    350 		*val = hw_stp->s.OutColCount;
    351 		break;
    352 
    353 	case MAC_STAT_RBYTES:
    354 		*val = sw_stp->rbytes;
    355 		break;
    356 
    357 	case MAC_STAT_IPACKETS:
    358 		*val = sw_stp->recv_count;
    359 		break;
    360 
    361 	case MAC_STAT_OBYTES:
    362 		*val = sw_stp->obytes;
    363 		break;
    364 
    365 	case MAC_STAT_OPACKETS:
    366 		*val = sw_stp->xmit_count;
    367 		break;
    368 
    369 	case ETHER_STAT_ALIGN_ERRORS:
    370 		regno = KS_BASE + KS_ifHInAlignErrCount * sizeof (uint32_t);
    371 		hw_stp->s.InAlignErrCount += nge_reg_get32(ngep, regno);
    372 		*val = hw_stp->s.InAlignErrCount;
    373 		break;
    374 
    375 	case ETHER_STAT_FCS_ERRORS:
    376 		regno = KS_BASE + KS_ifHInFCSErrCount * sizeof (uint32_t);
    377 		hw_stp->s.InFCSErrCount += nge_reg_get32(ngep, regno);
    378 		*val = hw_stp->s.InFCSErrCount;
    379 		break;
    380 
    381 	case ETHER_STAT_FIRST_COLLISIONS:
    382 		regno = KS_BASE + KS_ifHOutOneRetranCount * sizeof (uint32_t);
    383 		hw_stp->s.OutOneRetranCount += nge_reg_get32(ngep, regno);
    384 		*val = hw_stp->s.OutOneRetranCount;
    385 		break;
    386 
    387 	case ETHER_STAT_MULTI_COLLISIONS:
    388 		regno = KS_BASE + KS_ifHOutMoreRetranCount * sizeof (uint32_t);
    389 		hw_stp->s.OutMoreRetranCount += nge_reg_get32(ngep, regno);
    390 		*val =  hw_stp->s.OutMoreRetranCount;
    391 		break;
    392 
    393 	case ETHER_STAT_DEFER_XMTS:
    394 		regno = KS_BASE + KS_ifHOutExDecCount * sizeof (uint32_t);
    395 		hw_stp->s.OutExDecCount += nge_reg_get32(ngep, regno);
    396 		*val = hw_stp->s.OutExDecCount;
    397 		break;
    398 
    399 	case ETHER_STAT_TX_LATE_COLLISIONS:
    400 		regno = KS_BASE + KS_ifHOutColCount * sizeof (uint32_t);
    401 		hw_stp->s.OutColCount += nge_reg_get32(ngep, regno);
    402 		*val = hw_stp->s.OutColCount;
    403 		break;
    404 
    405 	case ETHER_STAT_EX_COLLISIONS:
    406 		regno = KS_BASE + KS_ifHOutOneRetranCount * sizeof (uint32_t);
    407 		hw_stp->s.OutOneRetranCount += nge_reg_get32(ngep, regno);
    408 		*val = hw_stp->s.OutOneRetranCount;
    409 		break;
    410 
    411 	case ETHER_STAT_CARRIER_ERRORS:
    412 		regno = KS_BASE + KS_ifHOutLOCCount * sizeof (uint32_t);
    413 		hw_stp->s.OutLOCCount += nge_reg_get32(ngep, regno);
    414 		*val = hw_stp->s.OutLOCCount;
    415 		break;
    416 
    417 	case ETHER_STAT_TOOLONG_ERRORS:
    418 		regno = KS_BASE + KS_ifHInOversizeErrCount * sizeof (uint32_t);
    419 		hw_stp->s.InOversizeErrCount += nge_reg_get32(ngep, regno);
    420 		*val = hw_stp->s.InOversizeErrCount;
    421 		break;
    422 
    423 	case ETHER_STAT_XCVR_ADDR:
    424 		*val = ngep->phy_xmii_addr;
    425 		break;
    426 
    427 	case ETHER_STAT_XCVR_ID:
    428 		*val = ngep->phy_id;
    429 		break;
    430 
    431 	case ETHER_STAT_XCVR_INUSE:
    432 		*val = XCVR_1000T;
    433 		break;
    434 
    435 	case ETHER_STAT_CAP_1000FDX:
    436 		*val = 1;
    437 		break;
    438 
    439 	case ETHER_STAT_CAP_1000HDX:
    440 		*val = 0;
    441 		break;
    442 
    443 	case ETHER_STAT_CAP_100FDX:
    444 		*val = 1;
    445 		break;
    446 
    447 	case ETHER_STAT_CAP_100HDX:
    448 		*val = 1;
    449 		break;
    450 
    451 	case ETHER_STAT_CAP_10FDX:
    452 		*val = 1;
    453 		break;
    454 
    455 	case ETHER_STAT_CAP_10HDX:
    456 		*val = 1;
    457 		break;
    458 
    459 	case ETHER_STAT_CAP_ASMPAUSE:
    460 		*val = 1;
    461 		break;
    462 
    463 	case ETHER_STAT_CAP_PAUSE:
    464 		*val = 1;
    465 		break;
    466 
    467 	case ETHER_STAT_CAP_AUTONEG:
    468 		*val = 1;
    469 		break;
    470 
    471 	case ETHER_STAT_ADV_CAP_1000FDX:
    472 		*val = ngep->param_adv_1000fdx;
    473 		break;
    474 
    475 	case ETHER_STAT_ADV_CAP_1000HDX:
    476 		*val = ngep->param_adv_1000hdx;
    477 		break;
    478 
    479 	case ETHER_STAT_ADV_CAP_100FDX:
    480 		*val = ngep->param_adv_100fdx;
    481 		break;
    482 
    483 	case ETHER_STAT_ADV_CAP_100HDX:
    484 		*val = ngep->param_adv_100hdx;
    485 		break;
    486 
    487 	case ETHER_STAT_ADV_CAP_10FDX:
    488 		*val = ngep->param_adv_10fdx;
    489 		break;
    490 
    491 	case ETHER_STAT_ADV_CAP_10HDX:
    492 		*val = ngep->param_adv_10hdx;
    493 		break;
    494 
    495 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
    496 		*val = ngep->param_adv_asym_pause;
    497 		break;
    498 
    499 	case ETHER_STAT_ADV_CAP_PAUSE:
    500 		*val = ngep->param_adv_pause;
    501 		break;
    502 
    503 	case ETHER_STAT_ADV_CAP_AUTONEG:
    504 		*val = ngep->param_adv_autoneg;
    505 		break;
    506 
    507 	case ETHER_STAT_LP_CAP_1000FDX:
    508 		*val = ngep->param_lp_1000fdx;
    509 		break;
    510 
    511 	case ETHER_STAT_LP_CAP_1000HDX:
    512 		*val = ngep->param_lp_1000hdx;
    513 		break;
    514 
    515 	case ETHER_STAT_LP_CAP_100FDX:
    516 		*val = ngep->param_lp_100fdx;
    517 		break;
    518 
    519 	case ETHER_STAT_LP_CAP_100HDX:
    520 		*val = ngep->param_lp_100hdx;
    521 		break;
    522 
    523 	case ETHER_STAT_LP_CAP_10FDX:
    524 		*val = ngep->param_lp_10fdx;
    525 		break;
    526 
    527 	case ETHER_STAT_LP_CAP_10HDX:
    528 		*val = ngep->param_lp_10hdx;
    529 		break;
    530 
    531 	case ETHER_STAT_LP_CAP_ASMPAUSE:
    532 		*val = ngep->param_lp_asym_pause;
    533 		break;
    534 
    535 	case ETHER_STAT_LP_CAP_PAUSE:
    536 		*val = ngep->param_lp_pause;
    537 		break;
    538 
    539 	case ETHER_STAT_LP_CAP_AUTONEG:
    540 		*val = ngep->param_lp_autoneg;
    541 		break;
    542 
    543 	case ETHER_STAT_LINK_ASMPAUSE:
    544 		*val = ngep->param_adv_asym_pause &&
    545 		    ngep->param_lp_asym_pause &&
    546 		    ngep->param_adv_pause != ngep->param_lp_pause;
    547 		break;
    548 
    549 	case ETHER_STAT_LINK_PAUSE:
    550 		*val = ngep->param_link_rx_pause;
    551 		break;
    552 
    553 	case ETHER_STAT_LINK_AUTONEG:
    554 		*val = ngep->param_link_autoneg;
    555 		break;
    556 
    557 	case ETHER_STAT_LINK_DUPLEX:
    558 		*val = ngep->param_link_duplex;
    559 		break;
    560 
    561 	case ETHER_STAT_CAP_100T4:
    562 	case ETHER_STAT_LP_CAP_100T4:
    563 		*val = 0;
    564 		break;
    565 
    566 	default:
    567 		return (ENOTSUP);
    568 	}
    569 
    570 	return (0);
    571 }
    572