Commit 19aefbc7 authored by Stanislav Lisovskiy's avatar Stanislav Lisovskiy Committed by Manasi Navare
Browse files

drm/i915: Fix wrong CDCLK adjustment changes



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: default avatarStanislav Lisovskiy <stanislav.lisovskiy@intel.com>
Fixes: cd191546 ("drm/i915: Adjust CDCLK accordingly to our DBuf bw needs")
Reviewed-by: default avatarManasi Navare <manasi.d.navare@intel.com>
Signed-off-by: default avatarManasi Navare <manasi.d.navare@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200601173058.5084-1-stanislav.lisovskiy@intel.com
parent b8226d62
Loading
Loading
Loading
Loading
+33 −19
Original line number Diff line number Diff line
@@ -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);

+11 −8
Original line number Diff line number Diff line
@@ -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);
	}
+11 −15
Original line number Diff line number Diff line
@@ -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;
	}