Commit 9fc48326 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[PKT_SCHED]: Make clock source configurable

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@redhat.com>
parent 7862e912
#ifndef __NET_PKT_SCHED_H #ifndef __NET_PKT_SCHED_H
#define __NET_PKT_SCHED_H #define __NET_PKT_SCHED_H
#define PSCHED_GETTIMEOFDAY 1
#define PSCHED_JIFFIES 2
#define PSCHED_CPU 3
#define PSCHED_CLOCK_SOURCE PSCHED_JIFFIES
#include <linux/config.h> #include <linux/config.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -179,25 +173,19 @@ __cls_set_class(unsigned long *clp, unsigned long cl) ...@@ -179,25 +173,19 @@ __cls_set_class(unsigned long *clp, unsigned long cl)
The reason is that, when it is not the same thing as The reason is that, when it is not the same thing as
gettimeofday, it returns invalid timestamp, which is gettimeofday, it returns invalid timestamp, which is
not updated, when net_bh is active. not updated, when net_bh is active.
So, use PSCHED_CLOCK_SOURCE = PSCHED_CPU on alpha and pentiums
with rtdsc. And PSCHED_JIFFIES on all other architectures, including [34]86
and pentiums without rtdsc.
You can use PSCHED_GETTIMEOFDAY on another architectures,
which have fast and precise clock source, but it is too expensive.
*/ */
/* General note about internal clock. /* General note about internal clock.
Any clock source returns time intervals, measured in units Any clock source returns time intervals, measured in units
close to 1usec. With source PSCHED_GETTIMEOFDAY it is precisely close to 1usec. With source CONFIG_NET_SCH_CLK_GETTIMEOFDAY it is precisely
microseconds, otherwise something close but different chosen to minimize microseconds, otherwise something close but different chosen to minimize
arithmetic cost. Ratio usec/internal untis in form nominator/denominator arithmetic cost. Ratio usec/internal untis in form nominator/denominator
may be read from /proc/net/psched. may be read from /proc/net/psched.
*/ */
#if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY #ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY
typedef struct timeval psched_time_t; typedef struct timeval psched_time_t;
typedef long psched_tdiff_t; typedef long psched_tdiff_t;
...@@ -206,12 +194,12 @@ typedef long psched_tdiff_t; ...@@ -206,12 +194,12 @@ typedef long psched_tdiff_t;
#define PSCHED_US2JIFFIE(usecs) (((usecs)+(1000000/HZ-1))/(1000000/HZ)) #define PSCHED_US2JIFFIE(usecs) (((usecs)+(1000000/HZ-1))/(1000000/HZ))
#define PSCHED_JIFFIE2US(delay) ((delay)*(1000000/HZ)) #define PSCHED_JIFFIE2US(delay) ((delay)*(1000000/HZ))
#else /* PSCHED_CLOCK_SOURCE != PSCHED_GETTIMEOFDAY */ #else /* !CONFIG_NET_SCH_CLK_GETTIMEOFDAY */
typedef u64 psched_time_t; typedef u64 psched_time_t;
typedef long psched_tdiff_t; typedef long psched_tdiff_t;
#if PSCHED_CLOCK_SOURCE == PSCHED_JIFFIES #ifdef CONFIG_NET_SCH_CLK_JIFFIES
#if HZ < 96 #if HZ < 96
#define PSCHED_JSCALE 14 #define PSCHED_JSCALE 14
...@@ -229,7 +217,8 @@ typedef long psched_tdiff_t; ...@@ -229,7 +217,8 @@ typedef long psched_tdiff_t;
#define PSCHED_US2JIFFIE(delay) (((delay)+(1<<PSCHED_JSCALE)-1)>>PSCHED_JSCALE) #define PSCHED_US2JIFFIE(delay) (((delay)+(1<<PSCHED_JSCALE)-1)>>PSCHED_JSCALE)
#define PSCHED_JIFFIE2US(delay) ((delay)<<PSCHED_JSCALE) #define PSCHED_JIFFIE2US(delay) ((delay)<<PSCHED_JSCALE)
#elif PSCHED_CLOCK_SOURCE == PSCHED_CPU #endif /* CONFIG_NET_SCH_CLK_JIFFIES */
#ifdef CONFIG_NET_SCH_CLK_CPU
#include <asm/timex.h> #include <asm/timex.h>
extern psched_tdiff_t psched_clock_per_hz; extern psched_tdiff_t psched_clock_per_hz;
...@@ -252,11 +241,11 @@ do { \ ...@@ -252,11 +241,11 @@ do { \
#define PSCHED_US2JIFFIE(delay) (((delay)+psched_clock_per_hz-1)/psched_clock_per_hz) #define PSCHED_US2JIFFIE(delay) (((delay)+psched_clock_per_hz-1)/psched_clock_per_hz)
#define PSCHED_JIFFIE2US(delay) ((delay)*psched_clock_per_hz) #define PSCHED_JIFFIE2US(delay) ((delay)*psched_clock_per_hz)
#endif /* PSCHED_CLOCK_SOURCE == PSCHED_JIFFIES */ #endif /* CONFIG_NET_SCH_CLK_CPU */
#endif /* PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY */ #endif /* !CONFIG_NET_SCH_CLK_GETTIMEOFDAY */
#if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY #ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY
#define PSCHED_TDIFF(tv1, tv2) \ #define PSCHED_TDIFF(tv1, tv2) \
({ \ ({ \
int __delta_sec = (tv1).tv_sec - (tv2).tv_sec; \ int __delta_sec = (tv1).tv_sec - (tv2).tv_sec; \
...@@ -320,7 +309,7 @@ extern int psched_tod_diff(int delta_sec, int bound); ...@@ -320,7 +309,7 @@ extern int psched_tod_diff(int delta_sec, int bound);
#define PSCHED_AUDIT_TDIFF(t) ({ if ((t) > 2000000) (t) = 2000000; }) #define PSCHED_AUDIT_TDIFF(t) ({ if ((t) > 2000000) (t) = 2000000; })
#else #else /* !CONFIG_NET_SCH_CLK_GETTIMEOFDAY */
#define PSCHED_TDIFF(tv1, tv2) (long)((tv1) - (tv2)) #define PSCHED_TDIFF(tv1, tv2) (long)((tv1) - (tv2))
#define PSCHED_TDIFF_SAFE(tv1, tv2, bound) \ #define PSCHED_TDIFF_SAFE(tv1, tv2, bound) \
...@@ -334,7 +323,7 @@ extern int psched_tod_diff(int delta_sec, int bound); ...@@ -334,7 +323,7 @@ extern int psched_tod_diff(int delta_sec, int bound);
#define PSCHED_IS_PASTPERFECT(t) ((t) == 0) #define PSCHED_IS_PASTPERFECT(t) ((t) == 0)
#define PSCHED_AUDIT_TDIFF(t) #define PSCHED_AUDIT_TDIFF(t)
#endif #endif /* !CONFIG_NET_SCH_CLK_GETTIMEOFDAY */
struct tcf_police struct tcf_police
{ {
......
# #
# Traffic control configuration. # Traffic control configuration.
# #
choice
prompt "Packet scheduler clock source"
depends on NET_SCHED
default NET_SCH_CLK_JIFFIES
help
Packet schedulers need a monotonic clock that increments at a static
rate. The kernel provides several suitable interfaces, each with
different properties:
- high resolution (us or better)
- fast to read (minimal locking, no i/o access)
- synchronized on all processors
- handles cpu clock frequency changes
but nothing provides all of the above.
config NET_SCH_CLK_JIFFIES
bool "Timer interrupt"
help
Say Y here if you want to use the timer interrupt (jiffies) as clock
source. This clock source is fast, synchronized on all processors and
handles cpu clock frequency changes, but its resolution is too low
for accurate shaping except at very low speed.
config NET_SCH_CLK_GETTIMEOFDAY
bool "gettimeofday"
help
Say Y here if you want to use gettimeofday as clock source. This clock
source has high resolution, is synchronized on all processors and
handles cpu clock frequency changes, but it is slow.
Choose this if you need a high resolution clock source but can't use
the CPU's cycle counter.
config NET_SCH_CLK_CPU
bool "CPU cycle counter"
depends on X86_TSC || X86_64 || ALPHA || SPARC64 || PPC64 || IA64
help
Say Y here if you want to use the CPU's cycle counter as clock source.
This is a cheap and high resolution clock source, but on some
architectures it is not synchronized on all processors and doesn't
handle cpu clock frequency changes.
The useable cycle counters are:
x86/x86_64 - Timestamp Counter
alpha - Cycle Counter
sparc64 - %ticks register
ppc64 - Time base
ia64 - Interval Time Counter
Choose this if your CPU's cycle counter is working properly.
endchoice
config NET_SCH_CBQ config NET_SCH_CBQ
tristate "CBQ packet scheduler" tristate "CBQ packet scheduler"
depends on NET_SCHED depends on NET_SCHED
......
...@@ -1088,7 +1088,7 @@ static struct file_operations psched_fops = { ...@@ -1088,7 +1088,7 @@ static struct file_operations psched_fops = {
}; };
#endif #endif
#if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY #ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY
int psched_tod_diff(int delta_sec, int bound) int psched_tod_diff(int delta_sec, int bound)
{ {
int delta; int delta;
...@@ -1103,7 +1103,7 @@ int psched_tod_diff(int delta_sec, int bound) ...@@ -1103,7 +1103,7 @@ int psched_tod_diff(int delta_sec, int bound)
EXPORT_SYMBOL(psched_tod_diff); EXPORT_SYMBOL(psched_tod_diff);
#endif #endif
#if PSCHED_CLOCK_SOURCE == PSCHED_CPU #ifdef CONFIG_NET_SCH_CLK_CPU
psched_tdiff_t psched_clock_per_hz; psched_tdiff_t psched_clock_per_hz;
int psched_clock_scale; int psched_clock_scale;
EXPORT_SYMBOL(psched_clock_per_hz); EXPORT_SYMBOL(psched_clock_per_hz);
...@@ -1169,10 +1169,10 @@ static int __init pktsched_init(void) ...@@ -1169,10 +1169,10 @@ static int __init pktsched_init(void)
{ {
struct rtnetlink_link *link_p; struct rtnetlink_link *link_p;
#if PSCHED_CLOCK_SOURCE == PSCHED_CPU #ifdef CONFIG_NET_SCH_CLK_CPU
if (psched_calibrate_clock() < 0) if (psched_calibrate_clock() < 0)
return -1; return -1;
#elif PSCHED_CLOCK_SOURCE == PSCHED_JIFFIES #elif defined(CONFIG_NET_SCH_CLK_JIFFIES)
psched_tick_per_us = HZ<<PSCHED_JSCALE; psched_tick_per_us = HZ<<PSCHED_JSCALE;
psched_us_per_tick = 1000000; psched_us_per_tick = 1000000;
#endif #endif
......
...@@ -193,7 +193,7 @@ struct hfsc_sched ...@@ -193,7 +193,7 @@ struct hfsc_sched
/* /*
* macros * macros
*/ */
#if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY #ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY
#include <linux/time.h> #include <linux/time.h>
#undef PSCHED_GET_TIME #undef PSCHED_GET_TIME
#define PSCHED_GET_TIME(stamp) \ #define PSCHED_GET_TIME(stamp) \
...@@ -429,10 +429,10 @@ actlist_get_minvt(struct hfsc_class *cl, u64 cur_time) ...@@ -429,10 +429,10 @@ actlist_get_minvt(struct hfsc_class *cl, u64 cur_time)
* ism: (psched_us/byte) << ISM_SHIFT * ism: (psched_us/byte) << ISM_SHIFT
* dx: psched_us * dx: psched_us
* *
* Time source resolution * Clock source resolution (CONFIG_NET_SCH_CLK_*)
* PSCHED_JIFFIES: for 48<=HZ<=1534 resolution is between 0.63us and 1.27us. * JIFFIES: for 48<=HZ<=1534 resolution is between 0.63us and 1.27us.
* PSCHED_CPU: resolution is between 0.5us and 1us. * CPU: resolution is between 0.5us and 1us.
* PSCHED_GETTIMEOFDAY: resolution is exactly 1us. * GETTIMEOFDAY: resolution is exactly 1us.
* *
* sm and ism are scaled in order to keep effective digits. * sm and ism are scaled in order to keep effective digits.
* SM_SHIFT and ISM_SHIFT are selected to keep at least 4 effective * SM_SHIFT and ISM_SHIFT are selected to keep at least 4 effective
......
...@@ -856,8 +856,13 @@ static void htb_charge_class(struct htb_sched *q,struct htb_class *cl, ...@@ -856,8 +856,13 @@ static void htb_charge_class(struct htb_sched *q,struct htb_class *cl,
if (net_ratelimit()) if (net_ratelimit())
printk(KERN_ERR "HTB: bad diff in charge, cl=%X diff=%lX now=%Lu then=%Lu j=%lu\n", printk(KERN_ERR "HTB: bad diff in charge, cl=%X diff=%lX now=%Lu then=%Lu j=%lu\n",
cl->classid, diff, cl->classid, diff,
#ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY
q->now.tv_sec * 1000000ULL + q->now.tv_usec,
cl->t_c.tv_sec * 1000000ULL + cl->t_c.tv_usec,
#else
(unsigned long long) q->now, (unsigned long long) q->now,
(unsigned long long) cl->t_c, (unsigned long long) cl->t_c,
#endif
q->jiffies); q->jiffies);
diff = 1000; diff = 1000;
} }
...@@ -927,8 +932,13 @@ static long htb_do_events(struct htb_sched *q,int level) ...@@ -927,8 +932,13 @@ static long htb_do_events(struct htb_sched *q,int level)
if (net_ratelimit()) if (net_ratelimit())
printk(KERN_ERR "HTB: bad diff in events, cl=%X diff=%lX now=%Lu then=%Lu j=%lu\n", printk(KERN_ERR "HTB: bad diff in events, cl=%X diff=%lX now=%Lu then=%Lu j=%lu\n",
cl->classid, diff, cl->classid, diff,
#ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY
q->now.tv_sec * 1000000ULL + q->now.tv_usec,
cl->t_c.tv_sec * 1000000ULL + cl->t_c.tv_usec,
#else
(unsigned long long) q->now, (unsigned long long) q->now,
(unsigned long long) cl->t_c, (unsigned long long) cl->t_c,
#endif
q->jiffies); q->jiffies);
diff = 1000; diff = 1000;
} }
......
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