aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-10-14 10:03:58 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2010-10-19 04:19:47 -0400
commitfbd5a26d500c7cd8943cc5f37ccc7e49cf386053 (patch)
tree28d8aa6e9d9818589f2abee0ca1f798c3cd63255
parentb5e4feb6615fe07150f05bb0e0ccc0ff9138b9ec (diff)
drm/i915: Rearrange acquisition of mutex during pwrite
... to avoid reacquiring it to drop the object reference count on exit. Note we have to make sure we now drop (and reacquire) the lock around acquiring the mm semaphore on the slow paths. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c170
1 files changed, 65 insertions, 105 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index b44c09ab8928..1177ff577914 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -635,9 +635,7 @@ fast_user_write(struct io_mapping *mapping,
635 unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset, 635 unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset,
636 user_data, length); 636 user_data, length);
637 io_mapping_unmap_atomic(vaddr_atomic, KM_USER0); 637 io_mapping_unmap_atomic(vaddr_atomic, KM_USER0);
638 if (unwritten) 638 return unwritten;
639 return -EFAULT;
640 return 0;
641} 639}
642 640
643/* Here's the write path which can sleep for 641/* Here's the write path which can sleep for
@@ -670,14 +668,14 @@ fast_shmem_write(struct page **pages,
670 char __user *data, 668 char __user *data,
671 int length) 669 int length)
672{ 670{
673 int unwritten;
674 char *vaddr; 671 char *vaddr;
672 int ret;
675 673
676 vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0); 674 vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0);
677 unwritten = __copy_from_user_inatomic(vaddr + page_offset, data, length); 675 ret = __copy_from_user_inatomic(vaddr + page_offset, data, length);
678 kunmap_atomic(vaddr, KM_USER0); 676 kunmap_atomic(vaddr, KM_USER0);
679 677
680 return unwritten ? -EFAULT : 0; 678 return ret;
681} 679}
682 680
683/** 681/**
@@ -695,24 +693,10 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj,
695 loff_t offset, page_base; 693 loff_t offset, page_base;
696 char __user *user_data; 694 char __user *user_data;
697 int page_offset, page_length; 695 int page_offset, page_length;
698 int ret;
699 696
700 user_data = (char __user *) (uintptr_t) args->data_ptr; 697 user_data = (char __user *) (uintptr_t) args->data_ptr;
701 remain = args->size; 698 remain = args->size;
702 699
703 ret = i915_mutex_lock_interruptible(dev);
704 if (ret)
705 return ret;
706
707 ret = i915_gem_object_pin(obj, 0);
708 if (ret) {
709 mutex_unlock(&dev->struct_mutex);
710 return ret;
711 }
712 ret = i915_gem_object_set_to_gtt_domain(obj, 1);
713 if (ret)
714 goto fail;
715
716 obj_priv = to_intel_bo(obj); 700 obj_priv = to_intel_bo(obj);
717 offset = obj_priv->gtt_offset + args->offset; 701 offset = obj_priv->gtt_offset + args->offset;
718 702
@@ -729,26 +713,21 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj,
729 if ((page_offset + remain) > PAGE_SIZE) 713 if ((page_offset + remain) > PAGE_SIZE)
730 page_length = PAGE_SIZE - page_offset; 714 page_length = PAGE_SIZE - page_offset;
731 715
732 ret = fast_user_write (dev_priv->mm.gtt_mapping, page_base,
733 page_offset, user_data, page_length);
734
735 /* If we get a fault while copying data, then (presumably) our 716 /* If we get a fault while copying data, then (presumably) our
736 * source page isn't available. Return the error and we'll 717 * source page isn't available. Return the error and we'll
737 * retry in the slow path. 718 * retry in the slow path.
738 */ 719 */
739 if (ret) 720 if (fast_user_write(dev_priv->mm.gtt_mapping, page_base,
740 goto fail; 721 page_offset, user_data, page_length))
722
723 return -EFAULT;
741 724
742 remain -= page_length; 725 remain -= page_length;
743 user_data += page_length; 726 user_data += page_length;
744 offset += page_length; 727 offset += page_length;
745 } 728 }
746 729
747fail: 730 return 0;
748 i915_gem_object_unpin(obj);
749 mutex_unlock(&dev->struct_mutex);
750
751 return ret;
752} 731}
753 732
754/** 733/**
@@ -785,30 +764,24 @@ i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
785 last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; 764 last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE;
786 num_pages = last_data_page - first_data_page + 1; 765 num_pages = last_data_page - first_data_page + 1;
787 766
788 user_pages = drm_calloc_large(num_pages, sizeof(struct page *)); 767 user_pages = drm_malloc_ab(num_pages, sizeof(struct page *));
789 if (user_pages == NULL) 768 if (user_pages == NULL)
790 return -ENOMEM; 769 return -ENOMEM;
791 770
771 mutex_unlock(&dev->struct_mutex);
792 down_read(&mm->mmap_sem); 772 down_read(&mm->mmap_sem);
793 pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr, 773 pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr,
794 num_pages, 0, 0, user_pages, NULL); 774 num_pages, 0, 0, user_pages, NULL);
795 up_read(&mm->mmap_sem); 775 up_read(&mm->mmap_sem);
776 mutex_lock(&dev->struct_mutex);
796 if (pinned_pages < num_pages) { 777 if (pinned_pages < num_pages) {
797 ret = -EFAULT; 778 ret = -EFAULT;
798 goto out_unpin_pages; 779 goto out_unpin_pages;
799 } 780 }
800 781
801 ret = i915_mutex_lock_interruptible(dev);
802 if (ret)
803 goto out_unpin_pages;
804
805 ret = i915_gem_object_pin(obj, 0);
806 if (ret)
807 goto out_unlock;
808
809 ret = i915_gem_object_set_to_gtt_domain(obj, 1); 782 ret = i915_gem_object_set_to_gtt_domain(obj, 1);
810 if (ret) 783 if (ret)
811 goto out_unpin_object; 784 goto out_unpin_pages;
812 785
813 obj_priv = to_intel_bo(obj); 786 obj_priv = to_intel_bo(obj);
814 offset = obj_priv->gtt_offset + args->offset; 787 offset = obj_priv->gtt_offset + args->offset;
@@ -844,10 +817,6 @@ i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
844 data_ptr += page_length; 817 data_ptr += page_length;
845 } 818 }
846 819
847out_unpin_object:
848 i915_gem_object_unpin(obj);
849out_unlock:
850 mutex_unlock(&dev->struct_mutex);
851out_unpin_pages: 820out_unpin_pages:
852 for (i = 0; i < pinned_pages; i++) 821 for (i = 0; i < pinned_pages; i++)
853 page_cache_release(user_pages[i]); 822 page_cache_release(user_pages[i]);
@@ -870,23 +839,10 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj,
870 loff_t offset, page_base; 839 loff_t offset, page_base;
871 char __user *user_data; 840 char __user *user_data;
872 int page_offset, page_length; 841 int page_offset, page_length;
873 int ret;
874 842
875 user_data = (char __user *) (uintptr_t) args->data_ptr; 843 user_data = (char __user *) (uintptr_t) args->data_ptr;
876 remain = args->size; 844 remain = args->size;
877 845
878 ret = i915_mutex_lock_interruptible(dev);
879 if (ret)
880 return ret;
881
882 ret = i915_gem_object_get_pages(obj, 0);
883 if (ret != 0)
884 goto fail_unlock;
885
886 ret = i915_gem_object_set_to_cpu_domain(obj, 1);
887 if (ret != 0)
888 goto fail_put_pages;
889
890 obj_priv = to_intel_bo(obj); 846 obj_priv = to_intel_bo(obj);
891 offset = args->offset; 847