aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel@biene.ffwll.ch>2009-03-29 08:09:41 -0400
committerEric Anholt <eric@anholt.net>2009-04-01 14:06:47 -0400
commit8d7773a32d8aa723030712b0a500a4a402a21c85 (patch)
tree8b3e9e0449f9c85fa97fbd44c761713a3821858c
parentc09bca786ff941ed17c5f381c4eca5b106808c51 (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>
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c13
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c16
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h3
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