diff options
author | Yinghai Lu <yinghai@kernel.org> | 2010-02-10 04:20:05 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2010-02-10 16:47:39 -0500 |
commit | 18dce6ba5c8c6bd0f3ab4efa4cbdd698dab5c40a (patch) | |
tree | 03deca24435fade73b13573020dc751204f3b963 /arch | |
parent | 318f6b228ba88a394ef560efc1bfe028ad5ae6b6 (diff) |
x86: Fix SCI on IOAPIC != 0
Thomas Renninger <trenn@suse.de> reported on IBM x3330
booting a latest kernel on this machine results in:
PCI: PCI BIOS revision 2.10 entry at 0xfd61c, last bus=1
PCI: Using configuration type 1 for base access bio: create slab <bio-0> at 0
ACPI: SCI (IRQ30) allocation failed
ACPI Exception: AE_NOT_ACQUIRED, Unable to install System Control Interrupt handler (20090903/evevent-161)
ACPI: Unable to start the ACPI Interpreter
Later all kind of devices fail...
and bisect it down to this commit:
commit b9c61b70075c87a8612624736faf4a2de5b1ed30
x86/pci: update pirq_enable_irq() to setup io apic routing
it turns out we need to set irq routing for the sci on ioapic1 early.
-v2: make it work without sparseirq too.
-v3: fix checkpatch.pl warning, and cc to stable
Reported-by: Thomas Renninger <trenn@suse.de>
Bisected-by: Thomas Renninger <trenn@suse.de>
Tested-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
LKML-Reference: <1265793639-15071-2-git-send-email-yinghai@kernel.org>
Cc: stable@kernel.org
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/include/asm/io_apic.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 9 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 50 |
3 files changed, 59 insertions, 1 deletions
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 7c7c16cde1f8..5f61f6e0ffdd 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h | |||
@@ -160,6 +160,7 @@ extern int io_apic_get_redir_entries(int ioapic); | |||
160 | struct io_apic_irq_attr; | 160 | struct io_apic_irq_attr; |
161 | extern int io_apic_set_pci_routing(struct device *dev, int irq, | 161 | extern int io_apic_set_pci_routing(struct device *dev, int irq, |
162 | struct io_apic_irq_attr *irq_attr); | 162 | struct io_apic_irq_attr *irq_attr); |
163 | void setup_IO_APIC_irq_extra(u32 gsi); | ||
163 | extern int (*ioapic_renumber_irq)(int ioapic, int irq); | 164 | extern int (*ioapic_renumber_irq)(int ioapic, int irq); |
164 | extern void ioapic_init_mappings(void); | 165 | extern void ioapic_init_mappings(void); |
165 | extern void ioapic_insert_resources(void); | 166 | extern void ioapic_insert_resources(void); |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 0acbcdfa5ca4..5c96b75c6ea8 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -446,6 +446,12 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger) | |||
446 | int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) | 446 | int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) |
447 | { | 447 | { |
448 | *irq = gsi; | 448 | *irq = gsi; |
449 | |||
450 | #ifdef CONFIG_X86_IO_APIC | ||
451 | if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) | ||
452 | setup_IO_APIC_irq_extra(gsi); | ||
453 | #endif | ||
454 | |||
449 | return 0; | 455 | return 0; |
450 | } | 456 | } |
451 | 457 | ||
@@ -473,7 +479,8 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) | |||
473 | plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity); | 479 | plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity); |
474 | } | 480 | } |
475 | #endif | 481 | #endif |
476 | acpi_gsi_to_irq(plat_gsi, &irq); | 482 | irq = plat_gsi; |
483 | |||
477 | return irq; | 484 | return irq; |
478 | } | 485 | } |
479 | 486 | ||
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 53243ca7816d..5e4cce254e43 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -1539,6 +1539,56 @@ static void __init setup_IO_APIC_irqs(void) | |||
1539 | } | 1539 | } |
1540 | 1540 | ||
1541 | /* | 1541 | /* |
1542 | * for the gsit that is not in first ioapic | ||
1543 | * but could not use acpi_register_gsi() | ||
1544 | * like some special sci in IBM x3330 | ||
1545 | */ | ||
1546 | void setup_IO_APIC_irq_extra(u32 gsi) | ||
1547 | { | ||
1548 | int apic_id = 0, pin, idx, irq; | ||
1549 | int node = cpu_to_node(boot_cpu_id); | ||
1550 | struct irq_desc *desc; | ||
1551 | struct irq_cfg *cfg; | ||
1552 | |||
1553 | /* | ||
1554 | * Convert 'gsi' to 'ioapic.pin'. | ||
1555 | */ | ||
1556 | apic_id = mp_find_ioapic(gsi); | ||
1557 | if (apic_id < 0) | ||
1558 | return; | ||
1559 | |||
1560 | pin = mp_find_ioapic_pin(apic_id, gsi); | ||
1561 | idx = find_irq_entry(apic_id, pin, mp_INT); | ||
1562 | if (idx == -1) | ||
1563 | return; | ||
1564 | |||
1565 | irq = pin_2_irq(idx, apic_id, pin); | ||
1566 | #ifdef CONFIG_SPARSE_IRQ | ||
1567 | desc = irq_to_desc(irq); | ||
1568 | if (desc) | ||
1569 | return; | ||
1570 | #endif | ||
1571 | desc = irq_to_desc_alloc_node(irq, node); | ||
1572 | if (!desc) { | ||
1573 | printk(KERN_INFO "can not get irq_desc for %d\n", irq); | ||
1574 | return; | ||
1575 | } | ||
1576 | |||
1577 | cfg = desc->chip_data; | ||
1578 | add_pin_to_irq_node(cfg, node, apic_id, pin); | ||
1579 | |||
1580 | if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) { | ||
1581 | pr_debug("Pin %d-%d already programmed\n", | ||
1582 | mp_ioapics[apic_id].apicid, pin); | ||
1583 | return; | ||
1584 | } | ||
1585 | set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed); | ||
1586 | |||
1587 | setup_IO_APIC_irq(apic_id, pin, irq, desc, | ||
1588 | irq_trigger(idx), irq_polarity(idx)); | ||
1589 | } | ||
1590 | |||
1591 | /* | ||
1542 | * Set up the timer pin, possibly with the 8259A-master behind. | 1592 | * Set up the timer pin, possibly with the 8259A-master behind. |
1543 | */ | 1593 | */ |
1544 | static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin, | 1594 | static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin, |