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. ...@@ -912,6 +912,10 @@ running once the system is up.
enabled. enabled.
noacpi [IA-32] Do not use ACPI for IRQ routing noacpi [IA-32] Do not use ACPI for IRQ routing
or for PCI scanning. 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 firmware [ARM] Do not re-enumerate the bus but
instead just use the configuration instead just use the configuration
......
...@@ -15,6 +15,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do ...@@ -15,6 +15,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
return pcibios_scan_root(busnum); return pcibios_scan_root(busnum);
} }
extern int pci_routeirq;
static int __init pci_acpi_init(void) static int __init pci_acpi_init(void)
{ {
struct pci_dev *dev = NULL; struct pci_dev *dev = NULL;
...@@ -30,14 +31,27 @@ static int __init pci_acpi_init(void) ...@@ -30,14 +31,27 @@ static int __init pci_acpi_init(void)
pcibios_scanned++; pcibios_scanned++;
pcibios_enable_irq = acpi_pci_irq_enable; pcibios_enable_irq = acpi_pci_irq_enable;
/* 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 * PCI IRQ routing is set up by pci_enable_device(), but we
* don't use pci_enable_device(). * 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); 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 #ifdef CONFIG_X86_IO_APIC
if (acpi_ioapic) if (acpi_ioapic)
print_IO_APIC(); print_IO_APIC();
......
...@@ -23,6 +23,7 @@ extern void pcibios_sort(void); ...@@ -23,6 +23,7 @@ extern void pcibios_sort(void);
unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
PCI_PROBE_MMCONF; PCI_PROBE_MMCONF;
int pci_routeirq;
int pcibios_last_bus = -1; int pcibios_last_bus = -1;
struct pci_bus *pci_root_bus = NULL; struct pci_bus *pci_root_bus = NULL;
struct pci_raw_ops *raw_pci_ops; struct pci_raw_ops *raw_pci_ops;
...@@ -227,6 +228,9 @@ char * __devinit pcibios_setup(char *str) ...@@ -227,6 +228,9 @@ char * __devinit pcibios_setup(char *str)
} else if (!strcmp(str, "assign-busses")) { } else if (!strcmp(str, "assign-busses")) {
pci_probe |= PCI_ASSIGN_ALL_BUSSES; pci_probe |= PCI_ASSIGN_ALL_BUSSES;
return NULL; return NULL;
} else if (!strcmp(str, "routeirq")) {
pci_routeirq = 1;
return NULL;
} }
return str; return str;
} }
......
...@@ -46,6 +46,8 @@ ...@@ -46,6 +46,8 @@
#define DBG(x...) #define DBG(x...)
#endif #endif
static int pci_routeirq;
/* /*
* Low-level SAL-based PCI configuration access functions. Note that SAL * Low-level SAL-based PCI configuration access functions. Note that SAL
* calls are already serialized (via sal_lock), so we don't need another * 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**); ...@@ -141,13 +143,28 @@ extern acpi_status acpi_map_iosapic (acpi_handle, u32, void*, void**);
acpi_get_devices(NULL, acpi_map_iosapic, NULL, NULL); acpi_get_devices(NULL, acpi_map_iosapic, NULL, NULL);
#endif #endif
/*
* PCI IRQ routing is set up by pci_enable_device(), but we if (pci_routeirq) {
* also do it here in case there are still broken drivers that /*
* don't use pci_enable_device(). * PCI IRQ routing is set up by pci_enable_device(), but we
*/ * also do it here in case there are still broken drivers that
while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) * don't use pci_enable_device().
acpi_pci_irq_enable(dev); */
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; return 0;
} }
...@@ -443,6 +460,8 @@ pcibios_align_resource (void *data, struct resource *res, ...@@ -443,6 +460,8 @@ pcibios_align_resource (void *data, struct resource *res,
char * __init char * __init
pcibios_setup (char *str) pcibios_setup (char *str)
{ {
if (!strcmp(str, "routeirq"))
pci_routeirq = 1;
return NULL; 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