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