aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-11-11 13:53:50 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-11-11 13:53:50 -0500
commitf21f237cf55494c3a4209de323281a3b0528da10 (patch)
tree40ebad408aebbc5bf4e54bd51a7c0077ad04508b
parent2f96cb57cde9957bac0991c712068d29364b2ac9 (diff)
parent5d5254f0d3b9bebc47d97e357374c0ad0c291a7d (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.c4
-rw-r--r--kernel/hrtimer.c17
-rw-r--r--kernel/softirq.c7
-rw-r--r--kernel/time/tick-sched.c4
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 */
569static void tick_nohz_kick_tick(int cpu) 569static 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