Skip to contentSkip to conversation

x86: 64bit support more than 256 irq v2

PATCH In review Yinghai Lu 6 participants 36 messages Jul 29, 2008 – Aug 1, 2008

Subsystems (15)
Network drivers x86 SCSI PCI +11 more subsystems
lore
Share & tools
lore

Yinghai Lu

author
#0 lore raw

PATCH 1/1 x86: 64bit support more than 256 irq v2

Dhaval Giani got:
kernel BUG at arch/x86/kernel/io_apic_64.c:357!
invalid opcode: 0000 [1] SMP
CPU 24

Modules linked in:
Pid: 1, comm: swapper Not tainted 2.6.27-rc1-autokern1 #1
RIP: 0010:[<ffffffff8021bb2e>]  [<ffffffff8021bb2e>] add_pin_to_irq+0x8e/0xa0
RSP: 0018:ffff88032e4b9b30  EFLAGS: 00010216
RAX: 00000000000000f0 RBX: 00000000000000f0 RCX: 0000000000000000
RDX: 000000000000afaf RSI: 0000000000000046 RDI: ffffffff80738234
RBP: 0000000000000006 R08: 0000000000000000 R09: ffff8800280992c0
R10: 0000000000000000 R11: ffffffff80372060 R12: 0000000000000018
R13: 0000000000000001 R14: 0000000000000018 R15: 0000000000000000
FS:  0000000000000000(0000) GS:ffff880bfe733540(0000) knlGS:0000000000000000
CS:  0010 DS: 0018 ES: 0018 CR0: 000000008005003b
CR2: 0000000000000000 CR3: 0000000000201000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process swapper (pid: 1, threadinfo ffff88032e4b8000, task ffff880bfe4ca050)
Stack:  00000000000000f0 0000000000000006 0000000000000001 ffffffff8021bbbe
 00000000000000f0 0000000000000001 0000000000000000 ffff88032e4b9c0c
 00000000000000f0 ffffffff80218d81 00000000000000f0 0000000000000000
Call Trace:
 [<ffffffff8021bbbe>] ? io_apic_set_pci_routing+0x7e/0xa0
 [<ffffffff80218d81>] ? mp_register_gsi+0xb1/0xd0
 [<ffffffff80218e0c>] ? acpi_register_gsi+0x6c/0x70
 [<ffffffff80392f30>] ? acpi_pci_irq_enable+0x178/0x260
 [<ffffffff80392cdd>] ? acpi_pci_allocate_irq+0x0/0x4c
 [<ffffffff80370657>] ? pci_enable_resources+0x27/0x160
 [<ffffffff8036be6a>] ? do_pci_enable_device+0x4a/0x70
 [<ffffffff8036bee1>] ? __pci_enable_device_flags+0x51/0x60
 [<ffffffff804e01e8>] ? tg3_init_one+0x58/0x1640
 [<ffffffff8022a980>] ? default_wake_function+0x0/0x10
 [<ffffffff8022efd8>] ? set_cpus_allowed_ptr+0xe8/0x110
 [<ffffffff8036e28f>] ? pci_device_probe+0xdf/0x130
 [<ffffffff803c2416>] ? driver_probe_device+0x96/0x1a0
 [<ffffffff803c25a9>] ? __driver_attach+0x89/0x90
 [<ffffffff803c2520>] ? __driver_attach+0x0/0x90
 [<ffffffff803c1a8d>] ? bus_for_each_dev+0x4d/0x80
 [<ffffffff8028e168>] ? kmem_cache_alloc+0xc8/0xf0
 [<ffffffff803c1f7e>] ? bus_add_driver+0xae/0x220
 [<ffffffff803c2836>] ? driver_register+0x56/0x130
 [<ffffffff8036e548>] ? __pci_register_driver+0x68/0xb0
 [<ffffffff806cf8e0>] ? tg3_init+0x0/0x20
 [<ffffffff806b15b1>] ? do_one_initcall+0x41/0x180
 [<ffffffff802d8a08>] ? create_proc_entry+0x58/0xa0
 [<ffffffff80261cc4>] ? register_irq_proc+0xd4/0xf0
 [<ffffffff806b1b53>] ? kernel_init+0x133/0x190
 [<ffffffff8020c529>] ? child_rip+0xa/0x11
 [<ffffffff806b1a20>] ? kernel_init+0x0/0x190
 [<ffffffff8020c51f>] ? child_rip+0x0/0x11


Code: 89 05 2b 54 42 00 7f 27 48 0f bf c1 48 8d 14 00 48 c1 e0 03 48 29 d0 48 8d 90 c0 5e 73 80 66 89 2a 66 44 89 62 02 5b 5d 41 5c c3 <0f> 0b eb fe 48 c7 c7 c8 db 5c 80 31 c0 e8 60 7e 01 00 48 83 ec
RIP  [<ffffffff8021bb2e>] add_pin_to_irq+0x8e/0xa0
 RSP <ffff88032e4b9b30>

his system (x3950) has 8 ioapic, irq > 256

caused by
commit 9b7dc567d03d74a1fbae84e88949b6a60d922d82
Author: Thomas Gleixner <[email protected]>
Date: Fri May 2 20:10:09 2008 +0200

x86: unify interrupt vector defines

The interrupt vector defines are copied 4 times around with minimal differences. Move them all into asm-x86/irq_vectors.h

64bit allow same vector for different cpu to serve different irq

also change next in irq_pin_list from short to int. because for 4096 NR_IRQS is 2^(8+12).

v2: accoding to Eric W. Biederman, change to NR_IRQ_VECTORS to NR_IRQS
use NR_VECTORS*NR_CPUS directly

need to create that array dynamically later

---
 arch/x86/kernel/io_apic_64.c  |    3 ++-
 include/asm-x86/irq_vectors.h |   14 ++++++--------
 2 files changed, 8 insertions(+), 9 deletions(-)
include/asm-x86/irq_vectors.h +6 -8
Index: linux-2.6/include/asm-x86/irq_vectors.h
===================================================================
@@ -113,28 +113,26 @@
 
 # if defined(CONFIG_X86_IO_APIC) || defined(CONFIG_PARAVIRT) || defined(CONFIG_X86_VISWS)
 
+#ifdef CONFIG_X86_64
+#  define NR_IRQS		(NR_VECTORS * NR_CPUS)
+#else
 #  define NR_IRQS		224
-
-#  if (224 >= 32 * NR_CPUS)
-#   define NR_IRQ_VECTORS	NR_IRQS
-#  else
-#   define NR_IRQ_VECTORS	(32 * NR_CPUS)
-#  endif
+#endif
 
 # else /* IO_APIC || PARAVIRT */
 
 #  define NR_IRQS		16
-#  define NR_IRQ_VECTORS	NR_IRQS
 
 # endif
 
 #else /* !VISWS && !VOYAGER */
 
 # define NR_IRQS		224
-# define NR_IRQ_VECTORS		NR_IRQS
 
 #endif /* VISWS */
 
+#define NR_IRQ_VECTORS		NR_IRQS
+
 /* Voyager specific defines */
 /* These define the CPIs we use in linux */
 #define VIC_CPI_LEVEL0			0
arch/x86/kernel/io_apic_64.c +2 -1
Index: linux-2.6/arch/x86/kernel/io_apic_64.c
===================================================================
@@ -140,7 +140,8 @@ DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BU
  */
 
 static struct irq_pin_list {
-	short apic, pin, next;
+	short apic, pin;
+	int next;
 } irq_2_pin[PIN_MAP_SIZE];
 
 struct io_apic {
author
#1 lore raw
Quoted 73 lines · Yinghai Lu

Dhaval Giani got:
kernel BUG at arch/x86/kernel/io_apic_64.c:357!
invalid opcode: 0000 [1] SMP
CPU 24

Modules linked in:
Pid: 1, comm: swapper Not tainted 2.6.27-rc1-autokern1 #1
RIP: 0010:[<ffffffff8021bb2e>]  [<ffffffff8021bb2e>] add_pin_to_irq+0x8e/0xa0
RSP: 0018:ffff88032e4b9b30  EFLAGS: 00010216
RAX: 00000000000000f0 RBX: 00000000000000f0 RCX: 0000000000000000
RDX: 000000000000afaf RSI: 0000000000000046 RDI: ffffffff80738234
RBP: 0000000000000006 R08: 0000000000000000 R09: ffff8800280992c0
R10: 0000000000000000 R11: ffffffff80372060 R12: 0000000000000018
R13: 0000000000000001 R14: 0000000000000018 R15: 0000000000000000
FS:  0000000000000000(0000) GS:ffff880bfe733540(0000) knlGS:0000000000000000
CS:  0010 DS: 0018 ES: 0018 CR0: 000000008005003b
CR2: 0000000000000000 CR3: 0000000000201000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process swapper (pid: 1, threadinfo ffff88032e4b8000, task ffff880bfe4ca050)
Stack:  00000000000000f0 0000000000000006 0000000000000001 ffffffff8021bbbe
 00000000000000f0 0000000000000001 0000000000000000 ffff88032e4b9c0c
 00000000000000f0 ffffffff80218d81 00000000000000f0 0000000000000000
Call Trace:
 [<ffffffff8021bbbe>] ? io_apic_set_pci_routing+0x7e/0xa0
 [<ffffffff80218d81>] ? mp_register_gsi+0xb1/0xd0
 [<ffffffff80218e0c>] ? acpi_register_gsi+0x6c/0x70
 [<ffffffff80392f30>] ? acpi_pci_irq_enable+0x178/0x260
 [<ffffffff80392cdd>] ? acpi_pci_allocate_irq+0x0/0x4c
 [<ffffffff80370657>] ? pci_enable_resources+0x27/0x160
 [<ffffffff8036be6a>] ? do_pci_enable_device+0x4a/0x70
 [<ffffffff8036bee1>] ? __pci_enable_device_flags+0x51/0x60
 [<ffffffff804e01e8>] ? tg3_init_one+0x58/0x1640
 [<ffffffff8022a980>] ? default_wake_function+0x0/0x10
 [<ffffffff8022efd8>] ? set_cpus_allowed_ptr+0xe8/0x110
 [<ffffffff8036e28f>] ? pci_device_probe+0xdf/0x130
 [<ffffffff803c2416>] ? driver_probe_device+0x96/0x1a0
 [<ffffffff803c25a9>] ? __driver_attach+0x89/0x90
 [<ffffffff803c2520>] ? __driver_attach+0x0/0x90
 [<ffffffff803c1a8d>] ? bus_for_each_dev+0x4d/0x80
 [<ffffffff8028e168>] ? kmem_cache_alloc+0xc8/0xf0
 [<ffffffff803c1f7e>] ? bus_add_driver+0xae/0x220
 [<ffffffff803c2836>] ? driver_register+0x56/0x130
 [<ffffffff8036e548>] ? __pci_register_driver+0x68/0xb0
 [<ffffffff806cf8e0>] ? tg3_init+0x0/0x20
 [<ffffffff806b15b1>] ? do_one_initcall+0x41/0x180
 [<ffffffff802d8a08>] ? create_proc_entry+0x58/0xa0
 [<ffffffff80261cc4>] ? register_irq_proc+0xd4/0xf0
 [<ffffffff806b1b53>] ? kernel_init+0x133/0x190
 [<ffffffff8020c529>] ? child_rip+0xa/0x11
 [<ffffffff806b1a20>] ? kernel_init+0x0/0x190
 [<ffffffff8020c51f>] ? child_rip+0x0/0x11


Code: 89 05 2b 54 42 00 7f 27 48 0f bf c1 48 8d 14 00 48 c1 e0 03 48 29 d0 48 8d 90 c0 5e 73 80 66 89 2a 66 44 89 62 02 5b 5d 41 5c c3 <0f> 0b eb fe 48 c7 c7 c8 db 5c 80 31 c0 e8 60 7e 01 00 48 83 ec
RIP  [<ffffffff8021bb2e>] add_pin_to_irq+0x8e/0xa0
 RSP <ffff88032e4b9b30>

his system (x3950) has 8 ioapic, irq > 256

caused by
commit 9b7dc567d03d74a1fbae84e88949b6a60d922d82
Author: Thomas Gleixner <[email protected]>
Date: Fri May 2 20:10:09 2008 +0200

x86: unify interrupt vector defines

The interrupt vector defines are copied 4 times around with minimal differences. Move them all into asm-x86/irq_vectors.h

64bit allow same vector for different cpu to serve different irq

Quoted 7 lines

also change next in irq_pin_list from short to int. because for 4096 NR_IRQS is 2^(8+12).

v2: accoding to Eric W. Biederman, change to NR_IRQ_VECTORS to NR_IRQS
use NR_VECTORS*NR_CPUS directly

need to create that array dynamically later

seems MAX_SMP doesn't like it. even can not be built.

working on make NR_IRQS related array to be allocated dynamically.

YH

#2 lore raw
In reply to Yinghai Lu
Quoted 72 lines · Yinghai Lu

Dhaval Giani got:
kernel BUG at arch/x86/kernel/io_apic_64.c:357!
invalid opcode: 0000 [1] SMP
CPU 24

Modules linked in:
Pid: 1, comm: swapper Not tainted 2.6.27-rc1-autokern1 #1
RIP: 0010:[<ffffffff8021bb2e>]  [<ffffffff8021bb2e>] add_pin_to_irq+0x8e/0xa0
RSP: 0018:ffff88032e4b9b30  EFLAGS: 00010216
RAX: 00000000000000f0 RBX: 00000000000000f0 RCX: 0000000000000000
RDX: 000000000000afaf RSI: 0000000000000046 RDI: ffffffff80738234
RBP: 0000000000000006 R08: 0000000000000000 R09: ffff8800280992c0
R10: 0000000000000000 R11: ffffffff80372060 R12: 0000000000000018
R13: 0000000000000001 R14: 0000000000000018 R15: 0000000000000000
FS:  0000000000000000(0000) GS:ffff880bfe733540(0000) knlGS:0000000000000000
CS:  0010 DS: 0018 ES: 0018 CR0: 000000008005003b
CR2: 0000000000000000 CR3: 0000000000201000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process swapper (pid: 1, threadinfo ffff88032e4b8000, task ffff880bfe4ca050)
Stack:  00000000000000f0 0000000000000006 0000000000000001 ffffffff8021bbbe
 00000000000000f0 0000000000000001 0000000000000000 ffff88032e4b9c0c
 00000000000000f0 ffffffff80218d81 00000000000000f0 0000000000000000
Call Trace:
 [<ffffffff8021bbbe>] ? io_apic_set_pci_routing+0x7e/0xa0
 [<ffffffff80218d81>] ? mp_register_gsi+0xb1/0xd0
 [<ffffffff80218e0c>] ? acpi_register_gsi+0x6c/0x70
 [<ffffffff80392f30>] ? acpi_pci_irq_enable+0x178/0x260
 [<ffffffff80392cdd>] ? acpi_pci_allocate_irq+0x0/0x4c
 [<ffffffff80370657>] ? pci_enable_resources+0x27/0x160
 [<ffffffff8036be6a>] ? do_pci_enable_device+0x4a/0x70
 [<ffffffff8036bee1>] ? __pci_enable_device_flags+0x51/0x60
 [<ffffffff804e01e8>] ? tg3_init_one+0x58/0x1640
 [<ffffffff8022a980>] ? default_wake_function+0x0/0x10
 [<ffffffff8022efd8>] ? set_cpus_allowed_ptr+0xe8/0x110
 [<ffffffff8036e28f>] ? pci_device_probe+0xdf/0x130
 [<ffffffff803c2416>] ? driver_probe_device+0x96/0x1a0
 [<ffffffff803c25a9>] ? __driver_attach+0x89/0x90
 [<ffffffff803c2520>] ? __driver_attach+0x0/0x90
 [<ffffffff803c1a8d>] ? bus_for_each_dev+0x4d/0x80
 [<ffffffff8028e168>] ? kmem_cache_alloc+0xc8/0xf0
 [<ffffffff803c1f7e>] ? bus_add_driver+0xae/0x220
 [<ffffffff803c2836>] ? driver_register+0x56/0x130
 [<ffffffff8036e548>] ? __pci_register_driver+0x68/0xb0
 [<ffffffff806cf8e0>] ? tg3_init+0x0/0x20
 [<ffffffff806b15b1>] ? do_one_initcall+0x41/0x180
 [<ffffffff802d8a08>] ? create_proc_entry+0x58/0xa0
 [<ffffffff80261cc4>] ? register_irq_proc+0xd4/0xf0
 [<ffffffff806b1b53>] ? kernel_init+0x133/0x190
 [<ffffffff8020c529>] ? child_rip+0xa/0x11
 [<ffffffff806b1a20>] ? kernel_init+0x0/0x190
 [<ffffffff8020c51f>] ? child_rip+0x0/0x11


Code: 89 05 2b 54 42 00 7f 27 48 0f bf c1 48 8d 14 00 48 c1 e0 03 48 29 d0 48 8d

90 c0 5e 73 80 66 89 2a 66 44 89 62 02 5b 5d 41 5c c3 <0f> 0b eb fe 48 c7 c7 c8 db 5c 80 31 c0 e8 60 7e 01 00 48 83 ec
RIP [<ffffffff8021bb2e>] add_pin_to_irq+0x8e/0xa0
RSP <ffff88032e4b9b30>

his system (x3950) has 8 ioapic, irq > 256

caused by
commit 9b7dc567d03d74a1fbae84e88949b6a60d922d82
Author: Thomas Gleixner <[email protected]>
Date: Fri May 2 20:10:09 2008 +0200

x86: unify interrupt vector defines

The interrupt vector defines are copied 4 times around with minimal differences. Move them all into asm-x86/irq_vectors.h

Quoted 7 lines

64bit allow same vector for different cpu to serve different irq

also change next in irq_pin_list from short to int. because for 4096 NR_IRQS is 2^(8+12).

v2: accoding to Eric W. Biederman, change to NR_IRQ_VECTORS to NR_IRQS
use NR_VECTORS*NR_CPUS directly

Apologies I didn't mean to set NR_IRQS to NR_VECTORS*NR_CPUS literally. That simply is a waste of space in current systems.

The original (NR_CPUS*32)+224 is much more reasonable and should cover all of the real world cases.

With respect to NR_IRQ_VECTORS if we can get per_irq vectors on x86_32 we can kill it. I had forgotten a detail.

irq_vector on x86_32 needs to be sized with NR_IRQS.
However acpi_table_parse_madt needs to the true limit on the number of irq sources we can handle which is NR_IRQ_VECTORS. It works because we have cool irq merging and other weird nonsense on x86_32 to fit within 256 irqs.

On x86_64 they are the same.

Eric

author
#3 lore raw

RFC [PATCH] x86: introduce nr_irqs for 64bit

In reply to Yinghai Lu

add DEFINE_DYN_ARRAY for dynamical array support

todo:
1. convert x86 32bit and other arch
2. nr_irqs auto probe via acpi_oem_check?

---
 arch/x86/kernel/io_apic_32.c      |    1 
 arch/x86/kernel/io_apic_64.c      |   59 ++++++++++++++++++++++++--------------
 arch/x86/kernel/irq_64.c          |    8 ++---
 arch/x86/kernel/irqinit_64.c      |    2 -
 arch/x86/kernel/setup.c           |    7 ++++
 arch/x86/kernel/vmlinux_64.lds.S  |    3 +
 drivers/char/hpet.c               |    2 -
 drivers/char/random.c             |    4 +-
 drivers/pci/intr_remapping.c      |   22 +++++++-------
 drivers/serial/8250.c             |    8 +++--
 drivers/serial/serial_core.c      |    2 -
 drivers/xen/events.c              |   12 +++----
 fs/proc/proc_misc.c               |   10 +++---
 include/asm-generic/vmlinux.lds.h |    7 ++++
 include/asm-x86/irq.h             |    4 ++
 include/asm-x86/irq_vectors.h     |   14 +++------
 include/linux/init.h              |   23 ++++++++++++++
 include/linux/irq.h               |    2 -
 init/main.c                       |   20 ++++++++++++
 kernel/irq/autoprobe.c            |   10 +++---
 kernel/irq/chip.c                 |   20 ++++++------
 kernel/irq/handle.c               |   34 +++++++++++++++------
 kernel/irq/manage.c               |   16 +++++-----
 kernel/irq/proc.c                 |    2 -
 kernel/irq/resend.c               |    4 +-
 kernel/irq/spurious.c             |    4 +-
 26 files changed, 199 insertions(+), 101 deletions(-)
arch/x86/kernel/io_apic_32.c +1 -0
Index: linux-2.6/arch/x86/kernel/io_apic_32.c
===================================================================
@@ -70,6 +70,7 @@ int timer_through_8259 __initdata;
  */
 int sis_apic_bug = -1;
 
+int nr_irqs = NR_IRQS;
 /*
  * # of IRQ routing registers
  */
arch/x86/kernel/io_apic_64.c +38 -21

177 lines not on this page · raw message

arch/x86/kernel/irq_64.c +4 -4
Index: linux-2.6/arch/x86/kernel/irq_64.c
===================================================================
@@ -81,7 +81,7 @@ int show_interrupts(struct seq_file *p,
 		seq_putc(p, '\n');
 	}
 
-	if (i < NR_IRQS) {
+	if (i < nr_irqs) {
 		unsigned any_count = 0;
 
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
@@ -112,7 +112,7 @@ int show_interrupts(struct seq_file *p,
 		seq_putc(p, '\n');
 skip:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	} else if (i == NR_IRQS) {
+	} else if (i == nr_irqs) {
 		seq_printf(p, "NMI: ");
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count);
@@ -201,7 +201,7 @@ asmlinkage unsigned int do_IRQ(struct pt
 	stack_overflow_check(regs);
 #endif
 
-	if (likely(irq < NR_IRQS))
+	if (likely(irq < nr_irqs))
 		generic_handle_irq(irq);
 	else {
 		if (!disable_apic)
@@ -224,7 +224,7 @@ void fixup_irqs(cpumask_t map)
 	unsigned int irq;
 	static int warned;
 
-	for (irq = 0; irq < NR_IRQS; irq++) {
+	for (irq = 0; irq < nr_irqs; irq++) {
 		cpumask_t mask;
 		int break_affinity = 0;
 		int set_affinity = 1;
arch/x86/kernel/irqinit_64.c +1 -1
Index: linux-2.6/arch/x86/kernel/irqinit_64.c
===================================================================
@@ -142,7 +142,7 @@ static void __init init_ISA_irqs (void)
 	init_bsp_APIC();
 	init_8259A(0);
 
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 0; i < nr_irqs; i++) {
 		irq_desc[i].status = IRQ_DISABLED;
 		irq_desc[i].action = NULL;
 		irq_desc[i].depth = 1;
arch/x86/kernel/setup.c +7 -0
Index: linux-2.6/arch/x86/kernel/setup.c
===================================================================
@@ -856,7 +856,14 @@ void __init setup_arch(char **cmdline_p)
 #endif
 
 	prefill_possible_map();
+
 #ifdef CONFIG_X86_64
+	/* need to wait for nr_cpu_ids settle down */
+	nr_irqs = NR_VECTORS * nr_cpu_ids;
+	pin_map_size = nr_irqs * 2;
+	first_free_entry = nr_irqs;
+	printk(KERN_INFO "nr_irqs: %d\n", nr_irqs);
+	pre_alloc_dyn_array();
 	init_cpu_to_node();
 #endif
 
arch/x86/kernel/vmlinux_64.lds.S +3 -0
Index: linux-2.6/arch/x86/kernel/vmlinux_64.lds.S
===================================================================
@@ -174,6 +174,9 @@ SECTIONS
 	*(.x86cpuvendor.init)
   }
   __x86cpuvendor_end = .;
+
+  DYN_ARRAY_INIT(8)
+
   SECURITY_INIT
 
   . = ALIGN(8);
drivers/char/hpet.c +1 -1
Index: linux-2.6/drivers/char/hpet.c
===================================================================
@@ -222,7 +222,7 @@ static void hpet_timer_set_irq(struct hp
 	for (irq = find_first_bit(&v, HPET_MAX_IRQ); irq < HPET_MAX_IRQ;
 		irq = find_next_bit(&v, HPET_MAX_IRQ, 1 + irq)) {
 
-		if (irq >= NR_IRQS) {
+		if (irq >= nr_irqs) {
 			irq = HPET_MAX_IRQ;
 			break;
 		}
drivers/char/random.c +2 -2
Index: linux-2.6/drivers/char/random.c
===================================================================
@@ -647,7 +647,7 @@ EXPORT_SYMBOL_GPL(add_input_randomness);
 
 void add_interrupt_randomness(int irq)
 {
-	if (irq >= NR_IRQS || irq_timer_state[irq] == NULL)
+	if (irq >= nr_irqs || irq_timer_state[irq] == NULL)
 		return;
 
 	DEBUG_ENT("irq event %d\n", irq);
@@ -911,7 +911,7 @@ void rand_initialize_irq(int irq)
 {
 	struct timer_rand_state *state;
 
-	if (irq >= NR_IRQS || irq_timer_state[irq])
+	if (irq >= nr_irqs || irq_timer_state[irq])
 		return;
 
 	/*
drivers/pci/intr_remapping.c +12 -10
Index: linux-2.6/drivers/pci/intr_remapping.c
===================================================================
@@ -11,18 +11,20 @@ static struct ioapic_scope ir_ioapic[MAX
 static int ir_ioapic_num;
 int intr_remapping_enabled;
 
-static struct {
+static struct irq_2_iommu {
 	struct intel_iommu *iommu;
 	u16 irte_index;
 	u16 sub_handle;
 	u8  irte_mask;
-} irq_2_iommu[NR_IRQS];
+} *irq_2_iommu;
+
+DEFINE_DYN_ARRAY(irq_2_iommu, sizeof(struct irq_2_iommu), nr_irqs, PAGE_SIZE, NULL);
 
 static DEFINE_SPINLOCK(irq_2_ir_lock);
 
 int irq_remapped(int irq)
 {
-	if (irq > NR_IRQS)
+	if (irq > nr_irqs)
 		return 0;
 
 	if (!irq_2_iommu[irq].iommu)
@@ -35,7 +37,7 @@ int get_irte(int irq, struct irte *entry
 {
 	int index;
 
-	if (!entry || irq > NR_IRQS)
+	if (!entry || irq > nr_irqs)
 		return -1;
 
 	spin_lock(&irq_2_ir_lock);
@@ -126,7 +128,7 @@ int map_irq_to_irte_handle(int irq, u16
 	int index;
 
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || !irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
@@ -140,7 +142,7 @@ int map_irq_to_irte_handle(int irq, u16
 int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
 {
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
@@ -158,7 +160,7 @@ int set_irte_irq(int irq, struct intel_i
 int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index)
 {
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || !irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
@@ -180,7 +182,7 @@ int modify_irte(int irq, struct irte *ir
 	struct intel_iommu *iommu;
 
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || !irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
@@ -205,7 +207,7 @@ int flush_irte(int irq)
 	struct intel_iommu *iommu;
 
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || !irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
@@ -248,7 +250,7 @@ int free_irte(int irq)
 	struct intel_iommu *iommu;
 
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || !irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
drivers/serial/8250.c +5 -3
Index: linux-2.6/drivers/serial/8250.c
===================================================================
@@ -149,7 +149,9 @@ struct irq_info {
 	struct list_head	*head;
 };
 
-static struct irq_info irq_lists[NR_IRQS];
+static struct irq_info *irq_lists;
+
+DEFINE_DYN_ARRAY(irq_lists, sizeof(struct irq_info), nr_irqs, sizeof(struct irq_info), NULL);
 
 /*
  * Here we define the default xmit fifo size used for each type of UART.
@@ -2433,7 +2435,7 @@ static void serial8250_config_port(struc
 static int
 serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
 {
-	if (ser->irq >= NR_IRQS || ser->irq < 0 ||
+	if (ser->irq >= nr_irqs || ser->irq < 0 ||
 	    ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
 	    ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
 	    ser->type == PORT_STARTECH)
@@ -2964,7 +2966,7 @@ static int __init serial8250_init(void)
 		"%d ports, IRQ sharing %sabled\n", nr_uarts,
 		share_irqs ? "en" : "dis");
 
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		spin_lock_init(&irq_lists[i].lock);
 
 	ret = uart_register_driver(&serial8250_reg);
drivers/serial/serial_core.c +1 -1
Index: linux-2.6/drivers/serial/serial_core.c
===================================================================
@@ -741,7 +741,7 @@ static int uart_set_info(struct uart_sta
 	if (port->ops->verify_port)
 		retval = port->ops->verify_port(port, &new_serial);
 
-	if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
+	if ((new_serial.irq >= nr_irqs) || (new_serial.irq < 0) ||
 	    (new_serial.baud_base < 9600))
 		retval = -EINVAL;
 
drivers/xen/events.c +6 -6
Index: linux-2.6/drivers/xen/events.c
===================================================================
@@ -150,7 +150,7 @@ static void init_evtchn_cpu_bindings(voi
 #ifdef CONFIG_SMP
 	int i;
 	/* By default all event channels notify CPU#0. */
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		irq_desc[i].affinity = cpumask_of_cpu(0);
 #endif
 
@@ -234,12 +234,12 @@ static int find_unbound_irq(void)
 	int irq;
 
 	/* Only allocate from dynirq range */
-	for (irq = 0; irq < NR_IRQS; irq++)
+	for (irq = 0; irq < nr_irqs; irq++)
 		if (irq_bindcount[irq] == 0)
 			break;
 
-	if (irq == NR_IRQS)
-		panic("No available IRQ to bind to: increase NR_IRQS!\n");
+	if (irq == nr_irqs)
+		panic("No available IRQ to bind to: increase nr_irqs!\n");
 
 	return irq;
 }
@@ -772,7 +772,7 @@ void xen_irq_resume(void)
 		mask_evtchn(evtchn);
 
 	/* No IRQ <-> event-channel mappings. */
-	for (irq = 0; irq < NR_IRQS; irq++)
+	for (irq = 0; irq < nr_irqs; irq++)
 		irq_info[irq].evtchn = 0; /* zap event-channel binding */
 
 	for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
@@ -804,7 +804,7 @@ void __init xen_init_IRQ(void)
 		mask_evtchn(i);
 
 	/* Dynamic IRQ space is currently unbound. Zero the refcnts. */
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		irq_bindcount[i] = 0;
 
 	irq_ctx_init(smp_processor_id());
fs/proc/proc_misc.c +5 -5
Index: linux-2.6/fs/proc/proc_misc.c
===================================================================
@@ -503,7 +503,7 @@ static int show_stat(struct seq_file *p,
 	struct timespec boottime;
 	unsigned int *per_irq_sum;
 
-	per_irq_sum = kzalloc(sizeof(unsigned int)*NR_IRQS, GFP_KERNEL);
+	per_irq_sum = kzalloc(sizeof(unsigned int)*nr_irqs, GFP_KERNEL);
 	if (!per_irq_sum)
 		return -ENOMEM;
 
@@ -525,7 +525,7 @@ static int show_stat(struct seq_file *p,
 		softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq);
 		steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal);
 		guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest);
-		for (j = 0; j < NR_IRQS; j++) {
+		for (j = 0; j < nr_irqs; j++) {
 			unsigned int temp = kstat_cpu(i).irqs[j];
 			sum += temp;
 			per_irq_sum[j] += temp;
@@ -571,7 +571,7 @@ static int show_stat(struct seq_file *p,
 	}
 	seq_printf(p, "intr %llu", (unsigned long long)sum);
 
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		seq_printf(p, " %u", per_irq_sum[i]);
 
 	seq_printf(p,
@@ -625,13 +625,13 @@ static const struct file_operations proc
  */
 static void *int_seq_start(struct seq_file *f, loff_t *pos)
 {
-	return (*pos <= NR_IRQS) ? pos : NULL;
+	return (*pos <= nr_irqs) ? pos : NULL;
 }
 
 static void *int_seq_next(struct seq_file *f, void *v, loff_t *pos)
 {
 	(*pos)++;
-	if (*pos > NR_IRQS)
+	if (*pos > nr_irqs)
 		return NULL;
 	return pos;
 }
include/asm-generic/vmlinux.lds.h +7 -0
Index: linux-2.6/include/asm-generic/vmlinux.lds.h
===================================================================
@@ -214,6 +214,13 @@
  * All archs are supposed to use RO_DATA() */
 #define RODATA RO_DATA(4096)
 
+#define DYN_ARRAY_INIT(align)							\
+	. = ALIGN((align));						\
+	.dyn_array.init : AT(ADDR(.dyn_array.init) - LOAD_OFFSET) {	\
+		VMLINUX_SYMBOL(__dyn_array_start) = .;			\
+		*(.dyn_array.init)					\
+		VMLINUX_SYMBOL(__dyn_array_end) = .;			\
+	}
 #define SECURITY_INIT							\
 	.security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \
 		VMLINUX_SYMBOL(__security_initcall_start) = .;		\
include/asm-x86/irq.h +4 -0
Index: linux-2.6/include/asm-x86/irq.h
===================================================================
@@ -10,6 +10,10 @@
 #include <asm/apicdef.h>
 #include <asm/irq_vectors.h>
 
+extern int nr_irqs;
+extern int pin_map_size;
+extern int first_free_entry;
+
 static inline int irq_canonicalize(int irq)
 {
 	return ((irq == 2) ? 9 : irq);
include/asm-x86/irq_vectors.h +6 -8
Index: linux-2.6/include/asm-x86/irq_vectors.h
===================================================================
@@ -113,28 +113,26 @@
 
 # if defined(CONFIG_X86_IO_APIC) || defined(CONFIG_PARAVIRT) || defined(CONFIG_X86_VISWS)
 
+#ifdef CONFIG_X86_64
+#  define NR_IRQS		(NR_VECTORS * NR_CPUS)
+#else
 #  define NR_IRQS		224
-
-#  if (224 >= 32 * NR_CPUS)
-#   define NR_IRQ_VECTORS	NR_IRQS
-#  else
-#   define NR_IRQ_VECTORS	(32 * NR_CPUS)
-#  endif
+#endif
 
 # else /* IO_APIC || PARAVIRT */
 
 #  define NR_IRQS		16
-#  define NR_IRQ_VECTORS	NR_IRQS
 
 # endif
 
 #else /* !VISWS && !VOYAGER */
 
 # define NR_IRQS		224
-# define NR_IRQ_VECTORS		NR_IRQS
 
 #endif /* VISWS */
 
+#define NR_IRQ_VECTORS		NR_IRQS
+
 /* Voyager specific defines */
 /* These define the CPIs we use in linux */
 #define VIC_CPI_LEVEL0			0
include/linux/init.h +23 -0
Index: linux-2.6/include/linux/init.h
===================================================================
@@ -249,6 +249,29 @@ struct obs_kernel_param {
 
 /* Relies on boot_command_line being set */
 void __init parse_early_param(void);
+
+struct dyn_array {
+        void **name;
+        unsigned long size;
+        unsigned int *nr;
+        unsigned long align;
+        void (*init_work)(void *);
+};
+extern struct dyn_array *__dyn_array_start[], *__dyn_array_end[];
+
+#define DEFINE_DYN_ARRAY(nameX, sizeX, nrX, alignX, init_workX) \
+		static struct dyn_array __dyn_array_##nameX __initdata = \
+		{	.name = &nameX,\
+			.size = sizeX,\
+			.nr   = &nrX,\
+			.align = alignX,\
+			.init_work = init_workX,\
+		}; \
+		static struct dyn_array *__dyn_array_ptr_##nameX __used \
+		__attribute__((__section__(".dyn_array.init"))) = \
+			&__dyn_array_##nameX
+
+extern void pre_alloc_dyn_array(void);
 #endif /* __ASSEMBLY__ */
 
 /**
include/linux/irq.h +1 -1
Index: linux-2.6/include/linux/irq.h
===================================================================
@@ -179,7 +179,7 @@ struct irq_desc {
 	const char		*name;
 } ____cacheline_internodealigned_in_smp;
 
-extern struct irq_desc irq_desc[NR_IRQS];
+extern struct irq_desc *irq_desc;
 
 /*
  * Migration helpers for obsolete names, they will go away:
init/main.c +20 -0
Index: linux-2.6/init/main.c
===================================================================
@@ -539,6 +539,26 @@ void __init __weak thread_info_cache_ini
 {
 }
 
+void pre_alloc_dyn_array(void)
+{
+	unsigned long size;
+	struct dyn_array **daa;
+
+	for (daa = __dyn_array_start ; daa < __dyn_array_end; daa++) {
+		struct dyn_array *da = *daa;
+
+		size = da->size * (*da->nr);
+		print_fn_descriptor_symbol("dyna_array %s", da->name);
+		printk(KERN_INFO "%p name:%p size:%lx nr:%d align:%lx",
+			da, da->name, da->size, *da->nr, da->align);
+		*da->name = __alloc_bootmem_nopanic(size, da->align, 16ULL<<20);
+		printk(KERN_CONT "  *name:%p\n", *da->name);
+
+		if (da->init_work)
+			da->init_work(da);
+	}
+}
+
 asmlinkage void __init start_kernel(void)
 {
 	char * command_line;
kernel/irq/autoprobe.c +5 -5
Index: linux-2.6/kernel/irq/autoprobe.c
===================================================================
@@ -38,7 +38,7 @@ unsigned long probe_irq_on(void)
 	 * something may have generated an irq long ago and we want to
 	 * flush such a longstanding irq before considering it as spurious.
 	 */
-	for (i = NR_IRQS-1; i > 0; i--) {
+	for (i = nr_irqs-1; i > 0; i--) {
 		desc = irq_desc + i;
 
 		spin_lock_irq(&desc->lock);
@@ -68,7 +68,7 @@ unsigned long probe_irq_on(void)
 	 * (we must startup again here because if a longstanding irq
 	 * happened in the previous stage, it may have masked itself)
 	 */
-	for (i = NR_IRQS-1; i > 0; i--) {
+	for (i = nr_irqs-1; i > 0; i--) {
 		desc = irq_desc + i;
 
 		spin_lock_irq(&desc->lock);
@@ -89,7 +89,7 @@ unsigned long probe_irq_on(void)
 	 * Now filter out any obviously spurious interrupts
 	 */
 	mask = 0;
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 0; i < nr_irqs; i++) {
 		unsigned int status;
 
 		desc = irq_desc + i;
@@ -130,7 +130,7 @@ unsigned int probe_irq_mask(unsigned lon
 	int i;
 
 	mask = 0;
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 0; i < nr_irqs; i++) {
 		struct irq_desc *desc = irq_desc + i;
 		unsigned int status;
 
@@ -173,7 +173,7 @@ int probe_irq_off(unsigned long val)
 {
 	int i, irq_found = 0, nr_irqs = 0;
 
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 0; i < nr_irqs; i++) {
 		struct irq_desc *desc = irq_desc + i;
 		unsigned int status;
 
kernel/irq/chip.c +10 -10
Index: linux-2.6/kernel/irq/chip.c
===================================================================
@@ -27,7 +27,7 @@ void dynamic_irq_init(unsigned int irq)
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq);
 		return;
 	}
@@ -60,7 +60,7 @@ void dynamic_irq_cleanup(unsigned int ir
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		WARN(1, KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq);
 		return;
 	}
@@ -92,7 +92,7 @@ int set_irq_chip(unsigned int irq, struc
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		WARN(1, KERN_ERR "Trying to install chip for IRQ%d\n", irq);
 		return -EINVAL;
 	}
@@ -121,7 +121,7 @@ int set_irq_type(unsigned int irq, unsig
 	unsigned long flags;
 	int ret = -ENXIO;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq);
 		return -ENODEV;
 	}
@@ -148,7 +148,7 @@ int set_irq_data(unsigned int irq, void
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR
 		       "Trying to install controller data for IRQ%d\n", irq);
 		return -EINVAL;
@@ -174,7 +174,7 @@ int set_irq_msi(unsigned int irq, struct
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR
 		       "Trying to install msi data for IRQ%d\n", irq);
 		return -EINVAL;
@@ -200,7 +200,7 @@ int set_irq_chip_data(unsigned int irq,
 	struct irq_desc *desc = irq_desc + irq;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS || !desc->chip) {
+	if (irq >= nr_irqs || !desc->chip) {
 		printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq);
 		return -EINVAL;
 	}
@@ -544,7 +544,7 @@ __set_irq_handler(unsigned int irq, irq_
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR
 		       "Trying to install type control for IRQ%d\n", irq);
 		return;
@@ -609,7 +609,7 @@ void __init set_irq_noprobe(unsigned int
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR "Trying to mark IRQ%d non-probeable\n", irq);
 
 		return;
@@ -627,7 +627,7 @@ void __init set_irq_probe(unsigned int i
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR "Trying to mark IRQ%d probeable\n", irq);
 
 		return;
kernel/irq/handle.c +24 -10
Index: linux-2.6/kernel/irq/handle.c
===================================================================
@@ -47,19 +47,33 @@ handle_bad_irq(unsigned int irq, struct
  *
  * Controller mappings for all interrupt sources:
  */
-struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
-	[0 ... NR_IRQS-1] = {
-		.status = IRQ_DISABLED,
-		.chip = &no_irq_chip,
-		.handle_irq = handle_bad_irq,
-		.depth = 1,
-		.lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock),
+static struct irq_desc irq_desc_init = {
+	.status = IRQ_DISABLED,
+	.chip = &no_irq_chip,
+	.handle_irq = handle_bad_irq,
+	.depth = 1,
+	.lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock),
 #ifdef CONFIG_SMP
-		.affinity = CPU_MASK_ALL
+	.affinity = CPU_MASK_ALL
 #endif
-	}
 };
 
+static void __init init_work(void *data)
+{
+        struct dyn_array *da = data;
+	int i;
+	struct  irq_desc *desc;
+
+	desc = *da->name;
+
+	for (i = 0; i < *da->nr; i++)
+		memcpy(&desc[i], &irq_desc_init, sizeof(struct irq_desc));
+}
+
+struct irq_desc *irq_desc;
+
+DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irqs, PAGE_SIZE, init_work);
+
 /*
  * What should we do if we get a hw irq event on an illegal vector?
  * Each architecture has to answer this themself.
@@ -265,7 +279,7 @@ void early_init_irq_lock_class(void)
 {
 	int i;
 
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		lockdep_set_class(&irq_desc[i].lock, &irq_desc_lock_class);
 }
 
kernel/irq/manage.c +8 -8
Index: linux-2.6/kernel/irq/manage.c
===================================================================
@@ -34,7 +34,7 @@ void synchronize_irq(unsigned int irq)
 	struct irq_desc *desc = irq_desc + irq;
 	unsigned int status;
 
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return;
 
 	do {
@@ -143,7 +143,7 @@ void disable_irq_nosync(unsigned int irq
 	struct irq_desc *desc = irq_desc + irq;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return;
 
 	spin_lock_irqsave(&desc->lock, flags);
@@ -171,7 +171,7 @@ void disable_irq(unsigned int irq)
 {
 	struct irq_desc *desc = irq_desc + irq;
 
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return;
 
 	disable_irq_nosync(irq);
@@ -214,7 +214,7 @@ void enable_irq(unsigned int irq)
 	struct irq_desc *desc = irq_desc + irq;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return;
 
 	spin_lock_irqsave(&desc->lock, flags);
@@ -290,7 +290,7 @@ int can_request_irq(unsigned int irq, un
 {
 	struct irqaction *action;
 
-	if (irq >= NR_IRQS || irq_desc[irq].status & IRQ_NOREQUEST)
+	if (irq >= nr_irqs || irq_desc[irq].status & IRQ_NOREQUEST)
 		return 0;
 
 	action = irq_desc[irq].action;
@@ -349,7 +349,7 @@ int setup_irq(unsigned int irq, struct i
 	int shared = 0;
 	int ret;
 
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return -EINVAL;
 
 	if (desc->chip == &no_irq_chip)
@@ -503,7 +503,7 @@ void free_irq(unsigned int irq, void *de
 	unsigned long flags;
 
 	WARN_ON(in_interrupt());
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return;
 
 	desc = irq_desc + irq;
@@ -617,7 +617,7 @@ int request_irq(unsigned int irq, irq_ha
 	 */
 	if ((irqflags & IRQF_SHARED) && !dev_id)
 		return -EINVAL;
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return -EINVAL;
 	if (irq_desc[irq].status & IRQ_NOREQUEST)
 		return -EINVAL;
kernel/irq/proc.c +1 -1
Index: linux-2.6/kernel/irq/proc.c
===================================================================
@@ -234,7 +234,7 @@ void init_irq_proc(void)
 	/*
 	 * Create entries for all existing IRQs.
 	 */
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		register_irq_proc(i);
 }
 
kernel/irq/resend.c +2 -2
Index: linux-2.6/kernel/irq/resend.c
===================================================================
@@ -33,8 +33,8 @@ static void resend_irqs(unsigned long ar
 	struct irq_desc *desc;
 	int irq;
 
-	while (!bitmap_empty(irqs_resend, NR_IRQS)) {
-		irq = find_first_bit(irqs_resend, NR_IRQS);
+	while (!bitmap_empty(irqs_resend, nr_irqs)) {
+		irq = find_first_bit(irqs_resend, nr_irqs);
 		clear_bit(irq, irqs_resend);
 		desc = irq_desc + irq;
 		local_irq_disable();
kernel/irq/spurious.c +2 -2
Index: linux-2.6/kernel/irq/spurious.c
===================================================================
@@ -91,7 +91,7 @@ static int misrouted_irq(int irq)
 	int i;
 	int ok = 0;
 
-	for (i = 1; i < NR_IRQS; i++) {
+	for (i = 1; i < nr_irqs; i++) {
 		struct irq_desc *desc = irq_desc + i;
 
 		if (i == irq)	/* Already tried */
@@ -107,7 +107,7 @@ static int misrouted_irq(int irq)
 static void poll_spurious_irqs(unsigned long dummy)
 {
 	int i;
-	for (i = 1; i < NR_IRQS; i++) {
+	for (i = 1; i < nr_irqs; i++) {
 		struct irq_desc *desc = irq_desc + i;
 		unsigned int status;
 
#4 lore raw

Re: RFC [PATCH] x86: introduce nr_irqs for 64bit

Quoted 7 lines · Yinghai Lu

add DEFINE_DYN_ARRAY for dynamical array support

todo:
1. convert x86 32bit and other arch
2. nr_irqs auto probe via acpi_oem_check?

wonderful!

I have one main structural suggestion: could we please keep the NR_IRQS name, and just change it to dynamic on x86? NR_IRQS is used in 540 places in the kernel, there's no point in touching all that code.

Also add an CONFIG_ARCH_HAS_DYNAMIC_NR_IRQS switch, define it in arch/x86/Kconfig and use it in include/linux/irq.h.

This will create far less migration pain than the widespread rename. That will also solve the "what about the other architectures" question.

Ingo

author
#7 lore raw

PATCH 1/1 x86: introduce nr_irqs for 64bit v2

In reply to Yinghai Lu

add DEFINE_DYN_ARRAY for dynamical array support

v2: other platform will have nr_irqs = NR_IRQS
for MAXSMP/UV: could set smaller nr_irqs in acpi_madt_oem_check in genx2_apic_uv_x

---
 arch/x86/kernel/io_apic_32.c            |   20 +++++------
 arch/x86/kernel/io_apic_64.c            |   57 ++++++++++++++++++++------------
 arch/x86/kernel/irq_32.c                |    8 ++--
 arch/x86/kernel/irq_64.c                |    8 ++--
 arch/x86/kernel/irqinit_32.c            |    2 -
 arch/x86/kernel/irqinit_64.c            |    2 -
 arch/x86/kernel/setup.c                 |    8 ++++
 arch/x86/kernel/vmlinux_32.lds.S        |    1 
 arch/x86/kernel/vmlinux_64.lds.S        |    3 +
 drivers/char/hpet.c                     |    2 -
 drivers/char/random.c                   |   10 ++++-
 drivers/char/vr41xx_giu.c               |    2 -
 drivers/net/3c59x.c                     |    4 +-
 drivers/net/hamradio/baycom_ser_fdx.c   |    4 +-
 drivers/net/hamradio/scc.c              |    6 +--
 drivers/net/wan/sbni.c                  |    2 -
 drivers/pci/intr_remapping.c            |   22 ++++++------
 drivers/pcmcia/at91_cf.c                |    2 -
 drivers/pcmcia/vrc4171_card.c           |    2 -
 drivers/rtc/rtc-vr41xx.c                |    4 +-
 drivers/scsi/aha152x.c                  |    2 -
 drivers/serial/8250.c                   |    4 +-
 drivers/serial/amba-pl010.c             |    2 -
 drivers/serial/amba-pl011.c             |    2 -
 drivers/serial/cpm_uart/cpm_uart_core.c |    2 -
 drivers/serial/m32r_sio.c               |    4 +-
 drivers/serial/serial_core.c            |    2 -
 drivers/serial/serial_lh7a40x.c         |    2 -
 drivers/serial/sh-sci.c                 |    2 -
 drivers/serial/ucc_uart.c               |    2 -
 drivers/xen/events.c                    |   12 +++---
 fs/proc/proc_misc.c                     |   10 ++---
 include/asm-generic/vmlinux.lds.h       |    7 +++
 include/asm-x86/irq.h                   |    3 +
 include/asm-x86/irq_vectors.h           |   14 +++----
 include/linux/init.h                    |   23 ++++++++++++
 include/linux/irq.h                     |    6 +++
 init/main.c                             |   21 +++++++++++
 kernel/irq/autoprobe.c                  |   10 ++---
 kernel/irq/chip.c                       |   20 +++++------
 kernel/irq/handle.c                     |   34 ++++++++++++++++++-
 kernel/irq/manage.c                     |   16 ++++----
 kernel/irq/proc.c                       |    2 -
 kernel/irq/resend.c                     |    4 +-
 kernel/irq/spurious.c                   |    4 +-
 45 files changed, 252 insertions(+), 127 deletions(-)
arch/x86/kernel/io_apic_32.c +10 -10
Index: linux-2.6/arch/x86/kernel/io_apic_32.c
===================================================================
@@ -70,6 +70,7 @@ int timer_through_8259 __initdata;
  */
 int sis_apic_bug = -1;
 
+int first_free_entry = NR_IRQS;
 /*
  * # of IRQ routing registers
  */
@@ -213,7 +214,6 @@ static void ioapic_mask_entry(int apic,
  */
 static void add_pin_to_irq(unsigned int irq, int apic, int pin)
 {
-	static int first_free_entry = NR_IRQS;
 	struct irq_pin_list *entry = irq_2_pin + irq;
 
 	while (entry->next)
@@ -457,7 +457,7 @@ static inline void rotate_irqs_among_cpu
 	int i, j;
 
 	for_each_online_cpu(i) {
-		for (j = 0; j < NR_IRQS; j++) {
+		for (j = 0; j < nr_irqs; j++) {
 			if (!irq_desc[j].action)
 				continue;
 			/* Is it a significant load ?  */
@@ -492,7 +492,7 @@ static void do_irq_balance(void)
 		if (!cpu_online(i))
 			continue;
 		package_index = CPU_TO_PACKAGEINDEX(i);
-		for (j = 0; j < NR_IRQS; j++) {
+		for (j = 0; j < nr_irqs; j++) {
 			unsigned long value_now, delta;
 			/* Is this an active IRQ or balancing disabled ? */
 			if (!irq_desc[j].action || irq_balancing_disabled(j))
@@ -587,7 +587,7 @@ tryanotherirq:
 	 */
 	move_this_load = 0;
 	selected_irq = -1;
-	for (j = 0; j < NR_IRQS; j++) {
+	for (j = 0; j < nr_irqs; j++) {
 		/* Is this an active IRQ? */
 		if (!irq_desc[j].action)
 			continue;
@@ -664,7 +664,7 @@ static int balanced_irq(void *unused)
 	long time_remaining = balanced_irq_interval;
 
 	/* push everything to CPU 0 to give us a starting point.  */
-	for (i = 0 ; i < NR_IRQS ; i++) {
+	for (i = 0 ; i < nr_irqs ; i++) {
 		irq_desc[i].pending_mask = cpumask_of_cpu(0);
 		set_pending_irq(i, cpumask_of_cpu(0));
 	}
@@ -712,8 +712,8 @@ static int __init balanced_irq_init(void
 		physical_balance = 1;
 
 	for_each_online_cpu(i) {
-		irq_cpu_data[i].irq_delta = kzalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
-		irq_cpu_data[i].last_irq = kzalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
+		irq_cpu_data[i].irq_delta = kzalloc(sizeof(unsigned long) * nr_irqs, GFP_KERNEL);
+		irq_cpu_data[i].last_irq = kzalloc(sizeof(unsigned long) * nr_irqs, GFP_KERNEL);
 		if (irq_cpu_data[i].irq_delta == NULL || irq_cpu_data[i].last_irq == NULL) {
 			printk(KERN_ERR "balanced_irq_init: out of memory");
 			goto failed;
@@ -1445,7 +1445,7 @@ __apicdebuginit(void) print_IO_APIC(void
 	}
 	}
 	printk(KERN_DEBUG "IRQ to pin mappings:\n");
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 0; i < nr_irqs; i++) {
 		struct irq_pin_list *entry = irq_2_pin + i;
 		if (entry->pin < 0)
 			continue;
@@ -2009,7 +2009,7 @@ static inline void init_IO_APIC_traps(vo
 	 * Also, we've got to be careful not to trash gate
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
-	for (irq = 0; irq < NR_IRQS ; irq++) {
+	for (irq = 0; irq < nr_irqs ; irq++) {
 		if (IO_APIC_IRQ(irq) && !irq_vector[irq]) {
 			/*
 			 * Hmm.. We don't have an entry for this,
@@ -2453,7 +2453,7 @@ int create_irq(void)
 
 	irq = -ENOSPC;
 	spin_lock_irqsave(&vector_lock, flags);
-	for (new = (NR_IRQS - 1); new >= 0; new--) {
+	for (new = (nr_irqs - 1); new >= 0; new--) {
 		if (platform_legacy_irq(new))
 			continue;
 		if (irq_vector[new] != 0)
arch/x86/kernel/io_apic_64.c +36 -21

175 lines not on this page · raw message

arch/x86/kernel/irq_32.c +4 -4
Index: linux-2.6/arch/x86/kernel/irq_32.c
===================================================================
@@ -226,7 +226,7 @@ unsigned int do_IRQ(struct pt_regs *regs
 	int overflow, irq = ~regs->orig_ax;
 	struct irq_desc *desc = irq_desc + irq;
 
-	if (unlikely((unsigned)irq >= NR_IRQS)) {
+	if (unlikely((unsigned)irq >= nr_irqs)) {
 		printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
 					__func__, irq);
 		BUG();
@@ -271,7 +271,7 @@ int show_interrupts(struct seq_file *p,
 		seq_putc(p, '\n');
 	}
 
-	if (i < NR_IRQS) {
+	if (i < nr_irqs) {
 		unsigned any_count = 0;
 
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
@@ -303,7 +303,7 @@ int show_interrupts(struct seq_file *p,
 		seq_putc(p, '\n');
 skip:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	} else if (i == NR_IRQS) {
+	} else if (i == nr_irqs) {
 		seq_printf(p, "NMI: ");
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", nmi_count(j));
@@ -396,7 +396,7 @@ void fixup_irqs(cpumask_t map)
 	unsigned int irq;
 	static int warned;
 
-	for (irq = 0; irq < NR_IRQS; irq++) {
+	for (irq = 0; irq < nr_irqs; irq++) {
 		cpumask_t mask;
 		if (irq == 2)
 			continue;
arch/x86/kernel/irq_64.c +4 -4
Index: linux-2.6/arch/x86/kernel/irq_64.c
===================================================================
@@ -81,7 +81,7 @@ int show_interrupts(struct seq_file *p,
 		seq_putc(p, '\n');
 	}
 
-	if (i < NR_IRQS) {
+	if (i < nr_irqs) {
 		unsigned any_count = 0;
 
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
@@ -112,7 +112,7 @@ int show_interrupts(struct seq_file *p,
 		seq_putc(p, '\n');
 skip:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	} else if (i == NR_IRQS) {
+	} else if (i == nr_irqs) {
 		seq_printf(p, "NMI: ");
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count);
@@ -201,7 +201,7 @@ asmlinkage unsigned int do_IRQ(struct pt
 	stack_overflow_check(regs);
 #endif
 
-	if (likely(irq < NR_IRQS))
+	if (likely(irq < nr_irqs))
 		generic_handle_irq(irq);
 	else {
 		if (!disable_apic)
@@ -224,7 +224,7 @@ void fixup_irqs(cpumask_t map)
 	unsigned int irq;
 	static int warned;
 
-	for (irq = 0; irq < NR_IRQS; irq++) {
+	for (irq = 0; irq < nr_irqs; irq++) {
 		cpumask_t mask;
 		int break_affinity = 0;
 		int set_affinity = 1;
arch/x86/kernel/irqinit_32.c +1 -1
Index: linux-2.6/arch/x86/kernel/irqinit_32.c
===================================================================
@@ -91,7 +91,7 @@ void __init native_init_IRQ(void)
 	 */
 	for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) {
 		int vector = FIRST_EXTERNAL_VECTOR + i;
-		if (i >= NR_IRQS)
+		if (i >= nr_irqs)
 			break;
 		/* SYSCALL_VECTOR was reserved in trap_init. */
 		if (!test_bit(vector, used_vectors))
arch/x86/kernel/irqinit_64.c +1 -1
Index: linux-2.6/arch/x86/kernel/irqinit_64.c
===================================================================
@@ -142,7 +142,7 @@ static void __init init_ISA_irqs (void)
 	init_bsp_APIC();
 	init_8259A(0);
 
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 0; i < nr_irqs; i++) {
 		irq_desc[i].status = IRQ_DISABLED;
 		irq_desc[i].action = NULL;
 		irq_desc[i].depth = 1;
arch/x86/kernel/setup.c +8 -0
Index: linux-2.6/arch/x86/kernel/setup.c
===================================================================
@@ -856,7 +856,15 @@ void __init setup_arch(char **cmdline_p)
 #endif
 
 	prefill_possible_map();
+
 #ifdef CONFIG_X86_64
+	/* need to wait for nr_cpu_ids settle down */
+	if (nr_irqs == NR_IRQS)
+		nr_irqs = 32 * nr_cpu_ids + 224;
+	pin_map_size = nr_irqs * 2;
+	first_free_entry = nr_irqs;
+	printk(KERN_INFO "nr_irqs: %d\n", nr_irqs);
+	pre_alloc_dyn_array();
 	init_cpu_to_node();
 #endif
 
arch/x86/kernel/vmlinux_32.lds.S +1 -0
Index: linux-2.6/arch/x86/kernel/vmlinux_32.lds.S
===================================================================
@@ -145,6 +145,7 @@ SECTIONS
 	*(.x86cpuvendor.init)
 	__x86cpuvendor_end = .;
   }
+  DYN_ARRAY_INIT(8)
   SECURITY_INIT
   . = ALIGN(4);
   .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
arch/x86/kernel/vmlinux_64.lds.S +3 -0
Index: linux-2.6/arch/x86/kernel/vmlinux_64.lds.S
===================================================================
@@ -174,6 +174,9 @@ SECTIONS
 	*(.x86cpuvendor.init)
   }
   __x86cpuvendor_end = .;
+
+  DYN_ARRAY_INIT(8)
+
   SECURITY_INIT
 
   . = ALIGN(8);
drivers/char/hpet.c +1 -1
Index: linux-2.6/drivers/char/hpet.c
===================================================================
@@ -222,7 +222,7 @@ static void hpet_timer_set_irq(struct hp
 	for (irq = find_first_bit(&v, HPET_MAX_IRQ); irq < HPET_MAX_IRQ;
 		irq = find_next_bit(&v, HPET_MAX_IRQ, 1 + irq)) {
 
-		if (irq >= NR_IRQS) {
+		if (irq >= nr_irqs) {
 			irq = HPET_MAX_IRQ;
 			break;
 		}
drivers/char/random.c +8 -2
Index: linux-2.6/drivers/char/random.c
===================================================================
@@ -558,7 +558,13 @@ struct timer_rand_state {
 };
 
 static struct timer_rand_state input_timer_state;
+
+#ifdef CONFIG_X86_64
+static struct timer_rand_state **irq_timer_state;
+DEFINE_DYN_ARRAY(irq_timer_state, sizeof(struct timer_rand_state *), nr_irqs, PAGE_SIZE, NULL);
+#else
 static struct timer_rand_state *irq_timer_state[NR_IRQS];
+#endif
 
 /*
  * This function adds entropy to the entropy "pool" by using timing
@@ -647,7 +653,7 @@ EXPORT_SYMBOL_GPL(add_input_randomness);
 
 void add_interrupt_randomness(int irq)
 {
-	if (irq >= NR_IRQS || irq_timer_state[irq] == NULL)
+	if (irq >= nr_irqs || irq_timer_state[irq] == NULL)
 		return;
 
 	DEBUG_ENT("irq event %d\n", irq);
@@ -911,7 +917,7 @@ void rand_initialize_irq(int irq)
 {
 	struct timer_rand_state *state;
 
-	if (irq >= NR_IRQS || irq_timer_state[irq])
+	if (irq >= nr_irqs || irq_timer_state[irq])
 		return;
 
 	/*
drivers/char/vr41xx_giu.c +1 -1
Index: linux-2.6/drivers/char/vr41xx_giu.c
===================================================================
@@ -641,7 +641,7 @@ static int __devinit giu_probe(struct pl
 	}
 
 	irq = platform_get_irq(dev, 0);
-	if (irq < 0 || irq >= NR_IRQS)
+	if (irq < 0 || irq >= nr_irqs)
 		return -EBUSY;
 
 	return cascade_irq(irq, giu_get_irq);
drivers/net/3c59x.c +2 -2
Index: linux-2.6/drivers/net/3c59x.c
===================================================================
@@ -90,7 +90,7 @@ static int vortex_debug = 1;
 #include <linux/eisa.h>
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
-#include <asm/irq.h>			/* For NR_IRQS only. */
+#include <asm/irq.h>			/* For nr_irqs only. */
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
@@ -1221,7 +1221,7 @@ static int __devinit vortex_probe1(struc
 	if (print_info)
 		printk(", IRQ %d\n", dev->irq);
 	/* Tell them about an invalid IRQ. */
-	if (dev->irq <= 0 || dev->irq >= NR_IRQS)
+	if (dev->irq <= 0 || dev->irq >= nr_irqs)
 		printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n",
 			   dev->irq);
 
drivers/net/hamradio/baycom_ser_fdx.c +2 -2
Index: linux-2.6/drivers/net/hamradio/baycom_ser_fdx.c
===================================================================
@@ -416,10 +416,10 @@ static int ser12_open(struct net_device
 	if (!dev || !bc)
 		return -ENXIO;
 	if (!dev->base_addr || dev->base_addr > 0xffff-SER12_EXTENT ||
-	    dev->irq < 2 || dev->irq > NR_IRQS) {
+	    dev->irq < 2 || dev->irq > nr_irqs) {
 		printk(KERN_INFO "baycom_ser_fdx: invalid portnumber (max %u) "
 				"or irq (2 <= irq <= %d)\n",
-				0xffff-SER12_EXTENT, NR_IRQS);
+				0xffff-SER12_EXTENT, nr_irqs);
 		return -ENXIO;
 	}
 	if (bc->baud < 300 || bc->baud > 4800) {
drivers/net/hamradio/scc.c +3 -3
Index: linux-2.6/drivers/net/hamradio/scc.c
===================================================================
@@ -1465,7 +1465,7 @@ static void z8530_init(void)
 	printk(KERN_INFO "Init Z8530 driver: %u channels, IRQ", Nchips*2);
 	
 	flag=" ";
-	for (k = 0; k < NR_IRQS; k++)
+	for (k = 0; k < nr_irqs; k++)
 		if (Ivec[k].used) 
 		{
 			printk("%s%d", flag, k);
@@ -1728,7 +1728,7 @@ static int scc_net_ioctl(struct net_devi
 
 			if (hwcfg.irq == 2) hwcfg.irq = 9;
 
-			if (hwcfg.irq < 0 || hwcfg.irq >= NR_IRQS)
+			if (hwcfg.irq < 0 || hwcfg.irq >= nr_irqs)
 				return -EINVAL;
 				
 			if (!Ivec[hwcfg.irq].used && hwcfg.irq)
@@ -2148,7 +2148,7 @@ static void __exit scc_cleanup_driver(vo
 		}
 		
 	/* To unload the port must be closed so no real IRQ pending */
-	for (k=0; k < NR_IRQS ; k++)
+	for (k=0; k < nr_irqs ; k++)
 		if (Ivec[k].used) free_irq(k, NULL);
 		
 	local_irq_enable();
drivers/net/wan/sbni.c +1 -1
Index: linux-2.6/drivers/net/wan/sbni.c
===================================================================
@@ -318,7 +318,7 @@ sbni_pci_probe( struct net_device  *dev
 				continue;
 		}
 
-		if( pci_irq_line <= 0  ||  pci_irq_line >= NR_IRQS )
+		if( pci_irq_line <= 0  ||  pci_irq_line >= nr_irqs )
 			printk( KERN_WARNING "  WARNING: The PCI BIOS assigned "
 				"this PCI card to IRQ %d, which is unlikely "
 				"to work!.\n"
drivers/pci/intr_remapping.c +12 -10
Index: linux-2.6/drivers/pci/intr_remapping.c
===================================================================
@@ -11,18 +11,20 @@ static struct ioapic_scope ir_ioapic[MAX
 static int ir_ioapic_num;
 int intr_remapping_enabled;
 
-static struct {
+static struct irq_2_iommu {
 	struct intel_iommu *iommu;
 	u16 irte_index;
 	u16 sub_handle;
 	u8  irte_mask;
-} irq_2_iommu[NR_IRQS];
+} *irq_2_iommu;
+
+DEFINE_DYN_ARRAY(irq_2_iommu, sizeof(struct irq_2_iommu), nr_irqs, PAGE_SIZE, NULL);
 
 static DEFINE_SPINLOCK(irq_2_ir_lock);
 
 int irq_remapped(int irq)
 {
-	if (irq > NR_IRQS)
+	if (irq > nr_irqs)
 		return 0;
 
 	if (!irq_2_iommu[irq].iommu)
@@ -35,7 +37,7 @@ int get_irte(int irq, struct irte *entry
 {
 	int index;
 
-	if (!entry || irq > NR_IRQS)
+	if (!entry || irq > nr_irqs)
 		return -1;
 
 	spin_lock(&irq_2_ir_lock);
@@ -126,7 +128,7 @@ int map_irq_to_irte_handle(int irq, u16
 	int index;
 
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || !irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
@@ -140,7 +142,7 @@ int map_irq_to_irte_handle(int irq, u16
 int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
 {
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
@@ -158,7 +160,7 @@ int set_irte_irq(int irq, struct intel_i
 int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index)
 {
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || !irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
@@ -180,7 +182,7 @@ int modify_irte(int irq, struct irte *ir
 	struct intel_iommu *iommu;
 
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || !irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
@@ -205,7 +207,7 @@ int flush_irte(int irq)
 	struct intel_iommu *iommu;
 
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || !irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
@@ -248,7 +250,7 @@ int free_irte(int irq)
 	struct intel_iommu *iommu;
 
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || !irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
drivers/pcmcia/at91_cf.c +1 -1
Index: linux-2.6/drivers/pcmcia/at91_cf.c
===================================================================
@@ -273,7 +273,7 @@ static int __init at91_cf_probe(struct p
 			goto fail0d;
 		cf->socket.pci_irq = board->irq_pin;
 	} else
-		cf->socket.pci_irq = NR_IRQS + 1;
+		cf->socket.pci_irq = nr_irqs + 1;
 
 	/* pcmcia layer only remaps "real" memory not iospace */
 	cf->socket.io_offset = (unsigned long)
drivers/pcmcia/vrc4171_card.c +1 -1
Index: linux-2.6/drivers/pcmcia/vrc4171_card.c
===================================================================
@@ -639,7 +639,7 @@ static int __devinit vrc4171_card_setup(
 		int irq;
 		options += 4;
 		irq = simple_strtoul(options, &options, 0);
-		if (irq >= 0 && irq < NR_IRQS)
+		if (irq >= 0 && irq < nr_irqs)
 			vrc4171_irq = irq;
 
 		if (*options != ',')
drivers/rtc/rtc-vr41xx.c +2 -2
Index: linux-2.6/drivers/rtc/rtc-vr41xx.c
===================================================================
@@ -360,7 +360,7 @@ static int __devinit rtc_probe(struct pl
 	spin_unlock_irq(&rtc_lock);
 
 	aie_irq = platform_get_irq(pdev, 0);
-	if (aie_irq < 0 || aie_irq >= NR_IRQS) {
+	if (aie_irq < 0 || aie_irq >= nr_irqs) {
 		retval = -EBUSY;
 		goto err_device_unregister;
 	}
@@ -371,7 +371,7 @@ static int __devinit rtc_probe(struct pl
 		goto err_device_unregister;
 
 	pie_irq = platform_get_irq(pdev, 1);
-	if (pie_irq < 0 || pie_irq >= NR_IRQS)
+	if (pie_irq < 0 || pie_irq >= nr_irqs)
 		goto err_free_irq;
 
 	retval = request_irq(pie_irq, rtclong1_interrupt, IRQF_DISABLED,
drivers/scsi/aha152x.c +1 -1
Index: linux-2.6/drivers/scsi/aha152x.c
===================================================================
@@ -337,7 +337,7 @@ CMD_INC_RESID(struct scsi_cmnd *cmd, int
 #else
 #define IRQ_MIN 9
 #if defined(__PPC)
-#define IRQ_MAX (NR_IRQS-1)
+#define IRQ_MAX (nr_irqs-1)
 #else
 #define IRQ_MAX 12
 #endif
drivers/serial/8250.c +2 -2
Index: linux-2.6/drivers/serial/8250.c
===================================================================
@@ -2433,7 +2433,7 @@ static void serial8250_config_port(struc
 static int
 serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
 {
-	if (ser->irq >= NR_IRQS || ser->irq < 0 ||
+	if (ser->irq >= nr_irqs || ser->irq < 0 ||
 	    ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
 	    ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
 	    ser->type == PORT_STARTECH)
@@ -2964,7 +2964,7 @@ static int __init serial8250_init(void)
 		"%d ports, IRQ sharing %sabled\n", nr_uarts,
 		share_irqs ? "en" : "dis");
 
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		spin_lock_init(&irq_lists[i].lock);
 
 	ret = uart_register_driver(&serial8250_reg);
drivers/serial/amba-pl010.c +1 -1
Index: linux-2.6/drivers/serial/amba-pl010.c
===================================================================
@@ -512,7 +512,7 @@ static int pl010_verify_port(struct uart
 	int ret = 0;
 	if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
 		ret = -EINVAL;
-	if (ser->irq < 0 || ser->irq >= NR_IRQS)
+	if (ser->irq < 0 || ser->irq >= nr_irqs)
 		ret = -EINVAL;
 	if (ser->baud_base < 9600)
 		ret = -EINVAL;
drivers/serial/amba-pl011.c +1 -1
Index: linux-2.6/drivers/serial/amba-pl011.c
===================================================================
@@ -572,7 +572,7 @@ static int pl010_verify_port(struct uart
 	int ret = 0;
 	if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
 		ret = -EINVAL;
-	if (ser->irq < 0 || ser->irq >= NR_IRQS)
+	if (ser->irq < 0 || ser->irq >= nr_irqs)
 		ret = -EINVAL;
 	if (ser->baud_base < 9600)
 		ret = -EINVAL;
drivers/serial/cpm_uart/cpm_uart_core.c +1 -1
Index: linux-2.6/drivers/serial/cpm_uart/cpm_uart_core.c
===================================================================
@@ -589,7 +589,7 @@ static int cpm_uart_verify_port(struct u
 
 	if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
 		ret = -EINVAL;
-	if (ser->irq < 0 || ser->irq >= NR_IRQS)
+	if (ser->irq < 0 || ser->irq >= nr_irqs)
 		ret = -EINVAL;
 	if (ser->baud_base < 9600)
 		ret = -EINVAL;
drivers/serial/m32r_sio.c +2 -2
Index: linux-2.6/drivers/serial/m32r_sio.c
===================================================================
@@ -922,7 +922,7 @@ static void m32r_sio_config_port(struct
 static int
 m32r_sio_verify_port(struct uart_port *port, struct serial_struct *ser)
 {
-	if (ser->irq >= NR_IRQS || ser->irq < 0 ||
+	if (ser->irq >= nr_irqs || ser->irq < 0 ||
 	    ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
 	    ser->type >= ARRAY_SIZE(uart_config))
 		return -EINVAL;
@@ -1162,7 +1162,7 @@ static int __init m32r_sio_init(void)
 
 	printk(KERN_INFO "Serial: M32R SIO driver\n");
 
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		spin_lock_init(&irq_lists[i].lock);
 
 	ret = uart_register_driver(&m32r_sio_reg);
drivers/serial/serial_core.c +1 -1
Index: linux-2.6/drivers/serial/serial_core.c
===================================================================
@@ -741,7 +741,7 @@ static int uart_set_info(struct uart_sta
 	if (port->ops->verify_port)
 		retval = port->ops->verify_port(port, &new_serial);
 
-	if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
+	if ((new_serial.irq >= nr_irqs) || (new_serial.irq < 0) ||
 	    (new_serial.baud_base < 9600))
 		retval = -EINVAL;
 
drivers/serial/serial_lh7a40x.c +1 -1
Index: linux-2.6/drivers/serial/serial_lh7a40x.c
===================================================================
@@ -460,7 +460,7 @@ static int lh7a40xuart_verify_port (stru
 
 	if (ser->type != PORT_UNKNOWN && ser->type != PORT_LH7A40X)
 		ret = -EINVAL;
-	if (ser->irq < 0 || ser->irq >= NR_IRQS)
+	if (ser->irq < 0 || ser->irq >= nr_irqs)
 		ret = -EINVAL;
 	if (ser->baud_base < 9600) /* *** FIXME: is this true? */
 		ret = -EINVAL;
drivers/serial/sh-sci.c +1 -1
Index: linux-2.6/drivers/serial/sh-sci.c
===================================================================
@@ -1157,7 +1157,7 @@ static int sci_verify_port(struct uart_p
 {
 	struct sci_port *s = &sci_ports[port->line];
 
-	if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > NR_IRQS)
+	if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs)
 		return -EINVAL;
 	if (ser->baud_base < 2400)
 		/* No paper tape reader for Mitch.. */
drivers/serial/ucc_uart.c +1 -1
Index: linux-2.6/drivers/serial/ucc_uart.c
===================================================================
@@ -1066,7 +1066,7 @@ static int qe_uart_verify_port(struct ua
 	if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
 		return -EINVAL;
 
-	if (ser->irq < 0 || ser->irq >= NR_IRQS)
+	if (ser->irq < 0 || ser->irq >= nr_irqs)
 		return -EINVAL;
 
 	if (ser->baud_base < 9600)
drivers/xen/events.c +6 -6
Index: linux-2.6/drivers/xen/events.c
===================================================================
@@ -150,7 +150,7 @@ static void init_evtchn_cpu_bindings(voi
 #ifdef CONFIG_SMP
 	int i;
 	/* By default all event channels notify CPU#0. */
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		irq_desc[i].affinity = cpumask_of_cpu(0);
 #endif
 
@@ -234,12 +234,12 @@ static int find_unbound_irq(void)
 	int irq;
 
 	/* Only allocate from dynirq range */
-	for (irq = 0; irq < NR_IRQS; irq++)
+	for (irq = 0; irq < nr_irqs; irq++)
 		if (irq_bindcount[irq] == 0)
 			break;
 
-	if (irq == NR_IRQS)
-		panic("No available IRQ to bind to: increase NR_IRQS!\n");
+	if (irq == nr_irqs)
+		panic("No available IRQ to bind to: increase nr_irqs!\n");
 
 	return irq;
 }
@@ -772,7 +772,7 @@ void xen_irq_resume(void)
 		mask_evtchn(evtchn);
 
 	/* No IRQ <-> event-channel mappings. */
-	for (irq = 0; irq < NR_IRQS; irq++)
+	for (irq = 0; irq < nr_irqs; irq++)
 		irq_info[irq].evtchn = 0; /* zap event-channel binding */
 
 	for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
@@ -804,7 +804,7 @@ void __init xen_init_IRQ(void)
 		mask_evtchn(i);
 
 	/* Dynamic IRQ space is currently unbound. Zero the refcnts. */
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		irq_bindcount[i] = 0;
 
 	irq_ctx_init(smp_processor_id());
fs/proc/proc_misc.c +5 -5
Index: linux-2.6/fs/proc/proc_misc.c
===================================================================
@@ -503,7 +503,7 @@ static int show_stat(struct seq_file *p,
 	struct timespec boottime;
 	unsigned int *per_irq_sum;
 
-	per_irq_sum = kzalloc(sizeof(unsigned int)*NR_IRQS, GFP_KERNEL);
+	per_irq_sum = kzalloc(sizeof(unsigned int)*nr_irqs, GFP_KERNEL);
 	if (!per_irq_sum)
 		return -ENOMEM;
 
@@ -525,7 +525,7 @@ static int show_stat(struct seq_file *p,
 		softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq);
 		steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal);
 		guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest);
-		for (j = 0; j < NR_IRQS; j++) {
+		for (j = 0; j < nr_irqs; j++) {
 			unsigned int temp = kstat_cpu(i).irqs[j];
 			sum += temp;
 			per_irq_sum[j] += temp;
@@ -571,7 +571,7 @@ static int show_stat(struct seq_file *p,
 	}
 	seq_printf(p, "intr %llu", (unsigned long long)sum);
 
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		seq_printf(p, " %u", per_irq_sum[i]);
 
 	seq_printf(p,
@@ -625,13 +625,13 @@ static const struct file_operations proc
  */
 static void *int_seq_start(struct seq_file *f, loff_t *pos)
 {
-	return (*pos <= NR_IRQS) ? pos : NULL;
+	return (*pos <= nr_irqs) ? pos : NULL;
 }
 
 static void *int_seq_next(struct seq_file *f, void *v, loff_t *pos)
 {
 	(*pos)++;
-	if (*pos > NR_IRQS)
+	if (*pos > nr_irqs)
 		return NULL;
 	return pos;
 }
include/asm-generic/vmlinux.lds.h +7 -0
Index: linux-2.6/include/asm-generic/vmlinux.lds.h
===================================================================
@@ -214,6 +214,13 @@
  * All archs are supposed to use RO_DATA() */
 #define RODATA RO_DATA(4096)
 
+#define DYN_ARRAY_INIT(align)							\
+	. = ALIGN((align));						\
+	.dyn_array.init : AT(ADDR(.dyn_array.init) - LOAD_OFFSET) {	\
+		VMLINUX_SYMBOL(__dyn_array_start) = .;			\
+		*(.dyn_array.init)					\
+		VMLINUX_SYMBOL(__dyn_array_end) = .;			\
+	}
 #define SECURITY_INIT							\
 	.security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \
 		VMLINUX_SYMBOL(__security_initcall_start) = .;		\
include/asm-x86/irq.h +3 -0
Index: linux-2.6/include/asm-x86/irq.h
===================================================================
@@ -10,6 +10,9 @@
 #include <asm/apicdef.h>
 #include <asm/irq_vectors.h>
 
+extern int pin_map_size;
+extern int first_free_entry;
+
 static inline int irq_canonicalize(int irq)
 {
 	return ((irq == 2) ? 9 : irq);
include/asm-x86/irq_vectors.h +6 -8
Index: linux-2.6/include/asm-x86/irq_vectors.h
===================================================================
@@ -113,28 +113,26 @@
 
 # if defined(CONFIG_X86_IO_APIC) || defined(CONFIG_PARAVIRT) || defined(CONFIG_X86_VISWS)
 
+#ifdef CONFIG_X86_64
+#  define NR_IRQS		(32 * NR_CPUS + 224)
+#else
 #  define NR_IRQS		224
-
-#  if (224 >= 32 * NR_CPUS)
-#   define NR_IRQ_VECTORS	NR_IRQS
-#  else
-#   define NR_IRQ_VECTORS	(32 * NR_CPUS)
-#  endif
+#endif
 
 # else /* IO_APIC || PARAVIRT */
 
 #  define NR_IRQS		16
-#  define NR_IRQ_VECTORS	NR_IRQS
 
 # endif
 
 #else /* !VISWS && !VOYAGER */
 
 # define NR_IRQS		224
-# define NR_IRQ_VECTORS		NR_IRQS
 
 #endif /* VISWS */
 
+#define NR_IRQ_VECTORS		NR_IRQS
+
 /* Voyager specific defines */
 /* These define the CPIs we use in linux */
 #define VIC_CPI_LEVEL0			0
include/linux/init.h +23 -0
Index: linux-2.6/include/linux/init.h
===================================================================
@@ -249,6 +249,29 @@ struct obs_kernel_param {
 
 /* Relies on boot_command_line being set */
 void __init parse_early_param(void);
+
+struct dyn_array {
+        void **name;
+        unsigned long size;
+        unsigned int *nr;
+        unsigned long align;
+        void (*init_work)(void *);
+};
+extern struct dyn_array *__dyn_array_start[], *__dyn_array_end[];
+
+#define DEFINE_DYN_ARRAY(nameX, sizeX, nrX, alignX, init_workX) \
+		static struct dyn_array __dyn_array_##nameX __initdata = \
+		{	.name = (void **)&nameX,\
+			.size = sizeX,\
+			.nr   = &nrX,\
+			.align = alignX,\
+			.init_work = init_workX,\
+		}; \
+		static struct dyn_array *__dyn_array_ptr_##nameX __used \
+		__attribute__((__section__(".dyn_array.init"))) = \
+			&__dyn_array_##nameX
+
+extern void pre_alloc_dyn_array(void);
 #endif /* __ASSEMBLY__ */
 
 /**
include/linux/irq.h +6 -0
Index: linux-2.6/include/linux/irq.h
===================================================================
@@ -24,6 +24,8 @@
 #include <asm/ptrace.h>
 #include <asm/irq_regs.h>
 
+extern int nr_irqs;
+
 struct irq_desc;
 typedef	void (*irq_flow_handler_t)(unsigned int irq,
 					    struct irq_desc *desc);
@@ -179,7 +181,11 @@ struct irq_desc {
 	const char		*name;
 } ____cacheline_internodealigned_in_smp;
 
+#ifdef CONFIG_X86_64
+extern struct irq_desc *irq_desc;
+#else
 extern struct irq_desc irq_desc[NR_IRQS];
+#endif
 
 /*
  * Migration helpers for obsolete names, they will go away:
init/main.c +21 -0
Index: linux-2.6/init/main.c
===================================================================
@@ -539,6 +539,27 @@ void __init __weak thread_info_cache_ini
 {
 }
 
+void pre_alloc_dyn_array(void)
+{
+	unsigned long size, phys = 0;
+	struct dyn_array **daa;
+
+	for (daa = __dyn_array_start ; daa < __dyn_array_end; daa++) {
+		struct dyn_array *da = *daa;
+
+		size = da->size * (*da->nr);
+		print_fn_descriptor_symbol("dyna_array %s ", da->name);
+		printk(KERN_CONT "size:%#lx nr:%d align:%#lx",
+			da->size, *da->nr, da->align);
+		*da->name = __alloc_bootmem_nopanic(size, da->align, phys);
+		phys = virt_to_phys(*da->name);
+		printk(KERN_CONT " ==> [%#lx - %#lx]\n", phys, phys + size);
+
+		if (da->init_work)
+			da->init_work(da);
+	}
+}
+
 asmlinkage void __init start_kernel(void)
 {
 	char * command_line;
kernel/irq/autoprobe.c +5 -5
Index: linux-2.6/kernel/irq/autoprobe.c
===================================================================
@@ -38,7 +38,7 @@ unsigned long probe_irq_on(void)
 	 * something may have generated an irq long ago and we want to
 	 * flush such a longstanding irq before considering it as spurious.
 	 */
-	for (i = NR_IRQS-1; i > 0; i--) {
+	for (i = nr_irqs-1; i > 0; i--) {
 		desc = irq_desc + i;
 
 		spin_lock_irq(&desc->lock);
@@ -68,7 +68,7 @@ unsigned long probe_irq_on(void)
 	 * (we must startup again here because if a longstanding irq
 	 * happened in the previous stage, it may have masked itself)
 	 */
-	for (i = NR_IRQS-1; i > 0; i--) {
+	for (i = nr_irqs-1; i > 0; i--) {
 		desc = irq_desc + i;
 
 		spin_lock_irq(&desc->lock);
@@ -89,7 +89,7 @@ unsigned long probe_irq_on(void)
 	 * Now filter out any obviously spurious interrupts
 	 */
 	mask = 0;
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 0; i < nr_irqs; i++) {
 		unsigned int status;
 
 		desc = irq_desc + i;
@@ -130,7 +130,7 @@ unsigned int probe_irq_mask(unsigned lon
 	int i;
 
 	mask = 0;
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 0; i < nr_irqs; i++) {
 		struct irq_desc *desc = irq_desc + i;
 		unsigned int status;
 
@@ -173,7 +173,7 @@ int probe_irq_off(unsigned long val)
 {
 	int i, irq_found = 0, nr_irqs = 0;
 
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 0; i < nr_irqs; i++) {
 		struct irq_desc *desc = irq_desc + i;
 		unsigned int status;
 
kernel/irq/chip.c +10 -10
Index: linux-2.6/kernel/irq/chip.c
===================================================================
@@ -27,7 +27,7 @@ void dynamic_irq_init(unsigned int irq)
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq);
 		return;
 	}
@@ -60,7 +60,7 @@ void dynamic_irq_cleanup(unsigned int ir
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		WARN(1, KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq);
 		return;
 	}
@@ -92,7 +92,7 @@ int set_irq_chip(unsigned int irq, struc
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		WARN(1, KERN_ERR "Trying to install chip for IRQ%d\n", irq);
 		return -EINVAL;
 	}
@@ -121,7 +121,7 @@ int set_irq_type(unsigned int irq, unsig
 	unsigned long flags;
 	int ret = -ENXIO;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq);
 		return -ENODEV;
 	}
@@ -148,7 +148,7 @@ int set_irq_data(unsigned int irq, void
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR
 		       "Trying to install controller data for IRQ%d\n", irq);
 		return -EINVAL;
@@ -174,7 +174,7 @@ int set_irq_msi(unsigned int irq, struct
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR
 		       "Trying to install msi data for IRQ%d\n", irq);
 		return -EINVAL;
@@ -200,7 +200,7 @@ int set_irq_chip_data(unsigned int irq,
 	struct irq_desc *desc = irq_desc + irq;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS || !desc->chip) {
+	if (irq >= nr_irqs || !desc->chip) {
 		printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq);
 		return -EINVAL;
 	}
@@ -544,7 +544,7 @@ __set_irq_handler(unsigned int irq, irq_
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR
 		       "Trying to install type control for IRQ%d\n", irq);
 		return;
@@ -609,7 +609,7 @@ void __init set_irq_noprobe(unsigned int
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR "Trying to mark IRQ%d non-probeable\n", irq);
 
 		return;
@@ -627,7 +627,7 @@ void __init set_irq_probe(unsigned int i
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR "Trying to mark IRQ%d probeable\n", irq);
 
 		return;
kernel/irq/handle.c +33 -1
Index: linux-2.6/kernel/irq/handle.c
===================================================================
@@ -47,6 +47,37 @@ handle_bad_irq(unsigned int irq, struct
  *
  * Controller mappings for all interrupt sources:
  */
+int nr_irqs = NR_IRQS;
+
+#ifdef CONFIG_X86_64
+static struct irq_desc irq_desc_init = {
+	.status = IRQ_DISABLED,
+	.chip = &no_irq_chip,
+	.handle_irq = handle_bad_irq,
+	.depth = 1,
+	.lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock),
+#ifdef CONFIG_SMP
+	.affinity = CPU_MASK_ALL
+#endif
+};
+
+static void __init init_work(void *data)
+{
+	struct dyn_array *da = data;
+	int i;
+	struct  irq_desc *desc;
+
+	desc = *da->name;
+
+	for (i = 0; i < *da->nr; i++)
+		memcpy(&desc[i], &irq_desc_init, sizeof(struct irq_desc));
+}
+
+struct irq_desc *irq_desc;
+DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irqs, PAGE_SIZE, init_work);
+
+#else
+
 struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
 	[0 ... NR_IRQS-1] = {
 		.status = IRQ_DISABLED,
@@ -59,6 +90,7 @@ struct irq_desc irq_desc[NR_IRQS] __cach
 #endif
 	}
 };
+#endif
 
 /*
  * What should we do if we get a hw irq event on an illegal vector?
@@ -265,7 +297,7 @@ void early_init_irq_lock_class(void)
 {
 	int i;
 
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		lockdep_set_class(&irq_desc[i].lock, &irq_desc_lock_class);
 }
 
kernel/irq/manage.c +8 -8
Index: linux-2.6/kernel/irq/manage.c
===================================================================
@@ -34,7 +34,7 @@ void synchronize_irq(unsigned int irq)
 	struct irq_desc *desc = irq_desc + irq;
 	unsigned int status;
 
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return;
 
 	do {
@@ -143,7 +143,7 @@ void disable_irq_nosync(unsigned int irq
 	struct irq_desc *desc = irq_desc + irq;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return;
 
 	spin_lock_irqsave(&desc->lock, flags);
@@ -171,7 +171,7 @@ void disable_irq(unsigned int irq)
 {
 	struct irq_desc *desc = irq_desc + irq;
 
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return;
 
 	disable_irq_nosync(irq);
@@ -214,7 +214,7 @@ void enable_irq(unsigned int irq)
 	struct irq_desc *desc = irq_desc + irq;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return;
 
 	spin_lock_irqsave(&desc->lock, flags);
@@ -290,7 +290,7 @@ int can_request_irq(unsigned int irq, un
 {
 	struct irqaction *action;
 
-	if (irq >= NR_IRQS || irq_desc[irq].status & IRQ_NOREQUEST)
+	if (irq >= nr_irqs || irq_desc[irq].status & IRQ_NOREQUEST)
 		return 0;
 
 	action = irq_desc[irq].action;
@@ -349,7 +349,7 @@ int setup_irq(unsigned int irq, struct i
 	int shared = 0;
 	int ret;
 
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return -EINVAL;
 
 	if (desc->chip == &no_irq_chip)
@@ -503,7 +503,7 @@ void free_irq(unsigned int irq, void *de
 	unsigned long flags;
 
 	WARN_ON(in_interrupt());
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return;
 
 	desc = irq_desc + irq;
@@ -617,7 +617,7 @@ int request_irq(unsigned int irq, irq_ha
 	 */
 	if ((irqflags & IRQF_SHARED) && !dev_id)
 		return -EINVAL;
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return -EINVAL;
 	if (irq_desc[irq].status & IRQ_NOREQUEST)
 		return -EINVAL;
kernel/irq/proc.c +1 -1
Index: linux-2.6/kernel/irq/proc.c
===================================================================
@@ -234,7 +234,7 @@ void init_irq_proc(void)
 	/*
 	 * Create entries for all existing IRQs.
 	 */
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		register_irq_proc(i);
 }
 
kernel/irq/resend.c +2 -2
Index: linux-2.6/kernel/irq/resend.c
===================================================================
@@ -33,8 +33,8 @@ static void resend_irqs(unsigned long ar
 	struct irq_desc *desc;
 	int irq;
 
-	while (!bitmap_empty(irqs_resend, NR_IRQS)) {
-		irq = find_first_bit(irqs_resend, NR_IRQS);
+	while (!bitmap_empty(irqs_resend, nr_irqs)) {
+		irq = find_first_bit(irqs_resend, nr_irqs);
 		clear_bit(irq, irqs_resend);
 		desc = irq_desc + irq;
 		local_irq_disable();
kernel/irq/spurious.c +2 -2
Index: linux-2.6/kernel/irq/spurious.c
===================================================================
@@ -91,7 +91,7 @@ static int misrouted_irq(int irq)
 	int i;
 	int ok = 0;
 
-	for (i = 1; i < NR_IRQS; i++) {
+	for (i = 1; i < nr_irqs; i++) {
 		struct irq_desc *desc = irq_desc + i;
 
 		if (i == irq)	/* Already tried */
@@ -107,7 +107,7 @@ static int misrouted_irq(int irq)
 static void poll_spurious_irqs(unsigned long dummy)
 {
 	int i;
-	for (i = 1; i < NR_IRQS; i++) {
+	for (i = 1; i < nr_irqs; i++) {
 		struct irq_desc *desc = irq_desc + i;
 		unsigned int status;
 
author
#5 lore raw

Re: RFC [PATCH] x86: introduce nr_irqs for 64bit

In reply to Ingo Molnar
Quoted 17 lines · Ingo Molnar
Quoted 7 lines · Yinghai Lu

add DEFINE_DYN_ARRAY for dynamical array support

todo:
1. convert x86 32bit and other arch
2. nr_irqs auto probe via acpi_oem_check?

wonderful!

I have one main structural suggestion: could we please keep the NR_IRQS name, and just change it to dynamic on x86? NR_IRQS is used in 540 places in the kernel, there's no point in touching all that code.

Quoted 5 lines

Also add an CONFIG_ARCH_HAS_DYNAMIC_NR_IRQS switch, define it in arch/x86/Kconfig and use it in include/linux/irq.h.

This will create far less migration pain than the widespread rename. That will also solve the "what about the other architectures" question.

just send out v2.

long term, i hope to make all arch to use nr_irqs and probe it earlier. and kill NR_IRQS

YH

#6 lore raw

Re: RFC [PATCH] x86: introduce nr_irqs for 64bit

In reply to Ingo Molnar
Quoted 8 lines · Ingo Molnar
Quoted 6 lines · Yinghai Lu

add DEFINE_DYN_ARRAY for dynamical array support

todo:
1. convert x86 32bit and other arch
2. nr_irqs auto probe via acpi_oem_check?

Quoted 7 lines
Quoted 1 line

wonderful!

I have one main structural suggestion: could we please keep the NR_IRQS name, and just change it to dynamic on x86? NR_IRQS is used in 540 places in the kernel, there's no point in touching all that code.

Good thought.

Quoted 3 lines

Also add an CONFIG_ARCH_HAS_DYNAMIC_NR_IRQS switch, define it in arch/x86/Kconfig and use it in include/linux/irq.h.

It could also revert DEFINE_DYN_ARRAY to a fixed array for more compact code in small machines.

Thanks,
Mike

Quoted 5 lines

This will create far less migration pain than the widespread rename. That will also solve the "what about the other architectures" question.

Ingo

author
#10 lore raw

PATCH 2/7 x86: introduce nr_irqs for 64bit v3

add DEFINE_DYN_ARRAY for dynamical array support

v2: other platform will have nr_irqs = NR_IRQS
for MAXSMP/UV: could set smaller nr_irqs in acpi_madt_oem_check in genx2_apic_uv_x
v3: seperate DYN_ARRAY and enabling to x86_64 to following patches

---

---
 arch/x86/kernel/io_apic_32.c            |   26 +++++++++++++------------
 arch/x86/kernel/io_apic_64.c            |   33 ++++++++++++++++----------------
 arch/x86/kernel/irq_32.c                |    8 +++----
 arch/x86/kernel/irq_64.c                |    8 +++----
 arch/x86/kernel/irqinit_32.c            |    2 -
 arch/x86/kernel/irqinit_64.c            |    2 -
 drivers/char/hpet.c                     |    2 -
 drivers/char/random.c                   |    4 +--
 drivers/char/vr41xx_giu.c               |    2 -
 drivers/net/3c59x.c                     |    4 +--
 drivers/net/hamradio/baycom_ser_fdx.c   |    4 +--
 drivers/net/hamradio/scc.c              |    6 ++---
 drivers/net/wan/sbni.c                  |    2 -
 drivers/pci/intr_remapping.c            |   16 +++++++--------
 drivers/pcmcia/at91_cf.c                |    2 -
 drivers/pcmcia/vrc4171_card.c           |    2 -
 drivers/rtc/rtc-vr41xx.c                |    4 +--
 drivers/scsi/aha152x.c                  |    2 -
 drivers/serial/8250.c                   |    4 +--
 drivers/serial/amba-pl010.c             |    2 -
 drivers/serial/amba-pl011.c             |    2 -
 drivers/serial/cpm_uart/cpm_uart_core.c |    2 -
 drivers/serial/m32r_sio.c               |    4 +--
 drivers/serial/serial_core.c            |    2 -
 drivers/serial/serial_lh7a40x.c         |    2 -
 drivers/serial/sh-sci.c                 |    2 -
 drivers/serial/ucc_uart.c               |    2 -
 drivers/xen/events.c                    |   12 +++++------
 fs/proc/proc_misc.c                     |   10 ++++-----
 include/asm-x86/irq.h                   |    3 ++
 include/linux/irq.h                     |    2 +
 kernel/irq/autoprobe.c                  |   10 ++++-----
 kernel/irq/chip.c                       |   20 +++++++++----------
 kernel/irq/handle.c                     |    3 +-
 kernel/irq/manage.c                     |   16 +++++++--------
 kernel/irq/proc.c                       |    2 -
 kernel/irq/resend.c                     |    4 +--
 kernel/irq/spurious.c                   |    4 +--
 38 files changed, 123 insertions(+), 114 deletions(-)
arch/x86/kernel/io_apic_32.c +14 -12
Index: linux-2.6/arch/x86/kernel/io_apic_32.c
===================================================================
@@ -70,6 +70,7 @@ int timer_through_8259 __initdata;
  */
 int sis_apic_bug = -1;
 
+int first_free_entry = NR_IRQS;
 /*
  * # of IRQ routing registers
  */
@@ -100,6 +101,8 @@ static int disable_timer_pin_1 __initdat
 #define MAX_PLUS_SHARED_IRQS NR_IRQS
 #define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
 
+int pin_map_size = PIN_MAP_SIZE;
+
 /*
  * This is performance-critical, we want to do it O(1)
  *
@@ -213,7 +216,6 @@ static void ioapic_mask_entry(int apic,
  */
 static void add_pin_to_irq(unsigned int irq, int apic, int pin)
 {
-	static int first_free_entry = NR_IRQS;
 	struct irq_pin_list *entry = irq_2_pin + irq;
 
 	while (entry->next)
@@ -222,7 +224,7 @@ static void add_pin_to_irq(unsigned int
 	if (entry->pin != -1) {
 		entry->next = first_free_entry;
 		entry = irq_2_pin + entry->next;
-		if (++first_free_entry >= PIN_MAP_SIZE)
+		if (++first_free_entry >= pin_map_size)
 			panic("io_apic.c: whoops");
 	}
 	entry->apic = apic;
@@ -457,7 +459,7 @@ static inline void rotate_irqs_among_cpu
 	int i, j;
 
 	for_each_online_cpu(i) {
-		for (j = 0; j < NR_IRQS; j++) {
+		for (j = 0; j < nr_irqs; j++) {
 			if (!irq_desc[j].action)
 				continue;
 			/* Is it a significant load ?  */
@@ -492,7 +494,7 @@ static void do_irq_balance(void)
 		if (!cpu_online(i))
 			continue;
 		package_index = CPU_TO_PACKAGEINDEX(i);
-		for (j = 0; j < NR_IRQS; j++) {
+		for (j = 0; j < nr_irqs; j++) {
 			unsigned long value_now, delta;
 			/* Is this an active IRQ or balancing disabled ? */
 			if (!irq_desc[j].action || irq_balancing_disabled(j))
@@ -587,7 +589,7 @@ tryanotherirq:
 	 */
 	move_this_load = 0;
 	selected_irq = -1;
-	for (j = 0; j < NR_IRQS; j++) {
+	for (j = 0; j < nr_irqs; j++) {
 		/* Is this an active IRQ? */
 		if (!irq_desc[j].action)
 			continue;
@@ -664,7 +666,7 @@ static int balanced_irq(void *unused)
 	long time_remaining = balanced_irq_interval;
 
 	/* push everything to CPU 0 to give us a starting point.  */
-	for (i = 0 ; i < NR_IRQS ; i++) {
+	for (i = 0 ; i < nr_irqs ; i++) {
 		irq_desc[i].pending_mask = cpumask_of_cpu(0);
 		set_pending_irq(i, cpumask_of_cpu(0));
 	}
@@ -712,8 +714,8 @@ static int __init balanced_irq_init(void
 		physical_balance = 1;
 
 	for_each_online_cpu(i) {
-		irq_cpu_data[i].irq_delta = kzalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
-		irq_cpu_data[i].last_irq = kzalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
+		irq_cpu_data[i].irq_delta = kzalloc(sizeof(unsigned long) * nr_irqs, GFP_KERNEL);
+		irq_cpu_data[i].last_irq = kzalloc(sizeof(unsigned long) * nr_irqs, GFP_KERNEL);
 		if (irq_cpu_data[i].irq_delta == NULL || irq_cpu_data[i].last_irq == NULL) {
 			printk(KERN_ERR "balanced_irq_init: out of memory");
 			goto failed;
@@ -1445,7 +1447,7 @@ __apicdebuginit(void) print_IO_APIC(void
 	}
 	}
 	printk(KERN_DEBUG "IRQ to pin mappings:\n");
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 0; i < nr_irqs; i++) {
 		struct irq_pin_list *entry = irq_2_pin + i;
 		if (entry->pin < 0)
 			continue;
@@ -1625,7 +1627,7 @@ static void __init enable_IO_APIC(void)
 	int i, apic;
 	unsigned long flags;
 
-	for (i = 0; i < PIN_MAP_SIZE; i++) {
+	for (i = 0; i < pin_map_size; i++) {
 		irq_2_pin[i].pin = -1;
 		irq_2_pin[i].next = 0;
 	}
@@ -2009,7 +2011,7 @@ static inline void init_IO_APIC_traps(vo
 	 * Also, we've got to be careful not to trash gate
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
-	for (irq = 0; irq < NR_IRQS ; irq++) {
+	for (irq = 0; irq < nr_irqs ; irq++) {
 		if (IO_APIC_IRQ(irq) && !irq_vector[irq]) {
 			/*
 			 * Hmm.. We don't have an entry for this,
@@ -2453,7 +2455,7 @@ int create_irq(void)
 
 	irq = -ENOSPC;
 	spin_lock_irqsave(&vector_lock, flags);
-	for (new = (NR_IRQS - 1); new >= 0; new--) {
+	for (new = (nr_irqs - 1); new >= 0; new--) {
 		if (platform_legacy_irq(new))
 			continue;
 		if (irq_vector[new] != 0)
arch/x86/kernel/io_apic_64.c +17 -16
Index: linux-2.6/arch/x86/kernel/io_apic_64.c
===================================================================
@@ -132,6 +132,7 @@ DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BU
 #define MAX_PLUS_SHARED_IRQS NR_IRQS
 #define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
 
+int pin_map_size = PIN_MAP_SIZE;
 /*
  * This is performance-critical, we want to do it O(1)
  *
@@ -224,7 +225,7 @@ static inline void io_apic_sync(unsigned
 	int pin;							\
 	struct irq_pin_list *entry = irq_2_pin + irq;			\
 									\
-	BUG_ON(irq >= NR_IRQS);						\
+	BUG_ON(irq >= nr_irqs);						\
 	for (;;) {							\
 		unsigned int reg;					\
 		pin = entry->pin;					\
@@ -301,7 +302,7 @@ static void __target_IO_APIC_irq(unsigne
 	int apic, pin;
 	struct irq_pin_list *entry = irq_2_pin + irq;
 
-	BUG_ON(irq >= NR_IRQS);
+	BUG_ON(irq >= nr_irqs);
 	for (;;) {
 		unsigned int reg;
 		apic = entry->apic;
@@ -358,19 +359,19 @@ static void set_ioapic_affinity_irq(unsi
  * shared ISA-space IRQs, so we have to support them. We are super
  * fast in the common case, and fast for shared ISA-space IRQs.
  */
+int first_free_entry = NR_IRQS;
 static void add_pin_to_irq(unsigned int irq, int apic, int pin)
 {
-	static int first_free_entry = NR_IRQS;
 	struct irq_pin_list *entry = irq_2_pin + irq;
 
-	BUG_ON(irq >= NR_IRQS);
+	BUG_ON(irq >= nr_irqs);
 	while (entry->next)
 		entry = irq_2_pin + entry->next;
 
 	if (entry->pin != -1) {
 		entry->next = first_free_entry;
 		entry = irq_2_pin + entry->next;
-		if (++first_free_entry >= PIN_MAP_SIZE)
+		if (++first_free_entry >= pin_map_size)
 			panic("io_apic.c: ran out of irq_2_pin entries!");
 	}
 	entry->apic = apic;
@@ -634,7 +635,7 @@ int IO_APIC_get_PCI_irq_vector(int bus,
 				best_guess = irq;
 		}
 	}
-	BUG_ON(best_guess >= NR_IRQS);
+	BUG_ON(best_guess >= nr_irqs);
 	return best_guess;
 }
 
@@ -766,7 +767,7 @@ static int pin_2_irq(int idx, int apic,
 			irq += nr_ioapic_registers[i++];
 		irq += pin;
 	}
-	BUG_ON(irq >= NR_IRQS);
+	BUG_ON(irq >= nr_irqs);
 	return irq;
 }
 
@@ -788,7 +789,7 @@ static int __assign_irq_vector(int irq,
 	int cpu;
 	struct irq_cfg *cfg;
 
-	BUG_ON((unsigned)irq >= NR_IRQS);
+	BUG_ON((unsigned)irq >= nr_irqs);
 	cfg = &irq_cfg[irq];
 
 	/* Only try and allocate irqs on cpus that are present */
@@ -862,7 +863,7 @@ static void __clear_irq_vector(int irq)
 	cpumask_t mask;
 	int cpu, vector;
 
-	BUG_ON((unsigned)irq >= NR_IRQS);
+	BUG_ON((unsigned)irq >= nr_irqs);
 	cfg = &irq_cfg[irq];
 	BUG_ON(!cfg->vector);
 
@@ -882,7 +883,7 @@ static void __setup_vector_irq(int cpu)
 	int irq, vector;
 
 	/* Mark the inuse vectors */
-	for (irq = 0; irq < NR_IRQS; ++irq) {
+	for (irq = 0; irq < nr_irqs; ++irq) {
 		if (!cpu_isset(cpu, irq_cfg[irq].domain))
 			continue;
 		vector = irq_cfg[irq].vector;
@@ -1188,7 +1189,7 @@ __apicdebuginit(void) print_IO_APIC(void
 	}
 	}
 	printk(KERN_DEBUG "IRQ to pin mappings:\n");
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 0; i < nr_irqs; i++) {
 		struct irq_pin_list *entry = irq_2_pin + i;
 		if (entry->pin < 0)
 			continue;
@@ -1361,7 +1362,7 @@ void __init enable_IO_APIC(void)
 	int i, apic;
 	unsigned long flags;
 
-	for (i = 0; i < PIN_MAP_SIZE; i++) {
+	for (i = 0; i < pin_map_size; i++) {
 		irq_2_pin[i].pin = -1;
 		irq_2_pin[i].next = 0;
 	}
@@ -1655,7 +1656,7 @@ static void ir_irq_migration(struct work
 {
 	int irq;
 
-	for (irq = 0; irq < NR_IRQS; irq++) {
+	for (irq = 0; irq < nr_irqs; irq++) {
 		struct irq_desc *desc = irq_desc + irq;
 		if (desc->status & IRQ_MOVE_PENDING) {
 			unsigned long flags;
@@ -1704,7 +1705,7 @@ asmlinkage void smp_irq_move_cleanup_int
 		struct irq_desc *desc;
 		struct irq_cfg *cfg;
 		irq = __get_cpu_var(vector_irq)[vector];
-		if (irq >= NR_IRQS)
+		if (irq >= nr_irqs)
 			continue;
 
 		desc = irq_desc + irq;
@@ -1862,7 +1863,7 @@ static inline void init_IO_APIC_traps(vo
 	 * Also, we've got to be careful not to trash gate
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
-	for (irq = 0; irq < NR_IRQS ; irq++) {
+	for (irq = 0; irq < nr_irqs ; irq++) {
 		if (IO_APIC_IRQ(irq) && !irq_cfg[irq].vector) {
 			/*
 			 * Hmm.. We don't have an entry for this,
@@ -2276,7 +2277,7 @@ int create_irq(void)
 
 	irq = -ENOSPC;
 	spin_lock_irqsave(&vector_lock, flags);
-	for (new = (NR_IRQS - 1); new >= 0; new--) {
+	for (new = (nr_irqs - 1); new >= 0; new--) {
 		if (platform_legacy_irq(new))
 			continue;
 		if (irq_cfg[new].vector != 0)
arch/x86/kernel/irq_32.c +4 -4
Index: linux-2.6/arch/x86/kernel/irq_32.c
===================================================================
@@ -226,7 +226,7 @@ unsigned int do_IRQ(struct pt_regs *regs
 	int overflow, irq = ~regs->orig_ax;
 	struct irq_desc *desc = irq_desc + irq;
 
-	if (unlikely((unsigned)irq >= NR_IRQS)) {
+	if (unlikely((unsigned)irq >= nr_irqs)) {
 		printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
 					__func__, irq);
 		BUG();
@@ -271,7 +271,7 @@ int show_interrupts(struct seq_file *p,
 		seq_putc(p, '\n');
 	}
 
-	if (i < NR_IRQS) {
+	if (i < nr_irqs) {
 		unsigned any_count = 0;
 
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
@@ -303,7 +303,7 @@ int show_interrupts(struct seq_file *p,
 		seq_putc(p, '\n');
 skip:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	} else if (i == NR_IRQS) {
+	} else if (i == nr_irqs) {
 		seq_printf(p, "NMI: ");
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", nmi_count(j));
@@ -396,7 +396,7 @@ void fixup_irqs(cpumask_t map)
 	unsigned int irq;
 	static int warned;
 
-	for (irq = 0; irq < NR_IRQS; irq++) {
+	for (irq = 0; irq < nr_irqs; irq++) {
 		cpumask_t mask;
 		if (irq == 2)
 			continue;
arch/x86/kernel/irq_64.c +4 -4
Index: linux-2.6/arch/x86/kernel/irq_64.c
===================================================================
@@ -81,7 +81,7 @@ int show_interrupts(struct seq_file *p,
 		seq_putc(p, '\n');
 	}
 
-	if (i < NR_IRQS) {
+	if (i < nr_irqs) {
 		unsigned any_count = 0;
 
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
@@ -112,7 +112,7 @@ int show_interrupts(struct seq_file *p,
 		seq_putc(p, '\n');
 skip:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	} else if (i == NR_IRQS) {
+	} else if (i == nr_irqs) {
 		seq_printf(p, "NMI: ");
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count);
@@ -201,7 +201,7 @@ asmlinkage unsigned int do_IRQ(struct pt
 	stack_overflow_check(regs);
 #endif
 
-	if (likely(irq < NR_IRQS))
+	if (likely(irq < nr_irqs))
 		generic_handle_irq(irq);
 	else {
 		if (!disable_apic)
@@ -224,7 +224,7 @@ void fixup_irqs(cpumask_t map)
 	unsigned int irq;
 	static int warned;
 
-	for (irq = 0; irq < NR_IRQS; irq++) {
+	for (irq = 0; irq < nr_irqs; irq++) {
 		cpumask_t mask;
 		int break_affinity = 0;
 		int set_affinity = 1;
arch/x86/kernel/irqinit_32.c +1 -1
Index: linux-2.6/arch/x86/kernel/irqinit_32.c
===================================================================
@@ -91,7 +91,7 @@ void __init native_init_IRQ(void)
 	 */
 	for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) {
 		int vector = FIRST_EXTERNAL_VECTOR + i;
-		if (i >= NR_IRQS)
+		if (i >= nr_irqs)
 			break;
 		/* SYSCALL_VECTOR was reserved in trap_init. */
 		if (!test_bit(vector, used_vectors))
arch/x86/kernel/irqinit_64.c +1 -1
Index: linux-2.6/arch/x86/kernel/irqinit_64.c
===================================================================
@@ -142,7 +142,7 @@ static void __init init_ISA_irqs (void)
 	init_bsp_APIC();
 	init_8259A(0);
 
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 0; i < nr_irqs; i++) {
 		irq_desc[i].status = IRQ_DISABLED;
 		irq_desc[i].action = NULL;
 		irq_desc[i].depth = 1;
drivers/char/hpet.c +1 -1
Index: linux-2.6/drivers/char/hpet.c
===================================================================
@@ -222,7 +222,7 @@ static void hpet_timer_set_irq(struct hp
 	for (irq = find_first_bit(&v, HPET_MAX_IRQ); irq < HPET_MAX_IRQ;
 		irq = find_next_bit(&v, HPET_MAX_IRQ, 1 + irq)) {
 
-		if (irq >= NR_IRQS) {
+		if (irq >= nr_irqs) {
 			irq = HPET_MAX_IRQ;
 			break;
 		}
drivers/char/random.c +2 -2
Index: linux-2.6/drivers/char/random.c
===================================================================
@@ -647,7 +647,7 @@ EXPORT_SYMBOL_GPL(add_input_randomness);
 
 void add_interrupt_randomness(int irq)
 {
-	if (irq >= NR_IRQS || irq_timer_state[irq] == NULL)
+	if (irq >= nr_irqs || irq_timer_state[irq] == NULL)
 		return;
 
 	DEBUG_ENT("irq event %d\n", irq);
@@ -911,7 +911,7 @@ void rand_initialize_irq(int irq)
 {
 	struct timer_rand_state *state;
 
-	if (irq >= NR_IRQS || irq_timer_state[irq])
+	if (irq >= nr_irqs || irq_timer_state[irq])
 		return;
 
 	/*
drivers/char/vr41xx_giu.c +1 -1
Index: linux-2.6/drivers/char/vr41xx_giu.c
===================================================================
@@ -641,7 +641,7 @@ static int __devinit giu_probe(struct pl
 	}
 
 	irq = platform_get_irq(dev, 0);
-	if (irq < 0 || irq >= NR_IRQS)
+	if (irq < 0 || irq >= nr_irqs)
 		return -EBUSY;
 
 	return cascade_irq(irq, giu_get_irq);
drivers/net/3c59x.c +2 -2
Index: linux-2.6/drivers/net/3c59x.c
===================================================================
@@ -90,7 +90,7 @@ static int vortex_debug = 1;
 #include <linux/eisa.h>
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
-#include <asm/irq.h>			/* For NR_IRQS only. */
+#include <asm/irq.h>			/* For nr_irqs only. */
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
@@ -1221,7 +1221,7 @@ static int __devinit vortex_probe1(struc
 	if (print_info)
 		printk(", IRQ %d\n", dev->irq);
 	/* Tell them about an invalid IRQ. */
-	if (dev->irq <= 0 || dev->irq >= NR_IRQS)
+	if (dev->irq <= 0 || dev->irq >= nr_irqs)
 		printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n",
 			   dev->irq);
 
drivers/net/hamradio/baycom_ser_fdx.c +2 -2
Index: linux-2.6/drivers/net/hamradio/baycom_ser_fdx.c
===================================================================
@@ -416,10 +416,10 @@ static int ser12_open(struct net_device
 	if (!dev || !bc)
 		return -ENXIO;
 	if (!dev->base_addr || dev->base_addr > 0xffff-SER12_EXTENT ||
-	    dev->irq < 2 || dev->irq > NR_IRQS) {
+	    dev->irq < 2 || dev->irq > nr_irqs) {
 		printk(KERN_INFO "baycom_ser_fdx: invalid portnumber (max %u) "
 				"or irq (2 <= irq <= %d)\n",
-				0xffff-SER12_EXTENT, NR_IRQS);
+				0xffff-SER12_EXTENT, nr_irqs);
 		return -ENXIO;
 	}
 	if (bc->baud < 300 || bc->baud > 4800) {
drivers/net/hamradio/scc.c +3 -3
Index: linux-2.6/drivers/net/hamradio/scc.c
===================================================================
@@ -1465,7 +1465,7 @@ static void z8530_init(void)
 	printk(KERN_INFO "Init Z8530 driver: %u channels, IRQ", Nchips*2);
 	
 	flag=" ";
-	for (k = 0; k < NR_IRQS; k++)
+	for (k = 0; k < nr_irqs; k++)
 		if (Ivec[k].used) 
 		{
 			printk("%s%d", flag, k);
@@ -1728,7 +1728,7 @@ static int scc_net_ioctl(struct net_devi
 
 			if (hwcfg.irq == 2) hwcfg.irq = 9;
 
-			if (hwcfg.irq < 0 || hwcfg.irq >= NR_IRQS)
+			if (hwcfg.irq < 0 || hwcfg.irq >= nr_irqs)
 				return -EINVAL;
 				
 			if (!Ivec[hwcfg.irq].used && hwcfg.irq)
@@ -2148,7 +2148,7 @@ static void __exit scc_cleanup_driver(vo
 		}
 		
 	/* To unload the port must be closed so no real IRQ pending */
-	for (k=0; k < NR_IRQS ; k++)
+	for (k=0; k < nr_irqs ; k++)
 		if (Ivec[k].used) free_irq(k, NULL);
 		
 	local_irq_enable();
drivers/net/wan/sbni.c +1 -1
Index: linux-2.6/drivers/net/wan/sbni.c
===================================================================
@@ -318,7 +318,7 @@ sbni_pci_probe( struct net_device  *dev
 				continue;
 		}
 
-		if( pci_irq_line <= 0  ||  pci_irq_line >= NR_IRQS )
+		if( pci_irq_line <= 0  ||  pci_irq_line >= nr_irqs )
 			printk( KERN_WARNING "  WARNING: The PCI BIOS assigned "
 				"this PCI card to IRQ %d, which is unlikely "
 				"to work!.\n"
drivers/pci/intr_remapping.c +8 -8
Index: linux-2.6/drivers/pci/intr_remapping.c
===================================================================
@@ -22,7 +22,7 @@ static DEFINE_SPINLOCK(irq_2_ir_lock);
 
 int irq_remapped(int irq)
 {
-	if (irq > NR_IRQS)
+	if (irq > nr_irqs)
 		return 0;
 
 	if (!irq_2_iommu[irq].iommu)
@@ -35,7 +35,7 @@ int get_irte(int irq, struct irte *entry
 {
 	int index;
 
-	if (!entry || irq > NR_IRQS)
+	if (!entry || irq > nr_irqs)
 		return -1;
 
 	spin_lock(&irq_2_ir_lock);
@@ -126,7 +126,7 @@ int map_irq_to_irte_handle(int irq, u16
 	int index;
 
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || !irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
@@ -140,7 +140,7 @@ int map_irq_to_irte_handle(int irq, u16
 int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
 {
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
@@ -158,7 +158,7 @@ int set_irte_irq(int irq, struct intel_i
 int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index)
 {
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || !irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
@@ -180,7 +180,7 @@ int modify_irte(int irq, struct irte *ir
 	struct intel_iommu *iommu;
 
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || !irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
@@ -205,7 +205,7 @@ int flush_irte(int irq)
 	struct intel_iommu *iommu;
 
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || !irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
@@ -248,7 +248,7 @@ int free_irte(int irq)
 	struct intel_iommu *iommu;
 
 	spin_lock(&irq_2_ir_lock);
-	if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
+	if (irq >= nr_irqs || !irq_2_iommu[irq].iommu) {
 		spin_unlock(&irq_2_ir_lock);
 		return -1;
 	}
drivers/pcmcia/at91_cf.c +1 -1
Index: linux-2.6/drivers/pcmcia/at91_cf.c
===================================================================
@@ -273,7 +273,7 @@ static int __init at91_cf_probe(struct p
 			goto fail0d;
 		cf->socket.pci_irq = board->irq_pin;
 	} else
-		cf->socket.pci_irq = NR_IRQS + 1;
+		cf->socket.pci_irq = nr_irqs + 1;
 
 	/* pcmcia layer only remaps "real" memory not iospace */
 	cf->socket.io_offset = (unsigned long)
drivers/pcmcia/vrc4171_card.c +1 -1
Index: linux-2.6/drivers/pcmcia/vrc4171_card.c
===================================================================
@@ -639,7 +639,7 @@ static int __devinit vrc4171_card_setup(
 		int irq;
 		options += 4;
 		irq = simple_strtoul(options, &options, 0);
-		if (irq >= 0 && irq < NR_IRQS)
+		if (irq >= 0 && irq < nr_irqs)
 			vrc4171_irq = irq;
 
 		if (*options != ',')
drivers/rtc/rtc-vr41xx.c +2 -2
Index: linux-2.6/drivers/rtc/rtc-vr41xx.c
===================================================================
@@ -360,7 +360,7 @@ static int __devinit rtc_probe(struct pl
 	spin_unlock_irq(&rtc_lock);
 
 	aie_irq = platform_get_irq(pdev, 0);
-	if (aie_irq < 0 || aie_irq >= NR_IRQS) {
+	if (aie_irq < 0 || aie_irq >= nr_irqs) {
 		retval = -EBUSY;
 		goto err_device_unregister;
 	}
@@ -371,7 +371,7 @@ static int __devinit rtc_probe(struct pl
 		goto err_device_unregister;
 
 	pie_irq = platform_get_irq(pdev, 1);
-	if (pie_irq < 0 || pie_irq >= NR_IRQS)
+	if (pie_irq < 0 || pie_irq >= nr_irqs)
 		goto err_free_irq;
 
 	retval = request_irq(pie_irq, rtclong1_interrupt, IRQF_DISABLED,
drivers/scsi/aha152x.c +1 -1
Index: linux-2.6/drivers/scsi/aha152x.c
===================================================================
@@ -337,7 +337,7 @@ CMD_INC_RESID(struct scsi_cmnd *cmd, int
 #else
 #define IRQ_MIN 9
 #if defined(__PPC)
-#define IRQ_MAX (NR_IRQS-1)
+#define IRQ_MAX (nr_irqs-1)
 #else
 #define IRQ_MAX 12
 #endif
drivers/serial/8250.c +2 -2
Index: linux-2.6/drivers/serial/8250.c
===================================================================
@@ -2433,7 +2433,7 @@ static void serial8250_config_port(struc
 static int
 serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
 {
-	if (ser->irq >= NR_IRQS || ser->irq < 0 ||
+	if (ser->irq >= nr_irqs || ser->irq < 0 ||
 	    ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
 	    ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
 	    ser->type == PORT_STARTECH)
@@ -2964,7 +2964,7 @@ static int __init serial8250_init(void)
 		"%d ports, IRQ sharing %sabled\n", nr_uarts,
 		share_irqs ? "en" : "dis");
 
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		spin_lock_init(&irq_lists[i].lock);
 
 	ret = uart_register_driver(&serial8250_reg);
drivers/serial/amba-pl010.c +1 -1
Index: linux-2.6/drivers/serial/amba-pl010.c
===================================================================
@@ -512,7 +512,7 @@ static int pl010_verify_port(struct uart
 	int ret = 0;
 	if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
 		ret = -EINVAL;
-	if (ser->irq < 0 || ser->irq >= NR_IRQS)
+	if (ser->irq < 0 || ser->irq >= nr_irqs)
 		ret = -EINVAL;
 	if (ser->baud_base < 9600)
 		ret = -EINVAL;
drivers/serial/amba-pl011.c +1 -1
Index: linux-2.6/drivers/serial/amba-pl011.c
===================================================================
@@ -572,7 +572,7 @@ static int pl010_verify_port(struct uart
 	int ret = 0;
 	if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
 		ret = -EINVAL;
-	if (ser->irq < 0 || ser->irq >= NR_IRQS)
+	if (ser->irq < 0 || ser->irq >= nr_irqs)
 		ret = -EINVAL;
 	if (ser->baud_base < 9600)
 		ret = -EINVAL;
drivers/serial/cpm_uart/cpm_uart_core.c +1 -1
Index: linux-2.6/drivers/serial/cpm_uart/cpm_uart_core.c
===================================================================
@@ -589,7 +589,7 @@ static int cpm_uart_verify_port(struct u
 
 	if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
 		ret = -EINVAL;
-	if (ser->irq < 0 || ser->irq >= NR_IRQS)
+	if (ser->irq < 0 || ser->irq >= nr_irqs)
 		ret = -EINVAL;
 	if (ser->baud_base < 9600)
 		ret = -EINVAL;
drivers/serial/m32r_sio.c +2 -2
Index: linux-2.6/drivers/serial/m32r_sio.c
===================================================================
@@ -922,7 +922,7 @@ static void m32r_sio_config_port(struct
 static int
 m32r_sio_verify_port(struct uart_port *port, struct serial_struct *ser)
 {
-	if (ser->irq >= NR_IRQS || ser->irq < 0 ||
+	if (ser->irq >= nr_irqs || ser->irq < 0 ||
 	    ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
 	    ser->type >= ARRAY_SIZE(uart_config))
 		return -EINVAL;
@@ -1162,7 +1162,7 @@ static int __init m32r_sio_init(void)
 
 	printk(KERN_INFO "Serial: M32R SIO driver\n");
 
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		spin_lock_init(&irq_lists[i].lock);
 
 	ret = uart_register_driver(&m32r_sio_reg);
drivers/serial/serial_core.c +1 -1
Index: linux-2.6/drivers/serial/serial_core.c
===================================================================
@@ -741,7 +741,7 @@ static int uart_set_info(struct uart_sta
 	if (port->ops->verify_port)
 		retval = port->ops->verify_port(port, &new_serial);
 
-	if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
+	if ((new_serial.irq >= nr_irqs) || (new_serial.irq < 0) ||
 	    (new_serial.baud_base < 9600))
 		retval = -EINVAL;
 
drivers/serial/serial_lh7a40x.c +1 -1
Index: linux-2.6/drivers/serial/serial_lh7a40x.c
===================================================================
@@ -460,7 +460,7 @@ static int lh7a40xuart_verify_port (stru
 
 	if (ser->type != PORT_UNKNOWN && ser->type != PORT_LH7A40X)
 		ret = -EINVAL;
-	if (ser->irq < 0 || ser->irq >= NR_IRQS)
+	if (ser->irq < 0 || ser->irq >= nr_irqs)
 		ret = -EINVAL;
 	if (ser->baud_base < 9600) /* *** FIXME: is this true? */
 		ret = -EINVAL;
drivers/serial/sh-sci.c +1 -1
Index: linux-2.6/drivers/serial/sh-sci.c
===================================================================
@@ -1157,7 +1157,7 @@ static int sci_verify_port(struct uart_p
 {
 	struct sci_port *s = &sci_ports[port->line];
 
-	if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > NR_IRQS)
+	if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs)
 		return -EINVAL;
 	if (ser->baud_base < 2400)
 		/* No paper tape reader for Mitch.. */
drivers/serial/ucc_uart.c +1 -1
Index: linux-2.6/drivers/serial/ucc_uart.c
===================================================================
@@ -1066,7 +1066,7 @@ static int qe_uart_verify_port(struct ua
 	if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
 		return -EINVAL;
 
-	if (ser->irq < 0 || ser->irq >= NR_IRQS)
+	if (ser->irq < 0 || ser->irq >= nr_irqs)
 		return -EINVAL;
 
 	if (ser->baud_base < 9600)
drivers/xen/events.c +6 -6
Index: linux-2.6/drivers/xen/events.c
===================================================================
@@ -150,7 +150,7 @@ static void init_evtchn_cpu_bindings(voi
 #ifdef CONFIG_SMP
 	int i;
 	/* By default all event channels notify CPU#0. */
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		irq_desc[i].affinity = cpumask_of_cpu(0);
 #endif
 
@@ -234,12 +234,12 @@ static int find_unbound_irq(void)
 	int irq;
 
 	/* Only allocate from dynirq range */
-	for (irq = 0; irq < NR_IRQS; irq++)
+	for (irq = 0; irq < nr_irqs; irq++)
 		if (irq_bindcount[irq] == 0)
 			break;
 
-	if (irq == NR_IRQS)
-		panic("No available IRQ to bind to: increase NR_IRQS!\n");
+	if (irq == nr_irqs)
+		panic("No available IRQ to bind to: increase nr_irqs!\n");
 
 	return irq;
 }
@@ -772,7 +772,7 @@ void xen_irq_resume(void)
 		mask_evtchn(evtchn);
 
 	/* No IRQ <-> event-channel mappings. */
-	for (irq = 0; irq < NR_IRQS; irq++)
+	for (irq = 0; irq < nr_irqs; irq++)
 		irq_info[irq].evtchn = 0; /* zap event-channel binding */
 
 	for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
@@ -804,7 +804,7 @@ void __init xen_init_IRQ(void)
 		mask_evtchn(i);
 
 	/* Dynamic IRQ space is currently unbound. Zero the refcnts. */
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		irq_bindcount[i] = 0;
 
 	irq_ctx_init(smp_processor_id());
fs/proc/proc_misc.c +5 -5
Index: linux-2.6/fs/proc/proc_misc.c
===================================================================
@@ -503,7 +503,7 @@ static int show_stat(struct seq_file *p,
 	struct timespec boottime;
 	unsigned int *per_irq_sum;
 
-	per_irq_sum = kzalloc(sizeof(unsigned int)*NR_IRQS, GFP_KERNEL);
+	per_irq_sum = kzalloc(sizeof(unsigned int)*nr_irqs, GFP_KERNEL);
 	if (!per_irq_sum)
 		return -ENOMEM;
 
@@ -525,7 +525,7 @@ static int show_stat(struct seq_file *p,
 		softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq);
 		steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal);
 		guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest);
-		for (j = 0; j < NR_IRQS; j++) {
+		for (j = 0; j < nr_irqs; j++) {
 			unsigned int temp = kstat_cpu(i).irqs[j];
 			sum += temp;
 			per_irq_sum[j] += temp;
@@ -571,7 +571,7 @@ static int show_stat(struct seq_file *p,
 	}
 	seq_printf(p, "intr %llu", (unsigned long long)sum);
 
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		seq_printf(p, " %u", per_irq_sum[i]);
 
 	seq_printf(p,
@@ -625,13 +625,13 @@ static const struct file_operations proc
  */
 static void *int_seq_start(struct seq_file *f, loff_t *pos)
 {
-	return (*pos <= NR_IRQS) ? pos : NULL;
+	return (*pos <= nr_irqs) ? pos : NULL;
 }
 
 static void *int_seq_next(struct seq_file *f, void *v, loff_t *pos)
 {
 	(*pos)++;
-	if (*pos > NR_IRQS)
+	if (*pos > nr_irqs)
 		return NULL;
 	return pos;
 }
include/asm-x86/irq.h +3 -0
Index: linux-2.6/include/asm-x86/irq.h
===================================================================
@@ -10,6 +10,9 @@
 #include <asm/apicdef.h>
 #include <asm/irq_vectors.h>
 
+extern int pin_map_size;
+extern int first_free_entry;
+
 static inline int irq_canonicalize(int irq)
 {
 	return ((irq == 2) ? 9 : irq);
include/linux/irq.h +2 -0
Index: linux-2.6/include/linux/irq.h
===================================================================
@@ -24,6 +24,8 @@
 #include <asm/ptrace.h>
 #include <asm/irq_regs.h>
 
+extern int nr_irqs;
+
 struct irq_desc;
 typedef	void (*irq_flow_handler_t)(unsigned int irq,
 					    struct irq_desc *desc);
kernel/irq/autoprobe.c +5 -5
Index: linux-2.6/kernel/irq/autoprobe.c
===================================================================
@@ -38,7 +38,7 @@ unsigned long probe_irq_on(void)
 	 * something may have generated an irq long ago and we want to
 	 * flush such a longstanding irq before considering it as spurious.
 	 */
-	for (i = NR_IRQS-1; i > 0; i--) {
+	for (i = nr_irqs-1; i > 0; i--) {
 		desc = irq_desc + i;
 
 		spin_lock_irq(&desc->lock);
@@ -68,7 +68,7 @@ unsigned long probe_irq_on(void)
 	 * (we must startup again here because if a longstanding irq
 	 * happened in the previous stage, it may have masked itself)
 	 */
-	for (i = NR_IRQS-1; i > 0; i--) {
+	for (i = nr_irqs-1; i > 0; i--) {
 		desc = irq_desc + i;
 
 		spin_lock_irq(&desc->lock);
@@ -89,7 +89,7 @@ unsigned long probe_irq_on(void)
 	 * Now filter out any obviously spurious interrupts
 	 */
 	mask = 0;
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 0; i < nr_irqs; i++) {
 		unsigned int status;
 
 		desc = irq_desc + i;
@@ -130,7 +130,7 @@ unsigned int probe_irq_mask(unsigned lon
 	int i;
 
 	mask = 0;
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 0; i < nr_irqs; i++) {
 		struct irq_desc *desc = irq_desc + i;
 		unsigned int status;
 
@@ -173,7 +173,7 @@ int probe_irq_off(unsigned long val)
 {
 	int i, irq_found = 0, nr_irqs = 0;
 
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 0; i < nr_irqs; i++) {
 		struct irq_desc *desc = irq_desc + i;
 		unsigned int status;
 
kernel/irq/chip.c +10 -10
Index: linux-2.6/kernel/irq/chip.c
===================================================================
@@ -27,7 +27,7 @@ void dynamic_irq_init(unsigned int irq)
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq);
 		return;
 	}
@@ -60,7 +60,7 @@ void dynamic_irq_cleanup(unsigned int ir
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		WARN(1, KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq);
 		return;
 	}
@@ -92,7 +92,7 @@ int set_irq_chip(unsigned int irq, struc
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		WARN(1, KERN_ERR "Trying to install chip for IRQ%d\n", irq);
 		return -EINVAL;
 	}
@@ -121,7 +121,7 @@ int set_irq_type(unsigned int irq, unsig
 	unsigned long flags;
 	int ret = -ENXIO;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq);
 		return -ENODEV;
 	}
@@ -148,7 +148,7 @@ int set_irq_data(unsigned int irq, void
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR
 		       "Trying to install controller data for IRQ%d\n", irq);
 		return -EINVAL;
@@ -174,7 +174,7 @@ int set_irq_msi(unsigned int irq, struct
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR
 		       "Trying to install msi data for IRQ%d\n", irq);
 		return -EINVAL;
@@ -200,7 +200,7 @@ int set_irq_chip_data(unsigned int irq,
 	struct irq_desc *desc = irq_desc + irq;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS || !desc->chip) {
+	if (irq >= nr_irqs || !desc->chip) {
 		printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq);
 		return -EINVAL;
 	}
@@ -544,7 +544,7 @@ __set_irq_handler(unsigned int irq, irq_
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR
 		       "Trying to install type control for IRQ%d\n", irq);
 		return;
@@ -609,7 +609,7 @@ void __init set_irq_noprobe(unsigned int
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR "Trying to mark IRQ%d non-probeable\n", irq);
 
 		return;
@@ -627,7 +627,7 @@ void __init set_irq_probe(unsigned int i
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS) {
+	if (irq >= nr_irqs) {
 		printk(KERN_ERR "Trying to mark IRQ%d probeable\n", irq);
 
 		return;
kernel/irq/handle.c +2 -1
Index: linux-2.6/kernel/irq/handle.c
===================================================================
@@ -47,6 +47,7 @@ handle_bad_irq(unsigned int irq, struct
  *
  * Controller mappings for all interrupt sources:
  */
+int nr_irqs = NR_IRQS;
 struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
 	[0 ... NR_IRQS-1] = {
 		.status = IRQ_DISABLED,
@@ -265,7 +266,7 @@ void early_init_irq_lock_class(void)
 {
 	int i;
 
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		lockdep_set_class(&irq_desc[i].lock, &irq_desc_lock_class);
 }
 
kernel/irq/manage.c +8 -8
Index: linux-2.6/kernel/irq/manage.c
===================================================================
@@ -34,7 +34,7 @@ void synchronize_irq(unsigned int irq)
 	struct irq_desc *desc = irq_desc + irq;
 	unsigned int status;
 
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return;
 
 	do {
@@ -143,7 +143,7 @@ void disable_irq_nosync(unsigned int irq
 	struct irq_desc *desc = irq_desc + irq;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return;
 
 	spin_lock_irqsave(&desc->lock, flags);
@@ -171,7 +171,7 @@ void disable_irq(unsigned int irq)
 {
 	struct irq_desc *desc = irq_desc + irq;
 
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return;
 
 	disable_irq_nosync(irq);
@@ -214,7 +214,7 @@ void enable_irq(unsigned int irq)
 	struct irq_desc *desc = irq_desc + irq;
 	unsigned long flags;
 
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return;
 
 	spin_lock_irqsave(&desc->lock, flags);
@@ -290,7 +290,7 @@ int can_request_irq(unsigned int irq, un
 {
 	struct irqaction *action;
 
-	if (irq >= NR_IRQS || irq_desc[irq].status & IRQ_NOREQUEST)
+	if (irq >= nr_irqs || irq_desc[irq].status & IRQ_NOREQUEST)
 		return 0;
 
 	action = irq_desc[irq].action;
@@ -349,7 +349,7 @@ int setup_irq(unsigned int irq, struct i
 	int shared = 0;
 	int ret;
 
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return -EINVAL;
 
 	if (desc->chip == &no_irq_chip)
@@ -503,7 +503,7 @@ void free_irq(unsigned int irq, void *de
 	unsigned long flags;
 
 	WARN_ON(in_interrupt());
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return;
 
 	desc = irq_desc + irq;
@@ -617,7 +617,7 @@ int request_irq(unsigned int irq, irq_ha
 	 */
 	if ((irqflags & IRQF_SHARED) && !dev_id)
 		return -EINVAL;
-	if (irq >= NR_IRQS)
+	if (irq >= nr_irqs)
 		return -EINVAL;
 	if (irq_desc[irq].status & IRQ_NOREQUEST)
 		return -EINVAL;
kernel/irq/proc.c +1 -1
Index: linux-2.6/kernel/irq/proc.c
===================================================================
@@ -234,7 +234,7 @@ void init_irq_proc(void)
 	/*
 	 * Create entries for all existing IRQs.
 	 */
-	for (i = 0; i < NR_IRQS; i++)
+	for (i = 0; i < nr_irqs; i++)
 		register_irq_proc(i);
 }
 
kernel/irq/resend.c +2 -2
Index: linux-2.6/kernel/irq/resend.c
===================================================================
@@ -33,8 +33,8 @@ static void resend_irqs(unsigned long ar
 	struct irq_desc *desc;
 	int irq;
 
-	while (!bitmap_empty(irqs_resend, NR_IRQS)) {
-		irq = find_first_bit(irqs_resend, NR_IRQS);
+	while (!bitmap_empty(irqs_resend, nr_irqs)) {
+		irq = find_first_bit(irqs_resend, nr_irqs);
 		clear_bit(irq, irqs_resend);
 		desc = irq_desc + irq;
 		local_irq_disable();
kernel/irq/spurious.c +2 -2
Index: linux-2.6/kernel/irq/spurious.c
===================================================================
@@ -91,7 +91,7 @@ static int misrouted_irq(int irq)
 	int i;
 	int ok = 0;
 
-	for (i = 1; i < NR_IRQS; i++) {
+	for (i = 1; i < nr_irqs; i++) {
 		struct irq_desc *desc = irq_desc + i;
 
 		if (i == irq)	/* Already tried */
@@ -107,7 +107,7 @@ static int misrouted_irq(int irq)
 static void poll_spurious_irqs(unsigned long dummy)
 {
 	int i;
-	for (i = 1; i < NR_IRQS; i++) {
+	for (i = 1; i < nr_irqs; i++) {
 		struct irq_desc *desc = irq_desc + i;
 		unsigned int status;
 
author
#13 lore raw

PATCH 5/7 pci: make irq2_iommu to use dyn_array

In reply to Yinghai Lu
---
 drivers/pci/intr_remapping.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/pci/intr_remapping.c +4 -2
Index: linux-2.6/drivers/pci/intr_remapping.c
===================================================================
@@ -11,12 +11,14 @@ static struct ioapic_scope ir_ioapic[MAX
 static int ir_ioapic_num;
 int intr_remapping_enabled;
 
-static struct {
+static struct irq_2_iommu {
 	struct intel_iommu *iommu;
 	u16 irte_index;
 	u16 sub_handle;
 	u8  irte_mask;
-} irq_2_iommu[NR_IRQS];
+} *irq_2_iommu;
+
+DEFINE_DYN_ARRAY(irq_2_iommu, sizeof(struct irq_2_iommu), nr_irqs, PAGE_SIZE, NULL);
 
 static DEFINE_SPINLOCK(irq_2_ir_lock);
 
author
#15 lore raw

PATCH 7/7 x86: make 64bit support dyn_array

In reply to Yinghai Lu

set nr_irqs according to nr_cpu_ids, so could get small footprint when use big kernel.

---
 arch/Kconfig                     |    2 ++
 arch/x86/Kconfig                 |    1 +
 arch/x86/kernel/io_apic_64.c     |   28 +++++++++++++++++++++-------
 arch/x86/kernel/setup.c          |    6 ++++++
 arch/x86/kernel/vmlinux_64.lds.S |    3 +++
 5 files changed, 33 insertions(+), 7 deletions(-)
arch/Kconfig +2 -0
Index: linux-2.6/arch/Kconfig
===================================================================
@@ -103,3 +103,5 @@ config HAVE_CLK
 	  The <linux/clk.h> calls support software clock gating and
 	  thus are a key power management tool on many systems.
 
+config HAVE_DYN_ARRAY
+	def_bool n
arch/x86/Kconfig +1 -0
Index: linux-2.6/arch/x86/Kconfig
===================================================================
@@ -33,6 +33,7 @@ config X86
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_GENERIC_DMA_COHERENT if X86_32
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_DYN_ARRAY if X86_64
 
 config ARCH_DEFCONFIG
 	string
arch/x86/kernel/io_apic_64.c +21 -7
Index: linux-2.6/arch/x86/kernel/io_apic_64.c
===================================================================
@@ -66,7 +66,7 @@ struct irq_cfg {
 };
 
 /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
-static struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = {
+static struct irq_cfg irq_cfg_legacy[] __initdata = {
 	[0]  = { .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR,  },
 	[1]  = { .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR,  },
 	[2]  = { .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR,  },
@@ -85,6 +85,17 @@ static struct irq_cfg irq_cfg[NR_IRQS] _
 	[15] = { .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, },
 };
 
+static struct irq_cfg *irq_cfg;
+
+static void __init init_work(void *data)
+{
+	struct dyn_array *da = data;
+
+	memcpy(*da->name, irq_cfg_legacy, sizeof(irq_cfg_legacy));
+}
+
+DEFINE_DYN_ARRAY(irq_cfg, sizeof(struct irq_cfg), nr_irqs, PAGE_SIZE, init_work);
+
 static int assign_irq_vector(int irq, cpumask_t mask);
 
 int first_system_vector = 0xfe;
@@ -129,10 +140,9 @@ DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BU
  * Rough estimation of how many shared IRQs there are, can
  * be changed anytime.
  */
-#define MAX_PLUS_SHARED_IRQS NR_IRQS
-#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
 
-int pin_map_size = PIN_MAP_SIZE;
+int pin_map_size;
+
 /*
  * This is performance-critical, we want to do it O(1)
  *
@@ -141,8 +151,12 @@ int pin_map_size = PIN_MAP_SIZE;
  */
 
 static struct irq_pin_list {
-	short apic, pin, next;
-} irq_2_pin[PIN_MAP_SIZE];
+	short apic, pin;
+	int next;
+} *irq_2_pin;
+
+DEFINE_DYN_ARRAY(irq_2_pin, sizeof(struct irq_pin_list), pin_map_size, sizeof(struct irq_pin_list), NULL);
+
 
 struct io_apic {
 	unsigned int index;
@@ -359,7 +373,7 @@ static void set_ioapic_affinity_irq(unsi
  * shared ISA-space IRQs, so we have to support them. We are super
  * fast in the common case, and fast for shared ISA-space IRQs.
  */
-int first_free_entry = NR_IRQS;
+int first_free_entry;
 static void add_pin_to_irq(unsigned int irq, int apic, int pin)
 {
 	struct irq_pin_list *entry = irq_2_pin + irq;
arch/x86/kernel/setup.c +6 -0
Index: linux-2.6/arch/x86/kernel/setup.c
===================================================================
@@ -856,7 +856,13 @@ void __init setup_arch(char **cmdline_p)
 #endif
 
 	prefill_possible_map();
+
 #ifdef CONFIG_X86_64
+	/* need to wait for nr_cpu_ids settle down */
+	if (nr_irqs == NR_IRQS)
+		nr_irqs = 32 * nr_cpu_ids + 224;
+	pin_map_size = nr_irqs * 2;
+	first_free_entry = nr_irqs;
 	init_cpu_to_node();
 #endif
 
arch/x86/kernel/vmlinux_64.lds.S +3 -0
Index: linux-2.6/arch/x86/kernel/vmlinux_64.lds.S
===================================================================
@@ -174,6 +174,9 @@ SECTIONS
 	*(.x86cpuvendor.init)
   }
   __x86cpuvendor_end = .;
+
+  DYN_ARRAY_INIT(8)
+
   SECURITY_INIT
 
   . = ALIGN(8);
author
#9 lore raw

PATCH 1/7 x86: 64bit support more than 256 irq v1

In reply to Yinghai Lu

Dhaval Giani got:
kernel BUG at arch/x86/kernel/io_apic_64.c:357!
invalid opcode: 0000 [1] SMP
CPU 24
...

his system (x3950) has 8 ioapic, irq > 256

caused by
commit 9b7dc567d03d74a1fbae84e88949b6a60d922d82
Author: Thomas Gleixner <[email protected]>
Date: Fri May 2 20:10:09 2008 +0200

x86: unify interrupt vector defines

The interrupt vector defines are copied 4 times around with minimal differences. Move them all into asm-x86/irq_vectors.h

because 64bit allow same vector for different cpu to serve different irq

need to create that array dynamically later

---
 include/asm-x86/irq_vectors.h |   14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)
include/asm-x86/irq_vectors.h +6 -8
Index: linux-2.6/include/asm-x86/irq_vectors.h
===================================================================
@@ -113,28 +113,26 @@
 
 # if defined(CONFIG_X86_IO_APIC) || defined(CONFIG_PARAVIRT) || defined(CONFIG_X86_VISWS)
 
+#ifdef CONFIG_X86_64
+#  define NR_IRQS		(32 * NR_CPUS + 224)
+#else
 #  define NR_IRQS		224
-
-#  if (224 >= 32 * NR_CPUS)
-#   define NR_IRQ_VECTORS	NR_IRQS
-#  else
-#   define NR_IRQ_VECTORS	(32 * NR_CPUS)
-#  endif
+#endif
 
 # else /* IO_APIC || PARAVIRT */
 
 #  define NR_IRQS		16
-#  define NR_IRQ_VECTORS	NR_IRQS
 
 # endif
 
 #else /* !VISWS && !VOYAGER */
 
 # define NR_IRQS		224
-# define NR_IRQ_VECTORS		NR_IRQS
 
 #endif /* VISWS */
 
+#define NR_IRQ_VECTORS		NR_IRQS
+
 /* Voyager specific defines */
 /* These define the CPIs we use in linux */
 #define VIC_CPI_LEVEL0			0
author
#11 lore raw

PATCH 3/7 add dyn_array support

In reply to Yinghai Lu

[
so could put some crazy big array in bootmem in init stage.

use CONFIG_HAVE_DYN_ARRAY to enable it or not

---
 include/asm-generic/vmlinux.lds.h |    7 +++++++
 include/linux/init.h              |   23 +++++++++++++++++++++++
 init/main.c                       |   25 +++++++++++++++++++++++++
 3 files changed, 55 insertions(+)
include/asm-generic/vmlinux.lds.h +7 -0
Index: linux-2.6/include/asm-generic/vmlinux.lds.h
===================================================================
@@ -214,6 +214,13 @@
  * All archs are supposed to use RO_DATA() */
 #define RODATA RO_DATA(4096)
 
+#define DYN_ARRAY_INIT(align)							\
+	. = ALIGN((align));						\
+	.dyn_array.init : AT(ADDR(.dyn_array.init) - LOAD_OFFSET) {	\
+		VMLINUX_SYMBOL(__dyn_array_start) = .;			\
+		*(.dyn_array.init)					\
+		VMLINUX_SYMBOL(__dyn_array_end) = .;			\
+	}
 #define SECURITY_INIT							\
 	.security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \
 		VMLINUX_SYMBOL(__security_initcall_start) = .;		\
include/linux/init.h +23 -0
Index: linux-2.6/include/linux/init.h
===================================================================
@@ -249,6 +249,29 @@ struct obs_kernel_param {
 
 /* Relies on boot_command_line being set */
 void __init parse_early_param(void);
+
+struct dyn_array {
+        void **name;
+        unsigned long size;
+        unsigned int *nr;
+        unsigned long align;
+        void (*init_work)(void *);
+};
+extern struct dyn_array *__dyn_array_start[], *__dyn_array_end[];
+
+#define DEFINE_DYN_ARRAY(nameX, sizeX, nrX, alignX, init_workX) \
+		static struct dyn_array __dyn_array_##nameX __initdata = \
+		{	.name = (void **)&nameX,\
+			.size = sizeX,\
+			.nr   = &nrX,\
+			.align = alignX,\
+			.init_work = init_workX,\
+		}; \
+		static struct dyn_array *__dyn_array_ptr_##nameX __used \
+		__attribute__((__section__(".dyn_array.init"))) = \
+			&__dyn_array_##nameX
+
+extern void pre_alloc_dyn_array(void);
 #endif /* __ASSEMBLY__ */
 
 /**
init/main.c +25 -0
Index: linux-2.6/init/main.c
===================================================================
@@ -539,6 +539,29 @@ void __init __weak thread_info_cache_ini
 {
 }
 
+void pre_alloc_dyn_array(void)
+{
+#ifdef CONFIG_HAVE_DYN_ARRAY
+	unsigned long size, phys = 0;
+	struct dyn_array **daa;
+
+	for (daa = __dyn_array_start ; daa < __dyn_array_end; daa++) {
+		struct dyn_array *da = *daa;
+
+		size = da->size * (*da->nr);
+		print_fn_descriptor_symbol("dyna_array %s ", da->name);
+		printk(KERN_CONT "size:%#lx nr:%d align:%#lx",
+			da->size, *da->nr, da->align);
+		*da->name = __alloc_bootmem_nopanic(size, da->align, phys);
+		phys = virt_to_phys(*da->name);
+		printk(KERN_CONT " ==> [%#lx - %#lx]\n", phys, phys + size);
+
+		if (da->init_work)
+			da->init_work(da);
+	}
+#endif
+}
+
 asmlinkage void __init start_kernel(void)
 {
 	char * command_line;
@@ -576,6 +599,8 @@ asmlinkage void __init start_kernel(void
 	printk(KERN_NOTICE);
 	printk(linux_banner);
 	setup_arch(&command_line);
+	printk(KERN_INFO "nr_irqs: %d\n", nr_irqs);
+	pre_alloc_dyn_array();
 	mm_init_owner(&init_mm, &init_task);
 	setup_command_line(command_line);
 	unwind_setup();
author
#14 lore raw

PATCH 6/7 irq: make irq_desc to use dyn_array

In reply to Yinghai Lu
---
 include/linux/irq.h |    4 ++++
 kernel/irq/handle.c |   31 +++++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+)
include/linux/irq.h +4 -0
Index: linux-2.6/include/linux/irq.h
===================================================================
@@ -181,7 +181,11 @@ struct irq_desc {
 	const char		*name;
 } ____cacheline_internodealigned_in_smp;
 
+#ifdef CONFIG_HAVE_DYN_ARRAY
+extern struct irq_desc *irq_desc;
+#else
 extern struct irq_desc irq_desc[NR_IRQS];
+#endif
 
 /*
  * Migration helpers for obsolete names, they will go away:
kernel/irq/handle.c +31 -0
Index: linux-2.6/kernel/irq/handle.c
===================================================================
@@ -48,6 +48,36 @@ handle_bad_irq(unsigned int irq, struct
  * Controller mappings for all interrupt sources:
  */
 int nr_irqs = NR_IRQS;
+
+#ifdef CONFIG_HAVE_DYN_ARRAY
+static struct irq_desc irq_desc_init = {
+	.status = IRQ_DISABLED,
+	.chip = &no_irq_chip,
+	.handle_irq = handle_bad_irq,
+	.depth = 1,
+	.lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock),
+#ifdef CONFIG_SMP
+	.affinity = CPU_MASK_ALL
+#endif
+};
+
+static void __init init_work(void *data)
+{
+	struct dyn_array *da = data;
+	int i;
+	struct  irq_desc *desc;
+
+	desc = *da->name;
+
+	for (i = 0; i < *da->nr; i++)
+		memcpy(&desc[i], &irq_desc_init, sizeof(struct irq_desc));
+}
+
+struct irq_desc *irq_desc;
+DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irqs, PAGE_SIZE, init_work);
+
+#else
+
 struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
 	[0 ... NR_IRQS-1] = {
 		.status = IRQ_DISABLED,
@@ -60,6 +90,7 @@ struct irq_desc irq_desc[NR_IRQS] __cach
 #endif
 	}
 };
+#endif
 
 /*
  * What should we do if we get a hw irq event on an illegal vector?
author
#12 lore raw

PATCH 4/7 random: make irq_timer_state to use dyn_array

In reply to Yinghai Lu
---
 drivers/char/random.c |    6 ++++++
 1 file changed, 6 insertions(+)
drivers/char/random.c +6 -0
Index: linux-2.6/drivers/char/random.c
===================================================================
@@ -558,7 +558,13 @@ struct timer_rand_state {
 };
 
 static struct timer_rand_state input_timer_state;
+
+#ifdef CONFIG_HAVE_DYN_ARRAY
+static struct timer_rand_state **irq_timer_state;
+DEFINE_DYN_ARRAY(irq_timer_state, sizeof(struct timer_rand_state *), nr_irqs, PAGE_SIZE, NULL);
+#else
 static struct timer_rand_state *irq_timer_state[NR_IRQS];
+#endif
 
 /*
  * This function adds entropy to the entropy "pool" by using timing
author
#17 lore raw

PATCH 1/3 serial: change irq_lists to use dyn_array

---
 drivers/serial/8250.c |    5 +++++
 1 file changed, 5 insertions(+)
drivers/serial/8250.c +5 -0
Index: linux-2.6/drivers/serial/8250.c
===================================================================
@@ -149,7 +149,12 @@ struct irq_info {
 	struct list_head	*head;
 };
 
+#if defined(CONFIG_HAVE_DYN_ARRAY) && !defined(MODULE)
+static struct irq_info *irq_lists;
+DEFINE_DYN_ARRAY(irq_lists, sizeof(struct irq_info), nr_irqs, PAGE_SIZE, NULL);
+#else
 static struct irq_info irq_lists[NR_IRQS];
+#endif
 
 /*
  * Here we define the default xmit fifo size used for each type of UART.
author
#25 lore raw

PATCH 2/3 add per_cpu_dyn_array support

In reply to Yinghai Lu

so could make array in per_cpu is allocated dynamically too

---
 arch/x86/kernel/setup_percpu.c    |    7 +++-
 include/asm-generic/vmlinux.lds.h |    6 ++++
 include/linux/init.h              |   27 ++++++++++++++++--
 init/main.c                       |   57 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 92 insertions(+), 5 deletions(-)
arch/x86/kernel/setup_percpu.c +5 -2
Index: linux-2.6/arch/x86/kernel/setup_percpu.c
===================================================================
@@ -140,7 +140,7 @@ static void __init setup_cpu_pda_map(voi
  */
 void __init setup_per_cpu_areas(void)
 {
-	ssize_t size = PERCPU_ENOUGH_ROOM;
+	ssize_t size, old_size;
 	char *ptr;
 	int cpu;
 
@@ -148,7 +148,8 @@ void __init setup_per_cpu_areas(void)
 	setup_cpu_pda_map();
 
 	/* Copy section for each CPU (we discard the original) */
-	size = PERCPU_ENOUGH_ROOM;
+	old_size = PERCPU_ENOUGH_ROOM;
+	size = old_size + per_cpu_dyn_array_size();
 	printk(KERN_INFO "PERCPU: Allocating %zd bytes of per cpu data\n",
 			  size);
 
@@ -176,6 +177,8 @@ void __init setup_per_cpu_areas(void)
 		per_cpu_offset(cpu) = ptr - __per_cpu_start;
 		memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
 
+		per_cpu_alloc_dyn_array(cpu, ptr + old_size);
+
 	}
 
 	printk(KERN_DEBUG "NR_CPUS: %d, nr_cpu_ids: %d, nr_node_ids %d\n",
include/asm-generic/vmlinux.lds.h +6 -0
Index: linux-2.6/include/asm-generic/vmlinux.lds.h
===================================================================
@@ -220,6 +220,12 @@
 		VMLINUX_SYMBOL(__dyn_array_start) = .;			\
 		*(.dyn_array.init)					\
 		VMLINUX_SYMBOL(__dyn_array_end) = .;			\
+	}								\
+	. = ALIGN((align));						\
+	.per_cpu_dyn_array.init : AT(ADDR(.per_cpu_dyn_array.init) - LOAD_OFFSET) {	\
+		VMLINUX_SYMBOL(__per_cpu_dyn_array_start) = .;		\
+		*(.per_cpu_dyn_array.init)				\
+		VMLINUX_SYMBOL(__per_cpu_dyn_array_end) = .;		\
 	}
 #define SECURITY_INIT							\
 	.security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \
include/linux/init.h +24 -3
Index: linux-2.6/include/linux/init.h
===================================================================
@@ -258,12 +258,13 @@ struct dyn_array {
         void (*init_work)(void *);
 };
 extern struct dyn_array *__dyn_array_start[], *__dyn_array_end[];
+extern struct dyn_array *__per_cpu_dyn_array_start[], *__per_cpu_dyn_array_end[];
 
-#define DEFINE_DYN_ARRAY(nameX, sizeX, nrX, alignX, init_workX) \
+#define DEFINE_DYN_ARRAY_ADDR(nameX, addrX, sizeX, nrX, alignX, init_workX) \
 		static struct dyn_array __dyn_array_##nameX __initdata = \
-		{	.name = (void **)&nameX,\
+		{	.name = (void **)&(nameX),\
 			.size = sizeX,\
-			.nr   = &nrX,\
+			.nr   = &(nrX),\
 			.align = alignX,\
 			.init_work = init_workX,\
 		}; \
@@ -271,7 +272,27 @@ extern struct dyn_array *__dyn_array_sta
 		__attribute__((__section__(".dyn_array.init"))) = \
 			&__dyn_array_##nameX
 
+#define DEFINE_DYN_ARRAY(nameX, sizeX, nrX, alignX, init_workX) \
+	DEFINE_DYN_ARRAY_ADDR(nameX, nameX, sizeX, nrX, alignX, init_workX)
+
+#define DEFINE_PER_CPU_DYN_ARRAY_ADDR(nameX, addrX, sizeX, nrX, alignX, init_workX) \
+		static struct dyn_array __per_cpu_dyn_array_##nameX __initdata = \
+		{	.name = (void **)&(addrX),\
+			.size = sizeX,\
+			.nr   = &(nrX),\
+			.align = alignX,\
+			.init_work = init_workX,\
+		}; \
+		static struct dyn_array *__per_cpu_dyn_array_ptr_##nameX __used \
+		__attribute__((__section__(".per_cpu_dyn_array.init"))) = \
+			&__per_cpu_dyn_array_##nameX
+
+#define DEFINE_PER_CPU_DYN_ARRAY(nameX, sizeX, nrX, alignX, init_workX) \
+	DEFINE_PER_CPU_DYN_ARRAY_ADDR(nameX, nameX, nrX, alignX, init_workX)
+
 extern void pre_alloc_dyn_array(void);
+extern unsigned long per_cpu_dyn_array_size(void);
+extern void per_cpu_alloc_dyn_array(int cpu, char *ptr);
 #endif /* __ASSEMBLY__ */
 
 /**
init/main.c +57 -0

63 lines not on this page · raw message

author
#26 lore raw

PATCH 3/3 irq: make irqs in kernel stat use per_cpu_dyn_array

In reply to Yinghai Lu
---
 include/linux/kernel_stat.h |    4 ++++
 kernel/sched.c              |    5 ++++-
 2 files changed, 8 insertions(+), 1 deletion(-)
include/linux/kernel_stat.h +4 -0
Index: linux-2.6/include/linux/kernel_stat.h
===================================================================
@@ -28,7 +28,11 @@ struct cpu_usage_stat {
 
 struct kernel_stat {
 	struct cpu_usage_stat	cpustat;
+#ifdef CONFIG_HAVE_DYN_ARRAY
+	unsigned int *irqs;
+#else
 	unsigned int irqs[NR_IRQS];
+#endif
 };
 
 DECLARE_PER_CPU(struct kernel_stat, kstat);
kernel/sched.c +4 -1
Index: linux-2.6/kernel/sched.c
===================================================================
@@ -4022,9 +4022,12 @@ static inline void idle_balance(int cpu,
 #endif
 
 DEFINE_PER_CPU(struct kernel_stat, kstat);
-
 EXPORT_PER_CPU_SYMBOL(kstat);
 
+#ifdef CONFIG_HAVE_DYN_ARRAY
+DEFINE_PER_CPU_DYN_ARRAY_ADDR(per_cpu__kstat_irqs, per_cpu__kstat.irqs, sizeof(unsigned int), nr_irqs, sizeof(unsigned long), NULL);
+#endif
+
 /*
  * Return p->sum_exec_runtime plus any more ns on the sched_clock
  * that have not yet been banked in case the task is currently running.
author
#19 lore raw

PATCH 1/1 serial: change remove NR_IRQS in 8250.c

In reply to Yinghai Lu

replace
[PATCH] serial: change irq_lists to use dyn_array
use small array with index to handle irq locking for serial port hope 32 slot is enough

---
 drivers/serial/8250.c |   73 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 67 insertions(+), 6 deletions(-)
drivers/serial/8250.c +67 -6
Index: linux-2.6/drivers/serial/8250.c
===================================================================
@@ -149,7 +149,55 @@ struct irq_info {
 	struct list_head	*head;
 };
 
-static struct irq_info irq_lists[NR_IRQS];
+struct irq_info_pair {
+	struct irq_info irq_info;
+	int irq_no;
+};
+
+#define NR_IRQ_INFO_PAIR	32
+
+static struct irq_info_pair irq_pair_lists[NR_IRQ_INFO_PAIR] = {
+	[0 ... NR_IRQ_INFO_PAIR-1] = {
+		.irq_no = -1,
+	}
+};
+
+static struct irq_info *get_irq_info(int irq, int with_free)
+{
+	int i, first_free = -1;
+
+	for (i = 0; i < NR_IRQ_INFO_PAIR; i++) {
+		if (irq_pair_lists[i].irq_no == irq)
+			return &irq_pair_lists[i].irq_info;
+		if (irq_pair_lists[i].irq_no == -1 && first_free == -1)
+			first_free = i;
+	}
+	if (!with_free)
+		return NULL;
+
+	if (first_free != -1) {
+		irq_pair_lists[first_free].irq_no = irq;
+		return &irq_pair_lists[first_free].irq_info;
+	}
+
+	WARN_ON("NR_IRQ_INFO_PAIR too small");
+
+	return NULL;
+}
+
+static void check_free_irq_info(int irq_no)
+{
+
+	int i;
+
+	for (i = 0; i < NR_IRQ_INFO_PAIR; i++) {
+		if (irq_pair_lists[i].irq_no != irq_no)
+			continue;
+
+		irq_pair_lists[i].irq_no = -1;
+		break;
+	}
+}
 
 /*
  * Here we define the default xmit fifo size used for each type of UART.
@@ -1554,9 +1602,12 @@ static void serial_do_unlink(struct irq_
 
 static int serial_link_irq_chain(struct uart_8250_port *up)
 {
-	struct irq_info *i = irq_lists + up->port.irq;
+	struct irq_info *i = get_irq_info(up->port.irq, 1);
 	int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
 
+	if (!i)
+		return -1;
+
 	spin_lock_irq(&i->lock);
 
 	if (i->head) {
@@ -1580,14 +1631,24 @@ static int serial_link_irq_chain(struct
 
 static void serial_unlink_irq_chain(struct uart_8250_port *up)
 {
-	struct irq_info *i = irq_lists + up->port.irq;
+	int irq_no = up->port.irq;
+	struct irq_info *i = get_irq_info(irq_no, 0);
+	int empty = 0;
+
+	if (!i)
+		return;
 
 	BUG_ON(i->head == NULL);
 
-	if (list_empty(i->head))
+	if (list_empty(i->head)) {
 		free_irq(up->port.irq, i);
+		empty = 1;
+	}
 
 	serial_do_unlink(i, up);
+
+	if (empty)
+		check_free_irq_info(irq_no);
 }
 
 /* Base timer interval for polling */
@@ -2964,8 +3025,8 @@ static int __init serial8250_init(void)
 		"%d ports, IRQ sharing %sabled\n", nr_uarts,
 		share_irqs ? "en" : "dis");
 
-	for (i = 0; i < nr_irqs; i++)
-		spin_lock_init(&irq_lists[i].lock);
+	for (i = 0; i < NR_IRQ_INFO_PAIR; i++)
+		spin_lock_init(&irq_pair_lists[i].irq_info.lock);
 
 	ret = uart_register_driver(&serial8250_reg);
 	if (ret)
author
#27 lore raw

PATCH 1/1 x86 remove irq_vectors_limit.h

In reply to Yinghai Lu

no user

later
1. need to make 32bit to support dyn_array for irq_vector[]
2. also need to probe nr_irqs via madt and mptable

include/asm-x86/mach-generic/irq_vectors_limits.h deleted +0 -14
Index: linux-2.6/include/asm-x86/mach-generic/irq_vectors_limits.h
===================================================================
@@ -1,14 +0,0 @@
-#ifndef ASM_X86__MACH_GENERIC__IRQ_VECTORS_LIMITS_H
-#define ASM_X86__MACH_GENERIC__IRQ_VECTORS_LIMITS_H
-
-/*
- * For Summit or generic (i.e. installer) kernels, we have lots of I/O APICs,
- * even with uni-proc kernels, so use a big array.
- *
- * This value should be the same in both the generic and summit subarches.
- * Change one, change 'em both.
- */
-#define NR_IRQS	224
-#define NR_IRQ_VECTORS	1024
-
-#endif /* ASM_X86__MACH_GENERIC__IRQ_VECTORS_LIMITS_H */
include/asm-x86/summit/irq_vectors_limits.h deleted +0 -14
Index: linux-2.6/include/asm-x86/summit/irq_vectors_limits.h
===================================================================
@@ -1,14 +0,0 @@
-#ifndef _ASM_IRQ_VECTORS_LIMITS_H
-#define _ASM_IRQ_VECTORS_LIMITS_H
-
-/*
- * For Summit or generic (i.e. installer) kernels, we have lots of I/O APICs,
- * even with uni-proc kernels, so use a big array.
- *
- * This value should be the same in both the generic and summit subarches.
- * Change one, change 'em both.
- */
-#define NR_IRQS	224
-#define NR_IRQ_VECTORS	1024
-
-#endif /* _ASM_IRQ_VECTORS_LIMITS_H */
#20 lore raw

Re: [PATCH] serial: change remove NR_IRQS in 8250.c

In reply to Yinghai Lu
Quoted 4 lines

replace
[PATCH] serial: change irq_lists to use dyn_array
use small array with index to handle irq locking for serial port hope 32 slot is enough

Could you size this array by NR_UARTS (our worst case usage) and place irq_no in struct irq_info?

Also you want to hold irq_info->lock when you set or clear irq_no. Just to be on the safe side. I expect we can avoid clearing the irq_no in the irq_lists and prevent a few more races from being a possibility.

Eric

#21 lore raw

Re: [PATCH] serial: change remove NR_IRQS in 8250.c

Quoted 7 lines · On Thu, 31 Jul 2008 04:50:21 -0700 [email protected] (Eric W. Biederman)…
Quoted 4 lines

replace
[PATCH] serial: change irq_lists to use dyn_array
use small array with index to handle irq locking for serial port hope 32 slot is enough

Could you size this array by NR_UARTS (our worst case usage) and place irq_no in struct irq_info?

NR_UARTS is likely to go away in time so don't get attached to it

#28 lore raw

Re: [PATCH 0/3] dyn_array support #2

In reply to Yinghai Lu
Quoted 5 lines · Yinghai Lu

please check the patches adding dyn_array and nr_irqs #2

Thanks

YH

It appears that the primary difference between your patch and Eric's is that you estimate the number of IRQ's required based on the number of cpus present, while Eric's patch grows the list based on the IRQ's being requested. For soon to be "power" desktop systems (say dual 8 core Nahalem's w/HT), you're reserving IRQ's for 32 cpus on a system which probably has one I/O bus (or maybe two). A dual socket Larabbee system will have 256 cpus. An SGI UV system has more of a "building block" approach, where you can grow all three (cpus, memory, I/O) independently.

One other very nice feature of Eric's approach is that the new "IRQ" struct being requested can be created in "node local" memory, cutting down significantly the number of "cross node" accesses.

Plus, I still like Ingo's suggestion to not change NR_IRQS ==> nr_irqs. CONFIG_ARCH_HAS_DYNAMIC_IRQS spells out exactly what NR_IRQS means. (Even more accurate would be CONFIG_ARCH_HAS_DYNAMIC_NR_IRQS.)

The DEFINE_DYN_ARRAY could be the following. (Changing general purpose DYN_ARRAY to specifically purposed IRQ_ARRAY.)

#ifdef CONFIG_ARCH_HAS_DYNAMIC_IRQS
#define DEFINE_IRQ_ARRAY <new variable irq array [or list] definition> #else
#define DEFINE_IRQ_ARRAY <old static irq array>
#endif

For the immediate problem, unraveling the code merge back to IRQ's based on NR_IOAPICS would seem to be the least intrusive.

Thanks,
Mike

#22 lore raw

Re: [PATCH] serial: change remove NR_IRQS in 8250.c

In reply to Alan Cox
Quoted 8 lines · Alan Cox
Quoted 5 lines · On Thu, 31 Jul 2008 04:50:21 -0700 [email protected] (Eric W. Biederman)…
Quoted 4 lines

replace
[PATCH] serial: change irq_lists to use dyn_array
use small array with index to handle irq locking for serial port hope 32 slot is enough

Quoted 4 lines
Quoted 2 lines

Could you size this array by NR_UARTS (our worst case usage) and place irq_no in struct irq_info?

NR_UARTS is likely to go away in time so don't get attached to it

I'm not attached to it, but NR_UARTS is a closer approximation to what we are trying to do then YH's hard coded 32. Do you know if we actually need the list of uarts per irq or if request_irq having a shared isa would work?

The practical question is how do we cleanly kill the array irq_lists[NR_IRQS]. YH's hack where he isn't paying attention to what the code is doing and just trying to avoid the problem is not something I am fond of seeing being merged.

It is also true that sorting out 8250.c and by extension the other serial drivers that have cloned it is the significant non-arch piece of work needed to kill NR_IRQs

Eric

author
#29 lore raw

Re: [PATCH 0/3] dyn_array support #2

In reply to Mike Travis
Quoted 17 lines · Mike Travis
Quoted 5 lines · Yinghai Lu

please check the patches adding dyn_array and nr_irqs #2

Thanks

YH

It appears that the primary difference between your patch and Eric's is that you estimate the number of IRQ's required based on the number of cpus present, while Eric's patch grows the list based on the IRQ's being requested. For soon to be "power" desktop systems (say dual 8 core Nahalem's w/HT), you're reserving IRQ's for 32 cpus on a system which probably has one I/O bus (or maybe two). A dual socket Larabbee system will have 256 cpus. An SGI UV system has more of a "building block" approach, where you can grow all three (cpus, memory, I/O) independently.

Quoted 3 lines

One other very nice feature of Eric's approach is that the new "IRQ" struct being requested can be created in "node local" memory, cutting down significantly the number of "cross node" accesses.

where is Eric's patch? I didn't get it...

Quoted 4 lines

Plus, I still like Ingo's suggestion to not change NR_IRQS ==> nr_irqs. CONFIG_ARCH_HAS_DYNAMIC_IRQS spells out exactly what NR_IRQS means. (Even more accurate would be CONFIG_ARCH_HAS_DYNAMIC_NR_IRQS.)

not every array need to be changed to dyn_array, if the static array is not big enough.
and some DEFINE_BIT map is using NR_IRQS.

Quoted 3 lines

The DEFINE_DYN_ARRAY could be the following. (Changing general purpose DYN_ARRAY to specifically purposed IRQ_ARRAY.)

dyn_array is some more generic, and nr_irqs is one of it's user

Quoted 9 lines

#ifdef CONFIG_ARCH_HAS_DYNAMIC_IRQS
#define DEFINE_IRQ_ARRAY <new variable irq array [or list] definition> #else
#define DEFINE_IRQ_ARRAY <old static irq array>
#endif

For the immediate problem, unraveling the code merge back to IRQ's based on NR_IOAPICS would seem to be the least intrusive.

less intrusive way could be use dyn_array and make nr_irqs to be set via acpi_madt_oem_check...

YH

#30 lore raw

Re: [PATCH 0/3] dyn_array support #2

In reply to Yinghai Lu
Quoted 1 line · Yinghai Lu

please check the patches adding dyn_array and nr_irqs #2

Why can't we use a radix tree like powerpc does?

author
#31 lore raw

Re: [PATCH 0/3] dyn_array support #2

Quoted 5 lines · Peter Zijlstra
Quoted 1 line · Yinghai Lu

please check the patches adding dyn_array and nr_irqs #2

Why can't we use a radix tree like powerpc does?

which file in arch/power i could look?

YH

#34 lore raw

Re: [PATCH 0/3] dyn_array support #2

In reply to Peter Zijlstra
Quoted 4 lines · Peter Zijlstra
Quoted 1 line · Yinghai Lu

please check the patches adding dyn_array and nr_irqs #2

Why can't we use a radix tree like powerpc does?

Unless I am mistaken the ppc uses the radix tree for something different. We don't have any architecture in the kernel to my knowledge that doesn't use an array of irq_desc entries.

Killing the array of irq_desc entries and along with it NR_IRQS is what needs to happen.

Eric

author
#32 lore raw

Re: [PATCH 0/3] dyn_array support #2

In reply to Yinghai Lu

please try attach nr_irqs dyn_array quilt patchset on your x3960 and UV...

it autodetect nr_irqs

need apply to tip/master.

Thanks

Yinghai Lu

#23 lore raw

Re: [PATCH] serial: change remove NR_IRQS in 8250.c

In reply to Eric W. Biederman
Quoted 8 lines

The practical question is how do we cleanly kill the array irq_lists[NR_IRQS]. YH's hack where he isn't paying attention to what the code is doing and just trying to avoid the problem is not something I am fond of seeing being merged.

It is also true that sorting out 8250.c and by extension the other serial drivers that have cloned it is the significant non-arch piece of work needed to kill NR_IRQs

Lets just make it happen next week. It needs doing and while it wasn't top of the serial work list this is a good reason to kill it off.

Alan

author
#24 lore raw

Re: [PATCH] serial: change remove NR_IRQS in 8250.c

In reply to Eric W. Biederman
Quoted 6 lines · Eric W. Biederman
Quoted 4 lines

replace
[PATCH] serial: change irq_lists to use dyn_array
use small array with index to handle irq locking for serial port hope 32 slot is enough

Could you size this array by NR_UARTS (our worst case usage)

how about crazy user set that too big?

Quoted 1 line

and place irq_no in struct irq_info?

should be ok

Quoted 4 lines

Also you want to hold irq_info->lock when you set or clear irq_no. Just to be on the safe side. I expect we can avoid clearing the irq_no in the irq_lists and prevent a few more races from being a possibility.

will try

YH

#35 lore raw

Re: [PATCH 0/7] dyn_array support

In reply to Yinghai Lu

Ugh. Looks like I forgot to hit send on this.

Quoted 1 line · Yinghai Lu

please check the patches adding dyn_array and nr_irqs

YH thank you for working on this.

To fix the post rc1 regression I believe your patch series is very much overkill. We need to fix this but the bug should be fixed first by restoring the old heuristics for NR_IRQS. I will carefully look at your first patch and see if it successfully restores the old heuristics, I don't think it quite does.

I very much do not like this approach of introducing nr_irqs instead of NR_IRQS. It does not kill NR_IRQS it just renames it and it does not appear to me to solve the real issues, and it seems to entrench some current mistakes instead of clean them up. When I said NR_IRQS must die I meant the concept not the spelling. Having a fixed sized array is only part of it. We actually use that array very sparsely. So even having an array of irq_desc structures is painful.

Further we want to user our irq numbers sparsely so that we can have a stable irq numbers even for things such as msis.

Outside of the arch specific code and the irq implementation there are currently only 40 mentions of NR_IRQS, and only 7 mentions of NR_IRQS as an array size.

git-ls-files | grep -v '^arch' | grep -v '^include/asm' | \
grep -v '^kernel/irq' | grep -v 'drivers/xen/events.c' | \
xargs grep '[^A-Za-z0-9_]NR_IRQS[^A-Za-z0-9_]' | wc -l

There is little to no excuse for the generic code to be using NR_IRQS. The usage in /dev/random should be moved in some form into irq_desc. The usage in the serial code and in intr_remapping are failures to use current best practices. For most of the rest simply introducing an irq valid helper function would solve the issue.

Further once we have killed the usage of NR_IRQS outside of the arch code. We don't need to introduce new infrastructure. We can call alloc_bootmem as appropriate, and we can consider important things such as NUMA affinity with the irq controllers, and where we expect the irqs to be serviced.

Plus we don't have to allocate anything beyond the gsi or their mptable equivalents until someone actually uses the msi or htirq interrupt.

Which means we can be a lot leaner, allocating precisely the irqs we need, and a lot more efficient with NUMA affinity and by allocating irqs as they show up.

Eric