[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1603346163-21645-3-git-send-email-kernelfans@gmail.com>
Date: Thu, 22 Oct 2020 13:56:02 +0800
From: Pingfan Liu <kernelfans@...il.com>
To: linux-kernel@...r.kernel.org
Cc: Pingfan Liu <kernelfans@...il.com>,
Thomas Gleixner <tglx@...utronix.de>,
Peter Zijlstra <peterz@...radead.org>,
Jisheng Zhang <Jisheng.Zhang@...aptics.com>,
Andrew Morton <akpm@...ux-foundation.org>,
"Guilherme G. Piccoli" <gpiccoli@...onical.com>,
Petr Mladek <pmladek@...e.com>, Marc Zyngier <maz@...nel.org>,
Linus Walleij <linus.walleij@...aro.org>,
afzal mohammed <afzal.mohd.ma@...il.com>,
Lina Iyer <ilina@...eaurora.org>,
"Gustavo A. R. Silva" <gustavo@...eddedor.com>,
Maulik Shah <mkshah@...eaurora.org>,
Al Viro <viro@...iv.linux.org.uk>,
Jonathan Corbet <corbet@....net>,
Pawan Gupta <pawan.kumar.gupta@...ux.intel.com>,
Mike Kravetz <mike.kravetz@...cle.com>,
Oliver Neukum <oneukum@...e.com>, linux-doc@...r.kernel.org,
kexec@...ts.infradead.org
Subject: [PATCH 2/3] kernel/watchdog: suppress max irq when irq floods
The capture kernel should try its best to save the crash info. Normally,
irq flood is caused by some trivial devices, which has no impact on saving
vmcore.
Introducing a parameter "irqflood_suppress" to enable suppress irq flood.
Signed-off-by: Pingfan Liu <kernelfans@...il.com>
Cc: Thomas Gleixner <tglx@...utronix.de>
Cc: Peter Zijlstra <peterz@...radead.org>
Cc: Jisheng Zhang <Jisheng.Zhang@...aptics.com>
Cc: Andrew Morton <akpm@...ux-foundation.org>
Cc: "Guilherme G. Piccoli" <gpiccoli@...onical.com>
Cc: Petr Mladek <pmladek@...e.com>
Cc: Marc Zyngier <maz@...nel.org>
Cc: Linus Walleij <linus.walleij@...aro.org>
Cc: afzal mohammed <afzal.mohd.ma@...il.com>
Cc: Lina Iyer <ilina@...eaurora.org>
Cc: "Gustavo A. R. Silva" <gustavo@...eddedor.com>
Cc: Maulik Shah <mkshah@...eaurora.org>
Cc: Al Viro <viro@...iv.linux.org.uk>
Cc: Jonathan Corbet <corbet@....net>
Cc: Pawan Gupta <pawan.kumar.gupta@...ux.intel.com>
Cc: Mike Kravetz <mike.kravetz@...cle.com>
Cc: Oliver Neukum <oneukum@...e.com>
To: linux-kernel@...r.kernel.org
Cc: linux-doc@...r.kernel.org
Cc: kexec@...ts.infradead.org
---
include/linux/irq.h | 2 ++
kernel/irq/spurious.c | 32 ++++++++++++++++++++++++++++++++
kernel/watchdog.c | 9 ++++++++-
3 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 1b7f4df..140cb61 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -684,6 +684,8 @@ extern void note_interrupt(struct irq_desc *desc, irqreturn_t action_ret);
/* Enable/disable irq debugging output: */
extern int noirqdebug_setup(char *str);
+void suppress_max_irq(void);
+
/* Checks whether the interrupt can be requested by request_irq(): */
extern int can_request_irq(unsigned int irq, unsigned long irqflags);
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index f865e5f..d3d94d6 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -464,3 +464,35 @@ static int __init irqpoll_setup(char *str)
}
__setup("irqpoll", irqpoll_setup);
+
+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
+
+static bool irqflood_suppress;
+
+static int __init irqflood_suppress_setup(char *str)
+{
+ irqflood_suppress = true;
+ pr_info("enable auto suppress irqflood\n");
+ return 1;
+}
+__setup("irqflood_suppress", irqflood_suppress_setup);
+
+void suppress_max_irq(void)
+{
+ unsigned int tmp, maxirq = 0, max = 0;
+ int irq;
+
+ if (!irqflood_suppress)
+ return;
+ for_each_active_irq(irq) {
+ tmp = kstat_irqs_cpu(irq, smp_processor_id());
+ if (max < tmp) {
+ maxirq = irq;
+ max = tmp;
+ }
+ }
+ pr_warn("Suppress irq:%u, which is triggered %u times\n",
+ maxirq, max);
+ disable_irq_nosync(maxirq);
+}
+#endif
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 230ac38..28a74e5 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -24,6 +24,7 @@
#include <linux/sched/isolation.h>
#include <linux/stop_machine.h>
#include <linux/kernel_stat.h>
+#include <linux/irq.h>
#include <asm/irq_regs.h>
#include <linux/kvm_para.h>
@@ -364,9 +365,15 @@ static void check_irq_flood(void)
percent = irqts * 100 / totalts;
percent = percent < 100 ? percent : 100;
__this_cpu_write(check_hint, -1);
- if (percent >= 98)
+ if (percent >= 98) {
pr_info("Irq flood occupies more than %lu%% of the past %lu seconds\n",
percent, totalts >> 30);
+ /*
+ * Suppress top irq when scheduler does not work for long time and irq
+ * occupies too much time.
+ */
+ suppress_max_irq();
+ }
} else if (cnt == 0) {
__this_cpu_write(last_total_ts, totalts);
__this_cpu_write(last_irq_ts, irqts);
--
2.7.5
Powered by blists - more mailing lists