intel: Handle resetting of input params after EINTR during SET_TILING
authorChris Wilson <chris@chris-wilson.co.uk>
Wed, 10 Feb 2010 09:45:13 +0000 (09:45 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Wed, 10 Feb 2010 09:52:36 +0000 (09:52 +0000)
The SET_TILING is pernicious in that it overwrites the input arguments
following an error in order to report the current tiling state of the
buffer. This caught us by surprise as we then fed those arguments back
into to the ioctl unmodified following an EINTR and so the kernel then
reported success for the no-op. We interpreted this success as meaning
that the tiling on the buffer had changed so updated our state and
started using the buffer incorrectly in the new tiled/untiled manner.
This lead to all sorts of random corruption and GPU hangs, even though
the batch buffers would look sane (when the GPU had not wandered off
into forbidden territory).

References:

  Bug 25475 - [i915] Xorg crash / Execbuf while wedged
  http://bugs.freedesktop.org/show_bug.cgi?id=25475

  Bug 25554 - i830_uxa_prepare_access: gtt bo map failed: Input/output error
  http://bugs.freedesktop.org/show_bug.cgi?id=25554

(And probably every other weird bug in the last few months.)

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
intel/intel_bufmgr_gem.c

index 66d12bc..4e61cef 100644 (file)
@@ -1423,18 +1423,15 @@ drm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
 
        memset(&set_tiling, 0, sizeof(set_tiling));
        set_tiling.handle = bo_gem->gem_handle;
 
        memset(&set_tiling, 0, sizeof(set_tiling));
        set_tiling.handle = bo_gem->gem_handle;
-       set_tiling.tiling_mode = *tiling_mode;
-       set_tiling.stride = stride;
 
        do {
 
        do {
+               set_tiling.tiling_mode = *tiling_mode;
+               set_tiling.stride = stride;
+
                ret = ioctl(bufmgr_gem->fd,
                            DRM_IOCTL_I915_GEM_SET_TILING,
                            &set_tiling);
        } while (ret == -1 && errno == EINTR);
                ret = ioctl(bufmgr_gem->fd,
                            DRM_IOCTL_I915_GEM_SET_TILING,
                            &set_tiling);
        } while (ret == -1 && errno == EINTR);
-       if (ret != 0) {
-               *tiling_mode = bo_gem->tiling_mode;
-               return -errno;
-       }
        bo_gem->tiling_mode = set_tiling.tiling_mode;
        bo_gem->swizzle_mode = set_tiling.swizzle_mode;
 
        bo_gem->tiling_mode = set_tiling.tiling_mode;
        bo_gem->swizzle_mode = set_tiling.swizzle_mode;
 
@@ -1445,7 +1442,7 @@ drm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
        drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem);
 
        *tiling_mode = bo_gem->tiling_mode;
        drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem);
 
        *tiling_mode = bo_gem->tiling_mode;
-       return 0;
+       return ret == 0 ? 0 : -errno;
 }
 
 static int
 }
 
 static int