xref: /illumos-gate/usr/src/uts/common/io/rge/rge_kstats.c (revision 0173c38a73f34277e0c97a19fedfd25d81ba8380)
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  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include "rge.h"
29 
30 #define	RGE_DBG		RGE_DBG_STATS	/* debug flag for this code	*/
31 
32 /*
33  * Local datatype for defining tables of (Offset, Name) pairs
34  */
35 typedef struct {
36 	offset_t	index;
37 	char		*name;
38 } rge_ksindex_t;
39 
40 static int
41 rge_params_update(kstat_t *ksp, int flag)
42 {
43 	rge_t *rgep;
44 	kstat_named_t *knp;
45 	int i;
46 
47 	if (flag != KSTAT_READ)
48 		return (EACCES);
49 
50 	rgep = ksp->ks_private;
51 	for (knp = ksp->ks_data, i = 0; i < PARAM_COUNT; ++knp, ++i)
52 		knp->value.ui64 = rgep->nd_params[i].ndp_val;
53 
54 	return (0);
55 }
56 
57 
58 static const rge_ksindex_t rge_driverinfo[] = {
59 	{ 0,		"rx_ring_addr"		},
60 	{ 1,		"rx_next"		},
61 	{ 2,		"rx_free"		},
62 	{ 3,		"rx_bcopy"		},
63 	{ 4,		"tx_ring_addr"		},
64 	{ 5,		"tx_next"		},
65 	{ 6,		"tx_free"		},
66 	{ 7,		"tx_flow"		},
67 	{ 8,		"resched_needed"	},
68 	{ 9,		"watchdog"		},
69 	{ 10,		"rx_config"		},
70 	{ 11,		"tx_config"		},
71 	{ 12,		"mac_ver"		},
72 	{ 13,		"phy_ver"		},
73 	{ 14,		"chip_reset"		},
74 	{ 15,		"phy_reset"		},
75 	{ -1,		NULL 			}
76 };
77 
78 static int
79 rge_driverinfo_update(kstat_t *ksp, int flag)
80 {
81 	rge_t *rgep;
82 	kstat_named_t *knp;
83 
84 	if (flag != KSTAT_READ)
85 		return (EACCES);
86 
87 	rgep = ksp->ks_private;
88 	knp = ksp->ks_data;
89 
90 	(knp++)->value.ui64 = rgep->dma_area_rxdesc.cookie.dmac_laddress;
91 	(knp++)->value.ui64 = rgep->rx_next;
92 	(knp++)->value.ui64 = rgep->rx_free;
93 	(knp++)->value.ui64 = rgep->rx_bcopy;
94 	(knp++)->value.ui64 = rgep->dma_area_txdesc.cookie.dmac_laddress;
95 	(knp++)->value.ui64 = rgep->tx_next;
96 	(knp++)->value.ui64 = rgep->tx_free;
97 	(knp++)->value.ui64 = rgep->tx_flow;
98 	(knp++)->value.ui64 = rgep->resched_needed;
99 	(knp++)->value.ui64 = rgep->watchdog;
100 	(knp++)->value.ui64 = rgep->chipid.rxconfig;
101 	(knp++)->value.ui64 = rgep->chipid.txconfig;
102 	(knp++)->value.ui64 = rgep->chipid.mac_ver;
103 	(knp++)->value.ui64 = rgep->chipid.phy_ver;
104 	(knp++)->value.ui64 = rgep->stats.chip_reset;
105 	(knp++)->value.ui64 = rgep->stats.phy_reset;
106 
107 	return (0);
108 }
109 
110 static kstat_t *
111 rge_setup_named_kstat(rge_t *rgep, int instance, char *name,
112 	const rge_ksindex_t *ksip, size_t size, int (*update)(kstat_t *, int))
113 {
114 	kstat_t *ksp;
115 	kstat_named_t *knp;
116 	char *np;
117 	int type;
118 
119 	size /= sizeof (rge_ksindex_t);
120 	ksp = kstat_create(RGE_DRIVER_NAME, instance, name, "net",
121 		KSTAT_TYPE_NAMED, size-1, KSTAT_FLAG_PERSISTENT);
122 	if (ksp == NULL)
123 		return (NULL);
124 
125 	ksp->ks_private = rgep;
126 	ksp->ks_update = update;
127 	for (knp = ksp->ks_data; (np = ksip->name) != NULL; ++knp, ++ksip) {
128 		switch (*np) {
129 		default:
130 			type = KSTAT_DATA_UINT64;
131 			break;
132 		case '%':
133 			np += 1;
134 			type = KSTAT_DATA_UINT32;
135 			break;
136 		case '$':
137 			np += 1;
138 			type = KSTAT_DATA_STRING;
139 			break;
140 		case '&':
141 			np += 1;
142 			type = KSTAT_DATA_CHAR;
143 			break;
144 		}
145 		kstat_named_init(knp, np, type);
146 	}
147 	kstat_install(ksp);
148 
149 	return (ksp);
150 }
151 
152 /*
153  * Create kstats corresponding to NDD parameters
154  */
155 static kstat_t *
156 rge_setup_params_kstat(rge_t *rgep, int instance, char *name,
157 	int (*update)(kstat_t *, int))
158 {
159 	kstat_t *ksp;
160 	kstat_named_t *knp;
161 	int i;
162 
163 	ksp = kstat_create(RGE_DRIVER_NAME, instance, name, "net",
164 		KSTAT_TYPE_NAMED, PARAM_COUNT, KSTAT_FLAG_PERSISTENT);
165 	if (ksp != NULL) {
166 		ksp->ks_private = rgep;
167 		ksp->ks_update = update;
168 		for (knp = ksp->ks_data, i = 0; i < PARAM_COUNT; ++knp, ++i)
169 			kstat_named_init(knp, rgep->nd_params[i].ndp_name+1,
170 				KSTAT_DATA_UINT64);
171 		kstat_install(ksp);
172 	}
173 
174 	return (ksp);
175 }
176 
177 void
178 rge_init_kstats(rge_t *rgep, int instance)
179 {
180 	rgep->rge_kstats[RGE_KSTAT_PARAMS] = rge_setup_params_kstat(rgep,
181 		instance, "parameters", rge_params_update);
182 
183 	rgep->rge_kstats[RGE_KSTAT_DRIVER] = rge_setup_named_kstat(rgep,
184 		instance, "driverinfo", rge_driverinfo,
185 		sizeof (rge_driverinfo), rge_driverinfo_update);
186 }
187 
188 void
189 rge_fini_kstats(rge_t *rgep)
190 {
191 	int i;
192 
193 	for (i = RGE_KSTAT_COUNT; --i >= 0; )
194 		if (rgep->rge_kstats[i] != NULL) {
195 			kstat_delete(rgep->rge_kstats[i]);
196 		}
197 }
198 
199 int
200 rge_m_stat(void *arg, uint_t stat, uint64_t *val)
201 {
202 	rge_t *rgep = arg;
203 	rge_hw_stats_t *bstp;
204 
205 	mutex_enter(rgep->genlock);
206 	rge_hw_stats_dump(rgep);
207 	mutex_exit(rgep->genlock);
208 	bstp = rgep->hw_stats;
209 
210 	switch (stat) {
211 	case MAC_STAT_IFSPEED:
212 		*val = rgep->param_link_speed * 1000000ull;
213 		break;
214 
215 	case MAC_STAT_MULTIRCV:
216 		*val = RGE_BSWAP_32(bstp->multi_rcv);
217 		break;
218 
219 	case MAC_STAT_BRDCSTRCV:
220 		*val = RGE_BSWAP_64(bstp->brdcst_rcv);
221 		break;
222 
223 	case MAC_STAT_NORCVBUF:
224 		*val = RGE_BSWAP_16(bstp->in_discards);
225 		break;
226 
227 	case MAC_STAT_IERRORS:
228 		*val = RGE_BSWAP_32(bstp->rcv_err);
229 		break;
230 
231 	case MAC_STAT_OERRORS:
232 		*val = RGE_BSWAP_64(bstp->xmt_err);
233 		break;
234 
235 	case MAC_STAT_COLLISIONS:
236 		*val = RGE_BSWAP_32(bstp->xmt_1col + bstp->xmt_mcol);
237 		break;
238 
239 	case MAC_STAT_RBYTES:
240 		*val = rgep->stats.rbytes;
241 		break;
242 
243 	case MAC_STAT_IPACKETS:
244 		*val = RGE_BSWAP_64(bstp->rcv_ok);
245 		break;
246 
247 	case MAC_STAT_OBYTES:
248 		*val = rgep->stats.obytes;
249 		break;
250 
251 	case MAC_STAT_OPACKETS:
252 		*val = RGE_BSWAP_64(bstp->xmt_ok);
253 		break;
254 
255 	case ETHER_STAT_ALIGN_ERRORS:
256 		*val = RGE_BSWAP_16(bstp->frame_err);
257 		break;
258 
259 	case ETHER_STAT_FIRST_COLLISIONS:
260 		*val = RGE_BSWAP_32(bstp->xmt_1col);
261 		break;
262 
263 	case ETHER_STAT_MULTI_COLLISIONS:
264 		*val = RGE_BSWAP_32(bstp->xmt_mcol);
265 		break;
266 
267 	case ETHER_STAT_DEFER_XMTS:
268 		*val = rgep->stats.defer;
269 		break;
270 
271 	case ETHER_STAT_XCVR_ADDR:
272 		*val = rgep->phy_mii_addr;
273 		break;
274 
275 	case ETHER_STAT_XCVR_ID:
276 		mutex_enter(rgep->genlock);
277 		*val = rge_mii_get16(rgep, MII_PHYIDH);
278 		*val <<= 16;
279 		*val |= rge_mii_get16(rgep, MII_PHYIDL);
280 		mutex_exit(rgep->genlock);
281 		break;
282 
283 	case ETHER_STAT_XCVR_INUSE:
284 		*val = XCVR_1000T;
285 		break;
286 
287 	case ETHER_STAT_CAP_1000FDX:
288 		*val = 1;
289 		break;
290 
291 	case ETHER_STAT_CAP_1000HDX:
292 		*val = 0;
293 		break;
294 
295 	case ETHER_STAT_CAP_100FDX:
296 		*val = 1;
297 		break;
298 
299 	case ETHER_STAT_CAP_100HDX:
300 		*val = 1;
301 		break;
302 
303 	case ETHER_STAT_CAP_10FDX:
304 		*val = 1;
305 		break;
306 
307 	case ETHER_STAT_CAP_10HDX:
308 		*val = 1;
309 		break;
310 
311 	case ETHER_STAT_CAP_ASMPAUSE:
312 		*val = 1;
313 		break;
314 
315 	case ETHER_STAT_CAP_PAUSE:
316 		*val = 1;
317 		break;
318 
319 	case ETHER_STAT_CAP_AUTONEG:
320 		*val = 1;
321 		break;
322 
323 	case ETHER_STAT_ADV_CAP_1000FDX:
324 		*val = rgep->param_adv_1000fdx;
325 		break;
326 
327 	case ETHER_STAT_ADV_CAP_1000HDX:
328 		*val = rgep->param_adv_1000hdx;
329 		break;
330 
331 	case ETHER_STAT_ADV_CAP_100FDX:
332 		*val = rgep->param_adv_100fdx;
333 		break;
334 
335 	case ETHER_STAT_ADV_CAP_100HDX:
336 		*val = rgep->param_adv_100hdx;
337 		break;
338 
339 	case ETHER_STAT_ADV_CAP_10FDX:
340 		*val = rgep->param_adv_10fdx;
341 		break;
342 
343 	case ETHER_STAT_ADV_CAP_10HDX:
344 		*val = rgep->param_adv_10hdx;
345 		break;
346 
347 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
348 		*val = rgep->param_adv_asym_pause;
349 		break;
350 
351 	case ETHER_STAT_ADV_CAP_PAUSE:
352 		*val = rgep->param_adv_pause;
353 		break;
354 
355 	case ETHER_STAT_ADV_CAP_AUTONEG:
356 		*val = rgep->param_adv_autoneg;
357 		break;
358 
359 	case ETHER_STAT_LINK_DUPLEX:
360 		*val = rgep->param_link_duplex;
361 		break;
362 
363 	default:
364 		return (ENOTSUP);
365 	}
366 
367 	return (0);
368 }
369