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