drm/i915: Fix wrong CDCLK adjustment changes
authorStanislav Lisovskiy <stanislav.lisovskiy@intel.com>
Mon, 1 Jun 2020 17:30:58 +0000 (20:30 +0300)
committerManasi Navare <manasi.d.navare@intel.com>
Thu, 4 Jun 2020 18:11:56 +0000 (11:11 -0700)
Previous patch didn't take into account all pipes
but only those in state, which could cause wrong
CDCLK conclcusions and calculations.
Also there was a severe issue with min_cdclk being
assigned to 0 every compare cycle.

Too bad this was found by me only after merge.
This could be also causing the issues in test, however
not clear - anyway marking this as fixing the
"Adjust CDCLK accordingly to our DBuf bw needs".

v2: - s/pipe/crtc->pipe/
    - save a bit of instructions by
      skipping inactive pipes, without
      getting 0 DBuf slice mask for it.

Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
Fixes: cd1915460861 ("drm/i915: Adjust CDCLK accordingly to our DBuf bw needs")
Reviewed-by: Manasi Navare <manasi.d.navare@intel.com>
Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200601173058.5084-1-stanislav.lisovskiy@intel.com
drivers/gpu/drm/i915/display/intel_bw.c
drivers/gpu/drm/i915/display/intel_cdclk.c
drivers/gpu/drm/i915/display/intel_display.c

index a79bd7a..bd06040 100644 (file)
@@ -437,6 +437,7 @@ int skl_bw_calc_min_cdclk(struct intel_atomic_state *state)
        struct intel_crtc *crtc;
        int max_bw = 0;
        int slice_id;
+       enum pipe pipe;
        int i;
 
        for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
@@ -447,10 +448,15 @@ int skl_bw_calc_min_cdclk(struct intel_atomic_state *state)
                if (IS_ERR(new_bw_state))
                        return PTR_ERR(new_bw_state);
 
+               old_bw_state = intel_atomic_get_old_bw_state(state);
+
                crtc_bw = &new_bw_state->dbuf_bw[crtc->pipe];
 
                memset(&crtc_bw->used_bw, 0, sizeof(crtc_bw->used_bw));
 
+               if (!crtc_state->hw.active)
+                       continue;
+
                for_each_plane_id_on_crtc(crtc, plane_id) {
                        const struct skl_ddb_entry *plane_alloc =
                                &crtc_state->wm.skl.plane_ddb_y[plane_id];
@@ -478,6 +484,15 @@ int skl_bw_calc_min_cdclk(struct intel_atomic_state *state)
                        for_each_dbuf_slice_in_mask(slice_id, dbuf_mask)
                                crtc_bw->used_bw[slice_id] += data_rate;
                }
+       }
+
+       if (!old_bw_state)
+               return 0;
+
+       for_each_pipe(dev_priv, pipe) {
+               struct intel_dbuf_bw *crtc_bw;
+
+               crtc_bw = &new_bw_state->dbuf_bw[pipe];
 
                for_each_dbuf_slice(slice_id) {
                        /*
@@ -490,14 +505,9 @@ int skl_bw_calc_min_cdclk(struct intel_atomic_state *state)
                         */
                        max_bw += crtc_bw->used_bw[slice_id];
                }
-
-               new_bw_state->min_cdclk = max_bw / 64;
-
-               old_bw_state = intel_atomic_get_old_bw_state(state);
        }
 
-       if (!old_bw_state)
-               return 0;
+       new_bw_state->min_cdclk = max_bw / 64;
 
        if (new_bw_state->min_cdclk != old_bw_state->min_cdclk) {
                int ret = intel_atomic_lock_global_state(&new_bw_state->base);
@@ -511,34 +521,38 @@ int skl_bw_calc_min_cdclk(struct intel_atomic_state *state)
 
 int intel_bw_calc_min_cdclk(struct intel_atomic_state *state)
 {
-       int i;
+       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+       struct intel_bw_state *new_bw_state = NULL;
+       struct intel_bw_state *old_bw_state = NULL;
        const struct intel_crtc_state *crtc_state;
        struct intel_crtc *crtc;
        int min_cdclk = 0;
-       struct intel_bw_state *new_bw_state = NULL;
-       struct intel_bw_state *old_bw_state = NULL;
+       enum pipe pipe;
+       int i;
 
        for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
-               struct intel_cdclk_state *cdclk_state;
-
                new_bw_state = intel_atomic_get_bw_state(state);
                if (IS_ERR(new_bw_state))
                        return PTR_ERR(new_bw_state);
 
-               cdclk_state = intel_atomic_get_cdclk_state(state);
-               if (IS_ERR(cdclk_state))
-                       return PTR_ERR(cdclk_state);
-
-               min_cdclk = max(cdclk_state->min_cdclk[crtc->pipe], min_cdclk);
-
-               new_bw_state->min_cdclk = min_cdclk;
-
                old_bw_state = intel_atomic_get_old_bw_state(state);
        }
 
        if (!old_bw_state)
                return 0;
 
+       for_each_pipe(dev_priv, pipe) {
+               struct intel_cdclk_state *cdclk_state;
+
+               cdclk_state = intel_atomic_get_new_cdclk_state(state);
+               if (!cdclk_state)
+                       return 0;
+
+               min_cdclk = max(cdclk_state->min_cdclk[pipe], min_cdclk);
+       }
+
+       new_bw_state->min_cdclk = min_cdclk;
+
        if (new_bw_state->min_cdclk != old_bw_state->min_cdclk) {
                int ret = intel_atomic_lock_global_state(&new_bw_state->base);
 
index f9b0fc7..08468b1 100644 (file)
@@ -2084,9 +2084,12 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
 static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state)
 {
        struct intel_atomic_state *state = cdclk_state->base.state;
+       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+       struct intel_bw_state *bw_state = NULL;
        struct intel_crtc *crtc;
        struct intel_crtc_state *crtc_state;
        int min_cdclk, i;
+       enum pipe pipe;
 
        for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
                int ret;
@@ -2095,6 +2098,10 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state)
                if (min_cdclk < 0)
                        return min_cdclk;
 
+               bw_state = intel_atomic_get_bw_state(state);
+               if (IS_ERR(bw_state))
+                       return PTR_ERR(bw_state);
+
                if (cdclk_state->min_cdclk[i] == min_cdclk)
                        continue;
 
@@ -2106,15 +2113,11 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state)
        }
 
        min_cdclk = cdclk_state->force_min_cdclk;
+       for_each_pipe(dev_priv, pipe) {
+               min_cdclk = max(cdclk_state->min_cdclk[pipe], min_cdclk);
 
-       for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
-               struct intel_bw_state *bw_state;
-
-               min_cdclk = max(cdclk_state->min_cdclk[crtc->pipe], min_cdclk);
-
-               bw_state = intel_atomic_get_bw_state(state);
-               if (IS_ERR(bw_state))
-                       return PTR_ERR(bw_state);
+               if (!bw_state)
+                       continue;
 
                min_cdclk = max(bw_state->min_cdclk, min_cdclk);
        }
index 0b0faf9..43de656 100644 (file)
@@ -14716,13 +14716,14 @@ static int intel_atomic_check_cdclk(struct intel_atomic_state *state,
                                    bool *need_cdclk_calc)
 {
        struct drm_i915_private *dev_priv = to_i915(state->base.dev);
-       int i;
+       struct intel_cdclk_state *new_cdclk_state;
        struct intel_plane_state *plane_state;
+       struct intel_bw_state *new_bw_state;
        struct intel_plane *plane;
+       int min_cdclk = 0;
+       enum pipe pipe;
        int ret;
-       struct intel_cdclk_state *new_cdclk_state;
-       struct intel_crtc_state *new_crtc_state;
-       struct intel_crtc *crtc;
+       int i;
        /*
         * active_planes bitmask has been updated, and potentially
         * affected planes are part of the state. We can now
@@ -14743,23 +14744,18 @@ static int intel_atomic_check_cdclk(struct intel_atomic_state *state,
        if (ret)
                return ret;
 
-       if (!new_cdclk_state)
-               return 0;
-
-       for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
-               struct intel_bw_state *bw_state;
-               int min_cdclk = 0;
+       new_bw_state = intel_atomic_get_new_bw_state(state);
 
-               min_cdclk = max(new_cdclk_state->min_cdclk[crtc->pipe], min_cdclk);
+       if (!new_cdclk_state || !new_bw_state)
+               return 0;
 
-               bw_state = intel_atomic_get_bw_state(state);
-               if (IS_ERR(bw_state))
-                       return PTR_ERR(bw_state);
+       for_each_pipe(dev_priv, pipe) {
+               min_cdclk = max(new_cdclk_state->min_cdclk[pipe], min_cdclk);
 
                /*
                 * Currently do this change only if we need to increase
                 */
-               if (bw_state->min_cdclk > min_cdclk)
+               if (new_bw_state->min_cdclk > min_cdclk)
                        *need_cdclk_calc = true;
        }