diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-10-14 14:47:43 +0200 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-10-19 10:19:37 +0200 |
commit | b5e4feb6615fe07150f05bb0e0ccc0ff9138b9ec (patch) | |
tree | 920be74c3946e1b882258a7d8c0af5266417fa66 /drivers/gpu | |
parent | drm/i915: Avoid taking the mutex for dropping the refcnt upon creation (diff) | |
download | linux-b5e4feb6615fe07150f05bb0e0ccc0ff9138b9ec.tar.xz linux-b5e4feb6615fe07150f05bb0e0ccc0ff9138b9ec.zip |
drm/i915: Attempt to prefault user pages for pread/pwrite
... in the hope that it makes the atomic fast paths more likely.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 33 |
1 files changed, 19 insertions, 14 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 942e4b351cdd..b44c09ab8928 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -265,19 +265,14 @@ fast_shmem_read(struct page **pages, char __user *data, int length) { - char __iomem *vaddr; int unwritten; + char *vaddr; vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0); - if (vaddr == NULL) - return -ENOMEM; unwritten = __copy_to_user_inatomic(data, vaddr + page_offset, length); kunmap_atomic(vaddr, KM_USER0); - if (unwritten) - return -EFAULT; - - return 0; + return unwritten ? -EFAULT : 0; } static int i915_gem_object_needs_bit17_swizzle(struct drm_gem_object *obj) @@ -602,6 +597,13 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, goto out; } + ret = fault_in_pages_writeable((char __user *)(uintptr_t)args->data_ptr, + args->size); + if (ret) { + ret = -EFAULT; + goto out; + } + if (i915_gem_object_needs_bit17_swizzle(obj)) { ret = i915_gem_shmem_pread_slow(dev, obj, args, file_priv); } else { @@ -668,18 +670,14 @@ fast_shmem_write(struct page **pages, char __user *data, int length) { - char __iomem *vaddr; - unsigned long unwritten; + int unwritten; + char *vaddr; vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0); - if (vaddr == NULL) - return -ENOMEM; unwritten = __copy_from_user_inatomic(vaddr + page_offset, data, length); kunmap_atomic(vaddr, KM_USER0); - if (unwritten) - return -EFAULT; - return 0; + return unwritten ? -EFAULT : 0; } /** @@ -1078,6 +1076,13 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, goto out; } + ret = fault_in_pages_readable((char __user *)(uintptr_t)args->data_ptr, + args->size); + if (ret) { + ret = -EFAULT; + goto out; + } + /* We can only do the GTT pwrite on untiled buffers, as otherwise * it would end up going through the fenced access, and we'll get * different detiling behavior between reading and writing. |