7d2c2f2
From a9abdc6767855e1668301a1dcc4b5fa8bed1ddfa Mon Sep 17 00:00:00 2001
7d2c2f2
From: Matt Roper <matthew.d.roper@intel.com>
7d2c2f2
Date: Thu, 12 May 2016 07:06:04 -0700
7d2c2f2
Subject: [PATCH 10/17] drm/i915/gen9: Drop re-allocation of DDB at atomic
7d2c2f2
 commit (v2)
7d2c2f2
7d2c2f2
Now that we're properly pre-allocating the DDB during the atomic check
7d2c2f2
phase and we trust that the allocation is appropriate, let's actually
7d2c2f2
use the allocation computed and not duplicate that work during the
7d2c2f2
commit phase.
7d2c2f2
7d2c2f2
v2:
7d2c2f2
 - Significant rebasing now that we can use cached data rates and
7d2c2f2
   minimum block allocations to avoid grabbing additional plane states.
7d2c2f2
7d2c2f2
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
7d2c2f2
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
7d2c2f2
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-11-git-send-email-matthew.d.roper@intel.com
7d2c2f2
---
7d2c2f2
 drivers/gpu/drm/i915/intel_display.c |  14 +--
7d2c2f2
 drivers/gpu/drm/i915/intel_pm.c      | 224 +++++++++++------------------------
7d2c2f2
 2 files changed, 67 insertions(+), 171 deletions(-)
7d2c2f2
7d2c2f2
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
7d2c2f2
index ecad0ef..4db10d7 100644
7d2c2f2
--- a/drivers/gpu/drm/i915/intel_display.c
7d2c2f2
+++ b/drivers/gpu/drm/i915/intel_display.c
7d2c2f2
@@ -13627,6 +13627,7 @@ static int intel_atomic_commit(struct drm_device *dev,
7d2c2f2
 	drm_atomic_helper_swap_state(dev, state);
7d2c2f2
 	dev_priv->wm.config = intel_state->wm_config;
7d2c2f2
 	dev_priv->wm.distrust_bios_wm = false;
7d2c2f2
+	dev_priv->wm.skl_results.ddb = intel_state->ddb;
7d2c2f2
 	intel_shared_dpll_commit(state);
7d2c2f2
 
7d2c2f2
 	if (intel_state->modeset) {
7d2c2f2
@@ -13744,19 +13745,6 @@ static int intel_atomic_commit(struct drm_device *dev,
7d2c2f2
 		intel_modeset_verify_crtc(crtc, old_crtc_state, crtc->state);
7d2c2f2
 	}
7d2c2f2
 
7d2c2f2
-	/*
7d2c2f2
-	 * Temporary sanity check: make sure our pre-computed DDB matches the
7d2c2f2
-	 * one we actually wind up programming.
7d2c2f2
-	 *
7d2c2f2
-	 * Not a great place to put this, but the easiest place we have access
7d2c2f2
-	 * to both the pre-computed and final DDB's; we'll be removing this
7d2c2f2
-	 * check in the next patch anyway.
7d2c2f2
-	 */
7d2c2f2
-	WARN(IS_GEN9(dev) &&
7d2c2f2
-	     memcmp(&intel_state->ddb, &dev_priv->wm.skl_results.ddb,
7d2c2f2
-		    sizeof(intel_state->ddb)),
7d2c2f2
-	     "Pre-computed DDB does not match final DDB!\n");
7d2c2f2
-
7d2c2f2
 	if (intel_state->modeset)
7d2c2f2
 		intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
7d2c2f2
 
7d2c2f2
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
7d2c2f2
index cfa4f80..0f0d4e1 100644
7d2c2f2
--- a/drivers/gpu/drm/i915/intel_pm.c
7d2c2f2
+++ b/drivers/gpu/drm/i915/intel_pm.c
7d2c2f2
@@ -2849,7 +2849,6 @@ skl_wm_plane_id(const struct intel_plane *plane)
7d2c2f2
 static void
7d2c2f2
 skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
7d2c2f2
 				   const struct intel_crtc_state *cstate,
7d2c2f2
-				   struct intel_wm_config *config,
7d2c2f2
 				   struct skl_ddb_entry *alloc, /* out */
7d2c2f2
 				   int *num_active /* out */)
7d2c2f2
 {
7d2c2f2
@@ -2857,24 +2856,22 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
7d2c2f2
 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
7d2c2f2
 	struct drm_i915_private *dev_priv = to_i915(dev);
7d2c2f2
 	struct drm_crtc *for_crtc = cstate->base.crtc;
7d2c2f2
-	struct drm_crtc *crtc;
7d2c2f2
 	unsigned int pipe_size, ddb_size;
7d2c2f2
 	int nth_active_pipe;
7d2c2f2
 	int pipe = to_intel_crtc(for_crtc)->pipe;
7d2c2f2
 
7d2c2f2
-	if (intel_state && intel_state->active_pipe_changes)
7d2c2f2
-		*num_active = hweight32(intel_state->active_crtcs);
7d2c2f2
-	else if (intel_state)
7d2c2f2
-		*num_active = hweight32(dev_priv->active_crtcs);
7d2c2f2
-	else
7d2c2f2
-		*num_active = config->num_pipes_active;
7d2c2f2
-
7d2c2f2
-	if (!cstate->base.active) {
7d2c2f2
+	if (WARN_ON(!state) || !cstate->base.active) {
7d2c2f2
 		alloc->start = 0;
7d2c2f2
 		alloc->end = 0;
7d2c2f2
+		*num_active = hweight32(dev_priv->active_crtcs);
7d2c2f2
 		return;
7d2c2f2
 	}
7d2c2f2
 
7d2c2f2
+	if (intel_state->active_pipe_changes)
7d2c2f2
+		*num_active = hweight32(intel_state->active_crtcs);
7d2c2f2
+	else
7d2c2f2
+		*num_active = hweight32(dev_priv->active_crtcs);
7d2c2f2
+
7d2c2f2
 	if (IS_BROXTON(dev))
7d2c2f2
 		ddb_size = BXT_DDB_SIZE;
7d2c2f2
 	else
7d2c2f2
@@ -2883,50 +2880,23 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
7d2c2f2
 	ddb_size -= 4; /* 4 blocks for bypass path allocation */
7d2c2f2
 
7d2c2f2
 	/*
7d2c2f2
-	 * FIXME: At the moment we may be called on either in-flight or fully
7d2c2f2
-	 * committed cstate's.  Once we fully move DDB allocation in the check
7d2c2f2
-	 * phase, we'll only be called on in-flight states and the 'else'
7d2c2f2
-	 * branch here will go away.
7d2c2f2
-	 *
7d2c2f2
-	 * The 'else' branch is slightly racy here, but it was racy to begin
7d2c2f2
-	 * with; since it's going away soon, no effort is made to address that.
7d2c2f2
+	 * If the state doesn't change the active CRTC's, then there's
7d2c2f2
+	 * no need to recalculate; the existing pipe allocation limits
7d2c2f2
+	 * should remain unchanged.  Note that we're safe from racing
7d2c2f2
+	 * commits since any racing commit that changes the active CRTC
7d2c2f2
+	 * list would need to grab _all_ crtc locks, including the one
7d2c2f2
+	 * we currently hold.
7d2c2f2
 	 */
7d2c2f2
-	if (state) {
7d2c2f2
-		/*
7d2c2f2
-		 * If the state doesn't change the active CRTC's, then there's
7d2c2f2
-		 * no need to recalculate; the existing pipe allocation limits
7d2c2f2
-		 * should remain unchanged.  Note that we're safe from racing
7d2c2f2
-		 * commits since any racing commit that changes the active CRTC
7d2c2f2
-		 * list would need to grab _all_ crtc locks, including the one
7d2c2f2
-		 * we currently hold.
7d2c2f2
-		 */
7d2c2f2
-		if (!intel_state->active_pipe_changes) {
7d2c2f2
-			*alloc = dev_priv->wm.skl_hw.ddb.pipe[pipe];
7d2c2f2
-			return;
7d2c2f2
-		}
7d2c2f2
-
7d2c2f2
-		nth_active_pipe = hweight32(intel_state->active_crtcs &
7d2c2f2
-					    (drm_crtc_mask(for_crtc) - 1));
7d2c2f2
-		pipe_size = ddb_size / hweight32(intel_state->active_crtcs);
7d2c2f2
-		alloc->start = nth_active_pipe * ddb_size / *num_active;
7d2c2f2
-		alloc->end = alloc->start + pipe_size;
7d2c2f2
-	} else {
7d2c2f2
-		nth_active_pipe = 0;
7d2c2f2
-		for_each_crtc(dev, crtc) {
7d2c2f2
-			if (!to_intel_crtc(crtc)->active)
7d2c2f2
-				continue;
7d2c2f2
-
7d2c2f2
-			if (crtc == for_crtc)
7d2c2f2
-				break;
7d2c2f2
-
7d2c2f2
-			nth_active_pipe++;
7d2c2f2
-		}
7d2c2f2
-
7d2c2f2
-		pipe_size = ddb_size / config->num_pipes_active;
7d2c2f2
-		alloc->start = nth_active_pipe * ddb_size /
7d2c2f2
-			config->num_pipes_active;
7d2c2f2
-		alloc->end = alloc->start + pipe_size;
7d2c2f2
+	if (!intel_state->active_pipe_changes) {
7d2c2f2
+		*alloc = dev_priv->wm.skl_hw.ddb.pipe[pipe];
7d2c2f2
+		return;
7d2c2f2
 	}
7d2c2f2
+
7d2c2f2
+	nth_active_pipe = hweight32(intel_state->active_crtcs &
7d2c2f2
+				    (drm_crtc_mask(for_crtc) - 1));
7d2c2f2
+	pipe_size = ddb_size / hweight32(intel_state->active_crtcs);
7d2c2f2
+	alloc->start = nth_active_pipe * ddb_size / *num_active;
7d2c2f2
+	alloc->end = alloc->start + pipe_size;
7d2c2f2
 }
7d2c2f2
 
7d2c2f2
 static unsigned int skl_cursor_allocation(int num_active)
7d2c2f2
@@ -3025,62 +2995,33 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate)
7d2c2f2
 	struct drm_crtc *crtc = cstate->crtc;
7d2c2f2
 	struct drm_device *dev = crtc->dev;
7d2c2f2
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
7d2c2f2
+	const struct drm_plane *plane;
7d2c2f2
 	const struct intel_plane *intel_plane;
7d2c2f2
+	struct drm_plane_state *pstate;
7d2c2f2
 	unsigned int rate, total_data_rate = 0;
7d2c2f2
 	int id;
7d2c2f2
+	int i;
7d2c2f2
+
7d2c2f2
+	if (WARN_ON(!state))
7d2c2f2
+		return 0;
7d2c2f2
 
7d2c2f2
 	/* Calculate and cache data rate for each plane */
7d2c2f2
-	/*
7d2c2f2
-	 * FIXME: At the moment this function can be called on either an
7d2c2f2
-	 * in-flight or a committed state object.  If it's in-flight then we
7d2c2f2
-	 * only want to re-calculate the plane data rate for planes that are
7d2c2f2
-	 * part of the transaction (i.e., we don't want to grab any additional
7d2c2f2
-	 * plane states if we don't have to).  If we're operating on committed
7d2c2f2
-	 * state, we'll just go ahead and recalculate the plane data rate for
7d2c2f2
-	 * all planes.
7d2c2f2
-	 *
7d2c2f2
-	 * Once we finish moving our DDB allocation to the atomic check phase,
7d2c2f2
-	 * we'll only be calling this function on in-flight state objects, so
7d2c2f2
-	 * the 'else' branch here will go away.
7d2c2f2
-	 */
7d2c2f2
-	if (state) {
7d2c2f2
-		struct drm_plane *plane;
7d2c2f2
-		struct drm_plane_state *pstate;
7d2c2f2
-		int i;
7d2c2f2
-
7d2c2f2
-		for_each_plane_in_state(state, plane, pstate, i) {
7d2c2f2
-			intel_plane = to_intel_plane(plane);
7d2c2f2
-			id = skl_wm_plane_id(intel_plane);
7d2c2f2
-
7d2c2f2
-			if (intel_plane->pipe != intel_crtc->pipe)
7d2c2f2
-				continue;
7d2c2f2
-
7d2c2f2
-			/* packed/uv */
7d2c2f2
-			rate = skl_plane_relative_data_rate(intel_cstate,
7d2c2f2
-							    pstate, 0);
7d2c2f2
-			intel_cstate->wm.skl.plane_data_rate[id] = rate;
7d2c2f2
-
7d2c2f2
-			/* y-plane */
7d2c2f2
-			rate = skl_plane_relative_data_rate(intel_cstate,
7d2c2f2
-							    pstate, 1);
7d2c2f2
-			intel_cstate->wm.skl.plane_y_data_rate[id] = rate;
7d2c2f2
-		}
7d2c2f2
-	} else {
7d2c2f2
-		for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
7d2c2f2
-			const struct drm_plane_state *pstate =
7d2c2f2
-				intel_plane->base.state;
7d2c2f2
-			int id = skl_wm_plane_id(intel_plane);
7d2c2f2
+	for_each_plane_in_state(state, plane, pstate, i) {
7d2c2f2
+		id = skl_wm_plane_id(to_intel_plane(plane));
7d2c2f2
+		intel_plane = to_intel_plane(plane);
7d2c2f2
 
7d2c2f2
-			/* packed/uv */
7d2c2f2
-			rate = skl_plane_relative_data_rate(intel_cstate,
7d2c2f2
-							    pstate, 0);
7d2c2f2
-			intel_cstate->wm.skl.plane_data_rate[id] = rate;
7d2c2f2
+		if (intel_plane->pipe != intel_crtc->pipe)
7d2c2f2
+			continue;
7d2c2f2
 
7d2c2f2
-			/* y-plane */
7d2c2f2
-			rate = skl_plane_relative_data_rate(intel_cstate,
7d2c2f2
-							    pstate, 1);
7d2c2f2
-			intel_cstate->wm.skl.plane_y_data_rate[id] = rate;
7d2c2f2
-		}
7d2c2f2
+		/* packed/uv */
7d2c2f2
+		rate = skl_plane_relative_data_rate(intel_cstate,
7d2c2f2
+						    pstate, 0);
7d2c2f2
+		intel_cstate->wm.skl.plane_data_rate[id] = rate;
7d2c2f2
+
7d2c2f2
+		/* y-plane */
7d2c2f2
+		rate = skl_plane_relative_data_rate(intel_cstate,
7d2c2f2
+						    pstate, 1);
7d2c2f2
+		intel_cstate->wm.skl.plane_y_data_rate[id] = rate;
7d2c2f2
 	}
7d2c2f2
 
7d2c2f2
 	/* Calculate CRTC's total data rate from cached values */
7d2c2f2
@@ -3104,8 +3045,6 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
7d2c2f2
 	struct drm_atomic_state *state = cstate->base.state;
7d2c2f2
 	struct drm_crtc *crtc = cstate->base.crtc;
7d2c2f2
 	struct drm_device *dev = crtc->dev;
7d2c2f2
-	struct drm_i915_private *dev_priv = to_i915(dev);
7d2c2f2
-	struct intel_wm_config *config = &dev_priv->wm.config;
7d2c2f2
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
7d2c2f2
 	struct intel_plane *intel_plane;
7d2c2f2
 	struct drm_plane *plane;
7d2c2f2
@@ -3119,6 +3058,9 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
7d2c2f2
 	int num_active;
7d2c2f2
 	int id, i;
7d2c2f2
 
7d2c2f2
+	if (WARN_ON(!state))
7d2c2f2
+		return 0;
7d2c2f2
+
7d2c2f2
 	if (!cstate->base.active) {
7d2c2f2
 		ddb->pipe[pipe].start = ddb->pipe[pipe].end = 0;
7d2c2f2
 		memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
7d2c2f2
@@ -3126,8 +3068,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
7d2c2f2
 		return 0;
7d2c2f2
 	}
7d2c2f2
 
7d2c2f2
-	skl_ddb_get_pipe_allocation_limits(dev, cstate, config, alloc,
7d2c2f2
-					   &num_active);
7d2c2f2
+	skl_ddb_get_pipe_allocation_limits(dev, cstate, alloc, &num_active);
7d2c2f2
 	alloc_size = skl_ddb_entry_size(alloc);
7d2c2f2
 	if (alloc_size == 0) {
7d2c2f2
 		memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
7d2c2f2
@@ -3139,53 +3080,31 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
7d2c2f2
 	ddb->plane[pipe][PLANE_CURSOR].end = alloc->end;
7d2c2f2
 
7d2c2f2
 	alloc_size -= cursor_blocks;
7d2c2f2
-	alloc->end -= cursor_blocks;
7d2c2f2
 
7d2c2f2
 	/* 1. Allocate the mininum required blocks for each active plane */
7d2c2f2
-	/*
7d2c2f2
-	 * TODO: Remove support for already-committed state once we
7d2c2f2
-	 * only allocate DDB on in-flight states.
7d2c2f2
-	 */
7d2c2f2
-	if (state) {
7d2c2f2
-		for_each_plane_in_state(state, plane, pstate, i) {
7d2c2f2
-			intel_plane = to_intel_plane(plane);
7d2c2f2
-			id = skl_wm_plane_id(intel_plane);
7d2c2f2
-
7d2c2f2
-			if (intel_plane->pipe != pipe)
7d2c2f2
-				continue;
7d2c2f2
-
7d2c2f2
-			if (!to_intel_plane_state(pstate)->visible) {
7d2c2f2
-				minimum[id] = 0;
7d2c2f2
-				y_minimum[id] = 0;
7d2c2f2
-				continue;
7d2c2f2
-			}
7d2c2f2
-			if (plane->type == DRM_PLANE_TYPE_CURSOR) {
7d2c2f2
-				minimum[id] = 0;
7d2c2f2
-				y_minimum[id] = 0;
7d2c2f2
-				continue;
7d2c2f2
-			}
7d2c2f2
-
7d2c2f2
-			minimum[id] = 8;
7d2c2f2
-			if (pstate->fb->pixel_format == DRM_FORMAT_NV12)
7d2c2f2
-				y_minimum[id] = 8;
7d2c2f2
-			else
7d2c2f2
-				y_minimum[id] = 0;
7d2c2f2
-		}
7d2c2f2
-	} else {
7d2c2f2
-		for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
7d2c2f2
-			struct drm_plane *plane = &intel_plane->base;
7d2c2f2
-			struct drm_framebuffer *fb = plane->state->fb;
7d2c2f2
-			int id = skl_wm_plane_id(intel_plane);
7d2c2f2
-
7d2c2f2
-			if (!to_intel_plane_state(plane->state)->visible)
7d2c2f2
-				continue;
7d2c2f2
+	for_each_plane_in_state(state, plane, pstate, i) {
7d2c2f2
+		intel_plane = to_intel_plane(plane);
7d2c2f2
+		id = skl_wm_plane_id(intel_plane);
7d2c2f2
 
7d2c2f2
-			if (plane->type == DRM_PLANE_TYPE_CURSOR)
7d2c2f2
-				continue;
7d2c2f2
+		if (intel_plane->pipe != pipe)
7d2c2f2
+			continue;
7d2c2f2
 
7d2c2f2
-			minimum[id] = 8;
7d2c2f2
-			y_minimum[id] = (fb->pixel_format == DRM_FORMAT_NV12) ? 8 : 0;
7d2c2f2
+		if (!to_intel_plane_state(pstate)->visible) {
7d2c2f2
+			minimum[id] = 0;
7d2c2f2
+			y_minimum[id] = 0;
7d2c2f2
+			continue;
7d2c2f2
+		}
7d2c2f2
+		if (plane->type == DRM_PLANE_TYPE_CURSOR) {
7d2c2f2
+			minimum[id] = 0;
7d2c2f2
+			y_minimum[id] = 0;
7d2c2f2
+			continue;
7d2c2f2
 		}
7d2c2f2
+
7d2c2f2
+		minimum[id] = 8;
7d2c2f2
+		if (pstate->fb->pixel_format == DRM_FORMAT_NV12)
7d2c2f2
+			y_minimum[id] = 8;
7d2c2f2
+		else
7d2c2f2
+			y_minimum[id] = 0;
7d2c2f2
 	}
7d2c2f2
 
7d2c2f2
 	for (i = 0; i < PLANE_CURSOR; i++) {
7d2c2f2
@@ -3736,7 +3655,6 @@ static bool skl_update_pipe_wm(struct drm_crtc *crtc,
7d2c2f2
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
7d2c2f2
 	struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
7d2c2f2
 
7d2c2f2
-	WARN_ON(skl_allocate_pipe_ddb(cstate, ddb) != 0);
7d2c2f2
 	skl_build_pipe_wm(cstate, ddb, pipe_wm);
7d2c2f2
 
7d2c2f2
 	if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
7d2c2f2
@@ -3800,16 +3718,6 @@ static void skl_clear_wm(struct skl_wm_values *watermarks, enum pipe pipe)
7d2c2f2
 	memset(watermarks->plane_trans[pipe],
7d2c2f2
 	       0, sizeof(uint32_t) * I915_MAX_PLANES);
7d2c2f2
 	watermarks->plane_trans[pipe][PLANE_CURSOR] = 0;
7d2c2f2
-
7d2c2f2
-	/* Clear ddb entries for pipe */
7d2c2f2
-	memset(&watermarks->ddb.pipe[pipe], 0, sizeof(struct skl_ddb_entry));
7d2c2f2
-	memset(&watermarks->ddb.plane[pipe], 0,
7d2c2f2
-	       sizeof(struct skl_ddb_entry) * I915_MAX_PLANES);
7d2c2f2
-	memset(&watermarks->ddb.y_plane[pipe], 0,
7d2c2f2
-	       sizeof(struct skl_ddb_entry) * I915_MAX_PLANES);
7d2c2f2
-	memset(&watermarks->ddb.plane[pipe][PLANE_CURSOR], 0,
7d2c2f2
-	       sizeof(struct skl_ddb_entry));
7d2c2f2
-
7d2c2f2
 }
7d2c2f2
 
7d2c2f2
 static int
7d2c2f2
-- 
7d2c2f2
2.7.4
7d2c2f2