Merge branches 'acpi-hotplug', 'acpi-sysfs' and 'acpi-sleep'
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / ttm / ttm_bo_vm.c
index c03514b93f9caf9543d28279c1a118e744417f2b..b249ab9b1eb29c402d407049a42c2fda83b3ffb1 100644 (file)
@@ -102,17 +102,33 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        int retval = VM_FAULT_NOPAGE;
        struct ttm_mem_type_manager *man =
                &bdev->man[bo->mem.mem_type];
+       struct vm_area_struct cvma;
 
        /*
         * Work around locking order reversal in fault / nopfn
         * between mmap_sem and bo_reserve: Perform a trylock operation
-        * for reserve, and if it fails, retry the fault after scheduling.
+        * for reserve, and if it fails, retry the fault after waiting
+        * for the buffer to become unreserved.
         */
-
-       ret = ttm_bo_reserve(bo, true, true, false, 0);
+       ret = ttm_bo_reserve(bo, true, true, false, NULL);
        if (unlikely(ret != 0)) {
-               if (ret == -EBUSY)
-                       set_need_resched();
+               if (ret != -EBUSY)
+                       return VM_FAULT_NOPAGE;
+
+               if (vmf->flags & FAULT_FLAG_ALLOW_RETRY) {
+                       if (!(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) {
+                               up_read(&vma->vm_mm->mmap_sem);
+                               (void) ttm_bo_wait_unreserved(bo);
+                       }
+
+                       return VM_FAULT_RETRY;
+               }
+
+               /*
+                * If we'd want to change locking order to
+                * mmap_sem -> bo::reserve, we'd use a blocking reserve here
+                * instead of retrying the fault...
+                */
                return VM_FAULT_NOPAGE;
        }
 
@@ -122,7 +138,6 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                case 0:
                        break;
                case -EBUSY:
-                       set_need_resched();
                case -ERESTARTSYS:
                        retval = VM_FAULT_NOPAGE;
                        goto out_unlock;
@@ -164,26 +179,21 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        }
 
        /*
-        * Strictly, we're not allowed to modify vma->vm_page_prot here,
-        * since the mmap_sem is only held in read mode. However, we
-        * modify only the caching bits of vma->vm_page_prot and
-        * consider those bits protected by
-        * the bo->mutex, as we should be the only writers.
-        * There shouldn't really be any readers of these bits except
-        * within vm_insert_mixed()? fork?
-        *
-        * TODO: Add a list of vmas to the bo, and change the
-        * vma->vm_page_prot when the object changes caching policy, with
-        * the correct locks held.
+        * Make a local vma copy to modify the page_prot member
+        * and vm_flags if necessary. The vma parameter is protected
+        * by mmap_sem in write mode.
         */
+       cvma = *vma;
+       cvma.vm_page_prot = vm_get_page_prot(cvma.vm_flags);
+
        if (bo->mem.bus.is_iomem) {
-               vma->vm_page_prot = ttm_io_prot(bo->mem.placement,
-                                               vma->vm_page_prot);
+               cvma.vm_page_prot = ttm_io_prot(bo->mem.placement,
+                                               cvma.vm_page_prot);
        } else {
                ttm = bo->ttm;
-               vma->vm_page_prot = (bo->mem.placement & TTM_PL_FLAG_CACHED) ?
-                   vm_get_page_prot(vma->vm_flags) :
-                   ttm_io_prot(bo->mem.placement, vma->vm_page_prot);
+               if (!(bo->mem.placement & TTM_PL_FLAG_CACHED))
+                       cvma.vm_page_prot = ttm_io_prot(bo->mem.placement,
+                                                       cvma.vm_page_prot);
 
                /* Allocate all page at once, most common usage */
                if (ttm->bdev->driver->ttm_tt_populate(ttm)) {
@@ -210,7 +220,7 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                        pfn = page_to_pfn(page);
                }
 
-               ret = vm_insert_mixed(vma, address, pfn);
+               ret = vm_insert_mixed(&cvma, address, pfn);
                /*
                 * Somebody beat us to this PTE or prefaulting to
                 * an already populated PTE, or prefaulting error.