diff options
author | Christian König <christian.koenig@amd.com> | 2013-08-01 11:34:07 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-08-07 17:37:11 -0400 |
commit | 2858c00d2823c83acce2a1175dbabb2cebee8678 (patch) | |
tree | 1751bd3ac36c6749a0fded1775def26b19be2dcb | |
parent | 797f203f622164a322b9a0f962ce431e3f6ca48e (diff) |
drm/radeon: fix halting UVD
Removing the clock/power or resetting the VCPU can cause
hangs if that happens in the middle of a register write.
Stall the memory and register bus before putting the VCPU
into reset. Keep it in reset when unloading the module or
suspending.
Signed-off-by: Christian König <christian.koenig@amd.com>
Cc: stable@vger.kernel.org
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/radeon/cik.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/ni.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv770.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/si.c | 6 |
7 files changed, 36 insertions, 11 deletions
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 6dacec4e2090..524db70aaf6e 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c | |||
@@ -6194,7 +6194,7 @@ int cik_suspend(struct radeon_device *rdev) | |||
6194 | radeon_vm_manager_fini(rdev); | 6194 | radeon_vm_manager_fini(rdev); |
6195 | cik_cp_enable(rdev, false); | 6195 | cik_cp_enable(rdev, false); |
6196 | cik_sdma_enable(rdev, false); | 6196 | cik_sdma_enable(rdev, false); |
6197 | r600_uvd_rbc_stop(rdev); | 6197 | r600_uvd_stop(rdev); |
6198 | radeon_uvd_suspend(rdev); | 6198 | radeon_uvd_suspend(rdev); |
6199 | cik_irq_suspend(rdev); | 6199 | cik_irq_suspend(rdev); |
6200 | radeon_wb_disable(rdev); | 6200 | radeon_wb_disable(rdev); |
@@ -6358,6 +6358,7 @@ void cik_fini(struct radeon_device *rdev) | |||
6358 | radeon_vm_manager_fini(rdev); | 6358 | radeon_vm_manager_fini(rdev); |
6359 | radeon_ib_pool_fini(rdev); | 6359 | radeon_ib_pool_fini(rdev); |
6360 | radeon_irq_kms_fini(rdev); | 6360 | radeon_irq_kms_fini(rdev); |
6361 | r600_uvd_stop(rdev); | ||
6361 | radeon_uvd_fini(rdev); | 6362 | radeon_uvd_fini(rdev); |
6362 | cik_pcie_gart_fini(rdev); | 6363 | cik_pcie_gart_fini(rdev); |
6363 | r600_vram_scratch_fini(rdev); | 6364 | r600_vram_scratch_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 038dcac7670c..5b98e573d60a 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -5291,10 +5291,10 @@ int evergreen_resume(struct radeon_device *rdev) | |||
5291 | int evergreen_suspend(struct radeon_device *rdev) | 5291 | int evergreen_suspend(struct radeon_device *rdev) |
5292 | { | 5292 | { |
5293 | r600_audio_fini(rdev); | 5293 | r600_audio_fini(rdev); |
5294 | r600_uvd_stop(rdev); | ||
5294 | radeon_uvd_suspend(rdev); | 5295 | radeon_uvd_suspend(rdev); |
5295 | r700_cp_stop(rdev); | 5296 | r700_cp_stop(rdev); |
5296 | r600_dma_stop(rdev); | 5297 | r600_dma_stop(rdev); |
5297 | r600_uvd_rbc_stop(rdev); | ||
5298 | evergreen_irq_suspend(rdev); | 5298 | evergreen_irq_suspend(rdev); |
5299 | radeon_wb_disable(rdev); | 5299 | radeon_wb_disable(rdev); |
5300 | evergreen_pcie_gart_disable(rdev); | 5300 | evergreen_pcie_gart_disable(rdev); |
@@ -5429,6 +5429,7 @@ void evergreen_fini(struct radeon_device *rdev) | |||
5429 | radeon_ib_pool_fini(rdev); | 5429 | radeon_ib_pool_fini(rdev); |
5430 | radeon_irq_kms_fini(rdev); | 5430 | radeon_irq_kms_fini(rdev); |
5431 | evergreen_pcie_gart_fini(rdev); | 5431 | evergreen_pcie_gart_fini(rdev); |
5432 | r600_uvd_stop(rdev); | ||
5432 | radeon_uvd_fini(rdev); | 5433 | radeon_uvd_fini(rdev); |
5433 | r600_vram_scratch_fini(rdev); | 5434 | r600_vram_scratch_fini(rdev); |
5434 | radeon_gem_fini(rdev); | 5435 | radeon_gem_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 56bd4f3be4fe..16e91b08bf57 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
@@ -2286,7 +2286,7 @@ int cayman_suspend(struct radeon_device *rdev) | |||
2286 | radeon_vm_manager_fini(rdev); | 2286 | radeon_vm_manager_fini(rdev); |
2287 | cayman_cp_enable(rdev, false); | 2287 | cayman_cp_enable(rdev, false); |
2288 | cayman_dma_stop(rdev); | 2288 | cayman_dma_stop(rdev); |
2289 | r600_uvd_rbc_stop(rdev); | 2289 | r600_uvd_stop(rdev); |
2290 | radeon_uvd_suspend(rdev); | 2290 | radeon_uvd_suspend(rdev); |
2291 | evergreen_irq_suspend(rdev); | 2291 | evergreen_irq_suspend(rdev); |
2292 | radeon_wb_disable(rdev); | 2292 | radeon_wb_disable(rdev); |
@@ -2418,6 +2418,7 @@ void cayman_fini(struct radeon_device *rdev) | |||
2418 | radeon_vm_manager_fini(rdev); | 2418 | radeon_vm_manager_fini(rdev); |
2419 | radeon_ib_pool_fini(rdev); | 2419 | radeon_ib_pool_fini(rdev); |
2420 | radeon_irq_kms_fini(rdev); | 2420 | radeon_irq_kms_fini(rdev); |
2421 | r600_uvd_stop(rdev); | ||
2421 | radeon_uvd_fini(rdev); | 2422 | radeon_uvd_fini(rdev); |
2422 | cayman_pcie_gart_fini(rdev); | 2423 | cayman_pcie_gart_fini(rdev); |
2423 | r600_vram_scratch_fini(rdev); | 2424 | r600_vram_scratch_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 10f712e37003..0a9553abec54 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -2697,12 +2697,29 @@ int r600_uvd_rbc_start(struct radeon_device *rdev) | |||
2697 | return 0; | 2697 | return 0; |
2698 | } | 2698 | } |
2699 | 2699 | ||
2700 | void r600_uvd_rbc_stop(struct radeon_device *rdev) | 2700 | void r600_uvd_stop(struct radeon_device *rdev) |
2701 | { | 2701 | { |
2702 | struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; | 2702 | struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; |
2703 | 2703 | ||
2704 | /* force RBC into idle state */ | 2704 | /* force RBC into idle state */ |
2705 | WREG32(UVD_RBC_RB_CNTL, 0x11010101); | 2705 | WREG32(UVD_RBC_RB_CNTL, 0x11010101); |
2706 | |||
2707 | /* Stall UMC and register bus before resetting VCPU */ | ||
2708 | WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8)); | ||
2709 | WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3)); | ||
2710 | mdelay(1); | ||
2711 | |||
2712 | /* put VCPU into reset */ | ||
2713 | WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET); | ||
2714 | mdelay(5); | ||
2715 | |||
2716 | /* disable VCPU clock */ | ||
2717 | WREG32(UVD_VCPU_CNTL, 0x0); | ||
2718 | |||
2719 | /* Unstall UMC and register bus */ | ||
2720 | WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8)); | ||
2721 | WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3)); | ||
2722 | |||
2706 | ring->ready = false; | 2723 | ring->ready = false; |
2707 | } | 2724 | } |
2708 | 2725 | ||
@@ -2722,6 +2739,11 @@ int r600_uvd_init(struct radeon_device *rdev) | |||
2722 | /* disable interupt */ | 2739 | /* disable interupt */ |
2723 | WREG32_P(UVD_MASTINT_EN, 0, ~(1 << 1)); | 2740 | WREG32_P(UVD_MASTINT_EN, 0, ~(1 << 1)); |
2724 | 2741 | ||
2742 | /* Stall UMC and register bus before resetting VCPU */ | ||
2743 | WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8)); | ||
2744 | WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3)); | ||
2745 | mdelay(1); | ||
2746 | |||
2725 | /* put LMI, VCPU, RBC etc... into reset */ | 2747 | /* put LMI, VCPU, RBC etc... into reset */ |
2726 | WREG32(UVD_SOFT_RESET, LMI_SOFT_RESET | VCPU_SOFT_RESET | | 2748 | WREG32(UVD_SOFT_RESET, LMI_SOFT_RESET | VCPU_SOFT_RESET | |
2727 | LBSI_SOFT_RESET | RBC_SOFT_RESET | CSM_SOFT_RESET | | 2749 | LBSI_SOFT_RESET | RBC_SOFT_RESET | CSM_SOFT_RESET | |
@@ -2751,10 +2773,6 @@ int r600_uvd_init(struct radeon_device *rdev) | |||
2751 | WREG32(UVD_MPC_SET_ALU, 0); | 2773 | WREG32(UVD_MPC_SET_ALU, 0); |
2752 | WREG32(UVD_MPC_SET_MUX, 0x88); | 2774 | WREG32(UVD_MPC_SET_MUX, 0x88); |
2753 | 2775 | ||
2754 | /* Stall UMC */ | ||
2755 | WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8)); | ||
2756 | WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3)); | ||
2757 | |||
2758 | /* take all subblocks out of reset, except VCPU */ | 2776 | /* take all subblocks out of reset, except VCPU */ |
2759 | WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET); | 2777 | WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET); |
2760 | mdelay(5); | 2778 | mdelay(5); |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 902479fa737f..3d61d5aac18f 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
@@ -441,7 +441,7 @@ void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rde | |||
441 | /* uvd */ | 441 | /* uvd */ |
442 | int r600_uvd_init(struct radeon_device *rdev); | 442 | int r600_uvd_init(struct radeon_device *rdev); |
443 | int r600_uvd_rbc_start(struct radeon_device *rdev); | 443 | int r600_uvd_rbc_start(struct radeon_device *rdev); |
444 | void r600_uvd_rbc_stop(struct radeon_device *rdev); | 444 | void r600_uvd_stop(struct radeon_device *rdev); |
445 | int r600_uvd_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); | 445 | int r600_uvd_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); |
446 | void r600_uvd_fence_emit(struct radeon_device *rdev, | 446 | void r600_uvd_fence_emit(struct radeon_device *rdev, |
447 | struct radeon_fence *fence); | 447 | struct radeon_fence *fence); |
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 30ea14e8854c..f1010131bac0 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
@@ -1983,6 +1983,7 @@ int rv770_resume(struct radeon_device *rdev) | |||
1983 | int rv770_suspend(struct radeon_device *rdev) | 1983 | int rv770_suspend(struct radeon_device *rdev) |
1984 | { | 1984 | { |
1985 | r600_audio_fini(rdev); | 1985 | r600_audio_fini(rdev); |
1986 | r600_uvd_stop(rdev); | ||
1986 | radeon_uvd_suspend(rdev); | 1987 | radeon_uvd_suspend(rdev); |
1987 | r700_cp_stop(rdev); | 1988 | r700_cp_stop(rdev); |
1988 | r600_dma_stop(rdev); | 1989 | r600_dma_stop(rdev); |
@@ -2098,6 +2099,7 @@ void rv770_fini(struct radeon_device *rdev) | |||
2098 | radeon_ib_pool_fini(rdev); | 2099 | radeon_ib_pool_fini(rdev); |
2099 | radeon_irq_kms_fini(rdev); | 2100 | radeon_irq_kms_fini(rdev); |
2100 | rv770_pcie_gart_fini(rdev); | 2101 | rv770_pcie_gart_fini(rdev); |
2102 | r600_uvd_stop(rdev); | ||
2101 | radeon_uvd_fini(rdev); | 2103 | radeon_uvd_fini(rdev); |
2102 | r600_vram_scratch_fini(rdev); | 2104 | r600_vram_scratch_fini(rdev); |
2103 | radeon_gem_fini(rdev); | 2105 | radeon_gem_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 6ca904673a4f..242c1ac83e23 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
@@ -6621,7 +6621,7 @@ int si_suspend(struct radeon_device *rdev) | |||
6621 | si_cp_enable(rdev, false); | 6621 | si_cp_enable(rdev, false); |
6622 | cayman_dma_stop(rdev); | 6622 | cayman_dma_stop(rdev); |
6623 | if (rdev->has_uvd) { | 6623 | if (rdev->has_uvd) { |
6624 | r600_uvd_rbc_stop(rdev); | 6624 | r600_uvd_stop(rdev); |
6625 | radeon_uvd_suspend(rdev); | 6625 | radeon_uvd_suspend(rdev); |
6626 | } | 6626 | } |
6627 | si_irq_suspend(rdev); | 6627 | si_irq_suspend(rdev); |
@@ -6763,8 +6763,10 @@ void si_fini(struct radeon_device *rdev) | |||
6763 | radeon_vm_manager_fini(rdev); | 6763 | radeon_vm_manager_fini(rdev); |
6764 | radeon_ib_pool_fini(rdev); | 6764 | radeon_ib_pool_fini(rdev); |
6765 | radeon_irq_kms_fini(rdev); | 6765 | radeon_irq_kms_fini(rdev); |
6766 | if (rdev->has_uvd) | 6766 | if (rdev->has_uvd) { |
6767 | r600_uvd_stop(rdev); | ||
6767 | radeon_uvd_fini(rdev); | 6768 | radeon_uvd_fini(rdev); |
6769 | } | ||
6768 | si_pcie_gart_fini(rdev); | 6770 | si_pcie_gart_fini(rdev); |
6769 | r600_vram_scratch_fini(rdev); | 6771 | r600_vram_scratch_fini(rdev); |
6770 | radeon_gem_fini(rdev); | 6772 | radeon_gem_fini(rdev); |