From 06d56f1a866165cef74ba57f56caee2b4d502c15 Mon Sep 17 00:00:00 2001 From: Huibin Hong Date: Mon, 22 Aug 2022 12:27:29 +0000 Subject: [PATCH] soc: rockchip: debug: rockchip_panic_notify_dump_irqs Dump irqs in one second when hard lock or rcu stall, panic and so on. Signed-off-by: Huibin Hong Change-Id: Ia35d02eef17055bf4f793b72a11c4b7711d81972 --- drivers/soc/rockchip/rockchip_debug.c | 88 +++++++++++++++++++++++++++ drivers/soc/rockchip/rockchip_debug.h | 1 + 2 files changed, 89 insertions(+) diff --git a/drivers/soc/rockchip/rockchip_debug.c b/drivers/soc/rockchip/rockchip_debug.c index d1a1c0514ca2..f6777deee0ae 100644 --- a/drivers/soc/rockchip/rockchip_debug.c +++ b/drivers/soc/rockchip/rockchip_debug.c @@ -55,6 +55,10 @@ #include #include #include +#include +#include +#include + #include "../../staging/android/fiq_debugger/fiq_debugger_priv.h" #include "rockchip_debug.h" @@ -76,6 +80,7 @@ static void __iomem *rockchip_cpu_debug[16]; static void __iomem *rockchip_cs_pmu[16]; static bool edpcsr_present; +static char log_buf[1024]; extern struct atomic_notifier_head hardlock_notifier_list; extern struct atomic_notifier_head rcu_stall_notifier_list; @@ -410,6 +415,85 @@ static int rockchip_panic_notify_pmpcsr(struct notifier_block *nb, } #endif +static int rockchip_show_interrupts(char *p, int irq) +{ + static int prec; + char *buf = p; + unsigned long any_count = 0; + int i = irq, j; + struct irqaction *action; + struct irq_desc *desc; + + if (i > nr_irqs) + return 0; + + /* print header and calculate the width of the first column */ + if (i == 0) { + for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec) + j *= 10; + + buf += sprintf(buf, "%*s", prec + 8, ""); + for_each_online_cpu(j) + buf += sprintf(buf, "CPU%-8d", j); + buf += sprintf(buf, "\n"); + } + + desc = irq_to_desc(i); + if (!desc) + goto outsparse; + + if (desc->kstat_irqs) + for_each_online_cpu(j) + any_count |= *per_cpu_ptr(desc->kstat_irqs, j); + + if ((!desc->action || (desc->action && desc->action == &chained_action)) && !any_count) + goto outsparse; + + buf += sprintf(buf, "%*d: ", prec, i); + for_each_online_cpu(j) + buf += sprintf(buf, "%10u ", desc->kstat_irqs ? + *per_cpu_ptr(desc->kstat_irqs, j) : 0); + + if (desc->irq_data.chip) { + if (desc->irq_data.chip->name) + buf += sprintf(buf, " %8s", desc->irq_data.chip->name); + else + buf += sprintf(buf, " %8s", "-"); + } else { + buf += sprintf(buf, " %8s", "None"); + } + if (desc->irq_data.domain) + buf += sprintf(buf, " %*d", prec, (int) desc->irq_data.hwirq); + else + buf += sprintf(buf, " %*s", prec, ""); +#ifdef CONFIG_GENERIC_IRQ_SHOW_LEVEL + buf += sprintf(buf, " %-8s", irqd_is_level_type(&desc->irq_data) ? "Level" : "Edge"); +#endif + if (desc->name) + buf += sprintf(buf, "-%-8s", desc->name); + + action = desc->action; + if (action) { + buf += sprintf(buf, " %s", action->name); + while ((action = action->next) != NULL) + buf += sprintf(buf, ", %s", action->name); + } + + sprintf(buf, "\n"); +outsparse: + return 0; +} + +static void rockchip_panic_notify_dump_irqs(void) +{ + int i = 0; + + for (i = 0; i < nr_irqs; i++) { + if (!rockchip_show_interrupts(log_buf, i) || i == 0) + printk("%s", log_buf); + } +} + static int rockchip_panic_notify(struct notifier_block *nb, unsigned long event, void *p) { @@ -417,6 +501,10 @@ static int rockchip_panic_notify(struct notifier_block *nb, unsigned long event, rockchip_panic_notify_edpcsr(nb, event, p); else rockchip_panic_notify_pmpcsr(nb, event, p); + + rockchip_panic_notify_dump_irqs(); + mdelay(1000); + rockchip_panic_notify_dump_irqs(); return NOTIFY_OK; } static struct notifier_block rockchip_panic_nb = { diff --git a/drivers/soc/rockchip/rockchip_debug.h b/drivers/soc/rockchip/rockchip_debug.h index 82036d8ebf72..755506ab0442 100644 --- a/drivers/soc/rockchip/rockchip_debug.h +++ b/drivers/soc/rockchip/rockchip_debug.h @@ -10,5 +10,6 @@ struct fiq_debugger_output; #if IS_ENABLED(CONFIG_FIQ_DEBUGGER) int rockchip_debug_dump_pcsr(struct fiq_debugger_output *output); #endif +extern struct irqaction chained_action; #endif