aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-11-06 21:22:10 -0500
committerDave Airlie <airlied@redhat.com>2013-11-06 21:22:10 -0500
commit212c444baa4efe0077fb2a07a65ccb3011b94e8f (patch)
treeb8892c347a6901dd711f0ba01dc5bc41ce7ad80b
parent1e95ab5846504b2c0e9a01405bbb3278e2e20480 (diff)
parent59c8e66378fb78adbcd05f0d09783dde6fef282b (diff)
Merge branch 'ttm-next-3.13' of git://people.freedesktop.org/~thomash/linux into drm-next
- A couple of fixes that never made it into fixes-3.12 - Make NO_EVICT bo's available for shrinkers when on delayed-delete list - Allow retrying page-faults that need to wait for GPU. * 'ttm-next-3.13' of git://people.freedesktop.org/~thomash/linux: drm/ttm: Fix memory type compatibility check drm/ttm: Fix ttm_bo_move_memcpy drm/ttm: Handle in-memory region copies drm/ttm: Make NO_EVICT bos available to shrinkers pending destruction drm/ttm: Allow vm fault retries
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c46
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_util.c30
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_vm.c62
3 files changed, 102 insertions, 36 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index f1a857ec1021..8d5a646ebe6a 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -429,8 +429,20 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)
429 sync_obj = driver->sync_obj_ref(bo->sync_obj); 429 sync_obj = driver->sync_obj_ref(bo->sync_obj);
430 spin_unlock(&bdev->fence_lock); 430 spin_unlock(&bdev->fence_lock);
431 431
432 if (!ret) 432 if (!ret) {
433
434 /*
435 * Make NO_EVICT bos immediately available to
436 * shrinkers, now that they are queued for
437 * destruction.
438 */
439 if (bo->mem.placement & TTM_PL_FLAG_NO_EVICT) {
440 bo->mem.placement &= ~TTM_PL_FLAG_NO_EVICT;
441 ttm_bo_add_to_lru(bo);
442 }
443
433 ww_mutex_unlock(&bo->resv->lock); 444 ww_mutex_unlock(&bo->resv->lock);
445 }
434 446
435 kref_get(&bo->list_kref); 447 kref_get(&bo->list_kref);
436 list_add_tail(&bo->ddestroy, &bdev->ddestroy); 448 list_add_tail(&bo->ddestroy, &bdev->ddestroy);
@@ -986,24 +998,32 @@ out_unlock:
986 return ret; 998 return ret;
987} 999}
988 1000
989static int ttm_bo_mem_compat(struct ttm_placement *placement, 1001static bool ttm_bo_mem_compat(struct ttm_placement *placement,
990 struct ttm_mem_reg *mem) 1002 struct ttm_mem_reg *mem,
1003 uint32_t *new_flags)
991{ 1004{
992 int i; 1005 int i;
993 1006
994 if (mem->mm_node && placement->lpfn != 0 && 1007 if (mem->mm_node && placement->lpfn != 0 &&
995 (mem->start < placement->fpfn || 1008 (mem->start < placement->fpfn ||
996 mem->start + mem->num_pages > placement->lpfn)) 1009 mem->start + mem->num_pages > placement->lpfn))
997 return -1; 1010 return false;
998 1011
999 for (i = 0; i < placement->num_placement; i++) { 1012 for (i = 0; i < placement->num_placement; i++) {
1000 if ((placement->placement[i] & mem->placement & 1013 *new_flags = placement->placement[i];
1001 TTM_PL_MASK_CACHING) && 1014 if ((*new_flags & mem->placement & TTM_PL_MASK_CACHING) &&
1002 (placement->placement[i] & mem->placement & 1015 (*new_flags & mem->placement & TTM_PL_MASK_MEM))
1003 TTM_PL_MASK_MEM)) 1016 return true;
1004 return i;
1005 } 1017 }
1006 return -1; 1018
1019 for (i = 0; i < placement->num_busy_placement; i++) {
1020 *new_flags = placement->busy_placement[i];
1021 if ((*new_flags & mem->placement & TTM_PL_MASK_CACHING) &&
1022 (*new_flags & mem->placement & TTM_PL_MASK_MEM))
1023 return true;
1024 }
1025
1026 return false;
1007} 1027}
1008 1028
1009int ttm_bo_validate(struct ttm_buffer_object *bo, 1029int ttm_bo_validate(struct ttm_buffer_object *bo,
@@ -1012,6 +1032,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
1012 bool no_wait_gpu) 1032 bool no_wait_gpu)
1013{ 1033{
1014 int ret; 1034 int ret;
1035 uint32_t new_flags;
1015 1036
1016 lockdep_assert_held(&bo->resv->lock.base); 1037 lockdep_assert_held(&bo->resv->lock.base);
1017 /* Check that range is valid */ 1038 /* Check that range is valid */
@@ -1022,8 +1043,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
1022 /* 1043 /*
1023 * Check whether we need to move buffer. 1044 * Check whether we need to move buffer.
1024 */ 1045 */
1025 ret = ttm_bo_mem_compat(placement, &bo->mem); 1046 if (!ttm_bo_mem_compat(placement, &bo->mem, &new_flags)) {
1026 if (ret < 0) {
1027 ret = ttm_bo_move_buffer(bo, placement, interruptible, 1047 ret = ttm_bo_move_buffer(bo, placement, interruptible,
1028 no_wait_gpu); 1048 no_wait_gpu);
1029 if (ret) 1049 if (ret)
@@ -1033,7 +1053,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
1033 * Use the access and other non-mapping-related flag bits from 1053 * Use the access and other non-mapping-related flag bits from
1034 * the compatible memory placement flags to the active flags 1054 * the compatible memory placement flags to the active flags
1035 */ 1055 */
1036 ttm_flag_masked(&bo->mem.placement, placement->placement[ret], 1056 ttm_flag_masked(&bo->mem.placement, new_flags,
1037 ~TTM_PL_MASK_MEMTYPE); 1057 ~TTM_PL_MASK_MEMTYPE);
1038 } 1058 }
1039 /* 1059 /*
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index 7cc904d3a4d1..4834c463c38b 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -343,19 +343,25 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
343 if (ret) 343 if (ret)
344 goto out; 344 goto out;
345 345
346 /*
347 * Single TTM move. NOP.
348 */
346 if (old_iomap == NULL && new_iomap == NULL) 349 if (old_iomap == NULL && new_iomap == NULL)
347 goto out2; 350 goto out2;
351
352 /*
353 * Move nonexistent data. NOP.
354 */
348 if (old_iomap == NULL && ttm == NULL) 355 if (old_iomap == NULL && ttm == NULL)
349 goto out2; 356 goto out2;
350 357
351 if (ttm->state == tt_unpopulated) { 358 /*
359 * TTM might be null for moves within the same region.
360 */
361 if (ttm && ttm->state == tt_unpopulated) {
352 ret = ttm->bdev->driver->ttm_tt_populate(ttm); 362 ret = ttm->bdev->driver->ttm_tt_populate(ttm);
353 if (ret) { 363 if (ret)
354 /* if we fail here don't nuke the mm node
355 * as the bo still owns it */
356 old_copy.mm_node = NULL;
357 goto out1; 364 goto out1;
358 }
359 } 365 }
360 366
361 add = 0; 367 add = 0;
@@ -381,11 +387,8 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
381 prot); 387 prot);
382 } else 388 } else
383 ret = ttm_copy_io_page(new_iomap, old_iomap, page); 389 ret = ttm_copy_io_page(new_iomap, old_iomap, page);
384 if (ret) { 390 if (ret)
385 /* failing here, means keep old copy as-is */
386 old_copy.mm_node = NULL;
387 goto out1; 391 goto out1;
388 }
389 } 392 }
390 mb(); 393 mb();
391out2: 394out2:
@@ -403,7 +406,12 @@ out1:
403 ttm_mem_reg_iounmap(bdev, old_mem, new_iomap); 406 ttm_mem_reg_iounmap(bdev, old_mem, new_iomap);
404out: 407out:
405 ttm_mem_reg_iounmap(bdev, &old_copy, old_iomap); 408 ttm_mem_reg_iounmap(bdev, &old_copy, old_iomap);
406 ttm_bo_mem_put(bo, &old_copy); 409
410 /*
411 * On error, keep the mm node!
412 */
413 if (!ret)
414 ttm_bo_mem_put(bo, &old_copy);
407 return ret; 415 return ret;
408} 416}
409EXPORT_SYMBOL(ttm_bo_move_memcpy); 417EXPORT_SYMBOL(ttm_bo_move_memcpy);
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
index 1006c15445e9..c03514b93f9c 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -41,6 +41,51 @@
41 41
42#define TTM_BO_VM_NUM_PREFAULT 16 42#define TTM_BO_VM_NUM_PREFAULT 16
43 43
44static int ttm_bo_vm_fault_idle(struct ttm_buffer_object *bo,
45 struct vm_area_struct *vma,
46 struct vm_fault *vmf)
47{
48 struct ttm_bo_device *bdev = bo->bdev;
49 int ret = 0;
50
51 spin_lock(&bdev->fence_lock);
52 if (likely(!test_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags)))
53 goto out_unlock;
54
55 /*
56 * Quick non-stalling check for idle.
57 */
58 ret = ttm_bo_wait(bo, false, false, true);
59 if (likely(ret == 0))
60 goto out_unlock;
61
62 /*
63 * If possible, avoid waiting for GPU with mmap_sem
64 * held.
65 */
66 if (vmf->flags & FAULT_FLAG_ALLOW_RETRY) {
67 ret = VM_FAULT_RETRY;
68 if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT)
69 goto out_unlock;
70
71 up_read(&vma->vm_mm->mmap_sem);
72 (void) ttm_bo_wait(bo, false, true, false);
73 goto out_unlock;
74 }
75
76 /*
77 * Ordinary wait.
78 */
79 ret = ttm_bo_wait(bo, false, true, false);
80 if (unlikely(ret != 0))
81 ret = (ret != -ERESTARTSYS) ? VM_FAULT_SIGBUS :
82 VM_FAULT_NOPAGE;
83
84out_unlock:
85 spin_unlock(&bdev->fence_lock);
86 return ret;
87}
88
44static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 89static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
45{ 90{
46 struct ttm_buffer_object *bo = (struct ttm_buffer_object *) 91 struct ttm_buffer_object *bo = (struct ttm_buffer_object *)
@@ -91,18 +136,11 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
91 * Wait for buffer data in transit, due to a pipelined 136 * Wait for buffer data in transit, due to a pipelined
92 * move. 137 * move.
93 */ 138 */
94 139 ret = ttm_bo_vm_fault_idle(bo, vma, vmf);
95 spin_lock(&bdev->fence_lock); 140 if (unlikely(ret != 0)) {
96 if (test_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags)) { 141 retval = ret;
97 ret = ttm_bo_wait(bo, false, true, false); 142 goto out_unlock;
98 spin_unlock(&bdev->fence_lock); 143 }
99 if (unlikely(ret != 0)) {
100 retval = (ret != -ERESTARTSYS) ?
101 VM_FAULT_SIGBUS : VM_FAULT_NOPAGE;
102 goto out_unlock;
103 }
104 } else
105 spin_unlock(&bdev->fence_lock);
106 144
107 ret = ttm_mem_io_lock(man, true); 145 ret = ttm_mem_io_lock(man, true);
108 if (unlikely(ret != 0)) { 146 if (unlikely(ret != 0)) {