aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic/apic.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/apic.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/apic.c')
-rw-r--r--arch/x86/kernel/apic/apic.c33
1 files changed, 18 insertions, 15 deletions
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
2126unsigned int default_cpu_mask_to_apicid(const struct cpumask *cpumask) 2126static 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; 2136int 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
2141unsigned int 2143int default_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
2142default_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/*