diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-11-11 13:53:50 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-11-11 13:53:50 -0500 |
commit | f21f237cf55494c3a4209de323281a3b0528da10 (patch) | |
tree | 40ebad408aebbc5bf4e54bd51a7c0077ad04508b | |
parent | 2f96cb57cde9957bac0991c712068d29364b2ac9 (diff) | |
parent | 5d5254f0d3b9bebc47d97e357374c0ad0c291a7d (diff) |
Merge branch 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
timers: handle HRTIMER_CB_IRQSAFE_UNLOCKED correctly from softirq context
nohz: disable tick_nohz_kick_tick() for now
irq: call __irq_enter() before calling the tick_idle_check
x86: HPET: enter hpet_interrupt_handler with interrupts disabled
x86: HPET: read from HPET_Tn_CMP() not HPET_T0_CMP
x86: HPET: convert WARN_ON to WARN_ON_ONCE
-rw-r--r-- | arch/x86/kernel/hpet.c | 4 | ||||
-rw-r--r-- | kernel/hrtimer.c | 17 | ||||
-rw-r--r-- | kernel/softirq.c | 7 | ||||
-rw-r--r-- | kernel/time/tick-sched.c | 4 |
4 files changed, 26 insertions, 6 deletions
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 77017e834cf7..067d8de913f6 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c | |||
@@ -322,7 +322,7 @@ static int hpet_next_event(unsigned long delta, | |||
322 | * what we wrote hit the chip before we compare it to the | 322 | * what we wrote hit the chip before we compare it to the |
323 | * counter. | 323 | * counter. |
324 | */ | 324 | */ |
325 | WARN_ON((u32)hpet_readl(HPET_T0_CMP) != cnt); | 325 | WARN_ON_ONCE((u32)hpet_readl(HPET_Tn_CMP(timer)) != cnt); |
326 | 326 | ||
327 | return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0; | 327 | return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0; |
328 | } | 328 | } |
@@ -445,7 +445,7 @@ static int hpet_setup_irq(struct hpet_dev *dev) | |||
445 | { | 445 | { |
446 | 446 | ||
447 | if (request_irq(dev->irq, hpet_interrupt_handler, | 447 | if (request_irq(dev->irq, hpet_interrupt_handler, |
448 | IRQF_SHARED|IRQF_NOBALANCING, dev->name, dev)) | 448 | IRQF_DISABLED|IRQF_NOBALANCING, dev->name, dev)) |
449 | return -1; | 449 | return -1; |
450 | 450 | ||
451 | disable_irq(dev->irq); | 451 | disable_irq(dev->irq); |
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 2b465dfde426..95d3949f2ae5 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -1209,6 +1209,7 @@ static void run_hrtimer_pending(struct hrtimer_cpu_base *cpu_base) | |||
1209 | enum hrtimer_restart (*fn)(struct hrtimer *); | 1209 | enum hrtimer_restart (*fn)(struct hrtimer *); |
1210 | struct hrtimer *timer; | 1210 | struct hrtimer *timer; |
1211 | int restart; | 1211 | int restart; |
1212 | int emulate_hardirq_ctx = 0; | ||
1212 | 1213 | ||
1213 | timer = list_entry(cpu_base->cb_pending.next, | 1214 | timer = list_entry(cpu_base->cb_pending.next, |
1214 | struct hrtimer, cb_entry); | 1215 | struct hrtimer, cb_entry); |
@@ -1217,10 +1218,24 @@ static void run_hrtimer_pending(struct hrtimer_cpu_base *cpu_base) | |||
1217 | timer_stats_account_hrtimer(timer); | 1218 | timer_stats_account_hrtimer(timer); |
1218 | 1219 | ||
1219 | fn = timer->function; | 1220 | fn = timer->function; |
1221 | /* | ||
1222 | * A timer might have been added to the cb_pending list | ||
1223 | * when it was migrated during a cpu-offline operation. | ||
1224 | * Emulate hardirq context for such timers. | ||
1225 | */ | ||
1226 | if (timer->cb_mode == HRTIMER_CB_IRQSAFE_PERCPU || | ||
1227 | timer->cb_mode == HRTIMER_CB_IRQSAFE_UNLOCKED) | ||
1228 | emulate_hardirq_ctx = 1; | ||
1229 | |||
1220 | __remove_hrtimer(timer, timer->base, HRTIMER_STATE_CALLBACK, 0); | 1230 | __remove_hrtimer(timer, timer->base, HRTIMER_STATE_CALLBACK, 0); |
1221 | spin_unlock_irq(&cpu_base->lock); | 1231 | spin_unlock_irq(&cpu_base->lock); |
1222 | 1232 | ||
1223 | restart = fn(timer); | 1233 | if (unlikely(emulate_hardirq_ctx)) { |
1234 | local_irq_disable(); | ||
1235 | restart = fn(timer); | ||
1236 | local_irq_enable(); | ||
1237 | } else | ||
1238 | restart = fn(timer); | ||
1224 | 1239 | ||
1225 | spin_lock_irq(&cpu_base->lock); | 1240 | spin_lock_irq(&cpu_base->lock); |
1226 | 1241 | ||
diff --git a/kernel/softirq.c b/kernel/softirq.c index 7110daeb9a90..e7c69a720d69 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -269,10 +269,11 @@ void irq_enter(void) | |||
269 | { | 269 | { |
270 | int cpu = smp_processor_id(); | 270 | int cpu = smp_processor_id(); |
271 | 271 | ||
272 | if (idle_cpu(cpu) && !in_interrupt()) | 272 | if (idle_cpu(cpu) && !in_interrupt()) { |
273 | __irq_enter(); | ||
273 | tick_check_idle(cpu); | 274 | tick_check_idle(cpu); |
274 | 275 | } else | |
275 | __irq_enter(); | 276 | __irq_enter(); |
276 | } | 277 | } |
277 | 278 | ||
278 | #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED | 279 | #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED |
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 5bbb1044f847..342fc9ccab46 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -568,6 +568,9 @@ static void tick_nohz_switch_to_nohz(void) | |||
568 | */ | 568 | */ |
569 | static void tick_nohz_kick_tick(int cpu) | 569 | static void tick_nohz_kick_tick(int cpu) |
570 | { | 570 | { |
571 | #if 0 | ||
572 | /* Switch back to 2.6.27 behaviour */ | ||
573 | |||
571 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | 574 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); |
572 | ktime_t delta, now; | 575 | ktime_t delta, now; |
573 | 576 | ||
@@ -584,6 +587,7 @@ static void tick_nohz_kick_tick(int cpu) | |||
584 | return; | 587 | return; |
585 | 588 | ||
586 | tick_nohz_restart(ts, now); | 589 | tick_nohz_restart(ts, now); |
590 | #endif | ||
587 | } | 591 | } |
588 | 592 | ||
589 | #else | 593 | #else |