Commit eb1e011a authored by Johannes Berg's avatar Johannes Berg

average: change to declare precision, not factor

Declaring the factor is counter-intuitive, and people are prone
to using small(-ish) values even when that makes no sense.

Change the DECLARE_EWMA() macro to take the fractional precision,
in bits, rather than a factor, and update all users.

While at it, add some more documentation.
Acked-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 48cac18e
...@@ -51,7 +51,7 @@ module_param(gso, bool, 0444); ...@@ -51,7 +51,7 @@ module_param(gso, bool, 0444);
* at once, the weight is chosen so that the EWMA will be insensitive to short- * at once, the weight is chosen so that the EWMA will be insensitive to short-
* term, transient changes in packet size. * term, transient changes in packet size.
*/ */
DECLARE_EWMA(pkt_len, 1, 64) DECLARE_EWMA(pkt_len, 0, 64)
/* With mergeable buffers we align buffer address and use the low bits to /* With mergeable buffers we align buffer address and use the low bits to
* encode its true size. Buffer size is up to 1 page so we need to align to * encode its true size. Buffer size is up to 1 page so we need to align to
......
...@@ -1252,7 +1252,7 @@ struct ath5k_statistics { ...@@ -1252,7 +1252,7 @@ struct ath5k_statistics {
#define ATH5K_TXQ_LEN_MAX (ATH_TXBUF / 4) /* bufs per queue */ #define ATH5K_TXQ_LEN_MAX (ATH_TXBUF / 4) /* bufs per queue */
#define ATH5K_TXQ_LEN_LOW (ATH5K_TXQ_LEN_MAX / 2) /* low mark */ #define ATH5K_TXQ_LEN_LOW (ATH5K_TXQ_LEN_MAX / 2) /* low mark */
DECLARE_EWMA(beacon_rssi, 1024, 8) DECLARE_EWMA(beacon_rssi, 10, 8)
/* Driver state associated with an instance of a device */ /* Driver state associated with an instance of a device */
struct ath5k_hw { struct ath5k_hw {
......
...@@ -257,7 +257,7 @@ struct link_qual { ...@@ -257,7 +257,7 @@ struct link_qual {
int tx_failed; int tx_failed;
}; };
DECLARE_EWMA(rssi, 1024, 8) DECLARE_EWMA(rssi, 10, 8)
/* /*
* Antenna settings about the currently active link. * Antenna settings about the currently active link.
......
#ifndef _LINUX_AVERAGE_H #ifndef _LINUX_AVERAGE_H
#define _LINUX_AVERAGE_H #define _LINUX_AVERAGE_H
/* Exponentially weighted moving average (EWMA) */ /*
* Exponentially weighted moving average (EWMA)
*
* This implements a fixed-precision EWMA algorithm, with both the
* precision and fall-off coefficient determined at compile-time
* and built into the generated helper funtions.
*
* The first argument to the macro is the name that will be used
* for the struct and helper functions.
*
* The second argument, the precision, expresses how many bits are
* used for the fractional part of the fixed-precision values.
*
* The third argument, the weight reciprocal, determines how the
* new values will be weighed vs. the old state, new values will
* get weight 1/weight_rcp and old values 1-1/weight_rcp. Note
* that this parameter must be a power of two for efficiency.
*/
#define DECLARE_EWMA(name, _factor, _weight) \ #define DECLARE_EWMA(name, _precision, _weight_rcp) \
struct ewma_##name { \ struct ewma_##name { \
unsigned long internal; \ unsigned long internal; \
}; \ }; \
static inline void ewma_##name##_init(struct ewma_##name *e) \ static inline void ewma_##name##_init(struct ewma_##name *e) \
{ \ { \
BUILD_BUG_ON(!__builtin_constant_p(_factor)); \ BUILD_BUG_ON(!__builtin_constant_p(_precision)); \
BUILD_BUG_ON(!__builtin_constant_p(_weight)); \ BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \
BUILD_BUG_ON_NOT_POWER_OF_2(_factor); \ /* \
BUILD_BUG_ON_NOT_POWER_OF_2(_weight); \ * Even if you want to feed it just 0/1 you should have \
* some bits for the non-fractional part... \
*/ \
BUILD_BUG_ON((_precision) > 30); \
BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \
e->internal = 0; \ e->internal = 0; \
} \ } \
static inline unsigned long \ static inline unsigned long \
ewma_##name##_read(struct ewma_##name *e) \ ewma_##name##_read(struct ewma_##name *e) \
{ \ { \
BUILD_BUG_ON(!__builtin_constant_p(_factor)); \ BUILD_BUG_ON(!__builtin_constant_p(_precision)); \
BUILD_BUG_ON(!__builtin_constant_p(_weight)); \ BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \
BUILD_BUG_ON_NOT_POWER_OF_2(_factor); \ BUILD_BUG_ON((_precision) > 30); \
BUILD_BUG_ON_NOT_POWER_OF_2(_weight); \ BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \
return e->internal >> ilog2(_factor); \ return e->internal >> (_precision); \
} \ } \
static inline void ewma_##name##_add(struct ewma_##name *e, \ static inline void ewma_##name##_add(struct ewma_##name *e, \
unsigned long val) \ unsigned long val) \
{ \ { \
unsigned long internal = ACCESS_ONCE(e->internal); \ unsigned long internal = ACCESS_ONCE(e->internal); \
unsigned long weight = ilog2(_weight); \ unsigned long weight_rcp = ilog2(_weight_rcp); \
unsigned long factor = ilog2(_factor); \ unsigned long precision = _precision; \
\ \
BUILD_BUG_ON(!__builtin_constant_p(_factor)); \ BUILD_BUG_ON(!__builtin_constant_p(_precision)); \
BUILD_BUG_ON(!__builtin_constant_p(_weight)); \ BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \
BUILD_BUG_ON_NOT_POWER_OF_2(_factor); \ BUILD_BUG_ON((_precision) > 30); \
BUILD_BUG_ON_NOT_POWER_OF_2(_weight); \ BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \
\ \
ACCESS_ONCE(e->internal) = internal ? \ ACCESS_ONCE(e->internal) = internal ? \
(((internal << weight) - internal) + \ (((internal << weight_rcp) - internal) + \
(val << factor)) >> weight : \ (val << precision)) >> weight_rcp : \
(val << factor); \ (val << precision); \
} }
#endif /* _LINUX_AVERAGE_H */ #endif /* _LINUX_AVERAGE_H */
...@@ -402,7 +402,7 @@ struct batadv_gw_node { ...@@ -402,7 +402,7 @@ struct batadv_gw_node {
struct rcu_head rcu; struct rcu_head rcu;
}; };
DECLARE_EWMA(throughput, 1024, 8) DECLARE_EWMA(throughput, 10, 8)
/** /**
* struct batadv_hardif_neigh_node_bat_v - B.A.T.M.A.N. V private neighbor * struct batadv_hardif_neigh_node_bat_v - B.A.T.M.A.N. V private neighbor
......
...@@ -428,7 +428,7 @@ struct ieee80211_sta_tx_tspec { ...@@ -428,7 +428,7 @@ struct ieee80211_sta_tx_tspec {
bool downgraded; bool downgraded;
}; };
DECLARE_EWMA(beacon_signal, 16, 4) DECLARE_EWMA(beacon_signal, 4, 4)
struct ieee80211_if_managed { struct ieee80211_if_managed {
struct timer_list timer; struct timer_list timer;
......
...@@ -372,7 +372,7 @@ struct mesh_sta { ...@@ -372,7 +372,7 @@ struct mesh_sta {
unsigned int fail_avg; unsigned int fail_avg;
}; };
DECLARE_EWMA(signal, 1024, 8) DECLARE_EWMA(signal, 10, 8)
struct ieee80211_sta_rx_stats { struct ieee80211_sta_rx_stats {
unsigned long packets; unsigned long packets;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment