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