Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i915/dp: Flush modeset commits during connector detection

Make sure that a DP connector detection doesn't happen in parallel
with an ongoing modeset on the connector. The reasons for this are:

- Besides reading the capabilities, EDID etc. the detection may change
the state of the sink (via the AUX bus), for instance by setting the
LTTPR mode or the source OUI (the latter introduced by an upcoming
patch). It's better to avoid such changes affecting an onging modeset
in any way.

- During a modeset's link training any access to DPCD registers, besides
the registers used for link training should be avoided, at least in
the LTTPR non-transparent and transparent link training modes.

Such asynchronous accesses - besides connector detection - can also
happen via the AUX device node for instance, for those a parallel
modeset will have to be avoided in a similar way to the change in this
patch. (A topic for a follow-up change.)

- The source OUI written to an eDP sink is valid only while the panel
power is enabled. A modeset on eDP will enable/disable the panel power
synchronously; this should be prevented in the middle of the connector
detection, to ensure a consistent sink state (which depends on the
source OUI) for the whole duration of detection. The panel power could
still get disabled during detection after an idle period (1 sec), this
will be prevented by the next patch.

v2: (Ville)
- s/wait_for_crtc_hw_done/wait_for_connector_hw_done
- Get drm_device using an intel_display instead of drm_i915_private ptr.

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241025160259.3088727-2-imre.deak@intel.com

+26 -4
+23 -4
drivers/gpu/drm/i915/display/intel_dp.c
··· 5039 5039 return false; 5040 5040 } 5041 5041 5042 + static void wait_for_connector_hw_done(const struct drm_connector_state *conn_state) 5043 + { 5044 + struct intel_connector *connector = to_intel_connector(conn_state->connector); 5045 + struct intel_display *display = to_intel_display(connector); 5046 + 5047 + drm_modeset_lock_assert_held(&display->drm->mode_config.connection_mutex); 5048 + 5049 + if (!conn_state->commit) 5050 + return; 5051 + 5052 + drm_WARN_ON(display->drm, 5053 + !wait_for_completion_timeout(&conn_state->commit->hw_done, 5054 + msecs_to_jiffies(5000))); 5055 + } 5056 + 5042 5057 int intel_dp_get_active_pipes(struct intel_dp *intel_dp, 5043 5058 struct drm_modeset_acquire_ctx *ctx, 5044 5059 u8 *pipe_mask) ··· 5090 5075 if (!crtc_state->hw.active) 5091 5076 continue; 5092 5077 5093 - if (conn_state->commit) 5094 - drm_WARN_ON(&i915->drm, 5095 - !wait_for_completion_timeout(&conn_state->commit->hw_done, 5096 - msecs_to_jiffies(5000))); 5078 + wait_for_connector_hw_done(conn_state); 5097 5079 5098 5080 *pipe_mask |= BIT(crtc->pipe); 5099 5081 } 5100 5082 drm_connector_list_iter_end(&conn_iter); 5101 5083 5102 5084 return ret; 5085 + } 5086 + 5087 + void intel_dp_flush_connector_commits(struct intel_connector *connector) 5088 + { 5089 + wait_for_connector_hw_done(connector->base.state); 5103 5090 } 5104 5091 5105 5092 static bool intel_dp_is_connected(struct intel_dp *intel_dp) ··· 5616 5599 5617 5600 if (!intel_display_driver_check_access(dev_priv)) 5618 5601 return connector->status; 5602 + 5603 + intel_dp_flush_connector_commits(intel_connector); 5619 5604 5620 5605 /* Can't disconnect eDP */ 5621 5606 if (intel_dp_is_edp(intel_dp))
+1
drivers/gpu/drm/i915/display/intel_dp.h
··· 54 54 int intel_dp_get_active_pipes(struct intel_dp *intel_dp, 55 55 struct drm_modeset_acquire_ctx *ctx, 56 56 u8 *pipe_mask); 57 + void intel_dp_flush_connector_commits(struct intel_connector *connector); 57 58 void intel_dp_link_check(struct intel_encoder *encoder); 58 59 void intel_dp_check_link_state(struct intel_dp *intel_dp); 59 60 void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode);
+2
drivers/gpu/drm/i915/display/intel_dp_mst.c
··· 1573 1573 if (!intel_display_driver_check_access(i915)) 1574 1574 return connector->status; 1575 1575 1576 + intel_dp_flush_connector_commits(intel_connector); 1577 + 1576 1578 return drm_dp_mst_detect_port(connector, ctx, &intel_dp->mst_mgr, 1577 1579 intel_connector->port); 1578 1580 }