diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2006-10-08 09:47:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-08 15:24:02 -0400 |
commit | c7111c1318ee8890f385813f232fdb32643e2653 (patch) | |
tree | e21f8ee81f45f0c127a6233ed77d8052615d1fc8 /arch/x86_64/kernel/genapic_flat.c | |
parent | b940d22d58c41b2ae491dca9232850f6f38f3653 (diff) |
[PATCH] x86_64 irq: Allocate a vector across all cpus for genapic_flat.
The problem we can't take advantage of lowest priority delivery mode if
the vectors are allocated for only one cpu at a time. Nor can we work
around hardware that assumes lowest priority delivery mode is always
used with several cpus.
So this patch introduces the concept of a vector_allocation_domain. A
set of cpus that will receive an irq on the same vector. Currently the
code for implementing this is placed in the genapic structure so we can
vary this depending on how we are using the io_apics.
This allows us to restore the previous behaviour of genapic_flat without
removing the benefits of having separate vector allocation for large
machines.
This should also fix the problem report where a hyperthreaded cpu was
receving the irq on the wrong hyperthread when in logical delivery mode
because the previous behaviour is restored.
This patch properly records our allocation of the first 16 irqs to the
first 16 available vectors on all cpus. This should be fine but it may
run into problems with multiple interrupts at the same interrupt level.
Except for some badly maintained comments in the code and the behaviour
of the interrupt allocator I have no real understanding of that problem.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Acked-by: Muli Ben-Yehuda <muli@il.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/x86_64/kernel/genapic_flat.c')
-rw-r--r-- | arch/x86_64/kernel/genapic_flat.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/arch/x86_64/kernel/genapic_flat.c b/arch/x86_64/kernel/genapic_flat.c index 50ad153eaac4..0dfc223c1839 100644 --- a/arch/x86_64/kernel/genapic_flat.c +++ b/arch/x86_64/kernel/genapic_flat.c | |||
@@ -22,6 +22,20 @@ static cpumask_t flat_target_cpus(void) | |||
22 | return cpu_online_map; | 22 | return cpu_online_map; |
23 | } | 23 | } |
24 | 24 | ||
25 | static cpumask_t flat_vector_allocation_domain(int cpu) | ||
26 | { | ||
27 | /* Careful. Some cpus do not strictly honor the set of cpus | ||
28 | * specified in the interrupt destination when using lowest | ||
29 | * priority interrupt delivery mode. | ||
30 | * | ||
31 | * In particular there was a hyperthreading cpu observed to | ||
32 | * deliver interrupts to the wrong hyperthread when only one | ||
33 | * hyperthread was specified in the interrupt desitination. | ||
34 | */ | ||
35 | cpumask_t domain = { { [0] = APIC_ALL_CPUS, } }; | ||
36 | return domain; | ||
37 | } | ||
38 | |||
25 | /* | 39 | /* |
26 | * Set up the logical destination ID. | 40 | * Set up the logical destination ID. |
27 | * | 41 | * |
@@ -121,6 +135,7 @@ struct genapic apic_flat = { | |||
121 | .int_delivery_mode = dest_LowestPrio, | 135 | .int_delivery_mode = dest_LowestPrio, |
122 | .int_dest_mode = (APIC_DEST_LOGICAL != 0), | 136 | .int_dest_mode = (APIC_DEST_LOGICAL != 0), |
123 | .target_cpus = flat_target_cpus, | 137 | .target_cpus = flat_target_cpus, |
138 | .vector_allocation_domain = flat_vector_allocation_domain, | ||
124 | .apic_id_registered = flat_apic_id_registered, | 139 | .apic_id_registered = flat_apic_id_registered, |
125 | .init_apic_ldr = flat_init_apic_ldr, | 140 | .init_apic_ldr = flat_init_apic_ldr, |
126 | .send_IPI_all = flat_send_IPI_all, | 141 | .send_IPI_all = flat_send_IPI_all, |
@@ -141,6 +156,14 @@ static cpumask_t physflat_target_cpus(void) | |||
141 | return cpumask_of_cpu(0); | 156 | return cpumask_of_cpu(0); |
142 | } | 157 | } |
143 | 158 | ||
159 | static cpumask_t physflat_vector_allocation_domain(int cpu) | ||
160 | { | ||
161 | cpumask_t domain = CPU_MASK_NONE; | ||
162 | cpu_set(cpu, domain); | ||
163 | return domain; | ||
164 | } | ||
165 | |||
166 | |||
144 | static void physflat_send_IPI_mask(cpumask_t cpumask, int vector) | 167 | static void physflat_send_IPI_mask(cpumask_t cpumask, int vector) |
145 | { | 168 | { |
146 | send_IPI_mask_sequence(cpumask, vector); | 169 | send_IPI_mask_sequence(cpumask, vector); |
@@ -179,6 +202,7 @@ struct genapic apic_physflat = { | |||
179 | .int_delivery_mode = dest_Fixed, | 202 | .int_delivery_mode = dest_Fixed, |
180 | .int_dest_mode = (APIC_DEST_PHYSICAL != 0), | 203 | .int_dest_mode = (APIC_DEST_PHYSICAL != 0), |
181 | .target_cpus = physflat_target_cpus, | 204 | .target_cpus = physflat_target_cpus, |
205 | .vector_allocation_domain = physflat_vector_allocation_domain, | ||
182 | .apic_id_registered = flat_apic_id_registered, | 206 | .apic_id_registered = flat_apic_id_registered, |
183 | .init_apic_ldr = flat_init_apic_ldr,/*not needed, but shouldn't hurt*/ | 207 | .init_apic_ldr = flat_init_apic_ldr,/*not needed, but shouldn't hurt*/ |
184 | .send_IPI_all = physflat_send_IPI_all, | 208 | .send_IPI_all = physflat_send_IPI_all, |