irq: remove not need bootmem code
PATCH 1/5 irq: remove not need bootmem code
mem_init is moved early already.
--- kernel/irq/handle.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-)
kernel/irq/handle.c +3 -11
@@ -19,7 +19,6 @@#include <linux/kernel_stat.h> #include <linux/rculist.h> #include <linux/hash.h> -#include <linux/bootmem.h> #include <trace/events/irq.h> #include "internals.h"
@@ -87,12 +86,8 @@ void __ref init_kstat_irqs(struct irq_de {void *ptr; -if (slab_is_available ()) - ptr =kzalloc_node (nr *sizeof (*desc->kstat_irqs), -GFP_ATOMIC , node); -else - ptr =alloc_bootmem_node (NODE_DATA (node), - nr *sizeof (*desc->kstat_irqs)); + ptr =kzalloc_node (nr *sizeof (*desc->kstat_irqs), +GFP_ATOMIC , node);/* * don't overwite if can not get new one
@@ -219,10 +214,7 @@ struct irq_desc * __ref irq_to_desc_alloif (desc) goto out_unlock; -if (slab_is_available ()) - desc =kzalloc_node (sizeof (*desc),GFP_ATOMIC , node); -else - desc =alloc_bootmem_node (NODE_DATA (node),sizeof (*desc)); + desc =kzalloc_node (sizeof (*desc),GFP_ATOMIC , node);printk (KERN_DEBUG " alloc irq_desc for %d on node %d\n" , irq, node);if (!desc) {
PATCH 2/5 radix: move radix init early
prepare to use it in early_irq_init()
--- init/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
init/main.c +1 -1
@@ -584,6 +584,7 @@ asmlinkage void __init start_kernel(voidlocal_irq_disable (); }rcu_init (); +radix_tree_init ();/* init some links before init_ISA_irqs() */ early_irq_init ();init_IRQ ();
@@ -659,7 +660,6 @@ asmlinkage void __init start_kernel(voidkey_init ();security_init ();vfs_caches_init (totalram_pages); -radix_tree_init ();signals_init ();/* rootfs populating might need page-writeback */ page_writeback_init ();
PATCH 3/5 sparseirq: change irq_desc_ptrs to static
In reply to Yinghai Luadd replace_irq_desc()
--- kernel/irq/handle.c | 8 +++++++- kernel/irq/internals.h | 6 +----- kernel/irq/numa_migrate.c | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-)
kernel/irq/handle.c +7 -1
@@ -127,7 +127,7 @@ static void init_one_irq_desc(int irq, s*/ DEFINE_RAW_SPINLOCK (sparse_irq_lock); -struct irq_desc **irq_desc_ptrs__read_mostly ; +static struct irq_desc **irq_desc_ptrs__read_mostly ; static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = { [0 ...NR_IRQS_LEGACY -1 ] = {
@@ -192,6 +192,12 @@ struct irq_desc *irq_to_desc(unsigned inreturn NULL ; } +void replace_irq_desc (unsigned int irq,struct irq_desc *desc) +{ +if (irq_desc_ptrs && irq < nr_irqs) + irq_desc_ptrs[irq] = desc; +} +struct irq_desc *__ref irq_to_desc_alloc_node (unsigned int irq,int node) {struct irq_desc *desc;
kernel/irq/internals.h +1 -5
@@ -21,11 +21,7 @@ extern void clear_kstat_irqs(struct irq_extern raw_spinlock_t sparse_irq_lock;#ifdef CONFIG_SPARSE_IRQ -/* irq_desc_ptrs allocated at boot time */ -extern struct irq_desc **irq_desc_ptrs; -#else -/* irq_desc_ptrs is a fixed size array */ -extern struct irq_desc *irq_desc_ptrs[NR_IRQS ]; +void replace_irq_desc (unsigned int irq,struct irq_desc *desc);#endif #ifdef CONFIG_PROC_FS
kernel/irq/numa_migrate.c +2 -2
@@ -70,7 +70,7 @@ static struct irq_desc *__real_move_irq_raw_spin_lock_irqsave (&sparse_irq_lock, flags);/* We have to check it to avoid races with another CPU */ - desc = irq_desc_ptrs[irq]; + desc =irq_to_desc (irq);if (desc && old_desc != desc) goto out_unlock;
@@ -90,7 +90,7 @@ static struct irq_desc *__real_move_irq_ goto out_unlock; } - irq_desc_ptrs[irq] = desc; +replace_irq_desc (irq, desc);raw_spin_unlock_irqrestore (&sparse_irq_lock, flags);/* free the old one */
PATCH 4/5 sparseirq: use radix_tree instead of ptrs array
In reply to Yinghai Luuse radix_tree irq_desc_tree instead of irq_desc_ptrs.
--- kernel/irq/handle.c | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-)
kernel/irq/handle.c +22 -25
@@ -19,6 +19,7 @@#include <linux/kernel_stat.h> #include <linux/rculist.h> #include <linux/hash.h> +#include <linux/radix-tree.h> #include <trace/events/irq.h> #include "internals.h"
@@ -127,7 +128,23 @@ static void init_one_irq_desc(int irq, s*/ DEFINE_RAW_SPINLOCK (sparse_irq_lock); -static struct irq_desc **irq_desc_ptrs__read_mostly ; +static RADIX_TREE(irq_desc_tree, GFP_KERNEL); + +static void set_irq_desc (unsigned int irq,struct irq_desc *desc) +{ +radix_tree_insert (&irq_desc_tree, irq, desc); +} + +struct irq_desc *irq_to_desc (unsigned int irq) +{ +return radix_tree_lookup (&irq_desc_tree, irq); +} + +void replace_irq_desc (unsigned int irq,struct irq_desc *desc) +{ +radix_tree_delete (&irq_desc_tree, irq); +radix_tree_insert (&irq_desc_tree, irq, desc); +} static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = { [0 ...NR_IRQS_LEGACY -1 ] = {
@@ -159,9 +176,6 @@ int __init early_irq_init(void) legacy_count =ARRAY_SIZE (irq_desc_legacy); node = first_online_node; -/* allocate irq_desc_ptrs array based on nr_irqs */ - irq_desc_ptrs =kcalloc (nr_irqs,sizeof (void *),GFP_NOWAIT ); -/* allocate based on nr_cpu_ids */ kstat_irqs_legacy =kzalloc_node (NR_IRQS_LEGACY * nr_cpu_ids *sizeof (int ),GFP_NOWAIT , node);
@@ -175,29 +189,12 @@ int __init early_irq_init(void)lockdep_set_class (&desc[i].lock, &irq_desc_lock_class);alloc_desc_masks (&desc[i], node, true);init_desc_masks (&desc[i]); - irq_desc_ptrs[i] = desc + i; +set_irq_desc (i, &desc[i]); } -for (i = legacy_count; i < nr_irqs; i++) - irq_desc_ptrs[i] =NULL ; -return arch_early_irq_init (); } -struct irq_desc *irq_to_desc (unsigned int irq) -{ -if (irq_desc_ptrs && irq < nr_irqs) -return irq_desc_ptrs[irq]; - -return NULL ; -} - -void replace_irq_desc (unsigned int irq,struct irq_desc *desc) -{ -if (irq_desc_ptrs && irq < nr_irqs) - irq_desc_ptrs[irq] = desc; -} -struct irq_desc *__ref irq_to_desc_alloc_node (unsigned int irq,int node) {struct irq_desc *desc;
@@ -209,14 +206,14 @@ struct irq_desc * __ref irq_to_desc_alloreturn NULL ; } - desc = irq_desc_ptrs[irq]; + desc =irq_to_desc (irq);if (desc)return desc;raw_spin_lock_irqsave (&sparse_irq_lock, flags);/* We have to check it to avoid races with another CPU */ - desc = irq_desc_ptrs[irq]; + desc =irq_to_desc (irq);if (desc) goto out_unlock;
@@ -229,7 +226,7 @@ struct irq_desc * __ref irq_to_desc_allo }init_one_irq_desc (irq, desc, node); - irq_desc_ptrs[irq] = desc; +set_irq_desc (irq, desc); out_unlock:raw_spin_unlock_irqrestore (&sparse_irq_lock, flags);
Re: [PATCH 4/5] sparseirq: use radix_tree instead of ptrs array
Quoted 33 lines · Yinghai Lu
use
radix_treeirq_desc_treeinstead ofirq_desc_ptrs.Signed-off-by Yinghai Lu <[email protected]>--- kernel/irq/handle.c | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-)Index:
linux-2.6/kernel/irq/handle.c
===================================================================kernel/irq/handle.c +9
-1@@ -19,6 +19,7 @@#include <linux/kernel_stat.h> #include <linux/rculist.h> #include <linux/hash.h> +#include <linux/radix-tree.h> #include <trace/events/irq.h> #include "internals.h" @@ -127,7 +128,23 @@ static void init_one_irq_desc(int irq, s*/ DEFINE_RAW_SPINLOCK (sparse_irq_lock); -static struct irq_desc **irq_desc_ptrs__read_mostly ; +static RADIX_TREE(irq_desc_tree, GFP_KERNEL); + +static void set_irq_desc (unsigned int irq,struct irq_desc *desc) +{ +radix_tree_insert (&irq_desc_tree, irq, desc); +} + +struct irq_desc *irq_to_desc (unsigned int irq)
kernel/irq/handle.c static void init_one_irq_desc(int irq, s · line 148
Quoted 10 lines
kernel/irq/handle.c +9
-0+{ +return radix_tree_lookup (&irq_desc_tree, irq); +} + +void replace_irq_desc (unsigned int irq,struct irq_desc *desc) +{ +radix_tree_delete (&irq_desc_tree, irq); +radix_tree_insert (&irq_desc_tree, irq, desc); +}
...
Hi Yinghai,
should not we printk\warn if radix_tree_insert() is get failed? This is hardly (if ever) happen on machines with small number of interrupts allocated but anyway.
Or I miss something?
-- Cyrill
Re: [PATCH 4/5] sparseirq: use radix_tree instead of ptrs array
Quoted 46 lines · Cyrill Gorcunov
Quoted 43 lines · Yinghai Lu
use
radix_treeirq_desc_treeinstead ofirq_desc_ptrs.Signed-off-by Yinghai Lu <[email protected]>--- kernel/irq/handle.c | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-)Index:
linux-2.6/kernel/irq/handle.c
===================================================================kernel/irq/handle.c +18
-1@@ -19,6 +19,7 @@#include <linux/kernel_stat.h> #include <linux/rculist.h> #include <linux/hash.h> +#include <linux/radix-tree.h> #include <trace/events/irq.h> #include "internals.h" @@ -127,7 +128,23 @@ static void init_one_irq_desc(int irq, s*/ DEFINE_RAW_SPINLOCK (sparse_irq_lock); -static struct irq_desc **irq_desc_ptrs__read_mostly ; +static RADIX_TREE(irq_desc_tree, GFP_KERNEL); + +static void set_irq_desc (unsigned int irq,struct irq_desc *desc) +{ +radix_tree_insert (&irq_desc_tree, irq, desc); +} + +struct irq_desc *irq_to_desc (unsigned int irq) +{ +return radix_tree_lookup (&irq_desc_tree, irq); +} + +void replace_irq_desc (unsigned int irq,struct irq_desc *desc) +{ +radix_tree_delete (&irq_desc_tree, irq); +radix_tree_insert (&irq_desc_tree, irq, desc); +}...
Quoted 7 lines
Hi Yinghai,
should not we printk\warn if
radix_tree_insert()is get failed? This is hardly (if ever) happen on machines with small number of interrupts allocated but anyway.Or I miss something?
It looks to me like we can use radix_tree_lookup_slot and radix_tree_replace_slot here. Since we don't have to allocate memory radix_tree_replace_slot can not fail. Using a case that can never fail seems better than worry about a case that can rarely fail.
Eric
PATCH 5/5 x86: update nr_irqs according cpu num
In reply to Yinghai Luthat is max number on run time.
--- arch/x86/kernel/apic/io_apic.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
arch/x86/kernel/apic/io_apic.c +7 -9
@@ -3840,16 +3840,14 @@ int __init arch_probe_nr_irqs(void) {int nr; -if (nr_irqs > (NR_VECTORS * nr_cpu_ids)) - nr_irqs =NR_VECTORS * nr_cpu_ids; - - nr = nr_irqs_gsi +8 * nr_cpu_ids; -#if defined(CONFIG_PCI_MSI ) || defined(CONFIG_HT_IRQ ) -/* -* for MSI and HT dyn irq -*/ - nr += nr_irqs_gsi *64 ; + nr =NR_VECTORS -FIRST_DEVICE_VECTOR ; +#ifdef CONFIG_SMP +/* system vectors */ + nr -=0x10 ;#endif + nr *= nr_cpu_ids; + nr +=FIRST_DEVICE_VECTOR -IRQ0_VECTOR ; +if (nr < nr_irqs) nr_irqs = nr;
Re: [PATCH 5/5] x86: update nr_irqs according cpu num
Quoted 1 line · Yinghai Lu
that is max number on run time.
Ouch! Unless I misread this code this will leave nr_irqs at NR_IRQS_LEGACY. aka 16.
Let's do something stupid and simple.nr_irqs = nr_cpus_ids * 256; /* Semi-arbitrary number */
Ideally we would set "nr_irqs = 0x7fffffff;" but we have just enough places using nr_irqs that I think those loops would get painful if we were to do that.
Eric
H. Peter Anvin
reviewerRe: [PATCH 5/5] x86: update nr_irqs according cpu num
Quoted 9 lines · Eric W. Biederman
Quoted 1 line · Yinghai Lu
that is max number on run time.
Ouch! Unless I misread this code this will leave
nr_irqsatNR_IRQS_LEGACY. aka 16.Let's do something stupid and simple.
nr_irqs=nr_cpus_ids* 256; /* Semi-arbitrary number */
This would be 1048576 on the biggest machines we currently support. Now, the number of IRQ *vectors* is limited to
(224-system vectors)*(cpu count), so one could argue that if there is anything that is not semi-arbitrary it would be that number, but that doesn't account for vector sharing.
Do we have any place which requires nr_irqs to be *stable*, or can we simply treat it as a high water mark for IRQ numbers used?
Quoted 3 lines
Ideally we would set "
nr_irqs=0x7fffffff;" but we have just enough places usingnr_irqsthat I think those loops would get painful if we were to do that.
Ideally we should presumably get rid of nr_irqs completely?
-hpa
Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center I work for Intel. I don't speak on their behalf.
Re: [PATCH 5/5] x86: update nr_irqs according cpu num
Quoted 8 lines · H. Peter Anvin
Quoted 7 lines · Eric W. Biederman
Quoted 1 line · Yinghai Lu
that is max number on run time.
Ouch! Unless I misread this code this will leave
nr_irqsatNR_IRQS_LEGACY. aka 16.
Quoted 8 lines
Quoted 2 lines
Let's do something stupid and simple.
nr_irqs=nr_cpus_ids* 256; /* Semi-arbitrary number */This would be 1048576 on the biggest machines we currently support. Now, the number of IRQ *vectors* is limited to
(224-system vectors)*(cpu count), so one could argue that if there is anything that is not semi-arbitrary it would be that number, but that doesn't account for vector sharing.
(256 - 32 - 16 - system_vectors) * cpu_count + 16
the 16 is legacy from IRQ0 to 15 has domain with all cpus set.
later could move arch_probe_nr_irqs out of early_irq_init, call it after init_IRQ(), so could use first_system_vector exactly instead of 0x10
Quoted 7 lines
Do we have any place which requires
nr_irqsto be *stable*, or can we simply treat it as a high water mark for IRQ numbers used?Quoted 3 lines
Ideally we would set "
nr_irqs=0x7fffffff;" but we have just enough places usingnr_irqsthat I think those loops would get painful if we were to do that.
yes, those loops
Quoted 2 lines
Ideally we should presumably get rid of
nr_irqscompletely?
some interface in /proc/interrupts need it to make sure sth in sequence.
YH
H. Peter Anvin
reviewerRe: [PATCH 5/5] x86: update nr_irqs according cpu num
Quoted 13 lines · Yinghai Lu
Quoted 4 lines
Quoted 4 lines
Ouch! Unless I misread this code this will leave
nr_irqsatNR_IRQS_LEGACY. aka 16.Quoted 8 lines
Quoted 2 lines
Let's do something stupid and simple.
nr_irqs=nr_cpus_ids* 256; /* Semi-arbitrary number */This would be 1048576 on the biggest machines we currently support. Now, the number of IRQ *vectors* is limited to
(224-system vectors)*(cpu count), so one could argue that if there is anything that is not semi-arbitrary it would be that number, but that doesn't account for vector sharing.
Quoted 4 lines
(256 - 32 - 16 -
system_vectors) *cpu_count+ 16the 16 is legacy from IRQ0 to 15 has domain with all cpus set.
... assuming you're on a platform with a legacy PIC. I would like to see the legacy PIC hard-coded assumptions to go away, and instead be done as runtime allocations on the relevant platforms.
Quoted 1 line
some interface in
/proc/interruptsneed it to make sure sth in sequence.
I can't even parse this sentence, never mind figuring out what it would mean. Certainly there is a better way to do that?
-hpa
Re: [PATCH 5/5] x86: update nr_irqs according cpu num
In reply to H. Peter AnvinQuoted 7 lines · H. Peter Anvin
Quoted 6 lines · Eric W. Biederman
Quoted 1 line · Yinghai Lu
that is max number on run time.
Ouch! Unless I misread this code this will leave
nr_irqsatNR_IRQS_LEGACY. aka 16.
I goofed and misread this. I was looking at nr_irqs_gsi which is initialized to 16.
We actually initialize nr_irqs to NR_IRQS, which has an unfortunately convoluted formula, that winds up being 8*NR_CPUS or 32 *MAX_IO_APICS. in the extreme cases.
Since there are still arrays sized at NR_IRQS (bleh) we can not increase nr_irqs to be greater than NR_IRQS.
So YN can you do the simple thing here and simply remove arch_probe_nr_irqs(). Sane code doesn't care how big nr_irqs is and code that does care needs to be fixed.
Quoted 8 lines
Quoted 2 lines
Let's do something stupid and simple.
nr_irqs=nr_cpus_ids* 256; /* Semi-arbitrary number */This would be 1048576 on the biggest machines we currently support. Now, the number of IRQ *vectors* is limited to
(224-system vectors)*(cpu count), so one could argue that if there is anything that is not semi-arbitrary it would be that number, but that doesn't account for vector sharing.
Except we have irq sources that we know about that are never utilized, Think of unconnected inputs to ioapics.
I don't know if we ever actually perform vector sharing. The only case I recall where the code could share vectors is if the firmware tables told us to irq sources were the same interrupt. I don't think that happens. We do have the remains of support for vector sharing in the code but I don't think it is utilized. MSI interrupts certainly can not share vectors.
My point with the semi-arbitrary number is that we should not think of nr_irqs as something defined by the resources of the receivers of interrupts. NR_IRQS has never been that. nr_irqs really is a limit on how many interrupt sources we have.
Quoted 2 lines
Do we have any place which requires
nr_irqsto be *stable*, or can we simply treat it as a high water mark for IRQ numbers used?
We have several loops that walk through the irq descriptors and look for an unbound irq. Which means having nr_irqs as a high water mark is not going to work today.
Quoted 5 lines
Quoted 3 lines
Ideally we would set "
nr_irqs=0x7fffffff;" but we have just enough places usingnr_irqsthat I think those loops would get painful if we were to do that.Ideally we should presumably get rid of
nr_irqscompletely?
Yes. It was enough of a pain the first pass at it that we wound up with nr_irqs, a value that can vary at boot time.
Once YH's radix tree changes get it in. A war on NR_IRQS and nr_irqs seems appropriate.
Eric
H. Peter Anvin
reviewerRe: [PATCH 5/5] x86: update nr_irqs according cpu num
Quoted 8 lines · Eric W. Biederman
I don't know if we ever actually perform vector sharing. The only case I recall where the code could share vectors is if the firmware tables told us to irq sources were the same interrupt. I don't think that happens. We do have the remains of support for vector sharing in the code but I don't think it is utilized. MSI interrupts certainly can not share vectors.
We probably will need to support that at some point, though, simply because it's not all that hard to construct a system in which there are more MSI-X interrupts than there are possible vectors in the system.
Until then we can do 224 * nr_cpus_ids, but it's still not the right thing.
Quoted 5 lines
Yes. It was enough of a pain the first pass at it that we wound up with
nr_irqs, a value that can vary at boot time.Once YH's radix tree changes get it in. A war on
NR_IRQSandnr_irqsseems appropriate.
Agreed.
-hpa
Re: [PATCH 5/5] x86: update nr_irqs according cpu num
In reply to Eric W. BiedermanQuoted 6 lines · Eric W. Biederman
Quoted 1 line · Yinghai Lu
that is max number on run time.
Ouch! Unless I misread this code this will leave
nr_irqsatNR_IRQS_LEGACY. aka 16.
nr_irqs is set to NR_IRQS before.
Quoted 7 lines
Let's do something stupid and simple.
nr_irqs=nr_cpus_ids* 256; /* Semi-arbitrary number */Ideally we would set "
nr_irqs=0x7fffffff;" but we have just enough places usingnr_irqsthat I think those loops would get painful if we were to do that.
or you need have NR_IRQS = NR_CPUS * 256 at first,
and then make nr_irqs = nr_cpu_ids * 224 ?
YH
Re: [PATCH 5/5] x86: update nr_irqs according cpu num
Quoted 10 lines · Yinghai Lu
Quoted 6 lines · Eric W. Biederman
Quoted 1 line · Yinghai Lu
that is max number on run time.
Ouch! Unless I misread this code this will leave
nr_irqsatNR_IRQS_LEGACY. aka 16.
nr_irqsis set toNR_IRQSbefore.
Yep my mistake.
Quoted 10 lines
Quoted 6 lines
Let's do something stupid and simple.
nr_irqs=nr_cpus_ids* 256; /* Semi-arbitrary number */Ideally we would set "
nr_irqs=0x7fffffff;" but we have just enough places usingnr_irqsthat I think those loops would get painful if we were to do that.or you need have
NR_IRQS=NR_CPUS* 256 at first,and then make
nr_irqs=nr_cpu_ids* 224 ?
The important part is that NR_IRQS become an arbitrary number larger than we can strictly support.
Based on my quick look the bad offenders (aka static sized arrays of NR_IRQS) all look at NR_IRQS not nr_irqs. So I don't see a point in having nr_irqs < NR_IRQS.
So let's just kill arch_probe_nr_irqs() on x86.
Then we can worry about things like fixing xen and the interrupt remapping code to not having NR_IRQS sized arrays.
Eric
Re: [PATCH 5/5] x86: update nr_irqs according cpu num
Quoted 8 lines · Eric W. Biederman
Based on my quick look the bad offenders (aka static sized arrays of
NR_IRQS) all look atNR_IRQSnotnr_irqs. So I don't see a point in havingnr_irqs<NR_IRQS.So let's just kill
arch_probe_nr_irqs()on x86.Then we can worry about things like fixing xen and the interrupt remapping code to not having
NR_IRQSsized arrays.
arch/sh/kernel/irq.c:int __init arch_probe_nr_irqs(void) arch/x86/kernel/apic/io_apic.c:int __init arch_probe_nr_irqs(void) arch/x86/kernel/apic/io_apic.c: * if we move calling of arch_probe_nr_irqs() after init_IRQ() include/linux/interrupt.h:extern int arch_probe_nr_irqs(void);kernel/irq/handle.c: arch_probe_nr_irqs();
kernel/softirq.c:int __init __weak arch_probe_nr_irqs(void)
sh have sparse_irq now...it has it's own copy for arch_probe_nr_irqs...
YH
Yinghai Lu <[email protected]> writes:
YH overall this looks like a good patch series, that enables additional cleanups beyond what it does. Thank you for putting this together.
Eric