aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic/es7000_32.c
diff options
context:
space:
mode:
authorAlexander Gordeev <agordeev@redhat.com>2012-06-07 09:15:59 -0400
committerIngo Molnar <mingo@kernel.org>2012-06-08 05:44:29 -0400
commitff164324123c0fe181d8de7dadcc7b3fbe25f2cf (patch)
tree110c0250f795bc2b71495566b3ead098b8b1a89b /arch/x86/kernel/apic/es7000_32.c
parent8637e38aff14d048b649075114023023a2e80fba (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.c21
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
528static unsigned int es7000_cpu_mask_to_apicid(const struct cpumask *cpumask) 528static int
529es7000_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
550static unsigned int 552static int
551es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask, 553es7000_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
569static int es7000_phys_pkg_id(int cpuid_apic, int index_msb) 572static int es7000_phys_pkg_id(int cpuid_apic, int index_msb)