summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h8
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.c12
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c7
3 files changed, 24 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index a29ab5ed98e1..cf3c98c6c3ce 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -654,6 +654,7 @@ struct i915_gtt {
struct i915_hw_ppgtt {
struct i915_address_space base;
+ struct kref ref;
struct drm_mm_node node;
unsigned num_pd_entries;
union {
@@ -703,6 +704,7 @@ struct i915_hw_context {
struct intel_ring_buffer *last_ring;
struct drm_i915_gem_object *obj;
struct i915_ctx_hang_stats hang_stats;
+ struct i915_address_space *vm;
struct list_head link;
};
@@ -2289,6 +2291,12 @@ static inline bool intel_enable_ppgtt(struct drm_device *dev, bool full)
return HAS_ALIASING_PPGTT(dev);
}
+static inline void ppgtt_release(struct kref *kref)
+{
+ struct i915_hw_ppgtt *ppgtt = container_of(kref, struct i915_hw_ppgtt, ref);
+
+ ppgtt->base.cleanup(&ppgtt->base);
+}
/* i915_gem_evict.c */
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index f5b0b8007594..80064aab6584 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -141,9 +141,19 @@ void i915_gem_context_free(struct kref *ctx_ref)
{
struct i915_hw_context *ctx = container_of(ctx_ref,
typeof(*ctx), ref);
+ struct i915_hw_ppgtt *ppgtt = NULL;
- list_del(&ctx->link);
+ /* We refcount even the aliasing PPGTT to keep the code symmetric */
+ if (USES_ALIASING_PPGTT(ctx->obj->base.dev))
+ ppgtt = container_of(ctx->vm, struct i915_hw_ppgtt, base);
+
+ /* XXX: Free up the object before tearing down the address space, in
+ * case we're bound in the PPGTT */
drm_gem_object_unreference(&ctx->obj->base);
+
+ if (ppgtt)
+ kref_put(&ppgtt->ref, ppgtt_release);
+ list_del(&ctx->link);
kfree(ctx);
}
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 6e9a43e57572..f9f7267e09a0 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -904,9 +904,11 @@ int i915_gem_init_ppgtt(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt)
else
BUG();
- if (!ret)
+ if (!ret) {
+ kref_init(&ppgtt->ref);
drm_mm_init(&ppgtt->base.mm, ppgtt->base.start,
ppgtt->base.total);
+ }
return ret;
}
@@ -919,7 +921,8 @@ void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev)
if (!ppgtt)
return;
- ppgtt->base.cleanup(&ppgtt->base);
+ kref_put(&dev_priv->mm.aliasing_ppgtt->ref, ppgtt_release);
+
dev_priv->mm.aliasing_ppgtt = NULL;
}