xref: /illumos-gate/usr/src/uts/common/io/ena/ena_stats.c (revision 6f443ebc)
1*6f443ebcSRyan Zezeski /*
2*6f443ebcSRyan Zezeski  * This file and its contents are supplied under the terms of the
3*6f443ebcSRyan Zezeski  * Common Development and Distribution License ("CDDL"), version 1.0.
4*6f443ebcSRyan Zezeski  * You may only use this file in accordance with the terms of version
5*6f443ebcSRyan Zezeski  * 1.0 of the CDDL.
6*6f443ebcSRyan Zezeski  *
7*6f443ebcSRyan Zezeski  * A full copy of the text of the CDDL should have accompanied this
8*6f443ebcSRyan Zezeski  * source.  A copy of the CDDL is also available via the Internet at
9*6f443ebcSRyan Zezeski  * http://www.illumos.org/license/CDDL.
10*6f443ebcSRyan Zezeski  */
11*6f443ebcSRyan Zezeski 
12*6f443ebcSRyan Zezeski /*
13*6f443ebcSRyan Zezeski  * Copyright 2021 Oxide Computer Company
14*6f443ebcSRyan Zezeski  */
15*6f443ebcSRyan Zezeski #include "ena.h"
16*6f443ebcSRyan Zezeski 
17*6f443ebcSRyan Zezeski /*
18*6f443ebcSRyan Zezeski  * The ENA device provides the following hardware stats. It appears
19*6f443ebcSRyan Zezeski  * that all stats are available at both a device-level and
20*6f443ebcSRyan Zezeski  * queue-level. However, Linux and FreeBSD don't implement queue
21*6f443ebcSRyan Zezeski  * scope. It's not clear how one would implement queue scope because
22*6f443ebcSRyan Zezeski  * there is nothing in the common code describing how to determine the
23*6f443ebcSRyan Zezeski  * queue index number. Both the SQ and CQ have device index values,
24*6f443ebcSRyan Zezeski  * but for a given logical queue they don't always match and so it's
25*6f443ebcSRyan Zezeski  * not clear what value to use for querying the stats. Therefore,
26*6f443ebcSRyan Zezeski  * device-wide basic and extended stats come from the device, while
27*6f443ebcSRyan Zezeski  * queue/ring stats come from driver.
28*6f443ebcSRyan Zezeski  *
29*6f443ebcSRyan Zezeski  * From empirical testing, these statistics appear to be cumulative.
30*6f443ebcSRyan Zezeski  * However, this guarantee is not explicitly documented anywhere in
31*6f443ebcSRyan Zezeski  * the common code that the author could find.
32*6f443ebcSRyan Zezeski  *
33*6f443ebcSRyan Zezeski  * BASIC (ENAHW_GET_STATS_TYPE_BASIC)
34*6f443ebcSRyan Zezeski  *
35*6f443ebcSRyan Zezeski  *     - Rx packets/bytes
36*6f443ebcSRyan Zezeski  *     - Rx drops
37*6f443ebcSRyan Zezeski  *     - Tx packets/bytes
38*6f443ebcSRyan Zezeski  *     - Tx drops
39*6f443ebcSRyan Zezeski  *
40*6f443ebcSRyan Zezeski  * EXTENDED (ENAHW_GET_STATS_TYPE_EXTENDED)
41*6f443ebcSRyan Zezeski  *
42*6f443ebcSRyan Zezeski  *     There is no structure defined for these stats in the Linux
43*6f443ebcSRyan Zezeski  *     driver. Based on the FreeBSD driver, it looks like extended
44*6f443ebcSRyan Zezeski  *     stats are simply a buffer of C strings? Come back to this
45*6f443ebcSRyan Zezeski  *     later.
46*6f443ebcSRyan Zezeski  *
47*6f443ebcSRyan Zezeski  * ENI (ENAHW_GET_STATS_TYPE_ENI)
48*6f443ebcSRyan Zezeski  *
49*6f443ebcSRyan Zezeski  *     - Rx Bandwidth Allowance Exceeded
50*6f443ebcSRyan Zezeski  *     - Tx Bandwidth Allowance Exceeded
51*6f443ebcSRyan Zezeski  *     - PPS Allowance Exceeded (presumably for combined Rx/Tx)
52*6f443ebcSRyan Zezeski  *     - Connection Tracking PPS Allowance Exceeded
53*6f443ebcSRyan Zezeski  *     - Link-local PPS Alloance Exceeded
54*6f443ebcSRyan Zezeski  */
55*6f443ebcSRyan Zezeski 
56*6f443ebcSRyan Zezeski static int
57*6f443ebcSRyan Zezeski ena_stat_device_basic_update(kstat_t *ksp, int rw)
58*6f443ebcSRyan Zezeski {
59*6f443ebcSRyan Zezeski 	ena_t *ena = ksp->ks_private;
60*6f443ebcSRyan Zezeski 	ena_basic_stat_t *ebs = ksp->ks_data;
61*6f443ebcSRyan Zezeski 	enahw_resp_desc_t resp;
62*6f443ebcSRyan Zezeski 	enahw_resp_basic_stats_t *stats = &resp.erd_resp.erd_basic_stats;
63*6f443ebcSRyan Zezeski 	int ret = 0;
64*6f443ebcSRyan Zezeski 
65*6f443ebcSRyan Zezeski 	if (rw == KSTAT_WRITE) {
66*6f443ebcSRyan Zezeski 		return (EACCES);
67*6f443ebcSRyan Zezeski 	}
68*6f443ebcSRyan Zezeski 
69*6f443ebcSRyan Zezeski 	if ((ret = ena_admin_get_basic_stats(ena, &resp)) != 0) {
70*6f443ebcSRyan Zezeski 		return (ret);
71*6f443ebcSRyan Zezeski 	}
72*6f443ebcSRyan Zezeski 
73*6f443ebcSRyan Zezeski 	mutex_enter(&ena->ena_lock);
74*6f443ebcSRyan Zezeski 
75*6f443ebcSRyan Zezeski 	ebs->ebs_tx_bytes.value.ui64 =
76*6f443ebcSRyan Zezeski 	    ((uint64_t)stats->erbs_tx_bytes_high << 32) |
77*6f443ebcSRyan Zezeski 	    (uint64_t)stats->erbs_tx_bytes_low;
78*6f443ebcSRyan Zezeski 	ebs->ebs_tx_pkts.value.ui64 =
79*6f443ebcSRyan Zezeski 	    ((uint64_t)stats->erbs_tx_pkts_high << 32) |
80*6f443ebcSRyan Zezeski 	    (uint64_t)stats->erbs_tx_pkts_low;
81*6f443ebcSRyan Zezeski 	ebs->ebs_tx_drops.value.ui64 =
82*6f443ebcSRyan Zezeski 	    ((uint64_t)stats->erbs_tx_drops_high << 32) |
83*6f443ebcSRyan Zezeski 	    (uint64_t)stats->erbs_tx_drops_low;
84*6f443ebcSRyan Zezeski 
85*6f443ebcSRyan Zezeski 	ebs->ebs_rx_bytes.value.ui64 =
86*6f443ebcSRyan Zezeski 	    ((uint64_t)stats->erbs_rx_bytes_high << 32) |
87*6f443ebcSRyan Zezeski 	    (uint64_t)stats->erbs_rx_bytes_low;
88*6f443ebcSRyan Zezeski 	ebs->ebs_rx_pkts.value.ui64 =
89*6f443ebcSRyan Zezeski 	    ((uint64_t)stats->erbs_rx_pkts_high << 32) |
90*6f443ebcSRyan Zezeski 	    (uint64_t)stats->erbs_rx_pkts_low;
91*6f443ebcSRyan Zezeski 	ebs->ebs_rx_drops.value.ui64 =
92*6f443ebcSRyan Zezeski 	    ((uint64_t)stats->erbs_rx_drops_high << 32) |
93*6f443ebcSRyan Zezeski 	    (uint64_t)stats->erbs_rx_drops_low;
94*6f443ebcSRyan Zezeski 
95*6f443ebcSRyan Zezeski 	mutex_exit(&ena->ena_lock);
96*6f443ebcSRyan Zezeski 
97*6f443ebcSRyan Zezeski 	return (0);
98*6f443ebcSRyan Zezeski }
99*6f443ebcSRyan Zezeski 
100*6f443ebcSRyan Zezeski void
101*6f443ebcSRyan Zezeski ena_stat_device_basic_cleanup(ena_t *ena)
102*6f443ebcSRyan Zezeski {
103*6f443ebcSRyan Zezeski 	if (ena->ena_device_basic_kstat != NULL) {
104*6f443ebcSRyan Zezeski 		kstat_delete(ena->ena_device_basic_kstat);
105*6f443ebcSRyan Zezeski 		ena->ena_device_basic_kstat = NULL;
106*6f443ebcSRyan Zezeski 	}
107*6f443ebcSRyan Zezeski }
108*6f443ebcSRyan Zezeski 
109*6f443ebcSRyan Zezeski boolean_t
110*6f443ebcSRyan Zezeski ena_stat_device_basic_init(ena_t *ena)
111*6f443ebcSRyan Zezeski {
112*6f443ebcSRyan Zezeski 	kstat_t *ksp = kstat_create(ENA_MODULE_NAME,
113*6f443ebcSRyan Zezeski 	    ddi_get_instance(ena->ena_dip), "device_basic", "net",
114*6f443ebcSRyan Zezeski 	    KSTAT_TYPE_NAMED,
115*6f443ebcSRyan Zezeski 	    sizeof (ena_basic_stat_t) / sizeof (kstat_named_t), 0);
116*6f443ebcSRyan Zezeski 	ena_basic_stat_t *ebs = NULL;
117*6f443ebcSRyan Zezeski 
118*6f443ebcSRyan Zezeski 	if (ksp == NULL) {
119*6f443ebcSRyan Zezeski 		ena_err(ena, "!failed to create device_basic kstats");
120*6f443ebcSRyan Zezeski 		return (B_FALSE);
121*6f443ebcSRyan Zezeski 	}
122*6f443ebcSRyan Zezeski 
123*6f443ebcSRyan Zezeski 	ena->ena_device_basic_kstat = ksp;
124*6f443ebcSRyan Zezeski 	ebs = ksp->ks_data;
125*6f443ebcSRyan Zezeski 	ksp->ks_update = ena_stat_device_basic_update;
126*6f443ebcSRyan Zezeski 	ksp->ks_private = ena;
127*6f443ebcSRyan Zezeski 
128*6f443ebcSRyan Zezeski 	kstat_named_init(&ebs->ebs_tx_bytes, "tx_bytes", KSTAT_DATA_UINT64);
129*6f443ebcSRyan Zezeski 	ebs->ebs_tx_bytes.value.ui64 = 0;
130*6f443ebcSRyan Zezeski 	kstat_named_init(&ebs->ebs_tx_pkts, "tx_packets", KSTAT_DATA_UINT64);
131*6f443ebcSRyan Zezeski 	ebs->ebs_tx_pkts.value.ui64 = 0;
132*6f443ebcSRyan Zezeski 	kstat_named_init(&ebs->ebs_tx_drops, "tx_drops", KSTAT_DATA_UINT64);
133*6f443ebcSRyan Zezeski 	ebs->ebs_tx_drops.value.ui64 = 0;
134*6f443ebcSRyan Zezeski 
135*6f443ebcSRyan Zezeski 	kstat_named_init(&ebs->ebs_rx_bytes, "rx_bytes", KSTAT_DATA_UINT64);
136*6f443ebcSRyan Zezeski 	ebs->ebs_rx_bytes.value.ui64 = 0;
137*6f443ebcSRyan Zezeski 	kstat_named_init(&ebs->ebs_rx_pkts, "rx_packets", KSTAT_DATA_UINT64);
138*6f443ebcSRyan Zezeski 	ebs->ebs_rx_pkts.value.ui64 = 0;
139*6f443ebcSRyan Zezeski 	kstat_named_init(&ebs->ebs_rx_drops, "rx_drops", KSTAT_DATA_UINT64);
140*6f443ebcSRyan Zezeski 	ebs->ebs_rx_drops.value.ui64 = 0;
141*6f443ebcSRyan Zezeski 
142*6f443ebcSRyan Zezeski 	kstat_install(ena->ena_device_basic_kstat);
143*6f443ebcSRyan Zezeski 	return (B_TRUE);
144*6f443ebcSRyan Zezeski }
145*6f443ebcSRyan Zezeski 
146*6f443ebcSRyan Zezeski int
147*6f443ebcSRyan Zezeski ena_stat_device_extended_update(kstat_t *ksp, int rw)
148*6f443ebcSRyan Zezeski {
149*6f443ebcSRyan Zezeski 	ena_t *ena = ksp->ks_private;
150*6f443ebcSRyan Zezeski 	ena_extended_stat_t *ees = ksp->ks_data;
151*6f443ebcSRyan Zezeski 	enahw_resp_desc_t resp;
152*6f443ebcSRyan Zezeski 	enahw_resp_eni_stats_t *stats = &resp.erd_resp.erd_eni_stats;
153*6f443ebcSRyan Zezeski 	int ret = 0;
154*6f443ebcSRyan Zezeski 
155*6f443ebcSRyan Zezeski 	if (rw == KSTAT_WRITE) {
156*6f443ebcSRyan Zezeski 		return (EACCES);
157*6f443ebcSRyan Zezeski 	}
158*6f443ebcSRyan Zezeski 
159*6f443ebcSRyan Zezeski 	if ((ret = ena_admin_get_eni_stats(ena, &resp)) != 0) {
160*6f443ebcSRyan Zezeski 		return (ret);
161*6f443ebcSRyan Zezeski 	}
162*6f443ebcSRyan Zezeski 
163*6f443ebcSRyan Zezeski 	mutex_enter(&ena->ena_lock);
164*6f443ebcSRyan Zezeski 
165*6f443ebcSRyan Zezeski 	ees->ees_bw_in_exceeded.value.ui64 = stats->eres_bw_in_exceeded;
166*6f443ebcSRyan Zezeski 	ees->ees_bw_out_exceeded.value.ui64 = stats->eres_bw_out_exceeded;
167*6f443ebcSRyan Zezeski 	ees->ees_pps_exceeded.value.ui64 = stats->eres_pps_exceeded;
168*6f443ebcSRyan Zezeski 	ees->ees_conns_exceeded.value.ui64 = stats->eres_conns_exceeded;
169*6f443ebcSRyan Zezeski 	ees->ees_linklocal_exceeded.value.ui64 = stats->eres_linklocal_exceeded;
170*6f443ebcSRyan Zezeski 
171*6f443ebcSRyan Zezeski 	mutex_exit(&ena->ena_lock);
172*6f443ebcSRyan Zezeski 
173*6f443ebcSRyan Zezeski 	return (0);
174*6f443ebcSRyan Zezeski }
175*6f443ebcSRyan Zezeski 
176*6f443ebcSRyan Zezeski void
177*6f443ebcSRyan Zezeski ena_stat_device_extended_cleanup(ena_t *ena)
178*6f443ebcSRyan Zezeski {
179*6f443ebcSRyan Zezeski 	if (ena->ena_device_extended_kstat != NULL) {
180*6f443ebcSRyan Zezeski 		kstat_delete(ena->ena_device_extended_kstat);
181*6f443ebcSRyan Zezeski 		ena->ena_device_extended_kstat = NULL;
182*6f443ebcSRyan Zezeski 	}
183*6f443ebcSRyan Zezeski }
184*6f443ebcSRyan Zezeski 
185*6f443ebcSRyan Zezeski boolean_t
186*6f443ebcSRyan Zezeski ena_stat_device_extended_init(ena_t *ena)
187*6f443ebcSRyan Zezeski {
188*6f443ebcSRyan Zezeski 	kstat_t *ksp = kstat_create(ENA_MODULE_NAME,
189*6f443ebcSRyan Zezeski 	    ddi_get_instance(ena->ena_dip), "device_ext", "net",
190*6f443ebcSRyan Zezeski 	    KSTAT_TYPE_NAMED,
191*6f443ebcSRyan Zezeski 	    sizeof (ena_extended_stat_t) / sizeof (kstat_named_t), 0);
192*6f443ebcSRyan Zezeski 	ena_extended_stat_t *ees;
193*6f443ebcSRyan Zezeski 
194*6f443ebcSRyan Zezeski 	if (ksp == NULL) {
195*6f443ebcSRyan Zezeski 		ena_err(ena, "!failed to create device_ext kstats");
196*6f443ebcSRyan Zezeski 		return (B_FALSE);
197*6f443ebcSRyan Zezeski 	}
198*6f443ebcSRyan Zezeski 
199*6f443ebcSRyan Zezeski 	ena->ena_device_extended_kstat = ksp;
200*6f443ebcSRyan Zezeski 	ees = ksp->ks_data;
201*6f443ebcSRyan Zezeski 	ksp->ks_update = ena_stat_device_extended_update;
202*6f443ebcSRyan Zezeski 	ksp->ks_private = ena;
203*6f443ebcSRyan Zezeski 
204*6f443ebcSRyan Zezeski 	kstat_named_init(&ees->ees_bw_in_exceeded, "bw_in_exceeded",
205*6f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
206*6f443ebcSRyan Zezeski 	ees->ees_bw_in_exceeded.value.ui64 = 0;
207*6f443ebcSRyan Zezeski 
208*6f443ebcSRyan Zezeski 	kstat_named_init(&ees->ees_bw_out_exceeded, "bw_out_exceeded",
209*6f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
210*6f443ebcSRyan Zezeski 	ees->ees_bw_out_exceeded.value.ui64 = 0;
211*6f443ebcSRyan Zezeski 
212*6f443ebcSRyan Zezeski 	kstat_named_init(&ees->ees_pps_exceeded, "pps_exceeded",
213*6f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
214*6f443ebcSRyan Zezeski 	ees->ees_pps_exceeded.value.ui64 = 0;
215*6f443ebcSRyan Zezeski 
216*6f443ebcSRyan Zezeski 	kstat_named_init(&ees->ees_conns_exceeded, "conns_exceeded",
217*6f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
218*6f443ebcSRyan Zezeski 	ees->ees_conns_exceeded.value.ui64 = 0;
219*6f443ebcSRyan Zezeski 
220*6f443ebcSRyan Zezeski 	kstat_named_init(&ees->ees_linklocal_exceeded, "linklocal_exceeded",
221*6f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
222*6f443ebcSRyan Zezeski 	ees->ees_linklocal_exceeded.value.ui64 = 0;
223*6f443ebcSRyan Zezeski 
224*6f443ebcSRyan Zezeski 	kstat_install(ena->ena_device_extended_kstat);
225*6f443ebcSRyan Zezeski 	return (B_TRUE);
226*6f443ebcSRyan Zezeski }
227*6f443ebcSRyan Zezeski 
228*6f443ebcSRyan Zezeski void
229*6f443ebcSRyan Zezeski ena_stat_aenq_cleanup(ena_t *ena)
230*6f443ebcSRyan Zezeski {
231*6f443ebcSRyan Zezeski 	if (ena->ena_aenq_kstat != NULL) {
232*6f443ebcSRyan Zezeski 		kstat_delete(ena->ena_aenq_kstat);
233*6f443ebcSRyan Zezeski 		ena->ena_aenq_kstat = NULL;
234*6f443ebcSRyan Zezeski 	}
235*6f443ebcSRyan Zezeski }
236*6f443ebcSRyan Zezeski 
237*6f443ebcSRyan Zezeski boolean_t
238*6f443ebcSRyan Zezeski ena_stat_aenq_init(ena_t *ena)
239*6f443ebcSRyan Zezeski {
240*6f443ebcSRyan Zezeski 	kstat_t *ksp = kstat_create(ENA_MODULE_NAME,
241*6f443ebcSRyan Zezeski 	    ddi_get_instance(ena->ena_dip), "aenq", "net", KSTAT_TYPE_NAMED,
242*6f443ebcSRyan Zezeski 	    sizeof (ena_aenq_stat_t) / sizeof (kstat_named_t),
243*6f443ebcSRyan Zezeski 	    KSTAT_FLAG_VIRTUAL);
244*6f443ebcSRyan Zezeski 	ena_aenq_stat_t *eas = &ena->ena_aenq_stat;
245*6f443ebcSRyan Zezeski 
246*6f443ebcSRyan Zezeski 	if (ksp == NULL) {
247*6f443ebcSRyan Zezeski 		ena_err(ena, "!failed to create aenq kstats");
248*6f443ebcSRyan Zezeski 		return (B_FALSE);
249*6f443ebcSRyan Zezeski 	}
250*6f443ebcSRyan Zezeski 
251*6f443ebcSRyan Zezeski 	ena->ena_aenq_kstat = ksp;
252*6f443ebcSRyan Zezeski 	ksp->ks_data = eas;
253*6f443ebcSRyan Zezeski 
254*6f443ebcSRyan Zezeski 	kstat_named_init(&eas->eaes_default, "default", KSTAT_DATA_UINT64);
255*6f443ebcSRyan Zezeski 	eas->eaes_default.value.ui64 = 0;
256*6f443ebcSRyan Zezeski 
257*6f443ebcSRyan Zezeski 	kstat_named_init(&eas->eaes_link_change, "link_change",
258*6f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
259*6f443ebcSRyan Zezeski 	eas->eaes_link_change.value.ui64 = 0;
260*6f443ebcSRyan Zezeski 
261*6f443ebcSRyan Zezeski 	kstat_install(ena->ena_aenq_kstat);
262*6f443ebcSRyan Zezeski 	return (B_TRUE);
263*6f443ebcSRyan Zezeski }
264*6f443ebcSRyan Zezeski 
265*6f443ebcSRyan Zezeski void
266*6f443ebcSRyan Zezeski ena_stat_txq_cleanup(ena_txq_t *txq)
267*6f443ebcSRyan Zezeski {
268*6f443ebcSRyan Zezeski 	if (txq->et_kstat != NULL) {
269*6f443ebcSRyan Zezeski 		kstat_delete(txq->et_kstat);
270*6f443ebcSRyan Zezeski 		txq->et_kstat = NULL;
271*6f443ebcSRyan Zezeski 	}
272*6f443ebcSRyan Zezeski }
273*6f443ebcSRyan Zezeski 
274*6f443ebcSRyan Zezeski boolean_t
275*6f443ebcSRyan Zezeski ena_stat_txq_init(ena_txq_t *txq)
276*6f443ebcSRyan Zezeski {
277*6f443ebcSRyan Zezeski 	ena_t *ena = txq->et_ena;
278*6f443ebcSRyan Zezeski 	kstat_t *ksp;
279*6f443ebcSRyan Zezeski 	char buf[128];
280*6f443ebcSRyan Zezeski 	ena_txq_stat_t *ets = &txq->et_stat;
281*6f443ebcSRyan Zezeski 
282*6f443ebcSRyan Zezeski 	(void) snprintf(buf, sizeof (buf), "txq_%d", txq->et_txqs_idx);
283*6f443ebcSRyan Zezeski 
284*6f443ebcSRyan Zezeski 	ksp = kstat_create(ENA_MODULE_NAME, ddi_get_instance(ena->ena_dip), buf,
285*6f443ebcSRyan Zezeski 	    "net", KSTAT_TYPE_NAMED,
286*6f443ebcSRyan Zezeski 	    sizeof (ena_txq_stat_t) / sizeof (kstat_named_t),
287*6f443ebcSRyan Zezeski 	    KSTAT_FLAG_VIRTUAL);
288*6f443ebcSRyan Zezeski 
289*6f443ebcSRyan Zezeski 	if (ksp == NULL) {
290*6f443ebcSRyan Zezeski 		ena_err(ena, "!failed to create %s kstats", buf);
291*6f443ebcSRyan Zezeski 		return (B_FALSE);
292*6f443ebcSRyan Zezeski 	}
293*6f443ebcSRyan Zezeski 
294*6f443ebcSRyan Zezeski 	txq->et_kstat = ksp;
295*6f443ebcSRyan Zezeski 	ksp->ks_data = ets;
296*6f443ebcSRyan Zezeski 
297*6f443ebcSRyan Zezeski 	kstat_named_init(&ets->ets_hck_meoifail, "meoi_fail",
298*6f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
299*6f443ebcSRyan Zezeski 	ets->ets_hck_meoifail.value.ui64 = 0;
300*6f443ebcSRyan Zezeski 
301*6f443ebcSRyan Zezeski 	kstat_named_init(&ets->ets_blocked, "blocked", KSTAT_DATA_UINT64);
302*6f443ebcSRyan Zezeski 	ets->ets_blocked.value.ui64 = 0;
303*6f443ebcSRyan Zezeski 
304*6f443ebcSRyan Zezeski 	kstat_named_init(&ets->ets_unblocked, "unblocked", KSTAT_DATA_UINT64);
305*6f443ebcSRyan Zezeski 	ets->ets_unblocked.value.ui64 = 0;
306*6f443ebcSRyan Zezeski 
307*6f443ebcSRyan Zezeski 	kstat_named_init(&ets->ets_recycled, "recycled", KSTAT_DATA_UINT64);
308*6f443ebcSRyan Zezeski 	ets->ets_recycled.value.ui64 = 0;
309*6f443ebcSRyan Zezeski 
310*6f443ebcSRyan Zezeski 	kstat_named_init(&ets->ets_bytes, "bytes", KSTAT_DATA_UINT64);
311*6f443ebcSRyan Zezeski 	ets->ets_bytes.value.ui64 = 0;
312*6f443ebcSRyan Zezeski 
313*6f443ebcSRyan Zezeski 	kstat_named_init(&ets->ets_packets, "packets", KSTAT_DATA_UINT64);
314*6f443ebcSRyan Zezeski 	ets->ets_packets.value.ui64 = 0;
315*6f443ebcSRyan Zezeski 
316*6f443ebcSRyan Zezeski 	kstat_install(txq->et_kstat);
317*6f443ebcSRyan Zezeski 	return (B_TRUE);
318*6f443ebcSRyan Zezeski }
319*6f443ebcSRyan Zezeski 
320*6f443ebcSRyan Zezeski void
321*6f443ebcSRyan Zezeski ena_stat_rxq_cleanup(ena_rxq_t *rxq)
322*6f443ebcSRyan Zezeski {
323*6f443ebcSRyan Zezeski 	if (rxq->er_kstat != NULL) {
324*6f443ebcSRyan Zezeski 		kstat_delete(rxq->er_kstat);
325*6f443ebcSRyan Zezeski 		rxq->er_kstat = NULL;
326*6f443ebcSRyan Zezeski 	}
327*6f443ebcSRyan Zezeski }
328*6f443ebcSRyan Zezeski 
329*6f443ebcSRyan Zezeski boolean_t
330*6f443ebcSRyan Zezeski ena_stat_rxq_init(ena_rxq_t *rxq)
331*6f443ebcSRyan Zezeski {
332*6f443ebcSRyan Zezeski 	ena_t *ena = rxq->er_ena;
333*6f443ebcSRyan Zezeski 	kstat_t *ksp;
334*6f443ebcSRyan Zezeski 	char buf[128];
335*6f443ebcSRyan Zezeski 	ena_rxq_stat_t *ers = &rxq->er_stat;
336*6f443ebcSRyan Zezeski 
337*6f443ebcSRyan Zezeski 	(void) snprintf(buf, sizeof (buf), "rxq_%d", rxq->er_rxqs_idx);
338*6f443ebcSRyan Zezeski 
339*6f443ebcSRyan Zezeski 	ksp = kstat_create(ENA_MODULE_NAME, ddi_get_instance(ena->ena_dip), buf,
340*6f443ebcSRyan Zezeski 	    "net", KSTAT_TYPE_NAMED,
341*6f443ebcSRyan Zezeski 	    sizeof (ena_rxq_stat_t) / sizeof (kstat_named_t),
342*6f443ebcSRyan Zezeski 	    KSTAT_FLAG_VIRTUAL);
343*6f443ebcSRyan Zezeski 
344*6f443ebcSRyan Zezeski 	if (ksp == NULL) {
345*6f443ebcSRyan Zezeski 		ena_err(ena, "!failed to create %s kstats", buf);
346*6f443ebcSRyan Zezeski 		return (B_FALSE);
347*6f443ebcSRyan Zezeski 	}
348*6f443ebcSRyan Zezeski 
349*6f443ebcSRyan Zezeski 	rxq->er_kstat = ksp;
350*6f443ebcSRyan Zezeski 	ksp->ks_data = ers;
351*6f443ebcSRyan Zezeski 
352*6f443ebcSRyan Zezeski 	kstat_named_init(&ers->ers_packets, "packets", KSTAT_DATA_UINT64);
353*6f443ebcSRyan Zezeski 	ers->ers_packets.value.ui64 = 0;
354*6f443ebcSRyan Zezeski 
355*6f443ebcSRyan Zezeski 	kstat_named_init(&ers->ers_bytes, "bytes", KSTAT_DATA_UINT64);
356*6f443ebcSRyan Zezeski 	ers->ers_bytes.value.ui64 = 0;
357*6f443ebcSRyan Zezeski 
358*6f443ebcSRyan Zezeski 	kstat_named_init(&ers->ers_multi_desc, "multi_desc", KSTAT_DATA_UINT64);
359*6f443ebcSRyan Zezeski 	ers->ers_multi_desc.value.ui64 = 0;
360*6f443ebcSRyan Zezeski 
361*6f443ebcSRyan Zezeski 	kstat_named_init(&ers->ers_allocb_fail, "allocb_fail",
362*6f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
363*6f443ebcSRyan Zezeski 	ers->ers_allocb_fail.value.ui64 = 0;
364*6f443ebcSRyan Zezeski 
365*6f443ebcSRyan Zezeski 	kstat_named_init(&ers->ers_intr_limit, "intr_limit", KSTAT_DATA_UINT64);
366*6f443ebcSRyan Zezeski 	ers->ers_intr_limit.value.ui64 = 0;
367*6f443ebcSRyan Zezeski 
368*6f443ebcSRyan Zezeski 	kstat_named_init(&ers->ers_hck_ipv4_err, "hck_ipv4_err",
369*6f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
370*6f443ebcSRyan Zezeski 	ers->ers_hck_ipv4_err.value.ui64 = 0;
371*6f443ebcSRyan Zezeski 
372*6f443ebcSRyan Zezeski 	kstat_named_init(&ers->ers_hck_l4_err, "hck_l4_err", KSTAT_DATA_UINT64);
373*6f443ebcSRyan Zezeski 	ers->ers_hck_l4_err.value.ui64 = 0;
374*6f443ebcSRyan Zezeski 
375*6f443ebcSRyan Zezeski 	kstat_install(rxq->er_kstat);
376*6f443ebcSRyan Zezeski 	return (B_TRUE);
377*6f443ebcSRyan Zezeski }
378*6f443ebcSRyan Zezeski 
379*6f443ebcSRyan Zezeski int
380*6f443ebcSRyan Zezeski ena_ring_rx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
381*6f443ebcSRyan Zezeski {
382*6f443ebcSRyan Zezeski 	int ret = 0;
383*6f443ebcSRyan Zezeski 	ena_rxq_t *rxq = (ena_rxq_t *)rh;
384*6f443ebcSRyan Zezeski 
385*6f443ebcSRyan Zezeski 	mutex_enter(&rxq->er_stat_lock);
386*6f443ebcSRyan Zezeski 
387*6f443ebcSRyan Zezeski 	switch (stat) {
388*6f443ebcSRyan Zezeski 	case MAC_STAT_RBYTES:
389*6f443ebcSRyan Zezeski 		*val = rxq->er_stat.ers_bytes.value.ui64;
390*6f443ebcSRyan Zezeski 		break;
391*6f443ebcSRyan Zezeski 	case MAC_STAT_IPACKETS:
392*6f443ebcSRyan Zezeski 		*val = rxq->er_stat.ers_packets.value.ui64;
393*6f443ebcSRyan Zezeski 		break;
394*6f443ebcSRyan Zezeski 	default:
395*6f443ebcSRyan Zezeski 		*val = 0;
396*6f443ebcSRyan Zezeski 		ret = ENOTSUP;
397*6f443ebcSRyan Zezeski 	}
398*6f443ebcSRyan Zezeski 
399*6f443ebcSRyan Zezeski 	mutex_exit(&rxq->er_stat_lock);
400*6f443ebcSRyan Zezeski 	return (ret);
401*6f443ebcSRyan Zezeski }
402*6f443ebcSRyan Zezeski 
403*6f443ebcSRyan Zezeski int
404*6f443ebcSRyan Zezeski ena_ring_tx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
405*6f443ebcSRyan Zezeski {
406*6f443ebcSRyan Zezeski 	int ret = 0;
407*6f443ebcSRyan Zezeski 	ena_txq_t *txq = (ena_txq_t *)rh;
408*6f443ebcSRyan Zezeski 
409*6f443ebcSRyan Zezeski 	mutex_enter(&txq->et_stat_lock);
410*6f443ebcSRyan Zezeski 
411*6f443ebcSRyan Zezeski 	switch (stat) {
412*6f443ebcSRyan Zezeski 	case MAC_STAT_OBYTES:
413*6f443ebcSRyan Zezeski 		*val = txq->et_stat.ets_bytes.value.ui64;
414*6f443ebcSRyan Zezeski 		break;
415*6f443ebcSRyan Zezeski 	case MAC_STAT_OPACKETS:
416*6f443ebcSRyan Zezeski 		*val = txq->et_stat.ets_packets.value.ui64;
417*6f443ebcSRyan Zezeski 		break;
418*6f443ebcSRyan Zezeski 	default:
419*6f443ebcSRyan Zezeski 		*val = 0;
420*6f443ebcSRyan Zezeski 		ret = ENOTSUP;
421*6f443ebcSRyan Zezeski 	}
422*6f443ebcSRyan Zezeski 
423*6f443ebcSRyan Zezeski 	mutex_exit(&txq->et_stat_lock);
424*6f443ebcSRyan Zezeski 	return (ret);
425*6f443ebcSRyan Zezeski }
426*6f443ebcSRyan Zezeski 
427*6f443ebcSRyan Zezeski int
428*6f443ebcSRyan Zezeski ena_m_stat(void *arg, uint_t stat, uint64_t *val)
429*6f443ebcSRyan Zezeski {
430*6f443ebcSRyan Zezeski 	ena_t *ena = arg;
431*6f443ebcSRyan Zezeski 	ena_basic_stat_t *ebs = ena->ena_device_basic_kstat->ks_data;
432*6f443ebcSRyan Zezeski 	int ret = 0;
433*6f443ebcSRyan Zezeski 
434*6f443ebcSRyan Zezeski 	ret = ena_stat_device_basic_update(ena->ena_device_basic_kstat,
435*6f443ebcSRyan Zezeski 	    KSTAT_READ);
436*6f443ebcSRyan Zezeski 
437*6f443ebcSRyan Zezeski 	if (ret != 0) {
438*6f443ebcSRyan Zezeski 		return (ret);
439*6f443ebcSRyan Zezeski 	}
440*6f443ebcSRyan Zezeski 
441*6f443ebcSRyan Zezeski 	mutex_enter(&ena->ena_lock);
442*6f443ebcSRyan Zezeski 
443*6f443ebcSRyan Zezeski 	/*
444*6f443ebcSRyan Zezeski 	 * The ENA device does not provide a lot of the stats that a
445*6f443ebcSRyan Zezeski 	 * traditional NIC device would.
446*6f443ebcSRyan Zezeski 	 */
447*6f443ebcSRyan Zezeski 	switch (stat) {
448*6f443ebcSRyan Zezeski 	case MAC_STAT_NORCVBUF:
449*6f443ebcSRyan Zezeski 		*val = ebs->ebs_rx_drops.value.ui64;
450*6f443ebcSRyan Zezeski 		break;
451*6f443ebcSRyan Zezeski 
452*6f443ebcSRyan Zezeski 	case MAC_STAT_RBYTES:
453*6f443ebcSRyan Zezeski 		*val = ebs->ebs_rx_bytes.value.ui64;
454*6f443ebcSRyan Zezeski 		break;
455*6f443ebcSRyan Zezeski 
456*6f443ebcSRyan Zezeski 	case MAC_STAT_IPACKETS:
457*6f443ebcSRyan Zezeski 		*val = ebs->ebs_rx_pkts.value.ui64;
458*6f443ebcSRyan Zezeski 		break;
459*6f443ebcSRyan Zezeski 
460*6f443ebcSRyan Zezeski 	case MAC_STAT_OBYTES:
461*6f443ebcSRyan Zezeski 		*val = ebs->ebs_tx_bytes.value.ui64;
462*6f443ebcSRyan Zezeski 		break;
463*6f443ebcSRyan Zezeski 
464*6f443ebcSRyan Zezeski 	case MAC_STAT_OPACKETS:
465*6f443ebcSRyan Zezeski 		*val = ebs->ebs_tx_pkts.value.ui64;
466*6f443ebcSRyan Zezeski 		break;
467*6f443ebcSRyan Zezeski 
468*6f443ebcSRyan Zezeski 	default:
469*6f443ebcSRyan Zezeski 		ret = ENOTSUP;
470*6f443ebcSRyan Zezeski 		break;
471*6f443ebcSRyan Zezeski 	}
472*6f443ebcSRyan Zezeski 
473*6f443ebcSRyan Zezeski 	mutex_exit(&ena->ena_lock);
474*6f443ebcSRyan Zezeski 	return (ret);
475*6f443ebcSRyan Zezeski }
476