drm/msm: dpu: Move crtc runtime resume to encoder
authorSean Paul <seanpaul@chromium.org>
Fri, 16 Nov 2018 18:42:22 +0000 (13:42 -0500)
committerRob Clark <robdclark@gmail.com>
Tue, 11 Dec 2018 18:10:11 +0000 (13:10 -0500)
The crtc runtime resume doesn't actually operate on the crtc, but rather
its encoders. The problem with this is that we need to inspect the crtc
state to get the currently connected encoders. Since runtime resume
isn't guaranteed to be called while holding the modeset locks (although
it sometimes is), this presents a race condition.

Now that we have ->enabled on the virtual encoders, and a lock to
protect it, just call resume on each encoder and only restore the ones
that are enabled.

Changes in v2:
- None

Cc: Jeykumar Sankaran <jsanka@codeaurora.org>
Reviewed-by: Jeykumar Sankaran <jsanka@codeaurora.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c

index 61449e3118198318c72aa72bf4e2c16d588e826f..44bd3b853b2c606da983add1bca3676d8e7eda0d 100644 (file)
@@ -857,30 +857,6 @@ static struct drm_crtc_state *dpu_crtc_duplicate_state(struct drm_crtc *crtc)
        return &cstate->base;
 }
 
-void dpu_crtc_runtime_resume(struct drm_crtc *crtc)
-{
-       struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
-       struct drm_encoder *encoder;
-
-       mutex_lock(&dpu_crtc->crtc_lock);
-
-       if (!dpu_crtc->enabled)
-               goto end;
-
-       trace_dpu_crtc_runtime_resume(DRMID(crtc));
-
-       /* restore encoder; crtc will be programmed during commit */
-       drm_for_each_encoder(encoder, crtc->dev) {
-               if (encoder->crtc != crtc)
-                       continue;
-
-               dpu_encoder_virt_restore(encoder);
-       }
-
-end:
-       mutex_unlock(&dpu_crtc->crtc_lock);
-}
-
 static void dpu_crtc_disable(struct drm_crtc *crtc)
 {
        struct dpu_crtc *dpu_crtc;
index d5cd7a0b302f1aca4f02ca205f7849072c852d24..7617132b8fb7e3bd15868f9dd6364879016419f2 100644 (file)
@@ -330,10 +330,4 @@ static inline bool dpu_crtc_is_enabled(struct drm_crtc *crtc)
        return crtc ? crtc->enabled : false;
 }
 
-/**
- * dpu_crtc_runtime_resume - called by the top-level on pm_runtime_resume
- * @crtc: CRTC to resume
- */
-void dpu_crtc_runtime_resume(struct drm_crtc *crtc);
-
 #endif /* _DPU_CRTC_H_ */
index c1b32ef1fc4602609a939a03010310d2e2e9f76e..83b25a1f65d64d90958cc99d606780717c740cdd 100644 (file)
@@ -1089,28 +1089,24 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
        _dpu_encoder_update_vsync_source(dpu_enc, &dpu_enc->disp_info);
 }
 
-void dpu_encoder_virt_restore(struct drm_encoder *drm_enc)
+void dpu_encoder_virt_runtime_resume(struct drm_encoder *drm_enc)
 {
-       struct dpu_encoder_virt *dpu_enc = NULL;
-       int i;
-
-       if (!drm_enc) {
-               DPU_ERROR("invalid encoder\n");
-               return;
-       }
-       dpu_enc = to_dpu_encoder_virt(drm_enc);
+       struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
 
-       for (i = 0; i < dpu_enc->num_phys_encs; i++) {
-               struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
+       mutex_lock(&dpu_enc->enc_lock);
 
-               if (phys && (phys != dpu_enc->cur_master) && phys->ops.restore)
-                       phys->ops.restore(phys);
-       }
+       if (!dpu_enc->enabled)
+               goto out;
 
+       if (dpu_enc->cur_slave && dpu_enc->cur_slave->ops.restore)
+               dpu_enc->cur_slave->ops.restore(dpu_enc->cur_slave);
        if (dpu_enc->cur_master && dpu_enc->cur_master->ops.restore)
                dpu_enc->cur_master->ops.restore(dpu_enc->cur_master);
 
        _dpu_encoder_virt_enable_helper(drm_enc);
+
+out:
+       mutex_unlock(&dpu_enc->enc_lock);
 }
 
 static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc)
index c2044122d609a9be6cf8d1ce2491f5f8f1ddcfa7..c9ebdf60a4baba99ea4ba6015a1de472f9547a5a 100644 (file)
@@ -128,10 +128,10 @@ int dpu_encoder_wait_for_event(struct drm_encoder *drm_encoder,
 enum dpu_intf_mode dpu_encoder_get_intf_mode(struct drm_encoder *encoder);
 
 /**
- * dpu_encoder_virt_restore - restore the encoder configs
+ * dpu_encoder_virt_runtime_resume - pm runtime resume the encoder configs
  * @encoder:   encoder pointer
  */
-void dpu_encoder_virt_restore(struct drm_encoder *encoder);
+void dpu_encoder_virt_runtime_resume(struct drm_encoder *encoder);
 
 /**
  * dpu_encoder_init - initialize virtual encoder object
index 610845bb72e0cee2d49b062a2233f9eb5ee18a44..606b284064a685577fc5ba0289189351371b879d 100644 (file)
@@ -1133,7 +1133,7 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev)
        int rc = -1;
        struct platform_device *pdev = to_platform_device(dev);
        struct dpu_kms *dpu_kms = platform_get_drvdata(pdev);
-       struct drm_crtc *crtc;
+       struct drm_encoder *encoder;
        struct drm_device *ddev;
        struct dss_module_power *mp = &dpu_kms->mp;
 
@@ -1151,8 +1151,8 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev)
 
        dpu_vbif_init_memtypes(dpu_kms);
 
-       drm_for_each_crtc(crtc, ddev)
-               dpu_crtc_runtime_resume(crtc);
+       drm_for_each_encoder(encoder, ddev)
+               dpu_encoder_virt_runtime_resume(encoder);
 
        return rc;
 }