Skip to content

Commit 55d657d

Browse files
committed
drm/i915/dp_mst: Fix side-band message timeouts due to long PPS delays
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 <[email protected]> Reviewed-by: Jani Nikula <[email protected]> Signed-off-by: Imre Deak <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 88f931c commit 55d657d

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

drivers/gpu/drm/i915/display/intel_dp_aux.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
247247
u32 aux_clock_divider;
248248
enum intel_display_power_domain aux_domain;
249249
intel_wakeref_t aux_wakeref;
250-
intel_wakeref_t pps_wakeref;
250+
intel_wakeref_t pps_wakeref = NULL;
251251
int i, ret, recv_bytes;
252252
int try, clock = 0;
253253
u32 status;
@@ -272,7 +272,20 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
272272
aux_domain = intel_aux_power_domain(dig_port);
273273

274274
aux_wakeref = intel_display_power_get(display, aux_domain);
275-
pps_wakeref = intel_pps_lock(intel_dp);
275+
276+
/*
277+
* The PPS state needs to be locked for:
278+
* - eDP on all platforms, since AUX transfers on eDP need VDD power
279+
* (either forced or via panel power) which depends on the PPS
280+
* state.
281+
* - non-eDP on platforms where the PPS is a pipe instance (VLV/CHV),
282+
* since changing the PPS state (via a parallel modeset for
283+
* instance) may interfere with the AUX transfers on a non-eDP
284+
* output as well.
285+
*/
286+
if (intel_dp_is_edp(intel_dp) ||
287+
display->platform.valleyview || display->platform.cherryview)
288+
pps_wakeref = intel_pps_lock(intel_dp);
276289

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

433-
intel_pps_unlock(intel_dp, pps_wakeref);
446+
if (pps_wakeref)
447+
intel_pps_unlock(intel_dp, pps_wakeref);
448+
434449
intel_display_power_put_async(display, aux_domain, aux_wakeref);
435450
out_unlock:
436451
intel_digital_port_unlock(encoder);

0 commit comments

Comments
 (0)