xref: /illumos-gate/usr/src/uts/common/io/ena/ena_stats.c (revision c46e4de3)
16f443ebcSRyan Zezeski /*
26f443ebcSRyan Zezeski  * This file and its contents are supplied under the terms of the
36f443ebcSRyan Zezeski  * Common Development and Distribution License ("CDDL"), version 1.0.
46f443ebcSRyan Zezeski  * You may only use this file in accordance with the terms of version
56f443ebcSRyan Zezeski  * 1.0 of the CDDL.
66f443ebcSRyan Zezeski  *
76f443ebcSRyan Zezeski  * A full copy of the text of the CDDL should have accompanied this
86f443ebcSRyan Zezeski  * source.  A copy of the CDDL is also available via the Internet at
96f443ebcSRyan Zezeski  * http://www.illumos.org/license/CDDL.
106f443ebcSRyan Zezeski  */
116f443ebcSRyan Zezeski 
126f443ebcSRyan Zezeski /*
13eebd18daSAndy Fiddaman  * Copyright 2024 Oxide Computer Company
146f443ebcSRyan Zezeski  */
15*c46e4de3SAndy Fiddaman 
166f443ebcSRyan Zezeski #include "ena.h"
176f443ebcSRyan Zezeski 
186f443ebcSRyan Zezeski /*
196f443ebcSRyan Zezeski  * The ENA device provides the following hardware stats. It appears
206f443ebcSRyan Zezeski  * that all stats are available at both a device-level and
216f443ebcSRyan Zezeski  * queue-level. However, Linux and FreeBSD don't implement queue
226f443ebcSRyan Zezeski  * scope. It's not clear how one would implement queue scope because
236f443ebcSRyan Zezeski  * there is nothing in the common code describing how to determine the
246f443ebcSRyan Zezeski  * queue index number. Both the SQ and CQ have device index values,
256f443ebcSRyan Zezeski  * but for a given logical queue they don't always match and so it's
266f443ebcSRyan Zezeski  * not clear what value to use for querying the stats. Therefore,
276f443ebcSRyan Zezeski  * device-wide basic and extended stats come from the device, while
286f443ebcSRyan Zezeski  * queue/ring stats come from driver.
296f443ebcSRyan Zezeski  *
306f443ebcSRyan Zezeski  * From empirical testing, these statistics appear to be cumulative.
316f443ebcSRyan Zezeski  * However, this guarantee is not explicitly documented anywhere in
326f443ebcSRyan Zezeski  * the common code that the author could find.
336f443ebcSRyan Zezeski  *
346f443ebcSRyan Zezeski  * BASIC (ENAHW_GET_STATS_TYPE_BASIC)
356f443ebcSRyan Zezeski  *
366f443ebcSRyan Zezeski  *     - Rx packets/bytes
376f443ebcSRyan Zezeski  *     - Rx drops
386f443ebcSRyan Zezeski  *     - Tx packets/bytes
396f443ebcSRyan Zezeski  *     - Tx drops
40*c46e4de3SAndy Fiddaman  *     - Rx overruns
416f443ebcSRyan Zezeski  *
426f443ebcSRyan Zezeski  * EXTENDED (ENAHW_GET_STATS_TYPE_EXTENDED)
436f443ebcSRyan Zezeski  *
446f443ebcSRyan Zezeski  *     There is no structure defined for these stats in the Linux
456f443ebcSRyan Zezeski  *     driver. Based on the FreeBSD driver, it looks like extended
466f443ebcSRyan Zezeski  *     stats are simply a buffer of C strings? Come back to this
476f443ebcSRyan Zezeski  *     later.
486f443ebcSRyan Zezeski  *
496f443ebcSRyan Zezeski  * ENI (ENAHW_GET_STATS_TYPE_ENI)
506f443ebcSRyan Zezeski  *
516f443ebcSRyan Zezeski  *     - Rx Bandwidth Allowance Exceeded
526f443ebcSRyan Zezeski  *     - Tx Bandwidth Allowance Exceeded
536f443ebcSRyan Zezeski  *     - PPS Allowance Exceeded (presumably for combined Rx/Tx)
546f443ebcSRyan Zezeski  *     - Connection Tracking PPS Allowance Exceeded
55*c46e4de3SAndy Fiddaman  *     - Link-local PPS Allowance Exceeded
566f443ebcSRyan Zezeski  */
576f443ebcSRyan Zezeski 
58*c46e4de3SAndy Fiddaman void
ena_stat_device_cleanup(ena_t * ena)59*c46e4de3SAndy Fiddaman ena_stat_device_cleanup(ena_t *ena)
60*c46e4de3SAndy Fiddaman {
61*c46e4de3SAndy Fiddaman 	if (ena->ena_device_kstat != NULL) {
62*c46e4de3SAndy Fiddaman 		kstat_delete(ena->ena_device_kstat);
63*c46e4de3SAndy Fiddaman 		ena->ena_device_kstat = NULL;
64*c46e4de3SAndy Fiddaman 	}
65*c46e4de3SAndy Fiddaman }
66*c46e4de3SAndy Fiddaman 
67*c46e4de3SAndy Fiddaman bool
ena_stat_device_init(ena_t * ena)68*c46e4de3SAndy Fiddaman ena_stat_device_init(ena_t *ena)
69*c46e4de3SAndy Fiddaman {
70*c46e4de3SAndy Fiddaman 	kstat_t *ksp = kstat_create(ENA_MODULE_NAME,
71*c46e4de3SAndy Fiddaman 	    ddi_get_instance(ena->ena_dip), "device", "net", KSTAT_TYPE_NAMED,
72*c46e4de3SAndy Fiddaman 	    sizeof (ena_device_stat_t) / sizeof (kstat_named_t),
73*c46e4de3SAndy Fiddaman 	    KSTAT_FLAG_VIRTUAL);
74*c46e4de3SAndy Fiddaman 	ena_device_stat_t *eds = &ena->ena_device_stat;
75*c46e4de3SAndy Fiddaman 
76*c46e4de3SAndy Fiddaman 	if (ksp == NULL) {
77*c46e4de3SAndy Fiddaman 		ena_err(ena, "!failed to create device kstats");
78*c46e4de3SAndy Fiddaman 		return (false);
79*c46e4de3SAndy Fiddaman 	}
80*c46e4de3SAndy Fiddaman 
81*c46e4de3SAndy Fiddaman 	ena->ena_device_kstat = ksp;
82*c46e4de3SAndy Fiddaman 	ksp->ks_data = eds;
83*c46e4de3SAndy Fiddaman 
84*c46e4de3SAndy Fiddaman 	kstat_named_init(&eds->eds_reset_forced, "reset_forced",
85*c46e4de3SAndy Fiddaman 	    KSTAT_DATA_UINT64);
86*c46e4de3SAndy Fiddaman 	kstat_named_init(&eds->eds_reset_error, "reset_error",
87*c46e4de3SAndy Fiddaman 	    KSTAT_DATA_UINT64);
88*c46e4de3SAndy Fiddaman 	kstat_named_init(&eds->eds_reset_fatal, "reset_fatal",
89*c46e4de3SAndy Fiddaman 	    KSTAT_DATA_UINT64);
90*c46e4de3SAndy Fiddaman 	kstat_named_init(&eds->eds_reset_keepalive, "reset_keepalive",
91*c46e4de3SAndy Fiddaman 	    KSTAT_DATA_UINT64);
92*c46e4de3SAndy Fiddaman 	kstat_named_init(&eds->eds_reset_txstall, "reset_txstall",
93*c46e4de3SAndy Fiddaman 	    KSTAT_DATA_UINT64);
94*c46e4de3SAndy Fiddaman 
95*c46e4de3SAndy Fiddaman 	kstat_install(ena->ena_device_kstat);
96*c46e4de3SAndy Fiddaman 	return (true);
97*c46e4de3SAndy Fiddaman }
98*c46e4de3SAndy Fiddaman 
996f443ebcSRyan Zezeski static int
ena_stat_device_basic_update(kstat_t * ksp,int rw)1006f443ebcSRyan Zezeski ena_stat_device_basic_update(kstat_t *ksp, int rw)
1016f443ebcSRyan Zezeski {
1026f443ebcSRyan Zezeski 	ena_t *ena = ksp->ks_private;
1036f443ebcSRyan Zezeski 	ena_basic_stat_t *ebs = ksp->ks_data;
1046f443ebcSRyan Zezeski 	enahw_resp_desc_t resp;
1056f443ebcSRyan Zezeski 	enahw_resp_basic_stats_t *stats = &resp.erd_resp.erd_basic_stats;
106*c46e4de3SAndy Fiddaman 	bool fetch;
1076f443ebcSRyan Zezeski 	int ret = 0;
1086f443ebcSRyan Zezeski 
1096f443ebcSRyan Zezeski 	if (rw == KSTAT_WRITE) {
1106f443ebcSRyan Zezeski 		return (EACCES);
1116f443ebcSRyan Zezeski 	}
1126f443ebcSRyan Zezeski 
113*c46e4de3SAndy Fiddaman 	mutex_enter(&ena->ena_device_basic_stat_lock);
114*c46e4de3SAndy Fiddaman 	fetch = gethrtime() - ena->ena_device_basic_stat_last_update >
115*c46e4de3SAndy Fiddaman 	    ENA_BASIC_STATS_MINIMUM_INTERVAL_NS;
116*c46e4de3SAndy Fiddaman 	mutex_exit(&ena->ena_device_basic_stat_lock);
117*c46e4de3SAndy Fiddaman 
118*c46e4de3SAndy Fiddaman 	if (!fetch)
119*c46e4de3SAndy Fiddaman 		return (0);
120*c46e4de3SAndy Fiddaman 
121*c46e4de3SAndy Fiddaman 	if ((ret = ena_admin_get_basic_stats(ena, &resp)) != 0)
1226f443ebcSRyan Zezeski 		return (ret);
1236f443ebcSRyan Zezeski 
124*c46e4de3SAndy Fiddaman 	mutex_enter(&ena->ena_device_basic_stat_lock);
125*c46e4de3SAndy Fiddaman 	ena->ena_device_basic_stat_last_update = gethrtime();
1266f443ebcSRyan Zezeski 
1276f443ebcSRyan Zezeski 	ebs->ebs_tx_bytes.value.ui64 =
1286f443ebcSRyan Zezeski 	    ((uint64_t)stats->erbs_tx_bytes_high << 32) |
1296f443ebcSRyan Zezeski 	    (uint64_t)stats->erbs_tx_bytes_low;
1306f443ebcSRyan Zezeski 	ebs->ebs_tx_pkts.value.ui64 =
1316f443ebcSRyan Zezeski 	    ((uint64_t)stats->erbs_tx_pkts_high << 32) |
1326f443ebcSRyan Zezeski 	    (uint64_t)stats->erbs_tx_pkts_low;
1336f443ebcSRyan Zezeski 	ebs->ebs_tx_drops.value.ui64 =
1346f443ebcSRyan Zezeski 	    ((uint64_t)stats->erbs_tx_drops_high << 32) |
1356f443ebcSRyan Zezeski 	    (uint64_t)stats->erbs_tx_drops_low;
1366f443ebcSRyan Zezeski 
1376f443ebcSRyan Zezeski 	ebs->ebs_rx_bytes.value.ui64 =
1386f443ebcSRyan Zezeski 	    ((uint64_t)stats->erbs_rx_bytes_high << 32) |
1396f443ebcSRyan Zezeski 	    (uint64_t)stats->erbs_rx_bytes_low;
1406f443ebcSRyan Zezeski 	ebs->ebs_rx_pkts.value.ui64 =
1416f443ebcSRyan Zezeski 	    ((uint64_t)stats->erbs_rx_pkts_high << 32) |
1426f443ebcSRyan Zezeski 	    (uint64_t)stats->erbs_rx_pkts_low;
1436f443ebcSRyan Zezeski 	ebs->ebs_rx_drops.value.ui64 =
1446f443ebcSRyan Zezeski 	    ((uint64_t)stats->erbs_rx_drops_high << 32) |
1456f443ebcSRyan Zezeski 	    (uint64_t)stats->erbs_rx_drops_low;
146*c46e4de3SAndy Fiddaman 	ebs->ebs_rx_overruns.value.ui64 =
147*c46e4de3SAndy Fiddaman 	    ((uint64_t)stats->erbs_rx_overruns_high << 32) |
148*c46e4de3SAndy Fiddaman 	    (uint64_t)stats->erbs_rx_overruns_low;
1496f443ebcSRyan Zezeski 
150*c46e4de3SAndy Fiddaman 	mutex_exit(&ena->ena_device_basic_stat_lock);
1516f443ebcSRyan Zezeski 
1526f443ebcSRyan Zezeski 	return (0);
1536f443ebcSRyan Zezeski }
1546f443ebcSRyan Zezeski 
1556f443ebcSRyan Zezeski void
ena_stat_device_basic_cleanup(ena_t * ena)1566f443ebcSRyan Zezeski ena_stat_device_basic_cleanup(ena_t *ena)
1576f443ebcSRyan Zezeski {
1586f443ebcSRyan Zezeski 	if (ena->ena_device_basic_kstat != NULL) {
159*c46e4de3SAndy Fiddaman 		mutex_destroy(&ena->ena_device_basic_stat_lock);
1606f443ebcSRyan Zezeski 		kstat_delete(ena->ena_device_basic_kstat);
1616f443ebcSRyan Zezeski 		ena->ena_device_basic_kstat = NULL;
1626f443ebcSRyan Zezeski 	}
1636f443ebcSRyan Zezeski }
1646f443ebcSRyan Zezeski 
165*c46e4de3SAndy Fiddaman bool
ena_stat_device_basic_init(ena_t * ena)1666f443ebcSRyan Zezeski ena_stat_device_basic_init(ena_t *ena)
1676f443ebcSRyan Zezeski {
1686f443ebcSRyan Zezeski 	kstat_t *ksp = kstat_create(ENA_MODULE_NAME,
1696f443ebcSRyan Zezeski 	    ddi_get_instance(ena->ena_dip), "device_basic", "net",
1706f443ebcSRyan Zezeski 	    KSTAT_TYPE_NAMED,
1716f443ebcSRyan Zezeski 	    sizeof (ena_basic_stat_t) / sizeof (kstat_named_t), 0);
1726f443ebcSRyan Zezeski 	ena_basic_stat_t *ebs = NULL;
1736f443ebcSRyan Zezeski 
1746f443ebcSRyan Zezeski 	if (ksp == NULL) {
1756f443ebcSRyan Zezeski 		ena_err(ena, "!failed to create device_basic kstats");
176*c46e4de3SAndy Fiddaman 		return (false);
1776f443ebcSRyan Zezeski 	}
1786f443ebcSRyan Zezeski 
179*c46e4de3SAndy Fiddaman 	mutex_init(&ena->ena_device_basic_stat_lock, NULL, MUTEX_DRIVER,
180*c46e4de3SAndy Fiddaman 	    DDI_INTR_PRI(ena->ena_intr_pri));
181*c46e4de3SAndy Fiddaman 	ena->ena_device_basic_stat_last_update = 0;
182*c46e4de3SAndy Fiddaman 
1836f443ebcSRyan Zezeski 	ena->ena_device_basic_kstat = ksp;
1846f443ebcSRyan Zezeski 	ebs = ksp->ks_data;
1856f443ebcSRyan Zezeski 	ksp->ks_update = ena_stat_device_basic_update;
1866f443ebcSRyan Zezeski 	ksp->ks_private = ena;
1876f443ebcSRyan Zezeski 
1886f443ebcSRyan Zezeski 	kstat_named_init(&ebs->ebs_tx_bytes, "tx_bytes", KSTAT_DATA_UINT64);
1896f443ebcSRyan Zezeski 	ebs->ebs_tx_bytes.value.ui64 = 0;
1906f443ebcSRyan Zezeski 	kstat_named_init(&ebs->ebs_tx_pkts, "tx_packets", KSTAT_DATA_UINT64);
1916f443ebcSRyan Zezeski 	ebs->ebs_tx_pkts.value.ui64 = 0;
1926f443ebcSRyan Zezeski 	kstat_named_init(&ebs->ebs_tx_drops, "tx_drops", KSTAT_DATA_UINT64);
1936f443ebcSRyan Zezeski 	ebs->ebs_tx_drops.value.ui64 = 0;
1946f443ebcSRyan Zezeski 
1956f443ebcSRyan Zezeski 	kstat_named_init(&ebs->ebs_rx_bytes, "rx_bytes", KSTAT_DATA_UINT64);
1966f443ebcSRyan Zezeski 	ebs->ebs_rx_bytes.value.ui64 = 0;
1976f443ebcSRyan Zezeski 	kstat_named_init(&ebs->ebs_rx_pkts, "rx_packets", KSTAT_DATA_UINT64);
1986f443ebcSRyan Zezeski 	ebs->ebs_rx_pkts.value.ui64 = 0;
1996f443ebcSRyan Zezeski 	kstat_named_init(&ebs->ebs_rx_drops, "rx_drops", KSTAT_DATA_UINT64);
2006f443ebcSRyan Zezeski 	ebs->ebs_rx_drops.value.ui64 = 0;
201*c46e4de3SAndy Fiddaman 	kstat_named_init(&ebs->ebs_rx_overruns, "rx_overruns",
202*c46e4de3SAndy Fiddaman 	    KSTAT_DATA_UINT64);
203*c46e4de3SAndy Fiddaman 	ebs->ebs_rx_overruns.value.ui64 = 0;
2046f443ebcSRyan Zezeski 
2056f443ebcSRyan Zezeski 	kstat_install(ena->ena_device_basic_kstat);
206*c46e4de3SAndy Fiddaman 	return (true);
2076f443ebcSRyan Zezeski }
2086f443ebcSRyan Zezeski 
209*c46e4de3SAndy Fiddaman static int
ena_stat_device_extended_update(kstat_t * ksp,int rw)2106f443ebcSRyan Zezeski ena_stat_device_extended_update(kstat_t *ksp, int rw)
2116f443ebcSRyan Zezeski {
2126f443ebcSRyan Zezeski 	ena_t *ena = ksp->ks_private;
2136f443ebcSRyan Zezeski 	ena_extended_stat_t *ees = ksp->ks_data;
2146f443ebcSRyan Zezeski 	enahw_resp_desc_t resp;
2156f443ebcSRyan Zezeski 	enahw_resp_eni_stats_t *stats = &resp.erd_resp.erd_eni_stats;
2166f443ebcSRyan Zezeski 	int ret = 0;
2176f443ebcSRyan Zezeski 
2186f443ebcSRyan Zezeski 	if (rw == KSTAT_WRITE) {
2196f443ebcSRyan Zezeski 		return (EACCES);
2206f443ebcSRyan Zezeski 	}
2216f443ebcSRyan Zezeski 
2226f443ebcSRyan Zezeski 	if ((ret = ena_admin_get_eni_stats(ena, &resp)) != 0) {
2236f443ebcSRyan Zezeski 		return (ret);
2246f443ebcSRyan Zezeski 	}
2256f443ebcSRyan Zezeski 
2266f443ebcSRyan Zezeski 	mutex_enter(&ena->ena_lock);
2276f443ebcSRyan Zezeski 
2286f443ebcSRyan Zezeski 	ees->ees_bw_in_exceeded.value.ui64 = stats->eres_bw_in_exceeded;
2296f443ebcSRyan Zezeski 	ees->ees_bw_out_exceeded.value.ui64 = stats->eres_bw_out_exceeded;
2306f443ebcSRyan Zezeski 	ees->ees_pps_exceeded.value.ui64 = stats->eres_pps_exceeded;
2316f443ebcSRyan Zezeski 	ees->ees_conns_exceeded.value.ui64 = stats->eres_conns_exceeded;
2326f443ebcSRyan Zezeski 	ees->ees_linklocal_exceeded.value.ui64 = stats->eres_linklocal_exceeded;
2336f443ebcSRyan Zezeski 
2346f443ebcSRyan Zezeski 	mutex_exit(&ena->ena_lock);
2356f443ebcSRyan Zezeski 
2366f443ebcSRyan Zezeski 	return (0);
2376f443ebcSRyan Zezeski }
2386f443ebcSRyan Zezeski 
2396f443ebcSRyan Zezeski void
ena_stat_device_extended_cleanup(ena_t * ena)2406f443ebcSRyan Zezeski ena_stat_device_extended_cleanup(ena_t *ena)
2416f443ebcSRyan Zezeski {
2426f443ebcSRyan Zezeski 	if (ena->ena_device_extended_kstat != NULL) {
2436f443ebcSRyan Zezeski 		kstat_delete(ena->ena_device_extended_kstat);
2446f443ebcSRyan Zezeski 		ena->ena_device_extended_kstat = NULL;
2456f443ebcSRyan Zezeski 	}
2466f443ebcSRyan Zezeski }
2476f443ebcSRyan Zezeski 
248*c46e4de3SAndy Fiddaman bool
ena_stat_device_extended_init(ena_t * ena)2496f443ebcSRyan Zezeski ena_stat_device_extended_init(ena_t *ena)
2506f443ebcSRyan Zezeski {
2516f443ebcSRyan Zezeski 	kstat_t *ksp = kstat_create(ENA_MODULE_NAME,
2526f443ebcSRyan Zezeski 	    ddi_get_instance(ena->ena_dip), "device_ext", "net",
2536f443ebcSRyan Zezeski 	    KSTAT_TYPE_NAMED,
2546f443ebcSRyan Zezeski 	    sizeof (ena_extended_stat_t) / sizeof (kstat_named_t), 0);
2556f443ebcSRyan Zezeski 	ena_extended_stat_t *ees;
2566f443ebcSRyan Zezeski 
2576f443ebcSRyan Zezeski 	if (ksp == NULL) {
2586f443ebcSRyan Zezeski 		ena_err(ena, "!failed to create device_ext kstats");
259*c46e4de3SAndy Fiddaman 		return (false);
2606f443ebcSRyan Zezeski 	}
2616f443ebcSRyan Zezeski 
2626f443ebcSRyan Zezeski 	ena->ena_device_extended_kstat = ksp;
2636f443ebcSRyan Zezeski 	ees = ksp->ks_data;
2646f443ebcSRyan Zezeski 	ksp->ks_update = ena_stat_device_extended_update;
2656f443ebcSRyan Zezeski 	ksp->ks_private = ena;
2666f443ebcSRyan Zezeski 
2676f443ebcSRyan Zezeski 	kstat_named_init(&ees->ees_bw_in_exceeded, "bw_in_exceeded",
2686f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
2696f443ebcSRyan Zezeski 	ees->ees_bw_in_exceeded.value.ui64 = 0;
2706f443ebcSRyan Zezeski 
2716f443ebcSRyan Zezeski 	kstat_named_init(&ees->ees_bw_out_exceeded, "bw_out_exceeded",
2726f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
2736f443ebcSRyan Zezeski 	ees->ees_bw_out_exceeded.value.ui64 = 0;
2746f443ebcSRyan Zezeski 
2756f443ebcSRyan Zezeski 	kstat_named_init(&ees->ees_pps_exceeded, "pps_exceeded",
2766f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
2776f443ebcSRyan Zezeski 	ees->ees_pps_exceeded.value.ui64 = 0;
2786f443ebcSRyan Zezeski 
2796f443ebcSRyan Zezeski 	kstat_named_init(&ees->ees_conns_exceeded, "conns_exceeded",
2806f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
2816f443ebcSRyan Zezeski 	ees->ees_conns_exceeded.value.ui64 = 0;
2826f443ebcSRyan Zezeski 
2836f443ebcSRyan Zezeski 	kstat_named_init(&ees->ees_linklocal_exceeded, "linklocal_exceeded",
2846f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
2856f443ebcSRyan Zezeski 	ees->ees_linklocal_exceeded.value.ui64 = 0;
2866f443ebcSRyan Zezeski 
2876f443ebcSRyan Zezeski 	kstat_install(ena->ena_device_extended_kstat);
288*c46e4de3SAndy Fiddaman 	return (true);
2896f443ebcSRyan Zezeski }
2906f443ebcSRyan Zezeski 
2916f443ebcSRyan Zezeski void
ena_stat_aenq_cleanup(ena_t * ena)2926f443ebcSRyan Zezeski ena_stat_aenq_cleanup(ena_t *ena)
2936f443ebcSRyan Zezeski {
2946f443ebcSRyan Zezeski 	if (ena->ena_aenq_kstat != NULL) {
2956f443ebcSRyan Zezeski 		kstat_delete(ena->ena_aenq_kstat);
2966f443ebcSRyan Zezeski 		ena->ena_aenq_kstat = NULL;
2976f443ebcSRyan Zezeski 	}
2986f443ebcSRyan Zezeski }
2996f443ebcSRyan Zezeski 
300*c46e4de3SAndy Fiddaman bool
ena_stat_aenq_init(ena_t * ena)3016f443ebcSRyan Zezeski ena_stat_aenq_init(ena_t *ena)
3026f443ebcSRyan Zezeski {
3036f443ebcSRyan Zezeski 	kstat_t *ksp = kstat_create(ENA_MODULE_NAME,
3046f443ebcSRyan Zezeski 	    ddi_get_instance(ena->ena_dip), "aenq", "net", KSTAT_TYPE_NAMED,
3056f443ebcSRyan Zezeski 	    sizeof (ena_aenq_stat_t) / sizeof (kstat_named_t),
3066f443ebcSRyan Zezeski 	    KSTAT_FLAG_VIRTUAL);
3076f443ebcSRyan Zezeski 	ena_aenq_stat_t *eas = &ena->ena_aenq_stat;
3086f443ebcSRyan Zezeski 
3096f443ebcSRyan Zezeski 	if (ksp == NULL) {
3106f443ebcSRyan Zezeski 		ena_err(ena, "!failed to create aenq kstats");
311*c46e4de3SAndy Fiddaman 		return (false);
3126f443ebcSRyan Zezeski 	}
3136f443ebcSRyan Zezeski 
3146f443ebcSRyan Zezeski 	ena->ena_aenq_kstat = ksp;
3156f443ebcSRyan Zezeski 	ksp->ks_data = eas;
3166f443ebcSRyan Zezeski 
3176f443ebcSRyan Zezeski 	kstat_named_init(&eas->eaes_default, "default", KSTAT_DATA_UINT64);
3186f443ebcSRyan Zezeski 	eas->eaes_default.value.ui64 = 0;
3196f443ebcSRyan Zezeski 
3206f443ebcSRyan Zezeski 	kstat_named_init(&eas->eaes_link_change, "link_change",
3216f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
3226f443ebcSRyan Zezeski 	eas->eaes_link_change.value.ui64 = 0;
3236f443ebcSRyan Zezeski 
324*c46e4de3SAndy Fiddaman 	kstat_named_init(&eas->eaes_notification, "notification",
325*c46e4de3SAndy Fiddaman 	    KSTAT_DATA_UINT64);
326*c46e4de3SAndy Fiddaman 	eas->eaes_notification.value.ui64 = 0;
327*c46e4de3SAndy Fiddaman 
328*c46e4de3SAndy Fiddaman 	kstat_named_init(&eas->eaes_keep_alive, "keep_alive",
329*c46e4de3SAndy Fiddaman 	    KSTAT_DATA_UINT64);
330*c46e4de3SAndy Fiddaman 	eas->eaes_keep_alive.value.ui64 = 0;
331*c46e4de3SAndy Fiddaman 
332*c46e4de3SAndy Fiddaman 	kstat_named_init(&eas->eaes_request_reset, "request_reset",
333*c46e4de3SAndy Fiddaman 	    KSTAT_DATA_UINT64);
334*c46e4de3SAndy Fiddaman 	eas->eaes_request_reset.value.ui64 = 0;
335*c46e4de3SAndy Fiddaman 
336*c46e4de3SAndy Fiddaman 	kstat_named_init(&eas->eaes_fatal_error, "fatal_error",
337*c46e4de3SAndy Fiddaman 	    KSTAT_DATA_UINT64);
338*c46e4de3SAndy Fiddaman 	eas->eaes_fatal_error.value.ui64 = 0;
339*c46e4de3SAndy Fiddaman 
340*c46e4de3SAndy Fiddaman 	kstat_named_init(&eas->eaes_warning, "warning", KSTAT_DATA_UINT64);
341*c46e4de3SAndy Fiddaman 	eas->eaes_warning.value.ui64 = 0;
342*c46e4de3SAndy Fiddaman 
3436f443ebcSRyan Zezeski 	kstat_install(ena->ena_aenq_kstat);
344*c46e4de3SAndy Fiddaman 	return (true);
3456f443ebcSRyan Zezeski }
3466f443ebcSRyan Zezeski 
3476f443ebcSRyan Zezeski void
ena_stat_txq_cleanup(ena_txq_t * txq)3486f443ebcSRyan Zezeski ena_stat_txq_cleanup(ena_txq_t *txq)
3496f443ebcSRyan Zezeski {
3506f443ebcSRyan Zezeski 	if (txq->et_kstat != NULL) {
3516f443ebcSRyan Zezeski 		kstat_delete(txq->et_kstat);
3526f443ebcSRyan Zezeski 		txq->et_kstat = NULL;
3536f443ebcSRyan Zezeski 	}
3546f443ebcSRyan Zezeski }
3556f443ebcSRyan Zezeski 
356*c46e4de3SAndy Fiddaman bool
ena_stat_txq_init(ena_txq_t * txq)3576f443ebcSRyan Zezeski ena_stat_txq_init(ena_txq_t *txq)
3586f443ebcSRyan Zezeski {
3596f443ebcSRyan Zezeski 	ena_t *ena = txq->et_ena;
3606f443ebcSRyan Zezeski 	kstat_t *ksp;
3616f443ebcSRyan Zezeski 	char buf[128];
3626f443ebcSRyan Zezeski 	ena_txq_stat_t *ets = &txq->et_stat;
3636f443ebcSRyan Zezeski 
3646f443ebcSRyan Zezeski 	(void) snprintf(buf, sizeof (buf), "txq_%d", txq->et_txqs_idx);
3656f443ebcSRyan Zezeski 
3666f443ebcSRyan Zezeski 	ksp = kstat_create(ENA_MODULE_NAME, ddi_get_instance(ena->ena_dip), buf,
3676f443ebcSRyan Zezeski 	    "net", KSTAT_TYPE_NAMED,
3686f443ebcSRyan Zezeski 	    sizeof (ena_txq_stat_t) / sizeof (kstat_named_t),
3696f443ebcSRyan Zezeski 	    KSTAT_FLAG_VIRTUAL);
3706f443ebcSRyan Zezeski 
3716f443ebcSRyan Zezeski 	if (ksp == NULL) {
3726f443ebcSRyan Zezeski 		ena_err(ena, "!failed to create %s kstats", buf);
373*c46e4de3SAndy Fiddaman 		return (false);
3746f443ebcSRyan Zezeski 	}
3756f443ebcSRyan Zezeski 
3766f443ebcSRyan Zezeski 	txq->et_kstat = ksp;
3776f443ebcSRyan Zezeski 	ksp->ks_data = ets;
3786f443ebcSRyan Zezeski 
3796f443ebcSRyan Zezeski 	kstat_named_init(&ets->ets_hck_meoifail, "meoi_fail",
3806f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
3816f443ebcSRyan Zezeski 	ets->ets_hck_meoifail.value.ui64 = 0;
3826f443ebcSRyan Zezeski 
3836f443ebcSRyan Zezeski 	kstat_named_init(&ets->ets_blocked, "blocked", KSTAT_DATA_UINT64);
3846f443ebcSRyan Zezeski 	ets->ets_blocked.value.ui64 = 0;
3856f443ebcSRyan Zezeski 
3866f443ebcSRyan Zezeski 	kstat_named_init(&ets->ets_unblocked, "unblocked", KSTAT_DATA_UINT64);
3876f443ebcSRyan Zezeski 	ets->ets_unblocked.value.ui64 = 0;
3886f443ebcSRyan Zezeski 
3896f443ebcSRyan Zezeski 	kstat_named_init(&ets->ets_recycled, "recycled", KSTAT_DATA_UINT64);
3906f443ebcSRyan Zezeski 	ets->ets_recycled.value.ui64 = 0;
3916f443ebcSRyan Zezeski 
3926f443ebcSRyan Zezeski 	kstat_named_init(&ets->ets_bytes, "bytes", KSTAT_DATA_UINT64);
3936f443ebcSRyan Zezeski 	ets->ets_bytes.value.ui64 = 0;
3946f443ebcSRyan Zezeski 
3956f443ebcSRyan Zezeski 	kstat_named_init(&ets->ets_packets, "packets", KSTAT_DATA_UINT64);
3966f443ebcSRyan Zezeski 	ets->ets_packets.value.ui64 = 0;
3976f443ebcSRyan Zezeski 
3986f443ebcSRyan Zezeski 	kstat_install(txq->et_kstat);
399*c46e4de3SAndy Fiddaman 	return (true);
4006f443ebcSRyan Zezeski }
4016f443ebcSRyan Zezeski 
4026f443ebcSRyan Zezeski void
ena_stat_rxq_cleanup(ena_rxq_t * rxq)4036f443ebcSRyan Zezeski ena_stat_rxq_cleanup(ena_rxq_t *rxq)
4046f443ebcSRyan Zezeski {
4056f443ebcSRyan Zezeski 	if (rxq->er_kstat != NULL) {
4066f443ebcSRyan Zezeski 		kstat_delete(rxq->er_kstat);
4076f443ebcSRyan Zezeski 		rxq->er_kstat = NULL;
4086f443ebcSRyan Zezeski 	}
4096f443ebcSRyan Zezeski }
4106f443ebcSRyan Zezeski 
411*c46e4de3SAndy Fiddaman bool
ena_stat_rxq_init(ena_rxq_t * rxq)4126f443ebcSRyan Zezeski ena_stat_rxq_init(ena_rxq_t *rxq)
4136f443ebcSRyan Zezeski {
4146f443ebcSRyan Zezeski 	ena_t *ena = rxq->er_ena;
4156f443ebcSRyan Zezeski 	kstat_t *ksp;
4166f443ebcSRyan Zezeski 	char buf[128];
4176f443ebcSRyan Zezeski 	ena_rxq_stat_t *ers = &rxq->er_stat;
4186f443ebcSRyan Zezeski 
4196f443ebcSRyan Zezeski 	(void) snprintf(buf, sizeof (buf), "rxq_%d", rxq->er_rxqs_idx);
4206f443ebcSRyan Zezeski 
4216f443ebcSRyan Zezeski 	ksp = kstat_create(ENA_MODULE_NAME, ddi_get_instance(ena->ena_dip), buf,
4226f443ebcSRyan Zezeski 	    "net", KSTAT_TYPE_NAMED,
4236f443ebcSRyan Zezeski 	    sizeof (ena_rxq_stat_t) / sizeof (kstat_named_t),
4246f443ebcSRyan Zezeski 	    KSTAT_FLAG_VIRTUAL);
4256f443ebcSRyan Zezeski 
4266f443ebcSRyan Zezeski 	if (ksp == NULL) {
4276f443ebcSRyan Zezeski 		ena_err(ena, "!failed to create %s kstats", buf);
428*c46e4de3SAndy Fiddaman 		return (false);
4296f443ebcSRyan Zezeski 	}
4306f443ebcSRyan Zezeski 
4316f443ebcSRyan Zezeski 	rxq->er_kstat = ksp;
4326f443ebcSRyan Zezeski 	ksp->ks_data = ers;
4336f443ebcSRyan Zezeski 
4346f443ebcSRyan Zezeski 	kstat_named_init(&ers->ers_packets, "packets", KSTAT_DATA_UINT64);
4356f443ebcSRyan Zezeski 	ers->ers_packets.value.ui64 = 0;
4366f443ebcSRyan Zezeski 
4376f443ebcSRyan Zezeski 	kstat_named_init(&ers->ers_bytes, "bytes", KSTAT_DATA_UINT64);
4386f443ebcSRyan Zezeski 	ers->ers_bytes.value.ui64 = 0;
4396f443ebcSRyan Zezeski 
4406f443ebcSRyan Zezeski 	kstat_named_init(&ers->ers_multi_desc, "multi_desc", KSTAT_DATA_UINT64);
4416f443ebcSRyan Zezeski 	ers->ers_multi_desc.value.ui64 = 0;
4426f443ebcSRyan Zezeski 
4436f443ebcSRyan Zezeski 	kstat_named_init(&ers->ers_allocb_fail, "allocb_fail",
4446f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
4456f443ebcSRyan Zezeski 	ers->ers_allocb_fail.value.ui64 = 0;
4466f443ebcSRyan Zezeski 
4476f443ebcSRyan Zezeski 	kstat_named_init(&ers->ers_intr_limit, "intr_limit", KSTAT_DATA_UINT64);
4486f443ebcSRyan Zezeski 	ers->ers_intr_limit.value.ui64 = 0;
4496f443ebcSRyan Zezeski 
4506f443ebcSRyan Zezeski 	kstat_named_init(&ers->ers_hck_ipv4_err, "hck_ipv4_err",
4516f443ebcSRyan Zezeski 	    KSTAT_DATA_UINT64);
4526f443ebcSRyan Zezeski 	ers->ers_hck_ipv4_err.value.ui64 = 0;
4536f443ebcSRyan Zezeski 
4546f443ebcSRyan Zezeski 	kstat_named_init(&ers->ers_hck_l4_err, "hck_l4_err", KSTAT_DATA_UINT64);
4556f443ebcSRyan Zezeski 	ers->ers_hck_l4_err.value.ui64 = 0;
4566f443ebcSRyan Zezeski 
4576f443ebcSRyan Zezeski 	kstat_install(rxq->er_kstat);
458*c46e4de3SAndy Fiddaman 	return (true);
4596f443ebcSRyan Zezeski }
4606f443ebcSRyan Zezeski 
4616f443ebcSRyan Zezeski int
ena_ring_rx_stat(mac_ring_driver_t rh,uint_t stat,uint64_t * val)4626f443ebcSRyan Zezeski ena_ring_rx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
4636f443ebcSRyan Zezeski {
4646f443ebcSRyan Zezeski 	int ret = 0;
4656f443ebcSRyan Zezeski 	ena_rxq_t *rxq = (ena_rxq_t *)rh;
4666f443ebcSRyan Zezeski 
4676f443ebcSRyan Zezeski 	mutex_enter(&rxq->er_stat_lock);
4686f443ebcSRyan Zezeski 
4696f443ebcSRyan Zezeski 	switch (stat) {
4706f443ebcSRyan Zezeski 	case MAC_STAT_RBYTES:
4716f443ebcSRyan Zezeski 		*val = rxq->er_stat.ers_bytes.value.ui64;
4726f443ebcSRyan Zezeski 		break;
4736f443ebcSRyan Zezeski 	case MAC_STAT_IPACKETS:
4746f443ebcSRyan Zezeski 		*val = rxq->er_stat.ers_packets.value.ui64;
4756f443ebcSRyan Zezeski 		break;
4766f443ebcSRyan Zezeski 	default:
4776f443ebcSRyan Zezeski 		*val = 0;
4786f443ebcSRyan Zezeski 		ret = ENOTSUP;
4796f443ebcSRyan Zezeski 	}
4806f443ebcSRyan Zezeski 
4816f443ebcSRyan Zezeski 	mutex_exit(&rxq->er_stat_lock);
4826f443ebcSRyan Zezeski 	return (ret);
4836f443ebcSRyan Zezeski }
4846f443ebcSRyan Zezeski 
4856f443ebcSRyan Zezeski int
ena_ring_tx_stat(mac_ring_driver_t rh,uint_t stat,uint64_t * val)4866f443ebcSRyan Zezeski ena_ring_tx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
4876f443ebcSRyan Zezeski {
4886f443ebcSRyan Zezeski 	int ret = 0;
4896f443ebcSRyan Zezeski 	ena_txq_t *txq = (ena_txq_t *)rh;
4906f443ebcSRyan Zezeski 
4916f443ebcSRyan Zezeski 	mutex_enter(&txq->et_stat_lock);
4926f443ebcSRyan Zezeski 
4936f443ebcSRyan Zezeski 	switch (stat) {
4946f443ebcSRyan Zezeski 	case MAC_STAT_OBYTES:
4956f443ebcSRyan Zezeski 		*val = txq->et_stat.ets_bytes.value.ui64;
4966f443ebcSRyan Zezeski 		break;
4976f443ebcSRyan Zezeski 	case MAC_STAT_OPACKETS:
4986f443ebcSRyan Zezeski 		*val = txq->et_stat.ets_packets.value.ui64;
4996f443ebcSRyan Zezeski 		break;
5006f443ebcSRyan Zezeski 	default:
5016f443ebcSRyan Zezeski 		*val = 0;
5026f443ebcSRyan Zezeski 		ret = ENOTSUP;
5036f443ebcSRyan Zezeski 	}
5046f443ebcSRyan Zezeski 
5056f443ebcSRyan Zezeski 	mutex_exit(&txq->et_stat_lock);
5066f443ebcSRyan Zezeski 	return (ret);
5076f443ebcSRyan Zezeski }
5086f443ebcSRyan Zezeski 
5096f443ebcSRyan Zezeski int
ena_m_stat(void * arg,uint_t stat,uint64_t * val)5106f443ebcSRyan Zezeski ena_m_stat(void *arg, uint_t stat, uint64_t *val)
5116f443ebcSRyan Zezeski {
5126f443ebcSRyan Zezeski 	ena_t *ena = arg;
513eebd18daSAndy Fiddaman 	ena_basic_stat_t *ebs;
5146f443ebcSRyan Zezeski 	int ret = 0;
515*c46e4de3SAndy Fiddaman 	bool fetch = false;
5166f443ebcSRyan Zezeski 
517eebd18daSAndy Fiddaman 	/*
518eebd18daSAndy Fiddaman 	 * The ENA device does not provide a lot of the stats that a
519eebd18daSAndy Fiddaman 	 * traditional NIC device would. Return ENOTSUP early for any we don't
520eebd18daSAndy Fiddaman 	 * support, and avoid a round trip to the controller.
521eebd18daSAndy Fiddaman 	 */
522eebd18daSAndy Fiddaman 	switch (stat) {
523*c46e4de3SAndy Fiddaman 	case ETHER_STAT_LINK_DUPLEX:
524*c46e4de3SAndy Fiddaman 	case MAC_STAT_IFSPEED:
525*c46e4de3SAndy Fiddaman 		break;
526*c46e4de3SAndy Fiddaman 	case MAC_STAT_IERRORS:
527*c46e4de3SAndy Fiddaman 	case MAC_STAT_OERRORS:
528eebd18daSAndy Fiddaman 	case MAC_STAT_NORCVBUF:
529eebd18daSAndy Fiddaman 	case MAC_STAT_RBYTES:
530eebd18daSAndy Fiddaman 	case MAC_STAT_IPACKETS:
531eebd18daSAndy Fiddaman 	case MAC_STAT_OBYTES:
532eebd18daSAndy Fiddaman 	case MAC_STAT_OPACKETS:
533*c46e4de3SAndy Fiddaman 		fetch = true;
534eebd18daSAndy Fiddaman 		break;
535eebd18daSAndy Fiddaman 	default:
536eebd18daSAndy Fiddaman 		return (ENOTSUP);
537eebd18daSAndy Fiddaman 	}
538eebd18daSAndy Fiddaman 
539*c46e4de3SAndy Fiddaman 	if (fetch) {
540*c46e4de3SAndy Fiddaman 		ret = ena_stat_device_basic_update(ena->ena_device_basic_kstat,
541*c46e4de3SAndy Fiddaman 		    KSTAT_READ);
5426f443ebcSRyan Zezeski 
543*c46e4de3SAndy Fiddaman 		if (ret != 0)
544*c46e4de3SAndy Fiddaman 			return (ret);
5456f443ebcSRyan Zezeski 	}
5466f443ebcSRyan Zezeski 
547*c46e4de3SAndy Fiddaman 	mutex_enter(&ena->ena_device_basic_stat_lock);
548eebd18daSAndy Fiddaman 	ebs = ena->ena_device_basic_kstat->ks_data;
5496f443ebcSRyan Zezeski 
5506f443ebcSRyan Zezeski 	switch (stat) {
551*c46e4de3SAndy Fiddaman 	case ETHER_STAT_LINK_DUPLEX:
552*c46e4de3SAndy Fiddaman 		*val = ena->ena_link_duplex;
553*c46e4de3SAndy Fiddaman 		break;
554*c46e4de3SAndy Fiddaman 
555*c46e4de3SAndy Fiddaman 	case MAC_STAT_IFSPEED:
556*c46e4de3SAndy Fiddaman 		*val = ena->ena_link_speed_mbits * 1000000ULL;
557*c46e4de3SAndy Fiddaman 		break;
558*c46e4de3SAndy Fiddaman 
5596f443ebcSRyan Zezeski 	case MAC_STAT_NORCVBUF:
560*c46e4de3SAndy Fiddaman 		*val = ebs->ebs_rx_overruns.value.ui64;
5616f443ebcSRyan Zezeski 		break;
5626f443ebcSRyan Zezeski 
5636f443ebcSRyan Zezeski 	case MAC_STAT_RBYTES:
5646f443ebcSRyan Zezeski 		*val = ebs->ebs_rx_bytes.value.ui64;
5656f443ebcSRyan Zezeski 		break;
5666f443ebcSRyan Zezeski 
5676f443ebcSRyan Zezeski 	case MAC_STAT_IPACKETS:
5686f443ebcSRyan Zezeski 		*val = ebs->ebs_rx_pkts.value.ui64;
5696f443ebcSRyan Zezeski 		break;
5706f443ebcSRyan Zezeski 
571*c46e4de3SAndy Fiddaman 	case MAC_STAT_IERRORS:
572*c46e4de3SAndy Fiddaman 		*val = ebs->ebs_rx_drops.value.ui64;
573*c46e4de3SAndy Fiddaman 		break;
574*c46e4de3SAndy Fiddaman 
5756f443ebcSRyan Zezeski 	case MAC_STAT_OBYTES:
5766f443ebcSRyan Zezeski 		*val = ebs->ebs_tx_bytes.value.ui64;
5776f443ebcSRyan Zezeski 		break;
5786f443ebcSRyan Zezeski 
5796f443ebcSRyan Zezeski 	case MAC_STAT_OPACKETS:
5806f443ebcSRyan Zezeski 		*val = ebs->ebs_tx_pkts.value.ui64;
5816f443ebcSRyan Zezeski 		break;
5826f443ebcSRyan Zezeski 
583*c46e4de3SAndy Fiddaman 	case MAC_STAT_OERRORS:
584*c46e4de3SAndy Fiddaman 		*val = ebs->ebs_tx_drops.value.ui64;
585*c46e4de3SAndy Fiddaman 		break;
586*c46e4de3SAndy Fiddaman 
5876f443ebcSRyan Zezeski 	default:
588eebd18daSAndy Fiddaman 		dev_err(ena->ena_dip, CE_PANIC, "unhandled stat, 0x%x", stat);
5896f443ebcSRyan Zezeski 	}
5906f443ebcSRyan Zezeski 
591*c46e4de3SAndy Fiddaman 	mutex_exit(&ena->ena_device_basic_stat_lock);
5926f443ebcSRyan Zezeski 	return (ret);
5936f443ebcSRyan Zezeski }
594