diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2018-01-29 09:09:41 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-03-13 14:02:28 -0700 |
commit | f43e42f46aa87bc0507bde9a0cd6ead663ba6a30 (patch) | |
tree | a6ea1824de32ee1ced90a1c0dcf73589868ece0b /arch/xtensa | |
parent | aad4dc749ed58c6f37abbe2b6f55a90a2129c375 (diff) | |
download | linux-rpi3-f43e42f46aa87bc0507bde9a0cd6ead663ba6a30.tar.gz linux-rpi3-f43e42f46aa87bc0507bde9a0cd6ead663ba6a30.tar.bz2 linux-rpi3-f43e42f46aa87bc0507bde9a0cd6ead663ba6a30.zip |
xtensa: SMP: fix ccount_timer_shutdown
[ Upstream commit 4fe8713b873fc881284722ce4ac47995de7cf62c ]
ccount_timer_shutdown is called from the atomic context in the
secondary_start_kernel, resulting in the following BUG:
BUG: sleeping function called from invalid context
in_atomic(): 1, irqs_disabled(): 1, pid: 0, name: swapper/1
Preemption disabled at:
secondary_start_kernel+0xa1/0x130
Call Trace:
___might_sleep+0xe7/0xfc
__might_sleep+0x41/0x44
synchronize_irq+0x24/0x64
disable_irq+0x11/0x14
ccount_timer_shutdown+0x12/0x20
clockevents_switch_state+0x82/0xb4
clockevents_exchange_device+0x54/0x60
tick_check_new_device+0x46/0x70
clockevents_register_device+0x8c/0xc8
clockevents_config_and_register+0x1d/0x2c
local_timer_setup+0x75/0x7c
secondary_start_kernel+0xb4/0x130
should_never_return+0x32/0x35
Use disable_irq_nosync instead of disable_irq to avoid it.
This is safe because the ccount timer IRQ is per-CPU, and once IRQ is
masked the ISR will not be called.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'arch/xtensa')
-rw-r--r-- | arch/xtensa/kernel/time.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index fd524a54d2ab..378186b5eb40 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -89,7 +89,7 @@ static int ccount_timer_shutdown(struct clock_event_device *evt) container_of(evt, struct ccount_timer, evt); if (timer->irq_enabled) { - disable_irq(evt->irq); + disable_irq_nosync(evt->irq); timer->irq_enabled = 0; } return 0; |