Linux PCI subsystem development
 help / color / mirror / Atom feed
* [PATCH v5] PCI/PME: Resume Catlow Lake Root Ports on PME with PME Status clear
@ 2026-11-03 19:31 Kuppuswamy Sathyanarayanan
  2026-11-03 19:39 ` sashiko-bot
  2026-11-04 14:24 ` Rafael J. Wysocki (Intel)
  0 siblings, 2 replies; 3+ messages in thread
From: Kuppuswamy Sathyanarayanan @ 2026-11-03 19:31 UTC (permalink / raw)
  To: Bjorn Helgaas, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86
  Cc: H . Peter Anvin, Lukas Wunner, Mika Westerberg,
	Rafael J . Wysocki, linux-pci, linux-pm, linux-kernel

Intel Catlow Lake PCH Root Ports do not set PME Status in the Root
Status register when they generate a PME for their own hotplug event.
The PME interrupt itself is delivered.  PMEs from devices below the Root
Port are reported correctly.

PME and hotplug share the same interrupt.  When a hotplug Root Port
runtime suspends to D3hot, pciehp disables hotplug interrupts and relies
on PME to resume the Port.  On a hot-add the Port signals PME, but Root
Status stays clear.  pcie_pme_irq() then returns IRQ_NONE.  pciehp_isr()
also returns IRQ_NONE because hotplug interrupts are disabled.  The Port
stays in D3hot and the new device is never enumerated.

Mark the affected Root Ports with a new PCI_DEV_FLAGS_PME_UNRELIABLE
flag.  If such a Port interrupts while not in D0 and PME Status is
clear, pcie_pme_irq() resumes the Port.  pciehp re-enables hotplug
interrupts on runtime resume, and pciehp_check_presence() finds the new
device.  pciehp itself is unchanged.

The workaround only applies to quirked Ports that are not in D0.  AER,
DPC and bandwidth notification also share the interrupt and stay enabled
in D3hot.  If one of them fires while a quirked Port is in D3hot, the
Port is resumed without need and runtime suspends again later.

This affects all steppings of the Catlow Lake PCH.  A public erratum is
not available yet.

Suggested-by: Lukas Wunner <lukas@wunner.de>
Link: https://lore.kernel.org/linux-pci/ara-_IPXV_i90if1@wunner.de/
Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
---
Changes since v4:
 * Moved the workaround from pciehp to the PME driver (Lukas). pciehp
   now keeps clearing HPIE on suspend as before (Bjorn).
 * Noted in the commit log and in pcie_pme_irq() that PME and hotplug
   share the same interrupt (Bjorn).
 * Dropped the PME Requester ID reference, since the code doesn't use
   it (Bjorn).
 * Dropped the "D3hot to D0 transitions" wording (Bjorn).
 * Updated the quirk comment and message for the PME driver approach.
 * Dropped Reviewed-by from Lukas since the approach changed.
 * The v4 approach in pciehp also fixes the issue on Catlow Lake. I am
   happy to go back to it if that is preferred.

Changes since v3:
 * Moved quirk from drivers/pci/quirks.c to arch/x86/pci/fixup.c (Lukas)
 * Renamed function to intel_pcie_pme_unreliable for x86-specific context.
 * Added Reviewed-by tag from Lukas

Changes since v2:
 * Switched from pm_runtime_disable() to PCI_DEV_FLAGS_PME_UNRELIABLE
   flag approach to avoid power regression (feedback from Rafael and Lukas)
 * Keep hotplug interrupts (HPIE) enabled during D3hot instead of
   preventing D3hot entry entirely
 * Port still enters D3hot for power savings; testing confirms no impact
   on PC6 package C-state residency
 * Modified pciehp to check pme_is_broken() before disabling/enabling
   hotplug interrupts during suspend/resume
 * Made quirk comment generic to cover both PME notification and status
   update issues, with Catlow Lake specifics documented separately

Changes since v1:
 * Removed hack in hotplug driver and disabled runtime PM on affected ports.
 * Fixed the commit log and comments accordingly.

v4: https://lore.kernel.org/linux-pci/20260323223056.3119060-1-sathyanarayanan.kuppuswamy@linux.intel.com/
v3: https://lore.kernel.org/linux-pci/20260316220807.2433661-1-sathyanarayanan.kuppuswamy@linux.intel.com/
v2: https://lore.kernel.org/linux-pci/20260213231428.613164-1-sathyanarayanan.kuppuswamy@linux.intel.com/
v1: https://lore.kernel.org/linux-pci/20260210172231.1465275-1-sathyanarayanan.kuppuswamy@linux.intel.com/

 arch/x86/pci/fixup.c   | 46 ++++++++++++++++++++++++++++++++++++++++++
 drivers/pci/pcie/pme.c | 24 +++++++++++++++++++++-
 include/linux/pci.h    |  2 ++
 3 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index 795d81c7a4de..eb3703e1cdbe 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -1180,3 +1180,49 @@ static void quirk_tuxeo_rp_d3(struct pci_dev *pdev)
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x1502, quirk_tuxeo_rp_d3);
 #endif /* CONFIG_SUSPEND */
+
+/*
+ * Intel Catlow Lake PCH Root Ports do not set PME Status in the Root
+ * Status register for a PME they generate for their own hotplug events,
+ * although the PME interrupt is delivered.  PMEs from devices below the
+ * Port are reported correctly.
+ *
+ * pciehp disables hotplug interrupts when the Port runtime suspends and
+ * relies on PME to resume it.  With PME Status clear, pcie_pme_irq()
+ * ignores the interrupt, the Port stays in D3hot and the hot-add is
+ * lost.  Mark these Ports so that the PME driver resumes them instead.
+ */
+static void intel_pcie_pme_unreliable(struct pci_dev *dev)
+{
+	dev->dev_flags |= PCI_DEV_FLAGS_PME_UNRELIABLE;
+	pci_info(dev, "PME status unreliable, resuming port on PME interrupt in D3hot\n");
+}
+/* Apply quirk to Catlow Lake PCH root ports (0x7a30 - 0x7a4b) */
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a30, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a31, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a32, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a33, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a34, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a35, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a36, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a37, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a38, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a39, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a3a, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a3b, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a3c, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a3d, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a3e, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a3f, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a40, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a41, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a42, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a43, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a44, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a45, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a46, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a47, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a48, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a49, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a4a, intel_pcie_pme_unreliable);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a4b, intel_pcie_pme_unreliable);
diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c
index 4996cc4789f3..56c22e416788 100644
--- a/drivers/pci/pcie/pme.c
+++ b/drivers/pci/pcie/pme.c
@@ -276,11 +276,33 @@ static irqreturn_t pcie_pme_irq(int irq, void *context)
 	spin_lock_irqsave(&data->lock, flags);
 	pcie_capability_read_dword(port, PCI_EXP_RTSTA, &rtsta);
 
-	if (PCI_POSSIBLE_ERROR(rtsta) || !(rtsta & PCI_EXP_RTSTA_PME)) {
+	if (PCI_POSSIBLE_ERROR(rtsta)) {
 		spin_unlock_irqrestore(&data->lock, flags);
 		return IRQ_NONE;
 	}
 
+	if (!(rtsta & PCI_EXP_RTSTA_PME)) {
+		spin_unlock_irqrestore(&data->lock, flags);
+
+		/*
+		 * Some Root Ports don't set PME Status for a PME they
+		 * generate for their own hotplug events.  PME shares its
+		 * interrupt with hotplug and the other Port services, so
+		 * only do this while the Port is not in D0.  Then PME is
+		 * the only interrupt it can signal for such events, so
+		 * resume it and let pciehp pick up the event.
+		 */
+		if ((port->dev_flags & PCI_DEV_FLAGS_PME_UNRELIABLE) &&
+		    port->current_state != PCI_D0) {
+			pci_dbg(port, "PME Status clear in %s, resuming Port\n",
+				pci_power_name(port->current_state));
+			pci_wakeup_event(port);
+			pm_request_resume(&port->dev);
+			return IRQ_HANDLED;
+		}
+		return IRQ_NONE;
+	}
+
 	pcie_pme_interrupt_enable(port, false);
 	spin_unlock_irqrestore(&data->lock, flags);
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index aa3765a20a96..d3915a3d59b9 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -266,6 +266,8 @@ enum pci_dev_flags {
 	 * integrated with the downstream devices and doesn't use real PCI.
 	 */
 	PCI_DEV_FLAGS_PCI_BRIDGE_NO_ALIAS = (__force pci_dev_flags_t) (1 << 14),
+	/* Root Port does not set PME Status for its own hotplug PMEs */
+	PCI_DEV_FLAGS_PME_UNRELIABLE = (__force pci_dev_flags_t) (1 << 15),
 };
 
 enum pci_irq_reroute_variant {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v5] PCI/PME: Resume Catlow Lake Root Ports on PME with PME Status clear
  2026-11-03 19:31 [PATCH v5] PCI/PME: Resume Catlow Lake Root Ports on PME with PME Status clear Kuppuswamy Sathyanarayanan
@ 2026-11-03 19:39 ` sashiko-bot
  2026-11-04 14:24 ` Rafael J. Wysocki (Intel)
  1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-11-03 19:39 UTC (permalink / raw)
  To: Kuppuswamy Sathyanarayanan; +Cc: linux-pci

> Intel Catlow Lake PCH Root Ports do not set PME Status in the Root
> Status register when they generate a PME for their own hotplug event.
> The PME interrupt itself is delivered.  PMEs from devices below the Root
> Port are reported correctly.
> 
> PME and hotplug share the same interrupt.  When a hotplug Root Port
> runtime suspends to D3hot, pciehp disables hotplug interrupts and relies
> on PME to resume the Port.  On a hot-add the Port signals PME, but Root
> Status stays clear.  pcie_pme_irq() then returns IRQ_NONE.  pciehp_isr()
> also returns IRQ_NONE because hotplug interrupts are disabled.  The Port
> stays in D3hot and the new device is never enumerated.
> 
> Mark the affected Root Ports with a new PCI_DEV_FLAGS_PME_UNRELIABLE
> flag.  If such a Port interrupts while not in D0 and PME Status is
> clear, pcie_pme_irq() resumes the Port.  pciehp re-enables hotplug
> interrupts on runtime resume, and pciehp_check_presence() finds the new
> device.  pciehp itself is unchanged.
> 
> The workaround only applies to quirked Ports that are not in D0.  AER,
> DPC and bandwidth notification also share the interrupt and stay enabled
> in D3hot.  If one of them fires while a quirked Port is in D3hot, the
> Port is resumed without need and runtime suspends again later.
> 
> This affects all steppings of the Catlow Lake PCH.  A public erratum is
> not available yet.
> 
> Suggested-by: Lukas Wunner <lukas@wunner.de>
> Link: https://lore.kernel.org/linux-pci/ara-_IPXV_i90if1@wunner.de/
> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261103193136.2410148-1-sathyanarayanan.kuppuswamy@linux.intel.com?part=1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v5] PCI/PME: Resume Catlow Lake Root Ports on PME with PME Status clear
  2026-11-03 19:31 [PATCH v5] PCI/PME: Resume Catlow Lake Root Ports on PME with PME Status clear Kuppuswamy Sathyanarayanan
  2026-11-03 19:39 ` sashiko-bot
@ 2026-11-04 14:24 ` Rafael J. Wysocki (Intel)
  1 sibling, 0 replies; 3+ messages in thread
From: Rafael J. Wysocki (Intel) @ 2026-11-04 14:24 UTC (permalink / raw)
  To: Kuppuswamy Sathyanarayanan
  Cc: Bjorn Helgaas, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H . Peter Anvin, Lukas Wunner, Mika Westerberg,
	Rafael J . Wysocki, linux-pci, linux-pm, linux-kernel

On Tue, Nov 3, 2026 at 8:31 PM Kuppuswamy Sathyanarayanan
<sathyanarayanan.kuppuswamy@linux.intel.com> wrote:
>
> Intel Catlow Lake PCH Root Ports do not set PME Status in the Root
> Status register when they generate a PME for their own hotplug event.
> The PME interrupt itself is delivered.  PMEs from devices below the Root
> Port are reported correctly.
>
> PME and hotplug share the same interrupt.  When a hotplug Root Port
> runtime suspends to D3hot, pciehp disables hotplug interrupts and relies
> on PME to resume the Port.  On a hot-add the Port signals PME, but Root
> Status stays clear.  pcie_pme_irq() then returns IRQ_NONE.  pciehp_isr()
> also returns IRQ_NONE because hotplug interrupts are disabled.  The Port
> stays in D3hot and the new device is never enumerated.
>
> Mark the affected Root Ports with a new PCI_DEV_FLAGS_PME_UNRELIABLE
> flag.  If such a Port interrupts while not in D0 and PME Status is
> clear, pcie_pme_irq() resumes the Port.  pciehp re-enables hotplug
> interrupts on runtime resume, and pciehp_check_presence() finds the new
> device.  pciehp itself is unchanged.
>
> The workaround only applies to quirked Ports that are not in D0.  AER,
> DPC and bandwidth notification also share the interrupt and stay enabled
> in D3hot.  If one of them fires while a quirked Port is in D3hot, the
> Port is resumed without need and runtime suspends again later.
>
> This affects all steppings of the Catlow Lake PCH.  A public erratum is
> not available yet.
>
> Suggested-by: Lukas Wunner <lukas@wunner.de>
> Link: https://lore.kernel.org/linux-pci/ara-_IPXV_i90if1@wunner.de/
> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>

Makes sense to me.

Acked-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>

> ---
> Changes since v4:
>  * Moved the workaround from pciehp to the PME driver (Lukas). pciehp
>    now keeps clearing HPIE on suspend as before (Bjorn).
>  * Noted in the commit log and in pcie_pme_irq() that PME and hotplug
>    share the same interrupt (Bjorn).
>  * Dropped the PME Requester ID reference, since the code doesn't use
>    it (Bjorn).
>  * Dropped the "D3hot to D0 transitions" wording (Bjorn).
>  * Updated the quirk comment and message for the PME driver approach.
>  * Dropped Reviewed-by from Lukas since the approach changed.
>  * The v4 approach in pciehp also fixes the issue on Catlow Lake. I am
>    happy to go back to it if that is preferred.
>
> Changes since v3:
>  * Moved quirk from drivers/pci/quirks.c to arch/x86/pci/fixup.c (Lukas)
>  * Renamed function to intel_pcie_pme_unreliable for x86-specific context.
>  * Added Reviewed-by tag from Lukas
>
> Changes since v2:
>  * Switched from pm_runtime_disable() to PCI_DEV_FLAGS_PME_UNRELIABLE
>    flag approach to avoid power regression (feedback from Rafael and Lukas)
>  * Keep hotplug interrupts (HPIE) enabled during D3hot instead of
>    preventing D3hot entry entirely
>  * Port still enters D3hot for power savings; testing confirms no impact
>    on PC6 package C-state residency
>  * Modified pciehp to check pme_is_broken() before disabling/enabling
>    hotplug interrupts during suspend/resume
>  * Made quirk comment generic to cover both PME notification and status
>    update issues, with Catlow Lake specifics documented separately
>
> Changes since v1:
>  * Removed hack in hotplug driver and disabled runtime PM on affected ports.
>  * Fixed the commit log and comments accordingly.
>
> v4: https://lore.kernel.org/linux-pci/20260323223056.3119060-1-sathyanarayanan.kuppuswamy@linux.intel.com/
> v3: https://lore.kernel.org/linux-pci/20260316220807.2433661-1-sathyanarayanan.kuppuswamy@linux.intel.com/
> v2: https://lore.kernel.org/linux-pci/20260213231428.613164-1-sathyanarayanan.kuppuswamy@linux.intel.com/
> v1: https://lore.kernel.org/linux-pci/20260210172231.1465275-1-sathyanarayanan.kuppuswamy@linux.intel.com/
>
>  arch/x86/pci/fixup.c   | 46 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/pci/pcie/pme.c | 24 +++++++++++++++++++++-
>  include/linux/pci.h    |  2 ++
>  3 files changed, 71 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
> index 795d81c7a4de..eb3703e1cdbe 100644
> --- a/arch/x86/pci/fixup.c
> +++ b/arch/x86/pci/fixup.c
> @@ -1180,3 +1180,49 @@ static void quirk_tuxeo_rp_d3(struct pci_dev *pdev)
>  }
>  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x1502, quirk_tuxeo_rp_d3);
>  #endif /* CONFIG_SUSPEND */
> +
> +/*
> + * Intel Catlow Lake PCH Root Ports do not set PME Status in the Root
> + * Status register for a PME they generate for their own hotplug events,
> + * although the PME interrupt is delivered.  PMEs from devices below the
> + * Port are reported correctly.
> + *
> + * pciehp disables hotplug interrupts when the Port runtime suspends and
> + * relies on PME to resume it.  With PME Status clear, pcie_pme_irq()
> + * ignores the interrupt, the Port stays in D3hot and the hot-add is
> + * lost.  Mark these Ports so that the PME driver resumes them instead.
> + */
> +static void intel_pcie_pme_unreliable(struct pci_dev *dev)
> +{
> +       dev->dev_flags |= PCI_DEV_FLAGS_PME_UNRELIABLE;
> +       pci_info(dev, "PME status unreliable, resuming port on PME interrupt in D3hot\n");
> +}
> +/* Apply quirk to Catlow Lake PCH root ports (0x7a30 - 0x7a4b) */
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a30, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a31, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a32, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a33, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a34, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a35, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a36, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a37, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a38, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a39, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a3a, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a3b, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a3c, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a3d, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a3e, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a3f, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a40, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a41, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a42, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a43, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a44, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a45, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a46, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a47, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a48, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a49, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a4a, intel_pcie_pme_unreliable);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x7a4b, intel_pcie_pme_unreliable);
> diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c
> index 4996cc4789f3..56c22e416788 100644
> --- a/drivers/pci/pcie/pme.c
> +++ b/drivers/pci/pcie/pme.c
> @@ -276,11 +276,33 @@ static irqreturn_t pcie_pme_irq(int irq, void *context)
>         spin_lock_irqsave(&data->lock, flags);
>         pcie_capability_read_dword(port, PCI_EXP_RTSTA, &rtsta);
>
> -       if (PCI_POSSIBLE_ERROR(rtsta) || !(rtsta & PCI_EXP_RTSTA_PME)) {
> +       if (PCI_POSSIBLE_ERROR(rtsta)) {
>                 spin_unlock_irqrestore(&data->lock, flags);
>                 return IRQ_NONE;
>         }
>
> +       if (!(rtsta & PCI_EXP_RTSTA_PME)) {
> +               spin_unlock_irqrestore(&data->lock, flags);
> +
> +               /*
> +                * Some Root Ports don't set PME Status for a PME they
> +                * generate for their own hotplug events.  PME shares its
> +                * interrupt with hotplug and the other Port services, so
> +                * only do this while the Port is not in D0.  Then PME is
> +                * the only interrupt it can signal for such events, so
> +                * resume it and let pciehp pick up the event.
> +                */
> +               if ((port->dev_flags & PCI_DEV_FLAGS_PME_UNRELIABLE) &&
> +                   port->current_state != PCI_D0) {
> +                       pci_dbg(port, "PME Status clear in %s, resuming Port\n",
> +                               pci_power_name(port->current_state));
> +                       pci_wakeup_event(port);
> +                       pm_request_resume(&port->dev);
> +                       return IRQ_HANDLED;
> +               }
> +               return IRQ_NONE;
> +       }
> +
>         pcie_pme_interrupt_enable(port, false);
>         spin_unlock_irqrestore(&data->lock, flags);
>
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index aa3765a20a96..d3915a3d59b9 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -266,6 +266,8 @@ enum pci_dev_flags {
>          * integrated with the downstream devices and doesn't use real PCI.
>          */
>         PCI_DEV_FLAGS_PCI_BRIDGE_NO_ALIAS = (__force pci_dev_flags_t) (1 << 14),
> +       /* Root Port does not set PME Status for its own hotplug PMEs */
> +       PCI_DEV_FLAGS_PME_UNRELIABLE = (__force pci_dev_flags_t) (1 << 15),
>  };
>
>  enum pci_irq_reroute_variant {
> --
> 2.43.0
>

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-11-04 14:25 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-03 19:31 [PATCH v5] PCI/PME: Resume Catlow Lake Root Ports on PME with PME Status clear Kuppuswamy Sathyanarayanan
2026-11-03 19:39 ` sashiko-bot
2026-11-04 14:24 ` Rafael J. Wysocki (Intel)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox