| Subject: ARM: smp: Move clear_tasks_mm_cpumask() call to __cpu_die() |
| From: Grygorii Strashko <grygorii.strashko@ti.com> |
| Date: Fri, 11 Sep 2015 21:21:23 +0300 |
| |
| When running with the RT-kernel (4.1.5-rt5) on TI OMAP dra7-evm and trying |
| to do Suspend to RAM, the following backtrace occurs: |
| |
| Disabling non-boot CPUs ... |
| PM: noirq suspend of devices complete after 7.295 msecs |
| Disabling non-boot CPUs ... |
| BUG: sleeping function called from invalid context at kernel/locking/rtmutex.c:917 |
| in_atomic(): 1, irqs_disabled(): 128, pid: 18, name: migration/1 |
| INFO: lockdep is turned off. |
| irq event stamp: 122 |
| hardirqs last enabled at (121): [<c06ac0ac>] _raw_spin_unlock_irqrestore+0x88/0x90 |
| hardirqs last disabled at (122): [<c06abed0>] _raw_spin_lock_irq+0x28/0x5c |
| softirqs last enabled at (0): [<c003d294>] copy_process.part.52+0x410/0x19d8 |
| softirqs last disabled at (0): [< (null)>] (null) |
| Preemption disabled at:[< (null)>] (null) |
| CPU: 1 PID: 18 Comm: migration/1 Tainted: G W 4.1.4-rt3-01046-g96ac8da #204 |
| Hardware name: Generic DRA74X (Flattened Device Tree) |
| [<c0019134>] (unwind_backtrace) from [<c0014774>] (show_stack+0x20/0x24) |
| [<c0014774>] (show_stack) from [<c06a70f4>] (dump_stack+0x88/0xdc) |
| [<c06a70f4>] (dump_stack) from [<c006cab8>] (___might_sleep+0x198/0x2a8) |
| [<c006cab8>] (___might_sleep) from [<c06ac4dc>] (rt_spin_lock+0x30/0x70) |
| [<c06ac4dc>] (rt_spin_lock) from [<c013f790>] (find_lock_task_mm+0x9c/0x174) |
| [<c013f790>] (find_lock_task_mm) from [<c00409ac>] (clear_tasks_mm_cpumask+0xb4/0x1ac) |
| [<c00409ac>] (clear_tasks_mm_cpumask) from [<c00166a4>] (__cpu_disable+0x98/0xbc) |
| [<c00166a4>] (__cpu_disable) from [<c06a2e8c>] (take_cpu_down+0x1c/0x50) |
| [<c06a2e8c>] (take_cpu_down) from [<c00f2600>] (multi_cpu_stop+0x11c/0x158) |
| [<c00f2600>] (multi_cpu_stop) from [<c00f2a9c>] (cpu_stopper_thread+0xc4/0x184) |
| [<c00f2a9c>] (cpu_stopper_thread) from [<c0069058>] (smpboot_thread_fn+0x18c/0x324) |
| [<c0069058>] (smpboot_thread_fn) from [<c00649c4>] (kthread+0xe8/0x104) |
| [<c00649c4>] (kthread) from [<c0010058>] (ret_from_fork+0x14/0x3c) |
| CPU1: shutdown |
| PM: Calling sched_clock_suspend+0x0/0x40 |
| PM: Calling timekeeping_suspend+0x0/0x2e0 |
| PM: Calling irq_gc_suspend+0x0/0x68 |
| PM: Calling fw_suspend+0x0/0x2c |
| PM: Calling cpu_pm_suspend+0x0/0x28 |
| |
| Also, sometimes system stucks right after displaying "Disabling non-boot |
| CPUs ...". The root cause of above backtrace is task_lock() which takes |
| a sleeping lock on -RT. |
| |
| To fix the issue, move clear_tasks_mm_cpumask() call from __cpu_disable() |
| to __cpu_die() which is called on the thread which is asking for a target |
| CPU to be shutdown. In addition, this change restores CPUhotplug functionality |
| on TI OMAP dra7-evm and CPU1 can be unplugged/plugged many times. |
| |
| Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com> |
| Cc: Steven Rostedt <rostedt@goodmis.org> |
| Cc: <linux-arm-kernel@lists.infradead.org> |
| Cc: Sekhar Nori <nsekhar@ti.com> |
| Cc: Austin Schuh <austin@peloton-tech.com> |
| Cc: <philipp@peloton-tech.com> |
| Cc: Russell King <linux@arm.linux.org.uk> |
| Cc: <bigeasy@linutronix.de> |
| Cc: stable-rt@vger.kernel.org |
| Link: http://lkml.kernel.org/r/1441995683-30817-1-git-send-email-grygorii.strashko@ti.com |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| --- |
| |
| RFC: I'm not sure how safe this change is and will be appreciated for any comments. |
| Most of arches call clear_tasks_mm_cpumask() from __cpu_disable(), but *powerpc* |
| calls it from CPU_DEAD notifier. This patch follows powerpc's approach in |
| general. |
| |
| This issue was first reported in: |
| http://www.spinics.net/lists/linux-rt-users/msg13752.html |
| |
| arch/arm/kernel/smp.c | 5 +++-- |
| 1 file changed, 3 insertions(+), 2 deletions(-) |
| |
| --- a/arch/arm/kernel/smp.c |
| +++ b/arch/arm/kernel/smp.c |
| @@ -234,8 +234,6 @@ int __cpu_disable(void) |
| flush_cache_louis(); |
| local_flush_tlb_all(); |
| |
| - clear_tasks_mm_cpumask(cpu); |
| - |
| return 0; |
| } |
| |
| @@ -251,6 +249,9 @@ void __cpu_die(unsigned int cpu) |
| pr_err("CPU%u: cpu didn't die\n", cpu); |
| return; |
| } |
| + |
| + clear_tasks_mm_cpumask(cpu); |
| + |
| pr_notice("CPU%u: shutdown\n", cpu); |
| |
| /* |