Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc: Convert global "BAD" interrupt to per cpu spurious

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 <anton@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

authored by

Anton Blanchard and committed by
Benjamin Herrenschmidt
17081102 89713ed1

+8 -15
+1 -3
arch/powerpc/include/asm/hardirq.h
··· 9 9 unsigned int timer_irqs; 10 10 unsigned int pmu_irqs; 11 11 unsigned int mce_exceptions; 12 + unsigned int spurious_irqs; 12 13 } ____cacheline_aligned irq_cpustat_t; 13 14 14 15 DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); ··· 25 24 26 25 extern u64 arch_irq_stat_cpu(unsigned int cpu); 27 26 #define arch_irq_stat_cpu arch_irq_stat_cpu 28 - 29 - extern u64 arch_irq_stat(void); 30 - #define arch_irq_stat arch_irq_stat 31 27 32 28 #endif /* _ASM_POWERPC_HARDIRQ_H */
+7 -12
arch/powerpc/kernel/irq.c
··· 77 77 EXPORT_PER_CPU_SYMBOL(irq_stat); 78 78 79 79 int __irq_offset_value; 80 - static int ppc_spurious_interrupts; 81 80 82 81 #ifdef CONFIG_PPC32 83 82 EXPORT_SYMBOL(__irq_offset_value); ··· 200 201 seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs); 201 202 seq_printf(p, " Local timer interrupts\n"); 202 203 204 + seq_printf(p, "%*s: ", prec, "SPU"); 205 + for_each_online_cpu(j) 206 + seq_printf(p, "%10u ", per_cpu(irq_stat, j).spurious_irqs); 207 + seq_printf(p, " Spurious interrupts\n"); 208 + 203 209 seq_printf(p, "%*s: ", prec, "CNT"); 204 210 for_each_online_cpu(j) 205 211 seq_printf(p, "%10u ", per_cpu(irq_stat, j).pmu_irqs); ··· 214 210 for_each_online_cpu(j) 215 211 seq_printf(p, "%10u ", per_cpu(irq_stat, j).mce_exceptions); 216 212 seq_printf(p, " Machine check exceptions\n"); 217 - 218 - seq_printf(p, "%*s: %10u\n", prec, "BAD", ppc_spurious_interrupts); 219 213 220 214 return 0; 221 215 } ··· 284 282 285 283 sum += per_cpu(irq_stat, cpu).pmu_irqs; 286 284 sum += per_cpu(irq_stat, cpu).mce_exceptions; 287 - 288 - return sum; 289 - } 290 - 291 - u64 arch_irq_stat(void) 292 - { 293 - u64 sum = ppc_spurious_interrupts; 285 + sum += per_cpu(irq_stat, cpu).spurious_irqs; 294 286 295 287 return sum; 296 288 } ··· 400 404 if (irq != NO_IRQ && irq != NO_IRQ_IGNORE) 401 405 handle_one_irq(irq); 402 406 else if (irq != NO_IRQ_IGNORE) 403 - /* That's not SMP safe ... but who cares ? */ 404 - ppc_spurious_interrupts++; 407 + __get_cpu_var(irq_stat).spurious_irqs++; 405 408 406 409 irq_exit(); 407 410 set_irq_regs(old_regs);