diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2010-02-28 04:06:34 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-02-28 04:33:25 -0500 |
commit | fad539956c9e69749a03f7817d22d1bab87657bf (patch) | |
tree | 81f42216ef32e1926fdae7488da6150c529731c3 /arch/x86 | |
parent | 21c2fd9970cc8e457058f84016450a2e9876125e (diff) |
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>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | 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 72ac2a332993..97e1e3ec2edf 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -1475,7 +1475,7 @@ static struct { | |||
1475 | 1475 | ||
1476 | static void __init setup_IO_APIC_irqs(void) | 1476 | static void __init setup_IO_APIC_irqs(void) |
1477 | { | 1477 | { |
1478 | int apic_id = 0, pin, idx, irq; | 1478 | int apic_id, pin, idx, irq; |
1479 | int notcon = 0; | 1479 | int notcon = 0; |
1480 | struct irq_desc *desc; | 1480 | struct irq_desc *desc; |
1481 | struct irq_cfg *cfg; | 1481 | struct irq_cfg *cfg; |
@@ -1483,14 +1483,7 @@ static void __init setup_IO_APIC_irqs(void) | |||
1483 | 1483 | ||
1484 | apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); | 1484 | apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); |
1485 | 1485 | ||
1486 | #ifdef CONFIG_ACPI | 1486 | for (apic_id = 0; apic_id < nr_ioapics; apic_id++) |
1487 | if (!acpi_disabled && acpi_ioapic) { | ||
1488 | apic_id = mp_find_ioapic(0); | ||
1489 | if (apic_id < 0) | ||
1490 | apic_id = 0; | ||
1491 | } | ||
1492 | #endif | ||
1493 | |||
1494 | for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) { | 1487 | for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) { |
1495 | idx = find_irq_entry(apic_id, pin, mp_INT); | 1488 | idx = find_irq_entry(apic_id, pin, mp_INT); |
1496 | if (idx == -1) { | 1489 | if (idx == -1) { |
@@ -1512,6 +1505,9 @@ static void __init setup_IO_APIC_irqs(void) | |||
1512 | 1505 | ||
1513 | irq = pin_2_irq(idx, apic_id, pin); | 1506 | irq = pin_2_irq(idx, apic_id, pin); |
1514 | 1507 | ||
1508 | if ((apic_id > 0) && (irq > 16)) | ||
1509 | continue; | ||
1510 | |||
1515 | /* | 1511 | /* |
1516 | * Skip the timer IRQ if there's a quirk handler | 1512 | * Skip the timer IRQ if there's a quirk handler |
1517 | * installed and if it returns 1: | 1513 | * installed and if it returns 1: |
@@ -4105,27 +4101,23 @@ int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity) | |||
4105 | #ifdef CONFIG_SMP | 4101 | #ifdef CONFIG_SMP |
4106 | void __init setup_ioapic_dest(void) | 4102 | void __init setup_ioapic_dest(void) |
4107 | { | 4103 | { |
4108 | int pin, ioapic = 0, irq, irq_entry; | 4104 | int pin, ioapic, irq, irq_entry; |
4109 | struct irq_desc *desc; | 4105 | struct irq_desc *desc; |
4110 | const struct cpumask *mask; | 4106 | const struct cpumask *mask; |
4111 | 4107 | ||
4112 | if (skip_ioapic_setup == 1) | 4108 | if (skip_ioapic_setup == 1) |
4113 | return; | 4109 | return; |
4114 | 4110 | ||
4115 | #ifdef CONFIG_ACPI | 4111 | for (ioapic = 0; ioapic < nr_ioapics; ioapic++) |
4116 | if (!acpi_disabled && acpi_ioapic) { | ||
4117 | ioapic = mp_find_ioapic(0); | ||
4118 | if (ioapic < 0) | ||
4119 | ioapic = 0; | ||
4120 | } | ||
4121 | #endif | ||
4122 | |||
4123 | for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) { | 4112 | for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) { |
4124 | irq_entry = find_irq_entry(ioapic, pin, mp_INT); | 4113 | irq_entry = find_irq_entry(ioapic, pin, mp_INT); |
4125 | if (irq_entry == -1) | 4114 | if (irq_entry == -1) |
4126 | continue; | 4115 | continue; |
4127 | irq = pin_2_irq(irq_entry, ioapic, pin); | 4116 | irq = pin_2_irq(irq_entry, ioapic, pin); |
4128 | 4117 | ||
4118 | if ((ioapic > 0) && (irq > 16)) | ||
4119 | continue; | ||
4120 | |||
4129 | desc = irq_to_desc(irq); | 4121 | desc = irq_to_desc(irq); |
4130 | 4122 | ||
4131 | /* | 4123 | /* |