summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig3
-rw-r--r--lib/Makefile2
-rw-r--r--lib/average.c61
-rw-r--r--lib/nlattr.c22
4 files changed, 77 insertions, 11 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
index fa9bf2c0619..3116aa631af 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -210,4 +210,7 @@ config GENERIC_ATOMIC64
config LRU_CACHE
tristate
+config AVERAGE
+ bool
+
endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 9e2db72d128..d7b6e30a3a1 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -106,6 +106,8 @@ obj-$(CONFIG_GENERIC_ATOMIC64) += atomic64.o
obj-$(CONFIG_ATOMIC64_SELFTEST) += atomic64_test.o
+obj-$(CONFIG_AVERAGE) += average.o
+
hostprogs-y := gen_crc32table
clean-files := crc32table.h
diff --git a/lib/average.c b/lib/average.c
new file mode 100644
index 00000000000..5576c284149
--- /dev/null
+++ b/lib/average.c
@@ -0,0 +1,61 @@
+/*
+ * lib/average.c
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/average.h>
+#include <linux/bug.h>
+#include <linux/log2.h>
+
+/**
+ * DOC: Exponentially Weighted Moving Average (EWMA)
+ *
+ * These are generic functions for calculating Exponentially Weighted Moving
+ * Averages (EWMA). We keep a structure with the EWMA parameters and a scaled
+ * up internal representation of the average value to prevent rounding errors.
+ * The factor for scaling up and the exponential weight (or decay rate) have to
+ * be specified thru the init fuction. The structure should not be accessed
+ * directly but only thru the helper functions.
+ */
+
+/**
+ * ewma_init() - Initialize EWMA parameters
+ * @avg: Average structure
+ * @factor: Factor to use for the scaled up internal value. The maximum value
+ * of averages can be ULONG_MAX/(factor*weight). For performance reasons
+ * factor has to be a power of 2.
+ * @weight: Exponential weight, or decay rate. This defines how fast the
+ * influence of older values decreases. For performance reasons weight has
+ * to be a power of 2.
+ *
+ * Initialize the EWMA parameters for a given struct ewma @avg.
+ */
+void ewma_init(struct ewma *avg, unsigned long factor, unsigned long weight)
+{
+ WARN_ON(!is_power_of_2(weight) || !is_power_of_2(factor));
+
+ avg->weight = ilog2(weight);
+ avg->factor = ilog2(factor);
+ avg->internal = 0;
+}
+EXPORT_SYMBOL(ewma_init);
+
+/**
+ * ewma_add() - Exponentially weighted moving average (EWMA)
+ * @avg: Average structure
+ * @val: Current value
+ *
+ * Add a sample to the average.
+ */
+struct ewma *ewma_add(struct ewma *avg, unsigned long val)
+{
+ avg->internal = avg->internal ?
+ (((avg->internal << avg->weight) - avg->internal) +
+ (val << avg->factor)) >> avg->weight :
+ (val << avg->factor);
+ return avg;
+}
+EXPORT_SYMBOL(ewma_add);
diff --git a/lib/nlattr.c b/lib/nlattr.c
index c4706eb98d3..00e8a02681a 100644
--- a/lib/nlattr.c
+++ b/lib/nlattr.c
@@ -15,7 +15,7 @@
#include <linux/types.h>
#include <net/netlink.h>
-static u16 nla_attr_minlen[NLA_TYPE_MAX+1] __read_mostly = {
+static const u16 nla_attr_minlen[NLA_TYPE_MAX+1] = {
[NLA_U8] = sizeof(u8),
[NLA_U16] = sizeof(u16),
[NLA_U32] = sizeof(u32),
@@ -23,7 +23,7 @@ static u16 nla_attr_minlen[NLA_TYPE_MAX+1] __read_mostly = {
[NLA_NESTED] = NLA_HDRLEN,
};
-static int validate_nla(struct nlattr *nla, int maxtype,
+static int validate_nla(const struct nlattr *nla, int maxtype,
const struct nla_policy *policy)
{
const struct nla_policy *pt;
@@ -115,10 +115,10 @@ static int validate_nla(struct nlattr *nla, int maxtype,
*
* Returns 0 on success or a negative error code.
*/
-int nla_validate(struct nlattr *head, int len, int maxtype,
+int nla_validate(const struct nlattr *head, int len, int maxtype,
const struct nla_policy *policy)
{
- struct nlattr *nla;
+ const struct nlattr *nla;
int rem, err;
nla_for_each_attr(nla, head, len, rem) {
@@ -173,10 +173,10 @@ nla_policy_len(const struct nla_policy *p, int n)
*
* Returns 0 on success or a negative error code.
*/
-int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
- const struct nla_policy *policy)
+int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
+ int len, const struct nla_policy *policy)
{
- struct nlattr *nla;
+ const struct nlattr *nla;
int rem, err;
memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
@@ -191,7 +191,7 @@ int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
goto errout;
}
- tb[type] = nla;
+ tb[type] = (struct nlattr *)nla;
}
}
@@ -212,14 +212,14 @@ errout:
*
* Returns the first attribute in the stream matching the specified type.
*/
-struct nlattr *nla_find(struct nlattr *head, int len, int attrtype)
+struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype)
{
- struct nlattr *nla;
+ const struct nlattr *nla;
int rem;
nla_for_each_attr(nla, head, len, rem)
if (nla_type(nla) == attrtype)
- return nla;
+ return (struct nlattr *)nla;
return NULL;
}