summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorRenn Wu <rewu@nvidia.com>2015-02-03 10:27:18 +0800
committerMatthew Pedro <mapedro@nvidia.com>2015-06-08 12:01:04 -0700
commitb1de4caf2f12e1bc9c3a4e08dd60b5de53b7520a (patch)
tree727935d014482a714ef9808ce4245ca4a6b19efc /arch
parentd89af238e13dbd1f2a01cb5392902313ad367ef2 (diff)
watchdog: use FIQ WDT for soft lockup stack dump
Using Tegra WDT to trigger FIQ when system is in soft lockup. Bug 1581432 Change-Id: I853a88a3f6e9402c978db18c5a63e903c582040a Signed-off-by: Renn Wu <rewu@nvidia.com> Reviewed-on: http://git-master/r/265871 (cherry picked from commit f115f435d471af22ddec5e9d969662f79193f846) Reviewed-on: http://git-master/r/680353 GVS: Gerrit_Virtual_Submit Reviewed-by: Bibek Basu <bbasu@nvidia.com> Reviewed-by: Winnie Hsu <whsu@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/common/Kconfig45
-rw-r--r--arch/arm/common/fiq_debugger.c44
-rw-r--r--arch/arm/configs/tegra12_defconfig10
-rw-r--r--arch/arm/mach-tegra/Kconfig56
-rw-r--r--arch/arm/mach-tegra/board-ardbeg.c1
5 files changed, 93 insertions, 63 deletions
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index a73a5bdfd0c9..709d85388621 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -22,51 +22,6 @@ config FIQ_GLUE
bool
select FIQ
-config FIQ_DEBUGGER
- bool "FIQ Mode Serial Debugger"
- select FIQ
- select FIQ_GLUE
- default n
- help
- The FIQ serial debugger can accept commands even when the
- kernel is unresponsive due to being stuck with interrupts
- disabled.
-
-config FIQ_DEBUGGER_NO_SLEEP
- bool "Keep serial debugger active"
- depends on FIQ_DEBUGGER
- default n
- help
- Enables the serial debugger at boot. Passing
- fiq_debugger.no_sleep on the kernel commandline will
- override this config option.
-
-config FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON
- bool "Don't disable wakeup IRQ when debugger is active"
- depends on FIQ_DEBUGGER
- default n
- help
- Don't disable the wakeup irq when enabling the uart clock. This will
- cause extra interrupts, but it makes the serial debugger usable with
- on some MSM radio builds that ignore the uart clock request in power
- collapse.
-
-config FIQ_DEBUGGER_CONSOLE
- bool "Console on FIQ Serial Debugger port"
- depends on FIQ_DEBUGGER
- default n
- help
- Enables a console so that printk messages are displayed on
- the debugger serial port as the occur.
-
-config FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE
- bool "Put the FIQ debugger into console mode by default"
- depends on FIQ_DEBUGGER_CONSOLE
- default n
- help
- If enabled, this puts the fiq debugger into console mode by default.
- Otherwise, the fiq debugger will start out in debug mode.
-
config GIC_SET_MULTIPLE_CPUS
bool "Use affinity hint to allow multiple CPUs for IRQ"
depends on ARM_GIC && SMP
diff --git a/arch/arm/common/fiq_debugger.c b/arch/arm/common/fiq_debugger.c
index 4156a7f51d62..2f10fea529b1 100644
--- a/arch/arm/common/fiq_debugger.c
+++ b/arch/arm/common/fiq_debugger.c
@@ -454,15 +454,21 @@ static void fiq_debugger_help(struct fiq_debugger_state *state)
#endif
}
-static void fiq_debugger_take_affinity(void *info)
+
+static void change_cpu_affinity(int fiq, int cpu)
{
- struct fiq_debugger_state *state = info;
struct cpumask cpumask;
cpumask_clear(&cpumask);
- cpumask_set_cpu(get_cpu(), &cpumask);
+ cpumask_set_cpu(cpu, &cpumask);
+ irq_set_affinity(fiq, &cpumask);
+}
- irq_set_affinity(state->uart_irq, &cpumask);
+static void fiq_debugger_take_affinity(void *info)
+{
+ struct fiq_debugger_state *state = info;
+
+ change_cpu_affinity(state->uart_irq, get_cpu());
}
static void fiq_debugger_switch_cpu(struct fiq_debugger_state *state, int cpu)
@@ -739,11 +745,33 @@ static void fiq_debugger_fiq(struct fiq_glue_handler *h,
unsigned int this_cpu = THREAD_INFO(svc_sp)->cpu;
bool need_irq;
+ unsigned int next_cpu;
+ static bool cpu0_again;
+
+ /*
+ * 1st FIQ always goes to CPU0. We will change FIQ CPU affinity, if CPU0
+ * enter the FIQ handler 2nd time, we know we have already done the
+ * stack dump for all CPUs and we can enter the debug console.
+ */
+ if (cpu0_again) {
+ need_irq = fiq_debugger_handle_uart_interrupt(state,
+ this_cpu, regs, svc_sp);
+ if (need_irq)
+ fiq_debugger_force_irq(state);
+ return;
+ }
+
+ fiq_debugger_dump_allregs(&state->output, regs);
+ fiq_debugger_dump_pc(&state->output, regs);
+ fiq_debugger_dump_stacktrace(&state->output, regs, 100, svc_sp);
+ /* let another online CPU handle the FIQ */
+ next_cpu = cpumask_next(this_cpu, cpu_online_mask);
+ if (next_cpu >= nr_cpu_ids) {
+ next_cpu = 0;
+ cpu0_again = true;
+ }
+ change_cpu_affinity(state->fiq, next_cpu);
- need_irq = fiq_debugger_handle_uart_interrupt(state, this_cpu, regs,
- svc_sp);
- if (need_irq)
- fiq_debugger_force_irq(state);
}
#endif
diff --git a/arch/arm/configs/tegra12_defconfig b/arch/arm/configs/tegra12_defconfig
index 01bcc94e8189..19a64000cc89 100644
--- a/arch/arm/configs/tegra12_defconfig
+++ b/arch/arm/configs/tegra12_defconfig
@@ -564,13 +564,3 @@ CONFIG_CRYPTO_ARC4=y
CONFIG_CRYPTO_TWOFISH=m
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_DEV_TEGRA_SE=y
-# CONFIG_FIQ is not set
-# CONFIG_TEGRA_FIQ_DEBUGGER is not set
-# CONFIG_FIQ_GLUE is not set
-# CONFIG_FIQ_DEBUGGER is not set
-# CONFIG_FIQ_DEBUGGER_NO_SLEEP is not set
-# CONFIG_FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON is not set
-# CONFIG_FIQ_DEBUGGER_CONSOLE is not set
-# CONFIG_FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE is not set
-# CONFIG_CONSOLE_POLL is not set
-
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 35f648fe57f2..d79a30000f93 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -240,6 +240,53 @@ config TEGRA_SIMULATION_SPLIT_MEM
setup. Select this only if you are an NVIDIA developer
working on a simulation platform.
+config FIQ_DEBUGGER
+ bool "FIQ Mode Serial Debugger"
+ select FIQ
+ select FIQ_GLUE
+ default n
+ help
+ The FIQ serial debugger can accept commands even when the
+ kernel is unresponsive due to being stuck with interrupts
+ disabled. Also, we can save kernel log in FIQ handler.
+ It will not work if FIQ not work or hardware hang.
+
+config FIQ_DEBUGGER_NO_SLEEP
+ bool "Keep serial debugger active"
+ depends on FIQ_DEBUGGER
+ default n
+ help
+ Enables the serial debugger at boot. Passing
+ fiq_debugger.no_sleep on the kernel commandline will
+ override this config option.
+ Enable this config then serial debugger will never off.
+
+config FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON
+ bool "Don't disable wakeup IRQ when debugger is active"
+ depends on FIQ_DEBUGGER
+ default n
+ help
+ Don't disable the wakeup irq when enabling the uart clock. This will
+ cause extra interrupts, but it makes the serial debugger usable with
+ on some MSM radio builds that ignore the uart clock request in power
+ collapse.
+
+config FIQ_DEBUGGER_CONSOLE
+ bool "Console on FIQ Serial Debugger port"
+ depends on FIQ_DEBUGGER
+ default n
+ help
+ Enables a console so that printk messages are displayed on
+ the debugger serial port as the occur.
+
+config FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE
+ bool "Put the FIQ debugger into console mode by default"
+ depends on FIQ_DEBUGGER_CONSOLE
+ default n
+ help
+ If enabled, this puts the fiq debugger into console mode by default.
+ Otherwise, the fiq debugger will start out in debug mode.
+
config TEGRA_FIQ_DEBUGGER
bool "Enable the FIQ serial debugger on Tegra"
default n
@@ -247,6 +294,15 @@ config TEGRA_FIQ_DEBUGGER
help
Enables the FIQ serial debugger on Tegra
+config TEGRA_WDT_FIQ_SOFT_HANG_STACK_DUMP
+ bool "Enable Tegra system soft hang stack dump"
+ default n
+ help
+ This option will generate stack dump for all online CPUs upon
+ soft hang detection by using the FIQ debugger mechanism even
+ the IRQ is disabled on the CPU. This option is useful if we
+ only have one watchdog generating FIQ for all CPUs.
+
config TEGRA_PTM
bool "Enable PTM debugger on Tegra"
default n
diff --git a/arch/arm/mach-tegra/board-ardbeg.c b/arch/arm/mach-tegra/board-ardbeg.c
index f83ccfae2930..46c4d3f338e1 100644
--- a/arch/arm/mach-tegra/board-ardbeg.c
+++ b/arch/arm/mach-tegra/board-ardbeg.c
@@ -415,6 +415,7 @@ static void __init ardbeg_uart_init(void)
#if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
tegra_serial_debug_init(TEGRA_UARTD_BASE, INT_WDT_AVP, NULL, -1, -1);
+ platform_device_register(uart_console_debug_device);
#else
tegra_serial_debug_init(TEGRA_UARTD_BASE, INT_WDT_CPU, NULL, -1, -1);
#endif