diff options
Diffstat (limited to 'drivers/gpu/drm/ttm/ttm_bo.c')
| -rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo.c | 86 |
1 files changed, 21 insertions, 65 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index a1cb783c7131..3ca77dc03915 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c | |||
| @@ -27,14 +27,6 @@ | |||
| 27 | /* | 27 | /* |
| 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> | 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> |
| 29 | */ | 29 | */ |
| 30 | /* Notes: | ||
| 31 | * | ||
| 32 | * We store bo pointer in drm_mm_node struct so we know which bo own a | ||
| 33 | * specific node. There is no protection on the pointer, thus to make | ||
| 34 | * sure things don't go berserk you have to access this pointer while | ||
| 35 | * holding the global lru lock and make sure anytime you free a node you | ||
| 36 | * reset the pointer to NULL. | ||
| 37 | */ | ||
| 38 | 30 | ||
| 39 | #include "ttm/ttm_module.h" | 31 | #include "ttm/ttm_module.h" |
| 40 | #include "ttm/ttm_bo_driver.h" | 32 | #include "ttm/ttm_bo_driver.h" |
| @@ -45,6 +37,7 @@ | |||
| 45 | #include <linux/mm.h> | 37 | #include <linux/mm.h> |
| 46 | #include <linux/file.h> | 38 | #include <linux/file.h> |
| 47 | #include <linux/module.h> | 39 | #include <linux/module.h> |
| 40 | #include <asm/atomic.h> | ||
| 48 | 41 | ||
| 49 | #define TTM_ASSERT_LOCKED(param) | 42 | #define TTM_ASSERT_LOCKED(param) |
| 50 | #define TTM_DEBUG(fmt, arg...) | 43 | #define TTM_DEBUG(fmt, arg...) |
| @@ -452,6 +445,11 @@ static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) | |||
| 452 | ttm_bo_mem_put(bo, &bo->mem); | 445 | ttm_bo_mem_put(bo, &bo->mem); |
| 453 | 446 | ||
| 454 | atomic_set(&bo->reserved, 0); | 447 | atomic_set(&bo->reserved, 0); |
| 448 | |||
| 449 | /* | ||
| 450 | * Make processes trying to reserve really pick it up. | ||
| 451 | */ | ||
| 452 | smp_mb__after_atomic_dec(); | ||
| 455 | wake_up_all(&bo->event_queue); | 453 | wake_up_all(&bo->event_queue); |
| 456 | } | 454 | } |
| 457 | 455 | ||
| @@ -460,7 +458,7 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo) | |||
| 460 | struct ttm_bo_device *bdev = bo->bdev; | 458 | struct ttm_bo_device *bdev = bo->bdev; |
| 461 | struct ttm_bo_global *glob = bo->glob; | 459 | struct ttm_bo_global *glob = bo->glob; |
| 462 | struct ttm_bo_driver *driver; | 460 | struct ttm_bo_driver *driver; |
| 463 | void *sync_obj; | 461 | void *sync_obj = NULL; |
| 464 | void *sync_obj_arg; | 462 | void *sync_obj_arg; |
| 465 | int put_count; | 463 | int put_count; |
| 466 | int ret; | 464 | int ret; |
| @@ -495,17 +493,20 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo) | |||
| 495 | spin_lock(&glob->lru_lock); | 493 | spin_lock(&glob->lru_lock); |
| 496 | } | 494 | } |
| 497 | queue: | 495 | queue: |
| 498 | sync_obj = bo->sync_obj; | ||
| 499 | sync_obj_arg = bo->sync_obj_arg; | ||
| 500 | driver = bdev->driver; | 496 | driver = bdev->driver; |
| 497 | if (bo->sync_obj) | ||
| 498 | sync_obj = driver->sync_obj_ref(bo->sync_obj); | ||
| 499 | sync_obj_arg = bo->sync_obj_arg; | ||
| 501 | 500 | ||
| 502 | kref_get(&bo->list_kref); | 501 | kref_get(&bo->list_kref); |
| 503 | list_add_tail(&bo->ddestroy, &bdev->ddestroy); | 502 | list_add_tail(&bo->ddestroy, &bdev->ddestroy); |
| 504 | spin_unlock(&glob->lru_lock); | 503 | spin_unlock(&glob->lru_lock); |
| 505 | spin_unlock(&bo->lock); | 504 | spin_unlock(&bo->lock); |
| 506 | 505 | ||
| 507 | if (sync_obj) | 506 | if (sync_obj) { |
| 508 | driver->sync_obj_flush(sync_obj, sync_obj_arg); | 507 | driver->sync_obj_flush(sync_obj, sync_obj_arg); |
| 508 | driver->sync_obj_unref(&sync_obj); | ||
| 509 | } | ||
| 509 | schedule_delayed_work(&bdev->wq, | 510 | schedule_delayed_work(&bdev->wq, |
| 510 | ((HZ / 100) < 1) ? 1 : HZ / 100); | 511 | ((HZ / 100) < 1) ? 1 : HZ / 100); |
| 511 | } | 512 | } |
| @@ -822,7 +823,6 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, | |||
| 822 | bool no_wait_gpu) | 823 | bool no_wait_gpu) |
| 823 | { | 824 | { |
| 824 | struct ttm_bo_device *bdev = bo->bdev; | 825 | struct ttm_bo_device *bdev = bo->bdev; |
| 825 | struct ttm_bo_global *glob = bdev->glob; | ||
| 826 | struct ttm_mem_type_manager *man = &bdev->man[mem_type]; | 826 | struct ttm_mem_type_manager *man = &bdev->man[mem_type]; |
| 827 | int ret; | 827 | int ret; |
| 828 | 828 | ||
| @@ -832,12 +832,6 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, | |||
| 832 | return ret; | 832 | return ret; |
| 833 | if (mem->mm_node) | 833 | if (mem->mm_node) |
| 834 | break; | 834 | break; |
| 835 | spin_lock(&glob->lru_lock); | ||
| 836 | if (list_empty(&man->lru)) { | ||
| 837 | spin_unlock(&glob->lru_lock); | ||
| 838 | break; | ||
| 839 | } | ||
| 840 | spin_unlock(&glob->lru_lock); | ||
| 841 | ret = ttm_mem_evict_first(bdev, mem_type, interruptible, | 835 | ret = ttm_mem_evict_first(bdev, mem_type, interruptible, |
| 842 | no_wait_reserve, no_wait_gpu); | 836 | no_wait_reserve, no_wait_gpu); |
| 843 | if (unlikely(ret != 0)) | 837 | if (unlikely(ret != 0)) |
| @@ -1125,35 +1119,9 @@ EXPORT_SYMBOL(ttm_bo_validate); | |||
| 1125 | int ttm_bo_check_placement(struct ttm_buffer_object *bo, | 1119 | int ttm_bo_check_placement(struct ttm_buffer_object *bo, |
| 1126 | struct ttm_placement *placement) | 1120 | struct ttm_placement *placement) |
| 1127 | { | 1121 | { |
| 1128 | int i; | 1122 | BUG_ON((placement->fpfn || placement->lpfn) && |
| 1123 | (bo->mem.num_pages > (placement->lpfn - placement->fpfn))); | ||
| 1129 | 1124 | ||
| 1130 | if (placement->fpfn || placement->lpfn) { | ||
| 1131 | if (bo->mem.num_pages > (placement->lpfn - placement->fpfn)) { | ||
| 1132 | printk(KERN_ERR TTM_PFX "Page number range to small " | ||
| 1133 | "Need %lu pages, range is [%u, %u]\n", | ||
| 1134 | bo->mem.num_pages, placement->fpfn, | ||
| 1135 | placement->lpfn); | ||
| 1136 | return -EINVAL; | ||
| 1137 | } | ||
| 1138 | } | ||
| 1139 | for (i = 0; i < placement->num_placement; i++) { | ||
| 1140 | if (!capable(CAP_SYS_ADMIN)) { | ||
| 1141 | if (placement->placement[i] & TTM_PL_FLAG_NO_EVICT) { | ||
| 1142 | printk(KERN_ERR TTM_PFX "Need to be root to " | ||
| 1143 | "modify NO_EVICT status.\n"); | ||
| 1144 | return -EINVAL; | ||
| 1145 | } | ||
| 1146 | } | ||
| 1147 | } | ||
| 1148 | for (i = 0; i < placement->num_busy_placement; i++) { | ||
| 1149 | if (!capable(CAP_SYS_ADMIN)) { | ||
| 1150 | if (placement->busy_placement[i] & TTM_PL_FLAG_NO_EVICT) { | ||
| 1151 | printk(KERN_ERR TTM_PFX "Need to be root to " | ||
| 1152 | "modify NO_EVICT status.\n"); | ||
| 1153 | return -EINVAL; | ||
| 1154 | } | ||
| 1155 | } | ||
| 1156 | } | ||
| 1157 | return 0; | 1125 | return 0; |
| 1158 | } | 1126 | } |
| 1159 | 1127 | ||
| @@ -1176,6 +1144,10 @@ int ttm_bo_init(struct ttm_bo_device *bdev, | |||
| 1176 | num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; | 1144 | num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; |
| 1177 | if (num_pages == 0) { | 1145 | if (num_pages == 0) { |
| 1178 | printk(KERN_ERR TTM_PFX "Illegal buffer object size.\n"); | 1146 | printk(KERN_ERR TTM_PFX "Illegal buffer object size.\n"); |
| 1147 | if (destroy) | ||
| 1148 | (*destroy)(bo); | ||
| 1149 | else | ||
| 1150 | kfree(bo); | ||
| 1179 | return -EINVAL; | 1151 | return -EINVAL; |
| 1180 | } | 1152 | } |
| 1181 | bo->destroy = destroy; | 1153 | bo->destroy = destroy; |
| @@ -1369,18 +1341,9 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, | |||
| 1369 | int ret = -EINVAL; | 1341 | int ret = -EINVAL; |
| 1370 | struct ttm_mem_type_manager *man; | 1342 | struct ttm_mem_type_manager *man; |
| 1371 | 1343 | ||
| 1372 | if (type >= TTM_NUM_MEM_TYPES) { | 1344 | BUG_ON(type >= TTM_NUM_MEM_TYPES); |
| 1373 | printk(KERN_ERR TTM_PFX "Illegal memory type %d\n", type); | ||
| 1374 | return ret; | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | man = &bdev->man[type]; | 1345 | man = &bdev->man[type]; |
| 1378 | if (man->has_type) { | 1346 | BUG_ON(man->has_type); |
| 1379 | printk(KERN_ERR TTM_PFX | ||
| 1380 | "Memory manager already initialized for type %d\n", | ||
| 1381 | type); | ||
| 1382 | return ret; | ||
| 1383 | } | ||
| 1384 | 1347 | ||
| 1385 | ret = bdev->driver->init_mem_type(bdev, type, man); | 1348 | ret = bdev->driver->init_mem_type(bdev, type, man); |
| 1386 | if (ret) | 1349 | if (ret) |
| @@ -1389,13 +1352,6 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, | |||
| 1389 | 1352 | ||
| 1390 | ret = 0; | 1353 | ret = 0; |
| 1391 | if (type != TTM_PL_SYSTEM) { | 1354 | if (type != TTM_PL_SYSTEM) { |
| 1392 | if (!p_size) { | ||
| 1393 | printk(KERN_ERR TTM_PFX | ||
| 1394 | "Zero size memory manager type %d\n", | ||
| 1395 | type); | ||
| 1396 | return ret; | ||
| 1397 | } | ||
| 1398 | |||
| 1399 | ret = (*man->func->init)(man, p_size); | 1355 | ret = (*man->func->init)(man, p_size); |
| 1400 | if (ret) | 1356 | if (ret) |
| 1401 | return ret; | 1357 | return ret; |
