Commit 77b25a97 authored by Chris Wilson's avatar Chris Wilson Committed by Daniel Vetter

drm/i915: Make i915_gem_context_mark_guilty() safe for unlocked updates

Since we make call i915_gem_context_mark_guilty() concurrently when
resetting different engines in parallel, we need to make sure that our
updates are safe for the unlocked access.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Michel Thierry <michel.thierry@intel.com>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Reviewed-by: default avatarMika Kuoppala <mika.kuoppala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20170721123238.16428-12-chris@chris-wilson.co.ukSigned-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent ed454f2c
...@@ -602,7 +602,7 @@ struct drm_i915_file_private { ...@@ -602,7 +602,7 @@ struct drm_i915_file_private {
* to limit the badly behaving clients access to gpu. * to limit the badly behaving clients access to gpu.
*/ */
#define I915_MAX_CLIENT_CONTEXT_BANS 3 #define I915_MAX_CLIENT_CONTEXT_BANS 3
int context_bans; atomic_t context_bans;
}; };
/* Used by dp and fdi links */ /* Used by dp and fdi links */
......
...@@ -2740,34 +2740,38 @@ i915_gem_object_pwrite_gtt(struct drm_i915_gem_object *obj, ...@@ -2740,34 +2740,38 @@ i915_gem_object_pwrite_gtt(struct drm_i915_gem_object *obj,
return 0; return 0;
} }
static bool ban_context(const struct i915_gem_context *ctx) static bool ban_context(const struct i915_gem_context *ctx,
unsigned int score)
{ {
return (i915_gem_context_is_bannable(ctx) && return (i915_gem_context_is_bannable(ctx) &&
ctx->ban_score >= CONTEXT_SCORE_BAN_THRESHOLD); score >= CONTEXT_SCORE_BAN_THRESHOLD);
} }
static void i915_gem_context_mark_guilty(struct i915_gem_context *ctx) static void i915_gem_context_mark_guilty(struct i915_gem_context *ctx)
{ {
ctx->guilty_count++; unsigned int score;
ctx->ban_score += CONTEXT_SCORE_GUILTY; bool banned;
if (ban_context(ctx))
i915_gem_context_set_banned(ctx);
DRM_DEBUG_DRIVER("context %s marked guilty (score %d) banned? %s\n", atomic_inc(&ctx->guilty_count);
ctx->name, ctx->ban_score,
yesno(i915_gem_context_is_banned(ctx)));
if (!i915_gem_context_is_banned(ctx) || IS_ERR_OR_NULL(ctx->file_priv)) score = atomic_add_return(CONTEXT_SCORE_GUILTY, &ctx->ban_score);
banned = ban_context(ctx, score);
DRM_DEBUG_DRIVER("context %s marked guilty (score %d) banned? %s\n",
ctx->name, score, yesno(banned));
if (!banned)
return; return;
ctx->file_priv->context_bans++; i915_gem_context_set_banned(ctx);
if (!IS_ERR_OR_NULL(ctx->file_priv)) {
atomic_inc(&ctx->file_priv->context_bans);
DRM_DEBUG_DRIVER("client %s has had %d context banned\n", DRM_DEBUG_DRIVER("client %s has had %d context banned\n",
ctx->name, ctx->file_priv->context_bans); ctx->name, atomic_read(&ctx->file_priv->context_bans));
}
} }
static void i915_gem_context_mark_innocent(struct i915_gem_context *ctx) static void i915_gem_context_mark_innocent(struct i915_gem_context *ctx)
{ {
ctx->active_count++; atomic_inc(&ctx->active_count);
} }
struct drm_i915_gem_request * struct drm_i915_gem_request *
......
...@@ -977,7 +977,7 @@ int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv) ...@@ -977,7 +977,7 @@ int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv)
static bool client_is_banned(struct drm_i915_file_private *file_priv) static bool client_is_banned(struct drm_i915_file_private *file_priv)
{ {
return file_priv->context_bans > I915_MAX_CLIENT_CONTEXT_BANS; return atomic_read(&file_priv->context_bans) > I915_MAX_CLIENT_CONTEXT_BANS;
} }
int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
...@@ -1179,8 +1179,8 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, ...@@ -1179,8 +1179,8 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev,
else else
args->reset_count = 0; args->reset_count = 0;
args->batch_active = READ_ONCE(ctx->guilty_count); args->batch_active = atomic_read(&ctx->guilty_count);
args->batch_pending = READ_ONCE(ctx->active_count); args->batch_pending = atomic_read(&ctx->active_count);
ret = 0; ret = 0;
out: out:
......
...@@ -191,17 +191,17 @@ struct i915_gem_context { ...@@ -191,17 +191,17 @@ struct i915_gem_context {
u32 desc_template; u32 desc_template;
/** guilty_count: How many times this context has caused a GPU hang. */ /** guilty_count: How many times this context has caused a GPU hang. */
unsigned int guilty_count; atomic_t guilty_count;
/** /**
* @active_count: How many times this context was active during a GPU * @active_count: How many times this context was active during a GPU
* hang, but did not cause it. * hang, but did not cause it.
*/ */
unsigned int active_count; atomic_t active_count;
#define CONTEXT_SCORE_GUILTY 10 #define CONTEXT_SCORE_GUILTY 10
#define CONTEXT_SCORE_BAN_THRESHOLD 40 #define CONTEXT_SCORE_BAN_THRESHOLD 40
/** ban_score: Accumulated score of all hangs caused by this context. */ /** ban_score: Accumulated score of all hangs caused by this context. */
int ban_score; atomic_t ban_score;
/** remap_slice: Bitmask of cache lines that need remapping */ /** remap_slice: Bitmask of cache lines that need remapping */
u8 remap_slice; u8 remap_slice;
......
...@@ -374,8 +374,7 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request) ...@@ -374,8 +374,7 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request)
i915_gem_request_remove_from_client(request); i915_gem_request_remove_from_client(request);
/* Retirement decays the ban score as it is a sign of ctx progress */ /* Retirement decays the ban score as it is a sign of ctx progress */
if (request->ctx->ban_score > 0) atomic_dec_if_positive(&request->ctx->ban_score);
request->ctx->ban_score--;
/* The backing object for the context is done after switching to the /* The backing object for the context is done after switching to the
* *next* context. Therefore we cannot retire the previous context until * *next* context. Therefore we cannot retire the previous context until
......
...@@ -1266,7 +1266,7 @@ static void record_request(struct drm_i915_gem_request *request, ...@@ -1266,7 +1266,7 @@ static void record_request(struct drm_i915_gem_request *request,
struct drm_i915_error_request *erq) struct drm_i915_error_request *erq)
{ {
erq->context = request->ctx->hw_id; erq->context = request->ctx->hw_id;
erq->ban_score = request->ctx->ban_score; erq->ban_score = atomic_read(&request->ctx->ban_score);
erq->seqno = request->global_seqno; erq->seqno = request->global_seqno;
erq->jiffies = request->emitted_jiffies; erq->jiffies = request->emitted_jiffies;
erq->head = request->head; erq->head = request->head;
...@@ -1357,9 +1357,9 @@ static void record_context(struct drm_i915_error_context *e, ...@@ -1357,9 +1357,9 @@ static void record_context(struct drm_i915_error_context *e,
e->handle = ctx->user_handle; e->handle = ctx->user_handle;
e->hw_id = ctx->hw_id; e->hw_id = ctx->hw_id;
e->ban_score = ctx->ban_score; e->ban_score = atomic_read(&ctx->ban_score);
e->guilty = ctx->guilty_count; e->guilty = atomic_read(&ctx->guilty_count);
e->active = ctx->active_count; e->active = atomic_read(&ctx->active_count);
} }
static void request_record_user_bo(struct drm_i915_gem_request *request, static void request_record_user_bo(struct drm_i915_gem_request *request,
......
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