aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/sch_generic.c')
-rw-r--r--net/sched/sch_generic.c44
1 files changed, 20 insertions, 24 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 20224086cc28..4626cef4b76e 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -901,37 +901,33 @@ void dev_shutdown(struct net_device *dev)
901void psched_ratecfg_precompute(struct psched_ratecfg *r, 901void psched_ratecfg_precompute(struct psched_ratecfg *r,
902 const struct tc_ratespec *conf) 902 const struct tc_ratespec *conf)
903{ 903{
904 u64 factor;
905 u64 mult;
906 int shift;
907
908 memset(r, 0, sizeof(*r)); 904 memset(r, 0, sizeof(*r));
909 r->overhead = conf->overhead; 905 r->overhead = conf->overhead;
910 r->rate_bps = (u64)conf->rate << 3; 906 r->rate_bytes_ps = conf->rate;
911 r->mult = 1; 907 r->mult = 1;
912 /* 908 /*
913 * Calibrate mult, shift so that token counting is accurate 909 * The deal here is to replace a divide by a reciprocal one
914 * for smallest packet size (64 bytes). Token (time in ns) is 910 * in fast path (a reciprocal divide is a multiply and a shift)
915 * computed as (bytes * 8) * NSEC_PER_SEC / rate_bps. It will 911 *
916 * work as long as the smallest packet transfer time can be 912 * Normal formula would be :
917 * accurately represented in nanosec. 913 * time_in_ns = (NSEC_PER_SEC * len) / rate_bps
914 *
915 * We compute mult/shift to use instead :
916 * time_in_ns = (len * mult) >> shift;
917 *
918 * We try to get the highest possible mult value for accuracy,
919 * but have to make sure no overflows will ever happen.
918 */ 920 */
919 if (r->rate_bps > 0) { 921 if (r->rate_bytes_ps > 0) {
920 /* 922 u64 factor = NSEC_PER_SEC;
921 * Higher shift gives better accuracy. Find the largest 923
922 * shift such that mult fits in 32 bits. 924 for (;;) {
923 */ 925 r->mult = div64_u64(factor, r->rate_bytes_ps);
924 for (shift = 0; shift < 16; shift++) { 926 if (r->mult & (1U << 31) || factor & (1ULL << 63))
925 r->shift = shift;
926 factor = 8LLU * NSEC_PER_SEC * (1 << r->shift);
927 mult = div64_u64(factor, r->rate_bps);
928 if (mult > UINT_MAX)
929 break; 927 break;
928 factor <<= 1;
929 r->shift++;
930 } 930 }
931
932 r->shift = shift - 1;
933 factor = 8LLU * NSEC_PER_SEC * (1 << r->shift);
934 r->mult = div64_u64(factor, r->rate_bps);
935 } 931 }
936} 932}
937EXPORT_SYMBOL(psched_ratecfg_precompute); 933EXPORT_SYMBOL(psched_ratecfg_precompute);