19d26e4fcSRobert Mustacchi /*
29d26e4fcSRobert Mustacchi  * This file and its contents are supplied under the terms of the
39d26e4fcSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
49d26e4fcSRobert Mustacchi  * You may only use this file in accordance with the terms of version
59d26e4fcSRobert Mustacchi  * 1.0 of the CDDL.
69d26e4fcSRobert Mustacchi  *
79d26e4fcSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
89d26e4fcSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
99d26e4fcSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
109d26e4fcSRobert Mustacchi  */
119d26e4fcSRobert Mustacchi 
129d26e4fcSRobert Mustacchi /*
139d26e4fcSRobert Mustacchi  * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved.
1409aee612SRyan Zezeski  * Copyright 2019 Joyent, Inc.
15*df36e06dSRobert Mustacchi  * Copyright 2021 Oxide Computer Company
169d26e4fcSRobert Mustacchi  */
179d26e4fcSRobert Mustacchi 
189d26e4fcSRobert Mustacchi #include "i40e_sw.h"
199d26e4fcSRobert Mustacchi 
209d26e4fcSRobert Mustacchi /*
219d26e4fcSRobert Mustacchi  * -------------------
229d26e4fcSRobert Mustacchi  * Statistics Overview
239d26e4fcSRobert Mustacchi  * -------------------
249d26e4fcSRobert Mustacchi  *
259d26e4fcSRobert Mustacchi  * As part of managing the driver and understanding what's going on, we keep
269d26e4fcSRobert Mustacchi  * track of statistics from two different sources:
279d26e4fcSRobert Mustacchi  *
289d26e4fcSRobert Mustacchi  *   - Statistics from the device
299d26e4fcSRobert Mustacchi  *   - Statistics maintained by the driver
309d26e4fcSRobert Mustacchi  *
319d26e4fcSRobert Mustacchi  * Generally, the hardware provides us traditional IETF and MIB Ethernet
329d26e4fcSRobert Mustacchi  * statistics, for example, the total packets in and out, various errors in
339d26e4fcSRobert Mustacchi  * packets, the negotiated status etc. The driver, on the other hand, primarily
349d26e4fcSRobert Mustacchi  * contains statistics around driver-specific issues, such as information about
359d26e4fcSRobert Mustacchi  * checksumming on receive and transmit and the data in and out of a specific
369d26e4fcSRobert Mustacchi  * ring.
379d26e4fcSRobert Mustacchi  *
389d26e4fcSRobert Mustacchi  * We export statistics in two different forms. The first form is the required
399d26e4fcSRobert Mustacchi  * GLDv3 endpoints, specifically:
409d26e4fcSRobert Mustacchi  *
419d26e4fcSRobert Mustacchi  *   - The general GLDv3 mc_getstat interface
429d26e4fcSRobert Mustacchi  *   - The GLDv3 ring mri_stat interface
439d26e4fcSRobert Mustacchi  *
449d26e4fcSRobert Mustacchi  * The second form that we export statistics is through kstats. kstats are
459d26e4fcSRobert Mustacchi  * exported in different ways. Particularly we arrange the kstats to monitor the
469d26e4fcSRobert Mustacchi  * layout of the device. Currently we have kstats which capture both the IEEE
479d26e4fcSRobert Mustacchi  * and driver-implementation specific stats. There are kstats for each of the
489d26e4fcSRobert Mustacchi  * following structures:
499d26e4fcSRobert Mustacchi  *
509d26e4fcSRobert Mustacchi  *   - Each physical function
519d26e4fcSRobert Mustacchi  *   - Each VSI
529d26e4fcSRobert Mustacchi  *   - Each Queue
539d26e4fcSRobert Mustacchi  *
549d26e4fcSRobert Mustacchi  * The PF's kstat is called 'pfstats' so as not to collide with other system
559d26e4fcSRobert Mustacchi  * provided kstats. Thus, for instance 0, usually the first PF, the full kstat
569d26e4fcSRobert Mustacchi  * would be: i40e:0:pfstats:.
579d26e4fcSRobert Mustacchi  *
589d26e4fcSRobert Mustacchi  * The kstat for each VSI is called vsi_%instance. So for the first PF, which is
599d26e4fcSRobert Mustacchi  * instance zero and the first vsi, which has id 0, it will be named vsi_0 and
609d26e4fcSRobert Mustacchi  * the full kstat would be i40e:0:vsi_0:.
619d26e4fcSRobert Mustacchi  *
629d26e4fcSRobert Mustacchi  * The kstat for each queue is trqpair_tx_%queue and trqpair_rx_%queue. Note
639d26e4fcSRobert Mustacchi  * that these are labeled based on their local index, which may mean that
649d26e4fcSRobert Mustacchi  * different instances have overlapping sets of queues. This isn't a problem as
659d26e4fcSRobert Mustacchi  * the kstats will always use the instance number of the pf to distinguish it in
669d26e4fcSRobert Mustacchi  * the kstat tuple.
679d26e4fcSRobert Mustacchi  *
689d26e4fcSRobert Mustacchi  * ---------------------
699d26e4fcSRobert Mustacchi  * Hardware Arrangements
709d26e4fcSRobert Mustacchi  * ---------------------
719d26e4fcSRobert Mustacchi  *
729d26e4fcSRobert Mustacchi  * The hardware keeps statistics at each physical function/MAC (PF) and it keeps
7309aee612SRyan Zezeski  * statistics on each virtual station interface (VSI).
749d26e4fcSRobert Mustacchi  *
759d26e4fcSRobert Mustacchi  * The hardware keeps these statistics as 32-bit and 48-bit counters. We are
769d26e4fcSRobert Mustacchi  * required to read them and then compute the differences between them. The
779d26e4fcSRobert Mustacchi  * 48-bit counters span more than one 32-bit register in the BAR. The hardware
789d26e4fcSRobert Mustacchi  * suggests that to read them, we perform 64-bit reads of the lower of the two
799d26e4fcSRobert Mustacchi  * registers that make up a 48-bit stat. The hardware guarantees that the reads
809d26e4fcSRobert Mustacchi  * of those two registers will be atomic and we'll get a consistent value, not a
819d26e4fcSRobert Mustacchi  * property it has for every read of two registers.
829d26e4fcSRobert Mustacchi  *
839d26e4fcSRobert Mustacchi  * For every kstat we have based on this, we have a corresponding uint64_t that
849d26e4fcSRobert Mustacchi  * we keep around as a base value in a separate structure. Whenever we read a
859d26e4fcSRobert Mustacchi  * value, we end up grabbing the current value, calculating a difference between
869d26e4fcSRobert Mustacchi  * the previously stored value and the current one, and updating the kstat with
879d26e4fcSRobert Mustacchi  * that difference. After which, we go through and update the base value that we
889d26e4fcSRobert Mustacchi  * stored. This is all encapsulated in i40e_stat_get_uint32() and
899d26e4fcSRobert Mustacchi  * i40e_stat_get_uint48().
909d26e4fcSRobert Mustacchi  *
919d26e4fcSRobert Mustacchi  * The only unfortunate thing here is that the hardware doesn't give us any kind
929d26e4fcSRobert Mustacchi  * of overflow counter. It just tries to make sure that the uint32_t and
939d26e4fcSRobert Mustacchi  * uint48_t counters are large enough to hopefully not overflow right away. This
949d26e4fcSRobert Mustacchi  * isn't the most reassuring statement and we should investigate ways of
959d26e4fcSRobert Mustacchi  * ensuring that if a system is active, but not actively measured, we don't lose
969d26e4fcSRobert Mustacchi  * data.
979d26e4fcSRobert Mustacchi  *
989d26e4fcSRobert Mustacchi  * The pf kstats data is stored in the i40e_t`i40e_pf_kstat. It is backed by the
9909aee612SRyan Zezeski  * i40e_t`i40e_pf_stat structure. Similarly the VSI related kstats are in
10009aee612SRyan Zezeski  * i40e_t`i40e_vsis[idx].iv_kstats and the data is backed in the
10109aee612SRyan Zezeski  * i40e_t`i40e_vsis[idx].iv_stats. All of this data is protected by the
10209aee612SRyan Zezeski  * i40e_stat_lock, which should be taken last, when acquiring locks.
1039d26e4fcSRobert Mustacchi  */
1049d26e4fcSRobert Mustacchi 
1059d26e4fcSRobert Mustacchi static void
i40e_stat_get_uint48(i40e_t * i40e,uintptr_t reg,kstat_named_t * kstat,uint64_t * base,boolean_t init)1069d26e4fcSRobert Mustacchi i40e_stat_get_uint48(i40e_t *i40e, uintptr_t reg, kstat_named_t *kstat,
1079d26e4fcSRobert Mustacchi     uint64_t *base, boolean_t init)
1089d26e4fcSRobert Mustacchi {
1099d26e4fcSRobert Mustacchi 	i40e_hw_t *hw = &i40e->i40e_hw_space;
1109d26e4fcSRobert Mustacchi 	uint64_t raw, delta;
1119d26e4fcSRobert Mustacchi 
1129d26e4fcSRobert Mustacchi 	ASSERT(MUTEX_HELD(&i40e->i40e_stat_lock));
1139d26e4fcSRobert Mustacchi 
1149d26e4fcSRobert Mustacchi 	raw = ddi_get64(i40e->i40e_osdep_space.ios_reg_handle,
1159d26e4fcSRobert Mustacchi 	    (uint64_t *)((uintptr_t)hw->hw_addr + reg));
1169d26e4fcSRobert Mustacchi 
1179d26e4fcSRobert Mustacchi 	if (init == B_TRUE) {
1189d26e4fcSRobert Mustacchi 		*base = raw;
1199d26e4fcSRobert Mustacchi 		return;
1209d26e4fcSRobert Mustacchi 	}
1219d26e4fcSRobert Mustacchi 
1229d26e4fcSRobert Mustacchi 	/*
1239d26e4fcSRobert Mustacchi 	 * Check for wraparound, note that the counter is actually only 48-bits,
1249d26e4fcSRobert Mustacchi 	 * even though it has two uint32_t regs present.
1259d26e4fcSRobert Mustacchi 	 */
1269d26e4fcSRobert Mustacchi 	if (raw >= *base) {
1279d26e4fcSRobert Mustacchi 		delta = raw - *base;
1289d26e4fcSRobert Mustacchi 	} else {
1299d26e4fcSRobert Mustacchi 		delta = 0x1000000000000ULL - *base + raw;
1309d26e4fcSRobert Mustacchi 	}
1319d26e4fcSRobert Mustacchi 
1329d26e4fcSRobert Mustacchi 	kstat->value.ui64 += delta;
1339d26e4fcSRobert Mustacchi 	*base = raw;
1349d26e4fcSRobert Mustacchi }
1359d26e4fcSRobert Mustacchi 
1369d26e4fcSRobert Mustacchi static void
i40e_stat_get_uint32(i40e_t * i40e,uintptr_t reg,kstat_named_t * kstat,uint64_t * base,boolean_t init)1379d26e4fcSRobert Mustacchi i40e_stat_get_uint32(i40e_t *i40e, uintptr_t reg, kstat_named_t *kstat,
1389d26e4fcSRobert Mustacchi     uint64_t *base, boolean_t init)
1399d26e4fcSRobert Mustacchi {
1409d26e4fcSRobert Mustacchi 	i40e_hw_t *hw = &i40e->i40e_hw_space;
1419d26e4fcSRobert Mustacchi 	uint64_t raw, delta;
1429d26e4fcSRobert Mustacchi 
1439d26e4fcSRobert Mustacchi 	ASSERT(MUTEX_HELD(&i40e->i40e_stat_lock));
1449d26e4fcSRobert Mustacchi 
1459d26e4fcSRobert Mustacchi 	raw = ddi_get32(i40e->i40e_osdep_space.ios_reg_handle,
1469d26e4fcSRobert Mustacchi 	    (uint32_t *)((uintptr_t)hw->hw_addr + reg));
1479d26e4fcSRobert Mustacchi 
1489d26e4fcSRobert Mustacchi 	if (init == B_TRUE) {
1499d26e4fcSRobert Mustacchi 		*base = raw;
1509d26e4fcSRobert Mustacchi 		return;
1519d26e4fcSRobert Mustacchi 	}
1529d26e4fcSRobert Mustacchi 
1539d26e4fcSRobert Mustacchi 	/*
1549d26e4fcSRobert Mustacchi 	 * Watch out for wraparound as we only have a 32-bit counter.
1559d26e4fcSRobert Mustacchi 	 */
1569d26e4fcSRobert Mustacchi 	if (raw >= *base) {
1579d26e4fcSRobert Mustacchi 		delta = raw - *base;
1589d26e4fcSRobert Mustacchi 	} else {
1599d26e4fcSRobert Mustacchi 		delta = 0x100000000ULL - *base + raw;
1609d26e4fcSRobert Mustacchi 	}
1619d26e4fcSRobert Mustacchi 
1629d26e4fcSRobert Mustacchi 	kstat->value.ui64 += delta;
1639d26e4fcSRobert Mustacchi 	*base = raw;
1649d26e4fcSRobert Mustacchi 
1659d26e4fcSRobert Mustacchi }
1669d26e4fcSRobert Mustacchi 
1679d26e4fcSRobert Mustacchi static void
i40e_stat_vsi_update(i40e_t * i40e,uint_t idx,boolean_t init)16809aee612SRyan Zezeski i40e_stat_vsi_update(i40e_t *i40e, uint_t idx, boolean_t init)
1699d26e4fcSRobert Mustacchi {
1709d26e4fcSRobert Mustacchi 	i40e_vsi_stats_t *ivs;
1719d26e4fcSRobert Mustacchi 	i40e_vsi_kstats_t *ivk;
17209aee612SRyan Zezeski 	uint16_t id = i40e->i40e_vsis[idx].iv_stats_id;
1739d26e4fcSRobert Mustacchi 
17409aee612SRyan Zezeski 	ASSERT3P(i40e->i40e_vsis[idx].iv_kstats, !=, NULL);
17509aee612SRyan Zezeski 	ivs = &i40e->i40e_vsis[idx].iv_stats;
17609aee612SRyan Zezeski 	ivk = i40e->i40e_vsis[idx].iv_kstats->ks_data;
1779d26e4fcSRobert Mustacchi 
1789d26e4fcSRobert Mustacchi 	mutex_enter(&i40e->i40e_stat_lock);
1799d26e4fcSRobert Mustacchi 
1809d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLV_GORCL(id), &ivk->ivk_rx_bytes,
1819d26e4fcSRobert Mustacchi 	    &ivs->ivs_rx_bytes, init);
1829d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLV_UPRCL(id), &ivk->ivk_rx_unicast,
1839d26e4fcSRobert Mustacchi 	    &ivs->ivs_rx_unicast, init);
1849d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLV_MPRCL(id), &ivk->ivk_rx_multicast,
1859d26e4fcSRobert Mustacchi 	    &ivs->ivs_rx_multicast, init);
1869d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLV_BPRCL(id), &ivk->ivk_rx_broadcast,
1879d26e4fcSRobert Mustacchi 	    &ivs->ivs_rx_broadcast, init);
1889d26e4fcSRobert Mustacchi 
1899d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLV_RDPC(id), &ivk->ivk_rx_discards,
1909d26e4fcSRobert Mustacchi 	    &ivs->ivs_rx_discards, init);
1919d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLV_RUPP(id),
1929d26e4fcSRobert Mustacchi 	    &ivk->ivk_rx_unknown_protocol,
1939d26e4fcSRobert Mustacchi 	    &ivs->ivs_rx_unknown_protocol,
1949d26e4fcSRobert Mustacchi 	    init);
1959d26e4fcSRobert Mustacchi 
1969d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLV_GOTCL(id), &ivk->ivk_tx_bytes,
1979d26e4fcSRobert Mustacchi 	    &ivs->ivs_tx_bytes, init);
1989d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLV_UPTCL(id), &ivk->ivk_tx_unicast,
1999d26e4fcSRobert Mustacchi 	    &ivs->ivs_tx_unicast, init);
2009d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLV_MPTCL(id), &ivk->ivk_tx_multicast,
2019d26e4fcSRobert Mustacchi 	    &ivs->ivs_tx_multicast, init);
2029d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLV_BPTCL(id), &ivk->ivk_tx_broadcast,
2039d26e4fcSRobert Mustacchi 	    &ivs->ivs_tx_broadcast, init);
2049d26e4fcSRobert Mustacchi 
2059d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLV_TEPC(id), &ivk->ivk_tx_errors,
2069d26e4fcSRobert Mustacchi 	    &ivs->ivs_tx_errors, init);
2079d26e4fcSRobert Mustacchi 
2089d26e4fcSRobert Mustacchi 	mutex_exit(&i40e->i40e_stat_lock);
2099d26e4fcSRobert Mustacchi 
2109d26e4fcSRobert Mustacchi 	/*
2119d26e4fcSRobert Mustacchi 	 * We follow ixgbe's lead here and that if a kstat update didn't work
2129d26e4fcSRobert Mustacchi 	 * 100% then we mark service unaffected as opposed to when fetching
2139d26e4fcSRobert Mustacchi 	 * things for MAC directly.
2149d26e4fcSRobert Mustacchi 	 */
2159d26e4fcSRobert Mustacchi 	if (i40e_check_acc_handle(i40e->i40e_osdep_space.ios_reg_handle) !=
2169d26e4fcSRobert Mustacchi 	    DDI_FM_OK) {
2179d26e4fcSRobert Mustacchi 		ddi_fm_service_impact(i40e->i40e_dip, DDI_SERVICE_UNAFFECTED);
2189d26e4fcSRobert Mustacchi 	}
2199d26e4fcSRobert Mustacchi }
2209d26e4fcSRobert Mustacchi 
2219d26e4fcSRobert Mustacchi static int
i40e_stat_vsi_kstat_update(kstat_t * ksp,int rw)2229d26e4fcSRobert Mustacchi i40e_stat_vsi_kstat_update(kstat_t *ksp, int rw)
2239d26e4fcSRobert Mustacchi {
2249d26e4fcSRobert Mustacchi 	i40e_t *i40e;
2259d26e4fcSRobert Mustacchi 
2269d26e4fcSRobert Mustacchi 	if (rw == KSTAT_WRITE)
2279d26e4fcSRobert Mustacchi 		return (EACCES);
2289d26e4fcSRobert Mustacchi 
2299d26e4fcSRobert Mustacchi 	i40e = ksp->ks_private;
23009aee612SRyan Zezeski 	for (uint_t i = 0; i < i40e->i40e_num_rx_groups; i++)
23109aee612SRyan Zezeski 		i40e_stat_vsi_update(i40e, i, B_FALSE);
23209aee612SRyan Zezeski 
2339d26e4fcSRobert Mustacchi 	return (0);
2349d26e4fcSRobert Mustacchi }
2359d26e4fcSRobert Mustacchi 
2369d26e4fcSRobert Mustacchi void
i40e_stat_vsi_fini(i40e_t * i40e,uint_t idx)23709aee612SRyan Zezeski i40e_stat_vsi_fini(i40e_t *i40e, uint_t idx)
2389d26e4fcSRobert Mustacchi {
23909aee612SRyan Zezeski 	if (i40e->i40e_vsis[idx].iv_kstats != NULL) {
24009aee612SRyan Zezeski 		kstat_delete(i40e->i40e_vsis[idx].iv_kstats);
24109aee612SRyan Zezeski 		i40e->i40e_vsis[idx].iv_kstats = NULL;
2429d26e4fcSRobert Mustacchi 	}
2439d26e4fcSRobert Mustacchi }
2449d26e4fcSRobert Mustacchi 
2459d26e4fcSRobert Mustacchi boolean_t
i40e_stat_vsi_init(i40e_t * i40e,uint_t idx)24609aee612SRyan Zezeski i40e_stat_vsi_init(i40e_t *i40e, uint_t idx)
2479d26e4fcSRobert Mustacchi {
2489d26e4fcSRobert Mustacchi 	kstat_t *ksp;
2499d26e4fcSRobert Mustacchi 	i40e_vsi_kstats_t *ivk;
2509d26e4fcSRobert Mustacchi 	char buf[64];
25109aee612SRyan Zezeski 	uint16_t vsi_id = i40e->i40e_vsis[idx].iv_seid;
2529d26e4fcSRobert Mustacchi 
25309aee612SRyan Zezeski 	(void) snprintf(buf, sizeof (buf), "vsi_%u", vsi_id);
2549d26e4fcSRobert Mustacchi 
2559d26e4fcSRobert Mustacchi 	ksp = kstat_create(I40E_MODULE_NAME, ddi_get_instance(i40e->i40e_dip),
2569d26e4fcSRobert Mustacchi 	    buf, "net", KSTAT_TYPE_NAMED,
2579d26e4fcSRobert Mustacchi 	    sizeof (i40e_vsi_kstats_t) / sizeof (kstat_named_t), 0);
2589d26e4fcSRobert Mustacchi 
2599d26e4fcSRobert Mustacchi 	if (ksp == NULL) {
26009aee612SRyan Zezeski 		i40e_error(i40e, "Failed to create kstats for VSI %u", vsi_id);
2619d26e4fcSRobert Mustacchi 		return (B_FALSE);
2629d26e4fcSRobert Mustacchi 	}
2639d26e4fcSRobert Mustacchi 
26409aee612SRyan Zezeski 	i40e->i40e_vsis[idx].iv_kstats = ksp;
2659d26e4fcSRobert Mustacchi 	ivk = ksp->ks_data;
2669d26e4fcSRobert Mustacchi 	ksp->ks_update = i40e_stat_vsi_kstat_update;
2679d26e4fcSRobert Mustacchi 	ksp->ks_private = i40e;
2689d26e4fcSRobert Mustacchi 
2699d26e4fcSRobert Mustacchi 	kstat_named_init(&ivk->ivk_rx_bytes, "rx_bytes",
2709d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
2719d26e4fcSRobert Mustacchi 	kstat_named_init(&ivk->ivk_rx_unicast, "rx_unicast",
2729d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
2739d26e4fcSRobert Mustacchi 	kstat_named_init(&ivk->ivk_rx_multicast, "rx_multicast",
2749d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
2759d26e4fcSRobert Mustacchi 	kstat_named_init(&ivk->ivk_rx_broadcast, "rx_broadcast",
2769d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
2779d26e4fcSRobert Mustacchi 	kstat_named_init(&ivk->ivk_rx_discards, "rx_discards",
2789d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
2799d26e4fcSRobert Mustacchi 	kstat_named_init(&ivk->ivk_rx_unknown_protocol, "rx_unknown_protocol",
2809d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
2819d26e4fcSRobert Mustacchi 	kstat_named_init(&ivk->ivk_tx_bytes, "tx_bytes",
2829d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
2839d26e4fcSRobert Mustacchi 	kstat_named_init(&ivk->ivk_tx_unicast, "tx_unicast",
2849d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
2859d26e4fcSRobert Mustacchi 	kstat_named_init(&ivk->ivk_tx_multicast, "tx_multicast",
2869d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
2879d26e4fcSRobert Mustacchi 	kstat_named_init(&ivk->ivk_tx_broadcast, "tx_broadcast",
2889d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
2899d26e4fcSRobert Mustacchi 	kstat_named_init(&ivk->ivk_tx_errors, "tx_errors",
2909d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
2919d26e4fcSRobert Mustacchi 
29209aee612SRyan Zezeski 	bzero(&i40e->i40e_vsis[idx].iv_stats, sizeof (i40e_vsi_stats_t));
29309aee612SRyan Zezeski 	i40e_stat_vsi_update(i40e, idx, B_TRUE);
29409aee612SRyan Zezeski 	kstat_install(i40e->i40e_vsis[idx].iv_kstats);
2959d26e4fcSRobert Mustacchi 
2969d26e4fcSRobert Mustacchi 	return (B_TRUE);
2979d26e4fcSRobert Mustacchi }
2989d26e4fcSRobert Mustacchi 
2999d26e4fcSRobert Mustacchi static void
i40e_stat_pf_update(i40e_t * i40e,boolean_t init)3009d26e4fcSRobert Mustacchi i40e_stat_pf_update(i40e_t *i40e, boolean_t init)
3019d26e4fcSRobert Mustacchi {
3029d26e4fcSRobert Mustacchi 	i40e_pf_stats_t *ips;
3039d26e4fcSRobert Mustacchi 	i40e_pf_kstats_t *ipk;
3049d26e4fcSRobert Mustacchi 	int port = i40e->i40e_hw_space.port;
3059d26e4fcSRobert Mustacchi 	int i;
3069d26e4fcSRobert Mustacchi 
3079d26e4fcSRobert Mustacchi 	ASSERT(i40e->i40e_pf_kstat != NULL);
3089d26e4fcSRobert Mustacchi 	ips = &i40e->i40e_pf_stat;
3099d26e4fcSRobert Mustacchi 	ipk = i40e->i40e_pf_kstat->ks_data;
3109d26e4fcSRobert Mustacchi 
3119d26e4fcSRobert Mustacchi 	mutex_enter(&i40e->i40e_stat_lock);
3129d26e4fcSRobert Mustacchi 
3139d26e4fcSRobert Mustacchi 	/* 64-bit PCIe regs */
3149d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_GORCL(port),
3159d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_bytes, &ips->ips_rx_bytes, init);
3169d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_UPRCL(port),
3179d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_unicast, &ips->ips_rx_unicast, init);
3189d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_MPRCL(port),
3199d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_multicast, &ips->ips_rx_multicast, init);
3209d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_BPRCL(port),
3219d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_broadcast, &ips->ips_rx_broadcast, init);
3229d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_GOTCL(port),
3239d26e4fcSRobert Mustacchi 	    &ipk->ipk_tx_bytes, &ips->ips_tx_bytes, init);
3249d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_UPTCL(port),
3259d26e4fcSRobert Mustacchi 	    &ipk->ipk_tx_unicast, &ips->ips_tx_unicast, init);
3269d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_MPTCL(port),
3279d26e4fcSRobert Mustacchi 	    &ipk->ipk_tx_multicast, &ips->ips_tx_multicast, init);
3289d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_BPTCL(port),
3299d26e4fcSRobert Mustacchi 	    &ipk->ipk_tx_broadcast, &ips->ips_tx_broadcast, init);
3309d26e4fcSRobert Mustacchi 
3319d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_PRC64L(port),
3329d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_size_64, &ips->ips_rx_size_64, init);
3339d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_PRC127L(port),
3349d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_size_127, &ips->ips_rx_size_127, init);
3359d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_PRC255L(port),
3369d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_size_255, &ips->ips_rx_size_255, init);
3379d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_PRC511L(port),
3389d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_size_511, &ips->ips_rx_size_511, init);
3399d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_PRC1023L(port),
3409d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_size_1023, &ips->ips_rx_size_1023, init);
3419d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_PRC1522L(port),
3429d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_size_1522, &ips->ips_rx_size_1522, init);
3439d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_PRC9522L(port),
3449d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_size_9522, &ips->ips_rx_size_9522, init);
3459d26e4fcSRobert Mustacchi 
3469d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_PTC64L(port),
3479d26e4fcSRobert Mustacchi 	    &ipk->ipk_tx_size_64, &ips->ips_tx_size_64, init);
3489d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_PTC127L(port),
3499d26e4fcSRobert Mustacchi 	    &ipk->ipk_tx_size_127, &ips->ips_tx_size_127, init);
3509d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_PTC255L(port),
3519d26e4fcSRobert Mustacchi 	    &ipk->ipk_tx_size_255, &ips->ips_tx_size_255, init);
3529d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_PTC511L(port),
3539d26e4fcSRobert Mustacchi 	    &ipk->ipk_tx_size_511, &ips->ips_tx_size_511, init);
3549d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_PTC1023L(port),
3559d26e4fcSRobert Mustacchi 	    &ipk->ipk_tx_size_1023, &ips->ips_tx_size_1023, init);
3569d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_PTC1522L(port),
3579d26e4fcSRobert Mustacchi 	    &ipk->ipk_tx_size_1522, &ips->ips_tx_size_1522, init);
3589d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GLPRT_PTC9522L(port),
3599d26e4fcSRobert Mustacchi 	    &ipk->ipk_tx_size_9522, &ips->ips_tx_size_9522, init);
3609d26e4fcSRobert Mustacchi 
3619d26e4fcSRobert Mustacchi 	/* 32-bit PCIe regs */
3629d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_LXONRXC(port),
3639d26e4fcSRobert Mustacchi 	    &ipk->ipk_link_xon_rx, &ips->ips_link_xon_rx, init);
3649d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_LXOFFRXC(port),
3659d26e4fcSRobert Mustacchi 	    &ipk->ipk_link_xoff_rx, &ips->ips_link_xoff_rx, init);
3669d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_LXONTXC(port),
3679d26e4fcSRobert Mustacchi 	    &ipk->ipk_link_xon_tx, &ips->ips_link_xon_tx, init);
3689d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_LXOFFTXC(port),
3699d26e4fcSRobert Mustacchi 	    &ipk->ipk_link_xoff_tx, &ips->ips_link_xoff_tx, init);
3709d26e4fcSRobert Mustacchi 
3719d26e4fcSRobert Mustacchi 	for (i = 0; i < 8; i++) {
3729d26e4fcSRobert Mustacchi 		i40e_stat_get_uint32(i40e, I40E_GLPRT_PXONRXC(port, i),
3739d26e4fcSRobert Mustacchi 		    &ipk->ipk_priority_xon_rx[i], &ips->ips_priority_xon_rx[i],
3749d26e4fcSRobert Mustacchi 		    init);
3759d26e4fcSRobert Mustacchi 		i40e_stat_get_uint32(i40e, I40E_GLPRT_PXOFFRXC(port, i),
3769d26e4fcSRobert Mustacchi 		    &ipk->ipk_priority_xoff_rx[i],
3779d26e4fcSRobert Mustacchi 		    &ips->ips_priority_xoff_rx[i],
3789d26e4fcSRobert Mustacchi 		    init);
3799d26e4fcSRobert Mustacchi 		i40e_stat_get_uint32(i40e, I40E_GLPRT_PXONTXC(port, i),
3809d26e4fcSRobert Mustacchi 		    &ipk->ipk_priority_xon_tx[i], &ips->ips_priority_xon_tx[i],
3819d26e4fcSRobert Mustacchi 		    init);
3829d26e4fcSRobert Mustacchi 		i40e_stat_get_uint32(i40e, I40E_GLPRT_PXOFFTXC(port, i),
3839d26e4fcSRobert Mustacchi 		    &ipk->ipk_priority_xoff_tx[i],
3849d26e4fcSRobert Mustacchi 		    &ips->ips_priority_xoff_tx[i],
3859d26e4fcSRobert Mustacchi 		    init);
3869d26e4fcSRobert Mustacchi 		i40e_stat_get_uint32(i40e, I40E_GLPRT_RXON2OFFCNT(port, i),
3879d26e4fcSRobert Mustacchi 		    &ipk->ipk_priority_xon_2_xoff[i],
3889d26e4fcSRobert Mustacchi 		    &ips->ips_priority_xon_2_xoff[i],
3899d26e4fcSRobert Mustacchi 		    init);
3909d26e4fcSRobert Mustacchi 	}
3919d26e4fcSRobert Mustacchi 
3929d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_CRCERRS(port),
3939d26e4fcSRobert Mustacchi 	    &ipk->ipk_crc_errors, &ips->ips_crc_errors, init);
3949d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_ILLERRC(port),
3959d26e4fcSRobert Mustacchi 	    &ipk->ipk_illegal_bytes, &ips->ips_illegal_bytes, init);
3969d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_MLFC(port),
3979d26e4fcSRobert Mustacchi 	    &ipk->ipk_mac_local_faults, &ips->ips_mac_local_faults, init);
3989d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_MRFC(port),
3999d26e4fcSRobert Mustacchi 	    &ipk->ipk_mac_remote_faults, &ips->ips_mac_remote_faults, init);
4009d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_RLEC(port),
4019d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_length_errors, &ips->ips_rx_length_errors, init);
4029d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_RUC(port),
4039d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_undersize, &ips->ips_rx_undersize, init);
4049d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_RFC(port),
4059d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_fragments, &ips->ips_rx_fragments, init);
4069d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_ROC(port),
4079d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_oversize, &ips->ips_rx_oversize, init);
4089d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_RJC(port),
4099d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_jabber, &ips->ips_rx_jabber, init);
4109d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_RDPC(port),
4119d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_discards, &ips->ips_rx_discards, init);
4129d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_LDPC(port),
4139d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_vm_discards, &ips->ips_rx_vm_discards, init);
4149d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_MSPDC(port),
4159d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_short_discards, &ips->ips_rx_short_discards, init);
4169d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_TDOLD(port),
4179d26e4fcSRobert Mustacchi 	    &ipk->ipk_tx_dropped_link_down, &ips->ips_tx_dropped_link_down,
4189d26e4fcSRobert Mustacchi 	    init);
4199d26e4fcSRobert Mustacchi 	i40e_stat_get_uint32(i40e, I40E_GLPRT_RUPP(port),
4209d26e4fcSRobert Mustacchi 	    &ipk->ipk_rx_unknown_protocol, &ips->ips_rx_unknown_protocol, init);
4219d26e4fcSRobert Mustacchi 
4229d26e4fcSRobert Mustacchi 	/* 64-bit */
4239d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GL_RXERR1_L(port), &ipk->ipk_rx_err1,
4249d26e4fcSRobert Mustacchi 	    &ips->ips_rx_err1, init);
4259d26e4fcSRobert Mustacchi 	i40e_stat_get_uint48(i40e, I40E_GL_RXERR2_L(port), &ipk->ipk_rx_err2,
4269d26e4fcSRobert Mustacchi 	    &ips->ips_rx_err2, init);
4279d26e4fcSRobert Mustacchi 
4289d26e4fcSRobert Mustacchi 	mutex_exit(&i40e->i40e_stat_lock);
4299d26e4fcSRobert Mustacchi 
4309d26e4fcSRobert Mustacchi 	/*
4319d26e4fcSRobert Mustacchi 	 * We follow ixgbe's lead here and that if a kstat update didn't work
4329d26e4fcSRobert Mustacchi 	 * 100% then we mark service unaffected as opposed to when fetching
4339d26e4fcSRobert Mustacchi 	 * things for MAC directly.
4349d26e4fcSRobert Mustacchi 	 */
4359d26e4fcSRobert Mustacchi 	if (i40e_check_acc_handle(i40e->i40e_osdep_space.ios_reg_handle) !=
4369d26e4fcSRobert Mustacchi 	    DDI_FM_OK) {
4379d26e4fcSRobert Mustacchi 		ddi_fm_service_impact(i40e->i40e_dip, DDI_SERVICE_UNAFFECTED);
4389d26e4fcSRobert Mustacchi 	}
4399d26e4fcSRobert Mustacchi }
4409d26e4fcSRobert Mustacchi 
4419d26e4fcSRobert Mustacchi static int
i40e_stat_pf_kstat_update(kstat_t * ksp,int rw)4429d26e4fcSRobert Mustacchi i40e_stat_pf_kstat_update(kstat_t *ksp, int rw)
4439d26e4fcSRobert Mustacchi {
4449d26e4fcSRobert Mustacchi 	i40e_t *i40e;
4459d26e4fcSRobert Mustacchi 
4469d26e4fcSRobert Mustacchi 	if (rw == KSTAT_WRITE)
4479d26e4fcSRobert Mustacchi 		return (EACCES);
4489d26e4fcSRobert Mustacchi 
4499d26e4fcSRobert Mustacchi 	i40e = ksp->ks_private;
4509d26e4fcSRobert Mustacchi 	i40e_stat_pf_update(i40e, B_FALSE);
4519d26e4fcSRobert Mustacchi 	return (0);
4529d26e4fcSRobert Mustacchi }
4539d26e4fcSRobert Mustacchi 
4549d26e4fcSRobert Mustacchi 
4559d26e4fcSRobert Mustacchi static boolean_t
i40e_stat_pf_init(i40e_t * i40e)4569d26e4fcSRobert Mustacchi i40e_stat_pf_init(i40e_t *i40e)
4579d26e4fcSRobert Mustacchi {
4589d26e4fcSRobert Mustacchi 	kstat_t *ksp;
4599d26e4fcSRobert Mustacchi 	i40e_pf_kstats_t *ipk;
4609d26e4fcSRobert Mustacchi 
4619d26e4fcSRobert Mustacchi 	ksp = kstat_create(I40E_MODULE_NAME, ddi_get_instance(i40e->i40e_dip),
4629d26e4fcSRobert Mustacchi 	    "pfstats", "net", KSTAT_TYPE_NAMED,
4639d26e4fcSRobert Mustacchi 	    sizeof (i40e_pf_kstats_t) / sizeof (kstat_named_t), 0);
4649d26e4fcSRobert Mustacchi 	if (ksp == NULL) {
4659d26e4fcSRobert Mustacchi 		i40e_error(i40e, "Could not create kernel statistics.");
4669d26e4fcSRobert Mustacchi 		return (B_FALSE);
4679d26e4fcSRobert Mustacchi 	}
4689d26e4fcSRobert Mustacchi 
4699d26e4fcSRobert Mustacchi 	i40e->i40e_pf_kstat = ksp;
4709d26e4fcSRobert Mustacchi 	ipk = ksp->ks_data;
4719d26e4fcSRobert Mustacchi 	ksp->ks_update = i40e_stat_pf_kstat_update;
4729d26e4fcSRobert Mustacchi 	ksp->ks_private = i40e;
4739d26e4fcSRobert Mustacchi 
4749d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_bytes, "rx_bytes",
4759d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
4769d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_unicast, "rx_unicast",
4779d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
4789d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_multicast, "rx_multicast",
4799d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
4809d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_broadcast, "rx_broadcast",
4819d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
4829d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_tx_bytes, "tx_bytes",
4839d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
4849d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_tx_unicast, "tx_unicast",
4859d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
4869d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_tx_multicast, "tx_multicast",
4879d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
4889d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_tx_broadcast, "tx_broadcast",
4899d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
4909d26e4fcSRobert Mustacchi 
4919d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_size_64, "rx_size_64",
4929d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
4939d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_size_127, "rx_size_127",
4949d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
4959d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_size_255, "rx_size_255",
4969d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
4979d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_size_511, "rx_size_511",
4989d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
4999d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_size_1023, "rx_size_1023",
5009d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5019d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_size_1522, "rx_size_1522",
5029d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5039d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_size_9522, "rx_size_9522",
5049d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5059d26e4fcSRobert Mustacchi 
5069d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_tx_size_64, "tx_size_64",
5079d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5089d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_tx_size_127, "tx_size_127",
5099d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5109d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_tx_size_255, "tx_size_255",
5119d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5129d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_tx_size_511, "tx_size_511",
5139d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5149d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_tx_size_1023, "tx_size_1023",
5159d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5169d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_tx_size_1522, "tx_size_1522",
5179d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5189d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_tx_size_9522, "tx_size_9522",
5199d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5209d26e4fcSRobert Mustacchi 
5219d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_link_xon_rx, "link_xon_rx",
5229d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5239d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_link_xoff_rx, "link_xoff_rx",
5249d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5259d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_link_xon_tx, "link_xon_tx",
5269d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5279d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_link_xoff_tx, "link_xoff_tx",
5289d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5299d26e4fcSRobert Mustacchi 
5309d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_rx[0], "priority_xon_rx[0]",
5319d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5329d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xoff_rx[0], "priority_xoff_rx[0]",
5339d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5349d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_tx[0], "priority_xon_tx[0]",
5359d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5369d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xoff_tx[0], "priority_xoff_tx[0]",
5379d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5389d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_2_xoff[0],
5399d26e4fcSRobert Mustacchi 	    "priority_xon_2_xoff[0]",
5409d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5419d26e4fcSRobert Mustacchi 
5429d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_rx[1], "priority_xon_rx[1]",
5439d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5449d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xoff_rx[1], "priority_xoff_rx[1]",
5459d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5469d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_tx[1], "priority_xon_tx[1]",
5479d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5489d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xoff_tx[1], "priority_xoff_tx[1]",
5499d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5509d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_2_xoff[1],
5519d26e4fcSRobert Mustacchi 	    "priority_xon_2_xoff[1]",
5529d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5539d26e4fcSRobert Mustacchi 
5549d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_rx[2], "priority_xon_rx[2]",
5559d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5569d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xoff_rx[2], "priority_xoff_rx[2]",
5579d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5589d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_tx[2], "priority_xon_tx[2]",
5599d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5609d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xoff_tx[2], "priority_xoff_tx[2]",
5619d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5629d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_2_xoff[2],
5639d26e4fcSRobert Mustacchi 	    "priority_xon_2_xoff[2]",
5649d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5659d26e4fcSRobert Mustacchi 
5669d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_rx[3], "priority_xon_rx[3]",
5679d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5689d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xoff_rx[3], "priority_xoff_rx[3]",
5699d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5709d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_tx[3], "priority_xon_tx[3]",
5719d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5729d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xoff_tx[3], "priority_xoff_tx[3]",
5739d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5749d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_2_xoff[3],
5759d26e4fcSRobert Mustacchi 	    "priority_xon_2_xoff[3]",
5769d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5779d26e4fcSRobert Mustacchi 
5789d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_rx[4], "priority_xon_rx[4]",
5799d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5809d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xoff_rx[4], "priority_xoff_rx[4]",
5819d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5829d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_tx[4], "priority_xon_tx[4]",
5839d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5849d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xoff_tx[4], "priority_xoff_tx[4]",
5859d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5869d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_2_xoff[4],
5879d26e4fcSRobert Mustacchi 	    "priority_xon_2_xoff[4]",
5889d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5899d26e4fcSRobert Mustacchi 
5909d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_rx[5], "priority_xon_rx[5]",
5919d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5929d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xoff_rx[5], "priority_xoff_rx[5]",
5939d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5949d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_tx[5], "priority_xon_tx[5]",
5959d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5969d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xoff_tx[5], "priority_xoff_tx[5]",
5979d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
5989d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_2_xoff[5],
5999d26e4fcSRobert Mustacchi 	    "priority_xon_2_xoff[5]",
6009d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6019d26e4fcSRobert Mustacchi 
6029d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_rx[6], "priority_xon_rx[6]",
6039d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6049d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xoff_rx[6], "priority_xoff_rx[6]",
6059d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6069d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_tx[6], "priority_xon_tx[6]",
6079d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6089d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xoff_tx[6], "priority_xoff_tx[6]",
6099d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6109d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_2_xoff[6],
6119d26e4fcSRobert Mustacchi 	    "priority_xon_2_xoff[6]",
6129d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6139d26e4fcSRobert Mustacchi 
6149d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_rx[7], "priority_xon_rx[7]",
6159d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6169d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xoff_rx[7], "priority_xoff_rx[7]",
6179d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6189d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_tx[7], "priority_xon_tx[7]",
6199d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6209d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xoff_tx[7], "priority_xoff_tx[7]",
6219d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6229d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_priority_xon_2_xoff[7],
6239d26e4fcSRobert Mustacchi 	    "priority_xon_2_xoff[7]",
6249d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6259d26e4fcSRobert Mustacchi 
6269d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_crc_errors, "crc_errors",
6279d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6289d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_illegal_bytes, "illegal_bytes",
6299d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6309d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_mac_local_faults, "mac_local_faults",
6319d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6329d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_mac_remote_faults, "mac_remote_faults",
6339d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6349d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_length_errors, "rx_length_errors",
6359d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6369d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_undersize, "rx_undersize",
6379d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6389d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_fragments, "rx_fragments",
6399d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6409d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_oversize, "rx_oversize",
6419d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6429d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_jabber, "rx_jabber",
6439d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6449d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_discards, "rx_discards",
6459d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6469d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_vm_discards, "rx_vm_discards",
6479d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6489d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_short_discards, "rx_short_discards",
6499d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6509d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_tx_dropped_link_down, "tx_dropped_link_down",
6519d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6529d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_unknown_protocol, "rx_unknown_protocol",
6539d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6549d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_err1, "rx_err1",
6559d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6569d26e4fcSRobert Mustacchi 	kstat_named_init(&ipk->ipk_rx_err2, "rx_err2",
6579d26e4fcSRobert Mustacchi 	    KSTAT_DATA_UINT64);
6589d26e4fcSRobert Mustacchi 
6599d26e4fcSRobert Mustacchi 
6609d26e4fcSRobert Mustacchi 	bzero(&i40e->i40e_pf_stat, sizeof (i40e_pf_stats_t));
6619d26e4fcSRobert Mustacchi 	i40e_stat_pf_update(i40e, B_TRUE);
6629d26e4fcSRobert Mustacchi 
6639d26e4fcSRobert Mustacchi 	kstat_install(i40e->i40e_pf_kstat);
6649d26e4fcSRobert Mustacchi 
6659d26e4fcSRobert Mustacchi 	return (B_TRUE);
6669d26e4fcSRobert Mustacchi }
6679d26e4fcSRobert Mustacchi 
6689d26e4fcSRobert Mustacchi void
i40e_stats_fini(i40e_t * i40e)6699d26e4fcSRobert Mustacchi i40e_stats_fini(i40e_t *i40e)
6709d26e4fcSRobert Mustacchi {
67109aee612SRyan Zezeski #ifdef DEBUG
67209aee612SRyan Zezeski 	for (uint_t i = 0; i < i40e->i40e_num_rx_groups; i++) {
67309aee612SRyan Zezeski 		ASSERT3P(i40e->i40e_vsis[i].iv_kstats, ==, NULL);
67409aee612SRyan Zezeski 	}
67509aee612SRyan Zezeski #endif
67609aee612SRyan Zezeski 
6779d26e4fcSRobert Mustacchi 	if (i40e->i40e_pf_kstat != NULL) {
6789d26e4fcSRobert Mustacchi 		kstat_delete(i40e->i40e_pf_kstat);
6799d26e4fcSRobert Mustacchi 		i40e->i40e_pf_kstat = NULL;
6809d26e4fcSRobert Mustacchi 	}
6819d26e4fcSRobert Mustacchi 
6829d26e4fcSRobert Mustacchi 	mutex_destroy(&i40e->i40e_stat_lock);
6839d26e4fcSRobert Mustacchi }
6849d26e4fcSRobert Mustacchi 
6859d26e4fcSRobert Mustacchi boolean_t
i40e_stats_init(i40e_t * i40e)6869d26e4fcSRobert Mustacchi i40e_stats_init(i40e_t *i40e)
6879d26e4fcSRobert Mustacchi {
6889d26e4fcSRobert Mustacchi 	mutex_init(&i40e->i40e_stat_lock, NULL, MUTEX_DRIVER, NULL);
6899d26e4fcSRobert Mustacchi 	if (i40e_stat_pf_init(i40e) == B_FALSE) {
6909d26e4fcSRobert Mustacchi 		mutex_destroy(&i40e->i40e_stat_lock);
6919d26e4fcSRobert Mustacchi 		return (B_FALSE);
6929d26e4fcSRobert Mustacchi 	}
6939d26e4fcSRobert Mustacchi 
6949d26e4fcSRobert Mustacchi 	return (B_TRUE);
6959d26e4fcSRobert Mustacchi }
6969d26e4fcSRobert Mustacchi 
6979d26e4fcSRobert Mustacchi /*
6989d26e4fcSRobert Mustacchi  * For Nemo/GLDv3.
6999d26e4fcSRobert Mustacchi  */
7009d26e4fcSRobert Mustacchi int
i40e_m_stat(void * arg,uint_t stat,uint64_t * val)7019d26e4fcSRobert Mustacchi i40e_m_stat(void *arg, uint_t stat, uint64_t *val)
7029d26e4fcSRobert Mustacchi {
7039d26e4fcSRobert Mustacchi 	i40e_t *i40e = (i40e_t *)arg;
7049d26e4fcSRobert Mustacchi 	i40e_hw_t *hw = &i40e->i40e_hw_space;
7059d26e4fcSRobert Mustacchi 	int port = i40e->i40e_hw_space.port;
7069d26e4fcSRobert Mustacchi 	i40e_pf_stats_t *ips;
7079d26e4fcSRobert Mustacchi 	i40e_pf_kstats_t *ipk;
7089d26e4fcSRobert Mustacchi 
7099d26e4fcSRobert Mustacchi 
7109d26e4fcSRobert Mustacchi 	ASSERT(i40e->i40e_pf_kstat != NULL);
7119d26e4fcSRobert Mustacchi 	ips = &i40e->i40e_pf_stat;
7129d26e4fcSRobert Mustacchi 	ipk = i40e->i40e_pf_kstat->ks_data;
7139d26e4fcSRobert Mustacchi 
7149d26e4fcSRobert Mustacchi 	/*
7159d26e4fcSRobert Mustacchi 	 * We need both locks, as various stats are protected by different
7169d26e4fcSRobert Mustacchi 	 * things here.
7179d26e4fcSRobert Mustacchi 	 */
7189d26e4fcSRobert Mustacchi 	mutex_enter(&i40e->i40e_general_lock);
7199d26e4fcSRobert Mustacchi 
7209d26e4fcSRobert Mustacchi 	if (i40e->i40e_state & I40E_SUSPENDED) {
7219d26e4fcSRobert Mustacchi 		mutex_exit(&i40e->i40e_general_lock);
7229d26e4fcSRobert Mustacchi 		return (ECANCELED);
7239d26e4fcSRobert Mustacchi 	}
7249d26e4fcSRobert Mustacchi 
7259d26e4fcSRobert Mustacchi 	mutex_enter(&i40e->i40e_stat_lock);
7269d26e4fcSRobert Mustacchi 
7279d26e4fcSRobert Mustacchi 	/*
7289d26e4fcSRobert Mustacchi 	 * Unfortunately the GLDv3 conflates two rather different things here.
7299d26e4fcSRobert Mustacchi 	 * We're combining statistics about the physical port represented by
7309d26e4fcSRobert Mustacchi 	 * this instance with statistics that describe the properties of the
7319d26e4fcSRobert Mustacchi 	 * logical interface. As such, we're going to use the various aspects of
7329d26e4fcSRobert Mustacchi 	 * the port to describe these stats as they represent what the physical
7339d26e4fcSRobert Mustacchi 	 * instance is doing, even though that that means some tools may be
7349d26e4fcSRobert Mustacchi 	 * confused and that to see the logical traffic on the interface itself
7359d26e4fcSRobert Mustacchi 	 * sans VNICs and the like will require more work.
7369d26e4fcSRobert Mustacchi 	 *
7379d26e4fcSRobert Mustacchi 	 * Stats which are not listed in this switch statement are unimplemented
7389d26e4fcSRobert Mustacchi 	 * at this time in hardware or don't currently apply to the device.
7399d26e4fcSRobert Mustacchi 	 */
7409d26e4fcSRobert Mustacchi 	switch (stat) {
7419d26e4fcSRobert Mustacchi 	/* MIB-II stats (RFC 1213 and RFC 1573) */
7429d26e4fcSRobert Mustacchi 	case MAC_STAT_IFSPEED:
7439d26e4fcSRobert Mustacchi 		*val = i40e->i40e_link_speed * 1000000ull;
7449d26e4fcSRobert Mustacchi 		break;
745