From: Arun R Murthy <arun.r.murthy@intel.com>
To: intel-gfx@lists.freedesktop.org
Cc: jani.nikula@intel.com, Arun R Murthy <arun.r.murthy@intel.com>
Subject: [PATCHv2] drm/i915/pps: reconcile a BIOS-enabled VDD without leaking its wakeref
Date: Mon, 31 Aug 2026 15:08:54 +0530 [thread overview]
Message-ID: <20260831093854.1427305-1-arun.r.murthy@intel.com> (raw)
In-Reply-To: <20260831044036.1236136-1-arun.r.murthy@intel.com>
When the BIOS leaves the eDP VDD force bit (EDP_FORCE_VDD) enabled at boot
(or resume), pps_vdd_init() adopts that state by taking an AUX power-domain
reference into intel_dp->pps.vdd_wakeref.
intel_pps_vdd_on_unlocked() decides whether it already owns a reference by
reading the live EDP_FORCE_VDD bit via edp_have_panel_vdd(). That bit can be
reset under the driver after the handover (DC states, DMC, BIOS). When it is,
the VDD-on path believes it holds nothing, overwrites vdd_wakeref with a
freshly acquired reference and orphans the adopted one. The leak surfaces at
suspend-late as:
i915 raw-wakerefs=1 wakelocks=1 on cleanup
with the leaked wakeref's backtrace pointing at pps_vdd_init() ->
intel_pps_init() from driver probe.
Blindly reusing a held vdd_wakeref in the VDD-on path would fix the leak but
also silently paper over genuine runtime enable/disable imbalances, which is
exactly what the WARN_ON() there is meant to catch.
Instead track the handover explicitly: pps_vdd_init() sets a vdd_wakeref_boot
flag when it adopts a BIOS-enabled VDD, and intel_pps_vdd_on_unlocked() only
reuses the held reference (clearing the flag) while that flag is set. In all
other cases it keeps depending on the HW read and the WARN_ON(), so real
runtime imbalances are still flagged. The flag is cleared whenever the
reference is released so it can never outlive the reference it describes.
v2: Reworked to allow reconcile only at bootime(Jani)
Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/work_items/8477
Assisted-by: Claude:claude-3-opus
Signed-off-by: Arun R Murthy <arun.r.murthy@intel.com>
---
.../drm/i915/display/intel_display_types.h | 4 ++++
drivers/gpu/drm/i915/display/intel_pps.c | 22 ++++++++++++++++---
2 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 20a07ea06b5e..f9f1958e8c6a 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1727,6 +1727,10 @@ struct intel_pps {
unsigned long last_backlight_off;
ktime_t panel_power_off_time;
struct ref_tracker *vdd_wakeref;
+ /* vdd_wakeref was adopted from an already-on VDD at the BIOS/firmware
+ * handover (boot/resume) and not yet reconciled into normal ownership.
+ */
+ bool vdd_wakeref_boot;
union {
/*
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index d4c98b150fa2..415288077439 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -758,9 +758,22 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp)
if (edp_have_panel_vdd(intel_dp))
return need_to_disable;
- drm_WARN_ON(display->drm, intel_dp->pps.vdd_wakeref);
- intel_dp->pps.vdd_wakeref = intel_display_power_get(display,
- intel_aux_power_domain(dig_port));
+ /*
+ * pps_vdd_init() may have taken a reference at the BIOS->driver handover
+ * for an already-on VDD whose HW force bit was since reset under us (DC
+ * states, DMC, BIOS). Only in that boot/resume handover case reuse the
+ * held reference instead of overwriting and leaking it. At runtime a
+ * held wakeref here is a real imbalance, so keep asserting it and depend
+ * on the HW read.
+ */
+ if (intel_dp->pps.vdd_wakeref_boot) {
+ intel_dp->pps.vdd_wakeref_boot = false;
+ } else {
+ drm_WARN_ON(display->drm, intel_dp->pps.vdd_wakeref);
+ intel_dp->pps.vdd_wakeref =
+ intel_display_power_get(display,
+ intel_aux_power_domain(dig_port));
+ }
pp_stat_reg = _pp_stat_reg(intel_dp);
pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
@@ -861,6 +874,7 @@ static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
intel_dp_invalidate_source_oui(intel_dp);
}
+ intel_dp->pps.vdd_wakeref_boot = false;
intel_display_power_put(display,
intel_aux_power_domain(dig_port),
fetch_and_zero(&intel_dp->pps.vdd_wakeref));
@@ -1063,6 +1077,7 @@ void intel_pps_off_unlocked(struct intel_dp *intel_dp)
intel_dp_invalidate_source_oui(intel_dp);
/* We got a reference when we enabled the VDD. */
+ intel_dp->pps.vdd_wakeref_boot = false;
intel_display_power_put(display,
intel_aux_power_domain(dig_port),
fetch_and_zero(&intel_dp->pps.vdd_wakeref));
@@ -1337,6 +1352,7 @@ static void pps_vdd_init(struct intel_dp *intel_dp)
drm_WARN_ON(display->drm, intel_dp->pps.vdd_wakeref);
intel_dp->pps.vdd_wakeref = intel_display_power_get(display,
intel_aux_power_domain(dig_port));
+ intel_dp->pps.vdd_wakeref_boot = true;
}
bool intel_pps_have_panel_power_or_vdd(struct intel_dp *intel_dp)
--
2.25.1
next prev parent reply other threads:[~2026-08-31 9:40 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-31 4:40 [PATCH] drm/i915/pps: don't orphan the VDD wakeref when the HW force bit is reset Arun R Murthy
2026-08-31 4:57 ` sashiko-bot
2026-08-31 5:22 ` ✓ i915.CI.BAT: success for " Patchwork
2026-08-31 6:32 ` [PATCH] " Jani Nikula
2026-09-02 8:52 ` Murthy, Arun R
2026-08-31 7:33 ` ✗ i915.CI.Full: failure for " Patchwork
2026-08-31 9:38 ` Arun R Murthy [this message]
2026-08-31 9:58 ` [PATCHv2] drm/i915/pps: reconcile a BIOS-enabled VDD without leaking its wakeref sashiko-bot
2026-08-31 15:26 ` ✓ i915.CI.BAT: success for drm/i915/pps: don't orphan the VDD wakeref when the HW force bit is reset (rev2) Patchwork
2026-08-31 21:21 ` ✓ i915.CI.Full: " Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260831093854.1427305-1-arun.r.murthy@intel.com \
--to=arun.r.murthy@intel.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=jani.nikula@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.