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