0903551
From 2dda82bdd570042820241e71c02ea36081835f67 Mon Sep 17 00:00:00 2001
0903551
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
0903551
Date: Mon, 20 Jun 2016 12:41:35 +0200
0903551
Subject: [PATCH 14/17] drm/i915/gen9: Propagate watermark calculation failures
0903551
 up the call chain
0903551
0903551
Upstream: since drm-intel-next-2016-05-22
0903551
commit 55994c2c38a1101f84cdf277b228f830af8a9c1b
0903551
0903551
Author:     Matt Roper <matthew.d.roper@intel.com>
0903551
AuthorDate: Thu May 12 07:06:08 2016 -0700
0903551
Commit:     Matt Roper <matthew.d.roper@intel.com>
0903551
CommitDate: Fri May 13 07:34:48 2016 -0700
0903551
0903551
    drm/i915/gen9: Propagate watermark calculation failures up the call chain
0903551
0903551
    Once we move watermark calculation to the atomic check phase, we'll want
0903551
    to start rejecting display configurations that exceed out watermark
0903551
    limits.  At the moment we just assume that there's always a valid set of
0903551
    watermarks, even though this may not actually be true.  Let's prepare by
0903551
    passing return codes up through the call stack in preparation.
0903551
0903551
    Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
0903551
    Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
0903551
    Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-15-git-send-email-matthew.d.roper@intel.com
0903551
---
0903551
 drivers/gpu/drm/i915/intel_display.c | 10 ++--
0903551
 drivers/gpu/drm/i915/intel_pm.c      | 90 ++++++++++++++++++++++--------------
0903551
 2 files changed, 61 insertions(+), 39 deletions(-)
0903551
0903551
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
0903551
index b484fda..9ac2346 100644
0903551
--- a/drivers/gpu/drm/i915/intel_display.c
0903551
+++ b/drivers/gpu/drm/i915/intel_display.c
0903551
@@ -13222,7 +13222,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
0903551
  * phase.  The code here should be run after the per-crtc and per-plane 'check'
0903551
  * handlers to ensure that all derived state has been updated.
0903551
  */
0903551
-static void calc_watermark_data(struct drm_atomic_state *state)
0903551
+static int calc_watermark_data(struct drm_atomic_state *state)
0903551
 {
0903551
 	struct drm_device *dev = state->dev;
0903551
 	struct drm_i915_private *dev_priv = to_i915(dev);
0903551
@@ -13258,7 +13258,9 @@ static void calc_watermark_data(struct drm_atomic_state *state)
0903551
 
0903551
 	/* Is there platform-specific watermark information to calculate? */
0903551
 	if (dev_priv->display.compute_global_watermarks)
0903551
-		dev_priv->display.compute_global_watermarks(state);
0903551
+		return dev_priv->display.compute_global_watermarks(state);
0903551
+
0903551
+	return 0;
0903551
 }
0903551
 
0903551
 /**
0903551
@@ -13345,9 +13347,7 @@ static int intel_atomic_check(struct drm_device *dev,
0903551
 		return ret;
0903551
 
0903551
 	intel_fbc_choose_crtc(dev_priv, state);
0903551
-	calc_watermark_data(state);
0903551
-
0903551
-	return 0;
0903551
+	return calc_watermark_data(state);
0903551
 }
0903551
 
0903551
 static int intel_atomic_prepare_commit(struct drm_device *dev,
0903551
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
0903551
index 611c5a1..ec22d93 100644
0903551
--- a/drivers/gpu/drm/i915/intel_pm.c
0903551
+++ b/drivers/gpu/drm/i915/intel_pm.c
0903551
@@ -3177,13 +3177,14 @@ static bool skl_ddb_allocation_changed(const struct skl_ddb_allocation *new_ddb,
0903551
 	return false;
0903551
 }
0903551
 
0903551
-static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
0903551
-				 struct intel_crtc_state *cstate,
0903551
-				 struct intel_plane_state *intel_pstate,
0903551
-				 uint16_t ddb_allocation,
0903551
-				 int level,
0903551
-				 uint16_t *out_blocks, /* out */
0903551
-				 uint8_t *out_lines /* out */)
0903551
+static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
0903551
+				struct intel_crtc_state *cstate,
0903551
+				struct intel_plane_state *intel_pstate,
0903551
+				uint16_t ddb_allocation,
0903551
+				int level,
0903551
+				uint16_t *out_blocks, /* out */
0903551
+				uint8_t *out_lines, /* out */
0903551
+				bool *enabled /* out */)
0903551
 {
0903551
 	struct drm_plane_state *pstate = &intel_pstate->base;
0903551
 	struct drm_framebuffer *fb = pstate->fb;
0903551
@@ -3195,8 +3196,10 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
0903551
 	uint8_t cpp;
0903551
 	uint32_t width = 0, height = 0;
0903551
 
0903551
-	if (latency == 0 || !cstate->base.active || !intel_pstate->visible)
0903551
-		return false;
0903551
+	if (latency == 0 || !cstate->base.active || !intel_pstate->visible) {
0903551
+		*enabled = false;
0903551
+		return 0;
0903551
+	}
0903551
 
0903551
 	width = drm_rect_width(&intel_pstate->src) >> 16;
0903551
 	height = drm_rect_height(&intel_pstate->src) >> 16;
0903551
@@ -3257,13 +3260,16 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
0903551
 			res_blocks++;
0903551
 	}
0903551
 
0903551
-	if (res_blocks >= ddb_allocation || res_lines > 31)
0903551
-		return false;
0903551
+	if (res_blocks >= ddb_allocation || res_lines > 31) {
0903551
+		*enabled = false;
0903551
+		return 0;
0903551
+	}
0903551
 
0903551
 	*out_blocks = res_blocks;
0903551
 	*out_lines = res_lines;
0903551
+	*enabled = true;
0903551
 
0903551
-	return true;
0903551
+	return 0;
0903551
 }
0903551
 
0903551
 static int
0903551
@@ -3281,6 +3287,7 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv,
0903551
 	struct intel_plane_state *intel_pstate;
0903551
 	uint16_t ddb_blocks;
0903551
 	enum pipe pipe = intel_crtc->pipe;
0903551
+	int ret;
0903551
 
0903551
 	/*
0903551
 	 * We'll only calculate watermarks for planes that are actually
0903551
@@ -3318,13 +3325,16 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv,
0903551
 
0903551
 		ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]);
0903551
 
0903551
-		result->plane_en[i] = skl_compute_plane_wm(dev_priv,
0903551
-						cstate,
0903551
-						intel_pstate,
0903551
-						ddb_blocks,
0903551
-						level,
0903551
-						&result->plane_res_b[i],
0903551
-						&result->plane_res_l[i]);
0903551
+		ret = skl_compute_plane_wm(dev_priv,
0903551
+					   cstate,
0903551
+					   intel_pstate,
0903551
+					   ddb_blocks,
0903551
+					   level,
0903551
+					   &result->plane_res_b[i],
0903551
+					   &result->plane_res_l[i],
0903551
+					   &result->plane_en[i]);
0903551
+		if (ret)
0903551
+			return ret;
0903551
 	}
0903551
 
0903551
 	return 0;
0903551
@@ -3361,21 +3371,26 @@ static void skl_compute_transition_wm(struct intel_crtc_state *cstate,
0903551
 	}
0903551
 }
0903551
 
0903551
-static void skl_build_pipe_wm(struct intel_crtc_state *cstate,
0903551
-			      struct skl_ddb_allocation *ddb,
0903551
-			      struct skl_pipe_wm *pipe_wm)
0903551
+static int skl_build_pipe_wm(struct intel_crtc_state *cstate,
0903551
+			     struct skl_ddb_allocation *ddb,
0903551
+			     struct skl_pipe_wm *pipe_wm)
0903551
 {
0903551
 	struct drm_device *dev = cstate->base.crtc->dev;
0903551
 	const struct drm_i915_private *dev_priv = dev->dev_private;
0903551
 	int level, max_level = ilk_wm_max_level(dev);
0903551
+	int ret;
0903551
 
0903551
 	for (level = 0; level <= max_level; level++) {
0903551
-		skl_compute_wm_level(dev_priv, ddb, cstate,
0903551
-				     level, &pipe_wm->wm[level]);
0903551
+		ret = skl_compute_wm_level(dev_priv, ddb, cstate,
0903551
+					   level, &pipe_wm->wm[level]);
0903551
+		if (ret)
0903551
+			return ret;
0903551
 	}
0903551
 	pipe_wm->linetime = skl_compute_linetime_wm(cstate);
0903551
 
0903551
 	skl_compute_transition_wm(cstate, &pipe_wm->trans_wm);
0903551
+
0903551
+	return 0;
0903551
 }
0903551
 
0903551
 static void skl_compute_wm_results(struct drm_device *dev,
0903551
@@ -3622,21 +3637,27 @@ static void skl_flush_wm_values(struct drm_i915_private *dev_priv,
0903551
 	}
0903551
 }
0903551
 
0903551
-static bool skl_update_pipe_wm(struct drm_crtc_state *cstate,
0903551
-			       struct skl_ddb_allocation *ddb, /* out */
0903551
-			       struct skl_pipe_wm *pipe_wm /* out */)
0903551
+static int skl_update_pipe_wm(struct drm_crtc_state *cstate,
0903551
+			      struct skl_ddb_allocation *ddb, /* out */
0903551
+			      struct skl_pipe_wm *pipe_wm, /* out */
0903551
+			      bool *changed /* out */)
0903551
 {
0903551
 	struct intel_crtc *intel_crtc = to_intel_crtc(cstate->crtc);
0903551
 	struct intel_crtc_state *intel_cstate = to_intel_crtc_state(cstate);
0903551
+	int ret;
0903551
 
0903551
-	skl_build_pipe_wm(intel_cstate, ddb, pipe_wm);
0903551
+	ret = skl_build_pipe_wm(intel_cstate, ddb, pipe_wm);
0903551
+	if (ret)
0903551
+		return ret;
0903551
 
0903551
 	if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
0903551
-		return false;
0903551
+		*changed = false;
0903551
+	else
0903551
+		*changed = true;
0903551
 
0903551
 	intel_crtc->wm.active.skl = *pipe_wm;
0903551
 
0903551
-	return true;
0903551
+	return 0;
0903551
 }
0903551
 
0903551
 static void skl_update_other_pipe_wm(struct drm_device *dev,
0903551
@@ -3669,8 +3690,8 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
0903551
 		if (!intel_crtc->active)
0903551
 			continue;
0903551
 
0903551
-		wm_changed = skl_update_pipe_wm(intel_crtc->base.state,
0903551
-						&r->ddb, &pipe_wm);
0903551
+		skl_update_pipe_wm(intel_crtc->base.state,
0903551
+				   &r->ddb, &pipe_wm, &wm_changed);
0903551
 
0903551
 		/*
0903551
 		 * If we end up re-computing the other pipe WM values, it's
0903551
@@ -3780,14 +3801,15 @@ static void skl_update_wm(struct drm_crtc *crtc)
0903551
 	struct skl_wm_values *results = &dev_priv->wm.skl_results;
0903551
 	struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
0903551
 	struct skl_pipe_wm *pipe_wm = &cstate->wm.skl.optimal;
0903551
-
0903551
+	bool wm_changed;
0903551
 
0903551
 	/* Clear all dirty flags */
0903551
 	results->dirty_pipes = 0;
0903551
 
0903551
 	skl_clear_wm(results, intel_crtc->pipe);
0903551
 
0903551
-	if (!skl_update_pipe_wm(crtc->state, &results->ddb, pipe_wm))
0903551
+	skl_update_pipe_wm(crtc->state, &results->ddb, pipe_wm, &wm_changed);
0903551
+	if (!wm_changed)
0903551
 		return;
0903551
 
0903551
 	skl_compute_wm_results(dev, pipe_wm, results, intel_crtc);
0903551
-- 
0903551
2.7.4
0903551