aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2013-07-12 10:18:09 -0400
committerAlex Deucher <alexander.deucher@amd.com>2013-07-14 10:11:30 -0400
commit9cc2e0e9f13315559c85c9f99f141e420967c955 (patch)
treecd5215addab4c8d8d9e8d81e2d682a08677745e9 /drivers/gpu
parentc9a6ca4abd5f1978ef15b3ece3474f4372ae5fe7 (diff)
drm/radeon: never unpin UVD bo v3
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@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/radeon/cik.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon.h3
-rw-r--r--drivers/gpu/drm/radeon/radeon_fence.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_uvd.c100
-rw-r--r--drivers/gpu/drm/radeon/rv770.c2
5 files changed, 53 insertions, 56 deletions
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 68b4fc599e03..6dacec4e2090 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)
6978 6978
6979 /* programm the VCPU memory controller bits 0-27 */ 6979 /* programm the VCPU memory controller bits 0-27 */
6980 addr = rdev->uvd.gpu_addr >> 3; 6980 addr = rdev->uvd.gpu_addr >> 3;
6981 size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3; 6981 size = RADEON_GPU_PAGE_ALIGN(rdev->uvd.fw_size + 4) >> 3;
6982 WREG32(UVD_VCPU_CACHE_OFFSET0, addr); 6982 WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
6983 WREG32(UVD_VCPU_CACHE_SIZE0, size); 6983 WREG32(UVD_VCPU_CACHE_SIZE0, size);
6984 6984
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 9b7025d02cd0..7b7d23ae3f27 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1460,6 +1460,8 @@ struct radeon_uvd {
1460 struct radeon_bo *vcpu_bo; 1460 struct radeon_bo *vcpu_bo;
1461 void *cpu_addr; 1461 void *cpu_addr;
1462 uint64_t gpu_addr; 1462 uint64_t gpu_addr;
1463 void *saved_bo;
1464 unsigned fw_size;
1463 atomic_t handles[RADEON_MAX_UVD_HANDLES]; 1465 atomic_t handles[RADEON_MAX_UVD_HANDLES];
1464 struct drm_file *filp[RADEON_MAX_UVD_HANDLES]; 1466 struct drm_file *filp[RADEON_MAX_UVD_HANDLES];
1465 struct delayed_work idle_work; 1467 struct delayed_work idle_work;
@@ -2054,7 +2056,6 @@ struct radeon_device {
2054 const struct firmware *rlc_fw; /* r6/700 RLC firmware */ 2056 const struct firmware *rlc_fw; /* r6/700 RLC firmware */
2055 const struct firmware *mc_fw; /* NI MC firmware */ 2057 const struct firmware *mc_fw; /* NI MC firmware */
2056 const struct firmware *ce_fw; /* SI CE firmware */ 2058 const struct firmware *ce_fw; /* SI CE firmware */
2057 const struct firmware *uvd_fw; /* UVD firmware */
2058 const struct firmware *mec_fw; /* CIK MEC firmware */ 2059 const struct firmware *mec_fw; /* CIK MEC firmware */
2059 const struct firmware *sdma_fw; /* CIK SDMA firmware */ 2060 const struct firmware *sdma_fw; /* CIK SDMA firmware */
2060 const struct firmware *smc_fw; /* SMC firmware */ 2061 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 ddb8f8e04eb5..7ddb0efe2408 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)
782 782
783 } else { 783 } else {
784 /* put fence directly behind firmware */ 784 /* put fence directly behind firmware */
785 index = ALIGN(rdev->uvd_fw->size, 8); 785 index = ALIGN(rdev->uvd.fw_size, 8);
786 rdev->fence_drv[ring].cpu_addr = rdev->uvd.cpu_addr + index; 786 rdev->fence_drv[ring].cpu_addr = rdev->uvd.cpu_addr + index;
787 rdev->fence_drv[ring].gpu_addr = rdev->uvd.gpu_addr + index; 787 rdev->fence_drv[ring].gpu_addr = rdev->uvd.gpu_addr + index;
788 } 788 }
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index 34444f62803f..414fd145d20e 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);
56 56
57int radeon_uvd_init(struct radeon_device *rdev) 57int radeon_uvd_init(struct radeon_device *rdev)
58{ 58{
59 const struct firmware *fw;
59 unsigned long bo_size; 60 unsigned long bo_size;
60 const char *fw_name; 61 const char *fw_name;
61 int i, r; 62 int i, r;
@@ -104,14 +105,14 @@ int radeon_uvd_init(struct radeon_device *rdev)
104 return -EINVAL; 105 return -EINVAL;
105 } 106 }
106 107
107 r = request_firmware(&rdev->uvd_fw, fw_name, rdev->dev); 108 r = request_firmware(&fw, fw_name, rdev->dev);
108 if (r) { 109 if (r) {
109 dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n", 110 dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
110 fw_name); 111 fw_name);
111 return r; 112 return r;
112 } 113 }
113 114
114 bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) + 115 bo_size = RADEON_GPU_PAGE_ALIGN(fw->size + 8) +
115 RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE; 116 RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE;
116 r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true, 117 r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
117 RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->uvd.vcpu_bo); 118 RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->uvd.vcpu_bo);
@@ -120,16 +121,35 @@ int radeon_uvd_init(struct radeon_device *rdev)
120 return r; 121 return r;
121 } 122 }
122 123
123 r = radeon_uvd_resume(rdev); 124 r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false);
124 if (r) 125 if (r) {
126 radeon_bo_unref(&rdev->uvd.vcpu_bo);
127 dev_err(rdev->dev, "(%d) failed to reserve UVD bo\n", r);
125 return r; 128 return r;
129 }
126 130
127 memset(rdev->uvd.cpu_addr, 0, bo_size); 131 r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM,
128 memcpy(rdev->uvd.cpu_addr, rdev->uvd_fw->data, rdev->uvd_fw->size); 132 &rdev->uvd.gpu_addr);
133 if (r) {
134 radeon_bo_unreserve(rdev->uvd.vcpu_bo);
135 radeon_bo_unref(&rdev->uvd.vcpu_bo);
136 dev_err(rdev->dev, "(%d) UVD bo pin failed\n", r);
137 return r;
138 }
129 139
130 r = radeon_uvd_suspend(rdev); 140 r = radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr);
131 if (r) 141 if (r) {
142 dev_err(rdev->dev, "(%d) UVD map failed\n", r);
132 return r; 143 return r;
144 }
145
146 radeon_bo_unreserve(rdev->uvd.vcpu_bo);
147
148 rdev->uvd.fw_size = fw->size;
149 memset(rdev->uvd.cpu_addr, 0, bo_size);
150 memcpy(rdev->uvd.cpu_addr, fw->data, fw->size);
151
152 release_firmware(fw);
133 153
134 for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { 154 for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
135 atomic_set(&rdev->uvd.handles[i], 0); 155 atomic_set(&rdev->uvd.handles[i], 0);
@@ -141,71 +161,47 @@ int radeon_uvd_init(struct radeon_device *rdev)
141 161
142void radeon_uvd_fini(struct radeon_device *rdev) 162void radeon_uvd_fini(struct radeon_device *rdev)
143{ 163{
144 radeon_uvd_suspend(rdev);
145 radeon_bo_unref(&rdev->uvd.vcpu_bo);
146}
147
148int radeon_uvd_suspend(struct radeon_device *rdev)
149{
150 int r; 164 int r;
151 165
152 if (rdev->uvd.vcpu_bo == NULL) 166 if (rdev->uvd.vcpu_bo == NULL)
153 return 0; 167 return;
154 168
155 r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false); 169 r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false);
156 if (!r) { 170 if (!r) {
157 radeon_bo_kunmap(rdev->uvd.vcpu_bo); 171 radeon_bo_kunmap(rdev->uvd.vcpu_bo);
158 radeon_bo_unpin(rdev->uvd.vcpu_bo); 172 radeon_bo_unpin(rdev->uvd.vcpu_bo);
159 rdev->uvd.cpu_addr = NULL;
160 if (!radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_CPU, NULL)) {
161 radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr);
162 }
163 radeon_bo_unreserve(rdev->uvd.vcpu_bo); 173 radeon_bo_unreserve(rdev->uvd.vcpu_bo);
164
165 if (rdev->uvd.cpu_addr) {
166 radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
167 } else {
168 rdev->fence_drv[R600_RING_TYPE_UVD_INDEX].cpu_addr = NULL;
169 }
170 } 174 }
171 return r; 175
176 radeon_bo_unref(&rdev->uvd.vcpu_bo);
172} 177}
173 178
174int radeon_uvd_resume(struct radeon_device *rdev) 179int radeon_uvd_suspend(struct radeon_device *rdev)
175{ 180{
176 int r; 181 unsigned size;
177 182
178 if (rdev->uvd.vcpu_bo == NULL) 183 if (rdev->uvd.vcpu_bo == NULL)
179 return -EINVAL; 184 return 0;
180 185
181 r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false); 186 size = radeon_bo_size(rdev->uvd.vcpu_bo);
182 if (r) { 187 rdev->uvd.saved_bo = kmalloc(size, GFP_KERNEL);
183 radeon_bo_unref(&rdev->uvd.vcpu_bo); 188 memcpy(rdev->uvd.saved_bo, rdev->uvd.cpu_addr, size);
184 dev_err(rdev->dev, "(%d) failed to reserve UVD bo\n", r);
185 return r;
186 }
187 189
188 /* Have been pin in cpu unmap unpin */ 190 return 0;
189 radeon_bo_kunmap(rdev->uvd.vcpu_bo); 191}
190 radeon_bo_unpin(rdev->uvd.vcpu_bo);
191 192
192 r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM, 193int radeon_uvd_resume(struct radeon_device *rdev)
193 &rdev->uvd.gpu_addr); 194{
194 if (r) { 195 if (rdev->uvd.vcpu_bo == NULL)
195 radeon_bo_unreserve(rdev->uvd.vcpu_bo); 196 return -EINVAL;
196 radeon_bo_unref(&rdev->uvd.vcpu_bo);
197 dev_err(rdev->dev, "(%d) UVD bo pin failed\n", r);
198 return r;
199 }
200 197
201 r = radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr); 198 if (rdev->uvd.saved_bo != NULL) {
202 if (r) { 199 unsigned size = radeon_bo_size(rdev->uvd.vcpu_bo);
203 dev_err(rdev->dev, "(%d) UVD map failed\n", r); 200 memcpy(rdev->uvd.cpu_addr, rdev->uvd.saved_bo, size);
204 return r; 201 kfree(rdev->uvd.saved_bo);
202 rdev->uvd.saved_bo = NULL;
205 } 203 }
206 204
207 radeon_bo_unreserve(rdev->uvd.vcpu_bo);
208
209 return 0; 205 return 0;
210} 206}
211 207
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 4a62ad2e5399..30ea14e8854c 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)
813 813
814 /* programm the VCPU memory controller bits 0-27 */ 814 /* programm the VCPU memory controller bits 0-27 */
815 addr = rdev->uvd.gpu_addr >> 3; 815 addr = rdev->uvd.gpu_addr >> 3;
816 size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3; 816 size = RADEON_GPU_PAGE_ALIGN(rdev->uvd.fw_size + 4) >> 3;
817 WREG32(UVD_VCPU_CACHE_OFFSET0, addr); 817 WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
818 WREG32(UVD_VCPU_CACHE_SIZE0, size); 818 WREG32(UVD_VCPU_CACHE_SIZE0, size);
819 819