walters / rpms / kernel

Forked from rpms/kernel 5 years ago
Clone
0d24915
From fbf53d8f1b7d1bcea1411f1f2cd0df6a6cc95332 Mon Sep 17 00:00:00 2001
0d24915
From: Matt Roper <matthew.d.roper@intel.com>
0d24915
Date: Thu, 12 May 2016 07:06:03 -0700
55efec4
Subject: [PATCH 09/17] drm/i915/gen9: Compute DDB allocation at atomic check
55efec4
 time (v4)
55efec4
0d24915
Calculate the DDB blocks needed to satisfy the current atomic
0d24915
transaction at atomic check time.  This is a prerequisite to calculating
0d24915
SKL watermarks during the 'check' phase and rejecting any configurations
0d24915
that we can't find valid watermarks for.
55efec4
0d24915
Due to the nature of DDB allocation, it's possible for the addition of a
0d24915
new CRTC to make the watermark configuration already in use on another,
0d24915
unchanged CRTC become invalid.  A change in which CRTC's are active
0d24915
triggers a recompute of the entire DDB, which unfortunately means we
0d24915
need to disallow any other atomic commits from racing with such an
0d24915
update.  If the active CRTC's change, we need to grab the lock on all
0d24915
CRTC's and run all CRTC's through their 'check' handler to recompute and
0d24915
re-check their per-CRTC DDB allocations.
55efec4
0d24915
Note that with this patch we only compute the DDB allocation but we
0d24915
don't actually use the computed values during watermark programming yet.
0d24915
For ease of review/testing/bisecting, we still recompute the DDB at
0d24915
watermark programming time and just WARN() if it doesn't match the
0d24915
precomputed values.  A future patch will switch over to using the
0d24915
precomputed values once we're sure they're being properly computed.
55efec4
0d24915
Another clarifying note:  DDB allocation itself shouldn't ever fail with
0d24915
the algorithm we use today (i.e., we have enough DDB blocks on BXT to
0d24915
support the minimum needs of the worst-case scenario of every pipe/plane
0d24915
enabled at full size).  However the watermarks calculations based on the
0d24915
DDB may fail and we'll be moving those to the atomic check as well in
0d24915
future patches.
55efec4
0d24915
v2:
0d24915
 - Skip DDB calculations in the rare case where our transaction doesn't
0d24915
   actually touch any CRTC's at all.  Assuming at least one CRTC state
0d24915
   is present in our transaction, then it means we can't race with any
0d24915
   transactions that would update dev_priv->active_crtcs (which requires
0d24915
   _all_ CRTC locks).
55efec4
0d24915
v3:
0d24915
 - Also calculate DDB during initial hw readout, to prevent using
0d24915
   incorrect bios values. (Maarten)
55efec4
0d24915
v4:
0d24915
 - Use new distrust_bios_wm flag instead of skip_initial_wm (which was
0d24915
   never actually set).
0d24915
 - Set intel_state->active_pipe_changes instead of just realloc_pipes
55efec4
0d24915
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
0d24915
Cc: Lyude Paul <cpaul@redhat.com>
0d24915
Cc: Radhakrishna Sripada <radhakrishna.sripada@intel.com>
0d24915
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
0d24915
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
0d24915
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
0d24915
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-10-git-send-email-matthew.d.roper@intel.com
55efec4
---
55efec4
 drivers/gpu/drm/i915/i915_drv.h      |  5 +++
55efec4
 drivers/gpu/drm/i915/intel_display.c | 18 ++++++++
55efec4
 drivers/gpu/drm/i915/intel_drv.h     |  3 ++
55efec4
 drivers/gpu/drm/i915/intel_pm.c      | 79 ++++++++++++++++++++++++++++++++++++
55efec4
 4 files changed, 105 insertions(+)
55efec4
55efec4
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
0d24915
index e21960d..b908a41 100644
55efec4
--- a/drivers/gpu/drm/i915/i915_drv.h
55efec4
+++ b/drivers/gpu/drm/i915/i915_drv.h
0d24915
@@ -339,6 +339,10 @@ struct i915_hotplug {
55efec4
 #define for_each_intel_crtc(dev, intel_crtc) \
55efec4
 	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
55efec4
 
55efec4
+#define for_each_intel_crtc_mask(dev, intel_crtc, crtc_mask) \
55efec4
+	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) \
55efec4
+		for_each_if ((crtc_mask) & (1 << drm_crtc_index(&intel_crtc->base)))
55efec4
+
55efec4
 #define for_each_intel_encoder(dev, intel_encoder)		\
55efec4
 	list_for_each_entry(intel_encoder,			\
55efec4
 			    &(dev)->mode_config.encoder_list,	\
0d24915
@@ -594,6 +598,7 @@ struct drm_i915_display_funcs {
0d24915
 				       struct intel_crtc_state *newstate);
0d24915
 	void (*initial_watermarks)(struct intel_crtc_state *cstate);
0d24915
 	void (*optimize_watermarks)(struct intel_crtc_state *cstate);
55efec4
+	int (*compute_global_watermarks)(struct drm_atomic_state *state);
55efec4
 	void (*update_wm)(struct drm_crtc *crtc);
55efec4
 	int (*modeset_calc_cdclk)(struct drm_atomic_state *state);
55efec4
 	void (*modeset_commit_cdclk)(struct drm_atomic_state *state);
55efec4
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
0d24915
index a9d2e30..ecad0ef 100644
55efec4
--- a/drivers/gpu/drm/i915/intel_display.c
55efec4
+++ b/drivers/gpu/drm/i915/intel_display.c
0d24915
@@ -13342,6 +13342,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
55efec4
 static void calc_watermark_data(struct drm_atomic_state *state)
55efec4
 {
55efec4
 	struct drm_device *dev = state->dev;
55efec4
+	struct drm_i915_private *dev_priv = to_i915(dev);
55efec4
 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
55efec4
 	struct drm_crtc *crtc;
55efec4
 	struct drm_crtc_state *cstate;
0d24915
@@ -13371,6 +13372,10 @@ static void calc_watermark_data(struct drm_atomic_state *state)
55efec4
 		    pstate->crtc_h != pstate->src_h >> 16)
55efec4
 			intel_state->wm_config.sprites_scaled = true;
55efec4
 	}
55efec4
+
55efec4
+	/* Is there platform-specific watermark information to calculate? */
55efec4
+	if (dev_priv->display.compute_global_watermarks)
55efec4
+		dev_priv->display.compute_global_watermarks(state);
55efec4
 }
55efec4
 
55efec4
 /**
0d24915
@@ -13739,6 +13744,19 @@ static int intel_atomic_commit(struct drm_device *dev,
0d24915
 		intel_modeset_verify_crtc(crtc, old_crtc_state, crtc->state);
55efec4
 	}
55efec4
 
55efec4
+	/*
55efec4
+	 * Temporary sanity check: make sure our pre-computed DDB matches the
55efec4
+	 * one we actually wind up programming.
55efec4
+	 *
55efec4
+	 * Not a great place to put this, but the easiest place we have access
55efec4
+	 * to both the pre-computed and final DDB's; we'll be removing this
55efec4
+	 * check in the next patch anyway.
55efec4
+	 */
55efec4
+	WARN(IS_GEN9(dev) &&
55efec4
+	     memcmp(&intel_state->ddb, &dev_priv->wm.skl_results.ddb,
55efec4
+		    sizeof(intel_state->ddb)),
55efec4
+	     "Pre-computed DDB does not match final DDB!\n");
55efec4
+
55efec4
 	if (intel_state->modeset)
55efec4
 		intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
55efec4
 
55efec4
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
0d24915
index d19e83e..2218290 100644
55efec4
--- a/drivers/gpu/drm/i915/intel_drv.h
55efec4
+++ b/drivers/gpu/drm/i915/intel_drv.h
0d24915
@@ -312,6 +312,9 @@ struct intel_atomic_state {
0d24915
 	 * don't bother calculating intermediate watermarks.
0d24915
 	 */
0d24915
 	bool skip_intermediate_wm;
55efec4
+
55efec4
+	/* Gen9+ only */
55efec4
+	struct skl_ddb_allocation ddb;
55efec4
 };
55efec4
 
55efec4
 struct intel_plane_state {
55efec4
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
0d24915
index a49faa7..cfa4f80 100644
55efec4
--- a/drivers/gpu/drm/i915/intel_pm.c
55efec4
+++ b/drivers/gpu/drm/i915/intel_pm.c
0d24915
@@ -3812,6 +3812,84 @@ static void skl_clear_wm(struct skl_wm_values *watermarks, enum pipe pipe)
55efec4
 
55efec4
 }
55efec4
 
55efec4
+static int
55efec4
+skl_compute_ddb(struct drm_atomic_state *state)
55efec4
+{
55efec4
+	struct drm_device *dev = state->dev;
55efec4
+	struct drm_i915_private *dev_priv = to_i915(dev);
55efec4
+	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
55efec4
+	struct intel_crtc *intel_crtc;
55efec4
+	unsigned realloc_pipes = dev_priv->active_crtcs;
55efec4
+	int ret;
55efec4
+
55efec4
+	/*
55efec4
+	 * If this is our first atomic update following hardware readout,
55efec4
+	 * we can't trust the DDB that the BIOS programmed for us.  Let's
55efec4
+	 * pretend that all pipes switched active status so that we'll
55efec4
+	 * ensure a full DDB recompute.
55efec4
+	 */
55efec4
+	if (dev_priv->wm.distrust_bios_wm)
55efec4
+		intel_state->active_pipe_changes = ~0;
55efec4
+
55efec4
+	/*
55efec4
+	 * If the modeset changes which CRTC's are active, we need to
55efec4
+	 * recompute the DDB allocation for *all* active pipes, even
55efec4
+	 * those that weren't otherwise being modified in any way by this
55efec4
+	 * atomic commit.  Due to the shrinking of the per-pipe allocations
55efec4
+	 * when new active CRTC's are added, it's possible for a pipe that
55efec4
+	 * we were already using and aren't changing at all here to suddenly
55efec4
+	 * become invalid if its DDB needs exceeds its new allocation.
55efec4
+	 *
55efec4
+	 * Note that if we wind up doing a full DDB recompute, we can't let
55efec4
+	 * any other display updates race with this transaction, so we need
55efec4
+	 * to grab the lock on *all* CRTC's.
55efec4
+	 */
55efec4
+	if (intel_state->active_pipe_changes)
55efec4
+		realloc_pipes = ~0;
55efec4
+
55efec4
+	for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) {
55efec4
+		struct intel_crtc_state *cstate;
55efec4
+
55efec4
+		cstate = intel_atomic_get_crtc_state(state, intel_crtc);
55efec4
+		if (IS_ERR(cstate))
55efec4
+			return PTR_ERR(cstate);
55efec4
+
55efec4
+		ret = skl_allocate_pipe_ddb(cstate, &intel_state->ddb);
55efec4
+		if (ret)
55efec4
+			return ret;
55efec4
+	}
55efec4
+
55efec4
+	return 0;
55efec4
+}
55efec4
+
55efec4
+static int
55efec4
+skl_compute_wm(struct drm_atomic_state *state)
55efec4
+{
55efec4
+	struct drm_crtc *crtc;
55efec4
+	struct drm_crtc_state *cstate;
55efec4
+	int ret, i;
55efec4
+	bool changed = false;
55efec4
+
55efec4
+	/*
55efec4
+	 * If this transaction isn't actually touching any CRTC's, don't
55efec4
+	 * bother with watermark calculation.  Note that if we pass this
55efec4
+	 * test, we're guaranteed to hold at least one CRTC state mutex,
55efec4
+	 * which means we can safely use values like dev_priv->active_crtcs
55efec4
+	 * since any racing commits that want to update them would need to
55efec4
+	 * hold _all_ CRTC state mutexes.
55efec4
+	 */
55efec4
+	for_each_crtc_in_state(state, crtc, cstate, i)
55efec4
+		changed = true;
55efec4
+	if (!changed)
55efec4
+		return 0;
55efec4
+
55efec4
+	ret = skl_compute_ddb(state);
55efec4
+	if (ret)
55efec4
+		return ret;
55efec4
+
55efec4
+	return 0;
55efec4
+}
55efec4
+
55efec4
 static void skl_update_wm(struct drm_crtc *crtc)
55efec4
 {
55efec4
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
0d24915
@@ -7384,6 +7462,7 @@ void intel_init_pm(struct drm_device *dev)
0d24915
 	if (INTEL_INFO(dev)->gen >= 9) {
0d24915
 		skl_setup_wm_latency(dev);
55efec4
 		dev_priv->display.update_wm = skl_update_wm;
55efec4
+		dev_priv->display.compute_global_watermarks = skl_compute_wm;
55efec4
 	} else if (HAS_PCH_SPLIT(dev)) {
55efec4
 		ilk_setup_wm_latency(dev);
55efec4
 
55efec4
-- 
55efec4
2.7.4
55efec4