diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-07-01 18:44:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-07-01 18:44:18 -0400 |
commit | 6ac15baacb6ecd87c66209627753b96ded3b4515 (patch) | |
tree | a2f2b1b1f23a9d37fdfd3bb52e65c0ba7f0f74d0 | |
parent | d5fb82137b6cd39e67c4321f4f5ce9b03d4d04e6 (diff) | |
parent | 65f26062cd8f653dac11d3c00d326f7f57b5e098 (diff) |
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer fixes from Thomas Gleixner:
"This contains:
- a build regression fix introduced by the timeconst move
- a hotplug regression fix introduced by the timer wheel diet
- a cpu hotplug bug fix for the exynos clocksource driver"
* 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
time: Remove development rules from Kbuild/Makefile
timer: Fix hotplug regression
clocksource: exynos_mct: Avoid blocking calls in the cpu hotplug notifier
-rw-r--r-- | Kbuild | 1 | ||||
-rw-r--r-- | drivers/clocksource/exynos_mct.c | 43 | ||||
-rw-r--r-- | kernel/time/Makefile | 2 | ||||
-rw-r--r-- | kernel/time/timer.c | 3 |
4 files changed, 32 insertions, 17 deletions
@@ -52,7 +52,6 @@ $(obj)/$(bounds-file): kernel/bounds.s FORCE | |||
52 | 52 | ||
53 | timeconst-file := include/generated/timeconst.h | 53 | timeconst-file := include/generated/timeconst.h |
54 | 54 | ||
55 | #always += $(timeconst-file) | ||
56 | targets += $(timeconst-file) | 55 | targets += $(timeconst-file) |
57 | 56 | ||
58 | quiet_cmd_gentimeconst = GEN $@ | 57 | quiet_cmd_gentimeconst = GEN $@ |
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index 935b05936dbd..9064ff743598 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c | |||
@@ -462,15 +462,12 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) | |||
462 | exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET); | 462 | exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET); |
463 | 463 | ||
464 | if (mct_int_type == MCT_INT_SPI) { | 464 | if (mct_int_type == MCT_INT_SPI) { |
465 | evt->irq = mct_irqs[MCT_L0_IRQ + cpu]; | 465 | |
466 | if (request_irq(evt->irq, exynos4_mct_tick_isr, | 466 | if (evt->irq == -1) |
467 | IRQF_TIMER | IRQF_NOBALANCING, | ||
468 | evt->name, mevt)) { | ||
469 | pr_err("exynos-mct: cannot register IRQ %d\n", | ||
470 | evt->irq); | ||
471 | return -EIO; | 467 | return -EIO; |
472 | } | 468 | |
473 | irq_force_affinity(mct_irqs[MCT_L0_IRQ + cpu], cpumask_of(cpu)); | 469 | irq_force_affinity(evt->irq, cpumask_of(cpu)); |
470 | enable_irq(evt->irq); | ||
474 | } else { | 471 | } else { |
475 | enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0); | 472 | enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0); |
476 | } | 473 | } |
@@ -483,10 +480,12 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) | |||
483 | static void exynos4_local_timer_stop(struct clock_event_device *evt) | 480 | static void exynos4_local_timer_stop(struct clock_event_device *evt) |
484 | { | 481 | { |
485 | evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); | 482 | evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); |
486 | if (mct_int_type == MCT_INT_SPI) | 483 | if (mct_int_type == MCT_INT_SPI) { |
487 | free_irq(evt->irq, this_cpu_ptr(&percpu_mct_tick)); | 484 | if (evt->irq != -1) |
488 | else | 485 | disable_irq_nosync(evt->irq); |
486 | } else { | ||
489 | disable_percpu_irq(mct_irqs[MCT_L0_IRQ]); | 487 | disable_percpu_irq(mct_irqs[MCT_L0_IRQ]); |
488 | } | ||
490 | } | 489 | } |
491 | 490 | ||
492 | static int exynos4_mct_cpu_notify(struct notifier_block *self, | 491 | static int exynos4_mct_cpu_notify(struct notifier_block *self, |
@@ -518,7 +517,7 @@ static struct notifier_block exynos4_mct_cpu_nb = { | |||
518 | 517 | ||
519 | static void __init exynos4_timer_resources(struct device_node *np, void __iomem *base) | 518 | static void __init exynos4_timer_resources(struct device_node *np, void __iomem *base) |
520 | { | 519 | { |
521 | int err; | 520 | int err, cpu; |
522 | struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); | 521 | struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); |
523 | struct clk *mct_clk, *tick_clk; | 522 | struct clk *mct_clk, *tick_clk; |
524 | 523 | ||
@@ -545,7 +544,25 @@ static void __init exynos4_timer_resources(struct device_node *np, void __iomem | |||
545 | WARN(err, "MCT: can't request IRQ %d (%d)\n", | 544 | WARN(err, "MCT: can't request IRQ %d (%d)\n", |
546 | mct_irqs[MCT_L0_IRQ], err); | 545 | mct_irqs[MCT_L0_IRQ], err); |
547 | } else { | 546 | } else { |
548 | irq_set_affinity(mct_irqs[MCT_L0_IRQ], cpumask_of(0)); | 547 | for_each_possible_cpu(cpu) { |
548 | int mct_irq = mct_irqs[MCT_L0_IRQ + cpu]; | ||
549 | struct mct_clock_event_device *pcpu_mevt = | ||
550 | per_cpu_ptr(&percpu_mct_tick, cpu); | ||
551 | |||
552 | pcpu_mevt->evt.irq = -1; | ||
553 | |||
554 | irq_set_status_flags(mct_irq, IRQ_NOAUTOEN); | ||
555 | if (request_irq(mct_irq, | ||
556 | exynos4_mct_tick_isr, | ||
557 | IRQF_TIMER | IRQF_NOBALANCING, | ||
558 | pcpu_mevt->name, pcpu_mevt)) { | ||
559 | pr_err("exynos-mct: cannot register IRQ (cpu%d)\n", | ||
560 | cpu); | ||
561 | |||
562 | continue; | ||
563 | } | ||
564 | pcpu_mevt->evt.irq = mct_irq; | ||
565 | } | ||
549 | } | 566 | } |
550 | 567 | ||
551 | err = register_cpu_notifier(&exynos4_mct_cpu_nb); | 568 | err = register_cpu_notifier(&exynos4_mct_cpu_nb); |
diff --git a/kernel/time/Makefile b/kernel/time/Makefile index ffc4cc3dcd47..49eca0beed32 100644 --- a/kernel/time/Makefile +++ b/kernel/time/Makefile | |||
@@ -12,5 +12,3 @@ obj-$(CONFIG_TICK_ONESHOT) += tick-oneshot.o tick-sched.o | |||
12 | obj-$(CONFIG_TIMER_STATS) += timer_stats.o | 12 | obj-$(CONFIG_TIMER_STATS) += timer_stats.o |
13 | obj-$(CONFIG_DEBUG_FS) += timekeeping_debug.o | 13 | obj-$(CONFIG_DEBUG_FS) += timekeeping_debug.o |
14 | obj-$(CONFIG_TEST_UDELAY) += test_udelay.o | 14 | obj-$(CONFIG_TEST_UDELAY) += test_udelay.o |
15 | |||
16 | $(obj)/time.o: $(objtree)/include/config/ | ||
diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 520499dd85af..5e097fa9faf7 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c | |||
@@ -1566,7 +1566,7 @@ static void migrate_timers(int cpu) | |||
1566 | 1566 | ||
1567 | BUG_ON(cpu_online(cpu)); | 1567 | BUG_ON(cpu_online(cpu)); |
1568 | old_base = per_cpu_ptr(&tvec_bases, cpu); | 1568 | old_base = per_cpu_ptr(&tvec_bases, cpu); |
1569 | new_base = this_cpu_ptr(&tvec_bases); | 1569 | new_base = get_cpu_ptr(&tvec_bases); |
1570 | /* | 1570 | /* |
1571 | * The caller is globally serialized and nobody else | 1571 | * The caller is globally serialized and nobody else |
1572 | * takes two locks at once, deadlock is not possible. | 1572 | * takes two locks at once, deadlock is not possible. |
@@ -1590,6 +1590,7 @@ static void migrate_timers(int cpu) | |||
1590 | 1590 | ||
1591 | spin_unlock(&old_base->lock); | 1591 | spin_unlock(&old_base->lock); |
1592 | spin_unlock_irq(&new_base->lock); | 1592 | spin_unlock_irq(&new_base->lock); |
1593 | put_cpu_ptr(&tvec_bases); | ||
1593 | } | 1594 | } |
1594 | 1595 | ||
1595 | static int timer_cpu_notify(struct notifier_block *self, | 1596 | static int timer_cpu_notify(struct notifier_block *self, |