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>
This commit is contained in:
		
					parent
					
						
							
								06b5dc646b
							
						
					
				
			
			
				commit
				
					
						18374d89e5
					
				
			
		
					 8 changed files with 22 additions and 41 deletions
				
			
		|  | @ -103,7 +103,8 @@ extern int assign_irq_vector(int, struct irq_cfg *, const struct cpumask *); | ||||||
| extern void send_cleanup_vector(struct irq_cfg *); | extern void send_cleanup_vector(struct irq_cfg *); | ||||||
| 
 | 
 | ||||||
| struct irq_desc; | struct irq_desc; | ||||||
| extern unsigned int set_desc_affinity(struct irq_desc *, const struct cpumask *); | extern unsigned int set_desc_affinity(struct irq_desc *, const struct cpumask *, | ||||||
|  | 				      unsigned int *dest_id); | ||||||
| extern int IO_APIC_get_PCI_irq_vector(int bus, int devfn, int pin, struct io_apic_irq_attr *irq_attr); | extern int IO_APIC_get_PCI_irq_vector(int bus, int devfn, int pin, struct io_apic_irq_attr *irq_attr); | ||||||
| extern void setup_ioapic_dest(void); | extern void setup_ioapic_dest(void); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -306,10 +306,7 @@ physflat_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | ||||||
| 		if (cpumask_test_cpu(cpu, cpu_online_mask)) | 		if (cpumask_test_cpu(cpu, cpu_online_mask)) | ||||||
| 			break; | 			break; | ||||||
| 	} | 	} | ||||||
| 	if (cpu < nr_cpu_ids) |  | ||||||
| 	return per_cpu(x86_cpu_to_apicid, cpu); | 	return per_cpu(x86_cpu_to_apicid, cpu); | ||||||
| 
 |  | ||||||
| 	return BAD_APICID; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct apic apic_physflat =  { | struct apic apic_physflat =  { | ||||||
|  |  | ||||||
|  | @ -131,10 +131,7 @@ static unsigned int bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | ||||||
| 		if (cpumask_test_cpu(cpu, cpu_online_mask)) | 		if (cpumask_test_cpu(cpu, cpu_online_mask)) | ||||||
| 			break; | 			break; | ||||||
| 	} | 	} | ||||||
| 	if (cpu < nr_cpu_ids) |  | ||||||
| 	return bigsmp_cpu_to_logical_apicid(cpu); | 	return bigsmp_cpu_to_logical_apicid(cpu); | ||||||
| 
 |  | ||||||
| 	return BAD_APICID; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb) | static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb) | ||||||
|  |  | ||||||
|  | @ -2276,26 +2276,28 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Either sets desc->affinity to a valid value, and returns |  * Either sets desc->affinity to a valid value, and returns | ||||||
|  * ->cpu_mask_to_apicid of that, or returns BAD_APICID and |  * ->cpu_mask_to_apicid of that in dest_id, or returns -1 and | ||||||
|  * leaves desc->affinity untouched. |  * leaves desc->affinity untouched. | ||||||
|  */ |  */ | ||||||
| unsigned int | unsigned int | ||||||
| set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask) | set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask, | ||||||
|  | 		  unsigned int *dest_id) | ||||||
| { | { | ||||||
| 	struct irq_cfg *cfg; | 	struct irq_cfg *cfg; | ||||||
| 	unsigned int irq; | 	unsigned int irq; | ||||||
| 
 | 
 | ||||||
| 	if (!cpumask_intersects(mask, cpu_online_mask)) | 	if (!cpumask_intersects(mask, cpu_online_mask)) | ||||||
| 		return BAD_APICID; | 		return -1; | ||||||
| 
 | 
 | ||||||
| 	irq = desc->irq; | 	irq = desc->irq; | ||||||
| 	cfg = desc->chip_data; | 	cfg = desc->chip_data; | ||||||
| 	if (assign_irq_vector(irq, cfg, mask)) | 	if (assign_irq_vector(irq, cfg, mask)) | ||||||
| 		return BAD_APICID; | 		return -1; | ||||||
| 
 | 
 | ||||||
| 	cpumask_copy(desc->affinity, mask); | 	cpumask_copy(desc->affinity, mask); | ||||||
| 
 | 
 | ||||||
| 	return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain); | 	*dest_id = apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain); | ||||||
|  | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
|  | @ -2311,12 +2313,11 @@ set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask) | ||||||
| 	cfg = desc->chip_data; | 	cfg = desc->chip_data; | ||||||
| 
 | 
 | ||||||
| 	spin_lock_irqsave(&ioapic_lock, flags); | 	spin_lock_irqsave(&ioapic_lock, flags); | ||||||
| 	dest = set_desc_affinity(desc, mask); | 	ret = set_desc_affinity(desc, mask, &dest); | ||||||
| 	if (dest != BAD_APICID) { | 	if (!ret) { | ||||||
| 		/* Only the high 8 bits are valid. */ | 		/* Only the high 8 bits are valid. */ | ||||||
| 		dest = SET_APIC_LOGICAL_ID(dest); | 		dest = SET_APIC_LOGICAL_ID(dest); | ||||||
| 		__target_IO_APIC_irq(irq, dest, cfg); | 		__target_IO_APIC_irq(irq, dest, cfg); | ||||||
| 		ret = 0; |  | ||||||
| 	} | 	} | ||||||
| 	spin_unlock_irqrestore(&ioapic_lock, flags); | 	spin_unlock_irqrestore(&ioapic_lock, flags); | ||||||
| 
 | 
 | ||||||
|  | @ -3351,8 +3352,7 @@ static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask) | ||||||
| 	struct msi_msg msg; | 	struct msi_msg msg; | ||||||
| 	unsigned int dest; | 	unsigned int dest; | ||||||
| 
 | 
 | ||||||
| 	dest = set_desc_affinity(desc, mask); | 	if (set_desc_affinity(desc, mask, &dest)) | ||||||
| 	if (dest == BAD_APICID) |  | ||||||
| 		return -1; | 		return -1; | ||||||
| 
 | 
 | ||||||
| 	cfg = desc->chip_data; | 	cfg = desc->chip_data; | ||||||
|  | @ -3384,8 +3384,7 @@ ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask) | ||||||
| 	if (get_irte(irq, &irte)) | 	if (get_irte(irq, &irte)) | ||||||
| 		return -1; | 		return -1; | ||||||
| 
 | 
 | ||||||
| 	dest = set_desc_affinity(desc, mask); | 	if (set_desc_affinity(desc, mask, &dest)) | ||||||
| 	if (dest == BAD_APICID) |  | ||||||
| 		return -1; | 		return -1; | ||||||
| 
 | 
 | ||||||
| 	irte.vector = cfg->vector; | 	irte.vector = cfg->vector; | ||||||
|  | @ -3567,8 +3566,7 @@ static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask) | ||||||
| 	struct msi_msg msg; | 	struct msi_msg msg; | ||||||
| 	unsigned int dest; | 	unsigned int dest; | ||||||
| 
 | 
 | ||||||
| 	dest = set_desc_affinity(desc, mask); | 	if (set_desc_affinity(desc, mask, &dest)) | ||||||
| 	if (dest == BAD_APICID) |  | ||||||
| 		return -1; | 		return -1; | ||||||
| 
 | 
 | ||||||
| 	cfg = desc->chip_data; | 	cfg = desc->chip_data; | ||||||
|  | @ -3623,8 +3621,7 @@ static int hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask) | ||||||
| 	struct msi_msg msg; | 	struct msi_msg msg; | ||||||
| 	unsigned int dest; | 	unsigned int dest; | ||||||
| 
 | 
 | ||||||
| 	dest = set_desc_affinity(desc, mask); | 	if (set_desc_affinity(desc, mask, &dest)) | ||||||
| 	if (dest == BAD_APICID) |  | ||||||
| 		return -1; | 		return -1; | ||||||
| 
 | 
 | ||||||
| 	cfg = desc->chip_data; | 	cfg = desc->chip_data; | ||||||
|  | @ -3730,8 +3727,7 @@ static int set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask) | ||||||
| 	struct irq_cfg *cfg; | 	struct irq_cfg *cfg; | ||||||
| 	unsigned int dest; | 	unsigned int dest; | ||||||
| 
 | 
 | ||||||
| 	dest = set_desc_affinity(desc, mask); | 	if (set_desc_affinity(desc, mask, &dest)) | ||||||
| 	if (dest == BAD_APICID) |  | ||||||
| 		return -1; | 		return -1; | ||||||
| 
 | 
 | ||||||
| 	cfg = desc->chip_data; | 	cfg = desc->chip_data; | ||||||
|  |  | ||||||
|  | @ -148,10 +148,7 @@ x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | ||||||
| 			break; | 			break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (cpu < nr_cpu_ids) |  | ||||||
| 	return per_cpu(x86_cpu_to_logical_apicid, cpu); | 	return per_cpu(x86_cpu_to_logical_apicid, cpu); | ||||||
| 
 |  | ||||||
| 	return BAD_APICID; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static unsigned int x2apic_cluster_phys_get_apic_id(unsigned long x) | static unsigned int x2apic_cluster_phys_get_apic_id(unsigned long x) | ||||||
|  |  | ||||||
|  | @ -146,10 +146,7 @@ x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | ||||||
| 			break; | 			break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (cpu < nr_cpu_ids) |  | ||||||
| 	return per_cpu(x86_cpu_to_apicid, cpu); | 	return per_cpu(x86_cpu_to_apicid, cpu); | ||||||
| 
 |  | ||||||
| 	return BAD_APICID; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static unsigned int x2apic_phys_get_apic_id(unsigned long x) | static unsigned int x2apic_phys_get_apic_id(unsigned long x) | ||||||
|  |  | ||||||
|  | @ -225,10 +225,7 @@ uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | ||||||
| 		if (cpumask_test_cpu(cpu, cpu_online_mask)) | 		if (cpumask_test_cpu(cpu, cpu_online_mask)) | ||||||
| 			break; | 			break; | ||||||
| 	} | 	} | ||||||
| 	if (cpu < nr_cpu_ids) |  | ||||||
| 	return per_cpu(x86_cpu_to_apicid, cpu); | 	return per_cpu(x86_cpu_to_apicid, cpu); | ||||||
| 
 |  | ||||||
| 	return BAD_APICID; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static unsigned int x2apic_get_apic_id(unsigned long x) | static unsigned int x2apic_get_apic_id(unsigned long x) | ||||||
|  |  | ||||||
|  | @ -215,8 +215,7 @@ static int uv_set_irq_affinity(unsigned int irq, const struct cpumask *mask) | ||||||
| 	unsigned long mmr_offset; | 	unsigned long mmr_offset; | ||||||
| 	unsigned mmr_pnode; | 	unsigned mmr_pnode; | ||||||
| 
 | 
 | ||||||
| 	dest = set_desc_affinity(desc, mask); | 	if (set_desc_affinity(desc, mask, &dest)) | ||||||
| 	if (dest == BAD_APICID) |  | ||||||
| 		return -1; | 		return -1; | ||||||
| 
 | 
 | ||||||
| 	mmr_value = 0; | 	mmr_value = 0; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Suresh Siddha
				Suresh Siddha