1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2024 Oxide Computer Company
14 */
15
16 /*
17 * This implements the stat routines that interface with the hardware directly.
18 */
19
20 #include "igc.h"
21
22 void
igc_stats_fini(igc_t * igc)23 igc_stats_fini(igc_t *igc)
24 {
25 if (igc->igc_ksp != NULL) {
26 kstat_delete(igc->igc_ksp);
27 igc->igc_ksp = NULL;
28 }
29 }
30
31 /*
32 * Read a pair of low and high registers to get a stat. The low register must
33 * come ahead of the high.
34 */
35 void
igc_stats_update_u64(igc_t * igc,kstat_named_t * ks,uint32_t reg)36 igc_stats_update_u64(igc_t *igc, kstat_named_t *ks, uint32_t reg)
37 {
38 uint64_t val = igc_read32(igc, reg);
39 val += (uint64_t)igc_read32(igc, reg + 4) << 32UL;
40 ks->value.ui64 += val;
41 }
42
43 static int
igc_stats_update(kstat_t * ksp,int rw)44 igc_stats_update(kstat_t *ksp, int rw)
45 {
46 igc_t *igc;
47 igc_stats_t *stats;
48
49 if (rw != KSTAT_READ)
50 return (EACCES);
51
52 igc = ksp->ks_private;
53 stats = &igc->igc_stats;
54
55 mutex_enter(&igc->igc_lock);
56
57 stats->is_crcerrs.value.ui64 += igc_read32(igc, IGC_CRCERRS);
58 stats->is_algnerrc.value.ui64 += igc_read32(igc, IGC_ALGNERRC);
59 stats->is_mpc.value.ui64 += igc_read32(igc, IGC_MPC);
60 stats->is_scc.value.ui64 += igc_read32(igc, IGC_SCC);
61 stats->is_ecol.value.ui64 += igc_read32(igc, IGC_ECOL);
62 stats->is_mcc.value.ui64 += igc_read32(igc, IGC_MCC);
63 stats->is_latecol.value.ui64 += igc_read32(igc, IGC_LATECOL);
64 stats->is_colc.value.ui64 += igc_read32(igc, IGC_COLC);
65 stats->is_rerc.value.ui64 += igc_read32(igc, IGC_RERC);
66 stats->is_dc.value.ui64 += igc_read32(igc, IGC_DC);
67 stats->is_tncrs.value.ui64 += igc_read32(igc, IGC_TNCRS);
68 stats->is_htdpmc.value.ui64 += igc_read32(igc, IGC_HTDPMC);
69 stats->is_rlec.value.ui64 += igc_read32(igc, IGC_RLEC);
70 stats->is_xonrxc.value.ui64 += igc_read32(igc, IGC_XONRXC);
71 stats->is_xontxc.value.ui64 += igc_read32(igc, IGC_XONTXC);
72 stats->is_xoffrxc.value.ui64 += igc_read32(igc, IGC_XOFFRXC);
73 stats->is_xofftxc.value.ui64 += igc_read32(igc, IGC_XOFFTXC);
74 stats->is_fcruc.value.ui64 += igc_read32(igc, IGC_FCRUC);
75 stats->is_prc64.value.ui64 += igc_read32(igc, IGC_PRC64);
76 stats->is_prc127.value.ui64 += igc_read32(igc, IGC_PRC127);
77 stats->is_prc255.value.ui64 += igc_read32(igc, IGC_PRC255);
78 stats->is_prc1023.value.ui64 += igc_read32(igc, IGC_PRC1023);
79 stats->is_prc1522.value.ui64 += igc_read32(igc, IGC_PRC1522);
80 stats->is_gprc.value.ui64 += igc_read32(igc, IGC_GPRC);
81 stats->is_bprc.value.ui64 += igc_read32(igc, IGC_BPRC);
82 stats->is_mprc.value.ui64 += igc_read32(igc, IGC_MPRC);
83 stats->is_gptc.value.ui64 += igc_read32(igc, IGC_GPTC);
84 igc_stats_update_u64(igc, &stats->is_gorc, IGC_GORCL);
85 igc_stats_update_u64(igc, &stats->is_gotc, IGC_GOTCL);
86 stats->is_rnbc.value.ui64 += igc_read32(igc, IGC_RNBC);
87 stats->is_ruc.value.ui64 += igc_read32(igc, IGC_RUC);
88 stats->is_rfc.value.ui64 += igc_read32(igc, IGC_RFC);
89 stats->is_roc.value.ui64 += igc_read32(igc, IGC_ROC);
90 stats->is_rjc.value.ui64 += igc_read32(igc, IGC_RJC);
91 stats->is_mgtprc.value.ui64 += igc_read32(igc, IGC_MGTPRC);
92 stats->is_mgtpdc.value.ui64 += igc_read32(igc, IGC_MGTPDC);
93 stats->is_mgtptc.value.ui64 += igc_read32(igc, IGC_MGTPTC);
94 igc_stats_update_u64(igc, &stats->is_tor, IGC_TORL);
95 igc_stats_update_u64(igc, &stats->is_tot, IGC_TOTL);
96 stats->is_tpr.value.ui64 += igc_read32(igc, IGC_TPR);
97 stats->is_tpt.value.ui64 += igc_read32(igc, IGC_TPT);
98 stats->is_ptc64.value.ui64 += igc_read32(igc, IGC_PTC64);
99 stats->is_ptc127.value.ui64 += igc_read32(igc, IGC_PTC127);
100 stats->is_ptc255.value.ui64 += igc_read32(igc, IGC_PTC255);
101 stats->is_ptc511.value.ui64 += igc_read32(igc, IGC_PTC511);
102 stats->is_ptc1023.value.ui64 += igc_read32(igc, IGC_PTC1023);
103 stats->is_ptc1522.value.ui64 += igc_read32(igc, IGC_PTC1522);
104 stats->is_mptc.value.ui64 += igc_read32(igc, IGC_MPTC);
105 stats->is_bptc.value.ui64 += igc_read32(igc, IGC_BPTC);
106 stats->is_tsctc.value.ui64 += igc_read32(igc, IGC_TSCTC);
107 stats->is_iac.value.ui64 += igc_read32(igc, IGC_IAC);
108 stats->is_rxdmtc.value.ui64 += igc_read32(igc, IGC_RXDMTC);
109 mutex_exit(&igc->igc_lock);
110
111 return (0);
112 }
113
114 bool
igc_stats_init(igc_t * igc)115 igc_stats_init(igc_t *igc)
116 {
117 kstat_t *ksp;
118 igc_stats_t *stats = &igc->igc_stats;
119
120 ksp = kstat_create(IGC_MOD_NAME, ddi_get_instance(igc->igc_dip),
121 "stats", "net", KSTAT_TYPE_NAMED, sizeof (igc_stats_t) /
122 sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);
123 if (ksp == NULL) {
124 dev_err(igc->igc_dip, CE_WARN, "failed to create kstats");
125 return (false);
126 }
127
128 igc->igc_ksp = ksp;
129 ksp->ks_update = igc_stats_update;
130 ksp->ks_private = igc;
131 ksp->ks_data = stats;
132
133 kstat_named_init(&stats->is_crcerrs, "crcerrs",
134 KSTAT_DATA_UINT64);
135 kstat_named_init(&stats->is_algnerrc, "algnerrc",
136 KSTAT_DATA_UINT64);
137 kstat_named_init(&stats->is_mpc, "mpc",
138 KSTAT_DATA_UINT64);
139 kstat_named_init(&stats->is_scc, "scc",
140 KSTAT_DATA_UINT64);
141 kstat_named_init(&stats->is_ecol, "ecol",
142 KSTAT_DATA_UINT64);
143 kstat_named_init(&stats->is_mcc, "mcc",
144 KSTAT_DATA_UINT64);
145 kstat_named_init(&stats->is_latecol, "latecol",
146 KSTAT_DATA_UINT64);
147 kstat_named_init(&stats->is_colc, "colc",
148 KSTAT_DATA_UINT64);
149 kstat_named_init(&stats->is_rerc, "rerc",
150 KSTAT_DATA_UINT64);
151 kstat_named_init(&stats->is_dc, "dc",
152 KSTAT_DATA_UINT64);
153 kstat_named_init(&stats->is_tncrs, "tncrs",
154 KSTAT_DATA_UINT64);
155 kstat_named_init(&stats->is_htdpmc, "htdpmc",
156 KSTAT_DATA_UINT64);
157 kstat_named_init(&stats->is_rlec, "rlec",
158 KSTAT_DATA_UINT64);
159 kstat_named_init(&stats->is_xonrxc, "xonrxc",
160 KSTAT_DATA_UINT64);
161 kstat_named_init(&stats->is_xontxc, "xontxc",
162 KSTAT_DATA_UINT64);
163 kstat_named_init(&stats->is_xoffrxc, "xoffrxc",
164 KSTAT_DATA_UINT64);
165 kstat_named_init(&stats->is_xofftxc, "xofftxc",
166 KSTAT_DATA_UINT64);
167 kstat_named_init(&stats->is_fcruc, "fcruc",
168 KSTAT_DATA_UINT64);
169 kstat_named_init(&stats->is_prc64, "prc64",
170 KSTAT_DATA_UINT64);
171 kstat_named_init(&stats->is_prc127, "prc127",
172 KSTAT_DATA_UINT64);
173 kstat_named_init(&stats->is_prc255, "prc255",
174 KSTAT_DATA_UINT64);
175 kstat_named_init(&stats->is_prc1023, "prc1023",
176 KSTAT_DATA_UINT64);
177 kstat_named_init(&stats->is_prc1522, "prc1522",
178 KSTAT_DATA_UINT64);
179 kstat_named_init(&stats->is_gprc, "gprc",
180 KSTAT_DATA_UINT64);
181 kstat_named_init(&stats->is_bprc, "bprc",
182 KSTAT_DATA_UINT64);
183 kstat_named_init(&stats->is_mprc, "mprc",
184 KSTAT_DATA_UINT64);
185 kstat_named_init(&stats->is_gptc, "gptc",
186 KSTAT_DATA_UINT64);
187 kstat_named_init(&stats->is_gorc, "gorc",
188 KSTAT_DATA_UINT64);
189 kstat_named_init(&stats->is_gotc, "gotc",
190 KSTAT_DATA_UINT64);
191 kstat_named_init(&stats->is_rnbc, "rnbc",
192 KSTAT_DATA_UINT64);
193 kstat_named_init(&stats->is_ruc, "ruc",
194 KSTAT_DATA_UINT64);
195 kstat_named_init(&stats->is_rfc, "rfc",
196 KSTAT_DATA_UINT64);
197 kstat_named_init(&stats->is_roc, "roc",
198 KSTAT_DATA_UINT64);
199 kstat_named_init(&stats->is_rjc, "rjc",
200 KSTAT_DATA_UINT64);
201 kstat_named_init(&stats->is_mgtprc, "mgtprc",
202 KSTAT_DATA_UINT64);
203 kstat_named_init(&stats->is_mgtpdc, "mgtpdc",
204 KSTAT_DATA_UINT64);
205 kstat_named_init(&stats->is_mgtptc, "mgtptc",
206 KSTAT_DATA_UINT64);
207 kstat_named_init(&stats->is_tor, "tor",
208 KSTAT_DATA_UINT64);
209 kstat_named_init(&stats->is_tot, "tot",
210 KSTAT_DATA_UINT64);
211 kstat_named_init(&stats->is_tpr, "tpr",
212 KSTAT_DATA_UINT64);
213 kstat_named_init(&stats->is_tpt, "tpt",
214 KSTAT_DATA_UINT64);
215 kstat_named_init(&stats->is_ptc64, "ptc64",
216 KSTAT_DATA_UINT64);
217 kstat_named_init(&stats->is_ptc127, "ptc127",
218 KSTAT_DATA_UINT64);
219 kstat_named_init(&stats->is_ptc255, "ptc255",
220 KSTAT_DATA_UINT64);
221 kstat_named_init(&stats->is_ptc511, "ptc511",
222 KSTAT_DATA_UINT64);
223 kstat_named_init(&stats->is_ptc1023, "ptc1023",
224 KSTAT_DATA_UINT64);
225 kstat_named_init(&stats->is_ptc1522, "ptc1522",
226 KSTAT_DATA_UINT64);
227 kstat_named_init(&stats->is_mptc, "mptc",
228 KSTAT_DATA_UINT64);
229 kstat_named_init(&stats->is_bptc, "bptc",
230 KSTAT_DATA_UINT64);
231 kstat_named_init(&stats->is_tsctc, "tsctc",
232 KSTAT_DATA_UINT64);
233 kstat_named_init(&stats->is_iac, "iac",
234 KSTAT_DATA_UINT64);
235 kstat_named_init(&stats->is_rxdmtc, "rxdmtc",
236 KSTAT_DATA_UINT64);
237
238 kstat_install(ksp);
239
240 return (true);
241 }
242
243 void
igc_rx_ring_stats_fini(igc_rx_ring_t * ring)244 igc_rx_ring_stats_fini(igc_rx_ring_t *ring)
245 {
246 if (ring->irr_kstat != NULL) {
247 kstat_delete(ring->irr_kstat);
248 ring->irr_kstat = NULL;
249 }
250 }
251
252 bool
igc_rx_ring_stats_init(igc_t * igc,igc_rx_ring_t * ring)253 igc_rx_ring_stats_init(igc_t *igc, igc_rx_ring_t *ring)
254 {
255 kstat_t *ksp;
256 igc_rx_stats_t *stats = &ring->irr_stat;
257 char name[32];
258
259 (void) snprintf(name, sizeof (name), "rxring%u", ring->irr_idx);
260 ksp = kstat_create(IGC_MOD_NAME, ddi_get_instance(igc->igc_dip),
261 name, "net", KSTAT_TYPE_NAMED, sizeof (igc_rx_stats_t) /
262 sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);
263 if (ksp == NULL) {
264 dev_err(igc->igc_dip, CE_WARN, "failed to create rx ring %u "
265 "kstats", ring->irr_idx);
266 return (false);
267 }
268
269 ring->irr_kstat = ksp;
270 ksp->ks_data = stats;
271
272 kstat_named_init(&stats->irs_rbytes, "rbytes", KSTAT_DATA_UINT64);
273 kstat_named_init(&stats->irs_ipackets, "ipackets", KSTAT_DATA_UINT64);
274 kstat_named_init(&stats->irs_desc_error, "desc_error",
275 KSTAT_DATA_UINT64);
276 kstat_named_init(&stats->irs_copy_nomem, "copy_nomem",
277 KSTAT_DATA_UINT64);
278 kstat_named_init(&stats->irs_bind_nobuf, "bind_nobuf",
279 KSTAT_DATA_UINT64);
280 kstat_named_init(&stats->irs_bind_nomp, "bind_nomp", KSTAT_DATA_UINT64);
281 kstat_named_init(&stats->irs_nbind, "nbind", KSTAT_DATA_UINT64);
282 kstat_named_init(&stats->irs_ncopy, "ncopy", KSTAT_DATA_UINT64);
283 kstat_named_init(&stats->irs_ixsm, "ixsm", KSTAT_DATA_UINT64);
284 kstat_named_init(&stats->irs_l3cksum_err, "l3cksum_err",
285 KSTAT_DATA_UINT64);
286 kstat_named_init(&stats->irs_l4cksum_err, "l4cksum_err",
287 KSTAT_DATA_UINT64);
288 kstat_named_init(&stats->irs_hcksum_miss, "hcksum_miss",
289 KSTAT_DATA_UINT64);
290 kstat_named_init(&stats->irs_hcksum_hit, "hcksum_hit",
291 KSTAT_DATA_UINT64);
292
293 kstat_install(ksp);
294
295 return (true);
296 }
297
298 void
igc_tx_ring_stats_fini(igc_tx_ring_t * ring)299 igc_tx_ring_stats_fini(igc_tx_ring_t *ring)
300 {
301 if (ring->itr_kstat != NULL) {
302 kstat_delete(ring->itr_kstat);
303 ring->itr_kstat = NULL;
304 }
305 }
306
307 bool
igc_tx_ring_stats_init(igc_t * igc,igc_tx_ring_t * ring)308 igc_tx_ring_stats_init(igc_t *igc, igc_tx_ring_t *ring)
309 {
310 kstat_t *ksp;
311 igc_tx_stats_t *stats = &ring->itr_stat;
312 char name[32];
313
314 (void) snprintf(name, sizeof (name), "txring%u", ring->itr_idx);
315 ksp = kstat_create(IGC_MOD_NAME, ddi_get_instance(igc->igc_dip),
316 name, "net", KSTAT_TYPE_NAMED, sizeof (igc_tx_stats_t) /
317 sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);
318 if (ksp == NULL) {
319 dev_err(igc->igc_dip, CE_WARN, "failed to create tx ring %u "
320 "kstats", ring->itr_idx);
321 return (false);
322 }
323
324 ring->itr_kstat = ksp;
325 ksp->ks_data = stats;
326
327 kstat_named_init(&stats->its_obytes, "obytes", KSTAT_DATA_UINT64);
328 kstat_named_init(&stats->its_opackets, "opackets", KSTAT_DATA_UINT64);
329 kstat_named_init(&stats->its_bad_meo, "bad_meo", KSTAT_DATA_UINT64);
330 kstat_named_init(&stats->its_ring_full, "ring_full", KSTAT_DATA_UINT64);
331 kstat_named_init(&stats->its_no_tx_bufs, "no_tx_bufs",
332 KSTAT_DATA_UINT64);
333 kstat_named_init(&stats->its_tx_copy, "tx_copy", KSTAT_DATA_UINT64);
334 kstat_named_init(&stats->its_tx_bind, "tx_bind", KSTAT_DATA_UINT64);
335 kstat_named_init(&stats->its_tx_bind_fail, "tx_bind_fail",
336 KSTAT_DATA_UINT64);
337
338 kstat_install(ksp);
339
340 return (true);
341 }
342