diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index e63cfb7fa390..c23bfd8fe414 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | |||
@@ -28,17 +28,22 @@ | |||
28 | static void amdgpu_ctx_do_release(struct kref *ref) | 28 | static void amdgpu_ctx_do_release(struct kref *ref) |
29 | { | 29 | { |
30 | struct amdgpu_ctx *ctx; | 30 | struct amdgpu_ctx *ctx; |
31 | unsigned i, j; | ||
31 | 32 | ||
32 | ctx = container_of(ref, struct amdgpu_ctx, refcount); | 33 | ctx = container_of(ref, struct amdgpu_ctx, refcount); |
34 | |||
35 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) | ||
36 | for (j = 0; j < AMDGPU_CTX_MAX_CS_PENDING; ++j) | ||
37 | fence_put(ctx->rings[i].fences[j]); | ||
33 | kfree(ctx); | 38 | kfree(ctx); |
34 | } | 39 | } |
35 | 40 | ||
36 | int amdgpu_ctx_alloc(struct amdgpu_device *adev, struct amdgpu_fpriv *fpriv, | 41 | int amdgpu_ctx_alloc(struct amdgpu_device *adev, struct amdgpu_fpriv *fpriv, |
37 | uint32_t *id) | 42 | uint32_t *id) |
38 | { | 43 | { |
39 | int r; | ||
40 | struct amdgpu_ctx *ctx; | 44 | struct amdgpu_ctx *ctx; |
41 | struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr; | 45 | struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr; |
46 | int i, r; | ||
42 | 47 | ||
43 | ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); | 48 | ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); |
44 | if (!ctx) | 49 | if (!ctx) |
@@ -55,6 +60,9 @@ int amdgpu_ctx_alloc(struct amdgpu_device *adev, struct amdgpu_fpriv *fpriv, | |||
55 | 60 | ||
56 | memset(ctx, 0, sizeof(*ctx)); | 61 | memset(ctx, 0, sizeof(*ctx)); |
57 | kref_init(&ctx->refcount); | 62 | kref_init(&ctx->refcount); |
63 | spin_lock_init(&ctx->ring_lock); | ||
64 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) | ||
65 | ctx->rings[i].sequence = 1; | ||
58 | mutex_unlock(&mgr->lock); | 66 | mutex_unlock(&mgr->lock); |
59 | 67 | ||
60 | return 0; | 68 | return 0; |
@@ -177,3 +185,53 @@ int amdgpu_ctx_put(struct amdgpu_ctx *ctx) | |||
177 | kref_put(&ctx->refcount, amdgpu_ctx_do_release); | 185 | kref_put(&ctx->refcount, amdgpu_ctx_do_release); |
178 | return 0; | 186 | return 0; |
179 | } | 187 | } |
188 | |||
189 | uint64_t amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, | ||
190 | struct fence *fence) | ||
191 | { | ||
192 | struct amdgpu_ctx_ring *cring = & ctx->rings[ring->idx]; | ||
193 | uint64_t seq = cring->sequence; | ||
194 | unsigned idx = seq % AMDGPU_CTX_MAX_CS_PENDING; | ||
195 | struct fence *other = cring->fences[idx]; | ||
196 | |||
197 | if (other) { | ||
198 | signed long r; | ||
199 | r = fence_wait_timeout(other, false, MAX_SCHEDULE_TIMEOUT); | ||
200 | if (r < 0) | ||
201 | DRM_ERROR("Error (%ld) waiting for fence!\n", r); | ||
202 | } | ||
203 | |||
204 | fence_get(fence); | ||
205 | |||
206 | spin_lock(&ctx->ring_lock); | ||
207 | cring->fences[idx] = fence; | ||
208 | cring->sequence++; | ||
209 | spin_unlock(&ctx->ring_lock); | ||
210 | |||
211 | fence_put(other); | ||
212 | |||
213 | return seq; | ||
214 | } | ||
215 | |||
216 | struct fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx, | ||
217 | struct amdgpu_ring *ring, uint64_t seq) | ||
218 | { | ||
219 | struct amdgpu_ctx_ring *cring = & ctx->rings[ring->idx]; | ||
220 | struct fence *fence; | ||
221 | |||
222 | spin_lock(&ctx->ring_lock); | ||
223 | if (seq >= cring->sequence) { | ||
224 | spin_unlock(&ctx->ring_lock); | ||
225 | return ERR_PTR(-EINVAL); | ||
226 | } | ||
227 | |||
228 | if (seq < cring->sequence - AMDGPU_CTX_MAX_CS_PENDING) { | ||
229 | spin_unlock(&ctx->ring_lock); | ||
230 | return NULL; | ||
231 | } | ||
232 | |||
233 | fence = fence_get(cring->fences[seq % AMDGPU_CTX_MAX_CS_PENDING]); | ||
234 | spin_unlock(&ctx->ring_lock); | ||
235 | |||
236 | return fence; | ||
237 | } | ||