diff options
author | Christian König <deathsimple@vodafone.de> | 2012-07-05 08:32:00 -0400 |
---|---|---|
committer | Christian König <deathsimple@vodafone.de> | 2012-07-17 04:32:55 -0400 |
commit | c6105f249a637e1bb2b04b1cad7feaf507d06e8c (patch) | |
tree | 6dfaa699908277f651d60bbea6089bf25ac228ae /drivers | |
parent | 6f72a631998d37673828b0e97c63dafc8e923382 (diff) |
drm/radeon: remove vm_manager start/suspend
Just restore the page table instead. Addressing three
problem with this change:
1. Calling vm_manager_suspend in the suspend path is
problematic cause it wants to wait for the VM use
to end, which in case of a lockup never happens.
2. In case of a locked up memory controller
unbinding the VM seems to make it even more
unstable, creating an unrecoverable lockup
in the end.
3. If we want to backup/restore the leftover ring
content we must not unbind VMs in between.
Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/radeon/ni.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_gart.c | 83 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/si.c | 12 |
4 files changed, 59 insertions, 50 deletions
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 4004376362ee..ec5307c582f4 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
@@ -1280,9 +1280,11 @@ static int cayman_startup(struct radeon_device *rdev) | |||
1280 | if (r) | 1280 | if (r) |
1281 | return r; | 1281 | return r; |
1282 | 1282 | ||
1283 | r = radeon_vm_manager_start(rdev); | 1283 | r = radeon_vm_manager_init(rdev); |
1284 | if (r) | 1284 | if (r) { |
1285 | dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); | ||
1285 | return r; | 1286 | return r; |
1287 | } | ||
1286 | 1288 | ||
1287 | r = r600_audio_init(rdev); | 1289 | r = r600_audio_init(rdev); |
1288 | if (r) | 1290 | if (r) |
@@ -1315,7 +1317,6 @@ int cayman_resume(struct radeon_device *rdev) | |||
1315 | int cayman_suspend(struct radeon_device *rdev) | 1317 | int cayman_suspend(struct radeon_device *rdev) |
1316 | { | 1318 | { |
1317 | r600_audio_fini(rdev); | 1319 | r600_audio_fini(rdev); |
1318 | radeon_vm_manager_suspend(rdev); | ||
1319 | cayman_cp_enable(rdev, false); | 1320 | cayman_cp_enable(rdev, false); |
1320 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; | 1321 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; |
1321 | evergreen_irq_suspend(rdev); | 1322 | evergreen_irq_suspend(rdev); |
@@ -1392,11 +1393,6 @@ int cayman_init(struct radeon_device *rdev) | |||
1392 | return r; | 1393 | return r; |
1393 | 1394 | ||
1394 | rdev->accel_working = true; | 1395 | rdev->accel_working = true; |
1395 | r = radeon_vm_manager_init(rdev); | ||
1396 | if (r) { | ||
1397 | dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); | ||
1398 | } | ||
1399 | |||
1400 | r = cayman_startup(rdev); | 1396 | r = cayman_startup(rdev); |
1401 | if (r) { | 1397 | if (r) { |
1402 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | 1398 | dev_err(rdev->dev, "disabling GPU acceleration\n"); |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 8a8c3f82950e..872270c9a0d0 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -1759,8 +1759,6 @@ extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size | |||
1759 | */ | 1759 | */ |
1760 | int radeon_vm_manager_init(struct radeon_device *rdev); | 1760 | int radeon_vm_manager_init(struct radeon_device *rdev); |
1761 | void radeon_vm_manager_fini(struct radeon_device *rdev); | 1761 | void radeon_vm_manager_fini(struct radeon_device *rdev); |
1762 | int radeon_vm_manager_start(struct radeon_device *rdev); | ||
1763 | int radeon_vm_manager_suspend(struct radeon_device *rdev); | ||
1764 | int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm); | 1762 | int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm); |
1765 | void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm); | 1763 | void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm); |
1766 | int radeon_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm); | 1764 | int radeon_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm); |
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index ee11c5073726..56752da4b816 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c | |||
@@ -282,27 +282,58 @@ void radeon_gart_fini(struct radeon_device *rdev) | |||
282 | * | 282 | * |
283 | * TODO bind a default page at vm initialization for default address | 283 | * TODO bind a default page at vm initialization for default address |
284 | */ | 284 | */ |
285 | |||
285 | int radeon_vm_manager_init(struct radeon_device *rdev) | 286 | int radeon_vm_manager_init(struct radeon_device *rdev) |
286 | { | 287 | { |
288 | struct radeon_vm *vm; | ||
289 | struct radeon_bo_va *bo_va; | ||
287 | int r; | 290 | int r; |
288 | 291 | ||
289 | rdev->vm_manager.enabled = false; | 292 | if (!rdev->vm_manager.enabled) { |
293 | /* mark first vm as always in use, it's the system one */ | ||
294 | r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager, | ||
295 | rdev->vm_manager.max_pfn * 8, | ||
296 | RADEON_GEM_DOMAIN_VRAM); | ||
297 | if (r) { | ||
298 | dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n", | ||
299 | (rdev->vm_manager.max_pfn * 8) >> 10); | ||
300 | return r; | ||
301 | } | ||
290 | 302 | ||
291 | /* mark first vm as always in use, it's the system one */ | 303 | r = rdev->vm_manager.funcs->init(rdev); |
292 | r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager, | 304 | if (r) |
293 | rdev->vm_manager.max_pfn * 8, | 305 | return r; |
294 | RADEON_GEM_DOMAIN_VRAM); | 306 | |
295 | if (r) { | 307 | rdev->vm_manager.enabled = true; |
296 | dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n", | 308 | |
297 | (rdev->vm_manager.max_pfn * 8) >> 10); | 309 | r = radeon_sa_bo_manager_start(rdev, &rdev->vm_manager.sa_manager); |
298 | return r; | 310 | if (r) |
311 | return r; | ||
299 | } | 312 | } |
300 | 313 | ||
301 | r = rdev->vm_manager.funcs->init(rdev); | 314 | /* restore page table */ |
302 | if (r == 0) | 315 | list_for_each_entry(vm, &rdev->vm_manager.lru_vm, list) { |
303 | rdev->vm_manager.enabled = true; | 316 | if (vm->id == -1) |
317 | continue; | ||
304 | 318 | ||
305 | return r; | 319 | list_for_each_entry(bo_va, &vm->va, vm_list) { |
320 | struct ttm_mem_reg *mem = NULL; | ||
321 | if (bo_va->valid) | ||
322 | mem = &bo_va->bo->tbo.mem; | ||
323 | |||
324 | bo_va->valid = false; | ||
325 | r = radeon_vm_bo_update_pte(rdev, vm, bo_va->bo, mem); | ||
326 | if (r) { | ||
327 | DRM_ERROR("Failed to update pte for vm %d!\n", vm->id); | ||
328 | } | ||
329 | } | ||
330 | |||
331 | r = rdev->vm_manager.funcs->bind(rdev, vm, vm->id); | ||
332 | if (r) { | ||
333 | DRM_ERROR("Failed to bind vm %d!\n", vm->id); | ||
334 | } | ||
335 | } | ||
336 | return 0; | ||
306 | } | 337 | } |
307 | 338 | ||
308 | /* global mutex must be lock */ | 339 | /* global mutex must be lock */ |
@@ -347,26 +378,11 @@ static void radeon_vm_unbind_locked(struct radeon_device *rdev, | |||
347 | 378 | ||
348 | void radeon_vm_manager_fini(struct radeon_device *rdev) | 379 | void radeon_vm_manager_fini(struct radeon_device *rdev) |
349 | { | 380 | { |
350 | if (rdev->vm_manager.sa_manager.bo == NULL) | ||
351 | return; | ||
352 | radeon_vm_manager_suspend(rdev); | ||
353 | rdev->vm_manager.funcs->fini(rdev); | ||
354 | radeon_sa_bo_manager_fini(rdev, &rdev->vm_manager.sa_manager); | ||
355 | rdev->vm_manager.enabled = false; | ||
356 | } | ||
357 | |||
358 | int radeon_vm_manager_start(struct radeon_device *rdev) | ||
359 | { | ||
360 | if (rdev->vm_manager.sa_manager.bo == NULL) { | ||
361 | return -EINVAL; | ||
362 | } | ||
363 | return radeon_sa_bo_manager_start(rdev, &rdev->vm_manager.sa_manager); | ||
364 | } | ||
365 | |||
366 | int radeon_vm_manager_suspend(struct radeon_device *rdev) | ||
367 | { | ||
368 | struct radeon_vm *vm, *tmp; | 381 | struct radeon_vm *vm, *tmp; |
369 | 382 | ||
383 | if (!rdev->vm_manager.enabled) | ||
384 | return; | ||
385 | |||
370 | mutex_lock(&rdev->vm_manager.lock); | 386 | mutex_lock(&rdev->vm_manager.lock); |
371 | /* unbind all active vm */ | 387 | /* unbind all active vm */ |
372 | list_for_each_entry_safe(vm, tmp, &rdev->vm_manager.lru_vm, list) { | 388 | list_for_each_entry_safe(vm, tmp, &rdev->vm_manager.lru_vm, list) { |
@@ -374,7 +390,10 @@ int radeon_vm_manager_suspend(struct radeon_device *rdev) | |||
374 | } | 390 | } |
375 | rdev->vm_manager.funcs->fini(rdev); | 391 | rdev->vm_manager.funcs->fini(rdev); |
376 | mutex_unlock(&rdev->vm_manager.lock); | 392 | mutex_unlock(&rdev->vm_manager.lock); |
377 | return radeon_sa_bo_manager_suspend(rdev, &rdev->vm_manager.sa_manager); | 393 | |
394 | radeon_sa_bo_manager_suspend(rdev, &rdev->vm_manager.sa_manager); | ||
395 | radeon_sa_bo_manager_fini(rdev, &rdev->vm_manager.sa_manager); | ||
396 | rdev->vm_manager.enabled = false; | ||
378 | } | 397 | } |
379 | 398 | ||
380 | /* global mutex must be locked */ | 399 | /* global mutex must be locked */ |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 7c2618b9aa34..2b691abef4f7 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
@@ -3777,9 +3777,11 @@ static int si_startup(struct radeon_device *rdev) | |||
3777 | return r; | 3777 | return r; |
3778 | } | 3778 | } |
3779 | 3779 | ||
3780 | r = radeon_vm_manager_start(rdev); | 3780 | r = radeon_vm_manager_init(rdev); |
3781 | if (r) | 3781 | if (r) { |
3782 | dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); | ||
3782 | return r; | 3783 | return r; |
3784 | } | ||
3783 | 3785 | ||
3784 | return 0; | 3786 | return 0; |
3785 | } | 3787 | } |
@@ -3809,7 +3811,6 @@ int si_resume(struct radeon_device *rdev) | |||
3809 | 3811 | ||
3810 | int si_suspend(struct radeon_device *rdev) | 3812 | int si_suspend(struct radeon_device *rdev) |
3811 | { | 3813 | { |
3812 | radeon_vm_manager_suspend(rdev); | ||
3813 | si_cp_enable(rdev, false); | 3814 | si_cp_enable(rdev, false); |
3814 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; | 3815 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; |
3815 | rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; | 3816 | rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; |
@@ -3899,11 +3900,6 @@ int si_init(struct radeon_device *rdev) | |||
3899 | return r; | 3900 | return r; |
3900 | 3901 | ||
3901 | rdev->accel_working = true; | 3902 | rdev->accel_working = true; |
3902 | r = radeon_vm_manager_init(rdev); | ||
3903 | if (r) { | ||
3904 | dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); | ||
3905 | } | ||
3906 | |||
3907 | r = si_startup(rdev); | 3903 | r = si_startup(rdev); |
3908 | if (r) { | 3904 | if (r) { |
3909 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | 3905 | dev_err(rdev->dev, "disabling GPU acceleration\n"); |