ARM: 7480/1: only call smp_send_stop() on SMP
commit
c5dff4ffd327088d85035bec535b7d0c9ea03151 upstream.
On reboot or poweroff (machine_shutdown()) a call to smp_send_stop() is
made (to stop the others CPU's) when CONFIG_SMP=y.
arch/arm/kernel/process.c:
void machine_shutdown(void)
{
#ifdef CONFIG_SMP
smp_send_stop();
#endif
}
smp_send_stop() calls the function pointer smp_cross_call(), which is set
on the smp_init_cpus() function for OMAP processors.
arch/arm/mach-omap2/omap-smp.c:
void __init smp_init_cpus(void)
{
...
set_smp_cross_call(gic_raise_softirq);
...
}
But the ARM setup_arch() function only calls smp_init_cpus()
if CONFIG_SMP=y && is_smp().
arm/kernel/setup.c:
void __init setup_arch(char **cmdline_p)
{
...
#ifdef CONFIG_SMP
if (is_smp())
smp_init_cpus();
#endif
...
}
Newer OMAP CPU's are SMP machines so omap2plus_defconfig sets
CONFIG_SMP=y. Unfortunately on an OMAP UP machine is_smp()
returns false and smp_init_cpus() is never called and the
smp_cross_call() function remains NULL.
If the machine is rebooted or powered off, smp_send_stop() will
be called (since CONFIG_SMP=y) leading to the following error:
[ 42.815551] Restarting system.
[ 42.819030] Unable to handle kernel NULL pointer dereference at virtual address
00000000
[ 42.827667] pgd =
d7a74000
[ 42.830566] [
00000000] *pgd=
96ce7831, *pte=
00000000, *ppte=
00000000
[ 42.837249] Internal error: Oops:
80000007 [#1] SMP ARM
[ 42.842773] Modules linked in:
[ 42.846008] CPU: 0 Not tainted (
3.5.0-rc3-next-20120622-00002-g62e87ba-dirty #44)
[ 42.854278] PC is at 0x0
[ 42.856994] LR is at smp_send_stop+0x4c/0xe4
[ 42.861511] pc : [<
00000000>] lr : [<
c00183a4>] psr:
60000013
[ 42.861511] sp :
d6c85e70 ip :
00000000 fp :
00000000
[ 42.873626] r10:
00000000 r9 :
d6c84000 r8 :
00000002
[ 42.879150] r7 :
c07235a0 r6 :
c06dd2d0 r5 :
000f4241 r4 :
d6c85e74
[ 42.886047] r3 :
00000000 r2 :
00000000 r1 :
00000006 r0 :
d6c85e74
[ 42.892944] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
[ 42.900482] Control:
10c5387d Table:
97a74019 DAC:
00000015
[ 42.906555] Process reboot (pid: 1166, stack limit = 0xd6c842f8)
[ 42.912902] Stack: (0xd6c85e70 to 0xd6c86000)
[ 42.917510] 5e60:
c07235a0 00000000 00000000 d6c84000
[ 42.926177] 5e80:
01234567 c00143d0 4321fedc c00511bc d6c85ebc 00000168 00000460 00000000
[ 42.934814] 5ea0:
c1017950 a0000013 c1017900 d8014390 d7ec3858 c0498e48 c1017950 00000000
[ 42.943481] 5ec0:
d6ddde10 d6c85f78 00000003 00000000 d6ddde10 d6c84000 00000000 00000000
[ 42.952117] 5ee0:
00000002 00000000 00000000 c0088c88 00000002 00000000 00000000 c00f4b90
[ 42.960784] 5f00:
00000000 d6c85ebc d8014390 d7e311c8 60000013 00000103 00000002 d6c84000
[ 42.969421] 5f20:
c00f3274 d6e00a00 00000001 60000013 d6c84000 00000000 00000000 c00895d4
[ 42.978057] 5f40:
00000002 d8007c80 d781f000 c00f6150 d8010cc0 c00f3274 d781f000 d6c84000
[ 42.986694] 5f60:
c0013020 d6e00a00 00000001 20000010 0001257c ef000000 00000000 c00895d4
[ 42.995361] 5f80:
00000002 00000001 00000003 00000000 00000001 00000003 00000000 00000058
[ 43.003997] 5fa0:
c00130c8 c0012f00 00000001 00000003 fee1dead 28121969 01234567 00000002
[ 43.012634] 5fc0:
00000001 00000003 00000000 00000058 00012584 0001257c 00000001 00000000
[ 43.021270] 5fe0:
000124bc bec5cc6c 00008f9c 4a2f7c40 20000010 fee1dead 00000000 00000000
[ 43.029968] [<
c00183a4>] (smp_send_stop+0x4c/0xe4) from [<
c00143d0>] (machine_restart+0xc/0x4c)
[ 43.039154] [<
c00143d0>] (machine_restart+0xc/0x4c) from [<
c00511bc>] (sys_reboot+0x144/0x1f0)
[ 43.048278] [<
c00511bc>] (sys_reboot+0x144/0x1f0) from [<
c0012f00>] (ret_fast_syscall+0x0/0x3c)
[ 43.057464] Code: bad PC value
[ 43.060760] ---[ end trace
c3988d1dd0b8f0fb ]---
Add a check so smp_cross_call() is only called when there is more than one CPU on-line.
Signed-off-by: Javier Martinez Canillas <javier at dowhile0.org>
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>