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