xref: /illumos-gate/usr/src/uts/common/io/igc/igc_stat.c (revision 9b9d39d2a32ff806d2431dbcc50968ef1e6d46b2)
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
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
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
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
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
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
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
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
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