Jelajahi Sumber

Merge branch 'irq-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'irq-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (76 commits)
  x86, apic: Fix dummy apic read operation together with broken MP handling
  x86, apic: Restore irqs on fail paths
  x86: Print real IOAPIC version for x86-64
  x86: enable_update_mptable should be a macro
  sparseirq: Allow early irq_desc allocation
  x86, io-apic: Don't mark pin_programmed early
  x86, irq: don't call mp_config_acpi_gsi() if update_mptable is not enabled
  x86, irq: update_mptable needs pci_routeirq
  x86: don't call read_apic_id if !cpu_has_apic
  x86, apic: introduce io_apic_irq_attr
  x86/pci: add 4 more return parameters to IO_APIC_get_PCI_irq_vector(), fix
  x86: read apic ID in the !acpi_lapic case
  x86: apic: Fixmap apic address even if apic disabled
  x86: display extended apic registers with print_local_APIC and cpu_debug code
  x86: read apic ID in the !acpi_lapic case
  x86: clean up and fix setup_clear/force_cpu_cap handling
  x86: apic: Check rev 3 fadt correctly for physical_apic bit
  x86/pci: update pirq_enable_irq() to setup io apic routing
  x86/acpi: move setup io apic routing out of CONFIG_ACPI scope
  x86/pci: add 4 more return parameters to IO_APIC_get_PCI_irq_vector()
  ...
Linus Torvalds 16 tahun lalu
induk
melakukan
f0d5e12bd4
80 mengubah file dengan 1128 tambahan dan 1233 penghapusan
  1. 3 0
      Documentation/kernel-parameters.txt
  2. 6 2
      arch/alpha/kernel/sys_dp264.c
  3. 3 1
      arch/alpha/kernel/sys_titan.c
  4. 3 1
      arch/arm/common/gic.c
  5. 3 1
      arch/cris/arch-v32/kernel/irq.c
  6. 2 1
      arch/ia64/hp/sim/hpsim_irq.c
  7. 3 2
      arch/ia64/kernel/acpi.c
  8. 6 4
      arch/ia64/kernel/iosapic.c
  9. 10 6
      arch/ia64/kernel/msi_ia64.c
  10. 3 1
      arch/ia64/sn/kernel/irq.c
  11. 5 3
      arch/ia64/sn/kernel/msi_sn.c
  12. 6 2
      arch/mips/cavium-octeon/octeon-irq.c
  13. 1 1
      arch/mips/include/asm/irq.h
  14. 3 2
      arch/mips/kernel/irq-gic.c
  15. 3 1
      arch/mips/mti-malta/malta-smtc.c
  16. 5 3
      arch/mips/sibyte/bcm1480/irq.c
  17. 5 3
      arch/mips/sibyte/sb1250/irq.c
  18. 4 2
      arch/parisc/kernel/irq.c
  19. 7 5
      arch/powerpc/platforms/pseries/xics.c
  20. 3 1
      arch/powerpc/sysdev/mpic.c
  21. 1 1
      arch/powerpc/sysdev/mpic.h
  22. 9 3
      arch/sparc/kernel/irq_64.c
  23. 3 9
      arch/x86/Kconfig
  24. 0 1
      arch/x86/configs/x86_64_defconfig
  25. 10 18
      arch/x86/include/asm/apic.h
  26. 4 4
      arch/x86/include/asm/apicdef.h
  27. 3 3
      arch/x86/include/asm/cpufeature.h
  28. 20 1
      arch/x86/include/asm/hw_irq.h
  29. 0 4
      arch/x86/include/asm/i8259.h
  30. 3 6
      arch/x86/include/asm/io_apic.h
  31. 1 1
      arch/x86/include/asm/irq_remapping.h
  32. 1 0
      arch/x86/include/asm/irq_vectors.h
  33. 5 10
      arch/x86/include/asm/mpspec.h
  34. 2 1
      arch/x86/include/asm/processor.h
  35. 0 1
      arch/x86/include/asm/setup.h
  36. 1 1
      arch/x86/include/asm/smp.h
  37. 1 1
      arch/x86/kernel/Makefile
  38. 53 103
      arch/x86/kernel/acpi/boot.c
  39. 191 120
      arch/x86/kernel/apic/apic.c
  40. 2 2
      arch/x86/kernel/apic/apic_flat_64.c
  41. 1 1
      arch/x86/kernel/apic/es7000_32.c
  42. 315 364
      arch/x86/kernel/apic/io_apic.c
  43. 1 1
      arch/x86/kernel/apic/probe_64.c
  44. 0 7
      arch/x86/kernel/apic/summit_32.c
  45. 4 1
      arch/x86/kernel/apic/x2apic_uv_x.c
  46. 1 1
      arch/x86/kernel/cpu/amd.c
  47. 18 5
      arch/x86/kernel/cpu/common.c
  48. 13 1
      arch/x86/kernel/cpu/cpu_debug.c
  49. 3 3
      arch/x86/kernel/cpu/intel.c
  50. 7 12
      arch/x86/kernel/irq.c
  51. 109 40
      arch/x86/kernel/irqinit.c
  52. 0 177
      arch/x86/kernel/irqinit_64.c
  53. 17 17
      arch/x86/kernel/mpparse.c
  54. 0 18
      arch/x86/kernel/setup.c
  55. 10 10
      arch/x86/kernel/smp.c
  56. 13 9
      arch/x86/kernel/smpboot.c
  57. 1 4
      arch/x86/kernel/traps.c
  58. 1 1
      arch/x86/lguest/boot.c
  59. 35 49
      arch/x86/pci/irq.c
  60. 3 2
      drivers/acpi/pci_irq.c
  61. 2 2
      drivers/char/hpet.c
  62. 4 2
      drivers/parisc/iosapic.c
  63. 28 26
      drivers/pci/hotplug/ibmphp_core.c
  64. 3 1
      drivers/pci/htirq.c
  65. 0 9
      drivers/pci/intel-iommu.c
  66. 31 23
      drivers/pci/intr_remapping.c
  67. 1 1
      drivers/pnp/pnpacpi/rsparser.c
  68. 8 6
      drivers/xen/events.c
  69. 1 1
      include/linux/acpi.h
  70. 3 0
      include/linux/dmar.h
  71. 1 1
      include/linux/interrupt.h
  72. 30 28
      include/linux/irq.h
  73. 1 1
      kernel/irq/Makefile
  74. 2 10
      kernel/irq/chip.c
  75. 30 28
      kernel/irq/handle.c
  76. 4 1
      kernel/irq/internals.h
  77. 11 6
      kernel/irq/manage.c
  78. 9 5
      kernel/irq/migration.c
  79. 12 26
      kernel/irq/numa_migrate.c
  80. 1 1
      kernel/softirq.c

+ 3 - 0
Documentation/kernel-parameters.txt

@@ -1575,6 +1575,9 @@ and is between 256 and 4096 characters. It is defined in the file
 	noinitrd	[RAM] Tells the kernel not to load any configured
 	noinitrd	[RAM] Tells the kernel not to load any configured
 			initial RAM disk.
 			initial RAM disk.
 
 
+	nointremap	[X86-64, Intel-IOMMU] Do not enable interrupt
+			remapping.
+
 	nointroute	[IA-64]
 	nointroute	[IA-64]
 
 
 	nojitter	[IA64] Disables jitter checking for ITC timers.
 	nojitter	[IA64] Disables jitter checking for ITC timers.

+ 6 - 2
arch/alpha/kernel/sys_dp264.c

@@ -176,22 +176,26 @@ cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
 	}
 	}
 }
 }
 
 
-static void
+static int
 dp264_set_affinity(unsigned int irq, const struct cpumask *affinity)
 dp264_set_affinity(unsigned int irq, const struct cpumask *affinity)
 { 
 { 
 	spin_lock(&dp264_irq_lock);
 	spin_lock(&dp264_irq_lock);
 	cpu_set_irq_affinity(irq, *affinity);
 	cpu_set_irq_affinity(irq, *affinity);
 	tsunami_update_irq_hw(cached_irq_mask);
 	tsunami_update_irq_hw(cached_irq_mask);
 	spin_unlock(&dp264_irq_lock);
 	spin_unlock(&dp264_irq_lock);
+
+	return 0;
 }
 }
 
 
-static void
+static int
 clipper_set_affinity(unsigned int irq, const struct cpumask *affinity)
 clipper_set_affinity(unsigned int irq, const struct cpumask *affinity)
 { 
 { 
 	spin_lock(&dp264_irq_lock);
 	spin_lock(&dp264_irq_lock);
 	cpu_set_irq_affinity(irq - 16, *affinity);
 	cpu_set_irq_affinity(irq - 16, *affinity);
 	tsunami_update_irq_hw(cached_irq_mask);
 	tsunami_update_irq_hw(cached_irq_mask);
 	spin_unlock(&dp264_irq_lock);
 	spin_unlock(&dp264_irq_lock);
+
+	return 0;
 }
 }
 
 
 static struct hw_interrupt_type dp264_irq_type = {
 static struct hw_interrupt_type dp264_irq_type = {

+ 3 - 1
arch/alpha/kernel/sys_titan.c

@@ -157,13 +157,15 @@ titan_cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
 
 
 }
 }
 
 
-static void
+static int
 titan_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
 titan_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
 { 
 { 
 	spin_lock(&titan_irq_lock);
 	spin_lock(&titan_irq_lock);
 	titan_cpu_set_irq_affinity(irq - 16, *affinity);
 	titan_cpu_set_irq_affinity(irq - 16, *affinity);
 	titan_update_irq_hw(titan_cached_irq_mask);
 	titan_update_irq_hw(titan_cached_irq_mask);
 	spin_unlock(&titan_irq_lock);
 	spin_unlock(&titan_irq_lock);
+
+	return 0;
 }
 }
 
 
 static void
 static void

+ 3 - 1
arch/arm/common/gic.c

@@ -109,7 +109,7 @@ static void gic_unmask_irq(unsigned int irq)
 }
 }
 
 
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
-static void gic_set_cpu(unsigned int irq, const struct cpumask *mask_val)
+static int gic_set_cpu(unsigned int irq, const struct cpumask *mask_val)
 {
 {
 	void __iomem *reg = gic_dist_base(irq) + GIC_DIST_TARGET + (gic_irq(irq) & ~3);
 	void __iomem *reg = gic_dist_base(irq) + GIC_DIST_TARGET + (gic_irq(irq) & ~3);
 	unsigned int shift = (irq % 4) * 8;
 	unsigned int shift = (irq % 4) * 8;
@@ -122,6 +122,8 @@ static void gic_set_cpu(unsigned int irq, const struct cpumask *mask_val)
 	val |= 1 << (cpu + shift);
 	val |= 1 << (cpu + shift);
 	writel(val, reg);
 	writel(val, reg);
 	spin_unlock(&irq_controller_lock);
 	spin_unlock(&irq_controller_lock);
+
+	return 0;
 }
 }
 #endif
 #endif
 
 

+ 3 - 1
arch/cris/arch-v32/kernel/irq.c

@@ -325,12 +325,14 @@ static void end_crisv32_irq(unsigned int irq)
 {
 {
 }
 }
 
 
-void set_affinity_crisv32_irq(unsigned int irq, const struct cpumask *dest)
+int set_affinity_crisv32_irq(unsigned int irq, const struct cpumask *dest)
 {
 {
 	unsigned long flags;
 	unsigned long flags;
 	spin_lock_irqsave(&irq_lock, flags);
 	spin_lock_irqsave(&irq_lock, flags);
 	irq_allocations[irq - FIRST_IRQ].mask = *dest;
 	irq_allocations[irq - FIRST_IRQ].mask = *dest;
 	spin_unlock_irqrestore(&irq_lock, flags);
 	spin_unlock_irqrestore(&irq_lock, flags);
+
+	return 0;
 }
 }
 
 
 static struct irq_chip crisv32_irq_type = {
 static struct irq_chip crisv32_irq_type = {

+ 2 - 1
arch/ia64/hp/sim/hpsim_irq.c

@@ -21,9 +21,10 @@ hpsim_irq_noop (unsigned int irq)
 {
 {
 }
 }
 
 
-static void
+static int
 hpsim_set_affinity_noop(unsigned int a, const struct cpumask *b)
 hpsim_set_affinity_noop(unsigned int a, const struct cpumask *b)
 {
 {
+	return 0;
 }
 }
 
 
 static struct hw_interrupt_type irq_type_hp_sim = {
 static struct hw_interrupt_type irq_type_hp_sim = {

+ 3 - 2
arch/ia64/kernel/acpi.c

@@ -636,7 +636,7 @@ void __init acpi_numa_arch_fixup(void)
  * success: return IRQ number (>=0)
  * success: return IRQ number (>=0)
  * failure: return < 0
  * failure: return < 0
  */
  */
-int acpi_register_gsi(u32 gsi, int triggering, int polarity)
+int acpi_register_gsi(struct device *dev, u32 gsi, int triggering, int polarity)
 {
 {
 	if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
 	if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
 		return gsi;
 		return gsi;
@@ -678,7 +678,8 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
 
 
 	fadt = (struct acpi_table_fadt *)fadt_header;
 	fadt = (struct acpi_table_fadt *)fadt_header;
 
 
-	acpi_register_gsi(fadt->sci_interrupt, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW);
+	acpi_register_gsi(NULL, fadt->sci_interrupt, ACPI_LEVEL_SENSITIVE,
+				 ACPI_ACTIVE_LOW);
 	return 0;
 	return 0;
 }
 }
 
 

+ 6 - 4
arch/ia64/kernel/iosapic.c

@@ -329,7 +329,7 @@ unmask_irq (unsigned int irq)
 }
 }
 
 
 
 
-static void
+static int
 iosapic_set_affinity(unsigned int irq, const struct cpumask *mask)
 iosapic_set_affinity(unsigned int irq, const struct cpumask *mask)
 {
 {
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
@@ -343,15 +343,15 @@ iosapic_set_affinity(unsigned int irq, const struct cpumask *mask)
 
 
 	cpu = cpumask_first_and(cpu_online_mask, mask);
 	cpu = cpumask_first_and(cpu_online_mask, mask);
 	if (cpu >= nr_cpu_ids)
 	if (cpu >= nr_cpu_ids)
-		return;
+		return -1;
 
 
 	if (irq_prepare_move(irq, cpu))
 	if (irq_prepare_move(irq, cpu))
-		return;
+		return -1;
 
 
 	dest = cpu_physical_id(cpu);
 	dest = cpu_physical_id(cpu);
 
 
 	if (!iosapic_intr_info[irq].count)
 	if (!iosapic_intr_info[irq].count)
-		return;			/* not an IOSAPIC interrupt */
+		return -1;			/* not an IOSAPIC interrupt */
 
 
 	set_irq_affinity_info(irq, dest, redir);
 	set_irq_affinity_info(irq, dest, redir);
 
 
@@ -376,7 +376,9 @@ iosapic_set_affinity(unsigned int irq, const struct cpumask *mask)
 		iosapic_write(iosapic, IOSAPIC_RTE_HIGH(rte_index), high32);
 		iosapic_write(iosapic, IOSAPIC_RTE_HIGH(rte_index), high32);
 		iosapic_write(iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
 		iosapic_write(iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
 	}
 	}
+
 #endif
 #endif
+	return 0;
 }
 }
 
 
 /*
 /*

+ 10 - 6
arch/ia64/kernel/msi_ia64.c

@@ -12,7 +12,7 @@
 static struct irq_chip	ia64_msi_chip;
 static struct irq_chip	ia64_msi_chip;
 
 
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
-static void ia64_set_msi_irq_affinity(unsigned int irq,
+static int ia64_set_msi_irq_affinity(unsigned int irq,
 				      const cpumask_t *cpu_mask)
 				      const cpumask_t *cpu_mask)
 {
 {
 	struct msi_msg msg;
 	struct msi_msg msg;
@@ -20,10 +20,10 @@ static void ia64_set_msi_irq_affinity(unsigned int irq,
 	int cpu = first_cpu(*cpu_mask);
 	int cpu = first_cpu(*cpu_mask);
 
 
 	if (!cpu_online(cpu))
 	if (!cpu_online(cpu))
-		return;
+		return -1;
 
 
 	if (irq_prepare_move(irq, cpu))
 	if (irq_prepare_move(irq, cpu))
-		return;
+		return -1;
 
 
 	read_msi_msg(irq, &msg);
 	read_msi_msg(irq, &msg);
 
 
@@ -39,6 +39,8 @@ static void ia64_set_msi_irq_affinity(unsigned int irq,
 
 
 	write_msi_msg(irq, &msg);
 	write_msi_msg(irq, &msg);
 	cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
 	cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
+
+	return 0;
 }
 }
 #endif /* CONFIG_SMP */
 #endif /* CONFIG_SMP */
 
 
@@ -130,17 +132,17 @@ void arch_teardown_msi_irq(unsigned int irq)
 
 
 #ifdef CONFIG_DMAR
 #ifdef CONFIG_DMAR
 #ifdef CONFIG_SMP
 #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_cfg *cfg = irq_cfg + irq;
 	struct irq_cfg *cfg = irq_cfg + irq;
 	struct msi_msg msg;
 	struct msi_msg msg;
 	int cpu = cpumask_first(mask);
 	int cpu = cpumask_first(mask);
 
 
 	if (!cpu_online(cpu))
 	if (!cpu_online(cpu))
-		return;
+		return -1;
 
 
 	if (irq_prepare_move(irq, cpu))
 	if (irq_prepare_move(irq, cpu))
-		return;
+		return -1;
 
 
 	dmar_msi_read(irq, &msg);
 	dmar_msi_read(irq, &msg);
 
 
@@ -151,6 +153,8 @@ static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
 
 
 	dmar_msi_write(irq, &msg);
 	dmar_msi_write(irq, &msg);
 	cpumask_copy(irq_desc[irq].affinity, mask);
 	cpumask_copy(irq_desc[irq].affinity, mask);
+
+	return 0;
 }
 }
 #endif /* CONFIG_SMP */
 #endif /* CONFIG_SMP */
 
 

+ 3 - 1
arch/ia64/sn/kernel/irq.c

@@ -227,7 +227,7 @@ finish_up:
 	return new_irq_info;
 	return new_irq_info;
 }
 }
 
 
-static void sn_set_affinity_irq(unsigned int irq, const struct cpumask *mask)
+static int sn_set_affinity_irq(unsigned int irq, const struct cpumask *mask)
 {
 {
 	struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
 	struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
 	nasid_t nasid;
 	nasid_t nasid;
@@ -239,6 +239,8 @@ static void sn_set_affinity_irq(unsigned int irq, const struct cpumask *mask)
 	list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
 	list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
 				 sn_irq_lh[irq], list)
 				 sn_irq_lh[irq], list)
 		(void)sn_retarget_vector(sn_irq_info, nasid, slice);
 		(void)sn_retarget_vector(sn_irq_info, nasid, slice);
+
+	return 0;
 }
 }
 
 
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP

+ 5 - 3
arch/ia64/sn/kernel/msi_sn.c

@@ -151,7 +151,7 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry)
 }
 }
 
 
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
-static void sn_set_msi_irq_affinity(unsigned int irq,
+static int sn_set_msi_irq_affinity(unsigned int irq,
 				    const struct cpumask *cpu_mask)
 				    const struct cpumask *cpu_mask)
 {
 {
 	struct msi_msg msg;
 	struct msi_msg msg;
@@ -168,7 +168,7 @@ static void sn_set_msi_irq_affinity(unsigned int irq,
 	cpu = cpumask_first(cpu_mask);
 	cpu = cpumask_first(cpu_mask);
 	sn_irq_info = sn_msi_info[irq].sn_irq_info;
 	sn_irq_info = sn_msi_info[irq].sn_irq_info;
 	if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
 	if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
-		return;
+		return -1;
 
 
 	/*
 	/*
 	 * Release XIO resources for the old MSI PCI address
 	 * Release XIO resources for the old MSI PCI address
@@ -189,7 +189,7 @@ static void sn_set_msi_irq_affinity(unsigned int irq,
 	new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice);
 	new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice);
 	sn_msi_info[irq].sn_irq_info = new_irq_info;
 	sn_msi_info[irq].sn_irq_info = new_irq_info;
 	if (new_irq_info == NULL)
 	if (new_irq_info == NULL)
-		return;
+		return -1;
 
 
 	/*
 	/*
 	 * Map the xio address into bus space
 	 * Map the xio address into bus space
@@ -206,6 +206,8 @@ static void sn_set_msi_irq_affinity(unsigned int irq,
 
 
 	write_msi_msg(irq, &msg);
 	write_msi_msg(irq, &msg);
 	cpumask_copy(irq_desc[irq].affinity, cpu_mask);
 	cpumask_copy(irq_desc[irq].affinity, cpu_mask);
+
+	return 0;
 }
 }
 #endif /* CONFIG_SMP */
 #endif /* CONFIG_SMP */
 
 

+ 6 - 2
arch/mips/cavium-octeon/octeon-irq.c

@@ -177,7 +177,7 @@ static void octeon_irq_ciu0_disable(unsigned int irq)
 }
 }
 
 
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
-static void octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *dest)
+static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *dest)
 {
 {
 	int cpu;
 	int cpu;
 	int bit = irq - OCTEON_IRQ_WORKQ0;	/* Bit 0-63 of EN0 */
 	int bit = irq - OCTEON_IRQ_WORKQ0;	/* Bit 0-63 of EN0 */
@@ -199,6 +199,8 @@ static void octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask
 	 */
 	 */
 	cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
 	cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
 	write_unlock(&octeon_irq_ciu0_rwlock);
 	write_unlock(&octeon_irq_ciu0_rwlock);
+
+	return 0;
 }
 }
 #endif
 #endif
 
 
@@ -292,7 +294,7 @@ static void octeon_irq_ciu1_disable(unsigned int irq)
 }
 }
 
 
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
-static void octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask *dest)
+static int octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask *dest)
 {
 {
 	int cpu;
 	int cpu;
 	int bit = irq - OCTEON_IRQ_WDOG0;	/* Bit 0-63 of EN1 */
 	int bit = irq - OCTEON_IRQ_WDOG0;	/* Bit 0-63 of EN1 */
@@ -315,6 +317,8 @@ static void octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask
 	 */
 	 */
 	cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
 	cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
 	write_unlock(&octeon_irq_ciu1_rwlock);
 	write_unlock(&octeon_irq_ciu1_rwlock);
+
+	return 0;
 }
 }
 #endif
 #endif
 
 

+ 1 - 1
arch/mips/include/asm/irq.h

@@ -49,7 +49,7 @@ static inline void smtc_im_ack_irq(unsigned int irq)
 #ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
 #ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
 #include <linux/cpumask.h>
 #include <linux/cpumask.h>
 
 
-extern void plat_set_irq_affinity(unsigned int irq,
+extern int plat_set_irq_affinity(unsigned int irq,
 				  const struct cpumask *affinity);
 				  const struct cpumask *affinity);
 extern void smtc_forward_irq(unsigned int irq);
 extern void smtc_forward_irq(unsigned int irq);
 
 

+ 3 - 2
arch/mips/kernel/irq-gic.c

@@ -155,7 +155,7 @@ static void gic_unmask_irq(unsigned int irq)
 
 
 static DEFINE_SPINLOCK(gic_lock);
 static DEFINE_SPINLOCK(gic_lock);
 
 
-static void gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
+static int gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
 {
 {
 	cpumask_t	tmp = CPU_MASK_NONE;
 	cpumask_t	tmp = CPU_MASK_NONE;
 	unsigned long	flags;
 	unsigned long	flags;
@@ -166,7 +166,7 @@ static void gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
 
 
 	cpumask_and(&tmp, cpumask, cpu_online_mask);
 	cpumask_and(&tmp, cpumask, cpu_online_mask);
 	if (cpus_empty(tmp))
 	if (cpus_empty(tmp))
-		return;
+		return -1;
 
 
 	/* Assumption : cpumask refers to a single CPU */
 	/* Assumption : cpumask refers to a single CPU */
 	spin_lock_irqsave(&gic_lock, flags);
 	spin_lock_irqsave(&gic_lock, flags);
@@ -190,6 +190,7 @@ static void gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
 	cpumask_copy(irq_desc[irq].affinity, cpumask);
 	cpumask_copy(irq_desc[irq].affinity, cpumask);
 	spin_unlock_irqrestore(&gic_lock, flags);
 	spin_unlock_irqrestore(&gic_lock, flags);
 
 
+	return 0;
 }
 }
 #endif
 #endif
 
 

+ 3 - 1
arch/mips/mti-malta/malta-smtc.c

@@ -114,7 +114,7 @@ struct plat_smp_ops msmtc_smp_ops = {
  */
  */
 
 
 
 
-void plat_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
+int plat_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
 {
 {
 	cpumask_t tmask;
 	cpumask_t tmask;
 	int cpu = 0;
 	int cpu = 0;
@@ -156,5 +156,7 @@ void plat_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
 
 
 	/* Do any generic SMTC IRQ affinity setup */
 	/* Do any generic SMTC IRQ affinity setup */
 	smtc_set_irq_affinity(irq, tmask);
 	smtc_set_irq_affinity(irq, tmask);
+
+	return 0;
 }
 }
 #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
 #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */

+ 5 - 3
arch/mips/sibyte/bcm1480/irq.c

@@ -50,7 +50,7 @@ static void enable_bcm1480_irq(unsigned int irq);
 static void disable_bcm1480_irq(unsigned int irq);
 static void disable_bcm1480_irq(unsigned int irq);
 static void ack_bcm1480_irq(unsigned int irq);
 static void ack_bcm1480_irq(unsigned int irq);
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
-static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask);
+static int bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask);
 #endif
 #endif
 
 
 #ifdef CONFIG_PCI
 #ifdef CONFIG_PCI
@@ -109,7 +109,7 @@ void bcm1480_unmask_irq(int cpu, int irq)
 }
 }
 
 
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
-static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask)
 {
 {
 	int i = 0, old_cpu, cpu, int_on, k;
 	int i = 0, old_cpu, cpu, int_on, k;
 	u64 cur_ints;
 	u64 cur_ints;
@@ -118,7 +118,7 @@ static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask)
 
 
 	if (cpumask_weight(mask) != 1) {
 	if (cpumask_weight(mask) != 1) {
 		printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
 		printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
-		return;
+		return -1;
 	}
 	}
 	i = cpumask_first(mask);
 	i = cpumask_first(mask);
 
 
@@ -152,6 +152,8 @@ static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask)
 		}
 		}
 	}
 	}
 	spin_unlock_irqrestore(&bcm1480_imr_lock, flags);
 	spin_unlock_irqrestore(&bcm1480_imr_lock, flags);
+
+	return 0;
 }
 }
 #endif
 #endif
 
 

+ 5 - 3
arch/mips/sibyte/sb1250/irq.c

@@ -50,7 +50,7 @@ static void enable_sb1250_irq(unsigned int irq);
 static void disable_sb1250_irq(unsigned int irq);
 static void disable_sb1250_irq(unsigned int irq);
 static void ack_sb1250_irq(unsigned int irq);
 static void ack_sb1250_irq(unsigned int irq);
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
-static void sb1250_set_affinity(unsigned int irq, const struct cpumask *mask);
+static int sb1250_set_affinity(unsigned int irq, const struct cpumask *mask);
 #endif
 #endif
 
 
 #ifdef CONFIG_SIBYTE_HAS_LDT
 #ifdef CONFIG_SIBYTE_HAS_LDT
@@ -103,7 +103,7 @@ void sb1250_unmask_irq(int cpu, int irq)
 }
 }
 
 
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
-static void sb1250_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int sb1250_set_affinity(unsigned int irq, const struct cpumask *mask)
 {
 {
 	int i = 0, old_cpu, cpu, int_on;
 	int i = 0, old_cpu, cpu, int_on;
 	u64 cur_ints;
 	u64 cur_ints;
@@ -113,7 +113,7 @@ static void sb1250_set_affinity(unsigned int irq, const struct cpumask *mask)
 
 
 	if (cpumask_weight(mask) > 1) {
 	if (cpumask_weight(mask) > 1) {
 		printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
 		printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
-		return;
+		return -1;
 	}
 	}
 
 
 	/* Convert logical CPU to physical CPU */
 	/* Convert logical CPU to physical CPU */
@@ -143,6 +143,8 @@ static void sb1250_set_affinity(unsigned int irq, const struct cpumask *mask)
 					R_IMR_INTERRUPT_MASK));
 					R_IMR_INTERRUPT_MASK));
 	}
 	}
 	spin_unlock_irqrestore(&sb1250_imr_lock, flags);
 	spin_unlock_irqrestore(&sb1250_imr_lock, flags);
+
+	return 0;
 }
 }
 #endif
 #endif
 
 

+ 4 - 2
arch/parisc/kernel/irq.c

@@ -130,15 +130,17 @@ int cpu_check_affinity(unsigned int irq, const struct cpumask *dest)
 	return cpu_dest;
 	return cpu_dest;
 }
 }
 
 
-static void cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest)
+static int cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest)
 {
 {
 	int cpu_dest;
 	int cpu_dest;
 
 
 	cpu_dest = cpu_check_affinity(irq, dest);
 	cpu_dest = cpu_check_affinity(irq, dest);
 	if (cpu_dest < 0)
 	if (cpu_dest < 0)
-		return;
+		return -1;
 
 
 	cpumask_copy(&irq_desc[irq].affinity, dest);
 	cpumask_copy(&irq_desc[irq].affinity, dest);
+
+	return 0;
 }
 }
 #endif
 #endif
 
 

+ 7 - 5
arch/powerpc/platforms/pseries/xics.c

@@ -333,7 +333,7 @@ static void xics_eoi_lpar(unsigned int virq)
 	lpar_xirr_info_set((0xff << 24) | irq);
 	lpar_xirr_info_set((0xff << 24) | irq);
 }
 }
 
 
-static void xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
+static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
 {
 {
 	unsigned int irq;
 	unsigned int irq;
 	int status;
 	int status;
@@ -342,14 +342,14 @@ static void xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
 
 
 	irq = (unsigned int)irq_map[virq].hwirq;
 	irq = (unsigned int)irq_map[virq].hwirq;
 	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
 	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
-		return;
+		return -1;
 
 
 	status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
 	status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
 
 
 	if (status) {
 	if (status) {
 		printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
 		printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
 			__func__, irq, status);
 			__func__, irq, status);
-		return;
+		return -1;
 	}
 	}
 
 
 	/*
 	/*
@@ -363,7 +363,7 @@ static void xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
 		printk(KERN_WARNING
 		printk(KERN_WARNING
 			"%s: No online cpus in the mask %s for irq %d\n",
 			"%s: No online cpus in the mask %s for irq %d\n",
 			__func__, cpulist, virq);
 			__func__, cpulist, virq);
-		return;
+		return -1;
 	}
 	}
 
 
 	status = rtas_call(ibm_set_xive, 3, 1, NULL,
 	status = rtas_call(ibm_set_xive, 3, 1, NULL,
@@ -372,8 +372,10 @@ static void xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
 	if (status) {
 	if (status) {
 		printk(KERN_ERR "%s: ibm,set-xive irq=%u returns %d\n",
 		printk(KERN_ERR "%s: ibm,set-xive irq=%u returns %d\n",
 			__func__, irq, status);
 			__func__, irq, status);
-		return;
+		return -1;
 	}
 	}
+
+	return 0;
 }
 }
 
 
 static struct irq_chip xics_pic_direct = {
 static struct irq_chip xics_pic_direct = {

+ 3 - 1
arch/powerpc/sysdev/mpic.c

@@ -807,7 +807,7 @@ static void mpic_end_ipi(unsigned int irq)
 
 
 #endif /* CONFIG_SMP */
 #endif /* CONFIG_SMP */
 
 
-void mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
+int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
 {
 {
 	struct mpic *mpic = mpic_from_irq(irq);
 	struct mpic *mpic = mpic_from_irq(irq);
 	unsigned int src = mpic_irq_to_hw(irq);
 	unsigned int src = mpic_irq_to_hw(irq);
@@ -824,6 +824,8 @@ void mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
 		mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION),
 		mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION),
 			       mpic_physmask(cpus_addr(tmp)[0]));
 			       mpic_physmask(cpus_addr(tmp)[0]));
 	}
 	}
+
+	return 0;
 }
 }
 
 
 static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
 static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)

+ 1 - 1
arch/powerpc/sysdev/mpic.h

@@ -36,6 +36,6 @@ static inline int mpic_pasemi_msi_init(struct mpic *mpic)
 
 
 extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
 extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
 extern void mpic_set_vector(unsigned int virq, unsigned int vector);
 extern void mpic_set_vector(unsigned int virq, unsigned int vector);
-extern void mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask);
+extern int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask);
 
 
 #endif /* _POWERPC_SYSDEV_MPIC_H */
 #endif /* _POWERPC_SYSDEV_MPIC_H */

+ 9 - 3
arch/sparc/kernel/irq_64.c

@@ -318,10 +318,12 @@ static void sun4u_irq_enable(unsigned int virt_irq)
 	}
 	}
 }
 }
 
 
-static void sun4u_set_affinity(unsigned int virt_irq,
+static int sun4u_set_affinity(unsigned int virt_irq,
 			       const struct cpumask *mask)
 			       const struct cpumask *mask)
 {
 {
 	sun4u_irq_enable(virt_irq);
 	sun4u_irq_enable(virt_irq);
+
+	return 0;
 }
 }
 
 
 /* Don't do anything.  The desc->status check for IRQ_DISABLED in
 /* Don't do anything.  The desc->status check for IRQ_DISABLED in
@@ -377,7 +379,7 @@ static void sun4v_irq_enable(unsigned int virt_irq)
 		       ino, err);
 		       ino, err);
 }
 }
 
 
-static void sun4v_set_affinity(unsigned int virt_irq,
+static int sun4v_set_affinity(unsigned int virt_irq,
 			       const struct cpumask *mask)
 			       const struct cpumask *mask)
 {
 {
 	unsigned int ino = virt_irq_table[virt_irq].dev_ino;
 	unsigned int ino = virt_irq_table[virt_irq].dev_ino;
@@ -388,6 +390,8 @@ static void sun4v_set_affinity(unsigned int virt_irq,
 	if (err != HV_EOK)
 	if (err != HV_EOK)
 		printk(KERN_ERR "sun4v_intr_settarget(%x,%lu): "
 		printk(KERN_ERR "sun4v_intr_settarget(%x,%lu): "
 		       "err(%d)\n", ino, cpuid, err);
 		       "err(%d)\n", ino, cpuid, err);
+
+	return 0;
 }
 }
 
 
 static void sun4v_irq_disable(unsigned int virt_irq)
 static void sun4v_irq_disable(unsigned int virt_irq)
@@ -445,7 +449,7 @@ static void sun4v_virq_enable(unsigned int virt_irq)
 		       dev_handle, dev_ino, err);
 		       dev_handle, dev_ino, err);
 }
 }
 
 
-static void sun4v_virt_set_affinity(unsigned int virt_irq,
+static int sun4v_virt_set_affinity(unsigned int virt_irq,
 				    const struct cpumask *mask)
 				    const struct cpumask *mask)
 {
 {
 	unsigned long cpuid, dev_handle, dev_ino;
 	unsigned long cpuid, dev_handle, dev_ino;
@@ -461,6 +465,8 @@ static void sun4v_virt_set_affinity(unsigned int virt_irq,
 		printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): "
 		printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): "
 		       "err(%d)\n",
 		       "err(%d)\n",
 		       dev_handle, dev_ino, cpuid, err);
 		       dev_handle, dev_ino, cpuid, err);
+
+	return 0;
 }
 }
 
 
 static void sun4v_virq_disable(unsigned int virt_irq)
 static void sun4v_virq_disable(unsigned int virt_irq)

+ 3 - 9
arch/x86/Kconfig

@@ -274,15 +274,9 @@ config SPARSE_IRQ
 
 
 	  If you don't know what to do here, say N.
 	  If you don't know what to do here, say N.
 
 
-config NUMA_MIGRATE_IRQ_DESC
-	bool "Move irq desc when changing irq smp_affinity"
+config NUMA_IRQ_DESC
+	def_bool y
 	depends on SPARSE_IRQ && NUMA
 	depends on SPARSE_IRQ && NUMA
-	depends on BROKEN
-	default n
-	---help---
-	  This enables moving irq_desc to cpu/node that irq will use handled.
-
-	  If you don't know what to do here, say N.
 
 
 config X86_MPPARSE
 config X86_MPPARSE
 	bool "Enable MPS table" if ACPI
 	bool "Enable MPS table" if ACPI
@@ -355,7 +349,7 @@ config X86_UV
 	depends on X86_64
 	depends on X86_64
 	depends on X86_EXTENDED_PLATFORM
 	depends on X86_EXTENDED_PLATFORM
 	depends on NUMA
 	depends on NUMA
-	select X86_X2APIC
+	depends on X86_X2APIC
 	---help---
 	---help---
 	  This option is needed in order to support SGI Ultraviolet systems.
 	  This option is needed in order to support SGI Ultraviolet systems.
 	  If you don't have one of these, you should say N here.
 	  If you don't have one of these, you should say N here.

+ 0 - 1
arch/x86/configs/x86_64_defconfig

@@ -195,7 +195,6 @@ CONFIG_HIGH_RES_TIMERS=y
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 CONFIG_SMP=y
 CONFIG_SMP=y
 CONFIG_SPARSE_IRQ=y
 CONFIG_SPARSE_IRQ=y
-# CONFIG_NUMA_MIGRATE_IRQ_DESC is not set
 CONFIG_X86_FIND_SMP_CONFIG=y
 CONFIG_X86_FIND_SMP_CONFIG=y
 CONFIG_X86_MPPARSE=y
 CONFIG_X86_MPPARSE=y
 # CONFIG_X86_ELAN is not set
 # CONFIG_X86_ELAN is not set

+ 10 - 18
arch/x86/include/asm/apic.h

@@ -107,8 +107,7 @@ extern u32 native_safe_apic_wait_icr_idle(void);
 extern void native_apic_icr_write(u32 low, u32 id);
 extern void native_apic_icr_write(u32 low, u32 id);
 extern u64 native_apic_icr_read(void);
 extern u64 native_apic_icr_read(void);
 
 
-#define EIM_8BIT_APIC_ID	0
-#define EIM_32BIT_APIC_ID	1
+extern int x2apic_mode;
 
 
 #ifdef CONFIG_X86_X2APIC
 #ifdef CONFIG_X86_X2APIC
 /*
 /*
@@ -166,10 +165,9 @@ static inline u64 native_x2apic_icr_read(void)
 	return val;
 	return val;
 }
 }
 
 
-extern int x2apic, x2apic_phys;
+extern int x2apic_phys;
 extern void check_x2apic(void);
 extern void check_x2apic(void);
 extern void enable_x2apic(void);
 extern void enable_x2apic(void);
-extern void enable_IR_x2apic(void);
 extern void x2apic_icr_write(u32 low, u32 id);
 extern void x2apic_icr_write(u32 low, u32 id);
 static inline int x2apic_enabled(void)
 static inline int x2apic_enabled(void)
 {
 {
@@ -183,6 +181,8 @@ static inline int x2apic_enabled(void)
 		return 1;
 		return 1;
 	return 0;
 	return 0;
 }
 }
+
+#define x2apic_supported()	(cpu_has_x2apic)
 #else
 #else
 static inline void check_x2apic(void)
 static inline void check_x2apic(void)
 {
 {
@@ -190,28 +190,20 @@ static inline void check_x2apic(void)
 static inline void enable_x2apic(void)
 static inline void enable_x2apic(void)
 {
 {
 }
 }
-static inline void enable_IR_x2apic(void)
-{
-}
 static inline int x2apic_enabled(void)
 static inline int x2apic_enabled(void)
 {
 {
 	return 0;
 	return 0;
 }
 }
 
 
-#define	x2apic	0
-
+#define	x2apic_preenabled 0
+#define	x2apic_supported()	0
 #endif
 #endif
 
 
-extern int get_physical_broadcast(void);
+extern void enable_IR_x2apic(void);
 
 
-#ifdef CONFIG_X86_X2APIC
-static inline void ack_x2APIC_irq(void)
-{
-	/* Docs say use 0 for future compatibility */
-	native_apic_msr_write(APIC_EOI, 0);
-}
-#endif
+extern int get_physical_broadcast(void);
 
 
+extern void apic_disable(void);
 extern int lapic_get_maxlvt(void);
 extern int lapic_get_maxlvt(void);
 extern void clear_local_APIC(void);
 extern void clear_local_APIC(void);
 extern void connect_bsp_APIC(void);
 extern void connect_bsp_APIC(void);
@@ -252,7 +244,7 @@ static inline void lapic_shutdown(void) { }
 #define local_apic_timer_c2_ok		1
 #define local_apic_timer_c2_ok		1
 static inline void init_apic_mappings(void) { }
 static inline void init_apic_mappings(void) { }
 static inline void disable_local_APIC(void) { }
 static inline void disable_local_APIC(void) { }
-
+static inline void apic_disable(void) { }
 #endif /* !CONFIG_X86_LOCAL_APIC */
 #endif /* !CONFIG_X86_LOCAL_APIC */
 
 
 #ifdef CONFIG_X86_64
 #ifdef CONFIG_X86_64

+ 4 - 4
arch/x86/include/asm/apicdef.h

@@ -22,6 +22,7 @@
 #  define	APIC_INTEGRATED(x)	(1)
 #  define	APIC_INTEGRATED(x)	(1)
 #endif
 #endif
 #define		APIC_XAPIC(x)		((x) >= 0x14)
 #define		APIC_XAPIC(x)		((x) >= 0x14)
+#define		APIC_EXT_SPACE(x)	((x) & 0x80000000)
 #define	APIC_TASKPRI	0x80
 #define	APIC_TASKPRI	0x80
 #define		APIC_TPRI_MASK		0xFFu
 #define		APIC_TPRI_MASK		0xFFu
 #define	APIC_ARBPRI	0x90
 #define	APIC_ARBPRI	0x90
@@ -116,7 +117,9 @@
 #define		APIC_TDR_DIV_32		0x8
 #define		APIC_TDR_DIV_32		0x8
 #define		APIC_TDR_DIV_64		0x9
 #define		APIC_TDR_DIV_64		0x9
 #define		APIC_TDR_DIV_128	0xA
 #define		APIC_TDR_DIV_128	0xA
-#define	APIC_EILVT0     0x500
+#define	APIC_EFEAT	0x400
+#define	APIC_ECTRL	0x410
+#define APIC_EILVTn(n)	(0x500 + 0x10 * n)
 #define		APIC_EILVT_NR_AMD_K8	1	/* # of extended interrupts */
 #define		APIC_EILVT_NR_AMD_K8	1	/* # of extended interrupts */
 #define		APIC_EILVT_NR_AMD_10H	4
 #define		APIC_EILVT_NR_AMD_10H	4
 #define		APIC_EILVT_LVTOFF(x)	(((x) >> 4) & 0xF)
 #define		APIC_EILVT_LVTOFF(x)	(((x) >> 4) & 0xF)
@@ -125,9 +128,6 @@
 #define		APIC_EILVT_MSG_NMI	0x4
 #define		APIC_EILVT_MSG_NMI	0x4
 #define		APIC_EILVT_MSG_EXT	0x7
 #define		APIC_EILVT_MSG_EXT	0x7
 #define		APIC_EILVT_MASKED	(1 << 16)
 #define		APIC_EILVT_MASKED	(1 << 16)
-#define	APIC_EILVT1     0x510
-#define	APIC_EILVT2     0x520
-#define	APIC_EILVT3     0x530
 
 
 #define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
 #define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
 #define APIC_BASE_MSR	0x800
 #define APIC_BASE_MSR	0x800

+ 3 - 3
arch/x86/include/asm/cpufeature.h

@@ -22,7 +22,7 @@
 #define X86_FEATURE_TSC		(0*32+ 4) /* Time Stamp Counter */
 #define X86_FEATURE_TSC		(0*32+ 4) /* Time Stamp Counter */
 #define X86_FEATURE_MSR		(0*32+ 5) /* Model-Specific Registers */
 #define X86_FEATURE_MSR		(0*32+ 5) /* Model-Specific Registers */
 #define X86_FEATURE_PAE		(0*32+ 6) /* Physical Address Extensions */
 #define X86_FEATURE_PAE		(0*32+ 6) /* Physical Address Extensions */
-#define X86_FEATURE_MCE		(0*32+ 7) /* Machine Check Architecture */
+#define X86_FEATURE_MCE		(0*32+ 7) /* Machine Check Exception */
 #define X86_FEATURE_CX8		(0*32+ 8) /* CMPXCHG8 instruction */
 #define X86_FEATURE_CX8		(0*32+ 8) /* CMPXCHG8 instruction */
 #define X86_FEATURE_APIC	(0*32+ 9) /* Onboard APIC */
 #define X86_FEATURE_APIC	(0*32+ 9) /* Onboard APIC */
 #define X86_FEATURE_SEP		(0*32+11) /* SYSENTER/SYSEXIT */
 #define X86_FEATURE_SEP		(0*32+11) /* SYSENTER/SYSEXIT */
@@ -192,11 +192,11 @@ extern const char * const x86_power_flags[32];
 #define clear_cpu_cap(c, bit)	clear_bit(bit, (unsigned long *)((c)->x86_capability))
 #define clear_cpu_cap(c, bit)	clear_bit(bit, (unsigned long *)((c)->x86_capability))
 #define setup_clear_cpu_cap(bit) do { \
 #define setup_clear_cpu_cap(bit) do { \
 	clear_cpu_cap(&boot_cpu_data, bit);	\
 	clear_cpu_cap(&boot_cpu_data, bit);	\
-	set_bit(bit, (unsigned long *)cleared_cpu_caps); \
+	set_bit(bit, (unsigned long *)cpu_caps_cleared); \
 } while (0)
 } while (0)
 #define setup_force_cpu_cap(bit) do { \
 #define setup_force_cpu_cap(bit) do { \
 	set_cpu_cap(&boot_cpu_data, bit);	\
 	set_cpu_cap(&boot_cpu_data, bit);	\
-	clear_bit(bit, (unsigned long *)cleared_cpu_caps);	\
+	set_bit(bit, (unsigned long *)cpu_caps_set);	\
 } while (0)
 } while (0)
 
 
 #define cpu_has_fpu		boot_cpu_has(X86_FEATURE_FPU)
 #define cpu_has_fpu		boot_cpu_has(X86_FEATURE_FPU)

+ 20 - 1
arch/x86/include/asm/hw_irq.h

@@ -63,7 +63,26 @@ extern unsigned long io_apic_irqs;
 extern void init_VISWS_APIC_irqs(void);
 extern void init_VISWS_APIC_irqs(void);
 extern void setup_IO_APIC(void);
 extern void setup_IO_APIC(void);
 extern void disable_IO_APIC(void);
 extern void disable_IO_APIC(void);
-extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
+
+struct io_apic_irq_attr {
+	int ioapic;
+	int ioapic_pin;
+	int trigger;
+	int polarity;
+};
+
+static inline void set_io_apic_irq_attr(struct io_apic_irq_attr *irq_attr,
+					int ioapic, int ioapic_pin,
+					int trigger, int polarity)
+{
+	irq_attr->ioapic     = ioapic;
+	irq_attr->ioapic_pin = ioapic_pin;
+	irq_attr->trigger    = trigger;
+	irq_attr->polarity   = polarity;
+}
+
+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);
 
 
 extern void enable_IO_APIC(void);
 extern void enable_IO_APIC(void);

+ 0 - 4
arch/x86/include/asm/i8259.h

@@ -60,8 +60,4 @@ extern struct irq_chip i8259A_chip;
 extern void mask_8259A(void);
 extern void mask_8259A(void);
 extern void unmask_8259A(void);
 extern void unmask_8259A(void);
 
 
-#ifdef CONFIG_X86_32
-extern void init_ISA_irqs(void);
-#endif
-
 #endif /* _ASM_X86_I8259_H */
 #endif /* _ASM_X86_I8259_H */

+ 3 - 6
arch/x86/include/asm/io_apic.h

@@ -154,22 +154,19 @@ extern int timer_through_8259;
 extern int io_apic_get_unique_id(int ioapic, int apic_id);
 extern int io_apic_get_unique_id(int ioapic, int apic_id);
 extern int io_apic_get_version(int ioapic);
 extern int io_apic_get_version(int ioapic);
 extern int io_apic_get_redir_entries(int ioapic);
 extern int io_apic_get_redir_entries(int ioapic);
-extern int io_apic_set_pci_routing(int ioapic, int pin, int irq,
-				   int edge_level, int active_high_low);
 #endif /* CONFIG_ACPI */
 #endif /* CONFIG_ACPI */
 
 
+struct io_apic_irq_attr;
+extern int io_apic_set_pci_routing(struct device *dev, int irq,
+		 struct io_apic_irq_attr *irq_attr);
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
 extern void ioapic_init_mappings(void);
 extern void ioapic_init_mappings(void);
 
 
-#ifdef CONFIG_X86_64
 extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
 extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
 extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
 extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
 extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
 extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
 extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
 extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
 extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
 extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
-extern void reinit_intr_remapped_IO_APIC(int intr_remapping,
-	struct IO_APIC_route_entry **ioapic_entries);
-#endif
 
 
 extern void probe_nr_irqs_gsi(void);
 extern void probe_nr_irqs_gsi(void);
 
 

+ 1 - 1
arch/x86/include/asm/irq_remapping.h

@@ -1,6 +1,6 @@
 #ifndef _ASM_X86_IRQ_REMAPPING_H
 #ifndef _ASM_X86_IRQ_REMAPPING_H
 #define _ASM_X86_IRQ_REMAPPING_H
 #define _ASM_X86_IRQ_REMAPPING_H
 
 
-#define IRTE_DEST(dest) ((x2apic) ? dest : dest << 8)
+#define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8)
 
 
 #endif	/* _ASM_X86_IRQ_REMAPPING_H */
 #endif	/* _ASM_X86_IRQ_REMAPPING_H */

+ 1 - 0
arch/x86/include/asm/irq_vectors.h

@@ -34,6 +34,7 @@
 
 
 #ifdef CONFIG_X86_32
 #ifdef CONFIG_X86_32
 # define SYSCALL_VECTOR			0x80
 # define SYSCALL_VECTOR			0x80
+# define IA32_SYSCALL_VECTOR		0x80
 #else
 #else
 # define IA32_SYSCALL_VECTOR		0x80
 # define IA32_SYSCALL_VECTOR		0x80
 #endif
 #endif

+ 5 - 10
arch/x86/include/asm/mpspec.h

@@ -61,9 +61,11 @@ extern void get_smp_config(void);
 #ifdef CONFIG_X86_MPPARSE
 #ifdef CONFIG_X86_MPPARSE
 extern void find_smp_config(void);
 extern void find_smp_config(void);
 extern void early_reserve_e820_mpc_new(void);
 extern void early_reserve_e820_mpc_new(void);
+extern int enable_update_mptable;
 #else
 #else
 static inline void find_smp_config(void) { }
 static inline void find_smp_config(void) { }
 static inline void early_reserve_e820_mpc_new(void) { }
 static inline void early_reserve_e820_mpc_new(void) { }
+#define enable_update_mptable 0
 #endif
 #endif
 
 
 void __cpuinit generic_processor_info(int apicid, int version);
 void __cpuinit generic_processor_info(int apicid, int version);
@@ -72,20 +74,13 @@ extern void mp_register_ioapic(int id, u32 address, u32 gsi_base);
 extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
 extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
 				   u32 gsi);
 				   u32 gsi);
 extern void mp_config_acpi_legacy_irqs(void);
 extern void mp_config_acpi_legacy_irqs(void);
-extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+struct device;
+extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level,
+				 int active_high_low);
 extern int acpi_probe_gsi(void);
 extern int acpi_probe_gsi(void);
 #ifdef CONFIG_X86_IO_APIC
 #ifdef CONFIG_X86_IO_APIC
-extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
-				u32 gsi, int triggering, int polarity);
 extern int mp_find_ioapic(int gsi);
 extern int mp_find_ioapic(int gsi);
 extern int mp_find_ioapic_pin(int ioapic, int gsi);
 extern int mp_find_ioapic_pin(int ioapic, int gsi);
-#else
-static inline int
-mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
-		   u32 gsi, int triggering, int polarity)
-{
-	return 0;
-}
 #endif
 #endif
 #else /* !CONFIG_ACPI: */
 #else /* !CONFIG_ACPI: */
 static inline int acpi_probe_gsi(void)
 static inline int acpi_probe_gsi(void)

+ 2 - 1
arch/x86/include/asm/processor.h

@@ -135,7 +135,8 @@ extern struct cpuinfo_x86	boot_cpu_data;
 extern struct cpuinfo_x86	new_cpu_data;
 extern struct cpuinfo_x86	new_cpu_data;
 
 
 extern struct tss_struct	doublefault_tss;
 extern struct tss_struct	doublefault_tss;
-extern __u32			cleared_cpu_caps[NCAPINTS];
+extern __u32			cpu_caps_cleared[NCAPINTS];
+extern __u32			cpu_caps_set[NCAPINTS];
 
 
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
 DECLARE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
 DECLARE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);

+ 0 - 1
arch/x86/include/asm/setup.h

@@ -33,7 +33,6 @@ struct x86_quirks {
 	int (*setup_ioapic_ids)(void);
 	int (*setup_ioapic_ids)(void);
 };
 };
 
 
-extern void x86_quirk_pre_intr_init(void);
 extern void x86_quirk_intr_init(void);
 extern void x86_quirk_intr_init(void);
 
 
 extern void x86_quirk_trap_init(void);
 extern void x86_quirk_trap_init(void);

+ 1 - 1
arch/x86/include/asm/smp.h

@@ -180,7 +180,7 @@ extern int safe_smp_processor_id(void);
 static inline int logical_smp_processor_id(void)
 static inline int logical_smp_processor_id(void)
 {
 {
 	/* we don't want to mark this access volatile - bad code generation */
 	/* we don't want to mark this access volatile - bad code generation */
-	return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
+	return GET_APIC_LOGICAL_ID(apic_read(APIC_LDR));
 }
 }
 
 
 #endif
 #endif

+ 1 - 1
arch/x86/kernel/Makefile

@@ -28,7 +28,7 @@ CFLAGS_paravirt.o	:= $(nostackp)
 obj-y			:= process_$(BITS).o signal.o entry_$(BITS).o
 obj-y			:= process_$(BITS).o signal.o entry_$(BITS).o
 obj-y			+= traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
 obj-y			+= traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
 obj-y			+= time_$(BITS).o ioport.o ldt.o dumpstack.o
 obj-y			+= time_$(BITS).o ioport.o ldt.o dumpstack.o
-obj-y			+= setup.o i8259.o irqinit_$(BITS).o
+obj-y			+= setup.o i8259.o irqinit.o
 obj-$(CONFIG_X86_VISWS)	+= visws_quirks.o
 obj-$(CONFIG_X86_VISWS)	+= visws_quirks.o
 obj-$(CONFIG_X86_32)	+= probe_roms_32.o
 obj-$(CONFIG_X86_32)	+= probe_roms_32.o
 obj-$(CONFIG_X86_32)	+= sys_i386_32.o i386_ksyms_32.o
 obj-$(CONFIG_X86_32)	+= sys_i386_32.o i386_ksyms_32.o

+ 53 - 103
arch/x86/kernel/acpi/boot.c

@@ -33,6 +33,7 @@
 #include <linux/irq.h>
 #include <linux/irq.h>
 #include <linux/bootmem.h>
 #include <linux/bootmem.h>
 #include <linux/ioport.h>
 #include <linux/ioport.h>
+#include <linux/pci.h>
 
 
 #include <asm/pgtable.h>
 #include <asm/pgtable.h>
 #include <asm/io_apic.h>
 #include <asm/io_apic.h>
@@ -522,7 +523,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
  * success: return IRQ number (>=0)
  * success: return IRQ number (>=0)
  * failure: return < 0
  * failure: return < 0
  */
  */
-int acpi_register_gsi(u32 gsi, int triggering, int polarity)
+int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
 {
 {
 	unsigned int irq;
 	unsigned int irq;
 	unsigned int plat_gsi = gsi;
 	unsigned int plat_gsi = gsi;
@@ -532,14 +533,14 @@ int acpi_register_gsi(u32 gsi, int triggering, int polarity)
 	 * Make sure all (legacy) PCI IRQs are set as level-triggered.
 	 * Make sure all (legacy) PCI IRQs are set as level-triggered.
 	 */
 	 */
 	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
 	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
-		if (triggering == ACPI_LEVEL_SENSITIVE)
+		if (trigger == ACPI_LEVEL_SENSITIVE)
 			eisa_set_level_irq(gsi);
 			eisa_set_level_irq(gsi);
 	}
 	}
 #endif
 #endif
 
 
 #ifdef CONFIG_X86_IO_APIC
 #ifdef CONFIG_X86_IO_APIC
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) {
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) {
-		plat_gsi = mp_register_gsi(gsi, triggering, polarity);
+		plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity);
 	}
 	}
 #endif
 #endif
 	acpi_gsi_to_irq(plat_gsi, &irq);
 	acpi_gsi_to_irq(plat_gsi, &irq);
@@ -903,10 +904,8 @@ extern int es7000_plat;
 #endif
 #endif
 
 
 static struct {
 static struct {
-	int apic_id;
 	int gsi_base;
 	int gsi_base;
 	int gsi_end;
 	int gsi_end;
-	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
 } mp_ioapic_routing[MAX_IO_APICS];
 } mp_ioapic_routing[MAX_IO_APICS];
 
 
 int mp_find_ioapic(int gsi)
 int mp_find_ioapic(int gsi)
@@ -986,16 +985,12 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
 
 
 	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
 	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
 	mp_ioapics[idx].apicid = uniq_ioapic_id(id);
 	mp_ioapics[idx].apicid = uniq_ioapic_id(id);
-#ifdef CONFIG_X86_32
 	mp_ioapics[idx].apicver = io_apic_get_version(idx);
 	mp_ioapics[idx].apicver = io_apic_get_version(idx);
-#else
-	mp_ioapics[idx].apicver = 0;
-#endif
+
 	/*
 	/*
 	 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
 	 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
 	 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
 	 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
 	 */
 	 */
-	mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].apicid;
 	mp_ioapic_routing[idx].gsi_base = gsi_base;
 	mp_ioapic_routing[idx].gsi_base = gsi_base;
 	mp_ioapic_routing[idx].gsi_end = gsi_base +
 	mp_ioapic_routing[idx].gsi_end = gsi_base +
 	    io_apic_get_redir_entries(idx);
 	    io_apic_get_redir_entries(idx);
@@ -1158,26 +1153,52 @@ void __init mp_config_acpi_legacy_irqs(void)
 	}
 	}
 }
 }
 
 
-int mp_register_gsi(u32 gsi, int triggering, int polarity)
+static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
+			int polarity)
 {
 {
+#ifdef CONFIG_X86_MPPARSE
+	struct mpc_intsrc mp_irq;
+	struct pci_dev *pdev;
+	unsigned char number;
+	unsigned int devfn;
 	int ioapic;
 	int ioapic;
-	int ioapic_pin;
-#ifdef CONFIG_X86_32
-#define MAX_GSI_NUM	4096
-#define IRQ_COMPRESSION_START	64
+	u8 pin;
 
 
-	static int pci_irq = IRQ_COMPRESSION_START;
-	/*
-	 * Mapping between Global System Interrupts, which
-	 * represent all possible interrupts, and IRQs
-	 * assigned to actual devices.
-	 */
-	static int gsi_to_irq[MAX_GSI_NUM];
-#else
+	if (!acpi_ioapic)
+		return 0;
+	if (!dev)
+		return 0;
+	if (dev->bus != &pci_bus_type)
+		return 0;
+
+	pdev = to_pci_dev(dev);
+	number = pdev->bus->number;
+	devfn = pdev->devfn;
+	pin = pdev->pin;
+	/* print the entry should happen on mptable identically */
+	mp_irq.type = MP_INTSRC;
+	mp_irq.irqtype = mp_INT;
+	mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+				(polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+	mp_irq.srcbus = number;
+	mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+	ioapic = mp_find_ioapic(gsi);
+	mp_irq.dstapic = mp_ioapics[ioapic].apicid;
+	mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
+
+	save_mp_irq(&mp_irq);
+#endif
+	return 0;
+}
+
+int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
+{
+	int ioapic;
+	int ioapic_pin;
+	struct io_apic_irq_attr irq_attr;
 
 
 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
 		return gsi;
 		return gsi;
-#endif
 
 
 	/* Don't set up the ACPI SCI because it's already set up */
 	/* Don't set up the ACPI SCI because it's already set up */
 	if (acpi_gbl_FADT.sci_interrupt == gsi)
 	if (acpi_gbl_FADT.sci_interrupt == gsi)
@@ -1196,93 +1217,22 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
 		gsi = ioapic_renumber_irq(ioapic, gsi);
 		gsi = ioapic_renumber_irq(ioapic, gsi);
 #endif
 #endif
 
 
-	/*
-	 * Avoid pin reprogramming.  PRTs typically include entries
-	 * with redundant pin->gsi mappings (but unique PCI devices);
-	 * we only program the IOAPIC on the first.
-	 */
 	if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
 	if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
 		printk(KERN_ERR "Invalid reference to IOAPIC pin "
 		printk(KERN_ERR "Invalid reference to IOAPIC pin "
-		       "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
+		       "%d-%d\n", mp_ioapics[ioapic].apicid,
 		       ioapic_pin);
 		       ioapic_pin);
 		return gsi;
 		return gsi;
 	}
 	}
-	if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) {
-		pr_debug("Pin %d-%d already programmed\n",
-			 mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
-#ifdef CONFIG_X86_32
-		return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
-#else
-		return gsi;
-#endif
-	}
-
-	set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed);
-#ifdef CONFIG_X86_32
-	/*
-	 * For GSI >= 64, use IRQ compression
-	 */
-	if ((gsi >= IRQ_COMPRESSION_START)
-	    && (triggering == ACPI_LEVEL_SENSITIVE)) {
-		/*
-		 * For PCI devices assign IRQs in order, avoiding gaps
-		 * due to unused I/O APIC pins.
-		 */
-		int irq = gsi;
-		if (gsi < MAX_GSI_NUM) {
-			/*
-			 * Retain the VIA chipset work-around (gsi > 15), but
-			 * avoid a problem where the 8254 timer (IRQ0) is setup
-			 * via an override (so it's not on pin 0 of the ioapic),
-			 * and at the same time, the pin 0 interrupt is a PCI
-			 * type.  The gsi > 15 test could cause these two pins
-			 * to be shared as IRQ0, and they are not shareable.
-			 * So test for this condition, and if necessary, avoid
-			 * the pin collision.
-			 */
-			gsi = pci_irq++;
-			/*
-			 * Don't assign IRQ used by ACPI SCI
-			 */
-			if (gsi == acpi_gbl_FADT.sci_interrupt)
-				gsi = pci_irq++;
-			gsi_to_irq[irq] = gsi;
-		} else {
-			printk(KERN_ERR "GSI %u is too high\n", gsi);
-			return gsi;
-		}
-	}
-#endif
-	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
-				triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
-				polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
-	return gsi;
-}
 
 
-int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
-			u32 gsi, int triggering, int polarity)
-{
-#ifdef CONFIG_X86_MPPARSE
-	struct mpc_intsrc mp_irq;
-	int ioapic;
+	if (enable_update_mptable)
+		mp_config_acpi_gsi(dev, gsi, trigger, polarity);
 
 
-	if (!acpi_ioapic)
-		return 0;
+	set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
+			     trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
+			     polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
+	io_apic_set_pci_routing(dev, gsi, &irq_attr);
 
 
-	/* print the entry should happen on mptable identically */
-	mp_irq.type = MP_INTSRC;
-	mp_irq.irqtype = mp_INT;
-	mp_irq.irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
-				(polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
-	mp_irq.srcbus = number;
-	mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
-	ioapic = mp_find_ioapic(gsi);
-	mp_irq.dstapic = mp_ioapic_routing[ioapic].apic_id;
-	mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
-
-	save_mp_irq(&mp_irq);
-#endif
-	return 0;
+	return gsi;
 }
 }
 
 
 /*
 /*

+ 191 - 120
arch/x86/kernel/apic/apic.c

@@ -98,6 +98,29 @@ early_param("lapic", parse_lapic);
 /* Local APIC was disabled by the BIOS and enabled by the kernel */
 /* Local APIC was disabled by the BIOS and enabled by the kernel */
 static int enabled_via_apicbase;
 static int enabled_via_apicbase;
 
 
+/*
+ * Handle interrupt mode configuration register (IMCR).
+ * This register controls whether the interrupt signals
+ * that reach the BSP come from the master PIC or from the
+ * local APIC. Before entering Symmetric I/O Mode, either
+ * the BIOS or the operating system must switch out of
+ * PIC Mode by changing the IMCR.
+ */
+static inline void imcr_pic_to_apic(void)
+{
+	/* select IMCR register */
+	outb(0x70, 0x22);
+	/* NMI and 8259 INTR go through APIC */
+	outb(0x01, 0x23);
+}
+
+static inline void imcr_apic_to_pic(void)
+{
+	/* select IMCR register */
+	outb(0x70, 0x22);
+	/* NMI and 8259 INTR go directly to BSP */
+	outb(0x00, 0x23);
+}
 #endif
 #endif
 
 
 #ifdef CONFIG_X86_64
 #ifdef CONFIG_X86_64
@@ -111,13 +134,19 @@ static __init int setup_apicpmtimer(char *s)
 __setup("apicpmtimer", setup_apicpmtimer);
 __setup("apicpmtimer", setup_apicpmtimer);
 #endif
 #endif
 
 
+int x2apic_mode;
 #ifdef CONFIG_X86_X2APIC
 #ifdef CONFIG_X86_X2APIC
-int x2apic;
 /* x2apic enabled before OS handover */
 /* x2apic enabled before OS handover */
 static int x2apic_preenabled;
 static int x2apic_preenabled;
 static int disable_x2apic;
 static int disable_x2apic;
 static __init int setup_nox2apic(char *str)
 static __init int setup_nox2apic(char *str)
 {
 {
+	if (x2apic_enabled()) {
+		pr_warning("Bios already enabled x2apic, "
+			   "can't enforce nox2apic");
+		return 0;
+	}
+
 	disable_x2apic = 1;
 	disable_x2apic = 1;
 	setup_clear_cpu_cap(X86_FEATURE_X2APIC);
 	setup_clear_cpu_cap(X86_FEATURE_X2APIC);
 	return 0;
 	return 0;
@@ -209,6 +238,31 @@ static int modern_apic(void)
 	return lapic_get_version() >= 0x14;
 	return lapic_get_version() >= 0x14;
 }
 }
 
 
+/*
+ * bare function to substitute write operation
+ * and it's _that_ fast :)
+ */
+static void native_apic_write_dummy(u32 reg, u32 v)
+{
+	WARN_ON_ONCE((cpu_has_apic || !disable_apic));
+}
+
+static u32 native_apic_read_dummy(u32 reg)
+{
+	WARN_ON_ONCE((cpu_has_apic && !disable_apic));
+	return 0;
+}
+
+/*
+ * right after this call apic->write/read doesn't do anything
+ * note that there is no restore operation it works one way
+ */
+void apic_disable(void)
+{
+	apic->read = native_apic_read_dummy;
+	apic->write = native_apic_write_dummy;
+}
+
 void native_apic_wait_icr_idle(void)
 void native_apic_wait_icr_idle(void)
 {
 {
 	while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
 	while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
@@ -348,7 +402,7 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
 
 
 static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask)
 static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask)
 {
 {
-	unsigned long reg = (lvt_off << 4) + APIC_EILVT0;
+	unsigned long reg = (lvt_off << 4) + APIC_EILVTn(0);
 	unsigned int  v   = (mask << 16) | (msg_type << 8) | vector;
 	unsigned int  v   = (mask << 16) | (msg_type << 8) | vector;
 
 
 	apic_write(reg, v);
 	apic_write(reg, v);
@@ -815,7 +869,7 @@ void clear_local_APIC(void)
 	u32 v;
 	u32 v;
 
 
 	/* APIC hasn't been mapped yet */
 	/* APIC hasn't been mapped yet */
-	if (!x2apic && !apic_phys)
+	if (!x2apic_mode && !apic_phys)
 		return;
 		return;
 
 
 	maxlvt = lapic_get_maxlvt();
 	maxlvt = lapic_get_maxlvt();
@@ -1287,7 +1341,7 @@ void check_x2apic(void)
 {
 {
 	if (x2apic_enabled()) {
 	if (x2apic_enabled()) {
 		pr_info("x2apic enabled by BIOS, switching to x2apic ops\n");
 		pr_info("x2apic enabled by BIOS, switching to x2apic ops\n");
-		x2apic_preenabled = x2apic = 1;
+		x2apic_preenabled = x2apic_mode = 1;
 	}
 	}
 }
 }
 
 
@@ -1295,7 +1349,7 @@ void enable_x2apic(void)
 {
 {
 	int msr, msr2;
 	int msr, msr2;
 
 
-	if (!x2apic)
+	if (!x2apic_mode)
 		return;
 		return;
 
 
 	rdmsr(MSR_IA32_APICBASE, msr, msr2);
 	rdmsr(MSR_IA32_APICBASE, msr, msr2);
@@ -1304,6 +1358,7 @@ void enable_x2apic(void)
 		wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0);
 		wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0);
 	}
 	}
 }
 }
+#endif /* CONFIG_X86_X2APIC */
 
 
 void __init enable_IR_x2apic(void)
 void __init enable_IR_x2apic(void)
 {
 {
@@ -1312,32 +1367,21 @@ void __init enable_IR_x2apic(void)
 	unsigned long flags;
 	unsigned long flags;
 	struct IO_APIC_route_entry **ioapic_entries = NULL;
 	struct IO_APIC_route_entry **ioapic_entries = NULL;
 
 
-	if (!cpu_has_x2apic)
-		return;
-
-	if (!x2apic_preenabled && disable_x2apic) {
-		pr_info("Skipped enabling x2apic and Interrupt-remapping "
-			"because of nox2apic\n");
-		return;
+	ret = dmar_table_init();
+	if (ret) {
+		pr_debug("dmar_table_init() failed with %d:\n", ret);
+		goto ir_failed;
 	}
 	}
 
 
-	if (x2apic_preenabled && disable_x2apic)
-		panic("Bios already enabled x2apic, can't enforce nox2apic");
-
-	if (!x2apic_preenabled && skip_ioapic_setup) {
-		pr_info("Skipped enabling x2apic and Interrupt-remapping "
-			"because of skipping io-apic setup\n");
-		return;
+	if (!intr_remapping_supported()) {
+		pr_debug("intr-remapping not supported\n");
+		goto ir_failed;
 	}
 	}
 
 
-	ret = dmar_table_init();
-	if (ret) {
-		pr_info("dmar_table_init() failed with %d:\n", ret);
 
 
-		if (x2apic_preenabled)
-			panic("x2apic enabled by bios. But IR enabling failed");
-		else
-			pr_info("Not enabling x2apic,Intr-remapping\n");
+	if (!x2apic_preenabled && skip_ioapic_setup) {
+		pr_info("Skipped enabling intr-remap because of skipping "
+			"io-apic setup\n");
 		return;
 		return;
 	}
 	}
 
 
@@ -1357,19 +1401,16 @@ void __init enable_IR_x2apic(void)
 	mask_IO_APIC_setup(ioapic_entries);
 	mask_IO_APIC_setup(ioapic_entries);
 	mask_8259A();
 	mask_8259A();
 
 
-	ret = enable_intr_remapping(EIM_32BIT_APIC_ID);
-
-	if (ret && x2apic_preenabled) {
-		local_irq_restore(flags);
-		panic("x2apic enabled by bios. But IR enabling failed");
-	}
-
+	ret = enable_intr_remapping(x2apic_supported());
 	if (ret)
 	if (ret)
 		goto end_restore;
 		goto end_restore;
 
 
-	if (!x2apic) {
-		x2apic = 1;
+	pr_info("Enabled Interrupt-remapping\n");
+
+	if (x2apic_supported() && !x2apic_mode) {
+		x2apic_mode = 1;
 		enable_x2apic();
 		enable_x2apic();
+		pr_info("Enabled x2apic\n");
 	}
 	}
 
 
 end_restore:
 end_restore:
@@ -1378,37 +1419,34 @@ end_restore:
 		 * IR enabling failed
 		 * IR enabling failed
 		 */
 		 */
 		restore_IO_APIC_setup(ioapic_entries);
 		restore_IO_APIC_setup(ioapic_entries);
-	else
-		reinit_intr_remapped_IO_APIC(x2apic_preenabled, ioapic_entries);
 
 
 	unmask_8259A();
 	unmask_8259A();
 	local_irq_restore(flags);
 	local_irq_restore(flags);
 
 
 end:
 end:
-	if (!ret) {
-		if (!x2apic_preenabled)
-			pr_info("Enabled x2apic and interrupt-remapping\n");
-		else
-			pr_info("Enabled Interrupt-remapping\n");
-	} else
-		pr_err("Failed to enable Interrupt-remapping and x2apic\n");
 	if (ioapic_entries)
 	if (ioapic_entries)
 		free_ioapic_entries(ioapic_entries);
 		free_ioapic_entries(ioapic_entries);
+
+	if (!ret)
+		return;
+
+ir_failed:
+	if (x2apic_preenabled)
+		panic("x2apic enabled by bios. But IR enabling failed");
+	else if (cpu_has_x2apic)
+		pr_info("Not enabling x2apic,Intr-remapping\n");
 #else
 #else
 	if (!cpu_has_x2apic)
 	if (!cpu_has_x2apic)
 		return;
 		return;
 
 
 	if (x2apic_preenabled)
 	if (x2apic_preenabled)
 		panic("x2apic enabled prior OS handover,"
 		panic("x2apic enabled prior OS handover,"
-		      " enable CONFIG_INTR_REMAP");
-
-	pr_info("Enable CONFIG_INTR_REMAP for enabling intr-remapping "
-		" and x2apic\n");
+		      " enable CONFIG_X86_X2APIC, CONFIG_INTR_REMAP");
 #endif
 #endif
 
 
 	return;
 	return;
 }
 }
-#endif /* CONFIG_X86_X2APIC */
+
 
 
 #ifdef CONFIG_X86_64
 #ifdef CONFIG_X86_64
 /*
 /*
@@ -1425,7 +1463,6 @@ static int __init detect_init_APIC(void)
 	}
 	}
 
 
 	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
 	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
-	boot_cpu_physical_apicid = 0;
 	return 0;
 	return 0;
 }
 }
 #else
 #else
@@ -1539,32 +1576,49 @@ void __init early_init_lapic_mapping(void)
  */
  */
 void __init init_apic_mappings(void)
 void __init init_apic_mappings(void)
 {
 {
-	if (x2apic) {
+	unsigned int new_apicid;
+
+	if (x2apic_mode) {
 		boot_cpu_physical_apicid = read_apic_id();
 		boot_cpu_physical_apicid = read_apic_id();
 		return;
 		return;
 	}
 	}
 
 
-	/*
-	 * If no local APIC can be found then set up a fake all
-	 * zeroes page to simulate the local APIC and another
-	 * one for the IO-APIC.
-	 */
+	/* If no local APIC can be found return early */
 	if (!smp_found_config && detect_init_APIC()) {
 	if (!smp_found_config && detect_init_APIC()) {
-		apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
-		apic_phys = __pa(apic_phys);
-	} else
+		/* lets NOP'ify apic operations */
+		pr_info("APIC: disable apic facility\n");
+		apic_disable();
+	} else {
 		apic_phys = mp_lapic_addr;
 		apic_phys = mp_lapic_addr;
 
 
-	set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
-	apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n",
-				APIC_BASE, apic_phys);
+		/*
+		 * acpi lapic path already maps that address in
+		 * acpi_register_lapic_address()
+		 */
+		if (!acpi_lapic)
+			set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
+
+		apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n",
+					APIC_BASE, apic_phys);
+	}
 
 
 	/*
 	/*
 	 * Fetch the APIC ID of the BSP in case we have a
 	 * Fetch the APIC ID of the BSP in case we have a
 	 * default configuration (or the MP table is broken).
 	 * default configuration (or the MP table is broken).
 	 */
 	 */
-	if (boot_cpu_physical_apicid == -1U)
-		boot_cpu_physical_apicid = read_apic_id();
+	new_apicid = read_apic_id();
+	if (boot_cpu_physical_apicid != new_apicid) {
+		boot_cpu_physical_apicid = new_apicid;
+		/*
+		 * yeah -- we lie about apic_version
+		 * in case if apic was disabled via boot option
+		 * but it's not a problem for SMP compiled kernel
+		 * since smp_sanity_check is prepared for such a case
+		 * and disable smp mode
+		 */
+		apic_version[new_apicid] =
+			 GET_APIC_VERSION(apic_read(APIC_LVR));
+	}
 }
 }
 
 
 /*
 /*
@@ -1733,8 +1787,7 @@ void __init connect_bsp_APIC(void)
 		 */
 		 */
 		apic_printk(APIC_VERBOSE, "leaving PIC mode, "
 		apic_printk(APIC_VERBOSE, "leaving PIC mode, "
 				"enabling APIC mode.\n");
 				"enabling APIC mode.\n");
-		outb(0x70, 0x22);
-		outb(0x01, 0x23);
+		imcr_pic_to_apic();
 	}
 	}
 #endif
 #endif
 	if (apic->enable_apic_mode)
 	if (apic->enable_apic_mode)
@@ -1762,8 +1815,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
 		 */
 		 */
 		apic_printk(APIC_VERBOSE, "disabling APIC mode, "
 		apic_printk(APIC_VERBOSE, "disabling APIC mode, "
 				"entering PIC mode.\n");
 				"entering PIC mode.\n");
-		outb(0x70, 0x22);
-		outb(0x00, 0x23);
+		imcr_apic_to_pic();
 		return;
 		return;
 	}
 	}
 #endif
 #endif
@@ -1969,10 +2021,10 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
 
 
 	local_irq_save(flags);
 	local_irq_save(flags);
 	disable_local_APIC();
 	disable_local_APIC();
-#ifdef CONFIG_INTR_REMAP
+
 	if (intr_remapping_enabled)
 	if (intr_remapping_enabled)
 		disable_intr_remapping();
 		disable_intr_remapping();
-#endif
+
 	local_irq_restore(flags);
 	local_irq_restore(flags);
 	return 0;
 	return 0;
 }
 }
@@ -1982,42 +2034,34 @@ static int lapic_resume(struct sys_device *dev)
 	unsigned int l, h;
 	unsigned int l, h;
 	unsigned long flags;
 	unsigned long flags;
 	int maxlvt;
 	int maxlvt;
-
-#ifdef CONFIG_INTR_REMAP
-	int ret;
+	int ret = 0;
 	struct IO_APIC_route_entry **ioapic_entries = NULL;
 	struct IO_APIC_route_entry **ioapic_entries = NULL;
 
 
 	if (!apic_pm_state.active)
 	if (!apic_pm_state.active)
 		return 0;
 		return 0;
 
 
 	local_irq_save(flags);
 	local_irq_save(flags);
-	if (x2apic) {
+	if (intr_remapping_enabled) {
 		ioapic_entries = alloc_ioapic_entries();
 		ioapic_entries = alloc_ioapic_entries();
 		if (!ioapic_entries) {
 		if (!ioapic_entries) {
 			WARN(1, "Alloc ioapic_entries in lapic resume failed.");
 			WARN(1, "Alloc ioapic_entries in lapic resume failed.");
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto restore;
 		}
 		}
 
 
 		ret = save_IO_APIC_setup(ioapic_entries);
 		ret = save_IO_APIC_setup(ioapic_entries);
 		if (ret) {
 		if (ret) {
 			WARN(1, "Saving IO-APIC state failed: %d\n", ret);
 			WARN(1, "Saving IO-APIC state failed: %d\n", ret);
 			free_ioapic_entries(ioapic_entries);
 			free_ioapic_entries(ioapic_entries);
-			return ret;
+			goto restore;
 		}
 		}
 
 
 		mask_IO_APIC_setup(ioapic_entries);
 		mask_IO_APIC_setup(ioapic_entries);
 		mask_8259A();
 		mask_8259A();
-		enable_x2apic();
 	}
 	}
-#else
-	if (!apic_pm_state.active)
-		return 0;
 
 
-	local_irq_save(flags);
-	if (x2apic)
+	if (x2apic_mode)
 		enable_x2apic();
 		enable_x2apic();
-#endif
-
 	else {
 	else {
 		/*
 		/*
 		 * Make sure the APICBASE points to the right address
 		 * Make sure the APICBASE points to the right address
@@ -2055,21 +2099,16 @@ static int lapic_resume(struct sys_device *dev)
 	apic_write(APIC_ESR, 0);
 	apic_write(APIC_ESR, 0);
 	apic_read(APIC_ESR);
 	apic_read(APIC_ESR);
 
 
-#ifdef CONFIG_INTR_REMAP
-	if (intr_remapping_enabled)
-		reenable_intr_remapping(EIM_32BIT_APIC_ID);
-
-	if (x2apic) {
+	if (intr_remapping_enabled) {
+		reenable_intr_remapping(x2apic_mode);
 		unmask_8259A();
 		unmask_8259A();
 		restore_IO_APIC_setup(ioapic_entries);
 		restore_IO_APIC_setup(ioapic_entries);
 		free_ioapic_entries(ioapic_entries);
 		free_ioapic_entries(ioapic_entries);
 	}
 	}
-#endif
-
+restore:
 	local_irq_restore(flags);
 	local_irq_restore(flags);
 
 
-
-	return 0;
+	return ret;
 }
 }
 
 
 /*
 /*
@@ -2117,31 +2156,14 @@ static void apic_pm_activate(void) { }
 #endif	/* CONFIG_PM */
 #endif	/* CONFIG_PM */
 
 
 #ifdef CONFIG_X86_64
 #ifdef CONFIG_X86_64
-/*
- * apic_is_clustered_box() -- Check if we can expect good TSC
- *
- * Thus far, the major user of this is IBM's Summit2 series:
- *
- * Clustered boxes may have unsynced TSC problems if they are
- * multi-chassis. Use available data to take a good guess.
- * If in doubt, go HPET.
- */
-__cpuinit int apic_is_clustered_box(void)
+
+static int __cpuinit apic_cluster_num(void)
 {
 {
 	int i, clusters, zeros;
 	int i, clusters, zeros;
 	unsigned id;
 	unsigned id;
 	u16 *bios_cpu_apicid;
 	u16 *bios_cpu_apicid;
 	DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
 	DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
 
 
-	/*
-	 * there is not this kind of box with AMD CPU yet.
-	 * Some AMD box with quadcore cpu and 8 sockets apicid
-	 * will be [4, 0x23] or [8, 0x27] could be thought to
-	 * vsmp box still need checking...
-	 */
-	if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && !is_vsmp_box())
-		return 0;
-
 	bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
 	bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
 	bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
 	bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
 
 
@@ -2177,18 +2199,67 @@ __cpuinit int apic_is_clustered_box(void)
 			++zeros;
 			++zeros;
 	}
 	}
 
 
-	/* ScaleMP vSMPowered boxes have one cluster per board and TSCs are
-	 * not guaranteed to be synced between boards
-	 */
-	if (is_vsmp_box() && clusters > 1)
+	return clusters;
+}
+
+static int __cpuinitdata multi_checked;
+static int __cpuinitdata multi;
+
+static int __cpuinit set_multi(const struct dmi_system_id *d)
+{
+	if (multi)
+		return 0;
+	pr_info("APIC: %s detected, Multi Chassis\n", d->ident);
+	multi = 1;
+	return 0;
+}
+
+static const __cpuinitconst struct dmi_system_id multi_dmi_table[] = {
+	{
+		.callback = set_multi,
+		.ident = "IBM System Summit2",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Summit2"),
+		},
+	},
+	{}
+};
+
+static void __cpuinit dmi_check_multi(void)
+{
+	if (multi_checked)
+		return;
+
+	dmi_check_system(multi_dmi_table);
+	multi_checked = 1;
+}
+
+/*
+ * apic_is_clustered_box() -- Check if we can expect good TSC
+ *
+ * Thus far, the major user of this is IBM's Summit2 series:
+ * Clustered boxes may have unsynced TSC problems if they are
+ * multi-chassis.
+ * Use DMI to check them
+ */
+__cpuinit int apic_is_clustered_box(void)
+{
+	dmi_check_multi();
+	if (multi)
 		return 1;
 		return 1;
 
 
+	if (!is_vsmp_box())
+		return 0;
+
 	/*
 	/*
-	 * If clusters > 2, then should be multi-chassis.
-	 * May have to revisit this when multi-core + hyperthreaded CPUs come
-	 * out, but AFAIK this will work even for them.
+	 * ScaleMP vSMPowered boxes have one cluster per board and TSCs are
+	 * not guaranteed to be synced between boards
 	 */
 	 */
-	return (clusters > 2);
+	if (apic_cluster_num() > 1)
+		return 1;
+
+	return 0;
 }
 }
 #endif
 #endif
 
 

+ 2 - 2
arch/x86/kernel/apic/apic_flat_64.c

@@ -161,7 +161,7 @@ static int flat_apic_id_registered(void)
 
 
 static int flat_phys_pkg_id(int initial_apic_id, int index_msb)
 static int flat_phys_pkg_id(int initial_apic_id, int index_msb)
 {
 {
-	return hard_smp_processor_id() >> index_msb;
+	return initial_apic_id >> index_msb;
 }
 }
 
 
 struct apic apic_flat =  {
 struct apic apic_flat =  {
@@ -235,7 +235,7 @@ static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 	 * regardless of how many processors are present (x86_64 ES7000
 	 * regardless of how many processors are present (x86_64 ES7000
 	 * is an example).
 	 * is an example).
 	 */
 	 */
-	if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID &&
+	if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
 		(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) {
 		(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) {
 		printk(KERN_DEBUG "system APIC only can use physical flat");
 		printk(KERN_DEBUG "system APIC only can use physical flat");
 		return 1;
 		return 1;

+ 1 - 1
arch/x86/kernel/apic/es7000_32.c

@@ -145,7 +145,7 @@ es7000_rename_gsi(int ioapic, int gsi)
 	return gsi;
 	return gsi;
 }
 }
 
 
-static int wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip)
+static int __cpuinit wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip)
 {
 {
 	unsigned long vect = 0, psaival = 0;
 	unsigned long vect = 0, psaival = 0;
 
 

File diff ditekan karena terlalu besar
+ 315 - 364
arch/x86/kernel/apic/io_apic.c


+ 1 - 1
arch/x86/kernel/apic/probe_64.c

@@ -50,7 +50,7 @@ static struct apic *apic_probe[] __initdata = {
 void __init default_setup_apic_routing(void)
 void __init default_setup_apic_routing(void)
 {
 {
 #ifdef CONFIG_X86_X2APIC
 #ifdef CONFIG_X86_X2APIC
-	if (x2apic && (apic != &apic_x2apic_phys &&
+	if (x2apic_mode && (apic != &apic_x2apic_phys &&
 #ifdef CONFIG_X86_UV
 #ifdef CONFIG_X86_UV
 		       apic != &apic_x2apic_uv_x &&
 		       apic != &apic_x2apic_uv_x &&
 #endif
 #endif

+ 0 - 7
arch/x86/kernel/apic/summit_32.c

@@ -173,13 +173,6 @@ static inline int is_WPEG(struct rio_detail *rio){
 		rio->type == LookOutAWPEG || rio->type == LookOutBWPEG);
 		rio->type == LookOutAWPEG || rio->type == LookOutBWPEG);
 }
 }
 
 
-
-/* In clustered mode, the high nibble of APIC ID is a cluster number.
- * The low nibble is a 4-bit bitmap. */
-#define XAPIC_DEST_CPUS_SHIFT	4
-#define XAPIC_DEST_CPUS_MASK	((1u << XAPIC_DEST_CPUS_SHIFT) - 1)
-#define XAPIC_DEST_CLUSTER_MASK	(XAPIC_DEST_CPUS_MASK << XAPIC_DEST_CPUS_SHIFT)
-
 #define SUMMIT_APIC_DFR_VALUE	(APIC_DFR_CLUSTER)
 #define SUMMIT_APIC_DFR_VALUE	(APIC_DFR_CLUSTER)
 
 
 static const struct cpumask *summit_target_cpus(void)
 static const struct cpumask *summit_target_cpus(void)

+ 4 - 1
arch/x86/kernel/apic/x2apic_uv_x.c

@@ -105,7 +105,7 @@ static void uv_vector_allocation_domain(int cpu, struct cpumask *retmask)
 	cpumask_set_cpu(cpu, retmask);
 	cpumask_set_cpu(cpu, retmask);
 }
 }
 
 
-static int uv_wakeup_secondary(int phys_apicid, unsigned long start_rip)
+static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_rip)
 {
 {
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
 	unsigned long val;
 	unsigned long val;
@@ -583,15 +583,18 @@ void __init uv_system_init(void)
 
 
 	bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
 	bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
 	uv_blade_info = kmalloc(bytes, GFP_KERNEL);
 	uv_blade_info = kmalloc(bytes, GFP_KERNEL);
+	BUG_ON(!uv_blade_info);
 
 
 	get_lowmem_redirect(&lowmem_redir_base, &lowmem_redir_size);
 	get_lowmem_redirect(&lowmem_redir_base, &lowmem_redir_size);
 
 
 	bytes = sizeof(uv_node_to_blade[0]) * num_possible_nodes();
 	bytes = sizeof(uv_node_to_blade[0]) * num_possible_nodes();
 	uv_node_to_blade = kmalloc(bytes, GFP_KERNEL);
 	uv_node_to_blade = kmalloc(bytes, GFP_KERNEL);
+	BUG_ON(!uv_node_to_blade);
 	memset(uv_node_to_blade, 255, bytes);
 	memset(uv_node_to_blade, 255, bytes);
 
 
 	bytes = sizeof(uv_cpu_to_blade[0]) * num_possible_cpus();
 	bytes = sizeof(uv_cpu_to_blade[0]) * num_possible_cpus();
 	uv_cpu_to_blade = kmalloc(bytes, GFP_KERNEL);
 	uv_cpu_to_blade = kmalloc(bytes, GFP_KERNEL);
+	BUG_ON(!uv_cpu_to_blade);
 	memset(uv_cpu_to_blade, 255, bytes);
 	memset(uv_cpu_to_blade, 255, bytes);
 
 
 	blade = 0;
 	blade = 0;

+ 1 - 1
arch/x86/kernel/cpu/amd.c

@@ -272,7 +272,7 @@ static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c)
 #if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
 #if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
 	int cpu = smp_processor_id();
 	int cpu = smp_processor_id();
 	int node;
 	int node;
-	unsigned apicid = hard_smp_processor_id();
+	unsigned apicid = cpu_has_apic ? hard_smp_processor_id() : c->apicid;
 
 
 	node = c->phys_proc_id;
 	node = c->phys_proc_id;
 	if (apicid_to_node[apicid] != NUMA_NO_NODE)
 	if (apicid_to_node[apicid] != NUMA_NO_NODE)

+ 18 - 5
arch/x86/kernel/cpu/common.c

@@ -299,7 +299,8 @@ static const char *__cpuinit table_lookup_model(struct cpuinfo_x86 *c)
 	return NULL;		/* Not found */
 	return NULL;		/* Not found */
 }
 }
 
 
-__u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
+__u32 cpu_caps_cleared[NCAPINTS] __cpuinitdata;
+__u32 cpu_caps_set[NCAPINTS] __cpuinitdata;
 
 
 void load_percpu_segment(int cpu)
 void load_percpu_segment(int cpu)
 {
 {
@@ -768,6 +769,12 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
 	if (this_cpu->c_identify)
 	if (this_cpu->c_identify)
 		this_cpu->c_identify(c);
 		this_cpu->c_identify(c);
 
 
+	/* Clear/Set all flags overriden by options, after probe */
+	for (i = 0; i < NCAPINTS; i++) {
+		c->x86_capability[i] &= ~cpu_caps_cleared[i];
+		c->x86_capability[i] |= cpu_caps_set[i];
+	}
+
 #ifdef CONFIG_X86_64
 #ifdef CONFIG_X86_64
 	c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
 	c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
 #endif
 #endif
@@ -813,6 +820,16 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
 #endif
 #endif
 
 
 	init_hypervisor(c);
 	init_hypervisor(c);
+
+	/*
+	 * Clear/Set all flags overriden by options, need do it
+	 * before following smp all cpus cap AND.
+	 */
+	for (i = 0; i < NCAPINTS; i++) {
+		c->x86_capability[i] &= ~cpu_caps_cleared[i];
+		c->x86_capability[i] |= cpu_caps_set[i];
+	}
+
 	/*
 	/*
 	 * On SMP, boot_cpu_data holds the common feature set between
 	 * On SMP, boot_cpu_data holds the common feature set between
 	 * all CPUs; so make sure that we indicate which features are
 	 * all CPUs; so make sure that we indicate which features are
@@ -825,10 +842,6 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
 			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
 			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
 	}
 	}
 
 
-	/* Clear all flags overriden by options */
-	for (i = 0; i < NCAPINTS; i++)
-		c->x86_capability[i] &= ~cleared_cpu_caps[i];
-
 #ifdef CONFIG_X86_MCE
 #ifdef CONFIG_X86_MCE
 	/* Init Machine Check Exception if available. */
 	/* Init Machine Check Exception if available. */
 	mcheck_init(c);
 	mcheck_init(c);

+ 13 - 1
arch/x86/kernel/cpu/cpu_debug.c

@@ -588,8 +588,20 @@ static void print_apic(void *arg)
 	seq_printf(seq, " TMICT\t\t: %08x\n",  apic_read(APIC_TMICT));
 	seq_printf(seq, " TMICT\t\t: %08x\n",  apic_read(APIC_TMICT));
 	seq_printf(seq, " TMCCT\t\t: %08x\n",  apic_read(APIC_TMCCT));
 	seq_printf(seq, " TMCCT\t\t: %08x\n",  apic_read(APIC_TMCCT));
 	seq_printf(seq, " TDCR\t\t: %08x\n",  apic_read(APIC_TDCR));
 	seq_printf(seq, " TDCR\t\t: %08x\n",  apic_read(APIC_TDCR));
-#endif /* CONFIG_X86_LOCAL_APIC */
+	if (boot_cpu_has(X86_FEATURE_EXTAPIC)) {
+		unsigned int i, v, maxeilvt;
+
+		v = apic_read(APIC_EFEAT);
+		maxeilvt = (v >> 16) & 0xff;
+		seq_printf(seq, " EFEAT\t\t: %08x\n", v);
+		seq_printf(seq, " ECTRL\t\t: %08x\n", apic_read(APIC_ECTRL));
 
 
+		for (i = 0; i < maxeilvt; i++) {
+			v = apic_read(APIC_EILVTn(i));
+			seq_printf(seq, " EILVT%d\t\t: %08x\n", i, v);
+		}
+	}
+#endif /* CONFIG_X86_LOCAL_APIC */
 	seq_printf(seq, "\n MSR\t:\n");
 	seq_printf(seq, "\n MSR\t:\n");
 }
 }
 
 

+ 3 - 3
arch/x86/kernel/cpu/intel.c

@@ -229,12 +229,12 @@ static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c)
 }
 }
 #endif
 #endif
 
 
-static void __cpuinit srat_detect_node(void)
+static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c)
 {
 {
 #if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
 #if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
 	unsigned node;
 	unsigned node;
 	int cpu = smp_processor_id();
 	int cpu = smp_processor_id();
-	int apicid = hard_smp_processor_id();
+	int apicid = cpu_has_apic ? hard_smp_processor_id() : c->apicid;
 
 
 	/* Don't do the funky fallback heuristics the AMD version employs
 	/* Don't do the funky fallback heuristics the AMD version employs
 	   for now. */
 	   for now. */
@@ -400,7 +400,7 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
 	}
 	}
 
 
 	/* Work around errata */
 	/* Work around errata */
-	srat_detect_node();
+	srat_detect_node(c);
 
 
 	if (cpu_has(c, X86_FEATURE_VMX))
 	if (cpu_has(c, X86_FEATURE_VMX))
 		detect_vmx_virtcap(c);
 		detect_vmx_virtcap(c);

+ 7 - 12
arch/x86/kernel/irq.c

@@ -24,9 +24,9 @@ void (*generic_interrupt_extension)(void) = NULL;
  */
  */
 void ack_bad_irq(unsigned int irq)
 void ack_bad_irq(unsigned int irq)
 {
 {
-	printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq);
+	if (printk_ratelimit())
+		pr_err("unexpected IRQ trap at vector %02x\n", irq);
 
 
-#ifdef CONFIG_X86_LOCAL_APIC
 	/*
 	/*
 	 * Currently unexpected vectors happen only on SMP and APIC.
 	 * Currently unexpected vectors happen only on SMP and APIC.
 	 * We _must_ ack these because every local APIC has only N
 	 * We _must_ ack these because every local APIC has only N
@@ -36,9 +36,7 @@ void ack_bad_irq(unsigned int irq)
 	 * completely.
 	 * completely.
 	 * But only ack when the APIC is enabled -AK
 	 * But only ack when the APIC is enabled -AK
 	 */
 	 */
-	if (cpu_has_apic)
-		ack_APIC_irq();
-#endif
+	ack_APIC_irq();
 }
 }
 
 
 #define irq_stats(x)		(&per_cpu(irq_stat, x))
 #define irq_stats(x)		(&per_cpu(irq_stat, x))
@@ -178,7 +176,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
 	sum += irq_stats(cpu)->irq_thermal_count;
 	sum += irq_stats(cpu)->irq_thermal_count;
 # ifdef CONFIG_X86_64
 # ifdef CONFIG_X86_64
 	sum += irq_stats(cpu)->irq_threshold_count;
 	sum += irq_stats(cpu)->irq_threshold_count;
-#endif
+# endif
 #endif
 #endif
 	return sum;
 	return sum;
 }
 }
@@ -213,14 +211,11 @@ unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
 	irq = __get_cpu_var(vector_irq)[vector];
 	irq = __get_cpu_var(vector_irq)[vector];
 
 
 	if (!handle_irq(irq, regs)) {
 	if (!handle_irq(irq, regs)) {
-#ifdef CONFIG_X86_64
-		if (!disable_apic)
-			ack_APIC_irq();
-#endif
+		ack_APIC_irq();
 
 
 		if (printk_ratelimit())
 		if (printk_ratelimit())
-			printk(KERN_EMERG "%s: %d.%d No irq handler for vector (irq %d)\n",
-			       __func__, smp_processor_id(), vector, irq);
+			pr_emerg("%s: %d.%d No irq handler for vector (irq %d)\n",
+				__func__, smp_processor_id(), vector, irq);
 	}
 	}
 
 
 	irq_exit();
 	irq_exit();

+ 109 - 40
arch/x86/kernel/irqinit_32.c → arch/x86/kernel/irqinit.c

@@ -1,20 +1,25 @@
+#include <linux/linkage.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
+#include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/random.h>
+#include <linux/kprobes.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
 #include <linux/kernel_stat.h>
 #include <linux/sysdev.h>
 #include <linux/sysdev.h>
 #include <linux/bitops.h>
 #include <linux/bitops.h>
+#include <linux/acpi.h>
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
 
 
 #include <asm/atomic.h>
 #include <asm/atomic.h>
 #include <asm/system.h>
 #include <asm/system.h>
 #include <asm/timer.h>
 #include <asm/timer.h>
+#include <asm/hw_irq.h>
 #include <asm/pgtable.h>
 #include <asm/pgtable.h>
 #include <asm/desc.h>
 #include <asm/desc.h>
 #include <asm/apic.h>
 #include <asm/apic.h>
@@ -22,7 +27,23 @@
 #include <asm/i8259.h>
 #include <asm/i8259.h>
 #include <asm/traps.h>
 #include <asm/traps.h>
 
 
+/*
+ * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
+ * (these are usually mapped to vectors 0x30-0x3f)
+ */
+
+/*
+ * The IO-APIC gives us many more interrupt sources. Most of these
+ * are unused but an SMP system is supposed to have enough memory ...
+ * sometimes (mostly wrt. hw bugs) we get corrupted vectors all
+ * across the spectrum, so we really want to be prepared to get all
+ * of these. Plus, more powerful systems might have more than 64
+ * IO-APIC registers.
+ *
+ * (these are usually mapped into the 0x30-0xff vector range)
+ */
 
 
+#ifdef CONFIG_X86_32
 /*
 /*
  * Note that on a 486, we don't want to do a SIGFPE on an irq13
  * Note that on a 486, we don't want to do a SIGFPE on an irq13
  * as the irq is unreliable, and exception 16 works correctly
  * as the irq is unreliable, and exception 16 works correctly
@@ -52,30 +73,7 @@ static struct irqaction fpu_irq = {
 	.handler = math_error_irq,
 	.handler = math_error_irq,
 	.name = "fpu",
 	.name = "fpu",
 };
 };
-
-void __init init_ISA_irqs(void)
-{
-	int i;
-
-#ifdef CONFIG_X86_LOCAL_APIC
-	init_bsp_APIC();
 #endif
 #endif
-	init_8259A(0);
-
-	/*
-	 * 16 old-style INTA-cycle interrupts:
-	 */
-	for (i = 0; i < NR_IRQS_LEGACY; i++) {
-		struct irq_desc *desc = irq_to_desc(i);
-
-		desc->status = IRQ_DISABLED;
-		desc->action = NULL;
-		desc->depth = 1;
-
-		set_irq_chip_and_handler_name(i, &i8259A_chip,
-					      handle_level_irq, "XT");
-	}
-}
 
 
 /*
 /*
  * IRQ2 is cascade interrupt to second interrupt controller
  * IRQ2 is cascade interrupt to second interrupt controller
@@ -118,29 +116,37 @@ int vector_used_by_percpu_irq(unsigned int vector)
 	return 0;
 	return 0;
 }
 }
 
 
-/* Overridden in paravirt.c */
-void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
-
-void __init native_init_IRQ(void)
+static void __init init_ISA_irqs(void)
 {
 {
 	int i;
 	int i;
 
 
-	/* Execute any quirks before the call gates are initialised: */
-	x86_quirk_pre_intr_init();
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
+	init_bsp_APIC();
+#endif
+	init_8259A(0);
 
 
 	/*
 	/*
-	 * Cover the whole vector space, no vector can escape
-	 * us. (some of these will be overridden and become
-	 * 'special' SMP interrupts)
+	 * 16 old-style INTA-cycle interrupts:
 	 */
 	 */
-	for (i =  FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) {
-		/* SYSCALL_VECTOR was reserved in trap_init. */
-		if (i != SYSCALL_VECTOR)
-			set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]);
+	for (i = 0; i < NR_IRQS_LEGACY; i++) {
+		struct irq_desc *desc = irq_to_desc(i);
+
+		desc->status = IRQ_DISABLED;
+		desc->action = NULL;
+		desc->depth = 1;
+
+		set_irq_chip_and_handler_name(i, &i8259A_chip,
+					      handle_level_irq, "XT");
 	}
 	}
+}
 
 
+/* Overridden in paravirt.c */
+void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
 
 
-#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_SMP)
+static void __init smp_intr_init(void)
+{
+#ifdef CONFIG_SMP
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
 	/*
 	/*
 	 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
 	 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
 	 * IPI, driven by wakeup.
 	 * IPI, driven by wakeup.
@@ -160,16 +166,27 @@ void __init native_init_IRQ(void)
 	/* IPI for generic function call */
 	/* IPI for generic function call */
 	alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
 	alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
 
 
-	/* IPI for single call function */
+	/* IPI for generic single function call */
 	alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
 	alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
-				 call_function_single_interrupt);
+			call_function_single_interrupt);
 
 
 	/* Low priority IPI to cleanup after moving an irq */
 	/* Low priority IPI to cleanup after moving an irq */
 	set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
 	set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
 	set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors);
 	set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors);
 #endif
 #endif
+#endif /* CONFIG_SMP */
+}
+
+static void __init apic_intr_init(void)
+{
+	smp_intr_init();
+
+#ifdef CONFIG_X86_64
+	alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
+	alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
+#endif
 
 
-#ifdef CONFIG_X86_LOCAL_APIC
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
 	/* self generated IPI for local APIC timer */
 	/* self generated IPI for local APIC timer */
 	alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
 	alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
 
 
@@ -179,16 +196,67 @@ void __init native_init_IRQ(void)
 	/* IPI vectors for APIC spurious and error interrupts */
 	/* IPI vectors for APIC spurious and error interrupts */
 	alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
 	alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
 	alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
 	alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
+
+	/* Performance monitoring interrupts: */
+# ifdef CONFIG_PERF_COUNTERS
+	alloc_intr_gate(LOCAL_PERF_VECTOR, perf_counter_interrupt);
+	alloc_intr_gate(LOCAL_PENDING_VECTOR, perf_pending_interrupt);
+# endif
+
 #endif
 #endif
 
 
+#ifdef CONFIG_X86_32
 #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_MCE_P4THERMAL)
 #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_MCE_P4THERMAL)
 	/* thermal monitor LVT interrupt */
 	/* thermal monitor LVT interrupt */
 	alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
 	alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
 #endif
 #endif
+#endif
+}
+
+/**
+ * x86_quirk_pre_intr_init - initialisation prior to setting up interrupt vectors
+ *
+ * Description:
+ *	Perform any necessary interrupt initialisation prior to setting up
+ *	the "ordinary" interrupt call gates.  For legacy reasons, the ISA
+ *	interrupts should be initialised here if the machine emulates a PC
+ *	in any way.
+ **/
+static void __init x86_quirk_pre_intr_init(void)
+{
+#ifdef CONFIG_X86_32
+	if (x86_quirks->arch_pre_intr_init) {
+		if (x86_quirks->arch_pre_intr_init())
+			return;
+	}
+#endif
+	init_ISA_irqs();
+}
+
+void __init native_init_IRQ(void)
+{
+	int i;
+
+	/* Execute any quirks before the call gates are initialised: */
+	x86_quirk_pre_intr_init();
+
+	apic_intr_init();
+
+	/*
+	 * Cover the whole vector space, no vector can escape
+	 * us. (some of these will be overridden and become
+	 * 'special' SMP interrupts)
+	 */
+	for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) {
+		/* IA32_SYSCALL_VECTOR could be used in trap_init already. */
+		if (!test_bit(i, used_vectors))
+			set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]);
+	}
 
 
 	if (!acpi_ioapic)
 	if (!acpi_ioapic)
 		setup_irq(2, &irq2);
 		setup_irq(2, &irq2);
 
 
+#ifdef CONFIG_X86_32
 	/*
 	/*
 	 * Call quirks after call gates are initialised (usually add in
 	 * Call quirks after call gates are initialised (usually add in
 	 * the architecture specific gates):
 	 * the architecture specific gates):
@@ -203,4 +271,5 @@ void __init native_init_IRQ(void)
 		setup_irq(FPU_IRQ, &fpu_irq);
 		setup_irq(FPU_IRQ, &fpu_irq);
 
 
 	irq_ctx_init(smp_processor_id());
 	irq_ctx_init(smp_processor_id());
+#endif
 }
 }

+ 0 - 177
arch/x86/kernel/irqinit_64.c

@@ -1,177 +0,0 @@
-#include <linux/linkage.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/sysdev.h>
-#include <linux/bitops.h>
-#include <linux/acpi.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-
-#include <asm/atomic.h>
-#include <asm/system.h>
-#include <asm/hw_irq.h>
-#include <asm/pgtable.h>
-#include <asm/desc.h>
-#include <asm/apic.h>
-#include <asm/i8259.h>
-
-/*
- * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
- * (these are usually mapped to vectors 0x30-0x3f)
- */
-
-/*
- * The IO-APIC gives us many more interrupt sources. Most of these
- * are unused but an SMP system is supposed to have enough memory ...
- * sometimes (mostly wrt. hw bugs) we get corrupted vectors all
- * across the spectrum, so we really want to be prepared to get all
- * of these. Plus, more powerful systems might have more than 64
- * IO-APIC registers.
- *
- * (these are usually mapped into the 0x30-0xff vector range)
- */
-
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-
-static struct irqaction irq2 = {
-	.handler = no_action,
-	.name = "cascade",
-};
-DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
-	[0 ... IRQ0_VECTOR - 1] = -1,
-	[IRQ0_VECTOR] = 0,
-	[IRQ1_VECTOR] = 1,
-	[IRQ2_VECTOR] = 2,
-	[IRQ3_VECTOR] = 3,
-	[IRQ4_VECTOR] = 4,
-	[IRQ5_VECTOR] = 5,
-	[IRQ6_VECTOR] = 6,
-	[IRQ7_VECTOR] = 7,
-	[IRQ8_VECTOR] = 8,
-	[IRQ9_VECTOR] = 9,
-	[IRQ10_VECTOR] = 10,
-	[IRQ11_VECTOR] = 11,
-	[IRQ12_VECTOR] = 12,
-	[IRQ13_VECTOR] = 13,
-	[IRQ14_VECTOR] = 14,
-	[IRQ15_VECTOR] = 15,
-	[IRQ15_VECTOR + 1 ... NR_VECTORS - 1] = -1
-};
-
-int vector_used_by_percpu_irq(unsigned int vector)
-{
-	int cpu;
-
-	for_each_online_cpu(cpu) {
-		if (per_cpu(vector_irq, cpu)[vector] != -1)
-			return 1;
-	}
-
-	return 0;
-}
-
-static void __init init_ISA_irqs(void)
-{
-	int i;
-
-	init_bsp_APIC();
-	init_8259A(0);
-
-	for (i = 0; i < NR_IRQS_LEGACY; i++) {
-		struct irq_desc *desc = irq_to_desc(i);
-
-		desc->status = IRQ_DISABLED;
-		desc->action = NULL;
-		desc->depth = 1;
-
-		/*
-		 * 16 old-style INTA-cycle interrupts:
-		 */
-		set_irq_chip_and_handler_name(i, &i8259A_chip,
-						      handle_level_irq, "XT");
-	}
-}
-
-void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
-
-static void __init smp_intr_init(void)
-{
-#ifdef CONFIG_SMP
-	/*
-	 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
-	 * IPI, driven by wakeup.
-	 */
-	alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
-
-	/* IPIs for invalidation */
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+0, invalidate_interrupt0);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+1, invalidate_interrupt1);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+2, invalidate_interrupt2);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+3, invalidate_interrupt3);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+4, invalidate_interrupt4);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+5, invalidate_interrupt5);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+6, invalidate_interrupt6);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+7, invalidate_interrupt7);
-
-	/* IPI for generic function call */
-	alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
-
-	/* IPI for generic single function call */
-	alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
-			call_function_single_interrupt);
-
-	/* Low priority IPI to cleanup after moving an irq */
-	set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
-	set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors);
-#endif
-}
-
-static void __init apic_intr_init(void)
-{
-	smp_intr_init();
-
-	alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
-	alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
-
-	/* self generated IPI for local APIC timer */
-	alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
-
-	/* generic IPI for platform specific use */
-	alloc_intr_gate(GENERIC_INTERRUPT_VECTOR, generic_interrupt);
-
-	/* IPI vectors for APIC spurious and error interrupts */
-	alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
-	alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
-}
-
-void __init native_init_IRQ(void)
-{
-	int i;
-
-	init_ISA_irqs();
-	/*
-	 * Cover the whole vector space, no vector can escape
-	 * us. (some of these will be overridden and become
-	 * 'special' SMP interrupts)
-	 */
-	for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) {
-		int vector = FIRST_EXTERNAL_VECTOR + i;
-		if (vector != IA32_SYSCALL_VECTOR)
-			set_intr_gate(vector, interrupt[i]);
-	}
-
-	apic_intr_init();
-
-	if (!acpi_ioapic)
-		setup_irq(2, &irq2);
-}

+ 17 - 17
arch/x86/kernel/mpparse.c

@@ -17,6 +17,7 @@
 #include <linux/acpi.h>
 #include <linux/acpi.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/smp.h>
 #include <linux/smp.h>
+#include <linux/pci.h>
 
 
 #include <asm/mtrr.h>
 #include <asm/mtrr.h>
 #include <asm/mpspec.h>
 #include <asm/mpspec.h>
@@ -870,24 +871,17 @@ static
 inline void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {}
 inline void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {}
 #endif /* CONFIG_X86_IO_APIC */
 #endif /* CONFIG_X86_IO_APIC */
 
 
-static int check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length,
-		      int count)
+static int
+check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length, int count)
 {
 {
-	if (!mpc_new_phys) {
-		pr_info("No spare slots, try to append...take your risk, "
-			"new mpc_length %x\n", count);
-	} else {
-		if (count <= mpc_new_length)
-			pr_info("No spare slots, try to append..., "
-				"new mpc_length %x\n", count);
-		else {
-			pr_err("mpc_new_length %lx is too small\n",
-				mpc_new_length);
-			return -1;
-		}
+	int ret = 0;
+
+	if (!mpc_new_phys || count <= mpc_new_length) {
+		WARN(1, "update_mptable: No spare slots (length: %x)\n", count);
+		return -1;
 	}
 	}
 
 
-	return 0;
+	return ret;
 }
 }
 
 
 static int  __init replace_intsrc_all(struct mpc_table *mpc,
 static int  __init replace_intsrc_all(struct mpc_table *mpc,
@@ -946,7 +940,7 @@ static int  __init replace_intsrc_all(struct mpc_table *mpc,
 		} else {
 		} else {
 			struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
 			struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
 			count += sizeof(struct mpc_intsrc);
 			count += sizeof(struct mpc_intsrc);
-			if (!check_slot(mpc_new_phys, mpc_new_length, count))
+			if (check_slot(mpc_new_phys, mpc_new_length, count) < 0)
 				goto out;
 				goto out;
 			assign_to_mpc_intsrc(&mp_irqs[i], m);
 			assign_to_mpc_intsrc(&mp_irqs[i], m);
 			mpc->length = count;
 			mpc->length = count;
@@ -963,11 +957,14 @@ out:
 	return 0;
 	return 0;
 }
 }
 
 
-static int __initdata enable_update_mptable;
+int enable_update_mptable;
 
 
 static int __init update_mptable_setup(char *str)
 static int __init update_mptable_setup(char *str)
 {
 {
 	enable_update_mptable = 1;
 	enable_update_mptable = 1;
+#ifdef CONFIG_PCI
+	pci_routeirq = 1;
+#endif
 	return 0;
 	return 0;
 }
 }
 early_param("update_mptable", update_mptable_setup);
 early_param("update_mptable", update_mptable_setup);
@@ -980,6 +977,9 @@ static int __initdata alloc_mptable;
 static int __init parse_alloc_mptable_opt(char *p)
 static int __init parse_alloc_mptable_opt(char *p)
 {
 {
 	enable_update_mptable = 1;
 	enable_update_mptable = 1;
+#ifdef CONFIG_PCI
+	pci_routeirq = 1;
+#endif
 	alloc_mptable = 1;
 	alloc_mptable = 1;
 	if (!p)
 	if (!p)
 		return 0;
 		return 0;

+ 0 - 18
arch/x86/kernel/setup.c

@@ -996,24 +996,6 @@ void __init setup_arch(char **cmdline_p)
 
 
 #ifdef CONFIG_X86_32
 #ifdef CONFIG_X86_32
 
 
-/**
- * x86_quirk_pre_intr_init - initialisation prior to setting up interrupt vectors
- *
- * Description:
- *	Perform any necessary interrupt initialisation prior to setting up
- *	the "ordinary" interrupt call gates.  For legacy reasons, the ISA
- *	interrupts should be initialised here if the machine emulates a PC
- *	in any way.
- **/
-void __init x86_quirk_pre_intr_init(void)
-{
-	if (x86_quirks->arch_pre_intr_init) {
-		if (x86_quirks->arch_pre_intr_init())
-			return;
-	}
-	init_ISA_irqs();
-}
-
 /**
 /**
  * x86_quirk_intr_init - post gate setup interrupt initialisation
  * x86_quirk_intr_init - post gate setup interrupt initialisation
  *
  *

+ 10 - 10
arch/x86/kernel/smp.c

@@ -193,19 +193,19 @@ void smp_call_function_single_interrupt(struct pt_regs *regs)
 }
 }
 
 
 struct smp_ops smp_ops = {
 struct smp_ops smp_ops = {
-	.smp_prepare_boot_cpu = native_smp_prepare_boot_cpu,
-	.smp_prepare_cpus = native_smp_prepare_cpus,
-	.smp_cpus_done = native_smp_cpus_done,
+	.smp_prepare_boot_cpu	= native_smp_prepare_boot_cpu,
+	.smp_prepare_cpus	= native_smp_prepare_cpus,
+	.smp_cpus_done		= native_smp_cpus_done,
 
 
-	.smp_send_stop = native_smp_send_stop,
-	.smp_send_reschedule = native_smp_send_reschedule,
+	.smp_send_stop		= native_smp_send_stop,
+	.smp_send_reschedule	= native_smp_send_reschedule,
 
 
-	.cpu_up = native_cpu_up,
-	.cpu_die = native_cpu_die,
-	.cpu_disable = native_cpu_disable,
-	.play_dead = native_play_dead,
+	.cpu_up			= native_cpu_up,
+	.cpu_die		= native_cpu_die,
+	.cpu_disable		= native_cpu_disable,
+	.play_dead		= native_play_dead,
 
 
-	.send_call_func_ipi = native_send_call_func_ipi,
+	.send_call_func_ipi	= native_send_call_func_ipi,
 	.send_call_func_single_ipi = native_send_call_func_single_ipi,
 	.send_call_func_single_ipi = native_send_call_func_single_ipi,
 };
 };
 EXPORT_SYMBOL_GPL(smp_ops);
 EXPORT_SYMBOL_GPL(smp_ops);

+ 13 - 9
arch/x86/kernel/smpboot.c

@@ -504,7 +504,7 @@ void __inquire_remote_apic(int apicid)
  * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
  * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
  * won't ... remember to clear down the APIC, etc later.
  * won't ... remember to clear down the APIC, etc later.
  */
  */
-int __devinit
+int __cpuinit
 wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip)
 wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip)
 {
 {
 	unsigned long send_status, accept_status = 0;
 	unsigned long send_status, accept_status = 0;
@@ -538,7 +538,7 @@ wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip)
 	return (send_status | accept_status);
 	return (send_status | accept_status);
 }
 }
 
 
-int __devinit
+static int __cpuinit
 wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
 wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
 {
 {
 	unsigned long send_status, accept_status = 0;
 	unsigned long send_status, accept_status = 0;
@@ -822,10 +822,12 @@ do_rest:
 	/* mark "stuck" area as not stuck */
 	/* mark "stuck" area as not stuck */
 	*((volatile unsigned long *)trampoline_base) = 0;
 	*((volatile unsigned long *)trampoline_base) = 0;
 
 
-	/*
-	 * Cleanup possible dangling ends...
-	 */
-	smpboot_restore_warm_reset_vector();
+	if (get_uv_system_type() != UV_NON_UNIQUE_APIC) {
+		/*
+		 * Cleanup possible dangling ends...
+		 */
+		smpboot_restore_warm_reset_vector();
+	}
 
 
 	return boot_error;
 	return boot_error;
 }
 }
@@ -990,10 +992,12 @@ static int __init smp_sanity_check(unsigned max_cpus)
 	 */
 	 */
 	if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) &&
 	if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) &&
 	    !cpu_has_apic) {
 	    !cpu_has_apic) {
-		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
-			boot_cpu_physical_apicid);
-		printk(KERN_ERR "... forcing use of dummy APIC emulation."
+		if (!disable_apic) {
+			pr_err("BIOS bug, local APIC #%d not detected!...\n",
+				boot_cpu_physical_apicid);
+			pr_err("... forcing use of dummy APIC emulation."
 				"(tell your hw vendor)\n");
 				"(tell your hw vendor)\n");
+		}
 		smpboot_clear_io_apic();
 		smpboot_clear_io_apic();
 		arch_disable_smp_support();
 		arch_disable_smp_support();
 		return -1;
 		return -1;

+ 1 - 4
arch/x86/kernel/traps.c

@@ -969,11 +969,8 @@ void __init trap_init(void)
 	for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
 	for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
 		set_bit(i, used_vectors);
 		set_bit(i, used_vectors);
 
 
-#ifdef CONFIG_X86_64
 	set_bit(IA32_SYSCALL_VECTOR, used_vectors);
 	set_bit(IA32_SYSCALL_VECTOR, used_vectors);
-#else
-	set_bit(SYSCALL_VECTOR, used_vectors);
-#endif
+
 	/*
 	/*
 	 * Should be a barrier for any external CPU state:
 	 * Should be a barrier for any external CPU state:
 	 */
 	 */

+ 1 - 1
arch/x86/lguest/boot.c

@@ -637,7 +637,7 @@ static void __init lguest_init_IRQ(void)
 
 
 void lguest_setup_irq(unsigned int irq)
 void lguest_setup_irq(unsigned int irq)
 {
 {
-	irq_to_desc_alloc_cpu(irq, 0);
+	irq_to_desc_alloc_node(irq, 0);
 	set_irq_chip_and_handler_name(irq, &lguest_irq_controller,
 	set_irq_chip_and_handler_name(irq, &lguest_irq_controller,
 				      handle_level_irq, "level");
 				      handle_level_irq, "level");
 }
 }

+ 35 - 49
arch/x86/pci/irq.c

@@ -889,6 +889,9 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
 		return 0;
 		return 0;
 	}
 	}
 
 
+	if (io_apic_assign_pci_irqs)
+		return 0;
+
 	/* Find IRQ routing entry */
 	/* Find IRQ routing entry */
 
 
 	if (!pirq_table)
 	if (!pirq_table)
@@ -1039,56 +1042,15 @@ static void __init pcibios_fixup_irqs(void)
 		pirq_penalty[dev->irq]++;
 		pirq_penalty[dev->irq]++;
 	}
 	}
 
 
+	if (io_apic_assign_pci_irqs)
+		return;
+
 	dev = NULL;
 	dev = NULL;
 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 		if (!pin)
 		if (!pin)
 			continue;
 			continue;
 
 
-#ifdef CONFIG_X86_IO_APIC
-		/*
-		 * Recalculate IRQ numbers if we use the I/O APIC.
-		 */
-		if (io_apic_assign_pci_irqs) {
-			int irq;
-
-			/*
-			 * interrupt pins are numbered starting from 1
-			 */
-			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
-				PCI_SLOT(dev->devfn), pin - 1);
-			/*
-			 * Busses behind bridges are typically not listed in the
-			 * MP-table.  In this case we have to look up the IRQ
-			 * based on the parent bus, parent slot, and pin number.
-			 * The SMP code detects such bridged busses itself so we
-			 * should get into this branch reliably.
-			 */
-			if (irq < 0 && dev->bus->parent) {
-				/* go back to the bridge */
-				struct pci_dev *bridge = dev->bus->self;
-				int bus;
-
-				pin = pci_swizzle_interrupt_pin(dev, pin);
-				bus = bridge->bus->number;
-				irq = IO_APIC_get_PCI_irq_vector(bus,
-						PCI_SLOT(bridge->devfn), pin - 1);
-				if (irq >= 0)
-					dev_warn(&dev->dev,
-						"using bridge %s INT %c to "
-							"get IRQ %d\n",
-						 pci_name(bridge),
-						 'A' + pin - 1, irq);
-			}
-			if (irq >= 0) {
-				dev_info(&dev->dev,
-					"PCI->APIC IRQ transform: INT %c "
-						"-> IRQ %d\n",
-					'A' + pin - 1, irq);
-				dev->irq = irq;
-			}
-		}
-#endif
 		/*
 		/*
 		 * Still no IRQ? Try to lookup one...
 		 * Still no IRQ? Try to lookup one...
 		 */
 		 */
@@ -1183,6 +1145,19 @@ int __init pcibios_irq_init(void)
 	pcibios_enable_irq = pirq_enable_irq;
 	pcibios_enable_irq = pirq_enable_irq;
 
 
 	pcibios_fixup_irqs();
 	pcibios_fixup_irqs();
+
+	if (io_apic_assign_pci_irqs && pci_routeirq) {
+		struct pci_dev *dev = NULL;
+		/*
+		 * PCI IRQ routing is set up by pci_enable_device(), but we
+		 * also do it here in case there are still broken drivers that
+		 * don't use pci_enable_device().
+		 */
+		printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n");
+		for_each_pci_dev(dev)
+			pirq_enable_irq(dev);
+	}
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1213,16 +1188,23 @@ void pcibios_penalize_isa_irq(int irq, int active)
 static int pirq_enable_irq(struct pci_dev *dev)
 static int pirq_enable_irq(struct pci_dev *dev)
 {
 {
 	u8 pin;
 	u8 pin;
-	struct pci_dev *temp_dev;
 
 
 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-	if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
+	if (pin && !pcibios_lookup_irq(dev, 1)) {
 		char *msg = "";
 		char *msg = "";
 
 
+		if (!io_apic_assign_pci_irqs && dev->irq)
+			return 0;
+
 		if (io_apic_assign_pci_irqs) {
 		if (io_apic_assign_pci_irqs) {
+#ifdef CONFIG_X86_IO_APIC
+			struct pci_dev *temp_dev;
 			int irq;
 			int irq;
+			struct io_apic_irq_attr irq_attr;
 
 
-			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin - 1);
+			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
+						PCI_SLOT(dev->devfn),
+						pin - 1, &irq_attr);
 			/*
 			/*
 			 * Busses behind bridges are typically not listed in the MP-table.
 			 * Busses behind bridges are typically not listed in the MP-table.
 			 * In this case we have to look up the IRQ based on the parent bus,
 			 * In this case we have to look up the IRQ based on the parent bus,
@@ -1235,7 +1217,8 @@ static int pirq_enable_irq(struct pci_dev *dev)
 
 
 				pin = pci_swizzle_interrupt_pin(dev, pin);
 				pin = pci_swizzle_interrupt_pin(dev, pin);
 				irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
 				irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
-						PCI_SLOT(bridge->devfn), pin - 1);
+						PCI_SLOT(bridge->devfn),
+						pin - 1, &irq_attr);
 				if (irq >= 0)
 				if (irq >= 0)
 					dev_warn(&dev->dev, "using bridge %s "
 					dev_warn(&dev->dev, "using bridge %s "
 						 "INT %c to get IRQ %d\n",
 						 "INT %c to get IRQ %d\n",
@@ -1245,12 +1228,15 @@ static int pirq_enable_irq(struct pci_dev *dev)
 			}
 			}
 			dev = temp_dev;
 			dev = temp_dev;
 			if (irq >= 0) {
 			if (irq >= 0) {
+				io_apic_set_pci_routing(&dev->dev, irq,
+							 &irq_attr);
+				dev->irq = irq;
 				dev_info(&dev->dev, "PCI->APIC IRQ transform: "
 				dev_info(&dev->dev, "PCI->APIC IRQ transform: "
 					 "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
 					 "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
-				dev->irq = irq;
 				return 0;
 				return 0;
 			} else
 			} else
 				msg = "; probably buggy MP table";
 				msg = "; probably buggy MP table";
+#endif
 		} else if (pci_probe & PCI_BIOS_IRQ_SCAN)
 		} else if (pci_probe & PCI_BIOS_IRQ_SCAN)
 			msg = "";
 			msg = "";
 		else
 		else

+ 3 - 2
drivers/acpi/pci_irq.c

@@ -401,7 +401,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 		/* Interrupt Line values above 0xF are forbidden */
 		/* Interrupt Line values above 0xF are forbidden */
 		if (dev->irq > 0 && (dev->irq <= 0xF)) {
 		if (dev->irq > 0 && (dev->irq <= 0xF)) {
 			printk(" - using IRQ %d\n", dev->irq);
 			printk(" - using IRQ %d\n", dev->irq);
-			acpi_register_gsi(dev->irq, ACPI_LEVEL_SENSITIVE,
+			acpi_register_gsi(&dev->dev, dev->irq,
+					  ACPI_LEVEL_SENSITIVE,
 					  ACPI_ACTIVE_LOW);
 					  ACPI_ACTIVE_LOW);
 			return 0;
 			return 0;
 		} else {
 		} else {
@@ -410,7 +411,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 		}
 		}
 	}
 	}
 
 
-	rc = acpi_register_gsi(gsi, triggering, polarity);
+	rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
 	if (rc < 0) {
 	if (rc < 0) {
 		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
 		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
 			 pin_name(pin));
 			 pin_name(pin));

+ 2 - 2
drivers/char/hpet.c

@@ -224,7 +224,7 @@ static void hpet_timer_set_irq(struct hpet_dev *devp)
 			break;
 			break;
 		}
 		}
 
 
-		gsi = acpi_register_gsi(irq, ACPI_LEVEL_SENSITIVE,
+		gsi = acpi_register_gsi(NULL, irq, ACPI_LEVEL_SENSITIVE,
 					ACPI_ACTIVE_LOW);
 					ACPI_ACTIVE_LOW);
 		if (gsi > 0)
 		if (gsi > 0)
 			break;
 			break;
@@ -939,7 +939,7 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
 		irqp = &res->data.extended_irq;
 		irqp = &res->data.extended_irq;
 
 
 		for (i = 0; i < irqp->interrupt_count; i++) {
 		for (i = 0; i < irqp->interrupt_count; i++) {
-			irq = acpi_register_gsi(irqp->interrupts[i],
+			irq = acpi_register_gsi(NULL, irqp->interrupts[i],
 				      irqp->triggering, irqp->polarity);
 				      irqp->triggering, irqp->polarity);
 			if (irq < 0)
 			if (irq < 0)
 				return AE_ERROR;
 				return AE_ERROR;

+ 4 - 2
drivers/parisc/iosapic.c

@@ -702,7 +702,7 @@ static unsigned int iosapic_startup_irq(unsigned int irq)
 }
 }
 
 
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
-static void iosapic_set_affinity_irq(unsigned int irq,
+static int iosapic_set_affinity_irq(unsigned int irq,
 				     const struct cpumask *dest)
 				     const struct cpumask *dest)
 {
 {
 	struct vector_info *vi = iosapic_get_vector(irq);
 	struct vector_info *vi = iosapic_get_vector(irq);
@@ -712,7 +712,7 @@ static void iosapic_set_affinity_irq(unsigned int irq,
 
 
 	dest_cpu = cpu_check_affinity(irq, dest);
 	dest_cpu = cpu_check_affinity(irq, dest);
 	if (dest_cpu < 0)
 	if (dest_cpu < 0)
-		return;
+		return -1;
 
 
 	cpumask_copy(irq_desc[irq].affinity, cpumask_of(dest_cpu));
 	cpumask_copy(irq_desc[irq].affinity, cpumask_of(dest_cpu));
 	vi->txn_addr = txn_affinity_addr(irq, dest_cpu);
 	vi->txn_addr = txn_affinity_addr(irq, dest_cpu);
@@ -724,6 +724,8 @@ static void iosapic_set_affinity_irq(unsigned int irq,
 	iosapic_set_irt_data(vi, &dummy_d0, &d1);
 	iosapic_set_irt_data(vi, &dummy_d0, &d1);
 	iosapic_wr_irt_entry(vi, d0, d1);
 	iosapic_wr_irt_entry(vi, d0, d1);
 	spin_unlock_irqrestore(&iosapic_lock, flags);
 	spin_unlock_irqrestore(&iosapic_lock, flags);
+
+	return 0;
 }
 }
 #endif
 #endif
 
 

+ 28 - 26
drivers/pci/hotplug/ibmphp_core.c

@@ -153,45 +153,47 @@ int ibmphp_init_devno(struct slot **cur_slot)
 		return -1;
 		return -1;
 	}
 	}
 	for (loop = 0; loop < len; loop++) {
 	for (loop = 0; loop < len; loop++) {
-		if ((*cur_slot)->number == rtable->slots[loop].slot) {
-		if ((*cur_slot)->bus == rtable->slots[loop].bus) {
+		if ((*cur_slot)->number == rtable->slots[loop].slot &&
+		    (*cur_slot)->bus == rtable->slots[loop].bus) {
+			struct io_apic_irq_attr irq_attr;
+
 			(*cur_slot)->device = PCI_SLOT(rtable->slots[loop].devfn);
 			(*cur_slot)->device = PCI_SLOT(rtable->slots[loop].devfn);
 			for (i = 0; i < 4; i++)
 			for (i = 0; i < 4; i++)
 				(*cur_slot)->irq[i] = IO_APIC_get_PCI_irq_vector((int) (*cur_slot)->bus,
 				(*cur_slot)->irq[i] = IO_APIC_get_PCI_irq_vector((int) (*cur_slot)->bus,
-						(int) (*cur_slot)->device, i);
-
-				debug("(*cur_slot)->irq[0] = %x\n",
-						(*cur_slot)->irq[0]);
-				debug("(*cur_slot)->irq[1] = %x\n",
-						(*cur_slot)->irq[1]);
-				debug("(*cur_slot)->irq[2] = %x\n",
-						(*cur_slot)->irq[2]);
-				debug("(*cur_slot)->irq[3] = %x\n",
-						(*cur_slot)->irq[3]);
-
-				debug("rtable->exlusive_irqs = %x\n",
+						(int) (*cur_slot)->device, i,
+						&irq_attr);
+
+			debug("(*cur_slot)->irq[0] = %x\n",
+					(*cur_slot)->irq[0]);
+			debug("(*cur_slot)->irq[1] = %x\n",
+					(*cur_slot)->irq[1]);
+			debug("(*cur_slot)->irq[2] = %x\n",
+					(*cur_slot)->irq[2]);
+			debug("(*cur_slot)->irq[3] = %x\n",
+					(*cur_slot)->irq[3]);
+
+			debug("rtable->exlusive_irqs = %x\n",
 					rtable->exclusive_irqs);
 					rtable->exclusive_irqs);
-				debug("rtable->slots[loop].irq[0].bitmap = %x\n",
+			debug("rtable->slots[loop].irq[0].bitmap = %x\n",
 					rtable->slots[loop].irq[0].bitmap);
 					rtable->slots[loop].irq[0].bitmap);
-				debug("rtable->slots[loop].irq[1].bitmap = %x\n",
+			debug("rtable->slots[loop].irq[1].bitmap = %x\n",
 					rtable->slots[loop].irq[1].bitmap);
 					rtable->slots[loop].irq[1].bitmap);
-				debug("rtable->slots[loop].irq[2].bitmap = %x\n",
+			debug("rtable->slots[loop].irq[2].bitmap = %x\n",
 					rtable->slots[loop].irq[2].bitmap);
 					rtable->slots[loop].irq[2].bitmap);
-				debug("rtable->slots[loop].irq[3].bitmap = %x\n",
+			debug("rtable->slots[loop].irq[3].bitmap = %x\n",
 					rtable->slots[loop].irq[3].bitmap);
 					rtable->slots[loop].irq[3].bitmap);
 
 
-				debug("rtable->slots[loop].irq[0].link = %x\n",
+			debug("rtable->slots[loop].irq[0].link = %x\n",
 					rtable->slots[loop].irq[0].link);
 					rtable->slots[loop].irq[0].link);
-				debug("rtable->slots[loop].irq[1].link = %x\n",
+			debug("rtable->slots[loop].irq[1].link = %x\n",
 					rtable->slots[loop].irq[1].link);
 					rtable->slots[loop].irq[1].link);
-				debug("rtable->slots[loop].irq[2].link = %x\n",
+			debug("rtable->slots[loop].irq[2].link = %x\n",
 					rtable->slots[loop].irq[2].link);
 					rtable->slots[loop].irq[2].link);
-				debug("rtable->slots[loop].irq[3].link = %x\n",
+			debug("rtable->slots[loop].irq[3].link = %x\n",
 					rtable->slots[loop].irq[3].link);
 					rtable->slots[loop].irq[3].link);
-				debug("end of init_devno\n");
-				kfree(rtable);
-				return 0;
-			}
+			debug("end of init_devno\n");
+			kfree(rtable);
+			return 0;
 		}
 		}
 	}
 	}
 
 

+ 3 - 1
drivers/pci/htirq.c

@@ -98,6 +98,7 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
 	int max_irq;
 	int max_irq;
 	int pos;
 	int pos;
 	int irq;
 	int irq;
+	int node;
 
 
 	pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ);
 	pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ);
 	if (!pos)
 	if (!pos)
@@ -125,7 +126,8 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
 	cfg->msg.address_lo = 0xffffffff;
 	cfg->msg.address_lo = 0xffffffff;
 	cfg->msg.address_hi = 0xffffffff;
 	cfg->msg.address_hi = 0xffffffff;
 
 
-	irq = create_irq();
+	node = dev_to_node(&dev->dev);
+	irq = create_irq_nr(0, node);
 
 
 	if (irq <= 0) {
 	if (irq <= 0) {
 		kfree(cfg);
 		kfree(cfg);

+ 0 - 9
drivers/pci/intel-iommu.c

@@ -1972,15 +1972,6 @@ static int __init init_dmars(void)
 		}
 		}
 	}
 	}
 
 
-#ifdef CONFIG_INTR_REMAP
-	if (!intr_remapping_enabled) {
-		ret = enable_intr_remapping(0);
-		if (ret)
-			printk(KERN_ERR
-			       "IOMMU: enable interrupt remapping failed\n");
-	}
-#endif
-
 	/*
 	/*
 	 * For each rmrr
 	 * For each rmrr
 	 *   for each dev attached to rmrr
 	 *   for each dev attached to rmrr

+ 31 - 23
drivers/pci/intr_remapping.c

@@ -15,6 +15,14 @@ static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
 static int ir_ioapic_num;
 static int ir_ioapic_num;
 int intr_remapping_enabled;
 int intr_remapping_enabled;
 
 
+static int disable_intremap;
+static __init int setup_nointremap(char *str)
+{
+	disable_intremap = 1;
+	return 0;
+}
+early_param("nointremap", setup_nointremap);
+
 struct irq_2_iommu {
 struct irq_2_iommu {
 	struct intel_iommu *iommu;
 	struct intel_iommu *iommu;
 	u16 irte_index;
 	u16 irte_index;
@@ -23,15 +31,12 @@ struct irq_2_iommu {
 };
 };
 
 
 #ifdef CONFIG_GENERIC_HARDIRQS
 #ifdef CONFIG_GENERIC_HARDIRQS
-static struct irq_2_iommu *get_one_free_irq_2_iommu(int cpu)
+static struct irq_2_iommu *get_one_free_irq_2_iommu(int node)
 {
 {
 	struct irq_2_iommu *iommu;
 	struct irq_2_iommu *iommu;
-	int node;
-
-	node = cpu_to_node(cpu);
 
 
 	iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node);
 	iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node);
-	printk(KERN_DEBUG "alloc irq_2_iommu on cpu %d node %d\n", cpu, node);
+	printk(KERN_DEBUG "alloc irq_2_iommu on node %d\n", node);
 
 
 	return iommu;
 	return iommu;
 }
 }
@@ -48,7 +53,7 @@ static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
 	return desc->irq_2_iommu;
 	return desc->irq_2_iommu;
 }
 }
 
 
-static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu)
+static struct irq_2_iommu *irq_2_iommu_alloc_node(unsigned int irq, int node)
 {
 {
 	struct irq_desc *desc;
 	struct irq_desc *desc;
 	struct irq_2_iommu *irq_iommu;
 	struct irq_2_iommu *irq_iommu;
@@ -56,7 +61,7 @@ static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu)
 	/*
 	/*
 	 * alloc irq desc if not allocated already.
 	 * alloc irq desc if not allocated already.
 	 */
 	 */
-	desc = irq_to_desc_alloc_cpu(irq, cpu);
+	desc = irq_to_desc_alloc_node(irq, node);
 	if (!desc) {
 	if (!desc) {
 		printk(KERN_INFO "can not get irq_desc for %d\n", irq);
 		printk(KERN_INFO "can not get irq_desc for %d\n", irq);
 		return NULL;
 		return NULL;
@@ -65,14 +70,14 @@ static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu)
 	irq_iommu = desc->irq_2_iommu;
 	irq_iommu = desc->irq_2_iommu;
 
 
 	if (!irq_iommu)
 	if (!irq_iommu)
-		desc->irq_2_iommu = get_one_free_irq_2_iommu(cpu);
+		desc->irq_2_iommu = get_one_free_irq_2_iommu(node);
 
 
 	return desc->irq_2_iommu;
 	return desc->irq_2_iommu;
 }
 }
 
 
 static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
 static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
 {
 {
-	return irq_2_iommu_alloc_cpu(irq, boot_cpu_id);
+	return irq_2_iommu_alloc_node(irq, cpu_to_node(boot_cpu_id));
 }
 }
 
 
 #else /* !CONFIG_SPARSE_IRQ */
 #else /* !CONFIG_SPARSE_IRQ */
@@ -423,20 +428,6 @@ static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
 		      readl, (sts & DMA_GSTS_IRTPS), sts);
 		      readl, (sts & DMA_GSTS_IRTPS), sts);
 	spin_unlock_irqrestore(&iommu->register_lock, flags);
 	spin_unlock_irqrestore(&iommu->register_lock, flags);
 
 
-	if (mode == 0) {
-		spin_lock_irqsave(&iommu->register_lock, flags);
-
-		/* enable comaptiblity format interrupt pass through */
-		cmd = iommu->gcmd | DMA_GCMD_CFI;
-		iommu->gcmd |= DMA_GCMD_CFI;
-		writel(cmd, iommu->reg + DMAR_GCMD_REG);
-
-		IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
-			      readl, (sts & DMA_GSTS_CFIS), sts);
-
-		spin_unlock_irqrestore(&iommu->register_lock, flags);
-	}
-
 	/*
 	/*
 	 * global invalidation of interrupt entry cache before enabling
 	 * global invalidation of interrupt entry cache before enabling
 	 * interrupt-remapping.
 	 * interrupt-remapping.
@@ -516,6 +507,23 @@ end:
 	spin_unlock_irqrestore(&iommu->register_lock, flags);
 	spin_unlock_irqrestore(&iommu->register_lock, flags);
 }
 }
 
 
+int __init intr_remapping_supported(void)
+{
+	struct dmar_drhd_unit *drhd;
+
+	if (disable_intremap)
+		return 0;
+
+	for_each_drhd_unit(drhd) {
+		struct intel_iommu *iommu = drhd->iommu;
+
+		if (!ecap_ir_support(iommu->ecap))
+			return 0;
+	}
+
+	return 1;
+}
+
 int __init enable_intr_remapping(int eim)
 int __init enable_intr_remapping(int eim)
 {
 {
 	struct dmar_drhd_unit *drhd;
 	struct dmar_drhd_unit *drhd;

+ 1 - 1
drivers/pnp/pnpacpi/rsparser.c

@@ -123,7 +123,7 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
 	}
 	}
 
 
 	flags = irq_flags(triggering, polarity, shareable);
 	flags = irq_flags(triggering, polarity, shareable);
-	irq = acpi_register_gsi(gsi, triggering, polarity);
+	irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
 	if (irq >= 0)
 	if (irq >= 0)
 		pcibios_penalize_isa_irq(irq, 1);
 		pcibios_penalize_isa_irq(irq, 1);
 	else
 	else

+ 8 - 6
drivers/xen/events.c

@@ -335,7 +335,7 @@ static int find_unbound_irq(void)
 	if (irq == nr_irqs)
 	if (irq == nr_irqs)
 		panic("No available IRQ to bind to: increase nr_irqs!\n");
 		panic("No available IRQ to bind to: increase nr_irqs!\n");
 
 
-	desc = irq_to_desc_alloc_cpu(irq, 0);
+	desc = irq_to_desc_alloc_node(irq, 0);
 	if (WARN_ON(desc == NULL))
 	if (WARN_ON(desc == NULL))
 		return -1;
 		return -1;
 
 
@@ -688,13 +688,13 @@ void rebind_evtchn_irq(int evtchn, int irq)
 }
 }
 
 
 /* Rebind an evtchn so that it gets delivered to a specific cpu */
 /* Rebind an evtchn so that it gets delivered to a specific cpu */
-static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
+static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
 {
 {
 	struct evtchn_bind_vcpu bind_vcpu;
 	struct evtchn_bind_vcpu bind_vcpu;
 	int evtchn = evtchn_from_irq(irq);
 	int evtchn = evtchn_from_irq(irq);
 
 
 	if (!VALID_EVTCHN(evtchn))
 	if (!VALID_EVTCHN(evtchn))
-		return;
+		return -1;
 
 
 	/* Send future instances of this interrupt to other vcpu. */
 	/* Send future instances of this interrupt to other vcpu. */
 	bind_vcpu.port = evtchn;
 	bind_vcpu.port = evtchn;
@@ -707,13 +707,15 @@ static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
 	 */
 	 */
 	if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
 	if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
 		bind_evtchn_to_cpu(evtchn, tcpu);
 		bind_evtchn_to_cpu(evtchn, tcpu);
-}
 
 
+	return 0;
+}
 
 
-static void set_affinity_irq(unsigned irq, const struct cpumask *dest)
+static int set_affinity_irq(unsigned irq, const struct cpumask *dest)
 {
 {
 	unsigned tcpu = cpumask_first(dest);
 	unsigned tcpu = cpumask_first(dest);
-	rebind_irq_to_cpu(irq, tcpu);
+
+	return rebind_irq_to_cpu(irq, tcpu);
 }
 }
 
 
 int resend_irq_on_evtchn(unsigned int irq)
 int resend_irq_on_evtchn(unsigned int irq)

+ 1 - 1
include/linux/acpi.h

@@ -119,7 +119,7 @@ extern int pci_mmcfg_config_num;
 extern int sbf_port;
 extern int sbf_port;
 extern unsigned long acpi_realmode_flags;
 extern unsigned long acpi_realmode_flags;
 
 
-int acpi_register_gsi (u32 gsi, int triggering, int polarity);
+int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity);
 int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 
 
 #ifdef CONFIG_X86_IO_APIC
 #ifdef CONFIG_X86_IO_APIC

+ 3 - 0
include/linux/dmar.h

@@ -108,6 +108,7 @@ struct irte {
 };
 };
 #ifdef CONFIG_INTR_REMAP
 #ifdef CONFIG_INTR_REMAP
 extern int intr_remapping_enabled;
 extern int intr_remapping_enabled;
+extern int intr_remapping_supported(void);
 extern int enable_intr_remapping(int);
 extern int enable_intr_remapping(int);
 extern void disable_intr_remapping(void);
 extern void disable_intr_remapping(void);
 extern int reenable_intr_remapping(int);
 extern int reenable_intr_remapping(int);
@@ -157,6 +158,8 @@ static inline struct intel_iommu *map_ioapic_to_ir(int apic)
 }
 }
 #define irq_remapped(irq)		(0)
 #define irq_remapped(irq)		(0)
 #define enable_intr_remapping(mode)	(-1)
 #define enable_intr_remapping(mode)	(-1)
+#define disable_intr_remapping()	(0)
+#define reenable_intr_remapping(mode)	(0)
 #define intr_remapping_enabled		(0)
 #define intr_remapping_enabled		(0)
 #endif
 #endif
 
 

+ 1 - 1
include/linux/interrupt.h

@@ -566,6 +566,6 @@ struct irq_desc;
 extern int early_irq_init(void);
 extern int early_irq_init(void);
 extern int arch_probe_nr_irqs(void);
 extern int arch_probe_nr_irqs(void);
 extern int arch_early_irq_init(void);
 extern int arch_early_irq_init(void);
-extern int arch_init_chip_data(struct irq_desc *desc, int cpu);
+extern int arch_init_chip_data(struct irq_desc *desc, int node);
 
 
 #endif
 #endif

+ 30 - 28
include/linux/irq.h

@@ -117,7 +117,7 @@ struct irq_chip {
 	void		(*eoi)(unsigned int irq);
 	void		(*eoi)(unsigned int irq);
 
 
 	void		(*end)(unsigned int irq);
 	void		(*end)(unsigned int irq);
-	void		(*set_affinity)(unsigned int irq,
+	int		(*set_affinity)(unsigned int irq,
 					const struct cpumask *dest);
 					const struct cpumask *dest);
 	int		(*retrigger)(unsigned int irq);
 	int		(*retrigger)(unsigned int irq);
 	int		(*set_type)(unsigned int irq, unsigned int flow_type);
 	int		(*set_type)(unsigned int irq, unsigned int flow_type);
@@ -187,7 +187,7 @@ struct irq_desc {
 	spinlock_t		lock;
 	spinlock_t		lock;
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
 	cpumask_var_t		affinity;
 	cpumask_var_t		affinity;
-	unsigned int		cpu;
+	unsigned int		node;
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 	cpumask_var_t		pending_mask;
 	cpumask_var_t		pending_mask;
 #endif
 #endif
@@ -201,26 +201,23 @@ struct irq_desc {
 } ____cacheline_internodealigned_in_smp;
 } ____cacheline_internodealigned_in_smp;
 
 
 extern void arch_init_copy_chip_data(struct irq_desc *old_desc,
 extern void arch_init_copy_chip_data(struct irq_desc *old_desc,
-					struct irq_desc *desc, int cpu);
+					struct irq_desc *desc, int node);
 extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc);
 extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc);
 
 
 #ifndef CONFIG_SPARSE_IRQ
 #ifndef CONFIG_SPARSE_IRQ
 extern struct irq_desc irq_desc[NR_IRQS];
 extern struct irq_desc irq_desc[NR_IRQS];
-#else /* CONFIG_SPARSE_IRQ */
-extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int cpu);
-#endif /* CONFIG_SPARSE_IRQ */
-
-extern struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu);
+#endif
 
 
-static inline struct irq_desc *
-irq_remap_to_desc(unsigned int irq, struct irq_desc *desc)
-{
-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
-	return irq_to_desc(irq);
+#ifdef CONFIG_NUMA_IRQ_DESC
+extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int node);
 #else
 #else
+static inline struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
+{
 	return desc;
 	return desc;
-#endif
 }
 }
+#endif
+
+extern struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node);
 
 
 /*
 /*
  * Migration helpers for obsolete names, they will go away:
  * Migration helpers for obsolete names, they will go away:
@@ -386,7 +383,7 @@ extern void set_irq_noprobe(unsigned int irq);
 extern void set_irq_probe(unsigned int irq);
 extern void set_irq_probe(unsigned int irq);
 
 
 /* Handle dynamic irq creation and destruction */
 /* Handle dynamic irq creation and destruction */
-extern unsigned int create_irq_nr(unsigned int irq_want);
+extern unsigned int create_irq_nr(unsigned int irq_want, int node);
 extern int create_irq(void);
 extern int create_irq(void);
 extern void destroy_irq(unsigned int irq);
 extern void destroy_irq(unsigned int irq);
 
 
@@ -424,47 +421,48 @@ extern int set_irq_msi(unsigned int irq, struct msi_desc *entry);
 
 
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
 /**
 /**
- * init_alloc_desc_masks - allocate cpumasks for irq_desc
+ * alloc_desc_masks - allocate cpumasks for irq_desc
  * @desc:	pointer to irq_desc struct
  * @desc:	pointer to irq_desc struct
  * @cpu:	cpu which will be handling the cpumasks
  * @cpu:	cpu which will be handling the cpumasks
  * @boot:	true if need bootmem
  * @boot:	true if need bootmem
  *
  *
  * Allocates affinity and pending_mask cpumask if required.
  * Allocates affinity and pending_mask cpumask if required.
  * Returns true if successful (or not required).
  * Returns true if successful (or not required).
- * Side effect: affinity has all bits set, pending_mask has all bits clear.
  */
  */
-static inline bool init_alloc_desc_masks(struct irq_desc *desc, int cpu,
+static inline bool alloc_desc_masks(struct irq_desc *desc, int node,
 								bool boot)
 								bool boot)
 {
 {
-	int node;
-
+#ifdef CONFIG_CPUMASK_OFFSTACK
 	if (boot) {
 	if (boot) {
 		alloc_bootmem_cpumask_var(&desc->affinity);
 		alloc_bootmem_cpumask_var(&desc->affinity);
-		cpumask_setall(desc->affinity);
 
 
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 		alloc_bootmem_cpumask_var(&desc->pending_mask);
 		alloc_bootmem_cpumask_var(&desc->pending_mask);
-		cpumask_clear(desc->pending_mask);
 #endif
 #endif
 		return true;
 		return true;
 	}
 	}
 
 
-	node = cpu_to_node(cpu);
-
 	if (!alloc_cpumask_var_node(&desc->affinity, GFP_ATOMIC, node))
 	if (!alloc_cpumask_var_node(&desc->affinity, GFP_ATOMIC, node))
 		return false;
 		return false;
-	cpumask_setall(desc->affinity);
 
 
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 	if (!alloc_cpumask_var_node(&desc->pending_mask, GFP_ATOMIC, node)) {
 	if (!alloc_cpumask_var_node(&desc->pending_mask, GFP_ATOMIC, node)) {
 		free_cpumask_var(desc->affinity);
 		free_cpumask_var(desc->affinity);
 		return false;
 		return false;
 	}
 	}
-	cpumask_clear(desc->pending_mask);
+#endif
 #endif
 #endif
 	return true;
 	return true;
 }
 }
 
 
+static inline void init_desc_masks(struct irq_desc *desc)
+{
+	cpumask_setall(desc->affinity);
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+	cpumask_clear(desc->pending_mask);
+#endif
+}
+
 /**
 /**
  * init_copy_desc_masks - copy cpumasks for irq_desc
  * init_copy_desc_masks - copy cpumasks for irq_desc
  * @old_desc:	pointer to old irq_desc struct
  * @old_desc:	pointer to old irq_desc struct
@@ -478,7 +476,7 @@ static inline bool init_alloc_desc_masks(struct irq_desc *desc, int cpu,
 static inline void init_copy_desc_masks(struct irq_desc *old_desc,
 static inline void init_copy_desc_masks(struct irq_desc *old_desc,
 					struct irq_desc *new_desc)
 					struct irq_desc *new_desc)
 {
 {
-#ifdef CONFIG_CPUMASKS_OFFSTACK
+#ifdef CONFIG_CPUMASK_OFFSTACK
 	cpumask_copy(new_desc->affinity, old_desc->affinity);
 	cpumask_copy(new_desc->affinity, old_desc->affinity);
 
 
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 #ifdef CONFIG_GENERIC_PENDING_IRQ
@@ -499,12 +497,16 @@ static inline void free_desc_masks(struct irq_desc *old_desc,
 
 
 #else /* !CONFIG_SMP */
 #else /* !CONFIG_SMP */
 
 
-static inline bool init_alloc_desc_masks(struct irq_desc *desc, int cpu,
+static inline bool alloc_desc_masks(struct irq_desc *desc, int node,
 								bool boot)
 								bool boot)
 {
 {
 	return true;
 	return true;
 }
 }
 
 
+static inline void init_desc_masks(struct irq_desc *desc)
+{
+}
+
 static inline void init_copy_desc_masks(struct irq_desc *old_desc,
 static inline void init_copy_desc_masks(struct irq_desc *old_desc,
 					struct irq_desc *new_desc)
 					struct irq_desc *new_desc)
 {
 {

+ 1 - 1
kernel/irq/Makefile

@@ -3,5 +3,5 @@ obj-y := handle.o manage.o spurious.o resend.o chip.o devres.o
 obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
 obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
 obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
-obj-$(CONFIG_NUMA_MIGRATE_IRQ_DESC) += numa_migrate.o
+obj-$(CONFIG_NUMA_IRQ_DESC) += numa_migrate.o
 obj-$(CONFIG_PM_SLEEP) += pm.o
 obj-$(CONFIG_PM_SLEEP) += pm.o

+ 2 - 10
kernel/irq/chip.c

@@ -359,7 +359,6 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
 
 
 	spin_lock(&desc->lock);
 	spin_lock(&desc->lock);
 	mask_ack_irq(desc, irq);
 	mask_ack_irq(desc, irq);
-	desc = irq_remap_to_desc(irq, desc);
 
 
 	if (unlikely(desc->status & IRQ_INPROGRESS))
 	if (unlikely(desc->status & IRQ_INPROGRESS))
 		goto out_unlock;
 		goto out_unlock;
@@ -438,7 +437,6 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
 	desc->status &= ~IRQ_INPROGRESS;
 	desc->status &= ~IRQ_INPROGRESS;
 out:
 out:
 	desc->chip->eoi(irq);
 	desc->chip->eoi(irq);
-	desc = irq_remap_to_desc(irq, desc);
 
 
 	spin_unlock(&desc->lock);
 	spin_unlock(&desc->lock);
 }
 }
@@ -475,7 +473,6 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
 		    !desc->action)) {
 		    !desc->action)) {
 		desc->status |= (IRQ_PENDING | IRQ_MASKED);
 		desc->status |= (IRQ_PENDING | IRQ_MASKED);
 		mask_ack_irq(desc, irq);
 		mask_ack_irq(desc, irq);
-		desc = irq_remap_to_desc(irq, desc);
 		goto out_unlock;
 		goto out_unlock;
 	}
 	}
 	kstat_incr_irqs_this_cpu(irq, desc);
 	kstat_incr_irqs_this_cpu(irq, desc);
@@ -483,7 +480,6 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
 	/* Start handling the irq */
 	/* Start handling the irq */
 	if (desc->chip->ack)
 	if (desc->chip->ack)
 		desc->chip->ack(irq);
 		desc->chip->ack(irq);
-	desc = irq_remap_to_desc(irq, desc);
 
 
 	/* Mark the IRQ currently in progress.*/
 	/* Mark the IRQ currently in progress.*/
 	desc->status |= IRQ_INPROGRESS;
 	desc->status |= IRQ_INPROGRESS;
@@ -544,10 +540,8 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
 	if (!noirqdebug)
 	if (!noirqdebug)
 		note_interrupt(irq, desc, action_ret);
 		note_interrupt(irq, desc, action_ret);
 
 
-	if (desc->chip->eoi) {
+	if (desc->chip->eoi)
 		desc->chip->eoi(irq);
 		desc->chip->eoi(irq);
-		desc = irq_remap_to_desc(irq, desc);
-	}
 }
 }
 
 
 void
 void
@@ -582,10 +576,8 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
 
 
 	/* Uninstall? */
 	/* Uninstall? */
 	if (handle == handle_bad_irq) {
 	if (handle == handle_bad_irq) {
-		if (desc->chip != &no_irq_chip) {
+		if (desc->chip != &no_irq_chip)
 			mask_ack_irq(desc, irq);
 			mask_ack_irq(desc, irq);
-			desc = irq_remap_to_desc(irq, desc);
-		}
 		desc->status |= IRQ_DISABLED;
 		desc->status |= IRQ_DISABLED;
 		desc->depth = 1;
 		desc->depth = 1;
 	}
 	}

+ 30 - 28
kernel/irq/handle.c

@@ -11,6 +11,7 @@
  */
  */
 
 
 #include <linux/irq.h>
 #include <linux/irq.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/random.h>
 #include <linux/random.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
@@ -81,45 +82,48 @@ static struct irq_desc irq_desc_init = {
 	.lock       = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
 	.lock       = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
 };
 };
 
 
-void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr)
+void __ref init_kstat_irqs(struct irq_desc *desc, int node, int nr)
 {
 {
-	int node;
 	void *ptr;
 	void *ptr;
 
 
-	node = cpu_to_node(cpu);
-	ptr = kzalloc_node(nr * sizeof(*desc->kstat_irqs), GFP_ATOMIC, node);
+	if (slab_is_available())
+		ptr = kzalloc_node(nr * sizeof(*desc->kstat_irqs),
+				   GFP_ATOMIC, node);
+	else
+		ptr = alloc_bootmem_node(NODE_DATA(node),
+				nr * sizeof(*desc->kstat_irqs));
 
 
 	/*
 	/*
 	 * don't overwite if can not get new one
 	 * don't overwite if can not get new one
 	 * init_copy_kstat_irqs() could still use old one
 	 * init_copy_kstat_irqs() could still use old one
 	 */
 	 */
 	if (ptr) {
 	if (ptr) {
-		printk(KERN_DEBUG "  alloc kstat_irqs on cpu %d node %d\n",
-			 cpu, node);
+		printk(KERN_DEBUG "  alloc kstat_irqs on node %d\n", node);
 		desc->kstat_irqs = ptr;
 		desc->kstat_irqs = ptr;
 	}
 	}
 }
 }
 
 
-static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu)
+static void init_one_irq_desc(int irq, struct irq_desc *desc, int node)
 {
 {
 	memcpy(desc, &irq_desc_init, sizeof(struct irq_desc));
 	memcpy(desc, &irq_desc_init, sizeof(struct irq_desc));
 
 
 	spin_lock_init(&desc->lock);
 	spin_lock_init(&desc->lock);
 	desc->irq = irq;
 	desc->irq = irq;
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
-	desc->cpu = cpu;
+	desc->node = node;
 #endif
 #endif
 	lockdep_set_class(&desc->lock, &irq_desc_lock_class);
 	lockdep_set_class(&desc->lock, &irq_desc_lock_class);
-	init_kstat_irqs(desc, cpu, nr_cpu_ids);
+	init_kstat_irqs(desc, node, nr_cpu_ids);
 	if (!desc->kstat_irqs) {
 	if (!desc->kstat_irqs) {
 		printk(KERN_ERR "can not alloc kstat_irqs\n");
 		printk(KERN_ERR "can not alloc kstat_irqs\n");
 		BUG_ON(1);
 		BUG_ON(1);
 	}
 	}
-	if (!init_alloc_desc_masks(desc, cpu, false)) {
+	if (!alloc_desc_masks(desc, node, false)) {
 		printk(KERN_ERR "can not alloc irq_desc cpumasks\n");
 		printk(KERN_ERR "can not alloc irq_desc cpumasks\n");
 		BUG_ON(1);
 		BUG_ON(1);
 	}
 	}
-	arch_init_chip_data(desc, cpu);
+	init_desc_masks(desc);
+	arch_init_chip_data(desc, node);
 }
 }
 
 
 /*
 /*
@@ -169,7 +173,8 @@ int __init early_irq_init(void)
 		desc[i].irq = i;
 		desc[i].irq = i;
 		desc[i].kstat_irqs = kstat_irqs_legacy + i * nr_cpu_ids;
 		desc[i].kstat_irqs = kstat_irqs_legacy + i * nr_cpu_ids;
 		lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
 		lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
-		init_alloc_desc_masks(&desc[i], 0, true);
+		alloc_desc_masks(&desc[i], 0, true);
+		init_desc_masks(&desc[i]);
 		irq_desc_ptrs[i] = desc + i;
 		irq_desc_ptrs[i] = desc + i;
 	}
 	}
 
 
@@ -187,11 +192,10 @@ struct irq_desc *irq_to_desc(unsigned int irq)
 	return NULL;
 	return NULL;
 }
 }
 
 
-struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu)
+struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node)
 {
 {
 	struct irq_desc *desc;
 	struct irq_desc *desc;
 	unsigned long flags;
 	unsigned long flags;
-	int node;
 
 
 	if (irq >= nr_irqs) {
 	if (irq >= nr_irqs) {
 		WARN(1, "irq (%d) >= nr_irqs (%d) in irq_to_desc_alloc\n",
 		WARN(1, "irq (%d) >= nr_irqs (%d) in irq_to_desc_alloc\n",
@@ -210,15 +214,17 @@ struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu)
 	if (desc)
 	if (desc)
 		goto out_unlock;
 		goto out_unlock;
 
 
-	node = cpu_to_node(cpu);
-	desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
-	printk(KERN_DEBUG "  alloc irq_desc for %d on cpu %d node %d\n",
-		 irq, cpu, node);
+	if (slab_is_available())
+		desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
+	else
+		desc = alloc_bootmem_node(NODE_DATA(node), sizeof(*desc));
+
+	printk(KERN_DEBUG "  alloc irq_desc for %d on node %d\n", irq, node);
 	if (!desc) {
 	if (!desc) {
 		printk(KERN_ERR "can not alloc irq_desc\n");
 		printk(KERN_ERR "can not alloc irq_desc\n");
 		BUG_ON(1);
 		BUG_ON(1);
 	}
 	}
-	init_one_irq_desc(irq, desc, cpu);
+	init_one_irq_desc(irq, desc, node);
 
 
 	irq_desc_ptrs[irq] = desc;
 	irq_desc_ptrs[irq] = desc;
 
 
@@ -256,7 +262,8 @@ int __init early_irq_init(void)
 
 
 	for (i = 0; i < count; i++) {
 	for (i = 0; i < count; i++) {
 		desc[i].irq = i;
 		desc[i].irq = i;
-		init_alloc_desc_masks(&desc[i], 0, true);
+		alloc_desc_masks(&desc[i], 0, true);
+		init_desc_masks(&desc[i]);
 		desc[i].kstat_irqs = kstat_irqs_all[i];
 		desc[i].kstat_irqs = kstat_irqs_all[i];
 	}
 	}
 	return arch_early_irq_init();
 	return arch_early_irq_init();
@@ -267,7 +274,7 @@ struct irq_desc *irq_to_desc(unsigned int irq)
 	return (irq < NR_IRQS) ? irq_desc + irq : NULL;
 	return (irq < NR_IRQS) ? irq_desc + irq : NULL;
 }
 }
 
 
-struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu)
+struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node)
 {
 {
 	return irq_to_desc(irq);
 	return irq_to_desc(irq);
 }
 }
@@ -453,11 +460,8 @@ unsigned int __do_IRQ(unsigned int irq)
 		/*
 		/*
 		 * No locking required for CPU-local interrupts:
 		 * No locking required for CPU-local interrupts:
 		 */
 		 */
-		if (desc->chip->ack) {
+		if (desc->chip->ack)
 			desc->chip->ack(irq);
 			desc->chip->ack(irq);
-			/* get new one */
-			desc = irq_remap_to_desc(irq, desc);
-		}
 		if (likely(!(desc->status & IRQ_DISABLED))) {
 		if (likely(!(desc->status & IRQ_DISABLED))) {
 			action_ret = handle_IRQ_event(irq, desc->action);
 			action_ret = handle_IRQ_event(irq, desc->action);
 			if (!noirqdebug)
 			if (!noirqdebug)
@@ -468,10 +472,8 @@ unsigned int __do_IRQ(unsigned int irq)
 	}
 	}
 
 
 	spin_lock(&desc->lock);
 	spin_lock(&desc->lock);
-	if (desc->chip->ack) {
+	if (desc->chip->ack)
 		desc->chip->ack(irq);
 		desc->chip->ack(irq);
-		desc = irq_remap_to_desc(irq, desc);
-	}
 	/*
 	/*
 	 * REPLAY is when Linux resends an IRQ that was dropped earlier
 	 * REPLAY is when Linux resends an IRQ that was dropped earlier
 	 * WAITING is used by probe to mark irqs that are being tested
 	 * WAITING is used by probe to mark irqs that are being tested

+ 4 - 1
kernel/irq/internals.h

@@ -16,7 +16,7 @@ extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp);
 extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume);
 extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume);
 
 
 extern struct lock_class_key irq_desc_lock_class;
 extern struct lock_class_key irq_desc_lock_class;
-extern void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr);
+extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr);
 extern void clear_kstat_irqs(struct irq_desc *desc);
 extern void clear_kstat_irqs(struct irq_desc *desc);
 extern spinlock_t sparse_irq_lock;
 extern spinlock_t sparse_irq_lock;
 
 
@@ -42,6 +42,9 @@ static inline void unregister_handler_proc(unsigned int irq,
 
 
 extern int irq_select_affinity_usr(unsigned int irq);
 extern int irq_select_affinity_usr(unsigned int irq);
 
 
+extern void
+irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask);
+
 /*
 /*
  * Debugging printout:
  * Debugging printout:
  */
  */

+ 11 - 6
kernel/irq/manage.c

@@ -80,7 +80,7 @@ int irq_can_set_affinity(unsigned int irq)
 	return 1;
 	return 1;
 }
 }
 
 
-static void
+void
 irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask)
 irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask)
 {
 {
 	struct irqaction *action = desc->action;
 	struct irqaction *action = desc->action;
@@ -109,17 +109,22 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
 	spin_lock_irqsave(&desc->lock, flags);
 	spin_lock_irqsave(&desc->lock, flags);
 
 
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 #ifdef CONFIG_GENERIC_PENDING_IRQ
-	if (desc->status & IRQ_MOVE_PCNTXT)
-		desc->chip->set_affinity(irq, cpumask);
+	if (desc->status & IRQ_MOVE_PCNTXT) {
+		if (!desc->chip->set_affinity(irq, cpumask)) {
+			cpumask_copy(desc->affinity, cpumask);
+			irq_set_thread_affinity(desc, cpumask);
+		}
+	}
 	else {
 	else {
 		desc->status |= IRQ_MOVE_PENDING;
 		desc->status |= IRQ_MOVE_PENDING;
 		cpumask_copy(desc->pending_mask, cpumask);
 		cpumask_copy(desc->pending_mask, cpumask);
 	}
 	}
 #else
 #else
-	cpumask_copy(desc->affinity, cpumask);
-	desc->chip->set_affinity(irq, cpumask);
+	if (!desc->chip->set_affinity(irq, cpumask)) {
+		cpumask_copy(desc->affinity, cpumask);
+		irq_set_thread_affinity(desc, cpumask);
+	}
 #endif
 #endif
-	irq_set_thread_affinity(desc, cpumask);
 	desc->status |= IRQ_AFFINITY_SET;
 	desc->status |= IRQ_AFFINITY_SET;
 	spin_unlock_irqrestore(&desc->lock, flags);
 	spin_unlock_irqrestore(&desc->lock, flags);
 	return 0;
 	return 0;

+ 9 - 5
kernel/irq/migration.c

@@ -1,5 +1,8 @@
 
 
 #include <linux/irq.h>
 #include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include "internals.h"
 
 
 void move_masked_irq(int irq)
 void move_masked_irq(int irq)
 {
 {
@@ -39,11 +42,12 @@ void move_masked_irq(int irq)
 	 * masking the irqs.
 	 * masking the irqs.
 	 */
 	 */
 	if (likely(cpumask_any_and(desc->pending_mask, cpu_online_mask)
 	if (likely(cpumask_any_and(desc->pending_mask, cpu_online_mask)
-		   < nr_cpu_ids)) {
-		cpumask_and(desc->affinity,
-			    desc->pending_mask, cpu_online_mask);
-		desc->chip->set_affinity(irq, desc->affinity);
-	}
+		   < nr_cpu_ids))
+		if (!desc->chip->set_affinity(irq, desc->pending_mask)) {
+			cpumask_copy(desc->affinity, desc->pending_mask);
+			irq_set_thread_affinity(desc, desc->pending_mask);
+		}
+
 	cpumask_clear(desc->pending_mask);
 	cpumask_clear(desc->pending_mask);
 }
 }
 
 

+ 12 - 26
kernel/irq/numa_migrate.c

@@ -15,9 +15,9 @@
 
 
 static void init_copy_kstat_irqs(struct irq_desc *old_desc,
 static void init_copy_kstat_irqs(struct irq_desc *old_desc,
 				 struct irq_desc *desc,
 				 struct irq_desc *desc,
-				 int cpu, int nr)
+				 int node, int nr)
 {
 {
-	init_kstat_irqs(desc, cpu, nr);
+	init_kstat_irqs(desc, node, nr);
 
 
 	if (desc->kstat_irqs != old_desc->kstat_irqs)
 	if (desc->kstat_irqs != old_desc->kstat_irqs)
 		memcpy(desc->kstat_irqs, old_desc->kstat_irqs,
 		memcpy(desc->kstat_irqs, old_desc->kstat_irqs,
@@ -34,20 +34,20 @@ static void free_kstat_irqs(struct irq_desc *old_desc, struct irq_desc *desc)
 }
 }
 
 
 static bool init_copy_one_irq_desc(int irq, struct irq_desc *old_desc,
 static bool init_copy_one_irq_desc(int irq, struct irq_desc *old_desc,
-		 struct irq_desc *desc, int cpu)
+		 struct irq_desc *desc, int node)
 {
 {
 	memcpy(desc, old_desc, sizeof(struct irq_desc));
 	memcpy(desc, old_desc, sizeof(struct irq_desc));
-	if (!init_alloc_desc_masks(desc, cpu, false)) {
+	if (!alloc_desc_masks(desc, node, false)) {
 		printk(KERN_ERR "irq %d: can not get new irq_desc cpumask "
 		printk(KERN_ERR "irq %d: can not get new irq_desc cpumask "
 				"for migration.\n", irq);
 				"for migration.\n", irq);
 		return false;
 		return false;
 	}
 	}
 	spin_lock_init(&desc->lock);
 	spin_lock_init(&desc->lock);
-	desc->cpu = cpu;
+	desc->node = node;
 	lockdep_set_class(&desc->lock, &irq_desc_lock_class);
 	lockdep_set_class(&desc->lock, &irq_desc_lock_class);
-	init_copy_kstat_irqs(old_desc, desc, cpu, nr_cpu_ids);
+	init_copy_kstat_irqs(old_desc, desc, node, nr_cpu_ids);
 	init_copy_desc_masks(old_desc, desc);
 	init_copy_desc_masks(old_desc, desc);
-	arch_init_copy_chip_data(old_desc, desc, cpu);
+	arch_init_copy_chip_data(old_desc, desc, node);
 	return true;
 	return true;
 }
 }
 
 
@@ -59,12 +59,11 @@ static void free_one_irq_desc(struct irq_desc *old_desc, struct irq_desc *desc)
 }
 }
 
 
 static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
 static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
-						int cpu)
+						int node)
 {
 {
 	struct irq_desc *desc;
 	struct irq_desc *desc;
 	unsigned int irq;
 	unsigned int irq;
 	unsigned long flags;
 	unsigned long flags;
-	int node;
 
 
 	irq = old_desc->irq;
 	irq = old_desc->irq;
 
 
@@ -76,7 +75,6 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
 	if (desc && old_desc != desc)
 	if (desc && old_desc != desc)
 		goto out_unlock;
 		goto out_unlock;
 
 
-	node = cpu_to_node(cpu);
 	desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
 	desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
 	if (!desc) {
 	if (!desc) {
 		printk(KERN_ERR "irq %d: can not get new irq_desc "
 		printk(KERN_ERR "irq %d: can not get new irq_desc "
@@ -85,7 +83,7 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
 		desc = old_desc;
 		desc = old_desc;
 		goto out_unlock;
 		goto out_unlock;
 	}
 	}
-	if (!init_copy_one_irq_desc(irq, old_desc, desc, cpu)) {
+	if (!init_copy_one_irq_desc(irq, old_desc, desc, node)) {
 		/* still use old one */
 		/* still use old one */
 		kfree(desc);
 		kfree(desc);
 		desc = old_desc;
 		desc = old_desc;
@@ -97,9 +95,7 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
 
 
 	/* free the old one */
 	/* free the old one */
 	free_one_irq_desc(old_desc, desc);
 	free_one_irq_desc(old_desc, desc);
-	spin_unlock(&old_desc->lock);
 	kfree(old_desc);
 	kfree(old_desc);
-	spin_lock(&desc->lock);
 
 
 	return desc;
 	return desc;
 
 
@@ -109,24 +105,14 @@ out_unlock:
 	return desc;
 	return desc;
 }
 }
 
 
-struct irq_desc *move_irq_desc(struct irq_desc *desc, int cpu)
+struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
 {
 {
-	int old_cpu;
-	int node, old_node;
-
 	/* those all static, do move them */
 	/* those all static, do move them */
 	if (desc->irq < NR_IRQS_LEGACY)
 	if (desc->irq < NR_IRQS_LEGACY)
 		return desc;
 		return desc;
 
 
-	old_cpu = desc->cpu;
-	if (old_cpu != cpu) {
-		node = cpu_to_node(cpu);
-		old_node = cpu_to_node(old_cpu);
-		if (old_node != node)
-			desc = __real_move_irq_desc(desc, cpu);
-		else
-			desc->cpu = cpu;
-	}
+	if (desc->node != node)
+		desc = __real_move_irq_desc(desc, node);
 
 
 	return desc;
 	return desc;
 }
 }

+ 1 - 1
kernel/softirq.c

@@ -828,7 +828,7 @@ int __init __weak arch_early_irq_init(void)
 	return 0;
 	return 0;
 }
 }
 
 
-int __weak arch_init_chip_data(struct irq_desc *desc, int cpu)
+int __weak arch_init_chip_data(struct irq_desc *desc, int node)
 {
 {
 	return 0;
 	return 0;
 }
 }

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini