Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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.uk


Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent ed454f2c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -602,7 +602,7 @@ struct drm_i915_file_private {
 * to limit the badly behaving clients access to gpu.
 */
#define I915_MAX_CLIENT_CONTEXT_BANS 3
	int context_bans;
	atomic_t context_bans;
};

/* Used by dp and fdi links */
+18 −14
Original line number Diff line number Diff line
@@ -2740,34 +2740,38 @@ i915_gem_object_pwrite_gtt(struct drm_i915_gem_object *obj,
	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) &&
		ctx->ban_score >= CONTEXT_SCORE_BAN_THRESHOLD);
		score >= CONTEXT_SCORE_BAN_THRESHOLD);
}

static void i915_gem_context_mark_guilty(struct i915_gem_context *ctx)
{
	ctx->guilty_count++;
	ctx->ban_score += CONTEXT_SCORE_GUILTY;
	if (ban_context(ctx))
		i915_gem_context_set_banned(ctx);
	unsigned int score;
	bool banned;

	DRM_DEBUG_DRIVER("context %s marked guilty (score %d) banned? %s\n",
			 ctx->name, ctx->ban_score,
			 yesno(i915_gem_context_is_banned(ctx)));
	atomic_inc(&ctx->guilty_count);

	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;

	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",
			 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)
{
	ctx->active_count++;
	atomic_inc(&ctx->active_count);
}

struct drm_i915_gem_request *
+3 −3
Original line number Diff line number Diff line
@@ -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)
{
	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,
@@ -1179,8 +1179,8 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev,
	else
		args->reset_count = 0;

	args->batch_active = READ_ONCE(ctx->guilty_count);
	args->batch_pending = READ_ONCE(ctx->active_count);
	args->batch_active = atomic_read(&ctx->guilty_count);
	args->batch_pending = atomic_read(&ctx->active_count);

	ret = 0;
out:
+3 −3
Original line number Diff line number Diff line
@@ -191,17 +191,17 @@ struct i915_gem_context {
	u32 desc_template;

	/** 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
	 * hang, but did not cause it.
	 */
	unsigned int active_count;
	atomic_t active_count;

#define CONTEXT_SCORE_GUILTY		10
#define CONTEXT_SCORE_BAN_THRESHOLD	40
	/** 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 */
	u8 remap_slice;
+1 −2
Original line number Diff line number Diff line
@@ -374,8 +374,7 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request)
	i915_gem_request_remove_from_client(request);

	/* Retirement decays the ban score as it is a sign of ctx progress */
	if (request->ctx->ban_score > 0)
		request->ctx->ban_score--;
	atomic_dec_if_positive(&request->ctx->ban_score);

	/* The backing object for the context is done after switching to the
	 * *next* context. Therefore we cannot retire the previous context until
Loading