diff options
| author | Andrew Morton <akpm@osdl.org> | 2004-10-05 22:25:07 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <greg@kroah.com> | 2004-10-05 22:25:07 -0700 |
| commit | 7bfaf2ed2f8a64bfb4e12cbcc912766196e0d826 (patch) | |
| tree | 94f51d3372042b94fe2e5218e3d4c81fc92ce5d1 | |
| parent | 3322aa43b71f3555d8ba74a9fb45c10e600f92fd (diff) | |
[PATCH] add-pci_fixup_enable-pass.patch
From: Bjorn Helgaas <bjorn.helgaas@hp.com>
Nick Piggin's USB driver stopped working when I removed the unconditional
PCI ACPI IRQ routing stuff. He has verified that the attached patch fixes
it. I sort of hate to add another pass of PCI fixups, so I'm open to
alternate solutions if anybody suggests one.
Add a "pci_fixup_enable" pass of PCI fixups. These are run at the end of
pci_enable_device() to fix up things like IRQs that are not set up until
then. Some VIA boards require a fixup after the IRQ is set up. Found by
Nick Piggin, initial patch by Bjorn Helgaas, reworked to fit into current
-mm by Nick.
Signed-off-by: Nick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
| -rw-r--r-- | drivers/pci/pci.c | 7 | ||||
| -rw-r--r-- | drivers/pci/quirks.c | 15 | ||||
| -rw-r--r-- | include/asm-generic/vmlinux.lds.h | 3 | ||||
| -rw-r--r-- | include/linux/pci.h | 7 |
4 files changed, 28 insertions, 4 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 46d56c8ccf10..089eaa832c37 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -382,8 +382,13 @@ pci_enable_device_bars(struct pci_dev *dev, int bars) int pci_enable_device(struct pci_dev *dev) { + int err; + dev->is_enabled = 1; - return pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); + if ((err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1))) + return err; + pci_fixup_device(pci_fixup_enable, dev); + return 0; } /** diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 92067ac842c2..49a9672c0801 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -491,9 +491,9 @@ static void __devinit quirk_via_irqpic(struct pci_dev *dev) pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); } } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irqpic ); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irqpic ); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_6, quirk_via_irqpic ); +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irqpic ); +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irqpic ); +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_6, quirk_via_irqpic ); /* @@ -1003,6 +1003,9 @@ extern struct pci_fixup __start_pci_fixups_header[]; extern struct pci_fixup __end_pci_fixups_header[]; extern struct pci_fixup __start_pci_fixups_final[]; extern struct pci_fixup __end_pci_fixups_final[]; +extern struct pci_fixup __start_pci_fixups_enable[]; +extern struct pci_fixup __end_pci_fixups_enable[]; + void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) { @@ -1018,6 +1021,12 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) start = __start_pci_fixups_final; end = __end_pci_fixups_final; break; + + case pci_fixup_enable: + start = __start_pci_fixups_enable; + end = __end_pci_fixups_enable; + break; + default: /* stupid compiler warning, you would think with an enum... */ return; diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index bb340cb5cb03..da1b3ba89b3e 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -24,6 +24,9 @@ VMLINUX_SYMBOL(__start_pci_fixups_final) = .; \ *(.pci_fixup_final) \ VMLINUX_SYMBOL(__end_pci_fixups_final) = .; \ + VMLINUX_SYMBOL(__start_pci_fixups_enable) = .; \ + *(.pci_fixup_enable) \ + VMLINUX_SYMBOL(__end_pci_fixups_enable) = .; \ } \ \ /* Kernel symbol table: Normal symbols */ \ diff --git a/include/linux/pci.h b/include/linux/pci.h index 48d939c7625c..169badd4917e 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1001,6 +1001,7 @@ struct pci_fixup { enum pci_fixup_pass { pci_fixup_header, /* Called immediately after reading configuration header */ pci_fixup_final, /* Final phase of device fixups */ + pci_fixup_enable, /* pci_enable_device() time */ }; /* Anonymous variables would be nice... */ @@ -1014,6 +1015,12 @@ enum pci_fixup_pass { __attribute__((__section__(".pci_fixup_final"))) = { \ vendor, device, hook }; +#define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook) \ + static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__ \ + __attribute__((__section__(".pci_fixup_enable"))) = { \ + vendor, device, hook }; + + void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); extern int pci_pci_problems; |
