]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 5 Aug 2013 09:41:57 +0000 (17:41 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 5 Aug 2013 09:41:57 +0000 (17:41 +0800)
added patches:
drm-radeon-never-unpin-uvd-bo-v3.patch

queue-3.10/drm-radeon-never-unpin-uvd-bo-v3.patch [new file with mode: 0644]
queue-3.10/series

diff --git a/queue-3.10/drm-radeon-never-unpin-uvd-bo-v3.patch b/queue-3.10/drm-radeon-never-unpin-uvd-bo-v3.patch
new file mode 100644 (file)
index 0000000..3e6a1db
--- /dev/null
@@ -0,0 +1,236 @@
+From 9cc2e0e9f13315559c85c9f99f141e420967c955 Mon Sep 17 00:00:00 2001
+From: Christian König <christian.koenig@amd.com>
+Date: Fri, 12 Jul 2013 10:18:09 -0400
+Subject: drm/radeon: never unpin UVD bo v3
+
+From: Christian König <christian.koenig@amd.com>
+
+commit 9cc2e0e9f13315559c85c9f99f141e420967c955 upstream.
+
+Changing the UVD BOs offset on suspend/resume doesn't work because the VCPU
+internally keeps pointers to it. Just keep it always pinned and save the
+content manually.
+
+Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=66425
+
+v2: fix compiler warning
+v3: fix CIK support
+v4: rebased for 3.10-stable tree
+
+Note: a version of this patch needs to go to stable.
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ drivers/gpu/drm/radeon/radeon.h       |    3 -
+ drivers/gpu/drm/radeon/radeon_fence.c |    2 
+ drivers/gpu/drm/radeon/radeon_uvd.c   |  100 ++++++++++++++++------------------
+ drivers/gpu/drm/radeon/rv770.c        |    2 
+ 4 files changed, 52 insertions(+), 55 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -1145,6 +1145,8 @@ struct radeon_uvd {
+       struct radeon_bo        *vcpu_bo;
+       void                    *cpu_addr;
+       uint64_t                gpu_addr;
++      void                    *saved_bo;
++      unsigned                fw_size;
+       atomic_t                handles[RADEON_MAX_UVD_HANDLES];
+       struct drm_file         *filp[RADEON_MAX_UVD_HANDLES];
+       struct delayed_work     idle_work;
+@@ -1684,7 +1686,6 @@ struct radeon_device {
+       const struct firmware *rlc_fw;  /* r6/700 RLC firmware */
+       const struct firmware *mc_fw;   /* NI MC firmware */
+       const struct firmware *ce_fw;   /* SI CE firmware */
+-      const struct firmware *uvd_fw;  /* UVD firmware */
+       struct r600_blit r600_blit;
+       struct r600_vram_scratch vram_scratch;
+       int msi_enabled; /* msi enabled */
+--- a/drivers/gpu/drm/radeon/radeon_fence.c
++++ b/drivers/gpu/drm/radeon/radeon_fence.c
+@@ -782,7 +782,7 @@ int radeon_fence_driver_start_ring(struc
+               } else {
+                       /* put fence directly behind firmware */
+-                      index = ALIGN(rdev->uvd_fw->size, 8);
++                      index = ALIGN(rdev->uvd.fw_size, 8);
+                       rdev->fence_drv[ring].cpu_addr = rdev->uvd.cpu_addr + index;
+                       rdev->fence_drv[ring].gpu_addr = rdev->uvd.gpu_addr + index;
+               }
+--- a/drivers/gpu/drm/radeon/radeon_uvd.c
++++ b/drivers/gpu/drm/radeon/radeon_uvd.c
+@@ -55,6 +55,7 @@ static void radeon_uvd_idle_work_handler
+ int radeon_uvd_init(struct radeon_device *rdev)
+ {
+       struct platform_device *pdev;
++      const struct firmware *fw;
+       unsigned long bo_size;
+       const char *fw_name;
+       int i, r;
+@@ -104,7 +105,7 @@ int radeon_uvd_init(struct radeon_device
+               return -EINVAL;
+       }
+-      r = request_firmware(&rdev->uvd_fw, fw_name, &pdev->dev);
++      r = request_firmware(&fw, fw_name, &pdev->dev);
+       if (r) {
+               dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
+                       fw_name);
+@@ -114,7 +115,7 @@ int radeon_uvd_init(struct radeon_device
+       platform_device_unregister(pdev);
+-      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);
+@@ -123,16 +124,35 @@ int radeon_uvd_init(struct radeon_device
+               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);
+@@ -144,71 +164,47 @@ int radeon_uvd_init(struct radeon_device
+ 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;
+ }
+--- a/drivers/gpu/drm/radeon/rv770.c
++++ b/drivers/gpu/drm/radeon/rv770.c
+@@ -813,7 +813,7 @@ int rv770_uvd_resume(struct radeon_devic
+       /* programm the VCPU memory controller bits 0-27 */
+       addr = rdev->uvd.gpu_addr >> 3;
+-      size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3;
++      size = RADEON_GPU_PAGE_ALIGN(rdev->uvd.fw_size + 4) >> 3;
+       WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
+       WREG32(UVD_VCPU_CACHE_SIZE0, size);
index 538aa95ee26c0f0fccb6e5653b1233aa3a93aba1..153fa16ede88252dba7b19ea5ea8cd1e2c2c5933 100644 (file)
@@ -75,3 +75,4 @@ xen-blkfront-use-a-different-scatterlist-for-each-request.patch
 drm-i915-preserve-the-ddi_a_4_lanes-bit-from-the-bios.patch
 fanotify-info-leak-in-copy_event_to_user.patch
 cgroup-fix-umount-vs-cgroup_cfts_commit-race.patch
+drm-radeon-never-unpin-uvd-bo-v3.patch