summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--drivers/staging/android/Makefile1
-rw-r--r--drivers/watchdog/tegra_wdt.c8
-rw-r--r--include/linux/nmi.h10
-rw-r--r--kernel/watchdog.c3
9 files changed, 113 insertions, 65 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
diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile
index 907b62f56203..0a01e1914905 100644
--- a/drivers/staging/android/Makefile
+++ b/drivers/staging/android/Makefile
@@ -1,7 +1,6 @@
ccflags-y += -I$(src) # needed for trace events
obj-y += ion/
-obj-$(CONFIG_FIQ_DEBUGGER) += fiq_debugger/
obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o
obj-$(CONFIG_ASHMEM) += ashmem.o
diff --git a/drivers/watchdog/tegra_wdt.c b/drivers/watchdog/tegra_wdt.c
index d83adeff021e..59a410038569 100644
--- a/drivers/watchdog/tegra_wdt.c
+++ b/drivers/watchdog/tegra_wdt.c
@@ -157,6 +157,11 @@ static irqreturn_t tegra_wdt_interrupt(int irq, void *dev_id)
#define PMC_RST_STATUS 0x1b4
struct tegra_wdt *tegra_wdt[MAX_NR_CPU_WDT];
+/*
+ * In order to generate the stack dump for the CPU which has IRQ off, we must
+ * use the FIQ. TEGRA WDT can generate the FIQ if we do not ACK the IRQ.
+ */
+bool wdt_nmi_ack_off;
static inline void tegra_wdt_ping(struct tegra_wdt *wdt)
{
@@ -170,7 +175,8 @@ static inline void tegra_wdt_ping(struct tegra_wdt *wdt)
#if !defined(CONFIG_TRUSTED_FOUNDATIONS) && \
defined(CONFIG_ARCH_TEGRA_12x_SOC) && defined(CONFIG_FIQ_DEBUGGER)
- writel(WDT_CMD_START_COUNTER, wdt->wdt_avp_source + WDT_CMD);
+ if (wdt_nmi_ack_off == false)
+ writel(WDT_CMD_START_COUNTER, wdt->wdt_avp_source + WDT_CMD);
#endif
}
diff --git a/include/linux/nmi.h b/include/linux/nmi.h
index a461766a8685..73fc09b5c1ec 100644
--- a/include/linux/nmi.h
+++ b/include/linux/nmi.h
@@ -1,6 +1,8 @@
/*
* linux/include/linux/nmi.h
+ * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
*/
+
#ifndef LINUX_NMI_H
#define LINUX_NMI_H
@@ -57,4 +59,12 @@ extern int proc_dowatchdog(struct ctl_table *, int ,
extern int watchdog_get_lockup_state(void);
#endif
+static inline void set_wdt_nmi_ack_off(void)
+{
+#if defined(CONFIG_TEGRA_WDT_FIQ_SOFT_HANG_STACK_DUMP)
+ extern bool wdt_nmi_ack_off;
+ wdt_nmi_ack_off = true;
+#endif
+}
+
#endif
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 274e737a92e6..38d0aab8a89b 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -2,6 +2,7 @@
* Detect hard and soft lockups on a system
*
* started by Don Zickus, Copyright (C) 2010 Red Hat, Inc.
+ * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
*
* Note: Most of this code is borrowed heavily from the original softlockup
* detector, so thanks to Ingo for the initial implementation.
@@ -415,6 +416,8 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
else
dump_stack();
+ set_wdt_nmi_ack_off();
+
if (softlockup_panic)
panic("softlockup: hung tasks");
__this_cpu_write(soft_watchdog_warn, true);