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