summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/display
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2020-03-02 19:44:42 +0200
committerVille Syrjälä <ville.syrjala@linux.intel.com>2020-03-09 22:28:33 +0200
commitbb9ca240dca5c7e4564d10546e4bddab7e606fe3 (patch)
tree90a592a397bf1ccf2cfa5837750e0f20f6b00b51 /drivers/gpu/drm/i915/display
parente10eb8dd59e1eef559537898f10b4472d355c022 (diff)
drm/i915: Lock gmbus/aux mutexes while changing cdclk
gmbus/aux may be clocked by cdclk, thus we should make sure no transfers are ongoing while the cdclk frequency is being changed. We do that by simply grabbing all the gmbus/aux mutexes. No one else should be holding any more than one of those at a time so the lock ordering here shouldn't matter. v2: Use mutex_lock_nest_lock() (Chris) Cc: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200302174442.5803-1-ville.syrjala@linux.intel.com Acked-by: Jani Nikula <jani.nikula@intel.com> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu/drm/i915/display')
-rw-r--r--drivers/gpu/drm/i915/display/intel_cdclk.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
index 0741d643455b..979a0241fdcb 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -1868,6 +1868,8 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv,
const struct intel_cdclk_config *cdclk_config,
enum pipe pipe)
{
+ struct intel_encoder *encoder;
+
if (!intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_config))
return;
@@ -1876,8 +1878,28 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv,
intel_dump_cdclk_config(cdclk_config, "Changing CDCLK to");
+ /*
+ * Lock aux/gmbus while we change cdclk in case those
+ * functions use cdclk. Not all platforms/ports do,
+ * but we'll lock them all for simplicity.
+ */
+ mutex_lock(&dev_priv->gmbus_mutex);
+ for_each_intel_dp(&dev_priv->drm, encoder) {
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+ mutex_lock_nest_lock(&intel_dp->aux.hw_mutex,
+ &dev_priv->gmbus_mutex);
+ }
+
dev_priv->display.set_cdclk(dev_priv, cdclk_config, pipe);
+ for_each_intel_dp(&dev_priv->drm, encoder) {
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+ mutex_unlock(&intel_dp->aux.hw_mutex);
+ }
+ mutex_unlock(&dev_priv->gmbus_mutex);
+
if (drm_WARN(&dev_priv->drm,
intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_config),
"cdclk state doesn't match!\n")) {