* [PATCH] drm/radeon: never unpin UVD bo v2
@ 2013-07-12 7:40 Christian König
2013-07-12 14:23 ` Alex Deucher
0 siblings, 1 reply; 2+ messages in thread
From: Christian König @ 2013-07-12 7:40 UTC (permalink / raw)
To: dri-devel
From: Christian König <christian.koenig@amd.com>
Changing the UVD BOs offset on suspend/resume doesn't work cause 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
Signed-off-by: Christian König <christian.koenig@amd.com>
Cc: stable@vger.kernel.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(-)
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 41efcec..43b083d 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -57,6 +57,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;
@@ -112,7 +113,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);
@@ -122,7 +123,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);
@@ -131,16 +132,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);
@@ -152,71 +172,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
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] drm/radeon: never unpin UVD bo v2
2013-07-12 7:40 [PATCH] drm/radeon: never unpin UVD bo v2 Christian König
@ 2013-07-12 14:23 ` Alex Deucher
0 siblings, 0 replies; 2+ messages in thread
From: Alex Deucher @ 2013-07-12 14:23 UTC (permalink / raw)
To: Christian König; +Cc: dri-devel
On Fri, Jul 12, 2013 at 3:40 AM, Christian König
<deathsimple@vodafone.de> wrote:
> From: Christian König <christian.koenig@amd.com>
>
> Changing the UVD BOs offset on suspend/resume doesn't work cause 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
>
> Signed-off-by: Christian König <christian.koenig@amd.com>
> Cc: stable@vger.kernel.org
I'll send this version to stable. I had to tweak it slightly for CIK
for 3.11. Applied.
Thanks,
Alex
> ---
> 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 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 41efcec..43b083d 100644
> --- a/drivers/gpu/drm/radeon/radeon_uvd.c
> +++ b/drivers/gpu/drm/radeon/radeon_uvd.c
> @@ -57,6 +57,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;
> @@ -112,7 +113,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);
> @@ -122,7 +123,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);
> @@ -131,16 +132,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);
> @@ -152,71 +172,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
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2013-07-12 14:23 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-07-12 7:40 [PATCH] drm/radeon: never unpin UVD bo v2 Christian König
2013-07-12 14:23 ` Alex Deucher
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).