2008-08-03 03:00:33

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 00/25] dyn_array and nr_irqs support v3

Peter, Andrew,

Please check dyn_array support for x86
v3: split changing to nr_irqs to small patches
fix checkpatch error
reorder the patch sequence to make dyn_array support go at first
so could use that with arrays other than NR_IRQS

01: should get into 2.6.27 for bug 11201
02: should get into tip
remove two unused files
03-06: should get into tip or -mm
for generic dyn_array support for x86
21: should get into serial tree?
others: are examples to use dyn_array with nr_irqs...

Thanks

Yinghai Lu


2008-08-03 03:00:55

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 01/25] 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
...

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

v2: change NR_IRQS to 1024

Signed-off-by: Yinghai Lu <[email protected]>
Tested-by: Dhaval Giani <[email protected]>
---
include/asm-x86/irq_vectors.h | 12 +++---------
1 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/include/asm-x86/irq_vectors.h b/include/asm-x86/irq_vectors.h
index 646d59f..0817a19 100644
--- a/include/asm-x86/irq_vectors.h
+++ b/include/asm-x86/irq_vectors.h
@@ -113,28 +113,22 @@

# if defined(CONFIG_X86_IO_APIC) || defined(CONFIG_PARAVIRT) || defined(CONFIG_X86_VISWS)

-# define NR_IRQS 224
-
-# if (224 >= 32 * NR_CPUS)
-# define NR_IRQ_VECTORS NR_IRQS
-# else
-# define NR_IRQ_VECTORS (32 * NR_CPUS)
-# endif
+#define NR_IRQS 1024

# 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
--
1.5.4.5

2008-08-03 03:01:18

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 02/25] x86: remove irq_vectors_limits

no user

Signed-off-by: Yinghai Lu <[email protected]>
---
include/asm-x86/mach-generic/irq_vectors_limits.h | 14 --------------
include/asm-x86/summit/irq_vectors_limits.h | 14 --------------
2 files changed, 0 insertions(+), 28 deletions(-)
delete mode 100644 include/asm-x86/mach-generic/irq_vectors_limits.h
delete mode 100644 include/asm-x86/summit/irq_vectors_limits.h

diff --git a/include/asm-x86/mach-generic/irq_vectors_limits.h b/include/asm-x86/mach-generic/irq_vectors_limits.h
deleted file mode 100644
index f7870e1..0000000
--- a/include/asm-x86/mach-generic/irq_vectors_limits.h
+++ /dev/null
@@ -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 */
diff --git a/include/asm-x86/summit/irq_vectors_limits.h b/include/asm-x86/summit/irq_vectors_limits.h
deleted file mode 100644
index 890ce3f..0000000
--- a/include/asm-x86/summit/irq_vectors_limits.h
+++ /dev/null
@@ -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 */
--
1.5.4.5

2008-08-03 03:01:48

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 04/25] add per_cpu_dyn_array support

could make array in per_cpu is allocated dynamically too

usage:
| /* in .h */
|struct kernel_stat {
| struct cpu_usage_stat cpustat;
| unsigned int *irqs;
|};
|
| /* in .c */
|DEFINE_PER_CPU(struct kernel_stat, kstat);
|
|DEFINE_PER_CPU_DYN_ARRAY_ADDR(per_cpu__kstat_irqs, per_cpu__kstat.irqs, sizeof(unsigned int), nr_irqs, sizeof(unsigned long), NULL);

after setup_percpu()/per_cpu_alloc_dyn_array(), that dyn_array in per_cpu area is ready to use

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/kernel/setup_percpu.c | 7 +++-
include/asm-generic/vmlinux.lds.h | 6 +++
include/linux/init.h | 27 ++++++++++++++--
init/main.c | 63 +++++++++++++++++++++++++++++++++++-
4 files changed, 96 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index 0e67f72..13ba7a8 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -140,7 +140,7 @@ static void __init setup_cpu_pda_map(void)
*/
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",
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 1c3daac..e76244a 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/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) { \
diff --git a/include/linux/init.h b/include/linux/init.h
index c31cd94..9fbe61b 100644
--- a/include/linux/init.h
+++ b/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_start[], *__dyn_array_end[];
__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__ */

/**
diff --git a/init/main.c b/init/main.c
index 54864c0..a600562 100644
--- a/init/main.c
+++ b/init/main.c
@@ -394,17 +394,19 @@ EXPORT_SYMBOL(__per_cpu_offset);

static void __init setup_per_cpu_areas(void)
{
- unsigned long size, i;
+ unsigned long size, i, old_size;
char *ptr;
unsigned long nr_possible_cpus = num_possible_cpus();

/* Copy section for each CPU (we discard the original) */
- size = ALIGN(PERCPU_ENOUGH_ROOM, PAGE_SIZE);
+ old_size = PERCPU_ENOUGH_ROOM;
+ size = ALIGN(old_size + per_cpu_dyn_array_size(), PAGE_SIZE);
ptr = alloc_bootmem_pages(size * nr_possible_cpus);

for_each_possible_cpu(i) {
__per_cpu_offset[i] = ptr - __per_cpu_start;
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
+ per_cpu_alloc_dyn_array(cpu, ptr + old_size);
ptr += size;
}
}
@@ -562,6 +564,63 @@ void pre_alloc_dyn_array(void)
#endif
}

+unsigned long per_cpu_dyn_array_size(void)
+{
+ unsigned long total_size = 0;
+#ifdef CONFIG_HAVE_DYN_ARRAY
+ unsigned long size;
+ struct dyn_array **daa;
+
+ for (daa = __per_cpu_dyn_array_start ; daa < __per_cpu_dyn_array_end; daa++) {
+ struct dyn_array *da = *daa;
+
+ size = da->size * (*da->nr);
+ print_fn_descriptor_symbol("per_cpu_dyna_array %s ", da->name);
+ printk(KERN_CONT "size:%#lx nr:%d align:%#lx\n",
+ da->size, *da->nr, da->align);
+ total_size += roundup(size, da->align);
+ }
+ if (total_size)
+ printk(KERN_DEBUG "per_cpu_dyna_array total_size: %#lx\n",
+ total_size);
+#endif
+ return total_size;
+}
+
+void per_cpu_alloc_dyn_array(int cpu, char *ptr)
+{
+#ifdef CONFIG_HAVE_DYN_ARRAY
+ unsigned long size, phys;
+ struct dyn_array **daa;
+ unsigned long addr;
+ void **array;
+
+ phys = virt_to_phys(ptr);
+
+ for (daa = __per_cpu_dyn_array_start ; daa < __per_cpu_dyn_array_end; daa++) {
+ struct dyn_array *da = *daa;
+
+ size = da->size * (*da->nr);
+ print_fn_descriptor_symbol("per_cpu_dyna_array %s ", da->name);
+ printk(KERN_CONT "size:%#lx nr:%d align:%#lx",
+ da->size, *da->nr, da->align);
+
+ phys = roundup(phys, da->align);
+ addr = (unsigned long)da->name;
+ addr += per_cpu_offset(cpu);
+ array = (void **)addr;
+ *array = phys_to_virt(phys);
+ *da->name = *array; /* so init_work could use it directly */
+ printk(KERN_CONT " %p ==> [%#lx - %#lx]\n", array, phys, phys + size);
+ phys += size;
+
+ if (da->init_work) {
+ da->init_work(da);
+ }
+ }
+#endif
+}
+
asmlinkage void __init start_kernel(void)
{
char * command_line;
--
1.5.4.5

2008-08-03 03:01:35

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 03/25] add dyn_array support

could have crazy big arrays and allocate them in bootmem at init stage.
also also to allocate array according to size we need to use to avoid wasting
memory
use CONFIG_HAVE_DYN_ARRAY to enable it or not

usage:

|static struct irq_desc irq_desc_init __initdata = {
| .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;
| struct irq_desc *desc;
| int i;
|
| 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);

after pre_alloc_dyn_array() after setup_arch(), that array is ready to use
in this way could replace irq_desc[NR_IRQS] array with dyn_array irq_desc[nr_irqs]

Signed-off-by: Yinghai Lu <[email protected]>
---
include/asm-generic/vmlinux.lds.h | 7 +++++++
include/linux/init.h | 23 +++++++++++++++++++++++
init/main.c | 24 ++++++++++++++++++++++++
3 files changed, 54 insertions(+), 0 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index a44ec7a..1c3daac 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/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) = .; \
diff --git a/include/linux/init.h b/include/linux/init.h
index 915c5b9..c31cd94 100644
--- a/include/linux/init.h
+++ b/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__ */

/**
diff --git a/init/main.c b/init/main.c
index 3f8fa37..54864c0 100644
--- a/init/main.c
+++ b/init/main.c
@@ -539,6 +539,29 @@ void __init __weak thread_info_cache_init(void)
{
}

+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,7 @@ asmlinkage void __init start_kernel(void)
printk(KERN_NOTICE);
printk(linux_banner);
setup_arch(&command_line);
+ pre_alloc_dyn_array();
mm_init_owner(&init_mm, &init_task);
setup_command_line(command_line);
unwind_setup();
--
1.5.4.5

2008-08-03 03:02:10

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 05/25] x86: alloc dyn_array all alltogether

so could spare some memory with small alignment in bootmem

also tighten the alignment checking..., and make print out less debug info

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/kernel/setup_percpu.c | 16 +++++++---
include/linux/init.h | 2 +-
init/main.c | 65 ++++++++++++++++++++++++++++++---------
3 files changed, 62 insertions(+), 21 deletions(-)

diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index 13ba7a8..4702c12 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -140,26 +140,31 @@ static void __init setup_cpu_pda_map(void)
*/
void __init setup_per_cpu_areas(void)
{
- ssize_t size, old_size;
+ ssize_t size, old_size, da_size;
char *ptr;
int cpu;
+ unsigned long align = 1;

/* Setup cpu_pda map */
setup_cpu_pda_map();

/* Copy section for each CPU (we discard the original) */
old_size = PERCPU_ENOUGH_ROOM;
- size = old_size + per_cpu_dyn_array_size();
+ da_size = per_cpu_dyn_array_size(&align);
+ align = max_t(unsigned long, PAGE_SIZE, align);
+ size = roundup(old_size + da_size, align);
printk(KERN_INFO "PERCPU: Allocating %zd bytes of per cpu data\n",
size);

for_each_possible_cpu(cpu) {
#ifndef CONFIG_NEED_MULTIPLE_NODES
- ptr = alloc_bootmem_pages(size);
+ ptr = __alloc_bootmem_nopanic(size, align,
+ __pa(MAX_DMA_ADDRESS));
#else
int node = early_cpu_to_node(cpu);
if (!node_online(node) || !NODE_DATA(node)) {
- ptr = alloc_bootmem_pages(size);
+ ptr = __alloc_bootmem_nopanic(size, align,
+ __pa(MAX_DMA_ADDRESS));
printk(KERN_INFO
"cpu %d has no node %d or node-local memory\n",
cpu, node);
@@ -168,7 +173,8 @@ void __init setup_per_cpu_areas(void)
cpu, __pa(ptr));
}
else {
- ptr = alloc_bootmem_pages_node(NODE_DATA(node), size);
+ ptr = __alloc_bootmem_node(NODE_DATA(node), size, align,
+ __pa(MAX_DMA_ADDRESS));
if (ptr)
printk(KERN_DEBUG "per cpu data for cpu%d on node%d at %016lx\n",
cpu, node, __pa(ptr));
diff --git a/include/linux/init.h b/include/linux/init.h
index 9fbe61b..2e42af8 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -291,7 +291,7 @@ extern struct dyn_array *__per_cpu_dyn_array_start[], *__per_cpu_dyn_array_end[]
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 unsigned long per_cpu_dyn_array_size(unsigned long *align);
extern void per_cpu_alloc_dyn_array(int cpu, char *ptr);
#endif /* __ASSEMBLY__ */

diff --git a/init/main.c b/init/main.c
index a600562..3454b4a 100644
--- a/init/main.c
+++ b/init/main.c
@@ -397,10 +397,14 @@ static void __init setup_per_cpu_areas(void)
unsigned long size, i, old_size;
char *ptr;
unsigned long nr_possible_cpus = num_possible_cpus();
+ unsigned long align = 1;
+ unsigned da_size;

/* Copy section for each CPU (we discard the original) */
old_size = PERCPU_ENOUGH_ROOM;
- size = ALIGN(old_size + per_cpu_dyn_array_size(), PAGE_SIZE);
+ da_size = per_cpu_dyn_array_size(&align);
+ align = max_t(unsigned long, PAGE_SIZE, align);
+ size = ALIGN(old_size + da_size, align);
ptr = alloc_bootmem_pages(size * nr_possible_cpus);

for_each_possible_cpu(i) {
@@ -544,45 +548,78 @@ void __init __weak thread_info_cache_init(void)
void pre_alloc_dyn_array(void)
{
#ifdef CONFIG_HAVE_DYN_ARRAY
- unsigned long size, phys = 0;
+ unsigned long total_size = 0, size, phys;
+ unsigned long max_align = 1;
struct dyn_array **daa;
+ char *ptr;

+ /* get the total size at first */
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",
+ print_fn_descriptor_symbol("dyn_array %s ", da->name);
+ printk(KERN_CONT "size:%#lx nr:%d align:%#lx\n",
da->size, *da->nr, da->align);
- *da->name = __alloc_bootmem_nopanic(size, da->align, phys);
- phys = virt_to_phys(*da->name);
+ total_size += roundup(size, da->align);
+ if (da->align > max_align)
+ max_align = da->align;
+ }
+ if (total_size)
+ printk(KERN_DEBUG "dyn_array total_size: %#lx\n",
+ total_size);
+ else
+ return;
+
+ /* allocate them all together */
+ max_align = max_t(unsigned long, max_align, PAGE_SIZE);
+ ptr = __alloc_bootmem_nopanic(total_size, max_align, 0);
+ if (!ptr)
+ panic("Can not alloc dyn_alloc\n");
+
+ phys = virt_to_phys(ptr);
+ for (daa = __dyn_array_start ; daa < __dyn_array_end; daa++) {
+ struct dyn_array *da = *daa;
+
+ size = da->size * (*da->nr);
+ print_fn_descriptor_symbol("dyn_array %s ", da->name);
+
+ phys = roundup(phys, da->align);
+ *da->name = phys_to_virt(phys);
printk(KERN_CONT " ==> [%#lx - %#lx]\n", phys, phys + size);

+ phys += size;
+
if (da->init_work)
da->init_work(da);
}
#endif
}

-unsigned long per_cpu_dyn_array_size(void)
+unsigned long per_cpu_dyn_array_size(unsigned long *align)
{
unsigned long total_size = 0;
#ifdef CONFIG_HAVE_DYN_ARRAY
unsigned long size;
struct dyn_array **daa;
+ unsigned max_align = 1;

for (daa = __per_cpu_dyn_array_start ; daa < __per_cpu_dyn_array_end; daa++) {
struct dyn_array *da = *daa;

size = da->size * (*da->nr);
- print_fn_descriptor_symbol("per_cpu_dyna_array %s ", da->name);
+ print_fn_descriptor_symbol("per_cpu_dyn_array %s ", da->name);
printk(KERN_CONT "size:%#lx nr:%d align:%#lx\n",
da->size, *da->nr, da->align);
total_size += roundup(size, da->align);
+ if (da->align > max_align)
+ max_align = da->align;
}
- if (total_size)
- printk(KERN_DEBUG "per_cpu_dyna_array total_size: %#lx\n",
+ if (total_size) {
+ printk(KERN_DEBUG "per_cpu_dyn_array total_size: %#lx\n",
total_size);
+ *align = max_align;
+ }
#endif
return total_size;
}
@@ -596,14 +633,11 @@ void per_cpu_alloc_dyn_array(int cpu, char *ptr)
void **array;

phys = virt_to_phys(ptr);
-
for (daa = __per_cpu_dyn_array_start ; daa < __per_cpu_dyn_array_end; daa++) {
struct dyn_array *da = *daa;

size = da->size * (*da->nr);
- print_fn_descriptor_symbol("per_cpu_dyna_array %s ", da->name);
- printk(KERN_CONT "size:%#lx nr:%d align:%#lx",
- da->size, *da->nr, da->align);
+ print_fn_descriptor_symbol("per_cpu_dyn_array %s ", da->name);

phys = roundup(phys, da->align);
addr = (unsigned long)da->name;
@@ -611,7 +645,8 @@ void per_cpu_alloc_dyn_array(int cpu, char *ptr)
array = (void **)addr;
*array = phys_to_virt(phys);
*da->name = *array; /* so init_work could use it directly */
- printk(KERN_CONT " %p ==> [%#lx - %#lx]\n", array, phys, phys + size);
+ printk(KERN_CONT " ==> [%#lx - %#lx]\n", phys, phys + size);
+
phys += size;

if (da->init_work) {
--
1.5.4.5

2008-08-03 03:02:42

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 07/25] introduce nr_irqs

and at this point it is equal NR_IRQS

Signed-off-by: Yinghai Lu <[email protected]>
---
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 ++--
8 files changed, 32 insertions(+), 29 deletions(-)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index 1d73d1a..bd69d90 100644
--- a/include/linux/irq.h
+++ b/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);
diff --git a/kernel/irq/autoprobe.c b/kernel/irq/autoprobe.c
index 533068c..c689e98 100644
--- a/kernel/irq/autoprobe.c
+++ b/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 long val)
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;

diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 3cd441e..20a9307 100644
--- a/kernel/irq/chip.c
+++ b/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 irq)
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, struct irq_chip *chip)
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, unsigned int type)
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 *data)
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 msi_desc *entry)
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, void *data)
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_flow_handler_t handle, int is_chained,
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 irq)
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 irq)
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;
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index f4c8a03..e9d022c 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -47,6 +47,7 @@ handle_bad_irq(unsigned int irq, struct irq_desc *desc)
*
* 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);
}

diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 22d10d3..3bd67c8 100644
--- a/kernel/irq/manage.c
+++ b/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, unsigned long irqflags)
{
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 irqaction *new)
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 *dev_id)
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_handler_t handler,
*/
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;
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index 6c6d35d..74d7922 100644
--- a/kernel/irq/proc.c
+++ b/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);
}

diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c
index a804679..cba8aa5 100644
--- a/kernel/irq/resend.c
+++ b/kernel/irq/resend.c
@@ -33,8 +33,8 @@ static void resend_irqs(unsigned long arg)
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();
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index 19fe9d6..e26ca1e 100644
--- a/kernel/irq/spurious.c
+++ b/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;

--
1.5.4.5

2008-08-03 03:02:27

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 06/25] x86: enable dyn_array support

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/Kconfig | 2 ++
arch/x86/Kconfig | 1 +
arch/x86/kernel/vmlinux_32.lds.S | 1 +
arch/x86/kernel/vmlinux_64.lds.S | 3 +++
4 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 0267bab..c1f9feb 100644
--- a/arch/Kconfig
+++ b/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
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index bd30e8b..d30b101 100644
--- a/arch/x86/Kconfig
+++ b/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

config ARCH_DEFCONFIG
string
diff --git a/arch/x86/kernel/vmlinux_32.lds.S b/arch/x86/kernel/vmlinux_32.lds.S
index 248a575..20b835a 100644
--- a/arch/x86/kernel/vmlinux_32.lds.S
+++ b/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) {
diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S
index 63e5c1a..5b9cc10 100644
--- a/arch/x86/kernel/vmlinux_64.lds.S
+++ b/arch/x86/kernel/vmlinux_64.lds.S
@@ -174,6 +174,9 @@ SECTIONS
*(.x86cpuvendor.init)
}
__x86cpuvendor_end = .;
+
+ DYN_ARRAY_INIT(8)
+
SECURITY_INIT

. = ALIGN(8);
--
1.5.4.5

2008-08-03 03:03:26

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 08/25] x86: using nr_irqs

also add first_free_entry and pin_map_size

Signed-off-by: Yinghai Lu <[email protected]>
---
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 +-
include/asm-x86/irq.h | 3 +++
7 files changed, 44 insertions(+), 38 deletions(-)

diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c
index 7f0d88c..d5953ff 100644
--- a/arch/x86/kernel/io_apic_32.c
+++ b/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 __initdata;
#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, int pin)
*/
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 irq, int apic, int pin)
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_cpus(unsigned long useful_load_threshold)
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(void)
* 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)
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
index 8800743..456f2e7 100644
--- a/arch/x86/kernel/io_apic_64.c
+++ b/arch/x86/kernel/io_apic_64.c
@@ -132,6 +132,7 @@ DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
#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 apic)
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(unsigned int irq, unsigned int dest, u8 vector)
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(unsigned int irq, cpumask_t mask)
* 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, int slot, int pin)
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, int pin)
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, cpumask_t mask)
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_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_interrupt(void)
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(void)
* 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)
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index 1cf8c1f..0cff2f4 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/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, void *v)
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, void *v)
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;
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c
index 1f78b23..de94c60 100644
--- a/arch/x86/kernel/irq_64.c
+++ b/arch/x86/kernel/irq_64.c
@@ -81,7 +81,7 @@ int show_interrupts(struct seq_file *p, void *v)
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, void *v)
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_regs *regs)
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;
diff --git a/arch/x86/kernel/irqinit_32.c b/arch/x86/kernel/irqinit_32.c
index d669142..b13d932 100644
--- a/arch/x86/kernel/irqinit_32.c
+++ b/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))
diff --git a/arch/x86/kernel/irqinit_64.c b/arch/x86/kernel/irqinit_64.c
index 1f26fd9..48674e6 100644
--- a/arch/x86/kernel/irqinit_64.c
+++ b/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;
diff --git a/include/asm-x86/irq.h b/include/asm-x86/irq.h
index 1e5f290..2a130c4 100644
--- a/include/asm-x86/irq.h
+++ b/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);
--
1.5.4.5

2008-08-03 03:03:40

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 09/25] drivers/char to use nr_irqs

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/char/hpet.c | 2 +-
drivers/char/random.c | 4 ++--
drivers/char/vr41xx_giu.c | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 2908a0e..8d562ae 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -219,7 +219,7 @@ static void hpet_timer_set_irq(struct hpet_dev *devp)
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;
}
diff --git a/drivers/char/random.c b/drivers/char/random.c
index e0d0e37..fdbdcfc 100644
--- a/drivers/char/random.c
+++ b/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;

/*
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c
index ffe9b4e..54c8372 100644
--- a/drivers/char/vr41xx_giu.c
+++ b/drivers/char/vr41xx_giu.c
@@ -641,7 +641,7 @@ static int __devinit giu_probe(struct platform_device *dev)
}

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);
--
1.5.4.5

2008-08-03 03:04:20

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 11/25] drivers intr remapping to use nr_irqs

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/intr_remapping.c | 16 ++++++++--------
1 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index bb642cc..980566e 100644
--- a/drivers/pci/intr_remapping.c
+++ b/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 *sub_handle)
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 *sub_handle)
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_iommu *iommu, u16 index, u16 subhandle)
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 *irte_modified)
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;
}
--
1.5.4.5

2008-08-03 03:03:56

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 10/25] drivers/net to use nr_irqs

Signed-off-by: Yinghai Lu <[email protected]>
---
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 +-
4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 8db4e6b..7449a1c 100644
--- a/drivers/net/3c59x.c
+++ b/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(struct device *gendev,
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);

diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
index 17ac697..b6a816e 100644
--- a/drivers/net/hamradio/baycom_ser_fdx.c
+++ b/drivers/net/hamradio/baycom_ser_fdx.c
@@ -416,10 +416,10 @@ static int ser12_open(struct net_device *dev)
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) {
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index 45ae9d1..c17e39b 100644
--- a/drivers/net/hamradio/scc.c
+++ b/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_device *dev, struct ifreq *ifr, int cmd)

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(void)
}

/* 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();
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index e59255a..8bd13b8 100644
--- a/drivers/net/wan/sbni.c
+++ b/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"
--
1.5.4.5

2008-08-03 03:04:35

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 12/25] drivers/pcmcia to use nr_irqs

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pcmcia/at91_cf.c | 2 +-
drivers/pcmcia/vrc4171_card.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index 6849685..194c8ba 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -273,7 +273,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
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)
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index eee2f1c..b2c4124 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -639,7 +639,7 @@ static int __devinit vrc4171_card_setup(char *options)
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 != ',')
--
1.5.4.5

2008-08-03 03:05:16

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 14/25] drivers/scsi to use nr_irqs

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/scsi/aha152x.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index b5a868d..1e5478a 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -337,7 +337,7 @@ CMD_INC_RESID(struct scsi_cmnd *cmd, int inc)
#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
--
1.5.4.5

2008-08-03 03:04:50

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 13/25] drivers/rtc to use nr_irqs

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/rtc/rtc-vr41xx.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
index 884b635..834dcc6 100644
--- a/drivers/rtc/rtc-vr41xx.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -360,7 +360,7 @@ static int __devinit rtc_probe(struct platform_device *pdev)
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 platform_device *pdev)
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,
--
1.5.4.5

2008-08-03 03:05:41

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 15/25] drivers/serial to use nr_irqs

Signed-off-by: Yinghai Lu <[email protected]>
---
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 +-
9 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 3a4d677..3920324 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2433,7 +2433,7 @@ static void serial8250_config_port(struct uart_port *port, int flags)
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);
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 90b56c2..7156268 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -512,7 +512,7 @@ static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
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;
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 9d08f27..b718004 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -572,7 +572,7 @@ static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
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;
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index a4f8692..b09fdc2 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -589,7 +589,7 @@ static int cpm_uart_verify_port(struct uart_port *port,

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;
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index 23d0305..611c97a 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -922,7 +922,7 @@ static void m32r_sio_config_port(struct uart_port *port, int flags)
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);
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index f977c98..effd0bd 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -741,7 +741,7 @@ static int uart_set_info(struct uart_state *state,
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;

diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index cb49a5a..61dc8b3 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -460,7 +460,7 @@ static int lh7a40xuart_verify_port (struct uart_port* port,

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;
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 3df2aae..667b4b8 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -1157,7 +1157,7 @@ static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)
{
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.. */
diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c
index 5c5d18d..503f0b9 100644
--- a/drivers/serial/ucc_uart.c
+++ b/drivers/serial/ucc_uart.c
@@ -1066,7 +1066,7 @@ static int qe_uart_verify_port(struct uart_port *port,
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)
--
1.5.4.5

2008-08-03 03:05:57

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 16/25] drivers proc to use nr_irqs

Signed-off-by: Yinghai Lu <[email protected]>
---
fs/proc/proc_misc.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index ded9698..1968251 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -503,7 +503,7 @@ static int show_stat(struct seq_file *p, void *v)
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, void *v)
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, void *v)
}
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_stat_operations = {
*/
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;
}
--
1.5.4.5

2008-08-03 03:06:19

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 17/25] drivers xen events to use nr_irqs

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/xen/events.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index a083703..8e329c2 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -139,7 +139,7 @@ static void init_evtchn_cpu_bindings(void)
#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

@@ -223,12 +223,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;
}
@@ -761,7 +761,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++)
@@ -793,7 +793,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());
--
1.5.4.5

2008-08-03 03:06:51

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 19/25] make irq2_iommu to use dyn_array

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/pci/intr_remapping.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index 980566e..ced5ebc 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -11,12 +11,14 @@ static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
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);

--
1.5.4.5

2008-08-03 03:06:35

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 18/25] make irq_timer_state to use dyn_array

Signed-off-by: Yinghai Lu <[email protected]>
---
drivers/char/random.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index fdbdcfc..872669e 100644
--- a/drivers/char/random.c
+++ b/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
--
1.5.4.5

2008-08-03 03:07:13

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 20/25] make irq_desc to use dyn_array

Signed-off-by: Yinghai Lu <[email protected]>
---
include/linux/irq.h | 4 ++++
kernel/irq/handle.c | 31 +++++++++++++++++++++++++++++++
2 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index bd69d90..c22e870 100644
--- a/include/linux/irq.h
+++ b/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:
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index e9d022c..6ea252d 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -48,6 +48,36 @@ handle_bad_irq(unsigned int irq, struct irq_desc *desc)
* Controller mappings for all interrupt sources:
*/
int nr_irqs = NR_IRQS;
+
+#ifdef CONFIG_HAVE_DYN_ARRAY
+static struct irq_desc irq_desc_init __initdata = {
+ .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] __cacheline_aligned_in_smp = {
#endif
}
};
+#endif

/*
* What should we do if we get a hw irq event on an illegal vector?
--
1.5.4.5

2008-08-03 03:07:44

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 21/25] serial: change remove NR_IRQS in 8250.c v2

use small array with index to handle irq locking for serial port
hope 32 slot is enough

v2: according to Eric, move irq_no into irq_info, and not clean irq_no

Signed-off-by: Yinghai Lu <[email protected]>
Cc: Alan Cox <[email protected]>
---
drivers/serial/8250.c | 45 +++++++++++++++++++++++++++++++++++++++++----
1 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 3920324..595b956 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -147,9 +147,39 @@ struct uart_8250_port {
struct irq_info {
spinlock_t lock;
struct list_head *head;
+ int irq_no;
};

-static struct irq_info irq_lists[NR_IRQS];
+#define NR_IRQ_INFO 32
+
+static struct irq_info irq_lists[NR_IRQ_INFO] = {
+ [0 ... NR_IRQ_INFO-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; i++) {
+ if (irq_lists[i].irq_no == irq)
+ return &irq_lists[i];
+ if (irq_lists[i].irq_no == -1 && first_free == -1)
+ first_free = i;
+ }
+ if (!with_free)
+ return NULL;
+
+ if (first_free != -1) {
+ irq_lists[first_free].irq_no = irq;
+ return &irq_lists[first_free];
+ }
+
+ WARN_ON("NR_IRQ_INFO too small");
+
+ return NULL;
+}

/*
* Here we define the default xmit fifo size used for each type of UART.
@@ -1554,9 +1584,12 @@ static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)

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,7 +1613,11 @@ static int serial_link_irq_chain(struct uart_8250_port *up)

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);
+
+ if (!i)
+ return;

BUG_ON(i->head == NULL);

@@ -2964,7 +3001,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_IRQ_INFO; i++)
spin_lock_init(&irq_lists[i].lock);

ret = uart_register_driver(&serial8250_reg);
--
1.5.4.5

2008-08-03 03:07:58

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 22/25] irq: make irqs in kernel stat use per_cpu_dyn_array

Signed-off-by: Yinghai Lu <[email protected]>
---
include/linux/kernel_stat.h | 4 ++++
kernel/sched.c | 5 ++++-
2 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
index cf9f40a..fe1f7fe 100644
--- a/include/linux/kernel_stat.h
+++ b/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);
diff --git a/kernel/sched.c b/kernel/sched.c
index 55cb4ce..21c0839 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -4021,9 +4021,12 @@ static inline void idle_balance(int cpu, struct rq *rq)
#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.
--
1.5.4.5

2008-08-03 03:08:23

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 23/25] x86: use dyn_array in io_apic_xx.c

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/kernel/io_apic_32.c | 54 +++++++++++++++++++++++++++++++++--------
arch/x86/kernel/io_apic_64.c | 28 ++++++++++++++++-----
arch/x86/kernel/setup.c | 6 ++++
3 files changed, 70 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c
index d5953ff..a0ce64c 100644
--- a/arch/x86/kernel/io_apic_32.c
+++ b/arch/x86/kernel/io_apic_32.c
@@ -70,7 +70,7 @@ int timer_through_8259 __initdata;
*/
int sis_apic_bug = -1;

-int first_free_entry = NR_IRQS;
+int first_free_entry;
/*
* # of IRQ routing registers
*/
@@ -98,10 +98,7 @@ static int disable_timer_pin_1 __initdata;
* 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)
@@ -112,7 +109,9 @@ int pin_map_size = PIN_MAP_SIZE;

static struct irq_pin_list {
int apic, pin, next;
-} irq_2_pin[PIN_MAP_SIZE];
+} *irq_2_pin;
+
+DEFINE_DYN_ARRAY(irq_2_pin, sizeof(struct irq_pin_list), pin_map_size, 16, NULL);

struct io_apic {
unsigned int index;
@@ -403,9 +402,28 @@ static struct irq_cpu_info {

#define CPU_TO_PACKAGEINDEX(i) (first_cpu(per_cpu(cpu_sibling_map, i)))

-static cpumask_t balance_irq_affinity[NR_IRQS] = {
- [0 ... NR_IRQS-1] = CPU_MASK_ALL
-};
+static cpumask_t balance_irq_affinity_init __initdata = CPU_MASK_ALL;
+
+static cpumask_t *balance_irq_affinity;
+
+
+static void __init irq_affinity_init_work(void *data)
+{
+ struct dyn_array *da = data;
+
+ int i;
+ struct balance_irq_affinity *affinity;
+
+ affinity = *da->name;
+
+ for (i = 0; i < *da->nr; i++)
+ memcpy(&affinity[i], &balance_irq_affinity_init,
+ sizeof(struct balance_irq_affinity));
+
+}
+
+DEFINE_DYN_ARRAY(balance_irq_affinity, sizeof(struct balance_irq_affinity), nr_irqs, PAGE_SIZE, irq_affinity_init_work);
+

void set_balance_irq_affinity(unsigned int irq, cpumask_t mask)
{
@@ -1170,14 +1188,28 @@ static inline int IO_APIC_irq_trigger(int irq)
}

/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
-static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
+static u8 irq_vector_init_first __initdata = FIRST_DEVICE_VECTOR;
+static u8 *irq_vector;
+
+static void __init irq_vector_init_work(void *data)
+{
+ struct dyn_array *da = data;
+
+ u8 *irq_vec;
+
+ irq_vec = *da->name;
+
+ irq_vec[0] = irq_vector_init_first;
+}
+
+DEFINE_DYN_ARRAY(irq_vector, sizeof(u8), nr_irqs, PAGE_SIZE, irq_vector_init_work);

static int __assign_irq_vector(int irq)
{
static int current_vector = FIRST_DEVICE_VECTOR, current_offset;
int vector, offset;

- BUG_ON((unsigned)irq >= NR_IRQ_VECTORS);
+ BUG_ON((unsigned)irq >= nr_irqs);

if (irq_vector[irq] > 0)
return irq_vector[irq];
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
index 456f2e7..9bcb6c2 100644
--- a/arch/x86/kernel/io_apic_64.c
+++ b/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] __read_mostly = {
[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_BUSSES);
* 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(unsigned int irq, cpumask_t mask)
* 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;
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 60e8de1..39c5106 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -856,9 +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;
init_cpu_to_node();
#endif
+ pin_map_size = nr_irqs * 2;
+ first_free_entry = nr_irqs;

init_apic_mappings();
ioapic_init_mappings();
--
1.5.4.5

2008-08-03 03:08:38

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 24/25] x86: get mp_irqs from madt

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/kernel/acpi/boot.c | 30 ++++++++++++++++++++++++++++--
include/asm-x86/mpspec.h | 1 +
2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 27ef365..443cb30 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -962,6 +962,29 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
nr_ioapics++;
}

+int get_nr_irqs_via_madt(void)
+{
+ int idx;
+ int nr = 0;
+
+ for (idx = 0; idx < nr_ioapics; idx++) {
+ if (mp_ioapic_routing[idx].gsi_end > nr)
+ nr = mp_ioapic_routing[idx].gsi_end;
+ }
+
+ nr++;
+
+ /* double it for hotplug and msi and nmi */
+ nr <<= 1;
+
+ /* something wrong ? */
+ if (nr < 32)
+ nr = 32;
+
+ return nr;
+
+}
+
static void assign_to_mp_irq(struct mp_config_intsrc *m,
struct mp_config_intsrc *mp_irq)
{
@@ -1259,9 +1282,12 @@ static int __init acpi_parse_madt_ioapic_entries(void)
return count;
}

+
+ nr_irqs = get_nr_irqs_via_madt();
+
count =
acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr,
- NR_IRQ_VECTORS);
+ nr_irqs);
if (count < 0) {
printk(KERN_ERR PREFIX
"Error parsing interrupt source overrides entry\n");
@@ -1281,7 +1307,7 @@ static int __init acpi_parse_madt_ioapic_entries(void)

count =
acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src,
- NR_IRQ_VECTORS);
+ nr_irqs);
if (count < 0) {
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
/* TBD: Cleanup to allow fallback to MPS */
diff --git a/include/asm-x86/mpspec.h b/include/asm-x86/mpspec.h
index 118da36..5daa0f4 100644
--- a/include/asm-x86/mpspec.h
+++ b/include/asm-x86/mpspec.h
@@ -59,6 +59,7 @@ extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
u32 gsi);
extern void mp_config_acpi_legacy_irqs(void);
extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+extern int get_nr_irqs_via_madt(void);
#ifdef CONFIG_X86_IO_APIC
extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
u32 gsi, int triggering, int polarity);
--
1.5.4.5

2008-08-03 03:08:54

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 25/25] x86: remove nr_irq_vectors

Signed-off-by: Yinghai Lu <[email protected]>
---
include/asm-x86/irq_vectors.h | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/include/asm-x86/irq_vectors.h b/include/asm-x86/irq_vectors.h
index 0817a19..821ff99 100644
--- a/include/asm-x86/irq_vectors.h
+++ b/include/asm-x86/irq_vectors.h
@@ -127,8 +127,6 @@

#endif /* VISWS */

-#define NR_IRQ_VECTORS NR_IRQS
-
/* Voyager specific defines */
/* These define the CPIs we use in linux */
#define VIC_CPI_LEVEL0 0
--
1.5.4.5

2008-08-03 04:03:36

by Johannes Weiner

[permalink] [raw]
Subject: Re: [PATCH 03/25] add dyn_array support

Hi,

Yinghai Lu <[email protected]> writes:

> could have crazy big arrays and allocate them in bootmem at init stage.
> also also to allocate array according to size we need to use to avoid wasting
> memory
> use CONFIG_HAVE_DYN_ARRAY to enable it or not
>
> usage:
>
> |static struct irq_desc irq_desc_init __initdata = {
> | .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;
> | struct irq_desc *desc;
> | int i;
> |
> | desc = *da->name;

Where *da->name might be NULL...

> |
> | for (i = 0; i < *da->nr; i++)
> | memcpy(&desc[i], &irq_desc_init, sizeof(struct irq_desc));

... boom.

> +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);

So, why is this _nopanic()?

> + phys = virt_to_phys(*da->name);
> + printk(KERN_CONT " ==> [%#lx - %#lx]\n", phys, phys + size);
> +
> + if (da->init_work)
> + da->init_work(da);
> + }
> +#endif

Hannes

2008-08-03 04:16:37

by Johannes Weiner

[permalink] [raw]
Subject: Re: [PATCH 05/25] x86: alloc dyn_array all alltogether

Hi,

Yinghai Lu <[email protected]> writes:

> @@ -544,45 +548,78 @@ void __init __weak thread_info_cache_init(void)
> void pre_alloc_dyn_array(void)
> {
> #ifdef CONFIG_HAVE_DYN_ARRAY
> - unsigned long size, phys = 0;
> + unsigned long total_size = 0, size, phys;
> + unsigned long max_align = 1;
> struct dyn_array **daa;
> + char *ptr;
>
> + /* get the total size at first */
> 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",
> + print_fn_descriptor_symbol("dyn_array %s ", da->name);

Is this a correction of a typo you introduced two pages earlier?

> + printk(KERN_CONT "size:%#lx nr:%d align:%#lx\n",
> da->size, *da->nr, da->align);
> - *da->name = __alloc_bootmem_nopanic(size, da->align, phys);
> - phys = virt_to_phys(*da->name);
> + total_size += roundup(size, da->align);
> + if (da->align > max_align)
> + max_align = da->align;
> + }
> + if (total_size)
> + printk(KERN_DEBUG "dyn_array total_size: %#lx\n",
> + total_size);
> + else
> + return;
> +
> + /* allocate them all together */
> + max_align = max_t(unsigned long, max_align, PAGE_SIZE);
> + ptr = __alloc_bootmem_nopanic(total_size, max_align, 0);
> + if (!ptr)
> + panic("Can not alloc dyn_alloc\n");

Uhm... :)

> +
> + phys = virt_to_phys(ptr);
> + for (daa = __dyn_array_start ; daa < __dyn_array_end; daa++) {
> + struct dyn_array *da = *daa;
> +
> + size = da->size * (*da->nr);
> + print_fn_descriptor_symbol("dyn_array %s ", da->name);
> +
> + phys = roundup(phys, da->align);
> + *da->name = phys_to_virt(phys);
> printk(KERN_CONT " ==> [%#lx - %#lx]\n", phys, phys + size);
>
> + phys += size;
> +
> if (da->init_work)
> da->init_work(da);
> }
> #endif
> }
>
> -unsigned long per_cpu_dyn_array_size(void)
> +unsigned long per_cpu_dyn_array_size(unsigned long *align)
> {
> unsigned long total_size = 0;
> #ifdef CONFIG_HAVE_DYN_ARRAY
> unsigned long size;
> struct dyn_array **daa;
> + unsigned max_align = 1;
>
> for (daa = __per_cpu_dyn_array_start ; daa < __per_cpu_dyn_array_end; daa++) {
> struct dyn_array *da = *daa;
>
> size = da->size * (*da->nr);
> - print_fn_descriptor_symbol("per_cpu_dyna_array %s ", da->name);
> + print_fn_descriptor_symbol("per_cpu_dyn_array %s ", da->name);
> printk(KERN_CONT "size:%#lx nr:%d align:%#lx\n",
> da->size, *da->nr, da->align);
> total_size += roundup(size, da->align);
> + if (da->align > max_align)
> + max_align = da->align;
> }
> - if (total_size)
> - printk(KERN_DEBUG "per_cpu_dyna_array total_size: %#lx\n",
> + if (total_size) {
> + printk(KERN_DEBUG "per_cpu_dyn_array total_size: %#lx\n",
> total_size);

...

> + *align = max_align;
> + }
> #endif
> return total_size;
> }
> @@ -596,14 +633,11 @@ void per_cpu_alloc_dyn_array(int cpu, char *ptr)
> void **array;
>
> phys = virt_to_phys(ptr);
> -
> for (daa = __per_cpu_dyn_array_start ; daa < __per_cpu_dyn_array_end; daa++) {
> struct dyn_array *da = *daa;
>
> size = da->size * (*da->nr);
> - print_fn_descriptor_symbol("per_cpu_dyna_array %s ", da->name);
> - printk(KERN_CONT "size:%#lx nr:%d align:%#lx",
> - da->size, *da->nr, da->align);
> + print_fn_descriptor_symbol("per_cpu_dyn_array %s ", da->name);

...

Hannes

2008-08-03 04:21:24

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 03/25] add dyn_array support

On Sat, Aug 2, 2008 at 9:03 PM, Johannes Weiner <[email protected]> wrote:
> Hi,
>
> Yinghai Lu <[email protected]> writes:
>
>> could have crazy big arrays and allocate them in bootmem at init stage.
>> also also to allocate array according to size we need to use to avoid wasting
>> memory
>> use CONFIG_HAVE_DYN_ARRAY to enable it or not
>>
>> usage:
>>
>> |static struct irq_desc irq_desc_init __initdata = {
>> | .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;
>> | struct irq_desc *desc;
>> | int i;
>> |
>> | desc = *da->name;
>
> Where *da->name might be NULL...

you can not pass compiling

+#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
+

YH

2008-08-03 04:56:16

by Johannes Weiner

[permalink] [raw]
Subject: Re: [PATCH 03/25] add dyn_array support

Hi,

"Yinghai Lu" <[email protected]> writes:

> On Sat, Aug 2, 2008 at 9:03 PM, Johannes Weiner <[email protected]> wrote:
>> Hi,
>>
>> Yinghai Lu <[email protected]> writes:
>>
>>> could have crazy big arrays and allocate them in bootmem at init stage.
>>> also also to allocate array according to size we need to use to avoid wasting
>>> memory
>>> use CONFIG_HAVE_DYN_ARRAY to enable it or not
>>>
>>> usage:
>>>
>>> |static struct irq_desc irq_desc_init __initdata = {
>>> | .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;
>>> | struct irq_desc *desc;
>>> | int i;
>>> |
>>> | desc = *da->name;
>>
>> Where *da->name might be NULL...
>
> you can not pass compiling
>
> +#define DEFINE_DYN_ARRAY(nameX, sizeX, nrX, alignX, init_workX) \
> + static struct dyn_array __dyn_array_##nameX __initdata = \
> + { .name = (void **)&nameX,\

I didn't mean da->name. Please reread my email, including the part you
stripped off in the reply.

> + .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
> +
>
> YH

Hannes

2008-08-03 05:04:38

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 03/25] add dyn_array support

On Sat, Aug 2, 2008 at 9:55 PM, Johannes Weiner <[email protected]> wrote:
> Hi,
>
> "Yinghai Lu" <[email protected]> writes:
>
>> On Sat, Aug 2, 2008 at 9:03 PM, Johannes Weiner <[email protected]> wrote:
>>> Hi,
>>>
>>> Yinghai Lu <[email protected]> writes:
>>>
>>>> could have crazy big arrays and allocate them in bootmem at init stage.
>>>> also also to allocate array according to size we need to use to avoid wasting
>>>> memory
>>>> use CONFIG_HAVE_DYN_ARRAY to enable it or not
>>>>
>>>> usage:
>>>>
>>>> |static struct irq_desc irq_desc_init __initdata = {
>>>> | .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;
>>>> | struct irq_desc *desc;
>>>> | int i;
>>>> |
>>>> | desc = *da->name;
>>>
>>> Where *da->name might be NULL...

*da->name = __alloc_bootmem_nopanic(size, da->align, phys);

YH

2008-08-03 05:32:11

by Johannes Weiner

[permalink] [raw]
Subject: Re: [PATCH 03/25] add dyn_array support

Hi,

"Yinghai Lu" <[email protected]> writes:

> On Sat, Aug 2, 2008 at 9:55 PM, Johannes Weiner <[email protected]> wrote:
>> Hi,
>>
>> "Yinghai Lu" <[email protected]> writes:
>>
>>> On Sat, Aug 2, 2008 at 9:03 PM, Johannes Weiner <[email protected]> wrote:
>>>> Hi,
>>>>
>>>> Yinghai Lu <[email protected]> writes:
>>>>
>>>>> could have crazy big arrays and allocate them in bootmem at init stage.
>>>>> also also to allocate array according to size we need to use to avoid wasting
>>>>> memory
>>>>> use CONFIG_HAVE_DYN_ARRAY to enable it or not
>>>>>
>>>>> usage:
>>>>>
>>>>> |static struct irq_desc irq_desc_init __initdata = {
>>>>> | .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;
>>>>> | struct irq_desc *desc;
>>>>> | int i;
>>>>> |
>>>>> | desc = *da->name;
>>>>
>>>> Where *da->name might be NULL...
>
> *da->name = __alloc_bootmem_nopanic(size, da->align, phys);

Exactly. Now, look up the possible return values of
__alloc_bootmem_nopanic and we are almost there...

Hannes

2008-08-03 05:39:18

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 03/25] add dyn_array support

On Sat, Aug 2, 2008 at 10:31 PM, Johannes Weiner <[email protected]> wrote:
> Hi,
>
> "Yinghai Lu" <[email protected]> writes:
>
>> On Sat, Aug 2, 2008 at 9:55 PM, Johannes Weiner <[email protected]> wrote:
>>> Hi,
>>>
>>> "Yinghai Lu" <[email protected]> writes:
>>>
>>>> On Sat, Aug 2, 2008 at 9:03 PM, Johannes Weiner <[email protected]> wrote:
>>>>> Hi,
>>>>>
>>>>> Yinghai Lu <[email protected]> writes:
>>>>>
>>>>>> could have crazy big arrays and allocate them in bootmem at init stage.
>>>>>> also also to allocate array according to size we need to use to avoid wasting
>>>>>> memory
>>>>>> use CONFIG_HAVE_DYN_ARRAY to enable it or not
>>>>>>
>>>>>> usage:
>>>>>>
>>>>>> |static struct irq_desc irq_desc_init __initdata = {
>>>>>> | .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;
>>>>>> | struct irq_desc *desc;
>>>>>> | int i;
>>>>>> |
>>>>>> | desc = *da->name;
>>>>>
>>>>> Where *da->name might be NULL...
>>
>> *da->name = __alloc_bootmem_nopanic(size, da->align, phys);
>
> Exactly. Now, look up the possible return values of
> __alloc_bootmem_nopanic and we are almost there...

04 fix that via allocating that all together

YH

2008-08-03 05:40:19

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 03/25] add dyn_array support

On Sat, Aug 2, 2008 at 10:39 PM, Yinghai Lu <[email protected]> wrote:
> On Sat, Aug 2, 2008 at 10:31 PM, Johannes Weiner <[email protected]> wrote:
>> Hi,
>>
>> "Yinghai Lu" <[email protected]> writes:
>>
>>> On Sat, Aug 2, 2008 at 9:55 PM, Johannes Weiner <[email protected]> wrote:
>>>> Hi,
>>>>
>>>> "Yinghai Lu" <[email protected]> writes:
>>>>
>>>>> On Sat, Aug 2, 2008 at 9:03 PM, Johannes Weiner <[email protected]> wrote:
>>>>>> Hi,
>>>>>>
>>>>>> Yinghai Lu <[email protected]> writes:
>>>>>>
>>>>>>> could have crazy big arrays and allocate them in bootmem at init stage.
>>>>>>> also also to allocate array according to size we need to use to avoid wasting
>>>>>>> memory
>>>>>>> use CONFIG_HAVE_DYN_ARRAY to enable it or not
>>>>>>>
>>>>>>> usage:
>>>>>>>
>>>>>>> |static struct irq_desc irq_desc_init __initdata = {
>>>>>>> | .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;
>>>>>>> | struct irq_desc *desc;
>>>>>>> | int i;
>>>>>>> |
>>>>>>> | desc = *da->name;
>>>>>>
>>>>>> Where *da->name might be NULL...
>>>
>>> *da->name = __alloc_bootmem_nopanic(size, da->align, phys);
>>
>> Exactly. Now, look up the possible return values of
>> __alloc_bootmem_nopanic and we are almost there...
>
> 04 fix that via allocating that all together

should be 05

YH

2008-08-03 05:47:50

by Johannes Weiner

[permalink] [raw]
Subject: Re: [PATCH 03/25] add dyn_array support

Hi,

"Yinghai Lu" <[email protected]> writes:

> On Sat, Aug 2, 2008 at 10:31 PM, Johannes Weiner <[email protected]> wrote:
>> Hi,
>>
>> "Yinghai Lu" <[email protected]> writes:
>>
>>> On Sat, Aug 2, 2008 at 9:55 PM, Johannes Weiner <[email protected]> wrote:
>>>> Hi,
>>>>
>>>> "Yinghai Lu" <[email protected]> writes:
>>>>
>>>>> On Sat, Aug 2, 2008 at 9:03 PM, Johannes Weiner <[email protected]> wrote:
>>>>>> Hi,
>>>>>>
>>>>>> Yinghai Lu <[email protected]> writes:
>>>>>>
>>>>>>> could have crazy big arrays and allocate them in bootmem at init stage.
>>>>>>> also also to allocate array according to size we need to use to avoid wasting
>>>>>>> memory
>>>>>>> use CONFIG_HAVE_DYN_ARRAY to enable it or not
>>>>>>>
>>>>>>> usage:
>>>>>>>
>>>>>>> |static struct irq_desc irq_desc_init __initdata = {
>>>>>>> | .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;
>>>>>>> | struct irq_desc *desc;
>>>>>>> | int i;
>>>>>>> |
>>>>>>> | desc = *da->name;
>>>>>>
>>>>>> Where *da->name might be NULL...
>>>
>>> *da->name = __alloc_bootmem_nopanic(size, da->align, phys);
>>
>> Exactly. Now, look up the possible return values of
>> __alloc_bootmem_nopanic and we are almost there...
>
> 04 fix that via allocating that all together

No patch should introduce wrong behaviour but instead be an atomic
switch to another working state. If 4 gets reverted for any reason
whatsoever, you will be left with a buggy version.

Hannes

2008-08-03 05:48:47

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 03/25] add dyn_array support

On Sat, Aug 2, 2008 at 10:47 PM, Johannes Weiner <[email protected]> wrote:
> Hi,
>
> "Yinghai Lu" <[email protected]> writes:
>
>> On Sat, Aug 2, 2008 at 10:31 PM, Johannes Weiner <[email protected]> wrote:
>>> Hi,
>>>
>>> "Yinghai Lu" <[email protected]> writes:
>>>
>>>> On Sat, Aug 2, 2008 at 9:55 PM, Johannes Weiner <[email protected]> wrote:
>>>>> Hi,
>>>>>
>>>>> "Yinghai Lu" <[email protected]> writes:
>>>>>
>>>>>> On Sat, Aug 2, 2008 at 9:03 PM, Johannes Weiner <[email protected]> wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> Yinghai Lu <[email protected]> writes:
>>>>>>>
>>>>>>>> could have crazy big arrays and allocate them in bootmem at init stage.
>>>>>>>> also also to allocate array according to size we need to use to avoid wasting
>>>>>>>> memory
>>>>>>>> use CONFIG_HAVE_DYN_ARRAY to enable it or not
>>>>>>>>
>>>>>>>> usage:
>>>>>>>>
>>>>>>>> |static struct irq_desc irq_desc_init __initdata = {
>>>>>>>> | .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;
>>>>>>>> | struct irq_desc *desc;
>>>>>>>> | int i;
>>>>>>>> |
>>>>>>>> | desc = *da->name;
>>>>>>>
>>>>>>> Where *da->name might be NULL...
>>>>
>>>> *da->name = __alloc_bootmem_nopanic(size, da->align, phys);
>>>
>>> Exactly. Now, look up the possible return values of
>>> __alloc_bootmem_nopanic and we are almost there...
>>
>> 04 fix that via allocating that all together
>
> No patch should introduce wrong behaviour but instead be an atomic
> switch to another working state. If 4 gets reverted for any reason
> whatsoever, you will be left with a buggy version.

ok, next version i will remove _nopanic

Yh

2008-08-03 05:53:18

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [PATCH 00/25] dyn_array and nr_irqs support v3


It appears that quite a few of the places you have changed are testing
to see if an irq is valid. The idiomatic way to perform that test in
the kernel is:

if (irq)

With no test to see if you are >= NR_IRQS.

I expect that is the change we want in the drivers that are performing such a silly
extra check.

Eric

2008-08-03 06:04:28

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 00/25] dyn_array and nr_irqs support v3

On Sat, Aug 2, 2008 at 10:51 PM, Eric W. Biederman
<[email protected]> wrote:
>
> It appears that quite a few of the places you have changed are testing
> to see if an irq is valid. The idiomatic way to perform that test in
> the kernel is:
>
> if (irq)

is uninitialized irq to be -1 or 0?

>
> With no test to see if you are >= NR_IRQS.
>
> I expect that is the change we want in the drivers that are performing such a silly
> extra check.

is_irq_valid(irq_no) ?

wait to see your new patchset about dyn irq_cfg and irq_desc

YH

2008-08-03 06:43:34

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [PATCH 00/25] dyn_array and nr_irqs support v3

"Yinghai Lu" <[email protected]> writes:

> On Sat, Aug 2, 2008 at 10:51 PM, Eric W. Biederman
> <[email protected]> wrote:
>>
>> It appears that quite a few of the places you have changed are testing
>> to see if an irq is valid. The idiomatic way to perform that test in
>> the kernel is:
>>
>> if (irq)
>
> is uninitialized irq to be -1 or 0?

0. There is a long history behind it, but by decree of Linus and to conform
with reasonable intuition 0 is not a valid irq except in certain arch specific
corner cases.

>> With no test to see if you are >= NR_IRQS.
>>
>> I expect that is the change we want in the drivers that are performing such a
> silly
>> extra check.
>
> is_irq_valid(irq_no) ?
>
> wait to see your new patchset about dyn irq_cfg and irq_desc

I haven't promised one, at least not lately. I went down a couple of
blind alleys and figured out what needed to be accomplished and then
ran out of steam about a year and a half 2 years ago, and I haven't
been able to get back to it.

Eric

2008-08-03 08:25:38

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 00/25] dyn_array and nr_irqs support v3

On Sat, Aug 2, 2008 at 11:39 PM, Eric W. Biederman
<[email protected]> wrote:
> "Yinghai Lu" <[email protected]> writes:
>
>> On Sat, Aug 2, 2008 at 10:51 PM, Eric W. Biederman
>> <[email protected]> wrote:
>>>
>>> It appears that quite a few of the places you have changed are testing
>>> to see if an irq is valid. The idiomatic way to perform that test in
>>> the kernel is:
>>>
>>> if (irq)
>>
>> is uninitialized irq to be -1 or 0?
>
> 0. There is a long history behind it, but by decree of Linus and to conform
> with reasonable intuition 0 is not a valid irq except in certain arch specific
> corner cases.
>
>>> With no test to see if you are >= NR_IRQS.
>>>
>>> I expect that is the change we want in the drivers that are performing such a
>> silly
>>> extra check.
>>
>> is_irq_valid(irq_no) ?
>>
>> wait to see your new patchset about dyn irq_cfg and irq_desc
>
> I haven't promised one, at least not lately. I went down a couple of
> blind alleys and figured out what needed to be accomplished and then
> ran out of steam about a year and a half 2 years ago, and I haven't
> been able to get back to it.
>

how about

diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index f4c8a03..aa6888c 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -47,19 +47,73 @@ handle_bad_irq(unsigned int irq, struct irq_desc *desc)
*
* 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 irq_desc **irq_desc_ptr;
+DEFINE_DYN_ARRAY(irq_desc_ptr, sizeof(struct irq_desc *), nr_irqs,
PAGE_SIZE, NULL);
+
+#define NR_IRQ_DESC 4096
+
+static struct irq_desc irq_desc__init = {
+ .irq = -1;
+ .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 int nr_irq_desc = NR_IRQ_DESC;
+
+static int __init parse_nr_irq_desc(char *arg)
+{
+ if (arg)
+ nr_irq_desc = simple_strtoul(arg, NULL, 0);
+ return 0;
+}
+
+early_param("nr_irq_desc", parse_nr_irq_desc);
+
+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));
+}
+
+static struct irq_desc *irq_desc;
+DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irq_desc,
PAGE_SIZE, init_work);
+
+struct irq_desc *get_irq_desc(int irq)
+{
+ struct irq_desc *desc;
+ int i;
+
+ desc = irq_desc_ptr[irq];
+
+ if (desc)
+ return desc;
+
+ for (i = 0; i < nr_irq_desc; i++) {
+ if (irq_desc[i]->irq != -1)
+ continue;
+
+ desc = &irq_desc[i];
+ desc->irq = irq;
+ irq_desc_ptr[irq] = desc;
+
+ return desc;
+ }
+
+ panic("please boot with nr_irq_desc=%d\n", nr_irq_desc * 2);
+}
+
/*
* What should we do if we get a hw irq event on an illegal vector?
* Each architecture has to answer this themself.


and later use get_irq_desc(i) instead irq_desc + i;

YH

2008-08-03 09:23:19

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [PATCH 00/25] dyn_array and nr_irqs support v3

"Yinghai Lu" <[email protected]> writes:

> how about
>
> diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
> index f4c8a03..aa6888c 100644
> --- a/kernel/irq/handle.c
> +++ b/kernel/irq/handle.c
> @@ -47,19 +47,73 @@ handle_bad_irq(unsigned int irq, struct irq_desc *desc)
> *
> * 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 irq_desc **irq_desc_ptr;
> +DEFINE_DYN_ARRAY(irq_desc_ptr, sizeof(struct irq_desc *), nr_irqs,
> PAGE_SIZE, NULL);
> +
> +#define NR_IRQ_DESC 4096
> +
> +static struct irq_desc irq_desc__init = {
> + .irq = -1;

Do you perhaps mean 0xffffffffU ?

> + .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 int nr_irq_desc = NR_IRQ_DESC;
> +
> +static int __init parse_nr_irq_desc(char *arg)
> +{
> + if (arg)
> + nr_irq_desc = simple_strtoul(arg, NULL, 0);
> + return 0;
> +}
> +
> +early_param("nr_irq_desc", parse_nr_irq_desc);
> +
> +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));
> +}
> +
> +static struct irq_desc *irq_desc;
> +DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irq_desc,
> PAGE_SIZE, init_work);
> +
> +struct irq_desc *get_irq_desc(int irq)

Ugh. This has the wrong type. It must be unsigned int irq.
> +{
> + struct irq_desc *desc;
> + int i;
> +
> + desc = irq_desc_ptr[irq];
> +
> + if (desc)
> + return desc;
> +
> + for (i = 0; i < nr_irq_desc; i++) {
> + if (irq_desc[i]->irq != -1)

Which makes this line wrong.
> + continue;
> +
> + desc = &irq_desc[i];
> + desc->irq = irq;
> + irq_desc_ptr[irq] = desc;
> +
> + return desc;
> + }
> +
> + panic("please boot with nr_irq_desc=%d\n", nr_irq_desc * 2);
> +}
> +
> /*
> * What should we do if we get a hw irq event on an illegal vector?
> * Each architecture has to answer this themself.
>
>
> and later use get_irq_desc(i) instead irq_desc + i;

That is the general idea.

Eric

2008-08-03 13:23:04

by Alan

[permalink] [raw]
Subject: Re: [PATCH 15/25] drivers/serial to use nr_irqs

> - for (i = 0; i < NR_IRQS; i++)
> + for (i = 0; i < nr_irqs; i++)
> spin_lock_init(&irq_lists[i].lock);
>

Don't you need to change how the array is allocated too ?


Alan

2008-08-03 13:23:25

by Alan

[permalink] [raw]
Subject: Re: [PATCH 21/25] serial: change remove NR_IRQS in 8250.c v2

On Sat, 2 Aug 2008 19:59:21 -0700
Yinghai Lu <[email protected]> wrote:

> use small array with index to handle irq locking for serial port
> hope 32 slot is enough
>
> v2: according to Eric, move irq_no into irq_info, and not clean irq_no

This wants doing with a hash not a prayer that "32 slots is enough"

2008-08-03 15:33:04

by Alan

[permalink] [raw]
Subject: Re: [PATCH 21/25] serial: change remove NR_IRQS in 8250.c v2

On Sat, 2 Aug 2008 19:59:21 -0700
Yinghai Lu <[email protected]> wrote:

> use small array with index to handle irq locking for serial port
> hope 32 slot is enough


Untested alternative approach

8250: Remove NR_IRQ usage

From: Alan Cox <[email protected]>


---

drivers/serial/68328serial.c | 11 ++---------
drivers/serial/8250.c | 41 ++++++++++++++++++++++++++++++++++-------
2 files changed, 36 insertions(+), 16 deletions(-)


diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 381b12a..277b78d 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -66,7 +66,6 @@
#endif

static struct m68k_serial m68k_soft[NR_PORTS];
-struct m68k_serial *IRQ_ports[NR_IRQS];

static unsigned int uart_irqs[NR_PORTS] = UART_IRQ_DEFNS;

@@ -375,15 +374,11 @@ clear_and_return:
*/
irqreturn_t rs_interrupt(int irq, void *dev_id)
{
- struct m68k_serial * info;
+ struct m68k_serial * info = dev_id;
m68328_uart *uart;
unsigned short rx;
unsigned short tx;

- info = IRQ_ports[irq];
- if(!info)
- return IRQ_NONE;
-
uart = &uart_addr[info->line];
rx = uart->urx.w;

@@ -1383,8 +1378,6 @@ rs68328_init(void)
info->port, info->irq);
printk(" is a builtin MC68328 UART\n");

- IRQ_ports[info->irq] = info; /* waste of space */
-
#ifdef CONFIG_M68VZ328
if (i > 0 )
PJSEL &= 0xCF; /* PSW enable second port output */
@@ -1393,7 +1386,7 @@ rs68328_init(void)
if (request_irq(uart_irqs[i],
rs_interrupt,
IRQF_DISABLED,
- "M68328_UART", NULL))
+ "M68328_UART", info))
panic("Unable to attach 68328 serial interrupt\n");
}
local_irq_restore(flags);
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index a97f1ae..7165e88 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -145,11 +145,14 @@ struct uart_8250_port {
};

struct irq_info {
- spinlock_t lock;
+ struct irq_info *next;
+ int irq;
+ spinlock_t lock; /* Protects list not the hash */
struct list_head *head;
};

-static struct irq_info irq_lists[NR_IRQS];
+static struct irq_info *irq_lists[NR_IRQ_HASH];
+static DEFINE_SPINLOCK(hash_lock); /* Used to walk the hash */

/*
* Here we define the default xmit fifo size used for each type of UART.
@@ -1541,9 +1544,28 @@ static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)

static int serial_link_irq_chain(struct uart_8250_port *up)
{
- struct irq_info *i = irq_lists + up->port.irq;
+ struct irq_info **list, *i;
int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;

+ spin_lock(&hash_lock);
+
+ list = &irq_lists[up->port.irq % NR_IRQ_HASH];
+ i = * list;
+
+ while(i != NULL && i->irq != up->port.irq)
+ i = i->next;
+ if (i == NULL) {
+ i = kzalloc(sizeof(struct irq_info), GFP_KERNEL);
+ if (i == NULL) {
+ spin_unlock(&hash_lock);
+ return -ENOMEM;
+ }
+ spin_lock_init(&i->lock);
+ i->next = *list;
+ *list = i;
+ }
+ spin_unlock(&hash_lock);
+
spin_lock_irq(&i->lock);

if (i->head) {
@@ -1567,8 +1589,16 @@ static int serial_link_irq_chain(struct uart_8250_port *up)

static void serial_unlink_irq_chain(struct uart_8250_port *up)
{
- struct irq_info *i = irq_lists + up->port.irq;
+ struct irq_info *i;
+
+ spin_lock(&hash_lock);

+ i = irq_lists[up->port.irq % NR_IRQ_HASH];
+ while(i != NULL && i->irq != up->port.irq)
+ i = i->next;
+ spin_unlock(&hash_lock);
+
+ BUG_ON(i == NULL);
BUG_ON(i->head == NULL);

if (list_empty(i->head))
@@ -2951,9 +2981,6 @@ 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);
-
ret = uart_register_driver(&serial8250_reg);
if (ret)
goto out;

2008-08-03 17:43:54

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 15/25] drivers/serial to use nr_irqs

On Sun, Aug 3, 2008 at 6:02 AM, Alan Cox <[email protected]> wrote:
>> - for (i = 0; i < NR_IRQS; i++)
>> + for (i = 0; i < nr_irqs; i++)
>> spin_lock_init(&irq_lists[i].lock);
>>
>
> Don't you need to change how the array is allocated too ?

this one is applied before removing NR_IRQS usage in array definition.

YH

2008-08-03 17:54:37

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 00/25] dyn_array and nr_irqs support v3

On Sun, Aug 3, 2008 at 2:15 AM, Eric W. Biederman <[email protected]> wrote:
> "Yinghai Lu" <[email protected]> writes:
>
>> how about
>>
>> diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
>> index f4c8a03..aa6888c 100644
>> --- a/kernel/irq/handle.c
>> +++ b/kernel/irq/handle.c
>> @@ -47,19 +47,73 @@ handle_bad_irq(unsigned int irq, struct irq_desc *desc)
>> *
>> * 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 irq_desc **irq_desc_ptr;
>> +DEFINE_DYN_ARRAY(irq_desc_ptr, sizeof(struct irq_desc *), nr_irqs,
>> PAGE_SIZE, NULL);
>> +
>> +#define NR_IRQ_DESC 4096
>> +
>> +static struct irq_desc irq_desc__init = {
>> + .irq = -1;
>
> Do you perhaps mean 0xffffffffU ?

-1U

>
>> + .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 int nr_irq_desc = NR_IRQ_DESC;
>> +
>> +static int __init parse_nr_irq_desc(char *arg)
>> +{
>> + if (arg)
>> + nr_irq_desc = simple_strtoul(arg, NULL, 0);
>> + return 0;
>> +}
>> +
>> +early_param("nr_irq_desc", parse_nr_irq_desc);
>> +
>> +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));
>> +}
>> +
>> +static struct irq_desc *irq_desc;
>> +DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irq_desc,
>> PAGE_SIZE, init_work);
>> +
>> +struct irq_desc *get_irq_desc(int irq)
>
> Ugh. This has the wrong type. It must be unsigned int irq.
>> +{
>> + struct irq_desc *desc;
>> + int i;
>> +
>> + desc = irq_desc_ptr[irq];
>> +
>> + if (desc)
>> + return desc;
>> +
>> + for (i = 0; i < nr_irq_desc; i++) {
>> + if (irq_desc[i]->irq != -1)
>
> Which makes this line wrong.
>> + continue;
>> +
>> + desc = &irq_desc[i];
>> + desc->irq = irq;
>> + irq_desc_ptr[irq] = desc;
>> +
>> + return desc;
>> + }
>> +
>> + panic("please boot with nr_irq_desc=%d\n", nr_irq_desc * 2);
>> +}
>> +
>> /*
>> * What should we do if we get a hw irq event on an illegal vector?
>> * Each architecture has to answer this themself.
>>
>>
>> and later use get_irq_desc(i) instead irq_desc + i;
>
> That is the general idea.

could use pre_allocate array + list to replace irq_desc array.

YH

2008-08-03 19:20:52

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 00/25] dyn_array and nr_irqs support v3

On Sun, Aug 3, 2008 at 10:54 AM, Yinghai Lu <[email protected]> wrote:
>>> * Each architecture has to answer this themself.
>>>
>>>
>>> and later use get_irq_desc(i) instead irq_desc + i;
>>
>> That is the general idea.
>
> could use pre_allocate array + list to replace irq_desc array.
>

how about this one?

diff --git a/include/linux/irq.h b/include/linux/irq.h
index bd69d90..9d87f6a 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -154,6 +154,8 @@ struct irq_chip {
* @name: flow handler name for /proc/interrupts output
*/
struct irq_desc {
+ unsigned int irq;
+ struct irq_desc *next;
irq_flow_handler_t handle_irq;
struct irq_chip *chip;
struct msi_desc *msi_desc;
@@ -181,7 +183,7 @@ struct irq_desc {
const char *name;
} ____cacheline_internodealigned_in_smp;

-extern struct irq_desc irq_desc[NR_IRQS];
+extern struct irq_desc *get_irq_desc(unsigned int irq);

/*
* Migration helpers for obsolete names, they will go away:
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index e9d022c..347edb8 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -48,7 +48,90 @@ handle_bad_irq(unsigned int irq, struct irq_desc *desc)
* Controller mappings for all interrupt sources:
*/
int nr_irqs = NR_IRQS;
-struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
+
+#ifdef CONFIG_HAVE_DYN_ARRAY
+static struct irq_desc irq_desc_init __initdata = {
+ .irq = -1U;
+ .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 int nr_irq_desc = NR_VECTORS;
+
+static int __init parse_nr_irq_desc(char *arg)
+{
+ if (arg)
+ nr_irq_desc = simple_strtoul(arg, NULL, 0);
+ return 0;
+}
+
+early_param("nr_irq_desc", parse_nr_irq_desc);
+
+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));
+
+ for (i = 1; i < *da->nr; i++)
+ desc[i-1].next = &desc[i];
+}
+
+static struct irq_desc *irq_desc;
+DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irq_desc,
PAGE_SIZE, init_work);
+
+struct irq_desc *get_irq_desc(unsigned int irq)
+{
+ struct irq_desc *desc, *desc_pri;
+
+ BUG_ON(irq == -1U);
+
+ desc = &irq_desc[0];
+ while (desc) {
+ if (desc->irq == irq)
+ return desc;
+
+ if (desc->irq == -1U) {
+ desc->irq = irq;
+ return desc;
+ }
+ desc_pri = desc;
+ desc = desc->next;
+ }
+
+ /*
+ * we run out of pre-allocate ones
+ * and __alloc_bootmem or kzalloc could be used
+ */
+
+ if (after_bootmem)
+ desc = (struct irq_desc *) get_zeroed_page(GFP_ATOMIC);
+ else
+ desc = alloc_bootmem_pages(PAGE_SIZE);
+
+ if (!desc || ((unsigned long)desc & ~PAGE_MASK))
+ panic("please boot with nr_irq_desc= %d\n", nr_irq_desc * 2);
+
+ desc_pri->next = desc;
+ desc->irq = irq;
+
+ return desc;
+}
+
+#else
+
+static struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
[0 ... NR_IRQS-1] = {
.status = IRQ_DISABLED,
.chip = &no_irq_chip,
@@ -61,6 +144,16 @@ struct irq_desc irq_desc[NR_IRQS]
__cacheline_aligned_in_smp = {
}
};

+struct irq_desc *get_irq_desc(unsigned int irq)
+{
+ if (irq < nr_irqs)
+ return &irq_desc[irq];
+
+ return NULL;
+}
+
+#endif
+
/*
* What should we do if we get a hw irq event on an illegal vector?
* Each architecture has to answer this themself.

do we need to lock to avoid racing in get_irq_desc?

YH

2008-08-03 20:03:20

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [PATCH 21/25] serial: change remove NR_IRQS in 8250.c v2

Alan Cox <[email protected]> writes:

> On Sat, 2 Aug 2008 19:59:21 -0700
> Yinghai Lu <[email protected]> wrote:
>
>> use small array with index to handle irq locking for serial port
>> hope 32 slot is enough
>
>
> Untested alternative approach

I like it.

Good catch on the m68k serial driver.


> 8250: Remove NR_IRQ usage
>
> From: Alan Cox <[email protected]>

Now to pick a few nits ;)

You are short a definition of NR_IRQ_HASH that is trivial.

>
> drivers/serial/68328serial.c | 11 ++---------
> drivers/serial/8250.c | 41 ++++++++++++++++++++++++++++++++++-------
> 2 files changed, 36 insertions(+), 16 deletions(-)


> diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
> index a97f1ae..7165e88 100644
> --- a/drivers/serial/8250.c
> +++ b/drivers/serial/8250.c
> @@ -145,11 +145,14 @@ struct uart_8250_port {
> };
>
> struct irq_info {
> - spinlock_t lock;
> + struct irq_info *next;
struct hlist_node hchain;
Would allow us to use the generic hash table code.
> + int irq;
> + spinlock_t lock; /* Protects list not the hash */
> struct list_head *head;
> };
>
> -static struct irq_info irq_lists[NR_IRQS];
> +static struct irq_info *irq_lists[NR_IRQ_HASH];
> +static DEFINE_SPINLOCK(hash_lock); /* Used to walk the hash */
static DEFINE_MUTEX(hash_mutex);

kzalloc sleeps....

Looks like we can also tweak serial_do_unlink to free irq_info when
the list goes empty, so we don't have a leak if the driver is ever
unloaded.

Eric

2008-08-04 02:00:09

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 00/25] dyn_array and nr_irqs support v3

[PATCH] x86_64: use get_irq_desc together with dyn_array

preallocate 32 irq_desc, and get_irq_desc will try to get more.

got:

Allocating PCI resources starting at 90000000 (gap: 88000000:76c00000)
dyn_array irq_2_pin+0x0/0x8 size:0x8 nr:192 align:0x8
dyn_array irq_cfg+0x0/0x8 size:0x108 nr:96 align:0x1000
dyn_array irq_desc+0x0/0x8 size:0x180 nr:32 align:0x1000
dyn_array irq_2_iommu+0x0/0x8 size:0x10 nr:96 align:0x1000
dyn_array irq_timer_state+0x0/0x50 size:0x8 nr:96 align:0x1000
dyn_array total_size: 0xc600
dyn_array irq_2_pin+0x0/0x8 ==> [0x28028000 - 0x28028600]
dyn_array irq_cfg+0x0/0x8 ==> [0x28029000 - 0x2802f300]
dyn_array irq_desc+0x0/0x8 ==> [0x28030000 - 0x28033000]
dyn_array irq_2_iommu+0x0/0x8 ==> [0x28033000 - 0x28033600]
dyn_array irq_timer_state+0x0/0x50 ==> [0x28034000 - 0x28034300]
per_cpu_dyn_array per_cpu__kstat+0x48/0x50 size:0x4 nr:96 align:0x8
per_cpu_dyn_array total_size: 0x180
PERCPU: Allocating 57344 bytes of per cpu data
per cpu data for cpu0 on node0 at 0000000028035000
per_cpu_dyn_array per_cpu__kstat+0x48/0x50 ==> [0x280422a8 - 0x28042428]
per cpu data for cpu1 on node0 at 0000000028043000
per_cpu_dyn_array per_cpu__kstat+0x48/0x50 ==> [0x280502a8 - 0x28050428]
per cpu data for cpu2 on node0 at 0000000028051000
per_cpu_dyn_array per_cpu__kstat+0x48/0x50 ==> [0x2805e2a8 - 0x2805e428]
per cpu data for cpu3 on node0 at 000000002805f000
per_cpu_dyn_array per_cpu__kstat+0x48/0x50 ==> [0x2806c2a8 - 0x2806c428]
per cpu data for cpu4 on node1 at 000000017ba18000
per_cpu_dyn_array per_cpu__kstat+0x48/0x50 ==> [0x17ba252a8 - 0x17ba25428]
per cpu data for cpu5 on node1 at 000000017ba26000
per_cpu_dyn_array per_cpu__kstat+0x48/0x50 ==> [0x17ba332a8 - 0x17ba33428]
per cpu data for cpu6 on node1 at 000000017ba34000
per_cpu_dyn_array per_cpu__kstat+0x48/0x50 ==> [0x17ba412a8 - 0x17ba41428]
per cpu data for cpu7 on node1 at 000000017ba42000
per_cpu_dyn_array per_cpu__kstat+0x48/0x50 ==> [0x17ba4f2a8 - 0x17ba4f428]
per cpu data for cpu8 on node2 at 000000027ba18000
per_cpu_dyn_array per_cpu__kstat+0x48/0x50 ==> [0x27ba252a8 - 0x27ba25428]
per cpu data for cpu9 on node2 at 000000027ba26000
per_cpu_dyn_array per_cpu__kstat+0x48/0x50 ==> [0x27ba332a8 - 0x27ba33428]
per cpu data for cpu10 on node2 at 000000027ba34000
per_cpu_dyn_array per_cpu__kstat+0x48/0x50 ==> [0x27ba412a8 - 0x27ba41428]
per cpu data for cpu11 on node2 at 000000027ba42000
per_cpu_dyn_array per_cpu__kstat+0x48/0x50 ==> [0x27ba4f2a8 - 0x27ba4f428]
per cpu data for cpu12 on node3 at 000000037ba18000
per_cpu_dyn_array per_cpu__kstat+0x48/0x50 ==> [0x37ba252a8 - 0x37ba25428]
per cpu data for cpu13 on node3 at 000000037ba26000
per_cpu_dyn_array per_cpu__kstat+0x48/0x50 ==> [0x37ba332a8 - 0x37ba33428]
per cpu data for cpu14 on node3 at 000000037ba34000
per_cpu_dyn_array per_cpu__kstat+0x48/0x50 ==> [0x37ba412a8 - 0x37ba41428]
per cpu data for cpu15 on node3 at 000000037ba42000
per_cpu_dyn_array per_cpu__kstat+0x48/0x50 ==> [0x37ba4f2a8 - 0x37ba4f428]
NR_CPUS: 1024, nr_cpu_ids: 16, nr_node_ids 4
Built 4 zonelists in Zone order, mobility grouping on. Total pages: 4129993
Policy zone: Normal
Kernel command line: console=uart8250,io,0x3f8,115200n8
initrd=kernel.org/mydisk11_x86_64.gz rw root=/dev/ram0 debug
show_msr=1 nopat initcall_debug apic=verbose pci=routeirq ip=dhcp
load_ramdisk=1 ramdisk_size=131072
BOOT_IMAGE=kernel.org/bzImage_2.6.27_k8.1
Initializing CPU#0
try to get more irq_desc 32
try to get more irq_desc 32
PID hash table entries: 4096 (order: 12, 32768 bytes)

to do:
1. do the same thing to irq_cfg
2. clean up nr_irqs reference and try to kill it, so could remove
after_bootmem/alloc_bootmem in get_irq_desc

Signed-off-by: Yinghai Lu <[email protected]>

---
arch/x86/kernel/io_apic_32.c | 46 ++++++++++----
arch/x86/kernel/io_apic_64.c | 71 ++++++++++++++--------
arch/x86/kernel/irq_32.c | 24 ++++---
arch/x86/kernel/irq_64.c | 35 +++++-----
arch/x86/kernel/irqinit_64.c | 10 +--
arch/x86/kernel/visws_quirks.c | 30 +++++----
arch/x86/mach-voyager/voyager_smp.c | 4 -
drivers/gpio/gpiolib.c | 2
drivers/mfd/asic3.c | 4 -
drivers/mfd/htc-egpio.c | 2
drivers/parisc/dino.c | 6 +
drivers/parisc/eisa.c | 4 -
drivers/parisc/gsc.c | 12 ++-
drivers/parisc/iosapic.c | 4 -
drivers/parisc/superio.c | 4 -
drivers/pcmcia/hd64465_ss.c | 12 ++-
drivers/xen/events.c | 8 +-
include/linux/irq.h | 32 ++++++---
kernel/irq/autoprobe.c | 10 +--
kernel/irq/chip.c | 32 +++++----
kernel/irq/handle.c | 116 ++++++++++++++++++++++++++++++++----
kernel/irq/manage.c | 35 ++++++----
kernel/irq/migration.c | 14 ++--
kernel/irq/proc.c | 36 ++++++-----
kernel/irq/resend.c | 2
kernel/irq/spurious.c | 5 -
26 files changed, 376 insertions(+), 184 deletions(-)

Index: linux-2.6/arch/x86/kernel/io_apic_32.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/io_apic_32.c
+++ linux-2.6/arch/x86/kernel/io_apic_32.c
@@ -345,6 +345,7 @@ static void set_ioapic_affinity_irq(unsi
struct irq_pin_list *entry = irq_2_pin + irq;
unsigned int apicid_value;
cpumask_t tmp;
+ struct irq_desc *desc;

cpus_and(tmp, cpumask, cpu_online_map);
if (cpus_empty(tmp))
@@ -365,7 +366,8 @@ static void set_ioapic_affinity_irq(unsi
break;
entry = irq_2_pin + entry->next;
}
- irq_desc[irq].affinity = cpumask;
+ desc = get_irq_desc(irq);
+ desc->affinity = cpumask;
spin_unlock_irqrestore(&ioapic_lock, flags);
}

@@ -475,10 +477,12 @@ static inline void balance_irq(int cpu,
static inline void rotate_irqs_among_cpus(unsigned long useful_load_threshold)
{
int i, j;
+ struct irq_desc *desc;

for_each_online_cpu(i) {
for (j = 0; j < nr_irqs; j++) {
- if (!irq_desc[j].action)
+ desc = get_irq_desc[j];
+ if (!desc->action)
continue;
/* Is it a significant load ? */
if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i), j) <
@@ -505,6 +509,7 @@ static void do_irq_balance(void)
unsigned long tmp_cpu_irq;
unsigned long imbalance = 0;
cpumask_t allowed_mask, target_cpu_mask, tmp;
+ struct irq_desc *desc;

for_each_possible_cpu(i) {
int package_index;
@@ -515,7 +520,8 @@ static void do_irq_balance(void)
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))
+ desc = get_irq_desc[j];
+ if (!desc->action || irq_balancing_disabled(j))
continue;
if (package_index == i)
IRQ_DELTA(package_index, j) = 0;
@@ -609,7 +615,8 @@ tryanotherirq:
selected_irq = -1;
for (j = 0; j < nr_irqs; j++) {
/* Is this an active IRQ? */
- if (!irq_desc[j].action)
+ desc = get_irq_desc[j];
+ if (!desc->action)
continue;
if (imbalance <= IRQ_DELTA(max_loaded, j))
continue;
@@ -682,10 +689,12 @@ static int balanced_irq(void *unused)
int i;
unsigned long prev_balance_time = jiffies;
long time_remaining = balanced_irq_interval;
+ struct irq_desc *desc;

/* push everything to CPU 0 to give us a starting point. */
for (i = 0 ; i < nr_irqs ; i++) {
- irq_desc[i].pending_mask = cpumask_of_cpu(0);
+ desc = get_irq_desc(i);
+ desc->pending_mask = cpumask_of_cpu(0);
set_pending_irq(i, cpumask_of_cpu(0));
}

@@ -1258,13 +1267,16 @@ static struct irq_chip ioapic_chip;

static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
{
+ struct irq_desc *desc;
+
+ desc = get_irq_desc(irq);
if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
trigger == IOAPIC_LEVEL) {
- irq_desc[irq].status |= IRQ_LEVEL;
+ desc->status |= IRQ_LEVEL;
set_irq_chip_and_handler_name(irq, &ioapic_chip,
handle_fasteoi_irq, "fasteoi");
} else {
- irq_desc[irq].status &= ~IRQ_LEVEL;
+ desc->status &= ~IRQ_LEVEL;
set_irq_chip_and_handler_name(irq, &ioapic_chip,
handle_edge_irq, "edge");
}
@@ -2031,6 +2043,7 @@ static struct irq_chip ioapic_chip __rea
static inline void init_IO_APIC_traps(void)
{
int irq;
+ struct irq_desc *desc;

/*
* NOTE! The local APIC isn't very good at handling
@@ -2044,6 +2057,7 @@ static inline void init_IO_APIC_traps(vo
* 0x80, because int 0x80 is hm, kind of importantish. ;)
*/
for (irq = 0; irq < nr_irqs ; irq++) {
+ desc = get_irq_desc(irq);
if (IO_APIC_IRQ(irq) && !irq_vector[irq]) {
/*
* Hmm.. We don't have an entry for this,
@@ -2052,9 +2066,10 @@ static inline void init_IO_APIC_traps(vo
*/
if (irq < 16)
make_8259A_irq(irq);
- else
+ else {
/* Strange. Oh, well.. */
- irq_desc[irq].chip = &no_irq_chip;
+ desc->chip = &no_irq_chip;
+ }
}
}
}
@@ -2093,7 +2108,10 @@ static struct irq_chip lapic_chip __read

static void lapic_register_intr(int irq, int vector)
{
- irq_desc[irq].status &= ~IRQ_LEVEL;
+ struct irq_desc *desc;
+
+ desc = get_irq_desc(irq);
+ desc->status &= ~IRQ_LEVEL;
set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
"edge");
set_intr_gate(vector, interrupt[irq]);
@@ -2560,6 +2578,7 @@ static void set_msi_irq_affinity(unsigne
unsigned int dest;
cpumask_t tmp;
int vector;
+ struct irq_desc *desc;

cpus_and(tmp, mask, cpu_online_map);
if (cpus_empty(tmp))
@@ -2579,7 +2598,8 @@ static void set_msi_irq_affinity(unsigne
msg.address_lo |= MSI_ADDR_DEST_ID(dest);

write_msi_msg(irq, &msg);
- irq_desc[irq].affinity = mask;
+ desc = get_irq_desc(irq);
+ desc->affinity = mask;
}
#endif /* CONFIG_SMP */

@@ -2653,6 +2673,7 @@ static void set_ht_irq_affinity(unsigned
{
unsigned int dest;
cpumask_t tmp;
+ struct irq_desc *desc;

cpus_and(tmp, mask, cpu_online_map);
if (cpus_empty(tmp))
@@ -2663,7 +2684,8 @@ static void set_ht_irq_affinity(unsigned
dest = cpu_mask_to_apicid(mask);

target_ht_irq(irq, dest);
- irq_desc[irq].affinity = mask;
+ desc = get_irq_desc(irq);
+ desc->affinity = mask;
}
#endif

Index: linux-2.6/arch/x86/kernel/io_apic_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/io_apic_64.c
+++ linux-2.6/arch/x86/kernel/io_apic_64.c
@@ -345,6 +345,7 @@ static void set_ioapic_affinity_irq(unsi
unsigned long flags;
unsigned int dest;
cpumask_t tmp;
+ struct irq_desc *desc;

cpus_and(tmp, mask, cpu_online_map);
if (cpus_empty(tmp))
@@ -361,9 +362,10 @@ static void set_ioapic_affinity_irq(unsi
*/
dest = SET_APIC_LOGICAL_ID(dest);

+ desc = get_irq_desc(irq);
spin_lock_irqsave(&ioapic_lock, flags);
__target_IO_APIC_irq(irq, dest, cfg->vector);
- irq_desc[irq].affinity = mask;
+ desc->affinity = mask;
spin_unlock_irqrestore(&ioapic_lock, flags);
}
#endif
@@ -928,14 +930,17 @@ static struct irq_chip ir_ioapic_chip;

static void ioapic_register_intr(int irq, unsigned long trigger)
{
+ struct irq_desc *desc;
+
+ desc = get_irq_desc(irq);
if (trigger)
- irq_desc[irq].status |= IRQ_LEVEL;
+ desc->status |= IRQ_LEVEL;
else
- irq_desc[irq].status &= ~IRQ_LEVEL;
+ desc->status &= ~IRQ_LEVEL;

#ifdef CONFIG_INTR_REMAP
if (irq_remapped(irq)) {
- irq_desc[irq].status |= IRQ_MOVE_PCNTXT;
+ desc->status |= IRQ_MOVE_PCNTXT;
if (trigger)
set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
handle_fasteoi_irq,
@@ -1593,7 +1598,7 @@ static DECLARE_DELAYED_WORK(ir_migration
static void migrate_ioapic_irq(int irq, cpumask_t mask)
{
struct irq_cfg *cfg = irq_cfg + irq;
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);
cpumask_t tmp, cleanup_mask;
struct irte irte;
int modify_ioapic_rte = desc->status & IRQ_LEVEL;
@@ -1634,12 +1639,13 @@ static void migrate_ioapic_irq(int irq,
cfg->move_in_progress = 0;
}

- irq_desc[irq].affinity = mask;
+ desc->affinity = mask;
}

static int migrate_irq_remapped_level(int irq)
{
int ret = -1;
+ struct irq_desc *desc = get_irq_desc(irq);

mask_IO_APIC_irq(irq);

@@ -1655,11 +1661,11 @@ static int migrate_irq_remapped_level(in
}

/* everthing is clear. we have right of way */
- migrate_ioapic_irq(irq, irq_desc[irq].pending_mask);
+ migrate_ioapic_irq(irq, desc->pending_mask);

ret = 0;
- irq_desc[irq].status &= ~IRQ_MOVE_PENDING;
- cpus_clear(irq_desc[irq].pending_mask);
+ desc->status &= ~IRQ_MOVE_PENDING;
+ cpus_clear(desc->pending_mask);

unmask:
unmask_IO_APIC_irq(irq);
@@ -1671,7 +1677,7 @@ static void ir_irq_migration(struct work
int irq;

for (irq = 0; irq < nr_irqs; irq++) {
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);
if (desc->status & IRQ_MOVE_PENDING) {
unsigned long flags;

@@ -1683,8 +1689,7 @@ static void ir_irq_migration(struct work
continue;
}

- desc->chip->set_affinity(irq,
- irq_desc[irq].pending_mask);
+ desc->chip->set_affinity(irq, desc->pending_mask);
spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -1695,9 +1700,11 @@ static void ir_irq_migration(struct work
*/
static void set_ir_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
{
- if (irq_desc[irq].status & IRQ_LEVEL) {
- irq_desc[irq].status |= IRQ_MOVE_PENDING;
- irq_desc[irq].pending_mask = mask;
+ struct irq_desc *desc = get_irq_desc(irq);
+
+ if (desc->status & IRQ_LEVEL) {
+ desc->status |= IRQ_MOVE_PENDING;
+ desc->pending_mask = mask;
migrate_irq_remapped_level(irq);
return;
}
@@ -1722,7 +1729,7 @@ asmlinkage void smp_irq_move_cleanup_int
if (irq >= nr_irqs)
continue;

- desc = irq_desc + irq;
+ desc = get_irq_desc(irq);
cfg = irq_cfg + irq;
spin_lock(&desc->lock);
if (!cfg->move_cleanup_count)
@@ -1788,7 +1795,7 @@ static void ack_apic_level(unsigned int
irq_complete_move(irq);
#ifdef CONFIG_GENERIC_PENDING_IRQ
/* If we are moving the irq we need to mask it */
- if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) {
+ if (unlikely(get_irq_desc(irq)->status & IRQ_MOVE_PENDING)) {
do_unmask_irq = 1;
mask_IO_APIC_irq(irq);
}
@@ -1865,6 +1872,7 @@ static struct irq_chip ir_ioapic_chip __
static inline void init_IO_APIC_traps(void)
{
int irq;
+ struct irq_desc *desc;

/*
* NOTE! The local APIC isn't very good at handling
@@ -1886,9 +1894,11 @@ static inline void init_IO_APIC_traps(vo
*/
if (irq < 16)
make_8259A_irq(irq);
- else
+ else {
+ desc = get_irq_desc(irq);
/* Strange. Oh, well.. */
- irq_desc[irq].chip = &no_irq_chip;
+ desc->chip = &no_irq_chip;
+ }
}
}
}
@@ -1923,7 +1933,10 @@ static struct irq_chip lapic_chip __read

static void lapic_register_intr(int irq)
{
- irq_desc[irq].status &= ~IRQ_LEVEL;
+ struct irq_desc *desc;
+
+ desc = get_irq_desc(irq);
+ desc->status &= ~IRQ_LEVEL;
set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
"edge");
}
@@ -2399,6 +2412,7 @@ static void set_msi_irq_affinity(unsigne
struct msi_msg msg;
unsigned int dest;
cpumask_t tmp;
+ struct irq_desc *desc;

cpus_and(tmp, mask, cpu_online_map);
if (cpus_empty(tmp))
@@ -2418,7 +2432,8 @@ static void set_msi_irq_affinity(unsigne
msg.address_lo |= MSI_ADDR_DEST_ID(dest);

write_msi_msg(irq, &msg);
- irq_desc[irq].affinity = mask;
+ desc = get_irq_desc(irq);
+ desc->affinity = mask;
}

#ifdef CONFIG_INTR_REMAP
@@ -2432,6 +2447,7 @@ static void ir_set_msi_irq_affinity(unsi
unsigned int dest;
cpumask_t tmp, cleanup_mask;
struct irte irte;
+ struct irq_desc *desc;

cpus_and(tmp, mask, cpu_online_map);
if (cpus_empty(tmp))
@@ -2466,7 +2482,8 @@ static void ir_set_msi_irq_affinity(unsi
cfg->move_in_progress = 0;
}

- irq_desc[irq].affinity = mask;
+ desc = get_irq_desc(irq);
+ desc->affinity = mask;
}
#endif
#endif /* CONFIG_SMP */
@@ -2540,7 +2557,7 @@ static int setup_msi_irq(struct pci_dev

#ifdef CONFIG_INTR_REMAP
if (irq_remapped(irq)) {
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);
/*
* irq migration in process context
*/
@@ -2652,6 +2669,7 @@ static void dmar_msi_set_affinity(unsign
struct msi_msg msg;
unsigned int dest;
cpumask_t tmp;
+ struct irq_desc *desc;

cpus_and(tmp, mask, cpu_online_map);
if (cpus_empty(tmp))
@@ -2671,7 +2689,8 @@ static void dmar_msi_set_affinity(unsign
msg.address_lo |= MSI_ADDR_DEST_ID(dest);

dmar_msi_write(irq, &msg);
- irq_desc[irq].affinity = mask;
+ desc = get_irq_desc(irq);
+ desc->affinity = mask;
}
#endif /* CONFIG_SMP */

@@ -2728,6 +2747,7 @@ static void set_ht_irq_affinity(unsigned
struct irq_cfg *cfg = irq_cfg + irq;
unsigned int dest;
cpumask_t tmp;
+ struct irq_desc *desc;

cpus_and(tmp, mask, cpu_online_map);
if (cpus_empty(tmp))
@@ -2740,7 +2760,8 @@ static void set_ht_irq_affinity(unsigned
dest = cpu_mask_to_apicid(tmp);

target_ht_irq(irq, dest, cfg->vector);
- irq_desc[irq].affinity = mask;
+ desc = get_irq_desc(irq);
+ desc->affinity = mask;
}
#endif

Index: linux-2.6/arch/x86/kernel/irq_32.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/irq_32.c
+++ linux-2.6/arch/x86/kernel/irq_32.c
@@ -224,7 +224,7 @@ unsigned int do_IRQ(struct pt_regs *regs
struct pt_regs *old_regs;
/* high bit used in ret_from_ code */
int overflow, irq = ~regs->orig_ax;
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);

if (unlikely((unsigned)irq >= nr_irqs)) {
printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
@@ -273,15 +273,16 @@ int show_interrupts(struct seq_file *p,

if (i < nr_irqs) {
unsigned any_count = 0;
+ struct irq_desc *desc = get_irq_desc(i);

- spin_lock_irqsave(&irq_desc[i].lock, flags);
+ spin_lock_irqsave(&desc->lock, flags);
#ifndef CONFIG_SMP
any_count = kstat_irqs(i);
#else
for_each_online_cpu(j)
any_count |= kstat_cpu(j).irqs[i];
#endif
- action = irq_desc[i].action;
+ action = desc->action;
if (!action && !any_count)
goto skip;
seq_printf(p, "%3d: ",i);
@@ -291,8 +292,8 @@ int show_interrupts(struct seq_file *p,
for_each_online_cpu(j)
seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
#endif
- seq_printf(p, " %8s", irq_desc[i].chip->name);
- seq_printf(p, "-%-8s", irq_desc[i].name);
+ seq_printf(p, " %8s", desc->chip->name);
+ seq_printf(p, "-%-8s", desc->name);

if (action) {
seq_printf(p, " %s", action->name);
@@ -302,7 +303,7 @@ int show_interrupts(struct seq_file *p,

seq_putc(p, '\n');
skip:
- spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ spin_unlock_irqrestore(&desc->lock, flags);
} else if (i == nr_irqs) {
seq_printf(p, "NMI: ");
for_each_online_cpu(j)
@@ -398,17 +399,20 @@ void fixup_irqs(cpumask_t map)

for (irq = 0; irq < nr_irqs; irq++) {
cpumask_t mask;
+ struct irq_desc *desc;
+
if (irq == 2)
continue;

- cpus_and(mask, irq_desc[irq].affinity, map);
+ desc = get_irq_desc(irq);
+ cpus_and(mask, desc->affinity, map);
if (any_online_cpu(mask) == NR_CPUS) {
printk("Breaking affinity for irq %i\n", irq);
mask = map;
}
- if (irq_desc[irq].chip->set_affinity)
- irq_desc[irq].chip->set_affinity(irq, mask);
- else if (irq_desc[irq].action && !(warned++))
+ if (desc->chip->set_affinity)
+ desc->chip->set_affinity(irq, mask);
+ else if (desc->action && !(warned++))
printk("Cannot set affinity for irq %i\n", irq);
}

Index: linux-2.6/arch/x86/kernel/irq_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/irq_64.c
+++ linux-2.6/arch/x86/kernel/irq_64.c
@@ -83,15 +83,16 @@ int show_interrupts(struct seq_file *p,

if (i < nr_irqs) {
unsigned any_count = 0;
+ struct irq_desc *desc = get_irq_desc(i);

- spin_lock_irqsave(&irq_desc[i].lock, flags);
+ spin_lock_irqsave(&desc->lock, flags);
#ifndef CONFIG_SMP
any_count = kstat_irqs(i);
#else
for_each_online_cpu(j)
any_count |= kstat_cpu(j).irqs[i];
#endif
- action = irq_desc[i].action;
+ action = desc->action;
if (!action && !any_count)
goto skip;
seq_printf(p, "%3d: ",i);
@@ -101,8 +102,8 @@ int show_interrupts(struct seq_file *p,
for_each_online_cpu(j)
seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
#endif
- seq_printf(p, " %8s", irq_desc[i].chip->name);
- seq_printf(p, "-%-8s", irq_desc[i].name);
+ seq_printf(p, " %8s", desc->chip->name);
+ seq_printf(p, "-%-8s", desc->name);

if (action) {
seq_printf(p, " %s", action->name);
@@ -111,7 +112,7 @@ int show_interrupts(struct seq_file *p,
}
seq_putc(p, '\n');
skip:
- spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ spin_unlock_irqrestore(&desc->lock, flags);
} else if (i == nr_irqs) {
seq_printf(p, "NMI: ");
for_each_online_cpu(j)
@@ -228,37 +229,39 @@ void fixup_irqs(cpumask_t map)
cpumask_t mask;
int break_affinity = 0;
int set_affinity = 1;
+ struct irq_desc *desc;

if (irq == 2)
continue;

+ desc = get_irq_desc(irq);
/* interrupt's are disabled at this point */
- spin_lock(&irq_desc[irq].lock);
+ spin_lock(&desc->lock);

if (!irq_has_action(irq) ||
- cpus_equal(irq_desc[irq].affinity, map)) {
- spin_unlock(&irq_desc[irq].lock);
+ cpus_equal(desc->affinity, map)) {
+ spin_unlock(&desc->lock);
continue;
}

- cpus_and(mask, irq_desc[irq].affinity, map);
+ cpus_and(mask, desc->affinity, map);
if (cpus_empty(mask)) {
break_affinity = 1;
mask = map;
}

- if (irq_desc[irq].chip->mask)
- irq_desc[irq].chip->mask(irq);
+ if (desc->chip->mask)
+ desc->chip->mask(irq);

- if (irq_desc[irq].chip->set_affinity)
- irq_desc[irq].chip->set_affinity(irq, mask);
+ if (desc->chip->set_affinity)
+ desc->chip->set_affinity(irq, mask);
else if (!(warned++))
set_affinity = 0;

- if (irq_desc[irq].chip->unmask)
- irq_desc[irq].chip->unmask(irq);
+ if (desc->chip->unmask)
+ desc->chip->unmask(irq);

- spin_unlock(&irq_desc[irq].lock);
+ spin_unlock(&desc->lock);

if (break_affinity && set_affinity)
printk("Broke affinity for irq %i\n", irq);
Index: linux-2.6/arch/x86/kernel/irqinit_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/irqinit_64.c
+++ linux-2.6/arch/x86/kernel/irqinit_64.c
@@ -143,9 +143,11 @@ static void __init init_ISA_irqs (void)
init_8259A(0);

for (i = 0; i < nr_irqs; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
+ struct irq_desc *desc = get_irq_desc(i);
+
+ desc->status = IRQ_DISABLED;
+ desc->action = NULL;
+ desc->depth = 1;

if (i < 16) {
/*
@@ -157,7 +159,7 @@ static void __init init_ISA_irqs (void)
/*
* 'high' PCI IRQs filled in on demand
*/
- irq_desc[i].chip = &no_irq_chip;
+ desc->chip = &no_irq_chip;
}
}
}
Index: linux-2.6/arch/x86/kernel/visws_quirks.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/visws_quirks.c
+++ linux-2.6/arch/x86/kernel/visws_quirks.c
@@ -486,10 +486,11 @@ static void disable_cobalt_irq(unsigned
static unsigned int startup_cobalt_irq(unsigned int irq)
{
unsigned long flags;
+ struct irq_desc *desc = get_irq_desc(irq);

spin_lock_irqsave(&cobalt_lock, flags);
- if ((irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS |
IRQ_WAITING)))
- irq_desc[irq].status &= ~(IRQ_DISABLED |
IRQ_INPROGRESS | IRQ_WAITING);
+ if ((desc->status & (IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING)))
+ desc->status &= ~(IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING);
enable_cobalt_irq(irq);
spin_unlock_irqrestore(&cobalt_lock, flags);
return 0;
@@ -508,9 +509,10 @@ static void ack_cobalt_irq(unsigned int
static void end_cobalt_irq(unsigned int irq)
{
unsigned long flags;
+ struct irq_desc *desc = get_irq_desc(irq);

spin_lock_irqsave(&cobalt_lock, flags);
- if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ if (!(desc->status & (IRQ_DISABLED | IRQ_INPROGRESS)))
enable_cobalt_irq(irq);
spin_unlock_irqrestore(&cobalt_lock, flags);
}
@@ -628,7 +630,7 @@ static irqreturn_t piix4_master_intr(int

spin_unlock_irqrestore(&i8259A_lock, flags);

- desc = irq_desc + realirq;
+ desc = get_irq_desc(realirq);

/*
* handle this 'virtual interrupt' as a Cobalt one now.
@@ -664,27 +666,29 @@ void init_VISWS_APIC_irqs(void)
int i;

for (i = 0; i < CO_IRQ_APIC0 + CO_APIC_LAST + 1; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 1;
+ struct irq_desc *desc = get_irq_desc(i);
+
+ desc->status = IRQ_DISABLED;
+ desc->action = 0;
+ desc->depth = 1;

if (i == 0) {
- irq_desc[i].chip = &cobalt_irq_type;
+ desc->chip = &cobalt_irq_type;
}
else if (i == CO_IRQ_IDE0) {
- irq_desc[i].chip = &cobalt_irq_type;
+ desc->chip = &cobalt_irq_type;
}
else if (i == CO_IRQ_IDE1) {
- irq_desc[i].chip = &cobalt_irq_type;
+ desc->chip = &cobalt_irq_type;
}
else if (i == CO_IRQ_8259) {
- irq_desc[i].chip = &piix4_master_irq_type;
+ desc->chip = &piix4_master_irq_type;
}
else if (i < CO_IRQ_APIC0) {
- irq_desc[i].chip = &piix4_virtual_irq_type;
+ desc->chip = &piix4_virtual_irq_type;
}
else if (IS_CO_APIC(i)) {
- irq_desc[i].chip = &cobalt_irq_type;
+ desc->chip = &cobalt_irq_type;
}
}

Index: linux-2.6/arch/x86/mach-voyager/voyager_smp.c
===================================================================
--- linux-2.6.orig/arch/x86/mach-voyager/voyager_smp.c
+++ linux-2.6/arch/x86/mach-voyager/voyager_smp.c
@@ -1481,7 +1481,7 @@ static void disable_local_vic_irq(unsign
* the interrupt off to another CPU */
static void before_handle_vic_irq(unsigned int irq)
{
- irq_desc_t *desc = irq_desc + irq;
+ irq_desc_t *desc = get_irq_desc(irq);
__u8 cpu = smp_processor_id();

_raw_spin_lock(&vic_irq_lock);
@@ -1516,7 +1516,7 @@ static void before_handle_vic_irq(unsign
/* Finish the VIC interrupt: basically mask */
static void after_handle_vic_irq(unsigned int irq)
{
- irq_desc_t *desc = irq_desc + irq;
+ irq_desc_t *desc = get_irq_desc(irq);

_raw_spin_lock(&vic_irq_lock);
{
Index: linux-2.6/drivers/gpio/gpiolib.c
===================================================================
--- linux-2.6.orig/drivers/gpio/gpiolib.c
+++ linux-2.6/drivers/gpio/gpiolib.c
@@ -1058,7 +1058,7 @@ static void gpiolib_dbg_show(struct seq_

if (!is_out) {
int irq = gpio_to_irq(gpio);
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);

/* This races with request_irq(), set_irq_type(),
* and set_irq_wake() ... but those are "rare".
Index: linux-2.6/drivers/mfd/asic3.c
===================================================================
--- linux-2.6.orig/drivers/mfd/asic3.c
+++ linux-2.6/drivers/mfd/asic3.c
@@ -124,7 +124,7 @@ static void asic3_irq_demux(unsigned int
irqnr = asic->irq_base +
(ASIC3_GPIOS_PER_BANK * bank)
+ i;
- desc = irq_desc + irqnr;
+ desc = get_irq_desc(irqnr);
desc->handle_irq(irqnr, desc);
if (asic->irq_bothedge[bank] & bit)
asic3_irq_flip_edge(asic, base,
@@ -137,7 +137,7 @@ static void asic3_irq_demux(unsigned int
for (i = ASIC3_NUM_GPIOS; i < ASIC3_NR_IRQS; i++) {
/* They start at bit 4 and go up */
if (status & (1 << (i - ASIC3_NUM_GPIOS + 4))) {
- desc = irq_desc + asic->irq_base + i;
+ desc = get_irq_desc(asic->irq_base + i);
desc->handle_irq(asic->irq_base + i,
desc);
}
Index: linux-2.6/drivers/mfd/htc-egpio.c
===================================================================
--- linux-2.6.orig/drivers/mfd/htc-egpio.c
+++ linux-2.6/drivers/mfd/htc-egpio.c
@@ -112,7 +112,7 @@ static void egpio_handler(unsigned int i
/* Run irq handler */
pr_debug("got IRQ %d\n", irqpin);
irq = ei->irq_start + irqpin;
- desc = &irq_desc[irq];
+ desc = get_irq_desc(irq);
desc->handle_irq(irq, desc);
}
}
Index: linux-2.6/drivers/parisc/dino.c
===================================================================
--- linux-2.6.orig/drivers/parisc/dino.c
+++ linux-2.6/drivers/parisc/dino.c
@@ -298,7 +298,8 @@ struct pci_port_ops dino_port_ops = {

static void dino_disable_irq(unsigned int irq)
{
- struct dino_device *dino_dev = irq_desc[irq].chip_data;
+ struct irq_desc *desc = get_irq_desc(irq);
+ struct dino_device *dino_dev = desc->chip_data;
int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq,
DINO_LOCAL_IRQS);

DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, irq);
@@ -310,7 +311,8 @@ static void dino_disable_irq(unsigned in

static void dino_enable_irq(unsigned int irq)
{
- struct dino_device *dino_dev = irq_desc[irq].chip_data;
+ struct irq_desc *desc = get_irq_desc(irq);
+ struct dino_device *dino_dev = desc->chip_data;
int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq,
DINO_LOCAL_IRQS);
u32 tmp;

Index: linux-2.6/drivers/parisc/eisa.c
===================================================================
--- linux-2.6.orig/drivers/parisc/eisa.c
+++ linux-2.6/drivers/parisc/eisa.c
@@ -346,10 +346,10 @@ static int __init eisa_probe(struct pari
}

/* Reserve IRQ2 */
- irq_desc[2].action = &irq2_action;
+ get_irq_desc(2)->action = &irq2_action;

for (i = 0; i < 16; i++) {
- irq_desc[i].chip = &eisa_interrupt_type;
+ get_irq_desc(i)->chip = &eisa_interrupt_type;
}

EISA_bus = 1;
Index: linux-2.6/drivers/parisc/gsc.c
===================================================================
--- linux-2.6.orig/drivers/parisc/gsc.c
+++ linux-2.6/drivers/parisc/gsc.c
@@ -108,7 +108,8 @@ int gsc_find_local_irq(unsigned int irq,

static void gsc_asic_disable_irq(unsigned int irq)
{
- struct gsc_asic *irq_dev = irq_desc[irq].chip_data;
+ struct irq_desc *desc = get_irq_desc(irq);
+ struct gsc_asic *irq_dev = desc->chip_data;
int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
u32 imr;

@@ -123,7 +124,8 @@ static void gsc_asic_disable_irq(unsigne

static void gsc_asic_enable_irq(unsigned int irq)
{
- struct gsc_asic *irq_dev = irq_desc[irq].chip_data;
+ struct irq_desc *desc = get_irq_desc(irq);
+ struct gsc_asic *irq_dev = desc->chip_data;
int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
u32 imr;

@@ -159,12 +161,14 @@ static struct hw_interrupt_type gsc_asic
int gsc_assign_irq(struct hw_interrupt_type *type, void *data)
{
static int irq = GSC_IRQ_BASE;
+ struct irq_desc *desc;

if (irq > GSC_IRQ_MAX)
return NO_IRQ;

- irq_desc[irq].chip = type;
- irq_desc[irq].chip_data = data;
+ desc = get_irq_desc(irq);
+ desc->chip = type;
+ desc->chip_data = data;
return irq++;
}

Index: linux-2.6/drivers/parisc/iosapic.c
===================================================================
--- linux-2.6.orig/drivers/parisc/iosapic.c
+++ linux-2.6/drivers/parisc/iosapic.c
@@ -619,7 +619,9 @@ iosapic_set_irt_data( struct vector_info

static struct vector_info *iosapic_get_vector(unsigned int irq)
{
- return irq_desc[irq].chip_data;
+ struct irq_desc *desc = get_irq_desc(irq);
+
+ return desc->chip_data;
}

static void iosapic_disable_irq(unsigned int irq)
Index: linux-2.6/drivers/parisc/superio.c
===================================================================
--- linux-2.6.orig/drivers/parisc/superio.c
+++ linux-2.6/drivers/parisc/superio.c
@@ -363,7 +363,9 @@ int superio_fixup_irq(struct pci_dev *pc
#endif

for (i = 0; i < 16; i++) {
- irq_desc[i].chip = &superio_interrupt_type;
+ struct irq_desc *desc = get_irq_desc(i);
+
+ desc->chip = &superio_interrupt_type;
}

/*
Index: linux-2.6/drivers/pcmcia/hd64465_ss.c
===================================================================
--- linux-2.6.orig/drivers/pcmcia/hd64465_ss.c
+++ linux-2.6/drivers/pcmcia/hd64465_ss.c
@@ -234,15 +234,18 @@ static struct hw_interrupt_type hd64465_
*/
static void hs_map_irq(hs_socket_t *sp, unsigned int irq)
{
+ struct irq_desc *desc;
+
DPRINTK("hs_map_irq(sock=%d irq=%d)\n", sp->number, irq);

if (irq >= HS_NUM_MAPPED_IRQS)
return;

+ desc = get_irq_desc(irq);
hs_mapped_irq[irq].sock = sp;
/* insert ourselves as the irq controller */
- hs_mapped_irq[irq].old_handler = irq_desc[irq].chip;
- irq_desc[irq].chip = &hd64465_ss_irq_type;
+ hs_mapped_irq[irq].old_handler = desc->chip;
+ desc->chip = &hd64465_ss_irq_type;
}


@@ -251,13 +254,16 @@ static void hs_map_irq(hs_socket_t *sp,
*/
static void hs_unmap_irq(hs_socket_t *sp, unsigned int irq)
{
+ struct irq_desc *desc;
+
DPRINTK("hs_unmap_irq(sock=%d irq=%d)\n", sp->number, irq);

if (irq >= HS_NUM_MAPPED_IRQS)
return;

+ desc = get_irq_desc(irq);
/* restore the original irq controller */
- irq_desc[irq].chip = hs_mapped_irq[irq].old_handler;
+ desc->chip = hs_mapped_irq[irq].old_handler;
}

/*============================================================*/
Index: linux-2.6/drivers/xen/events.c
===================================================================
--- linux-2.6.orig/drivers/xen/events.c
+++ linux-2.6/drivers/xen/events.c
@@ -125,7 +125,7 @@ static void bind_evtchn_to_cpu(unsigned

BUG_ON(irq == -1);
#ifdef CONFIG_SMP
- irq_desc[irq].affinity = cpumask_of_cpu(cpu);
+ get_irq_desc(irq)->affinity = cpumask_of_cpu(cpu);
#endif

__clear_bit(chn, cpu_evtchn_mask[cpu_evtchn[chn]]);
@@ -139,8 +139,10 @@ 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++)
- irq_desc[i].affinity = cpumask_of_cpu(0);
+ for (i = 0; i < nr_irqs; i++) {
+ struct irq_desc *desc = get_irq_desc(i);
+ desc->affinity = cpumask_of_cpu(0);
+ }
#endif

memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -154,6 +154,10 @@ struct irq_chip {
* @name: flow handler name for /proc/interrupts output
*/
struct irq_desc {
+#ifdef CONFIG_HAVE_DYN_ARRAY
+ unsigned int irq;
+ struct irq_desc *next;
+#endif
irq_flow_handler_t handle_irq;
struct irq_chip *chip;
struct msi_desc *msi_desc;
@@ -181,9 +185,9 @@ 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 *get_irq_desc(unsigned int irq);
+#ifndef CONFIG_HAVE_DYN_ARRAY
+/* could be removed if we get rid of all irq_desc reference */
extern struct irq_desc irq_desc[NR_IRQS];
#endif

@@ -251,7 +255,10 @@ extern int no_irq_affinity;

static inline int irq_balancing_disabled(unsigned int irq)
{
- return irq_desc[irq].status & IRQ_NO_BALANCING_MASK;
+ struct irq_desc *desc;
+
+ desc = get_irq_desc(irq);
+ return desc->status & IRQ_NO_BALANCING_MASK;
}

/* Handle irq action chains: */
@@ -283,7 +290,7 @@ extern unsigned int __do_IRQ(unsigned in
*/
static inline void generic_handle_irq(unsigned int irq)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);

#ifdef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
desc->handle_irq(irq, desc);
@@ -327,7 +334,10 @@ __set_irq_handler(unsigned int irq, irq_
static inline void __set_irq_handler_unlocked(int irq,
irq_flow_handler_t handler)
{
- irq_desc[irq].handle_irq = handler;
+ struct irq_desc *desc;
+
+ desc = get_irq_desc(irq);
+ desc->handle_irq = handler;
}

/*
@@ -361,7 +371,7 @@ extern void destroy_irq(unsigned int irq
/* Test to see if a driver has successfully requested an irq */
static inline int irq_has_action(unsigned int irq)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);
return desc->action != NULL;
}

@@ -376,10 +386,10 @@ extern int set_irq_chip_data(unsigned in
extern int set_irq_type(unsigned int irq, unsigned int type);
extern int set_irq_msi(unsigned int irq, struct msi_desc *entry);

-#define get_irq_chip(irq) (irq_desc[irq].chip)
-#define get_irq_chip_data(irq) (irq_desc[irq].chip_data)
-#define get_irq_data(irq) (irq_desc[irq].handler_data)
-#define get_irq_msi(irq) (irq_desc[irq].msi_desc)
+#define get_irq_chip(irq) (get_irq_desc(irq)->chip)
+#define get_irq_chip_data(irq) (get_irq_desc(irq)->chip_data)
+#define get_irq_data(irq) (get_irq_desc(irq)->handler_data)
+#define get_irq_msi(irq) (get_irq_desc(irq)->msi_desc)

#endif /* CONFIG_GENERIC_HARDIRQS */

Index: linux-2.6/kernel/irq/autoprobe.c
===================================================================
--- linux-2.6.orig/kernel/irq/autoprobe.c
+++ linux-2.6/kernel/irq/autoprobe.c
@@ -39,7 +39,7 @@ unsigned long probe_irq_on(void)
* flush such a longstanding irq before considering it as spurious.
*/
for (i = nr_irqs-1; i > 0; i--) {
- desc = irq_desc + i;
+ desc = get_irq_desc(i);

spin_lock_irq(&desc->lock);
if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
@@ -69,7 +69,7 @@ unsigned long probe_irq_on(void)
* happened in the previous stage, it may have masked itself)
*/
for (i = nr_irqs-1; i > 0; i--) {
- desc = irq_desc + i;
+ desc = get_irq_desc(i);

spin_lock_irq(&desc->lock);
if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
@@ -92,7 +92,7 @@ unsigned long probe_irq_on(void)
for (i = 0; i < nr_irqs; i++) {
unsigned int status;

- desc = irq_desc + i;
+ desc = get_irq_desc(i);
spin_lock_irq(&desc->lock);
status = desc->status;

@@ -131,7 +131,7 @@ unsigned int probe_irq_mask(unsigned lon

mask = 0;
for (i = 0; i < nr_irqs; i++) {
- struct irq_desc *desc = irq_desc + i;
+ struct irq_desc *desc = get_irq_desc(i);
unsigned int status;

spin_lock_irq(&desc->lock);
@@ -174,7 +174,7 @@ int probe_irq_off(unsigned long val)
int i, irq_found = 0, nr_irqs = 0;

for (i = 0; i < nr_irqs; i++) {
- struct irq_desc *desc = irq_desc + i;
+ struct irq_desc *desc = get_irq_desc(i);
unsigned int status;

spin_lock_irq(&desc->lock);
Index: linux-2.6/kernel/irq/chip.c
===================================================================
--- linux-2.6.orig/kernel/irq/chip.c
+++ linux-2.6/kernel/irq/chip.c
@@ -33,7 +33,7 @@ void dynamic_irq_init(unsigned int irq)
}

/* Ensure we don't have left over values from a previous use
of this irq */
- desc = irq_desc + irq;
+ desc = get_irq_desc(irq);
spin_lock_irqsave(&desc->lock, flags);
desc->status = IRQ_DISABLED;
desc->chip = &no_irq_chip;
@@ -65,7 +65,7 @@ void dynamic_irq_cleanup(unsigned int ir
return;
}

- desc = irq_desc + irq;
+ desc = get_irq_desc(irq);
spin_lock_irqsave(&desc->lock, flags);
if (desc->action) {
spin_unlock_irqrestore(&desc->lock, flags);
@@ -100,7 +100,7 @@ int set_irq_chip(unsigned int irq, struc
if (!chip)
chip = &no_irq_chip;

- desc = irq_desc + irq;
+ desc = get_irq_desc(irq);
spin_lock_irqsave(&desc->lock, flags);
irq_chip_set_defaults(chip);
desc->chip = chip;
@@ -126,7 +126,7 @@ int set_irq_type(unsigned int irq, unsig
return -ENODEV;
}

- desc = irq_desc + irq;
+ desc = get_irq_desc(irq);
if (desc->chip->set_type) {
spin_lock_irqsave(&desc->lock, flags);
ret = desc->chip->set_type(irq, type);
@@ -154,7 +154,7 @@ int set_irq_data(unsigned int irq, void
return -EINVAL;
}

- desc = irq_desc + irq;
+ desc = get_irq_desc(irq);
spin_lock_irqsave(&desc->lock, flags);
desc->handler_data = data;
spin_unlock_irqrestore(&desc->lock, flags);
@@ -179,7 +179,7 @@ int set_irq_msi(unsigned int irq, struct
"Trying to install msi data for IRQ%d\n", irq);
return -EINVAL;
}
- desc = irq_desc + irq;
+ desc = get_irq_desc(irq);
spin_lock_irqsave(&desc->lock, flags);
desc->msi_desc = entry;
if (entry)
@@ -197,9 +197,10 @@ int set_irq_msi(unsigned int irq, struct
*/
int set_irq_chip_data(unsigned int irq, void *data)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc;
unsigned long flags;

+ desc = get_irq_desc(irq);
if (irq >= nr_irqs || !desc->chip) {
printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq);
return -EINVAL;
@@ -218,8 +219,9 @@ EXPORT_SYMBOL(set_irq_chip_data);
*/
static void default_enable(unsigned int irq)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc;

+ desc = get_irq_desc(irq);
desc->chip->unmask(irq);
desc->status &= ~IRQ_MASKED;
}
@@ -236,7 +238,10 @@ static void default_disable(unsigned int
*/
static unsigned int default_startup(unsigned int irq)
{
- irq_desc[irq].chip->enable(irq);
+ struct irq_desc *desc;
+
+ desc = get_irq_desc(irq);
+ desc->chip->enable(irq);

return 0;
}
@@ -246,8 +251,9 @@ static unsigned int default_startup(unsi
*/
static void default_shutdown(unsigned int irq)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc;

+ desc = get_irq_desc(irq);
desc->chip->mask(irq);
desc->status |= IRQ_MASKED;
}
@@ -550,7 +556,7 @@ __set_irq_handler(unsigned int irq, irq_
return;
}

- desc = irq_desc + irq;
+ desc = get_irq_desc(irq);

if (!handle)
handle = handle_bad_irq;
@@ -615,7 +621,7 @@ void __init set_irq_noprobe(unsigned int
return;
}

- desc = irq_desc + irq;
+ desc = get_irq_desc(irq);

spin_lock_irqsave(&desc->lock, flags);
desc->status |= IRQ_NOPROBE;
@@ -633,7 +639,7 @@ void __init set_irq_probe(unsigned int i
return;
}

- desc = irq_desc + irq;
+ desc = get_irq_desc(irq);

spin_lock_irqsave(&desc->lock, flags);
desc->status &= ~IRQ_NOPROBE;
Index: linux-2.6/kernel/irq/handle.c
===================================================================
--- linux-2.6.orig/kernel/irq/handle.c
+++ linux-2.6/kernel/irq/handle.c
@@ -18,6 +18,14 @@

#include "internals.h"

+#ifdef CONFIG_TRACE_IRQFLAGS
+
+/*
+ * lockdep: we want to handle all irq_desc locks as a single lock-class:
+ */
+static struct lock_class_key irq_desc_lock_class;
+#endif
+
/**
* handle_bad_irq - handle spurious and unhandled irqs
* @irq: the interrupt number
@@ -51,6 +59,7 @@ int nr_irqs = NR_IRQS;

#ifdef CONFIG_HAVE_DYN_ARRAY
static struct irq_desc irq_desc_init __initdata = {
+ .irq = -1U,
.status = IRQ_DISABLED,
.chip = &no_irq_chip,
.handle_irq = handle_bad_irq,
@@ -61,6 +70,26 @@ static struct irq_desc irq_desc_init __i
#endif
};

+
+static void init_one_irq_desc(struct irq_desc *desc)
+{
+ memcpy(desc, &irq_desc_init, sizeof(struct irq_desc));
+#ifdef CONFIG_TRACE_IRQFLAGS
+ lockdep_set_class(&desc->lock, &irq_desc_lock_class);
+#endif
+}
+
+static int nr_irq_desc = 32;
+
+static int __init parse_nr_irq_desc(char *arg)
+{
+ if (arg)
+ nr_irq_desc = simple_strtoul(arg, NULL, 0);
+ return 0;
+}
+
+early_param("nr_irq_desc", parse_nr_irq_desc);
+
static void __init init_work(void *data)
{
struct dyn_array *da = data;
@@ -70,11 +99,65 @@ static void __init init_work(void *data)
desc = *da->name;

for (i = 0; i < *da->nr; i++)
- memcpy(&desc[i], &irq_desc_init, sizeof(struct irq_desc));
+ init_one_irq_desc(&desc[i]);
+
+ for (i = 1; i < *da->nr; i++)
+ desc[i-1].next = &desc[i];
}

-struct irq_desc *irq_desc;
-DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irqs,
PAGE_SIZE, init_work);
+static struct irq_desc *irq_desc;
+DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irq_desc,
PAGE_SIZE, init_work);
+
+extern int after_bootmem;
+extern void *__alloc_bootmem_nopanic(unsigned long size,
+ unsigned long align,
+ unsigned long goal);
+struct irq_desc *get_irq_desc(unsigned int irq)
+{
+ struct irq_desc *desc, *desc_pri;
+ int i;
+ int count = 0;
+
+ BUG_ON(irq == -1U);
+
+ desc_pri = desc = &irq_desc[0];
+ while (desc) {
+ if (desc->irq == irq)
+ return desc;
+
+ if (desc->irq == -1U) {
+ desc->irq = irq;
+ return desc;
+ }
+ desc_pri = desc;
+ desc = desc->next;
+ count++;
+ }
+
+ /*
+ * we run out of pre-allocate ones, allocate more
+ */
+ printk(KERN_DEBUG "try to get more irq_desc %d\n", nr_irq_desc);
+
+ if (after_bootmem)
+ desc = kzalloc(sizeof(struct irq_desc)*nr_irq_desc, GFP_ATOMIC);
+ else
+ desc = __alloc_bootmem_nopanic(sizeof(struct
irq_desc)*nr_irq_desc, PAGE_SIZE, 0);
+
+ if (!desc)
+ panic("please boot with nr_irq_desc= %d\n", count * 2);
+
+ for (i = 0; i < nr_irq_desc; i++)
+ init_one_irq_desc(&desc[i]);
+
+ for (i = 1; i < nr_irq_desc; i++)
+ desc[i-1].next = &desc[i];
+
+ desc->irq = irq;
+ desc_pri->next = desc;
+
+ return desc;
+}

#else

@@ -90,6 +173,15 @@ struct irq_desc irq_desc[NR_IRQS] __cach
#endif
}
};
+
+struct irq_desc *get_irq_desc(unsigned int irq)
+{
+ if (irq < nr_irqs)
+ return &irq_desc[irq];
+
+ return NULL;
+}
+
#endif

/*
@@ -98,7 +190,10 @@ struct irq_desc irq_desc[NR_IRQS] __cach
*/
static void ack_bad(unsigned int irq)
{
- print_irq_desc(irq, irq_desc + irq);
+ struct irq_desc *desc;
+
+ desc = get_irq_desc(irq);
+ print_irq_desc(irq, desc);
ack_bad_irq(irq);
}

@@ -195,7 +290,7 @@ irqreturn_t handle_IRQ_event(unsigned in
*/
unsigned int __do_IRQ(unsigned int irq)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);
struct irqaction *action;
unsigned int status;

@@ -286,19 +381,16 @@ out:
}
#endif

-#ifdef CONFIG_TRACE_IRQFLAGS
-
-/*
- * lockdep: we want to handle all irq_desc locks as a single lock-class:
- */
-static struct lock_class_key irq_desc_lock_class;

+#ifdef CONFIG_TRACE_IRQFLAGS
void early_init_irq_lock_class(void)
{
+#ifndef CONFIG_HAVE_DYN_ARRAY
int i;

for (i = 0; i < nr_irqs; i++)
lockdep_set_class(&irq_desc[i].lock, &irq_desc_lock_class);
+#endif
}
-
#endif
+
Index: linux-2.6/kernel/irq/manage.c
===================================================================
--- linux-2.6.orig/kernel/irq/manage.c
+++ linux-2.6/kernel/irq/manage.c
@@ -31,7 +31,7 @@ cpumask_t irq_default_affinity = CPU_MAS
*/
void synchronize_irq(unsigned int irq)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);
unsigned int status;

if (irq >= nr_irqs)
@@ -64,7 +64,7 @@ EXPORT_SYMBOL(synchronize_irq);
*/
int irq_can_set_affinity(unsigned int irq)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);

if (CHECK_IRQ_PER_CPU(desc->status) || !desc->chip ||
!desc->chip->set_affinity)
@@ -81,7 +81,7 @@ int irq_can_set_affinity(unsigned int ir
*/
int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);

if (!desc->chip->set_affinity)
return -EINVAL;
@@ -111,14 +111,16 @@ int irq_set_affinity(unsigned int irq, c
int irq_select_affinity(unsigned int irq)
{
cpumask_t mask;
+ struct irq_desc *desc;

if (!irq_can_set_affinity(irq))
return 0;

cpus_and(mask, cpu_online_map, irq_default_affinity);

- irq_desc[irq].affinity = mask;
- irq_desc[irq].chip->set_affinity(irq, mask);
+ desc = get_irq_desc(irq);
+ desc->affinity = mask;
+ desc->chip->set_affinity(irq, mask);

set_balance_irq_affinity(irq, mask);
return 0;
@@ -140,7 +142,7 @@ int irq_select_affinity(unsigned int irq
*/
void disable_irq_nosync(unsigned int irq)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);
unsigned long flags;

if (irq >= nr_irqs)
@@ -169,7 +171,7 @@ EXPORT_SYMBOL(disable_irq_nosync);
*/
void disable_irq(unsigned int irq)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);

if (irq >= nr_irqs)
return;
@@ -211,7 +213,7 @@ static void __enable_irq(struct irq_desc
*/
void enable_irq(unsigned int irq)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);
unsigned long flags;

if (irq >= nr_irqs)
@@ -225,7 +227,7 @@ EXPORT_SYMBOL(enable_irq);

int set_irq_wake_real(unsigned int irq, unsigned int on)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);
int ret = -ENXIO;

if (desc->chip->set_wake)
@@ -248,7 +250,7 @@ int set_irq_wake_real(unsigned int irq,
*/
int set_irq_wake(unsigned int irq, unsigned int on)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);
unsigned long flags;
int ret = 0;

@@ -288,12 +290,13 @@ EXPORT_SYMBOL(set_irq_wake);
*/
int can_request_irq(unsigned int irq, unsigned long irqflags)
{
+ struct irq_desc *desc = get_irq_desc(irq);
struct irqaction *action;

- if (irq >= nr_irqs || irq_desc[irq].status & IRQ_NOREQUEST)
+ if (irq >= nr_irqs || desc->status & IRQ_NOREQUEST)
return 0;

- action = irq_desc[irq].action;
+ action =desc->action;
if (action)
if (irqflags & action->flags & IRQF_SHARED)
action = NULL;
@@ -342,7 +345,7 @@ static int __irq_set_trigger(struct irq_
*/
int setup_irq(unsigned int irq, struct irqaction *new)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);
struct irqaction *old, **p;
const char *old_name = NULL;
unsigned long flags;
@@ -506,7 +509,7 @@ void free_irq(unsigned int irq, void *de
if (irq >= nr_irqs)
return;

- desc = irq_desc + irq;
+ desc = get_irq_desc(irq);
spin_lock_irqsave(&desc->lock, flags);
p = &desc->action;
for (;;) {
@@ -602,6 +605,7 @@ int request_irq(unsigned int irq, irq_ha
{
struct irqaction *action;
int retval;
+ struct irq_desc *desc;

#ifdef CONFIG_LOCKDEP
/*
@@ -619,7 +623,8 @@ int request_irq(unsigned int irq, irq_ha
return -EINVAL;
if (irq >= nr_irqs)
return -EINVAL;
- if (irq_desc[irq].status & IRQ_NOREQUEST)
+ desc = get_irq_desc(irq);
+ if (desc->status & IRQ_NOREQUEST)
return -EINVAL;
if (!handler)
return -EINVAL;
Index: linux-2.6/kernel/irq/migration.c
===================================================================
--- linux-2.6.orig/kernel/irq/migration.c
+++ linux-2.6/kernel/irq/migration.c
@@ -3,18 +3,18 @@

void set_pending_irq(unsigned int irq, cpumask_t mask)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);
unsigned long flags;

spin_lock_irqsave(&desc->lock, flags);
desc->status |= IRQ_MOVE_PENDING;
- irq_desc[irq].pending_mask = mask;
+ desc->pending_mask = mask;
spin_unlock_irqrestore(&desc->lock, flags);
}

void move_masked_irq(int irq)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);
cpumask_t tmp;

if (likely(!(desc->status & IRQ_MOVE_PENDING)))
@@ -30,7 +30,7 @@ void move_masked_irq(int irq)

desc->status &= ~IRQ_MOVE_PENDING;

- if (unlikely(cpus_empty(irq_desc[irq].pending_mask)))
+ if (unlikely(cpus_empty(desc->pending_mask)))
return;

if (!desc->chip->set_affinity)
@@ -38,7 +38,7 @@ void move_masked_irq(int irq)

assert_spin_locked(&desc->lock);

- cpus_and(tmp, irq_desc[irq].pending_mask, cpu_online_map);
+ cpus_and(tmp, desc->pending_mask, cpu_online_map);

/*
* If there was a valid mask to work with, please
@@ -55,12 +55,12 @@ void move_masked_irq(int irq)
if (likely(!cpus_empty(tmp))) {
desc->chip->set_affinity(irq,tmp);
}
- cpus_clear(irq_desc[irq].pending_mask);
+ cpus_clear(desc->pending_mask);
}

void move_native_irq(int irq)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);

if (likely(!(desc->status & IRQ_MOVE_PENDING)))
return;
Index: linux-2.6/kernel/irq/proc.c
===================================================================
--- linux-2.6.orig/kernel/irq/proc.c
+++ linux-2.6/kernel/irq/proc.c
@@ -19,7 +19,7 @@ static struct proc_dir_entry *root_irq_d
static int irq_affinity_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
- struct irq_desc *desc = irq_desc + (long)data;
+ struct irq_desc *desc = get_irq_desc((long)data);
cpumask_t *mask = &desc->affinity;
int len;

@@ -45,8 +45,9 @@ static int irq_affinity_write_proc(struc
{
unsigned int irq = (int)(long)data, full_count = count, err;
cpumask_t new_value;
+ struct irq_desc *desc = get_irq_desc(irq);

- if (!irq_desc[irq].chip->set_affinity || no_irq_affinity ||
+ if (!desc->chip->set_affinity || no_irq_affinity ||
irq_balancing_disabled(irq))
return -EIO;

@@ -112,20 +113,20 @@ static int default_affinity_write(struct
static int irq_spurious_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
- struct irq_desc *d = &irq_desc[(long) data];
+ struct irq_desc *desc = get_irq_desc((long) data);
return sprintf(page, "count %u\n"
"unhandled %u\n"
"last_unhandled %u ms\n",
- d->irq_count,
- d->irqs_unhandled,
- jiffies_to_msecs(d->last_unhandled));
+ desc->irq_count,
+ desc->irqs_unhandled,
+ jiffies_to_msecs(desc->last_unhandled));
}

#define MAX_NAMELEN 128

static int name_unique(unsigned int irq, struct irqaction *new_action)
{
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = get_irq_desc(irq);
struct irqaction *action;
unsigned long flags;
int ret = 1;
@@ -145,8 +146,9 @@ static int name_unique(unsigned int irq,
void register_handler_proc(unsigned int irq, struct irqaction *action)
{
char name [MAX_NAMELEN];
+ struct irq_desc *desc = get_irq_desc(irq);

- if (!irq_desc[irq].dir || action->dir || !action->name ||
+ if (!desc->dir || action->dir || !action->name ||
!name_unique(irq, action))
return;

@@ -154,7 +156,7 @@ void register_handler_proc(unsigned int
snprintf(name, MAX_NAMELEN, "%s", action->name);

/* create /proc/irq/1234/handler/ */
- action->dir = proc_mkdir(name, irq_desc[irq].dir);
+ action->dir = proc_mkdir(name, desc->dir);
}

#undef MAX_NAMELEN
@@ -165,22 +167,22 @@ void register_irq_proc(unsigned int irq)
{
char name [MAX_NAMELEN];
struct proc_dir_entry *entry;
+ struct irq_desc *desc = get_irq_desc(irq);

if (!root_irq_dir ||
- (irq_desc[irq].chip == &no_irq_chip) ||
- irq_desc[irq].dir)
+ (desc->chip == &no_irq_chip) || desc->dir)
return;

memset(name, 0, MAX_NAMELEN);
sprintf(name, "%d", irq);

/* create /proc/irq/1234 */
- irq_desc[irq].dir = proc_mkdir(name, root_irq_dir);
+ desc->dir = proc_mkdir(name, root_irq_dir);

#ifdef CONFIG_SMP
{
/* create /proc/irq/<irq>/smp_affinity */
- entry = create_proc_entry("smp_affinity", 0600,
irq_desc[irq].dir);
+ entry = create_proc_entry("smp_affinity", 0600, desc->dir);

if (entry) {
entry->data = (void *)(long)irq;
@@ -190,7 +192,7 @@ void register_irq_proc(unsigned int irq)
}
#endif

- entry = create_proc_entry("spurious", 0444, irq_desc[irq].dir);
+ entry = create_proc_entry("spurious", 0444, desc->dir);
if (entry) {
entry->data = (void *)(long)irq;
entry->read_proc = irq_spurious_read;
@@ -201,8 +203,10 @@ void register_irq_proc(unsigned int irq)

void unregister_handler_proc(unsigned int irq, struct irqaction *action)
{
- if (action->dir)
- remove_proc_entry(action->dir->name, irq_desc[irq].dir);
+ if (action->dir) {
+ struct irq_desc *desc = get_irq_desc(irq);
+ remove_proc_entry(action->dir->name, desc->dir);
+ }
}

void register_default_affinity_proc(void)
Index: linux-2.6/kernel/irq/resend.c
===================================================================
--- linux-2.6.orig/kernel/irq/resend.c
+++ linux-2.6/kernel/irq/resend.c
@@ -36,7 +36,7 @@ static void resend_irqs(unsigned long ar
while (!bitmap_empty(irqs_resend, nr_irqs)) {
irq = find_first_bit(irqs_resend, nr_irqs);
clear_bit(irq, irqs_resend);
- desc = irq_desc + irq;
+ desc = get_irq_desc(irq);
local_irq_disable();
desc->handle_irq(irq, desc);
local_irq_enable();
Index: linux-2.6/kernel/irq/spurious.c
===================================================================
--- linux-2.6.orig/kernel/irq/spurious.c
+++ linux-2.6/kernel/irq/spurious.c
@@ -92,11 +92,12 @@ static int misrouted_irq(int irq)
int ok = 0;

for (i = 1; i < nr_irqs; i++) {
- struct irq_desc *desc = irq_desc + i;
+ struct irq_desc *desc;

if (i == irq) /* Already tried */
continue;

+ desc = get_irq_desc(i);
if (try_one_irq(i, desc))
ok = 1;
}
@@ -108,7 +109,7 @@ static void poll_spurious_irqs(unsigned
{
int i;
for (i = 1; i < nr_irqs; i++) {
- struct irq_desc *desc = irq_desc + i;
+ struct irq_desc *desc = get_irq_desc(i);
unsigned int status;

/* Racy but it doesn't matter */

2008-08-04 14:32:39

by Mike Travis

[permalink] [raw]
Subject: Re: [PATCH 00/25] dyn_array and nr_irqs support v3

Eric W. Biederman wrote:
> "Yinghai Lu" <[email protected]> writes:
>
>> On Sat, Aug 2, 2008 at 10:51 PM, Eric W. Biederman
>> <[email protected]> wrote:
>>> It appears that quite a few of the places you have changed are testing
>>> to see if an irq is valid. The idiomatic way to perform that test in
>>> the kernel is:
>>>
>>> if (irq)
>> is uninitialized irq to be -1 or 0?
>
> 0. There is a long history behind it, but by decree of Linus and to conform
> with reasonable intuition 0 is not a valid irq except in certain arch specific
> corner cases.
>
>>> With no test to see if you are >= NR_IRQS.
>>>
>>> I expect that is the change we want in the drivers that are performing such a
>> silly
>>> extra check.
>> is_irq_valid(irq_no) ?
>>
>> wait to see your new patchset about dyn irq_cfg and irq_desc
>
> I haven't promised one, at least not lately. I went down a couple of
> blind alleys and figured out what needed to be accomplished and then
> ran out of steam about a year and a half 2 years ago, and I haven't
> been able to get back to it.
>
> Eric

I've put this on my queue of "items to examine more closely". Priority-wise,
it's not quite at the front yet.

Thanks,
Mike

2008-08-04 14:38:38

by Alan

[permalink] [raw]
Subject: Re: [PATCH 21/25] serial: change remove NR_IRQS in 8250.c v2

> Would allow us to use the generic hash table code.

Nice.. that makes the code a bit longer in source form but much clearer
and sharing common design.

> Looks like we can also tweak serial_do_unlink to free irq_info when
> the list goes empty, so we don't have a leak if the driver is ever
> unloaded.

Like this (again not yet tested)

8250: Remove NR_IRQ usage

From: Alan Cox <[email protected]>


---

drivers/serial/68328serial.c | 11 +------
drivers/serial/8250.c | 68 +++++++++++++++++++++++++++++++++---------
2 files changed, 56 insertions(+), 23 deletions(-)


diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 381b12a..277b78d 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -66,7 +66,6 @@
#endif

static struct m68k_serial m68k_soft[NR_PORTS];
-struct m68k_serial *IRQ_ports[NR_IRQS];

static unsigned int uart_irqs[NR_PORTS] = UART_IRQ_DEFNS;

@@ -375,15 +374,11 @@ clear_and_return:
*/
irqreturn_t rs_interrupt(int irq, void *dev_id)
{
- struct m68k_serial * info;
+ struct m68k_serial * info = dev_id;
m68328_uart *uart;
unsigned short rx;
unsigned short tx;

- info = IRQ_ports[irq];
- if(!info)
- return IRQ_NONE;
-
uart = &uart_addr[info->line];
rx = uart->urx.w;

@@ -1383,8 +1378,6 @@ rs68328_init(void)
info->port, info->irq);
printk(" is a builtin MC68328 UART\n");

- IRQ_ports[info->irq] = info; /* waste of space */
-
#ifdef CONFIG_M68VZ328
if (i > 0 )
PJSEL &= 0xCF; /* PSW enable second port output */
@@ -1393,7 +1386,7 @@ rs68328_init(void)
if (request_irq(uart_irqs[i],
rs_interrupt,
IRQF_DISABLED,
- "M68328_UART", NULL))
+ "M68328_UART", info))
panic("Unable to attach 68328 serial interrupt\n");
}
local_irq_restore(flags);
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 342e12f..2245cd4 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -145,11 +145,15 @@ struct uart_8250_port {
};

struct irq_info {
- spinlock_t lock;
+ struct hlist_node node;
+ int irq;
+ spinlock_t lock; /* Protects list not the hash */
struct list_head *head;
};

-static struct irq_info irq_lists[NR_IRQS];
+#define NR_IRQ_HASH 32 /* Can be adjusted later */
+static struct hlist_head irq_lists[NR_IRQ_HASH];
+static DEFINE_MUTEX(hash_mutex); /* Used to walk the hash */

/*
* Here we define the default xmit fifo size used for each type of UART.
@@ -1541,9 +1545,32 @@ static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)

static int serial_link_irq_chain(struct uart_8250_port *up)
{
- struct irq_info *i = irq_lists + up->port.irq;
+ struct hlist_head *h;
+ struct hlist_node *n;
+ struct irq_info *i;
int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;

+ mutex_lock(&hash_mutex);
+
+ h = &irq_lists[up->port.irq % NR_IRQ_HASH];
+
+ hlist_for_each(n, h) {
+ i = hlist_entry(n, struct irq_info, node);
+ if (i->irq == up->port.irq)
+ break;
+ }
+
+ if (n == NULL) {
+ i = kzalloc(sizeof(struct irq_info), GFP_KERNEL);
+ if (i == NULL) {
+ mutex_unlock(&hash_mutex);
+ return -ENOMEM;
+ }
+ spin_lock_init(&i->lock);
+ hlist_add_head(&i->node, h);
+ }
+ mutex_unlock(&hash_mutex);
+
spin_lock_irq(&i->lock);

if (i->head) {
@@ -1567,14 +1594,30 @@ static int serial_link_irq_chain(struct uart_8250_port *up)

static void serial_unlink_irq_chain(struct uart_8250_port *up)
{
- struct irq_info *i = irq_lists + up->port.irq;
+ struct irq_info *i;
+ struct hlist_node *n;
+ struct hlist_head *h;
+
+ mutex_lock(&hash_mutex);

+ h = &irq_lists[up->port.irq % NR_IRQ_HASH];
+
+ hlist_for_each(n, h) {
+ i = hlist_entry(n, struct irq_info, node);
+ if (i->irq == up->port.irq)
+ break;
+ }
+ BUG_ON(n == NULL);
BUG_ON(i->head == NULL);

- if (list_empty(i->head))
+ if (list_empty(i->head)) {
free_irq(up->port.irq, i);
-
- serial_do_unlink(i, up);
+ serial_do_unlink(i, up);
+ hlist_del(&i->node);
+ kfree(i);
+ } else
+ serial_do_unlink(i, up);
+ mutex_unlock(&hash_mutex);
}

/* Base timer interval for polling */
@@ -2942,7 +2985,7 @@ EXPORT_SYMBOL(serial8250_unregister_port);

static int __init serial8250_init(void)
{
- int ret, i;
+ int ret;

if (nr_uarts > UART_NR)
nr_uarts = UART_NR;
@@ -2951,9 +2994,6 @@ 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);
-
ret = uart_register_driver(&serial8250_reg);
if (ret)
goto out;
@@ -2976,11 +3016,11 @@ static int __init serial8250_init(void)
goto out;

platform_device_del(serial8250_isa_devs);
- put_dev:
+put_dev:
platform_device_put(serial8250_isa_devs);
- unreg_uart_drv:
+unreg_uart_drv:
uart_unregister_driver(&serial8250_reg);
- out:
+out:
return ret;
}

2008-08-04 18:19:02

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 21/25] serial: change remove NR_IRQS in 8250.c v2

On Mon, Aug 4, 2008 at 7:17 AM, Alan Cox <[email protected]> wrote:
>> Would allow us to use the generic hash table code.
>
> Nice.. that makes the code a bit longer in source form but much clearer
> and sharing common design.
>
>> Looks like we can also tweak serial_do_unlink to free irq_info when
>> the list goes empty, so we don't have a leak if the driver is ever
>> unloaded.
>
> Like this (again not yet tested)
>
> 8250: Remove NR_IRQ usage
>
> From: Alan Cox <[email protected]>
>
>
> ---
>
> drivers/serial/68328serial.c | 11 +------
> drivers/serial/8250.c | 68 +++++++++++++++++++++++++++++++++---------
> 2 files changed, 56 insertions(+), 23 deletions(-)
>

thanks. will test it.

YH

2008-08-04 18:53:47

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [PATCH 21/25] serial: change remove NR_IRQS in 8250.c v2

Alan Cox <[email protected]> writes:

>> Looks like we can also tweak serial_do_unlink to free irq_info when
>> the list goes empty, so we don't have a leak if the driver is ever
>> unloaded.
>
> Like this (again not yet tested)
>
> 8250: Remove NR_IRQ usage
>
> From: Alan Cox <[email protected]>

I think we've just about got it.

> /*
> * Here we define the default xmit fifo size used for each type of UART.
> @@ -1541,9 +1545,32 @@ static void serial_do_unlink(struct irq_info *i, struct
> uart_8250_port *up)
>
> static int serial_link_irq_chain(struct uart_8250_port *up)
> {
> - struct irq_info *i = irq_lists + up->port.irq;
> + struct hlist_head *h;
> + struct hlist_node *n;
> + struct irq_info *i;
> int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
>
> + mutex_lock(&hash_mutex);
> +
> + h = &irq_lists[up->port.irq % NR_IRQ_HASH];
> +
> + hlist_for_each(n, h) {
> + i = hlist_entry(n, struct irq_info, node);
> + if (i->irq == up->port.irq)
> + break;
> + }
> +
> + if (n == NULL) {
> + i = kzalloc(sizeof(struct irq_info), GFP_KERNEL);
> + if (i == NULL) {
> + mutex_unlock(&hash_mutex);
> + return -ENOMEM;
> + }
> + spin_lock_init(&i->lock);
> + hlist_add_head(&i->node, h);
> + }
> + mutex_unlock(&hash_mutex);
> +
> spin_lock_irq(&i->lock);
>
> if (i->head) {

Note there is also an error path that calls serial_do_unlink in serial_link_irq_chain.
That we might want to free the entry in. Do we want move hash table entry freeing
into serial_do_unlink or duplicate it here?

Eric

2008-08-05 23:16:14

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 00/25] dyn_array and nr_irqs support v3

On Tue, Aug 5, 2008 at 4:01 PM, H. Peter Anvin <[email protected]> wrote:
> Yinghai Lu wrote:
>>
>> Peter, Andrew,
>>
>> Please check dyn_array support for x86
>> v3: split changing to nr_irqs to small patches
>> fix checkpatch error
>> reorder the patch sequence to make dyn_array support go at first
>> so could use that with arrays other than NR_IRQS
>>
>
> The real issue is that I think Eric is right: the dyn_array is an
> interesting data structure, but it's the wrong solution for the problem. A
> static array would have to be ridiculously large given the potential number
> of interrupt sources.
>

i am working on dyn_array + condense irq_desc/irq_cfg.

it will use dyn_array to allocate 32 entry for irq_desc/irq_cfg, and
will use get_irq_desc via list to distribute it. later if need more,
will allocate more 32 entries....

so will send out v4.

YH

2008-08-05 23:25:16

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH 00/25] dyn_array and nr_irqs support v3

Yinghai Lu wrote:
> Peter, Andrew,
>
> Please check dyn_array support for x86
> v3: split changing to nr_irqs to small patches
> fix checkpatch error
> reorder the patch sequence to make dyn_array support go at first
> so could use that with arrays other than NR_IRQS
>

The real issue is that I think Eric is right: the dyn_array is an
interesting data structure, but it's the wrong solution for the problem.
A static array would have to be ridiculously large given the potential
number of interrupt sources.

-hpa

2008-08-05 23:27:08

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH 00/25] dyn_array and nr_irqs support v3

Yinghai Lu wrote:
>
> i am working on dyn_array + condense irq_desc/irq_cfg.
>
> it will use dyn_array to allocate 32 entry for irq_desc/irq_cfg, and
> will use get_irq_desc via list to distribute it. later if need more,
> will allocate more 32 entries....
>
> so will send out v4.
>

My understanding of dyn_array is that it only works at init time. How
does that work when you hotplug MSI-X devices?

-hpa

2008-08-05 23:54:04

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 00/25] dyn_array and nr_irqs support v3

On Tue, Aug 5, 2008 at 4:26 PM, H. Peter Anvin <[email protected]> wrote:
> Yinghai Lu wrote:
>>
>> i am working on dyn_array + condense irq_desc/irq_cfg.
>>
>> it will use dyn_array to allocate 32 entry for irq_desc/irq_cfg, and
>> will use get_irq_desc via list to distribute it. later if need more,
>> will allocate more 32 entries....
>>
>> so will send out v4.
>>
>
> My understanding of dyn_array is that it only works at init time.
> How does that work when you hotplug MSI-X devices?

actually create irq_desc like Eric suggest, but allocate 32 entry one
time, and use it one by one. share some init work function bewteen
init stage and later.

YH

2008-08-06 13:52:29

by Alan

[permalink] [raw]
Subject: [PATCH] serial: Remove NR_IRQS usage

Works on my test box with a quick test.

8250: Remove NR_IRQ usage

From: Alan Cox <[email protected]>

Signed-off-by: Alan Cox <[email protected]>

---

drivers/serial/68328serial.c | 11 +-----
drivers/serial/8250.c | 73 +++++++++++++++++++++++++++++++++---------
2 files changed, 60 insertions(+), 24 deletions(-)


diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 381b12a..277b78d 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -66,7 +66,6 @@
#endif

static struct m68k_serial m68k_soft[NR_PORTS];
-struct m68k_serial *IRQ_ports[NR_IRQS];

static unsigned int uart_irqs[NR_PORTS] = UART_IRQ_DEFNS;

@@ -375,15 +374,11 @@ clear_and_return:
*/
irqreturn_t rs_interrupt(int irq, void *dev_id)
{
- struct m68k_serial * info;
+ struct m68k_serial * info = dev_id;
m68328_uart *uart;
unsigned short rx;
unsigned short tx;

- info = IRQ_ports[irq];
- if(!info)
- return IRQ_NONE;
-
uart = &uart_addr[info->line];
rx = uart->urx.w;

@@ -1383,8 +1378,6 @@ rs68328_init(void)
info->port, info->irq);
printk(" is a builtin MC68328 UART\n");

- IRQ_ports[info->irq] = info; /* waste of space */
-
#ifdef CONFIG_M68VZ328
if (i > 0 )
PJSEL &= 0xCF; /* PSW enable second port output */
@@ -1393,7 +1386,7 @@ rs68328_init(void)
if (request_irq(uart_irqs[i],
rs_interrupt,
IRQF_DISABLED,
- "M68328_UART", NULL))
+ "M68328_UART", info))
panic("Unable to attach 68328 serial interrupt\n");
}
local_irq_restore(flags);
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 342e12f..6e9de80 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -145,11 +145,15 @@ struct uart_8250_port {
};

struct irq_info {
- spinlock_t lock;
+ struct hlist_node node;
+ int irq;
+ spinlock_t lock; /* Protects list not the hash */
struct list_head *head;
};

-static struct irq_info irq_lists[NR_IRQS];
+#define NR_IRQ_HASH 32 /* Can be adjusted later */
+static struct hlist_head irq_lists[NR_IRQ_HASH];
+static DEFINE_MUTEX(hash_mutex); /* Used to walk the hash */

/*
* Here we define the default xmit fifo size used for each type of UART.
@@ -1535,15 +1539,43 @@ static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
BUG_ON(i->head != &up->list);
i->head = NULL;
}
-
spin_unlock_irq(&i->lock);
+ /* List empty so throw away the hash node */
+ if (i->head == NULL) {
+ hlist_del(&i->node);
+ kfree(i);
+ }
}

static int serial_link_irq_chain(struct uart_8250_port *up)
{
- struct irq_info *i = irq_lists + up->port.irq;
+ struct hlist_head *h;
+ struct hlist_node *n;
+ struct irq_info *i;
int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;

+ mutex_lock(&hash_mutex);
+
+ h = &irq_lists[up->port.irq % NR_IRQ_HASH];
+
+ hlist_for_each(n, h) {
+ i = hlist_entry(n, struct irq_info, node);
+ if (i->irq == up->port.irq)
+ break;
+ }
+
+ if (n == NULL) {
+ i = kzalloc(sizeof(struct irq_info), GFP_KERNEL);
+ if (i == NULL) {
+ mutex_unlock(&hash_mutex);
+ return -ENOMEM;
+ }
+ spin_lock_init(&i->lock);
+ i->irq = up->port.irq;
+ hlist_add_head(&i->node, h);
+ }
+ mutex_unlock(&hash_mutex);
+
spin_lock_irq(&i->lock);

if (i->head) {
@@ -1567,14 +1599,28 @@ static int serial_link_irq_chain(struct uart_8250_port *up)

static void serial_unlink_irq_chain(struct uart_8250_port *up)
{
- struct irq_info *i = irq_lists + up->port.irq;
+ struct irq_info *i;
+ struct hlist_node *n;
+ struct hlist_head *h;

- BUG_ON(i->head == NULL);
+ mutex_lock(&hash_mutex);

- if (list_empty(i->head))
+ h = &irq_lists[up->port.irq % NR_IRQ_HASH];
+
+ hlist_for_each(n, h) {
+ i = hlist_entry(n, struct irq_info, node);
+ if (i->irq == up->port.irq)
+ break;
+ }
+
+ BUG_ON(n == NULL);
+ BUG_ON(i->head == NULL);
+
+ if (list_empty(i->head)) {
free_irq(up->port.irq, i);
-
+ }
serial_do_unlink(i, up);
+ mutex_unlock(&hash_mutex);
}

/* Base timer interval for polling */
@@ -2942,7 +2988,7 @@ EXPORT_SYMBOL(serial8250_unregister_port);

static int __init serial8250_init(void)
{
- int ret, i;
+ int ret;

if (nr_uarts > UART_NR)
nr_uarts = UART_NR;
@@ -2951,9 +2997,6 @@ 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);
-
ret = uart_register_driver(&serial8250_reg);
if (ret)
goto out;
@@ -2976,11 +3019,11 @@ static int __init serial8250_init(void)
goto out;

platform_device_del(serial8250_isa_devs);
- put_dev:
+put_dev:
platform_device_put(serial8250_isa_devs);
- unreg_uart_drv:
+unreg_uart_drv:
uart_unregister_driver(&serial8250_reg);
- out:
+out:
return ret;
}

2008-08-06 16:13:29

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [PATCH] serial: Remove NR_IRQS usage

Alan Cox <[email protected]> writes:

> Works on my test box with a quick test.
>
> 8250: Remove NR_IRQ usage
>
> From: Alan Cox <[email protected]>
>
> Signed-off-by: Alan Cox <[email protected]>

This looks good.

Two final nits.

> -static struct irq_info irq_lists[NR_IRQS];
> +#define NR_IRQ_HASH 32 /* Can be adjusted later */
> +static struct hlist_head irq_lists[NR_IRQ_HASH];
> +static DEFINE_MUTEX(hash_mutex); /* Used to walk the hash */

> static int serial_link_irq_chain(struct uart_8250_port *up)
> {
> - struct irq_info *i = irq_lists + up->port.irq;
> + struct hlist_head *h;
> + struct hlist_node *n;
> + struct irq_info *i;
> int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
>
> + mutex_lock(&hash_mutex);
> +
....
> + mutex_unlock(&hash_mutex);

Could you move the unlock down to the end of serial_link_irq_chain?
So that it covers serial_do_unlink on the error cleanup path?
> +
> spin_lock_irq(&i->lock);
>
> if (i->head) {
> @@ -1567,14 +1599,28 @@ static int serial_link_irq_chain(struct uart_8250_port
> *up)
>
> static void serial_unlink_irq_chain(struct uart_8250_port *up)
...
> - if (list_empty(i->head))
...
> +
> + if (list_empty(i->head)) {
> free_irq(up->port.irq, i);
> -
> + }

Adding the braces here just appears to be extra noise.

> serial_do_unlink(i, up);
> + mutex_unlock(&hash_mutex);
> }

Eric