mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-08 07:35:04 +00:00
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>
This commit is contained in:
parent
797f203f62
commit
2858c00d28
7 changed files with 36 additions and 11 deletions
|
@ -6194,7 +6194,7 @@ int cik_suspend(struct radeon_device *rdev)
|
||||||
radeon_vm_manager_fini(rdev);
|
radeon_vm_manager_fini(rdev);
|
||||||
cik_cp_enable(rdev, false);
|
cik_cp_enable(rdev, false);
|
||||||
cik_sdma_enable(rdev, false);
|
cik_sdma_enable(rdev, false);
|
||||||
r600_uvd_rbc_stop(rdev);
|
r600_uvd_stop(rdev);
|
||||||
radeon_uvd_suspend(rdev);
|
radeon_uvd_suspend(rdev);
|
||||||
cik_irq_suspend(rdev);
|
cik_irq_suspend(rdev);
|
||||||
radeon_wb_disable(rdev);
|
radeon_wb_disable(rdev);
|
||||||
|
@ -6358,6 +6358,7 @@ void cik_fini(struct radeon_device *rdev)
|
||||||
radeon_vm_manager_fini(rdev);
|
radeon_vm_manager_fini(rdev);
|
||||||
radeon_ib_pool_fini(rdev);
|
radeon_ib_pool_fini(rdev);
|
||||||
radeon_irq_kms_fini(rdev);
|
radeon_irq_kms_fini(rdev);
|
||||||
|
r600_uvd_stop(rdev);
|
||||||
radeon_uvd_fini(rdev);
|
radeon_uvd_fini(rdev);
|
||||||
cik_pcie_gart_fini(rdev);
|
cik_pcie_gart_fini(rdev);
|
||||||
r600_vram_scratch_fini(rdev);
|
r600_vram_scratch_fini(rdev);
|
||||||
|
|
|
@ -5291,10 +5291,10 @@ int evergreen_resume(struct radeon_device *rdev)
|
||||||
int evergreen_suspend(struct radeon_device *rdev)
|
int evergreen_suspend(struct radeon_device *rdev)
|
||||||
{
|
{
|
||||||
r600_audio_fini(rdev);
|
r600_audio_fini(rdev);
|
||||||
|
r600_uvd_stop(rdev);
|
||||||
radeon_uvd_suspend(rdev);
|
radeon_uvd_suspend(rdev);
|
||||||
r700_cp_stop(rdev);
|
r700_cp_stop(rdev);
|
||||||
r600_dma_stop(rdev);
|
r600_dma_stop(rdev);
|
||||||
r600_uvd_rbc_stop(rdev);
|
|
||||||
evergreen_irq_suspend(rdev);
|
evergreen_irq_suspend(rdev);
|
||||||
radeon_wb_disable(rdev);
|
radeon_wb_disable(rdev);
|
||||||
evergreen_pcie_gart_disable(rdev);
|
evergreen_pcie_gart_disable(rdev);
|
||||||
|
@ -5429,6 +5429,7 @@ void evergreen_fini(struct radeon_device *rdev)
|
||||||
radeon_ib_pool_fini(rdev);
|
radeon_ib_pool_fini(rdev);
|
||||||
radeon_irq_kms_fini(rdev);
|
radeon_irq_kms_fini(rdev);
|
||||||
evergreen_pcie_gart_fini(rdev);
|
evergreen_pcie_gart_fini(rdev);
|
||||||
|
r600_uvd_stop(rdev);
|
||||||
radeon_uvd_fini(rdev);
|
radeon_uvd_fini(rdev);
|
||||||
r600_vram_scratch_fini(rdev);
|
r600_vram_scratch_fini(rdev);
|
||||||
radeon_gem_fini(rdev);
|
radeon_gem_fini(rdev);
|
||||||
|
|
|
@ -2286,7 +2286,7 @@ int cayman_suspend(struct radeon_device *rdev)
|
||||||
radeon_vm_manager_fini(rdev);
|
radeon_vm_manager_fini(rdev);
|
||||||
cayman_cp_enable(rdev, false);
|
cayman_cp_enable(rdev, false);
|
||||||
cayman_dma_stop(rdev);
|
cayman_dma_stop(rdev);
|
||||||
r600_uvd_rbc_stop(rdev);
|
r600_uvd_stop(rdev);
|
||||||
radeon_uvd_suspend(rdev);
|
radeon_uvd_suspend(rdev);
|
||||||
evergreen_irq_suspend(rdev);
|
evergreen_irq_suspend(rdev);
|
||||||
radeon_wb_disable(rdev);
|
radeon_wb_disable(rdev);
|
||||||
|
@ -2418,6 +2418,7 @@ void cayman_fini(struct radeon_device *rdev)
|
||||||
radeon_vm_manager_fini(rdev);
|
radeon_vm_manager_fini(rdev);
|
||||||
radeon_ib_pool_fini(rdev);
|
radeon_ib_pool_fini(rdev);
|
||||||
radeon_irq_kms_fini(rdev);
|
radeon_irq_kms_fini(rdev);
|
||||||
|
r600_uvd_stop(rdev);
|
||||||
radeon_uvd_fini(rdev);
|
radeon_uvd_fini(rdev);
|
||||||
cayman_pcie_gart_fini(rdev);
|
cayman_pcie_gart_fini(rdev);
|
||||||
r600_vram_scratch_fini(rdev);
|
r600_vram_scratch_fini(rdev);
|
||||||
|
|
|
@ -2697,12 +2697,29 @@ int r600_uvd_rbc_start(struct radeon_device *rdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void r600_uvd_rbc_stop(struct radeon_device *rdev)
|
void r600_uvd_stop(struct radeon_device *rdev)
|
||||||
{
|
{
|
||||||
struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
|
struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
|
||||||
|
|
||||||
/* force RBC into idle state */
|
/* force RBC into idle state */
|
||||||
WREG32(UVD_RBC_RB_CNTL, 0x11010101);
|
WREG32(UVD_RBC_RB_CNTL, 0x11010101);
|
||||||
|
|
||||||
|
/* Stall UMC and register bus before resetting VCPU */
|
||||||
|
WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
|
||||||
|
WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
|
||||||
|
mdelay(1);
|
||||||
|
|
||||||
|
/* put VCPU into reset */
|
||||||
|
WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET);
|
||||||
|
mdelay(5);
|
||||||
|
|
||||||
|
/* disable VCPU clock */
|
||||||
|
WREG32(UVD_VCPU_CNTL, 0x0);
|
||||||
|
|
||||||
|
/* Unstall UMC and register bus */
|
||||||
|
WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
|
||||||
|
WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3));
|
||||||
|
|
||||||
ring->ready = false;
|
ring->ready = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2722,6 +2739,11 @@ int r600_uvd_init(struct radeon_device *rdev)
|
||||||
/* disable interupt */
|
/* disable interupt */
|
||||||
WREG32_P(UVD_MASTINT_EN, 0, ~(1 << 1));
|
WREG32_P(UVD_MASTINT_EN, 0, ~(1 << 1));
|
||||||
|
|
||||||
|
/* Stall UMC and register bus before resetting VCPU */
|
||||||
|
WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
|
||||||
|
WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
|
||||||
|
mdelay(1);
|
||||||
|
|
||||||
/* put LMI, VCPU, RBC etc... into reset */
|
/* put LMI, VCPU, RBC etc... into reset */
|
||||||
WREG32(UVD_SOFT_RESET, LMI_SOFT_RESET | VCPU_SOFT_RESET |
|
WREG32(UVD_SOFT_RESET, LMI_SOFT_RESET | VCPU_SOFT_RESET |
|
||||||
LBSI_SOFT_RESET | RBC_SOFT_RESET | CSM_SOFT_RESET |
|
LBSI_SOFT_RESET | RBC_SOFT_RESET | CSM_SOFT_RESET |
|
||||||
|
@ -2751,10 +2773,6 @@ int r600_uvd_init(struct radeon_device *rdev)
|
||||||
WREG32(UVD_MPC_SET_ALU, 0);
|
WREG32(UVD_MPC_SET_ALU, 0);
|
||||||
WREG32(UVD_MPC_SET_MUX, 0x88);
|
WREG32(UVD_MPC_SET_MUX, 0x88);
|
||||||
|
|
||||||
/* Stall UMC */
|
|
||||||
WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
|
|
||||||
WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
|
|
||||||
|
|
||||||
/* take all subblocks out of reset, except VCPU */
|
/* take all subblocks out of reset, except VCPU */
|
||||||
WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET);
|
WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET);
|
||||||
mdelay(5);
|
mdelay(5);
|
||||||
|
|
|
@ -441,7 +441,7 @@ void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rde
|
||||||
/* uvd */
|
/* uvd */
|
||||||
int r600_uvd_init(struct radeon_device *rdev);
|
int r600_uvd_init(struct radeon_device *rdev);
|
||||||
int r600_uvd_rbc_start(struct radeon_device *rdev);
|
int r600_uvd_rbc_start(struct radeon_device *rdev);
|
||||||
void r600_uvd_rbc_stop(struct radeon_device *rdev);
|
void r600_uvd_stop(struct radeon_device *rdev);
|
||||||
int r600_uvd_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
|
int r600_uvd_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
|
||||||
void r600_uvd_fence_emit(struct radeon_device *rdev,
|
void r600_uvd_fence_emit(struct radeon_device *rdev,
|
||||||
struct radeon_fence *fence);
|
struct radeon_fence *fence);
|
||||||
|
|
|
@ -1983,6 +1983,7 @@ int rv770_resume(struct radeon_device *rdev)
|
||||||
int rv770_suspend(struct radeon_device *rdev)
|
int rv770_suspend(struct radeon_device *rdev)
|
||||||
{
|
{
|
||||||
r600_audio_fini(rdev);
|
r600_audio_fini(rdev);
|
||||||
|
r600_uvd_stop(rdev);
|
||||||
radeon_uvd_suspend(rdev);
|
radeon_uvd_suspend(rdev);
|
||||||
r700_cp_stop(rdev);
|
r700_cp_stop(rdev);
|
||||||
r600_dma_stop(rdev);
|
r600_dma_stop(rdev);
|
||||||
|
@ -2098,6 +2099,7 @@ void rv770_fini(struct radeon_device *rdev)
|
||||||
radeon_ib_pool_fini(rdev);
|
radeon_ib_pool_fini(rdev);
|
||||||
radeon_irq_kms_fini(rdev);
|
radeon_irq_kms_fini(rdev);
|
||||||
rv770_pcie_gart_fini(rdev);
|
rv770_pcie_gart_fini(rdev);
|
||||||
|
r600_uvd_stop(rdev);
|
||||||
radeon_uvd_fini(rdev);
|
radeon_uvd_fini(rdev);
|
||||||
r600_vram_scratch_fini(rdev);
|
r600_vram_scratch_fini(rdev);
|
||||||
radeon_gem_fini(rdev);
|
radeon_gem_fini(rdev);
|
||||||
|
|
|
@ -6621,7 +6621,7 @@ int si_suspend(struct radeon_device *rdev)
|
||||||
si_cp_enable(rdev, false);
|
si_cp_enable(rdev, false);
|
||||||
cayman_dma_stop(rdev);
|
cayman_dma_stop(rdev);
|
||||||
if (rdev->has_uvd) {
|
if (rdev->has_uvd) {
|
||||||
r600_uvd_rbc_stop(rdev);
|
r600_uvd_stop(rdev);
|
||||||
radeon_uvd_suspend(rdev);
|
radeon_uvd_suspend(rdev);
|
||||||
}
|
}
|
||||||
si_irq_suspend(rdev);
|
si_irq_suspend(rdev);
|
||||||
|
@ -6763,8 +6763,10 @@ void si_fini(struct radeon_device *rdev)
|
||||||
radeon_vm_manager_fini(rdev);
|
radeon_vm_manager_fini(rdev);
|
||||||
radeon_ib_pool_fini(rdev);
|
radeon_ib_pool_fini(rdev);
|
||||||
radeon_irq_kms_fini(rdev);
|
radeon_irq_kms_fini(rdev);
|
||||||
if (rdev->has_uvd)
|
if (rdev->has_uvd) {
|
||||||
|
r600_uvd_stop(rdev);
|
||||||
radeon_uvd_fini(rdev);
|
radeon_uvd_fini(rdev);
|
||||||
|
}
|
||||||
si_pcie_gart_fini(rdev);
|
si_pcie_gart_fini(rdev);
|
||||||
r600_vram_scratch_fini(rdev);
|
r600_vram_scratch_fini(rdev);
|
||||||
radeon_gem_fini(rdev);
|
radeon_gem_fini(rdev);
|
||||||
|
|
Loading…
Add table
Reference in a new issue