aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic/x2apic_cluster.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/x2apic_cluster.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/x2apic_cluster.c')
-rw-r--r--arch/x86/kernel/apic/x2apic_cluster.c24
1 files changed, 14 insertions, 10 deletions
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
99static unsigned int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask) 99static int
100x2apic_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
114static unsigned int 115static int
115x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, 116x2apic_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
144static void init_x2apic_ldr(void) 148static void init_x2apic_ldr(void)