Commit 29c574c0 authored by Suresh Siddha's avatar Suresh Siddha Committed by H. Peter Anvin

x86, apic: Cleanup cfg->domain setup for legacy interrupts

Issues that need to be handled:
* Handle PIC interrupts on any CPU irrespective of the apic mode
* In the apic lowest priority logical flat delivery mode, be prepared to
  handle the interrupt on any CPU irrespective of what the IO-APIC RTE says.
* Because of above, when the IO-APIC starts handling the legacy PIC interrupt,
  use the same vector that is being used by the PIC while programming the
  corresponding IO-APIC RTE.

Start with all the cpu's in the legacy PIC interrupts cfg->domain.

By the time IO-APIC starts taking over the PIC interrupts, apic driver
model is finalized. So depend on the assign_irq_vector() to update the
cfg->domain and retain the same vector that was used by PIC before.

For the logical apic flat mode, cfg->domain is updated (during the first
call to assign_irq_vector()) to contain all the possible online cpu's (0xff).
Vector used for the legacy PIC interrupt doesn't change when the IO-APIC
starts handling the interrupt. Any interrupt migration after that
doesn't change the cfg->domain or the vector used.

For other apic modes like physical mode, cfg->domain is updated
(during the first call to assign_irq_vector()) to the boot cpu (cpu-0),
with the same vector that is being used by the PIC. When that interrupt is
migrated to a different cpu, cfg->domin and the vector assigned will change
accordingly.
Tested-by: default avatarBorislav Petkov <bp@alien8.de>
Signed-off-by: default avatarSuresh Siddha <suresh.b.siddha@intel.com>
Link: http://lkml.kernel.org/r/1353970176.21070.51.camel@sbsiddha-desk.sc.intel.comSigned-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
parent 4d0e42cc
...@@ -234,11 +234,11 @@ int __init arch_early_irq_init(void) ...@@ -234,11 +234,11 @@ int __init arch_early_irq_init(void)
zalloc_cpumask_var_node(&cfg[i].old_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 * For legacy IRQ's, start with assigning irq0 to irq15 to
* IRQ0_VECTOR to IRQ15_VECTOR on cpu 0. * IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
*/ */
if (i < legacy_pic->nr_legacy_irqs) { if (i < legacy_pic->nr_legacy_irqs) {
cfg[i].vector = IRQ0_VECTOR + i; cfg[i].vector = IRQ0_VECTOR + i;
cpumask_set_cpu(0, cfg[i].domain); cpumask_setall(cfg[i].domain);
} }
} }
...@@ -1141,7 +1141,8 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask) ...@@ -1141,7 +1141,8 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
* allocation for the members that are not used anymore. * allocation for the members that are not used anymore.
*/ */
cpumask_andnot(cfg->old_domain, cfg->domain, tmp_mask); cpumask_andnot(cfg->old_domain, cfg->domain, tmp_mask);
cfg->move_in_progress = 1; cfg->move_in_progress =
cpumask_intersects(cfg->old_domain, cpu_online_mask);
cpumask_and(cfg->domain, cfg->domain, tmp_mask); cpumask_and(cfg->domain, cfg->domain, tmp_mask);
break; break;
} }
...@@ -1172,8 +1173,9 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask) ...@@ -1172,8 +1173,9 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
current_vector = vector; current_vector = vector;
current_offset = offset; current_offset = offset;
if (cfg->vector) { if (cfg->vector) {
cfg->move_in_progress = 1;
cpumask_copy(cfg->old_domain, cfg->domain); cpumask_copy(cfg->old_domain, cfg->domain);
cfg->move_in_progress =
cpumask_intersects(cfg->old_domain, cpu_online_mask);
} }
for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask) for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask)
per_cpu(vector_irq, new_cpu)[vector] = irq; per_cpu(vector_irq, new_cpu)[vector] = irq;
...@@ -1241,12 +1243,6 @@ void __setup_vector_irq(int cpu) ...@@ -1241,12 +1243,6 @@ void __setup_vector_irq(int cpu)
cfg = irq_get_chip_data(irq); cfg = irq_get_chip_data(irq);
if (!cfg) if (!cfg)
continue; continue;
/*
* If it is a legacy IRQ handled by the legacy PIC, this cpu
* will be part of the irq_cfg's domain.
*/
if (irq < legacy_pic->nr_legacy_irqs && !IO_APIC_IRQ(irq))
cpumask_set_cpu(cpu, cfg->domain);
if (!cpumask_test_cpu(cpu, cfg->domain)) if (!cpumask_test_cpu(cpu, cfg->domain))
continue; continue;
...@@ -1356,16 +1352,6 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg, ...@@ -1356,16 +1352,6 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg,
if (!IO_APIC_IRQ(irq)) if (!IO_APIC_IRQ(irq))
return; return;
/*
* For legacy irqs, cfg->domain starts with cpu 0. Now that IO-APIC
* can handle this irq and the apic driver is finialized at this point,
* update the cfg->domain.
*/
if (irq < legacy_pic->nr_legacy_irqs &&
cpumask_equal(cfg->domain, cpumask_of(0)))
apic->vector_allocation_domain(0, cfg->domain,
apic->target_cpus());
if (assign_irq_vector(irq, cfg, apic->target_cpus())) if (assign_irq_vector(irq, cfg, apic->target_cpus()))
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment