Commit 6d913c32 authored by Damian Eppel's avatar Damian Eppel Committed by Anand Moon

clocksource: exynos_mct: Avoid blocking calls in the cpu hotplug notifier

Whilst testing cpu hotplug events on kernel configured with
DEBUG_PREEMPT and DEBUG_ATOMIC_SLEEP we get following BUG message,
caused by calling request_irq() and free_irq() in the context of
hotplug notification (which is in this case atomic context).

[    0.091617] [c0] CPU0: thread -1, cpu 0, socket 1, mpidr 80000100
[    0.091828] [c0] Running under secure firmware.
[    0.091901] [c0] Setting up static identity map for 0xc0618b98 - 0xc0618bf0
[    0.091962] [c0] Exynos-SnapShot: exynos_ss_init failed
[    0.112330] [c0] ftrace: Allocated trace_printk buffers
[    0.134323] [c1] CPU1: Booted secondary processor
[    0.134354] [c1] CPU1: thread -1, cpu 1, socket 1, mpidr 80000101
[    0.134402] [c1] BUG: sleeping function called from invalid context at mm/page_alloc.c:2638
[    0.134518] [c1] in_atomic(): 1, irqs_disabled(): 0, pid: 0, name: swapper/1
[    0.134560] [c1] no locks held by swapper/1/0.
[    0.134598] [c1] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 3.10.82-xu43hk #11
[    0.134640] [c1] Backtrace:
[    0.134694] [c1] [<c00132e4>] (dump_backtrace+0x0/0x114) from [<c0013554>] (show_stack+0x20/0x24)
[    0.134744] [c1]  r7:00000000 r6:00000000 r5:df2da000 r4:c098c9c0
[    0.134826] [c1] [<c0013534>] (show_stack+0x0/0x24) from [<c06124d8>] (dump_stack+0x24/0x28)
[    0.134887] [c1] [<c06124b4>] (dump_stack+0x0/0x28) from [<c00617f8>] (__might_sleep+0x144/0x148)
[    0.134952] [c1] [<c00616b4>] (__might_sleep+0x0/0x148) from [<c00f5590>] (__alloc_pages_nodemask+0x2a0/0xaac)
[    0.135006] [c1]  r5:00080008 r4:002012d0
[    0.135065] [c1] [<c00f52f0>] (__alloc_pages_nodemask+0x0/0xaac) from [<c012875c>] (new_slab+0x7c/0x22c)
[    0.135132] [c1] [<c01286e0>] (new_slab+0x0/0x22c) from [<c012a92c>] (__slab_alloc.isra.14.constprop.18+0x558/0x61c)
[    0.135187] [c1]  r9:00000000 r8:df001f00 r7:014f7000 r6:00000000 r5:c1dee9e0
[    0.135187] r4:c08f79e0
[    0.135295] [c1] [<c012a3d4>] (__slab_alloc.isra.14.constprop.18+0x0/0x61c) from [<c012af3c>] (kmem_cache_alloc_trace+0x194/0x1c8)
[    0.135367] [c1] [<c012ada8>] (kmem_cache_alloc_trace+0x0/0x1c8) from [<c00b04e0>] (request_threaded_irq+0x78/0x138)
[    0.135433] [c1] [<c00b0468>] (request_threaded_irq+0x0/0x138) from [<c0610f7c>] (exynos4_local_timer_setup+0x100/0x160)
[    0.135507] [c1] [<c0610e7c>] (exynos4_local_timer_setup+0x0/0x160) from [<c060de3c>] (percpu_timer_setup+0xa4/0xb0)
[    0.135562] [c1]  r8:4000406a r7:c0968c84 r6:10c0387d r5:c09148c0 r4:c1de9280
[    0.135655] [c1] [<c060dd98>] (percpu_timer_setup+0x0/0xb0) from [<c060e1e4>] (secondary_start_kernel+0x118/0x134)
[    0.135710] [c1]  r5:c09148c0 r4:00000001
[    0.135765] [c1] [<c060e0cc>] (secondary_start_kernel+0x0/0x134) from [<4060d784>] (0x4060d784)
[    0.135815] [c1]  r5:00000015 r4:5f13006a
[    0.144239] [c2] CPU2: Booted secondary processor
[    0.144267] [c2] CPU2: thread -1, cpu 2, socket 1, mpidr 80000102
[    0.154295] [c3] CPU3: Booted secondary processor

Change-Id: I78ee2d3997b2137e3c19432e17b3e3672523cf43
parent 2366f779
......@@ -413,6 +413,22 @@ static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
static const char *irq_names[] = {
"mct_tick0",
"mct_tick1",
"mct_tick2",
"mct_tick3",
"mct_tick4",
"mct_tick5",
"mct_tick6",
"mct_tick7",
};
static DEFINE_PER_CPU(struct irqaction, percpu_mct_irq) = {
.flags = IRQF_TIMER | IRQF_NOBALANCING,
.handler = exynos4_mct_tick_isr,
};
static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
{
struct mct_clock_event_device *mevt;
......@@ -433,15 +449,12 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET);
if (mct_int_type == MCT_INT_SPI) {
struct irqaction *mct_irq = this_cpu_ptr(&percpu_mct_irq);
mct_irq->dev_id = mevt;
evt->irq = mct_irqs[MCT_L0_IRQ + cpu];
if (request_irq(evt->irq, exynos4_mct_tick_isr,
IRQF_TIMER | IRQF_NOBALANCING,
evt->name, mevt)) {
pr_err("exynos-mct: cannot register IRQ %d\n",
evt->irq);
return -EIO;
}
irq_set_affinity(evt->irq, cpumask_of(cpu));
enable_irq(evt->irq);
} else {
enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0);
}
......@@ -456,7 +469,7 @@ static void exynos4_local_timer_stop(struct clock_event_device *evt)
{
evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
if (mct_int_type == MCT_INT_SPI)
free_irq(evt->irq, this_cpu_ptr(&percpu_mct_tick));
disable_irq(evt->irq);
else
disable_percpu_irq(mct_irqs[MCT_L0_IRQ]);
}
......@@ -465,6 +478,21 @@ static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
.setup = exynos4_local_timer_setup,
.stop = exynos4_local_timer_stop,
};
static void __init exynos4_local_timer_init(void)
{
int cpu;
if (mct_int_type == MCT_INT_SPI) {
for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
struct irqaction *mct_irq
= per_cpu_ptr(&percpu_mct_irq, cpu);
mct_irq->name = irq_names[cpu];
setup_irq(mct_irqs[MCT_L0_IRQ + cpu], mct_irq);
disable_irq(mct_irqs[MCT_L0_IRQ + cpu]);
}
}
}
#endif /* CONFIG_LOCAL_TIMERS */
static void __init exynos4_timer_resources(struct device_node *np, void __iomem *base)
......@@ -551,6 +579,9 @@ static void __init mct_init_dt(struct device_node *np, unsigned int int_type)
mct_irqs[i] = irq_of_parse_and_map(np, i);
exynos4_timer_resources(np, of_iomap(np, 0));
#ifdef CONFIG_LOCAL_TIMERS
exynos4_local_timer_init();
#endif
exynos4_clocksource_init();
exynos4_clockevent_init();
exynos4_timer_delay_init();
......
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