xref: /onnv-gate/usr/src/uts/common/io/softmac/softmac_stat.c (revision 9449:53d84bc6a35a)
15895Syz147064 /*
25895Syz147064  * CDDL HEADER START
35895Syz147064  *
45895Syz147064  * The contents of this file are subject to the terms of the
55895Syz147064  * Common Development and Distribution License (the "License").
65895Syz147064  * You may not use this file except in compliance with the License.
75895Syz147064  *
85895Syz147064  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95895Syz147064  * or http://www.opensolaris.org/os/licensing.
105895Syz147064  * See the License for the specific language governing permissions
115895Syz147064  * and limitations under the License.
125895Syz147064  *
135895Syz147064  * When distributing Covered Code, include this CDDL HEADER in each
145895Syz147064  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155895Syz147064  * If applicable, add the following below this CDDL HEADER, with the
165895Syz147064  * fields enclosed by brackets "[]" replaced with your own identifying
175895Syz147064  * information: Portions Copyright [yyyy] [name of copyright owner]
185895Syz147064  *
195895Syz147064  * CDDL HEADER END
205895Syz147064  */
215895Syz147064 /*
22*9449Sxiuyan.wang@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
235895Syz147064  * Use is subject to license terms.
245895Syz147064  */
255895Syz147064 
265895Syz147064 #include <sys/types.h>
275895Syz147064 #include <sys/kstat.h>
285895Syz147064 #include <sys/mac.h>
295895Syz147064 #include <sys/dls.h>
305895Syz147064 #include <sys/softmac_impl.h>
315895Syz147064 
325895Syz147064 typedef struct i_softmac_stat_info_s {
335895Syz147064 	uint_t		ssi_stat;
345895Syz147064 	char		*ssi_name;
355895Syz147064 	char		*ssi_alias;
365895Syz147064 } i_softmac_stat_info_t;
375895Syz147064 
385895Syz147064 /*
395895Syz147064  * Must be the same order as mac_driver_stat.
405895Syz147064  */
415895Syz147064 static i_softmac_stat_info_t	i_softmac_driver_si[] = {
425895Syz147064 	{ MAC_STAT_IFSPEED,	"ifspeed", 	"link_speed"	},
435895Syz147064 	{ MAC_STAT_MULTIRCV,	"multircv",	NULL		},
445895Syz147064 	{ MAC_STAT_BRDCSTRCV,	"brdcstrcv", 	NULL		},
455895Syz147064 	{ MAC_STAT_MULTIXMT,	"multixmt",	NULL		},
465895Syz147064 	{ MAC_STAT_BRDCSTXMT,	"brdcstxmt",	NULL		},
475895Syz147064 	{ MAC_STAT_NORCVBUF,	"norcvbuf",	"rx_no_buf"	},
485895Syz147064 	{ MAC_STAT_IERRORS,	"ierrors",	NULL		},
495895Syz147064 	{ MAC_STAT_UNKNOWNS,	"unknowns",	NULL		},
505895Syz147064 	{ MAC_STAT_NOXMTBUF,	"noxmtbuf",	"No Txpkt "	},
515895Syz147064 	{ MAC_STAT_OERRORS,	"oerrors",	NULL		},
525895Syz147064 	{ MAC_STAT_COLLISIONS,	"collisions",	NULL		},
535895Syz147064 	{ MAC_STAT_RBYTES,	"rbytes64",	"rbytes"	},
545895Syz147064 	{ MAC_STAT_IPACKETS,	"ipackets64",	"ipackets"	},
555895Syz147064 	{ MAC_STAT_OBYTES,	"obytes64",	"obytes"	},
565895Syz147064 	{ MAC_STAT_OPACKETS,	"opackets64",	"opackets"	},
575895Syz147064 	{ MAC_STAT_UNDERFLOWS,	"uflo",		NULL		},
585895Syz147064 	{ MAC_STAT_OVERFLOWS,	"oflo",		NULL		}
595895Syz147064 };
605895Syz147064 
61*9449Sxiuyan.wang@Sun.COM #define	SOFTMAC_DRIVER_SI_SZ						\
62*9449Sxiuyan.wang@Sun.COM 	(sizeof (i_softmac_driver_si) / sizeof (i_softmac_driver_si[0]))
63*9449Sxiuyan.wang@Sun.COM 
645895Syz147064 /*
655895Syz147064  * Must be the same order as ether_stat.
665895Syz147064  */
675895Syz147064 static i_softmac_stat_info_t	i_softmac_ether_si[] = {
685895Syz147064 	{ ETHER_STAT_ALIGN_ERRORS,	"align_errors",
695895Syz147064 	    "alignment_err" },
705895Syz147064 	{ ETHER_STAT_FCS_ERRORS, 	"fcs_errors",		"crc_err" },
715895Syz147064 	{ ETHER_STAT_FIRST_COLLISIONS,	"first_collisions",	NULL },
725895Syz147064 	{ ETHER_STAT_MULTI_COLLISIONS,	"multi_collisions",	NULL },
735895Syz147064 	{ ETHER_STAT_SQE_ERRORS,	"sqe_errors",		NULL },
745895Syz147064 	{ ETHER_STAT_DEFER_XMTS,	"defer_xmts",		NULL },
755895Syz147064 	{ ETHER_STAT_TX_LATE_COLLISIONS, "tx_late_collisions",
765895Syz147064 	    "late_collisions" },
775895Syz147064 	{ ETHER_STAT_EX_COLLISIONS,	"ex_collisions",
785895Syz147064 	    "excessive_collisions" },
795895Syz147064 	{ ETHER_STAT_MACXMT_ERRORS,	"macxmt_errors",	NULL },
805895Syz147064 	{ ETHER_STAT_CARRIER_ERRORS,	"carrier_errors",	NULL },
815895Syz147064 	{ ETHER_STAT_TOOLONG_ERRORS,	"toolong_errors", 	"length_err" },
825895Syz147064 	{ ETHER_STAT_MACRCV_ERRORS, 	"macrcv_errors",
835895Syz147064 	    "Rx Error Count" },
845895Syz147064 
855895Syz147064 	{ ETHER_STAT_XCVR_ADDR,		"xcvr_addr",		NULL },
865895Syz147064 	{ ETHER_STAT_XCVR_ID,		"xcvr_id",		NULL },
875895Syz147064 	{ ETHER_STAT_XCVR_INUSE,	"xcvr_inuse",		NULL },
885895Syz147064 
895895Syz147064 	{ ETHER_STAT_CAP_1000FDX,	"cap_1000fdx",		NULL },
905895Syz147064 	{ ETHER_STAT_CAP_1000HDX,	"cap_1000hdx",		NULL },
915895Syz147064 	{ ETHER_STAT_CAP_100FDX,	"cap_100fdx",		NULL },
925895Syz147064 	{ ETHER_STAT_CAP_100HDX,	"cap_100hdx",		NULL },
935895Syz147064 	{ ETHER_STAT_CAP_10FDX,		"cap_10fdx",		NULL },
945895Syz147064 	{ ETHER_STAT_CAP_10HDX,		"cap_10hdx",		NULL },
955895Syz147064 	{ ETHER_STAT_CAP_ASMPAUSE,	"cap_asmpause",		NULL },
965895Syz147064 	{ ETHER_STAT_CAP_PAUSE,		"cap_pause",		NULL },
975895Syz147064 	{ ETHER_STAT_CAP_AUTONEG,	"cap_autoneg",		NULL },
985895Syz147064 
995895Syz147064 	{ ETHER_STAT_ADV_CAP_1000FDX,	"adv_cap_1000fdx",	NULL },
1005895Syz147064 	{ ETHER_STAT_ADV_CAP_1000HDX,	"adv_cap_1000hdx",	NULL },
1015895Syz147064 	{ ETHER_STAT_ADV_CAP_100FDX,	"adv_cap_100fdx",	NULL },
1025895Syz147064 	{ ETHER_STAT_ADV_CAP_100HDX,	"adv_cap_100hdx",	NULL },
1035895Syz147064 	{ ETHER_STAT_ADV_CAP_10FDX,	"adv_cap_10fdx",	NULL },
1045895Syz147064 	{ ETHER_STAT_ADV_CAP_10HDX,	"adv_cap_10hdx",	NULL },
1055895Syz147064 	{ ETHER_STAT_ADV_CAP_ASMPAUSE,	"adv_cap_asmpause",	NULL },
1065895Syz147064 	{ ETHER_STAT_ADV_CAP_PAUSE,	"adv_cap_pause", 	NULL },
1075895Syz147064 	{ ETHER_STAT_ADV_CAP_AUTONEG,	"adv_cap_autoneg", 	NULL },
1085895Syz147064 
1095895Syz147064 	{ ETHER_STAT_LP_CAP_1000FDX,	"lp_cap_1000fdx",	NULL },
1105895Syz147064 	{ ETHER_STAT_LP_CAP_1000HDX,	"lp_cap_1000hdx",	NULL },
1115895Syz147064 	{ ETHER_STAT_LP_CAP_100FDX,	"lp_cap_100fdx",	NULL },
1125895Syz147064 	{ ETHER_STAT_LP_CAP_100HDX,	"lp_cap_100hdx",	NULL },
1135895Syz147064 	{ ETHER_STAT_LP_CAP_10FDX,	"lp_cap_10fdx",		NULL },
1145895Syz147064 	{ ETHER_STAT_LP_CAP_10HDX,	"lp_cap_10hdx",		NULL },
1155895Syz147064 	{ ETHER_STAT_LP_CAP_ASMPAUSE,	"lp_cap_asmpause",	NULL },
1165895Syz147064 	{ ETHER_STAT_LP_CAP_PAUSE,	"lp_cap_pause",		NULL },
1175895Syz147064 	{ ETHER_STAT_LP_CAP_AUTONEG,	"lp_cap_autoneg",	NULL },
1185895Syz147064 
1195895Syz147064 	{ ETHER_STAT_LINK_ASMPAUSE,	"link_asmpause",	NULL },
1205895Syz147064 	{ ETHER_STAT_LINK_PAUSE,	"link_pause",		NULL },
1215895Syz147064 	{ ETHER_STAT_LINK_AUTONEG,	"link_autoneg", 	NULL },
1225895Syz147064 	{ ETHER_STAT_LINK_DUPLEX,	"link_duplex",		"duplex" },
1235895Syz147064 
1245895Syz147064 	{ ETHER_STAT_TOOSHORT_ERRORS,	"runt_errors",		NULL },
1255895Syz147064 	{ ETHER_STAT_CAP_REMFAULT,	"cap_rem_fault",	NULL },
1265895Syz147064 	{ ETHER_STAT_ADV_REMFAULT,	"adv_rem_fault",	NULL },
1275895Syz147064 	{ ETHER_STAT_LP_REMFAULT,	"lp_rem_fault",		NULL },
1285895Syz147064 
1295895Syz147064 	{ ETHER_STAT_JABBER_ERRORS,	"jabber_errors",	NULL },
1305895Syz147064 	{ ETHER_STAT_CAP_100T4,		"cap_100T4",		NULL },
1315895Syz147064 	{ ETHER_STAT_ADV_CAP_100T4,	"adv_cap_100T4",	NULL },
132*9449Sxiuyan.wang@Sun.COM 	{ ETHER_STAT_LP_CAP_100T4,	"lp_cap_100T4", 	NULL },
133*9449Sxiuyan.wang@Sun.COM 
134*9449Sxiuyan.wang@Sun.COM 	{ ETHER_STAT_CAP_10GFDX,	"cap_10gfdx",		NULL },
135*9449Sxiuyan.wang@Sun.COM 	{ ETHER_STAT_ADV_CAP_10GFDX,	"adv_cap_10gfdx",	NULL },
136*9449Sxiuyan.wang@Sun.COM 	{ ETHER_STAT_LP_CAP_1000FDX,	"lp_cap_10gfdx",	NULL }
1375895Syz147064 };
1385895Syz147064 
139*9449Sxiuyan.wang@Sun.COM #define	SOFTMAC_ETHER_SI_SZ						\
140*9449Sxiuyan.wang@Sun.COM 	(sizeof (i_softmac_ether_si) / sizeof (i_softmac_ether_si[0]))
141*9449Sxiuyan.wang@Sun.COM 
1425895Syz147064 static kstat_t	*softmac_hold_dev_kstat(softmac_t *);
1435895Syz147064 static void	softmac_rele_dev_kstat(kstat_t *);
1445895Syz147064 static int	softmac_get_kstat(kstat_t *, char *, uint64_t *);
1455895Syz147064 
1465895Syz147064 static kstat_t *
softmac_hold_dev_kstat(softmac_t * softmac)1475895Syz147064 softmac_hold_dev_kstat(softmac_t *softmac)
1485895Syz147064 {
1495895Syz147064 	char		drv[MAXLINKNAMELEN];
1505895Syz147064 	uint_t		ppa;
1515895Syz147064 	kstat_t		*ksp;
1525895Syz147064 
1535895Syz147064 	if (ddi_parse(softmac->smac_devname, drv, &ppa) != DDI_SUCCESS)
1545895Syz147064 		return (NULL);
1555895Syz147064 
1565895Syz147064 	/*
1575895Syz147064 	 * Find the kstat by the module name and the instance number.
1585895Syz147064 	 */
1595895Syz147064 	ksp = kstat_hold_byname(drv, ppa, softmac->smac_devname, ALL_ZONES);
1605895Syz147064 	if (ksp != NULL) {
1615895Syz147064 		KSTAT_ENTER(ksp);
1625895Syz147064 
1635895Syz147064 		if ((ksp->ks_data != NULL) &&
1645895Syz147064 		    (ksp->ks_type == KSTAT_TYPE_NAMED)) {
1655895Syz147064 			/*
1665895Syz147064 			 * Update the kstat to get the latest statistics.
1675895Syz147064 			 */
1685895Syz147064 			if (KSTAT_UPDATE(ksp, KSTAT_READ) == 0)
1695895Syz147064 				return (ksp);
1705895Syz147064 		}
1715895Syz147064 
1725895Syz147064 		KSTAT_EXIT(ksp);
1735895Syz147064 		kstat_rele(ksp);
1745895Syz147064 	}
1755895Syz147064 	return (NULL);
1765895Syz147064 }
1775895Syz147064 
1785895Syz147064 static void
softmac_rele_dev_kstat(kstat_t * ksp)1795895Syz147064 softmac_rele_dev_kstat(kstat_t *ksp)
1805895Syz147064 {
1815895Syz147064 	KSTAT_EXIT(ksp);
1825895Syz147064 	kstat_rele(ksp);
1835895Syz147064 }
1845895Syz147064 
1855895Syz147064 /*
1865895Syz147064  * The kstat needs to be held when calling this function.
1875895Syz147064  */
1885895Syz147064 static int
softmac_get_kstat(kstat_t * ksp,char * name,uint64_t * valp)1895895Syz147064 softmac_get_kstat(kstat_t *ksp, char *name, uint64_t *valp)
1905895Syz147064 {
1915895Syz147064 	kstat_named_t	*knp;
1925895Syz147064 	int		i;
1935895Syz147064 	int		ret = ENOTSUP;
1945895Syz147064 
1955895Syz147064 	if (name == NULL)
1965895Syz147064 		return (ret);
1975895Syz147064 
1985895Syz147064 	/*
1995895Syz147064 	 * Search the kstat with the given name.
2005895Syz147064 	 */
2015895Syz147064 	for (i = 0, knp = KSTAT_NAMED_PTR(ksp); i < ksp->ks_ndata; i++, knp++) {
2025895Syz147064 		if (strcmp(knp->name, name) == 0) {
2035895Syz147064 			switch (knp->data_type) {
2045895Syz147064 			case KSTAT_DATA_INT32:
2055895Syz147064 			case KSTAT_DATA_UINT32:
2065895Syz147064 				*valp = (uint64_t)(knp->value.ui32);
2075895Syz147064 				ret = 0;
2085895Syz147064 				break;
2095895Syz147064 			case KSTAT_DATA_INT64:
2105895Syz147064 			case KSTAT_DATA_UINT64:
2115895Syz147064 				*valp = knp->value.ui64;
2125895Syz147064 				ret = 0;
2135895Syz147064 				break;
2145895Syz147064 #ifdef _LP64
2155895Syz147064 			case KSTAT_DATA_LONG:
2165895Syz147064 			case KSTAT_DATA_ULONG:
2175895Syz147064 				*valp = (uint64_t)knp->value.ul;
2185895Syz147064 				ret = 0;
2195895Syz147064 				break;
2205895Syz147064 #endif
2215895Syz147064 			case KSTAT_DATA_CHAR:
2225895Syz147064 				if (strcmp(name, "duplex") != 0)
2235895Syz147064 					break;
2245895Syz147064 				if (strncmp(knp->value.c, "full", 4) == 0)
2255895Syz147064 					*valp = LINK_DUPLEX_FULL;
2265895Syz147064 				else if (strncmp(knp->value.c, "half", 4) == 0)
2275895Syz147064 					*valp = LINK_DUPLEX_HALF;
2285895Syz147064 				else
2295895Syz147064 					*valp = LINK_DUPLEX_UNKNOWN;
2305895Syz147064 				ret = 0;
2315895Syz147064 				break;
2325895Syz147064 			}
2335895Syz147064 			break;
2345895Syz147064 		}
2355895Syz147064 	}
2365895Syz147064 
2375895Syz147064 	return (ret);
2385895Syz147064 }
2395895Syz147064 
2405895Syz147064 int
softmac_m_stat(void * arg,uint_t stat,uint64_t * val)2415895Syz147064 softmac_m_stat(void *arg, uint_t stat, uint64_t *val)
2425895Syz147064 {
2435895Syz147064 	softmac_t	*softmac = arg;
2445895Syz147064 	kstat_t		*ksp;
2455895Syz147064 	uint_t		index;
2465895Syz147064 	int		ret;
2475895Syz147064 
2485895Syz147064 	if ((ksp = softmac_hold_dev_kstat(softmac)) == NULL)
2495895Syz147064 		return (ENOTSUP);
2505895Syz147064 
2515895Syz147064 	if (IS_MAC_STAT(stat)) {
252*9449Sxiuyan.wang@Sun.COM 		i_softmac_stat_info_t *ssip = NULL;
253*9449Sxiuyan.wang@Sun.COM 
254*9449Sxiuyan.wang@Sun.COM 		for (index = 0; index < SOFTMAC_DRIVER_SI_SZ; index++) {
255*9449Sxiuyan.wang@Sun.COM 			if (stat == i_softmac_driver_si[index].ssi_stat) {
256*9449Sxiuyan.wang@Sun.COM 				ssip = &i_softmac_driver_si[index];
257*9449Sxiuyan.wang@Sun.COM 				break;
258*9449Sxiuyan.wang@Sun.COM 			}
259*9449Sxiuyan.wang@Sun.COM 		}
260*9449Sxiuyan.wang@Sun.COM 
261*9449Sxiuyan.wang@Sun.COM 		if (ssip == NULL) {
262*9449Sxiuyan.wang@Sun.COM 			ret = ENOTSUP;
263*9449Sxiuyan.wang@Sun.COM 		} else {
264*9449Sxiuyan.wang@Sun.COM 			if ((ret = softmac_get_kstat(ksp, ssip->ssi_name,
265*9449Sxiuyan.wang@Sun.COM 			    val)) != 0)
266*9449Sxiuyan.wang@Sun.COM 				ret = softmac_get_kstat(ksp, ssip->ssi_alias,
267*9449Sxiuyan.wang@Sun.COM 				    val);
2685895Syz147064 		}
2695895Syz147064 	} else {
2705895Syz147064 		ASSERT(IS_MACTYPE_STAT(stat));
2715895Syz147064 
2725895Syz147064 		switch (softmac->smac_media) {
273*9449Sxiuyan.wang@Sun.COM 		case DL_ETHER: {
274*9449Sxiuyan.wang@Sun.COM 			i_softmac_stat_info_t *ssip = NULL;
275*9449Sxiuyan.wang@Sun.COM 
276*9449Sxiuyan.wang@Sun.COM 			for (index = 0; index < SOFTMAC_ETHER_SI_SZ; index++) {
277*9449Sxiuyan.wang@Sun.COM 				if (stat ==
278*9449Sxiuyan.wang@Sun.COM 				    i_softmac_ether_si[index].ssi_stat) {
279*9449Sxiuyan.wang@Sun.COM 					ssip = &i_softmac_ether_si[index];
280*9449Sxiuyan.wang@Sun.COM 					break;
281*9449Sxiuyan.wang@Sun.COM 				}
2825895Syz147064 			}
283*9449Sxiuyan.wang@Sun.COM 
284*9449Sxiuyan.wang@Sun.COM 			if (ssip == NULL) {
285*9449Sxiuyan.wang@Sun.COM 				ret = ENOTSUP;
286*9449Sxiuyan.wang@Sun.COM 			} else {
287*9449Sxiuyan.wang@Sun.COM 				if ((ret = softmac_get_kstat(ksp,
288*9449Sxiuyan.wang@Sun.COM 				    ssip->ssi_name, val)) != 0)
289*9449Sxiuyan.wang@Sun.COM 					ret = softmac_get_kstat(ksp,
290*9449Sxiuyan.wang@Sun.COM 					    ssip->ssi_alias, val);
291*9449Sxiuyan.wang@Sun.COM 			}
292*9449Sxiuyan.wang@Sun.COM 
2935895Syz147064 			break;
294*9449Sxiuyan.wang@Sun.COM 		}
2955895Syz147064 		default:
2965895Syz147064 			ret = ENOTSUP;
2975895Syz147064 			break;
2985895Syz147064 		}
2995895Syz147064 	}
3005895Syz147064 
3015895Syz147064 	softmac_rele_dev_kstat(ksp);
3025895Syz147064 	return (ret);
3035895Syz147064 }
304