1/* SPDX-License-Identifier: GPL-2.0 */ 2#ifndef _LINUX_AVERAGE_H 3#define _LINUX_AVERAGE_H 4 5/* 6 * Exponentially weighted moving average (EWMA) 7 * 8 * This implements a fixed-precision EWMA algorithm, with both the 9 * precision and fall-off coefficient determined at compile-time 10 * and built into the generated helper funtions. 11 * 12 * The first argument to the macro is the name that will be used 13 * for the struct and helper functions. 14 * 15 * The second argument, the precision, expresses how many bits are 16 * used for the fractional part of the fixed-precision values. 17 * 18 * The third argument, the weight reciprocal, determines how the 19 * new values will be weighed vs. the old state, new values will 20 * get weight 1/weight_rcp and old values 1-1/weight_rcp. Note 21 * that this parameter must be a power of two for efficiency. 22 */ 23 24#define DECLARE_EWMA(name, _precision, _weight_rcp) \ 25 struct ewma_##name { \ 26 unsigned long internal; \ 27 }; \ 28 static inline void ewma_##name##_init(struct ewma_##name *e) \ 29 { \ 30 BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ 31 BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ 32 /* \ 33 * Even if you want to feed it just 0/1 you should have \ 34 * some bits for the non-fractional part... \ 35 */ \ 36 BUILD_BUG_ON((_precision) > 30); \ 37 BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ 38 e->internal = 0; \ 39 } \ 40 static inline unsigned long \ 41 ewma_##name##_read(struct ewma_##name *e) \ 42 { \ 43 BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ 44 BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ 45 BUILD_BUG_ON((_precision) > 30); \ 46 BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ 47 return e->internal >> (_precision); \ 48 } \ 49 static inline void ewma_##name##_add(struct ewma_##name *e, \ 50 unsigned long val) \ 51 { \ 52 unsigned long internal = ACCESS_ONCE(e->internal); \ 53 unsigned long weight_rcp = ilog2(_weight_rcp); \ 54 unsigned long precision = _precision; \ 55 \ 56 BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ 57 BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ 58 BUILD_BUG_ON((_precision) > 30); \ 59 BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ 60 \ 61 ACCESS_ONCE(e->internal) = internal ? \ 62 (((internal << weight_rcp) - internal) + \ 63 (val << precision)) >> weight_rcp : \ 64 (val << precision); \ 65 } 66 67#endif /* _LINUX_AVERAGE_H */ 68