xref: /linux/drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 #include "fbnic.h"
2 
3 u64 fbnic_stat_rd64(struct fbnic_dev *fbd, u32 reg, u32 offset)
4 {
5 	u32 prev_upper, upper, lower, diff;
6 
7 	prev_upper = rd32(fbd, reg + offset);
8 	lower = rd32(fbd, reg);
9 	upper = rd32(fbd, reg + offset);
10 
11 	diff = upper - prev_upper;
12 	if (!diff)
13 		return ((u64)upper << 32) | lower;
14 
15 	if (diff > 1)
16 		dev_warn_once(fbd->dev,
17 			      "Stats inconsistent, upper 32b of %#010x updating too quickly\n",
18 			      reg * 4);
19 
20 	/* Return only the upper bits as we cannot guarantee
21 	 * the accuracy of the lower bits. We will add them in
22 	 * when the counter slows down enough that we can get
23 	 * a snapshot with both upper values being the same
24 	 * between reads.
25 	 */
26 	return ((u64)upper << 32);
27 }
28