drm/radeon: implement pci config reset for CIK (v3)
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: fix rebase v3: hide behind module parameter Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
@@ -4880,6 +4880,160 @@ static void cik_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
|
|||||||
cik_print_gpu_status_regs(rdev);
|
cik_print_gpu_status_regs(rdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct kv_reset_save_regs {
|
||||||
|
u32 gmcon_reng_execute;
|
||||||
|
u32 gmcon_misc;
|
||||||
|
u32 gmcon_misc3;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void kv_save_regs_for_reset(struct radeon_device *rdev,
|
||||||
|
struct kv_reset_save_regs *save)
|
||||||
|
{
|
||||||
|
save->gmcon_reng_execute = RREG32(GMCON_RENG_EXECUTE);
|
||||||
|
save->gmcon_misc = RREG32(GMCON_MISC);
|
||||||
|
save->gmcon_misc3 = RREG32(GMCON_MISC3);
|
||||||
|
|
||||||
|
WREG32(GMCON_RENG_EXECUTE, save->gmcon_reng_execute & ~RENG_EXECUTE_ON_PWR_UP);
|
||||||
|
WREG32(GMCON_MISC, save->gmcon_misc & ~(RENG_EXECUTE_ON_REG_UPDATE |
|
||||||
|
STCTRL_STUTTER_EN));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kv_restore_regs_for_reset(struct radeon_device *rdev,
|
||||||
|
struct kv_reset_save_regs *save)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0);
|
||||||
|
WREG32(GMCON_PGFSM_CONFIG, 0x200010ff);
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0);
|
||||||
|
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0);
|
||||||
|
WREG32(GMCON_PGFSM_CONFIG, 0x300010ff);
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0);
|
||||||
|
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0x210000);
|
||||||
|
WREG32(GMCON_PGFSM_CONFIG, 0xa00010ff);
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0);
|
||||||
|
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0x21003);
|
||||||
|
WREG32(GMCON_PGFSM_CONFIG, 0xb00010ff);
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0);
|
||||||
|
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0x2b00);
|
||||||
|
WREG32(GMCON_PGFSM_CONFIG, 0xc00010ff);
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0);
|
||||||
|
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0);
|
||||||
|
WREG32(GMCON_PGFSM_CONFIG, 0xd00010ff);
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0);
|
||||||
|
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0x420000);
|
||||||
|
WREG32(GMCON_PGFSM_CONFIG, 0x100010ff);
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0);
|
||||||
|
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0x120202);
|
||||||
|
WREG32(GMCON_PGFSM_CONFIG, 0x500010ff);
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0);
|
||||||
|
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0x3e3e36);
|
||||||
|
WREG32(GMCON_PGFSM_CONFIG, 0x600010ff);
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0);
|
||||||
|
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0x373f3e);
|
||||||
|
WREG32(GMCON_PGFSM_CONFIG, 0x700010ff);
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0);
|
||||||
|
|
||||||
|
WREG32(GMCON_PGFSM_WRITE, 0x3e1332);
|
||||||
|
WREG32(GMCON_PGFSM_CONFIG, 0xe00010ff);
|
||||||
|
|
||||||
|
WREG32(GMCON_MISC3, save->gmcon_misc3);
|
||||||
|
WREG32(GMCON_MISC, save->gmcon_misc);
|
||||||
|
WREG32(GMCON_RENG_EXECUTE, save->gmcon_reng_execute);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cik_gpu_pci_config_reset(struct radeon_device *rdev)
|
||||||
|
{
|
||||||
|
struct evergreen_mc_save save;
|
||||||
|
struct kv_reset_save_regs kv_save = { 0 };
|
||||||
|
u32 tmp, i;
|
||||||
|
|
||||||
|
dev_info(rdev->dev, "GPU pci config reset\n");
|
||||||
|
|
||||||
|
/* disable dpm? */
|
||||||
|
|
||||||
|
/* disable cg/pg */
|
||||||
|
cik_fini_pg(rdev);
|
||||||
|
cik_fini_cg(rdev);
|
||||||
|
|
||||||
|
/* Disable GFX parsing/prefetching */
|
||||||
|
WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT);
|
||||||
|
|
||||||
|
/* Disable MEC parsing/prefetching */
|
||||||
|
WREG32(CP_MEC_CNTL, MEC_ME1_HALT | MEC_ME2_HALT);
|
||||||
|
|
||||||
|
/* sdma0 */
|
||||||
|
tmp = RREG32(SDMA0_ME_CNTL + SDMA0_REGISTER_OFFSET);
|
||||||
|
tmp |= SDMA_HALT;
|
||||||
|
WREG32(SDMA0_ME_CNTL + SDMA0_REGISTER_OFFSET, tmp);
|
||||||
|
/* sdma1 */
|
||||||
|
tmp = RREG32(SDMA0_ME_CNTL + SDMA1_REGISTER_OFFSET);
|
||||||
|
tmp |= SDMA_HALT;
|
||||||
|
WREG32(SDMA0_ME_CNTL + SDMA1_REGISTER_OFFSET, tmp);
|
||||||
|
/* XXX other engines? */
|
||||||
|
|
||||||
|
/* halt the rlc, disable cp internal ints */
|
||||||
|
cik_rlc_stop(rdev);
|
||||||
|
|
||||||
|
udelay(50);
|
||||||
|
|
||||||
|
/* 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");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rdev->flags & RADEON_IS_IGP)
|
||||||
|
kv_save_regs_for_reset(rdev, &kv_save);
|
||||||
|
|
||||||
|
/* disable BM */
|
||||||
|
pci_clear_master(rdev->pdev);
|
||||||
|
/* reset */
|
||||||
|
radeon_pci_config_reset(rdev);
|
||||||
|
|
||||||
|
udelay(100);
|
||||||
|
|
||||||
|
/* wait for asic to come out of reset */
|
||||||
|
for (i = 0; i < rdev->usec_timeout; i++) {
|
||||||
|
if (RREG32(CONFIG_MEMSIZE) != 0xffffffff)
|
||||||
|
break;
|
||||||
|
udelay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* does asic init need to be run first??? */
|
||||||
|
if (rdev->flags & RADEON_IS_IGP)
|
||||||
|
kv_restore_regs_for_reset(rdev, &kv_save);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cik_asic_reset - soft reset GPU
|
* cik_asic_reset - soft reset GPU
|
||||||
*
|
*
|
||||||
@@ -4898,10 +5052,17 @@ int cik_asic_reset(struct radeon_device *rdev)
|
|||||||
if (reset_mask)
|
if (reset_mask)
|
||||||
r600_set_bios_scratch_engine_hung(rdev, true);
|
r600_set_bios_scratch_engine_hung(rdev, true);
|
||||||
|
|
||||||
|
/* try soft reset */
|
||||||
cik_gpu_soft_reset(rdev, reset_mask);
|
cik_gpu_soft_reset(rdev, reset_mask);
|
||||||
|
|
||||||
reset_mask = cik_gpu_check_soft_reset(rdev);
|
reset_mask = cik_gpu_check_soft_reset(rdev);
|
||||||
|
|
||||||
|
/* try pci config reset */
|
||||||
|
if (reset_mask && radeon_hard_reset)
|
||||||
|
cik_gpu_pci_config_reset(rdev);
|
||||||
|
|
||||||
|
reset_mask = cik_gpu_check_soft_reset(rdev);
|
||||||
|
|
||||||
if (!reset_mask)
|
if (!reset_mask)
|
||||||
r600_set_bios_scratch_engine_hung(rdev, false);
|
r600_set_bios_scratch_engine_hung(rdev, false);
|
||||||
|
|
||||||
|
|||||||
@@ -724,6 +724,17 @@
|
|||||||
|
|
||||||
#define ATC_MISC_CG 0x3350
|
#define ATC_MISC_CG 0x3350
|
||||||
|
|
||||||
|
#define GMCON_RENG_EXECUTE 0x3508
|
||||||
|
#define RENG_EXECUTE_ON_PWR_UP (1 << 0)
|
||||||
|
#define GMCON_MISC 0x350c
|
||||||
|
#define RENG_EXECUTE_ON_REG_UPDATE (1 << 11)
|
||||||
|
#define STCTRL_STUTTER_EN (1 << 16)
|
||||||
|
|
||||||
|
#define GMCON_PGFSM_CONFIG 0x3538
|
||||||
|
#define GMCON_PGFSM_WRITE 0x353c
|
||||||
|
#define GMCON_PGFSM_READ 0x3540
|
||||||
|
#define GMCON_MISC3 0x3544
|
||||||
|
|
||||||
#define MC_SEQ_CNTL_3 0x3600
|
#define MC_SEQ_CNTL_3 0x3600
|
||||||
# define CAC_EN (1 << 31)
|
# define CAC_EN (1 << 31)
|
||||||
#define MC_SEQ_G5PDX_CTRL 0x3604
|
#define MC_SEQ_G5PDX_CTRL 0x3604
|
||||||
|
|||||||
Reference in New Issue
Block a user