Re: [PATCH v5 02/33] genirq: Add irq_alloc_reserved_desc()
From: Yinghai Lu
Date: Sat Feb 22 2014 - 17:05:12 EST
On Sat, Feb 22, 2014 at 9:28 AM, Yinghai Lu <yinghai@xxxxxxxxxx> wrote:
> On Sat, Feb 22, 2014 at 2:08 AM, Thomas Gleixner <tglx@xxxxxxxxxxxxx> wrote:
>>
>> As I said before irq_reserve_irq() is a misnomer and a
>> misconception. Of course this needs to be fixed as well.
>>
>> And you cannot just blindly change it because !SPARSE can use the
>> allocation. We are not creating stupid corner cases just to support
>> your sloppyness. Its not rocket science to do it the right way.
>>
>> That said, it might be worthwhile to get rid of the !SPARSE case
>> completely. That would probably make quite some stuff simpler.
>
> So we need to make all arches support SPARSE_IRQ at first?
>
> Now we have arm, arm64, c6x, metag, powerpc, sh, x86 support SPARSE_IRQ.
>
> The following are not with SPARSE_IRQ yet:
> alpha, arc, avr32, blackfin, cris, frv, hexagon, m32r, m68k, microblaze,
> mips, mn10300, openrisc, parisc, s390, score, sparc, tile, um,
> unicore32, xtensa.
or add calling irq_alloc_desc_at() before irq_set_chip... for !SPARSE_IRQ.
Please check attached partial patch if you like it.
If you are happy with that, I will split it into pieces and add other
irq_alloc_desc_at()
calling.
Thanks
Yinghai
diff --git a/arch/alpha/kernel/irq_alpha.c b/arch/alpha/kernel/irq_alpha.c
index 1c8625c..6c8728a 100644
--- a/arch/alpha/kernel/irq_alpha.c
+++ b/arch/alpha/kernel/irq_alpha.c
@@ -221,6 +221,7 @@ struct irqaction timer_irqaction = {
void __init
init_rtc_irq(void)
{
+ irq_alloc_desc_at(RTC_IRQ, 0);
irq_set_chip_and_handler_name(RTC_IRQ, &dummy_irq_chip,
handle_percpu_irq, "RTC");
setup_irq(RTC_IRQ, &timer_irqaction);
diff --git a/arch/alpha/kernel/irq_i8259.c b/arch/alpha/kernel/irq_i8259.c
index e1861c7..c522359 100644
--- a/arch/alpha/kernel/irq_i8259.c
+++ b/arch/alpha/kernel/irq_i8259.c
@@ -92,6 +92,7 @@ init_i8259a_irqs(void)
outb(0xff, 0xA1); /* mask all of 8259A-2 */
for (i = 0; i < 16; i++) {
+ irq_alloc_desc_at(i, 0);
irq_set_chip_and_handler(i, &i8259a_irq_type, handle_level_irq);
}
diff --git a/arch/alpha/kernel/irq_pyxis.c b/arch/alpha/kernel/irq_pyxis.c
index 13c97a5..b6da6d1 100644
--- a/arch/alpha/kernel/irq_pyxis.c
+++ b/arch/alpha/kernel/irq_pyxis.c
@@ -102,6 +102,7 @@ init_pyxis_irqs(unsigned long ignore_mask)
for (i = 16; i < 48; ++i) {
if ((ignore_mask >> i) & 1)
continue;
+ irq_alloc_desc_at(i, 0);
irq_set_chip_and_handler(i, &pyxis_irq_type, handle_level_irq);
irq_set_status_flags(i, IRQ_LEVEL);
}
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index bb27a26..2d1567b 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -88,9 +88,13 @@ static const struct irq_class irqclass_sub_desc[NR_ARCH_IRQS] = {
[CPU_RST] = {.name = "RST", .desc = "[CPU] CPU Restart"},
};
+int arch_probe_early_allocate_nr_irqs(void)
+{
+ return THIN_INTERRUPT;
+}
+
void __init init_IRQ(void)
{
- irq_reserve_irqs(0, THIN_INTERRUPT);
init_cio_interrupts();
init_airq_interrupts();
init_ext_interrupts();
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 6ad4658..398f9c4 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -206,9 +206,6 @@ int __init arch_early_irq_init(void)
count = ARRAY_SIZE(irq_cfgx);
node = cpu_to_node(0);
- /* Make sure the legacy interrupts are marked in the bitmap */
- irq_reserve_irqs(0, legacy_pic->nr_legacy_irqs);
-
for (i = 0; i < count; i++) {
irq_set_chip_data(i, &cfg[i]);
zalloc_cpumask_var_node(&cfg[i].domain, GFP_KERNEL, node);
diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
index 8f32a13..05118f92 100644
--- a/drivers/sh/intc/core.c
+++ b/drivers/sh/intc/core.c
@@ -81,11 +81,8 @@ static void __init intc_register_irq(struct intc_desc *desc,
unsigned long flags;
/*
- * Register the IRQ position with the global IRQ map, then insert
- * it in to the radix tree.
+ * insert it in to the radix tree.
*/
- irq_reserve_irq(irq);
-
raw_spin_lock_irqsave(&intc_big_lock, flags);
radix_tree_insert(&d->tree, enum_id, intc_irq_xlate_get(irq));
raw_spin_unlock_irqrestore(&intc_big_lock, flags);
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 7dc1003..584f0d7 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -613,18 +613,13 @@ int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
irq_alloc_descs(-1, from, cnt, node)
void irq_free_descs(unsigned int irq, unsigned int cnt);
-int irq_reserve_irqs(unsigned int from, unsigned int cnt);
+int arch_probe_early_allocate_nr_irqs(void);
static inline void irq_free_desc(unsigned int irq)
{
irq_free_descs(irq, 1);
}
-static inline int irq_reserve_irq(unsigned int irq)
-{
- return irq_reserve_irqs(irq, 1);
-}
-
#ifndef irq_reg_writel
# define irq_reg_writel(val, addr) writel(val, addr)
#endif
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index dc04c16..4d86cf5 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -38,12 +38,7 @@ int irq_set_chip(unsigned int irq, struct irq_chip *chip)
desc->irq_data.chip = chip;
irq_put_desc_unlock(desc, flags);
- /*
- * For !CONFIG_SPARSE_IRQ make the irq show up in
- * allocated_irqs. For the CONFIG_SPARSE_IRQ case, it is
- * already marked, and this call is harmless.
- */
- irq_reserve_irq(irq);
+
return 0;
}
EXPORT_SYMBOL(irq_set_chip);
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 8ab8e93..4b2ab96 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -248,10 +248,16 @@ struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
}
};
+int __weak arch_probe_early_allocate_nr_irqs(void)
+{
+ return 0;
+}
+
int __init early_irq_init(void)
{
int count, i, node = first_online_node;
struct irq_desc *desc;
+ int nr = arch_probe_early_allocate_nr_irqs();
init_irq_default_affinity();
@@ -267,6 +273,10 @@ int __init early_irq_init(void)
lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
desc_set_defaults(i, &desc[i], node, NULL);
}
+
+ for (i = 0; i < nr; i++)
+ set_bit(i, allocated_irqs);
+
return arch_early_irq_init();
}
@@ -390,31 +400,6 @@ err:
EXPORT_SYMBOL_GPL(__irq_alloc_descs);
/**
- * irq_reserve_irqs - mark irqs allocated
- * @from: mark from irq number
- * @cnt: number of irqs to mark
- *
- * Returns 0 on success or an appropriate error code
- */
-int irq_reserve_irqs(unsigned int from, unsigned int cnt)
-{
- unsigned int start;
- int ret = 0;
-
- if (!cnt || (from + cnt) > nr_irqs)
- return -EINVAL;
-
- mutex_lock(&sparse_irq_lock);
- start = bitmap_find_next_zero_area(allocated_irqs, nr_irqs, from, cnt, 0);
- if (start == from)
- bitmap_set(allocated_irqs, start, cnt);
- else
- ret = -EEXIST;
- mutex_unlock(&sparse_irq_lock);
- return ret;
-}
-
-/**
* irq_get_next_irq - get next allocated irq number
* @offset: where to start the search
*