]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
drm/i915: fix tiling limits for i915 class hw v2
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Sat, 17 Apr 2010 13:12:03 +0000 (15:12 +0200)
committerEric Anholt <eric@anholt.net>
Mon, 19 Apr 2010 00:58:24 +0000 (17:58 -0700)
Current code is definitely crap: Largest pitch allowed spills into
the TILING_Y bit of the fence registers ... :(

I've rewritten the limits check under the assumption that 3rd gen hw
has a 3d pitch limit of 8kb (like 2nd gen). This is supported by an
otherwise totally misleading XXX comment.

This bug mostly resulted in tiling-corrupted pixmaps because the kernel
allowed too wide buffers to be tiled. Bug brought to the light by the
xf86-video-intel 2.11 release because that unconditionally enabled
tiling for pixmaps, relying on the kernel to check things. Tiling for
the framebuffer was not affected because the ddx does some additional
checks there ensure the buffer is within hw-limits.

v2: Instead of computing the value that would be written into the
hw fence registers and then checking the limits simply check whether
the stride is above the 8kb limit. To better document the hw, add
some WARN_ONs in i915_write_fence_reg like I've done for the i830
case (using the right limits).

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=27449
Tested-by: Alexander Lam <lambchop468@gmail.com>
Cc: stable@kernel.org
Signed-off-by: Eric Anholt <eric@anholt.net>
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_tiling.c
drivers/gpu/drm/i915/i915_reg.h

index 80871c62a57102770867ad273cee16cafc27ff5c..8a8771711ceffa703c465794c856e1db20cfba2c 100644 (file)
@@ -2362,6 +2362,12 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
        pitch_val = obj_priv->stride / tile_width;
        pitch_val = ffs(pitch_val) - 1;
 
+       if (obj_priv->tiling_mode == I915_TILING_Y &&
+           HAS_128_BYTE_Y_TILING(dev))
+               WARN_ON(pitch_val > I830_FENCE_MAX_PITCH_VAL);
+       else
+               WARN_ON(pitch_val > I915_FENCE_MAX_PITCH_VAL);
+
        val = obj_priv->gtt_offset;
        if (obj_priv->tiling_mode == I915_TILING_Y)
                val |= 1 << I830_FENCE_TILING_Y_SHIFT;
index 449157f716106c96c016bc39aaded10fa1fe37ca..4bdccefcf2cf7b5f9733b00971f75dfa26b10505 100644 (file)
@@ -202,21 +202,17 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
                 * reg, so dont bother to check the size */
                if (stride / 128 > I965_FENCE_MAX_PITCH_VAL)
                        return false;
-       } else if (IS_I9XX(dev)) {
-               uint32_t pitch_val = ffs(stride / tile_width) - 1;
-
-               /* XXX: For Y tiling, FENCE_MAX_PITCH_VAL is actually 6 (8KB)
-                * instead of 4 (2KB) on 945s.
-                */
-               if (pitch_val > I915_FENCE_MAX_PITCH_VAL ||
-                   size > (I830_FENCE_MAX_SIZE_VAL << 20))
+       } else if (IS_GEN3(dev) || IS_GEN2(dev)) {
+               if (stride > 8192)
                        return false;
-       } else {
-               uint32_t pitch_val = ffs(stride / tile_width) - 1;
 
-               if (pitch_val > I830_FENCE_MAX_PITCH_VAL ||
-                   size > (I830_FENCE_MAX_SIZE_VAL << 19))
-                       return false;
+               if (IS_GEN3(dev)) {
+                       if (size > I830_FENCE_MAX_SIZE_VAL << 20)
+                               return false;
+               } else {
+                       if (size > I830_FENCE_MAX_SIZE_VAL << 19)
+                               return false;
+               }
        }
 
        /* 965+ just needs multiples of tile width */
index cbbf59f56dfa93c23008e4c98d0b38353a65a6a7..773c1adb2541075b64d85a91a68e37c96d2fd17f 100644 (file)
 #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   I915_FENCE_MAX_PITCH_VAL     0x10
+#define   I915_FENCE_MAX_PITCH_VAL     4
 #define   I830_FENCE_MAX_PITCH_VAL     6
 #define   I830_FENCE_MAX_SIZE_VAL      (1<<8)