aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic/io_apic.c
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2009-12-17 21:29:46 -0500
committerH. Peter Anvin <hpa@zytor.com>2009-12-18 01:03:06 -0500
commit18374d89e5fe96772102f44f535efb1198d9be08 (patch)
treeb289884f86615e01c5e3cccf808ee222e087d681 /arch/x86/kernel/apic/io_apic.c
parent06b5dc646b9479b786d77749936f25910cd82a37 (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/kernel/apic/io_apic.c')
-rw-r--r--arch/x86/kernel/apic/io_apic.c32
1 files changed, 14 insertions, 18 deletions
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 */
2282unsigned int 2282unsigned int
2283set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask) 2283set_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
2301static int 2303static 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;