diff options
Diffstat (limited to 'target/linux/generic/patches-3.3/045-codel-use-u16-field-instead-of-31bits-for-rec_inv_sq.patch')
-rw-r--r-- | target/linux/generic/patches-3.3/045-codel-use-u16-field-instead-of-31bits-for-rec_inv_sq.patch | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/target/linux/generic/patches-3.3/045-codel-use-u16-field-instead-of-31bits-for-rec_inv_sq.patch b/target/linux/generic/patches-3.3/045-codel-use-u16-field-instead-of-31bits-for-rec_inv_sq.patch new file mode 100644 index 0000000000..814aebc61d --- /dev/null +++ b/target/linux/generic/patches-3.3/045-codel-use-u16-field-instead-of-31bits-for-rec_inv_sq.patch @@ -0,0 +1,85 @@ +From 6ff272c9ad65eda219cd975b9da2dbc31cc812ee Mon Sep 17 00:00:00 2001 +From: Eric Dumazet <eric.dumazet@gmail.com> +Date: Sat, 12 May 2012 21:23:23 +0000 +Subject: [PATCH 46/50] codel: use u16 field instead of 31bits for + rec_inv_sqrt + +David pointed out gcc might generate poor code with 31bit fields. + +Using u16 is more than enough and permits a better code output. + +Also make the code intent more readable using constants, fixed point arithmetic +not being trivial for everybody. + +Suggested-by: David Miller <davem@davemloft.net> +Signed-off-by: Eric Dumazet <edumazet@google.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + include/net/codel.h | 25 +++++++++++++++---------- + 1 file changed, 15 insertions(+), 10 deletions(-) + +--- a/include/net/codel.h ++++ b/include/net/codel.h +@@ -133,13 +133,17 @@ struct codel_params { + struct codel_vars { + u32 count; + u32 lastcount; +- bool dropping:1; +- u32 rec_inv_sqrt:31; ++ bool dropping; ++ u16 rec_inv_sqrt; + codel_time_t first_above_time; + codel_time_t drop_next; + codel_time_t ldelay; + }; + ++#define REC_INV_SQRT_BITS (8 * sizeof(u16)) /* or sizeof_in_bits(rec_inv_sqrt) */ ++/* needed shift to get a Q0.32 number from rec_inv_sqrt */ ++#define REC_INV_SQRT_SHIFT (32 - REC_INV_SQRT_BITS) ++ + /** + * struct codel_stats - contains codel shared variables and stats + * @maxpacket: largest packet we've seen so far +@@ -173,17 +177,18 @@ static void codel_stats_init(struct code + * 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) ++ * Here, invsqrt is a fixed point number (< 1.0), 32bit mantissa, aka Q0.32 + */ + static void codel_Newton_step(struct codel_vars *vars) + { +- u32 invsqrt = vars->rec_inv_sqrt; +- u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 31; +- u64 val = (3LL << 31) - ((u64)vars->count * invsqrt2); ++ u32 invsqrt = ((u32)vars->rec_inv_sqrt) << REC_INV_SQRT_SHIFT; ++ u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 32; ++ u64 val = (3LL << 32) - ((u64)vars->count * invsqrt2); + +- val = (val * invsqrt) >> 32; ++ val >>= 2; /* avoid overflow in following multiply */ ++ val = (val * invsqrt) >> (32 - 2 + 1); + +- vars->rec_inv_sqrt = val; ++ vars->rec_inv_sqrt = val >> REC_INV_SQRT_SHIFT; + } + + /* +@@ -195,7 +200,7 @@ static codel_time_t codel_control_law(co + codel_time_t interval, + u32 rec_inv_sqrt) + { +- return t + reciprocal_divide(interval, rec_inv_sqrt << 1); ++ return t + reciprocal_divide(interval, rec_inv_sqrt << REC_INV_SQRT_SHIFT); + } + + +@@ -326,7 +331,7 @@ static struct sk_buff *codel_dequeue(str + codel_Newton_step(vars); + } else { + vars->count = 1; +- vars->rec_inv_sqrt = 0x7fffffff; ++ vars->rec_inv_sqrt = ~0U >> REC_INV_SQRT_SHIFT; + } + vars->lastcount = vars->count; + vars->drop_next = codel_control_law(now, params->interval, |