[Intel-gfx] [PATCH] x86/quirks: Fix logic to apply quirk once

Bjorn Helgaas helgaas at kernel.org
Wed Dec 29 23:27:52 UTC 2021


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.demarchi at 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
> 


More information about the Intel-gfx mailing list