]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: libwx: wrap-around and reset qmprc counter
authorJiawen Wu <jiawenwu@trustnetic.com>
Tue, 7 Apr 2026 02:56:15 +0000 (10:56 +0800)
committerJakub Kicinski <kuba@kernel.org>
Sun, 12 Apr 2026 15:42:29 +0000 (08:42 -0700)
The WX_PX_MPRC registers are not clear-on-read hardware counters. The
previous implementation directly read and accumulated these 32-bit values
into a 64-bit software counter. Now implement a rd32_wrap() helper
function to calculate the delta counter to correct the statistic.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
Link: https://patch.msgid.link/20260407025616.33652-9-jiawenwu@trustnetic.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/wangxun/libwx/wx_hw.c
drivers/net/ethernet/wangxun/libwx/wx_type.h

index 31259f69c0e2ff325423467c2bc25013f92f25e5..57d6671ec61856e7a8e2a77e48d608250058350a 100644 (file)
@@ -2915,11 +2915,10 @@ void wx_update_stats(struct wx *wx)
                hwstats->fdirmiss += rd32(wx, WX_RDB_FDIR_MISS);
        }
 
-       /* qmprc is not cleared on read, manual reset it */
-       hwstats->qmprc = 0;
        for (i = wx->num_vfs * wx->num_rx_queues_per_pool;
             i < wx->mac.max_rx_queues; i++)
-               hwstats->qmprc += rd32(wx, WX_PX_MPRC(i));
+               hwstats->qmprc += rd32_wrap(wx, WX_PX_MPRC(i),
+                                           &wx->last_stats.qmprc[i]);
 
        spin_unlock(&wx->hw_stats_lock);
 }
@@ -2936,8 +2935,11 @@ void wx_clear_hw_cntrs(struct wx *wx)
 {
        u16 i = 0;
 
-       for (i = 0; i < wx->mac.max_rx_queues; i++)
+       for (i = wx->num_vfs * wx->num_rx_queues_per_pool;
+            i < wx->mac.max_rx_queues; i++) {
                wr32(wx, WX_PX_MPRC(i), 0);
+               wx->last_stats.qmprc[i] = 0;
+       }
 
        rd32(wx, WX_RDM_PKT_CNT);
        rd32(wx, WX_TDM_PKT_CNT);
index 7831c5035be88124a21545cf2295821f022c407b..3c5a351974dd3c74c3dc9f48cd7220ca67cb9807 100644 (file)
@@ -1182,6 +1182,10 @@ struct wx_hw_stats {
        u64 fdirmiss;
 };
 
+struct wx_last_stats {
+       u32 qmprc[128];
+};
+
 enum wx_state {
        WX_STATE_RESETTING,
        WX_STATE_SWFW_BUSY,
@@ -1354,6 +1358,7 @@ struct wx {
        bool default_up;
 
        struct wx_hw_stats stats;
+       struct wx_last_stats last_stats;
        spinlock_t hw_stats_lock; /* spinlock for accessing to hw stats */
        u64 tx_busy;
        u64 non_eop_descs;
@@ -1464,6 +1469,18 @@ wr32ptp(struct wx *wx, u32 reg, u32 value)
        return wr32(wx, reg + 0xB500, value);
 }
 
+static inline u32
+rd32_wrap(struct wx *wx, u32 reg, u32 *last)
+{
+       u32 val, delta;
+
+       val = rd32(wx, reg);
+       delta = val - *last;
+       *last = val;
+
+       return delta;
+}
+
 /* On some domestic CPU platforms, sometimes IO is not synchronized with
  * flushing memory, here use readl() to flush PCI read and write.
  */