From 3205bc242b5e3950c808049dbf199fca91f2c844 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 29 Oct 2010 10:46:44 +0200 Subject: drm/ttm: Documentation update Remove an obsolete comment about mm nodes. Document the new bo range manager interface. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/gpu/drm/ttm/ttm_bo.c') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index a1cb783c7131..cf47978cf0e2 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -27,14 +27,6 @@ /* * Authors: Thomas Hellstrom */ -/* Notes: - * - * We store bo pointer in drm_mm_node struct so we know which bo own a - * specific node. There is no protection on the pointer, thus to make - * sure things don't go berserk you have to access this pointer while - * holding the global lru lock and make sure anytime you free a node you - * reset the pointer to NULL. - */ #include "ttm/ttm_module.h" #include "ttm/ttm_bo_driver.h" -- cgit v1.2.2 From 6e4c55db120b03d411e0eff7cd35f3edabbefe14 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 29 Oct 2010 10:46:46 +0200 Subject: drm/ttm: Remove pointless list_empty check Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/gpu/drm/ttm/ttm_bo.c') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index cf47978cf0e2..e6cedf43c2db 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -814,7 +814,6 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, bool no_wait_gpu) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_bo_global *glob = bdev->glob; struct ttm_mem_type_manager *man = &bdev->man[mem_type]; int ret; @@ -824,12 +823,6 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, return ret; if (mem->mm_node) break; - spin_lock(&glob->lru_lock); - if (list_empty(&man->lru)) { - spin_unlock(&glob->lru_lock); - break; - } - spin_unlock(&glob->lru_lock); ret = ttm_mem_evict_first(bdev, mem_type, interruptible, no_wait_reserve, no_wait_gpu); if (unlikely(ret != 0)) -- cgit v1.2.2 From dbc4a5b83585e89a6bce650d32426f61c8d4bca5 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 29 Oct 2010 10:46:47 +0200 Subject: drm/ttm: Remove mm init error printouts and checks Replace with BUG_ON(). These error messages remained from the time when TTM was initialized from user-space. Nowadays hitting one of those is really a kernel bug. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/ttm/ttm_bo.c') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index e6cedf43c2db..f561eead057d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1354,18 +1354,9 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, int ret = -EINVAL; struct ttm_mem_type_manager *man; - if (type >= TTM_NUM_MEM_TYPES) { - printk(KERN_ERR TTM_PFX "Illegal memory type %d\n", type); - return ret; - } - + BUG_ON(type >= TTM_NUM_MEM_TYPES); man = &bdev->man[type]; - if (man->has_type) { - printk(KERN_ERR TTM_PFX - "Memory manager already initialized for type %d\n", - type); - return ret; - } + BUG_ON(man->has_type); ret = bdev->driver->init_mem_type(bdev, type, man); if (ret) @@ -1374,13 +1365,6 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, ret = 0; if (type != TTM_PL_SYSTEM) { - if (!p_size) { - printk(KERN_ERR TTM_PFX - "Zero size memory manager type %d\n", - type); - return ret; - } - ret = (*man->func->init)(man, p_size); if (ret) return ret; -- cgit v1.2.2 From 06fba6d4168069d818593e2fcc2d4bd0f888e97b Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 29 Oct 2010 10:46:48 +0200 Subject: drm/ttm: Add a barrier when unreserving Since we're doing this outside of a spinlock to provide the necessary barriers, add an explicit barrier. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu/drm/ttm/ttm_bo.c') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index f561eead057d..a32fe41e5e24 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -37,6 +37,7 @@ #include #include #include +#include #define TTM_ASSERT_LOCKED(param) #define TTM_DEBUG(fmt, arg...) @@ -444,6 +445,11 @@ static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) ttm_bo_mem_put(bo, &bo->mem); atomic_set(&bo->reserved, 0); + + /* + * Make processes trying to reserve really pick it up. + */ + smp_mb__after_atomic_dec(); wake_up_all(&bo->event_queue); } -- cgit v1.2.2 From aa123268c2623c62e33248dafc0572f091689e86 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 2 Nov 2010 13:21:47 +0000 Subject: drm/ttm: Make sure a sync object doesn't disappear while we use it The sync object may disappear as soon as we release the bo::lock, so take a reference on it while we use it. One option would be to call sync_object_flush() before releasing the bo::lock, but that would put an atomic requirement on that function. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/ttm/ttm_bo.c') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index a32fe41e5e24..340dfb11959d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -458,7 +458,7 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo) struct ttm_bo_device *bdev = bo->bdev; struct ttm_bo_global *glob = bo->glob; struct ttm_bo_driver *driver; - void *sync_obj; + void *sync_obj = NULL; void *sync_obj_arg; int put_count; int ret; @@ -493,17 +493,20 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo) spin_lock(&glob->lru_lock); } queue: - sync_obj = bo->sync_obj; - sync_obj_arg = bo->sync_obj_arg; driver = bdev->driver; + if (bo->sync_obj) + sync_obj = driver->sync_obj_ref(bo->sync_obj); + sync_obj_arg = bo->sync_obj_arg; kref_get(&bo->list_kref); list_add_tail(&bo->ddestroy, &bdev->ddestroy); spin_unlock(&glob->lru_lock); spin_unlock(&bo->lock); - if (sync_obj) + if (sync_obj) { driver->sync_obj_flush(sync_obj, sync_obj_arg); + driver->sync_obj_unref(&sync_obj); + } schedule_delayed_work(&bdev->wq, ((HZ / 100) < 1) ? 1 : HZ / 100); } -- cgit v1.2.2 From 29e190e049168b01dc5fa26d577ef99cafd753ee Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 2 Nov 2010 13:21:48 +0000 Subject: drm/ttm: Remove the CAP_SYS_ADMIN requirement for bo pinning This breaks vmwgfx non-root EGL clients and is a remnant from the TTM user-space interface. This test should be done in the driver. Replace the remaining placement test with a BUG_ON, since triggering it is a driver bug. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) (limited to 'drivers/gpu/drm/ttm/ttm_bo.c') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 340dfb11959d..ce464579c485 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1119,35 +1119,9 @@ EXPORT_SYMBOL(ttm_bo_validate); int ttm_bo_check_placement(struct ttm_buffer_object *bo, struct ttm_placement *placement) { - int i; + BUG_ON((placement->fpfn || placement->lpfn) && + (bo->mem.num_pages > (placement->lpfn - placement->fpfn))); - if (placement->fpfn || placement->lpfn) { - if (bo->mem.num_pages > (placement->lpfn - placement->fpfn)) { - printk(KERN_ERR TTM_PFX "Page number range to small " - "Need %lu pages, range is [%u, %u]\n", - bo->mem.num_pages, placement->fpfn, - placement->lpfn); - return -EINVAL; - } - } - for (i = 0; i < placement->num_placement; i++) { - if (!capable(CAP_SYS_ADMIN)) { - if (placement->placement[i] & TTM_PL_FLAG_NO_EVICT) { - printk(KERN_ERR TTM_PFX "Need to be root to " - "modify NO_EVICT status.\n"); - return -EINVAL; - } - } - } - for (i = 0; i < placement->num_busy_placement; i++) { - if (!capable(CAP_SYS_ADMIN)) { - if (placement->busy_placement[i] & TTM_PL_FLAG_NO_EVICT) { - printk(KERN_ERR TTM_PFX "Need to be root to " - "modify NO_EVICT status.\n"); - return -EINVAL; - } - } - } return 0; } -- cgit v1.2.2 From 7dfbbdcffebc41441e64278961f57d2840a76259 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 9 Nov 2010 21:31:44 +0100 Subject: drm/ttm: Be consistent on ttm_bo_init() failures Call destroy() on _all_ ttm_bo_init() failures, and make sure that behavior is documented in the function description. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu/drm/ttm/ttm_bo.c') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index ce464579c485..3ca77dc03915 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1144,6 +1144,10 @@ int ttm_bo_init(struct ttm_bo_device *bdev, num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; if (num_pages == 0) { printk(KERN_ERR TTM_PFX "Illegal buffer object size.\n"); + if (destroy) + (*destroy)(bo); + else + kfree(bo); return -EINVAL; } bo->destroy = destroy; -- cgit v1.2.2 From 95ccb0f3bdc4438bf470c25450e6a8a6090ca253 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 11 Nov 2010 10:04:53 +0100 Subject: drm/ttm: Fix up a theoretical deadlock A process suspended waiting for a higher sequence or no sequence to unreserve, a bo may be beaten to the reservation by a process with a lower sequence. In that case the first process should give up trying to reserve and return -EAGAIN. In order for that to happen, we must wake waiting processes when we change sequence, so that they have a chance to detect the new sequence. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/gpu/drm/ttm/ttm_bo.c') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 3ca77dc03915..148a322d8f5d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -224,6 +224,9 @@ int ttm_bo_reserve_locked(struct ttm_buffer_object *bo, int ret; while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) { + /** + * Deadlock avoidance for multi-bo reserving. + */ if (use_sequence && bo->seq_valid && (sequence - bo->val_seq < (1 << 31))) { return -EAGAIN; @@ -241,6 +244,14 @@ int ttm_bo_reserve_locked(struct ttm_buffer_object *bo, } if (use_sequence) { + /** + * Wake up waiters that may need to recheck for deadlock, + * if we decreased the sequence number. + */ + if (unlikely((bo->val_seq - sequence < (1 << 31)) + || !bo->seq_valid)) + wake_up_all(&bo->event_queue); + bo->val_seq = sequence; bo->seq_valid = true; } else { -- cgit v1.2.2