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