* [PATCH 1/7] powerpc: Reduce footprint of irq_stat @ 2010-02-01 6:30 Anton Blanchard 2010-02-01 6:32 ` [PATCH 2/7] powerpc: Reduce footprint of xics_ipi_struct Anton Blanchard 2010-02-01 21:55 ` [PATCH 1/7] powerpc: Reduce footprint of irq_stat Christoph Hellwig 0 siblings, 2 replies; 10+ messages in thread From: Anton Blanchard @ 2010-02-01 6:30 UTC (permalink / raw) To: benh; +Cc: linuxppc-dev PowerPC is currently using asm-generic/hardirq.h which statically allocates an NR_CPUS irq_stat array. Switch to an arch specific implementation which uses per cpu data: On a kernel with NR_CPUS=1024, this saves quite a lot of memory: text data bss dec hex filename 8767938 2944132 1636796 13348866 cbb002 vmlinux.baseline 8767779 2944260 1505724 13217763 c9afe3 vmlinux.irq_cpustat A saving of around 128kB. Signed-off-by: Anton Blanchard <anton@samba.org> --- Index: linux-cpumask/arch/powerpc/include/asm/hardirq.h =================================================================== --- linux-cpumask.orig/arch/powerpc/include/asm/hardirq.h 2010-01-31 22:07:21.037211728 +1100 +++ linux-cpumask/arch/powerpc/include/asm/hardirq.h 2010-02-01 17:28:56.990963256 +1100 @@ -1 +1,22 @@ -#include <asm-generic/hardirq.h> +#ifndef _ASM_POWERPC_HARDIRQ_H +#define _ASM_POWERPC_HARDIRQ_H + +#include <linux/threads.h> +#include <linux/irq.h> + +typedef struct { + unsigned int __softirq_pending; +} ____cacheline_aligned irq_cpustat_t; + +DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); + +#define __ARCH_IRQ_STAT + +#define local_softirq_pending() __get_cpu_var(irq_stat).__softirq_pending + +static inline void ack_bad_irq(unsigned int irq) +{ + printk(KERN_CRIT "unexpected IRQ trap at vector %02x\n", irq); +} + +#endif /* _ASM_POWERPC_HARDIRQ_H */ Index: linux-cpumask/arch/powerpc/kernel/irq.c =================================================================== --- linux-cpumask.orig/arch/powerpc/kernel/irq.c 2010-01-31 22:07:21.027213106 +1100 +++ linux-cpumask/arch/powerpc/kernel/irq.c 2010-02-01 17:28:56.880963661 +1100 @@ -73,6 +73,9 @@ #define CREATE_TRACE_POINTS #include <asm/trace.h> +DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); +EXPORT_PER_CPU_SYMBOL(irq_stat); + int __irq_offset_value; static int ppc_spurious_interrupts; ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 2/7] powerpc: Reduce footprint of xics_ipi_struct 2010-02-01 6:30 [PATCH 1/7] powerpc: Reduce footprint of irq_stat Anton Blanchard @ 2010-02-01 6:32 ` Anton Blanchard 2010-02-01 6:33 ` [PATCH 3/7] powerpc: Rework /proc/interrupts Anton Blanchard 2010-02-01 21:55 ` [PATCH 1/7] powerpc: Reduce footprint of irq_stat Christoph Hellwig 1 sibling, 1 reply; 10+ messages in thread From: Anton Blanchard @ 2010-02-01 6:32 UTC (permalink / raw) To: benh; +Cc: linuxppc-dev Right now we allocate a cacheline sized NR_CPUS array for xics IPI communication. Use DECLARE_PER_CPU_SHARED_ALIGNED to put it in percpu data in its own cacheline since it is written to by other cpus. On a kernel with NR_CPUS=1024, this saves quite a lot of memory: text data bss dec hex filename 8767779 2944260 1505724 13217763 c9afe3 vmlinux.irq_cpustat 8767555 2813444 1505724 13086723 c7b003 vmlinux.xics A saving of around 128kB. Signed-off-by: Anton Blanchard <anton@samba.org> --- Index: linux-cpumask/arch/powerpc/platforms/pseries/xics.c =================================================================== --- linux-cpumask.orig/arch/powerpc/platforms/pseries/xics.c 2010-02-01 17:28:56.980961887 +1100 +++ linux-cpumask/arch/powerpc/platforms/pseries/xics.c 2010-02-01 17:29:00.980963118 +1100 @@ -514,15 +514,13 @@ static void __init xics_init_host(void) /* * XICS only has a single IPI, so encode the messages per CPU */ -struct xics_ipi_struct { - unsigned long value; - } ____cacheline_aligned; - -static struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; +static DEFINE_PER_CPU_SHARED_ALIGNED(unsigned long, xics_ipi_message); static inline void smp_xics_do_message(int cpu, int msg) { - set_bit(msg, &xics_ipi_message[cpu].value); + unsigned long *tgt = &per_cpu(xics_ipi_message, cpu); + + set_bit(msg, tgt); mb(); if (firmware_has_feature(FW_FEATURE_LPAR)) lpar_qirr_info(cpu, IPI_PRIORITY); @@ -548,25 +546,23 @@ void smp_xics_message_pass(int target, i static irqreturn_t xics_ipi_dispatch(int cpu) { + unsigned long *tgt = &per_cpu(xics_ipi_message, cpu); + WARN_ON(cpu_is_offline(cpu)); mb(); /* order mmio clearing qirr */ - while (xics_ipi_message[cpu].value) { - if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, - &xics_ipi_message[cpu].value)) { + while (*tgt) { + if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, tgt)) { smp_message_recv(PPC_MSG_CALL_FUNCTION); } - if (test_and_clear_bit(PPC_MSG_RESCHEDULE, - &xics_ipi_message[cpu].value)) { + if (test_and_clear_bit(PPC_MSG_RESCHEDULE, tgt)) { smp_message_recv(PPC_MSG_RESCHEDULE); } - if (test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE, - &xics_ipi_message[cpu].value)) { + if (test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE, tgt)) { smp_message_recv(PPC_MSG_CALL_FUNC_SINGLE); } #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) - if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK, - &xics_ipi_message[cpu].value)) { + if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK, tgt)) { smp_message_recv(PPC_MSG_DEBUGGER_BREAK); } #endif ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 3/7] powerpc: Rework /proc/interrupts 2010-02-01 6:32 ` [PATCH 2/7] powerpc: Reduce footprint of xics_ipi_struct Anton Blanchard @ 2010-02-01 6:33 ` Anton Blanchard 2010-02-01 6:33 ` [PATCH 4/7] powerpc: Remove whitespace in irq chip name fields Anton Blanchard 0 siblings, 1 reply; 10+ messages in thread From: Anton Blanchard @ 2010-02-01 6:33 UTC (permalink / raw) To: benh; +Cc: linuxppc-dev 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 <anton@samba.org> --- Index: linux-cpumask/arch/powerpc/kernel/irq.c =================================================================== --- linux-cpumask.orig/arch/powerpc/kernel/irq.c 2010-02-01 17:28:56.880963661 +1100 +++ linux-cpumask/arch/powerpc/kernel/irq.c 2010-02-01 17:29:02.007212291 +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; } ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 4/7] powerpc: Remove whitespace in irq chip name fields 2010-02-01 6:33 ` [PATCH 3/7] powerpc: Rework /proc/interrupts Anton Blanchard @ 2010-02-01 6:33 ` Anton Blanchard 2010-02-01 6:34 ` [PATCH 5/7] powerpc: Add timer, performance monitor and machine check counts to /proc/interrupts Anton Blanchard 0 siblings, 1 reply; 10+ messages in thread From: Anton Blanchard @ 2010-02-01 6:33 UTC (permalink / raw) To: benh; +Cc: linuxppc-dev Now we use printf style alignment there is no need to manually space these fields. Signed-off-by: Anton Blanchard <anton@samba.org> --- Index: linux-cpumask/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c =================================================================== --- linux-cpumask.orig/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c 2010-02-01 17:28:56.700961947 +1100 +++ linux-cpumask/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c 2010-02-01 17:29:02.987211921 +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-02-01 17:28:56.750962488 +1100 +++ linux-cpumask/arch/powerpc/platforms/85xx/socrates_fpga_pic.c 2010-02-01 17:29:02.997212166 +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-02-01 17:28:56.720961496 +1100 +++ linux-cpumask/arch/powerpc/platforms/cell/beat_interrupt.c 2010-02-01 17:29:02.997212166 +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-02-01 17:28:56.730973203 +1100 +++ linux-cpumask/arch/powerpc/platforms/cell/interrupt.c 2010-02-01 17:29:02.997212166 +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-02-01 17:28:56.720961496 +1100 +++ linux-cpumask/arch/powerpc/platforms/cell/spider-pic.c 2010-02-01 17:29:02.997212166 +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-02-01 17:28:56.690961770 +1100 +++ linux-cpumask/arch/powerpc/platforms/iseries/irq.c 2010-02-01 17:29:02.997212166 +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-02-01 17:28:56.710961247 +1100 +++ linux-cpumask/arch/powerpc/platforms/powermac/pic.c 2010-02-01 17:29:02.997212166 +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-02-01 17:29:00.980963118 +1100 +++ linux-cpumask/arch/powerpc/platforms/pseries/xics.c 2010-02-01 17:29:02.997212166 +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-02-01 17:28:56.810962592 +1100 +++ linux-cpumask/arch/powerpc/sysdev/cpm1.c 2010-02-01 17:29:02.997212166 +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-02-01 17:28:56.830961830 +1100 +++ linux-cpumask/arch/powerpc/sysdev/cpm2_pic.c 2010-02-01 17:29:02.997212166 +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-02-01 17:28:56.790962373 +1100 +++ linux-cpumask/arch/powerpc/sysdev/fsl_msi.c 2010-02-01 17:29:02.997212166 +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-02-01 17:28:56.800961602 +1100 +++ linux-cpumask/arch/powerpc/sysdev/i8259.c 2010-02-01 17:29:02.997212166 +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-02-01 17:28:56.770971720 +1100 +++ linux-cpumask/arch/powerpc/sysdev/ipic.c 2010-02-01 17:29:02.997212166 +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-02-01 17:28:56.780962529 +1100 +++ linux-cpumask/arch/powerpc/sysdev/mpc8xx_pic.c 2010-02-01 17:29:02.997212166 +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-02-01 17:28:56.820964610 +1100 +++ linux-cpumask/arch/powerpc/sysdev/mpic_pasemi_msi.c 2010-02-01 17:29:02.997212166 +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-02-01 17:28:56.780962529 +1100 +++ linux-cpumask/arch/powerpc/sysdev/qe_lib/qe_ic.c 2010-02-01 17:29:02.997212166 +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-02-01 17:28:56.760964179 +1100 +++ linux-cpumask/arch/powerpc/sysdev/uic.c 2010-02-01 17:29:02.997212166 +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, ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 5/7] powerpc: Add timer, performance monitor and machine check counts to /proc/interrupts 2010-02-01 6:33 ` [PATCH 4/7] powerpc: Remove whitespace in irq chip name fields Anton Blanchard @ 2010-02-01 6:34 ` Anton Blanchard 2010-02-01 6:34 ` [PATCH 6/7] powerpc: Convert global "BAD" interrupt to per cpu spurious Anton Blanchard 0 siblings, 1 reply; 10+ messages in thread From: Anton Blanchard @ 2010-02-01 6:34 UTC (permalink / raw) To: benh; +Cc: linuxppc-dev 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 <anton@samba.org> --- 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-02-01 17:28:56.990963256 +1100 +++ linux-cpumask/arch/powerpc/include/asm/hardirq.h 2010-02-01 17:29:03.887211643 +1100 @@ -6,6 +6,9 @@ typedef struct { unsigned int __softirq_pending; + unsigned int timer_irqs; + unsigned int pmu_irqs; + unsigned int mce_exceptions; } ____cacheline_aligned irq_cpustat_t; DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); @@ -19,4 +22,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-02-01 17:28:56.590961781 +1100 +++ linux-cpumask/arch/powerpc/kernel/time.c 2010-02-01 17:29:03.887211643 +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-02-01 17:29:02.007212291 +1100 +++ linux-cpumask/arch/powerpc/kernel/irq.c 2010-02-01 17:29:03.887211643 +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-02-01 17:28:56.570961322 +1100 +++ linux-cpumask/arch/powerpc/kernel/traps.c 2010-02-01 17:29:03.897211396 +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); } ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 6/7] powerpc: Convert global "BAD" interrupt to per cpu spurious 2010-02-01 6:34 ` [PATCH 5/7] powerpc: Add timer, performance monitor and machine check counts to /proc/interrupts Anton Blanchard @ 2010-02-01 6:34 ` Anton Blanchard 2010-02-01 6:34 ` [PATCH 7/7] powerpc: Increase NR_IRQS Kconfig maximum to 32768 Anton Blanchard 0 siblings, 1 reply; 10+ messages in thread From: Anton Blanchard @ 2010-02-01 6:34 UTC (permalink / raw) To: benh; +Cc: linuxppc-dev 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> --- 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-02-01 17:29:03.887211643 +1100 +++ linux-cpumask/arch/powerpc/include/asm/hardirq.h 2010-02-01 17:29:04.738461552 +1100 @@ -9,6 +9,7 @@ typedef struct { unsigned int timer_irqs; unsigned int pmu_irqs; unsigned int mce_exceptions; + unsigned int spurious_irqs; } ____cacheline_aligned irq_cpustat_t; DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); @@ -25,7 +26,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-02-01 17:29:03.887211643 +1100 +++ linux-cpumask/arch/powerpc/kernel/irq.c 2010-02-01 17:29:04.738461552 +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); ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 7/7] powerpc: Increase NR_IRQS Kconfig maximum to 32768 2010-02-01 6:34 ` [PATCH 6/7] powerpc: Convert global "BAD" interrupt to per cpu spurious Anton Blanchard @ 2010-02-01 6:34 ` Anton Blanchard 0 siblings, 0 replies; 10+ messages in thread From: Anton Blanchard @ 2010-02-01 6:34 UTC (permalink / raw) To: benh; +Cc: linuxppc-dev 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 <anton@samba.org> --- Index: linux-cpumask/arch/powerpc/Kconfig =================================================================== --- linux-cpumask.orig/arch/powerpc/Kconfig 2010-02-01 17:28:56.400961742 +1100 +++ linux-cpumask/arch/powerpc/Kconfig 2010-02-01 17:29:05.609711618 +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 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/7] powerpc: Reduce footprint of irq_stat 2010-02-01 6:30 [PATCH 1/7] powerpc: Reduce footprint of irq_stat Anton Blanchard 2010-02-01 6:32 ` [PATCH 2/7] powerpc: Reduce footprint of xics_ipi_struct Anton Blanchard @ 2010-02-01 21:55 ` Christoph Hellwig 2010-02-01 23:07 ` Benjamin Herrenschmidt 1 sibling, 1 reply; 10+ messages in thread From: Christoph Hellwig @ 2010-02-01 21:55 UTC (permalink / raw) To: Anton Blanchard; +Cc: linuxppc-dev On Mon, Feb 01, 2010 at 05:30:23PM +1100, Anton Blanchard wrote: > > PowerPC is currently using asm-generic/hardirq.h which statically allocates an > NR_CPUS irq_stat array. Switch to an arch specific implementation which uses > per cpu data: > > On a kernel with NR_CPUS=1024, this saves quite a lot of memory: > > text data bss dec hex filename > 8767938 2944132 1636796 13348866 cbb002 vmlinux.baseline > 8767779 2944260 1505724 13217763 c9afe3 vmlinux.irq_cpustat > > A saving of around 128kB. > > Signed-off-by: Anton Blanchard <anton@samba.org> > --- > > Index: linux-cpumask/arch/powerpc/include/asm/hardirq.h > =================================================================== > --- linux-cpumask.orig/arch/powerpc/include/asm/hardirq.h 2010-01-31 22:07:21.037211728 +1100 > +++ linux-cpumask/arch/powerpc/include/asm/hardirq.h 2010-02-01 17:28:56.990963256 +1100 > @@ -1 +1,22 @@ > -#include <asm-generic/hardirq.h> > +#ifndef _ASM_POWERPC_HARDIRQ_H > +#define _ASM_POWERPC_HARDIRQ_H > + > +#include <linux/threads.h> > +#include <linux/irq.h> > + > +typedef struct { > + unsigned int __softirq_pending; > +} ____cacheline_aligned irq_cpustat_t; No need to bother with an irq_cpustat_t type at all in this case, just declare a softirq_pending per-cpu variable. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/7] powerpc: Reduce footprint of irq_stat 2010-02-01 21:55 ` [PATCH 1/7] powerpc: Reduce footprint of irq_stat Christoph Hellwig @ 2010-02-01 23:07 ` Benjamin Herrenschmidt 2010-02-02 8:19 ` Christoph Hellwig 0 siblings, 1 reply; 10+ messages in thread From: Benjamin Herrenschmidt @ 2010-02-01 23:07 UTC (permalink / raw) To: Christoph Hellwig; +Cc: linuxppc-dev, Anton Blanchard On Mon, 2010-02-01 at 22:55 +0100, Christoph Hellwig wrote: > > +typedef struct { > > + unsigned int __softirq_pending; > > +} ____cacheline_aligned irq_cpustat_t; > > No need to bother with an irq_cpustat_t type at all in this case, just > declare a softirq_pending per-cpu variable. I think his subsequent patches add members to that struct for CE, MCE etc... stats. Cheers, Ben. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/7] powerpc: Reduce footprint of irq_stat 2010-02-01 23:07 ` Benjamin Herrenschmidt @ 2010-02-02 8:19 ` Christoph Hellwig 0 siblings, 0 replies; 10+ messages in thread From: Christoph Hellwig @ 2010-02-02 8:19 UTC (permalink / raw) To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Christoph Hellwig, Anton Blanchard On Tue, Feb 02, 2010 at 10:07:10AM +1100, Benjamin Herrenschmidt wrote: > On Mon, 2010-02-01 at 22:55 +0100, Christoph Hellwig wrote: > > > > +typedef struct { > > > + unsigned int __softirq_pending; > > > +} ____cacheline_aligned irq_cpustat_t; > > > > No need to bother with an irq_cpustat_t type at all in this case, just > > declare a softirq_pending per-cpu variable. > > I think his subsequent patches add members to that struct for > CE, MCE etc... stats. Well, if you want those in a structure for arch-local reasons please give them an arch-local name. I really want to get rid of the current concept of a generic irq_cpustat_t - it doens't make much sense in it's current form. Instead the API will be the local_softirq_pending() function/macro with arch specific or a generic implementation. ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2010-02-02 8:19 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-02-01 6:30 [PATCH 1/7] powerpc: Reduce footprint of irq_stat Anton Blanchard 2010-02-01 6:32 ` [PATCH 2/7] powerpc: Reduce footprint of xics_ipi_struct Anton Blanchard 2010-02-01 6:33 ` [PATCH 3/7] powerpc: Rework /proc/interrupts Anton Blanchard 2010-02-01 6:33 ` [PATCH 4/7] powerpc: Remove whitespace in irq chip name fields Anton Blanchard 2010-02-01 6:34 ` [PATCH 5/7] powerpc: Add timer, performance monitor and machine check counts to /proc/interrupts Anton Blanchard 2010-02-01 6:34 ` [PATCH 6/7] powerpc: Convert global "BAD" interrupt to per cpu spurious Anton Blanchard 2010-02-01 6:34 ` [PATCH 7/7] powerpc: Increase NR_IRQS Kconfig maximum to 32768 Anton Blanchard 2010-02-01 21:55 ` [PATCH 1/7] powerpc: Reduce footprint of irq_stat Christoph Hellwig 2010-02-01 23:07 ` Benjamin Herrenschmidt 2010-02-02 8:19 ` Christoph Hellwig
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).