aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeo Liu <leo.liu@amd.com>2016-04-01 10:36:06 -0400
committerAlex Deucher <alexander.deucher@amd.com>2016-04-04 17:00:50 -0400
commit3f99dd814a6fdf9e06562f210b8e7702db9e9158 (patch)
tree5f214a9b1aef6fe465051197259427fd91a4f461
parent749b48faaf64d1081d7216068ff3da92c230bad0 (diff)
drm/amdgpu: save and restore UVD context with suspend and resume
and revert fix following it accordingly Revert "drm/amdgpu: stop trying to suspend UVD sessions v2" Revert "drm/amdgpu: fix the UVD suspend sequence order" Signed-off-by: Leo Liu <leo.liu@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c45
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c7
5 files changed, 35 insertions, 26 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index c4a21c6428f5..62a778012fe0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1591,6 +1591,7 @@ struct amdgpu_uvd {
1591 struct amdgpu_bo *vcpu_bo; 1591 struct amdgpu_bo *vcpu_bo;
1592 void *cpu_addr; 1592 void *cpu_addr;
1593 uint64_t gpu_addr; 1593 uint64_t gpu_addr;
1594 void *saved_bo;
1594 atomic_t handles[AMDGPU_MAX_UVD_HANDLES]; 1595 atomic_t handles[AMDGPU_MAX_UVD_HANDLES];
1595 struct drm_file *filp[AMDGPU_MAX_UVD_HANDLES]; 1596 struct drm_file *filp[AMDGPU_MAX_UVD_HANDLES];
1596 struct delayed_work idle_work; 1597 struct delayed_work idle_work;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index c1a581044417..4b8ca3515fbc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -241,32 +241,34 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev)
241 241
242int amdgpu_uvd_suspend(struct amdgpu_device *adev) 242int amdgpu_uvd_suspend(struct amdgpu_device *adev)
243{ 243{
244 struct amdgpu_ring *ring = &adev->uvd.ring; 244 unsigned size;
245 int i, r; 245 void *ptr;
246 const struct common_firmware_header *hdr;
247 int i;
246 248
247 if (adev->uvd.vcpu_bo == NULL) 249 if (adev->uvd.vcpu_bo == NULL)
248 return 0; 250 return 0;
249 251
250 for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) { 252 for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i)
251 uint32_t handle = atomic_read(&adev->uvd.handles[i]); 253 if (atomic_read(&adev->uvd.handles[i]))
252 if (handle != 0) { 254 break;
253 struct fence *fence;
254 255
255 amdgpu_uvd_note_usage(adev); 256 if (i == AMDGPU_MAX_UVD_HANDLES)
257 return 0;
256 258
257 r = amdgpu_uvd_get_destroy_msg(ring, handle, false, &fence); 259 hdr = (const struct common_firmware_header *)adev->uvd.fw->data;
258 if (r) {
259 DRM_ERROR("Error destroying UVD (%d)!\n", r);
260 continue;
261 }
262 260
263 fence_wait(fence, false); 261 size = amdgpu_bo_size(adev->uvd.vcpu_bo);
264 fence_put(fence); 262 size -= le32_to_cpu(hdr->ucode_size_bytes);
265 263
266 adev->uvd.filp[i] = NULL; 264 ptr = adev->uvd.cpu_addr;
267 atomic_set(&adev->uvd.handles[i], 0); 265 ptr += le32_to_cpu(hdr->ucode_size_bytes);
268 } 266
269 } 267 adev->uvd.saved_bo = kmalloc(size, GFP_KERNEL);
268 if (!adev->uvd.saved_bo)
269 return -ENOMEM;
270
271 memcpy(adev->uvd.saved_bo, ptr, size);
270 272
271 return 0; 273 return 0;
272} 274}
@@ -291,7 +293,12 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
291 ptr = adev->uvd.cpu_addr; 293 ptr = adev->uvd.cpu_addr;
292 ptr += le32_to_cpu(hdr->ucode_size_bytes); 294 ptr += le32_to_cpu(hdr->ucode_size_bytes);
293 295
294 memset(ptr, 0, size); 296 if (adev->uvd.saved_bo != NULL) {
297 memcpy(ptr, adev->uvd.saved_bo, size);
298 kfree(adev->uvd.saved_bo);
299 adev->uvd.saved_bo = NULL;
300 } else
301 memset(ptr, 0, size);
295 302
296 return 0; 303 return 0;
297} 304}
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
index c606ccb38d8b..cb463753115b 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
@@ -224,11 +224,11 @@ static int uvd_v4_2_suspend(void *handle)
224 int r; 224 int r;
225 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 225 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
226 226
227 r = amdgpu_uvd_suspend(adev); 227 r = uvd_v4_2_hw_fini(adev);
228 if (r) 228 if (r)
229 return r; 229 return r;
230 230
231 r = uvd_v4_2_hw_fini(adev); 231 r = amdgpu_uvd_suspend(adev);
232 if (r) 232 if (r)
233 return r; 233 return r;
234 234
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
index e3c852d9d79a..16476d80f475 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
@@ -220,11 +220,11 @@ static int uvd_v5_0_suspend(void *handle)
220 int r; 220 int r;
221 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 221 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
222 222
223 r = amdgpu_uvd_suspend(adev); 223 r = uvd_v5_0_hw_fini(adev);
224 if (r) 224 if (r)
225 return r; 225 return r;
226 226
227 r = uvd_v5_0_hw_fini(adev); 227 r = amdgpu_uvd_suspend(adev);
228 if (r) 228 if (r)
229 return r; 229 return r;
230 230
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
index 3375e614ac67..d49379145ef2 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
@@ -214,15 +214,16 @@ static int uvd_v6_0_suspend(void *handle)
214 int r; 214 int r;
215 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 215 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
216 216
217 r = uvd_v6_0_hw_fini(adev);
218 if (r)
219 return r;
220
217 /* Skip this for APU for now */ 221 /* Skip this for APU for now */
218 if (!(adev->flags & AMD_IS_APU)) { 222 if (!(adev->flags & AMD_IS_APU)) {
219 r = amdgpu_uvd_suspend(adev); 223 r = amdgpu_uvd_suspend(adev);
220 if (r) 224 if (r)
221 return r; 225 return r;
222 } 226 }
223 r = uvd_v6_0_hw_fini(adev);
224 if (r)
225 return r;
226 227
227 return r; 228 return r;
228} 229}