diff options
Diffstat (limited to 'arch/x86/kernel/apic/io_apic.c')
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 915 | 
1 files changed, 457 insertions, 458 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 30da617d18e..b7a79207295 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -59,6 +59,7 @@  #include <asm/setup.h>  #include <asm/irq_remapping.h>  #include <asm/hpet.h> +#include <asm/hw_irq.h>  #include <asm/uv/uv_hub.h>  #include <asm/uv/uv_irq.h> @@ -129,12 +130,9 @@ struct irq_pin_list {  	struct irq_pin_list *next;  }; -static struct irq_pin_list *get_one_free_irq_2_pin(int cpu) +static struct irq_pin_list *get_one_free_irq_2_pin(int node)  {  	struct irq_pin_list *pin; -	int node; - -	node = cpu_to_node(cpu);  	pin = kzalloc_node(sizeof(*pin), GFP_ATOMIC, node); @@ -148,9 +146,6 @@ struct irq_cfg {  	unsigned move_cleanup_count;  	u8 vector;  	u8 move_in_progress : 1; -#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC -	u8 move_desc_pending : 1; -#endif  };  /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ @@ -182,16 +177,18 @@ int __init arch_early_irq_init(void)  	struct irq_cfg *cfg;  	struct irq_desc *desc;  	int count; +	int node;  	int i;  	cfg = irq_cfgx;  	count = ARRAY_SIZE(irq_cfgx); +	node= cpu_to_node(boot_cpu_id);  	for (i = 0; i < count; i++) {  		desc = irq_to_desc(i);  		desc->chip_data = &cfg[i]; -		alloc_bootmem_cpumask_var(&cfg[i].domain); -		alloc_bootmem_cpumask_var(&cfg[i].old_domain); +		zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node); +		zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_NOWAIT, node);  		if (i < NR_IRQS_LEGACY)  			cpumask_setall(cfg[i].domain);  	} @@ -212,12 +209,9 @@ static struct irq_cfg *irq_cfg(unsigned int irq)  	return cfg;  } -static struct irq_cfg *get_one_free_irq_cfg(int cpu) +static struct irq_cfg *get_one_free_irq_cfg(int node)  {  	struct irq_cfg *cfg; -	int node; - -	node = cpu_to_node(cpu);  	cfg = kzalloc_node(sizeof(*cfg), GFP_ATOMIC, node);  	if (cfg) { @@ -238,13 +232,13 @@ static struct irq_cfg *get_one_free_irq_cfg(int cpu)  	return cfg;  } -int arch_init_chip_data(struct irq_desc *desc, int cpu) +int arch_init_chip_data(struct irq_desc *desc, int node)  {  	struct irq_cfg *cfg;  	cfg = desc->chip_data;  	if (!cfg) { -		desc->chip_data = get_one_free_irq_cfg(cpu); +		desc->chip_data = get_one_free_irq_cfg(node);  		if (!desc->chip_data) {  			printk(KERN_ERR "can not alloc irq_cfg\n");  			BUG_ON(1); @@ -254,10 +248,9 @@ int arch_init_chip_data(struct irq_desc *desc, int cpu)  	return 0;  } -#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC - +/* for move_irq_desc */  static void -init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int cpu) +init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int node)  {  	struct irq_pin_list *old_entry, *head, *tail, *entry; @@ -266,7 +259,7 @@ init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int cpu)  	if (!old_entry)  		return; -	entry = get_one_free_irq_2_pin(cpu); +	entry = get_one_free_irq_2_pin(node);  	if (!entry)  		return; @@ -276,7 +269,7 @@ init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int cpu)  	tail		= entry;  	old_entry	= old_entry->next;  	while (old_entry) { -		entry = get_one_free_irq_2_pin(cpu); +		entry = get_one_free_irq_2_pin(node);  		if (!entry) {  			entry = head;  			while (entry) { @@ -316,12 +309,12 @@ static void free_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg)  }  void arch_init_copy_chip_data(struct irq_desc *old_desc, -				 struct irq_desc *desc, int cpu) +				 struct irq_desc *desc, int node)  {  	struct irq_cfg *cfg;  	struct irq_cfg *old_cfg; -	cfg = get_one_free_irq_cfg(cpu); +	cfg = get_one_free_irq_cfg(node);  	if (!cfg)  		return; @@ -332,7 +325,7 @@ void arch_init_copy_chip_data(struct irq_desc *old_desc,  	memcpy(cfg, old_cfg, sizeof(struct irq_cfg)); -	init_copy_irq_2_pin(old_cfg, cfg, cpu); +	init_copy_irq_2_pin(old_cfg, cfg, node);  }  static void free_irq_cfg(struct irq_cfg *old_cfg) @@ -356,19 +349,7 @@ void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)  		old_desc->chip_data = NULL;  	}  } - -static void -set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask) -{ -	struct irq_cfg *cfg = desc->chip_data; - -	if (!cfg->move_in_progress) { -		/* it means that domain is not changed */ -		if (!cpumask_intersects(desc->affinity, mask)) -			cfg->move_desc_pending = 1; -	} -} -#endif +/* end for move_irq_desc */  #else  static struct irq_cfg *irq_cfg(unsigned int irq) @@ -378,13 +359,6 @@ static struct irq_cfg *irq_cfg(unsigned int irq)  #endif -#ifndef CONFIG_NUMA_MIGRATE_IRQ_DESC -static inline void -set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask) -{ -} -#endif -  struct io_apic {  	unsigned int index;  	unsigned int unused[3]; @@ -488,7 +462,8 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)  static void  __ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)  { -	union entry_union eu; +	union entry_union eu = {{0, 0}}; +  	eu.entry = e;  	io_apic_write(apic, 0x11 + 2*pin, eu.w2);  	io_apic_write(apic, 0x10 + 2*pin, eu.w1); @@ -518,132 +493,18 @@ static void ioapic_mask_entry(int apic, int pin)  	spin_unlock_irqrestore(&ioapic_lock, flags);  } -#ifdef CONFIG_SMP -static void send_cleanup_vector(struct irq_cfg *cfg) -{ -	cpumask_var_t cleanup_mask; - -	if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) { -		unsigned int i; -		cfg->move_cleanup_count = 0; -		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask) -			cfg->move_cleanup_count++; -		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask) -			apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR); -	} else { -		cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask); -		cfg->move_cleanup_count = cpumask_weight(cleanup_mask); -		apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR); -		free_cpumask_var(cleanup_mask); -	} -	cfg->move_in_progress = 0; -} - -static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg) -{ -	int apic, pin; -	struct irq_pin_list *entry; -	u8 vector = cfg->vector; - -	entry = cfg->irq_2_pin; -	for (;;) { -		unsigned int reg; - -		if (!entry) -			break; - -		apic = entry->apic; -		pin = entry->pin; -		/* -		 * With interrupt-remapping, destination information comes -		 * from interrupt-remapping table entry. -		 */ -		if (!irq_remapped(irq)) -			io_apic_write(apic, 0x11 + pin*2, dest); -		reg = io_apic_read(apic, 0x10 + pin*2); -		reg &= ~IO_APIC_REDIR_VECTOR_MASK; -		reg |= vector; -		io_apic_modify(apic, 0x10 + pin*2, reg); -		if (!entry->next) -			break; -		entry = entry->next; -	} -} - -static int -assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask); - -/* - * Either sets desc->affinity to a valid value, and returns - * ->cpu_mask_to_apicid of that, or returns BAD_APICID and - * leaves desc->affinity untouched. - */ -static unsigned int -set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask) -{ -	struct irq_cfg *cfg; -	unsigned int irq; - -	if (!cpumask_intersects(mask, cpu_online_mask)) -		return BAD_APICID; - -	irq = desc->irq; -	cfg = desc->chip_data; -	if (assign_irq_vector(irq, cfg, mask)) -		return BAD_APICID; - -	/* check that before desc->addinity get updated */ -	set_extra_move_desc(desc, mask); - -	cpumask_copy(desc->affinity, mask); - -	return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain); -} - -static void -set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask) -{ -	struct irq_cfg *cfg; -	unsigned long flags; -	unsigned int dest; -	unsigned int irq; - -	irq = desc->irq; -	cfg = desc->chip_data; - -	spin_lock_irqsave(&ioapic_lock, flags); -	dest = set_desc_affinity(desc, mask); -	if (dest != BAD_APICID) { -		/* Only the high 8 bits are valid. */ -		dest = SET_APIC_LOGICAL_ID(dest); -		__target_IO_APIC_irq(irq, dest, cfg); -	} -	spin_unlock_irqrestore(&ioapic_lock, flags); -} - -static void -set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask) -{ -	struct irq_desc *desc; - -	desc = irq_to_desc(irq); - -	set_ioapic_affinity_irq_desc(desc, mask); -} -#endif /* CONFIG_SMP */ -  /*   * The common case is 1:1 IRQ<->pin mappings. Sometimes there are   * shared ISA-space IRQs, so we have to support them. We are super   * fast in the common case, and fast for shared ISA-space IRQs.   */ -static void add_pin_to_irq_cpu(struct irq_cfg *cfg, int cpu, int apic, int pin) +static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)  {  	struct irq_pin_list *entry;  	entry = cfg->irq_2_pin;  	if (!entry) { -		entry = get_one_free_irq_2_pin(cpu); +		entry = get_one_free_irq_2_pin(node);  		if (!entry) {  			printk(KERN_ERR "can not alloc irq_2_pin to add %d - %d\n",  					apic, pin); @@ -663,7 +524,7 @@ static void add_pin_to_irq_cpu(struct irq_cfg *cfg, int cpu, int apic, int pin)  		entry = entry->next;  	} -	entry->next = get_one_free_irq_2_pin(cpu); +	entry->next = get_one_free_irq_2_pin(node);  	entry = entry->next;  	entry->apic = apic;  	entry->pin = pin; @@ -672,7 +533,7 @@ static void add_pin_to_irq_cpu(struct irq_cfg *cfg, int cpu, int apic, int pin)  /*   * Reroute an IRQ to a different pin.   */ -static void __init replace_pin_at_irq_cpu(struct irq_cfg *cfg, int cpu, +static void __init replace_pin_at_irq_node(struct irq_cfg *cfg, int node,  				      int oldapic, int oldpin,  				      int newapic, int newpin)  { @@ -692,7 +553,7 @@ static void __init replace_pin_at_irq_cpu(struct irq_cfg *cfg, int cpu,  	/* why? call replace before add? */  	if (!replaced) -		add_pin_to_irq_cpu(cfg, cpu, newapic, newpin); +		add_pin_to_irq_node(cfg, node, newapic, newpin);  }  static inline void io_apic_modify_irq(struct irq_cfg *cfg, @@ -850,7 +711,6 @@ static int __init ioapic_pirq_setup(char *str)  __setup("pirq=", ioapic_pirq_setup);  #endif /* CONFIG_X86_32 */ -#ifdef CONFIG_INTR_REMAP  struct IO_APIC_route_entry **alloc_ioapic_entries(void)  {  	int apic; @@ -948,20 +808,6 @@ int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)  	return 0;  } -void reinit_intr_remapped_IO_APIC(int intr_remapping, -	struct IO_APIC_route_entry **ioapic_entries) - -{ -	/* -	 * for now plain restore of previous settings. -	 * TBD: In the case of OS enabling interrupt-remapping, -	 * IO-APIC RTE's need to be setup to point to interrupt-remapping -	 * table entries. for now, do a plain restore, and wait for -	 * the setup_IO_APIC_irqs() to do proper initialization. -	 */ -	restore_IO_APIC_setup(ioapic_entries); -} -  void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries)  {  	int apic; @@ -971,7 +817,6 @@ void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries)  	kfree(ioapic_entries);  } -#endif  /*   * Find the IRQ entry number of a certain pin. @@ -1032,54 +877,6 @@ static int __init find_isa_irq_apic(int irq, int type)  	return -1;  } -/* - * Find a specific PCI IRQ entry. - * Not an __init, possibly needed by modules - */ -static int pin_2_irq(int idx, int apic, int pin); - -int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) -{ -	int apic, i, best_guess = -1; - -	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n", -		bus, slot, pin); -	if (test_bit(bus, mp_bus_not_pci)) { -		apic_printk(APIC_VERBOSE, "PCI BIOS passed nonexistent PCI bus %d!\n", bus); -		return -1; -	} -	for (i = 0; i < mp_irq_entries; i++) { -		int lbus = mp_irqs[i].srcbus; - -		for (apic = 0; apic < nr_ioapics; apic++) -			if (mp_ioapics[apic].apicid == mp_irqs[i].dstapic || -			    mp_irqs[i].dstapic == MP_APIC_ALL) -				break; - -		if (!test_bit(lbus, mp_bus_not_pci) && -		    !mp_irqs[i].irqtype && -		    (bus == lbus) && -		    (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) { -			int irq = pin_2_irq(i, apic, mp_irqs[i].dstirq); - -			if (!(apic || IO_APIC_IRQ(irq))) -				continue; - -			if (pin == (mp_irqs[i].srcbusirq & 3)) -				return irq; -			/* -			 * Use the first all-but-pin matching entry as a -			 * best-guess fuzzy result for broken mptables. -			 */ -			if (best_guess < 0) -				best_guess = irq; -		} -	} -	return best_guess; -} - -EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector); -  #if defined(CONFIG_EISA) || defined(CONFIG_MCA)  /*   * EISA Edge/Level control register, ELCR @@ -1298,6 +1095,64 @@ static int pin_2_irq(int idx, int apic, int pin)  	return irq;  } +/* + * Find a specific PCI IRQ entry. + * Not an __init, possibly needed by modules + */ +int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin, +				struct io_apic_irq_attr *irq_attr) +{ +	int apic, i, best_guess = -1; + +	apic_printk(APIC_DEBUG, +		    "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n", +		    bus, slot, pin); +	if (test_bit(bus, mp_bus_not_pci)) { +		apic_printk(APIC_VERBOSE, +			    "PCI BIOS passed nonexistent PCI bus %d!\n", bus); +		return -1; +	} +	for (i = 0; i < mp_irq_entries; i++) { +		int lbus = mp_irqs[i].srcbus; + +		for (apic = 0; apic < nr_ioapics; apic++) +			if (mp_ioapics[apic].apicid == mp_irqs[i].dstapic || +			    mp_irqs[i].dstapic == MP_APIC_ALL) +				break; + +		if (!test_bit(lbus, mp_bus_not_pci) && +		    !mp_irqs[i].irqtype && +		    (bus == lbus) && +		    (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) { +			int irq = pin_2_irq(i, apic, mp_irqs[i].dstirq); + +			if (!(apic || IO_APIC_IRQ(irq))) +				continue; + +			if (pin == (mp_irqs[i].srcbusirq & 3)) { +				set_io_apic_irq_attr(irq_attr, apic, +						     mp_irqs[i].dstirq, +						     irq_trigger(i), +						     irq_polarity(i)); +				return irq; +			} +			/* +			 * Use the first all-but-pin matching entry as a +			 * best-guess fuzzy result for broken mptables. +			 */ +			if (best_guess < 0) { +				set_io_apic_irq_attr(irq_attr, apic, +						     mp_irqs[i].dstirq, +						     irq_trigger(i), +						     irq_polarity(i)); +				best_guess = irq; +			} +		} +	} +	return best_guess; +} +EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector); +  void lock_vector_lock(void)  {  	/* Used to the online set of cpus does not change @@ -1628,58 +1483,70 @@ static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq  	ioapic_write_entry(apic_id, pin, entry);  } +static struct { +	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1); +} mp_ioapic_routing[MAX_IO_APICS]; +  static void __init setup_IO_APIC_irqs(void)  { -	int apic_id, pin, idx, irq; +	int apic_id = 0, pin, idx, irq;  	int notcon = 0;  	struct irq_desc *desc;  	struct irq_cfg *cfg; -	int cpu = boot_cpu_id; +	int node = cpu_to_node(boot_cpu_id);  	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); -	for (apic_id = 0; apic_id < nr_ioapics; apic_id++) { -		for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) { +#ifdef CONFIG_ACPI +	if (!acpi_disabled && acpi_ioapic) { +		apic_id = mp_find_ioapic(0); +		if (apic_id < 0) +			apic_id = 0; +	} +#endif -			idx = find_irq_entry(apic_id, pin, mp_INT); -			if (idx == -1) { -				if (!notcon) { -					notcon = 1; -					apic_printk(APIC_VERBOSE, -						KERN_DEBUG " %d-%d", -						mp_ioapics[apic_id].apicid, pin); -				} else -					apic_printk(APIC_VERBOSE, " %d-%d", -						mp_ioapics[apic_id].apicid, pin); -				continue; -			} -			if (notcon) { +	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) { +		idx = find_irq_entry(apic_id, pin, mp_INT); +		if (idx == -1) { +			if (!notcon) { +				notcon = 1;  				apic_printk(APIC_VERBOSE, -					" (apicid-pin) not connected\n"); -				notcon = 0; -			} +					KERN_DEBUG " %d-%d", +					mp_ioapics[apic_id].apicid, pin); +			} else +				apic_printk(APIC_VERBOSE, " %d-%d", +					mp_ioapics[apic_id].apicid, pin); +			continue; +		} +		if (notcon) { +			apic_printk(APIC_VERBOSE, +				" (apicid-pin) not connected\n"); +			notcon = 0; +		} -			irq = pin_2_irq(idx, apic_id, pin); +		irq = pin_2_irq(idx, apic_id, pin); -			/* -			 * Skip the timer IRQ if there's a quirk handler -			 * installed and if it returns 1: -			 */ -			if (apic->multi_timer_check && -					apic->multi_timer_check(apic_id, irq)) -				continue; - -			desc = irq_to_desc_alloc_cpu(irq, cpu); -			if (!desc) { -				printk(KERN_INFO "can not get irq_desc for %d\n", irq); -				continue; -			} -			cfg = desc->chip_data; -			add_pin_to_irq_cpu(cfg, cpu, apic_id, pin); +		/* +		 * Skip the timer IRQ if there's a quirk handler +		 * installed and if it returns 1: +		 */ +		if (apic->multi_timer_check && +				apic->multi_timer_check(apic_id, irq)) +			continue; -			setup_IO_APIC_irq(apic_id, pin, irq, desc, -					irq_trigger(idx), irq_polarity(idx)); +		desc = irq_to_desc_alloc_node(irq, node); +		if (!desc) { +			printk(KERN_INFO "can not get irq_desc for %d\n", irq); +			continue;  		} +		cfg = desc->chip_data; +		add_pin_to_irq_node(cfg, node, apic_id, pin); +		/* +		 * don't mark it in pin_programmed, so later acpi could +		 * set it correctly when irq < 16 +		 */ +		setup_IO_APIC_irq(apic_id, pin, irq, desc, +				irq_trigger(idx), irq_polarity(idx));  	}  	if (notcon) @@ -1869,7 +1736,7 @@ __apicdebuginit(void) print_APIC_bitfield(int base)  __apicdebuginit(void) print_local_APIC(void *dummy)  { -	unsigned int v, ver, maxlvt; +	unsigned int i, v, ver, maxlvt;  	u64 icr;  	if (apic_verbosity == APIC_QUIET) @@ -1957,6 +1824,18 @@ __apicdebuginit(void) print_local_APIC(void *dummy)  	printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v);  	v = apic_read(APIC_TDCR);  	printk(KERN_DEBUG "... APIC TDCR: %08x\n", v); + +	if (boot_cpu_has(X86_FEATURE_EXTAPIC)) { +		v = apic_read(APIC_EFEAT); +		maxlvt = (v >> 16) & 0xff; +		printk(KERN_DEBUG "... APIC EFEAT: %08x\n", v); +		v = apic_read(APIC_ECTRL); +		printk(KERN_DEBUG "... APIC ECTRL: %08x\n", v); +		for (i = 0; i < maxlvt; i++) { +			v = apic_read(APIC_EILVTn(i)); +			printk(KERN_DEBUG "... APIC EILVT%d: %08x\n", i, v); +		} +	}  	printk("\n");  } @@ -2005,6 +1884,11 @@ __apicdebuginit(void) print_PIC(void)  __apicdebuginit(int) print_all_ICs(void)  {  	print_PIC(); + +	/* don't print out if apic is not there */ +	if (!cpu_has_apic || disable_apic) +		return 0; +  	print_all_local_APICs();  	print_IO_APIC(); @@ -2120,7 +2004,9 @@ void disable_IO_APIC(void)  	/*  	 * Use virtual wire A mode when interrupt remapping is enabled.  	 */ -	disconnect_bsp_APIC(!intr_remapping_enabled && ioapic_i8259.pin != -1); +	if (cpu_has_apic) +		disconnect_bsp_APIC(!intr_remapping_enabled && +				ioapic_i8259.pin != -1);  }  #ifdef CONFIG_X86_32 @@ -2360,6 +2246,118 @@ static int ioapic_retrigger_irq(unsigned int irq)   */  #ifdef CONFIG_SMP +static void send_cleanup_vector(struct irq_cfg *cfg) +{ +	cpumask_var_t cleanup_mask; + +	if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) { +		unsigned int i; +		cfg->move_cleanup_count = 0; +		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask) +			cfg->move_cleanup_count++; +		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask) +			apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR); +	} else { +		cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask); +		cfg->move_cleanup_count = cpumask_weight(cleanup_mask); +		apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR); +		free_cpumask_var(cleanup_mask); +	} +	cfg->move_in_progress = 0; +} + +static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg) +{ +	int apic, pin; +	struct irq_pin_list *entry; +	u8 vector = cfg->vector; + +	entry = cfg->irq_2_pin; +	for (;;) { +		unsigned int reg; + +		if (!entry) +			break; + +		apic = entry->apic; +		pin = entry->pin; +		/* +		 * With interrupt-remapping, destination information comes +		 * from interrupt-remapping table entry. +		 */ +		if (!irq_remapped(irq)) +			io_apic_write(apic, 0x11 + pin*2, dest); +		reg = io_apic_read(apic, 0x10 + pin*2); +		reg &= ~IO_APIC_REDIR_VECTOR_MASK; +		reg |= vector; +		io_apic_modify(apic, 0x10 + pin*2, reg); +		if (!entry->next) +			break; +		entry = entry->next; +	} +} + +static int +assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask); + +/* + * Either sets desc->affinity to a valid value, and returns + * ->cpu_mask_to_apicid of that, or returns BAD_APICID and + * leaves desc->affinity untouched. + */ +static unsigned int +set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask) +{ +	struct irq_cfg *cfg; +	unsigned int irq; + +	if (!cpumask_intersects(mask, cpu_online_mask)) +		return BAD_APICID; + +	irq = desc->irq; +	cfg = desc->chip_data; +	if (assign_irq_vector(irq, cfg, mask)) +		return BAD_APICID; + +	cpumask_copy(desc->affinity, mask); + +	return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain); +} + +static int +set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask) +{ +	struct irq_cfg *cfg; +	unsigned long flags; +	unsigned int dest; +	unsigned int irq; +	int ret = -1; + +	irq = desc->irq; +	cfg = desc->chip_data; + +	spin_lock_irqsave(&ioapic_lock, flags); +	dest = set_desc_affinity(desc, mask); +	if (dest != BAD_APICID) { +		/* 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); + +	return ret; +} + +static int +set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask) +{ +	struct irq_desc *desc; + +	desc = irq_to_desc(irq); + +	return set_ioapic_affinity_irq_desc(desc, mask); +}  #ifdef CONFIG_INTR_REMAP @@ -2374,26 +2372,25 @@ static int ioapic_retrigger_irq(unsigned int irq)   * Real vector that is used for interrupting cpu will be coming from   * the interrupt-remapping table entry.   */ -static void +static int  migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)  {  	struct irq_cfg *cfg;  	struct irte irte;  	unsigned int dest;  	unsigned int irq; +	int ret = -1;  	if (!cpumask_intersects(mask, cpu_online_mask)) -		return; +		return ret;  	irq = desc->irq;  	if (get_irte(irq, &irte)) -		return; +		return ret;  	cfg = desc->chip_data;  	if (assign_irq_vector(irq, cfg, mask)) -		return; - -	set_extra_move_desc(desc, mask); +		return ret;  	dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask); @@ -2409,27 +2406,30 @@ migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)  		send_cleanup_vector(cfg);  	cpumask_copy(desc->affinity, mask); + +	return 0;  }  /*   * Migrates the IRQ destination in the process context.   */ -static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc, +static int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,  					    const struct cpumask *mask)  { -	migrate_ioapic_irq_desc(desc, mask); +	return migrate_ioapic_irq_desc(desc, mask);  } -static void set_ir_ioapic_affinity_irq(unsigned int irq, +static int set_ir_ioapic_affinity_irq(unsigned int irq,  				       const struct cpumask *mask)  {  	struct irq_desc *desc = irq_to_desc(irq); -	set_ir_ioapic_affinity_irq_desc(desc, mask); +	return set_ir_ioapic_affinity_irq_desc(desc, mask);  }  #else -static inline void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc, +static inline int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,  						   const struct cpumask *mask)  { +	return 0;  }  #endif @@ -2491,86 +2491,19 @@ static void irq_complete_move(struct irq_desc **descp)  	struct irq_cfg *cfg = desc->chip_data;  	unsigned vector, me; -	if (likely(!cfg->move_in_progress)) { -#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC -		if (likely(!cfg->move_desc_pending)) -			return; - -		/* domain has not changed, but affinity did */ -		me = smp_processor_id(); -		if (cpumask_test_cpu(me, desc->affinity)) { -			*descp = desc = move_irq_desc(desc, me); -			/* get the new one */ -			cfg = desc->chip_data; -			cfg->move_desc_pending = 0; -		} -#endif +	if (likely(!cfg->move_in_progress))  		return; -	}  	vector = ~get_irq_regs()->orig_ax;  	me = smp_processor_id(); -	if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) { -#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC -		*descp = desc = move_irq_desc(desc, me); -		/* get the new one */ -		cfg = desc->chip_data; -#endif +	if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))  		send_cleanup_vector(cfg); -	}  }  #else  static inline void irq_complete_move(struct irq_desc **descp) {}  #endif -static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg) -{ -	int apic, pin; -	struct irq_pin_list *entry; - -	entry = cfg->irq_2_pin; -	for (;;) { - -		if (!entry) -			break; - -		apic = entry->apic; -		pin = entry->pin; -		io_apic_eoi(apic, pin); -		entry = entry->next; -	} -} - -static void -eoi_ioapic_irq(struct irq_desc *desc) -{ -	struct irq_cfg *cfg; -	unsigned long flags; -	unsigned int irq; - -	irq = desc->irq; -	cfg = desc->chip_data; - -	spin_lock_irqsave(&ioapic_lock, flags); -	__eoi_ioapic_irq(irq, cfg); -	spin_unlock_irqrestore(&ioapic_lock, flags); -} - -#ifdef CONFIG_X86_X2APIC -static void ack_x2apic_level(unsigned int irq) -{ -	struct irq_desc *desc = irq_to_desc(irq); -	ack_x2APIC_irq(); -	eoi_ioapic_irq(desc); -} - -static void ack_x2apic_edge(unsigned int irq) -{ -	ack_x2APIC_irq(); -} -#endif -  static void ack_apic_edge(unsigned int irq)  {  	struct irq_desc *desc = irq_to_desc(irq); @@ -2634,9 +2567,6 @@ static void ack_apic_level(unsigned int irq)  	 */  	ack_APIC_irq(); -	if (irq_remapped(irq)) -		eoi_ioapic_irq(desc); -  	/* Now we can move and renable the irq */  	if (unlikely(do_unmask_irq)) {  		/* Only migrate the irq if the ack has been received. @@ -2683,22 +2613,50 @@ static void ack_apic_level(unsigned int irq)  }  #ifdef CONFIG_INTR_REMAP +static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg) +{ +	int apic, pin; +	struct irq_pin_list *entry; + +	entry = cfg->irq_2_pin; +	for (;;) { + +		if (!entry) +			break; + +		apic = entry->apic; +		pin = entry->pin; +		io_apic_eoi(apic, pin); +		entry = entry->next; +	} +} + +static void +eoi_ioapic_irq(struct irq_desc *desc) +{ +	struct irq_cfg *cfg; +	unsigned long flags; +	unsigned int irq; + +	irq = desc->irq; +	cfg = desc->chip_data; + +	spin_lock_irqsave(&ioapic_lock, flags); +	__eoi_ioapic_irq(irq, cfg); +	spin_unlock_irqrestore(&ioapic_lock, flags); +} +  static void ir_ack_apic_edge(unsigned int irq)  { -#ifdef CONFIG_X86_X2APIC -       if (x2apic_enabled()) -               return ack_x2apic_edge(irq); -#endif -       return ack_apic_edge(irq); +	ack_APIC_irq();  }  static void ir_ack_apic_level(unsigned int irq)  { -#ifdef CONFIG_X86_X2APIC -       if (x2apic_enabled()) -               return ack_x2apic_level(irq); -#endif -       return ack_apic_level(irq); +	struct irq_desc *desc = irq_to_desc(irq); + +	ack_APIC_irq(); +	eoi_ioapic_irq(desc);  }  #endif /* CONFIG_INTR_REMAP */ @@ -2903,7 +2861,7 @@ static inline void __init check_timer(void)  {  	struct irq_desc *desc = irq_to_desc(0);  	struct irq_cfg *cfg = desc->chip_data; -	int cpu = boot_cpu_id; +	int node = cpu_to_node(boot_cpu_id);  	int apic1, pin1, apic2, pin2;  	unsigned long flags;  	int no_pin1 = 0; @@ -2969,7 +2927,7 @@ static inline void __init check_timer(void)  		 * Ok, does IRQ0 through the IOAPIC work?  		 */  		if (no_pin1) { -			add_pin_to_irq_cpu(cfg, cpu, apic1, pin1); +			add_pin_to_irq_node(cfg, node, apic1, pin1);  			setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);  		} else {  			/* for edge trigger, setup_IO_APIC_irq already @@ -3006,7 +2964,7 @@ static inline void __init check_timer(void)  		/*  		 * legacy devices should be connected to IO APIC #0  		 */ -		replace_pin_at_irq_cpu(cfg, cpu, apic1, pin1, apic2, pin2); +		replace_pin_at_irq_node(cfg, node, apic1, pin1, apic2, pin2);  		setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);  		enable_8259A_irq(0);  		if (timer_irq_works()) { @@ -3218,14 +3176,13 @@ static int nr_irqs_gsi = NR_IRQS_LEGACY;  /*   * Dynamic irq allocate and deallocation   */ -unsigned int create_irq_nr(unsigned int irq_want) +unsigned int create_irq_nr(unsigned int irq_want, int node)  {  	/* Allocate an unused irq */  	unsigned int irq;  	unsigned int new;  	unsigned long flags;  	struct irq_cfg *cfg_new = NULL; -	int cpu = boot_cpu_id;  	struct irq_desc *desc_new = NULL;  	irq = 0; @@ -3234,7 +3191,7 @@ unsigned int create_irq_nr(unsigned int irq_want)  	spin_lock_irqsave(&vector_lock, flags);  	for (new = irq_want; new < nr_irqs; new++) { -		desc_new = irq_to_desc_alloc_cpu(new, cpu); +		desc_new = irq_to_desc_alloc_node(new, node);  		if (!desc_new) {  			printk(KERN_INFO "can not get irq_desc for %d\n", new);  			continue; @@ -3243,6 +3200,9 @@ unsigned int create_irq_nr(unsigned int irq_want)  		if (cfg_new->vector != 0)  			continue; + +		desc_new = move_irq_desc(desc_new, node); +  		if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0)  			irq = new;  		break; @@ -3260,11 +3220,12 @@ unsigned int create_irq_nr(unsigned int irq_want)  int create_irq(void)  { +	int node = cpu_to_node(boot_cpu_id);  	unsigned int irq_want;  	int irq;  	irq_want = nr_irqs_gsi; -	irq = create_irq_nr(irq_want); +	irq = create_irq_nr(irq_want, node);  	if (irq == 0)  		irq = -1; @@ -3366,7 +3327,7 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms  }  #ifdef CONFIG_SMP -static void set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask) +static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)  {  	struct irq_desc *desc = irq_to_desc(irq);  	struct irq_cfg *cfg; @@ -3375,7 +3336,7 @@ static void set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)  	dest = set_desc_affinity(desc, mask);  	if (dest == BAD_APICID) -		return; +		return -1;  	cfg = desc->chip_data; @@ -3387,13 +3348,15 @@ static void set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)  	msg.address_lo |= MSI_ADDR_DEST_ID(dest);  	write_msi_msg_desc(desc, &msg); + +	return 0;  }  #ifdef CONFIG_INTR_REMAP  /*   * Migrate the MSI irq to another cpumask. This migration is   * done in the process context using interrupt-remapping hardware.   */ -static void +static int  ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)  {  	struct irq_desc *desc = irq_to_desc(irq); @@ -3402,11 +3365,11 @@ ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)  	struct irte irte;  	if (get_irte(irq, &irte)) -		return; +		return -1;  	dest = set_desc_affinity(desc, mask);  	if (dest == BAD_APICID) -		return; +		return -1;  	irte.vector = cfg->vector;  	irte.dest_id = IRTE_DEST(dest); @@ -3423,6 +3386,8 @@ ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)  	 */  	if (cfg->move_in_progress)  		send_cleanup_vector(cfg); + +	return 0;  }  #endif @@ -3518,15 +3483,17 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)  	unsigned int irq_want;  	struct intel_iommu *iommu = NULL;  	int index = 0; +	int node;  	/* x86 doesn't support multiple MSI yet */  	if (type == PCI_CAP_ID_MSI && nvec > 1)  		return 1; +	node = dev_to_node(&dev->dev);  	irq_want = nr_irqs_gsi;  	sub_handle = 0;  	list_for_each_entry(msidesc, &dev->msi_list, list) { -		irq = create_irq_nr(irq_want); +		irq = create_irq_nr(irq_want, node);  		if (irq == 0)  			return -1;  		irq_want = irq + 1; @@ -3576,7 +3543,7 @@ void arch_teardown_msi_irq(unsigned int irq)  #if defined (CONFIG_DMAR) || defined (CONFIG_INTR_REMAP)  #ifdef CONFIG_SMP -static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask) +static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)  {  	struct irq_desc *desc = irq_to_desc(irq);  	struct irq_cfg *cfg; @@ -3585,7 +3552,7 @@ static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)  	dest = set_desc_affinity(desc, mask);  	if (dest == BAD_APICID) -		return; +		return -1;  	cfg = desc->chip_data; @@ -3597,11 +3564,13 @@ static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)  	msg.address_lo |= MSI_ADDR_DEST_ID(dest);  	dmar_msi_write(irq, &msg); + +	return 0;  }  #endif /* CONFIG_SMP */ -struct irq_chip dmar_msi_type = { +static struct irq_chip dmar_msi_type = {  	.name = "DMAR_MSI",  	.unmask = dmar_msi_unmask,  	.mask = dmar_msi_mask, @@ -3630,7 +3599,7 @@ int arch_setup_dmar_msi(unsigned int irq)  #ifdef CONFIG_HPET_TIMER  #ifdef CONFIG_SMP -static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask) +static int hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)  {  	struct irq_desc *desc = irq_to_desc(irq);  	struct irq_cfg *cfg; @@ -3639,7 +3608,7 @@ static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)  	dest = set_desc_affinity(desc, mask);  	if (dest == BAD_APICID) -		return; +		return -1;  	cfg = desc->chip_data; @@ -3651,6 +3620,8 @@ static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)  	msg.address_lo |= MSI_ADDR_DEST_ID(dest);  	hpet_msi_write(irq, &msg); + +	return 0;  }  #endif /* CONFIG_SMP */ @@ -3707,7 +3678,7 @@ static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)  	write_ht_irq_msg(irq, &msg);  } -static void set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask) +static int set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)  {  	struct irq_desc *desc = irq_to_desc(irq);  	struct irq_cfg *cfg; @@ -3715,11 +3686,13 @@ static void set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)  	dest = set_desc_affinity(desc, mask);  	if (dest == BAD_APICID) -		return; +		return -1;  	cfg = desc->chip_data;  	target_ht_irq(irq, dest, cfg->vector); + +	return 0;  }  #endif @@ -3794,6 +3767,8 @@ int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,  	unsigned long flags;  	int err; +	BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long)); +  	cfg = irq_cfg(irq);  	err = assign_irq_vector(irq, cfg, eligible_cpu); @@ -3807,15 +3782,13 @@ int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,  	mmr_value = 0;  	entry = (struct uv_IO_APIC_route_entry *)&mmr_value; -	BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long)); - -	entry->vector = cfg->vector; -	entry->delivery_mode = apic->irq_delivery_mode; -	entry->dest_mode = apic->irq_dest_mode; -	entry->polarity = 0; -	entry->trigger = 0; -	entry->mask = 0; -	entry->dest = apic->cpu_mask_to_apicid(eligible_cpu); +	entry->vector		= cfg->vector; +	entry->delivery_mode	= apic->irq_delivery_mode; +	entry->dest_mode	= apic->irq_dest_mode; +	entry->polarity		= 0; +	entry->trigger		= 0; +	entry->mask		= 0; +	entry->dest		= apic->cpu_mask_to_apicid(eligible_cpu);  	mmr_pnode = uv_blade_to_pnode(mmr_blade);  	uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value); @@ -3833,10 +3806,10 @@ void arch_disable_uv_irq(int mmr_blade, unsigned long mmr_offset)  	struct uv_IO_APIC_route_entry *entry;  	int mmr_pnode; +	BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long)); +  	mmr_value = 0;  	entry = (struct uv_IO_APIC_route_entry *)&mmr_value; -	BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long)); -  	entry->mask = 1;  	mmr_pnode = uv_blade_to_pnode(mmr_blade); @@ -3900,6 +3873,71 @@ int __init arch_probe_nr_irqs(void)  }  #endif +static int __io_apic_set_pci_routing(struct device *dev, int irq, +				struct io_apic_irq_attr *irq_attr) +{ +	struct irq_desc *desc; +	struct irq_cfg *cfg; +	int node; +	int ioapic, pin; +	int trigger, polarity; + +	ioapic = irq_attr->ioapic; +	if (!IO_APIC_IRQ(irq)) { +		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n", +			ioapic); +		return -EINVAL; +	} + +	if (dev) +		node = dev_to_node(dev); +	else +		node = cpu_to_node(boot_cpu_id); + +	desc = irq_to_desc_alloc_node(irq, node); +	if (!desc) { +		printk(KERN_INFO "can not get irq_desc %d\n", irq); +		return 0; +	} + +	pin = irq_attr->ioapic_pin; +	trigger = irq_attr->trigger; +	polarity = irq_attr->polarity; + +	/* +	 * IRQs < 16 are already in the irq_2_pin[] map +	 */ +	if (irq >= NR_IRQS_LEGACY) { +		cfg = desc->chip_data; +		add_pin_to_irq_node(cfg, node, ioapic, pin); +	} + +	setup_IO_APIC_irq(ioapic, pin, irq, desc, trigger, polarity); + +	return 0; +} + +int io_apic_set_pci_routing(struct device *dev, int irq, +				struct io_apic_irq_attr *irq_attr) +{ +	int ioapic, pin; +	/* +	 * Avoid pin reprogramming.  PRTs typically include entries +	 * with redundant pin->gsi mappings (but unique PCI devices); +	 * we only program the IOAPIC on the first. +	 */ +	ioapic = irq_attr->ioapic; +	pin = irq_attr->ioapic_pin; +	if (test_bit(pin, mp_ioapic_routing[ioapic].pin_programmed)) { +		pr_debug("Pin %d-%d already programmed\n", +			 mp_ioapics[ioapic].apicid, pin); +		return 0; +	} +	set_bit(pin, mp_ioapic_routing[ioapic].pin_programmed); + +	return __io_apic_set_pci_routing(dev, irq, irq_attr); +} +  /* --------------------------------------------------------------------------                            ACPI-based IOAPIC Configuration     -------------------------------------------------------------------------- */ @@ -3980,6 +4018,7 @@ int __init io_apic_get_unique_id(int ioapic, int apic_id)  	return apic_id;  } +#endif  int __init io_apic_get_version(int ioapic)  { @@ -3992,39 +4031,6 @@ int __init io_apic_get_version(int ioapic)  	return reg_01.bits.version;  } -#endif - -int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity) -{ -	struct irq_desc *desc; -	struct irq_cfg *cfg; -	int cpu = boot_cpu_id; - -	if (!IO_APIC_IRQ(irq)) { -		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n", -			ioapic); -		return -EINVAL; -	} - -	desc = irq_to_desc_alloc_cpu(irq, cpu); -	if (!desc) { -		printk(KERN_INFO "can not get irq_desc %d\n", irq); -		return 0; -	} - -	/* -	 * IRQs < 16 are already in the irq_2_pin[] map -	 */ -	if (irq >= NR_IRQS_LEGACY) { -		cfg = desc->chip_data; -		add_pin_to_irq_cpu(cfg, cpu, ioapic, pin); -	} - -	setup_IO_APIC_irq(ioapic, pin, irq, desc, triggering, polarity); - -	return 0; -} -  int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)  { @@ -4055,51 +4061,44 @@ int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)  #ifdef CONFIG_SMP  void __init setup_ioapic_dest(void)  { -	int pin, ioapic, irq, irq_entry; +	int pin, ioapic = 0, irq, irq_entry;  	struct irq_desc *desc; -	struct irq_cfg *cfg;  	const struct cpumask *mask;  	if (skip_ioapic_setup == 1)  		return; -	for (ioapic = 0; ioapic < nr_ioapics; ioapic++) { -		for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) { -			irq_entry = find_irq_entry(ioapic, pin, mp_INT); -			if (irq_entry == -1) -				continue; -			irq = pin_2_irq(irq_entry, ioapic, pin); - -			/* setup_IO_APIC_irqs could fail to get vector for some device -			 * when you have too many devices, because at that time only boot -			 * cpu is online. -			 */ -			desc = irq_to_desc(irq); -			cfg = desc->chip_data; -			if (!cfg->vector) { -				setup_IO_APIC_irq(ioapic, pin, irq, desc, -						  irq_trigger(irq_entry), -						  irq_polarity(irq_entry)); -				continue; +#ifdef CONFIG_ACPI +	if (!acpi_disabled && acpi_ioapic) { +		ioapic = mp_find_ioapic(0); +		if (ioapic < 0) +			ioapic = 0; +	} +#endif -			} +	for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) { +		irq_entry = find_irq_entry(ioapic, pin, mp_INT); +		if (irq_entry == -1) +			continue; +		irq = pin_2_irq(irq_entry, ioapic, pin); -			/* -			 * Honour affinities which have been set in early boot -			 */ -			if (desc->status & -			    (IRQ_NO_BALANCING | IRQ_AFFINITY_SET)) -				mask = desc->affinity; -			else -				mask = apic->target_cpus(); +		desc = irq_to_desc(irq); -			if (intr_remapping_enabled) -				set_ir_ioapic_affinity_irq_desc(desc, mask); -			else -				set_ioapic_affinity_irq_desc(desc, mask); -		} +		/* +		 * Honour affinities which have been set in early boot +		 */ +		if (desc->status & +		    (IRQ_NO_BALANCING | IRQ_AFFINITY_SET)) +			mask = desc->affinity; +		else +			mask = apic->target_cpus(); +		if (intr_remapping_enabled) +			set_ir_ioapic_affinity_irq_desc(desc, mask); +		else +			set_ioapic_affinity_irq_desc(desc, mask);  	} +  }  #endif  |