Signed-off-by: Andrew Morton --- 25-akpm/Documentation/kernel-parameters.txt | 4 +++ 25-akpm/arch/i386/pci/acpi.c | 30 ++++++++++++++++++------- 25-akpm/arch/i386/pci/common.c | 4 +++ 25-akpm/arch/i386/pci/irq.c | 16 +++++-------- 25-akpm/arch/ia64/pci/pci.c | 33 ++++++++++++++++++++++------ 25-akpm/drivers/atm/idt77252.c | 4 +-- 25-akpm/drivers/isdn/tpam/tpam_main.c | 4 +-- 25-akpm/drivers/misc/ibmasm/module.c | 6 ++--- 25-akpm/drivers/net/tulip/de4x5.c | 4 +-- 25-akpm/drivers/pci/pci.c | 12 ++++++++++ arch/i386/kernel/acpi/boot.c | 0 11 files changed, 83 insertions(+), 34 deletions(-) diff -puN arch/i386/kernel/acpi/boot.c~bk-pci arch/i386/kernel/acpi/boot.c diff -puN arch/i386/pci/acpi.c~bk-pci arch/i386/pci/acpi.c --- 25/arch/i386/pci/acpi.c~bk-pci 2004-10-28 23:17:33.002273576 -0700 +++ 25-akpm/arch/i386/pci/acpi.c 2004-10-28 23:17:36.446749936 -0700 @@ -15,6 +15,7 @@ struct pci_bus * __devinit pci_acpi_scan 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_get_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(); diff -puN arch/i386/pci/common.c~bk-pci arch/i386/pci/common.c --- 25/arch/i386/pci/common.c~bk-pci 2004-10-28 23:17:33.004273272 -0700 +++ 25-akpm/arch/i386/pci/common.c 2004-10-28 23:17:36.447749784 -0700 @@ -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 *st } 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; } diff -puN arch/i386/pci/irq.c~bk-pci arch/i386/pci/irq.c --- 25/arch/i386/pci/irq.c~bk-pci 2004-10-28 23:17:33.005273120 -0700 +++ 25-akpm/arch/i386/pci/irq.c 2004-10-28 23:17:38.638416752 -0700 @@ -460,21 +460,17 @@ static int pirq_bios_set(struct pci_dev #endif - static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) { - struct pci_dev *dev1, *dev2; + static struct pci_device_id pirq_440gx[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) }, + { }, + }; /* 440GX has a proprietary PIRQ router -- don't use it */ - dev1 = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82443GX_0, NULL); - dev2 = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82443GX_2, NULL); - if ((dev1 != NULL) || (dev2 != NULL)) { - pci_dev_put(dev1); - pci_dev_put(dev2); + if (pci_dev_present(pirq_440gx)) return 0; - } switch(device) { diff -puN arch/ia64/pci/pci.c~bk-pci arch/ia64/pci/pci.c --- 25/arch/ia64/pci/pci.c~bk-pci 2004-10-28 23:17:33.006272968 -0700 +++ 25-akpm/arch/ia64/pci/pci.c 2004-10-28 23:17:38.639416600 -0700 @@ -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 (acp 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, stru char * __init pcibios_setup (char *str) { + if (!strcmp(str, "routeirq")) + pci_routeirq = 1; return NULL; } diff -puN Documentation/kernel-parameters.txt~bk-pci Documentation/kernel-parameters.txt --- 25/Documentation/kernel-parameters.txt~bk-pci 2004-10-28 23:17:33.008272664 -0700 +++ 25-akpm/Documentation/kernel-parameters.txt 2004-10-28 23:17:33.029269472 -0700 @@ -921,6 +921,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 diff -puN drivers/atm/idt77252.c~bk-pci drivers/atm/idt77252.c --- 25/drivers/atm/idt77252.c~bk-pci 2004-10-28 23:17:33.009272512 -0700 +++ 25-akpm/drivers/atm/idt77252.c 2004-10-28 23:17:38.642416144 -0700 @@ -3685,9 +3685,9 @@ idt77252_init_one(struct pci_dev *pcidev int i, err; - if (pci_enable_device(pcidev)) { + if ((err = pci_enable_device(pcidev))) { printk("idt77252: can't enable PCI device at %s\n", pci_name(pcidev)); - return -ENODEV; + return err; } if (pci_read_config_word(pcidev, PCI_REVISION_ID, &revision)) { diff -puN drivers/isdn/tpam/tpam_main.c~bk-pci drivers/isdn/tpam/tpam_main.c --- 25/drivers/isdn/tpam/tpam_main.c~bk-pci 2004-10-28 23:17:33.011272208 -0700 +++ 25-akpm/drivers/isdn/tpam/tpam_main.c 2004-10-28 23:17:38.642416144 -0700 @@ -88,10 +88,10 @@ static int __devinit tpam_probe(struct p tpam_card *card, *c; int i, err; - if (pci_enable_device(dev)) { + if ((err = pci_enable_device(dev))) { printk(KERN_ERR "TurboPAM: can't enable PCI device at %s\n", pci_name(dev)); - return -ENODEV; + return err; } /* allocate memory for the board structure */ diff -puN drivers/misc/ibmasm/module.c~bk-pci drivers/misc/ibmasm/module.c --- 25/drivers/misc/ibmasm/module.c~bk-pci 2004-10-28 23:17:33.012272056 -0700 +++ 25-akpm/drivers/misc/ibmasm/module.c 2004-10-28 23:17:38.643415992 -0700 @@ -59,13 +59,13 @@ static int __init ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { - int result = -ENOMEM; + int err, result = -ENOMEM; struct service_processor *sp; - if (pci_enable_device(pdev)) { + if ((err = pci_enable_device(pdev))) { printk(KERN_ERR "%s: can't enable PCI device at %s\n", DRIVER_NAME, pci_name(pdev)); - return -ENODEV; + return err; } sp = kmalloc(sizeof(struct service_processor), GFP_KERNEL); diff -puN drivers/net/tulip/de4x5.c~bk-pci drivers/net/tulip/de4x5.c --- 25/drivers/net/tulip/de4x5.c~bk-pci 2004-10-28 23:17:33.014271752 -0700 +++ 25-akpm/drivers/net/tulip/de4x5.c 2004-10-28 23:17:38.647415384 -0700 @@ -2242,8 +2242,8 @@ static int __devinit de4x5_pci_probe (st return -ENODEV; /* Ok, the device seems to be for us. */ - if (pci_enable_device (pdev)) - return -ENODEV; + if ((error = pci_enable_device (pdev))) + return error; if (!(dev = alloc_etherdev (sizeof (struct de4x5_private)))) { error = -ENOMEM; diff -puN drivers/pci/pci.c~bk-pci drivers/pci/pci.c --- 25/drivers/pci/pci.c~bk-pci 2004-10-28 23:17:33.016271448 -0700 +++ 25-akpm/drivers/pci/pci.c 2004-10-28 23:17:38.649415080 -0700 @@ -375,6 +375,16 @@ pci_enable_device(struct pci_dev *dev) } /** + * pcibios_disable_device - disable arch specific PCI resources for device dev + * @dev: the PCI device to disable + * + * Disables architecture specific PCI resources for the device. This + * is the default implementation. Architecture implementations can + * override this. + */ +void __attribute__ ((weak)) pcibios_disable_device (struct pci_dev *dev) {} + +/** * pci_disable_device - Disable PCI device after use * @dev: PCI device to be disabled * @@ -394,6 +404,8 @@ pci_disable_device(struct pci_dev *dev) pci_command &= ~PCI_COMMAND_MASTER; pci_write_config_word(dev, PCI_COMMAND, pci_command); } + + pcibios_disable_device(dev); } /** _