diff mbox

drm/i915: Split out aliasing-ppgtt from ggtt_bind_vma()

Message ID 1444906024-27778-1-git-send-email-chris@chris-wilson.co.uk
State New, archived
Headers show

Commit Message

Chris Wilson Oct. 15, 2015, 10:47 a.m. UTC
The presence of the aliasing-ppgtt (or rather its absence) causes some
confusion on old generations where we still pretend that there is a
difference between PIN_USER and PIN_GLOBAL even though we only have the
global GTT. The confusion has resulted in a bug where we do not mark the
vma as suitably bound for both types of access and so end up processing
the binding twice.

The double bind was accidentally introduced in

    commit 75d04a3773ecee617847de963ae4195d6aa74c28
    Author: Mika Kuoppala <mika.kuoppala@linux.intel.com>
    Date:   Tue Apr 28 17:56:17 2015 +0300

        drm/i915/gtt: Allocate va range only if vma is not bound

While at it implement an improved version suggested by Chris which
avoids the double-bind irrespective of what type of bind is done
first.

Note that this exact bug was already addressed in

commit d0e30adc42d979e4adc36b6c112b57337423b70c
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jul 29 20:02:48 2015 +0100

        drm/i915: Mark PIN_USER binding as GLOBAL_BIND without the aliasing ppgtt

but the problem is still that originally in

commit 0875546c5318c85c13d07014af5350e9000bc9e9
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
Date:   Mon Apr 20 09:04:05 2015 -0700

        drm/i915: Fix up the vma aliasing ppgtt binding

if forgotten to take into account there case where we have a
GLOBAL_BIND before a LOCAL_BIND.

Here we separate out the binding into the global GTT for machines where
we have the aliasing-ppgtt and where we do not, so that we can perform
the fixup without further confusion.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 62 +++++++++++++++++++++++++++----------
 1 file changed, 45 insertions(+), 17 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 0796aa06e9f5..81f4628ae0e6 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -2493,7 +2493,6 @@  static int ggtt_bind_vma(struct i915_vma *vma,
 			 enum i915_cache_level cache_level,
 			 u32 flags)
 {
-	struct drm_i915_private *dev_priv = to_i915(vma->vm->dev);
 	u32 pte_flags;
 	int ret;
 
@@ -2506,26 +2505,49 @@  static int ggtt_bind_vma(struct i915_vma *vma,
 	if (vma->obj->gt_ro)
 		pte_flags |= PTE_READ_ONLY;
 
-	if (!dev_priv->mm.aliasing_ppgtt || flags & GLOBAL_BIND) {
+	vma->vm->insert_entries(vma->vm,
+				vma->ggtt_view.pages,
+				vma->node.start,
+				cache_level, pte_flags);
+
+	/* Note the inconsistency here is due to absence of the
+	 * aliasing ppgtt on gen5 and earlier. Though we always
+	 * request PIN_USER for execbuffer (translated to LOCAL_BIND),
+	 * without the appgtt, we cannot honour that request and so
+	 * must substitute it with a global binding. Since we do this
+	 * behind the upper layers back, we need to explicitly set
+	 * the bound flag ourselves.
+	 */
+	vma->bound |= GLOBAL_BIND | LOCAL_BIND;
+	return 0;
+}
+
+static int agtt_bind_vma(struct i915_vma *vma,
+			 enum i915_cache_level cache_level,
+			 u32 flags)
+{
+	u32 pte_flags;
+	int ret;
+
+	ret = i915_get_ggtt_vma_pages(vma);
+	if (ret)
+		return ret;
+
+	/* Currently applicable only to VLV */
+	pte_flags = 0;
+	if (vma->obj->gt_ro)
+		pte_flags |= PTE_READ_ONLY;
+
+	if (flags & GLOBAL_BIND) {
 		vma->vm->insert_entries(vma->vm,
 					vma->ggtt_view.pages,
 					vma->node.start,
 					cache_level, pte_flags);
-
-		/* Note the inconsistency here is due to absence of the
-		 * aliasing ppgtt on gen4 and earlier. Though we always
-		 * request PIN_USER for execbuffer (translated to LOCAL_BIND),
-		 * without the appgtt, we cannot honour that request and so
-		 * must substitute it with a global binding. Since we do this
-		 * behind the upper layers back, we need to explicitly set
-		 * the bound flag ourselves.
-		 */
-		vma->bound |= GLOBAL_BIND;
-
 	}
 
-	if (dev_priv->mm.aliasing_ppgtt && flags & LOCAL_BIND) {
-		struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt;
+	if (flags & LOCAL_BIND) {
+		struct i915_hw_ppgtt *appgtt =
+			to_i915(vma->vm->dev)->mm.aliasing_ppgtt;
 		appgtt->base.insert_entries(&appgtt->base,
 					    vma->ggtt_view.pages,
 					    vma->node.start,
@@ -2959,7 +2981,10 @@  static int gen8_gmch_probe(struct drm_device *dev,
 	dev_priv->gtt.base.clear_range = gen8_ggtt_clear_range;
 	dev_priv->gtt.base.insert_page = gen8_ggtt_insert_page;
 	dev_priv->gtt.base.insert_entries = gen8_ggtt_insert_entries;
-	dev_priv->gtt.base.bind_vma = ggtt_bind_vma;
+	if (dev_priv->mm.aliasing_ppgtt)
+		dev_priv->gtt.base.bind_vma = agtt_bind_vma;
+	else
+		dev_priv->gtt.base.bind_vma = ggtt_bind_vma;
 	dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma;
 
 	return ret;
@@ -3002,7 +3027,10 @@  static int gen6_gmch_probe(struct drm_device *dev,
 	dev_priv->gtt.base.clear_range = gen6_ggtt_clear_range;
 	dev_priv->gtt.base.insert_page = gen6_ggtt_insert_page;
 	dev_priv->gtt.base.insert_entries = gen6_ggtt_insert_entries;
-	dev_priv->gtt.base.bind_vma = ggtt_bind_vma;
+	if (dev_priv->mm.aliasing_ppgtt)
+		dev_priv->gtt.base.bind_vma = agtt_bind_vma;
+	else
+		dev_priv->gtt.base.bind_vma = ggtt_bind_vma;
 	dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma;
 
 	return ret;