diff options
author | Christian König <christian.koenig@amd.com> | 2015-05-11 09:34:59 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2015-06-03 21:03:34 -0400 |
commit | 3cb485f34049b7f3a00f6f73d2325e0858f64ddb (patch) | |
tree | ed523717c68630c27010a39d112b360492b23c93 /drivers | |
parent | d919ad49ac04e1e417ea511d61455786a0f0fdb7 (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.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 8 |
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 { | |||
1236 | struct amdgpu_cs_parser { | 1235 | struct 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, | |||
2516 | static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring, | 2516 | static 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) | |||
3645 | static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, | 3645 | static 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) |