]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/radeon/radeon_uvd.c
drm/radeon: never unpin UVD bo v3
[karo-tx-linux.git] / drivers / gpu / drm / radeon / radeon_uvd.c
index 34444f62803fb3c65d484262d6c6c2c91cdcf3b1..414fd145d20eee458ebf8e0a5c1dfb1940ae2589 100644 (file)
@@ -56,6 +56,7 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work);
 
 int radeon_uvd_init(struct radeon_device *rdev)
 {
+       const struct firmware *fw;
        unsigned long bo_size;
        const char *fw_name;
        int i, r;
@@ -104,14 +105,14 @@ int radeon_uvd_init(struct radeon_device *rdev)
                return -EINVAL;
        }
 
-       r = request_firmware(&rdev->uvd_fw, fw_name, rdev->dev);
+       r = request_firmware(&fw, fw_name, rdev->dev);
        if (r) {
                dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
                        fw_name);
                return r;
        }
 
-       bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) +
+       bo_size = RADEON_GPU_PAGE_ALIGN(fw->size + 8) +
                  RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE;
        r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
                             RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->uvd.vcpu_bo);
@@ -120,16 +121,35 @@ int radeon_uvd_init(struct radeon_device *rdev)
                return r;
        }
 
-       r = radeon_uvd_resume(rdev);
-       if (r)
+       r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false);
+       if (r) {
+               radeon_bo_unref(&rdev->uvd.vcpu_bo);
+               dev_err(rdev->dev, "(%d) failed to reserve UVD bo\n", r);
                return r;
+       }
 
-       memset(rdev->uvd.cpu_addr, 0, bo_size);
-       memcpy(rdev->uvd.cpu_addr, rdev->uvd_fw->data, rdev->uvd_fw->size);
+       r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM,
+                         &rdev->uvd.gpu_addr);
+       if (r) {
+               radeon_bo_unreserve(rdev->uvd.vcpu_bo);
+               radeon_bo_unref(&rdev->uvd.vcpu_bo);
+               dev_err(rdev->dev, "(%d) UVD bo pin failed\n", r);
+               return r;
+       }
 
-       r = radeon_uvd_suspend(rdev);
-       if (r)
+       r = radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr);
+       if (r) {
+               dev_err(rdev->dev, "(%d) UVD map failed\n", r);
                return r;
+       }
+
+       radeon_bo_unreserve(rdev->uvd.vcpu_bo);
+
+       rdev->uvd.fw_size = fw->size;
+       memset(rdev->uvd.cpu_addr, 0, bo_size);
+       memcpy(rdev->uvd.cpu_addr, fw->data, fw->size);
+
+       release_firmware(fw);
 
        for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
                atomic_set(&rdev->uvd.handles[i], 0);
@@ -140,72 +160,48 @@ int radeon_uvd_init(struct radeon_device *rdev)
 }
 
 void radeon_uvd_fini(struct radeon_device *rdev)
-{
-       radeon_uvd_suspend(rdev);
-       radeon_bo_unref(&rdev->uvd.vcpu_bo);
-}
-
-int radeon_uvd_suspend(struct radeon_device *rdev)
 {
        int r;
 
        if (rdev->uvd.vcpu_bo == NULL)
-               return 0;
+               return;
 
        r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false);
        if (!r) {
                radeon_bo_kunmap(rdev->uvd.vcpu_bo);
                radeon_bo_unpin(rdev->uvd.vcpu_bo);
-               rdev->uvd.cpu_addr = NULL;
-               if (!radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_CPU, NULL)) {
-                       radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr);
-               }
                radeon_bo_unreserve(rdev->uvd.vcpu_bo);
-
-               if (rdev->uvd.cpu_addr) {
-                       radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
-               } else {
-                       rdev->fence_drv[R600_RING_TYPE_UVD_INDEX].cpu_addr = NULL;
-               }
        }
-       return r;
+
+       radeon_bo_unref(&rdev->uvd.vcpu_bo);
 }
 
-int radeon_uvd_resume(struct radeon_device *rdev)
+int radeon_uvd_suspend(struct radeon_device *rdev)
 {
-       int r;
+       unsigned size;
 
        if (rdev->uvd.vcpu_bo == NULL)
-               return -EINVAL;
+               return 0;
 
-       r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false);
-       if (r) {
-               radeon_bo_unref(&rdev->uvd.vcpu_bo);
-               dev_err(rdev->dev, "(%d) failed to reserve UVD bo\n", r);
-               return r;
-       }
+       size = radeon_bo_size(rdev->uvd.vcpu_bo);
+       rdev->uvd.saved_bo = kmalloc(size, GFP_KERNEL);
+       memcpy(rdev->uvd.saved_bo, rdev->uvd.cpu_addr, size);
 
-       /* Have been pin in cpu unmap unpin */
-       radeon_bo_kunmap(rdev->uvd.vcpu_bo);
-       radeon_bo_unpin(rdev->uvd.vcpu_bo);
+       return 0;
+}
 
-       r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM,
-                         &rdev->uvd.gpu_addr);
-       if (r) {
-               radeon_bo_unreserve(rdev->uvd.vcpu_bo);
-               radeon_bo_unref(&rdev->uvd.vcpu_bo);
-               dev_err(rdev->dev, "(%d) UVD bo pin failed\n", r);
-               return r;
-       }
+int radeon_uvd_resume(struct radeon_device *rdev)
+{
+       if (rdev->uvd.vcpu_bo == NULL)
+               return -EINVAL;
 
-       r = radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr);
-       if (r) {
-               dev_err(rdev->dev, "(%d) UVD map failed\n", r);
-               return r;
+       if (rdev->uvd.saved_bo != NULL) {
+               unsigned size = radeon_bo_size(rdev->uvd.vcpu_bo);
+               memcpy(rdev->uvd.cpu_addr, rdev->uvd.saved_bo, size);
+               kfree(rdev->uvd.saved_bo);
+               rdev->uvd.saved_bo = NULL;
        }
 
-       radeon_bo_unreserve(rdev->uvd.vcpu_bo);
-
        return 0;
 }