1*b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 2c5485a7eSBruno Randolf #ifndef _LINUX_AVERAGE_H 3c5485a7eSBruno Randolf #define _LINUX_AVERAGE_H 4c5485a7eSBruno Randolf 5eb1e011aSJohannes Berg #include <linux/bug.h> 6eb1e011aSJohannes Berg #include <linux/compiler.h> 7eb1e011aSJohannes Berg #include <linux/log2.h> 8eb1e011aSJohannes Berg 9eb1e011aSJohannes Berg /* 10eb1e011aSJohannes Berg * Exponentially weighted moving average (EWMA) 11eb1e011aSJohannes Berg * 12eb1e011aSJohannes Berg * This implements a fixed-precision EWMA algorithm, with both the 13eb1e011aSJohannes Berg * precision and fall-off coefficient determined at compile-time 14eb1e011aSJohannes Berg * and built into the generated helper funtions. 15eb1e011aSJohannes Berg * 16eb1e011aSJohannes Berg * The first argument to the macro is the name that will be used 17eb1e011aSJohannes Berg * for the struct and helper functions. 18eb1e011aSJohannes Berg * 19eb1e011aSJohannes Berg * The second argument, the precision, expresses how many bits are 20eb1e011aSJohannes Berg * used for the fractional part of the fixed-precision values. 21eb1e011aSJohannes Berg * 22eb1e011aSJohannes Berg * The third argument, the weight reciprocal, determines how the 23c5485a7eSBruno Randolf * new values will be weighed vs. the old state, new values will 24eb1e011aSJohannes Berg * get weight 1/weight_rcp and old values 1-1/weight_rcp. Note 252377799cSJohannes Berg * that this parameter must be a power of two for efficiency. 262377799cSJohannes Berg */ 272377799cSJohannes Berg 282377799cSJohannes Berg #define DECLARE_EWMA(name, _precision, _weight_rcp) \ 292377799cSJohannes Berg struct ewma_##name { \ 30eb1e011aSJohannes Berg unsigned long internal; \ 31eb1e011aSJohannes Berg }; \ 32eb1e011aSJohannes Berg static inline void ewma_##name##_init(struct ewma_##name *e) \ 33eb1e011aSJohannes Berg { \ 34eb1e011aSJohannes Berg BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ 35eb1e011aSJohannes Berg BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ 36eb1e011aSJohannes Berg /* \ 37eb1e011aSJohannes Berg * Even if you want to feed it just 0/1 you should have \ 382377799cSJohannes Berg * some bits for the non-fractional part... \ 392377799cSJohannes Berg */ \ 402377799cSJohannes Berg BUILD_BUG_ON((_precision) > 30); \ 412377799cSJohannes Berg BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ 422377799cSJohannes Berg e->internal = 0; \ 43eb1e011aSJohannes Berg } \ 44eb1e011aSJohannes Berg static inline unsigned long \ 45eb1e011aSJohannes Berg ewma_##name##_read(struct ewma_##name *e) \ 46eb1e011aSJohannes Berg { \ 47eb1e011aSJohannes Berg BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ 482377799cSJohannes Berg BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ 492377799cSJohannes Berg BUILD_BUG_ON((_precision) > 30); \ 502377799cSJohannes Berg BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ 512377799cSJohannes Berg return e->internal >> (_precision); \ 522377799cSJohannes Berg } \ 53eb1e011aSJohannes Berg static inline void ewma_##name##_add(struct ewma_##name *e, \ 54eb1e011aSJohannes Berg unsigned long val) \ 552377799cSJohannes Berg { \ 56eb1e011aSJohannes Berg unsigned long internal = READ_ONCE(e->internal); \ 57eb1e011aSJohannes Berg unsigned long weight_rcp = ilog2(_weight_rcp); \ 58eb1e011aSJohannes Berg unsigned long precision = _precision; \ 59eb1e011aSJohannes Berg \ 602377799cSJohannes Berg BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ 612377799cSJohannes Berg BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ 62eb1e011aSJohannes Berg BUILD_BUG_ON((_precision) > 30); \ 63eb1e011aSJohannes Berg BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ 64eb1e011aSJohannes Berg \ 652377799cSJohannes Berg WRITE_ONCE(e->internal, internal ? \ 662377799cSJohannes Berg (((internal << weight_rcp) - internal) + \ 67c5485a7eSBruno Randolf (val << precision)) >> weight_rcp : \ 68 (val << precision)); \ 69 } 70 71 #endif /* _LINUX_AVERAGE_H */ 72