mirror of
https://github.com/torvalds/linux.git
synced 2024-10-31 17:21:49 +00:00
ARM: mxs: Fix BUG() when invoking mxs_restart() from interrupt context
The mxs_restart() function uses of_iomap() which triggers the following BUG_ON(in_interrupt()) when called in interrupt context (e.g. thru SYSRQ-B): SysRq : Resetting ------------[ cut here ]------------ kernel BUG at mm/vmalloc.c:1310! Internal error: Oops - BUG: 0 [#1] PREEMPT ARM Modules linked in: i2c_dev CPU: 0 PID: 0 Comm: swapper Not tainted 3.11.0-rc2-next-20130729-karo+ #196 task: c04e1c38 ti: c04d8000 task.ti: c04d8000 PC is at __get_vm_area_node.clone.25+0x34/0x140 LR is at get_vm_area_caller+0x38/0x44 pc : [<c008a988>] lr : [<c008b434>] psr: 20000013 sp : c04d9db0 ip : 00000001 fp : 00000001 r10: c8800000 r9 : 00000000 r8 : 000000d0 r7 : 00002000 r6 : 00000001 r5 : 00000001 r4 : 00002000 r3 : 00010000 r2 : 00000001 r1 : c04d9db0 r0 : 00002000 Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel Control: 0005317f Table: 46920000 DAC: 00000017 Process swapper (pid: 0, stack limit = 0xc04d81b8) Create the mapping upon startup from mxs_machine_init(). Signed-off-by: Lothar Waßmann <LW@KARO-electronics.de> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
This commit is contained in:
parent
5cd86ef5e4
commit
56b7eec01d
@ -62,6 +62,8 @@
|
|||||||
static u32 chipid;
|
static u32 chipid;
|
||||||
static u32 socid;
|
static u32 socid;
|
||||||
|
|
||||||
|
static void __iomem *reset_addr;
|
||||||
|
|
||||||
static inline void __mxs_setl(u32 mask, void __iomem *reg)
|
static inline void __mxs_setl(u32 mask, void __iomem *reg)
|
||||||
{
|
{
|
||||||
__raw_writel(mask, reg + MXS_SET_ADDR);
|
__raw_writel(mask, reg + MXS_SET_ADDR);
|
||||||
@ -400,6 +402,27 @@ static const char __init *mxs_get_revision(void)
|
|||||||
return kasprintf(GFP_KERNEL, "%s", "Unknown");
|
return kasprintf(GFP_KERNEL, "%s", "Unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MX23_CLKCTRL_RESET_OFFSET 0x120
|
||||||
|
#define MX28_CLKCTRL_RESET_OFFSET 0x1e0
|
||||||
|
|
||||||
|
static int __init mxs_restart_init(void)
|
||||||
|
{
|
||||||
|
struct device_node *np;
|
||||||
|
|
||||||
|
np = of_find_compatible_node(NULL, NULL, "fsl,clkctrl");
|
||||||
|
reset_addr = of_iomap(np, 0);
|
||||||
|
if (!reset_addr)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (of_device_is_compatible(np, "fsl,imx23-clkctrl"))
|
||||||
|
reset_addr += MX23_CLKCTRL_RESET_OFFSET;
|
||||||
|
else
|
||||||
|
reset_addr += MX28_CLKCTRL_RESET_OFFSET;
|
||||||
|
of_node_put(np);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void __init mxs_machine_init(void)
|
static void __init mxs_machine_init(void)
|
||||||
{
|
{
|
||||||
struct device_node *root;
|
struct device_node *root;
|
||||||
@ -443,12 +466,12 @@ static void __init mxs_machine_init(void)
|
|||||||
of_platform_populate(NULL, of_default_bus_match_table,
|
of_platform_populate(NULL, of_default_bus_match_table,
|
||||||
NULL, parent);
|
NULL, parent);
|
||||||
|
|
||||||
|
mxs_restart_init();
|
||||||
|
|
||||||
if (of_machine_is_compatible("karo,tx28"))
|
if (of_machine_is_compatible("karo,tx28"))
|
||||||
tx28_post_init();
|
tx28_post_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MX23_CLKCTRL_RESET_OFFSET 0x120
|
|
||||||
#define MX28_CLKCTRL_RESET_OFFSET 0x1e0
|
|
||||||
#define MXS_CLKCTRL_RESET_CHIP (1 << 1)
|
#define MXS_CLKCTRL_RESET_CHIP (1 << 1)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -456,28 +479,16 @@ static void __init mxs_machine_init(void)
|
|||||||
*/
|
*/
|
||||||
static void mxs_restart(enum reboot_mode mode, const char *cmd)
|
static void mxs_restart(enum reboot_mode mode, const char *cmd)
|
||||||
{
|
{
|
||||||
struct device_node *np;
|
if (reset_addr) {
|
||||||
void __iomem *reset_addr;
|
/* reset the chip */
|
||||||
|
__mxs_setl(MXS_CLKCTRL_RESET_CHIP, reset_addr);
|
||||||
|
|
||||||
np = of_find_compatible_node(NULL, NULL, "fsl,clkctrl");
|
pr_err("Failed to assert the chip reset\n");
|
||||||
reset_addr = of_iomap(np, 0);
|
|
||||||
if (!reset_addr)
|
|
||||||
goto soft;
|
|
||||||
|
|
||||||
if (of_device_is_compatible(np, "fsl,imx23-clkctrl"))
|
/* Delay to allow the serial port to show the message */
|
||||||
reset_addr += MX23_CLKCTRL_RESET_OFFSET;
|
mdelay(50);
|
||||||
else
|
}
|
||||||
reset_addr += MX28_CLKCTRL_RESET_OFFSET;
|
|
||||||
|
|
||||||
/* reset the chip */
|
|
||||||
__mxs_setl(MXS_CLKCTRL_RESET_CHIP, reset_addr);
|
|
||||||
|
|
||||||
pr_err("Failed to assert the chip reset\n");
|
|
||||||
|
|
||||||
/* Delay to allow the serial port to show the message */
|
|
||||||
mdelay(50);
|
|
||||||
|
|
||||||
soft:
|
|
||||||
/* We'll take a jump through zero as a poor second */
|
/* We'll take a jump through zero as a poor second */
|
||||||
soft_restart(0);
|
soft_restart(0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user