From: Jiawen Wu Date: Tue, 7 Apr 2026 02:56:15 +0000 (+0800) Subject: net: libwx: wrap-around and reset qmprc counter X-Git-Tag: v7.1-rc1~173^2~46^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1dd9b0dafd21cfdac534b423b7e7ee980b3c535a;p=thirdparty%2Fkernel%2Flinux.git net: libwx: wrap-around and reset qmprc counter 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 Link: https://patch.msgid.link/20260407025616.33652-9-jiawenwu@trustnetic.com Signed-off-by: Jakub Kicinski --- diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c index 31259f69c0e2f..57d6671ec6185 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c @@ -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); diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index 7831c5035be88..3c5a351974dd3 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -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. */