Subject: ARM AT91 Use IRQF_TIMER flag to prevent early boot crash From: Carsten Emde Date: Sat, 30 May 2015 14:26:44 +0100 When threaded interrupts are configured, they may not be requested before the kthread daemon is running. The system crashes at an early boot stage, otherwise: Unable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = c0004000 [00000000] *pgd=00000000 Internal error: Oops: 5 [#1] PREEMPT THUMB2 Modules linked in: CPU: 0 PID: 0 Comm: swapper Not tainted 3.18.13-rt10 #15 task: c06a92f0 ti: c069e000 task.ti: c069e000 PC is at wake_up_process+0xc/0x3c LR is at kthread_create_on_node+0x7f/0xf4 pc : [] lr : [] psr: 600001f3 sp : c069fe90 ip : c002fe5f fp : 00100100 r10: 00000015 r9 : c003e339 r8 : ce802f40 r7 : c069fe90 r6 : c069fea4 r5 : c06b0200 r4 : 00000000 r3 : c07553e4 r2 : 00000000 r1 : c06a92f0 r0 : 00000000 Flags: nZCv IRQs off FIQs off Mode SVC_32 ISA Thumb Segment kernel Control: 50c53c7d Table: 20004059 DAC: 00000015 Process swapper (pid: 0, stack limit = 0xc069e238) Stack: (0xc069fe90 to 0xc06a0000) fe80: c07553e4 ce802f80 00000000 c002b037 fea0: c069fea8 00000000 c069fea8 c069fea8 ce8060c0 ce8060c0 0a820000 ce802f40 fec0: 00000015 00000000 c003e71f c0567f28 00000015 c05c14e4 ce8060c0 ce802f40 fee0: ce8060c0 00000004 c02efab5 ce802f00 00000000 c003eae7 cede4768 00000015 ff00: ce802400 ce802f00 cede4980 c07eb228 ce802408 c066a6fb c05c14e4 ce802f00 ff20: ce802408 cede4980 cede42b4 cede4980 c0476b24 c069ff28 c0476601 00000001 ff40: cede4768 cede396c 00000010 c0476634 ce802400 c066926b c05c1320 ce802400 ff60: 00000001 ce802440 cede396c ce802480 00000000 c073ac68 00000001 c0669003 ff80: 00200200 c073ac30 00000000 00000000 00000000 00000000 c0754700 c06a6000 ffa0: ffffffff c0754700 c067cac0 cefffbc0 00000000 c06482a7 00000000 c06458f1 ffc0: ffffffff ffffffff c064557d 00000000 00000000 c067cac0 c07548d4 c06a6074 ffe0: c067cabc c06aa630 20004059 410fc051 00000000 20008079 00000000 00000000 [] (wake_up_process) from [] (kthread_create_on_node+0x7f/0xf4) [] (kthread_create_on_node) from [] (__setup_irq+0x11f/0x408) [] (__setup_irq) from [] (request_threaded_irq+0x8b/0xe4) [] (request_threaded_irq) from [] (of_at91sam9x5_clk_utmi_setup+0xd3/0x10c) [] (of_at91sam9x5_clk_utmi_setup) from [] (of_at91_pmc_setup+0x10b/0x12c) [] (of_at91_pmc_setup) from [] (of_clk_init+0xbb/0x11c) [] (of_clk_init) from [] (time_init+0x17/0x20) [] (time_init) from [] (start_kernel+0x1dd/0x2e8) [] (start_kernel) from [<20008079>] (0x20008079) Code: b500 f7dd f983 4604 (6803) f013 ---[ end trace 0000000000000001 ]--- Add the IRQF_TIMER flag as recommended by Sebastian Siewior -> http://www.spinics.net/lists/linux-rt-users/msg13171.html Signed-off-by: Carsten Emde --- drivers/clk/at91/clk-main.c | 6 +++--- drivers/clk/at91/clk-master.c | 4 +--- drivers/clk/at91/clk-pll.c | 3 ++- drivers/clk/at91/clk-system.c | 2 +- drivers/clk/at91/clk-utmi.c | 2 +- drivers/clk/at91/pmc.c | 3 ++- drivers/rtc/rtc-at91rm9200.c | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) Index: linux-3.18.13-rt10-r7s4/drivers/clk/at91/clk-main.c =================================================================== --- linux-3.18.13-rt10-r7s4.orig/drivers/clk/at91/clk-main.c +++ linux-3.18.13-rt10-r7s4/drivers/clk/at91/clk-main.c @@ -170,7 +170,7 @@ at91_clk_register_main_osc(struct at91_p init_waitqueue_head(&osc->wait); irq_set_status_flags(osc->irq, IRQ_NOAUTOEN); ret = request_irq(osc->irq, clk_main_osc_irq_handler, - IRQF_TRIGGER_HIGH, name, osc); + IRQF_TRIGGER_HIGH | IRQF_NO_THREAD, name, osc); if (ret) return ERR_PTR(ret); @@ -324,7 +324,7 @@ at91_clk_register_main_rc_osc(struct at9 init_waitqueue_head(&osc->wait); irq_set_status_flags(osc->irq, IRQ_NOAUTOEN); ret = request_irq(osc->irq, clk_main_rc_osc_irq_handler, - IRQF_TRIGGER_HIGH, name, osc); + IRQF_TRIGGER_HIGH | IRQF_NO_THREAD, name, osc); if (ret) return ERR_PTR(ret); @@ -591,7 +591,7 @@ at91_clk_register_sam9x5_main(struct at9 init_waitqueue_head(&clkmain->wait); irq_set_status_flags(clkmain->irq, IRQ_NOAUTOEN); ret = request_irq(clkmain->irq, clk_sam9x5_main_irq_handler, - IRQF_TRIGGER_HIGH, name, clkmain); + IRQF_TRIGGER_HIGH | IRQF_NO_THREAD, name, clkmain); if (ret) return ERR_PTR(ret); Index: linux-3.18.13-rt10-r7s4/drivers/clk/at91/clk-master.c =================================================================== --- linux-3.18.13-rt10-r7s4.orig/drivers/clk/at91/clk-master.c +++ linux-3.18.13-rt10-r7s4/drivers/clk/at91/clk-master.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -70,7 +69,6 @@ static int clk_master_prepare(struct clk wait_event(master->wait, pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY); } - return 0; } @@ -164,7 +162,7 @@ at91_clk_register_master(struct at91_pmc init_waitqueue_head(&master->wait); irq_set_status_flags(master->irq, IRQ_NOAUTOEN); ret = request_irq(master->irq, clk_master_irq_handler, - IRQF_TRIGGER_HIGH, "clk-master", master); + IRQF_TRIGGER_HIGH | IRQF_NO_THREAD, "clk-master", master); if (ret) return ERR_PTR(ret); Index: linux-3.18.13-rt10-r7s4/drivers/clk/at91/clk-pll.c =================================================================== --- linux-3.18.13-rt10-r7s4.orig/drivers/clk/at91/clk-pll.c +++ linux-3.18.13-rt10-r7s4/drivers/clk/at91/clk-pll.c @@ -336,7 +336,8 @@ at91_clk_register_pll(struct at91_pmc *p pll->mul = PLL_MUL(tmp, layout); init_waitqueue_head(&pll->wait); irq_set_status_flags(pll->irq, IRQ_NOAUTOEN); - ret = request_irq(pll->irq, clk_pll_irq_handler, IRQF_TRIGGER_HIGH, + ret = request_irq(pll->irq, clk_pll_irq_handler, + IRQF_TRIGGER_HIGH | IRQF_NO_THREAD, id ? "clk-pllb" : "clk-plla", pll); if (ret) return ERR_PTR(ret); Index: linux-3.18.13-rt10-r7s4/drivers/clk/at91/clk-system.c =================================================================== --- linux-3.18.13-rt10-r7s4.orig/drivers/clk/at91/clk-system.c +++ linux-3.18.13-rt10-r7s4/drivers/clk/at91/clk-system.c @@ -129,7 +129,7 @@ at91_clk_register_system(struct at91_pmc init_waitqueue_head(&sys->wait); irq_set_status_flags(sys->irq, IRQ_NOAUTOEN); ret = request_irq(sys->irq, clk_system_irq_handler, - IRQF_TRIGGER_HIGH, name, sys); + IRQF_TRIGGER_HIGH | IRQF_NO_THREAD, name, sys); if (ret) return ERR_PTR(ret); } Index: linux-3.18.13-rt10-r7s4/drivers/clk/at91/clk-utmi.c =================================================================== --- linux-3.18.13-rt10-r7s4.orig/drivers/clk/at91/clk-utmi.c +++ linux-3.18.13-rt10-r7s4/drivers/clk/at91/clk-utmi.c @@ -117,7 +117,7 @@ at91_clk_register_utmi(struct at91_pmc * init_waitqueue_head(&utmi->wait); irq_set_status_flags(utmi->irq, IRQ_NOAUTOEN); ret = request_irq(utmi->irq, clk_utmi_irq_handler, - IRQF_TRIGGER_HIGH, "clk-utmi", utmi); + IRQF_TRIGGER_HIGH | IRQF_NO_THREAD, "clk-utmi", utmi); if (ret) return ERR_PTR(ret); Index: linux-3.18.13-rt10-r7s4/drivers/clk/at91/pmc.c =================================================================== --- linux-3.18.13-rt10-r7s4.orig/drivers/clk/at91/pmc.c +++ linux-3.18.13-rt10-r7s4/drivers/clk/at91/pmc.c @@ -233,7 +233,8 @@ static struct at91_pmc *__init at91_pmc_ pmc_write(pmc, AT91_PMC_IDR, 0xffffffff); if (request_irq(pmc->virq, pmc_irq_handler, - IRQF_SHARED | IRQF_COND_SUSPEND, "pmc", pmc)) + IRQF_SHARED | IRQF_NO_THREAD, + "pmc", pmc)) goto out_remove_irqdomain; return pmc; Index: linux-3.18.13-rt10-r7s4/drivers/rtc/rtc-at91rm9200.c =================================================================== --- linux-3.18.13-rt10-r7s4.orig/drivers/rtc/rtc-at91rm9200.c +++ linux-3.18.13-rt10-r7s4/drivers/rtc/rtc-at91rm9200.c @@ -416,7 +416,7 @@ static int __init at91_rtc_probe(struct AT91_RTC_CALEV); ret = devm_request_irq(&pdev->dev, irq, at91_rtc_interrupt, - IRQF_SHARED | IRQF_COND_SUSPEND, + IRQF_SHARED | IRQF_NO_THREAD, "at91_rtc", pdev); if (ret) { dev_err(&pdev->dev, "IRQ %d already in use.\n", irq);