Commit fc9e06d5 authored by Andrew Morton's avatar Andrew Morton Committed by Greg Kroah-Hartman

[PATCH] PCI: remove unconditional PCI ACPI IRQ routing

From: Bjorn Helgaas <bjorn.helgaas@hp.com>

Now that PCI interrupts are routed in pci_enable_device(), remove the
unconditional routing previously done in pci_acpi_init().

This has the potential to break drivers that don't use pci_enable_device()
correctly, so I also added a "pci=routeirq" kernel option that restores the
previous behavior.  I intend to remove that option, along with all the code
below, in a month or so.
Signed-off-by: default avatarBjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent d8cc66f8
......@@ -912,6 +912,10 @@ running once the system is up.
enabled.
noacpi [IA-32] Do not use ACPI for IRQ routing
or for PCI scanning.
routeirq Do IRQ routing for all PCI devices.
This is normally done in pci_enable_device(),
so this option is a temporary workaround
for broken drivers that don't call it.
firmware [ARM] Do not re-enumerate the bus but
instead just use the configuration
......
......@@ -15,6 +15,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
return pcibios_scan_root(busnum);
}
extern int pci_routeirq;
static int __init pci_acpi_init(void)
{
struct pci_dev *dev = NULL;
......@@ -30,14 +31,27 @@ static int __init pci_acpi_init(void)
pcibios_scanned++;
pcibios_enable_irq = acpi_pci_irq_enable;
/*
* PCI IRQ routing is set up by pci_enable_device(), but we
* also do it here in case there are still broken drivers that
* don't use pci_enable_device().
*/
while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
acpi_pci_irq_enable(dev);
if (pci_routeirq) {
/*
* PCI IRQ routing is set up by pci_enable_device(), but we
* also do it here in case there are still broken drivers that
* don't use pci_enable_device().
*/
printk(KERN_INFO "** Routing PCI interrupts for all devices because \"pci=routeirq\"\n");
printk(KERN_INFO "** was specified. If this was required to make a driver work,\n");
printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
printk(KERN_INFO "** so I can fix the driver.\n");
while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
acpi_pci_irq_enable(dev);
} else {
printk(KERN_INFO "** PCI interrupts are no longer routed automatically. If this\n");
printk(KERN_INFO "** causes a device to stop working, it is probably because the\n");
printk(KERN_INFO "** driver failed to call pci_enable_device(). As a temporary\n");
printk(KERN_INFO "** workaround, the \"pci=routeirq\" argument restores the old\n");
printk(KERN_INFO "** behavior. If this argument makes the device work again,\n");
printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
printk(KERN_INFO "** so I can fix the driver.\n");
}
#ifdef CONFIG_X86_IO_APIC
if (acpi_ioapic)
print_IO_APIC();
......
......@@ -23,6 +23,7 @@ extern void pcibios_sort(void);
unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
PCI_PROBE_MMCONF;
int pci_routeirq;
int pcibios_last_bus = -1;
struct pci_bus *pci_root_bus = NULL;
struct pci_raw_ops *raw_pci_ops;
......@@ -227,6 +228,9 @@ char * __devinit pcibios_setup(char *str)
} else if (!strcmp(str, "assign-busses")) {
pci_probe |= PCI_ASSIGN_ALL_BUSSES;
return NULL;
} else if (!strcmp(str, "routeirq")) {
pci_routeirq = 1;
return NULL;
}
return str;
}
......
......@@ -46,6 +46,8 @@
#define DBG(x...)
#endif
static int pci_routeirq;
/*
* Low-level SAL-based PCI configuration access functions. Note that SAL
* calls are already serialized (via sal_lock), so we don't need another
......@@ -141,13 +143,28 @@ extern acpi_status acpi_map_iosapic (acpi_handle, u32, void*, void**);
acpi_get_devices(NULL, acpi_map_iosapic, NULL, NULL);
#endif
/*
* PCI IRQ routing is set up by pci_enable_device(), but we
* also do it here in case there are still broken drivers that
* don't use pci_enable_device().
*/
while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
acpi_pci_irq_enable(dev);
if (pci_routeirq) {
/*
* PCI IRQ routing is set up by pci_enable_device(), but we
* also do it here in case there are still broken drivers that
* don't use pci_enable_device().
*/
printk(KERN_INFO "** Routing PCI interrupts for all devices because \"pci=routeirq\"\n");
printk(KERN_INFO "** was specified. If this was required to make a driver work,\n");
printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
printk(KERN_INFO "** so I can fix the driver.\n");
while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
acpi_pci_irq_enable(dev);
} else {
printk(KERN_INFO "** PCI interrupts are no longer routed automatically. If this\n");
printk(KERN_INFO "** causes a device to stop working, it is probably because the\n");
printk(KERN_INFO "** driver failed to call pci_enable_device(). As a temporary\n");
printk(KERN_INFO "** workaround, the \"pci=routeirq\" argument restores the old\n");
printk(KERN_INFO "** behavior. If this argument makes the device work again,\n");
printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
printk(KERN_INFO "** so I can fix the driver.\n");
}
return 0;
}
......@@ -443,6 +460,8 @@ pcibios_align_resource (void *data, struct resource *res,
char * __init
pcibios_setup (char *str)
{
if (!strcmp(str, "routeirq"))
pci_routeirq = 1;
return NULL;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment