msm: restart_7k: Move restart code out of pm2.c
We see a kernel panic when we reboot with recovery mode
from the UI. Though kernel prepares to stop the other
cores(cpu_relax), but in some race condition mpdecision kicks
in to wake up(CPU_UP_PREPARE) the other core, before we go
ahead for issuing pcom command from core-0 for restart and this
causes a BUG in stop machine code.
So to resolve this before we issue a PCOM_RESET_CHIP command from
core-0, we must ensure that IRQ and FIQ is disabled and also
map the user pages to 1:1 mapping so as to not have unpredictable
MMU errors or kernel panics.
Moving the code put of pm2.c as this code is more restart specific and
not related to power management code.
CRs-Fixed: 359879
Change-Id: If26fdf3a4dd1fb5ecc4c28859bfd68650ff4e747
Signed-off-by: Taniya Das <tdas@codeaurora.org>
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 2346cf8..e21eed5 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -39,6 +39,7 @@
select MSM_RUN_QUEUE_STATS if MSM_SOC_REV_A
select DONT_MAP_HOLE_AFTER_MEMBANK0
select MIGHT_HAVE_CACHE_L2X0
+ select MSM_MODEM_RESTART
config ARCH_MSM7X30
bool "MSM7x30"
@@ -65,6 +66,7 @@
select MULTI_IRQ_HANDLER
select MSM_PM2 if PM
select HOLES_IN_ZONE if SPARSEMEM
+ select MSM_MODEM_RESTART
config ARCH_QSD8X50
bool "QSD8X50"
@@ -78,6 +80,7 @@
select MSM_GPIOMUX
select MSM_DALRPC
select MSM_PM2 if PM
+ select MSM_MODEM_RESTART
config ARCH_MSM8X60
bool "MSM8X60"
@@ -2090,6 +2093,9 @@
config MSM_NATIVE_RESTART
bool
+config MSM_MODEM_RESTART
+ bool
+
config MSM_PM2
depends on PM
bool
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 841ed3c..f7f488a 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -363,6 +363,7 @@
obj-$(CONFIG_MSM_FAKE_BATTERY) += fish_battery.o
obj-$(CONFIG_MSM_RPC_VIBRATOR) += msm_vibrator.o
obj-$(CONFIG_MSM_NATIVE_RESTART) += restart.o
+obj-$(CONFIG_MSM_MODEM_RESTART) += restart_7k.o
obj-$(CONFIG_MSM_PROC_COMM_REGULATOR) += proccomm-regulator.o
ifdef CONFIG_MSM_PROC_COMM_REGULATOR
diff --git a/arch/arm/mach-msm/devices-msm7x2xa.h b/arch/arm/mach-msm/devices-msm7x2xa.h
index 4184a86..8febe26 100644
--- a/arch/arm/mach-msm/devices-msm7x2xa.h
+++ b/arch/arm/mach-msm/devices-msm7x2xa.h
@@ -33,4 +33,5 @@
void __init msm8x25_spm_device_init(void);
void __init msm8x25_kgsl_3d0_init(void);
void __iomem *core1_reset_base(void);
+extern void setup_mm_for_reboot(void);
#endif
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index 7a8e4c3..8fccda4 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -21,10 +21,8 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/pm.h>
#include <linux/pm_qos.h>
#include <linux/suspend.h>
-#include <linux/reboot.h>
#include <linux/io.h>
#include <linux/tick.h>
#include <linux/memory.h>
@@ -34,7 +32,6 @@
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#endif
-#include <asm/system_misc.h>
#ifdef CONFIG_CACHE_L2X0
#include <asm/hardware/cache-l2x0.h>
#endif
@@ -1577,55 +1574,6 @@
}
}
-/******************************************************************************
- * Restart Definitions
- *****************************************************************************/
-
-static uint32_t restart_reason = 0x776655AA;
-
-static void msm_pm_power_off(void)
-{
- msm_rpcrouter_close();
- msm_proc_comm(PCOM_POWER_DOWN, 0, 0);
- for (;;)
- ;
-}
-
-static void msm_pm_restart(char str, const char *cmd)
-{
- msm_rpcrouter_close();
- msm_proc_comm(PCOM_RESET_CHIP, &restart_reason, 0);
-
- for (;;)
- ;
-}
-
-static int msm_reboot_call
- (struct notifier_block *this, unsigned long code, void *_cmd)
-{
- if ((code == SYS_RESTART) && _cmd) {
- char *cmd = _cmd;
- if (!strcmp(cmd, "bootloader")) {
- restart_reason = 0x77665500;
- } else if (!strcmp(cmd, "recovery")) {
- restart_reason = 0x77665502;
- } else if (!strcmp(cmd, "eraseflash")) {
- restart_reason = 0x776655EF;
- } else if (!strncmp(cmd, "oem-", 4)) {
- unsigned code = simple_strtoul(cmd + 4, 0, 16) & 0xff;
- restart_reason = 0x6f656d00 | code;
- } else {
- restart_reason = 0x77665501;
- }
- }
- return NOTIFY_DONE;
-}
-
-static struct notifier_block msm_reboot_notifier = {
- .notifier_call = msm_reboot_call,
-};
-
-
/*
* Initialize the power management subsystem.
*
@@ -1693,10 +1641,6 @@
virt_to_phys(&msm_pm_pc_pgd));
#endif
- pm_power_off = msm_pm_power_off;
- arm_pm_restart = msm_pm_restart;
- register_reboot_notifier(&msm_reboot_notifier);
-
msm_pm_smem_data = smem_alloc(SMEM_APPS_DEM_SLAVE_DATA,
sizeof(*msm_pm_smem_data));
if (msm_pm_smem_data == NULL) {
diff --git a/arch/arm/mach-msm/restart_7k.c b/arch/arm/mach-msm/restart_7k.c
new file mode 100644
index 0000000..dc9edf4
--- /dev/null
+++ b/arch/arm/mach-msm/restart_7k.c
@@ -0,0 +1,101 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/reboot.h>
+#include <linux/pm.h>
+#include <asm/system_misc.h>
+#include <mach/proc_comm.h>
+
+#include "devices-msm7x2xa.h"
+#include "smd_rpcrouter.h"
+
+static uint32_t restart_reason = 0x776655AA;
+
+static void msm_pm_power_off(void)
+{
+ msm_rpcrouter_close();
+ msm_proc_comm(PCOM_POWER_DOWN, 0, 0);
+ for (;;)
+ ;
+}
+
+static void msm_pm_restart(char str, const char *cmd)
+{
+ msm_rpcrouter_close();
+ pr_debug("The reset reason is %x\n", restart_reason);
+
+ /* Disable interrupts */
+ local_irq_disable();
+ local_fiq_disable();
+
+ /*
+ * Take out a flat memory mapping and will
+ * insert a 1:1 mapping in place of
+ * the user-mode pages to ensure predictable results
+ * This function takes care of flushing the caches
+ * and flushing the TLB.
+ */
+ setup_mm_for_reboot();
+
+ msm_proc_comm(PCOM_RESET_CHIP, &restart_reason, 0);
+
+ for (;;)
+ ;
+}
+
+static int msm_reboot_call
+ (struct notifier_block *this, unsigned long code, void *_cmd)
+{
+ if ((code == SYS_RESTART) && _cmd) {
+ char *cmd = _cmd;
+ if (!strncmp(cmd, "bootloader", 10)) {
+ restart_reason = 0x77665500;
+ } else if (!strncmp(cmd, "recovery", 8)) {
+ restart_reason = 0x77665502;
+ } else if (!strncmp(cmd, "eraseflash", 10)) {
+ restart_reason = 0x776655EF;
+ } else if (!strncmp(cmd, "oem-", 4)) {
+ unsigned long code;
+ int res;
+ res = kstrtoul(cmd + 4, 16, &code);
+ code &= 0xff;
+ restart_reason = 0x6f656d00 | code;
+ } else {
+ restart_reason = 0x77665501;
+ }
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block msm_reboot_notifier = {
+ .notifier_call = msm_reboot_call,
+};
+
+static int __init msm_pm_restart_init(void)
+{
+ int ret;
+
+ pm_power_off = msm_pm_power_off;
+ arm_pm_restart = msm_pm_restart;
+
+ ret = register_reboot_notifier(&msm_reboot_notifier);
+ if (ret)
+ pr_err("Failed to register reboot notifier\n");
+
+ return ret;
+}
+late_initcall(msm_pm_restart_init);