diff options
author | Suresh Siddha <suresh.b.siddha@intel.com> | 2012-11-26 17:49:36 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2012-11-26 18:43:25 -0500 |
commit | 29c574c0aba8dc0736e19eb9b24aad28cc5c9098 (patch) | |
tree | c0f39f6228926d5e810b497e9a167f511f3b5d7f | |
parent | 4d0e42cc66f4e7e0bf08b29da1ae6ebd60549c4e (diff) |
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: Borislav Petkov <bp@alien8.de>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Link: http://lkml.kernel.org/r/1353970176.21070.51.camel@sbsiddha-desk.sc.intel.com
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 26 |
1 files changed, 6 insertions, 20 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index c265593ec2cd..0c1f36650568 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -234,11 +234,11 @@ int __init arch_early_irq_init(void) | |||
234 | zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_KERNEL, node); | 234 | zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_KERNEL, node); |
235 | /* | 235 | /* |
236 | * For legacy IRQ's, start with assigning irq0 to irq15 to | 236 | * For legacy IRQ's, start with assigning irq0 to irq15 to |
237 | * IRQ0_VECTOR to IRQ15_VECTOR on cpu 0. | 237 | * IRQ0_VECTOR to IRQ15_VECTOR for all cpu's. |
238 | */ | 238 | */ |
239 | if (i < legacy_pic->nr_legacy_irqs) { | 239 | if (i < legacy_pic->nr_legacy_irqs) { |
240 | cfg[i].vector = IRQ0_VECTOR + i; | 240 | cfg[i].vector = IRQ0_VECTOR + i; |
241 | cpumask_set_cpu(0, cfg[i].domain); | 241 | cpumask_setall(cfg[i].domain); |
242 | } | 242 | } |
243 | } | 243 | } |
244 | 244 | ||
@@ -1141,7 +1141,8 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask) | |||
1141 | * allocation for the members that are not used anymore. | 1141 | * allocation for the members that are not used anymore. |
1142 | */ | 1142 | */ |
1143 | cpumask_andnot(cfg->old_domain, cfg->domain, tmp_mask); | 1143 | cpumask_andnot(cfg->old_domain, cfg->domain, tmp_mask); |
1144 | cfg->move_in_progress = 1; | 1144 | cfg->move_in_progress = |
1145 | cpumask_intersects(cfg->old_domain, cpu_online_mask); | ||
1145 | cpumask_and(cfg->domain, cfg->domain, tmp_mask); | 1146 | cpumask_and(cfg->domain, cfg->domain, tmp_mask); |
1146 | break; | 1147 | break; |
1147 | } | 1148 | } |
@@ -1172,8 +1173,9 @@ next: | |||
1172 | current_vector = vector; | 1173 | current_vector = vector; |
1173 | current_offset = offset; | 1174 | current_offset = offset; |
1174 | if (cfg->vector) { | 1175 | if (cfg->vector) { |
1175 | cfg->move_in_progress = 1; | ||
1176 | cpumask_copy(cfg->old_domain, cfg->domain); | 1176 | cpumask_copy(cfg->old_domain, cfg->domain); |
1177 | cfg->move_in_progress = | ||
1178 | cpumask_intersects(cfg->old_domain, cpu_online_mask); | ||
1177 | } | 1179 | } |
1178 | for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask) | 1180 | for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask) |
1179 | per_cpu(vector_irq, new_cpu)[vector] = irq; | 1181 | per_cpu(vector_irq, new_cpu)[vector] = irq; |
@@ -1241,12 +1243,6 @@ void __setup_vector_irq(int cpu) | |||
1241 | cfg = irq_get_chip_data(irq); | 1243 | cfg = irq_get_chip_data(irq); |
1242 | if (!cfg) | 1244 | if (!cfg) |
1243 | continue; | 1245 | continue; |
1244 | /* | ||
1245 | * If it is a legacy IRQ handled by the legacy PIC, this cpu | ||
1246 | * will be part of the irq_cfg's domain. | ||
1247 | */ | ||
1248 | if (irq < legacy_pic->nr_legacy_irqs && !IO_APIC_IRQ(irq)) | ||
1249 | cpumask_set_cpu(cpu, cfg->domain); | ||
1250 | 1246 | ||
1251 | if (!cpumask_test_cpu(cpu, cfg->domain)) | 1247 | if (!cpumask_test_cpu(cpu, cfg->domain)) |
1252 | continue; | 1248 | continue; |
@@ -1356,16 +1352,6 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg, | |||
1356 | if (!IO_APIC_IRQ(irq)) | 1352 | if (!IO_APIC_IRQ(irq)) |
1357 | return; | 1353 | return; |
1358 | 1354 | ||
1359 | /* | ||
1360 | * For legacy irqs, cfg->domain starts with cpu 0. Now that IO-APIC | ||
1361 | * can handle this irq and the apic driver is finialized at this point, | ||
1362 | * update the cfg->domain. | ||
1363 | */ | ||
1364 | if (irq < legacy_pic->nr_legacy_irqs && | ||
1365 | cpumask_equal(cfg->domain, cpumask_of(0))) | ||
1366 | apic->vector_allocation_domain(0, cfg->domain, | ||
1367 | apic->target_cpus()); | ||
1368 | |||
1369 | if (assign_irq_vector(irq, cfg, apic->target_cpus())) | 1355 | if (assign_irq_vector(irq, cfg, apic->target_cpus())) |
1370 | return; | 1356 | return; |
1371 | 1357 | ||