[PATCH 55/66] drm/i915: Extract mm switching to function

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In order to do the full context switch with address space, it's
convenient to have a way to switch the address space. We already have
this in our code - just pull it out to be called by the context switch
code later.

Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_drv.h     |  2 +
 drivers/gpu/drm/i915/i915_gem_gtt.c | 79 +++++++++++++++++++++----------------
 2 files changed, 48 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 883d314..7865618 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -534,6 +534,8 @@ struct i915_hw_ppgtt {
 	gen6_gtt_pte_t (*pte_encode)(dma_addr_t addr,
 				     enum i915_cache_level level);
 	int (*enable)(struct i915_hw_ppgtt *ppgtt);
+	int (*switch_mm)(struct i915_hw_ppgtt *ppgtt,
+			 struct intel_ring_buffer *ring);
 	void (*cleanup)(struct i915_hw_ppgtt *ppgtt);
 };
 
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index be5c7a9..646e8ef 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -122,11 +122,54 @@ static void gen6_write_pdes(struct i915_hw_ppgtt *ppgtt)
 	readl(pd_addr);
 }
 
+static int gen6_mm_switch(struct i915_hw_ppgtt *ppgtt,
+			  struct intel_ring_buffer *ring)
+{
+	struct drm_device *dev = ppgtt->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t pd_offset = ppgtt->pd_offset;
+	int ret;
+
+	pd_offset /= 64; /* in cachelines, */
+	pd_offset <<= 16;
+
+	/* If we're in reset, we can assume the GPU is sufficiently idle
+	 * to manually frob these bits. Ideally we could use the ring
+	 * functions, except our error handling makes it quite difficult
+	 * (can't use intel_ring_begin, ring->flush, or
+	 * intel_ring_advance)
+	 */
+	if (i915_reset_in_progress(&dev_priv->gpu_error)) {
+		WARN_ON(ppgtt != dev_priv->gtt.aliasing_ppgtt);
+		I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
+		I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset);
+		return 0;
+	}
+
+	/* NB: TLBs must be flushed and invalidated before a switch */
+	ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
+	if (ret)
+		return ret;
+
+	ret = intel_ring_begin(ring, 6);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2));
+	intel_ring_emit(ring, RING_PP_DIR_DCLV(ring));
+	intel_ring_emit(ring, PP_DIR_DCLV_2G);
+	intel_ring_emit(ring, RING_PP_DIR_BASE(ring));
+	intel_ring_emit(ring, pd_offset);
+	intel_ring_emit(ring, MI_NOOP);
+	intel_ring_advance(ring);
+
+	return 0;
+}
+
 static int gen6_ppgtt_enable(struct i915_hw_ppgtt *ppgtt)
 {
 	struct drm_device *dev = ppgtt->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	uint32_t pd_offset;
 	struct intel_ring_buffer *ring;
 	int i;
 
@@ -134,10 +177,6 @@ static int gen6_ppgtt_enable(struct i915_hw_ppgtt *ppgtt)
 
 	gen6_write_pdes(ppgtt);
 
-	pd_offset = ppgtt->pd_offset;
-	pd_offset /= 64; /* in cachelines, */
-	pd_offset <<= 16;
-
 	if (INTEL_INFO(dev)->gen == 6) {
 		uint32_t ecochk, gab_ctl, ecobits;
 
@@ -179,36 +218,9 @@ static int gen6_ppgtt_enable(struct i915_hw_ppgtt *ppgtt)
 			I915_WRITE(RING_MODE_GEN7(ring),
 				   _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
 
-		/* If we're in reset, we can assume the GPU is sufficiently idle
-		 * to manually frob these bits. Ideally we could use the ring
-		 * functions, except our error handling makes it quite difficult
-		 * (can't use intel_ring_begin, ring->flush, or
-		 * intel_ring_advance)
-		 */
-		if (i915_reset_in_progress(&dev_priv->gpu_error)) {
-			WARN_ON(ppgtt != dev_priv->gtt.aliasing_ppgtt);
-			I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
-			I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset);
-			return 0;
-		}
-
-		/* NB: TLBs must be flushed and invalidated before a switch */
-		ret = ring->flush(ring, I915_GEM_GPU_DOMAINS,
-				  I915_GEM_GPU_DOMAINS);
+		ret = ppgtt->switch_mm(ppgtt, ring);
 		if (ret)
 			return ret;
-
-		ret = intel_ring_begin(ring, 6);
-		if (ret)
-			return ret;
-
-		intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2));
-		intel_ring_emit(ring, RING_PP_DIR_DCLV(ring));
-		intel_ring_emit(ring, PP_DIR_DCLV_2G);
-		intel_ring_emit(ring, RING_PP_DIR_BASE(ring));
-		intel_ring_emit(ring, pd_offset);
-		intel_ring_emit(ring, MI_NOOP);
-		intel_ring_advance(ring);
 	}
 	return 0;
 }
@@ -375,6 +387,7 @@ alloc:
 
 	ppgtt->num_pd_entries = GEN6_PPGTT_PD_ENTRIES;
 	ppgtt->enable = gen6_ppgtt_enable;
+	ppgtt->switch_mm = gen6_mm_switch;
 	ppgtt->cleanup = gen6_ppgtt_cleanup;
 
 	vm->clear_range = gen6_ppgtt_clear_range;
-- 
1.8.3.1



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux