diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 75e3b841fffb..b253257c028e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -301,6 +301,7 @@ i915_gem_shmem_pread(struct drm_device *dev, | |||
301 | int obj_do_bit17_swizzling, page_do_bit17_swizzling; | 301 | int obj_do_bit17_swizzling, page_do_bit17_swizzling; |
302 | int hit_slowpath = 0; | 302 | int hit_slowpath = 0; |
303 | int needs_clflush = 0; | 303 | int needs_clflush = 0; |
304 | int release_page; | ||
304 | 305 | ||
305 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 306 | user_data = (char __user *) (uintptr_t) args->data_ptr; |
306 | remain = args->size; | 307 | remain = args->size; |
@@ -335,10 +336,16 @@ i915_gem_shmem_pread(struct drm_device *dev, | |||
335 | if ((shmem_page_offset + page_length) > PAGE_SIZE) | 336 | if ((shmem_page_offset + page_length) > PAGE_SIZE) |
336 | page_length = PAGE_SIZE - shmem_page_offset; | 337 | page_length = PAGE_SIZE - shmem_page_offset; |
337 | 338 | ||
338 | page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT); | 339 | if (obj->pages) { |
339 | if (IS_ERR(page)) { | 340 | page = obj->pages[offset >> PAGE_SHIFT]; |
340 | ret = PTR_ERR(page); | 341 | release_page = 0; |
341 | goto out; | 342 | } else { |
343 | page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT); | ||
344 | if (IS_ERR(page)) { | ||
345 | ret = PTR_ERR(page); | ||
346 | goto out; | ||
347 | } | ||
348 | release_page = 1; | ||
342 | } | 349 | } |
343 | 350 | ||
344 | page_do_bit17_swizzling = obj_do_bit17_swizzling && | 351 | page_do_bit17_swizzling = obj_do_bit17_swizzling && |
@@ -358,7 +365,7 @@ i915_gem_shmem_pread(struct drm_device *dev, | |||
358 | } | 365 | } |
359 | 366 | ||
360 | hit_slowpath = 1; | 367 | hit_slowpath = 1; |
361 | 368 | page_cache_get(page); | |
362 | mutex_unlock(&dev->struct_mutex); | 369 | mutex_unlock(&dev->struct_mutex); |
363 | 370 | ||
364 | vaddr = kmap(page); | 371 | vaddr = kmap(page); |
@@ -377,9 +384,11 @@ i915_gem_shmem_pread(struct drm_device *dev, | |||
377 | kunmap(page); | 384 | kunmap(page); |
378 | 385 | ||
379 | mutex_lock(&dev->struct_mutex); | 386 | mutex_lock(&dev->struct_mutex); |
387 | page_cache_release(page); | ||
380 | next_page: | 388 | next_page: |
381 | mark_page_accessed(page); | 389 | mark_page_accessed(page); |
382 | page_cache_release(page); | 390 | if (release_page) |
391 | page_cache_release(page); | ||
383 | 392 | ||
384 | if (ret) { | 393 | if (ret) { |
385 | ret = -EFAULT; | 394 | ret = -EFAULT; |
@@ -660,6 +669,7 @@ i915_gem_shmem_pwrite(struct drm_device *dev, | |||
660 | int shmem_page_offset, page_length, ret = 0; | 669 | int shmem_page_offset, page_length, ret = 0; |
661 | int obj_do_bit17_swizzling, page_do_bit17_swizzling; | 670 | int obj_do_bit17_swizzling, page_do_bit17_swizzling; |
662 | int hit_slowpath = 0; | 671 | int hit_slowpath = 0; |
672 | int release_page; | ||
663 | 673 | ||
664 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 674 | user_data = (char __user *) (uintptr_t) args->data_ptr; |
665 | remain = args->size; | 675 | remain = args->size; |
@@ -684,10 +694,16 @@ i915_gem_shmem_pwrite(struct drm_device *dev, | |||
684 | if ((shmem_page_offset + page_length) > PAGE_SIZE) | 694 | if ((shmem_page_offset + page_length) > PAGE_SIZE) |
685 | page_length = PAGE_SIZE - shmem_page_offset; | 695 | page_length = PAGE_SIZE - shmem_page_offset; |
686 | 696 | ||
687 | page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT); | 697 | if (obj->pages) { |
688 | if (IS_ERR(page)) { | 698 | page = obj->pages[offset >> PAGE_SHIFT]; |
689 | ret = PTR_ERR(page); | 699 | release_page = 0; |
690 | goto out; | 700 | } else { |
701 | page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT); | ||
702 | if (IS_ERR(page)) { | ||
703 | ret = PTR_ERR(page); | ||
704 | goto out; | ||
705 | } | ||
706 | release_page = 1; | ||
691 | } | 707 | } |
692 | 708 | ||
693 | page_do_bit17_swizzling = obj_do_bit17_swizzling && | 709 | page_do_bit17_swizzling = obj_do_bit17_swizzling && |
@@ -705,7 +721,7 @@ i915_gem_shmem_pwrite(struct drm_device *dev, | |||
705 | } | 721 | } |
706 | 722 | ||
707 | hit_slowpath = 1; | 723 | hit_slowpath = 1; |
708 | 724 | page_cache_get(page); | |
709 | mutex_unlock(&dev->struct_mutex); | 725 | mutex_unlock(&dev->struct_mutex); |
710 | 726 | ||
711 | vaddr = kmap(page); | 727 | vaddr = kmap(page); |
@@ -720,10 +736,12 @@ i915_gem_shmem_pwrite(struct drm_device *dev, | |||
720 | kunmap(page); | 736 | kunmap(page); |
721 | 737 | ||
722 | mutex_lock(&dev->struct_mutex); | 738 | mutex_lock(&dev->struct_mutex); |
739 | page_cache_release(page); | ||
723 | next_page: | 740 | next_page: |
724 | set_page_dirty(page); | 741 | set_page_dirty(page); |
725 | mark_page_accessed(page); | 742 | mark_page_accessed(page); |
726 | page_cache_release(page); | 743 | if (release_page) |
744 | page_cache_release(page); | ||
727 | 745 | ||
728 | if (ret) { | 746 | if (ret) { |
729 | ret = -EFAULT; | 747 | ret = -EFAULT; |