aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2015-05-11 09:34:59 -0400
committerAlex Deucher <alexander.deucher@amd.com>2015-06-03 21:03:34 -0400
commit3cb485f34049b7f3a00f6f73d2325e0858f64ddb (patch)
treeed523717c68630c27010a39d112b360492b23c93 /drivers
parentd919ad49ac04e1e417ea511d61455786a0f0fdb7 (diff)
drm/amdgpu: fix context switch
Properly protect the state and also handle submission failures. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Jammy Zhou <Jammy.Zhou@amd.com> Reviewed-by: Monk Liu <monk.liu@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c8
5 files changed, 26 insertions, 21 deletions
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 {
893 struct amdgpu_fence *fence; 893 struct amdgpu_fence *fence;
894 struct amdgpu_user_fence *user; 894 struct amdgpu_user_fence *user;
895 struct amdgpu_vm *vm; 895 struct amdgpu_vm *vm;
896 struct amdgpu_ctx *ctx;
896 struct amdgpu_sync sync; 897 struct amdgpu_sync sync;
897 uint32_t gds_base, gds_size; 898 uint32_t gds_base, gds_size;
898 uint32_t gws_base, gws_size; 899 uint32_t gws_base, gws_size;
@@ -943,9 +944,7 @@ struct amdgpu_ring {
943 unsigned wptr_offs; 944 unsigned wptr_offs;
944 unsigned next_rptr_offs; 945 unsigned next_rptr_offs;
945 unsigned fence_offs; 946 unsigned fence_offs;
946 struct drm_file *current_filp; 947 struct amdgpu_ctx *current_ctx;
947 unsigned current_ctx;
948 bool need_ctx_switch;
949 enum amdgpu_ring_type type; 948 enum amdgpu_ring_type type;
950 char name[16]; 949 char name[16];
951}; 950};
@@ -1236,7 +1235,7 @@ struct amdgpu_cs_chunk {
1236struct amdgpu_cs_parser { 1235struct amdgpu_cs_parser {
1237 struct amdgpu_device *adev; 1236 struct amdgpu_device *adev;
1238 struct drm_file *filp; 1237 struct drm_file *filp;
1239 uint32_t ctx_id; 1238 struct amdgpu_ctx *ctx;
1240 struct amdgpu_bo_list *bo_list; 1239 struct amdgpu_bo_list *bo_list;
1241 /* chunks */ 1240 /* chunks */
1242 unsigned nchunks; 1241 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)
138 if (!cs->in.num_chunks) 138 if (!cs->in.num_chunks)
139 goto out; 139 goto out;
140 140
141 p->ctx_id = cs->in.ctx_id; 141 p->ctx = amdgpu_ctx_get(fpriv, cs->in.ctx_id);
142 if (!p->ctx) {
143 r = -EINVAL;
144 goto out;
145 }
142 p->bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle); 146 p->bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle);
143 147
144 /* get chunks */ 148 /* get chunks */
@@ -445,6 +449,8 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo
445 &parser->validated); 449 &parser->validated);
446 } 450 }
447 451
452 if (parser->ctx)
453 amdgpu_ctx_put(parser->ctx);
448 if (parser->bo_list) 454 if (parser->bo_list)
449 amdgpu_bo_list_put(parser->bo_list); 455 amdgpu_bo_list_put(parser->bo_list);
450 drm_free_large(parser->vm_bos); 456 drm_free_large(parser->vm_bos);
@@ -639,13 +645,7 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev,
639 ib->length_dw = chunk_ib->ib_bytes / 4; 645 ib->length_dw = chunk_ib->ib_bytes / 4;
640 646
641 ib->flags = chunk_ib->flags; 647 ib->flags = chunk_ib->flags;
642 648 ib->ctx = parser->ctx;
643 if ((ib->ring->current_filp != parser->filp) ||
644 (ib->ring->current_ctx != parser->ctx_id)) {
645 ib->ring->need_ctx_switch = true;
646 ib->ring->current_ctx = parser->ctx_id;
647 ib->ring->current_filp = parser->filp;
648 }
649 649
650 ib_bo = &parser->ib_bos[j]; 650 ib_bo = &parser->ib_bos[j];
651 ib_bo->robj = aobj; 651 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,
140{ 140{
141 struct amdgpu_ib *ib = &ibs[0]; 141 struct amdgpu_ib *ib = &ibs[0];
142 struct amdgpu_ring *ring; 142 struct amdgpu_ring *ring;
143 struct amdgpu_ctx *ctx, *old_ctx;
143 struct amdgpu_vm *vm; 144 struct amdgpu_vm *vm;
144 unsigned i; 145 unsigned i;
145 int r = 0; 146 int r = 0;
@@ -148,6 +149,7 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs,
148 return -EINVAL; 149 return -EINVAL;
149 150
150 ring = ibs->ring; 151 ring = ibs->ring;
152 ctx = ibs->ctx;
151 vm = ibs->vm; 153 vm = ibs->vm;
152 154
153 if (!ring->ready) { 155 if (!ring->ready) {
@@ -189,19 +191,23 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs,
189 if (ring->funcs->emit_hdp_flush) 191 if (ring->funcs->emit_hdp_flush)
190 amdgpu_ring_emit_hdp_flush(ring); 192 amdgpu_ring_emit_hdp_flush(ring);
191 193
194 old_ctx = ring->current_ctx;
192 for (i = 0; i < num_ibs; ++i) { 195 for (i = 0; i < num_ibs; ++i) {
193 ib = &ibs[i]; 196 ib = &ibs[i];
194 197
195 if (ib->ring != ring) { 198 if (ib->ring != ring || ib->ctx != ctx || ib->vm != vm) {
199 ring->current_ctx = old_ctx;
196 amdgpu_ring_unlock_undo(ring); 200 amdgpu_ring_unlock_undo(ring);
197 return -EINVAL; 201 return -EINVAL;
198 } 202 }
199 amdgpu_ring_emit_ib(ring, ib); 203 amdgpu_ring_emit_ib(ring, ib);
204 ring->current_ctx = ctx;
200 } 205 }
201 206
202 r = amdgpu_fence_emit(ring, owner, &ib->fence); 207 r = amdgpu_fence_emit(ring, owner, &ib->fence);
203 if (r) { 208 if (r) {
204 dev_err(adev->dev, "failed to emit fence (%d)\n", r); 209 dev_err(adev->dev, "failed to emit fence (%d)\n", r);
210 ring->current_ctx = old_ctx;
205 amdgpu_ring_unlock_undo(ring); 211 amdgpu_ring_unlock_undo(ring);
206 return r; 212 return r;
207 } 213 }
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,
2516static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring, 2516static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring,
2517 struct amdgpu_ib *ib) 2517 struct amdgpu_ib *ib)
2518{ 2518{
2519 bool need_ctx_switch = ring->current_ctx != ib->ctx;
2519 u32 header, control = 0; 2520 u32 header, control = 0;
2520 u32 next_rptr = ring->wptr + 5; 2521 u32 next_rptr = ring->wptr + 5;
2521 2522
2522 /* drop the CE preamble IB for the same context */ 2523 /* drop the CE preamble IB for the same context */
2523 if ((ring->type == AMDGPU_RING_TYPE_GFX) && 2524 if ((ring->type == AMDGPU_RING_TYPE_GFX) &&
2524 (ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && 2525 (ib->flags & AMDGPU_IB_FLAG_PREAMBLE) &&
2525 !ring->need_ctx_switch) 2526 !need_ctx_switch)
2526 return; 2527 return;
2527 2528
2528 if (ring->type == AMDGPU_RING_TYPE_COMPUTE) 2529 if (ring->type == AMDGPU_RING_TYPE_COMPUTE)
2529 control |= INDIRECT_BUFFER_VALID; 2530 control |= INDIRECT_BUFFER_VALID;
2530 2531
2531 if (ring->need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) 2532 if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX)
2532 next_rptr += 2; 2533 next_rptr += 2;
2533 2534
2534 next_rptr += 4; 2535 next_rptr += 4;
@@ -2539,10 +2540,9 @@ static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring,
2539 amdgpu_ring_write(ring, next_rptr); 2540 amdgpu_ring_write(ring, next_rptr);
2540 2541
2541 /* insert SWITCH_BUFFER packet before first IB in the ring frame */ 2542 /* insert SWITCH_BUFFER packet before first IB in the ring frame */
2542 if (ring->need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) { 2543 if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) {
2543 amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); 2544 amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
2544 amdgpu_ring_write(ring, 0); 2545 amdgpu_ring_write(ring, 0);
2545 ring->need_ctx_switch = false;
2546 } 2546 }
2547 2547
2548 if (ib->flags & AMDGPU_IB_FLAG_CE) 2548 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)
3645static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, 3645static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring,
3646 struct amdgpu_ib *ib) 3646 struct amdgpu_ib *ib)
3647{ 3647{
3648 bool need_ctx_switch = ring->current_ctx != ib->ctx;
3648 u32 header, control = 0; 3649 u32 header, control = 0;
3649 u32 next_rptr = ring->wptr + 5; 3650 u32 next_rptr = ring->wptr + 5;
3650 3651
3651 /* drop the CE preamble IB for the same context */ 3652 /* drop the CE preamble IB for the same context */
3652 if ((ring->type == AMDGPU_RING_TYPE_GFX) && 3653 if ((ring->type == AMDGPU_RING_TYPE_GFX) &&
3653 (ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && 3654 (ib->flags & AMDGPU_IB_FLAG_PREAMBLE) &&
3654 !ring->need_ctx_switch) 3655 !need_ctx_switch)
3655 return; 3656 return;
3656 3657
3657 if (ring->type == AMDGPU_RING_TYPE_COMPUTE) 3658 if (ring->type == AMDGPU_RING_TYPE_COMPUTE)
3658 control |= INDIRECT_BUFFER_VALID; 3659 control |= INDIRECT_BUFFER_VALID;
3659 3660
3660 if (ring->need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) 3661 if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX)
3661 next_rptr += 2; 3662 next_rptr += 2;
3662 3663
3663 next_rptr += 4; 3664 next_rptr += 4;
@@ -3668,10 +3669,9 @@ static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring,
3668 amdgpu_ring_write(ring, next_rptr); 3669 amdgpu_ring_write(ring, next_rptr);
3669 3670
3670 /* insert SWITCH_BUFFER packet before first IB in the ring frame */ 3671 /* insert SWITCH_BUFFER packet before first IB in the ring frame */
3671 if (ring->need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) { 3672 if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) {
3672 amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); 3673 amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
3673 amdgpu_ring_write(ring, 0); 3674 amdgpu_ring_write(ring, 0);
3674 ring->need_ctx_switch = false;
3675 } 3675 }
3676 3676
3677 if (ib->flags & AMDGPU_IB_FLAG_CE) 3677 if (ib->flags & AMDGPU_IB_FLAG_CE)