drm/radeon: implement pci config reset for evergreen/cayman (v2)

pci config reset is a low level reset that resets
the entire chip from the bus interface.  It can
be more reliable if soft reset fails.

v2: put behind module parameter

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Alex Deucher
2013-11-01 16:25:10 -04:00
parent de9ae7447a
commit b5470b036e
3 changed files with 59 additions and 2 deletions

View File

@@ -146,6 +146,7 @@ extern u32 si_get_csb_size(struct radeon_device *rdev);
extern void si_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer);
extern u32 cik_get_csb_size(struct radeon_device *rdev);
extern void cik_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer);
extern void rv770_set_clk_bypass_mode(struct radeon_device *rdev);
static const u32 evergreen_golden_registers[] =
{
@@ -3867,6 +3868,48 @@ static void evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
evergreen_print_gpu_status_regs(rdev);
}
void evergreen_gpu_pci_config_reset(struct radeon_device *rdev)
{
struct evergreen_mc_save save;
u32 tmp, i;
dev_info(rdev->dev, "GPU pci config reset\n");
/* disable dpm? */
/* Disable CP parsing/prefetching */
WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT);
udelay(50);
/* Disable DMA */
tmp = RREG32(DMA_RB_CNTL);
tmp &= ~DMA_RB_ENABLE;
WREG32(DMA_RB_CNTL, tmp);
/* XXX other engines? */
/* halt the rlc */
r600_rlc_stop(rdev);
udelay(50);
/* set mclk/sclk to bypass */
rv770_set_clk_bypass_mode(rdev);
/* disable BM */
pci_clear_master(rdev->pdev);
/* disable mem access */
evergreen_mc_stop(rdev, &save);
if (evergreen_mc_wait_for_idle(rdev)) {
dev_warn(rdev->dev, "Wait for MC idle timed out !\n");
}
/* reset */
radeon_pci_config_reset(rdev);
/* wait for asic to come out of reset */
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(CONFIG_MEMSIZE) != 0xffffffff)
break;
udelay(1);
}
}
int evergreen_asic_reset(struct radeon_device *rdev)
{
u32 reset_mask;
@@ -3876,10 +3919,17 @@ int evergreen_asic_reset(struct radeon_device *rdev)
if (reset_mask)
r600_set_bios_scratch_engine_hung(rdev, true);
/* try soft reset */
evergreen_gpu_soft_reset(rdev, reset_mask);
reset_mask = evergreen_gpu_check_soft_reset(rdev);
/* try pci config reset */
if (reset_mask && radeon_hard_reset)
evergreen_gpu_pci_config_reset(rdev);
reset_mask = evergreen_gpu_check_soft_reset(rdev);
if (!reset_mask)
r600_set_bios_scratch_engine_hung(rdev, false);