Commit 691e6415 authored by Chris Wilson's avatar Chris Wilson Committed by Jani Nikula

drm/i915: Always use kref tracking for all contexts.

If we always initialize kref for the context, even if we are using fake
contexts for hangstats when there is no hw support, we can forgo the
dance to dereference the ctx->obj and inspect whether we are permitted
to use kref inside i915_gem_context_reference() and _unreference().

My ulterior motive here is to improve the debugging of a use-after-free
of ctx->obj. This patch avoids the dereference here and instead forces
the assertion checks associated with kref.

v2: Refactor the fake contexts to being even more like the real
contexts, so that there is much less duplicated and special case code.

v3: Tweaks.
v4: Tweaks, minor.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=76671Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Tested-by: default avatarlu hua <huax.lu@intel.com>
Cc: Ben Widawsky <benjamin.widawsky@intel.com>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Reviewed-by: default avatarBen Widawsky <ben@bwidawsk.net>
[Jani: tiny change to backport to drm-intel-fixes.]
Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
parent c675949e
...@@ -2432,20 +2432,18 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file); ...@@ -2432,20 +2432,18 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file);
int i915_gem_context_enable(struct drm_i915_private *dev_priv); int i915_gem_context_enable(struct drm_i915_private *dev_priv);
void i915_gem_context_close(struct drm_device *dev, struct drm_file *file); void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
int i915_switch_context(struct intel_ring_buffer *ring, int i915_switch_context(struct intel_ring_buffer *ring,
struct drm_file *file, struct i915_hw_context *to); struct i915_hw_context *to);
struct i915_hw_context * struct i915_hw_context *
i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id); i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id);
void i915_gem_context_free(struct kref *ctx_ref); void i915_gem_context_free(struct kref *ctx_ref);
static inline void i915_gem_context_reference(struct i915_hw_context *ctx) static inline void i915_gem_context_reference(struct i915_hw_context *ctx)
{ {
if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev)) kref_get(&ctx->ref);
kref_get(&ctx->ref);
} }
static inline void i915_gem_context_unreference(struct i915_hw_context *ctx) static inline void i915_gem_context_unreference(struct i915_hw_context *ctx)
{ {
if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev)) kref_put(&ctx->ref, i915_gem_context_free);
kref_put(&ctx->ref, i915_gem_context_free);
} }
static inline bool i915_gem_context_is_default(const struct i915_hw_context *c) static inline bool i915_gem_context_is_default(const struct i915_hw_context *c)
......
...@@ -2790,7 +2790,7 @@ int i915_gpu_idle(struct drm_device *dev) ...@@ -2790,7 +2790,7 @@ int i915_gpu_idle(struct drm_device *dev)
/* Flush everything onto the inactive list. */ /* Flush everything onto the inactive list. */
for_each_ring(ring, dev_priv, i) { for_each_ring(ring, dev_priv, i) {
ret = i915_switch_context(ring, NULL, ring->default_context); ret = i915_switch_context(ring, ring->default_context);
if (ret) if (ret)
return ret; return ret;
......
This diff is collapsed.
...@@ -1221,7 +1221,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, ...@@ -1221,7 +1221,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
if (ret) if (ret)
goto err; goto err;
ret = i915_switch_context(ring, file, ctx); ret = i915_switch_context(ring, ctx);
if (ret) if (ret)
goto err; goto err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment