diff options
author | Suresh Siddha <suresh.b.siddha@intel.com> | 2009-12-17 21:29:46 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-12-18 01:03:06 -0500 |
commit | 18374d89e5fe96772102f44f535efb1198d9be08 (patch) | |
tree | b289884f86615e01c5e3cccf808ee222e087d681 /arch/x86 | |
parent | 06b5dc646b9479b786d77749936f25910cd82a37 (diff) |
x86, irq: Allow 0xff for /proc/irq/[n]/smp_affinity on an 8-cpu system
John Blackwood reported:
> on an older Dell PowerEdge 6650 system with 8 cpus (4 are hyper-threaded),
> and 32 bit (x86) kernel, once you change the irq smp_affinity of an irq
> to be less than all cpus in the system, you can never change really the
> irq smp_affinity back to be all cpus in the system (0xff) again,
> even though no error status is returned on the "/bin/echo ff >
> /proc/irq/[n]/smp_affinity" operation.
>
> This is due to that fact that BAD_APICID has the same value as
> all cpus (0xff) on 32bit kernels, and thus the value returned from
> set_desc_affinity() via the cpu_mask_to_apicid_and() function is treated
> as a failure in set_ioapic_affinity_irq_desc(), and no affinity changes
> are made.
set_desc_affinity() is already checking if the incoming cpu mask
intersects with the cpu online mask or not. So there is no need
for the apic op cpu_mask_to_apicid_and() to check again
and return BAD_APICID.
Remove the BAD_APICID return value from cpu_mask_to_apicid_and()
and also fix set_desc_affinity() to return -1 instead of using BAD_APICID
to represent error conditions (as cpu_mask_to_apicid_and() can return
logical or physical apicid values and BAD_APICID is really to represent
bad physical apic id).
Reported-by: John Blackwood <john.blackwood@ccur.com>
Root-caused-by: John Blackwood <john.blackwood@ccur.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
LKML-Reference: <1261103386.2535.409.camel@sbs-t61>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/hw_irq.h | 3 | ||||
-rw-r--r-- | arch/x86/kernel/apic/apic_flat_64.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/apic/bigsmp_32.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 32 | ||||
-rw-r--r-- | arch/x86/kernel/apic/x2apic_cluster.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/apic/x2apic_phys.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/apic/x2apic_uv_x.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/uv_irq.c | 3 |
8 files changed, 22 insertions, 41 deletions
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index 08c48a81841f..eeac829a0f44 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h | |||
@@ -103,7 +103,8 @@ extern int assign_irq_vector(int, struct irq_cfg *, const struct cpumask *); | |||
103 | extern void send_cleanup_vector(struct irq_cfg *); | 103 | extern void send_cleanup_vector(struct irq_cfg *); |
104 | 104 | ||
105 | struct irq_desc; | 105 | struct irq_desc; |
106 | extern unsigned int set_desc_affinity(struct irq_desc *, const struct cpumask *); | 106 | extern unsigned int set_desc_affinity(struct irq_desc *, const struct cpumask *, |
107 | unsigned int *dest_id); | ||
107 | extern int IO_APIC_get_PCI_irq_vector(int bus, int devfn, int pin, struct io_apic_irq_attr *irq_attr); | 108 | extern int IO_APIC_get_PCI_irq_vector(int bus, int devfn, int pin, struct io_apic_irq_attr *irq_attr); |
108 | extern void setup_ioapic_dest(void); | 109 | extern void setup_ioapic_dest(void); |
109 | 110 | ||
diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index d0c99abc26c3..eacbd2b31d27 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c | |||
@@ -306,10 +306,7 @@ physflat_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | |||
306 | if (cpumask_test_cpu(cpu, cpu_online_mask)) | 306 | if (cpumask_test_cpu(cpu, cpu_online_mask)) |
307 | break; | 307 | break; |
308 | } | 308 | } |
309 | if (cpu < nr_cpu_ids) | 309 | return per_cpu(x86_cpu_to_apicid, cpu); |
310 | return per_cpu(x86_cpu_to_apicid, cpu); | ||
311 | |||
312 | return BAD_APICID; | ||
313 | } | 310 | } |
314 | 311 | ||
315 | struct apic apic_physflat = { | 312 | struct apic apic_physflat = { |
diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c index 38dcecfa5818..cb804c5091b9 100644 --- a/arch/x86/kernel/apic/bigsmp_32.c +++ b/arch/x86/kernel/apic/bigsmp_32.c | |||
@@ -131,10 +131,7 @@ static unsigned int bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | |||
131 | if (cpumask_test_cpu(cpu, cpu_online_mask)) | 131 | if (cpumask_test_cpu(cpu, cpu_online_mask)) |
132 | break; | 132 | break; |
133 | } | 133 | } |
134 | if (cpu < nr_cpu_ids) | 134 | return bigsmp_cpu_to_logical_apicid(cpu); |
135 | return bigsmp_cpu_to_logical_apicid(cpu); | ||
136 | |||
137 | return BAD_APICID; | ||
138 | } | 135 | } |
139 | 136 | ||
140 | static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb) | 137 | static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb) |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index d5d498fbee4b..98ced709e829 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -2276,26 +2276,28 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq | |||
2276 | 2276 | ||
2277 | /* | 2277 | /* |
2278 | * Either sets desc->affinity to a valid value, and returns | 2278 | * Either sets desc->affinity to a valid value, and returns |
2279 | * ->cpu_mask_to_apicid of that, or returns BAD_APICID and | 2279 | * ->cpu_mask_to_apicid of that in dest_id, or returns -1 and |
2280 | * leaves desc->affinity untouched. | 2280 | * leaves desc->affinity untouched. |
2281 | */ | 2281 | */ |
2282 | unsigned int | 2282 | unsigned int |
2283 | set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask) | 2283 | set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask, |
2284 | unsigned int *dest_id) | ||
2284 | { | 2285 | { |
2285 | struct irq_cfg *cfg; | 2286 | struct irq_cfg *cfg; |
2286 | unsigned int irq; | 2287 | unsigned int irq; |
2287 | 2288 | ||
2288 | if (!cpumask_intersects(mask, cpu_online_mask)) | 2289 | if (!cpumask_intersects(mask, cpu_online_mask)) |
2289 | return BAD_APICID; | 2290 | return -1; |
2290 | 2291 | ||
2291 | irq = desc->irq; | 2292 | irq = desc->irq; |
2292 | cfg = desc->chip_data; | 2293 | cfg = desc->chip_data; |
2293 | if (assign_irq_vector(irq, cfg, mask)) | 2294 | if (assign_irq_vector(irq, cfg, mask)) |
2294 | return BAD_APICID; | 2295 | return -1; |
2295 | 2296 | ||
2296 | cpumask_copy(desc->affinity, mask); | 2297 | cpumask_copy(desc->affinity, mask); |
2297 | 2298 | ||
2298 | return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain); | 2299 | *dest_id = apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain); |
2300 | return 0; | ||
2299 | } | 2301 | } |
2300 | 2302 | ||
2301 | static int | 2303 | static int |
@@ -2311,12 +2313,11 @@ set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask) | |||
2311 | cfg = desc->chip_data; | 2313 | cfg = desc->chip_data; |
2312 | 2314 | ||
2313 | spin_lock_irqsave(&ioapic_lock, flags); | 2315 | spin_lock_irqsave(&ioapic_lock, flags); |
2314 | dest = set_desc_affinity(desc, mask); | 2316 | ret = set_desc_affinity(desc, mask, &dest); |
2315 | if (dest != BAD_APICID) { | 2317 | if (!ret) { |
2316 | /* Only the high 8 bits are valid. */ | 2318 | /* Only the high 8 bits are valid. */ |
2317 | dest = SET_APIC_LOGICAL_ID(dest); | 2319 | dest = SET_APIC_LOGICAL_ID(dest); |
2318 | __target_IO_APIC_irq(irq, dest, cfg); | 2320 | __target_IO_APIC_irq(irq, dest, cfg); |
2319 | ret = 0; | ||
2320 | } | 2321 | } |
2321 | spin_unlock_irqrestore(&ioapic_lock, flags); | 2322 | spin_unlock_irqrestore(&ioapic_lock, flags); |
2322 | 2323 | ||
@@ -3351,8 +3352,7 @@ static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask) | |||
3351 | struct msi_msg msg; | 3352 | struct msi_msg msg; |
3352 | unsigned int dest; | 3353 | unsigned int dest; |
3353 | 3354 | ||
3354 | dest = set_desc_affinity(desc, mask); | 3355 | if (set_desc_affinity(desc, mask, &dest)) |
3355 | if (dest == BAD_APICID) | ||
3356 | return -1; | 3356 | return -1; |
3357 | 3357 | ||
3358 | cfg = desc->chip_data; | 3358 | cfg = desc->chip_data; |
@@ -3384,8 +3384,7 @@ ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask) | |||
3384 | if (get_irte(irq, &irte)) | 3384 | if (get_irte(irq, &irte)) |
3385 | return -1; | 3385 | return -1; |
3386 | 3386 | ||
3387 | dest = set_desc_affinity(desc, mask); | 3387 | if (set_desc_affinity(desc, mask, &dest)) |
3388 | if (dest == BAD_APICID) | ||
3389 | return -1; | 3388 | return -1; |
3390 | 3389 | ||
3391 | irte.vector = cfg->vector; | 3390 | irte.vector = cfg->vector; |
@@ -3567,8 +3566,7 @@ static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask) | |||
3567 | struct msi_msg msg; | 3566 | struct msi_msg msg; |
3568 | unsigned int dest; | 3567 | unsigned int dest; |
3569 | 3568 | ||
3570 | dest = set_desc_affinity(desc, mask); | 3569 | if (set_desc_affinity(desc, mask, &dest)) |
3571 | if (dest == BAD_APICID) | ||
3572 | return -1; | 3570 | return -1; |
3573 | 3571 | ||
3574 | cfg = desc->chip_data; | 3572 | cfg = desc->chip_data; |
@@ -3623,8 +3621,7 @@ static int hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask) | |||
3623 | struct msi_msg msg; | 3621 | struct msi_msg msg; |
3624 | unsigned int dest; | 3622 | unsigned int dest; |
3625 | 3623 | ||
3626 | dest = set_desc_affinity(desc, mask); | 3624 | if (set_desc_affinity(desc, mask, &dest)) |
3627 | if (dest == BAD_APICID) | ||
3628 | return -1; | 3625 | return -1; |
3629 | 3626 | ||
3630 | cfg = desc->chip_data; | 3627 | cfg = desc->chip_data; |
@@ -3730,8 +3727,7 @@ static int set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask) | |||
3730 | struct irq_cfg *cfg; | 3727 | struct irq_cfg *cfg; |
3731 | unsigned int dest; | 3728 | unsigned int dest; |
3732 | 3729 | ||
3733 | dest = set_desc_affinity(desc, mask); | 3730 | if (set_desc_affinity(desc, mask, &dest)) |
3734 | if (dest == BAD_APICID) | ||
3735 | return -1; | 3731 | return -1; |
3736 | 3732 | ||
3737 | cfg = desc->chip_data; | 3733 | cfg = desc->chip_data; |
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index a5371ec36776..cf69c59f4910 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c | |||
@@ -148,10 +148,7 @@ x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | |||
148 | break; | 148 | break; |
149 | } | 149 | } |
150 | 150 | ||
151 | if (cpu < nr_cpu_ids) | 151 | return per_cpu(x86_cpu_to_logical_apicid, cpu); |
152 | return per_cpu(x86_cpu_to_logical_apicid, cpu); | ||
153 | |||
154 | return BAD_APICID; | ||
155 | } | 152 | } |
156 | 153 | ||
157 | static unsigned int x2apic_cluster_phys_get_apic_id(unsigned long x) | 154 | static unsigned int x2apic_cluster_phys_get_apic_id(unsigned long x) |
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index a8989aadc99a..8972f38c5ced 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c | |||
@@ -146,10 +146,7 @@ x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | |||
146 | break; | 146 | break; |
147 | } | 147 | } |
148 | 148 | ||
149 | if (cpu < nr_cpu_ids) | 149 | return per_cpu(x86_cpu_to_apicid, cpu); |
150 | return per_cpu(x86_cpu_to_apicid, cpu); | ||
151 | |||
152 | return BAD_APICID; | ||
153 | } | 150 | } |
154 | 151 | ||
155 | static unsigned int x2apic_phys_get_apic_id(unsigned long x) | 152 | static unsigned int x2apic_phys_get_apic_id(unsigned long x) |
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index b684bb303cbf..d56b0efb2057 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c | |||
@@ -225,10 +225,7 @@ uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | |||
225 | if (cpumask_test_cpu(cpu, cpu_online_mask)) | 225 | if (cpumask_test_cpu(cpu, cpu_online_mask)) |
226 | break; | 226 | break; |
227 | } | 227 | } |
228 | if (cpu < nr_cpu_ids) | 228 | return per_cpu(x86_cpu_to_apicid, cpu); |
229 | return per_cpu(x86_cpu_to_apicid, cpu); | ||
230 | |||
231 | return BAD_APICID; | ||
232 | } | 229 | } |
233 | 230 | ||
234 | static unsigned int x2apic_get_apic_id(unsigned long x) | 231 | static unsigned int x2apic_get_apic_id(unsigned long x) |
diff --git a/arch/x86/kernel/uv_irq.c b/arch/x86/kernel/uv_irq.c index 61d805df4c91..ece73d8e3240 100644 --- a/arch/x86/kernel/uv_irq.c +++ b/arch/x86/kernel/uv_irq.c | |||
@@ -215,8 +215,7 @@ static int uv_set_irq_affinity(unsigned int irq, const struct cpumask *mask) | |||
215 | unsigned long mmr_offset; | 215 | unsigned long mmr_offset; |
216 | unsigned mmr_pnode; | 216 | unsigned mmr_pnode; |
217 | 217 | ||
218 | dest = set_desc_affinity(desc, mask); | 218 | if (set_desc_affinity(desc, mask, &dest)) |
219 | if (dest == BAD_APICID) | ||
220 | return -1; | 219 | return -1; |
221 | 220 | ||
222 | mmr_value = 0; | 221 | mmr_value = 0; |