diff options
Diffstat (limited to 'target/linux/generic/patches-3.3/041-codel-use-Newton-method-instead-of-sqrt-and-divides.patch')
-rw-r--r-- | target/linux/generic/patches-3.3/041-codel-use-Newton-method-instead-of-sqrt-and-divides.patch | 185 |
1 files changed, 0 insertions, 185 deletions
diff --git a/target/linux/generic/patches-3.3/041-codel-use-Newton-method-instead-of-sqrt-and-divides.patch b/target/linux/generic/patches-3.3/041-codel-use-Newton-method-instead-of-sqrt-and-divides.patch deleted file mode 100644 index f91b42e..0000000 --- a/target/linux/generic/patches-3.3/041-codel-use-Newton-method-instead-of-sqrt-and-divides.patch +++ /dev/null @@ -1,185 +0,0 @@ -From 4a8056dfeef49b306ad6af24a5563d7d6867aae0 Mon Sep 17 00:00:00 2001 -From: Eric Dumazet <edumazet@google.com> -Date: Sat, 12 May 2012 03:32:13 +0000 -Subject: [PATCH] codel: use Newton method instead of sqrt() and divides - -commit 536edd67109df5e0cdb2c4ee759e9bade7976367 upstream. - -As Van pointed out, interval/sqrt(count) can be implemented using -multiplies only. - -http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots - -This patch implements the Newton method and reciprocal divide. - -Total cost is 15 cycles instead of 120 on my Corei5 machine (64bit -kernel). - -There is a small 'error' for count values < 5, but we don't really care. - -I reuse a hole in struct codel_vars : - - pack the dropping boolean into one bit - - use 31bit to store the reciprocal value of sqrt(count). - -Suggested-by: Van Jacobson <van@pollere.net> -Signed-off-by: Eric Dumazet <edumazet@google.com> -Cc: Dave Taht <dave.taht@bufferbloat.net> -Cc: Kathleen Nichols <nichols@pollere.com> -Cc: Tom Herbert <therbert@google.com> -Cc: Matt Mathis <mattmathis@google.com> -Cc: Yuchung Cheng <ycheng@google.com> -Cc: Nandita Dukkipati <nanditad@google.com> -Cc: Stephen Hemminger <shemminger@vyatta.com> -Signed-off-by: David S. Miller <davem@davemloft.net> ---- - include/net/codel.h | 68 ++++++++++++++++++++++++++++----------------------- - 1 file changed, 37 insertions(+), 31 deletions(-) - ---- a/include/net/codel.h -+++ b/include/net/codel.h -@@ -46,6 +46,7 @@ - #include <linux/skbuff.h> - #include <net/pkt_sched.h> - #include <net/inet_ecn.h> -+#include <linux/reciprocal_div.h> - - /* Controlling Queue Delay (CoDel) algorithm - * ========================================= -@@ -123,6 +124,7 @@ struct codel_params { - * entered dropping state - * @lastcount: count at entry to dropping state - * @dropping: set to true if in dropping state -+ * @rec_inv_sqrt: reciprocal value of sqrt(count) >> 1 - * @first_above_time: when we went (or will go) continuously above target - * for interval - * @drop_next: time to drop next packet, or when we dropped last -@@ -131,7 +133,8 @@ struct codel_params { - struct codel_vars { - u32 count; - u32 lastcount; -- bool dropping; -+ bool dropping:1; -+ u32 rec_inv_sqrt:31; - codel_time_t first_above_time; - codel_time_t drop_next; - codel_time_t ldelay; -@@ -158,11 +161,7 @@ static void codel_params_init(struct cod - - static void codel_vars_init(struct codel_vars *vars) - { -- vars->drop_next = 0; -- vars->first_above_time = 0; -- vars->dropping = false; /* exit dropping state */ -- vars->count = 0; -- vars->lastcount = 0; -+ memset(vars, 0, sizeof(*vars)); - } - - static void codel_stats_init(struct codel_stats *stats) -@@ -170,38 +169,37 @@ static void codel_stats_init(struct code - stats->maxpacket = 256; - } - --/* return interval/sqrt(x) with good precision -- * relies on int_sqrt(unsigned long x) kernel implementation -+/* -+ * http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots -+ * new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2) -+ * -+ * Here, invsqrt is a fixed point number (< 1.0), 31bit mantissa) - */ --static u32 codel_inv_sqrt(u32 _interval, u32 _x) -+static void codel_Newton_step(struct codel_vars *vars) - { -- u64 interval = _interval; -- unsigned long x = _x; -- -- /* Scale operands for max precision */ -+ u32 invsqrt = vars->rec_inv_sqrt; -+ u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 31; -+ u64 val = (3LL << 31) - ((u64)vars->count * invsqrt2); - --#if BITS_PER_LONG == 64 -- x <<= 32; /* On 64bit arches, we can prescale x by 32bits */ -- interval <<= 16; --#endif -+ val = (val * invsqrt) >> 32; - -- while (x < (1UL << (BITS_PER_LONG - 2))) { -- x <<= 2; -- interval <<= 1; -- } -- do_div(interval, int_sqrt(x)); -- return (u32)interval; -+ vars->rec_inv_sqrt = val; - } - -+/* -+ * CoDel control_law is t + interval/sqrt(count) -+ * We maintain in rec_inv_sqrt the reciprocal value of sqrt(count) to avoid -+ * both sqrt() and divide operation. -+ */ - static codel_time_t codel_control_law(codel_time_t t, - codel_time_t interval, -- u32 count) -+ u32 rec_inv_sqrt) - { -- return t + codel_inv_sqrt(interval, count); -+ return t + reciprocal_divide(interval, rec_inv_sqrt << 1); - } - - --static bool codel_should_drop(struct sk_buff *skb, -+static bool codel_should_drop(const struct sk_buff *skb, - unsigned int *backlog, - struct codel_vars *vars, - struct codel_params *params, -@@ -274,14 +272,16 @@ static struct sk_buff *codel_dequeue(str - */ - while (vars->dropping && - codel_time_after_eq(now, vars->drop_next)) { -- if (++vars->count == 0) /* avoid zero divides */ -- vars->count = ~0U; -+ vars->count++; /* dont care of possible wrap -+ * since there is no more divide -+ */ -+ codel_Newton_step(vars); - if (params->ecn && INET_ECN_set_ce(skb)) { - stats->ecn_mark++; - vars->drop_next = - codel_control_law(vars->drop_next, - params->interval, -- vars->count); -+ vars->rec_inv_sqrt); - goto end; - } - qdisc_drop(skb, sch); -@@ -296,7 +296,7 @@ static struct sk_buff *codel_dequeue(str - vars->drop_next = - codel_control_law(vars->drop_next, - params->interval, -- vars->count); -+ vars->rec_inv_sqrt); - } - } - } -@@ -319,12 +319,18 @@ static struct sk_buff *codel_dequeue(str - if (codel_time_before(now - vars->drop_next, - 16 * params->interval)) { - vars->count = (vars->count - vars->lastcount) | 1; -+ /* we dont care if rec_inv_sqrt approximation -+ * is not very precise : -+ * Next Newton steps will correct it quadratically. -+ */ -+ codel_Newton_step(vars); - } else { - vars->count = 1; -+ vars->rec_inv_sqrt = 0x7fffffff; - } - vars->lastcount = vars->count; - vars->drop_next = codel_control_law(now, params->interval, -- vars->count); -+ vars->rec_inv_sqrt); - } - end: - return skb; |