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

Commit 8325e6e3 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-intel-fixes-2018-06-21' of...

Merge tag 'drm-intel-fixes-2018-06-21' of git://anongit.freedesktop.org/drm/drm-intel

 into drm-fixes

drm/i915 fixes for v4.18-rc2:
- Mostly cc: stable display fixes, including a DBLSCAN regression fix
- GEM fixes for this merge window

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

Link: https://patchwork.freedesktop.org/patch/msgid/87d0wkuypy.fsf@intel.com
parents ae0c7306 7a3727f3
Loading
Loading
Loading
Loading
+14 −7
Original line number Diff line number Diff line
@@ -340,14 +340,21 @@ struct drm_i915_file_private {

	unsigned int bsd_engine;

/* Client can have a maximum of 3 contexts banned before
 * it is denied of creating new contexts. As one context
 * ban needs 4 consecutive hangs, and more if there is
 * progress in between, this is a last resort stop gap measure
 * to limit the badly behaving clients access to gpu.
 */
#define I915_MAX_CLIENT_CONTEXT_BANS 3
	atomic_t context_bans;
/*
 * Every context ban increments per client ban score. Also
 * hangs in short succession increments ban score. If ban threshold
 * is reached, client is considered banned and submitting more work
 * will fail. This is a stop gap measure to limit the badly behaving
 * clients access to gpu. Note that unbannable contexts never increment
 * the client ban score.
 */
#define I915_CLIENT_SCORE_HANG_FAST	1
#define   I915_CLIENT_FAST_HANG_JIFFIES (60 * HZ)
#define I915_CLIENT_SCORE_CONTEXT_BAN   3
#define I915_CLIENT_SCORE_BANNED	9
	/** ban_score: Accumulated score of all ctx bans and fast hangs. */
	atomic_t ban_score;
	unsigned long hang_timestamp;
};

/* Interface history:
+40 −17
Original line number Diff line number Diff line
@@ -2933,32 +2933,54 @@ i915_gem_object_pwrite_gtt(struct drm_i915_gem_object *obj,
	return 0;
}

static void i915_gem_context_mark_guilty(struct i915_gem_context *ctx)
static void i915_gem_client_mark_guilty(struct drm_i915_file_private *file_priv,
					const struct i915_gem_context *ctx)
{
	bool banned;
	unsigned int score;
	unsigned long prev_hang;

	atomic_inc(&ctx->guilty_count);
	if (i915_gem_context_is_banned(ctx))
		score = I915_CLIENT_SCORE_CONTEXT_BAN;
	else
		score = 0;

	prev_hang = xchg(&file_priv->hang_timestamp, jiffies);
	if (time_before(jiffies, prev_hang + I915_CLIENT_FAST_HANG_JIFFIES))
		score += I915_CLIENT_SCORE_HANG_FAST;

	if (score) {
		atomic_add(score, &file_priv->ban_score);

		DRM_DEBUG_DRIVER("client %s: gained %u ban score, now %u\n",
				 ctx->name, score,
				 atomic_read(&file_priv->ban_score));
	}
}

	banned = false;
	if (i915_gem_context_is_bannable(ctx)) {
static void i915_gem_context_mark_guilty(struct i915_gem_context *ctx)
{
	unsigned int score;
	bool banned, bannable;

	atomic_inc(&ctx->guilty_count);

		score = atomic_add_return(CONTEXT_SCORE_GUILTY,
					  &ctx->ban_score);
	bannable = i915_gem_context_is_bannable(ctx);
	score = atomic_add_return(CONTEXT_SCORE_GUILTY, &ctx->ban_score);
	banned = score >= CONTEXT_SCORE_BAN_THRESHOLD;

		DRM_DEBUG_DRIVER("context %s marked guilty (score %d) banned? %s\n",
				 ctx->name, score, yesno(banned));
	}
	if (!banned)
	DRM_DEBUG_DRIVER("context %s: guilty %d, score %u, ban %s\n",
			 ctx->name, atomic_read(&ctx->guilty_count),
			 score, yesno(banned && bannable));

	/* Cool contexts don't accumulate client ban score */
	if (!bannable)
		return;

	if (banned)
		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, atomic_read(&ctx->file_priv->context_bans));
	}

	if (!IS_ERR_OR_NULL(ctx->file_priv))
		i915_gem_client_mark_guilty(ctx->file_priv, ctx);
}

static void i915_gem_context_mark_innocent(struct i915_gem_context *ctx)
@@ -5736,6 +5758,7 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file)
	INIT_LIST_HEAD(&file_priv->mm.request_list);

	file_priv->bsd_engine = -1;
	file_priv->hang_timestamp = jiffies;

	ret = i915_gem_context_open(i915, file);
	if (ret)
+1 −1
Original line number Diff line number Diff line
@@ -652,7 +652,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 atomic_read(&file_priv->context_bans) > I915_MAX_CLIENT_CONTEXT_BANS;
	return atomic_read(&file_priv->ban_score) >= I915_CLIENT_SCORE_BANNED;
}

int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
+27 −22
Original line number Diff line number Diff line
@@ -489,7 +489,9 @@ eb_validate_vma(struct i915_execbuffer *eb,
}

static int
eb_add_vma(struct i915_execbuffer *eb, unsigned int i, struct i915_vma *vma)
eb_add_vma(struct i915_execbuffer *eb,
	   unsigned int i, unsigned batch_idx,
	   struct i915_vma *vma)
{
	struct drm_i915_gem_exec_object2 *entry = &eb->exec[i];
	int err;
@@ -522,6 +524,24 @@ eb_add_vma(struct i915_execbuffer *eb, unsigned int i, struct i915_vma *vma)
	eb->flags[i] = entry->flags;
	vma->exec_flags = &eb->flags[i];

	/*
	 * SNA is doing fancy tricks with compressing batch buffers, which leads
	 * to negative relocation deltas. Usually that works out ok since the
	 * relocate address is still positive, except when the batch is placed
	 * very low in the GTT. Ensure this doesn't happen.
	 *
	 * Note that actual hangs have only been observed on gen7, but for
	 * paranoia do it everywhere.
	 */
	if (i == batch_idx) {
		if (!(eb->flags[i] & EXEC_OBJECT_PINNED))
			eb->flags[i] |= __EXEC_OBJECT_NEEDS_BIAS;
		if (eb->reloc_cache.has_fence)
			eb->flags[i] |= EXEC_OBJECT_NEEDS_FENCE;

		eb->batch = vma;
	}

	err = 0;
	if (eb_pin_vma(eb, entry, vma)) {
		if (entry->offset != vma->node.start) {
@@ -716,7 +736,7 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
{
	struct radix_tree_root *handles_vma = &eb->ctx->handles_vma;
	struct drm_i915_gem_object *obj;
	unsigned int i;
	unsigned int i, batch;
	int err;

	if (unlikely(i915_gem_context_is_closed(eb->ctx)))
@@ -728,6 +748,8 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
	INIT_LIST_HEAD(&eb->relocs);
	INIT_LIST_HEAD(&eb->unbound);

	batch = eb_batch_index(eb);

	for (i = 0; i < eb->buffer_count; i++) {
		u32 handle = eb->exec[i].handle;
		struct i915_lut_handle *lut;
@@ -770,33 +792,16 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
		lut->handle = handle;

add_vma:
		err = eb_add_vma(eb, i, vma);
		err = eb_add_vma(eb, i, batch, vma);
		if (unlikely(err))
			goto err_vma;

		GEM_BUG_ON(vma != eb->vma[i]);
		GEM_BUG_ON(vma->exec_flags != &eb->flags[i]);
		GEM_BUG_ON(drm_mm_node_allocated(&vma->node) &&
			   eb_vma_misplaced(&eb->exec[i], vma, eb->flags[i]));
	}

	/* take note of the batch buffer before we might reorder the lists */
	i = eb_batch_index(eb);
	eb->batch = eb->vma[i];
	GEM_BUG_ON(eb->batch->exec_flags != &eb->flags[i]);

	/*
	 * SNA is doing fancy tricks with compressing batch buffers, which leads
	 * to negative relocation deltas. Usually that works out ok since the
	 * relocate address is still positive, except when the batch is placed
	 * very low in the GTT. Ensure this doesn't happen.
	 *
	 * Note that actual hangs have only been observed on gen7, but for
	 * paranoia do it everywhere.
	 */
	if (!(eb->flags[i] & EXEC_OBJECT_PINNED))
		eb->flags[i] |= __EXEC_OBJECT_NEEDS_BIAS;
	if (eb->reloc_cache.has_fence)
		eb->flags[i] |= EXEC_OBJECT_NEEDS_FENCE;

	eb->args->flags |= __EXEC_VALIDATED;
	return eb_reserve(eb);

+10 −2
Original line number Diff line number Diff line
@@ -1893,9 +1893,17 @@ static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv,

		/*
		 * Clear the PIPE*STAT regs before the IIR
		 *
		 * Toggle the enable bits to make sure we get an
		 * edge in the ISR pipe event bit if we don't clear
		 * all the enabled status bits. Otherwise the edge
		 * triggered IIR on i965/g4x wouldn't notice that
		 * an interrupt is still pending.
		 */
		if (pipe_stats[pipe])
			I915_WRITE(reg, enable_mask | pipe_stats[pipe]);
		if (pipe_stats[pipe]) {
			I915_WRITE(reg, pipe_stats[pipe]);
			I915_WRITE(reg, enable_mask);
		}
	}
	spin_unlock(&dev_priv->irq_lock);
}
Loading