diff options
author | Andi Kleen <andi@firstfloor.org> | 2009-01-09 15:17:39 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-09 15:46:22 -0500 |
commit | 8659c406ade32f47da2c95889094801921d6330a (patch) | |
tree | b2b263f1adda20a07415db7683f9807a903dc60e /arch/x86 | |
parent | 4ce5f24193cef2e26f182ce708e94ba1f5fafc0c (diff) |
x86: only scan the root bus in early PCI quirks
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>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kernel/early-quirks.c | 22 |
1 files changed, 14 insertions, 8 deletions
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index 744aa7fc49d5..76b8cd953dee 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c | |||
@@ -201,6 +201,12 @@ struct chipset { | |||
201 | void (*f)(int num, int slot, int func); | 201 | void (*f)(int num, int slot, int func); |
202 | }; | 202 | }; |
203 | 203 | ||
204 | /* | ||
205 | * Only works for devices on the root bus. If you add any devices | ||
206 | * not on bus 0 readd another loop level in early_quirks(). But | ||
207 | * be careful because at least the Nvidia quirk here relies on | ||
208 | * only matching on bus 0. | ||
209 | */ | ||
204 | static struct chipset early_qrk[] __initdata = { | 210 | static struct chipset early_qrk[] __initdata = { |
205 | { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, | 211 | { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, |
206 | PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, nvidia_bugs }, | 212 | 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) | |||
267 | 273 | ||
268 | void __init early_quirks(void) | 274 | void __init early_quirks(void) |
269 | { | 275 | { |
270 | int num, slot, func; | 276 | int slot, func; |
271 | 277 | ||
272 | if (!early_pci_allowed()) | 278 | if (!early_pci_allowed()) |
273 | return; | 279 | return; |
274 | 280 | ||
275 | /* Poor man's PCI discovery */ | 281 | /* Poor man's PCI discovery */ |
276 | for (num = 0; num < 32; num++) | 282 | /* Only scan the root bus */ |
277 | for (slot = 0; slot < 32; slot++) | 283 | for (slot = 0; slot < 32; slot++) |
278 | for (func = 0; func < 8; func++) { | 284 | for (func = 0; func < 8; func++) { |
279 | /* Only probe function 0 on single fn devices */ | 285 | /* Only probe function 0 on single fn devices */ |
280 | if (check_dev_quirk(num, slot, func)) | 286 | if (check_dev_quirk(0, slot, func)) |
281 | break; | 287 | break; |
282 | } | 288 | } |
283 | } | 289 | } |