All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: Other problem/regression with b9c61b70075c87a8612624736faf4a2de5b1ed30
       [not found]   ` <201002221258.38506.trenn@suse.de>
@ 2010-02-23  9:07     ` Yinghai Lu
  2010-02-23 18:40       ` Yinghai Lu
  2010-02-23 19:02       ` Other problem/regression with b9c61b70075c87a8612624736faf4a2de5b1ed30 Gary Hade
  0 siblings, 2 replies; 34+ messages in thread
From: Yinghai Lu @ 2010-02-23  9:07 UTC (permalink / raw)
  To: Thomas Renninger, Gary Hade, Ingo Molnar, Thomas Gleixner
  Cc: Iranna D Ankad, H. Peter Anvin, Eric W. Biederman, Suresh Siddha,
	len.brown, linux-kernel

Gary,

can you check this patch on your x3950?

Thanks

Yinghai

[PATCH] x86: fix out of order of gsi

found IBM x3950 will have problem after

|commit b9c61b70075c87a8612624736faf4a2de5b1ed30
|
|    x86/pci: update pirq_enable_irq() to setup io apic routing

The problem is that with the patch, the machine freezes when
console=ttyS0,... kernel serial parameter is passed.
It seem to freeze at DVD initialization and the whole problem seem
to be DVD/pata related, but somehow exposed through the serial
parameter.
Such apic problems can expose really weird behavior..

<6>ACPI: IOAPIC (id[0x10] address[0xfecff000] gsi_base[0])
<6>IOAPIC[0]: apic_id 16, version 0, address 0xfecff000, GSI 0-2
<6>ACPI: IOAPIC (id[0x0f] address[0xfec00000] gsi_base[3])
<6>IOAPIC[1]: apic_id 15, version 0, address 0xfec00000, GSI 3-38
<6>ACPI: IOAPIC (id[0x0e] address[0xfec01000] gsi_base[39])
<6>IOAPIC[2]: apic_id 14, version 0, address 0xfec01000, GSI 39-74
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 1 global_irq 4 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 5 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 3 global_irq 6 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 4 global_irq 7 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 6 global_irq 9 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 7 global_irq 10 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 8 global_irq 11 low edge)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 12 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 12 global_irq 15 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 13 global_irq 16 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 14 global_irq 17 low edge)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 15 global_irq 18 dfl dfl)

it turns out that system have three io apic controller. but put boot ioapic
routing in second one. and that gsi_base is not 0. it is using bunch of INT_SRC_OVR...

recent changes
1. one set routing for first io apic controller
2. assume irq = gsi
will break theat system.

so try to remap those gsi, need to seperate boot_ioapic_id detection out of enable_IO_APIC
and call them early.
introduce boot_ioapic_id, and remap_ioapic_gsi...

Reported-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Bisected-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Cc: Thomas Renninger <trenn@suse.de>
Cc: stable@kernel.org
Signed-off-by: Yinghai Lu <yinghai@kernel.org>

---
 arch/x86/include/asm/io_apic.h |    3 +-
 arch/x86/include/asm/mpspec.h  |    1 
 arch/x86/kernel/acpi/boot.c    |   27 +++++++++++++++++---
 arch/x86/kernel/apic/io_apic.c |   55 ++++++++++++++++++++++++-----------------
 4 files changed, 59 insertions(+), 27 deletions(-)

Index: linux-2.6/arch/x86/include/asm/io_apic.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/io_apic.h
+++ linux-2.6/arch/x86/include/asm/io_apic.h
@@ -113,6 +113,7 @@ struct IR_IO_APIC_route_entry {
  */
 extern int nr_ioapics;
 extern int nr_ioapic_registers[MAX_IO_APICS];
+extern int boot_ioapic_idx;
 
 #define MP_MAX_IOAPIC_PIN 127
 
@@ -160,7 +161,7 @@ extern int io_apic_get_redir_entries(int
 struct io_apic_irq_attr;
 extern int io_apic_set_pci_routing(struct device *dev, int irq,
 		 struct io_apic_irq_attr *irq_attr);
-void setup_IO_APIC_irq_extra(u32 gsi);
+void setup_IO_APIC_irq_extra(u32 gsi, unsigned int *irq);
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
 extern void ioapic_init_mappings(void);
 extern void ioapic_insert_resources(void);
Index: linux-2.6/arch/x86/include/asm/mpspec.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/mpspec.h
+++ linux-2.6/arch/x86/include/asm/mpspec.h
@@ -105,6 +105,7 @@ extern void mp_config_acpi_legacy_irqs(v
 struct device;
 extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level,
 				 int active_high_low);
+int remap_ioapic_gsi(int ioapic, u32 gsi);
 extern int acpi_probe_gsi(void);
 #ifdef CONFIG_X86_IO_APIC
 extern int mp_find_ioapic(int gsi);
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/acpi/boot.c
+++ linux-2.6/arch/x86/kernel/acpi/boot.c
@@ -449,7 +449,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned in
 
 #ifdef CONFIG_X86_IO_APIC
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
-		setup_IO_APIC_irq_extra(gsi);
+		setup_IO_APIC_irq_extra(gsi, irq);
 #endif
 
 	return 0;
@@ -1049,11 +1049,29 @@ static int mp_config_acpi_gsi(struct dev
 	return 0;
 }
 
+int remap_ioapic_gsi(int ioapic, u32 gsi)
+{
+	int base_boot = mp_gsi_routing[boot_ioapic_idx].gsi_base;
+	int base_x;
+
+	if (!base_boot)
+		return gsi;
+
+	base_x = mp_gsi_routing[ioapic].gsi_base;
+	if (base_x < base_boot)
+		gsi += base_boot;
+	else if (base_x == base_boot)
+		gsi -= base_boot;
+
+	return gsi;
+}
+
 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;
+	u32 plat_gsi;
 
 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
 		return gsi;
@@ -1074,12 +1092,13 @@ int mp_register_gsi(struct device *dev,
 	if (ioapic_renumber_irq)
 		gsi = ioapic_renumber_irq(ioapic, gsi);
 #endif
+	plat_gsi = remap_ioapic_gsi(ioapic, gsi);
 
 	if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
 		printk(KERN_ERR "Invalid reference to IOAPIC pin "
 		       "%d-%d\n", mp_ioapics[ioapic].apicid,
 		       ioapic_pin);
-		return gsi;
+		return plat_gsi;
 	}
 
 	if (enable_update_mptable)
@@ -1088,9 +1107,9 @@ int mp_register_gsi(struct device *dev,
 	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);
+	io_apic_set_pci_routing(dev, plat_gsi, &irq_attr);
 
-	return gsi;
+	return plat_gsi;
 }
 
 /*
Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/apic/io_apic.c
+++ linux-2.6/arch/x86/kernel/apic/io_apic.c
@@ -84,6 +84,7 @@ int nr_ioapic_registers[MAX_IO_APICS];
 /* I/O APIC entries */
 struct mpc_ioapic mp_ioapics[MAX_IO_APICS];
 int nr_ioapics;
+int boot_ioapic_idx;
 
 /* IO APIC gsi routing info */
 struct mp_ioapic_gsi  mp_gsi_routing[MAX_IO_APICS];
@@ -1028,13 +1029,18 @@ static int pin_2_irq(int idx, int apic,
 	if (test_bit(bus, mp_bus_not_pci)) {
 		irq = mp_irqs[idx].srcbusirq;
 	} else {
-		/*
-		 * PCI IRQs are mapped in order
-		 */
-		i = irq = 0;
-		while (i < apic)
-			irq += nr_ioapic_registers[i++];
-		irq += pin;
+		if (!acpi_ioapic) {
+			/*
+			 * PCI IRQs are mapped in order
+			 */
+			i = irq = 0;
+			while (i < apic)
+				irq += nr_ioapic_registers[i++];
+			irq += pin;
+		} else {
+			irq = pin + mp_gsi_routing[apic].gsi_base;
+			irq = remap_ioapic_gsi(apic, irq);
+		}
 		/*
                  * For MPS mode, so far only needed by ES7000 platform
                  */
@@ -1473,9 +1479,10 @@ static struct {
 	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
 } mp_ioapic_routing[MAX_IO_APICS];
 
-static void __init setup_IO_APIC_irqs(void)
+
+static void __init setup_IO_APIC_irqs(int apic_id)
 {
-	int apic_id = 0, pin, idx, irq;
+	int pin, idx, irq;
 	int notcon = 0;
 	struct irq_desc *desc;
 	struct irq_cfg *cfg;
@@ -1483,14 +1490,6 @@ static void __init setup_IO_APIC_irqs(vo
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		apic_id = mp_find_ioapic(0);
-		if (apic_id < 0)
-			apic_id = 0;
-	}
-#endif
-
 	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
 		idx = find_irq_entry(apic_id, pin, mp_INT);
 		if (idx == -1) {
@@ -1545,7 +1544,7 @@ static void __init setup_IO_APIC_irqs(vo
  * but could not use acpi_register_gsi()
  * like some special sci in IBM x3330
  */
-void setup_IO_APIC_irq_extra(u32 gsi)
+void setup_IO_APIC_irq_extra(u32 gsi, unsigned int *pirq)
 {
 	int apic_id = 0, pin, idx, irq;
 	int node = cpu_to_node(boot_cpu_id);
@@ -1565,6 +1564,7 @@ void setup_IO_APIC_irq_extra(u32 gsi)
 		return;
 
 	irq = pin_2_irq(idx, apic_id, pin);
+	*pirq = irq;
 #ifdef CONFIG_SPARSE_IRQ
 	desc = irq_to_desc(irq);
 	if (desc)
@@ -1940,11 +1940,10 @@ __apicdebuginit(int) print_ICs(void)
 
 fs_initcall(print_ICs);
 
-
 /* Where if anywhere is the i8259 connect in external int mode */
 static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
 
-void __init enable_IO_APIC(void)
+static void __init probe_ioapic_i8259(void)
 {
 	union IO_APIC_reg_01 reg_01;
 	int i8259_apic, i8259_pin;
@@ -2001,7 +2000,12 @@ void __init enable_IO_APIC(void)
 	{
 		printk(KERN_WARNING "ExtINT in hardware and MP table differ\n");
 	}
+}
 
+void __init enable_IO_APIC(void)
+{
+	if (!nr_legacy_irqs)
+		return;
 	/*
 	 * Do not trust the IO-APIC being empty at bootup
 	 */
@@ -3126,7 +3130,6 @@ out:
 
 void __init setup_IO_APIC(void)
 {
-
 	/*
 	 * calling enable_IO_APIC() is moved to setup_local_APIC for BP
 	 */
@@ -3139,7 +3142,15 @@ void __init setup_IO_APIC(void)
 	x86_init.mpparse.setup_ioapic_ids();
 
 	sync_Arb_IDs();
-	setup_IO_APIC_irqs();
+	probe_ioapic_i8259();
+	boot_ioapic_idx = ioapic_i8259.apic;
+#ifdef CONFIG_ACPI
+	if (!acpi_disabled && acpi_ioapic && boot_ioapic_idx < 0)
+		boot_ioapic_idx = mp_find_ioapic(0);
+#endif
+	if (boot_ioapic_idx < 0)
+		boot_ioapic_idx = 0;
+	setup_IO_APIC_irqs(boot_ioapic_idx);
 	init_IO_APIC_traps();
 	if (nr_legacy_irqs)
 		check_timer();

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: Other problem/regression with b9c61b70075c87a8612624736faf4a2de5b1ed30
  2010-02-23  9:07     ` Other problem/regression with b9c61b70075c87a8612624736faf4a2de5b1ed30 Yinghai Lu
@ 2010-02-23 18:40       ` Yinghai Lu
  2010-02-23 20:17         ` Eric W. Biederman
                           ` (2 more replies)
  2010-02-23 19:02       ` Other problem/regression with b9c61b70075c87a8612624736faf4a2de5b1ed30 Gary Hade
  1 sibling, 3 replies; 34+ messages in thread
From: Yinghai Lu @ 2010-02-23 18:40 UTC (permalink / raw)
  To: Thomas Renninger, Gary Hade, Ingo Molnar, Thomas Gleixner
  Cc: Iranna D Ankad, H. Peter Anvin, Eric W. Biederman, Suresh Siddha,
	len.brown, linux-kernel

On 02/23/2010 01:07 AM, Yinghai Lu wrote:
> Gary,
> 
> can you check this patch on your x3950?

Subject: [PATCH -v2] x86: fix out of order of gsi

found IBM x3950 will have problem after

|commit b9c61b70075c87a8612624736faf4a2de5b1ed30
|
|    x86/pci: update pirq_enable_irq() to setup io apic routing

The problem is that with the patch, the machine freezes when
console=ttyS0,... kernel serial parameter is passed.
It seem to freeze at DVD initialization and the whole problem seem
to be DVD/pata related, but somehow exposed through the serial
parameter.
Such apic problems can expose really weird behavior..

<6>ACPI: IOAPIC (id[0x10] address[0xfecff000] gsi_base[0])
<6>IOAPIC[0]: apic_id 16, version 0, address 0xfecff000, GSI 0-2
<6>ACPI: IOAPIC (id[0x0f] address[0xfec00000] gsi_base[3])
<6>IOAPIC[1]: apic_id 15, version 0, address 0xfec00000, GSI 3-38
<6>ACPI: IOAPIC (id[0x0e] address[0xfec01000] gsi_base[39])
<6>IOAPIC[2]: apic_id 14, version 0, address 0xfec01000, GSI 39-74
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 1 global_irq 4 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 5 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 3 global_irq 6 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 4 global_irq 7 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 6 global_irq 9 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 7 global_irq 10 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 8 global_irq 11 low edge)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 12 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 12 global_irq 15 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 13 global_irq 16 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 14 global_irq 17 low edge)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 15 global_irq 18 dfl dfl)

it turns out that system have three io apic controller. but put boot ioapic
routing in second one. and that gsi_base is not 0. it is using bunch of INT_SRC_OVR...

recent changes
1. one set routing for first io apic controller
2. assume irq = gsi
will break theat system.

so try to remap those gsi, need to seperate boot_ioapic_id detection out of enable_IO_APIC
and call them early.
introduce boot_ioapic_id, and remap_ioapic_gsi...

-v2: shift gsi with delta instead of gsi_base of boot_ioapic_idx

Reported-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Bisected-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Cc: Thomas Renninger <trenn@suse.de>
Cc: stable@kernel.org
Signed-off-by: Yinghai Lu <yinghai@kernel.org>

---
 arch/x86/include/asm/io_apic.h |    3 +-
 arch/x86/include/asm/mpspec.h  |    1 
 arch/x86/kernel/acpi/boot.c    |   30 +++++++++++++++++++---
 arch/x86/kernel/apic/io_apic.c |   55 ++++++++++++++++++++++++-----------------
 4 files changed, 62 insertions(+), 27 deletions(-)

Index: linux-2.6/arch/x86/include/asm/io_apic.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/io_apic.h
+++ linux-2.6/arch/x86/include/asm/io_apic.h
@@ -113,6 +113,7 @@ struct IR_IO_APIC_route_entry {
  */
 extern int nr_ioapics;
 extern int nr_ioapic_registers[MAX_IO_APICS];
+extern int boot_ioapic_idx;
 
 #define MP_MAX_IOAPIC_PIN 127
 
@@ -160,7 +161,7 @@ extern int io_apic_get_redir_entries(int
 struct io_apic_irq_attr;
 extern int io_apic_set_pci_routing(struct device *dev, int irq,
 		 struct io_apic_irq_attr *irq_attr);
-void setup_IO_APIC_irq_extra(u32 gsi);
+void setup_IO_APIC_irq_extra(u32 gsi, unsigned int *irq);
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
 extern void ioapic_init_mappings(void);
 extern void ioapic_insert_resources(void);
Index: linux-2.6/arch/x86/include/asm/mpspec.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/mpspec.h
+++ linux-2.6/arch/x86/include/asm/mpspec.h
@@ -105,6 +105,7 @@ extern void mp_config_acpi_legacy_irqs(v
 struct device;
 extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level,
 				 int active_high_low);
+int remap_ioapic_gsi(int ioapic, u32 gsi);
 extern int acpi_probe_gsi(void);
 #ifdef CONFIG_X86_IO_APIC
 extern int mp_find_ioapic(int gsi);
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/acpi/boot.c
+++ linux-2.6/arch/x86/kernel/acpi/boot.c
@@ -449,7 +449,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned in
 
 #ifdef CONFIG_X86_IO_APIC
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
-		setup_IO_APIC_irq_extra(gsi);
+		setup_IO_APIC_irq_extra(gsi, irq);
 #endif
 
 	return 0;
@@ -1052,11 +1052,32 @@ static int mp_config_acpi_gsi(struct dev
 	return 0;
 }
 
+int remap_ioapic_gsi(int ioapic, u32 gsi)
+{
+	int base_boot = mp_gsi_routing[boot_ioapic_idx].gsi_base;
+	int base_x;
+
+	if (!base_boot)
+		return gsi;
+
+	base_x = mp_gsi_routing[ioapic].gsi_base;
+	if (base_x < base_boot) {
+		int delta;
+		delta = mp_gsi_routing[boot_ioapic_idx].gsi_end + 1;
+		delta -= base_boot;
+		gsi += delta;
+	} else if (base_x == base_boot)
+		gsi -= base_boot;
+
+	return gsi;
+}
+
 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;
+	u32 plat_gsi;
 
 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
 		return gsi;
@@ -1077,12 +1098,13 @@ int mp_register_gsi(struct device *dev,
 	if (ioapic_renumber_irq)
 		gsi = ioapic_renumber_irq(ioapic, gsi);
 #endif
+	plat_gsi = remap_ioapic_gsi(ioapic, gsi);
 
 	if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
 		printk(KERN_ERR "Invalid reference to IOAPIC pin "
 		       "%d-%d\n", mp_ioapics[ioapic].apicid,
 		       ioapic_pin);
-		return gsi;
+		return plat_gsi;
 	}
 
 	if (enable_update_mptable)
@@ -1091,9 +1113,9 @@ int mp_register_gsi(struct device *dev,
 	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);
+	io_apic_set_pci_routing(dev, plat_gsi, &irq_attr);
 
-	return gsi;
+	return plat_gsi;
 }
 
 /*
Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/apic/io_apic.c
+++ linux-2.6/arch/x86/kernel/apic/io_apic.c
@@ -84,6 +84,7 @@ int nr_ioapic_registers[MAX_IO_APICS];
 /* I/O APIC entries */
 struct mpc_ioapic mp_ioapics[MAX_IO_APICS];
 int nr_ioapics;
+int boot_ioapic_idx;
 
 /* IO APIC gsi routing info */
 struct mp_ioapic_gsi  mp_gsi_routing[MAX_IO_APICS];
@@ -1028,13 +1029,18 @@ static int pin_2_irq(int idx, int apic,
 	if (test_bit(bus, mp_bus_not_pci)) {
 		irq = mp_irqs[idx].srcbusirq;
 	} else {
-		/*
-		 * PCI IRQs are mapped in order
-		 */
-		i = irq = 0;
-		while (i < apic)
-			irq += nr_ioapic_registers[i++];
-		irq += pin;
+		if (!acpi_ioapic) {
+			/*
+			 * PCI IRQs are mapped in order
+			 */
+			i = irq = 0;
+			while (i < apic)
+				irq += nr_ioapic_registers[i++];
+			irq += pin;
+		} else {
+			irq = pin + mp_gsi_routing[apic].gsi_base;
+			irq = remap_ioapic_gsi(apic, irq);
+		}
 		/*
                  * For MPS mode, so far only needed by ES7000 platform
                  */
@@ -1473,9 +1479,10 @@ static struct {
 	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
 } mp_ioapic_routing[MAX_IO_APICS];
 
-static void __init setup_IO_APIC_irqs(void)
+
+static void __init setup_IO_APIC_irqs(int apic_id)
 {
-	int apic_id = 0, pin, idx, irq;
+	int pin, idx, irq;
 	int notcon = 0;
 	struct irq_desc *desc;
 	struct irq_cfg *cfg;
@@ -1483,14 +1490,6 @@ static void __init setup_IO_APIC_irqs(vo
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		apic_id = mp_find_ioapic(0);
-		if (apic_id < 0)
-			apic_id = 0;
-	}
-#endif
-
 	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
 		idx = find_irq_entry(apic_id, pin, mp_INT);
 		if (idx == -1) {
@@ -1545,7 +1544,7 @@ static void __init setup_IO_APIC_irqs(vo
  * but could not use acpi_register_gsi()
  * like some special sci in IBM x3330
  */
-void setup_IO_APIC_irq_extra(u32 gsi)
+void setup_IO_APIC_irq_extra(u32 gsi, unsigned int *pirq)
 {
 	int apic_id = 0, pin, idx, irq;
 	int node = cpu_to_node(boot_cpu_id);
@@ -1565,6 +1564,7 @@ void setup_IO_APIC_irq_extra(u32 gsi)
 		return;
 
 	irq = pin_2_irq(idx, apic_id, pin);
+	*pirq = irq;
 #ifdef CONFIG_SPARSE_IRQ
 	desc = irq_to_desc(irq);
 	if (desc)
@@ -1940,11 +1940,10 @@ __apicdebuginit(int) print_ICs(void)
 
 fs_initcall(print_ICs);
 
-
 /* Where if anywhere is the i8259 connect in external int mode */
 static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
 
-void __init enable_IO_APIC(void)
+static void __init probe_ioapic_i8259(void)
 {
 	union IO_APIC_reg_01 reg_01;
 	int i8259_apic, i8259_pin;
@@ -2001,7 +2000,12 @@ void __init enable_IO_APIC(void)
 	{
 		printk(KERN_WARNING "ExtINT in hardware and MP table differ\n");
 	}
+}
 
+void __init enable_IO_APIC(void)
+{
+	if (!nr_legacy_irqs)
+		return;
 	/*
 	 * Do not trust the IO-APIC being empty at bootup
 	 */
@@ -3126,7 +3130,6 @@ out:
 
 void __init setup_IO_APIC(void)
 {
-
 	/*
 	 * calling enable_IO_APIC() is moved to setup_local_APIC for BP
 	 */
@@ -3139,7 +3142,15 @@ void __init setup_IO_APIC(void)
 	x86_init.mpparse.setup_ioapic_ids();
 
 	sync_Arb_IDs();
-	setup_IO_APIC_irqs();
+	probe_ioapic_i8259();
+	boot_ioapic_idx = ioapic_i8259.apic;
+#ifdef CONFIG_ACPI
+	if (!acpi_disabled && acpi_ioapic && boot_ioapic_idx < 0)
+		boot_ioapic_idx = mp_find_ioapic(0);
+#endif
+	if (boot_ioapic_idx < 0)
+		boot_ioapic_idx = 0;
+	setup_IO_APIC_irqs(boot_ioapic_idx);
 	init_IO_APIC_traps();
 	if (nr_legacy_irqs)
 		check_timer();

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: Other problem/regression with b9c61b70075c87a8612624736faf4a2de5b1ed30
  2010-02-23  9:07     ` Other problem/regression with b9c61b70075c87a8612624736faf4a2de5b1ed30 Yinghai Lu
  2010-02-23 18:40       ` Yinghai Lu
@ 2010-02-23 19:02       ` Gary Hade
  1 sibling, 0 replies; 34+ messages in thread
From: Gary Hade @ 2010-02-23 19:02 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Thomas Renninger, Gary Hade, Ingo Molnar, Thomas Gleixner,
	Iranna D Ankad, H. Peter Anvin, Eric W. Biederman, Suresh Siddha,
	len.brown, linux-kernel

On Tue, Feb 23, 2010 at 01:07:23AM -0800, Yinghai Lu wrote:
> Gary,
> 
> can you check this patch on your x3950?

Yinghai, Wouldn't it be better to have the person that
reported the problem (Iranna) do that?

Gary

-- 
Gary Hade
System x Enablement
IBM Linux Technology Center
503-578-4503  IBM T/L: 775-4503
garyhade@us.ibm.com
http://www.ibm.com/linux/ltc

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: Other problem/regression with b9c61b70075c87a8612624736faf4a2de5b1ed30
  2010-02-23 18:40       ` Yinghai Lu
@ 2010-02-23 20:17         ` Eric W. Biederman
  2010-02-26 19:30         ` [PATCH -v8 1/2] x86: fix out of order of gsi - have right boot_ioapic_idx Yinghai Lu
  2010-02-26 19:31         ` [PATCH -v8 2/2] x86: fix out of order of gsi -- add remap_ioapic_gsi_to_irq Yinghai Lu
  2 siblings, 0 replies; 34+ messages in thread
From: Eric W. Biederman @ 2010-02-23 20:17 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Thomas Renninger, Gary Hade, Ingo Molnar, Thomas Gleixner,
	Iranna D Ankad, H. Peter Anvin, Suresh Siddha, len.brown,
	linux-kernel

Yinghai Lu <yinghai@kernel.org> writes:

> On 02/23/2010 01:07 AM, Yinghai Lu wrote:
>> Gary,
>> 
>> can you check this patch on your x3950?
>
> Subject: [PATCH -v2] x86: fix out of order of gsi
>
> found IBM x3950 will have problem after
>
> |commit b9c61b70075c87a8612624736faf4a2de5b1ed30
> |
> |    x86/pci: update pirq_enable_irq() to setup io apic routing
>
> The problem is that with the patch, the machine freezes when
> console=ttyS0,... kernel serial parameter is passed.
> It seem to freeze at DVD initialization and the whole problem seem
> to be DVD/pata related, but somehow exposed through the serial
> parameter.
> Such apic problems can expose really weird behavior..
>
> <6>ACPI: IOAPIC (id[0x10] address[0xfecff000] gsi_base[0])
> <6>IOAPIC[0]: apic_id 16, version 0, address 0xfecff000, GSI 0-2
> <6>ACPI: IOAPIC (id[0x0f] address[0xfec00000] gsi_base[3])
> <6>IOAPIC[1]: apic_id 15, version 0, address 0xfec00000, GSI 3-38
> <6>ACPI: IOAPIC (id[0x0e] address[0xfec01000] gsi_base[39])
> <6>IOAPIC[2]: apic_id 14, version 0, address 0xfec01000, GSI 39-74
> <6>ACPI: INT_SRC_OVR (bus 0 bus_irq 1 global_irq 4 dfl dfl)
> <6>ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 5 dfl dfl)
> <6>ACPI: INT_SRC_OVR (bus 0 bus_irq 3 global_irq 6 dfl dfl)
> <6>ACPI: INT_SRC_OVR (bus 0 bus_irq 4 global_irq 7 dfl dfl)
> <6>ACPI: INT_SRC_OVR (bus 0 bus_irq 6 global_irq 9 dfl dfl)
> <6>ACPI: INT_SRC_OVR (bus 0 bus_irq 7 global_irq 10 dfl dfl)
> <6>ACPI: INT_SRC_OVR (bus 0 bus_irq 8 global_irq 11 low edge)
> <6>ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 12 dfl dfl)
> <6>ACPI: INT_SRC_OVR (bus 0 bus_irq 12 global_irq 15 dfl dfl)
> <6>ACPI: INT_SRC_OVR (bus 0 bus_irq 13 global_irq 16 dfl dfl)
> <6>ACPI: INT_SRC_OVR (bus 0 bus_irq 14 global_irq 17 low edge)
> <6>ACPI: INT_SRC_OVR (bus 0 bus_irq 15 global_irq 18 dfl dfl)
>
> it turns out that system have three io apic controller. but put boot ioapic
> routing in second one. and that gsi_base is not 0. it is using bunch of INT_SRC_OVR...
>
> recent changes
> 1. one set routing for first io apic controller
> 2. assume irq = gsi
> will break theat system.
>
> so try to remap those gsi, need to seperate boot_ioapic_id detection out of enable_IO_APIC
> and call them early.
> introduce boot_ioapic_id, and remap_ioapic_gsi...
>
> -v2: shift gsi with delta instead of gsi_base of boot_ioapic_idx
>
> Reported-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
> Bisected-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
> Cc: Thomas Renninger <trenn@suse.de>
> Cc: stable@kernel.org
> Signed-off-by: Yinghai Lu <yinghai@kernel.org>

> +int remap_ioapic_gsi(int ioapic, u32 gsi)
> +{
> +	int base_boot = mp_gsi_routing[boot_ioapic_idx].gsi_base;
> +	int base_x;
> +
> +	if (!base_boot)
> +		return gsi;
> +
> +	base_x = mp_gsi_routing[ioapic].gsi_base;
> +	if (base_x < base_boot) {
> +		int delta;
> +		delta = mp_gsi_routing[boot_ioapic_idx].gsi_end + 1;
> +		delta -= base_boot;
> +		gsi += delta;
> +	} else if (base_x == base_boot)
> +		gsi -= base_boot;
> +
> +	return gsi;
> +}

This looks like it is doing something very different from implementing a
one irq at a time override, and after the nasties remapping gsi have
caused in the past I find this function very scary.

Eric



^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH -v8 1/2] x86: fix out of order of gsi - have right boot_ioapic_idx
  2010-02-23 18:40       ` Yinghai Lu
  2010-02-23 20:17         ` Eric W. Biederman
@ 2010-02-26 19:30         ` Yinghai Lu
  2010-02-27 12:57           ` [tip:x86/apic] x86: Fix out of order gsi - have the " tip-bot for Yinghai Lu
  2010-02-26 19:31         ` [PATCH -v8 2/2] x86: fix out of order of gsi -- add remap_ioapic_gsi_to_irq Yinghai Lu
  2 siblings, 1 reply; 34+ messages in thread
From: Yinghai Lu @ 2010-02-26 19:30 UTC (permalink / raw)
  To: Thomas Renninger, Gary Hade, Ingo Molnar, Thomas Gleixner
  Cc: Iranna D Ankad, H. Peter Anvin, Eric W. Biederman, Suresh Siddha,
	len.brown, linux-kernel


found IBM x3950 will have problem after

|commit b9c61b70075c87a8612624736faf4a2de5b1ed30
|
|    x86/pci: update pirq_enable_irq() to setup io apic routing

The problem is that with the patch, the machine freezes when
console=ttyS0,... kernel serial parameter is passed.
It seem to freeze at DVD initialization and the whole problem seem
to be DVD/pata related, but somehow exposed through the serial
parameter.
Such apic problems can expose really weird behavior..

<6>ACPI: IOAPIC (id[0x10] address[0xfecff000] gsi_base[0])
<6>IOAPIC[0]: apic_id 16, version 0, address 0xfecff000, GSI 0-2
<6>ACPI: IOAPIC (id[0x0f] address[0xfec00000] gsi_base[3])
<6>IOAPIC[1]: apic_id 15, version 0, address 0xfec00000, GSI 3-38
<6>ACPI: IOAPIC (id[0x0e] address[0xfec01000] gsi_base[39])
<6>IOAPIC[2]: apic_id 14, version 0, address 0xfec01000, GSI 39-74
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 1 global_irq 4 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 5 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 3 global_irq 6 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 4 global_irq 7 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 6 global_irq 9 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 7 global_irq 10 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 8 global_irq 11 low edge)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 12 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 12 global_irq 15 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 13 global_irq 16 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 14 global_irq 17 low edge)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 15 global_irq 18 dfl dfl)

it turns out that system have three io apic controller. but put boot ioapic
routing in second one. and that gsi_base is not 0. it is using bunch of INT_SRC_OVR...

recent changes
1. one set routing for first io apic controller
2. assume irq = gsi
will break theat system.

so try to remap those gsi, need to seperate boot_ioapic_id detection out of enable_IO_APIC
and call them early.
introduce boot_ioapic_id, and remap_ioapic_gsi...

-v2: shift gsi with delta instead of gsi_base of boot_ioapic_idx
-v3: double check with find_isa_irq_apic(0, mp_INT) to get right boot_ioapic_idx
-v4: nr_legacy_irqs
-v5: add print out for boot_ioapic_idx, and also make it could be applied for current
     kernel and previous kernel
-v6: add bus_irq, in acpi_sci_ioapic_setup, so can get overwride for sci right mapping...
-v7: looks like pnpacpi get irq instead of gsi, so need to revert them back...
-v8: split to two patches
     this one only have right boot_ioapic_idx

Reported-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Bisected-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Tested-by: Gary Hade <garyhade@us.ibm.com>
Cc: Thomas Renninger <trenn@suse.de>
Cc: stable@kernel.org
Signed-off-by: Yinghai Lu <yinghai@kernel.org>

---
 arch/x86/include/asm/io_apic.h |    1 +
 arch/x86/kernel/apic/io_apic.c |   32 ++++++++++++++++++++------------
 2 files changed, 21 insertions(+), 12 deletions(-)

Index: linux-2.6/arch/x86/include/asm/io_apic.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/io_apic.h
+++ linux-2.6/arch/x86/include/asm/io_apic.h
@@ -113,6 +113,7 @@ struct IR_IO_APIC_route_entry {
  */
 extern int nr_ioapics;
 extern int nr_ioapic_registers[MAX_IO_APICS];
+extern int boot_ioapic_idx;
 
 #define MP_MAX_IOAPIC_PIN 127
 
Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/apic/io_apic.c
+++ linux-2.6/arch/x86/kernel/apic/io_apic.c
@@ -84,6 +84,7 @@ int nr_ioapic_registers[MAX_IO_APICS];
 /* I/O APIC entries */
 struct mpc_ioapic mp_ioapics[MAX_IO_APICS];
 int nr_ioapics;
+int boot_ioapic_idx;
 
 /* IO APIC gsi routing info */
 struct mp_ioapic_gsi  mp_gsi_routing[MAX_IO_APICS];
@@ -1467,9 +1468,9 @@ static struct {
 	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
 } mp_ioapic_routing[MAX_IO_APICS];
 
-static void __init setup_IO_APIC_irqs(void)
+static void __init setup_IO_APIC_irqs(int apic_id)
 {
-	int apic_id = 0, pin, idx, irq;
+	int pin, idx, irq;
 	int notcon = 0;
 	struct irq_desc *desc;
 	struct irq_cfg *cfg;
@@ -1477,14 +1478,6 @@ static void __init setup_IO_APIC_irqs(vo
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		apic_id = mp_find_ioapic(0);
-		if (apic_id < 0)
-			apic_id = 0;
-	}
-#endif
-
 	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
 		idx = find_irq_entry(apic_id, pin, mp_INT);
 		if (idx == -1) {
@@ -2002,6 +1995,21 @@ void __init enable_IO_APIC(void)
 	clear_IO_APIC();
 }
 
+static void __init probe_ioapic_i8259(void)
+{
+	/* probe boot ioapic idx */
+	boot_ioapic_idx = ioapic_i8259.apic;
+	if (boot_ioapic_idx < 0)
+		boot_ioapic_idx = find_isa_irq_apic(0, mp_INT);
+#ifdef CONFIG_ACPI
+	if (!acpi_disabled && acpi_ioapic && boot_ioapic_idx < 0)
+		boot_ioapic_idx = mp_find_ioapic(0);
+#endif
+	if (boot_ioapic_idx < 0)
+		boot_ioapic_idx = 0;
+	printk(KERN_INFO "boot_ioapic_idx: %d\n", boot_ioapic_idx);
+}
+
 /*
  * Not an __init, needed by the reboot code
  */
@@ -3120,7 +3128,6 @@ out:
 
 void __init setup_IO_APIC(void)
 {
-
 	/*
 	 * calling enable_IO_APIC() is moved to setup_local_APIC for BP
 	 */
@@ -3133,7 +3140,8 @@ void __init setup_IO_APIC(void)
 	x86_init.mpparse.setup_ioapic_ids();
 
 	sync_Arb_IDs();
-	setup_IO_APIC_irqs();
+	probe_ioapic_i8259();
+	setup_IO_APIC_irqs(boot_ioapic_idx);
 	init_IO_APIC_traps();
 	if (legacy_pic->nr_legacy_irqs)
 		check_timer();

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH -v8 2/2] x86: fix out of order of gsi -- add remap_ioapic_gsi_to_irq
  2010-02-23 18:40       ` Yinghai Lu
  2010-02-23 20:17         ` Eric W. Biederman
  2010-02-26 19:30         ` [PATCH -v8 1/2] x86: fix out of order of gsi - have right boot_ioapic_idx Yinghai Lu
@ 2010-02-26 19:31         ` Yinghai Lu
  2010-02-27 12:57           ` [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq() tip-bot for Yinghai Lu
  2 siblings, 1 reply; 34+ messages in thread
From: Yinghai Lu @ 2010-02-26 19:31 UTC (permalink / raw)
  To: Thomas Renninger, Gary Hade, Ingo Molnar, Thomas Gleixner
  Cc: Iranna D Ankad, H. Peter Anvin, Eric W. Biederman, Suresh Siddha,
	len.brown, linux-kernel


found IBM x3950 will have problem after

|commit b9c61b70075c87a8612624736faf4a2de5b1ed30
|
|    x86/pci: update pirq_enable_irq() to setup io apic routing

The problem is that with the patch, the machine freezes when
console=ttyS0,... kernel serial parameter is passed.
It seem to freeze at DVD initialization and the whole problem seem
to be DVD/pata related, but somehow exposed through the serial
parameter.
Such apic problems can expose really weird behavior..

<6>ACPI: IOAPIC (id[0x10] address[0xfecff000] gsi_base[0])
<6>IOAPIC[0]: apic_id 16, version 0, address 0xfecff000, GSI 0-2
<6>ACPI: IOAPIC (id[0x0f] address[0xfec00000] gsi_base[3])
<6>IOAPIC[1]: apic_id 15, version 0, address 0xfec00000, GSI 3-38
<6>ACPI: IOAPIC (id[0x0e] address[0xfec01000] gsi_base[39])
<6>IOAPIC[2]: apic_id 14, version 0, address 0xfec01000, GSI 39-74
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 1 global_irq 4 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 5 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 3 global_irq 6 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 4 global_irq 7 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 6 global_irq 9 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 7 global_irq 10 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 8 global_irq 11 low edge)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 12 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 12 global_irq 15 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 13 global_irq 16 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 14 global_irq 17 low edge)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 15 global_irq 18 dfl dfl)

it turns out that system have three io apic controller. but put boot ioapic
routing in second one. and that gsi_base is not 0. it is using bunch of INT_SRC_OVR...

recent changes
1. one set routing for first io apic controller
2. assume irq = gsi
will break theat system.

so try to remap those gsi, need to seperate boot_ioapic_id detection out of enable_IO_APIC
and call them early.
introduce boot_ioapic_id, and remap_ioapic_gsi...

-v2: shift gsi with delta instead of gsi_base of boot_ioapic_idx
-v3: double check with find_isa_irq_apic(0, mp_INT) to get right boot_ioapic_idx
-v4: nr_legacy_irqs
-v5: add print out for boot_ioapic_idx, and also make it could be applied for current
     kernel and previous kernel
-v6: add bus_irq, in acpi_sci_ioapic_setup, so can get overwride for sci right mapping...
-v7: looks like pnpacpi get irq instead of gsi, so need to revert them back...
-v8: seperate into two patches
     this one will use remap_ioapic_gsi_to_irq, so still can use gsi pin.
     otherwise assume irq == gsi, make overwrite entris in second ioapic will block
     the accessing to the entries in first ioapic

Reported-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Bisected-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Tested-by: Gary Hade <garyhade@us.ibm.com>
Cc: Thomas Renninger <trenn@suse.de>
Cc: stable@kernel.org
Signed-off-by: Yinghai Lu <yinghai@kernel.org>

---
 arch/x86/include/asm/io_apic.h |    2 -
 arch/x86/include/asm/mpspec.h  |    2 +
 arch/x86/kernel/acpi/boot.c    |   63 +++++++++++++++++++++++++++++++++++------
 arch/x86/kernel/apic/io_apic.c |   22 +++++++++-----
 drivers/pnp/pnpacpi/rsparser.c |    8 +++++
 5 files changed, 80 insertions(+), 17 deletions(-)

Index: linux-2.6/arch/x86/include/asm/io_apic.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/io_apic.h
+++ linux-2.6/arch/x86/include/asm/io_apic.h
@@ -159,7 +159,7 @@ extern int io_apic_get_redir_entries(int
 struct io_apic_irq_attr;
 extern int io_apic_set_pci_routing(struct device *dev, int irq,
 		 struct io_apic_irq_attr *irq_attr);
-void setup_IO_APIC_irq_extra(u32 gsi);
+void setup_IO_APIC_irq_extra(u32 gsi, unsigned int *irq);
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
 extern void ioapic_init_mappings(void);
 extern void ioapic_insert_resources(void);
Index: linux-2.6/arch/x86/include/asm/mpspec.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/mpspec.h
+++ linux-2.6/arch/x86/include/asm/mpspec.h
@@ -105,6 +105,8 @@ extern void mp_config_acpi_legacy_irqs(v
 struct device;
 extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level,
 				 int active_high_low);
+int remap_ioapic_gsi_to_irq(int ioapic, u32 gsi);
+int remap_ioapic_irq_to_gsi(int irq);
 extern int acpi_probe_gsi(void);
 #ifdef CONFIG_X86_IO_APIC
 extern int mp_find_ioapic(int gsi);
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/acpi/boot.c
+++ linux-2.6/arch/x86/kernel/acpi/boot.c
@@ -311,7 +311,8 @@ acpi_parse_ioapic(struct acpi_subtable_h
 /*
  * Parse Interrupt Source Override for the ACPI SCI
  */
-static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
+static void __init
+acpi_sci_ioapic_setup(u8 bus_irq, u32 gsi, u16 polarity, u16 trigger)
 {
 	if (trigger == 0)	/* compatible SCI trigger is level */
 		trigger = 3;
@@ -331,7 +332,7 @@ static void __init acpi_sci_ioapic_setup
 	 * If GSI is < 16, this will update its flags,
 	 * else it will create a new mp_irqs[] entry.
 	 */
-	mp_override_legacy_irq(gsi, polarity, trigger, gsi);
+	mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
 
 	/*
 	 * stash over-ride to indicate we've been here
@@ -355,7 +356,8 @@ acpi_parse_int_src_ovr(struct acpi_subta
 	acpi_table_print_madt_entry(header);
 
 	if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) {
-		acpi_sci_ioapic_setup(intsrc->global_irq,
+		acpi_sci_ioapic_setup(intsrc->source_irq,
+				      intsrc->global_irq,
 				      intsrc->inti_flags & ACPI_MADT_POLARITY_MASK,
 				      (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2);
 		return 0;
@@ -450,7 +452,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned in
 
 #ifdef CONFIG_X86_IO_APIC
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
-		setup_IO_APIC_irq_extra(gsi);
+		setup_IO_APIC_irq_extra(gsi, irq);
 #endif
 
 	return 0;
@@ -1053,11 +1055,54 @@ static int mp_config_acpi_gsi(struct dev
 	return 0;
 }
 
+int remap_ioapic_gsi_to_irq(int ioapic, u32 gsi)
+{
+	int irq = gsi;
+	int base_boot = mp_gsi_routing[boot_ioapic_idx].gsi_base;
+	int base_x;
+
+	if (!base_boot)
+		return irq;
+
+	base_x = mp_gsi_routing[ioapic].gsi_base;
+	if (base_x < base_boot) {
+		int delta;
+		delta = mp_gsi_routing[boot_ioapic_idx].gsi_end + 1;
+		delta -= base_boot;
+		irq = gsi + delta;
+	} else if (base_x == base_boot)
+		irq = gsi - base_boot;
+
+	return irq;
+}
+
+int remap_ioapic_irq_to_gsi(int irq)
+{
+	int gsi = irq;
+	int base_boot = mp_gsi_routing[boot_ioapic_idx].gsi_base;
+	int end_boot;
+	int delta;
+
+	if (!base_boot)
+		return gsi;
+
+	end_boot = mp_gsi_routing[boot_ioapic_idx].gsi_end + 1;
+	delta = end_boot - base_boot;
+
+	if (irq < delta)
+		gsi = irq + base_boot;
+	else if (irq < end_boot)
+		gsi = irq + delta;
+
+	return gsi;
+}
+
 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;
+	u32 irq;
 
 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
 		return gsi;
@@ -1078,12 +1123,13 @@ int mp_register_gsi(struct device *dev,
 	if (ioapic_renumber_irq)
 		gsi = ioapic_renumber_irq(ioapic, gsi);
 #endif
+	irq = remap_ioapic_gsi_to_irq(ioapic, gsi);
 
 	if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
 		printk(KERN_ERR "Invalid reference to IOAPIC pin "
 		       "%d-%d\n", mp_ioapics[ioapic].apicid,
 		       ioapic_pin);
-		return gsi;
+		return irq;
 	}
 
 	if (enable_update_mptable)
@@ -1092,9 +1138,9 @@ int mp_register_gsi(struct device *dev,
 	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);
+	io_apic_set_pci_routing(dev, irq, &irq_attr);
 
-	return gsi;
+	return irq;
 }
 
 /*
@@ -1152,7 +1198,8 @@ static int __init acpi_parse_madt_ioapic
 	 * pretend we got one so we can set the SCI flags.
 	 */
 	if (!acpi_sci_override_gsi)
-		acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0);
+		acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt,
+					 acpi_gbl_FADT.sci_interrupt, 0, 0);
 
 	/* Fill in identity legacy mappings where no override */
 	mp_config_acpi_legacy_irqs();
Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/apic/io_apic.c
+++ linux-2.6/arch/x86/kernel/apic/io_apic.c
@@ -1023,13 +1023,18 @@ static int pin_2_irq(int idx, int apic,
 	if (test_bit(bus, mp_bus_not_pci)) {
 		irq = mp_irqs[idx].srcbusirq;
 	} else {
-		/*
-		 * PCI IRQs are mapped in order
-		 */
-		i = irq = 0;
-		while (i < apic)
-			irq += nr_ioapic_registers[i++];
-		irq += pin;
+		if (!acpi_ioapic) {
+			/*
+			 * PCI IRQs are mapped in order
+			 */
+			i = irq = 0;
+			while (i < apic)
+				irq += nr_ioapic_registers[i++];
+			irq += pin;
+		} else {
+			irq = pin + mp_gsi_routing[apic].gsi_base;
+			irq = remap_ioapic_gsi_to_irq(apic, irq);
+		}
 		/*
                  * For MPS mode, so far only needed by ES7000 platform
                  */
@@ -1532,7 +1537,7 @@ static void __init setup_IO_APIC_irqs(in
  * but could not use acpi_register_gsi()
  * like some special sci in IBM x3330
  */
-void setup_IO_APIC_irq_extra(u32 gsi)
+void setup_IO_APIC_irq_extra(u32 gsi, unsigned int *pirq)
 {
 	int apic_id = 0, pin, idx, irq;
 	int node = cpu_to_node(boot_cpu_id);
@@ -1552,6 +1557,7 @@ void setup_IO_APIC_irq_extra(u32 gsi)
 		return;
 
 	irq = pin_2_irq(idx, apic_id, pin);
+	*pirq = irq;
 #ifdef CONFIG_SPARSE_IRQ
 	desc = irq_to_desc(irq);
 	if (desc)
Index: linux-2.6/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- linux-2.6.orig/drivers/pnp/pnpacpi/rsparser.c
+++ linux-2.6/drivers/pnp/pnpacpi/rsparser.c
@@ -123,6 +123,14 @@ static void pnpacpi_parse_allocated_irqr
 	}
 
 	flags = irq_flags(triggering, polarity, shareable);
+#ifdef CONFIG_X86_IO_APIC
+	/*
+	 * looks like IBM x3950 is using irq instead of gsi etc...
+	 * convert it back at first
+	 */
+	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
+		gsi = remap_ioapic_irq_to_gsi(gsi);
+#endif
 	irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
 	if (irq >= 0)
 		pcibios_penalize_isa_irq(irq, 1);

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [tip:x86/apic] x86: Fix out of order gsi - have the right boot_ioapic_idx
  2010-02-26 19:30         ` [PATCH -v8 1/2] x86: fix out of order of gsi - have right boot_ioapic_idx Yinghai Lu
@ 2010-02-27 12:57           ` tip-bot for Yinghai Lu
  0 siblings, 0 replies; 34+ messages in thread
From: tip-bot for Yinghai Lu @ 2010-02-27 12:57 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, hpa, mingo, yinghai, ebiederm, garyhade,
	iranna.ankad, suresh.b.siddha, tglx, trenn, mingo

Commit-ID:  ca8c764cb39bf6cade71933b38e8c830eb8b73c6
Gitweb:     http://git.kernel.org/tip/ca8c764cb39bf6cade71933b38e8c830eb8b73c6
Author:     Yinghai Lu <yinghai@kernel.org>
AuthorDate: Fri, 26 Feb 2010 11:30:30 -0800
Committer:  Ingo Molnar <mingo@elte.hu>
CommitDate: Sat, 27 Feb 2010 12:54:16 +0100

x86: Fix out of order gsi - have the right boot_ioapic_idx

Iranna D Ankad reported that IBM x3950 systems have boot problems
after this commit:

 |
 | commit b9c61b70075c87a8612624736faf4a2de5b1ed30
 |
 |    x86/pci: update pirq_enable_irq() to setup io apic routing
 |

The problem is that with the patch, the machine freezes when
console=ttyS0,... kernel serial parameter is passed.

It seem to freeze at DVD initialization and the whole problem
seem to be DVD/pata related, but somehow exposed through the
serial parameter.

Such apic problems can expose really weird behavior:

  ACPI: IOAPIC (id[0x10] address[0xfecff000] gsi_base[0])
  IOAPIC[0]: apic_id 16, version 0, address 0xfecff000, GSI 0-2
  ACPI: IOAPIC (id[0x0f] address[0xfec00000] gsi_base[3])
  IOAPIC[1]: apic_id 15, version 0, address 0xfec00000, GSI 3-38
  ACPI: IOAPIC (id[0x0e] address[0xfec01000] gsi_base[39])
  IOAPIC[2]: apic_id 14, version 0, address 0xfec01000, GSI 39-74
  ACPI: INT_SRC_OVR (bus 0 bus_irq 1 global_irq 4 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 5 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 3 global_irq 6 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 4 global_irq 7 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 6 global_irq 9 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 7 global_irq 10 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 8 global_irq 11 low edge)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 12 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 12 global_irq 15 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 13 global_irq 16 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 14 global_irq 17 low edge)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 15 global_irq 18 dfl dfl)

It turns out that the system has three io apic controllers, but
boot ioapic routing is in the second one, and that gsi_base is
not 0 - it is using a bunch of INT_SRC_OVR...

So these recent changes:

 1. one set routing for first io apic controller
 2. assume irq = gsi

... will break that system.

So try to remap those gsis, need to seperate boot_ioapic_idx
detection out of enable_IO_APIC() and call them early.

So introduce boot_ioapic_idx, and remap_ioapic_gsi()...

This patch introduces boot_ioapic_idx.

 -v2: shift gsi with delta instead of gsi_base of boot_ioapic_idx

 -v3: double check with find_isa_irq_apic(0, mp_INT) to get right
      boot_ioapic_idx

 -v4: nr_legacy_irqs

 -v5: add print out for boot_ioapic_idx, and also make it could be
      applied for current kernel and previous kernel

 -v6: add bus_irq, in acpi_sci_ioapic_setup, so can get overwride
      for sci right mapping...

 -v7: looks like pnpacpi get irq instead of gsi, so need to revert
      them back...

 -v8: split into two patches this one only have right boot_ioapic_idx

Reported-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Bisected-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Tested-by: Gary Hade <garyhade@us.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Thomas Renninger <trenn@suse.de>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: len.brown@intel.com
Cc: <stable@kernel.org> # .33.x
LKML-Reference: <4B882156.10507@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/x86/include/asm/io_apic.h |    1 +
 arch/x86/kernel/apic/io_apic.c |   32 ++++++++++++++++++++------------
 2 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 5f61f6e..b16c075 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -113,6 +113,7 @@ struct IR_IO_APIC_route_entry {
  */
 extern int nr_ioapics;
 extern int nr_ioapic_registers[MAX_IO_APICS];
+extern int boot_ioapic_idx;
 
 #define MP_MAX_IOAPIC_PIN 127
 
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 72ac2a3..53533a0 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -84,6 +84,7 @@ int nr_ioapic_registers[MAX_IO_APICS];
 /* I/O APIC entries */
 struct mpc_ioapic mp_ioapics[MAX_IO_APICS];
 int nr_ioapics;
+int boot_ioapic_idx;
 
 /* IO APIC gsi routing info */
 struct mp_ioapic_gsi  mp_gsi_routing[MAX_IO_APICS];
@@ -1473,9 +1474,9 @@ static struct {
 	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
 } mp_ioapic_routing[MAX_IO_APICS];
 
-static void __init setup_IO_APIC_irqs(void)
+static void __init setup_IO_APIC_irqs(int apic_id)
 {
-	int apic_id = 0, pin, idx, irq;
+	int pin, idx, irq;
 	int notcon = 0;
 	struct irq_desc *desc;
 	struct irq_cfg *cfg;
@@ -1483,14 +1484,6 @@ static void __init setup_IO_APIC_irqs(void)
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		apic_id = mp_find_ioapic(0);
-		if (apic_id < 0)
-			apic_id = 0;
-	}
-#endif
-
 	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
 		idx = find_irq_entry(apic_id, pin, mp_INT);
 		if (idx == -1) {
@@ -2008,6 +2001,21 @@ void __init enable_IO_APIC(void)
 	clear_IO_APIC();
 }
 
+static void __init probe_ioapic_i8259(void)
+{
+	/* probe boot ioapic idx */
+	boot_ioapic_idx = ioapic_i8259.apic;
+	if (boot_ioapic_idx < 0)
+		boot_ioapic_idx = find_isa_irq_apic(0, mp_INT);
+#ifdef CONFIG_ACPI
+	if (!acpi_disabled && acpi_ioapic && boot_ioapic_idx < 0)
+		boot_ioapic_idx = mp_find_ioapic(0);
+#endif
+	if (boot_ioapic_idx < 0)
+		boot_ioapic_idx = 0;
+	printk(KERN_INFO "boot_ioapic_idx: %d\n", boot_ioapic_idx);
+}
+
 /*
  * Not an __init, needed by the reboot code
  */
@@ -3126,7 +3134,6 @@ out:
 
 void __init setup_IO_APIC(void)
 {
-
 	/*
 	 * calling enable_IO_APIC() is moved to setup_local_APIC for BP
 	 */
@@ -3139,7 +3146,8 @@ void __init setup_IO_APIC(void)
 	x86_init.mpparse.setup_ioapic_ids();
 
 	sync_Arb_IDs();
-	setup_IO_APIC_irqs();
+	probe_ioapic_i8259();
+	setup_IO_APIC_irqs(boot_ioapic_idx);
 	init_IO_APIC_traps();
 	if (nr_legacy_irqs)
 		check_timer();

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
  2010-02-26 19:31         ` [PATCH -v8 2/2] x86: fix out of order of gsi -- add remap_ioapic_gsi_to_irq Yinghai Lu
@ 2010-02-27 12:57           ` tip-bot for Yinghai Lu
  2010-02-27 13:01             ` Ingo Molnar
  0 siblings, 1 reply; 34+ messages in thread
From: tip-bot for Yinghai Lu @ 2010-02-27 12:57 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, hpa, mingo, yinghai, ebiederm, garyhade,
	iranna.ankad, suresh.b.siddha, tglx, trenn, mingo

Commit-ID:  519d637a93116ffbcd50e9e3f2591f41584f372c
Gitweb:     http://git.kernel.org/tip/519d637a93116ffbcd50e9e3f2591f41584f372c
Author:     Yinghai Lu <yinghai@kernel.org>
AuthorDate: Fri, 26 Feb 2010 11:31:14 -0800
Committer:  Ingo Molnar <mingo@elte.hu>
CommitDate: Sat, 27 Feb 2010 12:54:17 +0100

x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()

Iranna D Ankad found (and bisected) that IBM x3950 will have
boot problems after:

 |
 | commit b9c61b70075c87a8612624736faf4a2de5b1ed30
 |
 |    x86/pci: update pirq_enable_irq() to setup io apic routing
 |

As explained in the previous patch ("x86: Fix out of order gsi - have
the right boot_ioapic_idx"), try to remap those gsis, we need to
seperate boot_ioapic_id detection out of enable_IO_APIC and call
them early.

This patch adds remap_ioapic_gsi() and fixes the regression.

Reported-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Bisected-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Tested-by: Gary Hade <garyhade@us.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Thomas Renninger <trenn@suse.de>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: len.brown@intel.com
Cc: <stable@kernel.org> # .33.x
LKML-Reference: <4B882182.4030205@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/x86/include/asm/io_apic.h |    2 +-
 arch/x86/include/asm/mpspec.h  |    2 +
 arch/x86/kernel/acpi/boot.c    |   63 ++++++++++++++++++++++++++++++++++-----
 arch/x86/kernel/apic/io_apic.c |   22 +++++++++-----
 drivers/pnp/pnpacpi/rsparser.c |    8 +++++
 5 files changed, 80 insertions(+), 17 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index b16c075..98458c7 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -161,7 +161,7 @@ extern int io_apic_get_redir_entries(int ioapic);
 struct io_apic_irq_attr;
 extern int io_apic_set_pci_routing(struct device *dev, int irq,
 		 struct io_apic_irq_attr *irq_attr);
-void setup_IO_APIC_irq_extra(u32 gsi);
+void setup_IO_APIC_irq_extra(u32 gsi, unsigned int *irq);
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
 extern void ioapic_init_mappings(void);
 extern void ioapic_insert_resources(void);
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
index d8bf23a..3642461 100644
--- a/arch/x86/include/asm/mpspec.h
+++ b/arch/x86/include/asm/mpspec.h
@@ -105,6 +105,8 @@ extern void mp_config_acpi_legacy_irqs(void);
 struct device;
 extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level,
 				 int active_high_low);
+int remap_ioapic_gsi_to_irq(int ioapic, u32 gsi);
+int remap_ioapic_irq_to_gsi(int irq);
 extern int acpi_probe_gsi(void);
 #ifdef CONFIG_X86_IO_APIC
 extern int mp_find_ioapic(int gsi);
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 5c96b75..70c4057 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -310,7 +310,8 @@ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
 /*
  * Parse Interrupt Source Override for the ACPI SCI
  */
-static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
+static void __init
+acpi_sci_ioapic_setup(u8 bus_irq, u32 gsi, u16 polarity, u16 trigger)
 {
 	if (trigger == 0)	/* compatible SCI trigger is level */
 		trigger = 3;
@@ -330,7 +331,7 @@ static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
 	 * If GSI is < 16, this will update its flags,
 	 * else it will create a new mp_irqs[] entry.
 	 */
-	mp_override_legacy_irq(gsi, polarity, trigger, gsi);
+	mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
 
 	/*
 	 * stash over-ride to indicate we've been here
@@ -354,7 +355,8 @@ acpi_parse_int_src_ovr(struct acpi_subtable_header * header,
 	acpi_table_print_madt_entry(header);
 
 	if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) {
-		acpi_sci_ioapic_setup(intsrc->global_irq,
+		acpi_sci_ioapic_setup(intsrc->source_irq,
+				      intsrc->global_irq,
 				      intsrc->inti_flags & ACPI_MADT_POLARITY_MASK,
 				      (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2);
 		return 0;
@@ -449,7 +451,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 
 #ifdef CONFIG_X86_IO_APIC
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
-		setup_IO_APIC_irq_extra(gsi);
+		setup_IO_APIC_irq_extra(gsi, irq);
 #endif
 
 	return 0;
@@ -1029,11 +1031,54 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
 	return 0;
 }
 
+int remap_ioapic_gsi_to_irq(int ioapic, u32 gsi)
+{
+	int irq = gsi;
+	int base_boot = mp_gsi_routing[boot_ioapic_idx].gsi_base;
+	int base_x;
+
+	if (!base_boot)
+		return irq;
+
+	base_x = mp_gsi_routing[ioapic].gsi_base;
+	if (base_x < base_boot) {
+		int delta;
+		delta = mp_gsi_routing[boot_ioapic_idx].gsi_end + 1;
+		delta -= base_boot;
+		irq = gsi + delta;
+	} else if (base_x == base_boot)
+		irq = gsi - base_boot;
+
+	return irq;
+}
+
+int remap_ioapic_irq_to_gsi(int irq)
+{
+	int gsi = irq;
+	int base_boot = mp_gsi_routing[boot_ioapic_idx].gsi_base;
+	int end_boot;
+	int delta;
+
+	if (!base_boot)
+		return gsi;
+
+	end_boot = mp_gsi_routing[boot_ioapic_idx].gsi_end + 1;
+	delta = end_boot - base_boot;
+
+	if (irq < delta)
+		gsi = irq + base_boot;
+	else if (irq < end_boot)
+		gsi = irq + delta;
+
+	return gsi;
+}
+
 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;
+	u32 irq;
 
 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
 		return gsi;
@@ -1054,12 +1099,13 @@ int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
 	if (ioapic_renumber_irq)
 		gsi = ioapic_renumber_irq(ioapic, gsi);
 #endif
+	irq = remap_ioapic_gsi_to_irq(ioapic, gsi);
 
 	if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
 		printk(KERN_ERR "Invalid reference to IOAPIC pin "
 		       "%d-%d\n", mp_ioapics[ioapic].apicid,
 		       ioapic_pin);
-		return gsi;
+		return irq;
 	}
 
 	if (enable_update_mptable)
@@ -1068,9 +1114,9 @@ int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
 	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);
+	io_apic_set_pci_routing(dev, irq, &irq_attr);
 
-	return gsi;
+	return irq;
 }
 
 /*
@@ -1128,7 +1174,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
 	 * pretend we got one so we can set the SCI flags.
 	 */
 	if (!acpi_sci_override_gsi)
-		acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0);
+		acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt,
+					 acpi_gbl_FADT.sci_interrupt, 0, 0);
 
 	/* Fill in identity legacy mappings where no override */
 	mp_config_acpi_legacy_irqs();
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 53533a0..13c7975 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -1029,13 +1029,18 @@ static int pin_2_irq(int idx, int apic, int pin)
 	if (test_bit(bus, mp_bus_not_pci)) {
 		irq = mp_irqs[idx].srcbusirq;
 	} else {
-		/*
-		 * PCI IRQs are mapped in order
-		 */
-		i = irq = 0;
-		while (i < apic)
-			irq += nr_ioapic_registers[i++];
-		irq += pin;
+		if (!acpi_ioapic) {
+			/*
+			 * PCI IRQs are mapped in order
+			 */
+			i = irq = 0;
+			while (i < apic)
+				irq += nr_ioapic_registers[i++];
+			irq += pin;
+		} else {
+			irq = pin + mp_gsi_routing[apic].gsi_base;
+			irq = remap_ioapic_gsi_to_irq(apic, irq);
+		}
 		/*
                  * For MPS mode, so far only needed by ES7000 platform
                  */
@@ -1538,7 +1543,7 @@ static void __init setup_IO_APIC_irqs(int apic_id)
  * but could not use acpi_register_gsi()
  * like some special sci in IBM x3330
  */
-void setup_IO_APIC_irq_extra(u32 gsi)
+void setup_IO_APIC_irq_extra(u32 gsi, unsigned int *pirq)
 {
 	int apic_id = 0, pin, idx, irq;
 	int node = cpu_to_node(boot_cpu_id);
@@ -1558,6 +1563,7 @@ void setup_IO_APIC_irq_extra(u32 gsi)
 		return;
 
 	irq = pin_2_irq(idx, apic_id, pin);
+	*pirq = irq;
 #ifdef CONFIG_SPARSE_IRQ
 	desc = irq_to_desc(irq);
 	if (desc)
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 5702b2c..a596888 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -123,6 +123,14 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
 	}
 
 	flags = irq_flags(triggering, polarity, shareable);
+#ifdef CONFIG_X86_IO_APIC
+	/*
+	 * looks like IBM x3950 is using irq instead of gsi etc...
+	 * convert it back at first
+	 */
+	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
+		gsi = remap_ioapic_irq_to_gsi(gsi);
+#endif
 	irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
 	if (irq >= 0)
 		pcibios_penalize_isa_irq(irq, 1);

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* Re: [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
  2010-02-27 12:57           ` [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq() tip-bot for Yinghai Lu
@ 2010-02-27 13:01             ` Ingo Molnar
  2010-02-27 18:52               ` Yinghai Lu
  2010-02-27 19:04               ` Eric W. Biederman
  0 siblings, 2 replies; 34+ messages in thread
From: Ingo Molnar @ 2010-02-27 13:01 UTC (permalink / raw)
  To: tip-bot for Yinghai Lu
  Cc: linux-tip-commits, linux-kernel, hpa, mingo, ebiederm, garyhade,
	iranna.ankad, suresh.b.siddha, tglx, trenn


Causes:

 arch/x86/kernel/apic/io_apic.c:1042: error: implicit declaration of function ?remap_ioapic_gsi_to_irq?

Please send delta fix.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
  2010-02-27 13:01             ` Ingo Molnar
@ 2010-02-27 18:52               ` Yinghai Lu
  2010-02-27 22:57                 ` H. Peter Anvin
  2010-02-27 19:04               ` Eric W. Biederman
  1 sibling, 1 reply; 34+ messages in thread
From: Yinghai Lu @ 2010-02-27 18:52 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-tip-commits, linux-kernel, hpa, mingo, ebiederm, garyhade,
	iranna.ankad, suresh.b.siddha, tglx, trenn

On 02/27/2010 05:01 AM, Ingo Molnar wrote:
>  arch/x86/kernel/apic/io_apic.c:1042: error: implicit declaration of function ?remap_ioapic_gsi_to_irq?
> 
please check

[PATCH] x86: fix warning with remap_ioapic_gsi_to_irq when !CONFIG_ACPI

Ingo found:
| x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
cause:
 arch/x86/kernel/apic/io_apic.c:1042: error: implicit declaration of function ?remap_ioapic_gsi_to_irq?

actually when !CONFIG_ACPI, we have
#define acpi_ioapic 0

somehow we still get warning for
#if (!0) {
	...
} else {
	...
	remap_ioapic_gsi_to_irq...
}

gcc bug?

Signed-off-by: Yinghai Lu <yinghai@kernel.org>

---
 arch/x86/include/asm/mpspec.h |    8 ++++++++
 1 file changed, 8 insertions(+)

Index: linux-2.6/arch/x86/include/asm/mpspec.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/mpspec.h
+++ linux-2.6/arch/x86/include/asm/mpspec.h
@@ -116,6 +116,14 @@ static inline int acpi_probe_gsi(void)
 {
 	return 0;
 }
+static inline int remap_ioapic_gsi_to_irq(int ioapic, u32 gsi)
+{
+	return gsi;
+}
+static inline int remap_ioapic_irq_to_gsi(int irq)
+{
+	return irq;
+}
 #endif /* CONFIG_ACPI */
 
 #define PHYSID_ARRAY_SIZE	BITS_TO_LONGS(MAX_APICS)

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
  2010-02-27 13:01             ` Ingo Molnar
  2010-02-27 18:52               ` Yinghai Lu
@ 2010-02-27 19:04               ` Eric W. Biederman
  2010-02-27 19:40                 ` Yinghai Lu
  1 sibling, 1 reply; 34+ messages in thread
From: Eric W. Biederman @ 2010-02-27 19:04 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: tip-bot for Yinghai Lu, linux-tip-commits, linux-kernel, hpa,
	mingo, garyhade, iranna.ankad, suresh.b.siddha, tglx, trenn

Ingo Molnar <mingo@elte.hu> writes:

> Causes:
>
>  arch/x86/kernel/apic/io_apic.c:1042: error: implicit declaration of function ?remap_ioapic_gsi_to_irq?
>
> Please send delta fix.

I am certain I have said this before but the entire concept of 
irq != gsi is broken.  We used to have code that did this and it was a
non-ending source of problems that we finally removed after we pushed
up the limit on the number of irqs.

We already have the irq_2_pin list which allows for arbitrary mappings
between irqs and the ioapics and pins.  So there should be no problem
mapping irq to gsi and assigning irqs to arbitrary ioapic pins.

I have yet to see something that even purports to be an explanation
of why our handling of acpi int_src_overrides is broken and why
it needs the mess that is a remapper.

I don't doubt YHs changes fix something but this feels like a direction
that trades off one bug for another instead of actually fixing the code.

It does look like we have weird old hard codes in some of the
irq_2_pin and pin_2_irq paths that YH is touching, and it may make sense
to introduce a concept of ioapic pin index.  

The touching of drivers/pnp/pnpacpi/rsparser.c feels like just the tip of
the iceberg in dealing with weird bugs if we continue down this path.

Eric

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
  2010-02-27 19:04               ` Eric W. Biederman
@ 2010-02-27 19:40                 ` Yinghai Lu
  2010-02-27 21:30                   ` Eric W. Biederman
  0 siblings, 1 reply; 34+ messages in thread
From: Yinghai Lu @ 2010-02-27 19:40 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Ingo Molnar, linux-tip-commits, linux-kernel, hpa, mingo,
	garyhade, iranna.ankad, suresh.b.siddha, tglx, trenn

On 02/27/2010 11:04 AM, Eric W. Biederman wrote:
> Ingo Molnar <mingo@elte.hu> writes:
> 
>> Causes:
>>
>>  arch/x86/kernel/apic/io_apic.c:1042: error: implicit declaration of function ?remap_ioapic_gsi_to_irq?
>>
>> Please send delta fix.
> 
> I am certain I have said this before but the entire concept of 
> irq != gsi is broken.  We used to have code that did this and it was a
> non-ending source of problems that we finally removed after we pushed
> up the limit on the number of irqs.
> 
> We already have the irq_2_pin list which allows for arbitrary mappings
> between irqs and the ioapics and pins.  So there should be no problem
> mapping irq to gsi and assigning irqs to arbitrary ioapic pins.
> 
> I have yet to see something that even purports to be an explanation
> of why our handling of acpi int_src_overrides is broken and why
> it needs the mess that is a remapper.
> 
> I don't doubt YHs changes fix something but this feels like a direction
> that trades off one bug for another instead of actually fixing the code.
> 
> It does look like we have weird old hard codes in some of the
> irq_2_pin and pin_2_irq paths that YH is touching, and it may make sense
> to introduce a concept of ioapic pin index.  
> 
> The touching of drivers/pnp/pnpacpi/rsparser.c feels like just the tip of
> the iceberg in dealing with weird bugs if we continue down this path.
> 

the x3950 has strange gsi base 

ACPI: IOAPIC (id[0x10] address[0xfecff000] gsi_base[0])
IOAPIC[0]: apic_id 16, version 0, address 0xfecff000, GSI 0-2
ACPI: IOAPIC (id[0x0f] address[0xfec00000] gsi_base[3])
IOAPIC[1]: apic_id 15, version 0, address 0xfec00000, GSI 3-38
ACPI: IOAPIC (id[0x0e] address[0xfec01000] gsi_base[39])
IOAPIC[2]: apic_id 14, version 0, address 0xfec01000, GSI 39-74

and BIOS using INT_SRC_OVR to map back gsi  3 - 18 to irq 0 - 15
ACPI: INT_SRC_OVR (bus 0 bus_irq 1 global_irq 4 dfl dfl)
ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 5 dfl dfl)
ACPI: INT_SRC_OVR (bus 0 bus_irq 3 global_irq 6 dfl dfl)
ACPI: INT_SRC_OVR (bus 0 bus_irq 4 global_irq 7 dfl dfl)
ACPI: INT_SRC_OVR (bus 0 bus_irq 6 global_irq 9 dfl dfl)
ACPI: INT_SRC_OVR (bus 0 bus_irq 7 global_irq 10 dfl dfl)
ACPI: INT_SRC_OVR (bus 0 bus_irq 8 global_irq 11 low edge)
ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 12 dfl dfl)
ACPI: INT_SRC_OVR (bus 0 bus_irq 12 global_irq 15 dfl dfl)
ACPI: INT_SRC_OVR (bus 0 bus_irq 13 global_irq 16 dfl dfl)
ACPI: INT_SRC_OVR (bus 0 bus_irq 14 global_irq 17 low edge)
ACPI: INT_SRC_OVR (bus 0 bus_irq 15 global_irq 18 dfl dfl)
if we dont have this patch to do the remap (swap some mapping between ioapic), and only assume irq = gsi,

the irq from first ioapic controller will be blocked.

so far this patch only affect (fix ) x3950.

all other platform will all have boot_ioapic_idx's gsi_base == 0, 
the function will just still return gsi.

other solution will ask IBM to fix their bios, so we can get

ACPI: IOAPIC (id[0x10] address[0xfecff000] gsi_base[36])
IOAPIC[0]: apic_id 16, version 0, address 0xfecff000, GSI 36-38
ACPI: IOAPIC (id[0x0f] address[0xfec00000] gsi_base[0])
IOAPIC[1]: apic_id 15, version 0, address 0xfec00000, GSI 0-35
ACPI: IOAPIC (id[0x0e] address[0xfec01000] gsi_base[39])
IOAPIC[2]: apic_id 14, version 0, address 0xfec01000, GSI 39-74
then they don't need append that bunch of OVR.

Yinghai

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
  2010-02-27 19:40                 ` Yinghai Lu
@ 2010-02-27 21:30                   ` Eric W. Biederman
  2010-02-27 22:00                     ` Yinghai Lu
  2010-03-01 16:46                     ` [LKML] " Konrad Rzeszutek Wilk
  0 siblings, 2 replies; 34+ messages in thread
From: Eric W. Biederman @ 2010-02-27 21:30 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Ingo Molnar, linux-tip-commits, linux-kernel, hpa, mingo,
	garyhade, iranna.ankad, suresh.b.siddha, tglx, trenn

Yinghai Lu <yinghai@kernel.org> writes:

> the x3950 has strange gsi base 
>
> ACPI: IOAPIC (id[0x10] address[0xfecff000] gsi_base[0])
> IOAPIC[0]: apic_id 16, version 0, address 0xfecff000, GSI 0-2
> ACPI: IOAPIC (id[0x0f] address[0xfec00000] gsi_base[3])
> IOAPIC[1]: apic_id 15, version 0, address 0xfec00000, GSI 3-38
> ACPI: IOAPIC (id[0x0e] address[0xfec01000] gsi_base[39])
> IOAPIC[2]: apic_id 14, version 0, address 0xfec01000, GSI 39-74
>
> and BIOS using INT_SRC_OVR to map back gsi  3 - 18 to irq 0 - 15
>
> ACPI: INT_SRC_OVR (bus 0 bus_irq 1 global_irq 4 dfl dfl)
> ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 5 dfl dfl)
> ACPI: INT_SRC_OVR (bus 0 bus_irq 3 global_irq 6 dfl dfl)
> ACPI: INT_SRC_OVR (bus 0 bus_irq 4 global_irq 7 dfl dfl)
> ACPI: INT_SRC_OVR (bus 0 bus_irq 6 global_irq 9 dfl dfl)
> ACPI: INT_SRC_OVR (bus 0 bus_irq 7 global_irq 10 dfl dfl)
> ACPI: INT_SRC_OVR (bus 0 bus_irq 8 global_irq 11 low edge)
> ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 12 dfl dfl)
> ACPI: INT_SRC_OVR (bus 0 bus_irq 12 global_irq 15 dfl dfl)
> ACPI: INT_SRC_OVR (bus 0 bus_irq 13 global_irq 16 dfl dfl)
> ACPI: INT_SRC_OVR (bus 0 bus_irq 14 global_irq 17 low edge)
> ACPI: INT_SRC_OVR (bus 0 bus_irq 15 global_irq 18 dfl dfl)
> if we dont have this patch to do the remap (swap some mapping between ioapic), and only assume irq = gsi,
> the irq from first ioapic controller will be blocked.

Bah.  I was hoping Len Brown would have looked at this earlier.
I just read through the relevant sections of the ACPI spec
1.0, 2.0 and 3.0 so I can understand what is really going on.

What the x3950 firmware does is stupid, and probably needs to be
changed but it is in spec.

I see two issues here.
- You broke x3950 by only initializing the first ioapic.
  We should be able to fix that by having setup_IO_APIC_irqs
  loop through all of the irqs and setup setup any irq with
  pin_2_irq < 16.  It is fragile and out of spec to assume only
  one ioapic will have all of the isa irqs connected to it.
  Plus extending your loop should be simpler and less intrusive
  patch than what you have posted.

  Although I suspect your patch to find the boot_ioapic_idx is
  good enough for now.

- The fact that our current code makes 3 gsis/irqs on the x3950 unusable.
  This is the justification for the remapping and unless this is
  also a regression I don't think we should fix this in the
  current merge window.

acpi guarantees there will be a 1 to 1 mapping between gsi's and
isa interrupts but it does not guarantee what that mapping will be.
acpi also specified that interrupt source overrides will only be
provided for the isa irqs.

linux irqs 0-15 must be the ISA irqs.

So to handle anything that is legitimate according to the acpi spec we
do need a mapping between gsi and irqs. Grrrr.

Something like:

/* By default isa irqs are identity mapped to gsis */
unsigned int isa_irq_to_gsi[16] = {
	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};

unsigned int gsi_to_irq(unsigned int gsi)
{
	unsigned int irq = gsi + 16;
	unsigned int i;
	for (i = 0; i < 16; i++) {
		if (isa_irq_to_gsi[i] == gsi)
			irq = i;
	}
	return irq;
}

unsigned int irq_to_gsi(unsigned int irq)
{
	unsigned int gsi;
	if (irq < 16) {
		gsi = isa_irq_to_gsi[irq];
	} else {
        	gsi = irq - 16;
        }
        return gsi;
}

When we process the interrupt source overrides we just need to
update the little isa_irq_to_gsi table.

I expect finding all of the places where we need to do a mapping
for gsi number to irq numbers is going to take some time to do
cleanly which suggests it is not a good idea for this merge window.

YH your current remapping patch looks like a pretty horrible hack
instead of real solution to the problem.  I honestly think starting
with it will just obscure what is going and make it harder to
introduce a clean gsi_to_irq/irq_to_gsi.

> so far this patch only affect (fix ) x3950.
>
> all other platform will all have boot_ioapic_idx's gsi_base == 0, 
> the function will just still return gsi.
>
> other solution will ask IBM to fix their bios, so we can get

The IBM x3950 clearly fails to be conservative in the tables it
generates which is a justification for fixing it if IBM is
so inclined.  I don't see how they will ever get the first
3 irqs to be used in older linux releases (aka Enterprise kernels)
if IBM doesn't update the firmware.

I wonder if we can get qemu to emulate a system with a twisted acpi
setup like this to give us an easier platform to test this kind of
code.

> ACPI: IOAPIC (id[0x10] address[0xfecff000] gsi_base[36])
> IOAPIC[0]: apic_id 16, version 0, address 0xfecff000, GSI 36-38
> ACPI: IOAPIC (id[0x0f] address[0xfec00000] gsi_base[0])
> IOAPIC[1]: apic_id 15, version 0, address 0xfec00000, GSI 0-35
> ACPI: IOAPIC (id[0x0e] address[0xfec01000] gsi_base[39])
> IOAPIC[2]: apic_id 14, version 0, address 0xfec01000, GSI 39-74
> then they don't need append that bunch of OVR.

Eric

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
  2010-02-27 21:30                   ` Eric W. Biederman
@ 2010-02-27 22:00                     ` Yinghai Lu
  2010-02-27 22:18                       ` Eric W. Biederman
  2010-03-01 19:37                       ` [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq() Eric W. Biederman
  2010-03-01 16:46                     ` [LKML] " Konrad Rzeszutek Wilk
  1 sibling, 2 replies; 34+ messages in thread
From: Yinghai Lu @ 2010-02-27 22:00 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Ingo Molnar, linux-tip-commits, linux-kernel, hpa, mingo,
	garyhade, iranna.ankad, suresh.b.siddha, tglx, trenn

On 02/27/2010 01:30 PM, Eric W. Biederman wrote:
> Yinghai Lu <yinghai@kernel.org> writes:
> 
>> the x3950 has strange gsi base 
>>
>> ACPI: IOAPIC (id[0x10] address[0xfecff000] gsi_base[0])
>> IOAPIC[0]: apic_id 16, version 0, address 0xfecff000, GSI 0-2
>> ACPI: IOAPIC (id[0x0f] address[0xfec00000] gsi_base[3])
>> IOAPIC[1]: apic_id 15, version 0, address 0xfec00000, GSI 3-38
>> ACPI: IOAPIC (id[0x0e] address[0xfec01000] gsi_base[39])
>> IOAPIC[2]: apic_id 14, version 0, address 0xfec01000, GSI 39-74
>>
>> and BIOS using INT_SRC_OVR to map back gsi  3 - 18 to irq 0 - 15
>>
>> ACPI: INT_SRC_OVR (bus 0 bus_irq 1 global_irq 4 dfl dfl)
>> ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 5 dfl dfl)
>> ACPI: INT_SRC_OVR (bus 0 bus_irq 3 global_irq 6 dfl dfl)
>> ACPI: INT_SRC_OVR (bus 0 bus_irq 4 global_irq 7 dfl dfl)
>> ACPI: INT_SRC_OVR (bus 0 bus_irq 6 global_irq 9 dfl dfl)
>> ACPI: INT_SRC_OVR (bus 0 bus_irq 7 global_irq 10 dfl dfl)
>> ACPI: INT_SRC_OVR (bus 0 bus_irq 8 global_irq 11 low edge)
>> ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 12 dfl dfl)
>> ACPI: INT_SRC_OVR (bus 0 bus_irq 12 global_irq 15 dfl dfl)
>> ACPI: INT_SRC_OVR (bus 0 bus_irq 13 global_irq 16 dfl dfl)
>> ACPI: INT_SRC_OVR (bus 0 bus_irq 14 global_irq 17 low edge)
>> ACPI: INT_SRC_OVR (bus 0 bus_irq 15 global_irq 18 dfl dfl)
>> if we dont have this patch to do the remap (swap some mapping between ioapic), and only assume irq = gsi,
>> the irq from first ioapic controller will be blocked.
> 
> Bah.  I was hoping Len Brown would have looked at this earlier.
> I just read through the relevant sections of the ACPI spec
> 1.0, 2.0 and 3.0 so I can understand what is really going on.
> 
> What the x3950 firmware does is stupid, and probably needs to be
> changed but it is in spec.
> 
> I see two issues here.
> - You broke x3950 by only initializing the first ioapic.
>   We should be able to fix that by having setup_IO_APIC_irqs
>   loop through all of the irqs and setup setup any irq with
>   pin_2_irq < 16.  It is fragile and out of spec to assume only
>   one ioapic will have all of the isa irqs connected to it.
>   Plus extending your loop should be simpler and less intrusive
>   patch than what you have posted.

then will have all irq_desc for ioapic stay with BSP node.

> 
>   Although I suspect your patch to find the boot_ioapic_idx is
>   good enough for now.
> 
> - The fact that our current code makes 3 gsis/irqs on the x3950 unusable.
>   This is the justification for the remapping and unless this is
>   also a regression I don't think we should fix this in the
>   current merge window.
> 
> acpi guarantees there will be a 1 to 1 mapping between gsi's and
> isa interrupts but it does not guarantee what that mapping will be.
> acpi also specified that interrupt source overrides will only be
> provided for the isa irqs.
> 
> linux irqs 0-15 must be the ISA irqs.
> 
> So to handle anything that is legitimate according to the acpi spec we
> do need a mapping between gsi and irqs. Grrrr.
> 
> Something like:
> 
> /* By default isa irqs are identity mapped to gsis */
> unsigned int isa_irq_to_gsi[16] = {
> 	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
> };
> 
> unsigned int gsi_to_irq(unsigned int gsi)
> {
> 	unsigned int irq = gsi + 16;
> 	unsigned int i;
> 	for (i = 0; i < 16; i++) {
> 		if (isa_irq_to_gsi[i] == gsi)
> 			irq = i;
> 	}
> 	return irq;
> }
> 
> unsigned int irq_to_gsi(unsigned int irq)
> {
> 	unsigned int gsi;
> 	if (irq < 16) {
> 		gsi = isa_irq_to_gsi[irq];
> 	} else {
>         	gsi = irq - 16;
>         }
>         return gsi;
> }
> 
> When we process the interrupt source overrides we just need to
> update the little isa_irq_to_gsi table.
> 
> I expect finding all of the places where we need to do a mapping
> for gsi number to irq numbers is going to take some time to do
> cleanly which suggests it is not a good idea for this merge window.
> 
> YH your current remapping patch looks like a pretty horrible hack
> instead of real solution to the problem.  I honestly think starting
> with it will just obscure what is going and make it harder to
> introduce a clean gsi_to_irq/irq_to_gsi.

good, the mapping looks much clear.

YH

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
  2010-02-27 22:00                     ` Yinghai Lu
@ 2010-02-27 22:18                       ` Eric W. Biederman
  2010-02-27 22:58                         ` Yinghai Lu
                                           ` (2 more replies)
  2010-03-01 19:37                       ` [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq() Eric W. Biederman
  1 sibling, 3 replies; 34+ messages in thread
From: Eric W. Biederman @ 2010-02-27 22:18 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Ingo Molnar, linux-tip-commits, linux-kernel, hpa, mingo,
	garyhade, iranna.ankad, suresh.b.siddha, tglx, trenn

Yinghai Lu <yinghai@kernel.org> writes:

> On 02/27/2010 01:30 PM, Eric W. Biederman wrote:
> then will have all irq_desc for ioapic stay with BSP node.

This is what I am thinking....

static void __init setup_IO_APIC_irqs(void)
{
	int apic_id, pin, idx, irq;
	int notcon = 0;
	struct irq_desc *desc;
	struct irq_cfg *cfg;
	int node = cpu_to_node(boot_cpu_id);

	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");

	for(apic_id = 0; apic_id < nr_ioapics; apic_id++) {
		for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
			idx = find_irq_entry(apic_id, pin, mp_INT);
			if (idx == -1) {
				if (!notcon) {
					notcon = 1;
					apic_printk(APIC_VERBOSE,
						KERN_DEBUG " %d-%d",
						mp_ioapics[apic_id].apicid, pin);
				} else
					apic_printk(APIC_VERBOSE, " %d-%d",
						mp_ioapics[apic_id].apicid, pin);
				continue;
			}
			if (notcon) {
				apic_printk(APIC_VERBOSE,
					" (apicid-pin) not connected\n");
				notcon = 0;
			}
			
			irq = pin_2_irq(idx, apic_id, pin);

+			if ((apic_id > 0) && (irq > 16))
+				continue;

			
			/*
			 * Skip the timer IRQ if there's a quirk handler
			 * installed and if it returns 1:
			 */
			if (apic->multi_timer_check &&
				apic->multi_timer_check(apic_id, irq))
				continue;
			
			desc = irq_to_desc_alloc_node(irq, node);
			if (!desc) {
				printk(KERN_INFO "can not get irq_desc for %d\n", irq);
				continue;
			}
			cfg = desc->chip_data;
			add_pin_to_irq_node(cfg, node, apic_id, pin);
			/*
			 * don't mark it in pin_programmed, so later acpi could
			 * set it correctly when irq < 16
			 */
			setup_IO_APIC_irq(apic_id, pin, irq, desc,
				irq_trigger(idx), irq_polarity(idx));
		}
	}
	
	if (notcon)
		apic_printk(APIC_VERBOSE,
			" (apicid-pin) not connected\n");
}


>> YH your current remapping patch looks like a pretty horrible hack
>> instead of real solution to the problem.  I honestly think starting
>> with it will just obscure what is going and make it harder to
>> introduce a clean gsi_to_irq/irq_to_gsi.
>
> good, the mapping looks much clear.

Thanks.  This code is just too convoluted to introduce many more
hacks and not have it fall over.

Eric

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
  2010-02-27 18:52               ` Yinghai Lu
@ 2010-02-27 22:57                 ` H. Peter Anvin
  0 siblings, 0 replies; 34+ messages in thread
From: H. Peter Anvin @ 2010-02-27 22:57 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Ingo Molnar, linux-tip-commits, linux-kernel, mingo, ebiederm,
	garyhade, iranna.ankad, suresh.b.siddha, tglx, trenn

On 02/27/2010 10:52 AM, Yinghai Lu wrote:
> 
> Ingo found:
> | x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
> cause:
>  arch/x86/kernel/apic/io_apic.c:1042: error: implicit declaration of function ?remap_ioapic_gsi_to_irq?
> 
> actually when !CONFIG_ACPI, we have
> #define acpi_ioapic 0
> 
> somehow we still get warning for
> #if (!0) {
> 	...
> } else {
> 	...
> 	remap_ioapic_gsi_to_irq...
> }
> 
> gcc bug?
> 

You're confusing #if and if ( ) { .. }.

Inside an if () { ... } clause the contents still needs to be correct,
even if it will get optimized out.

	-hpa


-- 
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
  2010-02-27 22:18                       ` Eric W. Biederman
@ 2010-02-27 22:58                         ` Yinghai Lu
  2010-02-28  1:12                         ` [PATCH -v9] x86: fix out of order of gsi Yinghai Lu
  2010-02-28  3:47                         ` [PATCH -v11] x86: fix out of order of gsi -- partial Yinghai Lu
  2 siblings, 0 replies; 34+ messages in thread
From: Yinghai Lu @ 2010-02-27 22:58 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Ingo Molnar, linux-tip-commits, linux-kernel, hpa, mingo,
	garyhade, iranna.ankad, suresh.b.siddha, tglx, trenn

On 02/27/2010 02:18 PM, Eric W. Biederman wrote:
> Yinghai Lu <yinghai@kernel.org> writes:
> 
>> On 02/27/2010 01:30 PM, Eric W. Biederman wrote:
>> then will have all irq_desc for ioapic stay with BSP node.
> 
> This is what I am thinking....
> 
> static void __init setup_IO_APIC_irqs(void)
> {
> 	int apic_id, pin, idx, irq;
> 	int notcon = 0;
> 	struct irq_desc *desc;
> 	struct irq_cfg *cfg;
> 	int node = cpu_to_node(boot_cpu_id);
> 
> 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
> 
> 	for(apic_id = 0; apic_id < nr_ioapics; apic_id++) {
> 		for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
> 			idx = find_irq_entry(apic_id, pin, mp_INT);
> 			if (idx == -1) {
> 				if (!notcon) {
> 					notcon = 1;
> 					apic_printk(APIC_VERBOSE,
> 						KERN_DEBUG " %d-%d",
> 						mp_ioapics[apic_id].apicid, pin);
> 				} else
> 					apic_printk(APIC_VERBOSE, " %d-%d",
> 						mp_ioapics[apic_id].apicid, pin);
> 				continue;
> 			}
> 			if (notcon) {
> 				apic_printk(APIC_VERBOSE,
> 					" (apicid-pin) not connected\n");
> 				notcon = 0;
> 			}
> 			
> 			irq = pin_2_irq(idx, apic_id, pin);
> 
> +			if ((apic_id > 0) && (irq > 16))
> +				continue;
looks right.

YH

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH -v9] x86: fix out of order of gsi
  2010-02-27 22:18                       ` Eric W. Biederman
  2010-02-27 22:58                         ` Yinghai Lu
@ 2010-02-28  1:12                         ` Yinghai Lu
  2010-02-28  3:26                           ` [PATCH -v10] " Yinghai Lu
  2010-02-28  3:47                         ` [PATCH -v11] x86: fix out of order of gsi -- partial Yinghai Lu
  2 siblings, 1 reply; 34+ messages in thread
From: Yinghai Lu @ 2010-02-28  1:12 UTC (permalink / raw)
  To: Eric W. Biederman, Ingo Molnar, garyhade, iranna.ankad
  Cc: linux-tip-commits, linux-kernel, hpa, mingo, suresh.b.siddha,
	tglx, trenn, Len Brown


found IBM x3950 will have problem after

|commit b9c61b70075c87a8612624736faf4a2de5b1ed30
|
|    x86/pci: update pirq_enable_irq() to setup io apic routing

The problem is that with the patch, the machine freezes when
console=ttyS0,... kernel serial parameter is passed.
It seem to freeze at DVD initialization and the whole problem seem
to be DVD/pata related, but somehow exposed through the serial
parameter.
Such apic problems can expose really weird behavior..

<6>ACPI: IOAPIC (id[0x10] address[0xfecff000] gsi_base[0])
<6>IOAPIC[0]: apic_id 16, version 0, address 0xfecff000, GSI 0-2
<6>ACPI: IOAPIC (id[0x0f] address[0xfec00000] gsi_base[3])
<6>IOAPIC[1]: apic_id 15, version 0, address 0xfec00000, GSI 3-38
<6>ACPI: IOAPIC (id[0x0e] address[0xfec01000] gsi_base[39])
<6>IOAPIC[2]: apic_id 14, version 0, address 0xfec01000, GSI 39-74
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 1 global_irq 4 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 5 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 3 global_irq 6 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 4 global_irq 7 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 6 global_irq 9 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 7 global_irq 10 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 8 global_irq 11 low edge)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 12 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 12 global_irq 15 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 13 global_irq 16 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 14 global_irq 17 low edge)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 15 global_irq 18 dfl dfl)

it turns out that system have three io apic controller. but put boot ioapic
routing in second one. and that gsi_base is not 0. it is using bunch of INT_SRC_OVR...

recent changes
1. one set routing for first io apic controller
2. assume irq = gsi
will break theat system.

so try to remap those gsi, need to seperate boot_ioapic_id detection out of enable_IO_APIC
and call them early.
introduce boot_ioapic_id, and remap_ioapic_gsi...

-v2: shift gsi with delta instead of gsi_base of boot_ioapic_idx
-v3: double check with find_isa_irq_apic(0, mp_INT) to get right boot_ioapic_idx
-v4: nr_legacy_irqs
-v5: add print out for boot_ioapic_idx, and also make it could be applied for current
-v9: according to Eric, use fixed 16 for shifting instead of remap

Reported-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Bisected-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Tested-by: Gary Hade <garyhade@us.ibm.com>
Cc: Thomas Renninger <trenn@suse.de>
Cc: stable@kernel.org
Signed-off-by: Yinghai Lu <yinghai@kernel.org>

---
 arch/x86/include/asm/io_apic.h |    2 
 arch/x86/include/asm/mpspec.h  |    3 +
 arch/x86/kernel/acpi/boot.c    |   28 ++++++----
 arch/x86/kernel/apic/io_apic.c |  110 ++++++++++++++++++++++++++++++-----------
 4 files changed, 105 insertions(+), 38 deletions(-)

Index: linux-2.6/arch/x86/include/asm/io_apic.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/io_apic.h
+++ linux-2.6/arch/x86/include/asm/io_apic.h
@@ -158,7 +158,7 @@ extern int io_apic_get_redir_entries(int
 struct io_apic_irq_attr;
 extern int io_apic_set_pci_routing(struct device *dev, int irq,
 		 struct io_apic_irq_attr *irq_attr);
-void setup_IO_APIC_irq_extra(u32 gsi);
+void setup_IO_APIC_irq_extra(u32 gsi, unsigned int *irq);
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
 extern void ioapic_init_mappings(void);
 extern void ioapic_insert_resources(void);
Index: linux-2.6/arch/x86/include/asm/mpspec.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/mpspec.h
+++ linux-2.6/arch/x86/include/asm/mpspec.h
@@ -96,6 +96,9 @@ static inline void early_reserve_e820_mp
 #endif
 
 void __cpuinit generic_processor_info(int apicid, int version);
+extern unsigned int isa_irq_to_gsi[];
+int gsi_to_irq(unsigned int gsi);
+unsigned int irq_to_gsi(int irq);
 #ifdef CONFIG_ACPI
 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,
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/acpi/boot.c
+++ linux-2.6/arch/x86/kernel/acpi/boot.c
@@ -311,7 +311,8 @@ acpi_parse_ioapic(struct acpi_subtable_h
 /*
  * Parse Interrupt Source Override for the ACPI SCI
  */
-static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
+static void __init
+acpi_sci_ioapic_setup(u8 bus_irq, u32 gsi, u16 polarity, u16 trigger)
 {
 	if (trigger == 0)	/* compatible SCI trigger is level */
 		trigger = 3;
@@ -331,7 +332,7 @@ static void __init acpi_sci_ioapic_setup
 	 * If GSI is < 16, this will update its flags,
 	 * else it will create a new mp_irqs[] entry.
 	 */
-	mp_override_legacy_irq(gsi, polarity, trigger, gsi);
+	mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
 
 	/*
 	 * stash over-ride to indicate we've been here
@@ -355,7 +356,8 @@ acpi_parse_int_src_ovr(struct acpi_subta
 	acpi_table_print_madt_entry(header);
 
 	if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) {
-		acpi_sci_ioapic_setup(intsrc->global_irq,
+		acpi_sci_ioapic_setup(intsrc->source_irq,
+				      intsrc->global_irq,
 				      intsrc->inti_flags & ACPI_MADT_POLARITY_MASK,
 				      (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2);
 		return 0;
@@ -450,7 +452,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned in
 
 #ifdef CONFIG_X86_IO_APIC
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
-		setup_IO_APIC_irq_extra(gsi);
+		setup_IO_APIC_irq_extra(gsi, irq);
 #endif
 
 	return 0;
@@ -945,6 +947,8 @@ void __init mp_override_legacy_irq(u8 bu
 	mp_irq.dstirq = pin;	/* INTIN# */
 
 	save_mp_irq(&mp_irq);
+
+	isa_irq_to_gsi[bus_irq] = gsi;
 }
 
 void __init mp_config_acpi_legacy_irqs(void)
@@ -974,7 +978,7 @@ void __init mp_config_acpi_legacy_irqs(v
 	/*
 	 * Locate the IOAPIC that manages the ISA IRQs (0-15).
 	 */
-	ioapic = mp_find_ioapic(0);
+	ioapic = mp_find_ioapic(irq_to_gsi(0));
 	if (ioapic < 0)
 		return;
 	dstapic = mp_ioapics[ioapic].apicid;
@@ -1057,6 +1061,7 @@ int mp_register_gsi(struct device *dev,
 {
 	int ioapic;
 	int ioapic_pin;
+	int irq;
 	struct io_apic_irq_attr irq_attr;
 
 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
@@ -1079,11 +1084,12 @@ int mp_register_gsi(struct device *dev,
 		gsi = ioapic_renumber_irq(ioapic, gsi);
 #endif
 
+	irq = gsi_to_irq(gsi);
 	if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
 		printk(KERN_ERR "Invalid reference to IOAPIC pin "
 		       "%d-%d\n", mp_ioapics[ioapic].apicid,
 		       ioapic_pin);
-		return gsi;
+		return irq;
 	}
 
 	if (enable_update_mptable)
@@ -1092,9 +1098,9 @@ int mp_register_gsi(struct device *dev,
 	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);
+	io_apic_set_pci_routing(dev, irq, &irq_attr);
 
-	return gsi;
+	return irq;
 }
 
 /*
@@ -1151,8 +1157,10 @@ static int __init acpi_parse_madt_ioapic
 	 * If BIOS did not supply an INT_SRC_OVR for the SCI
 	 * pretend we got one so we can set the SCI flags.
 	 */
-	if (!acpi_sci_override_gsi)
-		acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0);
+	if (!acpi_sci_override_gsi) {
+		int irq = gsi_to_irq(acpi_gbl_FADT.sci_interrupt);
+		acpi_sci_ioapic_setup(irq, acpi_gbl_FADT.sci_interrupt, 0, 0);
+	}
 
 	/* Fill in identity legacy mappings where no override */
 	mp_config_acpi_legacy_irqs();
Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/apic/io_apic.c
+++ linux-2.6/arch/x86/kernel/apic/io_apic.c
@@ -97,6 +97,41 @@ int mp_irq_entries;
 /* GSI interrupts */
 static int nr_irqs_gsi = NR_IRQS_LEGACY;
 
+/* By default isa irqs are identity mapped to gsis */
+unsigned int isa_irq_to_gsi[NR_IRQS_LEGACY] = {
+	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+};
+
+static int boot_ioapic_idx;
+static int gsi_delta;
+int gsi_to_irq(unsigned int gsi)
+{
+	unsigned int irq = gsi;
+	unsigned int i;
+
+	irq += gsi_delta;
+	for (i = 0; i < NR_IRQS_LEGACY; i++) {
+		if (isa_irq_to_gsi[i] == gsi) {
+			irq = i;
+			break;
+		}
+	}
+
+	return irq;
+}
+
+unsigned int irq_to_gsi(int irq)
+{
+	unsigned int gsi;
+
+	if (irq < NR_IRQS_LEGACY)
+		gsi = isa_irq_to_gsi[irq];
+	else
+		gsi = irq - gsi_delta;
+
+	return gsi;
+}
+
 #if defined (CONFIG_MCA) || defined (CONFIG_EISA)
 int mp_bus_id_to_type[MAX_MP_BUSSES];
 #endif
@@ -1006,7 +1041,7 @@ static inline int irq_trigger(int idx)
 int (*ioapic_renumber_irq)(int ioapic, int irq);
 static int pin_2_irq(int idx, int apic, int pin)
 {
-	int irq, i;
+	int irq;
 	int bus = mp_irqs[idx].srcbus;
 
 	/*
@@ -1018,18 +1053,28 @@ static int pin_2_irq(int idx, int apic,
 	if (test_bit(bus, mp_bus_not_pci)) {
 		irq = mp_irqs[idx].srcbusirq;
 	} else {
-		/*
-		 * PCI IRQs are mapped in order
-		 */
-		i = irq = 0;
-		while (i < apic)
-			irq += nr_ioapic_registers[i++];
-		irq += pin;
+		unsigned int gsi;
+		if (!acpi_ioapic) {
+			int i;
+			/*
+			 * PCI IRQs are mapped in order
+			 */
+			i = gsi = 0;
+			while (i < apic)
+				gsi += nr_ioapic_registers[i++];
+			gsi += pin;
+		} else
+			gsi = pin + mp_gsi_routing[apic].gsi_base;
+
+#ifdef CONFIG_X86_32
 		/*
                  * For MPS mode, so far only needed by ES7000 platform
                  */
 		if (ioapic_renumber_irq)
-			irq = ioapic_renumber_irq(apic, irq);
+			gsi = ioapic_renumber_irq(apic, gsi);
+#endif
+
+		irq = gsi_to_irq(gsi);
 	}
 
 #ifdef CONFIG_X86_32
@@ -1465,21 +1510,15 @@ static struct {
 
 static void __init setup_IO_APIC_irqs(void)
 {
-	int apic_id = 0, pin, idx, irq;
+	int pin, apic_id, idx, irq;
 	int notcon = 0;
 	struct irq_desc *desc;
 	struct irq_cfg *cfg;
 	int node = cpu_to_node(boot_cpu_id);
 
-	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+	apic_id = boot_ioapic_idx;
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		apic_id = mp_find_ioapic(0);
-		if (apic_id < 0)
-			apic_id = 0;
-	}
-#endif
+	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
 	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
 		idx = find_irq_entry(apic_id, pin, mp_INT);
@@ -1535,7 +1574,7 @@ static void __init setup_IO_APIC_irqs(vo
  * but could not use acpi_register_gsi()
  * like some special sci in IBM x3330
  */
-void setup_IO_APIC_irq_extra(u32 gsi)
+void setup_IO_APIC_irq_extra(u32 gsi, unsigned int *pirq)
 {
 	int apic_id = 0, pin, idx, irq;
 	int node = cpu_to_node(boot_cpu_id);
@@ -1555,6 +1594,7 @@ void setup_IO_APIC_irq_extra(u32 gsi)
 		return;
 
 	irq = pin_2_irq(idx, apic_id, pin);
+	*pirq = irq;
 #ifdef CONFIG_SPARSE_IRQ
 	desc = irq_to_desc(irq);
 	if (desc)
@@ -1998,6 +2038,27 @@ void __init enable_IO_APIC(void)
 	clear_IO_APIC();
 }
 
+static void __init probe_ioapic_i8259(void)
+{
+	/* probe boot ioapic idx */
+	boot_ioapic_idx = ioapic_i8259.apic;
+	if (boot_ioapic_idx < 0)
+		boot_ioapic_idx = find_isa_irq_apic(0, mp_INT);
+#ifdef CONFIG_ACPI
+	if (!acpi_disabled && acpi_ioapic && boot_ioapic_idx < 0)
+		boot_ioapic_idx = mp_find_ioapic(irq_to_gsi(0));
+#endif
+	if (boot_ioapic_idx < 0)
+		boot_ioapic_idx = 0;
+
+	if (mp_gsi_routing[boot_ioapic_idx].gsi_base) {
+		gsi_delta = NR_IRQS_LEGACY;
+		nr_irqs_gsi += NR_IRQS_LEGACY;
+	}
+
+	printk(KERN_INFO "boot_ioapic_idx: %d\n", boot_ioapic_idx);
+}
+
 /*
  * Not an __init, needed by the reboot code
  */
@@ -3111,6 +3172,7 @@ void __init setup_IO_APIC(void)
 	x86_init.mpparse.setup_ioapic_ids();
 
 	sync_Arb_IDs();
+	probe_ioapic_i8259();
 	setup_IO_APIC_irqs();
 	init_IO_APIC_traps();
 	if (legacy_pic->nr_legacy_irqs)
@@ -4061,20 +4123,14 @@ int acpi_get_override_irq(int bus_irq, i
 #ifdef CONFIG_SMP
 void __init setup_ioapic_dest(void)
 {
-	int pin, ioapic = 0, irq, irq_entry;
+	int pin, ioapic, irq, irq_entry;
 	struct irq_desc *desc;
 	const struct cpumask *mask;
 
 	if (skip_ioapic_setup == 1)
 		return;
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		ioapic = mp_find_ioapic(0);
-		if (ioapic < 0)
-			ioapic = 0;
-	}
-#endif
+	ioapic = boot_ioapic_idx;
 
 	for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
 		irq_entry = find_irq_entry(ioapic, pin, mp_INT);

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH -v10] x86: fix out of order of gsi
  2010-02-28  1:12                         ` [PATCH -v9] x86: fix out of order of gsi Yinghai Lu
@ 2010-02-28  3:26                           ` Yinghai Lu
  0 siblings, 0 replies; 34+ messages in thread
From: Yinghai Lu @ 2010-02-28  3:26 UTC (permalink / raw)
  To: Eric W. Biederman, Ingo Molnar, garyhade, iranna.ankad
  Cc: linux-tip-commits, linux-kernel, hpa, mingo, suresh.b.siddha,
	tglx, trenn, Len Brown


found IBM x3950 will have problem after

|commit b9c61b70075c87a8612624736faf4a2de5b1ed30
|
|    x86/pci: update pirq_enable_irq() to setup io apic routing

The problem is that with the patch, the machine freezes when
console=ttyS0,... kernel serial parameter is passed.
It seem to freeze at DVD initialization and the whole problem seem
to be DVD/pata related, but somehow exposed through the serial
parameter.
Such apic problems can expose really weird behavior..

<6>ACPI: IOAPIC (id[0x10] address[0xfecff000] gsi_base[0])
<6>IOAPIC[0]: apic_id 16, version 0, address 0xfecff000, GSI 0-2
<6>ACPI: IOAPIC (id[0x0f] address[0xfec00000] gsi_base[3])
<6>IOAPIC[1]: apic_id 15, version 0, address 0xfec00000, GSI 3-38
<6>ACPI: IOAPIC (id[0x0e] address[0xfec01000] gsi_base[39])
<6>IOAPIC[2]: apic_id 14, version 0, address 0xfec01000, GSI 39-74
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 1 global_irq 4 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 5 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 3 global_irq 6 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 4 global_irq 7 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 6 global_irq 9 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 7 global_irq 10 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 8 global_irq 11 low edge)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 12 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 12 global_irq 15 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 13 global_irq 16 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 14 global_irq 17 low edge)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 15 global_irq 18 dfl dfl)

it turns out that system have three io apic controller. but put boot ioapic
routing in second one. and that gsi_base is not 0. it is using bunch of INT_SRC_OVR...

recent changes
1. one set routing for first io apic controller
2. assume irq = gsi
will break theat system.

so try to remap those gsi, need to seperate boot_ioapic_id detection out of enable_IO_APIC
and call them early.
introduce boot_ioapic_id, and remap_ioapic_gsi...

-v2: shift gsi with delta instead of gsi_base of boot_ioapic_idx
-v3: double check with find_isa_irq_apic(0, mp_INT) to get right boot_ioapic_idx
-v4: nr_legacy_irqs
-v5: add print out for boot_ioapic_idx, and also make it could be applied for current
-v9: according to Eric, use fixed 16 for shifting instead of remap
-v10: still nee to touch rsparser.c

Reported-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Bisected-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Tested-by: Gary Hade <garyhade@us.ibm.com>
Cc: Thomas Renninger <trenn@suse.de>
Cc: stable@kernel.org
Signed-off-by: Yinghai Lu <yinghai@kernel.org>

---
 arch/x86/include/asm/io_apic.h |    2 
 arch/x86/include/asm/mpspec.h  |    3 +
 arch/x86/kernel/acpi/boot.c    |   28 ++++++----
 arch/x86/kernel/apic/io_apic.c |  112 ++++++++++++++++++++++++++++++-----------
 drivers/pnp/pnpacpi/rsparser.c |    8 ++
 5 files changed, 114 insertions(+), 39 deletions(-)

Index: linux-2.6/arch/x86/include/asm/io_apic.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/io_apic.h
+++ linux-2.6/arch/x86/include/asm/io_apic.h
@@ -158,7 +158,7 @@ extern int io_apic_get_redir_entries(int
 struct io_apic_irq_attr;
 extern int io_apic_set_pci_routing(struct device *dev, int irq,
 		 struct io_apic_irq_attr *irq_attr);
-void setup_IO_APIC_irq_extra(u32 gsi);
+void setup_IO_APIC_irq_extra(u32 gsi, unsigned int *irq);
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
 extern void ioapic_init_mappings(void);
 extern void ioapic_insert_resources(void);
Index: linux-2.6/arch/x86/include/asm/mpspec.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/mpspec.h
+++ linux-2.6/arch/x86/include/asm/mpspec.h
@@ -96,6 +96,9 @@ static inline void early_reserve_e820_mp
 #endif
 
 void __cpuinit generic_processor_info(int apicid, int version);
+extern unsigned int isa_irq_to_gsi[];
+int gsi_to_irq(unsigned int gsi);
+unsigned int irq_to_gsi(int irq);
 #ifdef CONFIG_ACPI
 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,
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/acpi/boot.c
+++ linux-2.6/arch/x86/kernel/acpi/boot.c
@@ -311,7 +311,8 @@ acpi_parse_ioapic(struct acpi_subtable_h
 /*
  * Parse Interrupt Source Override for the ACPI SCI
  */
-static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
+static void __init
+acpi_sci_ioapic_setup(u8 bus_irq, u32 gsi, u16 polarity, u16 trigger)
 {
 	if (trigger == 0)	/* compatible SCI trigger is level */
 		trigger = 3;
@@ -331,7 +332,7 @@ static void __init acpi_sci_ioapic_setup
 	 * If GSI is < 16, this will update its flags,
 	 * else it will create a new mp_irqs[] entry.
 	 */
-	mp_override_legacy_irq(gsi, polarity, trigger, gsi);
+	mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
 
 	/*
 	 * stash over-ride to indicate we've been here
@@ -355,7 +356,8 @@ acpi_parse_int_src_ovr(struct acpi_subta
 	acpi_table_print_madt_entry(header);
 
 	if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) {
-		acpi_sci_ioapic_setup(intsrc->global_irq,
+		acpi_sci_ioapic_setup(intsrc->source_irq,
+				      intsrc->global_irq,
 				      intsrc->inti_flags & ACPI_MADT_POLARITY_MASK,
 				      (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2);
 		return 0;
@@ -450,7 +452,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned in
 
 #ifdef CONFIG_X86_IO_APIC
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
-		setup_IO_APIC_irq_extra(gsi);
+		setup_IO_APIC_irq_extra(gsi, irq);
 #endif
 
 	return 0;
@@ -945,6 +947,8 @@ void __init mp_override_legacy_irq(u8 bu
 	mp_irq.dstirq = pin;	/* INTIN# */
 
 	save_mp_irq(&mp_irq);
+
+	isa_irq_to_gsi[bus_irq] = gsi;
 }
 
 void __init mp_config_acpi_legacy_irqs(void)
@@ -974,7 +978,7 @@ void __init mp_config_acpi_legacy_irqs(v
 	/*
 	 * Locate the IOAPIC that manages the ISA IRQs (0-15).
 	 */
-	ioapic = mp_find_ioapic(0);
+	ioapic = mp_find_ioapic(irq_to_gsi(0));
 	if (ioapic < 0)
 		return;
 	dstapic = mp_ioapics[ioapic].apicid;
@@ -1057,6 +1061,7 @@ int mp_register_gsi(struct device *dev,
 {
 	int ioapic;
 	int ioapic_pin;
+	int irq;
 	struct io_apic_irq_attr irq_attr;
 
 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
@@ -1079,11 +1084,12 @@ int mp_register_gsi(struct device *dev,
 		gsi = ioapic_renumber_irq(ioapic, gsi);
 #endif
 
+	irq = gsi_to_irq(gsi);
 	if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
 		printk(KERN_ERR "Invalid reference to IOAPIC pin "
 		       "%d-%d\n", mp_ioapics[ioapic].apicid,
 		       ioapic_pin);
-		return gsi;
+		return irq;
 	}
 
 	if (enable_update_mptable)
@@ -1092,9 +1098,9 @@ int mp_register_gsi(struct device *dev,
 	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);
+	io_apic_set_pci_routing(dev, irq, &irq_attr);
 
-	return gsi;
+	return irq;
 }
 
 /*
@@ -1151,8 +1157,10 @@ static int __init acpi_parse_madt_ioapic
 	 * If BIOS did not supply an INT_SRC_OVR for the SCI
 	 * pretend we got one so we can set the SCI flags.
 	 */
-	if (!acpi_sci_override_gsi)
-		acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0);
+	if (!acpi_sci_override_gsi) {
+		int irq = gsi_to_irq(acpi_gbl_FADT.sci_interrupt);
+		acpi_sci_ioapic_setup(irq, acpi_gbl_FADT.sci_interrupt, 0, 0);
+	}
 
 	/* Fill in identity legacy mappings where no override */
 	mp_config_acpi_legacy_irqs();
Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/apic/io_apic.c
+++ linux-2.6/arch/x86/kernel/apic/io_apic.c
@@ -97,6 +97,41 @@ int mp_irq_entries;
 /* GSI interrupts */
 static int nr_irqs_gsi = NR_IRQS_LEGACY;
 
+/* By default isa irqs are identity mapped to gsis */
+unsigned int isa_irq_to_gsi[NR_IRQS_LEGACY] = {
+	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+};
+
+static int boot_ioapic_idx;
+static int gsi_delta;
+int gsi_to_irq(unsigned int gsi)
+{
+	unsigned int irq = gsi;
+	unsigned int i;
+
+	irq += gsi_delta;
+	for (i = 0; i < NR_IRQS_LEGACY; i++) {
+		if (isa_irq_to_gsi[i] == gsi) {
+			irq = i;
+			break;
+		}
+	}
+
+	return irq;
+}
+
+unsigned int irq_to_gsi(int irq)
+{
+	unsigned int gsi;
+
+	if (irq < NR_IRQS_LEGACY)
+		gsi = isa_irq_to_gsi[irq];
+	else
+		gsi = irq - gsi_delta;
+
+	return gsi;
+}
+
 #if defined (CONFIG_MCA) || defined (CONFIG_EISA)
 int mp_bus_id_to_type[MAX_MP_BUSSES];
 #endif
@@ -1006,7 +1041,7 @@ static inline int irq_trigger(int idx)
 int (*ioapic_renumber_irq)(int ioapic, int irq);
 static int pin_2_irq(int idx, int apic, int pin)
 {
-	int irq, i;
+	int irq;
 	int bus = mp_irqs[idx].srcbus;
 
 	/*
@@ -1018,18 +1053,28 @@ static int pin_2_irq(int idx, int apic,
 	if (test_bit(bus, mp_bus_not_pci)) {
 		irq = mp_irqs[idx].srcbusirq;
 	} else {
-		/*
-		 * PCI IRQs are mapped in order
-		 */
-		i = irq = 0;
-		while (i < apic)
-			irq += nr_ioapic_registers[i++];
-		irq += pin;
+		unsigned int gsi;
+		if (!acpi_ioapic) {
+			int i;
+			/*
+			 * PCI IRQs are mapped in order
+			 */
+			i = gsi = 0;
+			while (i < apic)
+				gsi += nr_ioapic_registers[i++];
+			gsi += pin;
+		} else
+			gsi = pin + mp_gsi_routing[apic].gsi_base;
+
+#ifdef CONFIG_X86_32
 		/*
                  * For MPS mode, so far only needed by ES7000 platform
                  */
 		if (ioapic_renumber_irq)
-			irq = ioapic_renumber_irq(apic, irq);
+			gsi = ioapic_renumber_irq(apic, gsi);
+#endif
+
+		irq = gsi_to_irq(gsi);
 	}
 
 #ifdef CONFIG_X86_32
@@ -1465,21 +1510,15 @@ static struct {
 
 static void __init setup_IO_APIC_irqs(void)
 {
-	int apic_id = 0, pin, idx, irq;
+	int pin, apic_id, idx, irq;
 	int notcon = 0;
 	struct irq_desc *desc;
 	struct irq_cfg *cfg;
 	int node = cpu_to_node(boot_cpu_id);
 
-	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+	apic_id = boot_ioapic_idx;
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		apic_id = mp_find_ioapic(0);
-		if (apic_id < 0)
-			apic_id = 0;
-	}
-#endif
+	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
 	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
 		idx = find_irq_entry(apic_id, pin, mp_INT);
@@ -1535,7 +1574,7 @@ static void __init setup_IO_APIC_irqs(vo
  * but could not use acpi_register_gsi()
  * like some special sci in IBM x3330
  */
-void setup_IO_APIC_irq_extra(u32 gsi)
+void setup_IO_APIC_irq_extra(u32 gsi, unsigned int *pirq)
 {
 	int apic_id = 0, pin, idx, irq;
 	int node = cpu_to_node(boot_cpu_id);
@@ -1555,6 +1594,7 @@ void setup_IO_APIC_irq_extra(u32 gsi)
 		return;
 
 	irq = pin_2_irq(idx, apic_id, pin);
+	*pirq = irq;
 #ifdef CONFIG_SPARSE_IRQ
 	desc = irq_to_desc(irq);
 	if (desc)
@@ -1998,6 +2038,27 @@ void __init enable_IO_APIC(void)
 	clear_IO_APIC();
 }
 
+static void __init probe_ioapic_i8259(void)
+{
+	/* probe boot ioapic idx */
+	boot_ioapic_idx = ioapic_i8259.apic;
+	if (boot_ioapic_idx < 0)
+		boot_ioapic_idx = find_isa_irq_apic(0, mp_INT);
+#ifdef CONFIG_ACPI
+	if (!acpi_disabled && acpi_ioapic && boot_ioapic_idx < 0)
+		boot_ioapic_idx = mp_find_ioapic(irq_to_gsi(0));
+#endif
+	if (boot_ioapic_idx < 0)
+		boot_ioapic_idx = 0;
+
+	if (mp_gsi_routing[boot_ioapic_idx].gsi_base) {
+		gsi_delta = NR_IRQS_LEGACY;
+		nr_irqs_gsi += NR_IRQS_LEGACY;
+	}
+
+	printk(KERN_INFO "boot_ioapic_idx: %d\n", boot_ioapic_idx);
+}
+
 /*
  * Not an __init, needed by the reboot code
  */
@@ -2991,7 +3052,7 @@ static inline void __init check_timer(vo
 				legacy_pic->chip->unmask(desc);
 			}
 			if (disable_timer_pin_1 > 0)
-				clear_IO_APIC_pin(0, pin1);
+				clear_IO_APIC_pin(apic1, pin1);
 			goto out;
 		}
 		if (intr_remapping_enabled)
@@ -3111,6 +3172,7 @@ void __init setup_IO_APIC(void)
 	x86_init.mpparse.setup_ioapic_ids();
 
 	sync_Arb_IDs();
+	probe_ioapic_i8259();
 	setup_IO_APIC_irqs();
 	init_IO_APIC_traps();
 	if (legacy_pic->nr_legacy_irqs)
@@ -4061,20 +4123,14 @@ int acpi_get_override_irq(int bus_irq, i
 #ifdef CONFIG_SMP
 void __init setup_ioapic_dest(void)
 {
-	int pin, ioapic = 0, irq, irq_entry;
+	int pin, ioapic, irq, irq_entry;
 	struct irq_desc *desc;
 	const struct cpumask *mask;
 
 	if (skip_ioapic_setup == 1)
 		return;
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		ioapic = mp_find_ioapic(0);
-		if (ioapic < 0)
-			ioapic = 0;
-	}
-#endif
+	ioapic = boot_ioapic_idx;
 
 	for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
 		irq_entry = find_irq_entry(ioapic, pin, mp_INT);
Index: linux-2.6/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- linux-2.6.orig/drivers/pnp/pnpacpi/rsparser.c
+++ linux-2.6/drivers/pnp/pnpacpi/rsparser.c
@@ -123,6 +123,14 @@ static void pnpacpi_parse_allocated_irqr
 	}
 
 	flags = irq_flags(triggering, polarity, shareable);
+#ifdef CONFIG_X86_IO_APIC
+	/*
+	 * looks like IBM x3950 is using irq instead of gsi etc...
+	 * convert it back at first
+	 */
+	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
+		gsi = irq_to_gsi(gsi);
+#endif
 	irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
 	if (irq >= 0)
 		pcibios_penalize_isa_irq(irq, 1);

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH -v11] x86: fix out of order of gsi -- partial
  2010-02-27 22:18                       ` Eric W. Biederman
  2010-02-27 22:58                         ` Yinghai Lu
  2010-02-28  1:12                         ` [PATCH -v9] x86: fix out of order of gsi Yinghai Lu
@ 2010-02-28  3:47                         ` Yinghai Lu
  2010-02-28  8:09                           ` Ingo Molnar
  2 siblings, 1 reply; 34+ messages in thread
From: Yinghai Lu @ 2010-02-28  3:47 UTC (permalink / raw)
  To: Eric W. Biederman, Ingo Molnar, hpa, garyhade, tglx
  Cc: linux-tip-commits, linux-kernel, mingo, iranna.ankad,
	suresh.b.siddha, trenn

From: Eric W. Biederman <ebiederm@xmission.com>

found IBM x3950 will have problem after

|commit b9c61b70075c87a8612624736faf4a2de5b1ed30
|
|    x86/pci: update pirq_enable_irq() to setup io apic routing

The problem is that with the patch, the machine freezes when
console=ttyS0,... kernel serial parameter is passed.
It seem to freeze at DVD initialization and the whole problem seem
to be DVD/pata related, but somehow exposed through the serial
parameter.
Such apic problems can expose really weird behavior..

<6>ACPI: IOAPIC (id[0x10] address[0xfecff000] gsi_base[0])
<6>IOAPIC[0]: apic_id 16, version 0, address 0xfecff000, GSI 0-2
<6>ACPI: IOAPIC (id[0x0f] address[0xfec00000] gsi_base[3])
<6>IOAPIC[1]: apic_id 15, version 0, address 0xfec00000, GSI 3-38
<6>ACPI: IOAPIC (id[0x0e] address[0xfec01000] gsi_base[39])
<6>IOAPIC[2]: apic_id 14, version 0, address 0xfec01000, GSI 39-74
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 1 global_irq 4 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 5 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 3 global_irq 6 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 4 global_irq 7 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 6 global_irq 9 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 7 global_irq 10 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 8 global_irq 11 low edge)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 12 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 12 global_irq 15 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 13 global_irq 16 dfl dfl)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 14 global_irq 17 low edge)
<6>ACPI: INT_SRC_OVR (bus 0 bus_irq 15 global_irq 18 dfl dfl)

it turns out that system have three io apic controller. but put boot ioapic
routing in second one. and that gsi_base is not 0. it is using bunch of INT_SRC_OVR...

recent changes
1. one set routing for first io apic controller
2. assume irq = gsi
will break theat system.

so try to remap those gsi, need to seperate boot_ioapic_id detection out of enable_IO_APIC
and call them early.
introduce boot_ioapic_id, and remap_ioapic_gsi...

-v2: shift gsi with delta instead of gsi_base of boot_ioapic_idx
-v3: double check with find_isa_irq_apic(0, mp_INT) to get right boot_ioapic_idx
-v4: nr_legacy_irqs
-v5: add print out for boot_ioapic_idx, and also make it could be applied for current
-v5: add print out for boot_ioapic_idx, and also make it could be applied for current
-v9: according to Eric, use fixed 16 for shifting instead of remap
-v10: still nee to touch rsparser.c
-v11: just revert back to way Eric suggest...
      anyway the ioapic in first ioapic is blocked by second...

Reported-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Bisected-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Tested-by: Gary Hade <garyhade@us.ibm.com>
Cc: Thomas Renninger <trenn@suse.de>
Cc: stable@kernel.org
Signed-off-by: Yinghai Lu <yinghai@kernel.org>

---
 arch/x86/kernel/apic/io_apic.c |   28 ++++++++++------------------
 1 file changed, 10 insertions(+), 18 deletions(-)

Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/apic/io_apic.c
+++ linux-2.6/arch/x86/kernel/apic/io_apic.c
@@ -1465,7 +1465,7 @@ static struct {
 
 static void __init setup_IO_APIC_irqs(void)
 {
-	int apic_id = 0, pin, idx, irq;
+	int apic_id, pin, idx, irq;
 	int notcon = 0;
 	struct irq_desc *desc;
 	struct irq_cfg *cfg;
@@ -1473,14 +1473,7 @@ static void __init setup_IO_APIC_irqs(vo
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		apic_id = mp_find_ioapic(0);
-		if (apic_id < 0)
-			apic_id = 0;
-	}
-#endif
-
+	for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
 	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
 		idx = find_irq_entry(apic_id, pin, mp_INT);
 		if (idx == -1) {
@@ -1502,6 +1495,9 @@ static void __init setup_IO_APIC_irqs(vo
 
 		irq = pin_2_irq(idx, apic_id, pin);
 
+		if ((apic_id > 0) && (irq > 16))
+			continue;
+
 		/*
 		 * Skip the timer IRQ if there's a quirk handler
 		 * installed and if it returns 1:
@@ -4061,27 +4057,23 @@ int acpi_get_override_irq(int bus_irq, i
 #ifdef CONFIG_SMP
 void __init setup_ioapic_dest(void)
 {
-	int pin, ioapic = 0, irq, irq_entry;
+	int pin, ioapic, irq, irq_entry;
 	struct irq_desc *desc;
 	const struct cpumask *mask;
 
 	if (skip_ioapic_setup == 1)
 		return;
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		ioapic = mp_find_ioapic(0);
-		if (ioapic < 0)
-			ioapic = 0;
-	}
-#endif
-
+	for (ioapic = 0; ioapic < nr_ioapics; ioapic++)
 	for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
 		irq_entry = find_irq_entry(ioapic, pin, mp_INT);
 		if (irq_entry == -1)
 			continue;
 		irq = pin_2_irq(irq_entry, ioapic, pin);
 
+		if ((ioapic > 0) && (irq > 16))
+			continue;
+
 		desc = irq_to_desc(irq);
 
 		/*

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH -v11] x86: fix out of order of gsi -- partial
  2010-02-28  3:47                         ` [PATCH -v11] x86: fix out of order of gsi -- partial Yinghai Lu
@ 2010-02-28  8:09                           ` Ingo Molnar
  2010-02-28  9:05                             ` Yinghai Lu
                                               ` (2 more replies)
  0 siblings, 3 replies; 34+ messages in thread
From: Ingo Molnar @ 2010-02-28  8:09 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Eric W. Biederman, hpa, garyhade, tglx, linux-tip-commits,
	linux-kernel, mingo, iranna.ankad, suresh.b.siddha, trenn


* Yinghai Lu <yinghai@kernel.org> wrote:

> From: Eric W. Biederman <ebiederm@xmission.com>
> 
> found IBM x3950 will have problem after
> 
> |commit b9c61b70075c87a8612624736faf4a2de5b1ed30

Have you seen the commit notifications i sent for the v8 patches:

Commit-ID:  ca8c764cb39bf6cade71933b38e8c830eb8b73c6
Commit-ID:  519d637a93116ffbcd50e9e3f2591f41584f372c

Those include a much improved changelogs - please adopt those. (and preferably 
send deltas against tip:tmp.x86/apic.)

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH -v11] x86: fix out of order of gsi -- partial
  2010-02-28  8:09                           ` Ingo Molnar
@ 2010-02-28  9:05                             ` Yinghai Lu
  2010-03-01 14:40                               ` Thomas Renninger
  2010-02-28  9:06                             ` [PATCH -v12 1/2] " Yinghai Lu
  2010-02-28  9:08                             ` [PATCH -v12 2/2] x86: fix out of order of gsi - full Yinghai Lu
  2 siblings, 1 reply; 34+ messages in thread
From: Yinghai Lu @ 2010-02-28  9:05 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Eric W. Biederman, hpa, garyhade, tglx, linux-tip-commits,
	linux-kernel, mingo, iranna.ankad, suresh.b.siddha, trenn

On 02/28/2010 12:09 AM, Ingo Molnar wrote:
> 
> * Yinghai Lu <yinghai@kernel.org> wrote:
> 
>> From: Eric W. Biederman <ebiederm@xmission.com>
>>
>> found IBM x3950 will have problem after
>>
>> |commit b9c61b70075c87a8612624736faf4a2de5b1ed30
> 
> Have you seen the commit notifications i sent for the v8 patches:
> 
> Commit-ID:  ca8c764cb39bf6cade71933b38e8c830eb8b73c6
> Commit-ID:  519d637a93116ffbcd50e9e3f2591f41584f372c
> 
> Those include a much improved changelogs - please adopt those. (and preferably 
> send deltas against tip:tmp.x86/apic.)

please drop those two.

will send v12 to you.

Thanks

Yinghai

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH -v12 1/2] x86: fix out of order of gsi -- partial
  2010-02-28  8:09                           ` Ingo Molnar
  2010-02-28  9:05                             ` Yinghai Lu
@ 2010-02-28  9:06                             ` Yinghai Lu
  2010-02-28 19:51                               ` [tip:x86/apic] x86: Fix out of order of gsi tip-bot for Eric W. Biederman
  2010-02-28  9:08                             ` [PATCH -v12 2/2] x86: fix out of order of gsi - full Yinghai Lu
  2 siblings, 1 reply; 34+ messages in thread
From: Yinghai Lu @ 2010-02-28  9:06 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Eric W. Biederman, hpa, garyhade, tglx, linux-kernel, mingo,
	iranna.ankad, suresh.b.siddha, trenn


From: Eric W. Biederman <ebiederm@xmission.com>

Iranna D Ankad reported that IBM x3950 systems have boot problems
after this commit:

 |
 | commit b9c61b70075c87a8612624736faf4a2de5b1ed30
 |
 |    x86/pci: update pirq_enable_irq() to setup io apic routing
 |

The problem is that with the patch, the machine freezes when
console=ttyS0,... kernel serial parameter is passed.

It seem to freeze at DVD initialization and the whole problem
seem to be DVD/pata related, but somehow exposed through the
serial parameter.

Such apic problems can expose really weird behavior:

  ACPI: IOAPIC (id[0x10] address[0xfecff000] gsi_base[0])
  IOAPIC[0]: apic_id 16, version 0, address 0xfecff000, GSI 0-2
  ACPI: IOAPIC (id[0x0f] address[0xfec00000] gsi_base[3])
  IOAPIC[1]: apic_id 15, version 0, address 0xfec00000, GSI 3-38
  ACPI: IOAPIC (id[0x0e] address[0xfec01000] gsi_base[39])
  IOAPIC[2]: apic_id 14, version 0, address 0xfec01000, GSI 39-74
  ACPI: INT_SRC_OVR (bus 0 bus_irq 1 global_irq 4 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 5 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 3 global_irq 6 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 4 global_irq 7 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 6 global_irq 9 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 7 global_irq 10 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 8 global_irq 11 low edge)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 12 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 12 global_irq 15 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 13 global_irq 16 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 14 global_irq 17 low edge)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 15 global_irq 18 dfl dfl)

It turns out that the system has three io apic controllers, but
boot ioapic routing is in the second one, and that gsi_base is
not 0 - it is using a bunch of INT_SRC_OVR...

So these recent changes:

 1. one set routing for first io apic controller
 2. assume irq = gsi

... will break that system.

So try to remap those gsis, need to seperate boot_ioapic_idx
detection out of enable_IO_APIC() and call them early.

So introduce boot_ioapic_idx, and remap_ioapic_gsi()...

 -v2: shift gsi with delta instead of gsi_base of boot_ioapic_idx

 -v3: double check with find_isa_irq_apic(0, mp_INT) to get right
      boot_ioapic_idx

 -v4: nr_legacy_irqs

 -v5: add print out for boot_ioapic_idx, and also make it could be
      applied for current kernel and previous kernel

 -v6: add bus_irq, in acpi_sci_ioapic_setup, so can get overwride
      for sci right mapping...

 -v7: looks like pnpacpi get irq instead of gsi, so need to revert
      them back...

 -v8: split into two patches

 -v9: according to Eric, use fixed 16 for shifting instead of remap

 -v10: still need to touch rsparser.c

 -v11: just revert back to way Eric suggest...
      anyway the ioapic in first ioapic is blocked by second...

 -v12: two patches, this one will add more loop but check apic_id and irq > 16

Reported-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Bisected-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Tested-by: Gary Hade <garyhade@us.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Thomas Renninger <trenn@suse.de>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: len.brown@intel.com

---
 arch/x86/kernel/apic/io_apic.c |   28 ++++++++++------------------
 1 file changed, 10 insertions(+), 18 deletions(-)

Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/apic/io_apic.c
+++ linux-2.6/arch/x86/kernel/apic/io_apic.c
@@ -1475,7 +1475,7 @@ static struct {
 
 static void __init setup_IO_APIC_irqs(void)
 {
-	int apic_id = 0, pin, idx, irq;
+	int apic_id, pin, idx, irq;
 	int notcon = 0;
 	struct irq_desc *desc;
 	struct irq_cfg *cfg;
@@ -1483,14 +1483,7 @@ static void __init setup_IO_APIC_irqs(vo
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		apic_id = mp_find_ioapic(0);
-		if (apic_id < 0)
-			apic_id = 0;
-	}
-#endif
-
+	for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
 	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
 		idx = find_irq_entry(apic_id, pin, mp_INT);
 		if (idx == -1) {
@@ -1512,6 +1505,9 @@ static void __init setup_IO_APIC_irqs(vo
 
 		irq = pin_2_irq(idx, apic_id, pin);
 
+		if ((apic_id > 0) && (irq > 16))
+			continue;
+
 		/*
 		 * Skip the timer IRQ if there's a quirk handler
 		 * installed and if it returns 1:
@@ -4105,27 +4101,23 @@ int acpi_get_override_irq(int bus_irq, i
 #ifdef CONFIG_SMP
 void __init setup_ioapic_dest(void)
 {
-	int pin, ioapic = 0, irq, irq_entry;
+	int pin, ioapic, irq, irq_entry;
 	struct irq_desc *desc;
 	const struct cpumask *mask;
 
 	if (skip_ioapic_setup == 1)
 		return;
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		ioapic = mp_find_ioapic(0);
-		if (ioapic < 0)
-			ioapic = 0;
-	}
-#endif
-
+	for (ioapic = 0; ioapic < nr_ioapics; ioapic++)
 	for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
 		irq_entry = find_irq_entry(ioapic, pin, mp_INT);
 		if (irq_entry == -1)
 			continue;
 		irq = pin_2_irq(irq_entry, ioapic, pin);
 
+		if ((ioapic > 0) && (irq > 16))
+			continue;
+
 		desc = irq_to_desc(irq);
 
 		/*

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH -v12 2/2] x86: fix out of order of gsi - full
  2010-02-28  8:09                           ` Ingo Molnar
  2010-02-28  9:05                             ` Yinghai Lu
  2010-02-28  9:06                             ` [PATCH -v12 1/2] " Yinghai Lu
@ 2010-02-28  9:08                             ` Yinghai Lu
  2010-03-01 18:59                               ` Eric W. Biederman
  2 siblings, 1 reply; 34+ messages in thread
From: Yinghai Lu @ 2010-02-28  9:08 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Eric W. Biederman, hpa, garyhade, tglx, linux-tip-commits,
	linux-kernel, mingo, iranna.ankad, suresh.b.siddha, trenn



Iranna D Ankad reported that IBM x3950 systems have boot problems
after this commit:

 |
 | commit b9c61b70075c87a8612624736faf4a2de5b1ed30
 |
 |    x86/pci: update pirq_enable_irq() to setup io apic routing
 |

    As explained in the previous patch ("x86: Fix out of order gsi - partial)
    try to remap those gsis

    This patch adds boot_ioapic_idx and gsi_to_irq/irq_to_gsi

Reported-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Bisected-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Tested-by: Gary Hade <garyhade@us.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Thomas Renninger <trenn@suse.de>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: len.brown@intel.com


---
 arch/x86/include/asm/io_apic.h |    2 
 arch/x86/include/asm/mpspec.h  |    3 +
 arch/x86/kernel/acpi/boot.c    |   28 +++++++----
 arch/x86/kernel/apic/io_apic.c |  104 +++++++++++++++++++++++++++++++++--------
 drivers/pnp/pnpacpi/rsparser.c |    8 +++
 5 files changed, 114 insertions(+), 31 deletions(-)

Index: linux-2.6/arch/x86/include/asm/io_apic.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/io_apic.h
+++ linux-2.6/arch/x86/include/asm/io_apic.h
@@ -160,7 +160,7 @@ extern int io_apic_get_redir_entries(int
 struct io_apic_irq_attr;
 extern int io_apic_set_pci_routing(struct device *dev, int irq,
 		 struct io_apic_irq_attr *irq_attr);
-void setup_IO_APIC_irq_extra(u32 gsi);
+void setup_IO_APIC_irq_extra(u32 gsi, unsigned int *irq);
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
 extern void ioapic_init_mappings(void);
 extern void ioapic_insert_resources(void);
Index: linux-2.6/arch/x86/include/asm/mpspec.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/mpspec.h
+++ linux-2.6/arch/x86/include/asm/mpspec.h
@@ -97,6 +97,9 @@ static inline void early_reserve_e820_mp
 #endif
 
 void __cpuinit generic_processor_info(int apicid, int version);
+extern unsigned int isa_irq_to_gsi[];
+int gsi_to_irq(unsigned int gsi);
+unsigned int irq_to_gsi(int irq);
 #ifdef CONFIG_ACPI
 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,
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/acpi/boot.c
+++ linux-2.6/arch/x86/kernel/acpi/boot.c
@@ -310,7 +310,8 @@ acpi_parse_ioapic(struct acpi_subtable_h
 /*
  * Parse Interrupt Source Override for the ACPI SCI
  */
-static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
+static void __init
+acpi_sci_ioapic_setup(u8 bus_irq, u32 gsi, u16 polarity, u16 trigger)
 {
 	if (trigger == 0)	/* compatible SCI trigger is level */
 		trigger = 3;
@@ -330,7 +331,7 @@ static void __init acpi_sci_ioapic_setup
 	 * If GSI is < 16, this will update its flags,
 	 * else it will create a new mp_irqs[] entry.
 	 */
-	mp_override_legacy_irq(gsi, polarity, trigger, gsi);
+	mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
 
 	/*
 	 * stash over-ride to indicate we've been here
@@ -354,7 +355,8 @@ acpi_parse_int_src_ovr(struct acpi_subta
 	acpi_table_print_madt_entry(header);
 
 	if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) {
-		acpi_sci_ioapic_setup(intsrc->global_irq,
+		acpi_sci_ioapic_setup(intsrc->source_irq,
+				      intsrc->global_irq,
 				      intsrc->inti_flags & ACPI_MADT_POLARITY_MASK,
 				      (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2);
 		return 0;
@@ -449,7 +451,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned in
 
 #ifdef CONFIG_X86_IO_APIC
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
-		setup_IO_APIC_irq_extra(gsi);
+		setup_IO_APIC_irq_extra(gsi, irq);
 #endif
 
 	return 0;
@@ -921,6 +923,8 @@ void __init mp_override_legacy_irq(u8 bu
 	mp_irq.dstirq = pin;	/* INTIN# */
 
 	save_mp_irq(&mp_irq);
+
+	isa_irq_to_gsi[bus_irq] = gsi;
 }
 
 void __init mp_config_acpi_legacy_irqs(void)
@@ -950,7 +954,7 @@ void __init mp_config_acpi_legacy_irqs(v
 	/*
 	 * Locate the IOAPIC that manages the ISA IRQs (0-15).
 	 */
-	ioapic = mp_find_ioapic(0);
+	ioapic = mp_find_ioapic(irq_to_gsi(0));
 	if (ioapic < 0)
 		return;
 	dstapic = mp_ioapics[ioapic].apicid;
@@ -1033,6 +1037,7 @@ int mp_register_gsi(struct device *dev,
 {
 	int ioapic;
 	int ioapic_pin;
+	int irq;
 	struct io_apic_irq_attr irq_attr;
 
 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
@@ -1055,11 +1060,12 @@ int mp_register_gsi(struct device *dev,
 		gsi = ioapic_renumber_irq(ioapic, gsi);
 #endif
 
+	irq = gsi_to_irq(gsi);
 	if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
 		printk(KERN_ERR "Invalid reference to IOAPIC pin "
 		       "%d-%d\n", mp_ioapics[ioapic].apicid,
 		       ioapic_pin);
-		return gsi;
+		return irq;
 	}
 
 	if (enable_update_mptable)
@@ -1068,9 +1074,9 @@ int mp_register_gsi(struct device *dev,
 	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);
+	io_apic_set_pci_routing(dev, irq, &irq_attr);
 
-	return gsi;
+	return irq;
 }
 
 /*
@@ -1127,8 +1133,10 @@ static int __init acpi_parse_madt_ioapic
 	 * If BIOS did not supply an INT_SRC_OVR for the SCI
 	 * pretend we got one so we can set the SCI flags.
 	 */
-	if (!acpi_sci_override_gsi)
-		acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0);
+	if (!acpi_sci_override_gsi) {
+		int irq = gsi_to_irq(acpi_gbl_FADT.sci_interrupt);
+		acpi_sci_ioapic_setup(irq, acpi_gbl_FADT.sci_interrupt, 0, 0);
+	}
 
 	/* Fill in identity legacy mappings where no override */
 	mp_config_acpi_legacy_irqs();
Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/apic/io_apic.c
+++ linux-2.6/arch/x86/kernel/apic/io_apic.c
@@ -97,6 +97,41 @@ int mp_irq_entries;
 /* GSI interrupts */
 static int nr_irqs_gsi = NR_IRQS_LEGACY;
 
+/* By default isa irqs are identity mapped to gsis */
+unsigned int isa_irq_to_gsi[NR_IRQS_LEGACY] = {
+	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+};
+
+static int boot_ioapic_idx;
+static int gsi_delta;
+int gsi_to_irq(unsigned int gsi)
+{
+	unsigned int irq = gsi;
+	unsigned int i;
+
+	irq += gsi_delta;
+	for (i = 0; i < NR_IRQS_LEGACY; i++) {
+		if (isa_irq_to_gsi[i] == gsi) {
+			irq = i;
+			break;
+		}
+	}
+
+	return irq;
+}
+
+unsigned int irq_to_gsi(int irq)
+{
+	unsigned int gsi;
+
+	if (irq < NR_IRQS_LEGACY)
+		gsi = isa_irq_to_gsi[irq];
+	else
+		gsi = irq - gsi_delta;
+
+	return gsi;
+}
+
 #if defined (CONFIG_MCA) || defined (CONFIG_EISA)
 int mp_bus_id_to_type[MAX_MP_BUSSES];
 #endif
@@ -1016,7 +1051,7 @@ static inline int irq_trigger(int idx)
 int (*ioapic_renumber_irq)(int ioapic, int irq);
 static int pin_2_irq(int idx, int apic, int pin)
 {
-	int irq, i;
+	int irq;
 	int bus = mp_irqs[idx].srcbus;
 
 	/*
@@ -1028,18 +1063,28 @@ static int pin_2_irq(int idx, int apic,
 	if (test_bit(bus, mp_bus_not_pci)) {
 		irq = mp_irqs[idx].srcbusirq;
 	} else {
-		/*
-		 * PCI IRQs are mapped in order
-		 */
-		i = irq = 0;
-		while (i < apic)
-			irq += nr_ioapic_registers[i++];
-		irq += pin;
+		unsigned int gsi;
+		if (!acpi_ioapic) {
+			int i;
+			/*
+			 * PCI IRQs are mapped in order
+			 */
+			i = gsi = 0;
+			while (i < apic)
+				gsi += nr_ioapic_registers[i++];
+			gsi += pin;
+		} else
+			gsi = pin + mp_gsi_routing[apic].gsi_base;
+
+#ifdef CONFIG_X86_32
 		/*
                  * For MPS mode, so far only needed by ES7000 platform
                  */
 		if (ioapic_renumber_irq)
-			irq = ioapic_renumber_irq(apic, irq);
+			gsi = ioapic_renumber_irq(apic, gsi);
+#endif
+
+		irq = gsi_to_irq(gsi);
 	}
 
 #ifdef CONFIG_X86_32
@@ -1475,15 +1520,16 @@ static struct {
 
 static void __init setup_IO_APIC_irqs(void)
 {
-	int apic_id, pin, idx, irq;
+	int pin, apic_id, idx, irq;
 	int notcon = 0;
 	struct irq_desc *desc;
 	struct irq_cfg *cfg;
 	int node = cpu_to_node(boot_cpu_id);
 
+	apic_id = boot_ioapic_idx;
+
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
-	for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
 	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
 		idx = find_irq_entry(apic_id, pin, mp_INT);
 		if (idx == -1) {
@@ -1505,9 +1551,6 @@ static void __init setup_IO_APIC_irqs(vo
 
 		irq = pin_2_irq(idx, apic_id, pin);
 
-		if ((apic_id > 0) && (irq > 16))
-			continue;
-
 		/*
 		 * Skip the timer IRQ if there's a quirk handler
 		 * installed and if it returns 1:
@@ -1541,7 +1584,7 @@ static void __init setup_IO_APIC_irqs(vo
  * but could not use acpi_register_gsi()
  * like some special sci in IBM x3330
  */
-void setup_IO_APIC_irq_extra(u32 gsi)
+void setup_IO_APIC_irq_extra(u32 gsi, unsigned int *pirq)
 {
 	int apic_id = 0, pin, idx, irq;
 	int node = cpu_to_node(boot_cpu_id);
@@ -1561,6 +1604,7 @@ void setup_IO_APIC_irq_extra(u32 gsi)
 		return;
 
 	irq = pin_2_irq(idx, apic_id, pin);
+	*pirq = irq;
 #ifdef CONFIG_SPARSE_IRQ
 	desc = irq_to_desc(irq);
 	if (desc)
@@ -2004,6 +2048,27 @@ void __init enable_IO_APIC(void)
 	clear_IO_APIC();
 }
 
+static void __init probe_ioapic_i8259(void)
+{
+	/* probe boot ioapic idx */
+	boot_ioapic_idx = ioapic_i8259.apic;
+	if (boot_ioapic_idx < 0)
+		boot_ioapic_idx = find_isa_irq_apic(0, mp_INT);
+#ifdef CONFIG_ACPI
+	if (!acpi_disabled && acpi_ioapic && boot_ioapic_idx < 0)
+		boot_ioapic_idx = mp_find_ioapic(irq_to_gsi(0));
+#endif
+	if (boot_ioapic_idx < 0)
+		boot_ioapic_idx = 0;
+
+	if (mp_gsi_routing[boot_ioapic_idx].gsi_base) {
+		gsi_delta = NR_IRQS_LEGACY;
+		nr_irqs_gsi += NR_IRQS_LEGACY;
+	}
+
+	printk(KERN_INFO "boot_ioapic_idx: %d\n", boot_ioapic_idx);
+}
+
 /*
  * Not an __init, needed by the reboot code
  */
@@ -3015,7 +3080,7 @@ static inline void __init check_timer(vo
 				enable_8259A_irq(0);
 			}
 			if (disable_timer_pin_1 > 0)
-				clear_IO_APIC_pin(0, pin1);
+				clear_IO_APIC_pin(apic1, pin1);
 			goto out;
 		}
 		if (intr_remapping_enabled)
@@ -3135,6 +3200,7 @@ void __init setup_IO_APIC(void)
 	x86_init.mpparse.setup_ioapic_ids();
 
 	sync_Arb_IDs();
+	probe_ioapic_i8259();
 	setup_IO_APIC_irqs();
 	init_IO_APIC_traps();
 	if (nr_legacy_irqs)
@@ -4108,16 +4174,14 @@ void __init setup_ioapic_dest(void)
 	if (skip_ioapic_setup == 1)
 		return;
 
-	for (ioapic = 0; ioapic < nr_ioapics; ioapic++)
+	ioapic = boot_ioapic_idx;
+
 	for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
 		irq_entry = find_irq_entry(ioapic, pin, mp_INT);
 		if (irq_entry == -1)
 			continue;
 		irq = pin_2_irq(irq_entry, ioapic, pin);
 
-		if ((ioapic > 0) && (irq > 16))
-			continue;
-
 		desc = irq_to_desc(irq);
 
 		/*
Index: linux-2.6/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- linux-2.6.orig/drivers/pnp/pnpacpi/rsparser.c
+++ linux-2.6/drivers/pnp/pnpacpi/rsparser.c
@@ -123,6 +123,14 @@ static void pnpacpi_parse_allocated_irqr
 	}
 
 	flags = irq_flags(triggering, polarity, shareable);
+#ifdef CONFIG_X86_IO_APIC
+	/*
+	 * looks like IBM x3950 is using irq instead of gsi etc...
+	 * convert it back at first
+	 */
+	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
+		gsi = irq_to_gsi(gsi);
+#endif
 	irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
 	if (irq >= 0)
 		pcibios_penalize_isa_irq(irq, 1);

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [tip:x86/apic] x86: Fix out of order of gsi
  2010-02-28  9:06                             ` [PATCH -v12 1/2] " Yinghai Lu
@ 2010-02-28 19:51                               ` tip-bot for Eric W. Biederman
  0 siblings, 0 replies; 34+ messages in thread
From: tip-bot for Eric W. Biederman @ 2010-02-28 19:51 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, hpa, mingo, yinghai, ebiederm, garyhade,
	suresh.b.siddha, iranna.ankad, tglx, trenn, mingo

Commit-ID:  fad539956c9e69749a03f7817d22d1bab87657bf
Gitweb:     http://git.kernel.org/tip/fad539956c9e69749a03f7817d22d1bab87657bf
Author:     Eric W. Biederman <ebiederm@xmission.com>
AuthorDate: Sun, 28 Feb 2010 01:06:34 -0800
Committer:  Ingo Molnar <mingo@elte.hu>
CommitDate: Sun, 28 Feb 2010 10:33:25 +0100

x86: Fix out of order of gsi

Iranna D Ankad reported that IBM x3950 systems have boot
problems after this commit:

 |
 | commit b9c61b70075c87a8612624736faf4a2de5b1ed30
 |
 |    x86/pci: update pirq_enable_irq() to setup io apic routing
 |

The problem is that with the patch, the machine freezes when
console=ttyS0,... kernel serial parameter is passed.

It seem to freeze at DVD initialization and the whole problem
seem to be DVD/pata related, but somehow exposed through the
serial parameter.

Such apic problems can expose really weird behavior:

  ACPI: IOAPIC (id[0x10] address[0xfecff000] gsi_base[0])
  IOAPIC[0]: apic_id 16, version 0, address 0xfecff000, GSI 0-2
  ACPI: IOAPIC (id[0x0f] address[0xfec00000] gsi_base[3])
  IOAPIC[1]: apic_id 15, version 0, address 0xfec00000, GSI 3-38
  ACPI: IOAPIC (id[0x0e] address[0xfec01000] gsi_base[39])
  IOAPIC[2]: apic_id 14, version 0, address 0xfec01000, GSI 39-74
  ACPI: INT_SRC_OVR (bus 0 bus_irq 1 global_irq 4 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 5 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 3 global_irq 6 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 4 global_irq 7 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 6 global_irq 9 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 7 global_irq 10 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 8 global_irq 11 low edge)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 12 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 12 global_irq 15 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 13 global_irq 16 dfl dfl)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 14 global_irq 17 low edge)
  ACPI: INT_SRC_OVR (bus 0 bus_irq 15 global_irq 18 dfl dfl)

It turns out that the system has three io apic controllers, but
boot ioapic routing is in the second one, and that gsi_base is
not 0 - it is using a bunch of INT_SRC_OVR...

So these recent changes:

 1. one set routing for first io apic controller
 2. assume irq = gsi

... will break that system.

So try to remap those gsis, need to seperate boot_ioapic_idx
detection out of enable_IO_APIC() and call them early.

So introduce boot_ioapic_idx, and remap_ioapic_gsi()...

 -v2: shift gsi with delta instead of gsi_base of boot_ioapic_idx

 -v3: double check with find_isa_irq_apic(0, mp_INT) to get right
      boot_ioapic_idx

 -v4: nr_legacy_irqs

 -v5: add print out for boot_ioapic_idx, and also make it could be
      applied for current kernel and previous kernel

 -v6: add bus_irq, in acpi_sci_ioapic_setup, so can get overwride
      for sci right mapping...

 -v7: looks like pnpacpi get irq instead of gsi, so need to revert
      them back...

 -v8: split into two patches

 -v9: according to Eric, use fixed 16 for shifting instead of remap

 -v10: still need to touch rsparser.c

 -v11: just revert back to way Eric suggest...
      anyway the ioapic in first ioapic is blocked by second...

 -v12: two patches, this one will add more loop but check apic_id and irq > 16

Reported-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Bisected-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Tested-by: Gary Hade <garyhade@us.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Thomas Renninger <trenn@suse.de>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: len.brown@intel.com
LKML-Reference: <4B8A321A.1000008@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/x86/kernel/apic/io_apic.c |   28 ++++++++++------------------
 1 files changed, 10 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 72ac2a3..97e1e3e 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -1475,7 +1475,7 @@ static struct {
 
 static void __init setup_IO_APIC_irqs(void)
 {
-	int apic_id = 0, pin, idx, irq;
+	int apic_id, pin, idx, irq;
 	int notcon = 0;
 	struct irq_desc *desc;
 	struct irq_cfg *cfg;
@@ -1483,14 +1483,7 @@ static void __init setup_IO_APIC_irqs(void)
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		apic_id = mp_find_ioapic(0);
-		if (apic_id < 0)
-			apic_id = 0;
-	}
-#endif
-
+	for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
 	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
 		idx = find_irq_entry(apic_id, pin, mp_INT);
 		if (idx == -1) {
@@ -1512,6 +1505,9 @@ static void __init setup_IO_APIC_irqs(void)
 
 		irq = pin_2_irq(idx, apic_id, pin);
 
+		if ((apic_id > 0) && (irq > 16))
+			continue;
+
 		/*
 		 * Skip the timer IRQ if there's a quirk handler
 		 * installed and if it returns 1:
@@ -4105,27 +4101,23 @@ int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
 #ifdef CONFIG_SMP
 void __init setup_ioapic_dest(void)
 {
-	int pin, ioapic = 0, irq, irq_entry;
+	int pin, ioapic, irq, irq_entry;
 	struct irq_desc *desc;
 	const struct cpumask *mask;
 
 	if (skip_ioapic_setup == 1)
 		return;
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		ioapic = mp_find_ioapic(0);
-		if (ioapic < 0)
-			ioapic = 0;
-	}
-#endif
-
+	for (ioapic = 0; ioapic < nr_ioapics; ioapic++)
 	for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
 		irq_entry = find_irq_entry(ioapic, pin, mp_INT);
 		if (irq_entry == -1)
 			continue;
 		irq = pin_2_irq(irq_entry, ioapic, pin);
 
+		if ((ioapic > 0) && (irq > 16))
+			continue;
+
 		desc = irq_to_desc(irq);
 
 		/*

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* Re: [PATCH -v11] x86: fix out of order of gsi -- partial
  2010-02-28  9:05                             ` Yinghai Lu
@ 2010-03-01 14:40                               ` Thomas Renninger
  2010-03-01 18:31                                 ` Yinghai Lu
  0 siblings, 1 reply; 34+ messages in thread
From: Thomas Renninger @ 2010-03-01 14:40 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Ingo Molnar, Eric W. Biederman, hpa, garyhade, tglx,
	linux-tip-commits, linux-kernel, mingo, iranna.ankad,
	suresh.b.siddha

On Sunday 28 February 2010 10:05:33 Yinghai Lu wrote:
> On 02/28/2010 12:09 AM, Ingo Molnar wrote:
> > 
> > * Yinghai Lu <yinghai@kernel.org> wrote:
> > 
> >> From: Eric W. Biederman <ebiederm@xmission.com>
> >>
> >> found IBM x3950 will have problem after
> >>
> >> |commit b9c61b70075c87a8612624736faf4a2de5b1ed30
> > 
> > Have you seen the commit notifications i sent for the v8 patches:
> > 
> > Commit-ID:  ca8c764cb39bf6cade71933b38e8c830eb8b73c6
> > Commit-ID:  519d637a93116ffbcd50e9e3f2591f41584f372c
> > 
> > Those include a much improved changelogs - please adopt those. (and preferably 
> > send deltas against tip:tmp.x86/apic.)
> 
> please drop those two.
>  
> will send v12 to you.
Eh, not sure, but could it be Ingo forgot the 2nd
part of v12?

In linux-2.6-tip I see:
commit fad539956c9e69749a03f7817d22d1bab87657bf
Author: Eric W. Biederman <ebiederm@xmission.com>
Date:   Sun Feb 28 01:06:34 2010 -0800

    x86: Fix out of order of gsi

which equals:
[PATCH -v12 1/2] x86: fix out of order of gsi -- partial

but I cannot see:
[PATCH -v12 2/2] x86: fix out of order of gsi - full

Also this machine booted/worked fine up to 2.6.30.
Any chance this will get addressed in stable@ kernel(s)?

Thanks,

   Thomas

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [LKML] Re: [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
  2010-02-27 21:30                   ` Eric W. Biederman
  2010-02-27 22:00                     ` Yinghai Lu
@ 2010-03-01 16:46                     ` Konrad Rzeszutek Wilk
  2010-03-01 18:37                       ` Yinghai Lu
  2010-03-01 18:44                       ` Eric W. Biederman
  1 sibling, 2 replies; 34+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-03-01 16:46 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Yinghai Lu, Ingo Molnar, linux-tip-commits, linux-kernel, hpa,
	mingo, garyhade, iranna.ankad, suresh.b.siddha, tglx, trenn

> 
> > so far this patch only affect (fix ) x3950.

.. snip ..
> > other solution will ask IBM to fix their bios, so we can get

It isn't just IBM. Asus P2B-D (PIIX4) and SuperMicro X8DAL (possibly)
seem to have the same issue.

(http://lists.xensource.com/archives/html/xen-devel/2010-02/msg00715.html)
and
(http://lists.xensource.com/archives/html/xen-devel/2010-02/msg01239.html)

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH -v11] x86: fix out of order of gsi -- partial
  2010-03-01 14:40                               ` Thomas Renninger
@ 2010-03-01 18:31                                 ` Yinghai Lu
  0 siblings, 0 replies; 34+ messages in thread
From: Yinghai Lu @ 2010-03-01 18:31 UTC (permalink / raw)
  To: Thomas Renninger
  Cc: Ingo Molnar, Eric W. Biederman, hpa, garyhade, tglx,
	linux-tip-commits, linux-kernel, mingo, iranna.ankad,
	suresh.b.siddha

On 03/01/2010 06:40 AM, Thomas Renninger wrote:
> On Sunday 28 February 2010 10:05:33 Yinghai Lu wrote:
>> On 02/28/2010 12:09 AM, Ingo Molnar wrote:
>>>
>>> * Yinghai Lu <yinghai@kernel.org> wrote:
>>>
>>>> From: Eric W. Biederman <ebiederm@xmission.com>
>>>>
>>>> found IBM x3950 will have problem after
>>>>
>>>> |commit b9c61b70075c87a8612624736faf4a2de5b1ed30
>>>
>>> Have you seen the commit notifications i sent for the v8 patches:
>>>
>>> Commit-ID:  ca8c764cb39bf6cade71933b38e8c830eb8b73c6
>>> Commit-ID:  519d637a93116ffbcd50e9e3f2591f41584f372c
>>>
>>> Those include a much improved changelogs - please adopt those. (and preferably 
>>> send deltas against tip:tmp.x86/apic.)
>>
>> please drop those two.
>>  
>> will send v12 to you.
> Eh, not sure, but could it be Ingo forgot the 2nd
> part of v12?
> 
> In linux-2.6-tip I see:
> commit fad539956c9e69749a03f7817d22d1bab87657bf
> Author: Eric W. Biederman <ebiederm@xmission.com>
> Date:   Sun Feb 28 01:06:34 2010 -0800
> 
>     x86: Fix out of order of gsi
> 
> which equals:
> [PATCH -v12 1/2] x86: fix out of order of gsi -- partial
> 
> but I cannot see:
> [PATCH -v12 2/2] x86: fix out of order of gsi - full
> 
> Also this machine booted/worked fine up to 2.6.30.
> Any chance this will get addressed in stable@ kernel(s)?
> 

patch 1/2: should be with stable@ #.32 and #.33

patch 2/2: could be only with 2.6.34 or 2.6.35

Thanks

Yinghai

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [LKML] Re: [LKML] Re: [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
  2010-03-01 18:44                       ` Eric W. Biederman
@ 2010-03-01 18:33                         ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 34+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-03-01 18:33 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Yinghai Lu, Ingo Molnar, linux-tip-commits, linux-kernel, hpa,
	mingo, garyhade, iranna.ankad, suresh.b.siddha, tglx, trenn

On Mon, Mar 01, 2010 at 10:44:23AM -0800, Eric W. Biederman wrote:
> Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> writes:
> 
> >> 
> >> > so far this patch only affect (fix ) x3950.
> >
> > .. snip ..
> >> > other solution will ask IBM to fix their bios, so we can get
> >
> > It isn't just IBM. Asus P2B-D (PIIX4) and SuperMicro X8DAL (possibly)
> > seem to have the same issue.
> >
> > (http://lists.xensource.com/archives/html/xen-devel/2010-02/msg00715.html)
> > and
> > (http://lists.xensource.com/archives/html/xen-devel/2010-02/msg01239.html)
> 
> I can't find the reference to those boards in the email you quoted.  Xen

Might have to hit the past button a couple of times. Anyway, here is the
first description of the problem:
http://lists.xensource.com/archives/html/xen-devel/2010-01/msg01049.html

and the board name.

> does strange and very different things with it's irqs so it is unlikely to
> be the same issue.

I think I am confusing the patches. Adding in this patch:

[PATCH 01/35] x86: fix sci on ioapic 1 which was posted by Yinghai Lu on
Feb 9th fixed the issue with the ASUS board.

and the discussion here is for a different patch, so I think I am
raising unnecessary noise here - sorry about that.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [LKML] Re: [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
  2010-03-01 16:46                     ` [LKML] " Konrad Rzeszutek Wilk
@ 2010-03-01 18:37                       ` Yinghai Lu
  2010-03-01 18:44                       ` Eric W. Biederman
  1 sibling, 0 replies; 34+ messages in thread
From: Yinghai Lu @ 2010-03-01 18:37 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Eric W. Biederman, Ingo Molnar, linux-tip-commits, linux-kernel,
	hpa, mingo, garyhade, iranna.ankad, suresh.b.siddha, tglx, trenn

On 03/01/2010 08:46 AM, Konrad Rzeszutek Wilk wrote:
>>
>>> so far this patch only affect (fix ) x3950.
> 
> .. snip ..
>>> other solution will ask IBM to fix their bios, so we can get
> 
> It isn't just IBM. Asus P2B-D (PIIX4) and SuperMicro X8DAL (possibly)
> seem to have the same issue.
> 
> (http://lists.xensource.com/archives/html/xen-devel/2010-02/msg00715.html)
> and
> (http://lists.xensource.com/archives/html/xen-devel/2010-02/msg01239.html)

looks it is different...
their ioapic is sane...

ACPI: IOAPIC (id[0x08] address[0xfec00000] gsi_base[0])
IOAPIC[0]: apic_id 8, version 32, address 0xfec00000, GSI 0-23
ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low level)

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [LKML] Re: [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
  2010-03-01 16:46                     ` [LKML] " Konrad Rzeszutek Wilk
  2010-03-01 18:37                       ` Yinghai Lu
@ 2010-03-01 18:44                       ` Eric W. Biederman
  2010-03-01 18:33                         ` [LKML] " Konrad Rzeszutek Wilk
  1 sibling, 1 reply; 34+ messages in thread
From: Eric W. Biederman @ 2010-03-01 18:44 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Yinghai Lu, Ingo Molnar, linux-tip-commits, linux-kernel, hpa,
	mingo, garyhade, iranna.ankad, suresh.b.siddha, tglx, trenn

Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> writes:

>> 
>> > so far this patch only affect (fix ) x3950.
>
> .. snip ..
>> > other solution will ask IBM to fix their bios, so we can get
>
> It isn't just IBM. Asus P2B-D (PIIX4) and SuperMicro X8DAL (possibly)
> seem to have the same issue.
>
> (http://lists.xensource.com/archives/html/xen-devel/2010-02/msg00715.html)
> and
> (http://lists.xensource.com/archives/html/xen-devel/2010-02/msg01239.html)

I can't find the reference to those boards in the email you quoted.  Xen
does strange and very different things with it's irqs so it is unlikely to
be the same issue.

Eric

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH -v12 2/2] x86: fix out of order of gsi - full
  2010-02-28  9:08                             ` [PATCH -v12 2/2] x86: fix out of order of gsi - full Yinghai Lu
@ 2010-03-01 18:59                               ` Eric W. Biederman
  0 siblings, 0 replies; 34+ messages in thread
From: Eric W. Biederman @ 2010-03-01 18:59 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Ingo Molnar, hpa, garyhade, tglx, linux-tip-commits,
	linux-kernel, mingo, iranna.ankad, suresh.b.siddha, trenn

Yinghai Lu <yinghai@kernel.org> writes:

> Iranna D Ankad reported that IBM x3950 systems have boot problems
> after this commit:
>
>  |
>  | commit b9c61b70075c87a8612624736faf4a2de5b1ed30
>  |
>  |    x86/pci: update pirq_enable_irq() to setup io apic routing
>  |
>
>     As explained in the previous patch ("x86: Fix out of order gsi - partial)
>     try to remap those gsis
>
>     This patch adds boot_ioapic_idx and gsi_to_irq/irq_to_gsi


A couple of nits, that we will eventually want to fix.

> Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
> ===================================================================
> --- linux-2.6.orig/arch/x86/kernel/apic/io_apic.c
> +++ linux-2.6/arch/x86/kernel/apic/io_apic.c
> @@ -97,6 +97,41 @@ int mp_irq_entries;
>  /* GSI interrupts */
>  static int nr_irqs_gsi = NR_IRQS_LEGACY;
>  
> +/* By default isa irqs are identity mapped to gsis */
> +unsigned int isa_irq_to_gsi[NR_IRQS_LEGACY] = {
> +	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
> +};
> +
> +static int boot_ioapic_idx;
> +static int gsi_delta;
> +int gsi_to_irq(unsigned int gsi)
> +{
> +	unsigned int irq = gsi;
> +	unsigned int i;
> +
> +	irq += gsi_delta;
> +	for (i = 0; i < NR_IRQS_LEGACY; i++) {
> +		if (isa_irq_to_gsi[i] == gsi) {
> +			irq = i;
> +			break;
> +		}
> +	}
> +
> +	return irq;
> +}
> +
> +unsigned int irq_to_gsi(int irq)
> +{
> +	unsigned int gsi;
> +
> +	if (irq < NR_IRQS_LEGACY)
> +		gsi = isa_irq_to_gsi[irq];
> +	else
> +		gsi = irq - gsi_delta;
> +
> +	return gsi;
> +}

This should really live in arch/x86/kernel/acpi/boot.c or similar as
it has everything to do with acpi and gsis and nothing to do with the
ioapics.

Not this merge window, but ultimately we want a fixed value of 16 for
gsi_delta, and we want to always use it.  This has a greater chance of
breaking things but it will ensure in the long run that we flush out
every place that actually needs translation from irqs to gsis.

> Index: linux-2.6/drivers/pnp/pnpacpi/rsparser.c
> ===================================================================
> --- linux-2.6.orig/drivers/pnp/pnpacpi/rsparser.c
> +++ linux-2.6/drivers/pnp/pnpacpi/rsparser.c
> @@ -123,6 +123,14 @@ static void pnpacpi_parse_allocated_irqr
>  	}
>  
>  	flags = irq_flags(triggering, polarity, shareable);
> +#ifdef CONFIG_X86_IO_APIC
> +	/*
> +	 * looks like IBM x3950 is using irq instead of gsi etc...
> +	 * convert it back at first
> +	 */
> +	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
> +		gsi = irq_to_gsi(gsi);
> +#endif

I would like to understand this better.  I suspect the actual problem
is that we are getting passed bus_irq instead of gsi from acpi.  If we
are getting passed the bus_irq than doing this just for x3950 is wrong.

I really dislike having special cases for a specific motherboard.  Both
because they are hard to maintain (as quickly no one has that board) and
because may times they are a symptom of a bug elsewhere in the code
that we are trying to patch over instead of actually fix properly.

>  	irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
>  	if (irq >= 0)
>  		pcibios_penalize_isa_irq(irq, 1);

Eric

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
  2010-02-27 22:00                     ` Yinghai Lu
  2010-02-27 22:18                       ` Eric W. Biederman
@ 2010-03-01 19:37                       ` Eric W. Biederman
  2010-03-01 20:26                         ` Yinghai Lu
  1 sibling, 1 reply; 34+ messages in thread
From: Eric W. Biederman @ 2010-03-01 19:37 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Ingo Molnar, linux-tip-commits, linux-kernel, hpa, mingo,
	garyhade, iranna.ankad, suresh.b.siddha, tglx, trenn


>> /* By default isa irqs are identity mapped to gsis */
>> unsigned int isa_irq_to_gsi[16] = {
>> 	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
>> };
>> 
>> unsigned int gsi_to_irq(unsigned int gsi)
>> {
>> 	unsigned int irq = gsi + 16;
>> 	unsigned int i;
>> 	for (i = 0; i < 16; i++) {
>> 		if (isa_irq_to_gsi[i] == gsi)
>> 			irq = i;
>> 	}
>> 	return irq;
>> }

I just realized that we already have this function in
arch/x86/kernel/acpi/boot.c and arch/ia64/kernel/acpi.c it is called:
acpi_gsi_to_irq()

We still need this implementation but it will get really confusing if
we have two functions with the same name trying to do the same job.

I am relieved to see this because this should mean we shouldn't have
many hard fixed assumptions that irq == gsi.

This does mean though that your patch has a real bug in it because
you have not updated acpi_gsi_to_irq.

Eric

>> unsigned int irq_to_gsi(unsigned int irq)
>> {
>> 	unsigned int gsi;
>> 	if (irq < 16) {
>> 		gsi = isa_irq_to_gsi[irq];
>> 	} else {
>>         	gsi = irq - 16;
>>         }
>>         return gsi;
>> }

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq()
  2010-03-01 19:37                       ` [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq() Eric W. Biederman
@ 2010-03-01 20:26                         ` Yinghai Lu
  0 siblings, 0 replies; 34+ messages in thread
From: Yinghai Lu @ 2010-03-01 20:26 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Ingo Molnar, linux-tip-commits, linux-kernel, hpa, mingo,
	garyhade, iranna.ankad, suresh.b.siddha, tglx, trenn

please check

i still like to see gsi_delta to be 0 for sane system.

Thanks

Yinghai

Subject: [PATCH -v13] x86: fix out of order of gsi - full

Iranna D Ankad reported that IBM x3950 systems have boot problems
after this commit:

 |
 | commit b9c61b70075c87a8612624736faf4a2de5b1ed30
 |
 |    x86/pci: update pirq_enable_irq() to setup io apic routing
 |
  ACPI: IOAPIC (id[0x10] address[0xfecff000] gsi_base[0])
  IOAPIC[0]: apic_id 16, version 0, address 0xfecff000, GSI 0-2
  ACPI: IOAPIC (id[0x0f] address[0xfec00000] gsi_base[3])
  IOAPIC[1]: apic_id 15, version 0, address 0xfec00000, GSI 3-38
  ACPI: IOAPIC (id[0x0e] address[0xfec01000] gsi_base[39])
  IOAPIC[2]: apic_id 14, version 0, address 0xfec01000, GSI 39-74

  As explained in the previous patch ("x86: Fix out of order gsi)

  need to remap those gsis

  This patch adds boot_ioapic_idx and gsi_to_irq/irq_to_gsi
  So we could make sure for those kind of system will have
        irq: 0 - 15 for legacy irq
        irq:  16 after will be gsi + 16

 -v13: move gsi_to_irq/irq_to_gsi to acpi/boot.c

Reported-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Bisected-by: Iranna D Ankad <iranna.ankad@in.ibm.com>
Tested-by: Gary Hade <garyhade@us.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Thomas Renninger <trenn@suse.de>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: len.brown@intel.com


---
 arch/x86/include/asm/io_apic.h |    2 -
 arch/x86/include/asm/mpspec.h  |   12 +++++++
 arch/x86/kernel/acpi/boot.c    |   64 +++++++++++++++++++++++++++++++------
 arch/x86/kernel/apic/io_apic.c |   70 +++++++++++++++++++++++++++++------------
 drivers/pnp/pnpacpi/rsparser.c |    4 ++
 5 files changed, 121 insertions(+), 31 deletions(-)

Index: linux-2.6/arch/x86/include/asm/io_apic.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/io_apic.h
+++ linux-2.6/arch/x86/include/asm/io_apic.h
@@ -158,7 +158,7 @@ extern int io_apic_get_redir_entries(int
 struct io_apic_irq_attr;
 extern int io_apic_set_pci_routing(struct device *dev, int irq,
 		 struct io_apic_irq_attr *irq_attr);
-void setup_IO_APIC_irq_extra(u32 gsi);
+void setup_IO_APIC_irq_extra(u32 gsi, unsigned int *irq);
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
 extern void ioapic_init_mappings(void);
 extern void ioapic_insert_resources(void);
Index: linux-2.6/arch/x86/include/asm/mpspec.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/mpspec.h
+++ linux-2.6/arch/x86/include/asm/mpspec.h
@@ -97,6 +97,7 @@ static inline void early_reserve_e820_mp
 #endif
 
 void __cpuinit generic_processor_info(int apicid, int version);
+extern int gsi_delta;
 #ifdef CONFIG_ACPI
 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,
@@ -106,6 +107,8 @@ 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);
+int gsi_to_irq(unsigned int gsi);
+unsigned int irq_to_gsi(int irq);
 #ifdef CONFIG_X86_IO_APIC
 extern int mp_find_ioapic(int gsi);
 extern int mp_find_ioapic_pin(int ioapic, int gsi);
@@ -115,6 +118,15 @@ static inline int acpi_probe_gsi(void)
 {
 	return 0;
 }
+static inline int gsi_to_irq(unsigned int gsi)
+{
+	return gsi;
+}
+static inline unsigned int irq_to_gsi(int irq)
+{
+	return irq;
+}
+
 #endif /* CONFIG_ACPI */
 
 #define PHYSID_ARRAY_SIZE	BITS_TO_LONGS(MAX_APICS)
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/acpi/boot.c
+++ linux-2.6/arch/x86/kernel/acpi/boot.c
@@ -311,7 +311,8 @@ acpi_parse_ioapic(struct acpi_subtable_h
 /*
  * Parse Interrupt Source Override for the ACPI SCI
  */
-static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
+static void __init
+acpi_sci_ioapic_setup(u8 bus_irq, u32 gsi, u16 polarity, u16 trigger)
 {
 	if (trigger == 0)	/* compatible SCI trigger is level */
 		trigger = 3;
@@ -331,7 +332,7 @@ static void __init acpi_sci_ioapic_setup
 	 * If GSI is < 16, this will update its flags,
 	 * else it will create a new mp_irqs[] entry.
 	 */
-	mp_override_legacy_irq(gsi, polarity, trigger, gsi);
+	mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
 
 	/*
 	 * stash over-ride to indicate we've been here
@@ -355,7 +356,8 @@ acpi_parse_int_src_ovr(struct acpi_subta
 	acpi_table_print_madt_entry(header);
 
 	if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) {
-		acpi_sci_ioapic_setup(intsrc->global_irq,
+		acpi_sci_ioapic_setup(intsrc->source_irq,
+				      intsrc->global_irq,
 				      intsrc->inti_flags & ACPI_MADT_POLARITY_MASK,
 				      (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2);
 		return 0;
@@ -446,11 +448,11 @@ void __init acpi_pic_sci_set_trigger(uns
 
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 {
-	*irq = gsi;
+	*irq = gsi_to_irq(gsi);
 
 #ifdef CONFIG_X86_IO_APIC
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
-		setup_IO_APIC_irq_extra(gsi);
+		setup_IO_APIC_irq_extra(gsi, irq);
 #endif
 
 	return 0;
@@ -914,6 +916,40 @@ static void save_mp_irq(struct mpc_intsr
 		panic("Max # of irq sources exceeded!!\n");
 }
 
+/* By default isa irqs are identity mapped to gsis */
+static unsigned int isa_irq_to_gsi[NR_IRQS_LEGACY] = {
+	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+};
+
+int gsi_delta;
+int gsi_to_irq(unsigned int gsi)
+{
+	unsigned int irq = gsi;
+	unsigned int i;
+
+	irq += gsi_delta;
+	for (i = 0; i < NR_IRQS_LEGACY; i++) {
+		if (isa_irq_to_gsi[i] == gsi) {
+			irq = i;
+			break;
+		}
+	}
+
+	return irq;
+}
+
+unsigned int irq_to_gsi(int irq)
+{
+	unsigned int gsi;
+
+	if (irq < NR_IRQS_LEGACY)
+		gsi = isa_irq_to_gsi[irq];
+	else
+		gsi = irq - gsi_delta;
+
+	return gsi;
+}
+
 void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
 {
 	int ioapic;
@@ -945,6 +981,8 @@ void __init mp_override_legacy_irq(u8 bu
 	mp_irq.dstirq = pin;	/* INTIN# */
 
 	save_mp_irq(&mp_irq);
+
+	isa_irq_to_gsi[bus_irq] = gsi;
 }
 
 void __init mp_config_acpi_legacy_irqs(void)
@@ -974,7 +1012,7 @@ void __init mp_config_acpi_legacy_irqs(v
 	/*
 	 * Locate the IOAPIC that manages the ISA IRQs (0-15).
 	 */
-	ioapic = mp_find_ioapic(0);
+	ioapic = mp_find_ioapic(irq_to_gsi(0));
 	if (ioapic < 0)
 		return;
 	dstapic = mp_ioapics[ioapic].apicid;
@@ -1057,6 +1095,7 @@ int mp_register_gsi(struct device *dev,
 {
 	int ioapic;
 	int ioapic_pin;
+	int irq;
 	struct io_apic_irq_attr irq_attr;
 
 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
@@ -1079,11 +1118,12 @@ int mp_register_gsi(struct device *dev,
 		gsi = ioapic_renumber_irq(ioapic, gsi);
 #endif
 
+	irq = gsi_to_irq(gsi);
 	if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
 		printk(KERN_ERR "Invalid reference to IOAPIC pin "
 		       "%d-%d\n", mp_ioapics[ioapic].apicid,
 		       ioapic_pin);
-		return gsi;
+		return irq;
 	}
 
 	if (enable_update_mptable)
@@ -1092,9 +1132,9 @@ int mp_register_gsi(struct device *dev,
 	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);
+	io_apic_set_pci_routing(dev, irq, &irq_attr);
 
-	return gsi;
+	return irq;
 }
 
 /*
@@ -1151,8 +1191,10 @@ static int __init acpi_parse_madt_ioapic
 	 * If BIOS did not supply an INT_SRC_OVR for the SCI
 	 * pretend we got one so we can set the SCI flags.
 	 */
-	if (!acpi_sci_override_gsi)
-		acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0);
+	if (!acpi_sci_override_gsi) {
+		int irq = gsi_to_irq(acpi_gbl_FADT.sci_interrupt);
+		acpi_sci_ioapic_setup(irq, acpi_gbl_FADT.sci_interrupt, 0, 0);
+	}
 
 	/* Fill in identity legacy mappings where no override */
 	mp_config_acpi_legacy_irqs();
Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/apic/io_apic.c
+++ linux-2.6/arch/x86/kernel/apic/io_apic.c
@@ -97,6 +97,8 @@ int mp_irq_entries;
 /* GSI interrupts */
 static int nr_irqs_gsi = NR_IRQS_LEGACY;
 
+static int boot_ioapic_idx;
+
 #if defined (CONFIG_MCA) || defined (CONFIG_EISA)
 int mp_bus_id_to_type[MAX_MP_BUSSES];
 #endif
@@ -1015,7 +1017,7 @@ static inline int irq_trigger(int idx)
 int (*ioapic_renumber_irq)(int ioapic, int irq);
 static int pin_2_irq(int idx, int apic, int pin)
 {
-	int irq, i;
+	int irq;
 	int bus = mp_irqs[idx].srcbus;
 
 	/*
@@ -1027,18 +1029,28 @@ static int pin_2_irq(int idx, int apic,
 	if (test_bit(bus, mp_bus_not_pci)) {
 		irq = mp_irqs[idx].srcbusirq;
 	} else {
-		/*
-		 * PCI IRQs are mapped in order
-		 */
-		i = irq = 0;
-		while (i < apic)
-			irq += nr_ioapic_registers[i++];
-		irq += pin;
+		unsigned int gsi;
+		if (!acpi_ioapic) {
+			int i;
+			/*
+			 * PCI IRQs are mapped in order
+			 */
+			i = gsi = 0;
+			while (i < apic)
+				gsi += nr_ioapic_registers[i++];
+			gsi += pin;
+		} else
+			gsi = pin + mp_gsi_routing[apic].gsi_base;
+
+#ifdef CONFIG_X86_32
 		/*
                  * For MPS mode, so far only needed by ES7000 platform
                  */
 		if (ioapic_renumber_irq)
-			irq = ioapic_renumber_irq(apic, irq);
+			gsi = ioapic_renumber_irq(apic, gsi);
+#endif
+
+		irq = gsi_to_irq(gsi);
 	}
 
 #ifdef CONFIG_X86_32
@@ -1480,9 +1492,10 @@ static void __init setup_IO_APIC_irqs(vo
 	struct irq_cfg *cfg;
 	int node = cpu_to_node(boot_cpu_id);
 
+	apic_id = boot_ioapic_idx;
+
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
-	for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
 	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
 		idx = find_irq_entry(apic_id, pin, mp_INT);
 		if (idx == -1) {
@@ -1504,9 +1517,6 @@ static void __init setup_IO_APIC_irqs(vo
 
 		irq = pin_2_irq(idx, apic_id, pin);
 
-		if ((apic_id > 0) && (irq > 16))
-			continue;
-
 		/*
 		 * Skip the timer IRQ if there's a quirk handler
 		 * installed and if it returns 1:
@@ -1540,7 +1550,7 @@ static void __init setup_IO_APIC_irqs(vo
  * but could not use acpi_register_gsi()
  * like some special sci in IBM x3330
  */
-void setup_IO_APIC_irq_extra(u32 gsi)
+void setup_IO_APIC_irq_extra(u32 gsi, unsigned int *pirq)
 {
 	int apic_id = 0, pin, idx, irq;
 	int node = cpu_to_node(boot_cpu_id);
@@ -1560,6 +1570,7 @@ void setup_IO_APIC_irq_extra(u32 gsi)
 		return;
 
 	irq = pin_2_irq(idx, apic_id, pin);
+	*pirq = irq;
 #ifdef CONFIG_SPARSE_IRQ
 	desc = irq_to_desc(irq);
 	if (desc)
@@ -2003,6 +2014,28 @@ void __init enable_IO_APIC(void)
 	clear_IO_APIC();
 }
 
+static void __init probe_ioapic_i8259(void)
+{
+	/* probe boot ioapic idx */
+	boot_ioapic_idx = ioapic_i8259.apic;
+	if (boot_ioapic_idx < 0)
+		boot_ioapic_idx = find_isa_irq_apic(0, mp_INT);
+#ifdef CONFIG_ACPI
+	if (!acpi_disabled && acpi_ioapic && boot_ioapic_idx < 0)
+		boot_ioapic_idx = mp_find_ioapic(irq_to_gsi(0));
+#endif
+	if (boot_ioapic_idx < 0)
+		boot_ioapic_idx = 0;
+
+	if (mp_gsi_routing[boot_ioapic_idx].gsi_base) {
+		gsi_delta = NR_IRQS_LEGACY;
+		nr_irqs_gsi += NR_IRQS_LEGACY;
+		printk(KERN_DEBUG "new nr_irqs_gsi: %d\n", nr_irqs_gsi);
+	}
+
+	printk(KERN_INFO "boot_ioapic_idx: %d\n", boot_ioapic_idx);
+}
+
 /*
  * Not an __init, needed by the reboot code
  */
@@ -3014,7 +3047,7 @@ static inline void __init check_timer(vo
 				legacy_pic->chip->unmask(0);
 			}
 			if (disable_timer_pin_1 > 0)
-				clear_IO_APIC_pin(0, pin1);
+				clear_IO_APIC_pin(apic1, pin1);
 			goto out;
 		}
 		if (intr_remapping_enabled)
@@ -3134,6 +3167,7 @@ void __init setup_IO_APIC(void)
 	x86_init.mpparse.setup_ioapic_ids();
 
 	sync_Arb_IDs();
+	probe_ioapic_i8259();
 	setup_IO_APIC_irqs();
 	init_IO_APIC_traps();
 	if (legacy_pic->nr_legacy_irqs)
@@ -4107,16 +4141,14 @@ void __init setup_ioapic_dest(void)
 	if (skip_ioapic_setup == 1)
 		return;
 
-	for (ioapic = 0; ioapic < nr_ioapics; ioapic++)
+	ioapic = boot_ioapic_idx;
+
 	for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
 		irq_entry = find_irq_entry(ioapic, pin, mp_INT);
 		if (irq_entry == -1)
 			continue;
 		irq = pin_2_irq(irq_entry, ioapic, pin);
 
-		if ((ioapic > 0) && (irq > 16))
-			continue;
-
 		desc = irq_to_desc(irq);
 
 		/*
Index: linux-2.6/drivers/pnp/pnpacpi/rsparser.c
===================================================================
--- linux-2.6.orig/drivers/pnp/pnpacpi/rsparser.c
+++ linux-2.6/drivers/pnp/pnpacpi/rsparser.c
@@ -123,6 +123,10 @@ static void pnpacpi_parse_allocated_irqr
 	}
 
 	flags = irq_flags(triggering, polarity, shareable);
+#ifdef CONFIG_X86
+	/* bus_irq or gsi ? */
+	gsi = irq_to_gsi(gsi);
+#endif
 	irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
 	if (irq >= 0)
 		pcibios_penalize_isa_irq(irq, 1);

^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2010-03-01 20:28 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <201002221108.42847.trenn@suse.de>
     [not found] ` <4B826CA6.7060007@kernel.org>
     [not found]   ` <201002221258.38506.trenn@suse.de>
2010-02-23  9:07     ` Other problem/regression with b9c61b70075c87a8612624736faf4a2de5b1ed30 Yinghai Lu
2010-02-23 18:40       ` Yinghai Lu
2010-02-23 20:17         ` Eric W. Biederman
2010-02-26 19:30         ` [PATCH -v8 1/2] x86: fix out of order of gsi - have right boot_ioapic_idx Yinghai Lu
2010-02-27 12:57           ` [tip:x86/apic] x86: Fix out of order gsi - have the " tip-bot for Yinghai Lu
2010-02-26 19:31         ` [PATCH -v8 2/2] x86: fix out of order of gsi -- add remap_ioapic_gsi_to_irq Yinghai Lu
2010-02-27 12:57           ` [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq() tip-bot for Yinghai Lu
2010-02-27 13:01             ` Ingo Molnar
2010-02-27 18:52               ` Yinghai Lu
2010-02-27 22:57                 ` H. Peter Anvin
2010-02-27 19:04               ` Eric W. Biederman
2010-02-27 19:40                 ` Yinghai Lu
2010-02-27 21:30                   ` Eric W. Biederman
2010-02-27 22:00                     ` Yinghai Lu
2010-02-27 22:18                       ` Eric W. Biederman
2010-02-27 22:58                         ` Yinghai Lu
2010-02-28  1:12                         ` [PATCH -v9] x86: fix out of order of gsi Yinghai Lu
2010-02-28  3:26                           ` [PATCH -v10] " Yinghai Lu
2010-02-28  3:47                         ` [PATCH -v11] x86: fix out of order of gsi -- partial Yinghai Lu
2010-02-28  8:09                           ` Ingo Molnar
2010-02-28  9:05                             ` Yinghai Lu
2010-03-01 14:40                               ` Thomas Renninger
2010-03-01 18:31                                 ` Yinghai Lu
2010-02-28  9:06                             ` [PATCH -v12 1/2] " Yinghai Lu
2010-02-28 19:51                               ` [tip:x86/apic] x86: Fix out of order of gsi tip-bot for Eric W. Biederman
2010-02-28  9:08                             ` [PATCH -v12 2/2] x86: fix out of order of gsi - full Yinghai Lu
2010-03-01 18:59                               ` Eric W. Biederman
2010-03-01 19:37                       ` [tip:x86/apic] x86: Fix out of order gsi -- add remap_ioapic_gsi_to_irq() Eric W. Biederman
2010-03-01 20:26                         ` Yinghai Lu
2010-03-01 16:46                     ` [LKML] " Konrad Rzeszutek Wilk
2010-03-01 18:37                       ` Yinghai Lu
2010-03-01 18:44                       ` Eric W. Biederman
2010-03-01 18:33                         ` [LKML] " Konrad Rzeszutek Wilk
2010-02-23 19:02       ` Other problem/regression with b9c61b70075c87a8612624736faf4a2de5b1ed30 Gary Hade

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.