Message ID | 1375371247-2318-1-git-send-email-deathsimple@vodafone.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Aug 1, 2013 at 11:34 AM, Christian König <deathsimple@vodafone.de> wrote: > From: Christian König <christian.koenig@amd.com> > > 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 Applied to my -fixes queue. Alex > --- > drivers/gpu/drm/radeon/cik.c | 3 ++- > drivers/gpu/drm/radeon/evergreen.c | 3 ++- > drivers/gpu/drm/radeon/ni.c | 3 ++- > drivers/gpu/drm/radeon/r600.c | 28 +++++++++++++++++++++++----- > drivers/gpu/drm/radeon/radeon_asic.h | 2 +- > drivers/gpu/drm/radeon/rv770.c | 2 ++ > 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 6dacec4..524db70 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) > radeon_vm_manager_fini(rdev); > cik_cp_enable(rdev, false); > cik_sdma_enable(rdev, false); > - r600_uvd_rbc_stop(rdev); > + r600_uvd_stop(rdev); > radeon_uvd_suspend(rdev); > cik_irq_suspend(rdev); > radeon_wb_disable(rdev); > @@ -6358,6 +6358,7 @@ void cik_fini(struct radeon_device *rdev) > radeon_vm_manager_fini(rdev); > radeon_ib_pool_fini(rdev); > radeon_irq_kms_fini(rdev); > + r600_uvd_stop(rdev); > radeon_uvd_fini(rdev); > cik_pcie_gart_fini(rdev); > r600_vram_scratch_fini(rdev); > diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c > index 038dcac..5b98e57 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) > int evergreen_suspend(struct radeon_device *rdev) > { > r600_audio_fini(rdev); > + r600_uvd_stop(rdev); > radeon_uvd_suspend(rdev); > r700_cp_stop(rdev); > r600_dma_stop(rdev); > - r600_uvd_rbc_stop(rdev); > evergreen_irq_suspend(rdev); > radeon_wb_disable(rdev); > evergreen_pcie_gart_disable(rdev); > @@ -5429,6 +5429,7 @@ void evergreen_fini(struct radeon_device *rdev) > radeon_ib_pool_fini(rdev); > radeon_irq_kms_fini(rdev); > evergreen_pcie_gart_fini(rdev); > + r600_uvd_stop(rdev); > radeon_uvd_fini(rdev); > r600_vram_scratch_fini(rdev); > radeon_gem_fini(rdev); > diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c > index 56bd4f3..16e91b0 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) > radeon_vm_manager_fini(rdev); > cayman_cp_enable(rdev, false); > cayman_dma_stop(rdev); > - r600_uvd_rbc_stop(rdev); > + r600_uvd_stop(rdev); > radeon_uvd_suspend(rdev); > evergreen_irq_suspend(rdev); > radeon_wb_disable(rdev); > @@ -2418,6 +2418,7 @@ void cayman_fini(struct radeon_device *rdev) > radeon_vm_manager_fini(rdev); > radeon_ib_pool_fini(rdev); > radeon_irq_kms_fini(rdev); > + r600_uvd_stop(rdev); > radeon_uvd_fini(rdev); > cayman_pcie_gart_fini(rdev); > r600_vram_scratch_fini(rdev); > diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c > index 10f712e..0a9553a 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) > 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]; > > /* force RBC into idle state */ > 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; > } > > @@ -2722,6 +2739,11 @@ int r600_uvd_init(struct radeon_device *rdev) > /* disable interupt */ > 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 */ > WREG32(UVD_SOFT_RESET, LMI_SOFT_RESET | VCPU_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_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 */ > WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET); > mdelay(5); > diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h > index 902479f..3d61d5a 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 > /* uvd */ > int r600_uvd_init(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); > void r600_uvd_fence_emit(struct radeon_device *rdev, > struct radeon_fence *fence); > diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c > index 30ea14e..f101013 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) > int rv770_suspend(struct radeon_device *rdev) > { > r600_audio_fini(rdev); > + r600_uvd_stop(rdev); > radeon_uvd_suspend(rdev); > r700_cp_stop(rdev); > r600_dma_stop(rdev); > @@ -2098,6 +2099,7 @@ void rv770_fini(struct radeon_device *rdev) > radeon_ib_pool_fini(rdev); > radeon_irq_kms_fini(rdev); > rv770_pcie_gart_fini(rdev); > + r600_uvd_stop(rdev); > radeon_uvd_fini(rdev); > r600_vram_scratch_fini(rdev); > radeon_gem_fini(rdev); > diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c > index 6ca9046..242c1ac 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) > si_cp_enable(rdev, false); > cayman_dma_stop(rdev); > if (rdev->has_uvd) { > - r600_uvd_rbc_stop(rdev); > + r600_uvd_stop(rdev); > radeon_uvd_suspend(rdev); > } > si_irq_suspend(rdev); > @@ -6763,8 +6763,10 @@ void si_fini(struct radeon_device *rdev) > radeon_vm_manager_fini(rdev); > radeon_ib_pool_fini(rdev); > radeon_irq_kms_fini(rdev); > - if (rdev->has_uvd) > + if (rdev->has_uvd) { > + r600_uvd_stop(rdev); > radeon_uvd_fini(rdev); > + } > si_pcie_gart_fini(rdev); > r600_vram_scratch_fini(rdev); > radeon_gem_fini(rdev); > -- > 1.7.9.5 >
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 6dacec4..524db70 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) radeon_vm_manager_fini(rdev); cik_cp_enable(rdev, false); cik_sdma_enable(rdev, false); - r600_uvd_rbc_stop(rdev); + r600_uvd_stop(rdev); radeon_uvd_suspend(rdev); cik_irq_suspend(rdev); radeon_wb_disable(rdev); @@ -6358,6 +6358,7 @@ void cik_fini(struct radeon_device *rdev) radeon_vm_manager_fini(rdev); radeon_ib_pool_fini(rdev); radeon_irq_kms_fini(rdev); + r600_uvd_stop(rdev); radeon_uvd_fini(rdev); cik_pcie_gart_fini(rdev); r600_vram_scratch_fini(rdev); diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 038dcac..5b98e57 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) int evergreen_suspend(struct radeon_device *rdev) { r600_audio_fini(rdev); + r600_uvd_stop(rdev); radeon_uvd_suspend(rdev); r700_cp_stop(rdev); r600_dma_stop(rdev); - r600_uvd_rbc_stop(rdev); evergreen_irq_suspend(rdev); radeon_wb_disable(rdev); evergreen_pcie_gart_disable(rdev); @@ -5429,6 +5429,7 @@ void evergreen_fini(struct radeon_device *rdev) radeon_ib_pool_fini(rdev); radeon_irq_kms_fini(rdev); evergreen_pcie_gart_fini(rdev); + r600_uvd_stop(rdev); radeon_uvd_fini(rdev); r600_vram_scratch_fini(rdev); radeon_gem_fini(rdev); diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 56bd4f3..16e91b0 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) radeon_vm_manager_fini(rdev); cayman_cp_enable(rdev, false); cayman_dma_stop(rdev); - r600_uvd_rbc_stop(rdev); + r600_uvd_stop(rdev); radeon_uvd_suspend(rdev); evergreen_irq_suspend(rdev); radeon_wb_disable(rdev); @@ -2418,6 +2418,7 @@ void cayman_fini(struct radeon_device *rdev) radeon_vm_manager_fini(rdev); radeon_ib_pool_fini(rdev); radeon_irq_kms_fini(rdev); + r600_uvd_stop(rdev); radeon_uvd_fini(rdev); cayman_pcie_gart_fini(rdev); r600_vram_scratch_fini(rdev); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 10f712e..0a9553a 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) 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]; /* force RBC into idle state */ 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; } @@ -2722,6 +2739,11 @@ int r600_uvd_init(struct radeon_device *rdev) /* disable interupt */ 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 */ WREG32(UVD_SOFT_RESET, LMI_SOFT_RESET | VCPU_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_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 */ WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET); mdelay(5); diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 902479f..3d61d5a 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 /* uvd */ int r600_uvd_init(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); void r600_uvd_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 30ea14e..f101013 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) int rv770_suspend(struct radeon_device *rdev) { r600_audio_fini(rdev); + r600_uvd_stop(rdev); radeon_uvd_suspend(rdev); r700_cp_stop(rdev); r600_dma_stop(rdev); @@ -2098,6 +2099,7 @@ void rv770_fini(struct radeon_device *rdev) radeon_ib_pool_fini(rdev); radeon_irq_kms_fini(rdev); rv770_pcie_gart_fini(rdev); + r600_uvd_stop(rdev); radeon_uvd_fini(rdev); r600_vram_scratch_fini(rdev); radeon_gem_fini(rdev); diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 6ca9046..242c1ac 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) si_cp_enable(rdev, false); cayman_dma_stop(rdev); if (rdev->has_uvd) { - r600_uvd_rbc_stop(rdev); + r600_uvd_stop(rdev); radeon_uvd_suspend(rdev); } si_irq_suspend(rdev); @@ -6763,8 +6763,10 @@ void si_fini(struct radeon_device *rdev) radeon_vm_manager_fini(rdev); radeon_ib_pool_fini(rdev); radeon_irq_kms_fini(rdev); - if (rdev->has_uvd) + if (rdev->has_uvd) { + r600_uvd_stop(rdev); radeon_uvd_fini(rdev); + } si_pcie_gart_fini(rdev); r600_vram_scratch_fini(rdev); radeon_gem_fini(rdev);