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 *); | ||||
| 
 | ||||
| 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 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)) | ||||
| 			break; | ||||
| 	} | ||||
| 	if (cpu < nr_cpu_ids) | ||||
| 		return per_cpu(x86_cpu_to_apicid, cpu); | ||||
| 
 | ||||
| 	return BAD_APICID; | ||||
| 	return per_cpu(x86_cpu_to_apicid, cpu); | ||||
| } | ||||
| 
 | ||||
| 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)) | ||||
| 			break; | ||||
| 	} | ||||
| 	if (cpu < nr_cpu_ids) | ||||
| 		return bigsmp_cpu_to_logical_apicid(cpu); | ||||
| 
 | ||||
| 	return BAD_APICID; | ||||
| 	return bigsmp_cpu_to_logical_apicid(cpu); | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
|  * ->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. | ||||
|  */ | ||||
| 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; | ||||
| 	unsigned int irq; | ||||
| 
 | ||||
| 	if (!cpumask_intersects(mask, cpu_online_mask)) | ||||
| 		return BAD_APICID; | ||||
| 		return -1; | ||||
| 
 | ||||
| 	irq = desc->irq; | ||||
| 	cfg = desc->chip_data; | ||||
| 	if (assign_irq_vector(irq, cfg, mask)) | ||||
| 		return BAD_APICID; | ||||
| 		return -1; | ||||
| 
 | ||||
| 	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 | ||||
|  | @ -2311,12 +2313,11 @@ set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask) | |||
| 	cfg = desc->chip_data; | ||||
| 
 | ||||
| 	spin_lock_irqsave(&ioapic_lock, flags); | ||||
| 	dest = set_desc_affinity(desc, mask); | ||||
| 	if (dest != BAD_APICID) { | ||||
| 	ret = set_desc_affinity(desc, mask, &dest); | ||||
| 	if (!ret) { | ||||
| 		/* Only the high 8 bits are valid. */ | ||||
| 		dest = SET_APIC_LOGICAL_ID(dest); | ||||
| 		__target_IO_APIC_irq(irq, dest, cfg); | ||||
| 		ret = 0; | ||||
| 	} | ||||
| 	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; | ||||
| 	unsigned int dest; | ||||
| 
 | ||||
| 	dest = set_desc_affinity(desc, mask); | ||||
| 	if (dest == BAD_APICID) | ||||
| 	if (set_desc_affinity(desc, mask, &dest)) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	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)) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	dest = set_desc_affinity(desc, mask); | ||||
| 	if (dest == BAD_APICID) | ||||
| 	if (set_desc_affinity(desc, mask, &dest)) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	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; | ||||
| 	unsigned int dest; | ||||
| 
 | ||||
| 	dest = set_desc_affinity(desc, mask); | ||||
| 	if (dest == BAD_APICID) | ||||
| 	if (set_desc_affinity(desc, mask, &dest)) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	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; | ||||
| 	unsigned int dest; | ||||
| 
 | ||||
| 	dest = set_desc_affinity(desc, mask); | ||||
| 	if (dest == BAD_APICID) | ||||
| 	if (set_desc_affinity(desc, mask, &dest)) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	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; | ||||
| 	unsigned int dest; | ||||
| 
 | ||||
| 	dest = set_desc_affinity(desc, mask); | ||||
| 	if (dest == BAD_APICID) | ||||
| 	if (set_desc_affinity(desc, mask, &dest)) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	cfg = desc->chip_data; | ||||
|  |  | |||
|  | @ -148,10 +148,7 @@ x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | |||
| 			break; | ||||
| 	} | ||||
| 
 | ||||
| 	if (cpu < nr_cpu_ids) | ||||
| 		return per_cpu(x86_cpu_to_logical_apicid, cpu); | ||||
| 
 | ||||
| 	return BAD_APICID; | ||||
| 	return per_cpu(x86_cpu_to_logical_apicid, cpu); | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| 	} | ||||
| 
 | ||||
| 	if (cpu < nr_cpu_ids) | ||||
| 		return per_cpu(x86_cpu_to_apicid, cpu); | ||||
| 
 | ||||
| 	return BAD_APICID; | ||||
| 	return per_cpu(x86_cpu_to_apicid, cpu); | ||||
| } | ||||
| 
 | ||||
| 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)) | ||||
| 			break; | ||||
| 	} | ||||
| 	if (cpu < nr_cpu_ids) | ||||
| 		return per_cpu(x86_cpu_to_apicid, cpu); | ||||
| 
 | ||||
| 	return BAD_APICID; | ||||
| 	return per_cpu(x86_cpu_to_apicid, cpu); | ||||
| } | ||||
| 
 | ||||
| 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 mmr_pnode; | ||||
| 
 | ||||
| 	dest = set_desc_affinity(desc, mask); | ||||
| 	if (dest == BAD_APICID) | ||||
| 	if (set_desc_affinity(desc, mask, &dest)) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	mmr_value = 0; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Suresh Siddha
				Suresh Siddha