drm/i915: fall through pwrite_gtt_slow to the shmem slow path
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 14 Dec 2011 12:57:30 +0000 (13:57 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 30 Jan 2012 22:34:07 +0000 (23:34 +0100)
The gtt_pwrite slowpath grabs the userspace memory with
get_user_pages. This will not work for non-page backed memory, like a
gtt mmapped gem object. Hence fall throuh to the shmem paths if we hit
-EFAULT in the gtt paths.

Now the shmem paths have exactly the same problem, but this way we
only need to rearrange the code in one write path.

v2: v1 accidentaly falls back to shmem pwrite for phys objects. Fixed.

v3: Make the codeflow around phys_pwrite cleara as suggested by Chris
Wilson.

Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_gem.c

index df23c62734135705947f8aaa00147cdd0d0bd7ae..7bb32ecc13c5fa60b0f8d3213ee945a6b302badf 100644 (file)
@@ -996,10 +996,13 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
         * pread/pwrite currently are reading and writing from the CPU
         * perspective, requiring manual detiling by the client.
         */
-       if (obj->phys_obj)
+       if (obj->phys_obj) {
                ret = i915_gem_phys_pwrite(dev, obj, args, file);
-       else if (obj->gtt_space &&
-                obj->base.write_domain != I915_GEM_DOMAIN_CPU) {
+               goto out;
+       }
+
+       if (obj->gtt_space &&
+           obj->base.write_domain != I915_GEM_DOMAIN_CPU) {
                ret = i915_gem_object_pin(obj, 0, true);
                if (ret)
                        goto out;
@@ -1018,18 +1021,24 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
 
 out_unpin:
                i915_gem_object_unpin(obj);
-       } else {
-               ret = i915_gem_object_set_to_cpu_domain(obj, 1);
-               if (ret)
-                       goto out;
 
-               ret = -EFAULT;
-               if (!i915_gem_object_needs_bit17_swizzle(obj))
-                       ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file);
-               if (ret == -EFAULT)
-                       ret = i915_gem_shmem_pwrite_slow(dev, obj, args, file);
+               if (ret != -EFAULT)
+                       goto out;
+               /* Fall through to the shmfs paths because the gtt paths might
+                * fail with non-page-backed user pointers (e.g. gtt mappings
+                * when moving data between textures). */
        }
 
+       ret = i915_gem_object_set_to_cpu_domain(obj, 1);
+       if (ret)
+               goto out;
+
+       ret = -EFAULT;
+       if (!i915_gem_object_needs_bit17_swizzle(obj))
+               ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file);
+       if (ret == -EFAULT)
+               ret = i915_gem_shmem_pwrite_slow(dev, obj, args, file);
+
 out:
        drm_gem_object_unreference(&obj->base);
 unlock: