xref: /onnv-gate/usr/src/uts/common/io/rge/rge_kstats.c (revision 4403:77da60925cac)
1744Sgs150176 /*
2744Sgs150176  * CDDL HEADER START
3744Sgs150176  *
4744Sgs150176  * The contents of this file are subject to the terms of the
52311Sseb  * Common Development and Distribution License (the "License").
62311Sseb  * You may not use this file except in compliance with the License.
7744Sgs150176  *
8744Sgs150176  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9744Sgs150176  * or http://www.opensolaris.org/os/licensing.
10744Sgs150176  * See the License for the specific language governing permissions
11744Sgs150176  * and limitations under the License.
12744Sgs150176  *
13744Sgs150176  * When distributing Covered Code, include this CDDL HEADER in each
14744Sgs150176  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15744Sgs150176  * If applicable, add the following below this CDDL HEADER, with the
16744Sgs150176  * fields enclosed by brackets "[]" replaced with your own identifying
17744Sgs150176  * information: Portions Copyright [yyyy] [name of copyright owner]
18744Sgs150176  *
19744Sgs150176  * CDDL HEADER END
20744Sgs150176  */
21744Sgs150176 /*
22*4403Sgd78059  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23744Sgs150176  * Use is subject to license terms.
24744Sgs150176  */
25744Sgs150176 
26744Sgs150176 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27744Sgs150176 
28744Sgs150176 #include "rge.h"
29744Sgs150176 
30744Sgs150176 #define	RGE_DBG		RGE_DBG_STATS	/* debug flag for this code	*/
31744Sgs150176 
32744Sgs150176 /*
33744Sgs150176  * Local datatype for defining tables of (Offset, Name) pairs
34744Sgs150176  */
35744Sgs150176 typedef struct {
36744Sgs150176 	offset_t	index;
37744Sgs150176 	char		*name;
38744Sgs150176 } rge_ksindex_t;
39744Sgs150176 
40744Sgs150176 static const rge_ksindex_t rge_driverinfo[] = {
41744Sgs150176 	{ 0,		"rx_ring_addr"		},
42744Sgs150176 	{ 1,		"rx_next"		},
43744Sgs150176 	{ 2,		"rx_free"		},
44744Sgs150176 	{ 3,		"rx_bcopy"		},
45744Sgs150176 	{ 4,		"tx_ring_addr"		},
46744Sgs150176 	{ 5,		"tx_next"		},
47744Sgs150176 	{ 6,		"tx_free"		},
48744Sgs150176 	{ 7,		"tx_flow"		},
49744Sgs150176 	{ 8,		"resched_needed"	},
50744Sgs150176 	{ 9,		"watchdog"		},
51744Sgs150176 	{ 10,		"rx_config"		},
52744Sgs150176 	{ 11,		"tx_config"		},
53744Sgs150176 	{ 12,		"mac_ver"		},
54744Sgs150176 	{ 13,		"phy_ver"		},
55744Sgs150176 	{ 14,		"chip_reset"		},
56744Sgs150176 	{ 15,		"phy_reset"		},
57*4403Sgd78059 	{ 16,		"loop_mode"		},
58744Sgs150176 	{ -1,		NULL 			}
59744Sgs150176 };
60744Sgs150176 
61744Sgs150176 static int
rge_driverinfo_update(kstat_t * ksp,int flag)62744Sgs150176 rge_driverinfo_update(kstat_t *ksp, int flag)
63744Sgs150176 {
64744Sgs150176 	rge_t *rgep;
65744Sgs150176 	kstat_named_t *knp;
66744Sgs150176 
67744Sgs150176 	if (flag != KSTAT_READ)
68744Sgs150176 		return (EACCES);
69744Sgs150176 
70744Sgs150176 	rgep = ksp->ks_private;
71744Sgs150176 	knp = ksp->ks_data;
72744Sgs150176 
73744Sgs150176 	(knp++)->value.ui64 = rgep->dma_area_rxdesc.cookie.dmac_laddress;
74744Sgs150176 	(knp++)->value.ui64 = rgep->rx_next;
75744Sgs150176 	(knp++)->value.ui64 = rgep->rx_free;
76744Sgs150176 	(knp++)->value.ui64 = rgep->rx_bcopy;
77744Sgs150176 	(knp++)->value.ui64 = rgep->dma_area_txdesc.cookie.dmac_laddress;
78744Sgs150176 	(knp++)->value.ui64 = rgep->tx_next;
79744Sgs150176 	(knp++)->value.ui64 = rgep->tx_free;
80744Sgs150176 	(knp++)->value.ui64 = rgep->tx_flow;
81744Sgs150176 	(knp++)->value.ui64 = rgep->resched_needed;
82744Sgs150176 	(knp++)->value.ui64 = rgep->watchdog;
83744Sgs150176 	(knp++)->value.ui64 = rgep->chipid.rxconfig;
84744Sgs150176 	(knp++)->value.ui64 = rgep->chipid.txconfig;
85744Sgs150176 	(knp++)->value.ui64 = rgep->chipid.mac_ver;
86744Sgs150176 	(knp++)->value.ui64 = rgep->chipid.phy_ver;
87744Sgs150176 	(knp++)->value.ui64 = rgep->stats.chip_reset;
88744Sgs150176 	(knp++)->value.ui64 = rgep->stats.phy_reset;
89*4403Sgd78059 	(knp++)->value.ui64 = rgep->param_loop_mode;
90744Sgs150176 
91744Sgs150176 	return (0);
92744Sgs150176 }
93744Sgs150176 
94744Sgs150176 static kstat_t *
rge_setup_named_kstat(rge_t * rgep,int instance,char * name,const rge_ksindex_t * ksip,size_t size,int (* update)(kstat_t *,int))95744Sgs150176 rge_setup_named_kstat(rge_t *rgep, int instance, char *name,
96744Sgs150176 	const rge_ksindex_t *ksip, size_t size, int (*update)(kstat_t *, int))
97744Sgs150176 {
98744Sgs150176 	kstat_t *ksp;
99744Sgs150176 	kstat_named_t *knp;
100744Sgs150176 	char *np;
101744Sgs150176 	int type;
102744Sgs150176 
103744Sgs150176 	size /= sizeof (rge_ksindex_t);
104744Sgs150176 	ksp = kstat_create(RGE_DRIVER_NAME, instance, name, "net",
105744Sgs150176 		KSTAT_TYPE_NAMED, size-1, KSTAT_FLAG_PERSISTENT);
106744Sgs150176 	if (ksp == NULL)
107744Sgs150176 		return (NULL);
108744Sgs150176 
109744Sgs150176 	ksp->ks_private = rgep;
110744Sgs150176 	ksp->ks_update = update;
111744Sgs150176 	for (knp = ksp->ks_data; (np = ksip->name) != NULL; ++knp, ++ksip) {
112744Sgs150176 		switch (*np) {
113744Sgs150176 		default:
114744Sgs150176 			type = KSTAT_DATA_UINT64;
115744Sgs150176 			break;
116744Sgs150176 		case '%':
117744Sgs150176 			np += 1;
118744Sgs150176 			type = KSTAT_DATA_UINT32;
119744Sgs150176 			break;
120744Sgs150176 		case '$':
121744Sgs150176 			np += 1;
122744Sgs150176 			type = KSTAT_DATA_STRING;
123744Sgs150176 			break;
124744Sgs150176 		case '&':
125744Sgs150176 			np += 1;
126744Sgs150176 			type = KSTAT_DATA_CHAR;
127744Sgs150176 			break;
128744Sgs150176 		}
129744Sgs150176 		kstat_named_init(knp, np, type);
130744Sgs150176 	}
131744Sgs150176 	kstat_install(ksp);
132744Sgs150176 
133744Sgs150176 	return (ksp);
134744Sgs150176 }
135744Sgs150176 
136744Sgs150176 void
rge_init_kstats(rge_t * rgep,int instance)137744Sgs150176 rge_init_kstats(rge_t *rgep, int instance)
138744Sgs150176 {
139744Sgs150176 	rgep->rge_kstats[RGE_KSTAT_DRIVER] = rge_setup_named_kstat(rgep,
140744Sgs150176 		instance, "driverinfo", rge_driverinfo,
141744Sgs150176 		sizeof (rge_driverinfo), rge_driverinfo_update);
142744Sgs150176 }
143744Sgs150176 
144744Sgs150176 void
rge_fini_kstats(rge_t * rgep)145744Sgs150176 rge_fini_kstats(rge_t *rgep)
146744Sgs150176 {
147744Sgs150176 	int i;
148744Sgs150176 
149744Sgs150176 	for (i = RGE_KSTAT_COUNT; --i >= 0; )
150744Sgs150176 		if (rgep->rge_kstats[i] != NULL) {
151744Sgs150176 			kstat_delete(rgep->rge_kstats[i]);
152744Sgs150176 		}
153744Sgs150176 }
154744Sgs150176 
1552311Sseb int
rge_m_stat(void * arg,uint_t stat,uint64_t * val)1562311Sseb rge_m_stat(void *arg, uint_t stat, uint64_t *val)
157744Sgs150176 {
158744Sgs150176 	rge_t *rgep = arg;
159744Sgs150176 	rge_hw_stats_t *bstp;
160744Sgs150176 
161744Sgs150176 	mutex_enter(rgep->genlock);
162744Sgs150176 	rge_hw_stats_dump(rgep);
163744Sgs150176 	mutex_exit(rgep->genlock);
164744Sgs150176 	bstp = rgep->hw_stats;
165744Sgs150176 
166744Sgs150176 	switch (stat) {
167744Sgs150176 	case MAC_STAT_IFSPEED:
1682311Sseb 		*val = rgep->param_link_speed * 1000000ull;
169744Sgs150176 		break;
170744Sgs150176 
171744Sgs150176 	case MAC_STAT_MULTIRCV:
1722311Sseb 		*val = RGE_BSWAP_32(bstp->multi_rcv);
173744Sgs150176 		break;
174744Sgs150176 
175744Sgs150176 	case MAC_STAT_BRDCSTRCV:
1762311Sseb 		*val = RGE_BSWAP_64(bstp->brdcst_rcv);
177744Sgs150176 		break;
178744Sgs150176 
179744Sgs150176 	case MAC_STAT_NORCVBUF:
1802311Sseb 		*val = RGE_BSWAP_16(bstp->in_discards);
181744Sgs150176 		break;
182744Sgs150176 
183744Sgs150176 	case MAC_STAT_IERRORS:
1842311Sseb 		*val = RGE_BSWAP_32(bstp->rcv_err);
185744Sgs150176 		break;
186744Sgs150176 
187744Sgs150176 	case MAC_STAT_OERRORS:
1882311Sseb 		*val = RGE_BSWAP_64(bstp->xmt_err);
189744Sgs150176 		break;
190744Sgs150176 
191744Sgs150176 	case MAC_STAT_COLLISIONS:
1922311Sseb 		*val = RGE_BSWAP_32(bstp->xmt_1col + bstp->xmt_mcol);
193744Sgs150176 		break;
194744Sgs150176 
195744Sgs150176 	case MAC_STAT_RBYTES:
1962311Sseb 		*val = rgep->stats.rbytes;
197744Sgs150176 		break;
198744Sgs150176 
199744Sgs150176 	case MAC_STAT_IPACKETS:
2002311Sseb 		*val = RGE_BSWAP_64(bstp->rcv_ok);
201744Sgs150176 		break;
202744Sgs150176 
203744Sgs150176 	case MAC_STAT_OBYTES:
2042311Sseb 		*val = rgep->stats.obytes;
205744Sgs150176 		break;
206744Sgs150176 
207744Sgs150176 	case MAC_STAT_OPACKETS:
2082311Sseb 		*val = RGE_BSWAP_64(bstp->xmt_ok);
209744Sgs150176 		break;
210744Sgs150176 
2112311Sseb 	case ETHER_STAT_ALIGN_ERRORS:
2122311Sseb 		*val = RGE_BSWAP_16(bstp->frame_err);
213744Sgs150176 		break;
214744Sgs150176 
2152311Sseb 	case ETHER_STAT_FIRST_COLLISIONS:
2162311Sseb 		*val = RGE_BSWAP_32(bstp->xmt_1col);
217744Sgs150176 		break;
218744Sgs150176 
2192311Sseb 	case ETHER_STAT_MULTI_COLLISIONS:
2202311Sseb 		*val = RGE_BSWAP_32(bstp->xmt_mcol);
221744Sgs150176 		break;
222744Sgs150176 
2232311Sseb 	case ETHER_STAT_DEFER_XMTS:
2242311Sseb 		*val = rgep->stats.defer;
225744Sgs150176 		break;
226744Sgs150176 
2272311Sseb 	case ETHER_STAT_XCVR_ADDR:
2282311Sseb 		*val = rgep->phy_mii_addr;
229744Sgs150176 		break;
230744Sgs150176 
2312311Sseb 	case ETHER_STAT_XCVR_ID:
232744Sgs150176 		mutex_enter(rgep->genlock);
2332311Sseb 		*val = rge_mii_get16(rgep, MII_PHYIDH);
2342311Sseb 		*val <<= 16;
2352311Sseb 		*val |= rge_mii_get16(rgep, MII_PHYIDL);
236744Sgs150176 		mutex_exit(rgep->genlock);
237744Sgs150176 		break;
238744Sgs150176 
2392311Sseb 	case ETHER_STAT_XCVR_INUSE:
2402311Sseb 		*val = XCVR_1000T;
241744Sgs150176 		break;
242744Sgs150176 
2432311Sseb 	case ETHER_STAT_CAP_1000FDX:
2442311Sseb 		*val = 1;
245744Sgs150176 		break;
246744Sgs150176 
2472311Sseb 	case ETHER_STAT_CAP_1000HDX:
2482311Sseb 		*val = 0;
249744Sgs150176 		break;
250744Sgs150176 
2512311Sseb 	case ETHER_STAT_CAP_100FDX:
2522311Sseb 		*val = 1;
253744Sgs150176 		break;
254744Sgs150176 
2552311Sseb 	case ETHER_STAT_CAP_100HDX:
2562311Sseb 		*val = 1;
257744Sgs150176 		break;
258744Sgs150176 
2592311Sseb 	case ETHER_STAT_CAP_10FDX:
2602311Sseb 		*val = 1;
261744Sgs150176 		break;
262744Sgs150176 
2632311Sseb 	case ETHER_STAT_CAP_10HDX:
2642311Sseb 		*val = 1;
265744Sgs150176 		break;
266744Sgs150176 
2672311Sseb 	case ETHER_STAT_CAP_ASMPAUSE:
2682311Sseb 		*val = 1;
269744Sgs150176 		break;
270744Sgs150176 
2712311Sseb 	case ETHER_STAT_CAP_PAUSE:
2722311Sseb 		*val = 1;
273744Sgs150176 		break;
274744Sgs150176 
2752311Sseb 	case ETHER_STAT_CAP_AUTONEG:
2762311Sseb 		*val = 1;
277744Sgs150176 		break;
278744Sgs150176 
2792311Sseb 	case ETHER_STAT_ADV_CAP_1000FDX:
2802311Sseb 		*val = rgep->param_adv_1000fdx;
281744Sgs150176 		break;
282744Sgs150176 
2832311Sseb 	case ETHER_STAT_ADV_CAP_1000HDX:
2842311Sseb 		*val = rgep->param_adv_1000hdx;
285744Sgs150176 		break;
286744Sgs150176 
2872311Sseb 	case ETHER_STAT_ADV_CAP_100FDX:
2882311Sseb 		*val = rgep->param_adv_100fdx;
289744Sgs150176 		break;
290744Sgs150176 
2912311Sseb 	case ETHER_STAT_ADV_CAP_100HDX:
2922311Sseb 		*val = rgep->param_adv_100hdx;
293744Sgs150176 		break;
294744Sgs150176 
2952311Sseb 	case ETHER_STAT_ADV_CAP_10FDX:
2962311Sseb 		*val = rgep->param_adv_10fdx;
297744Sgs150176 		break;
298744Sgs150176 
2992311Sseb 	case ETHER_STAT_ADV_CAP_10HDX:
3002311Sseb 		*val = rgep->param_adv_10hdx;
301744Sgs150176 		break;
302744Sgs150176 
3032311Sseb 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
3042311Sseb 		*val = rgep->param_adv_asym_pause;
305744Sgs150176 		break;
306744Sgs150176 
3072311Sseb 	case ETHER_STAT_ADV_CAP_PAUSE:
3082311Sseb 		*val = rgep->param_adv_pause;
309744Sgs150176 		break;
310744Sgs150176 
3112311Sseb 	case ETHER_STAT_ADV_CAP_AUTONEG:
3122311Sseb 		*val = rgep->param_adv_autoneg;
3132311Sseb 		break;
3142311Sseb 
3152311Sseb 	case ETHER_STAT_LINK_DUPLEX:
3162311Sseb 		*val = rgep->param_link_duplex;
3172311Sseb 		break;
3182311Sseb 
319744Sgs150176 	default:
3202311Sseb 		return (ENOTSUP);
321744Sgs150176 	}
322744Sgs150176 
3232311Sseb 	return (0);
324744Sgs150176 }
325