Re: [PATCH] [1/5] Only scan the root bus in early PCI quirks.

Yinghai Lu
2009-01-04T23:51:19Z

On Sun, Jan 4, 2009 at 3:36 PM, Andi Kleen <andi@firstfloor.org> wrote:
>
> 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>
>
> ---
> arch/x86/kernel/early-quirks.c | 22 ++++++++++++++--------
> 1 file changed, 14 insertions(+), 8 deletions(-)
>
> Index: linux-2.6.28-test/arch/x86/kernel/early-quirks.c
> ===================================================================
> --- linux-2.6.28-test.orig/arch/x86/kernel/early-quirks.c 2008-11-24 16:42:46.000000000 +0100
> +++ linux-2.6.28-test/arch/x86/kernel/early-quirks.c 2008-12-29 05:25:09.000000000 +0100
> @@ -200,6 +200,12 @@
> 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 },
> @@ -266,17 +272,17 @@
>
> 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;
> + }
> }
> --

two cases:
1. how about system with two or more HT chains, and second will be
0x40, x0x80, or 0xc0 ?
2. some system with LinuxBIOS, could put first chain on bus 1

YH