diff mbox

[02/25] ARM: mxs: Fix BUG() when invoking mxs_restart() from interrupt context

Message ID 20991.26498.114005.439057@ipc1.ka-ro
State New
Headers show

Commit Message

Lothar Waßmann Aug. 5, 2013, 8:51 a.m. UTC
Hi,

Shawn Guo writes:
> On Wed, Jul 31, 2013 at 04:08:10PM +0200, Lothar Waßmann wrote:
[...]
> > +arch_initcall(mxs_restart_init);
> 
> The mxs is part of multiplatform build now.  We should not use the
> initcall like that, which will be invoked on other platforms that are
> part of multiplatform kernel image.
> 
> Calling it from machine specific hook like .init_machine should be fine.
> 
You're right, of course, new version of this patch below.

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>
---
 arch/arm/mach-mxs/mach-mxs.c |   53 +++++++++++++++++++++++++----------------
 1 files changed, 32 insertions(+), 21 deletions(-)

Comments

Shawn Guo Aug. 5, 2013, 9:18 a.m. UTC | #1
On Mon, Aug 05, 2013 at 10:51:14AM +0200, Lothar Waßmann wrote:
> You're right, of course, new version of this patch below.
> 
> 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>

Applied, thanks.
diff mbox

Patch

diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index 1868f32..2d7ad51 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -62,6 +62,8 @@ 
 static u32 chipid;
 static u32 socid;
 
+static void __iomem *reset_addr;
+
 static inline void __mxs_setl(u32 mask, void __iomem *reg)
 {
 	__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");
 }
 
+#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)
 {
 	struct device_node *root;
@@ -440,12 +463,12 @@  static void __init mxs_machine_init(void)
 	of_platform_populate(NULL, of_default_bus_match_table,
 			     NULL, parent);
 
+	mxs_restart_init();
+
 	if (of_machine_is_compatible("karo,tx28"))
 		tx28_post_init();
 }
 
-#define MX23_CLKCTRL_RESET_OFFSET	0x120
-#define MX28_CLKCTRL_RESET_OFFSET	0x1e0
 #define MXS_CLKCTRL_RESET_CHIP		(1 << 1)
 
 /*
@@ -453,28 +476,16 @@  static void __init mxs_machine_init(void)
  */
 static void mxs_restart(enum reboot_mode mode, const char *cmd)
 {
-	struct device_node *np;
-	void __iomem *reset_addr;
+	if (reset_addr) {
+		/* reset the chip */
+		__mxs_setl(MXS_CLKCTRL_RESET_CHIP, reset_addr);
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,clkctrl");
-	reset_addr = of_iomap(np, 0);
-	if (!reset_addr)
-		goto soft;
+		pr_err("Failed to assert the chip reset\n");
 
-	if (of_device_is_compatible(np, "fsl,imx23-clkctrl"))
-		reset_addr += MX23_CLKCTRL_RESET_OFFSET;
-	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);
+		/* Delay to allow the serial port to show the message */
+		mdelay(50);
+	}
 
-soft:
 	/* We'll take a jump through zero as a poor second */
 	soft_restart(0);
 }