Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) // Copyright (C) 2016, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) #define pr_fmt(fmt) "irq_timings: " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/percpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/static_key.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/idr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/math64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/log2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <trace/events/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include "internals.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) DEFINE_STATIC_KEY_FALSE(irq_timing_enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) DEFINE_PER_CPU(struct irq_timings, irq_timings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) static DEFINE_IDR(irqt_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) void irq_timings_enable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	static_branch_enable(&irq_timing_enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) void irq_timings_disable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	static_branch_disable(&irq_timing_enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)  * The main goal of this algorithm is to predict the next interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)  * occurrence on the current CPU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)  * Currently, the interrupt timings are stored in a circular array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  * buffer every time there is an interrupt, as a tuple: the interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  * number and the associated timestamp when the event occurred <irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  * timestamp>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)  * For every interrupt occurring in a short period of time, we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)  * measure the elapsed time between the occurrences for the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  * interrupt and we end up with a suite of intervals. The experience
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  * showed the interrupts are often coming following a periodic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  * pattern.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  * The objective of the algorithm is to find out this periodic pattern
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  * in a fastest way and use its period to predict the next irq event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * When the next interrupt event is requested, we are in the situation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * where the interrupts are disabled and the circular buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * containing the timings is filled with the events which happened
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  * after the previous next-interrupt-event request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  * At this point, we read the circular buffer and we fill the irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  * related statistics structure. After this step, the circular array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  * containing the timings is empty because all the values are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  * dispatched in their corresponding buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  * Now for each interrupt, we can predict the next event by using the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  * suffix array, log interval and exponential moving average
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  * 1. Suffix array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  * Suffix array is an array of all the suffixes of a string. It is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  * widely used as a data structure for compression, text search, ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  * For instance for the word 'banana', the suffixes will be: 'banana'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  * 'anana' 'nana' 'ana' 'na' 'a'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  * Usually, the suffix array is sorted but for our purpose it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  * not necessary and won't provide any improvement in the context of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  * the solved problem where we clearly define the boundaries of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)  * search by a max period and min period.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)  * The suffix array will build a suite of intervals of different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  * length and will look for the repetition of each suite. If the suite
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  * is repeating then we have the period because it is the length of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  * the suite whatever its position in the buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  * 2. Log interval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  * We saw the irq timings allow to compute the interval of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  * occurrences for a specific interrupt. We can reasonibly assume the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)  * longer is the interval, the higher is the error for the next event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)  * and we can consider storing those interval values into an array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90)  * where each slot in the array correspond to an interval at the power
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91)  * of 2 of the index. For example, index 12 will contain values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)  * between 2^11 and 2^12.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)  * At the end we have an array of values where at each index defines a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95)  * [2^index - 1, 2 ^ index] interval values allowing to store a large
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96)  * number of values inside a small array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98)  * For example, if we have the value 1123, then we store it at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99)  * ilog2(1123) = 10 index value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)  * Storing those value at the specific index is done by computing an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)  * exponential moving average for this specific slot. For instance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)  * for values 1800, 1123, 1453, ... fall under the same slot (10) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)  * the exponential moving average is computed every time a new value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)  * is stored at this slot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)  * 3. Exponential Moving Average
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)  * The EMA is largely used to track a signal for stocks or as a low
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)  * pass filter. The magic of the formula, is it is very simple and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)  * reactivity of the average can be tuned with the factors called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)  * alpha.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)  * The higher the alphas are, the faster the average respond to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)  * signal change. In our case, if a slot in the array is a big
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)  * interval, we can have numbers with a big difference between
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)  * them. The impact of those differences in the average computation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)  * can be tuned by changing the alpha value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)  *  -- The algorithm --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)  * We saw the different processing above, now let's see how they are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)  * used together.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)  * For each interrupt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)  *	For each interval:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)  *		Compute the index = ilog2(interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)  *		Compute a new_ema(buffer[index], interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)  *		Store the index in a circular buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)  *	Compute the suffix array of the indexes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)  *	For each suffix:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)  *		If the suffix is reverse-found 3 times
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)  *			Return suffix
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)  *	Return Not found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)  * However we can not have endless suffix array to be build, it won't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)  * make sense and it will add an extra overhead, so we can restrict
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)  * this to a maximum suffix length of 5 and a minimum suffix length of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)  * 2. The experience showed 5 is the majority of the maximum pattern
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)  * period found for different devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)  * The result is a pattern finding less than 1us for an interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)  * Example based on real values:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)  * Example 1 : MMC write/read interrupt interval:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)  *	223947, 1240, 1384, 1386, 1386,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)  *	217416, 1236, 1384, 1386, 1387,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)  *	214719, 1241, 1386, 1387, 1384,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)  *	213696, 1234, 1384, 1386, 1388,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)  *	219904, 1240, 1385, 1389, 1385,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)  *	212240, 1240, 1386, 1386, 1386,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)  *	214415, 1236, 1384, 1386, 1387,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)  *	214276, 1234, 1384, 1388, ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)  * For each element, apply ilog2(value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)  *	15, 8, 8, 8, 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)  *	15, 8, 8, 8, 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)  *	15, 8, 8, 8, 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)  *	15, 8, 8, 8, 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)  *	15, 8, 8, 8, 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)  *	15, 8, 8, 8, 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)  *	15, 8, 8, 8, 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)  *	15, 8, 8, 8, ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)  * Max period of 5, we take the last (max_period * 3) 15 elements as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)  * we can be confident if the pattern repeats itself three times it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)  * a repeating pattern.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)  *	             8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)  *	15, 8, 8, 8, 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)  *	15, 8, 8, 8, 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)  *	15, 8, 8, 8, ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)  * Suffixes are:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)  *  1) 8, 15, 8, 8, 8  <- max period
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)  *  2) 8, 15, 8, 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)  *  3) 8, 15, 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)  *  4) 8, 15           <- min period
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)  * From there we search the repeating pattern for each suffix.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)  * buffer: 8, 15, 8, 8, 8, 8, 15, 8, 8, 8, 8, 15, 8, 8, 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)  *         |   |  |  |  |  |   |  |  |  |  |   |  |  |  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)  *         8, 15, 8, 8, 8  |   |  |  |  |  |   |  |  |  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)  *                         8, 15, 8, 8, 8  |   |  |  |  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)  *                                         8, 15, 8, 8, 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)  * When moving the suffix, we found exactly 3 matches.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)  * The first suffix with period 5 is repeating.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)  * The next event is (3 * max_period) % suffix_period
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)  * In this example, the result 0, so the next event is suffix[0] => 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)  * However, 8 is the index in the array of exponential moving average
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)  * which was calculated on the fly when storing the values, so the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)  * interval is ema[8] = 1366
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)  * Example 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)  *	4, 3, 5, 100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)  *	3, 3, 5, 117,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)  *	4, 4, 5, 112,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)  *	4, 3, 4, 110,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)  *	3, 5, 3, 117,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)  *	4, 4, 5, 112,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)  *	4, 3, 4, 110,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)  *	3, 4, 5, 112,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)  *	4, 3, 4, 110
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)  * ilog2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)  *	0, 0, 0, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)  *	0, 0, 0, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)  *	0, 0, 0, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)  *	0, 0, 0, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)  *	0, 0, 0, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)  *	0, 0, 0, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)  *	0, 0, 0, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)  *	0, 0, 0, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)  *	0, 0, 0, 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)  * Max period 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)  *	   0, 0, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)  *	0, 0, 0, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)  *	0, 0, 0, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)  *	0, 0, 0, 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)  * Suffixes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)  *  1) 0, 0, 4, 0, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)  *  2) 0, 0, 4, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)  *  3) 0, 0, 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)  *  4) 0, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)  * buffer: 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)  *         |  |  |  |  |  |  X
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)  *         0, 0, 4, 0, 0, |  X
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)  *                        0, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)  * buffer: 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)  *         |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)  *         0, 0, 4, 0, |  |  |  |  |  |  |  |  |  |  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)  *                     0, 0, 4, 0, |  |  |  |  |  |  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)  *                                 0, 0, 4, 0, |  |  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)  *                                             0  0  4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)  * Pattern is found 3 times, the remaining is 1 which results from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)  * (max_period * 3) % suffix_period. This value is the index in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)  * suffix arrays. The suffix array for a period 4 has the value 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)  * at index 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) #define EMA_ALPHA_VAL		64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) #define EMA_ALPHA_SHIFT		7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) #define PREDICTION_PERIOD_MIN	3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) #define PREDICTION_PERIOD_MAX	5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) #define PREDICTION_FACTOR	4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) #define PREDICTION_MAX		10 /* 2 ^ PREDICTION_MAX useconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) #define PREDICTION_BUFFER_SIZE	16 /* slots for EMAs, hardly more than 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)  * Number of elements in the circular buffer: If it happens it was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)  * flushed before, then the number of elements could be smaller than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)  * IRQ_TIMINGS_SIZE, so the count is used, otherwise the array size is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)  * used as we wrapped. The index begins from zero when we did not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)  * wrap. That could be done in a nicer way with the proper circular
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)  * array structure type but with the cost of extra computation in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)  * interrupt handler hot path. We choose efficiency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) #define for_each_irqts(i, irqts)					\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	for (i = irqts->count < IRQ_TIMINGS_SIZE ?			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		     0 : irqts->count & IRQ_TIMINGS_MASK,		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		     irqts->count = min(IRQ_TIMINGS_SIZE,		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 					irqts->count);			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	     irqts->count > 0; irqts->count--,				\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		     i = (i + 1) & IRQ_TIMINGS_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct irqt_stat {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	u64	last_ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	u64	ema_time[PREDICTION_BUFFER_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	int	timings[IRQ_TIMINGS_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	int	circ_timings[IRQ_TIMINGS_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	int	count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)  * Exponential moving average computation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static u64 irq_timings_ema_new(u64 value, u64 ema_old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	s64 diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	if (unlikely(!ema_old))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		return value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	diff = (value - ema_old) * EMA_ALPHA_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	 * We can use a s64 type variable to be added with the u64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	 * ema_old variable as this one will never have its topmost
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	 * bit set, it will be always smaller than 2^63 nanosec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	 * interrupt interval (292 years).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	return ema_old + (diff >> EMA_ALPHA_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static int irq_timings_next_event_index(int *buffer, size_t len, int period_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	int period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	 * Move the beginning pointer to the end minus the max period x 3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	 * We are at the point we can begin searching the pattern
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	buffer = &buffer[len - (period_max * 3)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	/* Adjust the length to the maximum allowed period x 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	len = period_max * 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	 * The buffer contains the suite of intervals, in a ilog2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	 * basis, we are looking for a repetition. We point the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	 * beginning of the search three times the length of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	 * period beginning at the end of the buffer. We do that for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	 * each suffix.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	for (period = period_max; period >= PREDICTION_PERIOD_MIN; period--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		 * The first comparison always succeed because the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		 * suffix is deduced from the first n-period bytes of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		 * the buffer and we compare the initial suffix with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		 * itself, so we can skip the first iteration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		int idx = period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		size_t size = period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		 * We look if the suite with period 'i' repeat
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 		 * itself. If it is truncated at the end, as it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		 * repeats we can use the period to find out the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		 * element with the modulo.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		while (!memcmp(buffer, &buffer[idx], size * sizeof(int))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 			 * Move the index in a period basis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 			idx += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 			 * If this condition is reached, all previous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 			 * memcmp were successful, so the period is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 			 * found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 			if (idx == len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 				return buffer[len % period];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 			 * If the remaining elements to compare are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 			 * smaller than the period, readjust the size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 			 * of the comparison for the last iteration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 			if (len - idx < period)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 				size = len - idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static u64 __irq_timings_next_event(struct irqt_stat *irqs, int irq, u64 now)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	int index, i, period_max, count, start, min = INT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	if ((now - irqs->last_ts) >= NSEC_PER_SEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 		irqs->count = irqs->last_ts = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 		return U64_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	 * As we want to find three times the repetition, we need a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	 * number of intervals greater or equal to three times the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	 * maximum period, otherwise we truncate the max period.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	period_max = irqs->count > (3 * PREDICTION_PERIOD_MAX) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 		PREDICTION_PERIOD_MAX : irqs->count / 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	 * If we don't have enough irq timings for this prediction,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	 * just bail out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	if (period_max <= PREDICTION_PERIOD_MIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		return U64_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	 * 'count' will depends if the circular buffer wrapped or not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	count = irqs->count < IRQ_TIMINGS_SIZE ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		irqs->count : IRQ_TIMINGS_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	start = irqs->count < IRQ_TIMINGS_SIZE ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 		0 : (irqs->count & IRQ_TIMINGS_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	 * Copy the content of the circular buffer into another buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	 * in order to linearize the buffer instead of dealing with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	 * wrapping indexes and shifted array which will be prone to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	 * error and extremelly difficult to debug.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 		int index = (start + i) & IRQ_TIMINGS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 		irqs->timings[i] = irqs->circ_timings[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 		min = min_t(int, irqs->timings[i], min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	index = irq_timings_next_event_index(irqs->timings, count, period_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	if (index < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		return irqs->last_ts + irqs->ema_time[min];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	return irqs->last_ts + irqs->ema_time[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static __always_inline int irq_timings_interval_index(u64 interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	 * The PREDICTION_FACTOR increase the interval size for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	 * array of exponential average.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	u64 interval_us = (interval >> 10) / PREDICTION_FACTOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	return likely(interval_us) ? ilog2(interval_us) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) static __always_inline void __irq_timings_store(int irq, struct irqt_stat *irqs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 						u64 interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	 * Get the index in the ema table for this interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	index = irq_timings_interval_index(interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	if (index > PREDICTION_BUFFER_SIZE - 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		irqs->count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	 * Store the index as an element of the pattern in another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	 * circular array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	irqs->circ_timings[irqs->count & IRQ_TIMINGS_MASK] = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	irqs->ema_time[index] = irq_timings_ema_new(interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 						    irqs->ema_time[index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	irqs->count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static inline void irq_timings_store(int irq, struct irqt_stat *irqs, u64 ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	u64 old_ts = irqs->last_ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	u64 interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	 * The timestamps are absolute time values, we need to compute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	 * the timing interval between two interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	irqs->last_ts = ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	 * The interval type is u64 in order to deal with the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	 * type in our computation, that prevent mindfuck issues with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	 * overflow, sign and division.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	interval = ts - old_ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	 * The interrupt triggered more than one second apart, that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	 * ends the sequence as predictible for our purpose. In this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	 * case, assume we have the beginning of a sequence and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	 * timestamp is the first value. As it is impossible to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	 * predict anything at this point, return.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	 * Note the first timestamp of the sequence will always fall
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	 * in this test because the old_ts is zero. That is what we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	 * want as we need another timestamp to compute an interval.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	if (interval >= NSEC_PER_SEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 		irqs->count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	__irq_timings_store(irq, irqs, interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)  * irq_timings_next_event - Return when the next event is supposed to arrive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)  * During the last busy cycle, the number of interrupts is incremented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)  * and stored in the irq_timings structure. This information is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)  * necessary to:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)  * - know if the index in the table wrapped up:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)  *      If more than the array size interrupts happened during the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)  *      last busy/idle cycle, the index wrapped up and we have to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)  *      begin with the next element in the array which is the last one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)  *      in the sequence, otherwise it is a the index 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)  * - have an indication of the interrupts activity on this CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)  *   (eg. irq/sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)  * The values are 'consumed' after inserting in the statistical model,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)  * thus the count is reinitialized.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)  * The array of values **must** be browsed in the time direction, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)  * timestamp must increase between an element and the next one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)  * Returns a nanosec time based estimation of the earliest interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)  * U64_MAX otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) u64 irq_timings_next_event(u64 now)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	struct irq_timings *irqts = this_cpu_ptr(&irq_timings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	struct irqt_stat *irqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	struct irqt_stat __percpu *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	u64 ts, next_evt = U64_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	int i, irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	 * This function must be called with the local irq disabled in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	 * order to prevent the timings circular buffer to be updated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	 * while we are reading it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	lockdep_assert_irqs_disabled();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	if (!irqts->count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 		return next_evt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	 * Number of elements in the circular buffer: If it happens it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	 * was flushed before, then the number of elements could be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	 * smaller than IRQ_TIMINGS_SIZE, so the count is used,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	 * otherwise the array size is used as we wrapped. The index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 	 * begins from zero when we did not wrap. That could be done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	 * in a nicer way with the proper circular array structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	 * type but with the cost of extra computation in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	 * interrupt handler hot path. We choose efficiency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	 * Inject measured irq/timestamp to the pattern prediction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	 * model while decrementing the counter because we consume the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	 * data from our circular buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	for_each_irqts(i, irqts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 		irq = irq_timing_decode(irqts->values[i], &ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 		s = idr_find(&irqt_stats, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 		if (s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 			irq_timings_store(irq, this_cpu_ptr(s), ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	 * Look in the list of interrupts' statistics, the earliest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	 * next event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	idr_for_each_entry(&irqt_stats, s, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 		irqs = this_cpu_ptr(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 		ts = __irq_timings_next_event(irqs, i, now);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 		if (ts <= now)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 			return now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 		if (ts < next_evt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 			next_evt = ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	return next_evt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) void irq_timings_free(int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	struct irqt_stat __percpu *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	s = idr_find(&irqt_stats, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 	if (s) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 		free_percpu(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 		idr_remove(&irqt_stats, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) int irq_timings_alloc(int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	struct irqt_stat __percpu *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	 * Some platforms can have the same private interrupt per cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	 * so this function may be called several times with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	 * same interrupt number. Just bail out in case the per cpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	 * stat structure is already allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 	s = idr_find(&irqt_stats, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 	if (s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	s = alloc_percpu(*s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	if (!s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	idr_preload(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	id = idr_alloc(&irqt_stats, s, irq, irq + 1, GFP_NOWAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	idr_preload_end();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	if (id < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 		free_percpu(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 		return id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) #ifdef CONFIG_TEST_IRQ_TIMINGS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) struct timings_intervals {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 	u64 *intervals;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	size_t count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)  * Intervals are given in nanosecond base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) static u64 intervals0[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 	10000, 50000, 200000, 500000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	10000, 50000, 200000, 500000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	10000, 50000, 200000, 500000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 	10000, 50000, 200000, 500000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 	10000, 50000, 200000, 500000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	10000, 50000, 200000, 500000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 	10000, 50000, 200000, 500000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	10000, 50000, 200000, 500000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	10000, 50000, 200000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) static u64 intervals1[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 	223947000, 1240000, 1384000, 1386000, 1386000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	217416000, 1236000, 1384000, 1386000, 1387000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 	214719000, 1241000, 1386000, 1387000, 1384000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 	213696000, 1234000, 1384000, 1386000, 1388000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	219904000, 1240000, 1385000, 1389000, 1385000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 	212240000, 1240000, 1386000, 1386000, 1386000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 	214415000, 1236000, 1384000, 1386000, 1387000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 	214276000, 1234000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) static u64 intervals2[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 	4000, 3000, 5000, 100000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 	3000, 3000, 5000, 117000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	4000, 4000, 5000, 112000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 	4000, 3000, 4000, 110000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 	3000, 5000, 3000, 117000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	4000, 4000, 5000, 112000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 	4000, 3000, 4000, 110000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	3000, 4000, 5000, 112000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	4000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) static u64 intervals3[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 	1385000, 212240000, 1240000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 	1386000, 214415000, 1236000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 	1384000, 214276000, 1234000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 	1386000, 214415000, 1236000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 	1385000, 212240000, 1240000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 	1386000, 214415000, 1236000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 	1384000, 214276000, 1234000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 	1386000, 214415000, 1236000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 	1385000, 212240000, 1240000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static u64 intervals4[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 	10000, 50000, 10000, 50000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	10000, 50000, 10000, 50000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 	10000, 50000, 10000, 50000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 	10000, 50000, 10000, 50000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 	10000, 50000, 10000, 50000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 	10000, 50000, 10000, 50000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 	10000, 50000, 10000, 50000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 	10000, 50000, 10000, 50000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 	10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) static struct timings_intervals tis[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 	{ intervals0, ARRAY_SIZE(intervals0) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 	{ intervals1, ARRAY_SIZE(intervals1) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 	{ intervals2, ARRAY_SIZE(intervals2) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 	{ intervals3, ARRAY_SIZE(intervals3) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	{ intervals4, ARRAY_SIZE(intervals4) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) static int __init irq_timings_test_next_index(struct timings_intervals *ti)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 	int _buffer[IRQ_TIMINGS_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 	int buffer[IRQ_TIMINGS_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 	int index, start, i, count, period_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 	count = ti->count - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 	period_max = count > (3 * PREDICTION_PERIOD_MAX) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 		PREDICTION_PERIOD_MAX : count / 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 	 * Inject all values except the last one which will be used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	 * to compare with the next index result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 	pr_debug("index suite: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 	for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 		index = irq_timings_interval_index(ti->intervals[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 		_buffer[i & IRQ_TIMINGS_MASK] = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 		pr_cont("%d ", index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 	start = count < IRQ_TIMINGS_SIZE ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 		count & IRQ_TIMINGS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 	count = min_t(int, count, IRQ_TIMINGS_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 	for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 		int index = (start + i) & IRQ_TIMINGS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 		buffer[i] = _buffer[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 	index = irq_timings_next_event_index(buffer, count, period_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 	i = irq_timings_interval_index(ti->intervals[ti->count - 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 	if (index != i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 		pr_err("Expected (%d) and computed (%d) next indexes differ\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 		       i, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) static int __init irq_timings_next_index_selftest(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 	int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 	for (i = 0; i < ARRAY_SIZE(tis); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 		pr_info("---> Injecting intervals number #%d (count=%zd)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 			i, tis[i].count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 		ret = irq_timings_test_next_index(&tis[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) static int __init irq_timings_test_irqs(struct timings_intervals *ti)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 	struct irqt_stat __percpu *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 	struct irqt_stat *irqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 	int i, index, ret, irq = 0xACE5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 	ret = irq_timings_alloc(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 		pr_err("Failed to allocate irq timings\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 	s = idr_find(&irqt_stats, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 	if (!s) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 		ret = -EIDRM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 	irqs = this_cpu_ptr(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 	for (i = 0; i < ti->count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 		index = irq_timings_interval_index(ti->intervals[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 		pr_debug("%d: interval=%llu ema_index=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 			 i, ti->intervals[i], index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) 		__irq_timings_store(irq, irqs, ti->intervals[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 		if (irqs->circ_timings[i & IRQ_TIMINGS_MASK] != index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 			ret = -EBADSLT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 			pr_err("Failed to store in the circular buffer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 	if (irqs->count != ti->count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 		ret = -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 		pr_err("Count differs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 	ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 	irq_timings_free(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) static int __init irq_timings_irqs_selftest(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 	int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) 	for (i = 0; i < ARRAY_SIZE(tis); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) 		pr_info("---> Injecting intervals number #%d (count=%zd)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) 			i, tis[i].count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) 		ret = irq_timings_test_irqs(&tis[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) static int __init irq_timings_test_irqts(struct irq_timings *irqts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) 					 unsigned count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) 	int start = count >= IRQ_TIMINGS_SIZE ? count - IRQ_TIMINGS_SIZE : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 	int i, irq, oirq = 0xBEEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 	u64 ots = 0xDEAD, ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) 	 * Fill the circular buffer by using the dedicated function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) 	for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) 		pr_debug("%d: index=%d, ts=%llX irq=%X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) 			 i, i & IRQ_TIMINGS_MASK, ots + i, oirq + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) 		irq_timings_push(ots + i, oirq + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 	 * Compute the first elements values after the index wrapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 	 * up or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) 	ots += start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) 	oirq += start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) 	 * Test the circular buffer count is correct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) 	pr_debug("---> Checking timings array count (%d) is right\n", count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) 	if (WARN_ON(irqts->count != count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) 	 * Test the macro allowing to browse all the irqts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) 	pr_debug("---> Checking the for_each_irqts() macro\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) 	for_each_irqts(i, irqts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) 		irq = irq_timing_decode(irqts->values[i], &ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) 		pr_debug("index=%d, ts=%llX / %llX, irq=%X / %X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) 			 i, ts, ots, irq, oirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) 		if (WARN_ON(ts != ots || irq != oirq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) 		ots++; oirq++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) 	 * The circular buffer should have be flushed when browsed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) 	 * with for_each_irqts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) 	pr_debug("---> Checking timings array is empty after browsing it\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) 	if (WARN_ON(irqts->count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) static int __init irq_timings_irqts_selftest(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) 	struct irq_timings *irqts = this_cpu_ptr(&irq_timings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) 	int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) 	 * Test the circular buffer with different number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) 	 * elements. The purpose is to test at the limits (empty, half
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) 	 * full, full, wrapped with the cursor at the boundaries,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) 	 * wrapped several times, etc ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) 	int count[] = { 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) 			IRQ_TIMINGS_SIZE >> 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) 			IRQ_TIMINGS_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) 			IRQ_TIMINGS_SIZE + (IRQ_TIMINGS_SIZE >> 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) 			2 * IRQ_TIMINGS_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) 			(2 * IRQ_TIMINGS_SIZE) + 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) 	for (i = 0; i < ARRAY_SIZE(count); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) 		pr_info("---> Checking the timings with %d/%d values\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) 			count[i], IRQ_TIMINGS_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) 		ret = irq_timings_test_irqts(irqts, count[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) static int __init irq_timings_selftest(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) 	pr_info("------------------- selftest start -----------------\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) 	 * At this point, we don't except any subsystem to use the irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) 	 * timings but us, so it should not be enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) 	if (static_branch_unlikely(&irq_timing_enabled)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) 		pr_warn("irq timings already initialized, skipping selftest\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) 	ret = irq_timings_irqts_selftest();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) 	ret = irq_timings_irqs_selftest();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) 	ret = irq_timings_next_index_selftest();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) 	pr_info("---------- selftest end with %s -----------\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) 		ret ? "failure" : "success");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) early_initcall(irq_timings_selftest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) #endif