Commit f60d7f0c authored by Chris Wilson's avatar Chris Wilson Committed by Daniel Vetter

drm/i915: Pin backing pages for pread

By using the recently introduced pinning of pages, we can safely drop
the mutex in the knowledge that the pages are not going to disappear
beneath us, and so we can simplify the code for iterating over the pages.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarBen Widawsky <ben@bwidawsk.net>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 755d2218
...@@ -343,7 +343,7 @@ shmem_pread_fast(struct page *page, int shmem_page_offset, int page_length, ...@@ -343,7 +343,7 @@ shmem_pread_fast(struct page *page, int shmem_page_offset, int page_length,
page_length); page_length);
kunmap_atomic(vaddr); kunmap_atomic(vaddr);
return ret; return ret ? -EFAULT : 0;
} }
static void static void
...@@ -394,7 +394,7 @@ shmem_pread_slow(struct page *page, int shmem_page_offset, int page_length, ...@@ -394,7 +394,7 @@ shmem_pread_slow(struct page *page, int shmem_page_offset, int page_length,
page_length); page_length);
kunmap(page); kunmap(page);
return ret; return ret ? - EFAULT : 0;
} }
static int static int
...@@ -403,7 +403,6 @@ i915_gem_shmem_pread(struct drm_device *dev, ...@@ -403,7 +403,6 @@ i915_gem_shmem_pread(struct drm_device *dev,
struct drm_i915_gem_pread *args, struct drm_i915_gem_pread *args,
struct drm_file *file) struct drm_file *file)
{ {
struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
char __user *user_data; char __user *user_data;
ssize_t remain; ssize_t remain;
loff_t offset; loff_t offset;
...@@ -412,7 +411,6 @@ i915_gem_shmem_pread(struct drm_device *dev, ...@@ -412,7 +411,6 @@ i915_gem_shmem_pread(struct drm_device *dev,
int hit_slowpath = 0; int hit_slowpath = 0;
int prefaulted = 0; int prefaulted = 0;
int needs_clflush = 0; int needs_clflush = 0;
int release_page;
user_data = (char __user *) (uintptr_t) args->data_ptr; user_data = (char __user *) (uintptr_t) args->data_ptr;
remain = args->size; remain = args->size;
...@@ -433,6 +431,12 @@ i915_gem_shmem_pread(struct drm_device *dev, ...@@ -433,6 +431,12 @@ i915_gem_shmem_pread(struct drm_device *dev,
} }
} }
ret = i915_gem_object_get_pages(obj);
if (ret)
return ret;
i915_gem_object_pin_pages(obj);
offset = args->offset; offset = args->offset;
while (remain > 0) { while (remain > 0) {
...@@ -448,18 +452,7 @@ i915_gem_shmem_pread(struct drm_device *dev, ...@@ -448,18 +452,7 @@ i915_gem_shmem_pread(struct drm_device *dev,
if ((shmem_page_offset + page_length) > PAGE_SIZE) if ((shmem_page_offset + page_length) > PAGE_SIZE)
page_length = PAGE_SIZE - shmem_page_offset; page_length = PAGE_SIZE - shmem_page_offset;
if (obj->pages) { page = obj->pages[offset >> PAGE_SHIFT];
page = obj->pages[offset >> PAGE_SHIFT];
release_page = 0;
} else {
page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);
if (IS_ERR(page)) {
ret = PTR_ERR(page);
goto out;
}
release_page = 1;
}
page_do_bit17_swizzling = obj_do_bit17_swizzling && page_do_bit17_swizzling = obj_do_bit17_swizzling &&
(page_to_phys(page) & (1 << 17)) != 0; (page_to_phys(page) & (1 << 17)) != 0;
...@@ -470,7 +463,6 @@ i915_gem_shmem_pread(struct drm_device *dev, ...@@ -470,7 +463,6 @@ i915_gem_shmem_pread(struct drm_device *dev,
goto next_page; goto next_page;
hit_slowpath = 1; hit_slowpath = 1;
page_cache_get(page);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
if (!prefaulted) { if (!prefaulted) {
...@@ -488,16 +480,12 @@ i915_gem_shmem_pread(struct drm_device *dev, ...@@ -488,16 +480,12 @@ i915_gem_shmem_pread(struct drm_device *dev,
needs_clflush); needs_clflush);
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
page_cache_release(page);
next_page: next_page:
mark_page_accessed(page); mark_page_accessed(page);
if (release_page)
page_cache_release(page);
if (ret) { if (ret)
ret = -EFAULT;
goto out; goto out;
}
remain -= page_length; remain -= page_length;
user_data += page_length; user_data += page_length;
...@@ -505,6 +493,8 @@ i915_gem_shmem_pread(struct drm_device *dev, ...@@ -505,6 +493,8 @@ i915_gem_shmem_pread(struct drm_device *dev,
} }
out: out:
i915_gem_object_unpin_pages(obj);
if (hit_slowpath) { if (hit_slowpath) {
/* Fixup: Kill any reinstated backing storage pages */ /* Fixup: Kill any reinstated backing storage pages */
if (obj->madv == __I915_MADV_PURGED) if (obj->madv == __I915_MADV_PURGED)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment