diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 93edc2236282..b45020364cc0 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c @@ -459,33 +459,32 @@ int __init arch_early_irq_init(void) return arch_early_ioapic_init(); } -/* Initialize vector_irq on a new cpu */ -static void __setup_vector_irq(int cpu) +/* Temporary hack to keep things working */ +static void vector_update_shutdown_irqs(void) { - struct apic_chip_data *data; struct irq_desc *desc; - int irq, vector; + int irq; - /* Mark the inuse vectors */ for_each_irq_desc(irq, desc) { - struct irq_data *idata = irq_desc_get_irq_data(desc); + struct irq_data *irqd = irq_desc_get_irq_data(desc); + struct apic_chip_data *ad = apic_chip_data(irqd); - data = apic_chip_data(idata); - if (!data || !cpumask_test_cpu(cpu, data->domain)) - continue; - vector = data->cfg.vector; - per_cpu(vector_irq, cpu)[vector] = desc; + if (ad && cpumask_test_cpu(cpu, ad->domain) && ad->cfg.vector) + this_cpu_write(vector_irq[ad->cfg.vector], desc); } - /* Mark the free vectors */ - for (vector = 0; vector < NR_VECTORS; ++vector) { - desc = per_cpu(vector_irq, cpu)[vector]; - if (IS_ERR_OR_NULL(desc)) - continue; +} - data = apic_chip_data(irq_desc_get_irq_data(desc)); - if (!cpumask_test_cpu(cpu, data->domain)) - per_cpu(vector_irq, cpu)[vector] = VECTOR_UNUSED; - } +static struct irq_desc *__setup_vector_irq(int vector) +{ + int isairq = vector - ISA_IRQ_VECTOR(0); + + /* Check whether the irq is in the legacy space */ + if (isairq < 0 || isairq >= nr_legacy_irqs()) + return VECTOR_UNUSED; + /* Check whether the irq is handled by the IOAPIC */ + if (test_bit(isairq, &io_apic_irqs)) + return VECTOR_UNUSED; + return irq_to_desc(isairq); } /* @@ -493,20 +492,27 @@ static void __setup_vector_irq(int cpu) */ void setup_vector_irq(int cpu) { - int irq; + unsigned int vector; lockdep_assert_held(&vector_lock); /* - * On most of the platforms, legacy PIC delivers the interrupts on the - * boot cpu. But there are certain platforms where PIC interrupts are - * delivered to multiple cpu's. If the legacy IRQ is handled by the - * legacy PIC, for the new cpu that is coming online, setup the static - * legacy vector to irq mapping: + * The interrupt affinity logic never targets interrupts to offline + * CPUs. The exception are the legacy PIC interrupts. In general + * they are only targeted to CPU0, but depending on the platform + * they can be distributed to any online CPU in hardware. The + * kernel has no influence on that. So all active legacy vectors + * must be installed on all CPUs. All non legacy interrupts can be + * cleared. */ - for (irq = 0; irq < nr_legacy_irqs(); irq++) - per_cpu(vector_irq, cpu)[ISA_IRQ_VECTOR(irq)] = irq_to_desc(irq); + for (vector = 0; vector < NR_VECTORS; vector++) + this_cpu_write(vector_irq[vector], __setup_vector_irq(vector)); - __setup_vector_irq(cpu); + /* + * Until the rewrite of the managed interrupt management is in + * place it's necessary to walk the irq descriptors and check for + * interrupts which are targeted at this CPU. + */ + vector_update_shutdown_irqs(); } static int apic_retrigger_irq(struct irq_data *irq_data)