Skip to content

Commit

Permalink
drm/i915/dp_mst: Fix side-band message timeouts due to long PPS delays
Browse files Browse the repository at this point in the history
The Panel Power Sequencer lock held on an eDP port (a) blocks a DP AUX
transfer on another port (b), since the PPS lock is device global, thus
shared by all ports. The PPS lock can be held on port (a) for a longer
period due to the various PPS delays (panel/backlight on/off,
power-cycle delays). This in turn can cause an MST down-message request
on port (b) time out, if the above PPS delay defers the handling of the
reply to the request by more than 100ms: the MST branch device sending
the reply (signaling this via the DP_DOWN_REP_MSG_RDY flag in the
DP_DEVICE_SERVICE_IRQ_VECTOR DPCD register) may cancel the reply
(clearing DP_DOWN_REP_MSG_RDY and the reply message buffer) after 110
ms, if the reply is not processed by that time.

Avoid MST down-message timeouts described above, by locking the PPS
state for AUX transfers only if this is actually required: on eDP ports,
where the VDD power depends on the PPS state and on all DP and eDP ports
on VLV/CHV, where the PPS is a pipe instance and hence a modeset on any
port possibly affecting the PPS state.

v2: Don't move PPS locking/VDD enabling to a separate function. (Jani)

Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Link: https://lore.kernel.org/r/20250324180145.142884-3-imre.deak@intel.com
  • Loading branch information
Imre Deak committed Mar 25, 2025
1 parent 88f931c commit 55d657d
Showing 1 changed file with 18 additions and 3 deletions.
21 changes: 18 additions & 3 deletions drivers/gpu/drm/i915/display/intel_dp_aux.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
u32 aux_clock_divider;
enum intel_display_power_domain aux_domain;
intel_wakeref_t aux_wakeref;
intel_wakeref_t pps_wakeref;
intel_wakeref_t pps_wakeref = NULL;
int i, ret, recv_bytes;
int try, clock = 0;
u32 status;
Expand All @@ -272,7 +272,20 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
aux_domain = intel_aux_power_domain(dig_port);

aux_wakeref = intel_display_power_get(display, aux_domain);
pps_wakeref = intel_pps_lock(intel_dp);

/*
* The PPS state needs to be locked for:
* - eDP on all platforms, since AUX transfers on eDP need VDD power
* (either forced or via panel power) which depends on the PPS
* state.
* - non-eDP on platforms where the PPS is a pipe instance (VLV/CHV),
* since changing the PPS state (via a parallel modeset for
* instance) may interfere with the AUX transfers on a non-eDP
* output as well.
*/
if (intel_dp_is_edp(intel_dp) ||
display->platform.valleyview || display->platform.cherryview)
pps_wakeref = intel_pps_lock(intel_dp);

/*
* We will be called with VDD already enabled for dpcd/edid/oui reads.
Expand Down Expand Up @@ -430,7 +443,9 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
if (vdd)
intel_pps_vdd_off_unlocked(intel_dp, false);

intel_pps_unlock(intel_dp, pps_wakeref);
if (pps_wakeref)
intel_pps_unlock(intel_dp, pps_wakeref);

intel_display_power_put_async(display, aux_domain, aux_wakeref);
out_unlock:
intel_digital_port_unlock(encoder);
Expand Down

0 comments on commit 55d657d

Please sign in to comment.