diff options
author | Daniel Vetter <daniel@biene.ffwll.ch> | 2009-03-29 08:09:41 -0400 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2009-04-01 14:06:47 -0400 |
commit | 8d7773a32d8aa723030712b0a500a4a402a21c85 (patch) | |
tree | 8b3e9e0449f9c85fa97fbd44c761713a3821858c /drivers/gpu | |
parent | c09bca786ff941ed17c5f381c4eca5b106808c51 (diff) |
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: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_tiling.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 3 |
3 files changed, 27 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e0389ad1477d..0abccb761121 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -1990,20 +1990,23 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
1990 | int regnum = obj_priv->fence_reg; | 1990 | int regnum = obj_priv->fence_reg; |
1991 | uint32_t val; | 1991 | uint32_t val; |
1992 | uint32_t pitch_val; | 1992 | uint32_t pitch_val; |
1993 | uint32_t fence_size_bits; | ||
1993 | 1994 | ||
1994 | if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || | 1995 | if ((obj_priv->gtt_offset & ~I830_FENCE_START_MASK) || |
1995 | (obj_priv->gtt_offset & (obj->size - 1))) { | 1996 | (obj_priv->gtt_offset & (obj->size - 1))) { |
1996 | WARN(1, "%s: object 0x%08x not 1M or size aligned\n", | 1997 | WARN(1, "%s: object 0x%08x not 512K or size aligned\n", |
1997 | __func__, obj_priv->gtt_offset); | 1998 | __func__, obj_priv->gtt_offset); |
1998 | return; | 1999 | return; |
1999 | } | 2000 | } |
2000 | 2001 | ||
2001 | pitch_val = (obj_priv->stride / 128) - 1; | 2002 | pitch_val = (obj_priv->stride / 128) - 1; |
2002 | 2003 | WARN_ON(pitch_val & ~0x0000000f); | |
2003 | val = obj_priv->gtt_offset; | 2004 | val = obj_priv->gtt_offset; |
2004 | if (obj_priv->tiling_mode == I915_TILING_Y) | 2005 | if (obj_priv->tiling_mode == I915_TILING_Y) |
2005 | val |= 1 << I830_FENCE_TILING_Y_SHIFT; | 2006 | val |= 1 << I830_FENCE_TILING_Y_SHIFT; |
2006 | val |= I830_FENCE_SIZE_BITS(obj->size); | 2007 | fence_size_bits = I830_FENCE_SIZE_BITS(obj->size); |
2008 | WARN_ON(fence_size_bits & ~0x00000f00); | ||
2009 | val |= fence_size_bits; | ||
2007 | val |= pitch_val << I830_FENCE_PITCH_SHIFT; | 2010 | val |= pitch_val << I830_FENCE_PITCH_SHIFT; |
2008 | val |= I830_FENCE_REG_VALID; | 2011 | val |= I830_FENCE_REG_VALID; |
2009 | 2012 | ||
@@ -2194,7 +2197,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
2194 | return -EBUSY; | 2197 | return -EBUSY; |
2195 | if (alignment == 0) | 2198 | if (alignment == 0) |
2196 | alignment = i915_gem_get_gtt_alignment(obj); | 2199 | alignment = i915_gem_get_gtt_alignment(obj); |
2197 | if (alignment & (PAGE_SIZE - 1)) { | 2200 | if (alignment & (i915_gem_get_gtt_alignment(obj) - 1)) { |
2198 | DRM_ERROR("Invalid object alignment requested %u\n", alignment); | 2201 | DRM_ERROR("Invalid object alignment requested %u\n", alignment); |
2199 | return -EINVAL; | 2202 | return -EINVAL; |
2200 | } | 2203 | } |
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 4cce1aef438e..6be3f927c86a 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c | |||
@@ -216,6 +216,22 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) | |||
216 | else | 216 | else |
217 | tile_width = 512; | 217 | tile_width = 512; |
218 | 218 | ||
219 | /* check maximum stride & object size */ | ||
220 | if (IS_I965G(dev)) { | ||
221 | /* i965 stores the end address of the gtt mapping in the fence | ||
222 | * reg, so dont bother to check the size */ | ||
223 | if (stride / 128 > I965_FENCE_MAX_PITCH_VAL) | ||
224 | return false; | ||
225 | } else if (IS_I9XX(dev)) { | ||
226 | if (stride / tile_width > I830_FENCE_MAX_PITCH_VAL || | ||
227 | size > (I830_FENCE_MAX_SIZE_VAL << 20)) | ||
228 | return false; | ||
229 | } else { | ||
230 | if (stride / 128 > I830_FENCE_MAX_PITCH_VAL || | ||
231 | size > (I830_FENCE_MAX_SIZE_VAL << 19)) | ||
232 | return false; | ||
233 | } | ||
234 | |||
219 | /* 965+ just needs multiples of tile width */ | 235 | /* 965+ just needs multiples of tile width */ |
220 | if (IS_I965G(dev)) { | 236 | if (IS_I965G(dev)) { |
221 | if (stride & (tile_width - 1)) | 237 | if (stride & (tile_width - 1)) |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 377cc588f5e9..83357b09e546 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -190,6 +190,8 @@ | |||
190 | #define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8) | 190 | #define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8) |
191 | #define I830_FENCE_PITCH_SHIFT 4 | 191 | #define I830_FENCE_PITCH_SHIFT 4 |
192 | #define I830_FENCE_REG_VALID (1<<0) | 192 | #define I830_FENCE_REG_VALID (1<<0) |
193 | #define I830_FENCE_MAX_PITCH_VAL 0x10 | ||
194 | #define I830_FENCE_MAX_SIZE_VAL (1<<8) | ||
193 | 195 | ||
194 | #define I915_FENCE_START_MASK 0x0ff00000 | 196 | #define I915_FENCE_START_MASK 0x0ff00000 |
195 | #define I915_FENCE_SIZE_BITS(size) ((ffs((size) >> 20) - 1) << 8) | 197 | #define I915_FENCE_SIZE_BITS(size) ((ffs((size) >> 20) - 1) << 8) |
@@ -198,6 +200,7 @@ | |||
198 | #define I965_FENCE_PITCH_SHIFT 2 | 200 | #define I965_FENCE_PITCH_SHIFT 2 |
199 | #define I965_FENCE_TILING_Y_SHIFT 1 | 201 | #define I965_FENCE_TILING_Y_SHIFT 1 |
200 | #define I965_FENCE_REG_VALID (1<<0) | 202 | #define I965_FENCE_REG_VALID (1<<0) |
203 | #define I965_FENCE_MAX_PITCH_VAL 0x0400 | ||
201 | 204 | ||
202 | /* | 205 | /* |
203 | * Instruction and interrupt control regs | 206 | * Instruction and interrupt control regs |