git: fef4249f0728 - main - ixl(4): Use GL_RXERR1 register for correct oversize packet count

From: Eric Joyner <erj_at_FreeBSD.org>
Date: Tue, 27 Aug 2024 23:07:36 UTC
The branch main has been updated by erj:

URL: https://cgit.FreeBSD.org/src/commit/?id=fef4249f07287374b10087f597a62b8e00dedabc

commit fef4249f07287374b10087f597a62b8e00dedabc
Author:     Eric Joyner <erj@FreeBSD.org>
AuthorDate: 2024-08-27 22:59:49 +0000
Commit:     Eric Joyner <erj@FreeBSD.org>
CommitDate: 2024-08-27 22:59:49 +0000

    ixl(4): Use GL_RXERR1 register for correct oversize packet count
    
    The driver sets the Maximum Transmission Unit (MTU) at the Virtual Station
    Interface (VSI) level, which leads to a discrepancy in the GLPRT_ROC counter's
    ability to accurately tally oversized packets, as this counter operates at the
    physical port level. To rectify this issue, it is necessary to take an
    additional register (GL_RXERR1) into account to obtain the correct count of
    oversized packets.
    
    Signed-off-by: Yogesh Bhosale <yogesh.bhosale@intel.com>
    Signed-off-by: Eric Joyner <erj@FreeBSD.org>
    
    Reviewed by:    erj@
    Sponsored by:   Intel Corporation
    Differential Revision:  https://reviews.freebsd.org/D45870
---
 sys/dev/ixl/i40e_register.h |  12 ++--
 sys/dev/ixl/i40e_type.h     |   1 +
 sys/dev/ixl/ixl_pf.h        |   4 +-
 sys/dev/ixl/ixl_pf_main.c   | 158 ++++++++++++++++++++++++--------------------
 4 files changed, 100 insertions(+), 75 deletions(-)

diff --git a/sys/dev/ixl/i40e_register.h b/sys/dev/ixl/i40e_register.h
index 22a0f779db09..c267fef41af3 100644
--- a/sys/dev/ixl/i40e_register.h
+++ b/sys/dev/ixl/i40e_register.h
@@ -2431,10 +2431,14 @@
 #define I40E_GL_FCOERPDC_MAX_INDEX      143
 #define I40E_GL_FCOERPDC_FCOERPDC_SHIFT 0
 #define I40E_GL_FCOERPDC_FCOERPDC_MASK  I40E_MASK(0xFFFFFFFF, I40E_GL_FCOERPDC_FCOERPDC_SHIFT)
-#define I40E_GL_RXERR1_L(_i)             (0x00318000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
-#define I40E_GL_RXERR1_L_MAX_INDEX       143
-#define I40E_GL_RXERR1_L_FCOEDIFRC_SHIFT 0
-#define I40E_GL_RXERR1_L_FCOEDIFRC_MASK  I40E_MASK(0xFFFFFFFF, I40E_GL_RXERR1_L_FCOEDIFRC_SHIFT)
+#define I40E_GL_RXERR1H(_i)             (0x00318004 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
+#define I40E_GL_RXERR1H_MAX_INDEX       143
+#define I40E_GL_RXERR1H_RXERR1H_SHIFT   0
+#define I40E_GL_RXERR1H_RXERR1H_MASK    I40E_MASK(0xFFFFFFFF, I40E_GL_RXERR1H_RXERR1H_SHIFT)
+#define I40E_GL_RXERR1L(_i)             (0x00318000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
+#define I40E_GL_RXERR1L_MAX_INDEX       143
+#define I40E_GL_RXERR1L_RXERR1L_SHIFT   0
+#define I40E_GL_RXERR1L_RXERR1L_MASK    I40E_MASK(0xFFFFFFFF, I40E_GL_RXERR1L_RXERR1L_SHIFT)
 #define I40E_GL_RXERR2_L(_i)             (0x0031c000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
 #define I40E_GL_RXERR2_L_MAX_INDEX       143
 #define I40E_GL_RXERR2_L_FCOEDIXAC_SHIFT 0
diff --git a/sys/dev/ixl/i40e_type.h b/sys/dev/ixl/i40e_type.h
index 9c2809a3e41a..20e8f09b0813 100644
--- a/sys/dev/ixl/i40e_type.h
+++ b/sys/dev/ixl/i40e_type.h
@@ -1472,6 +1472,7 @@ struct i40e_hw_port_stats {
 	u64 rx_undersize;		/* ruc */
 	u64 rx_fragments;		/* rfc */
 	u64 rx_oversize;		/* roc */
+	u64 rx_err1;			/* rxerr1 */
 	u64 rx_jabber;			/* rjc */
 	u64 tx_size_64;			/* ptc64 */
 	u64 tx_size_127;		/* ptc127 */
diff --git a/sys/dev/ixl/ixl_pf.h b/sys/dev/ixl/ixl_pf.h
index 96303c43d4e8..f0d42f18cef0 100644
--- a/sys/dev/ixl/ixl_pf.h
+++ b/sys/dev/ixl/ixl_pf.h
@@ -318,7 +318,9 @@ void	ixl_disable_queue(struct i40e_hw *, int);
 void	ixl_enable_intr0(struct i40e_hw *);
 void	ixl_disable_intr0(struct i40e_hw *);
 void	ixl_nvm_version_str(struct i40e_hw *hw, struct sbuf *buf);
-void	ixl_stat_update48(struct i40e_hw *, u32, u32, bool,
+void    ixl_stat_update64(struct i40e_hw *, u32, bool,
+			u64 *, u64 *);
+void	ixl_stat_update48(struct i40e_hw *, u32, bool,
 		    u64 *, u64 *);
 void	ixl_stat_update32(struct i40e_hw *, u32, bool,
 		    u64 *, u64 *);
diff --git a/sys/dev/ixl/ixl_pf_main.c b/sys/dev/ixl/ixl_pf_main.c
index af253faeac7a..4e1b1001efdc 100644
--- a/sys/dev/ixl/ixl_pf_main.c
+++ b/sys/dev/ixl/ixl_pf_main.c
@@ -2109,45 +2109,37 @@ ixl_update_stats_counters(struct ixl_pf *pf)
 	ixl_stat_update32(hw, I40E_GLPRT_ILLERRC(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->illegal_bytes, &nsd->illegal_bytes);
-	ixl_stat_update48(hw, I40E_GLPRT_GORCH(hw->port),
-			   I40E_GLPRT_GORCL(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_GORCL(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->eth.rx_bytes, &nsd->eth.rx_bytes);
-	ixl_stat_update48(hw, I40E_GLPRT_GOTCH(hw->port),
-			   I40E_GLPRT_GOTCL(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_GOTCL(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->eth.tx_bytes, &nsd->eth.tx_bytes);
 	ixl_stat_update32(hw, I40E_GLPRT_RDPC(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->eth.rx_discards,
 			   &nsd->eth.rx_discards);
-	ixl_stat_update48(hw, I40E_GLPRT_UPRCH(hw->port),
-			   I40E_GLPRT_UPRCL(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_UPRCL(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->eth.rx_unicast,
 			   &nsd->eth.rx_unicast);
-	ixl_stat_update48(hw, I40E_GLPRT_UPTCH(hw->port),
-			   I40E_GLPRT_UPTCL(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_UPTCL(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->eth.tx_unicast,
 			   &nsd->eth.tx_unicast);
-	ixl_stat_update48(hw, I40E_GLPRT_MPRCH(hw->port),
-			   I40E_GLPRT_MPRCL(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_MPRCL(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->eth.rx_multicast,
 			   &nsd->eth.rx_multicast);
-	ixl_stat_update48(hw, I40E_GLPRT_MPTCH(hw->port),
-			   I40E_GLPRT_MPTCL(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_MPTCL(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->eth.tx_multicast,
 			   &nsd->eth.tx_multicast);
-	ixl_stat_update48(hw, I40E_GLPRT_BPRCH(hw->port),
-			   I40E_GLPRT_BPRCL(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_BPRCL(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->eth.rx_broadcast,
 			   &nsd->eth.rx_broadcast);
-	ixl_stat_update48(hw, I40E_GLPRT_BPTCH(hw->port),
-			   I40E_GLPRT_BPTCL(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_BPTCL(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->eth.tx_broadcast,
 			   &nsd->eth.tx_broadcast);
@@ -2191,62 +2183,48 @@ ixl_update_stats_counters(struct ixl_pf *pf)
 		vsi->shared->isc_pause_frames = 1;
 
 	/* Packet size stats rx */
-	ixl_stat_update48(hw, I40E_GLPRT_PRC64H(hw->port),
-			   I40E_GLPRT_PRC64L(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_PRC64L(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->rx_size_64, &nsd->rx_size_64);
-	ixl_stat_update48(hw, I40E_GLPRT_PRC127H(hw->port),
-			   I40E_GLPRT_PRC127L(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_PRC127L(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->rx_size_127, &nsd->rx_size_127);
-	ixl_stat_update48(hw, I40E_GLPRT_PRC255H(hw->port),
-			   I40E_GLPRT_PRC255L(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_PRC255L(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->rx_size_255, &nsd->rx_size_255);
-	ixl_stat_update48(hw, I40E_GLPRT_PRC511H(hw->port),
-			   I40E_GLPRT_PRC511L(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_PRC511L(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->rx_size_511, &nsd->rx_size_511);
-	ixl_stat_update48(hw, I40E_GLPRT_PRC1023H(hw->port),
-			   I40E_GLPRT_PRC1023L(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_PRC1023L(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->rx_size_1023, &nsd->rx_size_1023);
-	ixl_stat_update48(hw, I40E_GLPRT_PRC1522H(hw->port),
-			   I40E_GLPRT_PRC1522L(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_PRC1522L(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->rx_size_1522, &nsd->rx_size_1522);
-	ixl_stat_update48(hw, I40E_GLPRT_PRC9522H(hw->port),
-			   I40E_GLPRT_PRC9522L(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_PRC9522L(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->rx_size_big, &nsd->rx_size_big);
 
 	/* Packet size stats tx */
-	ixl_stat_update48(hw, I40E_GLPRT_PTC64H(hw->port),
-			   I40E_GLPRT_PTC64L(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_PTC64L(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->tx_size_64, &nsd->tx_size_64);
-	ixl_stat_update48(hw, I40E_GLPRT_PTC127H(hw->port),
-			   I40E_GLPRT_PTC127L(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_PTC127L(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->tx_size_127, &nsd->tx_size_127);
-	ixl_stat_update48(hw, I40E_GLPRT_PTC255H(hw->port),
-			   I40E_GLPRT_PTC255L(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_PTC255L(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->tx_size_255, &nsd->tx_size_255);
-	ixl_stat_update48(hw, I40E_GLPRT_PTC511H(hw->port),
-			   I40E_GLPRT_PTC511L(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_PTC511L(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->tx_size_511, &nsd->tx_size_511);
-	ixl_stat_update48(hw, I40E_GLPRT_PTC1023H(hw->port),
-			   I40E_GLPRT_PTC1023L(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_PTC1023L(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->tx_size_1023, &nsd->tx_size_1023);
-	ixl_stat_update48(hw, I40E_GLPRT_PTC1522H(hw->port),
-			   I40E_GLPRT_PTC1522L(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_PTC1522L(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->tx_size_1522, &nsd->tx_size_1522);
-	ixl_stat_update48(hw, I40E_GLPRT_PTC9522H(hw->port),
-			   I40E_GLPRT_PTC9522L(hw->port),
+	ixl_stat_update48(hw, I40E_GLPRT_PTC9522L(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->tx_size_big, &nsd->tx_size_big);
 
@@ -2256,9 +2234,29 @@ ixl_update_stats_counters(struct ixl_pf *pf)
 	ixl_stat_update32(hw, I40E_GLPRT_RFC(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->rx_fragments, &nsd->rx_fragments);
+
+	u64 rx_roc;
 	ixl_stat_update32(hw, I40E_GLPRT_ROC(hw->port),
 			   pf->stat_offsets_loaded,
-			   &osd->rx_oversize, &nsd->rx_oversize);
+			   &osd->rx_oversize, &rx_roc);
+
+	/*
+	 * Read from RXERR1 register to get the count for the packets
+	 * larger than RX MAX and include that in total rx_oversize count.
+	 *
+	 * Also need to add BIT(7) to hw->port value while indexing
+	 * I40E_GL_RXERR1 register as indexes 0..127 are for VFs when
+	 * SR-IOV is enabled. Indexes 128..143 are for PFs.
+	 */
+	u64 rx_err1;
+	ixl_stat_update64(hw,
+			   I40E_GL_RXERR1L(hw->pf_id + BIT(7)),
+			   pf->stat_offsets_loaded,
+			   &osd->rx_err1,
+			   &rx_err1);
+
+	nsd->rx_oversize = rx_roc + rx_err1;
+
 	ixl_stat_update32(hw, I40E_GLPRT_RJC(hw->port),
 			   pf->stat_offsets_loaded,
 			   &osd->rx_jabber, &nsd->rx_jabber);
@@ -2305,37 +2303,29 @@ ixl_update_eth_stats(struct ixl_vsi *vsi)
 			   vsi->stat_offsets_loaded,
 			   &oes->rx_discards, &es->rx_discards);
 
-	ixl_stat_update48(hw, I40E_GLV_GORCH(stat_idx),
-			   I40E_GLV_GORCL(stat_idx),
+	ixl_stat_update48(hw, I40E_GLV_GORCL(stat_idx),
 			   vsi->stat_offsets_loaded,
 			   &oes->rx_bytes, &es->rx_bytes);
-	ixl_stat_update48(hw, I40E_GLV_UPRCH(stat_idx),
-			   I40E_GLV_UPRCL(stat_idx),
+	ixl_stat_update48(hw, I40E_GLV_UPRCL(stat_idx),
 			   vsi->stat_offsets_loaded,
 			   &oes->rx_unicast, &es->rx_unicast);
-	ixl_stat_update48(hw, I40E_GLV_MPRCH(stat_idx),
-			   I40E_GLV_MPRCL(stat_idx),
+	ixl_stat_update48(hw, I40E_GLV_MPRCL(stat_idx),
 			   vsi->stat_offsets_loaded,
 			   &oes->rx_multicast, &es->rx_multicast);
-	ixl_stat_update48(hw, I40E_GLV_BPRCH(stat_idx),
-			   I40E_GLV_BPRCL(stat_idx),
+	ixl_stat_update48(hw, I40E_GLV_BPRCL(stat_idx),
 			   vsi->stat_offsets_loaded,
 			   &oes->rx_broadcast, &es->rx_broadcast);
 
-	ixl_stat_update48(hw, I40E_GLV_GOTCH(stat_idx),
-			   I40E_GLV_GOTCL(stat_idx),
+	ixl_stat_update48(hw, I40E_GLV_GOTCL(stat_idx),
 			   vsi->stat_offsets_loaded,
 			   &oes->tx_bytes, &es->tx_bytes);
-	ixl_stat_update48(hw, I40E_GLV_UPTCH(stat_idx),
-			   I40E_GLV_UPTCL(stat_idx),
+	ixl_stat_update48(hw, I40E_GLV_UPTCL(stat_idx),
 			   vsi->stat_offsets_loaded,
 			   &oes->tx_unicast, &es->tx_unicast);
-	ixl_stat_update48(hw, I40E_GLV_MPTCH(stat_idx),
-			   I40E_GLV_MPTCL(stat_idx),
+	ixl_stat_update48(hw, I40E_GLV_MPTCL(stat_idx),
 			   vsi->stat_offsets_loaded,
 			   &oes->tx_multicast, &es->tx_multicast);
-	ixl_stat_update48(hw, I40E_GLV_BPTCH(stat_idx),
-			   I40E_GLV_BPTCL(stat_idx),
+	ixl_stat_update48(hw, I40E_GLV_BPTCL(stat_idx),
 			   vsi->stat_offsets_loaded,
 			   &oes->tx_broadcast, &es->tx_broadcast);
 	vsi->stat_offsets_loaded = true;
@@ -2409,28 +2399,56 @@ ixl_vsi_reset_stats(struct ixl_vsi *vsi)
 }
 
 /**
- * Read and update a 48 bit stat from the hw
+ * Helper function for reading and updating 48/64 bit stats from the hw
  *
  * Since the device stats are not reset at PFReset, they likely will not
  * be zeroed when the driver starts.  We'll save the first values read
  * and use them as offsets to be subtracted from the raw values in order
  * to report stats that count from zero.
  **/
-void
-ixl_stat_update48(struct i40e_hw *hw, u32 hireg, u32 loreg,
-	bool offset_loaded, u64 *offset, u64 *stat)
+static void
+_ixl_stat_update_helper(struct i40e_hw *hw, u32 reg,
+	bool offset_loaded, u64 mask, u64 *offset, u64 *stat)
 {
-	u64 new_data;
-
-	new_data = rd64(hw, loreg);
+	u64 new_data = rd64(hw, reg);
 
 	if (!offset_loaded)
 		*offset = new_data;
 	if (new_data >= *offset)
 		*stat = new_data - *offset;
 	else
-		*stat = (new_data + ((u64)1 << 48)) - *offset;
-	*stat &= 0xFFFFFFFFFFFFULL;
+		*stat = (new_data + mask) - *offset + 1;
+	*stat &= mask;
+}
+
+/**
+ * Read and update a 48 bit stat from the hw
+ **/
+void
+ixl_stat_update48(struct i40e_hw *hw, u32 reg,
+	bool offset_loaded, u64 *offset, u64 *stat)
+{
+	_ixl_stat_update_helper(hw,
+		reg,
+		offset_loaded,
+		0xFFFFFFFFFFFFULL,
+		offset,
+		stat);
+}
+
+/**
+ * ixl_stat_update64 - read and update a 64 bit stat from the chip.
+ **/
+void
+ixl_stat_update64(struct i40e_hw *hw, u32 reg,
+			       bool offset_loaded, u64 *offset, u64 *stat)
+{
+	_ixl_stat_update_helper(hw,
+		reg,
+		offset_loaded,
+		0xFFFFFFFFFFFFFFFFULL,
+		offset,
+		stat);
 }
 
 /**