xref: /illumos-gate/usr/src/uts/common/io/nge/nge_kstats.c (revision 2b55f462)
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 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 
28 #include "nge.h"
29 
30 #undef	NGE_DBG
31 #define	NGE_DBG		NGE_DBG_STATS	/* debug flag for this code	*/
32 
33 /*
34  * Table of Hardware-defined Statistics Block Offsets and Names
35  */
36 #define	KS_NAME(s)			{ KS_ ## s, #s }
37 
38 const nge_ksindex_t nge_statistics[] = {
39 
40 	KS_NAME(ifHOutOctets),
41 	KS_NAME(ifHOutZeroRetranCount),
42 	KS_NAME(ifHOutOneRetranCount),
43 	KS_NAME(ifHOutMoreRetranCount),
44 	KS_NAME(ifHOutColCount),
45 	KS_NAME(ifHOutFifoovCount),
46 	KS_NAME(ifHOutLOCCount),
47 	KS_NAME(ifHOutExDecCount),
48 	KS_NAME(ifHOutRetryCount),
49 	KS_NAME(ifHInFrameErrCount),
50 	KS_NAME(ifHInExtraOctErrCount),
51 	KS_NAME(ifHInLColErrCount),
52 	KS_NAME(ifHInOversizeErrCount),
53 	KS_NAME(ifHInFovErrCount),
54 	KS_NAME(ifHInFCSErrCount),
55 	KS_NAME(ifHInAlignErrCount),
56 	KS_NAME(ifHInLenErrCount),
57 	KS_NAME(ifHInUniPktsCount),
58 	KS_NAME(ifHInBroadPksCount),
59 	KS_NAME(ifHInMulPksCount),
60 	{ KS_STATS_SIZE, NULL }
61 };
62 
63 /*
64  * Local datatype for defining tables of (Offset, Name) pairs
65  */
66 static int
nge_statistics_update(kstat_t * ksp,int flag)67 nge_statistics_update(kstat_t *ksp, int flag)
68 {
69 	uint32_t regno;
70 	nge_t *ngep;
71 	nge_statistics_t *istp;
72 	nge_hw_statistics_t *hw_stp;
73 	kstat_named_t *knp;
74 	const nge_ksindex_t *ksip;
75 
76 	if (flag != KSTAT_READ)
77 		return (EACCES);
78 
79 	ngep = ksp->ks_private;
80 	istp = &ngep->statistics;
81 	hw_stp = &istp->hw_statistics;
82 	knp = ksp->ks_data;
83 
84 	/*
85 	 * Transfer the statistics values from the hardware statistics regs
86 	 */
87 	for (ksip = nge_statistics; ksip->name != NULL; ++knp, ++ksip) {
88 		regno = KS_BASE + ksip->index * sizeof (uint32_t);
89 		hw_stp->a[ksip->index] += nge_reg_get32(ngep, regno);
90 		knp->value.ui64 = hw_stp->a[ksip->index];
91 	}
92 
93 	return (0);
94 }
95 
96 
97 static const nge_ksindex_t nge_chipinfo[] = {
98 	{ 0,				"businfo"		},
99 	{ 1,				"command"		},
100 	{ 2,				"vendor_id"		},
101 	{ 3,				"device_id"		},
102 	{ 4,				"subsystem_vendor_id"	},
103 	{ 5,				"subsystem_device_id"	},
104 	{ 6,				"revision_id"		},
105 	{ 7,				"cache_line_size"	},
106 	{ 8,				"latency_timer"		},
107 	{ 9,				"phy_mode"		},
108 	{ 10,				"phy_id"		},
109 	{ 11,				"hw_mac_addr"		},
110 	{ 12,				"&bus_type"		},
111 	{ 13,				"&bus_speed"		},
112 	{ 14,				"&bus_size"		},
113 	{ -1,				NULL 			}
114 };
115 
116 static const nge_ksindex_t nge_debuginfo[] = {
117 	{ 0,				"rx_realloc"		},
118 	{ 1,				"rx_realloc_fails"	},
119 	{ 2,				"rx_realloc_DMA_fails"	},
120 	{ 3,				"rx_realloc_MP_fails"	},
121 	{ 4,				"rx_rcfree"		},
122 	{ 5,				"context_switch"	},
123 	{ 6,				"ip_hsum_err"		},
124 	{ 7,				"tcp_hsum_err"		},
125 	{ 8,				"tc_next"		},
126 	{ 9,				"tx_next"		},
127 	{ 10,				"tx_free"		},
128 	{ 11,				"tx_flow"		},
129 	{ 12,				"rx_prod"		},
130 	{ 13,				"rx_hold"		},
131 	{ 14,				"rx_nobuf"		},
132 	{ 15,				"rx_err"		},
133 	{16,				"tx_err"		},
134 	{17,				"tx_stall"		},
135 	{ -1,				NULL 			}
136 };
137 
138 static int
nge_chipinfo_update(kstat_t * ksp,int flag)139 nge_chipinfo_update(kstat_t *ksp, int flag)
140 {
141 	nge_t *ngep;
142 	kstat_named_t *knp;
143 	chip_info_t *infop;
144 
145 	if (flag != KSTAT_READ)
146 		return (EACCES);
147 
148 	ngep = ksp->ks_private;
149 	infop = &ngep->chipinfo;
150 	knp = ksp->ks_data;
151 
152 	(knp++)->value.ui64 = infop->businfo;
153 	(knp++)->value.ui64 = infop->command;
154 	(knp++)->value.ui64 = infop->vendor;
155 	(knp++)->value.ui64 = infop->device;
156 	(knp++)->value.ui64 = infop->subven;
157 	(knp++)->value.ui64 = infop->subdev;
158 	(knp++)->value.ui64 = infop->revision;
159 	(knp++)->value.ui64 = infop->clsize;
160 	(knp++)->value.ui64 = infop->latency;
161 	(knp++)->value.ui64 = ngep->phy_mode;
162 	(knp++)->value.ui64 = ngep->phy_id;
163 	(knp++)->value.ui64 = infop->hw_mac_addr;
164 	return (0);
165 }
166 
167 static int
nge_debuginfo_update(kstat_t * ksp,int flag)168 nge_debuginfo_update(kstat_t *ksp, int flag)
169 {
170 	nge_t *ngep;
171 	kstat_named_t *knp;
172 	nge_sw_statistics_t *sw_stp;
173 
174 	if (flag != KSTAT_READ)
175 		return (EACCES);
176 
177 	ngep = ksp->ks_private;
178 	sw_stp = &ngep->statistics.sw_statistics;
179 	knp = ksp->ks_data;
180 
181 	(knp++)->value.ui64 = sw_stp->recv_realloc;
182 	(knp++)->value.ui64 = sw_stp->kmem_alloc_err;
183 	(knp++)->value.ui64 = sw_stp->dma_alloc_err;
184 	(knp++)->value.ui64 = sw_stp->mp_alloc_err;
185 	(knp++)->value.ui64 = sw_stp->recy_free;
186 	(knp++)->value.ui64 = sw_stp->load_context;
187 	(knp++)->value.ui64 = sw_stp->ip_hwsum_err;
188 	(knp++)->value.ui64 = sw_stp->tcp_hwsum_err;
189 	(knp++)->value.ui64 = ngep->send->tc_next;
190 	(knp++)->value.ui64 = ngep->send->tx_next;
191 	(knp++)->value.ui64 = ngep->send->tx_free;
192 	(knp++)->value.ui64 = ngep->send->tx_flow;
193 	(knp++)->value.ui64 = ngep->recv->prod_index;
194 	(knp++)->value.ui64 = ngep->buff->rx_hold;
195 	(knp++)->value.ui64 = sw_stp->rx_nobuffer;
196 	(knp++)->value.ui64 = sw_stp->rx_err;
197 	(knp++)->value.ui64 = sw_stp->tx_stop_err;
198 	(knp++)->value.ui64 = sw_stp->tx_stall;
199 	return (0);
200 }
201 
202 static kstat_t *
nge_setup_named_kstat(nge_t * ngep,int instance,char * name,const nge_ksindex_t * ksip,size_t size,int (* update)(kstat_t *,int))203 nge_setup_named_kstat(nge_t *ngep, int instance, char *name,
204 	const nge_ksindex_t *ksip, size_t size, int (*update)(kstat_t *, int))
205 {
206 	kstat_t *ksp;
207 	kstat_named_t *knp;
208 	char *np;
209 	int type;
210 
211 	size /= sizeof (nge_ksindex_t);
212 	ksp = kstat_create(NGE_DRIVER_NAME, instance, name, "net",
213 	    KSTAT_TYPE_NAMED, size-1, KSTAT_FLAG_PERSISTENT);
214 	if (ksp == NULL)
215 		return (NULL);
216 
217 	ksp->ks_private = ngep;
218 	ksp->ks_update = update;
219 	for (knp = ksp->ks_data; (np = ksip->name) != NULL; ++knp, ++ksip) {
220 		switch (*np) {
221 		default:
222 			type = KSTAT_DATA_UINT64;
223 			break;
224 		case '%':
225 			np += 1;
226 			type = KSTAT_DATA_UINT32;
227 			break;
228 
229 		case '$':
230 			np ++;
231 			type = KSTAT_DATA_STRING;
232 			break;
233 		case '&':
234 			np ++;
235 			type = KSTAT_DATA_CHAR;
236 			break;
237 		}
238 		kstat_named_init(knp, np, type);
239 	}
240 	kstat_install(ksp);
241 
242 	return (ksp);
243 }
244 
245 void
nge_init_kstats(nge_t * ngep,int instance)246 nge_init_kstats(nge_t *ngep, int instance)
247 {
248 	NGE_TRACE(("nge_init_kstats($%p, %d)", (void *)ngep, instance));
249 
250 	ngep->nge_kstats[NGE_KSTAT_STATS] = nge_setup_named_kstat(ngep,
251 	    instance, "statistics", nge_statistics,
252 	    sizeof (nge_statistics), nge_statistics_update);
253 
254 	ngep->nge_kstats[NGE_KSTAT_CHIPID] = nge_setup_named_kstat(ngep,
255 	    instance, "chipinfo", nge_chipinfo,
256 	    sizeof (nge_chipinfo), nge_chipinfo_update);
257 
258 	ngep->nge_kstats[NGE_KSTAT_DEBUG] = nge_setup_named_kstat(ngep,
259 	    instance, "driver-debug", nge_debuginfo,
260 	    sizeof (nge_debuginfo), nge_debuginfo_update);
261 
262 }
263 
264 void
nge_fini_kstats(nge_t * ngep)265 nge_fini_kstats(nge_t *ngep)
266 {
267 	int i;
268 
269 	NGE_TRACE(("nge_fini_kstats($%p)", (void *)ngep));
270 	for (i = NGE_KSTAT_COUNT;  --i >= 0; )
271 		if (ngep->nge_kstats[i] != NULL)
272 			kstat_delete(ngep->nge_kstats[i]);
273 }
274 
275 int
nge_m_stat(void * arg,uint_t stat,uint64_t * val)276 nge_m_stat(void *arg, uint_t stat, uint64_t *val)
277 {
278 	nge_t *ngep = arg;
279 	uint32_t regno;
280 	nge_statistics_t *nstp = &ngep->statistics;
281 	nge_hw_statistics_t *hw_stp = &nstp->hw_statistics;
282 	nge_sw_statistics_t *sw_stp = &nstp->sw_statistics;
283 
284 	switch (stat) {
285 	case MAC_STAT_IFSPEED:
286 		*val = ngep->param_link_speed * 1000000ull;
287 		break;
288 
289 	case MAC_STAT_MULTIRCV:
290 		regno = KS_BASE + KS_ifHInMulPksCount * sizeof (uint32_t);
291 		hw_stp->s.InMulPksCount += nge_reg_get32(ngep, regno);
292 		*val = hw_stp->s.InMulPksCount;
293 		break;
294 
295 	case MAC_STAT_BRDCSTRCV:
296 		regno = KS_BASE +  KS_ifHInBroadPksCount * sizeof (uint32_t);
297 		hw_stp->s.InBroadPksCount += nge_reg_get32(ngep, regno);
298 		*val = hw_stp->s.InBroadPksCount;
299 		break;
300 
301 	case MAC_STAT_NORCVBUF:
302 		*val = sw_stp->rx_nobuffer;
303 		break;
304 
305 	case MAC_STAT_IERRORS:
306 		regno = KS_BASE + KS_ifHInFrameErrCount * sizeof (uint32_t);
307 		hw_stp->s.InFrameErrCount += nge_reg_get32(ngep, regno);
308 		regno = KS_BASE + KS_ifHInExtraOctErrCount * sizeof (uint32_t);
309 		hw_stp->s.InExtraOctErrCount += nge_reg_get32(ngep, regno);
310 		regno = KS_BASE + KS_ifHInLColErrCount * sizeof (uint32_t);
311 		hw_stp->s.InLColErrCount += nge_reg_get32(ngep, regno);
312 		regno = KS_BASE + KS_ifHInOversizeErrCount * sizeof (uint32_t);
313 		hw_stp->s.InOversizeErrCount += nge_reg_get32(ngep, regno);
314 		regno = KS_BASE + KS_ifHInFovErrCount * sizeof (uint32_t);
315 		hw_stp->s.InFovErrCount += nge_reg_get32(ngep, regno);
316 		regno = KS_BASE + KS_ifHInFCSErrCount * sizeof (uint32_t);
317 		hw_stp->s.InFCSErrCount += nge_reg_get32(ngep, regno);
318 		regno = KS_BASE + KS_ifHInAlignErrCount * sizeof (uint32_t);
319 		hw_stp->s.InAlignErrCount += nge_reg_get32(ngep, regno);
320 		regno = KS_BASE + KS_ifHInLenErrCount * sizeof (uint32_t);
321 		hw_stp->s.InLenErrCount += nge_reg_get32(ngep, regno);
322 		*val = hw_stp->s.InFrameErrCount +
323 		    hw_stp->s.InExtraOctErrCount +
324 		    hw_stp->s.InLColErrCount +
325 		    hw_stp->s.InOversizeErrCount +
326 		    hw_stp->s.InFovErrCount +
327 		    hw_stp->s.InFCSErrCount +
328 		    hw_stp->s.InAlignErrCount +
329 		    hw_stp->s.InLenErrCount;
330 		break;
331 
332 	case MAC_STAT_OERRORS:
333 		regno = KS_BASE + KS_ifHOutFifoovCount * sizeof (uint32_t);
334 		hw_stp->s.OutFifoovCount += nge_reg_get32(ngep, regno);
335 		regno = KS_BASE + KS_ifHOutLOCCount * sizeof (uint32_t);
336 		hw_stp->s.OutLOCCount += nge_reg_get32(ngep, regno);
337 		regno = KS_BASE + KS_ifHOutExDecCount * sizeof (uint32_t);
338 		hw_stp->s.OutExDecCount += nge_reg_get32(ngep, regno);
339 		regno = KS_BASE + KS_ifHOutRetryCount * sizeof (uint32_t);
340 		hw_stp->s.OutRetryCount += nge_reg_get32(ngep, regno);
341 		*val = hw_stp->s.OutFifoovCount +
342 		    hw_stp->s.OutLOCCount +
343 		    hw_stp->s.OutExDecCount +
344 		    hw_stp->s.OutRetryCount;
345 		break;
346 
347 	case MAC_STAT_COLLISIONS:
348 		regno = KS_BASE + KS_ifHOutColCount * sizeof (uint32_t);
349 		hw_stp->s.OutColCount += nge_reg_get32(ngep, regno);
350 		*val = hw_stp->s.OutColCount;
351 		break;
352 
353 	case MAC_STAT_RBYTES:
354 		*val = sw_stp->rbytes;
355 		break;
356 
357 	case MAC_STAT_IPACKETS:
358 		*val = sw_stp->recv_count;
359 		break;
360 
361 	case MAC_STAT_OBYTES:
362 		*val = sw_stp->obytes;
363 		break;
364 
365 	case MAC_STAT_OPACKETS:
366 		*val = sw_stp->xmit_count;
367 		break;
368 
369 	case ETHER_STAT_ALIGN_ERRORS:
370 		regno = KS_BASE + KS_ifHInAlignErrCount * sizeof (uint32_t);
371 		hw_stp->s.InAlignErrCount += nge_reg_get32(ngep, regno);
372 		*val = hw_stp->s.InAlignErrCount;
373 		break;
374 
375 	case ETHER_STAT_FCS_ERRORS:
376 		regno = KS_BASE + KS_ifHInFCSErrCount * sizeof (uint32_t);
377 		hw_stp->s.InFCSErrCount += nge_reg_get32(ngep, regno);
378 		*val = hw_stp->s.InFCSErrCount;
379 		break;
380 
381 	case ETHER_STAT_FIRST_COLLISIONS:
382 		regno = KS_BASE + KS_ifHOutOneRetranCount * sizeof (uint32_t);
383 		hw_stp->s.OutOneRetranCount += nge_reg_get32(ngep, regno);
384 		*val = hw_stp->s.OutOneRetranCount;
385 		break;
386 
387 	case ETHER_STAT_MULTI_COLLISIONS:
388 		regno = KS_BASE + KS_ifHOutMoreRetranCount * sizeof (uint32_t);
389 		hw_stp->s.OutMoreRetranCount += nge_reg_get32(ngep, regno);
390 		*val =  hw_stp->s.OutMoreRetranCount;
391 		break;
392 
393 	case ETHER_STAT_DEFER_XMTS:
394 		regno = KS_BASE + KS_ifHOutExDecCount * sizeof (uint32_t);
395 		hw_stp->s.OutExDecCount += nge_reg_get32(ngep, regno);
396 		*val = hw_stp->s.OutExDecCount;
397 		break;
398 
399 	case ETHER_STAT_TX_LATE_COLLISIONS:
400 		regno = KS_BASE + KS_ifHOutColCount * sizeof (uint32_t);
401 		hw_stp->s.OutColCount += nge_reg_get32(ngep, regno);
402 		*val = hw_stp->s.OutColCount;
403 		break;
404 
405 	case ETHER_STAT_EX_COLLISIONS:
406 		regno = KS_BASE + KS_ifHOutOneRetranCount * sizeof (uint32_t);
407 		hw_stp->s.OutOneRetranCount += nge_reg_get32(ngep, regno);
408 		*val = hw_stp->s.OutOneRetranCount;
409 		break;
410 
411 	case ETHER_STAT_CARRIER_ERRORS:
412 		regno = KS_BASE + KS_ifHOutLOCCount * sizeof (uint32_t);
413 		hw_stp->s.OutLOCCount += nge_reg_get32(ngep, regno);
414 		*val = hw_stp->s.OutLOCCount;
415 		break;
416 
417 	case ETHER_STAT_TOOLONG_ERRORS:
418 		regno = KS_BASE + KS_ifHInOversizeErrCount * sizeof (uint32_t);
419 		hw_stp->s.InOversizeErrCount += nge_reg_get32(ngep, regno);
420 		*val = hw_stp->s.InOversizeErrCount;
421 		break;
422 
423 	case ETHER_STAT_XCVR_ADDR:
424 		*val = ngep->phy_xmii_addr;
425 		break;
426 
427 	case ETHER_STAT_XCVR_ID:
428 		*val = ngep->phy_id;
429 		break;
430 
431 	case ETHER_STAT_XCVR_INUSE:
432 		*val = XCVR_1000T;
433 		break;
434 
435 	case ETHER_STAT_CAP_1000FDX:
436 		*val = 1;
437 		break;
438 
439 	case ETHER_STAT_CAP_1000HDX:
440 		*val = 0;
441 		break;
442 
443 	case ETHER_STAT_CAP_100FDX:
444 		*val = 1;
445 		break;
446 
447 	case ETHER_STAT_CAP_100HDX:
448 		*val = 1;
449 		break;
450 
451 	case ETHER_STAT_CAP_10FDX:
452 		*val = 1;
453 		break;
454 
455 	case ETHER_STAT_CAP_10HDX:
456 		*val = 1;
457 		break;
458 
459 	case ETHER_STAT_CAP_ASMPAUSE:
460 		*val = 1;
461 		break;
462 
463 	case ETHER_STAT_CAP_PAUSE:
464 		*val = 1;
465 		break;
466 
467 	case ETHER_STAT_CAP_AUTONEG:
468 		*val = 1;
469 		break;
470 
471 	case ETHER_STAT_ADV_CAP_1000FDX:
472 		*val = ngep->param_adv_1000fdx;
473 		break;
474 
475 	case ETHER_STAT_ADV_CAP_1000HDX:
476 		*val = ngep->param_adv_1000hdx;
477 		break;
478 
479 	case ETHER_STAT_ADV_CAP_100FDX:
480 		*val = ngep->param_adv_100fdx;
481 		break;
482 
483 	case ETHER_STAT_ADV_CAP_100HDX:
484 		*val = ngep->param_adv_100hdx;
485 		break;
486 
487 	case ETHER_STAT_ADV_CAP_10FDX:
488 		*val = ngep->param_adv_10fdx;
489 		break;
490 
491 	case ETHER_STAT_ADV_CAP_10HDX:
492 		*val = ngep->param_adv_10hdx;
493 		break;
494 
495 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
496 		*val = ngep->param_adv_asym_pause;
497 		break;
498 
499 	case ETHER_STAT_ADV_CAP_PAUSE:
500 		*val = ngep->param_adv_pause;
501 		break;
502 
503 	case ETHER_STAT_ADV_CAP_AUTONEG:
504 		*val = ngep->param_adv_autoneg;
505 		break;
506 
507 	case ETHER_STAT_LP_CAP_1000FDX:
508 		*val = ngep->param_lp_1000fdx;
509 		break;
510 
511 	case ETHER_STAT_LP_CAP_1000HDX:
512 		*val = ngep->param_lp_1000hdx;
513 		break;
514 
515 	case ETHER_STAT_LP_CAP_100FDX:
516 		*val = ngep->param_lp_100fdx;
517 		break;
518 
519 	case ETHER_STAT_LP_CAP_100HDX:
520 		*val = ngep->param_lp_100hdx;
521 		break;
522 
523 	case ETHER_STAT_LP_CAP_10FDX:
524 		*val = ngep->param_lp_10fdx;
525 		break;
526 
527 	case ETHER_STAT_LP_CAP_10HDX:
528 		*val = ngep->param_lp_10hdx;
529 		break;
530 
531 	case ETHER_STAT_LP_CAP_ASMPAUSE:
532 		*val = ngep->param_lp_asym_pause;
533 		break;
534 
535 	case ETHER_STAT_LP_CAP_PAUSE:
536 		*val = ngep->param_lp_pause;
537 		break;
538 
539 	case ETHER_STAT_LP_CAP_AUTONEG:
540 		*val = ngep->param_lp_autoneg;
541 		break;
542 
543 	case ETHER_STAT_LINK_ASMPAUSE:
544 		*val = ngep->param_adv_asym_pause &&
545 		    ngep->param_lp_asym_pause &&
546 		    ngep->param_adv_pause != ngep->param_lp_pause;
547 		break;
548 
549 	case ETHER_STAT_LINK_PAUSE:
550 		*val = ngep->param_link_rx_pause;
551 		break;
552 
553 	case ETHER_STAT_LINK_AUTONEG:
554 		*val = ngep->param_link_autoneg;
555 		break;
556 
557 	case ETHER_STAT_LINK_DUPLEX:
558 		*val = ngep->param_link_duplex;
559 		break;
560 
561 	case ETHER_STAT_CAP_100T4:
562 	case ETHER_STAT_LP_CAP_100T4:
563 		*val = 0;
564 		break;
565 
566 	default:
567 		return (ENOTSUP);
568 	}
569 
570 	return (0);
571 }
572