x86: only scan the root bus in early PCI quirks
authorAndi Kleen <andi@firstfloor.org>
Fri, 9 Jan 2009 20:17:39 +0000 (12:17 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 9 Jan 2009 20:46:22 +0000 (12:46 -0800)
We found a situation on Linus' machine that the Nvidia timer quirk hit on
a Intel chipset system.  The problem is that the system has a fancy Nvidia
card with an own PCI bridge, and the early-quirks code looking for any
NVidia bridge triggered on it incorrectly.  This didn't lead a boot
failure by luck, but the timer routing code selecting the wrong timer
first and some ugly messages.  It might lead to real problems on other
systems.

I checked all the devices which are currently checked for by early_quirks
and it turns out they are all located in the root bus zero.

So change the early-quirks loop to only scan bus 0.  This incidently also
saves quite some unnecessary scanning work, because early_quirks doesn't
go through all the non root busses.

The graphics card is not on bus 0, so it is not matched anymore.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/x86/kernel/early-quirks.c

index 744aa7fc49d5e875403b6ffc64c0a2cae74f9c55..76b8cd953deed9f8a50d572cdc52b5edb68bc3b7 100644 (file)
@@ -201,6 +201,12 @@ struct chipset {
        void (*f)(int num, int slot, int func);
 };
 
+/*
+ * Only works for devices on the root bus. If you add any devices
+ * not on bus 0 readd another loop level in early_quirks(). But
+ * be careful because at least the Nvidia quirk here relies on
+ * only matching on bus 0.
+ */
 static struct chipset early_qrk[] __initdata = {
        { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
          PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, nvidia_bugs },
@@ -267,17 +273,17 @@ static int __init check_dev_quirk(int num, int slot, int func)
 
 void __init early_quirks(void)
 {
-       int num, slot, func;
+       int slot, func;
 
        if (!early_pci_allowed())
                return;
 
        /* Poor man's PCI discovery */
-       for (num = 0; num < 32; num++)
-               for (slot = 0; slot < 32; slot++)
-                       for (func = 0; func < 8; func++) {
-                               /* Only probe function 0 on single fn devices */
-                               if (check_dev_quirk(num, slot, func))
-                                       break;
-                       }
+       /* Only scan the root bus */
+       for (slot = 0; slot < 32; slot++)
+               for (func = 0; func < 8; func++) {
+                       /* Only probe function 0 on single fn devices */
+                       if (check_dev_quirk(0, slot, func))
+                               break;
+               }
 }