diff options
author | Jon Hunter <jon-hunter@ti.com> | 2009-08-18 13:45:11 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2009-11-13 14:46:24 -0500 |
commit | 97813f2fe77804a4464564c75ba8d8826377feea (patch) | |
tree | 5dc7154c5687edaee5712408c8baf605463ff093 | |
parent | 27185016b806d5a1181ff501cae120582b2b27dd (diff) |
nohz: Allow 32-bit machines to sleep for more than 2.15 seconds
In the dynamic tick code, "max_delta_ns" (member of the
"clock_event_device" structure) represents the maximum sleep time
that can occur between timer events in nanoseconds.
The variable, "max_delta_ns", is defined as an unsigned long
which is a 32-bit integer for 32-bit machines and a 64-bit
integer for 64-bit machines (if -m64 option is used for gcc).
The value of max_delta_ns is set by calling the function
"clockevent_delta2ns()" which returns a maximum value of LONG_MAX.
For a 32-bit machine LONG_MAX is equal to 0x7fffffff and in
nanoseconds this equates to ~2.15 seconds. Hence, the maximum
sleep time for a 32-bit machine is ~2.15 seconds, where as for
a 64-bit machine it will be many years.
This patch changes the type of max_delta_ns to be "u64" instead of
"unsigned long" so that this variable is a 64-bit type for both 32-bit
and 64-bit machines. It also changes the maximum value returned by
clockevent_delta2ns() to KTIME_MAX. Hence this allows a 32-bit
machine to sleep for longer than ~2.15 seconds. Please note that this
patch also changes "min_delta_ns" to be "u64" too and although this is
unnecessary, it makes the patch simpler as it avoids to fixup all
callers of clockevent_delta2ns().
[ tglx: changed "unsigned long long" to u64 as we use this data type
through out the time code ]
Signed-off-by: Jon Hunter <jon-hunter@ti.com>
Cc: John Stultz <johnstul@us.ibm.com>
LKML-Reference: <1250617512-23567-3-git-send-email-jon-hunter@ti.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | include/linux/clockchips.h | 8 | ||||
-rw-r--r-- | kernel/hrtimer.c | 3 | ||||
-rw-r--r-- | kernel/time/clockevents.c | 11 | ||||
-rw-r--r-- | kernel/time/tick-oneshot.c | 4 | ||||
-rw-r--r-- | kernel/time/timer_list.c | 6 |
5 files changed, 17 insertions, 15 deletions
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index 4d438b0bc10a..0cf725bdd2a1 100644 --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h | |||
@@ -77,8 +77,8 @@ enum clock_event_nofitiers { | |||
77 | struct clock_event_device { | 77 | struct clock_event_device { |
78 | const char *name; | 78 | const char *name; |
79 | unsigned int features; | 79 | unsigned int features; |
80 | unsigned long max_delta_ns; | 80 | u64 max_delta_ns; |
81 | unsigned long min_delta_ns; | 81 | u64 min_delta_ns; |
82 | u32 mult; | 82 | u32 mult; |
83 | u32 shift; | 83 | u32 shift; |
84 | int rating; | 84 | int rating; |
@@ -116,8 +116,8 @@ static inline unsigned long div_sc(unsigned long ticks, unsigned long nsec, | |||
116 | } | 116 | } |
117 | 117 | ||
118 | /* Clock event layer functions */ | 118 | /* Clock event layer functions */ |
119 | extern unsigned long clockevent_delta2ns(unsigned long latch, | 119 | extern u64 clockevent_delta2ns(unsigned long latch, |
120 | struct clock_event_device *evt); | 120 | struct clock_event_device *evt); |
121 | extern void clockevents_register_device(struct clock_event_device *dev); | 121 | extern void clockevents_register_device(struct clock_event_device *dev); |
122 | 122 | ||
123 | extern void clockevents_exchange_device(struct clock_event_device *old, | 123 | extern void clockevents_exchange_device(struct clock_event_device *old, |
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 6d7020490f94..c215b74cd953 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -1240,7 +1240,8 @@ hrtimer_interrupt_hanging(struct clock_event_device *dev, | |||
1240 | force_clock_reprogram = 1; | 1240 | force_clock_reprogram = 1; |
1241 | dev->min_delta_ns = (unsigned long)try_time.tv64 * 3; | 1241 | dev->min_delta_ns = (unsigned long)try_time.tv64 * 3; |
1242 | printk(KERN_WARNING "hrtimer: interrupt too slow, " | 1242 | printk(KERN_WARNING "hrtimer: interrupt too slow, " |
1243 | "forcing clock min delta to %lu ns\n", dev->min_delta_ns); | 1243 | "forcing clock min delta to %llu ns\n", |
1244 | (unsigned long long) dev->min_delta_ns); | ||
1244 | } | 1245 | } |
1245 | /* | 1246 | /* |
1246 | * High resolution timer interrupt | 1247 | * High resolution timer interrupt |
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 620b58abdc32..05e8aeedcdf3 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c | |||
@@ -37,10 +37,9 @@ static DEFINE_SPINLOCK(clockevents_lock); | |||
37 | * | 37 | * |
38 | * Math helper, returns latch value converted to nanoseconds (bound checked) | 38 | * Math helper, returns latch value converted to nanoseconds (bound checked) |
39 | */ | 39 | */ |
40 | unsigned long clockevent_delta2ns(unsigned long latch, | 40 | u64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt) |
41 | struct clock_event_device *evt) | ||
42 | { | 41 | { |
43 | u64 clc = ((u64) latch << evt->shift); | 42 | u64 clc = (u64) latch << evt->shift; |
44 | 43 | ||
45 | if (unlikely(!evt->mult)) { | 44 | if (unlikely(!evt->mult)) { |
46 | evt->mult = 1; | 45 | evt->mult = 1; |
@@ -50,10 +49,10 @@ unsigned long clockevent_delta2ns(unsigned long latch, | |||
50 | do_div(clc, evt->mult); | 49 | do_div(clc, evt->mult); |
51 | if (clc < 1000) | 50 | if (clc < 1000) |
52 | clc = 1000; | 51 | clc = 1000; |
53 | if (clc > LONG_MAX) | 52 | if (clc > KTIME_MAX) |
54 | clc = LONG_MAX; | 53 | clc = KTIME_MAX; |
55 | 54 | ||
56 | return (unsigned long) clc; | 55 | return clc; |
57 | } | 56 | } |
58 | EXPORT_SYMBOL_GPL(clockevent_delta2ns); | 57 | EXPORT_SYMBOL_GPL(clockevent_delta2ns); |
59 | 58 | ||
diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c index a96c0e2b89cf..0a8a213016f0 100644 --- a/kernel/time/tick-oneshot.c +++ b/kernel/time/tick-oneshot.c | |||
@@ -50,9 +50,9 @@ int tick_dev_program_event(struct clock_event_device *dev, ktime_t expires, | |||
50 | dev->min_delta_ns += dev->min_delta_ns >> 1; | 50 | dev->min_delta_ns += dev->min_delta_ns >> 1; |
51 | 51 | ||
52 | printk(KERN_WARNING | 52 | printk(KERN_WARNING |
53 | "CE: %s increasing min_delta_ns to %lu nsec\n", | 53 | "CE: %s increasing min_delta_ns to %llu nsec\n", |
54 | dev->name ? dev->name : "?", | 54 | dev->name ? dev->name : "?", |
55 | dev->min_delta_ns << 1); | 55 | (unsigned long long) dev->min_delta_ns << 1); |
56 | 56 | ||
57 | i = 0; | 57 | i = 0; |
58 | } | 58 | } |
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c index fa00da108a14..665c76edbf17 100644 --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c | |||
@@ -204,8 +204,10 @@ print_tickdevice(struct seq_file *m, struct tick_device *td, int cpu) | |||
204 | return; | 204 | return; |
205 | } | 205 | } |
206 | SEQ_printf(m, "%s\n", dev->name); | 206 | SEQ_printf(m, "%s\n", dev->name); |
207 | SEQ_printf(m, " max_delta_ns: %lu\n", dev->max_delta_ns); | 207 | SEQ_printf(m, " max_delta_ns: %llu\n", |
208 | SEQ_printf(m, " min_delta_ns: %lu\n", dev->min_delta_ns); | 208 | (unsigned long long) dev->max_delta_ns); |
209 | SEQ_printf(m, " min_delta_ns: %llu\n", | ||
210 | (unsigned long long) dev->min_delta_ns); | ||
209 | SEQ_printf(m, " mult: %u\n", dev->mult); | 211 | SEQ_printf(m, " mult: %u\n", dev->mult); |
210 | SEQ_printf(m, " shift: %u\n", dev->shift); | 212 | SEQ_printf(m, " shift: %u\n", dev->shift); |
211 | SEQ_printf(m, " mode: %d\n", dev->mode); | 213 | SEQ_printf(m, " mode: %d\n", dev->mode); |