+ now = local_clock();
+ prev = timings->timestamp;
+ timings->timestamp = now;
+
+ /*
+ * If it is the first interrupt of the series, we can't
+ * compute an interval, just store the timestamp and exit.
+ */
+ if (unlikely(!prev))
+ return;
The delta will be large enough that you drop out in the check below. So you
can spare that conditional.
+
+ diff = now - prev;
+
+ /*
+ * microsec (actually 1024th of a milisec) precision is good
+ * enough for our purpose.
+ */
+ diff >>= 10;
And that shift instruction is required because of the following?
* Otherwise we know the magnitude of diff is
+ * well within 32 bits.
AFAICT that's pointless. You are not saving anything because NSEC_PER_SEC is
smaller than 2^32 and your 8 values are not going to overflow 64 bit in the
sum.
+ */
+ if (unlikely(diff > USEC_PER_SEC)) {
+ memset(timings, 0, sizeof(*timings));
+ timings->timestamp = now;
Redundant store.
+ return;
+ }
+
+ /* The oldest value corresponds to the next index. */
+ timings->w_index = (timings->w_index + 1) & IRQ_TIMINGS_MASK;
+
+ /*
+ * Remove the oldest value from the summing. If this is the
+ * first time we go through this array slot, the previous
+ * value will be zero and we won't substract anything from the
+ * current sum. Hence this code relies on a zero-ed structure.
+ */
+ timings->sum -= timings->values[timings->w_index];
+ timings->values[timings->w_index] = diff;
+ timings->sum += diff;
Now the real question is whether you really need all that math, checks and
memsets in the irq hotpath. If you make the storage slightly larger then you
can just store the values unconditionally in the circular buffer and do all
the computational stuff when you really it.