diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 267f1f97b9f0981c37a7b10133632ddc6d2400b5..0ee9e154359fdaaa5b8702385c77cc8f080209c8 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1912,7 +1912,6 @@ static void gen6_ppgtt_cleanup(struct i915_address_space *vm) { struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(i915_vm_to_ppgtt(vm)); - i915_vma_unpin(ppgtt->vma); i915_vma_destroy(ppgtt->vma); gen6_ppgtt_free_pd(ppgtt); @@ -1998,10 +1997,19 @@ static struct i915_vma *pd_vma_create(struct gen6_hw_ppgtt *ppgtt, int size) return vma; } -static int gen6_ppgtt_pin(struct i915_hw_ppgtt *base) +int gen6_ppgtt_pin(struct i915_hw_ppgtt *base) { struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(base); + /* + * Workaround the limited maximum vma->pin_count and the aliasing_ppgtt + * which will be pinned into every active context. + * (When vma->pin_count becomes atomic, I expect we will naturally + * need a larger, unpacked, type and kill this redundancy.) + */ + if (ppgtt->pin_count++) + return 0; + /* * PPGTT PDEs reside in the GGTT and consists of 512 entries. The * allocator works in address space sizes, so it's multiplied by page @@ -2012,6 +2020,17 @@ static int gen6_ppgtt_pin(struct i915_hw_ppgtt *base) PIN_GLOBAL | PIN_HIGH); } +void gen6_ppgtt_unpin(struct i915_hw_ppgtt *base) +{ + struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(base); + + GEM_BUG_ON(!ppgtt->pin_count); + if (--ppgtt->pin_count) + return; + + i915_vma_unpin(ppgtt->vma); +} + static struct i915_hw_ppgtt *gen6_ppgtt_create(struct drm_i915_private *i915) { struct i915_ggtt * const ggtt = &i915->ggtt; @@ -2053,21 +2072,8 @@ static struct i915_hw_ppgtt *gen6_ppgtt_create(struct drm_i915_private *i915) if (err) goto err_vma; - err = gen6_ppgtt_pin(&ppgtt->base); - if (err) - goto err_pd; - - DRM_DEBUG_DRIVER("Allocated pde space (%lldM) at GTT entry: %llx\n", - ppgtt->vma->node.size >> 20, - ppgtt->vma->node.start / PAGE_SIZE); - - DRM_DEBUG_DRIVER("Adding PPGTT at offset %x\n", - ppgtt->base.pd.base.ggtt_offset << 10); - return &ppgtt->base; -err_pd: - gen6_ppgtt_free_pd(ppgtt); err_vma: i915_vma_destroy(ppgtt->vma); err_scratch: diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 6e9acd99ecc61b4a6928cf365e057dd4c57ce01f..d7b7b4afe060bdcb173b5403c68c6e2058035871 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -412,6 +412,8 @@ struct gen6_hw_ppgtt { struct i915_vma *vma; gen6_pte_t __iomem *pd_addr; + + unsigned int pin_count; }; #define __to_gen6_ppgtt(base) container_of(base, struct gen6_hw_ppgtt, base) @@ -625,6 +627,9 @@ static inline void i915_ppgtt_put(struct i915_hw_ppgtt *ppgtt) kref_put(&ppgtt->ref, i915_ppgtt_release); } +int gen6_ppgtt_pin(struct i915_hw_ppgtt *base); +void gen6_ppgtt_unpin(struct i915_hw_ppgtt *base); + void i915_check_and_clear_faults(struct drm_i915_private *dev_priv); void i915_gem_suspend_gtt_mappings(struct drm_i915_private *dev_priv); void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 735622dc73ec2d47031ca91bb742ba4b90cf8eb4..6a937a89665193c4a1c90f6de4c42f9159c11a4f 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1179,6 +1179,27 @@ static void intel_ring_context_destroy(struct intel_context *ce) __i915_gem_object_release_unless_active(ce->state->obj); } +static int __context_pin_ppgtt(struct i915_gem_context *ctx) +{ + struct i915_hw_ppgtt *ppgtt; + int err = 0; + + ppgtt = ctx->ppgtt ?: ctx->i915->mm.aliasing_ppgtt; + if (ppgtt) + err = gen6_ppgtt_pin(ppgtt); + + return err; +} + +static void __context_unpin_ppgtt(struct i915_gem_context *ctx) +{ + struct i915_hw_ppgtt *ppgtt; + + ppgtt = ctx->ppgtt ?: ctx->i915->mm.aliasing_ppgtt; + if (ppgtt) + gen6_ppgtt_unpin(ppgtt); +} + static int __context_pin(struct intel_context *ce) { struct i915_vma *vma; @@ -1227,6 +1248,7 @@ static void __context_unpin(struct intel_context *ce) static void intel_ring_context_unpin(struct intel_context *ce) { + __context_unpin_ppgtt(ce->gem_context); __context_unpin(ce); i915_gem_context_put(ce->gem_context); @@ -1324,6 +1346,10 @@ __ring_context_pin(struct intel_engine_cs *engine, if (err) goto err; + err = __context_pin_ppgtt(ce->gem_context); + if (err) + goto err_unpin; + i915_gem_context_get(ctx); /* One ringbuffer to rule them all */ @@ -1332,6 +1358,8 @@ __ring_context_pin(struct intel_engine_cs *engine, return ce; +err_unpin: + __context_unpin(ce); err: ce->pin_count = 0; return ERR_PTR(err);