diff options
author | Jerome Glisse <jglisse@redhat.com> | 2012-05-09 15:34:57 +0200 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-05-09 17:22:40 +0100 |
commit | a8c05940bd590d96229bc170a63f14a22fb9c803 (patch) | |
tree | 74619acfa5d70690b437d3477b14513caf22bbc2 /drivers/gpu/drm/radeon/radeon_semaphore.c | |
parent | c3b7fe8b8a0b717f90a4a0c49cffae27e46e3fb7 (diff) | |
download | linux-a8c05940bd590d96229bc170a63f14a22fb9c803.tar.bz2 |
drm/radeon: simplify semaphore handling v2
Directly use the suballocator to get small chunks of memory.
It's equally fast and doesn't crash when we encounter a GPU reset.
v2: rebased on new SA interface.
Signed-off-by: Christian König <deathsimple@vodafone.de>
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_semaphore.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_semaphore.c | 137 |
1 files changed, 23 insertions, 114 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c index dbde874b2e5e..1bc5513a5292 100644 --- a/drivers/gpu/drm/radeon/radeon_semaphore.c +++ b/drivers/gpu/drm/radeon/radeon_semaphore.c @@ -31,118 +31,40 @@ #include "drm.h" #include "radeon.h" -static int radeon_semaphore_add_bo(struct radeon_device *rdev) -{ - struct radeon_semaphore_bo *bo; - unsigned long irq_flags; - uint64_t gpu_addr; - uint32_t *cpu_ptr; - int r, i; - - bo = kmalloc(sizeof(struct radeon_semaphore_bo), GFP_KERNEL); - if (bo == NULL) { - return -ENOMEM; - } - INIT_LIST_HEAD(&bo->free); - INIT_LIST_HEAD(&bo->list); - bo->nused = 0; - - r = radeon_ib_get(rdev, 0, &bo->ib, RADEON_SEMAPHORE_BO_SIZE); - if (r) { - dev_err(rdev->dev, "failed to get a bo after 5 retry\n"); - kfree(bo); - return r; - } - gpu_addr = radeon_sa_bo_gpu_addr(bo->ib->sa_bo); - cpu_ptr = radeon_sa_bo_cpu_addr(bo->ib->sa_bo); - for (i = 0; i < (RADEON_SEMAPHORE_BO_SIZE/8); i++) { - bo->semaphores[i].gpu_addr = gpu_addr; - bo->semaphores[i].cpu_ptr = cpu_ptr; - bo->semaphores[i].bo = bo; - list_add_tail(&bo->semaphores[i].list, &bo->free); - gpu_addr += 8; - cpu_ptr += 2; - } - write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags); - list_add_tail(&bo->list, &rdev->semaphore_drv.bo); - write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags); - return 0; -} - -static void radeon_semaphore_del_bo_locked(struct radeon_device *rdev, - struct radeon_semaphore_bo *bo) -{ - radeon_sa_bo_free(rdev, &bo->ib->sa_bo, NULL); - radeon_fence_unref(&bo->ib->fence); - list_del(&bo->list); - kfree(bo); -} - -void radeon_semaphore_shrink_locked(struct radeon_device *rdev) -{ - struct radeon_semaphore_bo *bo, *n; - - if (list_empty(&rdev->semaphore_drv.bo)) { - return; - } - /* only shrink if first bo has free semaphore */ - bo = list_first_entry(&rdev->semaphore_drv.bo, struct radeon_semaphore_bo, list); - if (list_empty(&bo->free)) { - return; - } - list_for_each_entry_safe_continue(bo, n, &rdev->semaphore_drv.bo, list) { - if (bo->nused) - continue; - radeon_semaphore_del_bo_locked(rdev, bo); - } -} int radeon_semaphore_create(struct radeon_device *rdev, struct radeon_semaphore **semaphore) { - struct radeon_semaphore_bo *bo; - unsigned long irq_flags; - bool do_retry = true; int r; -retry: - *semaphore = NULL; - write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags); - list_for_each_entry(bo, &rdev->semaphore_drv.bo, list) { - if (list_empty(&bo->free)) - continue; - *semaphore = list_first_entry(&bo->free, struct radeon_semaphore, list); - (*semaphore)->cpu_ptr[0] = 0; - (*semaphore)->cpu_ptr[1] = 0; - list_del(&(*semaphore)->list); - bo->nused++; - break; - } - write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags); - + *semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL); if (*semaphore == NULL) { - if (do_retry) { - do_retry = false; - r = radeon_semaphore_add_bo(rdev); - if (r) - return r; - goto retry; - } return -ENOMEM; } - + r = radeon_sa_bo_new(rdev, &rdev->ib_pool.sa_manager, + &(*semaphore)->sa_bo, 8, 8, true); + if (r) { + kfree(*semaphore); + *semaphore = NULL; + return r; + } + (*semaphore)->waiters = 0; + (*semaphore)->gpu_addr = radeon_sa_bo_gpu_addr((*semaphore)->sa_bo); + *((uint64_t*)radeon_sa_bo_cpu_addr((*semaphore)->sa_bo)) = 0; return 0; } void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring, struct radeon_semaphore *semaphore) { + --semaphore->waiters; radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, false); } void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, struct radeon_semaphore *semaphore) { + ++semaphore->waiters; radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, true); } @@ -200,29 +122,16 @@ error: } void radeon_semaphore_free(struct radeon_device *rdev, - struct radeon_semaphore *semaphore) + struct radeon_semaphore *semaphore, + struct radeon_fence *fence) { - unsigned long irq_flags; - - write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags); - semaphore->bo->nused--; - list_add_tail(&semaphore->list, &semaphore->bo->free); - radeon_semaphore_shrink_locked(rdev); - write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags); -} - -void radeon_semaphore_driver_fini(struct radeon_device *rdev) -{ - struct radeon_semaphore_bo *bo, *n; - unsigned long irq_flags; - - write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags); - /* we force to free everything */ - list_for_each_entry_safe(bo, n, &rdev->semaphore_drv.bo, list) { - if (!list_empty(&bo->free)) { - dev_err(rdev->dev, "still in use semaphore\n"); - } - radeon_semaphore_del_bo_locked(rdev, bo); + if (semaphore == NULL) { + return; + } + if (semaphore->waiters > 0) { + dev_err(rdev->dev, "semaphore %p has more waiters than signalers," + " hardware lockup imminent!\n", semaphore); } - write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags); + radeon_sa_bo_free(rdev, &semaphore->sa_bo, fence); + kfree(semaphore); } |