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 --- drivers/net/ethernet/wangxun/libwx/wx_hw.c | 10 ++++++---- drivers/net/ethernet/wangxun/libwx/wx_type.h | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c index 31259f69c0e2..57d6671ec618 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 7831c5035be8..3c5a351974dd 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. */ -- 2.48.1