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 /arch/x86/kernel/apic/es7000_32.c | |
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>
Diffstat (limited to 'arch/x86/kernel/apic/es7000_32.c')
-rw-r--r-- | arch/x86/kernel/apic/es7000_32.c | 21 |
1 files changed, 12 insertions, 9 deletions
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) |