On Fri, Dec 17, 2021 at 10:13:13PM -0800, Lucas De Marchi wrote:
> When using QFLAG_APPLY_ONCE we make sure the quirk is applied only once.

Maybe "called" only once, since you're about to add a distinction
between "called" and "applied"?

I'm not really sure the concept of QFLAG_APPLY_ONCE, QFLAG_APPLIED,
QFLAG_DONE is general purpose enough to be handled at the level of
check_dev_quirk().

We don't have anything like that for the regular PCI fixups (see
pci_do_fixups()).  If a regular fixup needed something like that, it
would use a static local variable.  Maybe that would be simpler
overall here, too, since the quirk would be *always* called for
matching devices, and the "one-time" logic would be encapsulated in
the quirk itself where it's more obvious?

> This is useful when it's enough one device to trigger a certain
> condition or when the resource in each that applies is global to the
> system rather than local to the device.
> 
> However we call the quirk handler based on vendor, class, and device,
> allowing the specific handler to do additional filtering. In that case
> check_dev_quirk() may incorrectly mark the quirk as applied when it's
> not. This is particularly bad for intel_graphics_quirks() that uses
> PCI_ANY_ID and then compares with a long list of devices. This hasn't
> been problematic so far because those devices are integrated GPUs and
> there can only be one in the system.  However as Intel starts to
> release discrete cards, this condition is no longer true and we fail to
> reserve the stolen memory (for the integrated gpu) depending on the bus
> topology: if the traversal finds the discrete card first, for which
> there is no system stolen memory, we will fail to reserve it for the
> integrated card.

s/integrated gpu/integrated GPU/ (to match previous use)

> This fixes the stolen memory reservation for an Alderlake-P system with
> one additional DG2. In this system we have:

DG2?

>       - 00:01.0 Bridge
>         `- 03:00.0 DG2
>       - Alderklake-P's integrated graphics

s/Alderklake-P/Alderlake-P/

Might be nice to include the integrated GPU PCI address to be parallel
with the bridge and DG2.

> Since we do a depth-first traversal, when we call the handler because of
> DG2 we were marking it as already being applied and never reserving the
> stolen memory for Alderlake-P.
> 
> Here we change the quirk fucntions to return bool in case it applied a
> quirk so we only flag it as applied when that really happened. This only
> makes a difference for quirks using QFLAG_APPLY_ONCE, so all the others
> simply returns true in order to avoid unnecessary complication.

s/fucntions/functions/
s/returns true/return true/

I would consider splitting this into two patches:

  1) Change the quirk signature, make them all return "true", and
  update check_dev_quirk().  This would have no functional impact.

  2) Update intel_graphics_quirks() to return "false" when it doesn't
  reserve the stolen memory.

Then the important change will be in a small patch by itself and will
be easier to understand and revert if that should be necessary.

> Signed-off-by: Lucas De Marchi <lucas.demar...@intel.com>
> ---
>  arch/x86/kernel/early-quirks.c | 75 ++++++++++++++++++++++------------
>  1 file changed, 49 insertions(+), 26 deletions(-)
> 
> diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
> index 391a4e2b8604..5d235fe2a07a 100644
> --- a/arch/x86/kernel/early-quirks.c
> +++ b/arch/x86/kernel/early-quirks.c
> @@ -28,7 +28,7 @@
>  #include <asm/irq_remapping.h>
>  #include <asm/early_ioremap.h>
>  
> -static void __init fix_hypertransport_config(int num, int slot, int func)
> +static bool __init fix_hypertransport_config(int num, int slot, int func)
>  {
>       u32 htcfg;
>       /*
> @@ -51,10 +51,10 @@ static void __init fix_hypertransport_config(int num, int 
> slot, int func)
>               }
>       }
>  
> -
> +     return true;
>  }
>  
> -static void __init via_bugs(int  num, int slot, int func)
> +static bool __init via_bugs(int  num, int slot, int func)
>  {
>  #ifdef CONFIG_GART_IOMMU
>       if ((max_pfn > MAX_DMA32_PFN ||  force_iommu) &&
> @@ -63,8 +63,12 @@ static void __init via_bugs(int  num, int slot, int func)
>                      "Looks like a VIA chipset. Disabling IOMMU."
>                      " Override with iommu=allowed\n");
>               gart_iommu_aperture_disabled = 1;
> +
> +             return true;
>       }
>  #endif
> +
> +     return false;
>  }
>  
>  #ifdef CONFIG_ACPI
> @@ -77,7 +81,7 @@ static int __init nvidia_hpet_check(struct 
> acpi_table_header *header)
>  #endif /* CONFIG_X86_IO_APIC */
>  #endif /* CONFIG_ACPI */
>  
> -static void __init nvidia_bugs(int num, int slot, int func)
> +static bool __init nvidia_bugs(int num, int slot, int func)
>  {
>  #ifdef CONFIG_ACPI
>  #ifdef CONFIG_X86_IO_APIC
> @@ -86,7 +90,7 @@ static void __init nvidia_bugs(int num, int slot, int func)
>        * Nvidia graphics cards with PCI ports on secondary buses.
>        */
>       if (num)
> -             return;
> +             return false;
>  
>       /*
>        * All timer overrides on Nvidia are
> @@ -96,7 +100,7 @@ static void __init nvidia_bugs(int num, int slot, int func)
>        * at least allow a command line override.
>        */
>       if (acpi_use_timer_override)
> -             return;
> +             return false;
>  
>       if (acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check)) {
>               acpi_skip_timer_override = 1;
> @@ -105,11 +109,14 @@ static void __init nvidia_bugs(int num, int slot, int 
> func)
>                      "timer override.\n");
>               printk(KERN_INFO "If you got timer trouble "
>                       "try acpi_use_timer_override\n");
> +
> +             return true;
>       }
>  #endif
>  #endif
>       /* RED-PEN skip them on mptables too? */
>  
> +     return false;
>  }
>  
>  #if defined(CONFIG_ACPI) && defined(CONFIG_X86_IO_APIC)
> @@ -131,13 +138,13 @@ static u32 __init ati_ixp4x0_rev(int num, int slot, int 
> func)
>       return d;
>  }
>  
> -static void __init ati_bugs(int num, int slot, int func)
> +static bool __init ati_bugs(int num, int slot, int func)
>  {
>       u32 d;
>       u8  b;
>  
>       if (acpi_use_timer_override)
> -             return;
> +             return true;
>  
>       d = ati_ixp4x0_rev(num, slot, func);
>       if (d  < 0x82)
> @@ -155,6 +162,8 @@ static void __init ati_bugs(int num, int slot, int func)
>               printk(KERN_INFO "If you got timer trouble "
>                      "try acpi_use_timer_override\n");
>       }
> +
> +     return true;
>  }
>  
>  static u32 __init ati_sbx00_rev(int num, int slot, int func)
> @@ -167,7 +176,7 @@ static u32 __init ati_sbx00_rev(int num, int slot, int 
> func)
>       return d;
>  }
>  
> -static void __init ati_bugs_contd(int num, int slot, int func)
> +static bool __init ati_bugs_contd(int num, int slot, int func)
>  {
>       u32 d, rev;
>  
> @@ -181,10 +190,10 @@ static void __init ati_bugs_contd(int num, int slot, 
> int func)
>        * SB800: revisions 0x40, 0x41, ...
>        */
>       if (rev >= 0x39)
> -             return;
> +             return true;
>  
>       if (acpi_use_timer_override)
> -             return;
> +             return true;
>  
>       /* check for IRQ0 interrupt swap */
>       d = read_pci_config(num, slot, func, 0x64);
> @@ -197,18 +206,22 @@ static void __init ati_bugs_contd(int num, int slot, 
> int func)
>               printk(KERN_INFO "If you got timer trouble "
>                      "try acpi_use_timer_override\n");
>       }
> +
> +     return true;
>  }
>  #else
> -static void __init ati_bugs(int num, int slot, int func)
> +static bool __init ati_bugs(int num, int slot, int func)
>  {
> +     return true;
>  }
>  
> -static void __init ati_bugs_contd(int num, int slot, int func)
> +static bool __init ati_bugs_contd(int num, int slot, int func)
>  {
> +     return true;
>  }
>  #endif
>  
> -static void __init intel_remapping_check(int num, int slot, int func)
> +static bool __init intel_remapping_check(int num, int slot, int func)
>  {
>       u8 revision;
>       u16 device;
> @@ -226,6 +239,8 @@ static void __init intel_remapping_check(int num, int 
> slot, int func)
>               set_irq_remapping_broken();
>       else if (device == 0x3405 && revision == 0x22)
>               set_irq_remapping_broken();
> +
> +     return true;
>  }
>  
>  /*
> @@ -585,7 +600,7 @@ intel_graphics_stolen(int num, int slot, int func,
>       e820__update_table(e820_table);
>  }
>  
> -static void __init intel_graphics_quirks(int num, int slot, int func)
> +static bool __init intel_graphics_quirks(int num, int slot, int func)
>  {
>       const struct intel_early_ops *early_ops;
>       u16 device;
> @@ -603,16 +618,20 @@ static void __init intel_graphics_quirks(int num, int 
> slot, int func)
>  
>               intel_graphics_stolen(num, slot, func, early_ops);
>  
> -             return;
> +             return true;
>       }
> +
> +     return false;
>  }
>  
> -static void __init force_disable_hpet(int num, int slot, int func)
> +static bool __init force_disable_hpet(int num, int slot, int func)
>  {
>  #ifdef CONFIG_HPET_TIMER
>       boot_hpet_disable = true;
>       pr_info("x86/hpet: Will disable the HPET for this platform because it's 
> not reliable\n");
>  #endif
> +
> +     return true;
>  }
>  
>  #define BCM4331_MMIO_SIZE    16384
> @@ -620,7 +639,7 @@ static void __init force_disable_hpet(int num, int slot, 
> int func)
>  #define bcma_aread32(reg)    ioread32(mmio + 1 * BCMA_CORE_SIZE + reg)
>  #define bcma_awrite32(reg, val)      iowrite32(val, mmio + 1 * 
> BCMA_CORE_SIZE + reg)
>  
> -static void __init apple_airport_reset(int bus, int slot, int func)
> +static bool __init apple_airport_reset(int bus, int slot, int func)
>  {
>       void __iomem *mmio;
>       u16 pmcsr;
> @@ -628,7 +647,7 @@ static void __init apple_airport_reset(int bus, int slot, 
> int func)
>       int i;
>  
>       if (!x86_apple_machine)
> -             return;
> +             return true;
>  
>       /* Card may have been put into PCI_D3hot by grub quirk */
>       pmcsr = read_pci_config_16(bus, slot, func, BCM4331_PM_CAP + 
> PCI_PM_CTRL);
> @@ -642,7 +661,7 @@ static void __init apple_airport_reset(int bus, int slot, 
> int func)
>               if ((pmcsr & PCI_PM_CTRL_STATE_MASK) != PCI_D0) {
>                       pr_err("pci 0000:%02x:%02x.%d: Cannot power up Apple 
> AirPort card\n",
>                              bus, slot, func);
> -                     return;
> +                     return true;
>               }
>       }
>  
> @@ -654,7 +673,7 @@ static void __init apple_airport_reset(int bus, int slot, 
> int func)
>       if (!mmio) {
>               pr_err("pci 0000:%02x:%02x.%d: Cannot iomap Apple AirPort 
> card\n",
>                      bus, slot, func);
> -             return;
> +             return true;
>       }
>  
>       pr_info("Resetting Apple AirPort card (left enabled by EFI)\n");
> @@ -671,6 +690,8 @@ static void __init apple_airport_reset(int bus, int slot, 
> int func)
>       udelay(10);
>  
>       early_iounmap(mmio, BCM4331_MMIO_SIZE);
> +
> +     return true;
>  }
>  
>  #define QFLAG_APPLY_ONCE     0x1
> @@ -682,7 +703,7 @@ struct chipset {
>       u32 class;
>       u32 class_mask;
>       u32 flags;
> -     void (*f)(int num, int slot, int func);
> +     bool (*f)(int num, int slot, int func);
>  };
>  
>  static struct chipset early_qrk[] __initdata = {
> @@ -757,11 +778,13 @@ static int __init check_dev_quirk(int num, int slot, 
> int func)
>                       (early_qrk[i].device == device)) &&
>                       (!((early_qrk[i].class ^ class) &
>                           early_qrk[i].class_mask))) {
> -                             if ((early_qrk[i].flags &
> -                                  QFLAG_DONE) != QFLAG_DONE)
> -                                     early_qrk[i].f(num, slot, func);
> -                             early_qrk[i].flags |= QFLAG_APPLIED;
> +                     if ((early_qrk[i].flags & QFLAG_DONE) != QFLAG_DONE) {
> +                             bool applied = early_qrk[i].f(num, slot, func);
> +
> +                             if (applied)
> +                                     early_qrk[i].flags |= QFLAG_APPLIED;
>                       }
> +             }
>       }
>  
>       type = read_pci_config_byte(num, slot, func,
> -- 
> 2.34.1
> 

Reply via email to