]> Git Repo - linux.git/blob - drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
drm/amdgpu: use entity instead of ring for CS
[linux.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_ctx.c
1 /*
2  * Copyright 2015 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: monk liu <[email protected]>
23  */
24
25 #include <drm/drmP.h>
26 #include <drm/drm_auth.h>
27 #include "amdgpu.h"
28 #include "amdgpu_sched.h"
29
30 #define to_amdgpu_ctx_ring(e)   \
31         container_of((e), struct amdgpu_ctx_ring, entity)
32
33 static int amdgpu_ctx_priority_permit(struct drm_file *filp,
34                                       enum drm_sched_priority priority)
35 {
36         /* NORMAL and below are accessible by everyone */
37         if (priority <= DRM_SCHED_PRIORITY_NORMAL)
38                 return 0;
39
40         if (capable(CAP_SYS_NICE))
41                 return 0;
42
43         if (drm_is_current_master(filp))
44                 return 0;
45
46         return -EACCES;
47 }
48
49 static int amdgpu_ctx_init(struct amdgpu_device *adev,
50                            enum drm_sched_priority priority,
51                            struct drm_file *filp,
52                            struct amdgpu_ctx *ctx)
53 {
54         struct drm_sched_rq *sdma_rqs[AMDGPU_MAX_RINGS];
55         struct drm_sched_rq *comp_rqs[AMDGPU_MAX_RINGS];
56         unsigned i, j, num_sdma_rqs, num_comp_rqs;
57         int r;
58
59         if (priority < 0 || priority >= DRM_SCHED_PRIORITY_MAX)
60                 return -EINVAL;
61
62         r = amdgpu_ctx_priority_permit(filp, priority);
63         if (r)
64                 return r;
65
66         memset(ctx, 0, sizeof(*ctx));
67         ctx->adev = adev;
68         kref_init(&ctx->refcount);
69         spin_lock_init(&ctx->ring_lock);
70         ctx->fences = kcalloc(amdgpu_sched_jobs * AMDGPU_MAX_RINGS,
71                               sizeof(struct dma_fence*), GFP_KERNEL);
72         if (!ctx->fences)
73                 return -ENOMEM;
74
75         mutex_init(&ctx->lock);
76
77         for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
78                 ctx->rings[i].sequence = 1;
79                 ctx->rings[i].fences = &ctx->fences[amdgpu_sched_jobs * i];
80         }
81
82         ctx->reset_counter = atomic_read(&adev->gpu_reset_counter);
83         ctx->reset_counter_query = ctx->reset_counter;
84         ctx->vram_lost_counter = atomic_read(&adev->vram_lost_counter);
85         ctx->init_priority = priority;
86         ctx->override_priority = DRM_SCHED_PRIORITY_UNSET;
87
88         num_sdma_rqs = 0;
89         num_comp_rqs = 0;
90         for (i = 0; i < adev->num_rings; i++) {
91                 struct amdgpu_ring *ring = adev->rings[i];
92                 struct drm_sched_rq *rq;
93
94                 rq = &ring->sched.sched_rq[priority];
95                 if (ring->funcs->type == AMDGPU_RING_TYPE_SDMA)
96                         sdma_rqs[num_sdma_rqs++] = rq;
97                 else if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE)
98                         comp_rqs[num_comp_rqs++] = rq;
99         }
100
101         /* create context entity for each ring */
102         for (i = 0; i < adev->num_rings; i++) {
103                 struct amdgpu_ring *ring = adev->rings[i];
104
105                 if (ring == &adev->gfx.kiq.ring)
106                         continue;
107
108                 if (ring->funcs->type == AMDGPU_RING_TYPE_SDMA) {
109                         r = drm_sched_entity_init(&ctx->rings[i].entity,
110                                                   sdma_rqs, num_sdma_rqs,
111                                                   &ctx->guilty);
112                 } else if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) {
113                         r = drm_sched_entity_init(&ctx->rings[i].entity,
114                                                   comp_rqs, num_comp_rqs,
115                                                   &ctx->guilty);
116                 } else {
117                         struct drm_sched_rq *rq;
118
119                         rq = &ring->sched.sched_rq[priority];
120                         r = drm_sched_entity_init(&ctx->rings[i].entity,
121                                                   &rq, 1, &ctx->guilty);
122                 }
123                 if (r)
124                         goto failed;
125         }
126
127         return 0;
128
129 failed:
130         for (j = 0; j < i; j++)
131                 drm_sched_entity_destroy(&ctx->rings[j].entity);
132         kfree(ctx->fences);
133         ctx->fences = NULL;
134         return r;
135 }
136
137 static void amdgpu_ctx_fini(struct kref *ref)
138 {
139         struct amdgpu_ctx *ctx = container_of(ref, struct amdgpu_ctx, refcount);
140         struct amdgpu_device *adev = ctx->adev;
141         unsigned i, j;
142
143         if (!adev)
144                 return;
145
146         for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
147                 for (j = 0; j < amdgpu_sched_jobs; ++j)
148                         dma_fence_put(ctx->rings[i].fences[j]);
149         kfree(ctx->fences);
150         ctx->fences = NULL;
151
152         mutex_destroy(&ctx->lock);
153
154         kfree(ctx);
155 }
156
157 int amdgpu_ctx_get_entity(struct amdgpu_ctx *ctx, u32 hw_ip, u32 instance,
158                           u32 ring, struct drm_sched_entity **entity)
159 {
160         struct amdgpu_device *adev = ctx->adev;
161         unsigned num_rings = 0;
162         struct amdgpu_ring *out_ring;
163
164         /* Right now all IPs have only one instance - multiple rings. */
165         if (instance != 0) {
166                 DRM_DEBUG("invalid ip instance: %d\n", instance);
167                 return -EINVAL;
168         }
169
170         switch (hw_ip) {
171         case AMDGPU_HW_IP_GFX:
172                 out_ring = &adev->gfx.gfx_ring[ring];
173                 num_rings = adev->gfx.num_gfx_rings;
174                 break;
175         case AMDGPU_HW_IP_COMPUTE:
176                 out_ring = &adev->gfx.compute_ring[ring];
177                 num_rings = adev->gfx.num_compute_rings;
178                 break;
179         case AMDGPU_HW_IP_DMA:
180                 out_ring = &adev->sdma.instance[ring].ring;
181                 num_rings = adev->sdma.num_instances;
182                 break;
183         case AMDGPU_HW_IP_UVD:
184                 out_ring = &adev->uvd.inst[0].ring;
185                 num_rings = adev->uvd.num_uvd_inst;
186                 break;
187         case AMDGPU_HW_IP_VCE:
188                 out_ring = &adev->vce.ring[ring];
189                 num_rings = adev->vce.num_rings;
190                 break;
191         case AMDGPU_HW_IP_UVD_ENC:
192                 out_ring = &adev->uvd.inst[0].ring_enc[ring];
193                 num_rings = adev->uvd.num_enc_rings;
194                 break;
195         case AMDGPU_HW_IP_VCN_DEC:
196                 out_ring = &adev->vcn.ring_dec;
197                 num_rings = 1;
198                 break;
199         case AMDGPU_HW_IP_VCN_ENC:
200                 out_ring = &adev->vcn.ring_enc[ring];
201                 num_rings = adev->vcn.num_enc_rings;
202                 break;
203         case AMDGPU_HW_IP_VCN_JPEG:
204                 out_ring = &adev->vcn.ring_jpeg;
205                 num_rings = 1;
206                 break;
207         default:
208                 DRM_ERROR("unknown HW IP type: %d\n", hw_ip);
209                 return -EINVAL;
210         }
211
212         if (ring > num_rings)
213                 return -EINVAL;
214
215         *entity = &ctx->rings[out_ring->idx].entity;
216         return 0;
217 }
218
219 static int amdgpu_ctx_alloc(struct amdgpu_device *adev,
220                             struct amdgpu_fpriv *fpriv,
221                             struct drm_file *filp,
222                             enum drm_sched_priority priority,
223                             uint32_t *id)
224 {
225         struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr;
226         struct amdgpu_ctx *ctx;
227         int r;
228
229         ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
230         if (!ctx)
231                 return -ENOMEM;
232
233         mutex_lock(&mgr->lock);
234         r = idr_alloc(&mgr->ctx_handles, ctx, 1, 0, GFP_KERNEL);
235         if (r < 0) {
236                 mutex_unlock(&mgr->lock);
237                 kfree(ctx);
238                 return r;
239         }
240
241         *id = (uint32_t)r;
242         r = amdgpu_ctx_init(adev, priority, filp, ctx);
243         if (r) {
244                 idr_remove(&mgr->ctx_handles, *id);
245                 *id = 0;
246                 kfree(ctx);
247         }
248         mutex_unlock(&mgr->lock);
249         return r;
250 }
251
252 static void amdgpu_ctx_do_release(struct kref *ref)
253 {
254         struct amdgpu_ctx *ctx;
255         u32 i;
256
257         ctx = container_of(ref, struct amdgpu_ctx, refcount);
258
259         for (i = 0; i < ctx->adev->num_rings; i++) {
260
261                 if (ctx->adev->rings[i] == &ctx->adev->gfx.kiq.ring)
262                         continue;
263
264                 drm_sched_entity_destroy(&ctx->rings[i].entity);
265         }
266
267         amdgpu_ctx_fini(ref);
268 }
269
270 static int amdgpu_ctx_free(struct amdgpu_fpriv *fpriv, uint32_t id)
271 {
272         struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr;
273         struct amdgpu_ctx *ctx;
274
275         mutex_lock(&mgr->lock);
276         ctx = idr_remove(&mgr->ctx_handles, id);
277         if (ctx)
278                 kref_put(&ctx->refcount, amdgpu_ctx_do_release);
279         mutex_unlock(&mgr->lock);
280         return ctx ? 0 : -EINVAL;
281 }
282
283 static int amdgpu_ctx_query(struct amdgpu_device *adev,
284                             struct amdgpu_fpriv *fpriv, uint32_t id,
285                             union drm_amdgpu_ctx_out *out)
286 {
287         struct amdgpu_ctx *ctx;
288         struct amdgpu_ctx_mgr *mgr;
289         unsigned reset_counter;
290
291         if (!fpriv)
292                 return -EINVAL;
293
294         mgr = &fpriv->ctx_mgr;
295         mutex_lock(&mgr->lock);
296         ctx = idr_find(&mgr->ctx_handles, id);
297         if (!ctx) {
298                 mutex_unlock(&mgr->lock);
299                 return -EINVAL;
300         }
301
302         /* TODO: these two are always zero */
303         out->state.flags = 0x0;
304         out->state.hangs = 0x0;
305
306         /* determine if a GPU reset has occured since the last call */
307         reset_counter = atomic_read(&adev->gpu_reset_counter);
308         /* TODO: this should ideally return NO, GUILTY, or INNOCENT. */
309         if (ctx->reset_counter_query == reset_counter)
310                 out->state.reset_status = AMDGPU_CTX_NO_RESET;
311         else
312                 out->state.reset_status = AMDGPU_CTX_UNKNOWN_RESET;
313         ctx->reset_counter_query = reset_counter;
314
315         mutex_unlock(&mgr->lock);
316         return 0;
317 }
318
319 static int amdgpu_ctx_query2(struct amdgpu_device *adev,
320         struct amdgpu_fpriv *fpriv, uint32_t id,
321         union drm_amdgpu_ctx_out *out)
322 {
323         struct amdgpu_ctx *ctx;
324         struct amdgpu_ctx_mgr *mgr;
325
326         if (!fpriv)
327                 return -EINVAL;
328
329         mgr = &fpriv->ctx_mgr;
330         mutex_lock(&mgr->lock);
331         ctx = idr_find(&mgr->ctx_handles, id);
332         if (!ctx) {
333                 mutex_unlock(&mgr->lock);
334                 return -EINVAL;
335         }
336
337         out->state.flags = 0x0;
338         out->state.hangs = 0x0;
339
340         if (ctx->reset_counter != atomic_read(&adev->gpu_reset_counter))
341                 out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RESET;
342
343         if (ctx->vram_lost_counter != atomic_read(&adev->vram_lost_counter))
344                 out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_VRAMLOST;
345
346         if (atomic_read(&ctx->guilty))
347                 out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_GUILTY;
348
349         mutex_unlock(&mgr->lock);
350         return 0;
351 }
352
353 int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
354                      struct drm_file *filp)
355 {
356         int r;
357         uint32_t id;
358         enum drm_sched_priority priority;
359
360         union drm_amdgpu_ctx *args = data;
361         struct amdgpu_device *adev = dev->dev_private;
362         struct amdgpu_fpriv *fpriv = filp->driver_priv;
363
364         r = 0;
365         id = args->in.ctx_id;
366         priority = amdgpu_to_sched_priority(args->in.priority);
367
368         /* For backwards compatibility reasons, we need to accept
369          * ioctls with garbage in the priority field */
370         if (priority == DRM_SCHED_PRIORITY_INVALID)
371                 priority = DRM_SCHED_PRIORITY_NORMAL;
372
373         switch (args->in.op) {
374         case AMDGPU_CTX_OP_ALLOC_CTX:
375                 r = amdgpu_ctx_alloc(adev, fpriv, filp, priority, &id);
376                 args->out.alloc.ctx_id = id;
377                 break;
378         case AMDGPU_CTX_OP_FREE_CTX:
379                 r = amdgpu_ctx_free(fpriv, id);
380                 break;
381         case AMDGPU_CTX_OP_QUERY_STATE:
382                 r = amdgpu_ctx_query(adev, fpriv, id, &args->out);
383                 break;
384         case AMDGPU_CTX_OP_QUERY_STATE2:
385                 r = amdgpu_ctx_query2(adev, fpriv, id, &args->out);
386                 break;
387         default:
388                 return -EINVAL;
389         }
390
391         return r;
392 }
393
394 struct amdgpu_ctx *amdgpu_ctx_get(struct amdgpu_fpriv *fpriv, uint32_t id)
395 {
396         struct amdgpu_ctx *ctx;
397         struct amdgpu_ctx_mgr *mgr;
398
399         if (!fpriv)
400                 return NULL;
401
402         mgr = &fpriv->ctx_mgr;
403
404         mutex_lock(&mgr->lock);
405         ctx = idr_find(&mgr->ctx_handles, id);
406         if (ctx)
407                 kref_get(&ctx->refcount);
408         mutex_unlock(&mgr->lock);
409         return ctx;
410 }
411
412 int amdgpu_ctx_put(struct amdgpu_ctx *ctx)
413 {
414         if (ctx == NULL)
415                 return -EINVAL;
416
417         kref_put(&ctx->refcount, amdgpu_ctx_do_release);
418         return 0;
419 }
420
421 int amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx,
422                          struct drm_sched_entity *entity,
423                          struct dma_fence *fence, uint64_t* handle)
424 {
425         struct amdgpu_ctx_ring *cring = to_amdgpu_ctx_ring(entity);
426         uint64_t seq = cring->sequence;
427         struct dma_fence *other = NULL;
428         unsigned idx = 0;
429
430         idx = seq & (amdgpu_sched_jobs - 1);
431         other = cring->fences[idx];
432         if (other)
433                 BUG_ON(!dma_fence_is_signaled(other));
434
435         dma_fence_get(fence);
436
437         spin_lock(&ctx->ring_lock);
438         cring->fences[idx] = fence;
439         cring->sequence++;
440         spin_unlock(&ctx->ring_lock);
441
442         dma_fence_put(other);
443         if (handle)
444                 *handle = seq;
445
446         return 0;
447 }
448
449 struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
450                                        struct drm_sched_entity *entity,
451                                        uint64_t seq)
452 {
453         struct amdgpu_ctx_ring *cring = to_amdgpu_ctx_ring(entity);
454         struct dma_fence *fence;
455
456         spin_lock(&ctx->ring_lock);
457
458         if (seq == ~0ull)
459                 seq = cring->sequence - 1;
460
461         if (seq >= cring->sequence) {
462                 spin_unlock(&ctx->ring_lock);
463                 return ERR_PTR(-EINVAL);
464         }
465
466
467         if (seq + amdgpu_sched_jobs < cring->sequence) {
468                 spin_unlock(&ctx->ring_lock);
469                 return NULL;
470         }
471
472         fence = dma_fence_get(cring->fences[seq & (amdgpu_sched_jobs - 1)]);
473         spin_unlock(&ctx->ring_lock);
474
475         return fence;
476 }
477
478 void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx,
479                                   enum drm_sched_priority priority)
480 {
481         int i;
482         struct amdgpu_device *adev = ctx->adev;
483         struct drm_sched_entity *entity;
484         struct amdgpu_ring *ring;
485         enum drm_sched_priority ctx_prio;
486
487         ctx->override_priority = priority;
488
489         ctx_prio = (ctx->override_priority == DRM_SCHED_PRIORITY_UNSET) ?
490                         ctx->init_priority : ctx->override_priority;
491
492         for (i = 0; i < adev->num_rings; i++) {
493                 ring = adev->rings[i];
494                 entity = &ctx->rings[i].entity;
495
496                 if (ring->funcs->type == AMDGPU_RING_TYPE_KIQ)
497                         continue;
498
499                 drm_sched_entity_set_priority(entity, ctx_prio);
500         }
501 }
502
503 int amdgpu_ctx_wait_prev_fence(struct amdgpu_ctx *ctx,
504                                struct drm_sched_entity *entity)
505 {
506         struct amdgpu_ctx_ring *cring = to_amdgpu_ctx_ring(entity);
507         unsigned idx = cring->sequence & (amdgpu_sched_jobs - 1);
508         struct dma_fence *other = cring->fences[idx];
509
510         if (other) {
511                 signed long r;
512                 r = dma_fence_wait(other, true);
513                 if (r < 0) {
514                         if (r != -ERESTARTSYS)
515                                 DRM_ERROR("Error (%ld) waiting for fence!\n", r);
516
517                         return r;
518                 }
519         }
520
521         return 0;
522 }
523
524 void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr)
525 {
526         mutex_init(&mgr->lock);
527         idr_init(&mgr->ctx_handles);
528 }
529
530 void amdgpu_ctx_mgr_entity_flush(struct amdgpu_ctx_mgr *mgr)
531 {
532         struct amdgpu_ctx *ctx;
533         struct idr *idp;
534         uint32_t id, i;
535         long max_wait = MAX_WAIT_SCHED_ENTITY_Q_EMPTY;
536
537         idp = &mgr->ctx_handles;
538
539         mutex_lock(&mgr->lock);
540         idr_for_each_entry(idp, ctx, id) {
541
542                 if (!ctx->adev) {
543                         mutex_unlock(&mgr->lock);
544                         return;
545                 }
546
547                 for (i = 0; i < ctx->adev->num_rings; i++) {
548
549                         if (ctx->adev->rings[i] == &ctx->adev->gfx.kiq.ring)
550                                 continue;
551
552                         max_wait = drm_sched_entity_flush(&ctx->rings[i].entity,
553                                                           max_wait);
554                 }
555         }
556         mutex_unlock(&mgr->lock);
557 }
558
559 void amdgpu_ctx_mgr_entity_fini(struct amdgpu_ctx_mgr *mgr)
560 {
561         struct amdgpu_ctx *ctx;
562         struct idr *idp;
563         uint32_t id, i;
564
565         idp = &mgr->ctx_handles;
566
567         idr_for_each_entry(idp, ctx, id) {
568
569                 if (!ctx->adev)
570                         return;
571
572                 for (i = 0; i < ctx->adev->num_rings; i++) {
573
574                         if (ctx->adev->rings[i] == &ctx->adev->gfx.kiq.ring)
575                                 continue;
576
577                         if (kref_read(&ctx->refcount) == 1)
578                                 drm_sched_entity_fini(&ctx->rings[i].entity);
579                         else
580                                 DRM_ERROR("ctx %p is still alive\n", ctx);
581                 }
582         }
583 }
584
585 void amdgpu_ctx_mgr_fini(struct amdgpu_ctx_mgr *mgr)
586 {
587         struct amdgpu_ctx *ctx;
588         struct idr *idp;
589         uint32_t id;
590
591         amdgpu_ctx_mgr_entity_fini(mgr);
592
593         idp = &mgr->ctx_handles;
594
595         idr_for_each_entry(idp, ctx, id) {
596                 if (kref_put(&ctx->refcount, amdgpu_ctx_fini) != 1)
597                         DRM_ERROR("ctx %p is still alive\n", ctx);
598         }
599
600         idr_destroy(&mgr->ctx_handles);
601         mutex_destroy(&mgr->lock);
602 }
This page took 0.0736 seconds and 4 git commands to generate.