From d38ceaf99ed015f2a0b9af3499791bd3a3daae21 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 20 Apr 2015 16:55:21 -0400 Subject: drm/amdgpu: add core driver (v4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the non-asic specific core driver code. v2: remove extra kconfig option v3: implement minor fixes from Fengguang Wu v4: fix cast in amdgpu_ucode.c Acked-by: Christian König Acked-by: Jammy Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 345 +++++++++++++++++++++++++++++++++ 1 file changed, 345 insertions(+) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c new file mode 100644 index 000000000000..847cab2b3fff --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -0,0 +1,345 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + * Christian König + */ +#include +#include +#include +#include +#include "amdgpu.h" +#include "atom.h" + +/* + * IB + * IBs (Indirect Buffers) and areas of GPU accessible memory where + * commands are stored. You can put a pointer to the IB in the + * command ring and the hw will fetch the commands from the IB + * and execute them. Generally userspace acceleration drivers + * produce command buffers which are send to the kernel and + * put in IBs for execution by the requested ring. + */ +static int amdgpu_debugfs_sa_init(struct amdgpu_device *adev); + +/** + * amdgpu_ib_get - request an IB (Indirect Buffer) + * + * @ring: ring index the IB is associated with + * @size: requested IB size + * @ib: IB object returned + * + * Request an IB (all asics). IBs are allocated using the + * suballocator. + * Returns 0 on success, error on failure. + */ +int amdgpu_ib_get(struct amdgpu_ring *ring, struct amdgpu_vm *vm, + unsigned size, struct amdgpu_ib *ib) +{ + struct amdgpu_device *adev = ring->adev; + int r; + + if (size) { + r = amdgpu_sa_bo_new(adev, &adev->ring_tmp_bo, + &ib->sa_bo, size, 256); + if (r) { + dev_err(adev->dev, "failed to get a new IB (%d)\n", r); + return r; + } + + ib->ptr = amdgpu_sa_bo_cpu_addr(ib->sa_bo); + + if (!vm) + ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo); + else + ib->gpu_addr = 0; + + } else { + ib->sa_bo = NULL; + ib->ptr = NULL; + ib->gpu_addr = 0; + } + + amdgpu_sync_create(&ib->sync); + + ib->ring = ring; + ib->fence = NULL; + ib->user = NULL; + ib->vm = vm; + ib->is_const_ib = false; + ib->gds_base = 0; + ib->gds_size = 0; + ib->gws_base = 0; + ib->gws_size = 0; + ib->oa_base = 0; + ib->oa_size = 0; + + return 0; +} + +/** + * amdgpu_ib_free - free an IB (Indirect Buffer) + * + * @adev: amdgpu_device pointer + * @ib: IB object to free + * + * Free an IB (all asics). + */ +void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib) +{ + amdgpu_sync_free(adev, &ib->sync, ib->fence); + amdgpu_sa_bo_free(adev, &ib->sa_bo, ib->fence); + amdgpu_fence_unref(&ib->fence); +} + +/** + * amdgpu_ib_schedule - schedule an IB (Indirect Buffer) on the ring + * + * @adev: amdgpu_device pointer + * @num_ibs: number of IBs to schedule + * @ibs: IB objects to schedule + * @owner: owner for creating the fences + * + * Schedule an IB on the associated ring (all asics). + * Returns 0 on success, error on failure. + * + * On SI, there are two parallel engines fed from the primary ring, + * the CE (Constant Engine) and the DE (Drawing Engine). Since + * resource descriptors have moved to memory, the CE allows you to + * prime the caches while the DE is updating register state so that + * the resource descriptors will be already in cache when the draw is + * processed. To accomplish this, the userspace driver submits two + * IBs, one for the CE and one for the DE. If there is a CE IB (called + * a CONST_IB), it will be put on the ring prior to the DE IB. Prior + * to SI there was just a DE IB. + */ +int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs, + struct amdgpu_ib *ibs, void *owner) +{ + struct amdgpu_ring *ring; + struct amdgpu_vm *vm = ibs->vm; + struct amdgpu_ib *ib = &ibs[0]; + unsigned i; + int r = 0; + bool flush_hdp = true; + + if (num_ibs == 0) + return -EINVAL; + + ring = ibs->ring; + if (!ring->ready) { + dev_err(adev->dev, "couldn't schedule ib\n"); + return -EINVAL; + } + + r = amdgpu_ring_lock(ring, (256 + AMDGPU_NUM_SYNCS * 8) * num_ibs); + if (r) { + dev_err(adev->dev, "scheduling IB failed (%d).\n", r); + return r; + } + + if (vm) { + /* grab a vm id if necessary */ + struct amdgpu_fence *vm_id_fence = NULL; + vm_id_fence = amdgpu_vm_grab_id(ibs->ring, ibs->vm); + amdgpu_sync_fence(&ibs->sync, vm_id_fence); + } + + r = amdgpu_sync_rings(&ibs->sync, ring); + if (r) { + amdgpu_ring_unlock_undo(ring); + dev_err(adev->dev, "failed to sync rings (%d)\n", r); + return r; + } + + if (vm) { + /* do context switch */ + amdgpu_vm_flush(ring, vm, ib->sync.last_vm_update); + } + + if (ring->funcs->emit_gds_switch && ib->vm && ib->gds_needed) + amdgpu_ring_emit_gds_switch(ring, ib->vm->ids[ring->idx].id, + ib->gds_base, ib->gds_size, + ib->gws_base, ib->gws_size, + ib->oa_base, ib->oa_size); + + for (i = 0; i < num_ibs; ++i) { + ib = &ibs[i]; + + if (ib->ring != ring) { + amdgpu_ring_unlock_undo(ring); + return -EINVAL; + } + ib->flush_hdp_writefifo = flush_hdp; + flush_hdp = false; + amdgpu_ring_emit_ib(ring, ib); + } + + r = amdgpu_fence_emit(ring, owner, &ib->fence); + if (r) { + dev_err(adev->dev, "failed to emit fence (%d)\n", r); + amdgpu_ring_unlock_undo(ring); + return r; + } + + /* wrap the last IB with fence */ + if (ib->user) { + uint64_t addr = amdgpu_bo_gpu_offset(ib->user->bo); + addr += ib->user->offset; + amdgpu_ring_emit_fence(ring, addr, ib->fence->seq, true); + } + + if (ib->vm) + amdgpu_vm_fence(adev, ib->vm, ib->fence); + + amdgpu_ring_unlock_commit(ring); + return 0; +} + +/** + * amdgpu_ib_pool_init - Init the IB (Indirect Buffer) pool + * + * @adev: amdgpu_device pointer + * + * Initialize the suballocator to manage a pool of memory + * for use as IBs (all asics). + * Returns 0 on success, error on failure. + */ +int amdgpu_ib_pool_init(struct amdgpu_device *adev) +{ + int r; + + if (adev->ib_pool_ready) { + return 0; + } + r = amdgpu_sa_bo_manager_init(adev, &adev->ring_tmp_bo, + AMDGPU_IB_POOL_SIZE*64*1024, + AMDGPU_GPU_PAGE_SIZE, + AMDGPU_GEM_DOMAIN_GTT); + if (r) { + return r; + } + + r = amdgpu_sa_bo_manager_start(adev, &adev->ring_tmp_bo); + if (r) { + return r; + } + + adev->ib_pool_ready = true; + if (amdgpu_debugfs_sa_init(adev)) { + dev_err(adev->dev, "failed to register debugfs file for SA\n"); + } + return 0; +} + +/** + * amdgpu_ib_pool_fini - Free the IB (Indirect Buffer) pool + * + * @adev: amdgpu_device pointer + * + * Tear down the suballocator managing the pool of memory + * for use as IBs (all asics). + */ +void amdgpu_ib_pool_fini(struct amdgpu_device *adev) +{ + if (adev->ib_pool_ready) { + amdgpu_sa_bo_manager_suspend(adev, &adev->ring_tmp_bo); + amdgpu_sa_bo_manager_fini(adev, &adev->ring_tmp_bo); + adev->ib_pool_ready = false; + } +} + +/** + * amdgpu_ib_ring_tests - test IBs on the rings + * + * @adev: amdgpu_device pointer + * + * Test an IB (Indirect Buffer) on each ring. + * If the test fails, disable the ring. + * Returns 0 on success, error if the primary GFX ring + * IB test fails. + */ +int amdgpu_ib_ring_tests(struct amdgpu_device *adev) +{ + unsigned i; + int r; + + for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { + struct amdgpu_ring *ring = adev->rings[i]; + + if (!ring || !ring->ready) + continue; + + r = amdgpu_ring_test_ib(ring); + if (r) { + ring->ready = false; + adev->needs_reset = false; + + if (ring == &adev->gfx.gfx_ring[0]) { + /* oh, oh, that's really bad */ + DRM_ERROR("amdgpu: failed testing IB on GFX ring (%d).\n", r); + adev->accel_working = false; + return r; + + } else { + /* still not good, but we can live with it */ + DRM_ERROR("amdgpu: failed testing IB on ring %d (%d).\n", i, r); + } + } + } + return 0; +} + +/* + * Debugfs info + */ +#if defined(CONFIG_DEBUG_FS) + +static int amdgpu_debugfs_sa_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct amdgpu_device *adev = dev->dev_private; + + amdgpu_sa_bo_dump_debug_info(&adev->ring_tmp_bo, m); + + return 0; + +} + +static struct drm_info_list amdgpu_debugfs_sa_list[] = { + {"amdgpu_sa_info", &amdgpu_debugfs_sa_info, 0, NULL}, +}; + +#endif + +static int amdgpu_debugfs_sa_init(struct amdgpu_device *adev) +{ +#if defined(CONFIG_DEBUG_FS) + return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_sa_list, 1); +#else + return 0; +#endif +} -- cgit v1.2.3 From de807f818b953f11b9a132a2d1997711a79bbfa3 Mon Sep 17 00:00:00 2001 From: Jammy Zhou Date: Mon, 11 May 2015 23:41:41 +0800 Subject: drm/amdgpu: add flags for amdgpu_ib structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jammy Zhou Reviewed-by: Christian König --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 ++---- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 2 +- 5 files changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index a88302c0c93a..aaa62f33870f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -892,13 +892,12 @@ struct amdgpu_ib { struct amdgpu_fence *fence; struct amdgpu_user_fence *user; struct amdgpu_vm *vm; - bool is_const_ib; bool flush_hdp_writefifo; struct amdgpu_sync sync; - bool gds_needed; uint32_t gds_base, gds_size; uint32_t gws_base, gws_size; uint32_t oa_base, oa_size; + uint32_t flags; }; enum amdgpu_ring_type { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 1035e443700f..de17f845a84b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -638,10 +638,8 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev, } ib->length_dw = chunk_ib->ib_bytes / 4; - if (chunk_ib->flags & AMDGPU_IB_FLAG_CE) - ib->is_const_ib = true; - if (chunk_ib->flags & AMDGPU_IB_FLAG_GDS) - ib->gds_needed = true; + ib->flags = chunk_ib->flags; + if ((ib->ring->current_filp != parser->filp) || (ib->ring->current_ctx != parser->ctx_id)) { ib->ring->need_ctx_switch = true; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 847cab2b3fff..a83ff03ffc80 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -88,13 +88,13 @@ int amdgpu_ib_get(struct amdgpu_ring *ring, struct amdgpu_vm *vm, ib->fence = NULL; ib->user = NULL; ib->vm = vm; - ib->is_const_ib = false; ib->gds_base = 0; ib->gds_size = 0; ib->gws_base = 0; ib->gws_size = 0; ib->oa_base = 0; ib->oa_size = 0; + ib->flags = 0; return 0; } @@ -179,7 +179,7 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs, amdgpu_vm_flush(ring, vm, ib->sync.last_vm_update); } - if (ring->funcs->emit_gds_switch && ib->vm && ib->gds_needed) + if (ring->funcs->emit_gds_switch && ib->vm && (ib->flags & AMDGPU_IB_FLAG_GDS)) amdgpu_ring_emit_gds_switch(ring, ib->vm->ids[ring->idx].id, ib->gds_base, ib->gds_size, ib->gws_base, ib->gws_size, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 26df23eaf09e..7428c4305418 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -2544,7 +2544,7 @@ static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring, ring->need_ctx_switch = false; } - if (ib->is_const_ib) + if (ib->flags & AMDGPU_IB_FLAG_CE) header = PACKET3(PACKET3_INDIRECT_BUFFER_CONST, 2); else header = PACKET3(PACKET3_INDIRECT_BUFFER, 2); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 3762998df351..48de9204ff5e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -3673,7 +3673,7 @@ static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, ring->need_ctx_switch = false; } - if (ib->is_const_ib) + if (ib->flags & AMDGPU_IB_FLAG_CE) header = PACKET3(PACKET3_INDIRECT_BUFFER_CONST, 2); else header = PACKET3(PACKET3_INDIRECT_BUFFER, 2); -- cgit v1.2.3 From 66782cec7ad8f48c09d96ee59b713f694265cfa1 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 11 May 2015 13:52:09 +0200 Subject: drm/amdgpu: always emit GDS switch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise a process can access the GDS data of another process. Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Jammy Zhou Reviewed-by: Monk Liu --- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index a83ff03ffc80..f2442b2cec00 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -179,7 +179,7 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs, amdgpu_vm_flush(ring, vm, ib->sync.last_vm_update); } - if (ring->funcs->emit_gds_switch && ib->vm && (ib->flags & AMDGPU_IB_FLAG_GDS)) + if (vm && ring->funcs->emit_gds_switch) amdgpu_ring_emit_gds_switch(ring, ib->vm->ids[ring->idx].id, ib->gds_base, ib->gds_size, ib->gws_base, ib->gws_size, -- cgit v1.2.3 From d2edb07b10fce5127a60671b55ca53921c212bc3 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 11 May 2015 14:10:34 +0200 Subject: drm/amdgpu: cleanup HDP flush handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Jammy Zhou Reviewed-by: Monk Liu --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 15 +++------------ drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 11 +++-------- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 9 ++------- drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 13 ++----------- drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 15 +++------------ 7 files changed, 18 insertions(+), 54 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index aaa62f33870f..72d9d9ec5c9f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -382,6 +382,7 @@ struct amdgpu_ring_funcs { bool emit_wait); void (*emit_vm_flush)(struct amdgpu_ring *ring, unsigned vm_id, uint64_t pd_addr); + void (*emit_hdp_flush)(struct amdgpu_ring *ring); void (*emit_gds_switch)(struct amdgpu_ring *ring, uint32_t vmid, uint32_t gds_base, uint32_t gds_size, uint32_t gws_base, uint32_t gws_size, @@ -892,7 +893,6 @@ struct amdgpu_ib { struct amdgpu_fence *fence; struct amdgpu_user_fence *user; struct amdgpu_vm *vm; - bool flush_hdp_writefifo; struct amdgpu_sync sync; uint32_t gds_base, gds_size; uint32_t gws_base, gws_size; @@ -2203,6 +2203,7 @@ static inline void amdgpu_ring_write(struct amdgpu_ring *ring, uint32_t v) #define amdgpu_ring_emit_fence(r, addr, seq, write64bit) (r)->funcs->emit_fence((r), (addr), (seq), (write64bit)) #define amdgpu_ring_emit_semaphore(r, semaphore, emit_wait) (r)->funcs->emit_semaphore((r), (semaphore), (emit_wait)) #define amdgpu_ring_emit_gds_switch(r, v, db, ds, wb, ws, ab, as) (r)->funcs->emit_gds_switch((r), (v), (db), (ds), (wb), (ws), (ab), (as)) +#define amdgpu_ring_emit_hdp_flush(r) (r)->funcs->emit_hdp_flush((r)) #define amdgpu_ih_get_wptr(adev) (adev)->irq.ih_funcs->get_wptr((adev)) #define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv)) #define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index f2442b2cec00..66c66f83b407 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -143,7 +143,6 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs, struct amdgpu_ib *ib = &ibs[0]; unsigned i; int r = 0; - bool flush_hdp = true; if (num_ibs == 0) return -EINVAL; @@ -185,6 +184,9 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs, ib->gws_base, ib->gws_size, ib->oa_base, ib->oa_size); + if (ring->funcs->emit_hdp_flush) + amdgpu_ring_emit_hdp_flush(ring); + for (i = 0; i < num_ibs; ++i) { ib = &ibs[i]; @@ -192,8 +194,6 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs, amdgpu_ring_unlock_undo(ring); return -EINVAL; } - ib->flush_hdp_writefifo = flush_hdp; - flush_hdp = false; amdgpu_ring_emit_ib(ring, ib); } diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index 037e3db69547..d5055ea4d112 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -188,8 +188,6 @@ static void cik_sdma_ring_set_wptr(struct amdgpu_ring *ring) WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[me], (ring->wptr << 2) & 0x3fffc); } -static void cik_sdma_hdp_flush_ring_emit(struct amdgpu_ring *); - /** * cik_sdma_ring_emit_ib - Schedule an IB on the DMA engine * @@ -204,9 +202,6 @@ static void cik_sdma_ring_emit_ib(struct amdgpu_ring *ring, u32 extra_bits = (ib->vm ? ib->vm->ids[ring->idx].id : 0) & 0xf; u32 next_rptr = ring->wptr + 5; - if (ib->flush_hdp_writefifo) - next_rptr += 6; - while ((next_rptr & 7) != 4) next_rptr++; @@ -217,11 +212,6 @@ static void cik_sdma_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, 1); /* number of DWs to follow */ amdgpu_ring_write(ring, next_rptr); - if (ib->flush_hdp_writefifo) { - /* flush HDP */ - cik_sdma_hdp_flush_ring_emit(ring); - } - /* IB packet must end on a 8 DW boundary */ while ((ring->wptr & 7) != 4) amdgpu_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0)); @@ -233,13 +223,13 @@ static void cik_sdma_ring_emit_ib(struct amdgpu_ring *ring, } /** - * cik_sdma_hdp_flush_ring_emit - emit an hdp flush on the DMA ring + * cik_sdma_ring_emit_hdp_flush - emit an hdp flush on the DMA ring * * @ring: amdgpu ring pointer * * Emit an hdp flush packet on the requested DMA ring. */ -static void cik_sdma_hdp_flush_ring_emit(struct amdgpu_ring *ring) +static void cik_sdma_ring_emit_hdp_flush(struct amdgpu_ring *ring) { u32 extra_bits = (SDMA_POLL_REG_MEM_EXTRA_OP(1) | SDMA_POLL_REG_MEM_EXTRA_FUNC(3)); /* == */ @@ -1317,6 +1307,7 @@ static const struct amdgpu_ring_funcs cik_sdma_ring_funcs = { .emit_fence = cik_sdma_ring_emit_fence, .emit_semaphore = cik_sdma_ring_emit_semaphore, .emit_vm_flush = cik_sdma_ring_emit_vm_flush, + .emit_hdp_flush = cik_sdma_ring_emit_hdp_flush, .test_ring = cik_sdma_ring_test_ring, .test_ib = cik_sdma_ring_test_ib, .is_lockup = cik_sdma_ring_is_lockup, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index cec46ebae5f7..855b5272f4b5 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -2366,14 +2366,14 @@ static int gfx_v7_0_ring_test_ring(struct amdgpu_ring *ring) } /** - * gfx_v7_0_hdp_flush_cp_ring_emit - emit an hdp flush on the cp + * gfx_v7_0_ring_emit_hdp - emit an hdp flush on the cp * * @adev: amdgpu_device pointer * @ridx: amdgpu ring index * * Emits an hdp flush on the cp. */ -static void gfx_v7_0_hdp_flush_cp_ring_emit(struct amdgpu_ring *ring) +static void gfx_v7_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) { u32 ref_and_mask; @@ -2528,9 +2528,6 @@ static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring, if (ring->type == AMDGPU_RING_TYPE_COMPUTE) control |= INDIRECT_BUFFER_VALID; - if (ib->flush_hdp_writefifo) - next_rptr += 7; - if (ring->need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) next_rptr += 2; @@ -2541,9 +2538,6 @@ static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff); amdgpu_ring_write(ring, next_rptr); - if (ib->flush_hdp_writefifo) - gfx_v7_0_hdp_flush_cp_ring_emit(ring); - /* insert SWITCH_BUFFER packet before first IB in the ring frame */ if (ring->need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) { amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); @@ -5522,6 +5516,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = { .emit_semaphore = gfx_v7_0_ring_emit_semaphore, .emit_vm_flush = gfx_v7_0_ring_emit_vm_flush, .emit_gds_switch = gfx_v7_0_ring_emit_gds_switch, + .emit_hdp_flush = gfx_v7_0_ring_emit_hdp_flush, .test_ring = gfx_v7_0_ring_test_ring, .test_ib = gfx_v7_0_ring_test_ib, .is_lockup = gfx_v7_0_ring_is_lockup, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index fc8c46209db4..63ed3b01cea1 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -3610,7 +3610,7 @@ static void gfx_v8_0_ring_set_wptr_gfx(struct amdgpu_ring *ring) } } -static void gfx_v8_0_hdp_flush_cp_ring_emit(struct amdgpu_ring *ring) +static void gfx_v8_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) { u32 ref_and_mask, reg_mem_engine; @@ -3657,9 +3657,6 @@ static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, if (ring->type == AMDGPU_RING_TYPE_COMPUTE) control |= INDIRECT_BUFFER_VALID; - if (ib->flush_hdp_writefifo) - next_rptr += 7; - if (ring->need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) next_rptr += 2; @@ -3670,9 +3667,6 @@ static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff); amdgpu_ring_write(ring, next_rptr); - if (ib->flush_hdp_writefifo) - gfx_v8_0_hdp_flush_cp_ring_emit(ring); - /* insert SWITCH_BUFFER packet before first IB in the ring frame */ if (ring->need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) { amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); @@ -4149,6 +4143,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = { .emit_semaphore = gfx_v8_0_ring_emit_semaphore, .emit_vm_flush = gfx_v8_0_ring_emit_vm_flush, .emit_gds_switch = gfx_v8_0_ring_emit_gds_switch, + .emit_hdp_flush = gfx_v8_0_ring_emit_hdp_flush, .test_ring = gfx_v8_0_ring_test_ring, .test_ib = gfx_v8_0_ring_test_ib, .is_lockup = gfx_v8_0_ring_is_lockup, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index 389509aeddf8..f1423a412867 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -214,8 +214,6 @@ static void sdma_v2_4_ring_set_wptr(struct amdgpu_ring *ring) WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[me], ring->wptr << 2); } -static void sdma_v2_4_hdp_flush_ring_emit(struct amdgpu_ring *); - /** * sdma_v2_4_ring_emit_ib - Schedule an IB on the DMA engine * @@ -230,9 +228,6 @@ static void sdma_v2_4_ring_emit_ib(struct amdgpu_ring *ring, u32 vmid = (ib->vm ? ib->vm->ids[ring->idx].id : 0) & 0xf; u32 next_rptr = ring->wptr + 5; - if (ib->flush_hdp_writefifo) - next_rptr += 6; - while ((next_rptr & 7) != 2) next_rptr++; @@ -245,11 +240,6 @@ static void sdma_v2_4_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, SDMA_PKT_WRITE_UNTILED_DW_3_COUNT(1)); amdgpu_ring_write(ring, next_rptr); - if (ib->flush_hdp_writefifo) { - /* flush HDP */ - sdma_v2_4_hdp_flush_ring_emit(ring); - } - /* IB packet must end on a 8 DW boundary */ while ((ring->wptr & 7) != 2) amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_NOP)); @@ -271,7 +261,7 @@ static void sdma_v2_4_ring_emit_ib(struct amdgpu_ring *ring, * * Emit an hdp flush packet on the requested DMA ring. */ -static void sdma_v2_4_hdp_flush_ring_emit(struct amdgpu_ring *ring) +static void sdma_v2_4_ring_emit_hdp_flush(struct amdgpu_ring *ring) { u32 ref_and_mask = 0; @@ -1340,6 +1330,7 @@ static const struct amdgpu_ring_funcs sdma_v2_4_ring_funcs = { .emit_fence = sdma_v2_4_ring_emit_fence, .emit_semaphore = sdma_v2_4_ring_emit_semaphore, .emit_vm_flush = sdma_v2_4_ring_emit_vm_flush, + .emit_hdp_flush = sdma_v2_4_ring_emit_hdp_flush, .test_ring = sdma_v2_4_ring_test_ring, .test_ib = sdma_v2_4_ring_test_ib, .is_lockup = sdma_v2_4_ring_is_lockup, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index d3eda315e719..7c4abff5005d 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -269,8 +269,6 @@ static void sdma_v3_0_ring_set_wptr(struct amdgpu_ring *ring) } } -static void sdma_v3_0_hdp_flush_ring_emit(struct amdgpu_ring *); - /** * sdma_v3_0_ring_emit_ib - Schedule an IB on the DMA engine * @@ -285,9 +283,6 @@ static void sdma_v3_0_ring_emit_ib(struct amdgpu_ring *ring, u32 vmid = (ib->vm ? ib->vm->ids[ring->idx].id : 0) & 0xf; u32 next_rptr = ring->wptr + 5; - if (ib->flush_hdp_writefifo) - next_rptr += 6; - while ((next_rptr & 7) != 2) next_rptr++; next_rptr += 6; @@ -299,11 +294,6 @@ static void sdma_v3_0_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, SDMA_PKT_WRITE_UNTILED_DW_3_COUNT(1)); amdgpu_ring_write(ring, next_rptr); - /* flush HDP */ - if (ib->flush_hdp_writefifo) { - sdma_v3_0_hdp_flush_ring_emit(ring); - } - /* IB packet must end on a 8 DW boundary */ while ((ring->wptr & 7) != 2) amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_NOP)); @@ -320,13 +310,13 @@ static void sdma_v3_0_ring_emit_ib(struct amdgpu_ring *ring, } /** - * sdma_v3_0_hdp_flush_ring_emit - emit an hdp flush on the DMA ring + * sdma_v3_0_ring_emit_hdp_flush - emit an hdp flush on the DMA ring * * @ring: amdgpu ring pointer * * Emit an hdp flush packet on the requested DMA ring. */ -static void sdma_v3_0_hdp_flush_ring_emit(struct amdgpu_ring *ring) +static void sdma_v3_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) { u32 ref_and_mask = 0; @@ -1407,6 +1397,7 @@ static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = { .emit_fence = sdma_v3_0_ring_emit_fence, .emit_semaphore = sdma_v3_0_ring_emit_semaphore, .emit_vm_flush = sdma_v3_0_ring_emit_vm_flush, + .emit_hdp_flush = sdma_v3_0_ring_emit_hdp_flush, .test_ring = sdma_v3_0_ring_test_ring, .test_ib = sdma_v3_0_ring_test_ib, .is_lockup = sdma_v3_0_ring_is_lockup, -- cgit v1.2.3 From d919ad49ac04e1e417ea511d61455786a0f0fdb7 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 11 May 2015 14:32:17 +0200 Subject: drm/amdgpu: fix dereference before check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Jammy Zhou Reviewed-by: Monk Liu --- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 66c66f83b407..74ed94ee7102 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -138,9 +138,9 @@ void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib) int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs, struct amdgpu_ib *ibs, void *owner) { - struct amdgpu_ring *ring; - struct amdgpu_vm *vm = ibs->vm; struct amdgpu_ib *ib = &ibs[0]; + struct amdgpu_ring *ring; + struct amdgpu_vm *vm; unsigned i; int r = 0; @@ -148,6 +148,8 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs, return -EINVAL; ring = ibs->ring; + vm = ibs->vm; + if (!ring->ready) { dev_err(adev->dev, "couldn't schedule ib\n"); return -EINVAL; -- cgit v1.2.3 From 3cb485f34049b7f3a00f6f73d2325e0858f64ddb Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 11 May 2015 15:34:59 +0200 Subject: drm/amdgpu: fix context switch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Properly protect the state and also handle submission failures. Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Jammy Zhou Reviewed-by: Monk Liu --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 7 +++---- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 16 ++++++++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 8 +++++++- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 8 ++++---- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 8 ++++---- 5 files changed, 26 insertions(+), 21 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 72d9d9ec5c9f..003fa2d12bfb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -893,6 +893,7 @@ struct amdgpu_ib { struct amdgpu_fence *fence; struct amdgpu_user_fence *user; struct amdgpu_vm *vm; + struct amdgpu_ctx *ctx; struct amdgpu_sync sync; uint32_t gds_base, gds_size; uint32_t gws_base, gws_size; @@ -943,9 +944,7 @@ struct amdgpu_ring { unsigned wptr_offs; unsigned next_rptr_offs; unsigned fence_offs; - struct drm_file *current_filp; - unsigned current_ctx; - bool need_ctx_switch; + struct amdgpu_ctx *current_ctx; enum amdgpu_ring_type type; char name[16]; }; @@ -1236,7 +1235,7 @@ struct amdgpu_cs_chunk { struct amdgpu_cs_parser { struct amdgpu_device *adev; struct drm_file *filp; - uint32_t ctx_id; + struct amdgpu_ctx *ctx; struct amdgpu_bo_list *bo_list; /* chunks */ unsigned nchunks; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index de17f845a84b..ecb30a1a73cc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -138,7 +138,11 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) if (!cs->in.num_chunks) goto out; - p->ctx_id = cs->in.ctx_id; + p->ctx = amdgpu_ctx_get(fpriv, cs->in.ctx_id); + if (!p->ctx) { + r = -EINVAL; + goto out; + } p->bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle); /* get chunks */ @@ -445,6 +449,8 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo &parser->validated); } + if (parser->ctx) + amdgpu_ctx_put(parser->ctx); if (parser->bo_list) amdgpu_bo_list_put(parser->bo_list); drm_free_large(parser->vm_bos); @@ -639,13 +645,7 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev, ib->length_dw = chunk_ib->ib_bytes / 4; ib->flags = chunk_ib->flags; - - if ((ib->ring->current_filp != parser->filp) || - (ib->ring->current_ctx != parser->ctx_id)) { - ib->ring->need_ctx_switch = true; - ib->ring->current_ctx = parser->ctx_id; - ib->ring->current_filp = parser->filp; - } + ib->ctx = parser->ctx; ib_bo = &parser->ib_bos[j]; ib_bo->robj = aobj; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 74ed94ee7102..560c5fd347be 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -140,6 +140,7 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs, { struct amdgpu_ib *ib = &ibs[0]; struct amdgpu_ring *ring; + struct amdgpu_ctx *ctx, *old_ctx; struct amdgpu_vm *vm; unsigned i; int r = 0; @@ -148,6 +149,7 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs, return -EINVAL; ring = ibs->ring; + ctx = ibs->ctx; vm = ibs->vm; if (!ring->ready) { @@ -189,19 +191,23 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs, if (ring->funcs->emit_hdp_flush) amdgpu_ring_emit_hdp_flush(ring); + old_ctx = ring->current_ctx; for (i = 0; i < num_ibs; ++i) { ib = &ibs[i]; - if (ib->ring != ring) { + if (ib->ring != ring || ib->ctx != ctx || ib->vm != vm) { + ring->current_ctx = old_ctx; amdgpu_ring_unlock_undo(ring); return -EINVAL; } amdgpu_ring_emit_ib(ring, ib); + ring->current_ctx = ctx; } r = amdgpu_fence_emit(ring, owner, &ib->fence); if (r) { dev_err(adev->dev, "failed to emit fence (%d)\n", r); + ring->current_ctx = old_ctx; amdgpu_ring_unlock_undo(ring); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 855b5272f4b5..5315c13a8921 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -2516,19 +2516,20 @@ static bool gfx_v7_0_ring_emit_semaphore(struct amdgpu_ring *ring, static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib) { + bool need_ctx_switch = ring->current_ctx != ib->ctx; u32 header, control = 0; u32 next_rptr = ring->wptr + 5; /* drop the CE preamble IB for the same context */ if ((ring->type == AMDGPU_RING_TYPE_GFX) && (ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && - !ring->need_ctx_switch) + !need_ctx_switch) return; if (ring->type == AMDGPU_RING_TYPE_COMPUTE) control |= INDIRECT_BUFFER_VALID; - if (ring->need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) + if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) next_rptr += 2; next_rptr += 4; @@ -2539,10 +2540,9 @@ static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, next_rptr); /* insert SWITCH_BUFFER packet before first IB in the ring frame */ - if (ring->need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) { + if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) { amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); amdgpu_ring_write(ring, 0); - ring->need_ctx_switch = false; } if (ib->flags & AMDGPU_IB_FLAG_CE) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 63ed3b01cea1..188a7abbddaf 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -3645,19 +3645,20 @@ static void gfx_v8_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib) { + bool need_ctx_switch = ring->current_ctx != ib->ctx; u32 header, control = 0; u32 next_rptr = ring->wptr + 5; /* drop the CE preamble IB for the same context */ if ((ring->type == AMDGPU_RING_TYPE_GFX) && (ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && - !ring->need_ctx_switch) + !need_ctx_switch) return; if (ring->type == AMDGPU_RING_TYPE_COMPUTE) control |= INDIRECT_BUFFER_VALID; - if (ring->need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) + if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) next_rptr += 2; next_rptr += 4; @@ -3668,10 +3669,9 @@ static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, next_rptr); /* insert SWITCH_BUFFER packet before first IB in the ring frame */ - if (ring->need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) { + if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) { amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); amdgpu_ring_write(ring, 0); - ring->need_ctx_switch = false; } if (ib->flags & AMDGPU_IB_FLAG_CE) -- cgit v1.2.3 From 890ee23fc60193d7c2bca17e099569f1510b3053 Mon Sep 17 00:00:00 2001 From: Chunming Zhou Date: Mon, 1 Jun 2015 14:35:03 +0800 Subject: drm/amdgpu: disable user fence interrupt (v2) amdgpu submits both kernel and user fences, but just need one interrupt, disable user fence interrupt and don't effect user fence. v2: fix merge error Signed-off-by: Chunming Zhou Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 7 +++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 4 +++- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h | 2 +- drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 3 ++- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 13 +++++++++---- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 14 ++++++++++---- drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | 4 ++-- 13 files changed, 46 insertions(+), 26 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index c33c1af36fa2..37aeed7b454d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -317,7 +317,7 @@ struct amdgpu_ring_funcs { void (*emit_ib)(struct amdgpu_ring *ring, struct amdgpu_ib *ib); void (*emit_fence)(struct amdgpu_ring *ring, uint64_t addr, - uint64_t seq, bool write64bit); + uint64_t seq, unsigned flags); bool (*emit_semaphore)(struct amdgpu_ring *ring, struct amdgpu_semaphore *semaphore, bool emit_wait); @@ -392,6 +392,9 @@ struct amdgpu_fence_driver { #define AMDGPU_FENCE_OWNER_VM ((void*)1ul) #define AMDGPU_FENCE_OWNER_MOVE ((void*)2ul) +#define AMDGPU_FENCE_FLAG_64BIT (1 << 0) +#define AMDGPU_FENCE_FLAG_INT (1 << 1) + struct amdgpu_fence { struct fence base; @@ -2142,7 +2145,7 @@ static inline void amdgpu_ring_write(struct amdgpu_ring *ring, uint32_t v) #define amdgpu_ring_set_wptr(r) (r)->funcs->set_wptr((r)) #define amdgpu_ring_emit_ib(r, ib) (r)->funcs->emit_ib((r), (ib)) #define amdgpu_ring_emit_vm_flush(r, vmid, addr) (r)->funcs->emit_vm_flush((r), (vmid), (addr)) -#define amdgpu_ring_emit_fence(r, addr, seq, write64bit) (r)->funcs->emit_fence((r), (addr), (seq), (write64bit)) +#define amdgpu_ring_emit_fence(r, addr, seq, flags) (r)->funcs->emit_fence((r), (addr), (seq), (flags)) #define amdgpu_ring_emit_semaphore(r, semaphore, emit_wait) (r)->funcs->emit_semaphore((r), (semaphore), (emit_wait)) #define amdgpu_ring_emit_gds_switch(r, v, db, ds, wb, ws, ab, as) (r)->funcs->emit_gds_switch((r), (v), (db), (ds), (wb), (ws), (ab), (as)) #define amdgpu_ring_emit_hdp_flush(r) (r)->funcs->emit_hdp_flush((r)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c index 48ca637c5029..5c9918d01bf9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c @@ -128,7 +128,9 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, void *owner, fence_init(&(*fence)->base, &amdgpu_fence_ops, &adev->fence_queue.lock, adev->fence_context + ring->idx, (*fence)->seq); - amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, (*fence)->seq, false); + amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, + (*fence)->seq, + AMDGPU_FENCE_FLAG_INT); trace_amdgpu_fence_emit(ring->adev->ddev, ring->idx, (*fence)->seq); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 560c5fd347be..52dff75aac6f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -216,7 +216,8 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs, if (ib->user) { uint64_t addr = amdgpu_bo_gpu_offset(ib->user->bo); addr += ib->user->offset; - amdgpu_ring_emit_fence(ring, addr, ib->fence->seq, true); + amdgpu_ring_emit_fence(ring, addr, ib->fence->seq, + AMDGPU_FENCE_FLAG_64BIT); } if (ib->vm) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index 62018b37273e..1127a504f118 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -637,9 +637,9 @@ void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib) * */ void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, - bool write64bits) + unsigned flags) { - WARN_ON(write64bits); + WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT); amdgpu_ring_write(ring, VCE_CMD_FENCE); amdgpu_ring_write(ring, addr); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h index 4294854912e7..b6a9d0956c60 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h @@ -40,7 +40,7 @@ bool amdgpu_vce_ring_emit_semaphore(struct amdgpu_ring *ring, bool emit_wait); void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib); void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, - bool write64bit); + unsigned flags); int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring); int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring); diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index ef5e9f9b5ab2..fb931638a7e6 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -259,8 +259,9 @@ static void cik_sdma_ring_emit_hdp_flush(struct amdgpu_ring *ring) * an interrupt if needed (CIK). */ static void cik_sdma_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, - bool write64bit) + unsigned flags) { + bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT; /* write the fence */ amdgpu_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_FENCE, 0, 0)); amdgpu_ring_write(ring, lower_32_bits(addr)); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 5fefe402e085..afa703c0efeb 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -2414,8 +2414,10 @@ static void gfx_v7_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) * GPU caches. */ static void gfx_v7_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr, - u64 seq, bool write64bit) + u64 seq, unsigned flags) { + bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT; + bool int_sel = flags & AMDGPU_FENCE_FLAG_INT; /* Workaround for cache flush problems. First send a dummy EOP * event down the pipe with seq one below. */ @@ -2438,7 +2440,7 @@ static void gfx_v7_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr, EVENT_INDEX(5))); amdgpu_ring_write(ring, addr & 0xfffffffc); amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xffff) | - DATA_SEL(write64bit ? 2 : 1) | INT_SEL(2)); + DATA_SEL(write64bit ? 2 : 1) | INT_SEL(int_sel ? 2 : 0)); amdgpu_ring_write(ring, lower_32_bits(seq)); amdgpu_ring_write(ring, upper_32_bits(seq)); } @@ -2454,15 +2456,18 @@ static void gfx_v7_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr, */ static void gfx_v7_0_ring_emit_fence_compute(struct amdgpu_ring *ring, u64 addr, u64 seq, - bool write64bits) + unsigned flags) { + bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT; + bool int_sel = flags & AMDGPU_FENCE_FLAG_INT; + /* RELEASE_MEM - flush caches, send int */ amdgpu_ring_write(ring, PACKET3(PACKET3_RELEASE_MEM, 5)); amdgpu_ring_write(ring, (EOP_TCL1_ACTION_EN | EOP_TC_ACTION_EN | EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5))); - amdgpu_ring_write(ring, DATA_SEL(write64bits ? 2 : 1) | INT_SEL(2)); + amdgpu_ring_write(ring, DATA_SEL(write64bit ? 2 : 1) | INT_SEL(int_sel ? 2 : 0)); amdgpu_ring_write(ring, addr & 0xfffffffc); amdgpu_ring_write(ring, upper_32_bits(addr)); amdgpu_ring_write(ring, lower_32_bits(seq)); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 04b91523008c..6ae2d6be126a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -3713,8 +3713,11 @@ static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, } static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr, - u64 seq, bool write64bit) + u64 seq, unsigned flags) { + bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT; + bool int_sel = flags & AMDGPU_FENCE_FLAG_INT; + /* EVENT_WRITE_EOP - flush caches, send int */ amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); amdgpu_ring_write(ring, (EOP_TCL1_ACTION_EN | @@ -3723,7 +3726,7 @@ static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr, EVENT_INDEX(5))); amdgpu_ring_write(ring, addr & 0xfffffffc); amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xffff) | - DATA_SEL(write64bit ? 2 : 1) | INT_SEL(2)); + DATA_SEL(write64bit ? 2 : 1) | INT_SEL(int_sel ? 2 : 0)); amdgpu_ring_write(ring, lower_32_bits(seq)); amdgpu_ring_write(ring, upper_32_bits(seq)); } @@ -3880,15 +3883,18 @@ static void gfx_v8_0_ring_set_wptr_compute(struct amdgpu_ring *ring) static void gfx_v8_0_ring_emit_fence_compute(struct amdgpu_ring *ring, u64 addr, u64 seq, - bool write64bits) + unsigned flags) { + bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT; + bool int_sel = flags & AMDGPU_FENCE_FLAG_INT; + /* RELEASE_MEM - flush caches, send int */ amdgpu_ring_write(ring, PACKET3(PACKET3_RELEASE_MEM, 5)); amdgpu_ring_write(ring, (EOP_TCL1_ACTION_EN | EOP_TC_ACTION_EN | EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5))); - amdgpu_ring_write(ring, DATA_SEL(write64bits ? 2 : 1) | INT_SEL(2)); + amdgpu_ring_write(ring, DATA_SEL(write64bit ? 2 : 1) | INT_SEL(int_sel ? 2 : 0)); amdgpu_ring_write(ring, addr & 0xfffffffc); amdgpu_ring_write(ring, upper_32_bits(addr)); amdgpu_ring_write(ring, lower_32_bits(seq)); diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index d09aa7eeb40e..d7895885fe0c 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -292,8 +292,9 @@ static void sdma_v2_4_ring_emit_hdp_flush(struct amdgpu_ring *ring) * an interrupt if needed (VI). */ static void sdma_v2_4_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, - bool write64bits) + unsigned flags) { + bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT; /* write the fence */ amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE)); amdgpu_ring_write(ring, lower_32_bits(addr)); @@ -301,7 +302,7 @@ static void sdma_v2_4_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se amdgpu_ring_write(ring, lower_32_bits(seq)); /* optionally write high bits as well */ - if (write64bits) { + if (write64bit) { addr += 4; amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE)); amdgpu_ring_write(ring, lower_32_bits(addr)); diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index 555c0e1e4c97..e3c1fde75363 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -347,8 +347,9 @@ static void sdma_v3_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) * an interrupt if needed (VI). */ static void sdma_v3_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, - bool write64bits) + unsigned flags) { + bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT; /* write the fence */ amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE)); amdgpu_ring_write(ring, lower_32_bits(addr)); @@ -356,7 +357,7 @@ static void sdma_v3_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se amdgpu_ring_write(ring, lower_32_bits(seq)); /* optionally write high bits as well */ - if (write64bits) { + if (write64bit) { addr += 4; amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE)); amdgpu_ring_write(ring, lower_32_bits(addr)); diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c index 292932a73c81..4efd671d7a9b 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c @@ -417,9 +417,9 @@ static void uvd_v4_2_stop(struct amdgpu_device *adev) * Write a fence and a trap command to the ring. */ static void uvd_v4_2_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, - bool write64bit) + unsigned flags) { - WARN_ON(write64bit); + WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT); amdgpu_ring_write(ring, PACKET0(mmUVD_CONTEXT_ID, 0)); amdgpu_ring_write(ring, seq); diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c index 004c56496fc4..b756bd99c0fd 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c @@ -461,9 +461,9 @@ static void uvd_v5_0_stop(struct amdgpu_device *adev) * Write a fence and a trap command to the ring. */ static void uvd_v5_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, - bool write64bit) + unsigned flags) { - WARN_ON(write64bit); + WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT); amdgpu_ring_write(ring, PACKET0(mmUVD_CONTEXT_ID, 0)); amdgpu_ring_write(ring, seq); diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index 8c790fb31e2f..49aa931b2cb4 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -457,9 +457,9 @@ static void uvd_v6_0_stop(struct amdgpu_device *adev) * Write a fence and a trap command to the ring. */ static void uvd_v6_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, - bool write64bit) + unsigned flags) { - WARN_ON(write64bit); + WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT); amdgpu_ring_write(ring, PACKET0(mmUVD_CONTEXT_ID, 0)); amdgpu_ring_write(ring, seq); -- cgit v1.2.3