diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-21 13:48:00 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-21 13:48:00 -0700 |
commit | 266c73b77706f2d05b4a3e70a5bb702ed35431d6 (patch) | |
tree | 381461b90a8bd10c0c36b0cdbb2e6e4bbf6c5e87 /drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | |
parent | 2c856e14dad8cb1b085ae1f30c5e125c6d46019b (diff) | |
parent | 568d7c764ae01f3706085ac8f0d8a8ac7e826bd7 (diff) | |
download | talos-op-linux-266c73b77706f2d05b4a3e70a5bb702ed35431d6.tar.gz talos-op-linux-266c73b77706f2d05b4a3e70a5bb702ed35431d6.zip |
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie:
"This is the main drm pull request for 4.6 kernel.
Overall the coolest thing here for me is the nouveau maxwell signed
firmware support from NVidia, it's taken a long while to extract this
from them.
I also wish the ARM vendors just designed one set of display IP, ARM
display block proliferation is definitely increasing.
Core:
- drm_event cleanups
- Internal API cleanup making mode_fixup optional.
- Apple GMUX vga switcheroo support.
- DP AUX testing interface
Panel:
- Refactoring of DSI core for use over more transports.
New driver:
- ARM hdlcd driver
i915:
- FBC/PSR (framebuffer compression, panel self refresh) enabled by default.
- Ongoing atomic display support work
- Ongoing runtime PM work
- Pixel clock limit checks
- VBT DSI description support
- GEM fixes
- GuC firmware scheduler enhancements
amdkfd:
- Deferred probing fixes to avoid make file or link ordering.
amdgpu/radeon:
- ACP support for i2s audio support.
- Command Submission/GPU scheduler/GPUVM optimisations
- Initial GPU reset support for amdgpu
vmwgfx:
- Support for DX10 gen mipmaps
- Pageflipping and other fixes.
exynos:
- Exynos5420 SoC support for FIMD
- Exynos5422 SoC support for MIPI-DSI
nouveau:
- GM20x secure boot support - adds acceleration for Maxwell GPUs.
- GM200 support
- GM20B clock driver support
- Power sensors work
etnaviv:
- Correctness fixes for GPU cache flushing
- Better support for i.MX6 systems.
imx-drm:
- VBlank IRQ support
- Fence support
- OF endpoint support
msm:
- HDMI support for 8996 (snapdragon 820)
- Adreno 430 support
- Timestamp queries support
virtio-gpu:
- Fixes for Android support.
rockchip:
- Add support for Innosilicion HDMI
rcar-du:
- Support for 4 crtcs
- R8A7795 support
- RCar Gen 3 support
omapdrm:
- HDMI interlace output support
- dma-buf import support
- Refactoring to remove a lot of legacy code.
tilcdc:
- Rewrite of pageflipping code
- dma-buf support
- pinctrl support
vc4:
- HDMI modesetting bug fixes
- Significant 3D performance improvement.
fsl-dcu (FreeScale):
- Lots of fixes
tegra:
- Two small fixes
sti:
- Atomic support for planes
- Improved HDMI support"
* 'drm-next' of git://people.freedesktop.org/~airlied/linux: (1063 commits)
drm/amdgpu: release_pages requires linux/pagemap.h
drm/sti: restore mode_fixup callback
drm/amdgpu/gfx7: add MTYPE definition
drm/amdgpu: removing BO_VAs shouldn't be interruptible
drm/amd/powerplay: show uvd/vce power gate enablement for tonga.
drm/amd/powerplay: show uvd/vce power gate info for fiji
drm/amdgpu: use sched fence if possible
drm/amdgpu: move ib.fence to job.fence
drm/amdgpu: give a fence param to ib_free
drm/amdgpu: include the right version of gmc header files for iceland
drm/radeon: fix indentation.
drm/amd/powerplay: add uvd/vce dpm enabling flag to fix the performance issue for CZ
drm/amdgpu: switch back to 32bit hw fences v2
drm/amdgpu: remove amdgpu_fence_is_signaled
drm/amdgpu: drop the extra fence range check v2
drm/amdgpu: signal fences directly in amdgpu_fence_process
drm/amdgpu: cleanup amdgpu_fence_wait_empty v2
drm/amdgpu: keep all fences in an RCU protected array v2
drm/amdgpu: add number of hardware submissions to amdgpu_fence_driver_init_ring
drm/amdgpu: RCU protected amd_sched_fence_release
...
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | 238 |
1 files changed, 72 insertions, 166 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c index 181ce39ef5e5..c48b4fce5e57 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c @@ -37,6 +37,8 @@ struct amdgpu_sync_entry { struct fence *fence; }; +static struct kmem_cache *amdgpu_sync_slab; + /** * amdgpu_sync_create - zero init sync object * @@ -46,26 +48,22 @@ struct amdgpu_sync_entry { */ void amdgpu_sync_create(struct amdgpu_sync *sync) { - unsigned i; - - for (i = 0; i < AMDGPU_NUM_SYNCS; ++i) - sync->semaphores[i] = NULL; - - for (i = 0; i < AMDGPU_MAX_RINGS; ++i) - sync->sync_to[i] = NULL; - hash_init(sync->fences); sync->last_vm_update = NULL; } +/** + * amdgpu_sync_same_dev - test if fence belong to us + * + * @adev: amdgpu device to use for the test + * @f: fence to test + * + * Test if the fence was issued by us. + */ static bool amdgpu_sync_same_dev(struct amdgpu_device *adev, struct fence *f) { - struct amdgpu_fence *a_fence = to_amdgpu_fence(f); struct amd_sched_fence *s_fence = to_amd_sched_fence(f); - if (a_fence) - return a_fence->ring->adev == adev; - if (s_fence) { struct amdgpu_ring *ring; @@ -76,17 +74,31 @@ static bool amdgpu_sync_same_dev(struct amdgpu_device *adev, struct fence *f) return false; } -static bool amdgpu_sync_test_owner(struct fence *f, void *owner) +/** + * amdgpu_sync_get_owner - extract the owner of a fence + * + * @fence: fence get the owner from + * + * Extract who originally created the fence. + */ +static void *amdgpu_sync_get_owner(struct fence *f) { - struct amdgpu_fence *a_fence = to_amdgpu_fence(f); struct amd_sched_fence *s_fence = to_amd_sched_fence(f); + if (s_fence) - return s_fence->owner == owner; - if (a_fence) - return a_fence->owner == owner; - return false; + return s_fence->owner; + + return AMDGPU_FENCE_OWNER_UNDEFINED; } +/** + * amdgpu_sync_keep_later - Keep the later fence + * + * @keep: existing fence to test + * @fence: new fence + * + * Either keep the existing fence or the new one, depending which one is later. + */ static void amdgpu_sync_keep_later(struct fence **keep, struct fence *fence) { if (*keep && fence_is_later(*keep, fence)) @@ -107,59 +119,39 @@ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync, struct fence *f) { struct amdgpu_sync_entry *e; - struct amdgpu_fence *fence; if (!f) return 0; if (amdgpu_sync_same_dev(adev, f) && - amdgpu_sync_test_owner(f, AMDGPU_FENCE_OWNER_VM)) + amdgpu_sync_get_owner(f) == AMDGPU_FENCE_OWNER_VM) amdgpu_sync_keep_later(&sync->last_vm_update, f); - fence = to_amdgpu_fence(f); - if (!fence || fence->ring->adev != adev) { - hash_for_each_possible(sync->fences, e, node, f->context) { - if (unlikely(e->fence->context != f->context)) - continue; - - amdgpu_sync_keep_later(&e->fence, f); - return 0; - } - - e = kmalloc(sizeof(struct amdgpu_sync_entry), GFP_KERNEL); - if (!e) - return -ENOMEM; + hash_for_each_possible(sync->fences, e, node, f->context) { + if (unlikely(e->fence->context != f->context)) + continue; - hash_add(sync->fences, &e->node, f->context); - e->fence = fence_get(f); + amdgpu_sync_keep_later(&e->fence, f); return 0; } - amdgpu_sync_keep_later(&sync->sync_to[fence->ring->idx], f); + e = kmem_cache_alloc(amdgpu_sync_slab, GFP_KERNEL); + if (!e) + return -ENOMEM; + hash_add(sync->fences, &e->node, f->context); + e->fence = fence_get(f); return 0; } -static void *amdgpu_sync_get_owner(struct fence *f) -{ - struct amdgpu_fence *a_fence = to_amdgpu_fence(f); - struct amd_sched_fence *s_fence = to_amd_sched_fence(f); - - if (s_fence) - return s_fence->owner; - else if (a_fence) - return a_fence->owner; - return AMDGPU_FENCE_OWNER_UNDEFINED; -} - /** - * amdgpu_sync_resv - use the semaphores to sync to a reservation object + * amdgpu_sync_resv - sync to a reservation object * * @sync: sync object to add fences from reservation object to * @resv: reservation object with embedded fence * @shared: true if we should only sync to the exclusive fence * - * Sync to the fence using the semaphore objects + * Sync to the fence */ int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync, @@ -224,7 +216,7 @@ struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync) f = e->fence; hash_del(&e->node); - kfree(e); + kmem_cache_free(amdgpu_sync_slab, e); if (!fence_is_signaled(f)) return f; @@ -247,109 +239,7 @@ int amdgpu_sync_wait(struct amdgpu_sync *sync) hash_del(&e->node); fence_put(e->fence); - kfree(e); - } - - if (amdgpu_enable_semaphores) - return 0; - - for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { - struct fence *fence = sync->sync_to[i]; - if (!fence) - continue; - - r = fence_wait(fence, false); - if (r) - return r; - } - - return 0; -} - -/** - * amdgpu_sync_rings - sync ring to all registered fences - * - * @sync: sync object to use - * @ring: ring that needs sync - * - * Ensure that all registered fences are signaled before letting - * the ring continue. The caller must hold the ring lock. - */ -int amdgpu_sync_rings(struct amdgpu_sync *sync, - struct amdgpu_ring *ring) -{ - struct amdgpu_device *adev = ring->adev; - unsigned count = 0; - int i, r; - - for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { - struct amdgpu_ring *other = adev->rings[i]; - struct amdgpu_semaphore *semaphore; - struct amdgpu_fence *fence; - - if (!sync->sync_to[i]) - continue; - - fence = to_amdgpu_fence(sync->sync_to[i]); - - /* check if we really need to sync */ - if (!amdgpu_enable_scheduler && - !amdgpu_fence_need_sync(fence, ring)) - continue; - - /* prevent GPU deadlocks */ - if (!other->ready) { - dev_err(adev->dev, "Syncing to a disabled ring!"); - return -EINVAL; - } - - if (amdgpu_enable_scheduler || !amdgpu_enable_semaphores) { - r = fence_wait(sync->sync_to[i], true); - if (r) - return r; - continue; - } - - if (count >= AMDGPU_NUM_SYNCS) { - /* not enough room, wait manually */ - r = fence_wait(&fence->base, false); - if (r) - return r; - continue; - } - r = amdgpu_semaphore_create(adev, &semaphore); - if (r) - return r; - - sync->semaphores[count++] = semaphore; - - /* allocate enough space for sync command */ - r = amdgpu_ring_alloc(other, 16); - if (r) - return r; - - /* emit the signal semaphore */ - if (!amdgpu_semaphore_emit_signal(other, semaphore)) { - /* signaling wasn't successful wait manually */ - amdgpu_ring_undo(other); - r = fence_wait(&fence->base, false); - if (r) - return r; - continue; - } - - /* we assume caller has already allocated space on waiters ring */ - if (!amdgpu_semaphore_emit_wait(ring, semaphore)) { - /* waiting wasn't successful wait manually */ - amdgpu_ring_undo(other); - r = fence_wait(&fence->base, false); - if (r) - return r; - continue; - } - - amdgpu_ring_commit(other); - amdgpu_fence_note_sync(fence, ring); + kmem_cache_free(amdgpu_sync_slab, e); } return 0; @@ -358,15 +248,11 @@ int amdgpu_sync_rings(struct amdgpu_sync *sync, /** * amdgpu_sync_free - free the sync object * - * @adev: amdgpu_device pointer * @sync: sync object to use - * @fence: fence to use for the free * - * Free the sync object by freeing all semaphores in it. + * Free the sync object. */ -void amdgpu_sync_free(struct amdgpu_device *adev, - struct amdgpu_sync *sync, - struct fence *fence) +void amdgpu_sync_free(struct amdgpu_sync *sync) { struct amdgpu_sync_entry *e; struct hlist_node *tmp; @@ -375,14 +261,34 @@ void amdgpu_sync_free(struct amdgpu_device *adev, hash_for_each_safe(sync->fences, i, tmp, e, node) { hash_del(&e->node); fence_put(e->fence); - kfree(e); + kmem_cache_free(amdgpu_sync_slab, e); } - for (i = 0; i < AMDGPU_NUM_SYNCS; ++i) - amdgpu_semaphore_free(adev, &sync->semaphores[i], fence); + fence_put(sync->last_vm_update); +} + +/** + * amdgpu_sync_init - init sync object subsystem + * + * Allocate the slab allocator. + */ +int amdgpu_sync_init(void) +{ + amdgpu_sync_slab = kmem_cache_create( + "amdgpu_sync", sizeof(struct amdgpu_sync_entry), 0, + SLAB_HWCACHE_ALIGN, NULL); + if (!amdgpu_sync_slab) + return -ENOMEM; - for (i = 0; i < AMDGPU_MAX_RINGS; ++i) - fence_put(sync->sync_to[i]); + return 0; +} - fence_put(sync->last_vm_update); +/** + * amdgpu_sync_fini - fini sync object subsystem + * + * Free the slab allocator. + */ +void amdgpu_sync_fini(void) +{ + kmem_cache_destroy(amdgpu_sync_slab); } |