diff options
author | Yinghai Lu <yinghai@kernel.org> | 2012-09-17 22:22:30 -0700 |
---|---|---|
committer | Yinghai Lu <yinghai@kernel.org> | 2012-09-17 22:22:30 -0700 |
commit | d408eb9be5a382f4edead59916d8978412999a08 (patch) | |
tree | ae83d296eb79c4c937da8da4a2c4ad381496df93 | |
parent | 2ef8fc381b26206982c869247b8d2c507aebe6c7 (diff) | |
download | linux-yinghai-d408eb9be5a382f4edead59916d8978412999a08.tar.gz |
x86, irq: pre-reserve irq range that are used by ioapic
realloc_irq_and_cfg_at already can handle pre-reserved case.
those for non-hot add ioapic, but make them to share same code path that
will be used by hot add ioapic.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Henrik Kretzschmar <henne@nachtwindheim.de>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-rw-r--r-- | arch/x86/include/asm/io_apic.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 133 |
2 files changed, 88 insertions, 46 deletions
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 274d991cd9cdbc..6a7a6f0a969be5 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h @@ -163,6 +163,7 @@ extern void setup_ioapic_ids_from_mpc_nocheck(void); struct mp_ioapic_gsi{ u32 gsi_base; u32 gsi_end; + u32 irq_base; }; extern struct mp_ioapic_gsi mp_gsi_routing[]; extern u32 gsi_top; diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 1e98a286aa8031..b2c1749217a79d 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -201,51 +201,6 @@ static struct irq_pin_list *alloc_irq_pin_list(int node) return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node); } - -/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ -static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY]; - -int __init arch_early_irq_init(void) -{ - struct irq_cfg *cfg; - int count, node, i; - - if (!legacy_pic->nr_legacy_irqs) - io_apic_irqs = ~0UL; - - for (i = 0; i < nr_ioapics; i++) { - ioapics[i].saved_registers = - kzalloc(sizeof(struct IO_APIC_route_entry) * - ioapics[i].nr_registers, GFP_KERNEL); - if (!ioapics[i].saved_registers) - pr_err("IOAPIC %d: suspend/resume impossible!\n", i); - } - - cfg = irq_cfgx; - 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++) { - INIT_LIST_HEAD(&cfg[i].irq_2_pin); - irq_set_chip_data(i, &cfg[i]); - zalloc_cpumask_var_node(&cfg[i].domain, GFP_KERNEL, node); - zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_KERNEL, node); - /* - * For legacy IRQ's, start with assigning irq0 to irq15 to - * IRQ0_VECTOR to IRQ15_VECTOR on cpu 0. - */ - if (i < legacy_pic->nr_legacy_irqs) { - cfg[i].vector = IRQ0_VECTOR + i; - cpumask_set_cpu(0, cfg[i].domain); - } - } - - return 0; -} - static struct irq_cfg *irq_cfg(unsigned int irq) { return irq_get_chip_data(irq); @@ -349,6 +304,91 @@ static struct irq_cfg *realloc_irq_and_cfg_at(unsigned int at, int node) return alloc_irq_and_cfg_at(at, node); } +static int reserve_ioapic_gsi_irq_base(int idx) +{ + int irq; + struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(idx); + int cnt = gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1; + + irq = __irq_reserve_irqs(-1, gsi_cfg->gsi_base, cnt); + if (irq >= 0) { + gsi_cfg->irq_base = irq; + printk(KERN_INFO + "IOAPIC[%d]: apic_id %d, GSI %d-%d ==> irq %d-%d reserved\n", + idx, mpc_ioapic_id(idx), + gsi_cfg->gsi_base, gsi_cfg->gsi_end, + irq, irq + cnt - 1); + } else + printk(KERN_INFO + "IOAPIC[%d]: apic_id %d, GSI %d-%d ==> irq reserve failed\n", + idx, mpc_ioapic_id(idx), + gsi_cfg->gsi_base, gsi_cfg->gsi_end); + + return irq; +} + +static void __init reserve_ioapic_gsi_irq_extra(void) +{ + int irq; + + /* to prevent hot add ioapic taking those slots */ + if (gsi_top) { + irq = irq_reserve_irqs(gsi_top, NR_IRQS_LEGACY); + if (irq >= 0) + printk(KERN_INFO + "IOAPIC[extra]: GSI %d-%d ==> irq %d-%d reserved\n", + gsi_top, gsi_top + NR_IRQS_LEGACY - 1, + irq, irq + NR_IRQS_LEGACY - 1); + else + printk(KERN_INFO + "IOAPIC[extra]: GSI %d-%d ==> irq reserve failed\n", + gsi_top, gsi_top + NR_IRQS_LEGACY - 1); + } +} + +static void alloc_ioapic_saved_registers(int idx) +{ + if (ioapics[idx].saved_registers) + return; + + ioapics[idx].saved_registers = + kzalloc(sizeof(struct IO_APIC_route_entry) * + ioapics[idx].nr_registers, GFP_KERNEL); + + if (!ioapics[idx].saved_registers) + pr_err("IOAPIC %d: suspend/resume impossible!\n", idx); +} + +int __init arch_early_irq_init(void) +{ + int node = cpu_to_node(0); + struct irq_cfg *cfg; + int i; + + if (!legacy_pic->nr_legacy_irqs) + io_apic_irqs = ~0UL; + + for (i = 0; i < nr_ioapics; i++) + alloc_ioapic_saved_registers(i); + + for (i = 0; i < nr_ioapics; i++) + reserve_ioapic_gsi_irq_base(i); + + reserve_ioapic_gsi_irq_extra(); + + /* + * For legacy IRQ's, start with assigning irq0 to irq15 to + * IRQ0_VECTOR to IRQ15_VECTOR on cpu 0. + */ + for (i = 0; i < legacy_pic->nr_legacy_irqs; i++) { + cfg = realloc_irq_and_cfg_at(i, node); + cfg->vector = IRQ0_VECTOR + i; + cpumask_set_cpu(0, cfg->domain); + } + + return 0; +} + struct io_apic { unsigned int index; unsigned int unused[3]; @@ -3552,7 +3592,8 @@ int __init arch_probe_nr_irqs(void) if (nr < nr_irqs) nr_irqs = nr; - return NR_IRQS_LEGACY; + /* x86 arch code will allocate irq_desc/cfg */ + return 0; } int io_apic_set_pci_routing(struct device *dev, int irq, |