Support vector domain on ia64
Subsystems (10)
cover Support vector domain on ia64
Hi,
Here is a series of patches for ia64 vector domain. By these patches, we can use more than NR_VECTORS(256) irqs. This is based on existing x86-64 vector domain code. I tested it on my ia64 box.
Changes from previous patchset:
- rebase to 2.6.22
- remove unnecessary whitespaces
- do the build test for all configs under arch/ia64/configs/
- define NR_IRQS as follow:
Vector domain can provide the number of irqs being proportional to the number of CPUs theoretically. However, the relation between them is actually not linear, especially in large system. To avoid the memory consumption derived from too many irqs, I define NR_IRQS as follows:
#if (NR_VECTORS + 32 * NR_CPUS) < 1024 #define NR_IRQS (NR_VECTORS + 32 * NR_CPUS) #else #define NR_IRQS 1024 #endif
- change initial value of vector_irq to IA64_SPURIOUS_INT_VECTOR. It is pointed by Tony.
http://www.gelato.unsw.edu.au/archives/linux-ia64/0707/20673.html
I marged it into [PATCH take3 8/12]
- add the description of vector domain in Documentation/kernel-parameters.txt
There are 12 patches for ia64 vector domain:
[PATCH take3 1/12] Remove block structure for locking in iosapic.c [PATCH take3 2/12] Remove duplicated members in iosapic_rte_info [PATCH take3 3/12] Cleanup lock order in iosapic_register_intr [PATCH take3 4/12] Use per iosapic lock for indirect iosapic register access [PATCH take3 5/12] Use dynamic irq for iosapic interrupts [PATCH take3 6/12] Fix invalid irq vector assumption for iosapic [PATCH take3 7/12] Check if irq is sharable [PATCH take3 8/12] Add mapping table between irq and vector [PATCH take3 9/12] Add support for vector domain
[PATCH take3 10/12] Support irq migration across domain [PATCH take3 11/12] Enable percpu vector domain for IA64_GENERIC [PATCH take3 12/12] Enable percpu vector domain for IA64_DIG
For more details, please refer to the header of each patch.
Any comments or questions are welcome.
Thanks.
Yasuaki Ishimatsu
Getting close now. New (I think it's new, I didn't notice it last time, but I may have missed it in the other build noise) concern while compiling this version was the warning:
arch/ia64/kernel/iosapic.c:597: warning: 'iosapic_free_rte' defined but not used
This isn't spurious, the only call to iosapic_free_rte() has been removed, but there is still a call to iosapic_alloc_rte() ... which means we must have a memory leak.
-Tony
Quoted 7 lines · Yasuaki Ishimatsu
- define
NR_IRQSas follow:Vector domain can provide the number of irqs being proportional to the number of CPUs theoretically. However, the relation between them is actually not linear, especially in large system. To avoid the memory consumption derived from too many irqs, I define
NR_IRQSas follows:
Quoted 5 lines
#if (NR_VECTORS + 32 * NR_CPUS) < 1024 #define NR_IRQS (NR_VECTORS + 32 * NR_CPUS) #else #define NR_IRQS 1024 #endif
Below is my old patch to address this in a different way. Basically this moves the per cpu counter of the number of times an irq has happened on an individual cpu out of the per cpu area. Honestly I think this might even have better cache performance.
Anyway something to think about.
Eric
From e02f708c0eca6708c8f79824717705379e982fe3 Mon Sep 17 00:00:00 2001
From: Eric W. Biederman <[email protected]>
Date: Tue, 13 Feb 2007 02:42:50 -0700
Subject: [PATCH] genirq: Kill the percpu NR_IRQS sized array in kstat.
In struct kernel_stat which has one instance per cpu we keep a count of how many times each irq has occured on that cpu. Given that we don't usually use all of our irqs this is very wasteful of space and in particular percpu space.
This patch replaces that array on all architectures that use GENERIC_HARD_IRQS with a point to a array of cpus in struct irq_desc. This allocates the array at boot time after we have generated the cpu_possible_map and is only large enough to hold the largest possible cpu index.
Assuming the common case of dense cpu numbers this consumes roughly the same amount of space as the current mechanism and removes the NR_IRQS sized array.
The only immediate win is to get these counts out of the limited size percpu areas.
Shortly I will make the need for NR_IRQS sized arrays obsolete, allowing a single kernel to support huge numbers of irqs and still be efficient on small machines.
With the removal of the NR_IRQS sized arrays this patch will be a clear size win in space consumption for small machines.
--- arch/alpha/kernel/irq.c | 2 +- arch/alpha/kernel/irq_alpha.c | 2 +- arch/arm/kernel/irq.c | 2 +- arch/avr32/kernel/irq.c | 2 +- arch/cris/kernel/irq.c | 2 +- arch/frv/kernel/irq.c | 2 +- arch/i386/kernel/io_apic.c | 2 +- arch/i386/kernel/irq.c | 2 +- arch/i386/mach-visws/visws_apic.c | 2 +- arch/ia64/kernel/irq.c | 2 +- arch/ia64/kernel/irq_ia64.c | 4 ++-- arch/m32r/kernel/irq.c | 2 +- arch/mips/au1000/common/time.c | 4 ++-- arch/mips/kernel/irq.c | 2 +- arch/mips/kernel/time.c | 4 ++-- arch/mips/sgi-ip22/ip22-int.c | 2 +- arch/mips/sgi-ip22/ip22-time.c | 4 ++-- arch/mips/sgi-ip27/ip27-timer.c | 2 +- arch/mips/sibyte/bcm1480/smp.c | 2 +- arch/mips/sibyte/sb1250/irq.c | 2 +- arch/mips/sibyte/sb1250/smp.c | 2 +- arch/parisc/kernel/irq.c | 2 +- arch/powerpc/kernel/irq.c | 2 +- arch/ppc/amiga/amiints.c | 4 ++-- arch/ppc/amiga/cia.c | 2 +- arch/ppc/amiga/ints.c | 4 ++-- arch/sh/kernel/irq.c | 2 +- arch/sparc64/kernel/irq.c | 4 ++-- arch/sparc64/kernel/smp.c | 2 +- arch/um/kernel/irq.c | 2 +- arch/x86_64/kernel/irq.c | 6 +----- arch/xtensa/kernel/irq.c | 2 +- fs/proc/proc_misc.c | 2 +- include/linux/irq.h | 4 ++++ include/linux/kernel_stat.h | 20 +++++++++++++++++--- init/main.c | 1 + kernel/irq/chip.c | 15 +++++---------- kernel/irq/handle.c | 29 +++++++++++++++++++++++++++-- 38 files changed, 94 insertions(+), 59 deletions(-)
arch/alpha/kernel/irq.c +1 -1
@@ -88,7 +88,7 @@ show_interrupts(struct seq_file *p, void *v)seq_printf (p,"%10u " ,kstat_irqs (irq));#else for_each_online_cpu (j) -seq_printf (p,"%10u " ,kstat_cpu (j).irqs[irq]); +seq_printf (p,"%10u " ,kstat_irqs_cpu (i, j));#endif seq_printf (p," %14s" , irq_desc[irq].chip->typename); seq_printf(p, " %c%s",
arch/alpha/kernel/irq_alpha.c +1 -1
@@ -64,7 +64,7 @@ do_entInt(unsigned long type, unsigned long vector,smp_percpu_timer_interrupt (regs); cpu =smp_processor_id ();if (cpu != boot_cpuid) { -kstat_cpu (cpu).irqs[RTC_IRQ ]++; + irq_desc[RTC_IRQ ].kstat_irqs[cpu]++; }else {handle_irq (RTC_IRQ ); }
arch/arm/kernel/irq.c +1 -1
@@ -76,7 +76,7 @@ int show_interrupts(struct seq_file *p, void *v)seq_printf (p,"%3d: " , i);for_each_present_cpu (cpu) -seq_printf (p,"%10u " ,kstat_cpu (cpu).irqs[i]); +seq_printf (p,"%10u " ,kstat_irqs_cpu (i, cpu));seq_printf (p," %10s" , irq_desc[i].chip->name ? :"-" );seq_printf (p," %s" , action->name);for (action = action->next; action; action = action->next)
arch/avr32/kernel/irq.c +1 -1
@@ -56,7 +56,7 @@ int show_interrupts(struct seq_file *p, void *v)seq_printf (p,"%3d: " , i);for_each_online_cpu (cpu) -seq_printf (p,"%10u " ,kstat_cpu (cpu).irqs[i]); +seq_printf (p,"%10u " ,kstat_irqs_cpu (i, cpu));seq_printf (p," %8s" , irq_desc[i].chip->name ? :"-" );seq_printf (p," %s" , action->name);for (action = action->next; action; action = action->next)
arch/cris/kernel/irq.c +1 -1
@@ -66,7 +66,7 @@ int show_interrupts(struct seq_file *p, void *v)seq_printf (p,"%10u " ,kstat_irqs (i));#else for_each_online_cpu (j) -seq_printf (p,"%10u " ,kstat_cpu (j).irqs[i]); +seq_printf (p,"%10u " ,kstat_irqs_cpu (i, j));#endif seq_printf (p," %14s" , irq_desc[i].chip->typename);seq_printf (p," %s" , action->name);
arch/frv/kernel/irq.c +1 -1
@@ -75,7 +75,7 @@ int show_interrupts(struct seq_file *p, void *v)if (action) {seq_printf (p,"%3d: " , i);for_each_present_cpu (cpu) -seq_printf (p,"%10u " ,kstat_cpu (cpu).irqs[i]); +seq_printf (p,"%10u " ,kstat_irqs_cpu (i, cpu));seq_printf (p," %10s" , irq_desc[i].chip->name ? :"-" );seq_printf (p," %s" , action->name); for (action = action->next;
arch/i386/kernel/io_apic.c +1 -1
@@ -488,7 +488,7 @@ static void do_irq_balance(void)if ( package_index = i )IRQ_DELTA (package_index,j) =0 ;/* Determine the total count per processor per IRQ */ - value_now = (unsigned long )kstat_cpu (i).irqs[j]; + value_now = (unsigned long )kstat_irqs_cpu (j, i);/* Determine the activity per processor per IRQ */ delta = value_now -LAST_CPU_IRQ (i,j);
arch/i386/kernel/irq.c +1 -1
@@ -279,7 +279,7 @@ int show_interrupts(struct seq_file *p, void *v)seq_printf (p,"%10u " ,kstat_irqs (i));#else for_each_online_cpu (j) -seq_printf (p,"%10u " ,kstat_cpu (j).irqs[i]); +seq_printf (p,"%10u " ,kstat_irqs_cpu (i, j));#endif seq_printf (p," %8s" , irq_desc[i].chip->name);seq_printf (p,"-%-8s" , irq_desc[i].name);
arch/i386/mach-visws/visws_apic.c +1 -1
@@ -240,7 +240,7 @@ static irqreturn_t piix4_master_intr(int irq, void *dev_id)/* * handle this 'virtual interrupt' as a Cobalt one now. */ -kstat_cpu (smp_processor_id ()).irqs[realirq]++; + desc->kstat_irqs[smp_processor_id ()]++;if (likely (desc->action !=NULL ))handle_IRQ_event (realirq, desc->action);
arch/ia64/kernel/irq.c +1 -1
@@ -73,7 +73,7 @@ int show_interrupts(struct seq_file *p, void *v)seq_printf (p,"%10u " ,kstat_irqs (i));#else for_each_online_cpu (j) { -seq_printf (p,"%10u " ,kstat_cpu (j).irqs[i]); +seq_printf (p,"%10u " ,kstat_irqs_cpu (i, j)); }#endif seq_printf (p," %14s" , irq_desc[i].chip->name);
arch/ia64/kernel/irq_ia64.c +2 -2
@@ -181,7 +181,7 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)ia64_srlz_d ();while (vector !=IA64_SPURIOUS_INT_VECTOR ) {if (unlikely (IS_RESCHEDULE (vector))) - kstat_this_cpu.irqs[vector]++; +kstat_irqs_this_cpu (&irq_desc[vector])++;else {ia64_setreg (_IA64_REG_CR_TPR, vector);ia64_srlz_d ();
@@ -228,7 +228,7 @@ void ia64_process_pending_intr(void)*/ while (vector !=IA64_SPURIOUS_INT_VECTOR ) {if (unlikely (IS_RESCHEDULE (vector))) - kstat_this_cpu.irqs[vector]++; +kstat_irqs_this_cpu (&irq_desc[vector])++;else {struct pt_regs *old_regs =set_irq_regs (NULL );
arch/m32r/kernel/irq.c +1 -1
@@ -52,7 +52,7 @@ int show_interrupts(struct seq_file *p, void *v)seq_printf (p,"%10u " ,kstat_irqs (i));#else for_each_online_cpu (j) -seq_printf (p,"%10u " ,kstat_cpu (j).irqs[i]); +seq_printf (p,"%10u " ,kstat_irqs_cpu (i, j));#endif seq_printf (p," %14s" , irq_desc[i].chip->typename);seq_printf (p," %s" , action->name);
arch/mips/au1000/common/time.c +2 -2
@@ -81,13 +81,13 @@ void mips_timer_interrupt(void)int irq =63 ;irq_enter (); - kstat_this_cpu.irqs[irq]++; +kstat_irqs_this_cpu (&irq_desc[irq])++;if (r4k_offset =0 ) goto null; do { - kstat_this_cpu.irqs[irq]++; + kstat_irqs_this_cpu(&irq_desc[irq])++; do_timer(1); #ifndef CONFIG_SMP update_process_times(user_mode(get_irq_regs()));
arch/mips/kernel/irq.c +1 -1
@@ -115,7 +115,7 @@ int show_interrupts(struct seq_file *p, void *v)seq_printf (p,"%10u " ,kstat_irqs (i));#else for_each_online_cpu (j) -seq_printf (p,"%10u " ,kstat_cpu (j).irqs[i]); +seq_printf (p,"%10u " ,kstat_irqs_cpu (i, j));#endif seq_printf (p," %14s" , irq_desc[i].chip->name);seq_printf (p," %s" , action->name);
arch/mips/kernel/time.c +2 -2
@@ -204,7 +204,7 @@ asmlinkage void ll_timer_interrupt(int irq)int r2 = cpu_has_mips_r2;irq_enter (); - kstat_this_cpu.irqs[irq]++; +kstat_irqs_this_cpu (&irq_desc[irq])++;/* * Suckage alert:
@@ -228,7 +228,7 @@ asmlinkage void ll_local_timer_interrupt(int irq) {irq_enter ();if (smp_processor_id () !=0 ) - kstat_this_cpu.irqs[irq]++; +kstat_irqs_this_cpu (&irq_desc[irq])++;/* we keep interrupt disabled all the time */ local_timer_interrupt (irq,NULL );
arch/mips/sgi-ip22/ip22-int.c +1 -1
@@ -164,7 +164,7 @@ static void indy_buserror_irq(void)int irq =SGI_BUSERR_IRQ ;irq_enter (); - kstat_this_cpu.irqs[irq]++; +kstat_irqs_this_cpu (&irq_desc[irq])++;ip22_be_interrupt (irq);irq_exit (); }
arch/mips/sgi-ip22/ip22-time.c +2 -2
@@ -182,7 +182,7 @@ void indy_8254timer_irq(void)char c;irq_enter (); - kstat_this_cpu.irqs[irq]++; +kstat_irqs_this_cpu (&irq_desc[irq])++;printk (KERN_ALERT "Oops, got 8254 interrupt.\n" );ArcRead (0 , &c,1 , &cnt);ArcEnterInteractiveMode ();
@@ -194,7 +194,7 @@ void indy_r4k_timer_interrupt(void)int irq =SGI_TIMER_IRQ ;irq_enter (); - kstat_this_cpu.irqs[irq]++; +kstat_irqs_this_cpu (&irq_desc[irq])++;timer_interrupt (irq,NULL );irq_exit (); }
arch/mips/sgi-ip27/ip27-timer.c +1 -1
@@ -106,7 +106,7 @@ again:if (LOCAL_HUB_L (PI_RT_COUNT ) >= ct_cur[cpu]) goto again; - kstat_this_cpu.irqs[irq]++;/* kstat only for bootcpu? */ + irq_desc[irq].kstat_irqs[cpu]++;/* kstat only for bootcpu? */ if (cpu =0 )do_timer (1 );
arch/mips/sibyte/bcm1480/smp.c +1 -1
@@ -93,7 +93,7 @@ void bcm1480_mailbox_interrupt(void)int cpu =smp_processor_id ();unsigned int action; - kstat_this_cpu.irqs[K_BCM1480_INT_MBOX_0_0 ]++; + irq_desc[K_BCM1480_INT_MBOX_0_0 ].kstat_irqs[cpu]++;/* Load the mailbox register to figure out what we're supposed to do */ action = (__raw_readq (mailbox_0_regs[cpu]) >>48 ) &0xffff ;
arch/mips/sibyte/sb1250/irq.c +1 -1
@@ -390,7 +390,7 @@ static void sb1250_kgdb_interrupt(void)* host to stop the break, since we would see another * interrupt on the end-of-break too) */ - kstat_this_cpu.irqs[kgdb_irq]++; +kstat_irqs_this_cpu (&irq_desc[kgdb_irq])++;mdelay (500 );duart_out (R_DUART_CMD ,V_DUART_MISC_CMD_RESET_BREAK_INT |M_DUART_RX_EN |M_DUART_TX_EN );
arch/mips/sibyte/sb1250/smp.c +1 -1
@@ -81,7 +81,7 @@ void sb1250_mailbox_interrupt(void)int cpu =smp_processor_id ();unsigned int action; - kstat_this_cpu.irqs[K_INT_MBOX_0 ]++; + irq_desc[K_INT_MBOX_0 ].kstat_irqs[cpu]++;/* Load the mailbox register to figure out what we're supposed to do */ action = (____raw_readq (mailbox_regs[cpu]) >>48 ) &0xffff ;
arch/parisc/kernel/irq.c +1 -1
@@ -192,7 +192,7 @@ int show_interrupts(struct seq_file *p, void *v)seq_printf (p,"%3d: " , i);#ifdef CONFIG_SMP for_each_online_cpu (j) -seq_printf (p,"%10u " ,kstat_cpu (j).irqs[i]); +seq_printf (p,"%10u " ,kstat_irqs_cpu (i, j));#else seq_printf (p,"%10u " ,kstat_irqs (i));#endif
arch/powerpc/kernel/irq.c +1 -1
@@ -189,7 +189,7 @@ int show_interrupts(struct seq_file *p, void *v)seq_printf (p,"%3d: " , i);#ifdef CONFIG_SMP for_each_online_cpu (j) -seq_printf (p,"%10u " ,kstat_cpu (j).irqs[i]); +seq_printf (p,"%10u " ,kstat_irqs_cpu (i, j));#else seq_printf (p,"%10u " ,kstat_irqs (i));#endif /* CONFIG_SMP */
arch/ppc/amiga/amiints.c +2 -2
@@ -184,7 +184,7 @@ inline void amiga_do_irq(int irq, struct pt_regs *fp)irq_desc_t *desc = irq_desc + irq;struct irqaction *action = desc->action; -kstat_cpu (0 ).irqs[irq]++; + desc->kstat_irqs[0 ]++; action->handler (irq, action->dev_id, fp); }
@@ -193,7 +193,7 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp)irq_desc_t *desc = irq_desc + irq;struct irqaction *action; -kstat_cpu (0 ).irqs[irq]++; + desc->kstat_irqs[0 ]++; amiga_custom.intreq = ami_intena_vals[irq];
arch/ppc/amiga/cia.c +1 -1
@@ -146,7 +146,7 @@ static void cia_handler(int irq, void *dev_id, struct pt_regs *fp) amiga_custom.intreq = base->int_mask;for (i =0 ; i <CIA_IRQS ; i++, irq++) {if (ints &1 ) { -kstat_cpu (0 ).irqs[irq]++; + desc->kstat_irqs[0 ]++; action = desc->action; action->handler (irq, action->dev_id, fp); }
arch/ppc/amiga/ints.c +2 -2
@@ -128,7 +128,7 @@ asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) {if (vec >=VEC_INT1 && vec <=VEC_INT7 && !MACH_IS_BVME6000 ) { vec -=VEC_SPUR ; -kstat_cpu (0 ).irqs[vec]++; + irq_desc[vec].kstat_irqs[0 ]++; irq_list[vec].handler (vec, irq_list[vec].dev_id, fp); }else {if (mach_process_int)
@@ -147,7 +147,7 @@ int m68k_get_irq_list(struct seq_file *p, void *v)if (mach_default_handler) {for (i =0 ; i <SYS_IRQS ; i++) {seq_printf (p,"auto %2d: %10u " , i, - i ?kstat_cpu (0 ).irqs[i] : num_spurious); + i ?kstat_irqs_cpu (i,0 ) : num_spurious);seq_puts (p," " );seq_printf (p,"%s\n" , irq_list[i].devname); }
arch/sh/kernel/irq.c +1 -1
@@ -52,7 +52,7 @@ int show_interrupts(struct seq_file *p, void *v) goto unlock;seq_printf (p,"%3d: " ,i);for_each_online_cpu (j) -seq_printf (p,"%10u " ,kstat_cpu (j).irqs[i]); +seq_printf (p,"%10u " ,kstat_cpu (i, j));seq_printf (p," %14s" , irq_desc[i].chip->name);seq_printf (p,"-%-8s" , irq_desc[i].name);seq_printf (p," %s" , action->name);
arch/sparc64/kernel/irq.c +2 -2
@@ -154,7 +154,7 @@ int show_interrupts(struct seq_file *p, void *v)seq_printf (p,"%10u " ,kstat_irqs (i));#else for_each_online_cpu (j) -seq_printf (p,"%10u " ,kstat_cpu (j).irqs[i]); +seq_printf (p,"%10u " ,kstat_irqs_cpu (i, j));#endif seq_printf (p," %9s" , irq_desc[i].chip->typename);seq_printf (p," %s" , action->name);
@@ -605,7 +605,7 @@ void timer_irq(int irq, struct pt_regs *regs) old_regs =set_irq_regs (regs);irq_enter (); - kstat_this_cpu.irqs[0 ]++; + irq_desc[0 ].kstat_irqs[0 ]++;timer_interrupt (irq,NULL );irq_exit ();
arch/sparc64/kernel/smp.c +1 -1
@@ -1212,7 +1212,7 @@ void smp_percpu_timer_interrupt(struct pt_regs *regs)irq_enter ();if (cpu = boot_cpu_id) { - kstat_this_cpu.irqs[0 ]++; + irq_desc[0 ].kstat_irqs[cpu]++;timer_tick_interrupt (regs); }
arch/um/kernel/irq.c +1 -1
@@ -61,7 +61,7 @@ int show_interrupts(struct seq_file *p, void *v)seq_printf (p,"%10u " ,kstat_irqs (i));#else for_each_online_cpu (j) -seq_printf (p,"%10u " ,kstat_cpu (j).irqs[i]); +seq_printf (p,"%10u " ,kstat_irqs_cpu (i, j));#endif seq_printf (p," %14s" , irq_desc[i].chip->typename);seq_printf (p," %s" , action->name);
arch/x86_64/kernel/irq.c +1 -5
@@ -69,12 +69,8 @@ int show_interrupts(struct seq_file *p, void *v)if (!action) goto skip;seq_printf (p,"%3d: " ,i); -#ifndef CONFIG_SMP -seq_printf (p,"%10u " ,kstat_irqs (i)); -#else for_each_online_cpu (j) -seq_printf (p,"%10u " ,kstat_cpu (j).irqs[i]); -#endif +seq_printf (p,"%10u " ,kstat_irqs_cpu (i, j));seq_printf (p," %8s" , irq_desc[i].chip->name);seq_printf (p,"-%-8s" , irq_desc[i].name);
arch/xtensa/kernel/irq.c +1 -1
@@ -99,7 +99,7 @@ int show_interrupts(struct seq_file *p, void *v)seq_printf (p,"%10u " ,kstat_irqs (i));#else for_each_online_cpu (j) -seq_printf (p,"%10u " ,kstat_cpu (j).irqs[i]); +seq_printf (p,"%10u " ,kstat_irqs_cpu (i, j));#endif seq_printf (p," %14s" , irq_desc[i].chip->typename);seq_printf (p," %s" , action->name);
fs/proc/proc_misc.c +1 -1
@@ -472,7 +472,7 @@ static int show_stat(struct seq_file *p, void *v) softirq =cputime64_add (softirq,kstat_cpu (i).cpustat.softirq); steal =cputime64_add (steal,kstat_cpu (i).cpustat.steal);for (j =0 ; j <NR_IRQS ; j++) - sum +=kstat_cpu (i).irqs[j]; + sum +=kstat_irqs_cpu (j, i); } seq_printf(p, "cpu %llu %llu %llu %llu %llu %llu %llu %llu\n",
include/linux/irq.h +4 -0
@@ -156,6 +156,7 @@ struct irq_desc {void *handler_data;void *chip_data;struct irqaction *action;/* IRQ action list */ +unsigned int *kstat_irqs;unsigned int status;/* IRQ status */ unsigned int depth;/* nested irq disables */
@@ -178,6 +179,9 @@ struct irq_desc {extern struct irq_desc irq_desc[NR_IRQS ]; +#define kstat_irqs_this_cpu (DESC ) \ + ((DESC)->kstat_irqs[smp_processor_id()]) +/* * Migration helpers for obsolete names, they will go away: */
include/linux/kernel_stat.h +17 -3
@@ -27,7 +27,9 @@ struct cpu_usage_stat {struct kernel_stat {struct cpu_usage_stat cpustat; +#ifndef CONFIG_GENERIC_HARDIRQS unsigned int irqs[NR_IRQS ]; +#endif }; DECLARE_PER_CPU(struct kernel_stat, kstat);
@@ -38,15 +40,27 @@ DECLARE_PER_CPU(struct kernel_stat, kstat);extern unsigned long long nr_context_switches (void ); +#ifndef CONFIG_GENERIC_HARDIRQS +static inline unsigned int kstat_irqs_cpu (unsigned int irq,int cpu) +{ +return kstat_cpu (cpu).irqs[irq]; +} +static inline void init_kstat_irqs (void ) {} +#else +extern unsigned int kstat_irqs_cpu (unsigned int irq,int cpu); +extern void init_kstat_irqs (void ); +#endif /* CONFIG_GENERIC_HARDIRQS */ +/* * Number of interrupts per specific IRQ source, since bootup */ -static inline int kstat_irqs (int irq) +static inline unsigned int kstat_irqs (unsigned int irq) { -int cpu, sum =0 ; +unsigned int sum =0 ; +int cpu;for_each_possible_cpu (cpu) - sum +=kstat_cpu (cpu).irqs[irq]; + sum +=kstat_irqs_cpu (irq, cpu);return sum; }
init/main.c +1 -0
@@ -559,6 +559,7 @@ asmlinkage void __init start_kernel(void)sort_main_extable ();trap_init ();rcu_init (); +init_kstat_irqs ();init_IRQ ();pidhash_init ();init_timers ();
kernel/irq/chip.c +5 -10
@@ -288,13 +288,12 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc) {struct irqaction *action;irqreturn_t action_ret; -const unsigned int cpu =smp_processor_id ();spin_lock (&desc->lock);if (unlikely (desc->status &IRQ_INPROGRESS )) goto out_unlock; -kstat_cpu (cpu).irqs[irq]++; +kstat_irqs_this_cpu (desc)++; action = desc->action;if (unlikely (!action || (desc->status &IRQ_DISABLED ))) {
@@ -332,7 +331,6 @@ out_unlock: void fastcallhandle_level_irq (unsigned int irq,struct irq_desc *desc) { -unsigned int cpu =smp_processor_id ();struct irqaction *action;irqreturn_t action_ret;
@@ -342,7 +340,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)if (unlikely (desc->status &IRQ_INPROGRESS )) goto out_unlock; desc->status &= ~(IRQ_REPLAY |IRQ_WAITING ); -kstat_cpu (cpu).irqs[irq]++; +kstat_irqs_this_cpu (desc)++;/* * If its disabled or no action available
@@ -383,7 +381,6 @@ out_unlock: void fastcallhandle_fasteoi_irq (unsigned int irq,struct irq_desc *desc) { -unsigned int cpu =smp_processor_id ();struct irqaction *action;irqreturn_t action_ret;
@@ -393,7 +390,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) goto out; desc->status &= ~(IRQ_REPLAY |IRQ_WAITING ); -kstat_cpu (cpu).irqs[irq]++; +kstat_irqs_this_cpu (desc)++;/* * If its disabled or no action available
@@ -442,8 +439,6 @@ out: void fastcallhandle_edge_irq (unsigned int irq,struct irq_desc *desc) { -const unsigned int cpu =smp_processor_id (); -spin_lock (&desc->lock); desc->status &= ~(IRQ_REPLAY |IRQ_WAITING );
@@ -460,7 +455,7 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) goto out_unlock; } -kstat_cpu (cpu).irqs[irq]++; +kstat_irqs_this_cpu (desc)++;/* Start handling the irq */ desc->chip->ack (irq);
@@ -516,7 +511,7 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc) {irqreturn_t action_ret; - kstat_this_cpu.irqs[irq]++; +kstat_irqs_this_cpu (desc)++;if (desc->chip->ack) desc->chip->ack (irq);
kernel/irq/handle.c +27 -2
@@ -15,6 +15,7 @@#include <linux/random.h> #include <linux/interrupt.h> #include <linux/kernel_stat.h> +#include <linux/bootmem.h> #include "internals.h"
@@ -30,7 +31,7 @@ void fastcall handle_bad_irq(unsigned int irq, struct irq_desc *desc) {print_irq_desc (irq, desc); - kstat_this_cpu.irqs[irq]++; +kstat_irqs_this_cpu (desc)++;ack_bad_irq (irq); }
@@ -170,7 +171,7 @@ fastcall unsigned int __do_IRQ(unsigned int irq)struct irqaction *action;unsigned int status; - kstat_this_cpu.irqs[irq]++; +kstat_irqs_this_cpu (desc)++;if (CHECK_IRQ_PER_CPU (desc->status)) {irqreturn_t action_ret;
@@ -269,3 +270,27 @@ void early_init_irq_lock_class(void) }#endif + +__init void init_kstat_irqs (void ) +{ +unsigned entries =0 , cpu; +unsigned int irq; +unsigned bytes; + +/* Compute the worst case size of a per cpu array */ +for_each_possible_cpu (cpu) +if (cpu >= entries) + entries = cpu +1 ; + +/* Compute how many bytes we need per irq and allocate them */ + bytes = entries*sizeof (unsigned int ); +for (irq =0 ; irq <NR_IRQS ; irq++) + irq_desc[irq].kstat_irqs =alloc_bootmem (bytes); +} + +unsigned int kstat_irqs_cpu (unsigned int irq,int cpu) +{ +struct irq_desc *desc = irq_desc + irq; +return desc->kstat_irqs[cpu]; +} +EXPORT_SYMBOL (kstat_irqs_cpu);
Signature · 1 line
1.5.0.g53756
Hi Tony,
Quoted 7 lines · Tony
Getting close now. New (I think it's new, I didn't notice it last time, but I may have missed it in the other build noise) concern while compiling this version was the warning:
arch/ia64/kernel/iosapic.c:597: warning: 'iosapic_free_rte' defined but not usedThis isn't spurious, the only call to
iosapic_free_rte()has been removed, but there is still a call toiosapic_alloc_rte()... which means we must have a memory leak.
I did it on purpose (and gave the warning a miss...) and I consider iosapic_free_rte() is no longer needed.
I decided to remain iosapic_rte_info to keep gsi-to-irq binding after device disable. Indeed it needs some extra memory, but it is only "sizeof(iosapic_rte_info) * <the number of removed devices>" bytes and has no memory leak becasue re-enabled devices use the iosapic_rte_info which they used before disabling.
Here is a iosapic_free_rte() removal patch which remove the warning message and can be applied after 12/12.
Thanks,
Yasuaki Ishimatsu
arch/ia64/kernel/iosapic.c | 8 -------- 1 files changed, 8 deletions(-)
Index: linux-2.6.22/arch/ia64/kernel/iosapic.c
=================================--- linux-2.6.22.orig/arch/ia64/kernel/iosapic.c 2007-07-17 12:09:47.000000000 +0900
+++ linux-2.6.22/arch/ia64/kernel/iosapic.c 2007-07-18 11:59:33.000000000 +0900
@@ -593,14 +593,6 @@ static struct iosapic_rte_info *iosapic_
return rte;
}
-static void iosapic_free_rte (struct iosapic_rte_info *rte) -{
- if (rte->flags & RTE_PREALLOCATED)
- list_add_tail(&rte->rte_list, &free_rte_list);
- else
- kfree(rte);
-}
-
static inline int irq_is_shared (int irq)
{
return (iosapic_intr_info[irq].count > 1);
Hi Eric,
Quoted 16 lines · Eric W. Biederman
Quoted 7 lines · Yasuaki Ishimatsu
- define
NR_IRQSas follow:Vector domain can provide the number of irqs being proportional to the number of CPUs theoretically. However, the relation between them is actually not linear, especially in large system. To avoid the memory consumption derived from too many irqs, I define
NR_IRQSas follows:Quoted 5 lines
#if (NR_VECTORS + 32 * NR_CPUS) < 1024 #define NR_IRQS (NR_VECTORS + 32 * NR_CPUS) #else #define NR_IRQS 1024 #endif
Quoted 5 lines
Below is my old patch to address this in a different way. Basically this moves the per cpu counter of the number of times an irq has happened on an individual cpu out of the per cpu area. Honestly I think this might even have better cache performance.
Sorry for my late reply.
I overviewed your patch and the patch looks good to me. It can improve not only ia64 vector domain but also x86_64 vector domain. I'll consider testing the patch after rebasing it, and if it'll be OK, including your idea (or similar one) into my patchset.
BTW, I googled to find the discussion related to your patch, but can't find it at all. Where did you submit it to?
Thanks,
Yasuaki Ishimatsu
Quoted 27 lines · Yasuaki Ishimatsu
Hi Eric,
Quoted 16 lines · Eric W. Biederman
Quoted 7 lines · Yasuaki Ishimatsu
- define
NR_IRQSas follow:Vector domain can provide the number of irqs being proportional to the number of CPUs theoretically. However, the relation between them is actually not linear, especially in large system. To avoid the memory consumption derived from too many irqs, I define
NR_IRQSas follows:Quoted 5 lines
#if (NR_VECTORS + 32 * NR_CPUS) < 1024 #define NR_IRQS (NR_VECTORS + 32 * NR_CPUS) #else #define NR_IRQS 1024 #endifQuoted 5 lines
Below is my old patch to address this in a different way. Basically this moves the per cpu counter of the number of times an irq has happened on an individual cpu out of the per cpu area. Honestly I think this might even have better cache performance.
Sorry for my late reply.
Quoted 7 lines
I overviewed your patch and the patch looks good to me. It can improve not only ia64 vector domain but also
x86_64vector domain. I'll consider testing the patch after rebasing it, and if it'll be OK, including your idea (or similar one) into my patchset.BTW, I googled to find the discussion related to your patch, but can't find it at all. Where did you submit it to?
I just started the discussion. :)
Basically I have a tree where I am working on removing all arrays of
size NR_IRQS. Which makes it then possible to assign irq numbers
with a stable scheme even when we have a bunch of them. You might find a little bit about that on linux-arch.
I haven't had time to finish my internal tree merge it anywhere. So the half complete pieces are just sitting on my hard drive.
Eric