* [PATCH v6 0/7] pm_pme support on display hotplug
@ 2026-09-14 19:47 Vinod Govindapillai
2026-09-14 19:47 ` [PATCH v6 1/7] drm/xe/pm: initialize the device's system wakeup capabilities Vinod Govindapillai
` (7 more replies)
0 siblings, 8 replies; 12+ messages in thread
From: Vinod Govindapillai @ 2026-09-14 19:47 UTC (permalink / raw)
To: intel-xe, intel-gfx; +Cc: jouni.hogander
Introduce PME support for PME capable devices and avoid
HPD polling on runtime suspend. For PME capable devices
HPD will trigger PME which will wakeup the system. And
rest of the runtime resume call is same as before.
v2: Instead of plumbing keep_hpd and pme_capability to
the existing interfaces, a separate helper function to
set and get pme capability is added.
HPD polling is handled directly inside the
intel_hpd_poll_enable() based on the pme capability
flag
v3: Lockdep related splats were observed during some rare testing
scenarios. The PCI PME api to enable wake internally use kmalloc
and can trigger deadlocks. So the calls to the PCI PME APIs are
updated and placed within the no reclaim loop. Also any display
specific calls are isolated within xe / i915 blocks and display
parent interface is used to tackle the inter dependencies to
keep the display module design clean.
v4: No need to maintaining another variable to keep track of PME
can be generated from HPD in intel_hotplug. Instead the parent
interface function can be used directly to get the xe.pme.enabled
to know PME is enabled and configure the IRQ resets and HPD polling
Vinod Govindapillai (7):
drm/xe/pm: initialize the device's system wakeup capabilities
drm/xe/pm: introduce PM PME support
drm/xe/pm: avoid reclaim when arming PME wakeup
drm/i915: add pme_enabled() to the parent interface
drm/i915/xe: plug the pme_enabed implementation for xe
drm/i915/irq: conditional HPD IRQ resets based on PME capability
drm/i915/hotplug: avoid HPD polling if the device is PME capable
.../gpu/drm/i915/display/intel_display_irq.c | 19 +++++++----
.../gpu/drm/i915/display/intel_display_rpm.c | 7 ++++
.../gpu/drm/i915/display/intel_display_rpm.h | 1 +
drivers/gpu/drm/i915/display/intel_hotplug.c | 5 +++
drivers/gpu/drm/xe/display/xe_display_rpm.c | 6 ++++
drivers/gpu/drm/xe/xe_device_types.h | 13 ++++++++
drivers/gpu/drm/xe/xe_pci.c | 26 ++++++++++++++-
drivers/gpu/drm/xe/xe_pm.c | 33 +++++++++++++++++++
drivers/gpu/drm/xe/xe_pm.h | 2 ++
include/drm/intel/display_parent_interface.h | 1 +
10 files changed, 105 insertions(+), 8 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v6 1/7] drm/xe/pm: initialize the device's system wakeup capabilities
2026-09-14 19:47 [PATCH v6 0/7] pm_pme support on display hotplug Vinod Govindapillai
@ 2026-09-14 19:47 ` Vinod Govindapillai
2026-09-14 20:00 ` sashiko-bot
2026-09-14 19:47 ` [PATCH v6 2/7] drm/xe/pm: introduce PM PME support Vinod Govindapillai
` (6 subsequent siblings)
7 siblings, 1 reply; 12+ messages in thread
From: Vinod Govindapillai @ 2026-09-14 19:47 UTC (permalink / raw)
To: intel-xe, intel-gfx; +Cc: jouni.hogander
NVL+ XE devices are capable of generating PME from HPDs. Enable
the device as a wakeup device so the display hotplugs can
generate PM PME events and can invoke pm runtime resume routine.
Bspec: 52979, 52980, 68857, 68867, 68970
Assisted-by: GitHub_Copilot:claude-opus-5
Signed-off-by: Vinod Govindapillai <vinod.govindapillai@intel.com>
---
drivers/gpu/drm/xe/xe_pci.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index ab4da1d9a9f1..f8e16aefd2f8 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -1217,6 +1217,10 @@ static int __xe_pci_probe(struct pci_dev *pdev, const struct xe_device_desc *des
pci_set_master(pdev);
+ err = devm_device_init_wakeup(&pdev->dev);
+ if (err)
+ return err;
+
err = xe_probe_info_early(xe, desc, &probed_info);
if (err)
return err;
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v6 2/7] drm/xe/pm: introduce PM PME support
2026-09-14 19:47 [PATCH v6 0/7] pm_pme support on display hotplug Vinod Govindapillai
2026-09-14 19:47 ` [PATCH v6 1/7] drm/xe/pm: initialize the device's system wakeup capabilities Vinod Govindapillai
@ 2026-09-14 19:47 ` Vinod Govindapillai
2026-09-14 20:01 ` sashiko-bot
2026-09-14 19:47 ` [PATCH v6 3/7] drm/xe/pm: avoid reclaim when arming PME wakeup Vinod Govindapillai
` (5 subsequent siblings)
7 siblings, 1 reply; 12+ messages in thread
From: Vinod Govindapillai @ 2026-09-14 19:47 UTC (permalink / raw)
To: intel-xe, intel-gfx; +Cc: jouni.hogander
Introduce PME support for PME capable devices. Whether device is
PME capable is assessed during PCI probe routine. And the whether
PME is enabled for a specific context is assessed during the PM
runtime suspend call if the device is PME capable.
If the PME is enabled, HPDs can generate PME which in turn call
the runtime resume call and do the wakeup routines. Till now
the driver was relying on HPD polling to wakeup in case of any
HPDs. HPD polling can be avoided in platforms with PME support
and instead rely on this PCI PME for HPD induced wakeup.
v2: access functions for xe.pme.enabled status and clear the pme.
enabled in case of error in xe_pm_runtime_suspend()
Bspec: 52979, 52980, 68857, 68867, 68970
Assisted-by: GitHub_Copilot:claude-opus-5
Signed-off-by: Vinod Govindapillai <vinod.govindapillai@intel.com>
---
drivers/gpu/drm/xe/xe_device_types.h | 13 +++++++++++
drivers/gpu/drm/xe/xe_pci.c | 16 +++++++++++++-
drivers/gpu/drm/xe/xe_pm.c | 33 ++++++++++++++++++++++++++++
drivers/gpu/drm/xe/xe_pm.h | 2 ++
4 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index f88bacf63c83..37190473f6db 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -454,6 +454,19 @@ struct xe_device {
struct mutex lock;
} d3cold;
+ /** @pme: Encapsulate pme related stuff */
+ struct {
+ /** @pme.capable: Indicates if device is PME capable */
+ bool capable;
+
+ /** @pme.enabled:
+ *
+ * Indicates if PME is enabled - depends on user controllable
+ * sysfs interface as well
+ */
+ bool enabled;
+ } pme;
+
/** @pm_notifier: Our PM notifier to perform actions in response to various PM events. */
struct notifier_block pm_notifier;
/** @pm_block: Completion to block validating tasks on suspend / hibernate prepare */
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index f8e16aefd2f8..e7e6b5a7d738 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -1385,8 +1385,14 @@ static int xe_pci_runtime_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct xe_device *xe = pdev_to_xe_device(pdev);
+ bool pme_enabled;
int err;
+ pme_enabled = xe->pme.capable && !xe->d3cold.allowed &&
+ pci_enable_wake(pdev, PCI_D3hot, true) == 0;
+
+ xe_pm_update_pme_enabled(xe, pme_enabled);
+
/*
* We hold an additional reference to the runtime PM to keep PF in D0
* during VFs lifetime, as our VFs do not implement the PM capability.
@@ -1397,8 +1403,14 @@ static int xe_pci_runtime_suspend(struct device *dev)
xe_assert(xe, !pci_num_vf(pdev));
err = xe_pm_runtime_suspend(xe);
- if (err)
+ if (err) {
+ if (xe_pm_pme_enabled(xe)) {
+ pci_enable_wake(pdev, PCI_D3hot, false);
+ xe_pm_update_pme_enabled(xe, false);
+ }
+
return err;
+ }
pci_save_state(pdev);
@@ -1427,6 +1439,8 @@ static int xe_pci_runtime_resume(struct device *dev)
pci_restore_state(pdev);
+ xe_pm_update_pme_enabled(xe, false);
+
if (xe->d3cold.allowed) {
err = pci_enable_device(pdev);
if (err)
diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c
index f517bf453b54..f282f7676826 100644
--- a/drivers/gpu/drm/xe/xe_pm.c
+++ b/drivers/gpu/drm/xe/xe_pm.c
@@ -78,6 +78,8 @@
* management (RPS).
*/
+#define HAS_PM_PME_SUPPORT(xe) (GRAPHICS_VERx100(xe) >= 3500)
+
#ifdef CONFIG_LOCKDEP
static struct lockdep_map xe_pm_runtime_d3cold_map = {
.name = "xe_rpm_d3cold_map"
@@ -384,6 +386,14 @@ int xe_pm_init_early(struct xe_device *xe)
}
ALLOW_ERROR_INJECTION(xe_pm_init_early, ERRNO); /* See xe_pci_probe() */
+static bool xe_pm_pci_pme_capable(struct xe_device *xe)
+{
+ struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
+
+ return HAS_PM_PME_SUPPORT(xe) ?
+ pci_pme_capable(pdev, PCI_D3hot) : false;
+}
+
/**
* xe_pm_probe() - Initialize Xe Power Management
* @xe: the &xe_device instance
@@ -397,6 +407,9 @@ int xe_pm_probe(struct xe_device *xe)
xe->d3cold.capable = xe_pm_pci_d3cold_capable(xe);
xe_dbg(xe, "d3cold: capable=%s\n", str_yes_no(xe->d3cold.capable));
+ xe->pme.capable = xe_pm_pci_pme_capable(xe);
+ xe_dbg(xe, "pme: capable=%s\n", str_yes_no(xe->pme.capable));
+
return 0;
}
@@ -650,6 +663,7 @@ int xe_pm_runtime_suspend(struct xe_device *xe)
return 0;
out_resume:
+ xe_pm_update_pme_enabled(xe, false);
xe_display_pm_runtime_resume(xe);
xe_pxp_pm_resume(xe->pxp);
out:
@@ -993,6 +1007,25 @@ int xe_pm_set_vram_threshold(struct xe_device *xe, u32 threshold)
return 0;
}
+bool xe_pm_pme_enabled(struct xe_device *xe)
+{
+ return xe->pme.enabled;
+}
+
+/**
+ * xe_pm_update_pme_enabled - Update the PME enabled state
+ * @xe: xe device instance
+ * @status: New PME enabled status
+ *
+ * To be called during runtime_pm suspend / resume.
+ * True if conditions are met during runtime_suspend.
+ * False during runtime_resume and other error scenarios in suspend.
+ */
+void xe_pm_update_pme_enabled(struct xe_device *xe, bool status)
+{
+ xe->pme.enabled = status;
+}
+
/**
* xe_pm_d3cold_allowed_toggle - Check conditions to toggle d3cold.allowed
* @xe: xe device instance
diff --git a/drivers/gpu/drm/xe/xe_pm.h b/drivers/gpu/drm/xe/xe_pm.h
index 6d5ab09cb769..037c73ea4342 100644
--- a/drivers/gpu/drm/xe/xe_pm.h
+++ b/drivers/gpu/drm/xe/xe_pm.h
@@ -33,6 +33,8 @@ bool xe_pm_runtime_resume_and_get(struct xe_device *xe);
void xe_pm_assert_unbounded_bridge(struct xe_device *xe);
int xe_pm_set_vram_threshold(struct xe_device *xe, u32 threshold);
void xe_pm_d3cold_allowed_toggle(struct xe_device *xe);
+bool xe_pm_pme_enabled(struct xe_device *xe);
+void xe_pm_update_pme_enabled(struct xe_device *xe, bool status);
bool xe_rpm_reclaim_safe(const struct xe_device *xe);
struct task_struct *xe_pm_read_callback_task(struct xe_device *xe);
int xe_pm_block_on_suspend(struct xe_device *xe);
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v6 3/7] drm/xe/pm: avoid reclaim when arming PME wakeup
2026-09-14 19:47 [PATCH v6 0/7] pm_pme support on display hotplug Vinod Govindapillai
2026-09-14 19:47 ` [PATCH v6 1/7] drm/xe/pm: initialize the device's system wakeup capabilities Vinod Govindapillai
2026-09-14 19:47 ` [PATCH v6 2/7] drm/xe/pm: introduce PM PME support Vinod Govindapillai
@ 2026-09-14 19:47 ` Vinod Govindapillai
2026-09-14 19:47 ` [PATCH v6 4/7] drm/i915: add pme_enabled() to the parent interface Vinod Govindapillai
` (4 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Vinod Govindapillai @ 2026-09-14 19:47 UTC (permalink / raw)
To: intel-xe, intel-gfx; +Cc: jouni.hogander
pci_enable_wake() evaluates ACPI methods and allocates with GFP_KERNEL.
xe's shrinker calls xe_pm_runtime_get() and blocks until the runtime
suspend transition completes, so fs_reclaim sits above the runtime PM
lockmap (primed in xe_pm_runtime_lockdep_prime()). An allocation that
enters reclaim from the suspend path can therefore deadlock against a
task already holding fs_reclaim and waiting on that transition.
Wrap the call in memalloc_noreclaim_save()/restore() so the allocation
is satisfied from reserves and never enters reclaim.
Assisted-by: GitHub_Copilot:claude-opus-5
Signed-off-by: Vinod Govindapillai <vinod.govindapillai@intel.com>
---
drivers/gpu/drm/xe/xe_pci.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index e7e6b5a7d738..2fa051579c0b 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -1385,11 +1385,14 @@ static int xe_pci_runtime_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct xe_device *xe = pdev_to_xe_device(pdev);
+ unsigned int flags;
bool pme_enabled;
int err;
+ flags = memalloc_noreclaim_save();
pme_enabled = xe->pme.capable && !xe->d3cold.allowed &&
pci_enable_wake(pdev, PCI_D3hot, true) == 0;
+ memalloc_noreclaim_restore(flags);
xe_pm_update_pme_enabled(xe, pme_enabled);
@@ -1405,7 +1408,10 @@ static int xe_pci_runtime_suspend(struct device *dev)
err = xe_pm_runtime_suspend(xe);
if (err) {
if (xe_pm_pme_enabled(xe)) {
+ flags = memalloc_noreclaim_save();
pci_enable_wake(pdev, PCI_D3hot, false);
+ memalloc_noreclaim_restore(flags);
+
xe_pm_update_pme_enabled(xe, false);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v6 4/7] drm/i915: add pme_enabled() to the parent interface
2026-09-14 19:47 [PATCH v6 0/7] pm_pme support on display hotplug Vinod Govindapillai
` (2 preceding siblings ...)
2026-09-14 19:47 ` [PATCH v6 3/7] drm/xe/pm: avoid reclaim when arming PME wakeup Vinod Govindapillai
@ 2026-09-14 19:47 ` Vinod Govindapillai
2026-09-14 19:47 ` [PATCH v6 5/7] drm/i915/xe: plug the pme_enabed implementation for xe Vinod Govindapillai
` (3 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Vinod Govindapillai @ 2026-09-14 19:47 UTC (permalink / raw)
To: intel-xe, intel-gfx; +Cc: jouni.hogander
PME capabiliy need to be assessed very early during runtime suspend
routine to avoid resetting HPDs during IRQ resets. As display
runtime pm routines are being executed in the independent intel
display driver entry points, we need to have independent access
to the pme status as well. Add a provision to query the optional
pme_enabled to the parent interface so that it could be called
independently based on xe/i915's pme_enabled() implementation.
Assisted-by: GitHub_Copilot:claude-opus-5
Signed-off-by: Vinod Govindapillai <vinod.govindapillai@intel.com>
---
drivers/gpu/drm/i915/display/intel_display_rpm.c | 7 +++++++
drivers/gpu/drm/i915/display/intel_display_rpm.h | 1 +
include/drm/intel/display_parent_interface.h | 1 +
3 files changed, 9 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_display_rpm.c b/drivers/gpu/drm/i915/display/intel_display_rpm.c
index 0a331f89b4db..9927119a0fd1 100644
--- a/drivers/gpu/drm/i915/display/intel_display_rpm.c
+++ b/drivers/gpu/drm/i915/display/intel_display_rpm.c
@@ -46,6 +46,13 @@ bool intel_display_rpm_suspended(struct intel_display *display)
return display->parent->rpm->suspended(display->drm);
}
+bool intel_display_rpm_pme_enabled(struct intel_display *display)
+{
+ const struct intel_display_rpm_interface *rpm = display->parent->rpm;
+
+ return rpm->pme_enabled && rpm->pme_enabled(display->drm);
+}
+
void assert_display_rpm_held(struct intel_display *display)
{
display->parent->rpm->assert_held(display->drm);
diff --git a/drivers/gpu/drm/i915/display/intel_display_rpm.h b/drivers/gpu/drm/i915/display/intel_display_rpm.h
index 6ef48515f84b..5d9a1cdddfa7 100644
--- a/drivers/gpu/drm/i915/display/intel_display_rpm.h
+++ b/drivers/gpu/drm/i915/display/intel_display_rpm.h
@@ -21,6 +21,7 @@ void intel_display_rpm_put(struct intel_display *display, struct ref_tracker *wa
/* Only for special cases. */
bool intel_display_rpm_suspended(struct intel_display *display);
+bool intel_display_rpm_pme_enabled(struct intel_display *display);
void assert_display_rpm_held(struct intel_display *display);
void intel_display_rpm_assert_block(struct intel_display *display);
diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h
index 5e44c022d1ae..f36134e89cb6 100644
--- a/include/drm/intel/display_parent_interface.h
+++ b/include/drm/intel/display_parent_interface.h
@@ -196,6 +196,7 @@ struct intel_display_rpm_interface {
void (*put_unchecked)(const struct drm_device *drm);
bool (*suspended)(const struct drm_device *drm);
+ bool (*pme_enabled)(const struct drm_device *drm); /* Optional */
void (*assert_held)(const struct drm_device *drm);
void (*assert_block)(const struct drm_device *drm);
void (*assert_unblock)(const struct drm_device *drm);
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v6 5/7] drm/i915/xe: plug the pme_enabed implementation for xe
2026-09-14 19:47 [PATCH v6 0/7] pm_pme support on display hotplug Vinod Govindapillai
` (3 preceding siblings ...)
2026-09-14 19:47 ` [PATCH v6 4/7] drm/i915: add pme_enabled() to the parent interface Vinod Govindapillai
@ 2026-09-14 19:47 ` Vinod Govindapillai
2026-09-14 19:47 ` [PATCH v6 6/7] drm/i915/irq: conditional HPD IRQ resets based on PME capability Vinod Govindapillai
` (2 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Vinod Govindapillai @ 2026-09-14 19:47 UTC (permalink / raw)
To: intel-xe, intel-gfx; +Cc: jouni.hogander
Plug the pme_enabled query for xe. It will return the current
PME status for the device. For supported platforms, PME is
enabled during runtime suspend calls if the device is PME is capable.
v2: use the xe_pm_pme_enabled()
Assisted-by: GitHub_Copilot:claude-opus-5
Signed-off-by: Vinod Govindapillai <vinod.govindapillai@intel.com>
---
drivers/gpu/drm/xe/display/xe_display_rpm.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/xe/display/xe_display_rpm.c b/drivers/gpu/drm/xe/display/xe_display_rpm.c
index 548b503aa024..57bcfb41bdda 100644
--- a/drivers/gpu/drm/xe/display/xe_display_rpm.c
+++ b/drivers/gpu/drm/xe/display/xe_display_rpm.c
@@ -45,6 +45,11 @@ static bool xe_display_rpm_suspended(const struct drm_device *drm)
return pm_runtime_suspended(xe->drm.dev);
}
+static bool xe_display_rpm_pme_enabled(const struct drm_device *drm)
+{
+ return xe_pm_pme_enabled(to_xe_device(drm));
+}
+
static void xe_display_rpm_assert_held(const struct drm_device *drm)
{
/* FIXME */
@@ -69,6 +74,7 @@ const struct intel_display_rpm_interface xe_display_rpm_interface = {
.put_raw = xe_display_rpm_put,
.put_unchecked = xe_display_rpm_put_unchecked,
.suspended = xe_display_rpm_suspended,
+ .pme_enabled = xe_display_rpm_pme_enabled,
.assert_held = xe_display_rpm_assert_held,
.assert_block = xe_display_rpm_assert_block,
.assert_unblock = xe_display_rpm_assert_unblock
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v6 6/7] drm/i915/irq: conditional HPD IRQ resets based on PME capability
2026-09-14 19:47 [PATCH v6 0/7] pm_pme support on display hotplug Vinod Govindapillai
` (4 preceding siblings ...)
2026-09-14 19:47 ` [PATCH v6 5/7] drm/i915/xe: plug the pme_enabed implementation for xe Vinod Govindapillai
@ 2026-09-14 19:47 ` Vinod Govindapillai
2026-09-14 20:06 ` sashiko-bot
2026-09-14 19:47 ` [PATCH v6 7/7] drm/i915/hotplug: avoid HPD polling if the device is PME capable Vinod Govindapillai
2026-09-14 19:52 ` ✗ Fi.CI.BUILD: failure for pm_pme support on display hotplug (rev6) Patchwork
7 siblings, 1 reply; 12+ messages in thread
From: Vinod Govindapillai @ 2026-09-14 19:47 UTC (permalink / raw)
To: intel-xe, intel-gfx; +Cc: jouni.hogander
If a device supports generating PME from HPDs, resetting HPD IRQs
will be counter productive as HPDs itself will be lost. During
suspend routines, all the IRQs are reset. So if the device is
capable of generating PME rom HPDs, keep the HPD related IRQs from
reset based on the PME capability of the device on a target power
state. PME capability will be assessed and updated separately.
v2: change keep_hpd to reset_hpd
v3: use intel_display_rpm_pme_enabled() directly (JaniN)
Bspec: 52979, 52980, 68857, 68867, 68970
Assisted-by: GitHub_Copilot:claude-opus-5
Signed-off-by: Vinod Govindapillai <vinod.govindapillai@intel.com>
---
.../gpu/drm/i915/display/intel_display_irq.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c
index a59b75830bd1..7e71c96c663f 100644
--- a/drivers/gpu/drm/i915/display/intel_display_irq.c
+++ b/drivers/gpu/drm/i915/display/intel_display_irq.c
@@ -22,6 +22,7 @@
#include "intel_fdi_regs.h"
#include "intel_fifo_underrun.h"
#include "intel_gmbus.h"
+#include "intel_hotplug.h"
#include "intel_hotplug_irq.h"
#include "intel_lpe_audio.h"
#include "intel_parent.h"
@@ -2217,8 +2218,10 @@ static void gen11_display_irq_reset(struct intel_display *display)
enum pipe pipe;
u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
+ bool reset_hpd = !intel_display_rpm_pme_enabled(display);
- intel_de_write(display, GEN11_DISPLAY_INT_CTL, 0);
+ if (reset_hpd)
+ intel_de_write(display, GEN11_DISPLAY_INT_CTL, 0);
if (DISPLAY_VER(display) >= 12) {
enum transcoder trans;
@@ -2250,13 +2253,15 @@ static void gen11_display_irq_reset(struct intel_display *display)
irq_reset(display, GEN8_DE_PORT_IRQ_REGS);
irq_reset(display, GEN8_DE_MISC_IRQ_REGS);
- if (DISPLAY_VER(display) >= 14)
- irq_reset(display, PICAINTERRUPT_IRQ_REGS);
- else
- irq_reset(display, GEN11_DE_HPD_IRQ_REGS);
+ if (reset_hpd) {
+ if (DISPLAY_VER(display) >= 14)
+ irq_reset(display, PICAINTERRUPT_IRQ_REGS);
+ else
+ irq_reset(display, GEN11_DE_HPD_IRQ_REGS);
- if (INTEL_PCH_TYPE(display) >= PCH_ICP)
- irq_reset(display, SDE_IRQ_REGS);
+ if (INTEL_PCH_TYPE(display) >= PCH_ICP)
+ irq_reset(display, SDE_IRQ_REGS);
+ }
}
void gen8_irq_power_well_post_enable(struct intel_display *display,
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v6 7/7] drm/i915/hotplug: avoid HPD polling if the device is PME capable
2026-09-14 19:47 [PATCH v6 0/7] pm_pme support on display hotplug Vinod Govindapillai
` (5 preceding siblings ...)
2026-09-14 19:47 ` [PATCH v6 6/7] drm/i915/irq: conditional HPD IRQ resets based on PME capability Vinod Govindapillai
@ 2026-09-14 19:47 ` Vinod Govindapillai
2026-09-14 19:52 ` ✗ Fi.CI.BUILD: failure for pm_pme support on display hotplug (rev6) Patchwork
7 siblings, 0 replies; 12+ messages in thread
From: Vinod Govindapillai @ 2026-09-14 19:47 UTC (permalink / raw)
To: intel-xe, intel-gfx; +Cc: jouni.hogander
In supported devices, HPDs can generate PME and which in turn
can invoke runtime resume calls for xe. No need to keep the
HPD polling in such PME capable devices.
v2: use intel_display_rpm_pme_enabled() directly (JaniN)
Bspec: 52979, 52980, 68857, 68867, 68970
Assisted-by: GitHub_Copilot:claude-opus-5
Signed-off-by: Vinod Govindapillai <vinod.govindapillai@intel.com>
---
drivers/gpu/drm/i915/display/intel_hotplug.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c
index 970aa95ee344..d095eb13dc06 100644
--- a/drivers/gpu/drm/i915/display/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/display/intel_hotplug.c
@@ -867,6 +867,11 @@ void intel_hpd_poll_enable(struct intel_display *display)
if (!HAS_DISPLAY(display) || !intel_display_device_enabled(display))
return;
+ if (intel_display_rpm_pme_enabled(display)) {
+ drm_dbg_kms(display->drm, "PME wake capable device, skipping HPD polling.\n");
+ return;
+ }
+
WRITE_ONCE(display->hotplug.poll_enabled, true);
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* ✗ Fi.CI.BUILD: failure for pm_pme support on display hotplug (rev6)
2026-09-14 19:47 [PATCH v6 0/7] pm_pme support on display hotplug Vinod Govindapillai
` (6 preceding siblings ...)
2026-09-14 19:47 ` [PATCH v6 7/7] drm/i915/hotplug: avoid HPD polling if the device is PME capable Vinod Govindapillai
@ 2026-09-14 19:52 ` Patchwork
7 siblings, 0 replies; 12+ messages in thread
From: Patchwork @ 2026-09-14 19:52 UTC (permalink / raw)
To: Vinod Govindapillai; +Cc: intel-gfx
== Series Details ==
Series: pm_pme support on display hotplug (rev6)
URL : https://patchwork.freedesktop.org/series/172306/
State : failure
== Summary ==
Error: patch https://patchwork.freedesktop.org/api/1.0/series/172306/revisions/6/mbox/ not applied
Applying: drm/xe/pm: initialize the device's system wakeup capabilities
Using index info to reconstruct a base tree...
M drivers/gpu/drm/xe/xe_pci.c
Falling back to patching base and 3-way merge...
Auto-merging drivers/gpu/drm/xe/xe_pci.c
CONFLICT (content): Merge conflict in drivers/gpu/drm/xe/xe_pci.c
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 drm/xe/pm: initialize the device's system wakeup capabilities
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Build failed, no error log produced
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 1/7] drm/xe/pm: initialize the device's system wakeup capabilities
2026-09-14 19:47 ` [PATCH v6 1/7] drm/xe/pm: initialize the device's system wakeup capabilities Vinod Govindapillai
@ 2026-09-14 20:00 ` sashiko-bot
0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-09-14 20:00 UTC (permalink / raw)
To: Vinod Govindapillai; +Cc: intel-xe, intel-gfx
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Using devm_device_init_wakeup() on a PCI device corrupts bus-managed can_wakeup state on unbind.
- [Medium] Unconditional execution of devm_device_init_wakeup() forcefully overrides PCI PME capabilities and violates SR-IOV VF constraints.
--
commit df4a3e5da10819a464844de67d48ba7d13070965
Author: Vinod Govindapillai <vinod.govindapillai@intel.com>
drm/xe/pm: initialize the device's system wakeup capabilities
This commit enables the device as a wakeup device so display hotplugs can
generate PM PME events. This enables invoking the PM runtime resume routine
for NVL+ XE devices.
> diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
> index 5f2a0b19839d1..32e10e1a26eff 100644
> --- a/drivers/gpu/drm/xe/xe_pci.c
> +++ b/drivers/gpu/drm/xe/xe_pci.c
> @@ -1200,6 +1200,10 @@ static int xe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>
> pci_set_master(pdev);
>
> + err = devm_device_init_wakeup(&pdev->dev);
[Severity: High]
Does calling devm_device_init_wakeup() on a PCI device corrupt the
bus-managed can_wakeup state on unbind?
When the driver is unbound, the devres cleanup triggers
device_disable_wakeup(), which explicitly calls
device_set_wakeup_capable(dev, false). This causes the device to permanently
lose its can_wakeup capability in the driver model, breaking PME capabilities
and userspace sysfs interfaces after a driver unbind/rebind cycle.
Should the driver use device_wakeup_enable() to toggle only the
should_wakeup state, rather than overriding the bus-owned capability flag set
during bus enumeration?
[Severity: Medium]
Does this unconditional execution of devm_device_init_wakeup() forcefully
override PCI PME capabilities and violate SR-IOV VF constraints?
The driver forcefully sets can_wakeup = true on devices that physically do
not support PME (like Virtual Functions or older hardware), leading to
invalid sysfs attributes and potential power management misbehavior.
This happens before xe_probe_info_early() determines the hardware generation
and without checking IS_SRIOV_VF() to ensure this PF-only power management
configuration is not executed on VFs. Should this initialization be
conditionally guarded based on the hardware capabilities and virtual function
constraints?
> + if (err)
> + return err;
> +
> err = xe_probe_info_early(xe, desc, &probed_info);
> if (err)
> return err;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260914194737.272679-1-vinod.govindapillai@intel.com?part=1
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 2/7] drm/xe/pm: introduce PM PME support
2026-09-14 19:47 ` [PATCH v6 2/7] drm/xe/pm: introduce PM PME support Vinod Govindapillai
@ 2026-09-14 20:01 ` sashiko-bot
0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-09-14 20:01 UTC (permalink / raw)
To: Vinod Govindapillai; +Cc: intel-xe, intel-gfx
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Failed runtime suspend leaves PCI PME wake enabled because the software flag is prematurely cleared before the hardware cleanup check.
--
commit 31cf117b704a2fc5858594d67a6c704b16fd2e7b
Author: Vinod Govindapillai <vinod.govindapillai@intel.com>
drm/xe/pm: introduce PM PME support
This commit introduces PME support for capable devices to avoid relying on
HPD polling. It assesses PME capabilities during PCI probe and enables them
for specific contexts during the PM runtime suspend call.
> diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
> index 32e10e1a26eff..ef5fefdd09e4d 100644
> --- a/drivers/gpu/drm/xe/xe_pci.c
> +++ b/drivers/gpu/drm/xe/xe_pci.c
[ ... ]
> @@ -1380,8 +1386,14 @@ static int xe_pci_runtime_suspend(struct device *dev)
> xe_assert(xe, !pci_num_vf(pdev));
>
> err = xe_pm_runtime_suspend(xe);
> - if (err)
> + if (err) {
> + if (xe_pm_pme_enabled(xe)) {
[Severity: Medium]
Since xe_pm_runtime_suspend() already clears the software flag in its
failure path, will this check always evaluate to false?
If the flag is cleared early by the callee, it appears
pci_enable_wake(pdev, PCI_D3hot, false) is skipped. Could this leave the
PCI device with PME wake enabled while in D0 after a failed runtime suspend,
potentially causing spurious PME interrupts?
> + pci_enable_wake(pdev, PCI_D3hot, false);
> + xe_pm_update_pme_enabled(xe, false);
> + }
> +
> return err;
> + }
>
> pci_save_state(pdev);
[ ... ]
> diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c
> index a5289a9df8d25..6453adbc3410d 100644
> --- a/drivers/gpu/drm/xe/xe_pm.c
> +++ b/drivers/gpu/drm/xe/xe_pm.c
[ ... ]
> @@ -650,6 +663,7 @@ int xe_pm_runtime_suspend(struct xe_device *xe)
> return 0;
>
> out_resume:
> + xe_pm_update_pme_enabled(xe, false);
[Severity: Medium]
Does clearing the PME enabled flag here inadvertently defeat the hardware
cleanup logic in the xe_pci_runtime_suspend() caller?
> xe_display_pm_runtime_resume(xe);
> xe_pxp_pm_resume(xe->pxp);
> out:
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260914194737.272679-1-vinod.govindapillai@intel.com?part=2
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 6/7] drm/i915/irq: conditional HPD IRQ resets based on PME capability
2026-09-14 19:47 ` [PATCH v6 6/7] drm/i915/irq: conditional HPD IRQ resets based on PME capability Vinod Govindapillai
@ 2026-09-14 20:06 ` sashiko-bot
0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-09-14 20:06 UTC (permalink / raw)
To: Vinod Govindapillai; +Cc: intel-xe, intel-gfx
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] The patch uses a runtime PM flag (`xe->pme.enabled` via `intel_display_rpm_pme_enabled`) to conditionally skip HPD IRQ resets in a path shared by both system PM and runtime PM, violating subsystem guidelines and breaking system PM behavior.
- [High] Pending HPD interrupts that woke the system from runtime suspend are cleared and lost during the resume path because the IIR register is reset before they can be handled.
- [Medium] Skipping the reset of `SDE_IRQ_REGS` entirely leaves all non-HPD South Display Engine (SDE) interrupts active during suspend, which can cause spurious wakeups.
--
commit 52d852459481153001bd323a577aaf67b9baae9c
Author: Vinod Govindapillai <vinod.govindapillai@intel.com>
Subject: drm/i915/irq: conditional HPD IRQ resets based on PME capability
This patch conditionally skips HPD IRQ resets during suspend routines
based on the PME capability of the device. If the device supports
generating PME from HPDs, the HPD-related IRQs are left active to
prevent losing the HPD events.
> diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c
> index a59b75830bd13..7e71c96c663fa 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_irq.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c
[ ... ]
> @@ -2217,8 +2218,10 @@ static void gen11_display_irq_reset(struct intel_display *display)
> enum pipe pipe;
> u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
> BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
> + bool reset_hpd = !intel_display_rpm_pme_enabled(display);
[Severity: High]
Does this violate context separation guidelines by using a runtime PM flag
to control a path shared with system PM?
During system suspend, the device is typically runtime-resumed first or
already active, meaning the runtime flag accessed via
intel_display_rpm_pme_enabled() evaluates to false. This results in
reset_hpd being true, which unconditionally wipes HPD IRQs during S3
suspend and defeats the intended PME wakeup behavior.
Additionally, in the i915 driver, the .pme_enabled callback appears to be
unimplemented in i915_display_rpm_interface, which would mean it always
returns false, rendering this logic non-functional for i915.
>
> - intel_de_write(display, GEN11_DISPLAY_INT_CTL, 0);
> + if (reset_hpd)
> + intel_de_write(display, GEN11_DISPLAY_INT_CTL, 0);
>
> if (DISPLAY_VER(display) >= 12) {
[ ... ]
> @@ -2250,13 +2253,15 @@ static void gen11_display_irq_reset(struct intel_display *display)
> irq_reset(display, GEN8_DE_PORT_IRQ_REGS);
> irq_reset(display, GEN8_DE_MISC_IRQ_REGS);
>
> - if (DISPLAY_VER(display) >= 14)
> - irq_reset(display, PICAINTERRUPT_IRQ_REGS);
> - else
> - irq_reset(display, GEN11_DE_HPD_IRQ_REGS);
[Severity: High]
Does this clear and lose pending HPD interrupts that woke the system from
runtime suspend?
When an HPD event triggers a PME wakeup from runtime suspend, the hardware
sets the corresponding bit in the IIR register. During runtime resume, the
PCI driver first clears the PME capability flag, and then eventually calls
gen11_display_irq_reset().
Because the PME enabled flag was just cleared,
intel_display_rpm_pme_enabled() evaluates to false, making reset_hpd
evaluate to true. This causes the driver to write 0xffffffff to the IIR
register here in irq_reset(), destroying the pending HPD event before the
interrupt handler is re-enabled to process it.
> + if (reset_hpd) {
> + if (DISPLAY_VER(display) >= 14)
> + irq_reset(display, PICAINTERRUPT_IRQ_REGS);
> + else
> + irq_reset(display, GEN11_DE_HPD_IRQ_REGS);
>
> - if (INTEL_PCH_TYPE(display) >= PCH_ICP)
> - irq_reset(display, SDE_IRQ_REGS);
> + if (INTEL_PCH_TYPE(display) >= PCH_ICP)
> + irq_reset(display, SDE_IRQ_REGS);
[Severity: Medium]
By skipping the reset of SDE_IRQ_REGS when reset_hpd is false, does this
leave all non-HPD South Display Engine (SDE) interrupts active during
suspend?
SDE_IRQ_REGS controls many interrupts beyond HPD, such as GMBUS (I2C) and
Audio. Because the master interrupt control (GEN11_DISPLAY_INT_CTL) is
also intentionally left active to support PME, any activity on these
non-HPD sources during suspend could trigger the master interrupt and
spuriously wake the system.
Should this selectively mask out non-HPD sources via read-modify-write to
the IMR registers rather than bypassing the reset completely?
> + }
> }
>
> void gen8_irq_power_well_post_enable(struct intel_display *display,
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260914194737.272679-1-vinod.govindapillai@intel.com?part=6
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-09-14 20:06 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-14 19:47 [PATCH v6 0/7] pm_pme support on display hotplug Vinod Govindapillai
2026-09-14 19:47 ` [PATCH v6 1/7] drm/xe/pm: initialize the device's system wakeup capabilities Vinod Govindapillai
2026-09-14 20:00 ` sashiko-bot
2026-09-14 19:47 ` [PATCH v6 2/7] drm/xe/pm: introduce PM PME support Vinod Govindapillai
2026-09-14 20:01 ` sashiko-bot
2026-09-14 19:47 ` [PATCH v6 3/7] drm/xe/pm: avoid reclaim when arming PME wakeup Vinod Govindapillai
2026-09-14 19:47 ` [PATCH v6 4/7] drm/i915: add pme_enabled() to the parent interface Vinod Govindapillai
2026-09-14 19:47 ` [PATCH v6 5/7] drm/i915/xe: plug the pme_enabed implementation for xe Vinod Govindapillai
2026-09-14 19:47 ` [PATCH v6 6/7] drm/i915/irq: conditional HPD IRQ resets based on PME capability Vinod Govindapillai
2026-09-14 20:06 ` sashiko-bot
2026-09-14 19:47 ` [PATCH v6 7/7] drm/i915/hotplug: avoid HPD polling if the device is PME capable Vinod Govindapillai
2026-09-14 19:52 ` ✗ Fi.CI.BUILD: failure for pm_pme support on display hotplug (rev6) Patchwork
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox