diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/pci_irq.c | 56 | ||||
-rw-r--r-- | drivers/acpi/toshiba_acpi.c | 54 |
2 files changed, 85 insertions, 25 deletions
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 11acaee14d66..bf79d83bdfbb 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -384,6 +384,27 @@ acpi_pci_free_irq(struct acpi_prt_entry *entry, return irq; } +#ifdef CONFIG_X86_IO_APIC +extern int noioapicquirk; + +static int bridge_has_boot_interrupt_variant(struct pci_bus *bus) +{ + struct pci_bus *bus_it; + + for (bus_it = bus ; bus_it ; bus_it = bus_it->parent) { + if (!bus_it->self) + return 0; + + printk(KERN_INFO "vendor=%04x device=%04x\n", bus_it->self->vendor, + bus_it->self->device); + + if (bus_it->self->irq_reroute_variant) + return bus_it->self->irq_reroute_variant; + } + return 0; +} +#endif /* CONFIG_X86_IO_APIC */ + /* * acpi_pci_irq_lookup * success: return IRQ >= 0 @@ -413,6 +434,41 @@ acpi_pci_irq_lookup(struct pci_bus *bus, } ret = func(entry, triggering, polarity, link); + +#ifdef CONFIG_X86_IO_APIC + /* + * Some chipsets (e.g. intel 6700PXH) generate a legacy INTx when the + * IRQ entry in the chipset's IO-APIC is masked (as, e.g. the RT kernel + * does during interrupt handling). When this INTx generation cannot be + * disabled, we reroute these interrupts to their legacy equivalent to + * get rid of spurious interrupts. + */ + if (!noioapicquirk) { + switch (bridge_has_boot_interrupt_variant(bus)) { + case 0: + /* no rerouting necessary */ + break; + + case INTEL_IRQ_REROUTE_VARIANT: + /* + * Remap according to INTx routing table in 6700PXH + * specs, intel order number 302628-002, section + * 2.15.2. Other chipsets (80332, ...) have the same + * mapping and are handled here as well. + */ + printk(KERN_INFO "pci irq %d -> rerouted to legacy " + "irq %d\n", ret, (ret % 4) + 16); + ret = (ret % 4) + 16; + break; + + default: + printk(KERN_INFO "not rerouting irq %d to legacy irq: " + "unknown mapping\n", ret); + break; + } + } +#endif /* CONFIG_X86_IO_APIC */ + return ret; } diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c index 25f531d892de..40e60fc2e596 100644 --- a/drivers/acpi/toshiba_acpi.c +++ b/drivers/acpi/toshiba_acpi.c @@ -824,32 +824,36 @@ static int __init toshiba_acpi_init(void) toshiba_acpi_exit(); return -ENOMEM; } - } - /* Register input device for kill switch */ - toshiba_acpi.poll_dev = input_allocate_polled_device(); - if (!toshiba_acpi.poll_dev) { - printk(MY_ERR "unable to allocate kill-switch input device\n"); - toshiba_acpi_exit(); - return -ENOMEM; - } - toshiba_acpi.poll_dev->private = &toshiba_acpi; - toshiba_acpi.poll_dev->poll = bt_poll_rfkill; - toshiba_acpi.poll_dev->poll_interval = 1000; /* msecs */ - - toshiba_acpi.poll_dev->input->name = toshiba_acpi.rfk_name; - toshiba_acpi.poll_dev->input->id.bustype = BUS_HOST; - toshiba_acpi.poll_dev->input->id.vendor = 0x0930; /* Toshiba USB ID */ - set_bit(EV_SW, toshiba_acpi.poll_dev->input->evbit); - set_bit(SW_RFKILL_ALL, toshiba_acpi.poll_dev->input->swbit); - input_report_switch(toshiba_acpi.poll_dev->input, SW_RFKILL_ALL, TRUE); - input_sync(toshiba_acpi.poll_dev->input); - - ret = input_register_polled_device(toshiba_acpi.poll_dev); - if (ret) { - printk(MY_ERR "unable to register kill-switch input device\n"); - toshiba_acpi_exit(); - return ret; + /* Register input device for kill switch */ + toshiba_acpi.poll_dev = input_allocate_polled_device(); + if (!toshiba_acpi.poll_dev) { + printk(MY_ERR + "unable to allocate kill-switch input device\n"); + toshiba_acpi_exit(); + return -ENOMEM; + } + toshiba_acpi.poll_dev->private = &toshiba_acpi; + toshiba_acpi.poll_dev->poll = bt_poll_rfkill; + toshiba_acpi.poll_dev->poll_interval = 1000; /* msecs */ + + toshiba_acpi.poll_dev->input->name = toshiba_acpi.rfk_name; + toshiba_acpi.poll_dev->input->id.bustype = BUS_HOST; + /* Toshiba USB ID */ + toshiba_acpi.poll_dev->input->id.vendor = 0x0930; + set_bit(EV_SW, toshiba_acpi.poll_dev->input->evbit); + set_bit(SW_RFKILL_ALL, toshiba_acpi.poll_dev->input->swbit); + input_report_switch(toshiba_acpi.poll_dev->input, + SW_RFKILL_ALL, TRUE); + input_sync(toshiba_acpi.poll_dev->input); + + ret = input_register_polled_device(toshiba_acpi.poll_dev); + if (ret) { + printk(MY_ERR + "unable to register kill-switch input device\n"); + toshiba_acpi_exit(); + return ret; + } } return 0; |