xref: /illumos-gate/usr/src/uts/common/io/ena/ena_stats.c (revision c46e4de36cfe07276cbfb1e05a749e7765e50533)
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 #include "ena.h"
17 
18 /*
19  * The ENA device provides the following hardware stats. It appears
20  * that all stats are available at both a device-level and
21  * queue-level. However, Linux and FreeBSD don't implement queue
22  * scope. It's not clear how one would implement queue scope because
23  * there is nothing in the common code describing how to determine the
24  * queue index number. Both the SQ and CQ have device index values,
25  * but for a given logical queue they don't always match and so it's
26  * not clear what value to use for querying the stats. Therefore,
27  * device-wide basic and extended stats come from the device, while
28  * queue/ring stats come from driver.
29  *
30  * From empirical testing, these statistics appear to be cumulative.
31  * However, this guarantee is not explicitly documented anywhere in
32  * the common code that the author could find.
33  *
34  * BASIC (ENAHW_GET_STATS_TYPE_BASIC)
35  *
36  *     - Rx packets/bytes
37  *     - Rx drops
38  *     - Tx packets/bytes
39  *     - Tx drops
40  *     - Rx overruns
41  *
42  * EXTENDED (ENAHW_GET_STATS_TYPE_EXTENDED)
43  *
44  *     There is no structure defined for these stats in the Linux
45  *     driver. Based on the FreeBSD driver, it looks like extended
46  *     stats are simply a buffer of C strings? Come back to this
47  *     later.
48  *
49  * ENI (ENAHW_GET_STATS_TYPE_ENI)
50  *
51  *     - Rx Bandwidth Allowance Exceeded
52  *     - Tx Bandwidth Allowance Exceeded
53  *     - PPS Allowance Exceeded (presumably for combined Rx/Tx)
54  *     - Connection Tracking PPS Allowance Exceeded
55  *     - Link-local PPS Allowance Exceeded
56  */
57 
58 void
ena_stat_device_cleanup(ena_t * ena)59 ena_stat_device_cleanup(ena_t *ena)
60 {
61 	if (ena->ena_device_kstat != NULL) {
62 		kstat_delete(ena->ena_device_kstat);
63 		ena->ena_device_kstat = NULL;
64 	}
65 }
66 
67 bool
ena_stat_device_init(ena_t * ena)68 ena_stat_device_init(ena_t *ena)
69 {
70 	kstat_t *ksp = kstat_create(ENA_MODULE_NAME,
71 	    ddi_get_instance(ena->ena_dip), "device", "net", KSTAT_TYPE_NAMED,
72 	    sizeof (ena_device_stat_t) / sizeof (kstat_named_t),
73 	    KSTAT_FLAG_VIRTUAL);
74 	ena_device_stat_t *eds = &ena->ena_device_stat;
75 
76 	if (ksp == NULL) {
77 		ena_err(ena, "!failed to create device kstats");
78 		return (false);
79 	}
80 
81 	ena->ena_device_kstat = ksp;
82 	ksp->ks_data = eds;
83 
84 	kstat_named_init(&eds->eds_reset_forced, "reset_forced",
85 	    KSTAT_DATA_UINT64);
86 	kstat_named_init(&eds->eds_reset_error, "reset_error",
87 	    KSTAT_DATA_UINT64);
88 	kstat_named_init(&eds->eds_reset_fatal, "reset_fatal",
89 	    KSTAT_DATA_UINT64);
90 	kstat_named_init(&eds->eds_reset_keepalive, "reset_keepalive",
91 	    KSTAT_DATA_UINT64);
92 	kstat_named_init(&eds->eds_reset_txstall, "reset_txstall",
93 	    KSTAT_DATA_UINT64);
94 
95 	kstat_install(ena->ena_device_kstat);
96 	return (true);
97 }
98 
99 static int
ena_stat_device_basic_update(kstat_t * ksp,int rw)100 ena_stat_device_basic_update(kstat_t *ksp, int rw)
101 {
102 	ena_t *ena = ksp->ks_private;
103 	ena_basic_stat_t *ebs = ksp->ks_data;
104 	enahw_resp_desc_t resp;
105 	enahw_resp_basic_stats_t *stats = &resp.erd_resp.erd_basic_stats;
106 	bool fetch;
107 	int ret = 0;
108 
109 	if (rw == KSTAT_WRITE) {
110 		return (EACCES);
111 	}
112 
113 	mutex_enter(&ena->ena_device_basic_stat_lock);
114 	fetch = gethrtime() - ena->ena_device_basic_stat_last_update >
115 	    ENA_BASIC_STATS_MINIMUM_INTERVAL_NS;
116 	mutex_exit(&ena->ena_device_basic_stat_lock);
117 
118 	if (!fetch)
119 		return (0);
120 
121 	if ((ret = ena_admin_get_basic_stats(ena, &resp)) != 0)
122 		return (ret);
123 
124 	mutex_enter(&ena->ena_device_basic_stat_lock);
125 	ena->ena_device_basic_stat_last_update = gethrtime();
126 
127 	ebs->ebs_tx_bytes.value.ui64 =
128 	    ((uint64_t)stats->erbs_tx_bytes_high << 32) |
129 	    (uint64_t)stats->erbs_tx_bytes_low;
130 	ebs->ebs_tx_pkts.value.ui64 =
131 	    ((uint64_t)stats->erbs_tx_pkts_high << 32) |
132 	    (uint64_t)stats->erbs_tx_pkts_low;
133 	ebs->ebs_tx_drops.value.ui64 =
134 	    ((uint64_t)stats->erbs_tx_drops_high << 32) |
135 	    (uint64_t)stats->erbs_tx_drops_low;
136 
137 	ebs->ebs_rx_bytes.value.ui64 =
138 	    ((uint64_t)stats->erbs_rx_bytes_high << 32) |
139 	    (uint64_t)stats->erbs_rx_bytes_low;
140 	ebs->ebs_rx_pkts.value.ui64 =
141 	    ((uint64_t)stats->erbs_rx_pkts_high << 32) |
142 	    (uint64_t)stats->erbs_rx_pkts_low;
143 	ebs->ebs_rx_drops.value.ui64 =
144 	    ((uint64_t)stats->erbs_rx_drops_high << 32) |
145 	    (uint64_t)stats->erbs_rx_drops_low;
146 	ebs->ebs_rx_overruns.value.ui64 =
147 	    ((uint64_t)stats->erbs_rx_overruns_high << 32) |
148 	    (uint64_t)stats->erbs_rx_overruns_low;
149 
150 	mutex_exit(&ena->ena_device_basic_stat_lock);
151 
152 	return (0);
153 }
154 
155 void
ena_stat_device_basic_cleanup(ena_t * ena)156 ena_stat_device_basic_cleanup(ena_t *ena)
157 {
158 	if (ena->ena_device_basic_kstat != NULL) {
159 		mutex_destroy(&ena->ena_device_basic_stat_lock);
160 		kstat_delete(ena->ena_device_basic_kstat);
161 		ena->ena_device_basic_kstat = NULL;
162 	}
163 }
164 
165 bool
ena_stat_device_basic_init(ena_t * ena)166 ena_stat_device_basic_init(ena_t *ena)
167 {
168 	kstat_t *ksp = kstat_create(ENA_MODULE_NAME,
169 	    ddi_get_instance(ena->ena_dip), "device_basic", "net",
170 	    KSTAT_TYPE_NAMED,
171 	    sizeof (ena_basic_stat_t) / sizeof (kstat_named_t), 0);
172 	ena_basic_stat_t *ebs = NULL;
173 
174 	if (ksp == NULL) {
175 		ena_err(ena, "!failed to create device_basic kstats");
176 		return (false);
177 	}
178 
179 	mutex_init(&ena->ena_device_basic_stat_lock, NULL, MUTEX_DRIVER,
180 	    DDI_INTR_PRI(ena->ena_intr_pri));
181 	ena->ena_device_basic_stat_last_update = 0;
182 
183 	ena->ena_device_basic_kstat = ksp;
184 	ebs = ksp->ks_data;
185 	ksp->ks_update = ena_stat_device_basic_update;
186 	ksp->ks_private = ena;
187 
188 	kstat_named_init(&ebs->ebs_tx_bytes, "tx_bytes", KSTAT_DATA_UINT64);
189 	ebs->ebs_tx_bytes.value.ui64 = 0;
190 	kstat_named_init(&ebs->ebs_tx_pkts, "tx_packets", KSTAT_DATA_UINT64);
191 	ebs->ebs_tx_pkts.value.ui64 = 0;
192 	kstat_named_init(&ebs->ebs_tx_drops, "tx_drops", KSTAT_DATA_UINT64);
193 	ebs->ebs_tx_drops.value.ui64 = 0;
194 
195 	kstat_named_init(&ebs->ebs_rx_bytes, "rx_bytes", KSTAT_DATA_UINT64);
196 	ebs->ebs_rx_bytes.value.ui64 = 0;
197 	kstat_named_init(&ebs->ebs_rx_pkts, "rx_packets", KSTAT_DATA_UINT64);
198 	ebs->ebs_rx_pkts.value.ui64 = 0;
199 	kstat_named_init(&ebs->ebs_rx_drops, "rx_drops", KSTAT_DATA_UINT64);
200 	ebs->ebs_rx_drops.value.ui64 = 0;
201 	kstat_named_init(&ebs->ebs_rx_overruns, "rx_overruns",
202 	    KSTAT_DATA_UINT64);
203 	ebs->ebs_rx_overruns.value.ui64 = 0;
204 
205 	kstat_install(ena->ena_device_basic_kstat);
206 	return (true);
207 }
208 
209 static int
ena_stat_device_extended_update(kstat_t * ksp,int rw)210 ena_stat_device_extended_update(kstat_t *ksp, int rw)
211 {
212 	ena_t *ena = ksp->ks_private;
213 	ena_extended_stat_t *ees = ksp->ks_data;
214 	enahw_resp_desc_t resp;
215 	enahw_resp_eni_stats_t *stats = &resp.erd_resp.erd_eni_stats;
216 	int ret = 0;
217 
218 	if (rw == KSTAT_WRITE) {
219 		return (EACCES);
220 	}
221 
222 	if ((ret = ena_admin_get_eni_stats(ena, &resp)) != 0) {
223 		return (ret);
224 	}
225 
226 	mutex_enter(&ena->ena_lock);
227 
228 	ees->ees_bw_in_exceeded.value.ui64 = stats->eres_bw_in_exceeded;
229 	ees->ees_bw_out_exceeded.value.ui64 = stats->eres_bw_out_exceeded;
230 	ees->ees_pps_exceeded.value.ui64 = stats->eres_pps_exceeded;
231 	ees->ees_conns_exceeded.value.ui64 = stats->eres_conns_exceeded;
232 	ees->ees_linklocal_exceeded.value.ui64 = stats->eres_linklocal_exceeded;
233 
234 	mutex_exit(&ena->ena_lock);
235 
236 	return (0);
237 }
238 
239 void
ena_stat_device_extended_cleanup(ena_t * ena)240 ena_stat_device_extended_cleanup(ena_t *ena)
241 {
242 	if (ena->ena_device_extended_kstat != NULL) {
243 		kstat_delete(ena->ena_device_extended_kstat);
244 		ena->ena_device_extended_kstat = NULL;
245 	}
246 }
247 
248 bool
ena_stat_device_extended_init(ena_t * ena)249 ena_stat_device_extended_init(ena_t *ena)
250 {
251 	kstat_t *ksp = kstat_create(ENA_MODULE_NAME,
252 	    ddi_get_instance(ena->ena_dip), "device_ext", "net",
253 	    KSTAT_TYPE_NAMED,
254 	    sizeof (ena_extended_stat_t) / sizeof (kstat_named_t), 0);
255 	ena_extended_stat_t *ees;
256 
257 	if (ksp == NULL) {
258 		ena_err(ena, "!failed to create device_ext kstats");
259 		return (false);
260 	}
261 
262 	ena->ena_device_extended_kstat = ksp;
263 	ees = ksp->ks_data;
264 	ksp->ks_update = ena_stat_device_extended_update;
265 	ksp->ks_private = ena;
266 
267 	kstat_named_init(&ees->ees_bw_in_exceeded, "bw_in_exceeded",
268 	    KSTAT_DATA_UINT64);
269 	ees->ees_bw_in_exceeded.value.ui64 = 0;
270 
271 	kstat_named_init(&ees->ees_bw_out_exceeded, "bw_out_exceeded",
272 	    KSTAT_DATA_UINT64);
273 	ees->ees_bw_out_exceeded.value.ui64 = 0;
274 
275 	kstat_named_init(&ees->ees_pps_exceeded, "pps_exceeded",
276 	    KSTAT_DATA_UINT64);
277 	ees->ees_pps_exceeded.value.ui64 = 0;
278 
279 	kstat_named_init(&ees->ees_conns_exceeded, "conns_exceeded",
280 	    KSTAT_DATA_UINT64);
281 	ees->ees_conns_exceeded.value.ui64 = 0;
282 
283 	kstat_named_init(&ees->ees_linklocal_exceeded, "linklocal_exceeded",
284 	    KSTAT_DATA_UINT64);
285 	ees->ees_linklocal_exceeded.value.ui64 = 0;
286 
287 	kstat_install(ena->ena_device_extended_kstat);
288 	return (true);
289 }
290 
291 void
ena_stat_aenq_cleanup(ena_t * ena)292 ena_stat_aenq_cleanup(ena_t *ena)
293 {
294 	if (ena->ena_aenq_kstat != NULL) {
295 		kstat_delete(ena->ena_aenq_kstat);
296 		ena->ena_aenq_kstat = NULL;
297 	}
298 }
299 
300 bool
ena_stat_aenq_init(ena_t * ena)301 ena_stat_aenq_init(ena_t *ena)
302 {
303 	kstat_t *ksp = kstat_create(ENA_MODULE_NAME,
304 	    ddi_get_instance(ena->ena_dip), "aenq", "net", KSTAT_TYPE_NAMED,
305 	    sizeof (ena_aenq_stat_t) / sizeof (kstat_named_t),
306 	    KSTAT_FLAG_VIRTUAL);
307 	ena_aenq_stat_t *eas = &ena->ena_aenq_stat;
308 
309 	if (ksp == NULL) {
310 		ena_err(ena, "!failed to create aenq kstats");
311 		return (false);
312 	}
313 
314 	ena->ena_aenq_kstat = ksp;
315 	ksp->ks_data = eas;
316 
317 	kstat_named_init(&eas->eaes_default, "default", KSTAT_DATA_UINT64);
318 	eas->eaes_default.value.ui64 = 0;
319 
320 	kstat_named_init(&eas->eaes_link_change, "link_change",
321 	    KSTAT_DATA_UINT64);
322 	eas->eaes_link_change.value.ui64 = 0;
323 
324 	kstat_named_init(&eas->eaes_notification, "notification",
325 	    KSTAT_DATA_UINT64);
326 	eas->eaes_notification.value.ui64 = 0;
327 
328 	kstat_named_init(&eas->eaes_keep_alive, "keep_alive",
329 	    KSTAT_DATA_UINT64);
330 	eas->eaes_keep_alive.value.ui64 = 0;
331 
332 	kstat_named_init(&eas->eaes_request_reset, "request_reset",
333 	    KSTAT_DATA_UINT64);
334 	eas->eaes_request_reset.value.ui64 = 0;
335 
336 	kstat_named_init(&eas->eaes_fatal_error, "fatal_error",
337 	    KSTAT_DATA_UINT64);
338 	eas->eaes_fatal_error.value.ui64 = 0;
339 
340 	kstat_named_init(&eas->eaes_warning, "warning", KSTAT_DATA_UINT64);
341 	eas->eaes_warning.value.ui64 = 0;
342 
343 	kstat_install(ena->ena_aenq_kstat);
344 	return (true);
345 }
346 
347 void
ena_stat_txq_cleanup(ena_txq_t * txq)348 ena_stat_txq_cleanup(ena_txq_t *txq)
349 {
350 	if (txq->et_kstat != NULL) {
351 		kstat_delete(txq->et_kstat);
352 		txq->et_kstat = NULL;
353 	}
354 }
355 
356 bool
ena_stat_txq_init(ena_txq_t * txq)357 ena_stat_txq_init(ena_txq_t *txq)
358 {
359 	ena_t *ena = txq->et_ena;
360 	kstat_t *ksp;
361 	char buf[128];
362 	ena_txq_stat_t *ets = &txq->et_stat;
363 
364 	(void) snprintf(buf, sizeof (buf), "txq_%d", txq->et_txqs_idx);
365 
366 	ksp = kstat_create(ENA_MODULE_NAME, ddi_get_instance(ena->ena_dip), buf,
367 	    "net", KSTAT_TYPE_NAMED,
368 	    sizeof (ena_txq_stat_t) / sizeof (kstat_named_t),
369 	    KSTAT_FLAG_VIRTUAL);
370 
371 	if (ksp == NULL) {
372 		ena_err(ena, "!failed to create %s kstats", buf);
373 		return (false);
374 	}
375 
376 	txq->et_kstat = ksp;
377 	ksp->ks_data = ets;
378 
379 	kstat_named_init(&ets->ets_hck_meoifail, "meoi_fail",
380 	    KSTAT_DATA_UINT64);
381 	ets->ets_hck_meoifail.value.ui64 = 0;
382 
383 	kstat_named_init(&ets->ets_blocked, "blocked", KSTAT_DATA_UINT64);
384 	ets->ets_blocked.value.ui64 = 0;
385 
386 	kstat_named_init(&ets->ets_unblocked, "unblocked", KSTAT_DATA_UINT64);
387 	ets->ets_unblocked.value.ui64 = 0;
388 
389 	kstat_named_init(&ets->ets_recycled, "recycled", KSTAT_DATA_UINT64);
390 	ets->ets_recycled.value.ui64 = 0;
391 
392 	kstat_named_init(&ets->ets_bytes, "bytes", KSTAT_DATA_UINT64);
393 	ets->ets_bytes.value.ui64 = 0;
394 
395 	kstat_named_init(&ets->ets_packets, "packets", KSTAT_DATA_UINT64);
396 	ets->ets_packets.value.ui64 = 0;
397 
398 	kstat_install(txq->et_kstat);
399 	return (true);
400 }
401 
402 void
ena_stat_rxq_cleanup(ena_rxq_t * rxq)403 ena_stat_rxq_cleanup(ena_rxq_t *rxq)
404 {
405 	if (rxq->er_kstat != NULL) {
406 		kstat_delete(rxq->er_kstat);
407 		rxq->er_kstat = NULL;
408 	}
409 }
410 
411 bool
ena_stat_rxq_init(ena_rxq_t * rxq)412 ena_stat_rxq_init(ena_rxq_t *rxq)
413 {
414 	ena_t *ena = rxq->er_ena;
415 	kstat_t *ksp;
416 	char buf[128];
417 	ena_rxq_stat_t *ers = &rxq->er_stat;
418 
419 	(void) snprintf(buf, sizeof (buf), "rxq_%d", rxq->er_rxqs_idx);
420 
421 	ksp = kstat_create(ENA_MODULE_NAME, ddi_get_instance(ena->ena_dip), buf,
422 	    "net", KSTAT_TYPE_NAMED,
423 	    sizeof (ena_rxq_stat_t) / sizeof (kstat_named_t),
424 	    KSTAT_FLAG_VIRTUAL);
425 
426 	if (ksp == NULL) {
427 		ena_err(ena, "!failed to create %s kstats", buf);
428 		return (false);
429 	}
430 
431 	rxq->er_kstat = ksp;
432 	ksp->ks_data = ers;
433 
434 	kstat_named_init(&ers->ers_packets, "packets", KSTAT_DATA_UINT64);
435 	ers->ers_packets.value.ui64 = 0;
436 
437 	kstat_named_init(&ers->ers_bytes, "bytes", KSTAT_DATA_UINT64);
438 	ers->ers_bytes.value.ui64 = 0;
439 
440 	kstat_named_init(&ers->ers_multi_desc, "multi_desc", KSTAT_DATA_UINT64);
441 	ers->ers_multi_desc.value.ui64 = 0;
442 
443 	kstat_named_init(&ers->ers_allocb_fail, "allocb_fail",
444 	    KSTAT_DATA_UINT64);
445 	ers->ers_allocb_fail.value.ui64 = 0;
446 
447 	kstat_named_init(&ers->ers_intr_limit, "intr_limit", KSTAT_DATA_UINT64);
448 	ers->ers_intr_limit.value.ui64 = 0;
449 
450 	kstat_named_init(&ers->ers_hck_ipv4_err, "hck_ipv4_err",
451 	    KSTAT_DATA_UINT64);
452 	ers->ers_hck_ipv4_err.value.ui64 = 0;
453 
454 	kstat_named_init(&ers->ers_hck_l4_err, "hck_l4_err", KSTAT_DATA_UINT64);
455 	ers->ers_hck_l4_err.value.ui64 = 0;
456 
457 	kstat_install(rxq->er_kstat);
458 	return (true);
459 }
460 
461 int
ena_ring_rx_stat(mac_ring_driver_t rh,uint_t stat,uint64_t * val)462 ena_ring_rx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
463 {
464 	int ret = 0;
465 	ena_rxq_t *rxq = (ena_rxq_t *)rh;
466 
467 	mutex_enter(&rxq->er_stat_lock);
468 
469 	switch (stat) {
470 	case MAC_STAT_RBYTES:
471 		*val = rxq->er_stat.ers_bytes.value.ui64;
472 		break;
473 	case MAC_STAT_IPACKETS:
474 		*val = rxq->er_stat.ers_packets.value.ui64;
475 		break;
476 	default:
477 		*val = 0;
478 		ret = ENOTSUP;
479 	}
480 
481 	mutex_exit(&rxq->er_stat_lock);
482 	return (ret);
483 }
484 
485 int
ena_ring_tx_stat(mac_ring_driver_t rh,uint_t stat,uint64_t * val)486 ena_ring_tx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
487 {
488 	int ret = 0;
489 	ena_txq_t *txq = (ena_txq_t *)rh;
490 
491 	mutex_enter(&txq->et_stat_lock);
492 
493 	switch (stat) {
494 	case MAC_STAT_OBYTES:
495 		*val = txq->et_stat.ets_bytes.value.ui64;
496 		break;
497 	case MAC_STAT_OPACKETS:
498 		*val = txq->et_stat.ets_packets.value.ui64;
499 		break;
500 	default:
501 		*val = 0;
502 		ret = ENOTSUP;
503 	}
504 
505 	mutex_exit(&txq->et_stat_lock);
506 	return (ret);
507 }
508 
509 int
ena_m_stat(void * arg,uint_t stat,uint64_t * val)510 ena_m_stat(void *arg, uint_t stat, uint64_t *val)
511 {
512 	ena_t *ena = arg;
513 	ena_basic_stat_t *ebs;
514 	int ret = 0;
515 	bool fetch = false;
516 
517 	/*
518 	 * The ENA device does not provide a lot of the stats that a
519 	 * traditional NIC device would. Return ENOTSUP early for any we don't
520 	 * support, and avoid a round trip to the controller.
521 	 */
522 	switch (stat) {
523 	case ETHER_STAT_LINK_DUPLEX:
524 	case MAC_STAT_IFSPEED:
525 		break;
526 	case MAC_STAT_IERRORS:
527 	case MAC_STAT_OERRORS:
528 	case MAC_STAT_NORCVBUF:
529 	case MAC_STAT_RBYTES:
530 	case MAC_STAT_IPACKETS:
531 	case MAC_STAT_OBYTES:
532 	case MAC_STAT_OPACKETS:
533 		fetch = true;
534 		break;
535 	default:
536 		return (ENOTSUP);
537 	}
538 
539 	if (fetch) {
540 		ret = ena_stat_device_basic_update(ena->ena_device_basic_kstat,
541 		    KSTAT_READ);
542 
543 		if (ret != 0)
544 			return (ret);
545 	}
546 
547 	mutex_enter(&ena->ena_device_basic_stat_lock);
548 	ebs = ena->ena_device_basic_kstat->ks_data;
549 
550 	switch (stat) {
551 	case ETHER_STAT_LINK_DUPLEX:
552 		*val = ena->ena_link_duplex;
553 		break;
554 
555 	case MAC_STAT_IFSPEED:
556 		*val = ena->ena_link_speed_mbits * 1000000ULL;
557 		break;
558 
559 	case MAC_STAT_NORCVBUF:
560 		*val = ebs->ebs_rx_overruns.value.ui64;
561 		break;
562 
563 	case MAC_STAT_RBYTES:
564 		*val = ebs->ebs_rx_bytes.value.ui64;
565 		break;
566 
567 	case MAC_STAT_IPACKETS:
568 		*val = ebs->ebs_rx_pkts.value.ui64;
569 		break;
570 
571 	case MAC_STAT_IERRORS:
572 		*val = ebs->ebs_rx_drops.value.ui64;
573 		break;
574 
575 	case MAC_STAT_OBYTES:
576 		*val = ebs->ebs_tx_bytes.value.ui64;
577 		break;
578 
579 	case MAC_STAT_OPACKETS:
580 		*val = ebs->ebs_tx_pkts.value.ui64;
581 		break;
582 
583 	case MAC_STAT_OERRORS:
584 		*val = ebs->ebs_tx_drops.value.ui64;
585 		break;
586 
587 	default:
588 		dev_err(ena->ena_dip, CE_PANIC, "unhandled stat, 0x%x", stat);
589 	}
590 
591 	mutex_exit(&ena->ena_device_basic_stat_lock);
592 	return (ret);
593 }
594