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
31 #include <drm/drm.h>
32 #include <drm/drm_drv.h>
33
34 #include "amdgpu.h"
35 #include "amdgpu_pm.h"
36 #include "amdgpu_vce.h"
37 #include "amdgpu_cs.h"
38 #include "cikd.h"
39
40 /* 1 second timeout */
41 #define VCE_IDLE_TIMEOUT msecs_to_jiffies(1000)
42
43 /* Firmware Names */
44 #ifdef CONFIG_DRM_AMDGPU_SI
45 #define FIRMWARE_VCE_V1_0 "amdgpu/vce_1_0_0.bin"
46 #endif
47 #ifdef CONFIG_DRM_AMDGPU_CIK
48 #define FIRMWARE_BONAIRE "amdgpu/bonaire_vce.bin"
49 #define FIRMWARE_KABINI "amdgpu/kabini_vce.bin"
50 #define FIRMWARE_KAVERI "amdgpu/kaveri_vce.bin"
51 #define FIRMWARE_HAWAII "amdgpu/hawaii_vce.bin"
52 #define FIRMWARE_MULLINS "amdgpu/mullins_vce.bin"
53 #endif
54 #define FIRMWARE_TONGA "amdgpu/tonga_vce.bin"
55 #define FIRMWARE_CARRIZO "amdgpu/carrizo_vce.bin"
56 #define FIRMWARE_FIJI "amdgpu/fiji_vce.bin"
57 #define FIRMWARE_STONEY "amdgpu/stoney_vce.bin"
58 #define FIRMWARE_POLARIS10 "amdgpu/polaris10_vce.bin"
59 #define FIRMWARE_POLARIS11 "amdgpu/polaris11_vce.bin"
60 #define FIRMWARE_POLARIS12 "amdgpu/polaris12_vce.bin"
61 #define FIRMWARE_VEGAM "amdgpu/vegam_vce.bin"
62
63 #define FIRMWARE_VEGA10 "amdgpu/vega10_vce.bin"
64 #define FIRMWARE_VEGA12 "amdgpu/vega12_vce.bin"
65 #define FIRMWARE_VEGA20 "amdgpu/vega20_vce.bin"
66
67 #ifdef CONFIG_DRM_AMDGPU_SI
68 MODULE_FIRMWARE(FIRMWARE_VCE_V1_0);
69 #endif
70 #ifdef CONFIG_DRM_AMDGPU_CIK
71 MODULE_FIRMWARE(FIRMWARE_BONAIRE);
72 MODULE_FIRMWARE(FIRMWARE_KABINI);
73 MODULE_FIRMWARE(FIRMWARE_KAVERI);
74 MODULE_FIRMWARE(FIRMWARE_HAWAII);
75 MODULE_FIRMWARE(FIRMWARE_MULLINS);
76 #endif
77 MODULE_FIRMWARE(FIRMWARE_TONGA);
78 MODULE_FIRMWARE(FIRMWARE_CARRIZO);
79 MODULE_FIRMWARE(FIRMWARE_FIJI);
80 MODULE_FIRMWARE(FIRMWARE_STONEY);
81 MODULE_FIRMWARE(FIRMWARE_POLARIS10);
82 MODULE_FIRMWARE(FIRMWARE_POLARIS11);
83 MODULE_FIRMWARE(FIRMWARE_POLARIS12);
84 MODULE_FIRMWARE(FIRMWARE_VEGAM);
85
86 MODULE_FIRMWARE(FIRMWARE_VEGA10);
87 MODULE_FIRMWARE(FIRMWARE_VEGA12);
88 MODULE_FIRMWARE(FIRMWARE_VEGA20);
89
90 static void amdgpu_vce_idle_work_handler(struct work_struct *work);
91 static int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
92 struct dma_fence **fence);
93 static int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
94 bool direct, struct dma_fence **fence);
95
96 /**
97 * amdgpu_vce_firmware_name() - determine the firmware file name for VCE
98 *
99 * @adev: amdgpu_device pointer
100 *
101 * Each chip that has VCE IP may need a different firmware.
102 * This function returns the name of the VCE firmware file
103 * appropriate for the current chip.
104 */
amdgpu_vce_firmware_name(struct amdgpu_device * adev)105 static const char *amdgpu_vce_firmware_name(struct amdgpu_device *adev)
106 {
107 switch (adev->asic_type) {
108 #ifdef CONFIG_DRM_AMDGPU_SI
109 case CHIP_PITCAIRN:
110 case CHIP_TAHITI:
111 case CHIP_VERDE:
112 return FIRMWARE_VCE_V1_0;
113 #endif
114 #ifdef CONFIG_DRM_AMDGPU_CIK
115 case CHIP_BONAIRE:
116 return FIRMWARE_BONAIRE;
117 case CHIP_KAVERI:
118 return FIRMWARE_KAVERI;
119 case CHIP_KABINI:
120 return FIRMWARE_KABINI;
121 case CHIP_HAWAII:
122 return FIRMWARE_HAWAII;
123 case CHIP_MULLINS:
124 return FIRMWARE_MULLINS;
125 #endif
126 case CHIP_TONGA:
127 return FIRMWARE_TONGA;
128 case CHIP_CARRIZO:
129 return FIRMWARE_CARRIZO;
130 case CHIP_FIJI:
131 return FIRMWARE_FIJI;
132 case CHIP_STONEY:
133 return FIRMWARE_STONEY;
134 case CHIP_POLARIS10:
135 return FIRMWARE_POLARIS10;
136 case CHIP_POLARIS11:
137 return FIRMWARE_POLARIS11;
138 case CHIP_POLARIS12:
139 return FIRMWARE_POLARIS12;
140 case CHIP_VEGAM:
141 return FIRMWARE_VEGAM;
142 case CHIP_VEGA10:
143 return FIRMWARE_VEGA10;
144 case CHIP_VEGA12:
145 return FIRMWARE_VEGA12;
146 case CHIP_VEGA20:
147 return FIRMWARE_VEGA20;
148
149 default:
150 return NULL;
151 }
152 }
153
154 /**
155 * amdgpu_vce_early_init() - try to load VCE firmware
156 *
157 * @adev: amdgpu_device pointer
158 *
159 * Tries to load the VCE firmware.
160 *
161 * When not found, returns ENOENT so that the driver can
162 * still load and initialize the rest of the IP blocks.
163 * The GPU can function just fine without VCE, they will just
164 * not support video encoding.
165 */
amdgpu_vce_early_init(struct amdgpu_device * adev)166 int amdgpu_vce_early_init(struct amdgpu_device *adev)
167 {
168 const char *fw_name = amdgpu_vce_firmware_name(adev);
169 const struct common_firmware_header *hdr;
170 unsigned int ucode_version, version_major, version_minor, binary_id;
171 int r;
172
173 if (!fw_name)
174 return -ENOENT;
175
176 r = amdgpu_ucode_request(adev, &adev->vce.fw, AMDGPU_UCODE_REQUIRED, "%s", fw_name);
177 if (r) {
178 dev_err(adev->dev,
179 "amdgpu_vce: Firmware \"%s\" not found or failed to validate (%d)\n",
180 fw_name, r);
181
182 amdgpu_ucode_release(&adev->vce.fw);
183 return -ENOENT;
184 }
185
186 hdr = (const struct common_firmware_header *)adev->vce.fw->data;
187
188 ucode_version = le32_to_cpu(hdr->ucode_version);
189 version_major = (ucode_version >> 20) & 0xfff;
190 version_minor = (ucode_version >> 8) & 0xfff;
191 binary_id = ucode_version & 0xff;
192 dev_info(adev->dev, "Found VCE firmware Version: %d.%d Binary ID: %d\n",
193 version_major, version_minor, binary_id);
194 adev->vce.fw_version = ((version_major << 24) | (version_minor << 16) |
195 (binary_id << 8));
196
197 return 0;
198 }
199
200 /**
201 * amdgpu_vce_sw_init() - allocate memory for VCE BO
202 *
203 * @adev: amdgpu_device pointer
204 * @size: size for the new BO
205 *
206 * First step to get VCE online: allocate memory for VCE BO.
207 * The VCE firmware binary is copied into the VCE BO later,
208 * in amdgpu_vce_resume. The VCE executes its code from the
209 * VCE BO and also uses the space in this BO for its stack and data.
210 *
211 * Ideally this BO should be placed in VRAM for optimal performance,
212 * although technically it also runs from system RAM (albeit slowly).
213 */
amdgpu_vce_sw_init(struct amdgpu_device * adev,unsigned long size)214 int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
215 {
216 int i, r;
217
218 if (!adev->vce.fw)
219 return -ENOENT;
220
221 r = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE,
222 AMDGPU_GEM_DOMAIN_VRAM |
223 AMDGPU_GEM_DOMAIN_GTT,
224 &adev->vce.vcpu_bo,
225 &adev->vce.gpu_addr, &adev->vce.cpu_addr);
226 if (r) {
227 dev_err(adev->dev, "(%d) failed to allocate VCE bo\n", r);
228 return r;
229 }
230
231 for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) {
232 atomic_set(&adev->vce.handles[i], 0);
233 adev->vce.filp[i] = NULL;
234 }
235
236 INIT_DELAYED_WORK(&adev->vce.idle_work, amdgpu_vce_idle_work_handler);
237 mutex_init(&adev->vce.idle_mutex);
238
239 return 0;
240 }
241
242 /**
243 * amdgpu_vce_sw_fini - free memory
244 *
245 * @adev: amdgpu_device pointer
246 *
247 * Last step on VCE teardown, free firmware memory
248 */
amdgpu_vce_sw_fini(struct amdgpu_device * adev)249 int amdgpu_vce_sw_fini(struct amdgpu_device *adev)
250 {
251 unsigned int i;
252
253 if (adev->vce.vcpu_bo == NULL)
254 return 0;
255
256 drm_sched_entity_destroy(&adev->vce.entity);
257
258 for (i = 0; i < adev->vce.num_rings; i++)
259 amdgpu_ring_fini(&adev->vce.ring[i]);
260
261 amdgpu_ucode_release(&adev->vce.fw);
262 mutex_destroy(&adev->vce.idle_mutex);
263
264 amdgpu_bo_free_kernel(&adev->vce.vcpu_bo, &adev->vce.gpu_addr,
265 (void **)&adev->vce.cpu_addr);
266
267 return 0;
268 }
269
270 /**
271 * amdgpu_vce_entity_init - init entity
272 *
273 * @adev: amdgpu_device pointer
274 * @ring: amdgpu_ring pointer to check
275 *
276 * Initialize the entity used for handle management in the kernel driver.
277 */
amdgpu_vce_entity_init(struct amdgpu_device * adev,struct amdgpu_ring * ring)278 int amdgpu_vce_entity_init(struct amdgpu_device *adev, struct amdgpu_ring *ring)
279 {
280 if (ring == &adev->vce.ring[0]) {
281 struct drm_gpu_scheduler *sched = &ring->sched;
282 int r;
283
284 r = drm_sched_entity_init(&adev->vce.entity, DRM_SCHED_PRIORITY_NORMAL,
285 &sched, 1, NULL);
286 if (r != 0) {
287 DRM_ERROR("Failed setting up VCE run queue.\n");
288 return r;
289 }
290 }
291
292 return 0;
293 }
294
295 /**
296 * amdgpu_vce_suspend - unpin VCE fw memory
297 *
298 * @adev: amdgpu_device pointer
299 *
300 */
amdgpu_vce_suspend(struct amdgpu_device * adev)301 int amdgpu_vce_suspend(struct amdgpu_device *adev)
302 {
303 int i;
304
305 cancel_delayed_work_sync(&adev->vce.idle_work);
306
307 if (adev->vce.vcpu_bo == NULL)
308 return 0;
309
310 for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i)
311 if (atomic_read(&adev->vce.handles[i]))
312 break;
313
314 if (i == AMDGPU_MAX_VCE_HANDLES)
315 return 0;
316
317 /* TODO: suspending running encoding sessions isn't supported */
318 return -EINVAL;
319 }
320
321 /**
322 * amdgpu_vce_resume - pin VCE fw memory
323 *
324 * @adev: amdgpu_device pointer
325 *
326 */
amdgpu_vce_resume(struct amdgpu_device * adev)327 int amdgpu_vce_resume(struct amdgpu_device *adev)
328 {
329 const struct common_firmware_header *hdr;
330 unsigned int offset;
331 int idx;
332
333 if (adev->vce.vcpu_bo == NULL)
334 return -EINVAL;
335
336 hdr = (const struct common_firmware_header *)adev->vce.fw->data;
337 offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
338
339 if (drm_dev_enter(adev_to_drm(adev), &idx)) {
340 memset_io(adev->vce.cpu_addr, 0, amdgpu_bo_size(adev->vce.vcpu_bo));
341 memcpy_toio(adev->vce.cpu_addr, adev->vce.fw->data + offset,
342 adev->vce.fw->size - offset);
343 drm_dev_exit(idx);
344 }
345
346 return 0;
347 }
348
349 /**
350 * amdgpu_vce_idle_work_handler - power off VCE
351 *
352 * @work: pointer to work structure
353 *
354 * power of VCE when it's not used any more
355 */
amdgpu_vce_idle_work_handler(struct work_struct * work)356 static void amdgpu_vce_idle_work_handler(struct work_struct *work)
357 {
358 struct amdgpu_device *adev =
359 container_of(work, struct amdgpu_device, vce.idle_work.work);
360 unsigned int i, count = 0;
361
362 for (i = 0; i < adev->vce.num_rings; i++)
363 count += amdgpu_fence_count_emitted(&adev->vce.ring[i]);
364
365 if (count == 0) {
366 if (adev->pm.dpm_enabled) {
367 amdgpu_dpm_enable_vce(adev, false);
368 } else {
369 amdgpu_asic_set_vce_clocks(adev, 0, 0);
370 amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
371 AMD_PG_STATE_GATE);
372 amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
373 AMD_CG_STATE_GATE);
374 }
375 } else {
376 schedule_delayed_work(&adev->vce.idle_work, VCE_IDLE_TIMEOUT);
377 }
378 }
379
380 /**
381 * amdgpu_vce_ring_begin_use - power up VCE
382 *
383 * @ring: amdgpu ring
384 *
385 * Make sure VCE is powerd up when we want to use it
386 */
amdgpu_vce_ring_begin_use(struct amdgpu_ring * ring)387 void amdgpu_vce_ring_begin_use(struct amdgpu_ring *ring)
388 {
389 struct amdgpu_device *adev = ring->adev;
390 bool set_clocks;
391
392 if (amdgpu_sriov_vf(adev))
393 return;
394
395 mutex_lock(&adev->vce.idle_mutex);
396 set_clocks = !cancel_delayed_work_sync(&adev->vce.idle_work);
397 if (set_clocks) {
398 if (adev->pm.dpm_enabled) {
399 amdgpu_dpm_enable_vce(adev, true);
400 } else {
401 amdgpu_asic_set_vce_clocks(adev, 53300, 40000);
402 amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
403 AMD_CG_STATE_UNGATE);
404 amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
405 AMD_PG_STATE_UNGATE);
406
407 }
408 }
409 mutex_unlock(&adev->vce.idle_mutex);
410 }
411
412 /**
413 * amdgpu_vce_ring_end_use - power VCE down
414 *
415 * @ring: amdgpu ring
416 *
417 * Schedule work to power VCE down again
418 */
amdgpu_vce_ring_end_use(struct amdgpu_ring * ring)419 void amdgpu_vce_ring_end_use(struct amdgpu_ring *ring)
420 {
421 if (!amdgpu_sriov_vf(ring->adev))
422 schedule_delayed_work(&ring->adev->vce.idle_work, VCE_IDLE_TIMEOUT);
423 }
424
425 /**
426 * amdgpu_vce_free_handles - free still open VCE handles
427 *
428 * @adev: amdgpu_device pointer
429 * @filp: drm file pointer
430 *
431 * Close all VCE handles still open by this file pointer
432 */
amdgpu_vce_free_handles(struct amdgpu_device * adev,struct drm_file * filp)433 void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
434 {
435 struct amdgpu_ring *ring = &adev->vce.ring[0];
436 int i, r;
437
438 for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) {
439 uint32_t handle = atomic_read(&adev->vce.handles[i]);
440
441 if (!handle || adev->vce.filp[i] != filp)
442 continue;
443
444 r = amdgpu_vce_get_destroy_msg(ring, handle, false, NULL);
445 if (r)
446 DRM_ERROR("Error destroying VCE handle (%d)!\n", r);
447
448 adev->vce.filp[i] = NULL;
449 atomic_set(&adev->vce.handles[i], 0);
450 }
451 }
452
453 /**
454 * amdgpu_vce_get_create_msg - generate a VCE create msg
455 *
456 * @ring: ring we should submit the msg to
457 * @handle: VCE session handle to use
458 * @fence: optional fence to return
459 *
460 * Open up a stream for HW test
461 */
amdgpu_vce_get_create_msg(struct amdgpu_ring * ring,uint32_t handle,struct dma_fence ** fence)462 static int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
463 struct dma_fence **fence)
464 {
465 const unsigned int ib_size_dw = 1024;
466 struct amdgpu_job *job;
467 struct amdgpu_ib *ib;
468 struct amdgpu_ib ib_msg;
469 struct dma_fence *f = NULL;
470 uint64_t addr;
471 int i, r;
472
473 r = amdgpu_job_alloc_with_ib(ring->adev, &ring->adev->vce.entity,
474 AMDGPU_FENCE_OWNER_UNDEFINED,
475 ib_size_dw * 4, AMDGPU_IB_POOL_DIRECT,
476 AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST,
477 &job);
478 if (r)
479 return r;
480
481 memset(&ib_msg, 0, sizeof(ib_msg));
482 /* only one gpu page is needed, alloc +1 page to make addr aligned. */
483 r = amdgpu_ib_get(ring->adev, NULL, AMDGPU_GPU_PAGE_SIZE * 2,
484 AMDGPU_IB_POOL_DIRECT,
485 &ib_msg);
486 if (r)
487 goto err;
488
489 ib = &job->ibs[0];
490 /* let addr point to page boundary */
491 addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg.gpu_addr);
492
493 /* stitch together an VCE create msg */
494 ib->length_dw = 0;
495 ib->ptr[ib->length_dw++] = 0x0000000c; /* len */
496 ib->ptr[ib->length_dw++] = 0x00000001; /* session cmd */
497 ib->ptr[ib->length_dw++] = handle;
498
499 if ((ring->adev->vce.fw_version >> 24) >= 52)
500 ib->ptr[ib->length_dw++] = 0x00000040; /* len */
501 else
502 ib->ptr[ib->length_dw++] = 0x00000030; /* len */
503 ib->ptr[ib->length_dw++] = 0x01000001; /* create cmd */
504 ib->ptr[ib->length_dw++] = 0x00000000;
505 ib->ptr[ib->length_dw++] = 0x00000042;
506 ib->ptr[ib->length_dw++] = 0x0000000a;
507 ib->ptr[ib->length_dw++] = 0x00000001;
508 ib->ptr[ib->length_dw++] = 0x00000080;
509 ib->ptr[ib->length_dw++] = 0x00000060;
510 ib->ptr[ib->length_dw++] = 0x00000100;
511 ib->ptr[ib->length_dw++] = 0x00000100;
512 ib->ptr[ib->length_dw++] = 0x0000000c;
513 ib->ptr[ib->length_dw++] = 0x00000000;
514 if ((ring->adev->vce.fw_version >> 24) >= 52) {
515 ib->ptr[ib->length_dw++] = 0x00000000;
516 ib->ptr[ib->length_dw++] = 0x00000000;
517 ib->ptr[ib->length_dw++] = 0x00000000;
518 ib->ptr[ib->length_dw++] = 0x00000000;
519 }
520
521 ib->ptr[ib->length_dw++] = 0x00000014; /* len */
522 ib->ptr[ib->length_dw++] = 0x05000005; /* feedback buffer */
523 ib->ptr[ib->length_dw++] = upper_32_bits(addr);
524 ib->ptr[ib->length_dw++] = addr;
525 ib->ptr[ib->length_dw++] = 0x00000001;
526
527 for (i = ib->length_dw; i < ib_size_dw; ++i)
528 ib->ptr[i] = 0x0;
529
530 r = amdgpu_job_submit_direct(job, ring, &f);
531 amdgpu_ib_free(&ib_msg, f);
532 if (r)
533 goto err;
534
535 if (fence)
536 *fence = dma_fence_get(f);
537 dma_fence_put(f);
538 return 0;
539
540 err:
541 amdgpu_job_free(job);
542 return r;
543 }
544
545 /**
546 * amdgpu_vce_get_destroy_msg - generate a VCE destroy msg
547 *
548 * @ring: ring we should submit the msg to
549 * @handle: VCE session handle to use
550 * @direct: direct or delayed pool
551 * @fence: optional fence to return
552 *
553 * Close up a stream for HW test or if userspace failed to do so
554 */
amdgpu_vce_get_destroy_msg(struct amdgpu_ring * ring,uint32_t handle,bool direct,struct dma_fence ** fence)555 static int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
556 bool direct, struct dma_fence **fence)
557 {
558 const unsigned int ib_size_dw = 1024;
559 struct amdgpu_job *job;
560 struct amdgpu_ib *ib;
561 struct dma_fence *f = NULL;
562 int i, r;
563
564 r = amdgpu_job_alloc_with_ib(ring->adev, &ring->adev->vce.entity,
565 AMDGPU_FENCE_OWNER_UNDEFINED,
566 ib_size_dw * 4,
567 direct ? AMDGPU_IB_POOL_DIRECT :
568 AMDGPU_IB_POOL_DELAYED,
569 AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST,
570 &job);
571 if (r)
572 return r;
573
574 ib = &job->ibs[0];
575
576 /* stitch together an VCE destroy msg */
577 ib->length_dw = 0;
578 ib->ptr[ib->length_dw++] = 0x0000000c; /* len */
579 ib->ptr[ib->length_dw++] = 0x00000001; /* session cmd */
580 ib->ptr[ib->length_dw++] = handle;
581
582 ib->ptr[ib->length_dw++] = 0x00000020; /* len */
583 ib->ptr[ib->length_dw++] = 0x00000002; /* task info */
584 ib->ptr[ib->length_dw++] = 0xffffffff; /* next task info, set to 0xffffffff if no */
585 ib->ptr[ib->length_dw++] = 0x00000001; /* destroy session */
586 ib->ptr[ib->length_dw++] = 0x00000000;
587 ib->ptr[ib->length_dw++] = 0x00000000;
588 ib->ptr[ib->length_dw++] = 0xffffffff; /* feedback is not needed, set to 0xffffffff and firmware will not output feedback */
589 ib->ptr[ib->length_dw++] = 0x00000000;
590
591 ib->ptr[ib->length_dw++] = 0x00000008; /* len */
592 ib->ptr[ib->length_dw++] = 0x02000001; /* destroy cmd */
593
594 for (i = ib->length_dw; i < ib_size_dw; ++i)
595 ib->ptr[i] = 0x0;
596
597 if (direct)
598 r = amdgpu_job_submit_direct(job, ring, &f);
599 else
600 f = amdgpu_job_submit(job);
601 if (r)
602 goto err;
603
604 if (fence)
605 *fence = dma_fence_get(f);
606 dma_fence_put(f);
607 return 0;
608
609 err:
610 amdgpu_job_free(job);
611 return r;
612 }
613
614 /**
615 * amdgpu_vce_validate_bo - make sure not to cross 4GB boundary
616 *
617 * @p: cs parser
618 * @ib: indirect buffer to use
619 * @lo: address of lower dword
620 * @hi: address of higher dword
621 * @size: minimum size
622 * @index: bs/fb index
623 *
624 * Make sure that no BO cross a 4GB boundary.
625 */
amdgpu_vce_validate_bo(struct amdgpu_cs_parser * p,struct amdgpu_ib * ib,int lo,int hi,unsigned int size,int32_t index)626 static int amdgpu_vce_validate_bo(struct amdgpu_cs_parser *p,
627 struct amdgpu_ib *ib, int lo, int hi,
628 unsigned int size, int32_t index)
629 {
630 int64_t offset = ((uint64_t)size) * ((int64_t)index);
631 struct ttm_operation_ctx ctx = { false, false };
632 struct amdgpu_bo_va_mapping *mapping;
633 unsigned int i, fpfn, lpfn;
634 struct amdgpu_bo *bo;
635 uint64_t addr;
636 int r;
637
638 addr = ((uint64_t)amdgpu_ib_get_value(ib, lo)) |
639 ((uint64_t)amdgpu_ib_get_value(ib, hi)) << 32;
640 if (index >= 0) {
641 addr += offset;
642 fpfn = PAGE_ALIGN(offset) >> PAGE_SHIFT;
643 lpfn = 0x100000000ULL >> PAGE_SHIFT;
644 } else {
645 fpfn = 0;
646 lpfn = (0x100000000ULL - PAGE_ALIGN(offset)) >> PAGE_SHIFT;
647 }
648
649 r = amdgpu_cs_find_mapping(p, addr, &bo, &mapping);
650 if (r) {
651 DRM_ERROR("Can't find BO for addr 0x%010llx %d %d %d %d\n",
652 addr, lo, hi, size, index);
653 return r;
654 }
655
656 for (i = 0; i < bo->placement.num_placement; ++i) {
657 bo->placements[i].fpfn = max(bo->placements[i].fpfn, fpfn);
658 bo->placements[i].lpfn = bo->placements[i].lpfn ?
659 min(bo->placements[i].lpfn, lpfn) : lpfn;
660 }
661 return ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
662 }
663
664
665 /**
666 * amdgpu_vce_cs_reloc - command submission relocation
667 *
668 * @p: parser context
669 * @ib: indirect buffer to use
670 * @lo: address of lower dword
671 * @hi: address of higher dword
672 * @size: minimum size
673 * @index: bs/fb index
674 *
675 * Patch relocation inside command stream with real buffer address
676 */
amdgpu_vce_cs_reloc(struct amdgpu_cs_parser * p,struct amdgpu_ib * ib,int lo,int hi,unsigned int size,uint32_t index)677 static int amdgpu_vce_cs_reloc(struct amdgpu_cs_parser *p, struct amdgpu_ib *ib,
678 int lo, int hi, unsigned int size, uint32_t index)
679 {
680 struct amdgpu_bo_va_mapping *mapping;
681 struct amdgpu_bo *bo;
682 uint64_t addr;
683 int r;
684
685 if (lo >= ib->length_dw || hi >= ib->length_dw)
686 return -EINVAL;
687
688 if (index == 0xffffffff)
689 index = 0;
690
691 addr = ((uint64_t)amdgpu_ib_get_value(ib, lo)) |
692 ((uint64_t)amdgpu_ib_get_value(ib, hi)) << 32;
693 addr += ((uint64_t)size) * ((uint64_t)index);
694
695 r = amdgpu_cs_find_mapping(p, addr, &bo, &mapping);
696 if (r) {
697 DRM_ERROR("Can't find BO for addr 0x%010llx %d %d %d %d\n",
698 addr, lo, hi, size, index);
699 return r;
700 }
701
702 if ((addr + (uint64_t)size) >
703 (mapping->last + 1) * AMDGPU_GPU_PAGE_SIZE) {
704 DRM_ERROR("BO too small for addr 0x%010llx %d %d\n",
705 addr, lo, hi);
706 return -EINVAL;
707 }
708
709 addr -= mapping->start * AMDGPU_GPU_PAGE_SIZE;
710 addr += amdgpu_bo_gpu_offset(bo);
711 addr -= ((uint64_t)size) * ((uint64_t)index);
712
713 amdgpu_ib_set_value(ib, lo, lower_32_bits(addr));
714 amdgpu_ib_set_value(ib, hi, upper_32_bits(addr));
715
716 return 0;
717 }
718
719 /**
720 * amdgpu_vce_validate_handle - validate stream handle
721 *
722 * @p: parser context
723 * @handle: handle to validate
724 * @allocated: allocated a new handle?
725 *
726 * Validates the handle and return the found session index or -EINVAL
727 * we don't have another free session index.
728 */
amdgpu_vce_validate_handle(struct amdgpu_cs_parser * p,uint32_t handle,uint32_t * allocated)729 static int amdgpu_vce_validate_handle(struct amdgpu_cs_parser *p,
730 uint32_t handle, uint32_t *allocated)
731 {
732 unsigned int i;
733
734 /* validate the handle */
735 for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) {
736 if (atomic_read(&p->adev->vce.handles[i]) == handle) {
737 if (p->adev->vce.filp[i] != p->filp) {
738 DRM_ERROR("VCE handle collision detected!\n");
739 return -EINVAL;
740 }
741 return i;
742 }
743 }
744
745 /* handle not found try to alloc a new one */
746 for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) {
747 if (!atomic_cmpxchg(&p->adev->vce.handles[i], 0, handle)) {
748 p->adev->vce.filp[i] = p->filp;
749 p->adev->vce.img_size[i] = 0;
750 *allocated |= 1 << i;
751 return i;
752 }
753 }
754
755 DRM_ERROR("No more free VCE handles!\n");
756 return -EINVAL;
757 }
758
759 /**
760 * amdgpu_vce_ring_parse_cs - parse and validate the command stream
761 *
762 * @p: parser context
763 * @job: the job to parse
764 * @ib: the IB to patch
765 */
amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser * p,struct amdgpu_job * job,struct amdgpu_ib * ib)766 int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p,
767 struct amdgpu_job *job,
768 struct amdgpu_ib *ib)
769 {
770 unsigned int fb_idx = 0, bs_idx = 0;
771 int session_idx = -1;
772 uint32_t destroyed = 0;
773 uint32_t created = 0;
774 uint32_t allocated = 0;
775 uint32_t tmp, handle = 0;
776 uint32_t dummy = 0xffffffff;
777 uint32_t *size = &dummy;
778 unsigned int idx;
779 int i, r = 0;
780
781 job->vm = NULL;
782
783 for (idx = 0; idx < ib->length_dw;) {
784 uint32_t len = amdgpu_ib_get_value(ib, idx);
785 uint32_t cmd = amdgpu_ib_get_value(ib, idx + 1);
786
787 if ((len < 8) || (len & 3)) {
788 DRM_ERROR("invalid VCE command length (%d)!\n", len);
789 r = -EINVAL;
790 goto out;
791 }
792
793 switch (cmd) {
794 case 0x00000002: /* task info */
795 fb_idx = amdgpu_ib_get_value(ib, idx + 6);
796 bs_idx = amdgpu_ib_get_value(ib, idx + 7);
797 break;
798
799 case 0x03000001: /* encode */
800 r = amdgpu_vce_validate_bo(p, ib, idx + 10, idx + 9,
801 0, 0);
802 if (r)
803 goto out;
804
805 r = amdgpu_vce_validate_bo(p, ib, idx + 12, idx + 11,
806 0, 0);
807 if (r)
808 goto out;
809 break;
810
811 case 0x05000001: /* context buffer */
812 r = amdgpu_vce_validate_bo(p, ib, idx + 3, idx + 2,
813 0, 0);
814 if (r)
815 goto out;
816 break;
817
818 case 0x05000004: /* video bitstream buffer */
819 tmp = amdgpu_ib_get_value(ib, idx + 4);
820 r = amdgpu_vce_validate_bo(p, ib, idx + 3, idx + 2,
821 tmp, bs_idx);
822 if (r)
823 goto out;
824 break;
825
826 case 0x05000005: /* feedback buffer */
827 r = amdgpu_vce_validate_bo(p, ib, idx + 3, idx + 2,
828 4096, fb_idx);
829 if (r)
830 goto out;
831 break;
832
833 case 0x0500000d: /* MV buffer */
834 r = amdgpu_vce_validate_bo(p, ib, idx + 3, idx + 2,
835 0, 0);
836 if (r)
837 goto out;
838
839 r = amdgpu_vce_validate_bo(p, ib, idx + 8, idx + 7,
840 0, 0);
841 if (r)
842 goto out;
843 break;
844 }
845
846 idx += len / 4;
847 }
848
849 for (idx = 0; idx < ib->length_dw;) {
850 uint32_t len = amdgpu_ib_get_value(ib, idx);
851 uint32_t cmd = amdgpu_ib_get_value(ib, idx + 1);
852
853 switch (cmd) {
854 case 0x00000001: /* session */
855 handle = amdgpu_ib_get_value(ib, idx + 2);
856 session_idx = amdgpu_vce_validate_handle(p, handle,
857 &allocated);
858 if (session_idx < 0) {
859 r = session_idx;
860 goto out;
861 }
862 size = &p->adev->vce.img_size[session_idx];
863 break;
864
865 case 0x00000002: /* task info */
866 fb_idx = amdgpu_ib_get_value(ib, idx + 6);
867 bs_idx = amdgpu_ib_get_value(ib, idx + 7);
868 break;
869
870 case 0x01000001: /* create */
871 created |= 1 << session_idx;
872 if (destroyed & (1 << session_idx)) {
873 destroyed &= ~(1 << session_idx);
874 allocated |= 1 << session_idx;
875
876 } else if (!(allocated & (1 << session_idx))) {
877 DRM_ERROR("Handle already in use!\n");
878 r = -EINVAL;
879 goto out;
880 }
881
882 uint32_t width, height;
883 width = amdgpu_ib_get_value(ib, idx + 8);
884 height = amdgpu_ib_get_value(ib, idx + 10);
885
886 if (width == 0 || height == 0 ||
887 width > 4096 || height > 2304) {
888 DRM_ERROR("invalid VCE image size: %ux%u\n",
889 width, height);
890 r = -EINVAL;
891 goto out;
892 }
893
894 *size = width * height * 8 * 3 / 2;
895
896 break;
897
898 case 0x04000001: /* config extension */
899 case 0x04000002: /* pic control */
900 case 0x04000005: /* rate control */
901 case 0x04000007: /* motion estimation */
902 case 0x04000008: /* rdo */
903 case 0x04000009: /* vui */
904 case 0x05000002: /* auxiliary buffer */
905 case 0x05000009: /* clock table */
906 break;
907
908 case 0x0500000c: /* hw config */
909 switch (p->adev->asic_type) {
910 #ifdef CONFIG_DRM_AMDGPU_CIK
911 case CHIP_KAVERI:
912 case CHIP_MULLINS:
913 #endif
914 case CHIP_CARRIZO:
915 break;
916 default:
917 r = -EINVAL;
918 goto out;
919 }
920 break;
921
922 case 0x03000001: /* encode */
923 r = amdgpu_vce_cs_reloc(p, ib, idx + 10, idx + 9,
924 *size, 0);
925 if (r)
926 goto out;
927
928 r = amdgpu_vce_cs_reloc(p, ib, idx + 12, idx + 11,
929 *size / 3, 0);
930 if (r)
931 goto out;
932 break;
933
934 case 0x02000001: /* destroy */
935 destroyed |= 1 << session_idx;
936 break;
937
938 case 0x05000001: /* context buffer */
939 r = amdgpu_vce_cs_reloc(p, ib, idx + 3, idx + 2,
940 *size * 2, 0);
941 if (r)
942 goto out;
943 break;
944
945 case 0x05000004: /* video bitstream buffer */
946 tmp = amdgpu_ib_get_value(ib, idx + 4);
947 r = amdgpu_vce_cs_reloc(p, ib, idx + 3, idx + 2,
948 tmp, bs_idx);
949 if (r)
950 goto out;
951 break;
952
953 case 0x05000005: /* feedback buffer */
954 r = amdgpu_vce_cs_reloc(p, ib, idx + 3, idx + 2,
955 4096, fb_idx);
956 if (r)
957 goto out;
958 break;
959
960 case 0x0500000d: /* MV buffer */
961 r = amdgpu_vce_cs_reloc(p, ib, idx + 3,
962 idx + 2, *size, 0);
963 if (r)
964 goto out;
965
966 r = amdgpu_vce_cs_reloc(p, ib, idx + 8,
967 idx + 7, *size / 12, 0);
968 if (r)
969 goto out;
970 break;
971
972 default:
973 DRM_ERROR("invalid VCE command (0x%x)!\n", cmd);
974 r = -EINVAL;
975 goto out;
976 }
977
978 if (session_idx == -1) {
979 DRM_ERROR("no session command at start of IB\n");
980 r = -EINVAL;
981 goto out;
982 }
983
984 idx += len / 4;
985 }
986
987 if (allocated & ~created) {
988 DRM_ERROR("New session without create command!\n");
989 r = -ENOENT;
990 }
991
992 out:
993 if (!r) {
994 /* No error, free all destroyed handle slots */
995 tmp = destroyed;
996 } else {
997 /* Error during parsing, free all allocated handle slots */
998 tmp = allocated;
999 }
1000
1001 for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i)
1002 if (tmp & (1 << i))
1003 atomic_set(&p->adev->vce.handles[i], 0);
1004
1005 return r;
1006 }
1007
1008 /**
1009 * amdgpu_vce_ring_parse_cs_vm - parse the command stream in VM mode
1010 *
1011 * @p: parser context
1012 * @job: the job to parse
1013 * @ib: the IB to patch
1014 */
amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser * p,struct amdgpu_job * job,struct amdgpu_ib * ib)1015 int amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser *p,
1016 struct amdgpu_job *job,
1017 struct amdgpu_ib *ib)
1018 {
1019 int session_idx = -1;
1020 uint32_t destroyed = 0;
1021 uint32_t created = 0;
1022 uint32_t allocated = 0;
1023 uint32_t tmp, handle = 0;
1024 int i, r = 0, idx = 0;
1025
1026 while (idx < ib->length_dw) {
1027 uint32_t len = amdgpu_ib_get_value(ib, idx);
1028 uint32_t cmd = amdgpu_ib_get_value(ib, idx + 1);
1029
1030 if ((len < 8) || (len & 3)) {
1031 DRM_ERROR("invalid VCE command length (%d)!\n", len);
1032 r = -EINVAL;
1033 goto out;
1034 }
1035
1036 switch (cmd) {
1037 case 0x00000001: /* session */
1038 handle = amdgpu_ib_get_value(ib, idx + 2);
1039 session_idx = amdgpu_vce_validate_handle(p, handle,
1040 &allocated);
1041 if (session_idx < 0) {
1042 r = session_idx;
1043 goto out;
1044 }
1045 break;
1046
1047 case 0x01000001: /* create */
1048 created |= 1 << session_idx;
1049 if (destroyed & (1 << session_idx)) {
1050 destroyed &= ~(1 << session_idx);
1051 allocated |= 1 << session_idx;
1052
1053 } else if (!(allocated & (1 << session_idx))) {
1054 DRM_ERROR("Handle already in use!\n");
1055 r = -EINVAL;
1056 goto out;
1057 }
1058
1059 break;
1060
1061 case 0x02000001: /* destroy */
1062 destroyed |= 1 << session_idx;
1063 break;
1064
1065 default:
1066 break;
1067 }
1068
1069 if (session_idx == -1) {
1070 DRM_ERROR("no session command at start of IB\n");
1071 r = -EINVAL;
1072 goto out;
1073 }
1074
1075 idx += len / 4;
1076 }
1077
1078 if (allocated & ~created) {
1079 DRM_ERROR("New session without create command!\n");
1080 r = -ENOENT;
1081 }
1082
1083 out:
1084 if (!r) {
1085 /* No error, free all destroyed handle slots */
1086 tmp = destroyed;
1087 } else {
1088 /* Error during parsing, free all allocated handle slots */
1089 tmp = allocated;
1090 }
1091
1092 for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i)
1093 if (tmp & (1 << i))
1094 atomic_set(&p->adev->vce.handles[i], 0);
1095
1096 return r;
1097 }
1098
1099 /**
1100 * amdgpu_vce_ring_emit_ib - execute indirect buffer
1101 *
1102 * @ring: engine to use
1103 * @job: job to retrieve vmid from
1104 * @ib: the IB to execute
1105 * @flags: unused
1106 *
1107 */
amdgpu_vce_ring_emit_ib(struct amdgpu_ring * ring,struct amdgpu_job * job,struct amdgpu_ib * ib,uint32_t flags)1108 void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring,
1109 struct amdgpu_job *job,
1110 struct amdgpu_ib *ib,
1111 uint32_t flags)
1112 {
1113 amdgpu_ring_write(ring, VCE_CMD_IB);
1114 amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
1115 amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
1116 amdgpu_ring_write(ring, ib->length_dw);
1117 }
1118
1119 /**
1120 * amdgpu_vce_ring_emit_fence - add a fence command to the ring
1121 *
1122 * @ring: engine to use
1123 * @addr: address
1124 * @seq: sequence number
1125 * @flags: fence related flags
1126 *
1127 */
amdgpu_vce_ring_emit_fence(struct amdgpu_ring * ring,u64 addr,u64 seq,unsigned int flags)1128 void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
1129 unsigned int flags)
1130 {
1131 WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
1132
1133 amdgpu_ring_write(ring, VCE_CMD_FENCE);
1134 amdgpu_ring_write(ring, addr);
1135 amdgpu_ring_write(ring, upper_32_bits(addr));
1136 amdgpu_ring_write(ring, seq);
1137 amdgpu_ring_write(ring, VCE_CMD_TRAP);
1138 amdgpu_ring_write(ring, VCE_CMD_END);
1139 }
1140
1141 /**
1142 * amdgpu_vce_ring_test_ring - test if VCE ring is working
1143 *
1144 * @ring: the engine to test on
1145 *
1146 */
amdgpu_vce_ring_test_ring(struct amdgpu_ring * ring)1147 int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring)
1148 {
1149 struct amdgpu_device *adev = ring->adev;
1150 uint32_t rptr;
1151 unsigned int i;
1152 int r, timeout = adev->usec_timeout;
1153
1154 /* skip ring test for sriov*/
1155 if (amdgpu_sriov_vf(adev))
1156 return 0;
1157
1158 r = amdgpu_ring_alloc(ring, 16);
1159 if (r)
1160 return r;
1161
1162 rptr = amdgpu_ring_get_rptr(ring);
1163
1164 amdgpu_ring_write(ring, VCE_CMD_END);
1165 amdgpu_ring_commit(ring);
1166
1167 for (i = 0; i < timeout; i++) {
1168 if (amdgpu_ring_get_rptr(ring) != rptr)
1169 break;
1170 udelay(1);
1171 }
1172
1173 if (i >= timeout)
1174 r = -ETIMEDOUT;
1175
1176 return r;
1177 }
1178
1179 /**
1180 * amdgpu_vce_ring_test_ib - test if VCE IBs are working
1181 *
1182 * @ring: the engine to test on
1183 * @timeout: timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
1184 *
1185 */
amdgpu_vce_ring_test_ib(struct amdgpu_ring * ring,long timeout)1186 int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout)
1187 {
1188 struct dma_fence *fence = NULL;
1189 long r;
1190
1191 /* skip vce ring1/2 ib test for now, since it's not reliable */
1192 if (ring != &ring->adev->vce.ring[0])
1193 return 0;
1194
1195 r = amdgpu_vce_get_create_msg(ring, 1, NULL);
1196 if (r)
1197 goto error;
1198
1199 r = amdgpu_vce_get_destroy_msg(ring, 1, true, &fence);
1200 if (r)
1201 goto error;
1202
1203 r = dma_fence_wait_timeout(fence, false, timeout);
1204 if (r == 0)
1205 r = -ETIMEDOUT;
1206 else if (r > 0)
1207 r = 0;
1208
1209 error:
1210 dma_fence_put(fence);
1211 return r;
1212 }
1213
amdgpu_vce_get_ring_prio(int ring)1214 enum amdgpu_ring_priority_level amdgpu_vce_get_ring_prio(int ring)
1215 {
1216 switch (ring) {
1217 case 0:
1218 return AMDGPU_RING_PRIO_0;
1219 case 1:
1220 return AMDGPU_RING_PRIO_1;
1221 case 2:
1222 return AMDGPU_RING_PRIO_2;
1223 default:
1224 return AMDGPU_RING_PRIO_0;
1225 }
1226 }
1227