Hi,
as requested a rebased version of the patch is attached.
This one should apply cleanly on 3.10.
Cheers,
Christian.
Am 05.08.2013 05:00, schrieb gregkh@xxxxxxxxxxxxxxxxxxx:
The patch below does not apply to the 3.10-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@xxxxxxxxxxxxxxx>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 9cc2e0e9f13315559c85c9f99f141e420967c955 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@xxxxxxx>
Date: Fri, 12 Jul 2013 10:18:09 -0400
Subject: [PATCH] drm/radeon: never unpin UVD bo v3
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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
Note: a version of this patch needs to go to stable.
Signed-off-by: Christian K??nig <christian.koenig@xxxxxxx>
Signed-off-by: Alex Deucher <alexander.deucher@xxxxxxx>
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 68b4fc5..6dacec4 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -6978,7 +6978,7 @@ int cik_uvd_resume(struct radeon_device *rdev)
/* 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/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 9b7025d..7b7d23a 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1460,6 +1460,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;
@@ -2054,7 +2056,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 */
const struct firmware *mec_fw; /* CIK MEC firmware */
const struct firmware *sdma_fw; /* CIK SDMA firmware */
const struct firmware *smc_fw; /* SMC firmware */
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index ddb8f8e..7ddb0ef 100644
--- 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(struct radeon_device *rdev, int ring)
} 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;
}
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index 34444f6..414fd14 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -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);
@@ -141,71 +161,47 @@ 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;
}
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 4a62ad2..30ea14e 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -813,7 +813,7 @@ int rv770_uvd_resume(struct radeon_device *rdev)
/* 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);
>From 120de9359a416fd1deff173cc63d8a66726e32cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@xxxxxxx>
Date: Fri, 12 Jul 2013 10:18:09 -0400
Subject: [PATCH] drm/radeon: never unpin UVD bo v4
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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@xxxxxxx>
Signed-off-by: Alex Deucher <alexander.deucher@xxxxxxx>
---
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(-)
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index f4dcfdd..aad18e6 100644
--- 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 */
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index ddb8f8e..7ddb0ef 100644
--- 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(struct radeon_device *rdev, int ring)
} 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;
}
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index cad735d..1b3a91b 100644
--- 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(struct work_struct *work);
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 *rdev)
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 *rdev)
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 *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);
@@ -144,71 +164,47 @@ 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;
}
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 4a62ad2..30ea14e 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -813,7 +813,7 @@ int rv770_uvd_resume(struct radeon_device *rdev)
/* 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);
--
1.7.9.5