GNU Linux-libre 4.14.290-gnu1
[releases.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_vce.c
1 /*
2  * Copyright 2013 Advanced Micro Devices, Inc.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sub license, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
16  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
17  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19  * USE OR OTHER DEALINGS IN THE SOFTWARE.
20  *
21  * The above copyright notice and this permission notice (including the
22  * next paragraph) shall be included in all copies or substantial portions
23  * of the Software.
24  *
25  * Authors: Christian König <christian.koenig@amd.com>
26  */
27
28 #include <linux/firmware.h>
29 #include <linux/module.h>
30 #include <drm/drmP.h>
31 #include <drm/drm.h>
32
33 #include "amdgpu.h"
34 #include "amdgpu_pm.h"
35 #include "amdgpu_vce.h"
36 #include "cikd.h"
37
38 /* 1 second timeout */
39 #define VCE_IDLE_TIMEOUT        msecs_to_jiffies(1000)
40
41 /* Firmware Names */
42 #ifdef CONFIG_DRM_AMDGPU_CIK
43 #define FIRMWARE_BONAIRE        "/*(DEBLOBBED)*/"
44 #define FIRMWARE_KABINI "/*(DEBLOBBED)*/"
45 #define FIRMWARE_KAVERI "/*(DEBLOBBED)*/"
46 #define FIRMWARE_HAWAII "/*(DEBLOBBED)*/"
47 #define FIRMWARE_MULLINS        "/*(DEBLOBBED)*/"
48 #endif
49 #define FIRMWARE_TONGA          "/*(DEBLOBBED)*/"
50 #define FIRMWARE_CARRIZO        "/*(DEBLOBBED)*/"
51 #define FIRMWARE_FIJI           "/*(DEBLOBBED)*/"
52 #define FIRMWARE_STONEY         "/*(DEBLOBBED)*/"
53 #define FIRMWARE_POLARIS10      "/*(DEBLOBBED)*/"
54 #define FIRMWARE_POLARIS11         "/*(DEBLOBBED)*/"
55 #define FIRMWARE_POLARIS12         "/*(DEBLOBBED)*/"
56
57 #define FIRMWARE_VEGA10         "/*(DEBLOBBED)*/"
58
59 #ifdef CONFIG_DRM_AMDGPU_CIK
60 /*(DEBLOBBED)*/
61 #endif
62 /*(DEBLOBBED)*/
63
64 static void amdgpu_vce_idle_work_handler(struct work_struct *work);
65
66 /**
67  * amdgpu_vce_init - allocate memory, load vce firmware
68  *
69  * @adev: amdgpu_device pointer
70  *
71  * First step to get VCE online, allocate memory and load the firmware
72  */
73 int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
74 {
75         struct amdgpu_ring *ring;
76         struct amd_sched_rq *rq;
77         const char *fw_name;
78         const struct common_firmware_header *hdr;
79         unsigned ucode_version, version_major, version_minor, binary_id;
80         int i, r;
81
82         switch (adev->asic_type) {
83 #ifdef CONFIG_DRM_AMDGPU_CIK
84         case CHIP_BONAIRE:
85                 fw_name = FIRMWARE_BONAIRE;
86                 break;
87         case CHIP_KAVERI:
88                 fw_name = FIRMWARE_KAVERI;
89                 break;
90         case CHIP_KABINI:
91                 fw_name = FIRMWARE_KABINI;
92                 break;
93         case CHIP_HAWAII:
94                 fw_name = FIRMWARE_HAWAII;
95                 break;
96         case CHIP_MULLINS:
97                 fw_name = FIRMWARE_MULLINS;
98                 break;
99 #endif
100         case CHIP_TONGA:
101                 fw_name = FIRMWARE_TONGA;
102                 break;
103         case CHIP_CARRIZO:
104                 fw_name = FIRMWARE_CARRIZO;
105                 break;
106         case CHIP_FIJI:
107                 fw_name = FIRMWARE_FIJI;
108                 break;
109         case CHIP_STONEY:
110                 fw_name = FIRMWARE_STONEY;
111                 break;
112         case CHIP_POLARIS10:
113                 fw_name = FIRMWARE_POLARIS10;
114                 break;
115         case CHIP_POLARIS11:
116                 fw_name = FIRMWARE_POLARIS11;
117                 break;
118         case CHIP_VEGA10:
119                 fw_name = FIRMWARE_VEGA10;
120                 break;
121         case CHIP_POLARIS12:
122                 fw_name = FIRMWARE_POLARIS12;
123                 break;
124
125         default:
126                 return -EINVAL;
127         }
128
129         r = reject_firmware(&adev->vce.fw, fw_name, adev->dev);
130         if (r) {
131                 dev_err(adev->dev, "amdgpu_vce: Can't load firmware \"%s\"\n",
132                         fw_name);
133                 return r;
134         }
135
136         r = amdgpu_ucode_validate(adev->vce.fw);
137         if (r) {
138                 dev_err(adev->dev, "amdgpu_vce: Can't validate firmware \"%s\"\n",
139                         fw_name);
140                 release_firmware(adev->vce.fw);
141                 adev->vce.fw = NULL;
142                 return r;
143         }
144
145         hdr = (const struct common_firmware_header *)adev->vce.fw->data;
146
147         ucode_version = le32_to_cpu(hdr->ucode_version);
148         version_major = (ucode_version >> 20) & 0xfff;
149         version_minor = (ucode_version >> 8) & 0xfff;
150         binary_id = ucode_version & 0xff;
151         DRM_INFO("Found VCE firmware Version: %hhd.%hhd Binary ID: %hhd\n",
152                 version_major, version_minor, binary_id);
153         adev->vce.fw_version = ((version_major << 24) | (version_minor << 16) |
154                                 (binary_id << 8));
155
156         r = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE,
157                                     AMDGPU_GEM_DOMAIN_VRAM, &adev->vce.vcpu_bo,
158                                     &adev->vce.gpu_addr, &adev->vce.cpu_addr);
159         if (r) {
160                 dev_err(adev->dev, "(%d) failed to allocate VCE bo\n", r);
161                 return r;
162         }
163
164         ring = &adev->vce.ring[0];
165         rq = &ring->sched.sched_rq[AMD_SCHED_PRIORITY_NORMAL];
166         r = amd_sched_entity_init(&ring->sched, &adev->vce.entity,
167                                   rq, amdgpu_sched_jobs);
168         if (r != 0) {
169                 DRM_ERROR("Failed setting up VCE run queue.\n");
170                 return r;
171         }
172
173         for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) {
174                 atomic_set(&adev->vce.handles[i], 0);
175                 adev->vce.filp[i] = NULL;
176         }
177
178         INIT_DELAYED_WORK(&adev->vce.idle_work, amdgpu_vce_idle_work_handler);
179         mutex_init(&adev->vce.idle_mutex);
180
181         return 0;
182 }
183
184 /**
185  * amdgpu_vce_fini - free memory
186  *
187  * @adev: amdgpu_device pointer
188  *
189  * Last step on VCE teardown, free firmware memory
190  */
191 int amdgpu_vce_sw_fini(struct amdgpu_device *adev)
192 {
193         unsigned i;
194
195         if (adev->vce.vcpu_bo == NULL)
196                 return 0;
197
198         amd_sched_entity_fini(&adev->vce.ring[0].sched, &adev->vce.entity);
199
200         amdgpu_bo_free_kernel(&adev->vce.vcpu_bo, &adev->vce.gpu_addr,
201                 (void **)&adev->vce.cpu_addr);
202
203         for (i = 0; i < adev->vce.num_rings; i++)
204                 amdgpu_ring_fini(&adev->vce.ring[i]);
205
206         release_firmware(adev->vce.fw);
207         mutex_destroy(&adev->vce.idle_mutex);
208
209         return 0;
210 }
211
212 /**
213  * amdgpu_vce_suspend - unpin VCE fw memory
214  *
215  * @adev: amdgpu_device pointer
216  *
217  */
218 int amdgpu_vce_suspend(struct amdgpu_device *adev)
219 {
220         int i;
221
222         cancel_delayed_work_sync(&adev->vce.idle_work);
223
224         if (adev->vce.vcpu_bo == NULL)
225                 return 0;
226
227         for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i)
228                 if (atomic_read(&adev->vce.handles[i]))
229                         break;
230
231         if (i == AMDGPU_MAX_VCE_HANDLES)
232                 return 0;
233
234         /* TODO: suspending running encoding sessions isn't supported */
235         return -EINVAL;
236 }
237
238 /**
239  * amdgpu_vce_resume - pin VCE fw memory
240  *
241  * @adev: amdgpu_device pointer
242  *
243  */
244 int amdgpu_vce_resume(struct amdgpu_device *adev)
245 {
246         void *cpu_addr;
247         const struct common_firmware_header *hdr;
248         unsigned offset;
249         int r;
250
251         if (adev->vce.vcpu_bo == NULL)
252                 return -EINVAL;
253
254         r = amdgpu_bo_reserve(adev->vce.vcpu_bo, false);
255         if (r) {
256                 dev_err(adev->dev, "(%d) failed to reserve VCE bo\n", r);
257                 return r;
258         }
259
260         r = amdgpu_bo_kmap(adev->vce.vcpu_bo, &cpu_addr);
261         if (r) {
262                 amdgpu_bo_unreserve(adev->vce.vcpu_bo);
263                 dev_err(adev->dev, "(%d) VCE map failed\n", r);
264                 return r;
265         }
266
267         hdr = (const struct common_firmware_header *)adev->vce.fw->data;
268         offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
269         memcpy_toio(cpu_addr, adev->vce.fw->data + offset,
270                     adev->vce.fw->size - offset);
271
272         amdgpu_bo_kunmap(adev->vce.vcpu_bo);
273
274         amdgpu_bo_unreserve(adev->vce.vcpu_bo);
275
276         return 0;
277 }
278
279 /**
280  * amdgpu_vce_idle_work_handler - power off VCE
281  *
282  * @work: pointer to work structure
283  *
284  * power of VCE when it's not used any more
285  */
286 static void amdgpu_vce_idle_work_handler(struct work_struct *work)
287 {
288         struct amdgpu_device *adev =
289                 container_of(work, struct amdgpu_device, vce.idle_work.work);
290         unsigned i, count = 0;
291
292         if (amdgpu_sriov_vf(adev))
293                 return;
294
295         for (i = 0; i < adev->vce.num_rings; i++)
296                 count += amdgpu_fence_count_emitted(&adev->vce.ring[i]);
297
298         if (count == 0) {
299                 if (adev->pm.dpm_enabled) {
300                         amdgpu_dpm_enable_vce(adev, false);
301                 } else {
302                         amdgpu_asic_set_vce_clocks(adev, 0, 0);
303                         amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
304                                                             AMD_PG_STATE_GATE);
305                         amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
306                                                             AMD_CG_STATE_GATE);
307                 }
308         } else {
309                 schedule_delayed_work(&adev->vce.idle_work, VCE_IDLE_TIMEOUT);
310         }
311 }
312
313 /**
314  * amdgpu_vce_ring_begin_use - power up VCE
315  *
316  * @ring: amdgpu ring
317  *
318  * Make sure VCE is powerd up when we want to use it
319  */
320 void amdgpu_vce_ring_begin_use(struct amdgpu_ring *ring)
321 {
322         struct amdgpu_device *adev = ring->adev;
323         bool set_clocks;
324
325         if (amdgpu_sriov_vf(adev))
326                 return;
327
328         mutex_lock(&adev->vce.idle_mutex);
329         set_clocks = !cancel_delayed_work_sync(&adev->vce.idle_work);
330         if (set_clocks) {
331                 if (adev->pm.dpm_enabled) {
332                         amdgpu_dpm_enable_vce(adev, true);
333                 } else {
334                         amdgpu_asic_set_vce_clocks(adev, 53300, 40000);
335                         amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
336                                                             AMD_CG_STATE_UNGATE);
337                         amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
338                                                             AMD_PG_STATE_UNGATE);
339
340                 }
341         }
342         mutex_unlock(&adev->vce.idle_mutex);
343 }
344
345 /**
346  * amdgpu_vce_ring_end_use - power VCE down
347  *
348  * @ring: amdgpu ring
349  *
350  * Schedule work to power VCE down again
351  */
352 void amdgpu_vce_ring_end_use(struct amdgpu_ring *ring)
353 {
354         schedule_delayed_work(&ring->adev->vce.idle_work, VCE_IDLE_TIMEOUT);
355 }
356
357 /**
358  * amdgpu_vce_free_handles - free still open VCE handles
359  *
360  * @adev: amdgpu_device pointer
361  * @filp: drm file pointer
362  *
363  * Close all VCE handles still open by this file pointer
364  */
365 void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
366 {
367         struct amdgpu_ring *ring = &adev->vce.ring[0];
368         int i, r;
369         for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) {
370                 uint32_t handle = atomic_read(&adev->vce.handles[i]);
371
372                 if (!handle || adev->vce.filp[i] != filp)
373                         continue;
374
375                 r = amdgpu_vce_get_destroy_msg(ring, handle, false, NULL);
376                 if (r)
377                         DRM_ERROR("Error destroying VCE handle (%d)!\n", r);
378
379                 adev->vce.filp[i] = NULL;
380                 atomic_set(&adev->vce.handles[i], 0);
381         }
382 }
383
384 /**
385  * amdgpu_vce_get_create_msg - generate a VCE create msg
386  *
387  * @adev: amdgpu_device pointer
388  * @ring: ring we should submit the msg to
389  * @handle: VCE session handle to use
390  * @fence: optional fence to return
391  *
392  * Open up a stream for HW test
393  */
394 int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
395                               struct dma_fence **fence)
396 {
397         const unsigned ib_size_dw = 1024;
398         struct amdgpu_job *job;
399         struct amdgpu_ib *ib;
400         struct dma_fence *f = NULL;
401         uint64_t dummy;
402         int i, r;
403
404         r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
405         if (r)
406                 return r;
407
408         ib = &job->ibs[0];
409
410         dummy = ib->gpu_addr + 1024;
411
412         /* stitch together an VCE create msg */
413         ib->length_dw = 0;
414         ib->ptr[ib->length_dw++] = 0x0000000c; /* len */
415         ib->ptr[ib->length_dw++] = 0x00000001; /* session cmd */
416         ib->ptr[ib->length_dw++] = handle;
417
418         if ((ring->adev->vce.fw_version >> 24) >= 52)
419                 ib->ptr[ib->length_dw++] = 0x00000040; /* len */
420         else
421                 ib->ptr[ib->length_dw++] = 0x00000030; /* len */
422         ib->ptr[ib->length_dw++] = 0x01000001; /* create cmd */
423         ib->ptr[ib->length_dw++] = 0x00000000;
424         ib->ptr[ib->length_dw++] = 0x00000042;
425         ib->ptr[ib->length_dw++] = 0x0000000a;
426         ib->ptr[ib->length_dw++] = 0x00000001;
427         ib->ptr[ib->length_dw++] = 0x00000080;
428         ib->ptr[ib->length_dw++] = 0x00000060;
429         ib->ptr[ib->length_dw++] = 0x00000100;
430         ib->ptr[ib->length_dw++] = 0x00000100;
431         ib->ptr[ib->length_dw++] = 0x0000000c;
432         ib->ptr[ib->length_dw++] = 0x00000000;
433         if ((ring->adev->vce.fw_version >> 24) >= 52) {
434                 ib->ptr[ib->length_dw++] = 0x00000000;
435                 ib->ptr[ib->length_dw++] = 0x00000000;
436                 ib->ptr[ib->length_dw++] = 0x00000000;
437                 ib->ptr[ib->length_dw++] = 0x00000000;
438         }
439
440         ib->ptr[ib->length_dw++] = 0x00000014; /* len */
441         ib->ptr[ib->length_dw++] = 0x05000005; /* feedback buffer */
442         ib->ptr[ib->length_dw++] = upper_32_bits(dummy);
443         ib->ptr[ib->length_dw++] = dummy;
444         ib->ptr[ib->length_dw++] = 0x00000001;
445
446         for (i = ib->length_dw; i < ib_size_dw; ++i)
447                 ib->ptr[i] = 0x0;
448
449         r = amdgpu_ib_schedule(ring, 1, ib, NULL, &f);
450         job->fence = dma_fence_get(f);
451         if (r)
452                 goto err;
453
454         amdgpu_job_free(job);
455         if (fence)
456                 *fence = dma_fence_get(f);
457         dma_fence_put(f);
458         return 0;
459
460 err:
461         amdgpu_job_free(job);
462         return r;
463 }
464
465 /**
466  * amdgpu_vce_get_destroy_msg - generate a VCE destroy msg
467  *
468  * @adev: amdgpu_device pointer
469  * @ring: ring we should submit the msg to
470  * @handle: VCE session handle to use
471  * @fence: optional fence to return
472  *
473  * Close up a stream for HW test or if userspace failed to do so
474  */
475 int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
476                                bool direct, struct dma_fence **fence)
477 {
478         const unsigned ib_size_dw = 1024;
479         struct amdgpu_job *job;
480         struct amdgpu_ib *ib;
481         struct dma_fence *f = NULL;
482         int i, r;
483
484         r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
485         if (r)
486                 return r;
487
488         ib = &job->ibs[0];
489
490         /* stitch together an VCE destroy msg */
491         ib->length_dw = 0;
492         ib->ptr[ib->length_dw++] = 0x0000000c; /* len */
493         ib->ptr[ib->length_dw++] = 0x00000001; /* session cmd */
494         ib->ptr[ib->length_dw++] = handle;
495
496         ib->ptr[ib->length_dw++] = 0x00000020; /* len */
497         ib->ptr[ib->length_dw++] = 0x00000002; /* task info */
498         ib->ptr[ib->length_dw++] = 0xffffffff; /* next task info, set to 0xffffffff if no */
499         ib->ptr[ib->length_dw++] = 0x00000001; /* destroy session */
500         ib->ptr[ib->length_dw++] = 0x00000000;
501         ib->ptr[ib->length_dw++] = 0x00000000;
502         ib->ptr[ib->length_dw++] = 0xffffffff; /* feedback is not needed, set to 0xffffffff and firmware will not output feedback */
503         ib->ptr[ib->length_dw++] = 0x00000000;
504
505         ib->ptr[ib->length_dw++] = 0x00000008; /* len */
506         ib->ptr[ib->length_dw++] = 0x02000001; /* destroy cmd */
507
508         for (i = ib->length_dw; i < ib_size_dw; ++i)
509                 ib->ptr[i] = 0x0;
510
511         if (direct) {
512                 r = amdgpu_ib_schedule(ring, 1, ib, NULL, &f);
513                 job->fence = dma_fence_get(f);
514                 if (r)
515                         goto err;
516
517                 amdgpu_job_free(job);
518         } else {
519                 r = amdgpu_job_submit(job, ring, &ring->adev->vce.entity,
520                                       AMDGPU_FENCE_OWNER_UNDEFINED, &f);
521                 if (r)
522                         goto err;
523         }
524
525         if (fence)
526                 *fence = dma_fence_get(f);
527         dma_fence_put(f);
528         return 0;
529
530 err:
531         amdgpu_job_free(job);
532         return r;
533 }
534
535 /**
536  * amdgpu_vce_cs_reloc - command submission relocation
537  *
538  * @p: parser context
539  * @lo: address of lower dword
540  * @hi: address of higher dword
541  * @size: minimum size
542  *
543  * Patch relocation inside command stream with real buffer address
544  */
545 static int amdgpu_vce_cs_reloc(struct amdgpu_cs_parser *p, uint32_t ib_idx,
546                                int lo, int hi, unsigned size, uint32_t index)
547 {
548         struct amdgpu_bo_va_mapping *mapping;
549         struct amdgpu_bo *bo;
550         uint64_t addr;
551
552         if (index == 0xffffffff)
553                 index = 0;
554
555         addr = ((uint64_t)amdgpu_get_ib_value(p, ib_idx, lo)) |
556                ((uint64_t)amdgpu_get_ib_value(p, ib_idx, hi)) << 32;
557         addr += ((uint64_t)size) * ((uint64_t)index);
558
559         mapping = amdgpu_cs_find_mapping(p, addr, &bo);
560         if (mapping == NULL) {
561                 DRM_ERROR("Can't find BO for addr 0x%010Lx %d %d %d %d\n",
562                           addr, lo, hi, size, index);
563                 return -EINVAL;
564         }
565
566         if ((addr + (uint64_t)size) >
567             (mapping->last + 1) * AMDGPU_GPU_PAGE_SIZE) {
568                 DRM_ERROR("BO to small for addr 0x%010Lx %d %d\n",
569                           addr, lo, hi);
570                 return -EINVAL;
571         }
572
573         addr -= mapping->start * AMDGPU_GPU_PAGE_SIZE;
574         addr += amdgpu_bo_gpu_offset(bo);
575         addr -= ((uint64_t)size) * ((uint64_t)index);
576
577         amdgpu_set_ib_value(p, ib_idx, lo, lower_32_bits(addr));
578         amdgpu_set_ib_value(p, ib_idx, hi, upper_32_bits(addr));
579
580         return 0;
581 }
582
583 /**
584  * amdgpu_vce_validate_handle - validate stream handle
585  *
586  * @p: parser context
587  * @handle: handle to validate
588  * @allocated: allocated a new handle?
589  *
590  * Validates the handle and return the found session index or -EINVAL
591  * we we don't have another free session index.
592  */
593 static int amdgpu_vce_validate_handle(struct amdgpu_cs_parser *p,
594                                       uint32_t handle, uint32_t *allocated)
595 {
596         unsigned i;
597
598         /* validate the handle */
599         for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) {
600                 if (atomic_read(&p->adev->vce.handles[i]) == handle) {
601                         if (p->adev->vce.filp[i] != p->filp) {
602                                 DRM_ERROR("VCE handle collision detected!\n");
603                                 return -EINVAL;
604                         }
605                         return i;
606                 }
607         }
608
609         /* handle not found try to alloc a new one */
610         for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) {
611                 if (!atomic_cmpxchg(&p->adev->vce.handles[i], 0, handle)) {
612                         p->adev->vce.filp[i] = p->filp;
613                         p->adev->vce.img_size[i] = 0;
614                         *allocated |= 1 << i;
615                         return i;
616                 }
617         }
618
619         DRM_ERROR("No more free VCE handles!\n");
620         return -EINVAL;
621 }
622
623 /**
624  * amdgpu_vce_cs_parse - parse and validate the command stream
625  *
626  * @p: parser context
627  *
628  */
629 int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx)
630 {
631         struct amdgpu_ib *ib = &p->job->ibs[ib_idx];
632         unsigned fb_idx = 0, bs_idx = 0;
633         int session_idx = -1;
634         uint32_t destroyed = 0;
635         uint32_t created = 0;
636         uint32_t allocated = 0;
637         uint32_t tmp, handle = 0;
638         uint32_t *size = &tmp;
639         int i, r = 0, idx = 0;
640
641         p->job->vm = NULL;
642         ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo);
643
644         r = amdgpu_cs_sysvm_access_required(p);
645         if (r)
646                 return r;
647
648         while (idx < ib->length_dw) {
649                 uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx);
650                 uint32_t cmd = amdgpu_get_ib_value(p, ib_idx, idx + 1);
651
652                 if ((len < 8) || (len & 3)) {
653                         DRM_ERROR("invalid VCE command length (%d)!\n", len);
654                         r = -EINVAL;
655                         goto out;
656                 }
657
658                 switch (cmd) {
659                 case 0x00000001: /* session */
660                         handle = amdgpu_get_ib_value(p, ib_idx, idx + 2);
661                         session_idx = amdgpu_vce_validate_handle(p, handle,
662                                                                  &allocated);
663                         if (session_idx < 0) {
664                                 r = session_idx;
665                                 goto out;
666                         }
667                         size = &p->adev->vce.img_size[session_idx];
668                         break;
669
670                 case 0x00000002: /* task info */
671                         fb_idx = amdgpu_get_ib_value(p, ib_idx, idx + 6);
672                         bs_idx = amdgpu_get_ib_value(p, ib_idx, idx + 7);
673                         break;
674
675                 case 0x01000001: /* create */
676                         created |= 1 << session_idx;
677                         if (destroyed & (1 << session_idx)) {
678                                 destroyed &= ~(1 << session_idx);
679                                 allocated |= 1 << session_idx;
680
681                         } else if (!(allocated & (1 << session_idx))) {
682                                 DRM_ERROR("Handle already in use!\n");
683                                 r = -EINVAL;
684                                 goto out;
685                         }
686
687                         *size = amdgpu_get_ib_value(p, ib_idx, idx + 8) *
688                                 amdgpu_get_ib_value(p, ib_idx, idx + 10) *
689                                 8 * 3 / 2;
690                         break;
691
692                 case 0x04000001: /* config extension */
693                 case 0x04000002: /* pic control */
694                 case 0x04000005: /* rate control */
695                 case 0x04000007: /* motion estimation */
696                 case 0x04000008: /* rdo */
697                 case 0x04000009: /* vui */
698                 case 0x05000002: /* auxiliary buffer */
699                 case 0x05000009: /* clock table */
700                         break;
701
702                 case 0x0500000c: /* hw config */
703                         switch (p->adev->asic_type) {
704 #ifdef CONFIG_DRM_AMDGPU_CIK
705                         case CHIP_KAVERI:
706                         case CHIP_MULLINS:
707 #endif
708                         case CHIP_CARRIZO:
709                                 break;
710                         default:
711                                 r = -EINVAL;
712                                 goto out;
713                         }
714                         break;
715
716                 case 0x03000001: /* encode */
717                         r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 10, idx + 9,
718                                                 *size, 0);
719                         if (r)
720                                 goto out;
721
722                         r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 12, idx + 11,
723                                                 *size / 3, 0);
724                         if (r)
725                                 goto out;
726                         break;
727
728                 case 0x02000001: /* destroy */
729                         destroyed |= 1 << session_idx;
730                         break;
731
732                 case 0x05000001: /* context buffer */
733                         r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 3, idx + 2,
734                                                 *size * 2, 0);
735                         if (r)
736                                 goto out;
737                         break;
738
739                 case 0x05000004: /* video bitstream buffer */
740                         tmp = amdgpu_get_ib_value(p, ib_idx, idx + 4);
741                         r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 3, idx + 2,
742                                                 tmp, bs_idx);
743                         if (r)
744                                 goto out;
745                         break;
746
747                 case 0x05000005: /* feedback buffer */
748                         r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 3, idx + 2,
749                                                 4096, fb_idx);
750                         if (r)
751                                 goto out;
752                         break;
753
754                 default:
755                         DRM_ERROR("invalid VCE command (0x%x)!\n", cmd);
756                         r = -EINVAL;
757                         goto out;
758                 }
759
760                 if (session_idx == -1) {
761                         DRM_ERROR("no session command at start of IB\n");
762                         r = -EINVAL;
763                         goto out;
764                 }
765
766                 idx += len / 4;
767         }
768
769         if (allocated & ~created) {
770                 DRM_ERROR("New session without create command!\n");
771                 r = -ENOENT;
772         }
773
774 out:
775         if (!r) {
776                 /* No error, free all destroyed handle slots */
777                 tmp = destroyed;
778         } else {
779                 /* Error during parsing, free all allocated handle slots */
780                 tmp = allocated;
781         }
782
783         for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i)
784                 if (tmp & (1 << i))
785                         atomic_set(&p->adev->vce.handles[i], 0);
786
787         return r;
788 }
789
790 /**
791  * amdgpu_vce_cs_parse_vm - parse the command stream in VM mode
792  *
793  * @p: parser context
794  *
795  */
796 int amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser *p, uint32_t ib_idx)
797 {
798         struct amdgpu_ib *ib = &p->job->ibs[ib_idx];
799         int session_idx = -1;
800         uint32_t destroyed = 0;
801         uint32_t created = 0;
802         uint32_t allocated = 0;
803         uint32_t tmp, handle = 0;
804         int i, r = 0, idx = 0;
805
806         while (idx < ib->length_dw) {
807                 uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx);
808                 uint32_t cmd = amdgpu_get_ib_value(p, ib_idx, idx + 1);
809
810                 if ((len < 8) || (len & 3)) {
811                         DRM_ERROR("invalid VCE command length (%d)!\n", len);
812                         r = -EINVAL;
813                         goto out;
814                 }
815
816                 switch (cmd) {
817                 case 0x00000001: /* session */
818                         handle = amdgpu_get_ib_value(p, ib_idx, idx + 2);
819                         session_idx = amdgpu_vce_validate_handle(p, handle,
820                                                                  &allocated);
821                         if (session_idx < 0) {
822                                 r = session_idx;
823                                 goto out;
824                         }
825                         break;
826
827                 case 0x01000001: /* create */
828                         created |= 1 << session_idx;
829                         if (destroyed & (1 << session_idx)) {
830                                 destroyed &= ~(1 << session_idx);
831                                 allocated |= 1 << session_idx;
832
833                         } else if (!(allocated & (1 << session_idx))) {
834                                 DRM_ERROR("Handle already in use!\n");
835                                 r = -EINVAL;
836                                 goto out;
837                         }
838
839                         break;
840
841                 case 0x02000001: /* destroy */
842                         destroyed |= 1 << session_idx;
843                         break;
844
845                 default:
846                         break;
847                 }
848
849                 if (session_idx == -1) {
850                         DRM_ERROR("no session command at start of IB\n");
851                         r = -EINVAL;
852                         goto out;
853                 }
854
855                 idx += len / 4;
856         }
857
858         if (allocated & ~created) {
859                 DRM_ERROR("New session without create command!\n");
860                 r = -ENOENT;
861         }
862
863 out:
864         if (!r) {
865                 /* No error, free all destroyed handle slots */
866                 tmp = destroyed;
867                 amdgpu_ib_free(p->adev, ib, NULL);
868         } else {
869                 /* Error during parsing, free all allocated handle slots */
870                 tmp = allocated;
871         }
872
873         for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i)
874                 if (tmp & (1 << i))
875                         atomic_set(&p->adev->vce.handles[i], 0);
876
877         return r;
878 }
879
880 /**
881  * amdgpu_vce_ring_emit_ib - execute indirect buffer
882  *
883  * @ring: engine to use
884  * @ib: the IB to execute
885  *
886  */
887 void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib,
888                              unsigned vm_id, bool ctx_switch)
889 {
890         amdgpu_ring_write(ring, VCE_CMD_IB);
891         amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
892         amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
893         amdgpu_ring_write(ring, ib->length_dw);
894 }
895
896 /**
897  * amdgpu_vce_ring_emit_fence - add a fence command to the ring
898  *
899  * @ring: engine to use
900  * @fence: the fence
901  *
902  */
903 void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
904                                 unsigned flags)
905 {
906         WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
907
908         amdgpu_ring_write(ring, VCE_CMD_FENCE);
909         amdgpu_ring_write(ring, addr);
910         amdgpu_ring_write(ring, upper_32_bits(addr));
911         amdgpu_ring_write(ring, seq);
912         amdgpu_ring_write(ring, VCE_CMD_TRAP);
913         amdgpu_ring_write(ring, VCE_CMD_END);
914 }
915
916 /**
917  * amdgpu_vce_ring_test_ring - test if VCE ring is working
918  *
919  * @ring: the engine to test on
920  *
921  */
922 int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring)
923 {
924         struct amdgpu_device *adev = ring->adev;
925         uint32_t rptr = amdgpu_ring_get_rptr(ring);
926         unsigned i;
927         int r, timeout = adev->usec_timeout;
928
929         /* skip ring test for sriov*/
930         if (amdgpu_sriov_vf(adev))
931                 return 0;
932
933         r = amdgpu_ring_alloc(ring, 16);
934         if (r) {
935                 DRM_ERROR("amdgpu: vce failed to lock ring %d (%d).\n",
936                           ring->idx, r);
937                 return r;
938         }
939         amdgpu_ring_write(ring, VCE_CMD_END);
940         amdgpu_ring_commit(ring);
941
942         for (i = 0; i < timeout; i++) {
943                 if (amdgpu_ring_get_rptr(ring) != rptr)
944                         break;
945                 DRM_UDELAY(1);
946         }
947
948         if (i < timeout) {
949                 DRM_INFO("ring test on %d succeeded in %d usecs\n",
950                          ring->idx, i);
951         } else {
952                 DRM_ERROR("amdgpu: ring %d test failed\n",
953                           ring->idx);
954                 r = -ETIMEDOUT;
955         }
956
957         return r;
958 }
959
960 /**
961  * amdgpu_vce_ring_test_ib - test if VCE IBs are working
962  *
963  * @ring: the engine to test on
964  *
965  */
966 int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout)
967 {
968         struct dma_fence *fence = NULL;
969         long r;
970
971         /* skip vce ring1/2 ib test for now, since it's not reliable */
972         if (ring != &ring->adev->vce.ring[0])
973                 return 0;
974
975         r = amdgpu_vce_get_create_msg(ring, 1, NULL);
976         if (r) {
977                 DRM_ERROR("amdgpu: failed to get create msg (%ld).\n", r);
978                 goto error;
979         }
980
981         r = amdgpu_vce_get_destroy_msg(ring, 1, true, &fence);
982         if (r) {
983                 DRM_ERROR("amdgpu: failed to get destroy ib (%ld).\n", r);
984                 goto error;
985         }
986
987         r = dma_fence_wait_timeout(fence, false, timeout);
988         if (r == 0) {
989                 DRM_ERROR("amdgpu: IB test timed out.\n");
990                 r = -ETIMEDOUT;
991         } else if (r < 0) {
992                 DRM_ERROR("amdgpu: fence wait failed (%ld).\n", r);
993         } else {
994                 DRM_INFO("ib test on ring %d succeeded\n", ring->idx);
995                 r = 0;
996         }
997 error:
998         dma_fence_put(fence);
999         return r;
1000 }