PCI: allow quirks to be compiled out
Thomas Petazzoni [Tue, 19 Aug 2008 08:28:24 +0000 (10:28 +0200)]
This patch adds the CONFIG_PCI_QUIRKS option which allows to remove all
the PCI quirks, which are not necessarily used on embedded systems when
PCI is working properly. As this is a size-reduction option, it depends
on CONFIG_EMBEDDED. It allows to save almost 12 kilobytes of kernel
code:

   text    data     bss     dec     hex filename
1287806  123596  212992 1624394  18c94a vmlinux.old
1275854  123596  212992 1612442  189a9a vmlinux
 -11952       0       0  -11952   -2EB0 +/-

This patch has originally been written by Zwane Mwaikambo
<zwane@arm.linux.org.uk> and is part of the Linux Tiny project.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

drivers/pci/quirks.c
init/Kconfig

index e872ac9..246918f 100644 (file)
 #include <linux/kallsyms.h>
 #include "pci.h"
 
+int isa_dma_bridge_buggy;
+EXPORT_SYMBOL(isa_dma_bridge_buggy);
+int pci_pci_problems;
+EXPORT_SYMBOL(pci_pci_problems);
+int pcie_mch_quirk;
+EXPORT_SYMBOL(pcie_mch_quirk);
+
+#ifdef CONFIG_PCI_QUIRKS
 /* The Mellanox Tavor device gives false positive parity errors
  * Mark this device with a broken_parity_status, to allow
  * PCI scanning code to "skip" this now blacklisted device.
@@ -62,8 +70,6 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441,      quirk_p
     
     This appears to be BIOS not version dependent. So presumably there is a 
     chipset level fix */
-int isa_dma_bridge_buggy;
-EXPORT_SYMBOL(isa_dma_bridge_buggy);
     
 static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev)
 {
@@ -84,9 +90,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,    PCI_DEVICE_ID_NEC_CBUS_1,       quirk_isa_d
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,     PCI_DEVICE_ID_NEC_CBUS_2,       quirk_isa_dma_hangs);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,     PCI_DEVICE_ID_NEC_CBUS_3,       quirk_isa_dma_hangs);
 
-int pci_pci_problems;
-EXPORT_SYMBOL(pci_pci_problems);
-
 /*
  *     Chipsets where PCI->PCI transfers vanish or hang
  */
@@ -1362,9 +1365,6 @@ static void __init quirk_alder_ioapic(struct pci_dev *pdev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_EESSC,      quirk_alder_ioapic);
 #endif
 
-int pcie_mch_quirk;
-EXPORT_SYMBOL(pcie_mch_quirk);
-
 static void __devinit quirk_pcie_mch(struct pci_dev *pdev)
 {
        pcie_mch_quirk = 1;
@@ -1555,84 +1555,6 @@ static void __devinit fixup_rev1_53c810(struct pci_dev* dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
 
-static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end)
-{
-       while (f < end) {
-               if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
-                   (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
-#ifdef DEBUG
-                       dev_dbg(&dev->dev, "calling %pF\n", f->hook);
-#endif
-                       f->hook(dev);
-               }
-               f++;
-       }
-}
-
-extern struct pci_fixup __start_pci_fixups_early[];
-extern struct pci_fixup __end_pci_fixups_early[];
-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[];
-extern struct pci_fixup __start_pci_fixups_resume[];
-extern struct pci_fixup __end_pci_fixups_resume[];
-extern struct pci_fixup __start_pci_fixups_resume_early[];
-extern struct pci_fixup __end_pci_fixups_resume_early[];
-extern struct pci_fixup __start_pci_fixups_suspend[];
-extern struct pci_fixup __end_pci_fixups_suspend[];
-
-
-void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
-{
-       struct pci_fixup *start, *end;
-
-       switch(pass) {
-       case pci_fixup_early:
-               start = __start_pci_fixups_early;
-               end = __end_pci_fixups_early;
-               break;
-
-       case pci_fixup_header:
-               start = __start_pci_fixups_header;
-               end = __end_pci_fixups_header;
-               break;
-
-       case pci_fixup_final:
-               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;
-
-       case pci_fixup_resume:
-               start = __start_pci_fixups_resume;
-               end = __end_pci_fixups_resume;
-               break;
-
-       case pci_fixup_resume_early:
-               start = __start_pci_fixups_resume_early;
-               end = __end_pci_fixups_resume_early;
-               break;
-
-       case pci_fixup_suspend:
-               start = __start_pci_fixups_suspend;
-               end = __end_pci_fixups_suspend;
-               break;
-
-       default:
-               /* stupid compiler warning, you would think with an enum... */
-               return;
-       }
-       pci_do_fixups(dev, start, end);
-}
-EXPORT_SYMBOL(pci_fixup_device);
-
 /* Enable 1k I/O space granularity on the Intel P64H2 */
 static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
 {
@@ -2006,3 +1928,85 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375,
                        quirk_msi_intx_disable_bug);
 
 #endif /* CONFIG_PCI_MSI */
+
+static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end)
+{
+       while (f < end) {
+               if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
+                   (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
+#ifdef DEBUG
+                       dev_dbg(&dev->dev, "calling ");
+                       print_fn_descriptor_symbol("%s\n", f->hook);
+#endif
+                       f->hook(dev);
+               }
+               f++;
+       }
+}
+
+extern struct pci_fixup __start_pci_fixups_early[];
+extern struct pci_fixup __end_pci_fixups_early[];
+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[];
+extern struct pci_fixup __start_pci_fixups_resume[];
+extern struct pci_fixup __end_pci_fixups_resume[];
+extern struct pci_fixup __start_pci_fixups_resume_early[];
+extern struct pci_fixup __end_pci_fixups_resume_early[];
+extern struct pci_fixup __start_pci_fixups_suspend[];
+extern struct pci_fixup __end_pci_fixups_suspend[];
+
+
+void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
+{
+       struct pci_fixup *start, *end;
+
+       switch(pass) {
+       case pci_fixup_early:
+               start = __start_pci_fixups_early;
+               end = __end_pci_fixups_early;
+               break;
+
+       case pci_fixup_header:
+               start = __start_pci_fixups_header;
+               end = __end_pci_fixups_header;
+               break;
+
+       case pci_fixup_final:
+               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;
+
+       case pci_fixup_resume:
+               start = __start_pci_fixups_resume;
+               end = __end_pci_fixups_resume;
+               break;
+
+       case pci_fixup_resume_early:
+               start = __start_pci_fixups_resume_early;
+               end = __end_pci_fixups_resume_early;
+               break;
+
+       case pci_fixup_suspend:
+               start = __start_pci_fixups_suspend;
+               end = __end_pci_fixups_suspend;
+               break;
+
+       default:
+               /* stupid compiler warning, you would think with an enum... */
+               return;
+       }
+       pci_do_fixups(dev, start, end);
+}
+#else
+void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {}
+#endif
+EXPORT_SYMBOL(pci_fixup_device);
index 8828ed0..06330a3 100644 (file)
@@ -737,6 +737,14 @@ config VM_EVENT_COUNTERS
          on EMBEDDED systems.  /proc/vmstat will only show page counts
          if VM event counters are disabled.
 
+config PCI_QUIRKS
+       default y
+       bool "Enable PCI quirk workarounds" if EMBEDDED && PCI
+       help
+         This enables workarounds for various PCI chipset
+          bugs/quirks. Disable this only if your target machine is
+          unaffected by PCI quirks.
+
 config SLUB_DEBUG
        default y
        bool "Enable SLUB debugging support" if EMBEDDED