1#ifndef _LINUX_AVERAGE_H
2#define _LINUX_AVERAGE_H
3
4/* Exponentially weighted moving average (EWMA) */
5
6#define DECLARE_EWMA(name, _factor, _weight)				\
7	struct ewma_##name {						\
8		unsigned long internal;					\
9	};								\
10	static inline void ewma_##name##_init(struct ewma_##name *e)	\
11	{								\
12		BUILD_BUG_ON(!__builtin_constant_p(_factor));		\
13		BUILD_BUG_ON(!__builtin_constant_p(_weight));		\
14		BUILD_BUG_ON_NOT_POWER_OF_2(_factor);			\
15		BUILD_BUG_ON_NOT_POWER_OF_2(_weight);			\
16		e->internal = 0;					\
17	}								\
18	static inline unsigned long					\
19	ewma_##name##_read(struct ewma_##name *e)			\
20	{								\
21		BUILD_BUG_ON(!__builtin_constant_p(_factor));		\
22		BUILD_BUG_ON(!__builtin_constant_p(_weight));		\
23		BUILD_BUG_ON_NOT_POWER_OF_2(_factor);			\
24		BUILD_BUG_ON_NOT_POWER_OF_2(_weight);			\
25		return e->internal >> ilog2(_factor);			\
26	}								\
27	static inline void ewma_##name##_add(struct ewma_##name *e,	\
28					     unsigned long val)		\
29	{								\
30		unsigned long internal = ACCESS_ONCE(e->internal);	\
31		unsigned long weight = ilog2(_weight);			\
32		unsigned long factor = ilog2(_factor);			\
33									\
34		BUILD_BUG_ON(!__builtin_constant_p(_factor));		\
35		BUILD_BUG_ON(!__builtin_constant_p(_weight));		\
36		BUILD_BUG_ON_NOT_POWER_OF_2(_factor);			\
37		BUILD_BUG_ON_NOT_POWER_OF_2(_weight);			\
38									\
39		ACCESS_ONCE(e->internal) = internal ?			\
40			(((internal << weight) - internal) +		\
41				(val << factor)) >> weight :		\
42			(val << factor);				\
43	}
44
45#endif /* _LINUX_AVERAGE_H */
46