From: Greg Kroah-Hartman Date: Mon, 5 Aug 2013 09:41:57 +0000 (+0800) Subject: 3.10-stable patches X-Git-Tag: v3.0.90~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=63ba5ccac6c5269e449230f32cd67edfe1177868;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: drm-radeon-never-unpin-uvd-bo-v3.patch --- 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 index 00000000000..3e6a1db3f10 --- /dev/null +++ b/queue-3.10/drm-radeon-never-unpin-uvd-bo-v3.patch @@ -0,0 +1,236 @@ +From 9cc2e0e9f13315559c85c9f99f141e420967c955 Mon Sep 17 00:00:00 2001 +From: Christian König +Date: Fri, 12 Jul 2013 10:18:09 -0400 +Subject: drm/radeon: never unpin UVD bo v3 + +From: Christian König + +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 +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + + +--- + 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); + diff --git a/queue-3.10/series b/queue-3.10/series index 538aa95ee26..153fa16ede8 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -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