[PATCH 1/5] powerpc: Rework /proc/interrupts

STALE6027d

8 messages, 3 authors, 2010-02-01 · open the first message on its own page

[PATCH 1/5] powerpc: Rework /proc/interrupts

From: Anton Blanchard <hidden>
Date: 2010-01-31 11:09:38

On a large machine I noticed the columns of /proc/interrupts failed to line up
with the header after CPU9. At sufficiently large numbers of CPUs it becomes
impossible to line up the CPU number with the counts.

While fixing this I noticed x86 has a number of updates that we may as well
pull in. On PowerPC we currently omit an interrupt completely if there is no
active handler, whereas on x86 it is printed if there is a non zero count.

The x86 code also spaces the first column correctly based on nr_irqs.

Signed-off-by: Anton Blanchard <redacted>
---

This patch follows on from "powerpc: Reduce footprint of irq_stat" and
"powerpc: Reduce footprint of xics_ipi_struct"

Index: linux-cpumask/arch/powerpc/kernel/irq.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/kernel/irq.c	2010-01-30 19:56:31.650960989 +1100
+++ linux-cpumask/arch/powerpc/kernel/irq.c	2010-01-30 22:31:00.037227967 +1100
@@ -183,30 +183,46 @@ notrace void raw_local_irq_restore(unsig
 EXPORT_SYMBOL(raw_local_irq_restore);
 #endif /* CONFIG_PPC64 */
 
+static int show_other_interrupts(struct seq_file *p, int prec)
+{
+	int j;
+
+#if defined(CONFIG_PPC32) && defined(CONFIG_TAU_INT)
+	if (tau_initialized) {
+		seq_printf(p, "%*s: ", prec, "TAU");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ", tau_interrupts(j));
+		seq_puts(p, "  PowerPC             Thermal Assist (cpu temp)\n");
+	}
+#endif /* CONFIG_PPC32 && CONFIG_TAU_INT */
+
+	seq_printf(p, "%*s: %10u\n", prec, "BAD", ppc_spurious_interrupts);
+
+	return 0;
+}
+
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i = *(loff_t *)v, j;
+	unsigned long flags, any_count = 0;
+	int i = *(loff_t *) v, j, prec;
 	struct irqaction *action;
 	struct irq_desc *desc;
-	unsigned long flags;
 
+	if (i > nr_irqs)
+		return 0;
+
+	for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec)
+		j *= 10;
+
+	if (i == nr_irqs)
+		return show_other_interrupts(p, prec);
+
+	/* print header */
 	if (i == 0) {
-		seq_puts(p, "           ");
+		seq_printf(p, "%*s", prec + 8, "");
 		for_each_online_cpu(j)
-			seq_printf(p, "CPU%d       ", j);
+			seq_printf(p, "CPU%-8d", j);
 		seq_putc(p, '\n');
-	} else if (i == nr_irqs) {
-#if defined(CONFIG_PPC32) && defined(CONFIG_TAU_INT)
-		if (tau_initialized){
-			seq_puts(p, "TAU: ");
-			for_each_online_cpu(j)
-				seq_printf(p, "%10u ", tau_interrupts(j));
-			seq_puts(p, "  PowerPC             Thermal Assist (cpu temp)\n");
-		}
-#endif /* CONFIG_PPC32 && CONFIG_TAU_INT*/
-		seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
-
-		return 0;
 	}
 
 	desc = irq_to_desc(i);
@@ -214,34 +230,31 @@ int show_interrupts(struct seq_file *p, 
 		return 0;
 
 	raw_spin_lock_irqsave(&desc->lock, flags);
-
+	for_each_online_cpu(j)
+		any_count |= kstat_irqs_cpu(i, j);
 	action = desc->action;
-	if (!action || !action->handler)
-		goto skip;
+	if (!action && !any_count)
+		goto out;
 
-	seq_printf(p, "%3d: ", i);
-#ifdef CONFIG_SMP
+	seq_printf(p, "%*d: ", prec, i);
 	for_each_online_cpu(j)
 		seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-#else
-	seq_printf(p, "%10u ", kstat_irqs(i));
-#endif /* CONFIG_SMP */
 
 	if (desc->chip)
-		seq_printf(p, " %s ", desc->chip->name);
+		seq_printf(p, "  %-16s", desc->chip->name);
 	else
-		seq_puts(p, "  None      ");
+		seq_printf(p, "  %-16s", "None");
+	seq_printf(p, " %-8s", (desc->status & IRQ_LEVEL) ? "Level" : "Edge");
 
-	seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge  ");
-	seq_printf(p, "    %s", action->name);
+	if (action) {
+		seq_printf(p, "     %s", action->name);
+		while ((action = action->next) != NULL)
+			seq_printf(p, ", %s", action->name);
+	}
 
-	for (action = action->next; action; action = action->next)
-		seq_printf(p, ", %s", action->name);
 	seq_putc(p, '\n');
-
-skip:
+out:
 	raw_spin_unlock_irqrestore(&desc->lock, flags);
-
 	return 0;
 }
 

[PATCH 2/5] powerpc: Remove whitespace in irq chip name fields

From: Anton Blanchard <hidden>
Date: 2010-01-31 11:10:12

Now we use printf style alignment there is no need to manually space
these fields.

Signed-off-by: Anton Blanchard <redacted>
---

Index: linux-cpumask/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c	2010-01-30 19:56:29.019715672 +1100
+++ linux-cpumask/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c	2010-01-30 19:56:34.010961169 +1100
@@ -79,7 +79,7 @@ cpld_unmask_irq(unsigned int irq)
 }
 
 static struct irq_chip cpld_pic = {
-	.name = " CPLD PIC ",
+	.name = "CPLD PIC",
 	.mask = cpld_mask_irq,
 	.ack = cpld_mask_irq,
 	.unmask = cpld_unmask_irq,
Index: linux-cpumask/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/platforms/85xx/socrates_fpga_pic.c	2010-01-30 19:56:29.079716769 +1100
+++ linux-cpumask/arch/powerpc/platforms/85xx/socrates_fpga_pic.c	2010-01-30 19:56:34.010961169 +1100
@@ -232,7 +232,7 @@ static int socrates_fpga_pic_set_type(un
 }
 
 static struct irq_chip socrates_fpga_pic_chip = {
-	.name		= " FPGA-PIC ",
+	.name		= "FPGA-PIC",
 	.ack		= socrates_fpga_pic_ack,
 	.mask           = socrates_fpga_pic_mask,
 	.mask_ack       = socrates_fpga_pic_mask_ack,
Index: linux-cpumask/arch/powerpc/platforms/cell/beat_interrupt.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/platforms/cell/beat_interrupt.c	2010-01-30 19:56:29.049717504 +1100
+++ linux-cpumask/arch/powerpc/platforms/cell/beat_interrupt.c	2010-01-30 19:56:34.010961169 +1100
@@ -110,7 +110,7 @@ static void beatic_end_irq(unsigned int 
 }
 
 static struct irq_chip beatic_pic = {
-	.name = " CELL-BEAT ",
+	.name = "CELL-BEAT",
 	.unmask = beatic_unmask_irq,
 	.mask = beatic_mask_irq,
 	.eoi = beatic_end_irq,
Index: linux-cpumask/arch/powerpc/platforms/cell/interrupt.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/platforms/cell/interrupt.c	2010-01-30 19:56:29.059714370 +1100
+++ linux-cpumask/arch/powerpc/platforms/cell/interrupt.c	2010-01-30 19:56:34.010961169 +1100
@@ -88,7 +88,7 @@ static void iic_eoi(unsigned int irq)
 }
 
 static struct irq_chip iic_chip = {
-	.name = " CELL-IIC ",
+	.name = "CELL-IIC",
 	.mask = iic_mask,
 	.unmask = iic_unmask,
 	.eoi = iic_eoi,
@@ -133,7 +133,7 @@ static void iic_ioexc_cascade(unsigned i
 
 
 static struct irq_chip iic_ioexc_chip = {
-	.name = " CELL-IOEX",
+	.name = "CELL-IOEX",
 	.mask = iic_mask,
 	.unmask = iic_unmask,
 	.eoi = iic_ioexc_eoi,
Index: linux-cpumask/arch/powerpc/platforms/cell/spider-pic.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/platforms/cell/spider-pic.c	2010-01-30 19:56:29.049717504 +1100
+++ linux-cpumask/arch/powerpc/platforms/cell/spider-pic.c	2010-01-30 19:56:34.010961169 +1100
@@ -168,7 +168,7 @@ static int spider_set_irq_type(unsigned 
 }
 
 static struct irq_chip spider_pic = {
-	.name = " SPIDER   ",
+	.name = "SPIDER",
 	.unmask = spider_unmask_irq,
 	.mask = spider_mask_irq,
 	.ack = spider_ack_irq,
Index: linux-cpumask/arch/powerpc/platforms/iseries/irq.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/platforms/iseries/irq.c	2010-01-30 19:56:29.009711380 +1100
+++ linux-cpumask/arch/powerpc/platforms/iseries/irq.c	2010-01-30 19:56:34.010961169 +1100
@@ -273,7 +273,7 @@ static void iseries_end_IRQ(unsigned int
 }
 
 static struct irq_chip iseries_pic = {
-	.name	= "iSeries irq controller",
+	.name		= "iSeries",
 	.startup	= iseries_startup_IRQ,
 	.shutdown	= iseries_shutdown_IRQ,
 	.unmask		= iseries_enable_IRQ,
Index: linux-cpumask/arch/powerpc/platforms/powermac/pic.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/platforms/powermac/pic.c	2010-01-30 19:56:29.039711810 +1100
+++ linux-cpumask/arch/powerpc/platforms/powermac/pic.c	2010-01-30 19:56:34.010961169 +1100
@@ -195,7 +195,7 @@ static int pmac_retrigger(unsigned int v
 }
 
 static struct irq_chip pmac_pic = {
-	.name		= " PMAC-PIC ",
+	.name		= "PMAC-PIC",
 	.startup	= pmac_startup_irq,
 	.mask		= pmac_mask_irq,
 	.ack		= pmac_ack_irq,
Index: linux-cpumask/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/platforms/pseries/xics.c	2010-01-30 19:56:32.388460978 +1100
+++ linux-cpumask/arch/powerpc/platforms/pseries/xics.c	2010-01-30 19:56:34.010961169 +1100
@@ -428,7 +428,7 @@ static int xics_set_affinity(unsigned in
 }
 
 static struct irq_chip xics_pic_direct = {
-	.name = " XICS     ",
+	.name = "XICS",
 	.startup = xics_startup,
 	.mask = xics_mask_irq,
 	.unmask = xics_unmask_irq,
@@ -437,7 +437,7 @@ static struct irq_chip xics_pic_direct =
 };
 
 static struct irq_chip xics_pic_lpar = {
-	.name = " XICS     ",
+	.name = "XICS",
 	.startup = xics_startup,
 	.mask = xics_mask_irq,
 	.unmask = xics_unmask_irq,
Index: linux-cpumask/arch/powerpc/sysdev/cpm1.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/sysdev/cpm1.c	2010-01-30 19:56:29.129711920 +1100
+++ linux-cpumask/arch/powerpc/sysdev/cpm1.c	2010-01-30 19:56:34.010961169 +1100
@@ -77,7 +77,7 @@ static void cpm_end_irq(unsigned int irq
 }
 
 static struct irq_chip cpm_pic = {
-	.name = " CPM PIC ",
+	.name = "CPM PIC",
 	.mask = cpm_mask_irq,
 	.unmask = cpm_unmask_irq,
 	.eoi = cpm_end_irq,
Index: linux-cpumask/arch/powerpc/sysdev/cpm2_pic.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/sysdev/cpm2_pic.c	2010-01-30 19:56:29.149713109 +1100
+++ linux-cpumask/arch/powerpc/sysdev/cpm2_pic.c	2010-01-30 19:56:34.010961169 +1100
@@ -198,7 +198,7 @@ err_sense:
 }
 
 static struct irq_chip cpm2_pic = {
-	.name = " CPM2 SIU ",
+	.name = "CPM2 SIU",
 	.mask = cpm2_mask_irq,
 	.unmask = cpm2_unmask_irq,
 	.ack = cpm2_ack,
Index: linux-cpumask/arch/powerpc/sysdev/fsl_msi.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/sysdev/fsl_msi.c	2010-01-30 19:56:29.119713229 +1100
+++ linux-cpumask/arch/powerpc/sysdev/fsl_msi.c	2010-01-30 19:56:34.010961169 +1100
@@ -47,7 +47,7 @@ static struct irq_chip fsl_msi_chip = {
 	.mask		= mask_msi_irq,
 	.unmask		= unmask_msi_irq,
 	.ack		= fsl_msi_end_irq,
-	.name	= " FSL-MSI  ",
+	.name		= "FSL-MSI",
 };
 
 static int fsl_msi_host_map(struct irq_host *h, unsigned int virq,
Index: linux-cpumask/arch/powerpc/sysdev/i8259.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/sysdev/i8259.c	2010-01-30 19:56:29.119713229 +1100
+++ linux-cpumask/arch/powerpc/sysdev/i8259.c	2010-01-30 19:56:34.010961169 +1100
@@ -135,7 +135,7 @@ static void i8259_unmask_irq(unsigned in
 }
 
 static struct irq_chip i8259_pic = {
-	.name		= " i8259    ",
+	.name		= "i8259",
 	.mask		= i8259_mask_irq,
 	.disable	= i8259_mask_irq,
 	.unmask		= i8259_unmask_irq,
Index: linux-cpumask/arch/powerpc/sysdev/ipic.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/sysdev/ipic.c	2010-01-30 19:56:29.089713470 +1100
+++ linux-cpumask/arch/powerpc/sysdev/ipic.c	2010-01-30 19:56:34.010961169 +1100
@@ -660,7 +660,7 @@ static int ipic_set_irq_type(unsigned in
 
 /* level interrupts and edge interrupts have different ack operations */
 static struct irq_chip ipic_level_irq_chip = {
-	.name		= " IPIC  ",
+	.name		= "IPIC",
 	.unmask		= ipic_unmask_irq,
 	.mask		= ipic_mask_irq,
 	.mask_ack	= ipic_mask_irq,
@@ -668,7 +668,7 @@ static struct irq_chip ipic_level_irq_ch
 };
 
 static struct irq_chip ipic_edge_irq_chip = {
-	.name		= " IPIC  ",
+	.name		= "IPIC",
 	.unmask		= ipic_unmask_irq,
 	.mask		= ipic_mask_irq,
 	.mask_ack	= ipic_mask_irq_and_ack,
Index: linux-cpumask/arch/powerpc/sysdev/mpc8xx_pic.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/sysdev/mpc8xx_pic.c	2010-01-30 19:56:29.109716536 +1100
+++ linux-cpumask/arch/powerpc/sysdev/mpc8xx_pic.c	2010-01-30 19:56:34.010961169 +1100
@@ -94,7 +94,7 @@ static int mpc8xx_set_irq_type(unsigned 
 }
 
 static struct irq_chip mpc8xx_pic = {
-	.name = " MPC8XX SIU ",
+	.name = "MPC8XX SIU",
 	.unmask = mpc8xx_unmask_irq,
 	.mask = mpc8xx_mask_irq,
 	.ack = mpc8xx_ack,
Index: linux-cpumask/arch/powerpc/sysdev/mpic_pasemi_msi.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/sysdev/mpic_pasemi_msi.c	2010-01-30 19:56:29.139718229 +1100
+++ linux-cpumask/arch/powerpc/sysdev/mpic_pasemi_msi.c	2010-01-30 19:56:34.010961169 +1100
@@ -60,7 +60,7 @@ static struct irq_chip mpic_pasemi_msi_c
 	.eoi		= mpic_end_irq,
 	.set_type	= mpic_set_irq_type,
 	.set_affinity	= mpic_set_affinity,
-	.name		= "PASEMI-MSI ",
+	.name		= "PASEMI-MSI",
 };
 
 static int pasemi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
Index: linux-cpumask/arch/powerpc/sysdev/qe_lib/qe_ic.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/sysdev/qe_lib/qe_ic.c	2010-01-30 19:56:29.099711483 +1100
+++ linux-cpumask/arch/powerpc/sysdev/qe_lib/qe_ic.c	2010-01-30 19:56:34.010961169 +1100
@@ -237,7 +237,7 @@ static void qe_ic_mask_irq(unsigned int 
 }
 
 static struct irq_chip qe_ic_irq_chip = {
-	.name = " QEIC  ",
+	.name = "QEIC",
 	.unmask = qe_ic_unmask_irq,
 	.mask = qe_ic_mask_irq,
 	.mask_ack = qe_ic_mask_irq,
Index: linux-cpumask/arch/powerpc/sysdev/uic.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/sysdev/uic.c	2010-01-30 19:56:29.089713470 +1100
+++ linux-cpumask/arch/powerpc/sysdev/uic.c	2010-01-30 19:56:34.010961169 +1100
@@ -177,7 +177,7 @@ static int uic_set_irq_type(unsigned int
 }
 
 static struct irq_chip uic_irq_chip = {
-	.name		= " UIC  ",
+	.name		= "UIC",
 	.unmask		= uic_unmask_irq,
 	.mask		= uic_mask_irq,
  	.mask_ack	= uic_mask_ack_irq,

[PATCH 3/5] powerpc: Add timer, performance monitor and machine check counts to /proc/interrupts

From: Anton Blanchard <hidden>
Date: 2010-01-31 11:11:55

With NO_HZ it is useful to know how often the decrementer is going off. The
patch below adds an entry for it and also adds it into the /proc/stat
summaries.

While here, I added performance monitoring and machine check exceptions.
I found it useful to keep an eye on the PMU exception rate
when using the perf tool. Since it's possible to take a completely
handled machine check on a System p box it also sounds like a good idea to
keep a machine check summary.

The event naming matches x86 to keep gratuitous differences to a minimum.

Signed-off-by: Anton Blanchard <redacted>
---

If people really don't like the x86 short names, we can think up something
else.

Index: linux-cpumask/arch/powerpc/include/asm/hardirq.h
===================================================================
--- linux-cpumask.orig/arch/powerpc/include/asm/hardirq.h	2010-01-30 20:15:07.148462638 +1100
+++ linux-cpumask/arch/powerpc/include/asm/hardirq.h	2010-01-30 21:33:43.160961369 +1100
@@ -6,6 +6,9 @@
 
 typedef struct {
 	unsigned int __softirq_pending;
+	unsigned int timer_irqs;
+	unsigned int pmu_irqs;
+	unsigned int mce_exceptions;
 #if defined(CONFIG_XICS) && defined(CONFIG_SMP)
 	unsigned long xics_ipi;
 #endif
@@ -22,4 +25,10 @@ static inline void ack_bad_irq(unsigned 
 	printk(KERN_CRIT "unexpected IRQ trap at vector %02x\n", irq);
 }
 
+extern u64 arch_irq_stat_cpu(unsigned int cpu);
+#define arch_irq_stat_cpu	arch_irq_stat_cpu
+
+extern u64 arch_irq_stat(void);
+#define arch_irq_stat		arch_irq_stat
+
 #endif /* _ASM_POWERPC_HARDIRQ_H */
Index: linux-cpumask/arch/powerpc/kernel/time.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/kernel/time.c	2010-01-30 20:15:07.138465242 +1100
+++ linux-cpumask/arch/powerpc/kernel/time.c	2010-01-30 20:15:21.077211379 +1100
@@ -575,6 +575,8 @@ void timer_interrupt(struct pt_regs * re
 
 	trace_timer_interrupt_entry(regs);
 
+	__get_cpu_var(irq_stat).timer_irqs++;
+
 	/* Ensure a positive value is written to the decrementer, or else
 	 * some CPUs will continuue to take decrementer exceptions */
 	set_dec(DECREMENTER_MAX);
Index: linux-cpumask/arch/powerpc/kernel/irq.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/kernel/irq.c	2010-01-30 20:15:17.287210745 +1100
+++ linux-cpumask/arch/powerpc/kernel/irq.c	2010-01-30 21:35:54.528460683 +1100
@@ -196,6 +196,21 @@ static int show_other_interrupts(struct 
 	}
 #endif /* CONFIG_PPC32 && CONFIG_TAU_INT */
 
+	seq_printf(p, "%*s: ", prec, "LOC");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs);
+        seq_printf(p, "  Local timer interrupts\n");
+
+	seq_printf(p, "%*s: ", prec, "CNT");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", per_cpu(irq_stat, j).pmu_irqs);
+	seq_printf(p, "  Performance monitoring interrupts\n");
+
+	seq_printf(p, "%*s: ", prec, "MCE");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", per_cpu(irq_stat, j).mce_exceptions);
+	seq_printf(p, "  Machine check exceptions\n");
+
 	seq_printf(p, "%*s: %10u\n", prec, "BAD", ppc_spurious_interrupts);
 
 	return 0;
@@ -258,6 +273,26 @@ out:
 	return 0;
 }
 
+/*
+ * /proc/stat helpers
+ */
+u64 arch_irq_stat_cpu(unsigned int cpu)
+{
+	u64 sum = per_cpu(irq_stat, cpu).timer_irqs;
+
+	sum += per_cpu(irq_stat, cpu).pmu_irqs;
+	sum += per_cpu(irq_stat, cpu).mce_exceptions;
+
+	return sum;
+}
+
+u64 arch_irq_stat(void)
+{
+	u64 sum = ppc_spurious_interrupts;
+
+	return sum;
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 void fixup_irqs(cpumask_t map)
 {
Index: linux-cpumask/arch/powerpc/kernel/traps.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/kernel/traps.c	2010-01-30 20:15:07.118462038 +1100
+++ linux-cpumask/arch/powerpc/kernel/traps.c	2010-01-30 21:31:57.487211520 +1100
@@ -478,6 +478,8 @@ void machine_check_exception(struct pt_r
 {
 	int recover = 0;
 
+	__get_cpu_var(irq_stat).mce_exceptions++;
+
 	/* See if any machine dependent calls. In theory, we would want
 	 * to call the CPU first, and call the ppc_md. one if the CPU
 	 * one returns a positive number. However there is existing code
@@ -960,6 +962,8 @@ void vsx_unavailable_exception(struct pt
 
 void performance_monitor_exception(struct pt_regs *regs)
 {
+	__get_cpu_var(irq_stat).pmu_irqs++;
+
 	perf_irq(regs);
 }
 

[PATCH 4/5] powerpc: Convert global "BAD" interrupt to per cpu spurious

From: Anton Blanchard <hidden>
Date: 2010-01-31 11:13:15

I often get asked if BAD interrupts are really bad. On some boxes (eg
IBM machines running a hypervisor) there are valid cases where are
presented with an interrupt that is not for us. These cases are common
enough to show up as thousands of BAD interrupts a day.

Tone them down by calling them spurious. Since they can be a significant cause
of OS jitter, we may as well log them per cpu so we know where they are
occurring.

Signed-off-by: Anton Blanchard <redacted>
---

Again, the short name matches x86 but if people are sufficiently confused by
it ("SPU"), then we can think up something else.

Index: linux-cpumask/arch/powerpc/include/asm/hardirq.h
===================================================================
--- linux-cpumask.orig/arch/powerpc/include/asm/hardirq.h	2010-01-30 23:27:24.787211611 +1100
+++ linux-cpumask/arch/powerpc/include/asm/hardirq.h	2010-01-30 23:27:32.277210667 +1100
@@ -9,6 +9,7 @@ typedef struct {
 	unsigned int timer_irqs;
 	unsigned int pmu_irqs;
 	unsigned int mce_exceptions;
+	unsigned int spurious_irqs;
 #if defined(CONFIG_XICS) && defined(CONFIG_SMP)
 	unsigned long xics_ipi;
 #endif
@@ -28,7 +29,4 @@ static inline void ack_bad_irq(unsigned 
 extern u64 arch_irq_stat_cpu(unsigned int cpu);
 #define arch_irq_stat_cpu	arch_irq_stat_cpu
 
-extern u64 arch_irq_stat(void);
-#define arch_irq_stat		arch_irq_stat
-
 #endif /* _ASM_POWERPC_HARDIRQ_H */
Index: linux-cpumask/arch/powerpc/kernel/irq.c
===================================================================
--- linux-cpumask.orig/arch/powerpc/kernel/irq.c	2010-01-30 23:27:24.787211611 +1100
+++ linux-cpumask/arch/powerpc/kernel/irq.c	2010-01-30 23:27:25.080961389 +1100
@@ -77,7 +77,6 @@ DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpusta
 EXPORT_PER_CPU_SYMBOL(irq_stat);
 
 int __irq_offset_value;
-static int ppc_spurious_interrupts;
 
 #ifdef CONFIG_PPC32
 EXPORT_SYMBOL(__irq_offset_value);
@@ -201,6 +200,11 @@ static int show_other_interrupts(struct 
 		seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs);
         seq_printf(p, "  Local timer interrupts\n");
 
+	seq_printf(p, "%*s: ", prec, "SPU");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", per_cpu(irq_stat, j).spurious_irqs);
+	seq_printf(p, "  Spurious interrupts\n");
+
 	seq_printf(p, "%*s: ", prec, "CNT");
 	for_each_online_cpu(j)
 		seq_printf(p, "%10u ", per_cpu(irq_stat, j).pmu_irqs);
@@ -211,8 +215,6 @@ static int show_other_interrupts(struct 
 		seq_printf(p, "%10u ", per_cpu(irq_stat, j).mce_exceptions);
 	seq_printf(p, "  Machine check exceptions\n");
 
-	seq_printf(p, "%*s: %10u\n", prec, "BAD", ppc_spurious_interrupts);
-
 	return 0;
 }
 
@@ -282,13 +284,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
 
 	sum += per_cpu(irq_stat, cpu).pmu_irqs;
 	sum += per_cpu(irq_stat, cpu).mce_exceptions;
-
-	return sum;
-}
-
-u64 arch_irq_stat(void)
-{
-	u64 sum = ppc_spurious_interrupts;
+	sum += per_cpu(irq_stat, cpu).spurious_irqs;
 
 	return sum;
 }
@@ -404,8 +400,7 @@ void do_IRQ(struct pt_regs *regs)
 	if (irq != NO_IRQ && irq != NO_IRQ_IGNORE)
 		handle_one_irq(irq);
 	else if (irq != NO_IRQ_IGNORE)
-		/* That's not SMP safe ... but who cares ? */
-		ppc_spurious_interrupts++;
+		__get_cpu_var(irq_stat).spurious_irqs++;
 
 	irq_exit();
 	set_irq_regs(old_regs);

[PATCH 5/5] powerpc: Increase NR_IRQS Kconfig maximum to 32768

From: Anton Blanchard <hidden>
Date: 2010-01-31 11:14:03

With dynamic irq descriptors the overhead of a large NR_IRQS is much lower
than it used to be. With more MSI-X capable adapters and drivers exploiting 
multiple vectors we may as well allow the user to increase it beyond the
current maximum of 512.

32768 seems large enough that we'd never have to bump it again (although I bet
my prediction is horribly wrong). It boot tests OK and the vmlinux footprint
increase is only around 500kB due to:

struct irq_map_entry irq_map[NR_IRQS];

We format /proc/interrupts correctly with the previous changes:

             CPU0       CPU1       CPU2       CPU3       CPU4       CPU5
  286:          0          0          0          0          0          0     
  516:          0          0          0          0          0          0     
16689:       1833          0          0          0          0          0     
17157:          0          0          0          0          0          0     
17158:        319          0          0          0          0          0     
25092:          0          0          0          0          0          0     

Signed-off-by: Anton Blanchard <redacted>
---

Index: linux-cpumask/arch/powerpc/Kconfig
===================================================================
--- linux-cpumask.orig/arch/powerpc/Kconfig	2010-01-31 15:07:11.707211107 +1100
+++ linux-cpumask/arch/powerpc/Kconfig	2010-01-31 21:52:39.999711689 +1100
@@ -58,7 +58,7 @@ config IRQ_PER_CPU
 
 config NR_IRQS
 	int "Number of virtual interrupt numbers"
-	range 32 512
+	range 32 32768
 	default "512"
 	help
 	  This defines the number of virtual interrupt numbers the kernel

Re: [PATCH 5/5] powerpc: Increase NR_IRQS Kconfig maximum to 32768

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: 2010-01-31 20:35:42

On Sun, 2010-01-31 at 22:14 +1100, Anton Blanchard wrote:
With dynamic irq descriptors the overhead of a large NR_IRQS is much lower
than it used to be. With more MSI-X capable adapters and drivers exploiting 
multiple vectors we may as well allow the user to increase it beyond the
current maximum of 512.

32768 seems large enough that we'd never have to bump it again (although I bet
my prediction is horribly wrong). It boot tests OK and the vmlinux footprint
increase is only around 500kB due to:

struct irq_map_entry irq_map[NR_IRQS];
We could dynamically allocate that one.

Cheers,
Ben.
quoted hunk
We format /proc/interrupts correctly with the previous changes:

             CPU0       CPU1       CPU2       CPU3       CPU4       CPU5
  286:          0          0          0          0          0          0     
  516:          0          0          0          0          0          0     
16689:       1833          0          0          0          0          0     
17157:          0          0          0          0          0          0     
17158:        319          0          0          0          0          0     
25092:          0          0          0          0          0          0     

Signed-off-by: Anton Blanchard <redacted>
---

Index: linux-cpumask/arch/powerpc/Kconfig
===================================================================
--- linux-cpumask.orig/arch/powerpc/Kconfig	2010-01-31 15:07:11.707211107 +1100
+++ linux-cpumask/arch/powerpc/Kconfig	2010-01-31 21:52:39.999711689 +1100
@@ -58,7 +58,7 @@ config IRQ_PER_CPU
 
 config NR_IRQS
 	int "Number of virtual interrupt numbers"
-	range 32 512
+	range 32 32768
 	default "512"
 	help
 	  This defines the number of virtual interrupt numbers the kernel

Re: [PATCH 5/5] powerpc: Increase NR_IRQS Kconfig maximum to 32768

From: Gabriel Paubert <hidden>
Date: 2010-02-01 09:10:02

On Sun, Jan 31, 2010 at 10:14:03PM +1100, Anton Blanchard wrote:
With dynamic irq descriptors the overhead of a large NR_IRQS is much lower
than it used to be. With more MSI-X capable adapters and drivers exploiting 
multiple vectors we may as well allow the user to increase it beyond the
current maximum of 512.

32768 seems large enough that we'd never have to bump it again (although I bet
my prediction is horribly wrong). It boot tests OK and the vmlinux footprint
increase is only around 500kB due to:
Only 1/2 MB? 

I'm running Linux on 12 year old PPC machines which have 16MB
or RAM (ok, they are still running an old kernel, but a few
patches like this and they wont't even boot). The kernels
I have are well below 1MB, code+data+bss. 

Yes it is configurable, thanks, and 64 is enough for these
machines (8259 plus an MPIC), so it's not that crucial.

What I object to is calling 1/2MB negligible.

	Gabriel

Re: [PATCH 5/5] powerpc: Increase NR_IRQS Kconfig maximum to 32768

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: 2010-02-01 10:04:36

On Mon, 2010-02-01 at 10:09 +0100, Gabriel Paubert wrote:
On Sun, Jan 31, 2010 at 10:14:03PM +1100, Anton Blanchard wrote:
quoted
With dynamic irq descriptors the overhead of a large NR_IRQS is much lower
than it used to be. With more MSI-X capable adapters and drivers exploiting 
multiple vectors we may as well allow the user to increase it beyond the
current maximum of 512.

32768 seems large enough that we'd never have to bump it again (although I bet
my prediction is horribly wrong). It boot tests OK and the vmlinux footprint
increase is only around 500kB due to:
Only 1/2 MB? 

I'm running Linux on 12 year old PPC machines which have 16MB
or RAM (ok, they are still running an old kernel, but a few
patches like this and they wont't even boot). The kernels
I have are well below 1MB, code+data+bss. 

Yes it is configurable, thanks, and 64 is enough for these
machines (8259 plus an MPIC), so it's not that crucial.

What I object to is calling 1/2MB negligible.
Yeah well, all Anton did was to push up the -max- value you can set in
the config, not the default :-)

But yeah, it's not "negligible" per-se.

Cheers,
Ben.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help