aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2011-02-22 12:25:49 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2011-02-23 19:33:49 -0500
commitc2e0eb167070a6e9dcb49c84c13c79a30d672431 (patch)
tree3adb50528eb95cb0c7df47b0231f1a3b2ee60b5e
parent011b9910bdaf2e52c48c012490ab444fceea1959 (diff)
drm/i915: fix corruptions on i8xx due to relaxed fencing
It looks like gen2 has a peculiar interleaved 2-row inter-tile layout. Probably inherited from i81x which had 2kb tiles (which naturally fit an even-number-of-tile-rows scheme to fit onto 4kb pages). There is no other mention of this in any docs (also not in the Intel internal documention according to Chris Wilson). Problem manifests itself in corruptions in the second half of the last tile row (if the bo has an odd number of tiles). Which can only happen with relaxed tiling (introduced in a00b10c360b35d6431a9). So reject set_tiling calls that don't satisfy this constrain to prevent broken userspace from causing havoc. While at it, also check the size for newer chipsets. LKML: https://lkml.org/lkml/2011/2/19/5 Reported-by: Indan Zupancic <indan@nul.nu> Tested-by: Indan Zupancic <indan@nul.nu> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index 22a32b9932c5..79a04fde69b5 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -184,7 +184,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
184static bool 184static bool
185i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) 185i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
186{ 186{
187 int tile_width; 187 int tile_width, tile_height;
188 188
189 /* Linear is always fine */ 189 /* Linear is always fine */
190 if (tiling_mode == I915_TILING_NONE) 190 if (tiling_mode == I915_TILING_NONE)
@@ -215,6 +215,20 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
215 } 215 }
216 } 216 }
217 217
218 if (IS_GEN2(dev) ||
219 (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)))
220 tile_height = 32;
221 else
222 tile_height = 8;
223 /* i8xx is strange: It has 2 interleaved rows of tiles, so needs an even
224 * number of tile rows. */
225 if (IS_GEN2(dev))
226 tile_height *= 2;
227
228 /* Size needs to be aligned to a full tile row */
229 if (size & (tile_height * stride - 1))
230 return false;
231
218 /* 965+ just needs multiples of tile width */ 232 /* 965+ just needs multiples of tile width */
219 if (INTEL_INFO(dev)->gen >= 4) { 233 if (INTEL_INFO(dev)->gen >= 4) {
220 if (stride & (tile_width - 1)) 234 if (stride & (tile_width - 1))