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