diff options
author | Alexander Gordeev <agordeev@redhat.com> | 2012-06-07 09:15:59 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-06-08 05:44:29 -0400 |
commit | ff164324123c0fe181d8de7dadcc7b3fbe25f2cf (patch) | |
tree | 110c0250f795bc2b71495566b3ead098b8b1a89b | |
parent | 8637e38aff14d048b649075114023023a2e80fba (diff) |
x86/apic: Make cpu_mask_to_apicid() operations return error code
Current cpu_mask_to_apicid() and cpu_mask_to_apicid_and()
implementations have few shortcomings:
1. A value returned by cpu_mask_to_apicid() is written to
hardware registers unconditionally. Should BAD_APICID get ever
returned it will be written to a hardware too. But the value of
BAD_APICID is not universal across all hardware in all modes and
might cause unexpected results, i.e. interrupts might get routed
to CPUs that are not configured to receive it.
2. Because the value of BAD_APICID is not universal it is
counter- intuitive to return it for a hardware where it does not
make sense (i.e. x2apic).
3. cpu_mask_to_apicid_and() operation is thought as an
complement to cpu_mask_to_apicid() that only applies a AND mask
on top of a cpumask being passed. Yet, as consequence of 18374d8
commit the two operations are inconsistent in that of:
cpu_mask_to_apicid() should not get a offline CPU with the cpumask
cpu_mask_to_apicid_and() should not fail and return BAD_APICID
These limitations are impossible to realize just from looking at
the operations prototypes.
Most of these shortcomings are resolved by returning a error
code instead of BAD_APICID. As the result, faults are reported
back early rather than possibilities to cause a unexpected
behaviour exist (in case of [1]).
The only exception is setup_timer_IRQ0_pin() routine. Although
obviously controversial to this fix, its existing behaviour is
preserved to not break the fragile check_timer() and would
better addressed in a separate fix.
Signed-off-by: Alexander Gordeev <agordeev@redhat.com>
Acked-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/20120607131559.GF4759@dhcp-26-207.brq.redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/include/asm/apic.h | 44 | ||||
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 33 | ||||
-rw-r--r-- | arch/x86/kernel/apic/es7000_32.c | 21 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 88 | ||||
-rw-r--r-- | arch/x86/kernel/apic/numaq_32.c | 14 | ||||
-rw-r--r-- | arch/x86/kernel/apic/summit_32.c | 22 | ||||
-rw-r--r-- | arch/x86/kernel/apic/x2apic_cluster.c | 24 | ||||
-rw-r--r-- | arch/x86/kernel/apic/x2apic_uv_x.c | 27 | ||||
-rw-r--r-- | arch/x86/platform/uv/uv_irq.c | 7 | ||||
-rw-r--r-- | drivers/iommu/intel_irq_remapping.c | 13 |
10 files changed, 188 insertions, 105 deletions
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index e3fecd50d5ca..ae91f9c7e360 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h | |||
@@ -331,9 +331,11 @@ struct apic { | |||
331 | unsigned long (*set_apic_id)(unsigned int id); | 331 | unsigned long (*set_apic_id)(unsigned int id); |
332 | unsigned long apic_id_mask; | 332 | unsigned long apic_id_mask; |
333 | 333 | ||
334 | unsigned int (*cpu_mask_to_apicid)(const struct cpumask *cpumask); | 334 | int (*cpu_mask_to_apicid)(const struct cpumask *cpumask, |
335 | unsigned int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask, | 335 | unsigned int *apicid); |
336 | const struct cpumask *andmask); | 336 | int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask, |
337 | const struct cpumask *andmask, | ||
338 | unsigned int *apicid); | ||
337 | 339 | ||
338 | /* ipi */ | 340 | /* ipi */ |
339 | void (*send_IPI_mask)(const struct cpumask *mask, int vector); | 341 | void (*send_IPI_mask)(const struct cpumask *mask, int vector); |
@@ -591,29 +593,45 @@ static inline int default_phys_pkg_id(int cpuid_apic, int index_msb) | |||
591 | 593 | ||
592 | #endif | 594 | #endif |
593 | 595 | ||
594 | static inline unsigned int | 596 | static inline int |
595 | flat_cpu_mask_to_apicid(const struct cpumask *cpumask) | 597 | __flat_cpu_mask_to_apicid(unsigned long cpu_mask, unsigned int *apicid) |
596 | { | 598 | { |
597 | return cpumask_bits(cpumask)[0] & APIC_ALL_CPUS; | 599 | cpu_mask &= APIC_ALL_CPUS; |
600 | if (likely(cpu_mask)) { | ||
601 | *apicid = (unsigned int)cpu_mask; | ||
602 | return 0; | ||
603 | } else { | ||
604 | return -EINVAL; | ||
605 | } | ||
598 | } | 606 | } |
599 | 607 | ||
600 | static inline unsigned int | 608 | static inline int |
609 | flat_cpu_mask_to_apicid(const struct cpumask *cpumask, | ||
610 | unsigned int *apicid) | ||
611 | { | ||
612 | return __flat_cpu_mask_to_apicid(cpumask_bits(cpumask)[0], apicid); | ||
613 | } | ||
614 | |||
615 | static inline int | ||
601 | flat_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | 616 | flat_cpu_mask_to_apicid_and(const struct cpumask *cpumask, |
602 | const struct cpumask *andmask) | 617 | const struct cpumask *andmask, |
618 | unsigned int *apicid) | ||
603 | { | 619 | { |
604 | unsigned long mask1 = cpumask_bits(cpumask)[0]; | 620 | unsigned long mask1 = cpumask_bits(cpumask)[0]; |
605 | unsigned long mask2 = cpumask_bits(andmask)[0]; | 621 | unsigned long mask2 = cpumask_bits(andmask)[0]; |
606 | unsigned long mask3 = cpumask_bits(cpu_online_mask)[0]; | 622 | unsigned long mask3 = cpumask_bits(cpu_online_mask)[0]; |
607 | 623 | ||
608 | return (unsigned int)(mask1 & mask2 & mask3); | 624 | return __flat_cpu_mask_to_apicid(mask1 & mask2 & mask3, apicid); |
609 | } | 625 | } |
610 | 626 | ||
611 | extern unsigned int | 627 | extern int |
612 | default_cpu_mask_to_apicid(const struct cpumask *cpumask); | 628 | default_cpu_mask_to_apicid(const struct cpumask *cpumask, |
629 | unsigned int *apicid); | ||
613 | 630 | ||
614 | extern unsigned int | 631 | extern int |
615 | default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | 632 | default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, |
616 | const struct cpumask *andmask); | 633 | const struct cpumask *andmask, |
634 | unsigned int *apicid); | ||
617 | 635 | ||
618 | static inline bool | 636 | static inline bool |
619 | flat_vector_allocation_domain(int cpu, struct cpumask *retmask) | 637 | flat_vector_allocation_domain(int cpu, struct cpumask *retmask) |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 96a2608252f1..b8d92606f84f 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -2123,24 +2123,26 @@ void default_init_apic_ldr(void) | |||
2123 | apic_write(APIC_LDR, val); | 2123 | apic_write(APIC_LDR, val); |
2124 | } | 2124 | } |
2125 | 2125 | ||
2126 | unsigned int default_cpu_mask_to_apicid(const struct cpumask *cpumask) | 2126 | static inline int __default_cpu_to_apicid(int cpu, unsigned int *apicid) |
2127 | { | 2127 | { |
2128 | int cpu; | 2128 | if (likely((unsigned int)cpu < nr_cpu_ids)) { |
2129 | 2129 | *apicid = per_cpu(x86_cpu_to_apicid, cpu); | |
2130 | /* | 2130 | return 0; |
2131 | * We're using fixed IRQ delivery, can only return one phys APIC ID. | 2131 | } else { |
2132 | * May as well be the first. | 2132 | return -EINVAL; |
2133 | */ | 2133 | } |
2134 | cpu = cpumask_first(cpumask); | 2134 | } |
2135 | if (likely((unsigned)cpu < nr_cpu_ids)) | ||
2136 | return per_cpu(x86_cpu_to_apicid, cpu); | ||
2137 | 2135 | ||
2138 | return BAD_APICID; | 2136 | int default_cpu_mask_to_apicid(const struct cpumask *cpumask, |
2137 | unsigned int *apicid) | ||
2138 | { | ||
2139 | int cpu = cpumask_first(cpumask); | ||
2140 | return __default_cpu_to_apicid(cpu, apicid); | ||
2139 | } | 2141 | } |
2140 | 2142 | ||
2141 | unsigned int | 2143 | int default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, |
2142 | default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | 2144 | const struct cpumask *andmask, |
2143 | const struct cpumask *andmask) | 2145 | unsigned int *apicid) |
2144 | { | 2146 | { |
2145 | int cpu; | 2147 | int cpu; |
2146 | 2148 | ||
@@ -2148,7 +2150,8 @@ default_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | |||
2148 | if (cpumask_test_cpu(cpu, cpu_online_mask)) | 2150 | if (cpumask_test_cpu(cpu, cpu_online_mask)) |
2149 | break; | 2151 | break; |
2150 | } | 2152 | } |
2151 | return per_cpu(x86_cpu_to_apicid, cpu); | 2153 | |
2154 | return __default_cpu_to_apicid(cpu, apicid); | ||
2152 | } | 2155 | } |
2153 | 2156 | ||
2154 | /* | 2157 | /* |
diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index 3c42865757e2..515ebb00a9fc 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c | |||
@@ -525,7 +525,8 @@ static int es7000_check_phys_apicid_present(int cpu_physical_apicid) | |||
525 | return 1; | 525 | return 1; |
526 | } | 526 | } |
527 | 527 | ||
528 | static unsigned int es7000_cpu_mask_to_apicid(const struct cpumask *cpumask) | 528 | static int |
529 | es7000_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id) | ||
529 | { | 530 | { |
530 | unsigned int round = 0; | 531 | unsigned int round = 0; |
531 | int cpu, uninitialized_var(apicid); | 532 | int cpu, uninitialized_var(apicid); |
@@ -539,31 +540,33 @@ static unsigned int es7000_cpu_mask_to_apicid(const struct cpumask *cpumask) | |||
539 | if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { | 540 | if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { |
540 | WARN(1, "Not a valid mask!"); | 541 | WARN(1, "Not a valid mask!"); |
541 | 542 | ||
542 | return BAD_APICID; | 543 | return -EINVAL; |
543 | } | 544 | } |
544 | apicid = new_apicid; | 545 | apicid = new_apicid; |
545 | round++; | 546 | round++; |
546 | } | 547 | } |
547 | return apicid; | 548 | *dest_id = apicid; |
549 | return 0; | ||
548 | } | 550 | } |
549 | 551 | ||
550 | static unsigned int | 552 | static int |
551 | es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask, | 553 | es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask, |
552 | const struct cpumask *andmask) | 554 | const struct cpumask *andmask, |
555 | unsigned int *apicid) | ||
553 | { | 556 | { |
554 | int apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0); | 557 | *apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0); |
555 | cpumask_var_t cpumask; | 558 | cpumask_var_t cpumask; |
556 | 559 | ||
557 | if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) | 560 | if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) |
558 | return apicid; | 561 | return 0; |
559 | 562 | ||
560 | cpumask_and(cpumask, inmask, andmask); | 563 | cpumask_and(cpumask, inmask, andmask); |
561 | cpumask_and(cpumask, cpumask, cpu_online_mask); | 564 | cpumask_and(cpumask, cpumask, cpu_online_mask); |
562 | apicid = es7000_cpu_mask_to_apicid(cpumask); | 565 | es7000_cpu_mask_to_apicid(cpumask, apicid); |
563 | 566 | ||
564 | free_cpumask_var(cpumask); | 567 | free_cpumask_var(cpumask); |
565 | 568 | ||
566 | return apicid; | 569 | return 0; |
567 | } | 570 | } |
568 | 571 | ||
569 | static int es7000_phys_pkg_id(int cpuid_apic, int index_msb) | 572 | static int es7000_phys_pkg_id(int cpuid_apic, int index_msb) |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 4061a7dee5c9..0deb773404e5 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -1359,7 +1359,14 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg, | |||
1359 | if (assign_irq_vector(irq, cfg, apic->target_cpus())) | 1359 | if (assign_irq_vector(irq, cfg, apic->target_cpus())) |
1360 | return; | 1360 | return; |
1361 | 1361 | ||
1362 | dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus()); | 1362 | if (apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus(), |
1363 | &dest)) { | ||
1364 | pr_warn("Failed to obtain apicid for ioapic %d, pin %d\n", | ||
1365 | mpc_ioapic_id(attr->ioapic), attr->ioapic_pin); | ||
1366 | __clear_irq_vector(irq, cfg); | ||
1367 | |||
1368 | return; | ||
1369 | } | ||
1363 | 1370 | ||
1364 | apic_printk(APIC_VERBOSE,KERN_DEBUG | 1371 | apic_printk(APIC_VERBOSE,KERN_DEBUG |
1365 | "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> " | 1372 | "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> " |
@@ -1474,6 +1481,7 @@ static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx, | |||
1474 | unsigned int pin, int vector) | 1481 | unsigned int pin, int vector) |
1475 | { | 1482 | { |
1476 | struct IO_APIC_route_entry entry; | 1483 | struct IO_APIC_route_entry entry; |
1484 | unsigned int dest; | ||
1477 | 1485 | ||
1478 | if (irq_remapping_enabled) | 1486 | if (irq_remapping_enabled) |
1479 | return; | 1487 | return; |
@@ -1484,9 +1492,12 @@ static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx, | |||
1484 | * We use logical delivery to get the timer IRQ | 1492 | * We use logical delivery to get the timer IRQ |
1485 | * to the first CPU. | 1493 | * to the first CPU. |
1486 | */ | 1494 | */ |
1495 | if (unlikely(apic->cpu_mask_to_apicid(apic->target_cpus(), &dest))) | ||
1496 | dest = BAD_APICID; | ||
1497 | |||
1487 | entry.dest_mode = apic->irq_dest_mode; | 1498 | entry.dest_mode = apic->irq_dest_mode; |
1488 | entry.mask = 0; /* don't mask IRQ for edge */ | 1499 | entry.mask = 0; /* don't mask IRQ for edge */ |
1489 | entry.dest = apic->cpu_mask_to_apicid(apic->target_cpus()); | 1500 | entry.dest = dest; |
1490 | entry.delivery_mode = apic->irq_delivery_mode; | 1501 | entry.delivery_mode = apic->irq_delivery_mode; |
1491 | entry.polarity = 0; | 1502 | entry.polarity = 0; |
1492 | entry.trigger = 0; | 1503 | entry.trigger = 0; |
@@ -2245,16 +2256,25 @@ int __ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, | |||
2245 | unsigned int *dest_id) | 2256 | unsigned int *dest_id) |
2246 | { | 2257 | { |
2247 | struct irq_cfg *cfg = data->chip_data; | 2258 | struct irq_cfg *cfg = data->chip_data; |
2259 | unsigned int irq = data->irq; | ||
2260 | int err; | ||
2248 | 2261 | ||
2249 | if (!cpumask_intersects(mask, cpu_online_mask)) | 2262 | if (!cpumask_intersects(mask, cpu_online_mask)) |
2250 | return -1; | 2263 | return -EINVAL; |
2251 | 2264 | ||
2252 | if (assign_irq_vector(data->irq, data->chip_data, mask)) | 2265 | err = assign_irq_vector(irq, cfg, mask); |
2253 | return -1; | 2266 | if (err) |
2267 | return err; | ||
2268 | |||
2269 | err = apic->cpu_mask_to_apicid_and(mask, cfg->domain, dest_id); | ||
2270 | if (err) { | ||
2271 | if (assign_irq_vector(irq, cfg, data->affinity)) | ||
2272 | pr_err("Failed to recover vector for irq %d\n", irq); | ||
2273 | return err; | ||
2274 | } | ||
2254 | 2275 | ||
2255 | cpumask_copy(data->affinity, mask); | 2276 | cpumask_copy(data->affinity, mask); |
2256 | 2277 | ||
2257 | *dest_id = apic->cpu_mask_to_apicid_and(mask, cfg->domain); | ||
2258 | return 0; | 2278 | return 0; |
2259 | } | 2279 | } |
2260 | 2280 | ||
@@ -3040,7 +3060,10 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, | |||
3040 | if (err) | 3060 | if (err) |
3041 | return err; | 3061 | return err; |
3042 | 3062 | ||
3043 | dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus()); | 3063 | err = apic->cpu_mask_to_apicid_and(cfg->domain, |
3064 | apic->target_cpus(), &dest); | ||
3065 | if (err) | ||
3066 | return err; | ||
3044 | 3067 | ||
3045 | if (irq_remapped(cfg)) { | 3068 | if (irq_remapped(cfg)) { |
3046 | compose_remapped_msi_msg(pdev, irq, dest, msg, hpet_id); | 3069 | compose_remapped_msi_msg(pdev, irq, dest, msg, hpet_id); |
@@ -3361,6 +3384,8 @@ static struct irq_chip ht_irq_chip = { | |||
3361 | int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) | 3384 | int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) |
3362 | { | 3385 | { |
3363 | struct irq_cfg *cfg; | 3386 | struct irq_cfg *cfg; |
3387 | struct ht_irq_msg msg; | ||
3388 | unsigned dest; | ||
3364 | int err; | 3389 | int err; |
3365 | 3390 | ||
3366 | if (disable_apic) | 3391 | if (disable_apic) |
@@ -3368,36 +3393,37 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) | |||
3368 | 3393 | ||
3369 | cfg = irq_cfg(irq); | 3394 | cfg = irq_cfg(irq); |
3370 | err = assign_irq_vector(irq, cfg, apic->target_cpus()); | 3395 | err = assign_irq_vector(irq, cfg, apic->target_cpus()); |
3371 | if (!err) { | 3396 | if (err) |
3372 | struct ht_irq_msg msg; | 3397 | return err; |
3373 | unsigned dest; | ||
3374 | 3398 | ||
3375 | dest = apic->cpu_mask_to_apicid_and(cfg->domain, | 3399 | err = apic->cpu_mask_to_apicid_and(cfg->domain, |
3376 | apic->target_cpus()); | 3400 | apic->target_cpus(), &dest); |
3401 | if (err) | ||
3402 | return err; | ||
3377 | 3403 | ||
3378 | msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest); | 3404 | msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest); |
3379 | 3405 | ||
3380 | msg.address_lo = | 3406 | msg.address_lo = |
3381 | HT_IRQ_LOW_BASE | | 3407 | HT_IRQ_LOW_BASE | |
3382 | HT_IRQ_LOW_DEST_ID(dest) | | 3408 | HT_IRQ_LOW_DEST_ID(dest) | |
3383 | HT_IRQ_LOW_VECTOR(cfg->vector) | | 3409 | HT_IRQ_LOW_VECTOR(cfg->vector) | |
3384 | ((apic->irq_dest_mode == 0) ? | 3410 | ((apic->irq_dest_mode == 0) ? |
3385 | HT_IRQ_LOW_DM_PHYSICAL : | 3411 | HT_IRQ_LOW_DM_PHYSICAL : |
3386 | HT_IRQ_LOW_DM_LOGICAL) | | 3412 | HT_IRQ_LOW_DM_LOGICAL) | |
3387 | HT_IRQ_LOW_RQEOI_EDGE | | 3413 | HT_IRQ_LOW_RQEOI_EDGE | |
3388 | ((apic->irq_delivery_mode != dest_LowestPrio) ? | 3414 | ((apic->irq_delivery_mode != dest_LowestPrio) ? |
3389 | HT_IRQ_LOW_MT_FIXED : | 3415 | HT_IRQ_LOW_MT_FIXED : |
3390 | HT_IRQ_LOW_MT_ARBITRATED) | | 3416 | HT_IRQ_LOW_MT_ARBITRATED) | |
3391 | HT_IRQ_LOW_IRQ_MASKED; | 3417 | HT_IRQ_LOW_IRQ_MASKED; |
3392 | 3418 | ||
3393 | write_ht_irq_msg(irq, &msg); | 3419 | write_ht_irq_msg(irq, &msg); |
3394 | 3420 | ||
3395 | irq_set_chip_and_handler_name(irq, &ht_irq_chip, | 3421 | irq_set_chip_and_handler_name(irq, &ht_irq_chip, |
3396 | handle_edge_irq, "edge"); | 3422 | handle_edge_irq, "edge"); |
3397 | 3423 | ||
3398 | dev_printk(KERN_DEBUG, &dev->dev, "irq %d for HT\n", irq); | 3424 | dev_printk(KERN_DEBUG, &dev->dev, "irq %d for HT\n", irq); |
3399 | } | 3425 | |
3400 | return err; | 3426 | return 0; |
3401 | } | 3427 | } |
3402 | #endif /* CONFIG_HT_IRQ */ | 3428 | #endif /* CONFIG_HT_IRQ */ |
3403 | 3429 | ||
diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c index eb2d466fd81a..2b55514c328b 100644 --- a/arch/x86/kernel/apic/numaq_32.c +++ b/arch/x86/kernel/apic/numaq_32.c | |||
@@ -406,16 +406,20 @@ static inline int numaq_check_phys_apicid_present(int phys_apicid) | |||
406 | * We use physical apicids here, not logical, so just return the default | 406 | * We use physical apicids here, not logical, so just return the default |
407 | * physical broadcast to stop people from breaking us | 407 | * physical broadcast to stop people from breaking us |
408 | */ | 408 | */ |
409 | static unsigned int numaq_cpu_mask_to_apicid(const struct cpumask *cpumask) | 409 | static int |
410 | numaq_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *apicid) | ||
410 | { | 411 | { |
411 | return 0x0F; | 412 | *apicid = 0x0F; |
413 | return 0; | ||
412 | } | 414 | } |
413 | 415 | ||
414 | static inline unsigned int | 416 | static int |
415 | numaq_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | 417 | numaq_cpu_mask_to_apicid_and(const struct cpumask *cpumask, |
416 | const struct cpumask *andmask) | 418 | const struct cpumask *andmask, |
419 | unsigned int *apicid) | ||
417 | { | 420 | { |
418 | return 0x0F; | 421 | *apicid = 0x0F; |
422 | return 0; | ||
419 | } | 423 | } |
420 | 424 | ||
421 | /* No NUMA-Q box has a HT CPU, but it can't hurt to use the default code. */ | 425 | /* No NUMA-Q box has a HT CPU, but it can't hurt to use the default code. */ |
diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c index 35d254c1fec2..5766d84f12d6 100644 --- a/arch/x86/kernel/apic/summit_32.c +++ b/arch/x86/kernel/apic/summit_32.c | |||
@@ -263,7 +263,8 @@ static int summit_check_phys_apicid_present(int physical_apicid) | |||
263 | return 1; | 263 | return 1; |
264 | } | 264 | } |
265 | 265 | ||
266 | static unsigned int summit_cpu_mask_to_apicid(const struct cpumask *cpumask) | 266 | static int |
267 | summit_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id) | ||
267 | { | 268 | { |
268 | unsigned int round = 0; | 269 | unsigned int round = 0; |
269 | int cpu, apicid = 0; | 270 | int cpu, apicid = 0; |
@@ -276,30 +277,33 @@ static unsigned int summit_cpu_mask_to_apicid(const struct cpumask *cpumask) | |||
276 | 277 | ||
277 | if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { | 278 | if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { |
278 | printk("%s: Not a valid mask!\n", __func__); | 279 | printk("%s: Not a valid mask!\n", __func__); |
279 | return BAD_APICID; | 280 | return -EINVAL; |
280 | } | 281 | } |
281 | apicid |= new_apicid; | 282 | apicid |= new_apicid; |
282 | round++; | 283 | round++; |
283 | } | 284 | } |
284 | return apicid; | 285 | *dest_id = apicid; |
286 | return 0; | ||
285 | } | 287 | } |
286 | 288 | ||
287 | static unsigned int summit_cpu_mask_to_apicid_and(const struct cpumask *inmask, | 289 | static int |
288 | const struct cpumask *andmask) | 290 | summit_cpu_mask_to_apicid_and(const struct cpumask *inmask, |
291 | const struct cpumask *andmask, | ||
292 | unsigned int *apicid) | ||
289 | { | 293 | { |
290 | int apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0); | 294 | *apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0); |
291 | cpumask_var_t cpumask; | 295 | cpumask_var_t cpumask; |
292 | 296 | ||
293 | if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) | 297 | if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) |
294 | return apicid; | 298 | return 0; |
295 | 299 | ||
296 | cpumask_and(cpumask, inmask, andmask); | 300 | cpumask_and(cpumask, inmask, andmask); |
297 | cpumask_and(cpumask, cpumask, cpu_online_mask); | 301 | cpumask_and(cpumask, cpumask, cpu_online_mask); |
298 | apicid = summit_cpu_mask_to_apicid(cpumask); | 302 | summit_cpu_mask_to_apicid(cpumask, apicid); |
299 | 303 | ||
300 | free_cpumask_var(cpumask); | 304 | free_cpumask_var(cpumask); |
301 | 305 | ||
302 | return apicid; | 306 | return 0; |
303 | } | 307 | } |
304 | 308 | ||
305 | /* | 309 | /* |
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index 612622c47dfb..5f86f79335f4 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c | |||
@@ -96,24 +96,26 @@ static void x2apic_send_IPI_all(int vector) | |||
96 | __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLINC); | 96 | __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLINC); |
97 | } | 97 | } |
98 | 98 | ||
99 | static unsigned int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask) | 99 | static int |
100 | x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *apicid) | ||
100 | { | 101 | { |
101 | int cpu = cpumask_first(cpumask); | 102 | int cpu = cpumask_first(cpumask); |
102 | u32 dest = 0; | ||
103 | int i; | 103 | int i; |
104 | 104 | ||
105 | if (cpu > nr_cpu_ids) | 105 | if (cpu >= nr_cpu_ids) |
106 | return BAD_APICID; | 106 | return -EINVAL; |
107 | 107 | ||
108 | *apicid = 0; | ||
108 | for_each_cpu_and(i, cpumask, per_cpu(cpus_in_cluster, cpu)) | 109 | for_each_cpu_and(i, cpumask, per_cpu(cpus_in_cluster, cpu)) |
109 | dest |= per_cpu(x86_cpu_to_logical_apicid, i); | 110 | *apicid |= per_cpu(x86_cpu_to_logical_apicid, i); |
110 | 111 | ||
111 | return dest; | 112 | return 0; |
112 | } | 113 | } |
113 | 114 | ||
114 | static unsigned int | 115 | static int |
115 | x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | 116 | x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, |
116 | const struct cpumask *andmask) | 117 | const struct cpumask *andmask, |
118 | unsigned int *apicid) | ||
117 | { | 119 | { |
118 | u32 dest = 0; | 120 | u32 dest = 0; |
119 | u16 cluster; | 121 | u16 cluster; |
@@ -128,7 +130,7 @@ x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | |||
128 | } | 130 | } |
129 | 131 | ||
130 | if (!dest) | 132 | if (!dest) |
131 | return BAD_APICID; | 133 | return -EINVAL; |
132 | 134 | ||
133 | for_each_cpu_and(i, cpumask, andmask) { | 135 | for_each_cpu_and(i, cpumask, andmask) { |
134 | if (!cpumask_test_cpu(i, cpu_online_mask)) | 136 | if (!cpumask_test_cpu(i, cpu_online_mask)) |
@@ -138,7 +140,9 @@ x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | |||
138 | dest |= per_cpu(x86_cpu_to_logical_apicid, i); | 140 | dest |= per_cpu(x86_cpu_to_logical_apicid, i); |
139 | } | 141 | } |
140 | 142 | ||
141 | return dest; | 143 | *apicid = dest; |
144 | |||
145 | return 0; | ||
142 | } | 146 | } |
143 | 147 | ||
144 | static void init_x2apic_ldr(void) | 148 | static void init_x2apic_ldr(void) |
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index df89a7d78748..2f3030fef31e 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c | |||
@@ -269,23 +269,31 @@ static void uv_init_apic_ldr(void) | |||
269 | { | 269 | { |
270 | } | 270 | } |
271 | 271 | ||
272 | static unsigned int uv_cpu_mask_to_apicid(const struct cpumask *cpumask) | 272 | static inline int __uv_cpu_to_apicid(int cpu, unsigned int *apicid) |
273 | { | ||
274 | if (likely((unsigned int)cpu < nr_cpu_ids)) { | ||
275 | *apicid = per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits; | ||
276 | return 0; | ||
277 | } else { | ||
278 | return -EINVAL; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | static int | ||
283 | uv_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *apicid) | ||
273 | { | 284 | { |
274 | /* | 285 | /* |
275 | * We're using fixed IRQ delivery, can only return one phys APIC ID. | 286 | * We're using fixed IRQ delivery, can only return one phys APIC ID. |
276 | * May as well be the first. | 287 | * May as well be the first. |
277 | */ | 288 | */ |
278 | int cpu = cpumask_first(cpumask); | 289 | int cpu = cpumask_first(cpumask); |
279 | 290 | return __uv_cpu_to_apicid(cpu, apicid); | |
280 | if ((unsigned)cpu < nr_cpu_ids) | ||
281 | return per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits; | ||
282 | else | ||
283 | return BAD_APICID; | ||
284 | } | 291 | } |
285 | 292 | ||
286 | static unsigned int | 293 | static int |
287 | uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | 294 | uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask, |
288 | const struct cpumask *andmask) | 295 | const struct cpumask *andmask, |
296 | unsigned int *apicid) | ||
289 | { | 297 | { |
290 | int cpu; | 298 | int cpu; |
291 | 299 | ||
@@ -297,7 +305,8 @@ uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | |||
297 | if (cpumask_test_cpu(cpu, cpu_online_mask)) | 305 | if (cpumask_test_cpu(cpu, cpu_online_mask)) |
298 | break; | 306 | break; |
299 | } | 307 | } |
300 | return per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits; | 308 | |
309 | return __uv_cpu_to_apicid(cpu, apicid); | ||
301 | } | 310 | } |
302 | 311 | ||
303 | static unsigned int x2apic_get_apic_id(unsigned long x) | 312 | static unsigned int x2apic_get_apic_id(unsigned long x) |
diff --git a/arch/x86/platform/uv/uv_irq.c b/arch/x86/platform/uv/uv_irq.c index f25c2765a5c9..dd1ff39a464c 100644 --- a/arch/x86/platform/uv/uv_irq.c +++ b/arch/x86/platform/uv/uv_irq.c | |||
@@ -135,6 +135,7 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade, | |||
135 | unsigned long mmr_value; | 135 | unsigned long mmr_value; |
136 | struct uv_IO_APIC_route_entry *entry; | 136 | struct uv_IO_APIC_route_entry *entry; |
137 | int mmr_pnode, err; | 137 | int mmr_pnode, err; |
138 | unsigned int dest; | ||
138 | 139 | ||
139 | BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != | 140 | BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != |
140 | sizeof(unsigned long)); | 141 | sizeof(unsigned long)); |
@@ -143,6 +144,10 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade, | |||
143 | if (err != 0) | 144 | if (err != 0) |
144 | return err; | 145 | return err; |
145 | 146 | ||
147 | err = apic->cpu_mask_to_apicid(eligible_cpu, &dest); | ||
148 | if (err != 0) | ||
149 | return err; | ||
150 | |||
146 | if (limit == UV_AFFINITY_CPU) | 151 | if (limit == UV_AFFINITY_CPU) |
147 | irq_set_status_flags(irq, IRQ_NO_BALANCING); | 152 | irq_set_status_flags(irq, IRQ_NO_BALANCING); |
148 | else | 153 | else |
@@ -159,7 +164,7 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade, | |||
159 | entry->polarity = 0; | 164 | entry->polarity = 0; |
160 | entry->trigger = 0; | 165 | entry->trigger = 0; |
161 | entry->mask = 0; | 166 | entry->mask = 0; |
162 | entry->dest = apic->cpu_mask_to_apicid(eligible_cpu); | 167 | entry->dest = dest; |
163 | 168 | ||
164 | mmr_pnode = uv_blade_to_pnode(mmr_blade); | 169 | mmr_pnode = uv_blade_to_pnode(mmr_blade); |
165 | uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value); | 170 | uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value); |
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 6d347064b8b0..dafbad06390a 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c | |||
@@ -924,6 +924,7 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, | |||
924 | struct irq_cfg *cfg = data->chip_data; | 924 | struct irq_cfg *cfg = data->chip_data; |
925 | unsigned int dest, irq = data->irq; | 925 | unsigned int dest, irq = data->irq; |
926 | struct irte irte; | 926 | struct irte irte; |
927 | int err; | ||
927 | 928 | ||
928 | if (!cpumask_intersects(mask, cpu_online_mask)) | 929 | if (!cpumask_intersects(mask, cpu_online_mask)) |
929 | return -EINVAL; | 930 | return -EINVAL; |
@@ -931,10 +932,16 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, | |||
931 | if (get_irte(irq, &irte)) | 932 | if (get_irte(irq, &irte)) |
932 | return -EBUSY; | 933 | return -EBUSY; |
933 | 934 | ||
934 | if (assign_irq_vector(irq, cfg, mask)) | 935 | err = assign_irq_vector(irq, cfg, mask); |
935 | return -EBUSY; | 936 | if (err) |
937 | return err; | ||
936 | 938 | ||
937 | dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask); | 939 | err = apic->cpu_mask_to_apicid_and(cfg->domain, mask, &dest); |
940 | if (err) { | ||
941 | if (assign_irq_vector(irq, cfg, data->affinity)); | ||
942 | pr_err("Failed to recover vector for irq %d\n", irq); | ||
943 | return err; | ||
944 | } | ||
938 | 945 | ||
939 | irte.vector = cfg->vector; | 946 | irte.vector = cfg->vector; |
940 | irte.dest_id = IRTE_DEST(dest); | 947 | irte.dest_id = IRTE_DEST(dest); |