aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/igc/if_igc.h
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/igc/if_igc.h')
-rw-r--r--sys/dev/igc/if_igc.h65
1 files changed, 55 insertions, 10 deletions
diff --git a/sys/dev/igc/if_igc.h b/sys/dev/igc/if_igc.h
index 236a16c4add3..57b3fdcb0f13 100644
--- a/sys/dev/igc/if_igc.h
+++ b/sys/dev/igc/if_igc.h
@@ -171,8 +171,18 @@
#define IGC_EITR_DIVIDEND 1000000
#define IGC_EITR_SHIFT 2
#define IGC_QVECTOR_MASK 0x7FFC
-#define IGC_INTS_TO_EITR(i) (((IGC_EITR_DIVIDEND/i) & IGC_QVECTOR_MASK) << \
- IGC_EITR_SHIFT)
+#define IGC_INTS_TO_EITR(i) \
+ (((IGC_EITR_DIVIDEND / (i)) << IGC_EITR_SHIFT) & IGC_QVECTOR_MASK)
+#define IGC_EITR_TO_INTS(i) ((IGC_EITR_DIVIDEND << IGC_EITR_SHIFT) / \
+ ((i) & IGC_QVECTOR_MASK))
+
+/*
+ * The average packet size calculation in igc_ring_itr() yields an EITR
+ * interval field value. That field is quarter microsecond granular (see
+ * IGC_EITR_SHIFT), so an interval of V is 1000000 / (V / 4) interrupts per
+ * second.
+ */
+#define IGC_AIM_DIVIDEND (IGC_EITR_DIVIDEND << IGC_EITR_SHIFT)
/*
* TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be
@@ -232,9 +242,18 @@ struct tx_ring {
/* Soft stats */
unsigned long tx_irq;
- unsigned long tx_packets;
- unsigned long tx_bytes;
+ /*
+ * Free running AIM counters. The producer updates these while
+ * encapsulating packets, then publishes both together at the TX
+ * doorbell. The interrupt handler samples only the published value,
+ * so it cannot observe one counter without the other.
+ */
+ u32 tx_packets;
+ u32 tx_bytes;
+ uint64_t tx_aim_snapshot __aligned(8);
+ u32 tx_packets_last;
+ u32 tx_bytes_last;
/* Saved csum offloading context information */
int csum_flags;
@@ -249,6 +268,15 @@ struct tx_ring {
uint32_t csum_txd_lower; /* last field */
};
+static __inline void
+igc_aim_publish(struct tx_ring *txr)
+{
+ uint64_t snapshot;
+
+ snapshot = ((uint64_t)txr->tx_bytes << 32) | txr->tx_packets;
+ atomic_store_rel_64(&txr->tx_aim_snapshot, snapshot);
+}
+
/*
* The Receive ring, one per rx queue
*/
@@ -267,13 +295,29 @@ struct rx_ring {
/* Soft stats */
unsigned long rx_irq;
unsigned long rx_discarded;
- unsigned long rx_packets;
- unsigned long rx_bytes;
- /* Next requested EITR latency */
- u8 rx_nextlatency;
+ /*
+ * Free running AIM counters. RX publishes both together when iflib
+ * returns descriptors to hardware. The interrupt handler samples only
+ * the published value, so watchdog-driven RX processing cannot expose
+ * one counter without the other.
+ */
+ u32 rx_packets;
+ u32 rx_bytes;
+ uint64_t rx_aim_snapshot __aligned(8);
+ u32 rx_packets_last;
+ u32 rx_bytes_last;
};
+static __inline void
+igc_aim_publish_rx(struct rx_ring *rxr)
+{
+ uint64_t snapshot;
+
+ snapshot = ((uint64_t)rxr->rx_bytes << 32) | rxr->rx_packets;
+ atomic_store_rel_64(&rxr->rx_aim_snapshot, snapshot);
+}
+
struct igc_tx_queue {
struct igc_softc *sc;
u32 msix;
@@ -343,6 +387,9 @@ struct igc_softc {
/* Multicast array memory */
u8 *mta;
+ /* Retained across resets to restore the hardware VLAN filter table. */
+ u32 shadow_vfta[IGC_VFTA_SIZE];
+
/* Info about the interface */
u16 link_active;
u16 fc;
@@ -367,8 +414,6 @@ struct igc_softc {
unsigned long dropped_pkts;
unsigned long link_irq;
unsigned long rx_overruns;
- unsigned long watchdog_events;
-
struct igc_hw_stats stats;
u16 vf_ifp;
};