]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
drm/amdgpu: export reservation_object from dmabuf to ttm (v2)
[karo-tx-linux.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_uvd.c
index 2f7a5efa21c23ab0fda25ee0ebbb360efae966ea..3cc86631d5d6d8d4a1a9d127900f2475d6c7d5c0 100644 (file)
@@ -52,6 +52,7 @@
 #endif
 #define FIRMWARE_TONGA         "amdgpu/tonga_uvd.bin"
 #define FIRMWARE_CARRIZO       "amdgpu/carrizo_uvd.bin"
+#define FIRMWARE_FIJI          "amdgpu/fiji_uvd.bin"
 
 /**
  * amdgpu_uvd_cs_ctx - Command submission parser context
@@ -81,6 +82,7 @@ MODULE_FIRMWARE(FIRMWARE_MULLINS);
 #endif
 MODULE_FIRMWARE(FIRMWARE_TONGA);
 MODULE_FIRMWARE(FIRMWARE_CARRIZO);
+MODULE_FIRMWARE(FIRMWARE_FIJI);
 
 static void amdgpu_uvd_note_usage(struct amdgpu_device *adev);
 static void amdgpu_uvd_idle_work_handler(struct work_struct *work);
@@ -116,6 +118,9 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
        case CHIP_TONGA:
                fw_name = FIRMWARE_TONGA;
                break;
+       case CHIP_FIJI:
+               fw_name = FIRMWARE_FIJI;
+               break;
        case CHIP_CARRIZO:
                fw_name = FIRMWARE_CARRIZO;
                break;
@@ -149,7 +154,9 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
        bo_size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8)
                 +  AMDGPU_UVD_STACK_SIZE + AMDGPU_UVD_HEAP_SIZE;
        r = amdgpu_bo_create(adev, bo_size, PAGE_SIZE, true,
-                            AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, &adev->uvd.vcpu_bo);
+                            AMDGPU_GEM_DOMAIN_VRAM,
+                            AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+                            NULL, NULL, &adev->uvd.vcpu_bo);
        if (r) {
                dev_err(adev->dev, "(%d) failed to allocate UVD bo\n", r);
                return r;
@@ -216,31 +223,32 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev)
 
 int amdgpu_uvd_suspend(struct amdgpu_device *adev)
 {
-       unsigned size;
-       void *ptr;
-       const struct common_firmware_header *hdr;
-       int i;
+       struct amdgpu_ring *ring = &adev->uvd.ring;
+       int i, r;
 
        if (adev->uvd.vcpu_bo == NULL)
                return 0;
 
-       for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i)
-               if (atomic_read(&adev->uvd.handles[i]))
-                       break;
-
-       if (i == AMDGPU_MAX_UVD_HANDLES)
-               return 0;
+       for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) {
+               uint32_t handle = atomic_read(&adev->uvd.handles[i]);
+               if (handle != 0) {
+                       struct fence *fence;
 
-       hdr = (const struct common_firmware_header *)adev->uvd.fw->data;
+                       amdgpu_uvd_note_usage(adev);
 
-       size = amdgpu_bo_size(adev->uvd.vcpu_bo);
-       size -= le32_to_cpu(hdr->ucode_size_bytes);
+                       r = amdgpu_uvd_get_destroy_msg(ring, handle, &fence);
+                       if (r) {
+                               DRM_ERROR("Error destroying UVD (%d)!\n", r);
+                               continue;
+                       }
 
-       ptr = adev->uvd.cpu_addr;
-       ptr += le32_to_cpu(hdr->ucode_size_bytes);
+                       fence_wait(fence, false);
+                       fence_put(fence);
 
-       adev->uvd.saved_bo = kmalloc(size, GFP_KERNEL);
-       memcpy(adev->uvd.saved_bo, ptr, size);
+                       adev->uvd.filp[i] = NULL;
+                       atomic_set(&adev->uvd.handles[i], 0);
+               }
+       }
 
        return 0;
 }
@@ -265,12 +273,7 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
        ptr = adev->uvd.cpu_addr;
        ptr += le32_to_cpu(hdr->ucode_size_bytes);
 
-       if (adev->uvd.saved_bo != NULL) {
-               memcpy(ptr, adev->uvd.saved_bo, size);
-               kfree(adev->uvd.saved_bo);
-               adev->uvd.saved_bo = NULL;
-       } else
-               memset(ptr, 0, size);
+       memset(ptr, 0, size);
 
        return 0;
 }
@@ -283,7 +286,7 @@ void amdgpu_uvd_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
        for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) {
                uint32_t handle = atomic_read(&adev->uvd.handles[i]);
                if (handle != 0 && adev->uvd.filp[i] == filp) {
-                       struct amdgpu_fence *fence;
+                       struct fence *fence;
 
                        amdgpu_uvd_note_usage(adev);
 
@@ -293,8 +296,8 @@ void amdgpu_uvd_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
                                continue;
                        }
 
-                       amdgpu_fence_wait(fence, false);
-                       amdgpu_fence_unref(&fence);
+                       fence_wait(fence, false);
+                       fence_put(fence);
 
                        adev->uvd.filp[i] = NULL;
                        atomic_set(&adev->uvd.handles[i], 0);
@@ -375,6 +378,7 @@ static int amdgpu_uvd_cs_msg_decode(uint32_t *msg, unsigned buf_sizes[])
        unsigned fs_in_mb = width_in_mb * height_in_mb;
 
        unsigned image_size, tmp, min_dpb_size, num_dpb_buffer;
+       unsigned min_ctx_size = 0;
 
        image_size = width * height;
        image_size += image_size / 2;
@@ -466,6 +470,8 @@ static int amdgpu_uvd_cs_msg_decode(uint32_t *msg, unsigned buf_sizes[])
 
                num_dpb_buffer = (le32_to_cpu(msg[59]) & 0xff) + 2;
                min_dpb_size = image_size * num_dpb_buffer;
+               min_ctx_size = ((width + 255) / 16) * ((height + 255) / 16)
+                                          * 16 * num_dpb_buffer + 52 * 1024;
                break;
 
        default:
@@ -486,6 +492,7 @@ static int amdgpu_uvd_cs_msg_decode(uint32_t *msg, unsigned buf_sizes[])
 
        buf_sizes[0x1] = dpb_size;
        buf_sizes[0x2] = image_size;
+       buf_sizes[0x4] = min_ctx_size;
        return 0;
 }
 
@@ -504,28 +511,25 @@ static int amdgpu_uvd_cs_msg(struct amdgpu_uvd_cs_ctx *ctx,
 {
        struct amdgpu_device *adev = ctx->parser->adev;
        int32_t *msg, msg_type, handle;
-       struct fence *f;
        void *ptr;
-
-       int i, r;
+       long r;
+       int i;
 
        if (offset & 0x3F) {
                DRM_ERROR("UVD messages must be 64 byte aligned!\n");
                return -EINVAL;
        }
 
-       f = reservation_object_get_excl(bo->tbo.resv);
-       if (f) {
-               r = amdgpu_fence_wait((struct amdgpu_fence *)f, false);
-               if (r) {
-                       DRM_ERROR("Failed waiting for UVD message (%d)!\n", r);
-                       return r;
-               }
+       r = reservation_object_wait_timeout_rcu(bo->tbo.resv, true, false,
+                                               MAX_SCHEDULE_TIMEOUT);
+       if (r < 0) {
+               DRM_ERROR("Failed waiting for UVD message (%ld)!\n", r);
+               return r;
        }
 
        r = amdgpu_bo_kmap(bo, &ptr);
        if (r) {
-               DRM_ERROR("Failed mapping the UVD message (%d)!\n", r);
+               DRM_ERROR("Failed mapping the UVD message (%ld)!\n", r);
                return r;
        }
 
@@ -628,6 +632,13 @@ static int amdgpu_uvd_cs_pass2(struct amdgpu_uvd_cs_ctx *ctx)
                        return -EINVAL;
                }
 
+       } else if (cmd == 0x206) {
+               if ((end - start) < ctx->buf_sizes[4]) {
+                       DRM_ERROR("buffer (%d) to small (%d / %d)!\n", cmd,
+                                         (unsigned)(end - start),
+                                         ctx->buf_sizes[4]);
+                       return -EINVAL;
+               }
        } else if ((cmd != 0x100) && (cmd != 0x204)) {
                DRM_ERROR("invalid UVD command %X!\n", cmd);
                return -EINVAL;
@@ -755,9 +766,10 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx)
        struct amdgpu_uvd_cs_ctx ctx = {};
        unsigned buf_sizes[] = {
                [0x00000000]    =       2048,
-               [0x00000001]    =       32 * 1024 * 1024,
-               [0x00000002]    =       2048 * 1152 * 3,
+               [0x00000001]    =       0xFFFFFFFF,
+               [0x00000002]    =       0xFFFFFFFF,
                [0x00000003]    =       2048,
+               [0x00000004]    =       0xFFFFFFFF,
        };
        struct amdgpu_ib *ib = &parser->ibs[ib_idx];
        int r;
@@ -792,14 +804,24 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx)
        return 0;
 }
 
+static int amdgpu_uvd_free_job(
+       struct amdgpu_job *sched_job)
+{
+       amdgpu_ib_free(sched_job->adev, sched_job->ibs);
+       kfree(sched_job->ibs);
+       return 0;
+}
+
 static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring,
                               struct amdgpu_bo *bo,
-                              struct amdgpu_fence **fence)
+                              struct fence **fence)
 {
        struct ttm_validate_buffer tv;
        struct ww_acquire_ctx ticket;
        struct list_head head;
-       struct amdgpu_ib ib;
+       struct amdgpu_ib *ib = NULL;
+       struct fence *f = NULL;
+       struct amdgpu_device *adev = ring->adev;
        uint64_t addr;
        int i, r;
 
@@ -821,34 +843,49 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring,
        r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
        if (r)
                goto err;
-
-       r = amdgpu_ib_get(ring, NULL, 64, &ib);
-       if (r)
+       ib = kzalloc(sizeof(struct amdgpu_ib), GFP_KERNEL);
+       if (!ib) {
+               r = -ENOMEM;
                goto err;
+       }
+       r = amdgpu_ib_get(ring, NULL, 64, ib);
+       if (r)
+               goto err1;
 
        addr = amdgpu_bo_gpu_offset(bo);
-       ib.ptr[0] = PACKET0(mmUVD_GPCOM_VCPU_DATA0, 0);
-       ib.ptr[1] = addr;
-       ib.ptr[2] = PACKET0(mmUVD_GPCOM_VCPU_DATA1, 0);
-       ib.ptr[3] = addr >> 32;
-       ib.ptr[4] = PACKET0(mmUVD_GPCOM_VCPU_CMD, 0);
-       ib.ptr[5] = 0;
+       ib->ptr[0] = PACKET0(mmUVD_GPCOM_VCPU_DATA0, 0);
+       ib->ptr[1] = addr;
+       ib->ptr[2] = PACKET0(mmUVD_GPCOM_VCPU_DATA1, 0);
+       ib->ptr[3] = addr >> 32;
+       ib->ptr[4] = PACKET0(mmUVD_GPCOM_VCPU_CMD, 0);
+       ib->ptr[5] = 0;
        for (i = 6; i < 16; ++i)
-               ib.ptr[i] = PACKET2(0);
-       ib.length_dw = 16;
+               ib->ptr[i] = PACKET2(0);
+       ib->length_dw = 16;
 
-       r = amdgpu_ib_schedule(ring->adev, 1, &ib, AMDGPU_FENCE_OWNER_UNDEFINED);
+       r = amdgpu_sched_ib_submit_kernel_helper(adev, ring, ib, 1,
+                                                &amdgpu_uvd_free_job,
+                                                AMDGPU_FENCE_OWNER_UNDEFINED,
+                                                &f);
        if (r)
-               goto err;
-       ttm_eu_fence_buffer_objects(&ticket, &head, &ib.fence->base);
+               goto err2;
 
-       if (fence)
-               *fence = amdgpu_fence_ref(ib.fence);
+       ttm_eu_fence_buffer_objects(&ticket, &head, f);
 
-       amdgpu_ib_free(ring->adev, &ib);
+       if (fence)
+               *fence = fence_get(f);
        amdgpu_bo_unref(&bo);
-       return 0;
+       fence_put(f);
+       if (amdgpu_enable_scheduler)
+               return 0;
 
+       amdgpu_ib_free(ring->adev, ib);
+       kfree(ib);
+       return 0;
+err2:
+       amdgpu_ib_free(ring->adev, ib);
+err1:
+       kfree(ib);
 err:
        ttm_eu_backoff_reservation(&ticket, &head);
        return r;
@@ -858,7 +895,7 @@ err:
    crash the vcpu so just try to emmit a dummy create/destroy msg to
    avoid this */
 int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
-                             struct amdgpu_fence **fence)
+                             struct fence **fence)
 {
        struct amdgpu_device *adev = ring->adev;
        struct amdgpu_bo *bo;
@@ -866,7 +903,9 @@ int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
        int r, i;
 
        r = amdgpu_bo_create(adev, 1024, PAGE_SIZE, true,
-                            AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, &bo);
+                            AMDGPU_GEM_DOMAIN_VRAM,
+                            AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+                            NULL, NULL, &bo);
        if (r)
                return r;
 
@@ -905,7 +944,7 @@ int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
 }
 
 int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
-                              struct amdgpu_fence **fence)
+                              struct fence **fence)
 {
        struct amdgpu_device *adev = ring->adev;
        struct amdgpu_bo *bo;
@@ -913,7 +952,9 @@ int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
        int r, i;
 
        r = amdgpu_bo_create(adev, 1024, PAGE_SIZE, true,
-                            AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, &bo);
+                            AMDGPU_GEM_DOMAIN_VRAM,
+                            AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+                            NULL, NULL, &bo);
        if (r)
                return r;