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

Commit 8d7773a3 authored by Daniel Vetter's avatar Daniel Vetter Committed by Eric Anholt
Browse files

drm/i915: fix up tiling/fence reg setup on i8xx class hw

This fixes all the tiling problems with the 2d ddx. glxgears still doesn't work.
Changes:

- fix a copy&paste error in i8xx fence reg setup. It resulted in an at most a
  512KB offset of the fence reg window, so was only visible sometimes.
- add tests for stride and object size constrains (also for i915 and 1965 class
  hw). Userspace seems to have an of-by-one bug there, which changes the fence
  size by at most 512KB due to an overflow.
- because i8xx hw is quite old (and therefore not as well-tested) I left 2 debug
  WARN_ONs in the i8xx fence reg setup code to hopefully catch any further
  overflows in the bit-fields. Lastly there's one small change to make the
  alignment checks more consistent.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=20289


Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
parent c09bca78
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -1990,20 +1990,23 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
	int regnum = obj_priv->fence_reg;
	uint32_t val;
	uint32_t pitch_val;
	uint32_t fence_size_bits;

	if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
	if ((obj_priv->gtt_offset & ~I830_FENCE_START_MASK) ||
	    (obj_priv->gtt_offset & (obj->size - 1))) {
		WARN(1, "%s: object 0x%08x not 1M or size aligned\n",
		WARN(1, "%s: object 0x%08x not 512K or size aligned\n",
		     __func__, obj_priv->gtt_offset);
		return;
	}

	pitch_val = (obj_priv->stride / 128) - 1;

	WARN_ON(pitch_val & ~0x0000000f);
	val = obj_priv->gtt_offset;
	if (obj_priv->tiling_mode == I915_TILING_Y)
		val |= 1 << I830_FENCE_TILING_Y_SHIFT;
	val |= I830_FENCE_SIZE_BITS(obj->size);
	fence_size_bits = I830_FENCE_SIZE_BITS(obj->size);
	WARN_ON(fence_size_bits & ~0x00000f00);
	val |= fence_size_bits;
	val |= pitch_val << I830_FENCE_PITCH_SHIFT;
	val |= I830_FENCE_REG_VALID;

@@ -2194,7 +2197,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
		return -EBUSY;
	if (alignment == 0)
		alignment = i915_gem_get_gtt_alignment(obj);
	if (alignment & (PAGE_SIZE - 1)) {
	if (alignment & (i915_gem_get_gtt_alignment(obj) - 1)) {
		DRM_ERROR("Invalid object alignment requested %u\n", alignment);
		return -EINVAL;
	}
+16 −0
Original line number Diff line number Diff line
@@ -216,6 +216,22 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
	else
		tile_width = 512;

	/* check maximum stride & object size */
	if (IS_I965G(dev)) {
		/* i965 stores the end address of the gtt mapping in the fence
		 * reg, so dont bother to check the size */
		if (stride / 128 > I965_FENCE_MAX_PITCH_VAL)
			return false;
	} else if (IS_I9XX(dev)) {
		if (stride / tile_width > I830_FENCE_MAX_PITCH_VAL ||
		    size > (I830_FENCE_MAX_SIZE_VAL << 20))
			return false;
	} else {
		if (stride / 128 > I830_FENCE_MAX_PITCH_VAL ||
		    size > (I830_FENCE_MAX_SIZE_VAL << 19))
			return false;
	}

	/* 965+ just needs multiples of tile width */
	if (IS_I965G(dev)) {
		if (stride & (tile_width - 1))
+3 −0
Original line number Diff line number Diff line
@@ -190,6 +190,8 @@
#define   I830_FENCE_SIZE_BITS(size)	((ffs((size) >> 19) - 1) << 8)
#define   I830_FENCE_PITCH_SHIFT	4
#define   I830_FENCE_REG_VALID		(1<<0)
#define   I830_FENCE_MAX_PITCH_VAL	0x10
#define   I830_FENCE_MAX_SIZE_VAL	(1<<8)

#define   I915_FENCE_START_MASK		0x0ff00000
#define   I915_FENCE_SIZE_BITS(size)	((ffs((size) >> 20) - 1) << 8)
@@ -198,6 +200,7 @@
#define   I965_FENCE_PITCH_SHIFT	2
#define   I965_FENCE_TILING_Y_SHIFT	1
#define   I965_FENCE_REG_VALID		(1<<0)
#define   I965_FENCE_MAX_PITCH_VAL	0x0400

/*
 * Instruction and interrupt control regs