Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 90aca4d2 authored by Jerome Glisse's avatar Jerome Glisse Committed by Dave Airlie
Browse files

drm/radeon/kms: simplify & improve GPU reset V2



This simplify and improve GPU reset for R1XX-R6XX hw, it's
not 100% reliable here are result:
- R1XX/R2XX works bunch of time in a row, sometimes it
  seems it can work indifinitly
- R3XX/R3XX the most unreliable one, sometimes you will be
  able to reset few times, sometimes not even once
- R5XX more reliable than previous hw, seems to work most
  of the times but once in a while it fails for no obvious
  reasons (same status than previous reset just no same
  happy ending)
- R6XX/R7XX are lot more reliable with this patch, still
  it seems that it can fail after a bunch (reset every
  2sec for 3hour bring down the GPU & computer)

This have been tested on various hw, for some odd reasons
i wasn't able to lockup RS480/RS690 (while they use to
love locking up).

Note that on R1XX-R5XX the cursor will disapear after
lockup haven't checked why, switch to console and back
to X will restore cursor.

Next step is to record the bogus command that leaded to
the lockup.

V2 Fix r6xx resume path to avoid reinitializing blit
module, use the gpu_lockup boolean to avoid entering
inifinite waiting loop on fence while reiniting the GPU

Signed-off-by: default avatarJerome Glisse <jglisse@redhat.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent a2d07b74
Loading
Loading
Loading
Loading
+64 −116
Original line number Original line Diff line number Diff line
@@ -662,26 +662,6 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
	if (r100_debugfs_cp_init(rdev)) {
	if (r100_debugfs_cp_init(rdev)) {
		DRM_ERROR("Failed to register debugfs file for CP !\n");
		DRM_ERROR("Failed to register debugfs file for CP !\n");
	}
	}
	/* Reset CP */
	tmp = RREG32(RADEON_CP_CSQ_STAT);
	if ((tmp & (1 << 31))) {
		DRM_INFO("radeon: cp busy (0x%08X) resetting\n", tmp);
		WREG32(RADEON_CP_CSQ_MODE, 0);
		WREG32(RADEON_CP_CSQ_CNTL, 0);
		WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_CP);
		tmp = RREG32(RADEON_RBBM_SOFT_RESET);
		mdelay(2);
		WREG32(RADEON_RBBM_SOFT_RESET, 0);
		tmp = RREG32(RADEON_RBBM_SOFT_RESET);
		mdelay(2);
		tmp = RREG32(RADEON_CP_CSQ_STAT);
		if ((tmp & (1 << 31))) {
			DRM_INFO("radeon: cp reset failed (0x%08X)\n", tmp);
		}
	} else {
		DRM_INFO("radeon: cp idle (0x%08X)\n", tmp);
	}

	if (!rdev->me_fw) {
	if (!rdev->me_fw) {
		r = r100_cp_init_microcode(rdev);
		r = r100_cp_init_microcode(rdev);
		if (r) {
		if (r) {
@@ -786,39 +766,6 @@ void r100_cp_disable(struct radeon_device *rdev)
	}
	}
}
}


int r100_cp_reset(struct radeon_device *rdev)
{
	uint32_t tmp;
	bool reinit_cp;
	int i;

	reinit_cp = rdev->cp.ready;
	rdev->cp.ready = false;
	WREG32(RADEON_CP_CSQ_MODE, 0);
	WREG32(RADEON_CP_CSQ_CNTL, 0);
	WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_CP);
	(void)RREG32(RADEON_RBBM_SOFT_RESET);
	udelay(200);
	WREG32(RADEON_RBBM_SOFT_RESET, 0);
	/* Wait to prevent race in RBBM_STATUS */
	mdelay(1);
	for (i = 0; i < rdev->usec_timeout; i++) {
		tmp = RREG32(RADEON_RBBM_STATUS);
		if (!(tmp & (1 << 16))) {
			DRM_INFO("CP reset succeed (RBBM_STATUS=0x%08X)\n",
				 tmp);
			if (reinit_cp) {
				return r100_cp_init(rdev, rdev->cp.ring_size);
			}
			return 0;
		}
		DRM_UDELAY(1);
	}
	tmp = RREG32(RADEON_RBBM_STATUS);
	DRM_ERROR("Failed to reset CP (RBBM_STATUS=0x%08X)!\n", tmp);
	return -1;
}

void r100_cp_commit(struct radeon_device *rdev)
void r100_cp_commit(struct radeon_device *rdev)
{
{
	WREG32(RADEON_CP_RB_WPTR, rdev->cp.wptr);
	WREG32(RADEON_CP_RB_WPTR, rdev->cp.wptr);
@@ -1732,51 +1679,6 @@ int r100_mc_wait_for_idle(struct radeon_device *rdev)
	return -1;
	return -1;
}
}


void r100_gpu_init(struct radeon_device *rdev)
{
	/* TODO: anythings to do here ? pipes ? */
	r100_hdp_reset(rdev);
}

void r100_hdp_reset(struct radeon_device *rdev)
{
	uint32_t tmp;

	tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL;
	tmp |= (7 << 28);
	WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE);
	(void)RREG32(RADEON_HOST_PATH_CNTL);
	udelay(200);
	WREG32(RADEON_RBBM_SOFT_RESET, 0);
	WREG32(RADEON_HOST_PATH_CNTL, tmp);
	(void)RREG32(RADEON_HOST_PATH_CNTL);
}

int r100_rb2d_reset(struct radeon_device *rdev)
{
	uint32_t tmp;
	int i;

	WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_E2);
	(void)RREG32(RADEON_RBBM_SOFT_RESET);
	udelay(200);
	WREG32(RADEON_RBBM_SOFT_RESET, 0);
	/* Wait to prevent race in RBBM_STATUS */
	mdelay(1);
	for (i = 0; i < rdev->usec_timeout; i++) {
		tmp = RREG32(RADEON_RBBM_STATUS);
		if (!(tmp & (1 << 26))) {
			DRM_INFO("RB2D reset succeed (RBBM_STATUS=0x%08X)\n",
				 tmp);
			return 0;
		}
		DRM_UDELAY(1);
	}
	tmp = RREG32(RADEON_RBBM_STATUS);
	DRM_ERROR("Failed to reset RB2D (RBBM_STATUS=0x%08X)!\n", tmp);
	return -1;
}

void r100_gpu_lockup_update(struct r100_gpu_lockup *lockup, struct radeon_cp *cp)
void r100_gpu_lockup_update(struct r100_gpu_lockup *lockup, struct radeon_cp *cp)
{
{
	lockup->last_cp_rptr = cp->rptr;
	lockup->last_cp_rptr = cp->rptr;
@@ -1863,31 +1765,77 @@ bool r100_gpu_is_lockup(struct radeon_device *rdev)
	return r100_gpu_cp_is_lockup(rdev, &rdev->config.r100.lockup, &rdev->cp);
	return r100_gpu_cp_is_lockup(rdev, &rdev->config.r100.lockup, &rdev->cp);
}
}


void r100_bm_disable(struct radeon_device *rdev)
{
	u32 tmp;

	/* disable bus mastering */
	tmp = RREG32(R_000030_BUS_CNTL);
	WREG32(R_000030_BUS_CNTL, (tmp & 0xFFFFFFFF) | 0x00000044);
	mdelay(1);
	WREG32(R_000030_BUS_CNTL, (tmp & 0xFFFFFFFF) | 0x00000042);
	mdelay(1);
	WREG32(R_000030_BUS_CNTL, (tmp & 0xFFFFFFFF) | 0x00000040);
	tmp = RREG32(RADEON_BUS_CNTL);
	mdelay(1);
	pci_read_config_word(rdev->pdev, 0x4, (u16*)&tmp);
	pci_write_config_word(rdev->pdev, 0x4, tmp & 0xFFFB);
	mdelay(1);
}

int r100_asic_reset(struct radeon_device *rdev)
int r100_asic_reset(struct radeon_device *rdev)
{
{
	uint32_t status;
	struct r100_mc_save save;
	u32 status, tmp;


	/* reset order likely matter */
	r100_mc_stop(rdev, &save);
	status = RREG32(RADEON_RBBM_STATUS);
	status = RREG32(R_000E40_RBBM_STATUS);
	/* reset HDP */
	if (!G_000E40_GUI_ACTIVE(status)) {
	r100_hdp_reset(rdev);
		return 0;
	/* reset rb2d */
	if (status & ((1 << 17) | (1 << 18) | (1 << 27))) {
		r100_rb2d_reset(rdev);
	}
	}
	/* TODO: reset 3D engine */
	status = RREG32(R_000E40_RBBM_STATUS);
	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
	/* stop CP */
	WREG32(RADEON_CP_CSQ_CNTL, 0);
	tmp = RREG32(RADEON_CP_RB_CNTL);
	WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA);
	WREG32(RADEON_CP_RB_RPTR_WR, 0);
	WREG32(RADEON_CP_RB_WPTR, 0);
	WREG32(RADEON_CP_RB_CNTL, tmp);
	/* save PCI state */
	pci_save_state(rdev->pdev);
	/* disable bus mastering */
	r100_bm_disable(rdev);
	WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_SE(1) |
					S_0000F0_SOFT_RESET_RE(1) |
					S_0000F0_SOFT_RESET_PP(1) |
					S_0000F0_SOFT_RESET_RB(1));
	RREG32(R_0000F0_RBBM_SOFT_RESET);
	mdelay(500);
	WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
	mdelay(1);
	status = RREG32(R_000E40_RBBM_STATUS);
	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
	/* reset CP */
	/* reset CP */
	status = RREG32(RADEON_RBBM_STATUS);
	WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_CP(1));
	if (status & (1 << 16)) {
	RREG32(R_0000F0_RBBM_SOFT_RESET);
		r100_cp_reset(rdev);
	mdelay(500);
	}
	WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
	mdelay(1);
	status = RREG32(R_000E40_RBBM_STATUS);
	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
	/* restore PCI & busmastering */
	pci_restore_state(rdev->pdev);
	r100_enable_bm(rdev);
	/* Check if GPU is idle */
	/* Check if GPU is idle */
	status = RREG32(RADEON_RBBM_STATUS);
	if (G_000E40_SE_BUSY(status) || G_000E40_RE_BUSY(status) ||
	if (status & RADEON_RBBM_ACTIVE) {
		G_000E40_TAM_BUSY(status) || G_000E40_PB_BUSY(status)) {
		DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status);
		dev_err(rdev->dev, "failed to reset GPU\n");
		rdev->gpu_lockup = true;
		return -1;
		return -1;
	}
	}
	DRM_INFO("GPU reset succeed (RBBM_STATUS=0x%08X)\n", status);
	r100_mc_resume(rdev, &save);
	dev_info(rdev->dev, "GPU reset succeed\n");
	return 0;
	return 0;
}
}


@@ -3475,7 +3423,7 @@ static int r100_startup(struct radeon_device *rdev)
	/* Resume clock */
	/* Resume clock */
	r100_clock_startup(rdev);
	r100_clock_startup(rdev);
	/* Initialize GPU configuration (# pipes, ...) */
	/* Initialize GPU configuration (# pipes, ...) */
	r100_gpu_init(rdev);
//	r100_gpu_init(rdev);
	/* Initialize GART (initialize after TTM so we can allocate
	/* Initialize GART (initialize after TTM so we can allocate
	 * memory through TTM but finalize after TTM) */
	 * memory through TTM but finalize after TTM) */
	r100_enable_bm(rdev);
	r100_enable_bm(rdev);
+128 −0
Original line number Original line Diff line number Diff line
@@ -74,6 +74,134 @@
#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)


/* Registers */
/* Registers */
#define R_0000F0_RBBM_SOFT_RESET                     0x0000F0
#define   S_0000F0_SOFT_RESET_CP(x)                    (((x) & 0x1) << 0)
#define   G_0000F0_SOFT_RESET_CP(x)                    (((x) >> 0) & 0x1)
#define   C_0000F0_SOFT_RESET_CP                       0xFFFFFFFE
#define   S_0000F0_SOFT_RESET_HI(x)                    (((x) & 0x1) << 1)
#define   G_0000F0_SOFT_RESET_HI(x)                    (((x) >> 1) & 0x1)
#define   C_0000F0_SOFT_RESET_HI                       0xFFFFFFFD
#define   S_0000F0_SOFT_RESET_SE(x)                    (((x) & 0x1) << 2)
#define   G_0000F0_SOFT_RESET_SE(x)                    (((x) >> 2) & 0x1)
#define   C_0000F0_SOFT_RESET_SE                       0xFFFFFFFB
#define   S_0000F0_SOFT_RESET_RE(x)                    (((x) & 0x1) << 3)
#define   G_0000F0_SOFT_RESET_RE(x)                    (((x) >> 3) & 0x1)
#define   C_0000F0_SOFT_RESET_RE                       0xFFFFFFF7
#define   S_0000F0_SOFT_RESET_PP(x)                    (((x) & 0x1) << 4)
#define   G_0000F0_SOFT_RESET_PP(x)                    (((x) >> 4) & 0x1)
#define   C_0000F0_SOFT_RESET_PP                       0xFFFFFFEF
#define   S_0000F0_SOFT_RESET_E2(x)                    (((x) & 0x1) << 5)
#define   G_0000F0_SOFT_RESET_E2(x)                    (((x) >> 5) & 0x1)
#define   C_0000F0_SOFT_RESET_E2                       0xFFFFFFDF
#define   S_0000F0_SOFT_RESET_RB(x)                    (((x) & 0x1) << 6)
#define   G_0000F0_SOFT_RESET_RB(x)                    (((x) >> 6) & 0x1)
#define   C_0000F0_SOFT_RESET_RB                       0xFFFFFFBF
#define   S_0000F0_SOFT_RESET_HDP(x)                   (((x) & 0x1) << 7)
#define   G_0000F0_SOFT_RESET_HDP(x)                   (((x) >> 7) & 0x1)
#define   C_0000F0_SOFT_RESET_HDP                      0xFFFFFF7F
#define   S_0000F0_SOFT_RESET_MC(x)                    (((x) & 0x1) << 8)
#define   G_0000F0_SOFT_RESET_MC(x)                    (((x) >> 8) & 0x1)
#define   C_0000F0_SOFT_RESET_MC                       0xFFFFFEFF
#define   S_0000F0_SOFT_RESET_AIC(x)                   (((x) & 0x1) << 9)
#define   G_0000F0_SOFT_RESET_AIC(x)                   (((x) >> 9) & 0x1)
#define   C_0000F0_SOFT_RESET_AIC                      0xFFFFFDFF
#define   S_0000F0_SOFT_RESET_VIP(x)                   (((x) & 0x1) << 10)
#define   G_0000F0_SOFT_RESET_VIP(x)                   (((x) >> 10) & 0x1)
#define   C_0000F0_SOFT_RESET_VIP                      0xFFFFFBFF
#define   S_0000F0_SOFT_RESET_DISP(x)                  (((x) & 0x1) << 11)
#define   G_0000F0_SOFT_RESET_DISP(x)                  (((x) >> 11) & 0x1)
#define   C_0000F0_SOFT_RESET_DISP                     0xFFFFF7FF
#define   S_0000F0_SOFT_RESET_CG(x)                    (((x) & 0x1) << 12)
#define   G_0000F0_SOFT_RESET_CG(x)                    (((x) >> 12) & 0x1)
#define   C_0000F0_SOFT_RESET_CG                       0xFFFFEFFF
#define R_000030_BUS_CNTL                            0x000030
#define   S_000030_BUS_DBL_RESYNC(x)                   (((x) & 0x1) << 0)
#define   G_000030_BUS_DBL_RESYNC(x)                   (((x) >> 0) & 0x1)
#define   C_000030_BUS_DBL_RESYNC                      0xFFFFFFFE
#define   S_000030_BUS_MSTR_RESET(x)                   (((x) & 0x1) << 1)
#define   G_000030_BUS_MSTR_RESET(x)                   (((x) >> 1) & 0x1)
#define   C_000030_BUS_MSTR_RESET                      0xFFFFFFFD
#define   S_000030_BUS_FLUSH_BUF(x)                    (((x) & 0x1) << 2)
#define   G_000030_BUS_FLUSH_BUF(x)                    (((x) >> 2) & 0x1)
#define   C_000030_BUS_FLUSH_BUF                       0xFFFFFFFB
#define   S_000030_BUS_STOP_REQ_DIS(x)                 (((x) & 0x1) << 3)
#define   G_000030_BUS_STOP_REQ_DIS(x)                 (((x) >> 3) & 0x1)
#define   C_000030_BUS_STOP_REQ_DIS                    0xFFFFFFF7
#define   S_000030_BUS_PM4_READ_COMBINE_EN(x)          (((x) & 0x1) << 4)
#define   G_000030_BUS_PM4_READ_COMBINE_EN(x)          (((x) >> 4) & 0x1)
#define   C_000030_BUS_PM4_READ_COMBINE_EN             0xFFFFFFEF
#define   S_000030_BUS_WRT_COMBINE_EN(x)               (((x) & 0x1) << 5)
#define   G_000030_BUS_WRT_COMBINE_EN(x)               (((x) >> 5) & 0x1)
#define   C_000030_BUS_WRT_COMBINE_EN                  0xFFFFFFDF
#define   S_000030_BUS_MASTER_DIS(x)                   (((x) & 0x1) << 6)
#define   G_000030_BUS_MASTER_DIS(x)                   (((x) >> 6) & 0x1)
#define   C_000030_BUS_MASTER_DIS                      0xFFFFFFBF
#define   S_000030_BIOS_ROM_WRT_EN(x)                  (((x) & 0x1) << 7)
#define   G_000030_BIOS_ROM_WRT_EN(x)                  (((x) >> 7) & 0x1)
#define   C_000030_BIOS_ROM_WRT_EN                     0xFFFFFF7F
#define   S_000030_BM_DAC_CRIPPLE(x)                   (((x) & 0x1) << 8)
#define   G_000030_BM_DAC_CRIPPLE(x)                   (((x) >> 8) & 0x1)
#define   C_000030_BM_DAC_CRIPPLE                      0xFFFFFEFF
#define   S_000030_BUS_NON_PM4_READ_COMBINE_EN(x)      (((x) & 0x1) << 9)
#define   G_000030_BUS_NON_PM4_READ_COMBINE_EN(x)      (((x) >> 9) & 0x1)
#define   C_000030_BUS_NON_PM4_READ_COMBINE_EN         0xFFFFFDFF
#define   S_000030_BUS_XFERD_DISCARD_EN(x)             (((x) & 0x1) << 10)
#define   G_000030_BUS_XFERD_DISCARD_EN(x)             (((x) >> 10) & 0x1)
#define   C_000030_BUS_XFERD_DISCARD_EN                0xFFFFFBFF
#define   S_000030_BUS_SGL_READ_DISABLE(x)             (((x) & 0x1) << 11)
#define   G_000030_BUS_SGL_READ_DISABLE(x)             (((x) >> 11) & 0x1)
#define   C_000030_BUS_SGL_READ_DISABLE                0xFFFFF7FF
#define   S_000030_BIOS_DIS_ROM(x)                     (((x) & 0x1) << 12)
#define   G_000030_BIOS_DIS_ROM(x)                     (((x) >> 12) & 0x1)
#define   C_000030_BIOS_DIS_ROM                        0xFFFFEFFF
#define   S_000030_BUS_PCI_READ_RETRY_EN(x)            (((x) & 0x1) << 13)
#define   G_000030_BUS_PCI_READ_RETRY_EN(x)            (((x) >> 13) & 0x1)
#define   C_000030_BUS_PCI_READ_RETRY_EN               0xFFFFDFFF
#define   S_000030_BUS_AGP_AD_STEPPING_EN(x)           (((x) & 0x1) << 14)
#define   G_000030_BUS_AGP_AD_STEPPING_EN(x)           (((x) >> 14) & 0x1)
#define   C_000030_BUS_AGP_AD_STEPPING_EN              0xFFFFBFFF
#define   S_000030_BUS_PCI_WRT_RETRY_EN(x)             (((x) & 0x1) << 15)
#define   G_000030_BUS_PCI_WRT_RETRY_EN(x)             (((x) >> 15) & 0x1)
#define   C_000030_BUS_PCI_WRT_RETRY_EN                0xFFFF7FFF
#define   S_000030_BUS_RETRY_WS(x)                     (((x) & 0xF) << 16)
#define   G_000030_BUS_RETRY_WS(x)                     (((x) >> 16) & 0xF)
#define   C_000030_BUS_RETRY_WS                        0xFFF0FFFF
#define   S_000030_BUS_MSTR_RD_MULT(x)                 (((x) & 0x1) << 20)
#define   G_000030_BUS_MSTR_RD_MULT(x)                 (((x) >> 20) & 0x1)
#define   C_000030_BUS_MSTR_RD_MULT                    0xFFEFFFFF
#define   S_000030_BUS_MSTR_RD_LINE(x)                 (((x) & 0x1) << 21)
#define   G_000030_BUS_MSTR_RD_LINE(x)                 (((x) >> 21) & 0x1)
#define   C_000030_BUS_MSTR_RD_LINE                    0xFFDFFFFF
#define   S_000030_BUS_SUSPEND(x)                      (((x) & 0x1) << 22)
#define   G_000030_BUS_SUSPEND(x)                      (((x) >> 22) & 0x1)
#define   C_000030_BUS_SUSPEND                         0xFFBFFFFF
#define   S_000030_LAT_16X(x)                          (((x) & 0x1) << 23)
#define   G_000030_LAT_16X(x)                          (((x) >> 23) & 0x1)
#define   C_000030_LAT_16X                             0xFF7FFFFF
#define   S_000030_BUS_RD_DISCARD_EN(x)                (((x) & 0x1) << 24)
#define   G_000030_BUS_RD_DISCARD_EN(x)                (((x) >> 24) & 0x1)
#define   C_000030_BUS_RD_DISCARD_EN                   0xFEFFFFFF
#define   S_000030_ENFRCWRDY(x)                        (((x) & 0x1) << 25)
#define   G_000030_ENFRCWRDY(x)                        (((x) >> 25) & 0x1)
#define   C_000030_ENFRCWRDY                           0xFDFFFFFF
#define   S_000030_BUS_MSTR_WS(x)                      (((x) & 0x1) << 26)
#define   G_000030_BUS_MSTR_WS(x)                      (((x) >> 26) & 0x1)
#define   C_000030_BUS_MSTR_WS                         0xFBFFFFFF
#define   S_000030_BUS_PARKING_DIS(x)                  (((x) & 0x1) << 27)
#define   G_000030_BUS_PARKING_DIS(x)                  (((x) >> 27) & 0x1)
#define   C_000030_BUS_PARKING_DIS                     0xF7FFFFFF
#define   S_000030_BUS_MSTR_DISCONNECT_EN(x)           (((x) & 0x1) << 28)
#define   G_000030_BUS_MSTR_DISCONNECT_EN(x)           (((x) >> 28) & 0x1)
#define   C_000030_BUS_MSTR_DISCONNECT_EN              0xEFFFFFFF
#define   S_000030_SERR_EN(x)                          (((x) & 0x1) << 29)
#define   G_000030_SERR_EN(x)                          (((x) >> 29) & 0x1)
#define   C_000030_SERR_EN                             0xDFFFFFFF
#define   S_000030_BUS_READ_BURST(x)                   (((x) & 0x1) << 30)
#define   G_000030_BUS_READ_BURST(x)                   (((x) >> 30) & 0x1)
#define   C_000030_BUS_READ_BURST                      0xBFFFFFFF
#define   S_000030_BUS_RDY_READ_DLY(x)                 (((x) & 0x1) << 31)
#define   G_000030_BUS_RDY_READ_DLY(x)                 (((x) >> 31) & 0x1)
#define   C_000030_BUS_RDY_READ_DLY                    0x7FFFFFFF
#define R_000040_GEN_INT_CNTL                        0x000040
#define R_000040_GEN_INT_CNTL                        0x000040
#define   S_000040_CRTC_VBLANK(x)                      (((x) & 0x1) << 0)
#define   S_000040_CRTC_VBLANK(x)                      (((x) & 0x1) << 0)
#define   G_000040_CRTC_VBLANK(x)                      (((x) >> 0) & 0x1)
#define   G_000040_CRTC_VBLANK(x)                      (((x) >> 0) & 0x1)
+59 −75
Original line number Original line Diff line number Diff line
@@ -151,6 +151,10 @@ void rv370_pcie_gart_disable(struct radeon_device *rdev)
	u32 tmp;
	u32 tmp;
	int r;
	int r;


	WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, 0);
	WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, 0);
	WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0);
	WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0);
	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
	tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
	tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
	WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN);
	WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN);
@@ -323,7 +327,6 @@ void r300_gpu_init(struct radeon_device *rdev)
{
{
	uint32_t gb_tile_config, tmp;
	uint32_t gb_tile_config, tmp;


	r100_hdp_reset(rdev);
	/* FIXME: rv380 one pipes ? */
	/* FIXME: rv380 one pipes ? */
	if ((rdev->family == CHIP_R300 && rdev->pdev->device != 0x4144) ||
	if ((rdev->family == CHIP_R300 && rdev->pdev->device != 0x4144) ||
	    (rdev->family == CHIP_R350)) {
	    (rdev->family == CHIP_R350)) {
@@ -376,57 +379,6 @@ void r300_gpu_init(struct radeon_device *rdev)
		 rdev->num_gb_pipes, rdev->num_z_pipes);
		 rdev->num_gb_pipes, rdev->num_z_pipes);
}
}


int r300_ga_reset(struct radeon_device *rdev)
{
	uint32_t tmp;
	bool reinit_cp;
	int i;

	reinit_cp = rdev->cp.ready;
	rdev->cp.ready = false;
	for (i = 0; i < rdev->usec_timeout; i++) {
		WREG32(RADEON_CP_CSQ_MODE, 0);
		WREG32(RADEON_CP_CSQ_CNTL, 0);
		WREG32(RADEON_RBBM_SOFT_RESET, 0x32005);
		(void)RREG32(RADEON_RBBM_SOFT_RESET);
		udelay(200);
		WREG32(RADEON_RBBM_SOFT_RESET, 0);
		/* Wait to prevent race in RBBM_STATUS */
		mdelay(1);
		tmp = RREG32(RADEON_RBBM_STATUS);
		if (tmp & ((1 << 20) | (1 << 26))) {
			DRM_ERROR("VAP & CP still busy (RBBM_STATUS=0x%08X)", tmp);
			/* GA still busy soft reset it */
			WREG32(0x429C, 0x200);
			WREG32(R300_VAP_PVS_STATE_FLUSH_REG, 0);
			WREG32(R300_RE_SCISSORS_TL, 0);
			WREG32(R300_RE_SCISSORS_BR, 0);
			WREG32(0x24AC, 0);
		}
		/* Wait to prevent race in RBBM_STATUS */
		mdelay(1);
		tmp = RREG32(RADEON_RBBM_STATUS);
		if (!(tmp & ((1 << 20) | (1 << 26)))) {
			break;
		}
	}
	for (i = 0; i < rdev->usec_timeout; i++) {
		tmp = RREG32(RADEON_RBBM_STATUS);
		if (!(tmp & ((1 << 20) | (1 << 26)))) {
			DRM_INFO("GA reset succeed (RBBM_STATUS=0x%08X)\n",
				 tmp);
			if (reinit_cp) {
				return r100_cp_init(rdev, rdev->cp.ring_size);
			}
			return 0;
		}
		DRM_UDELAY(1);
	}
	tmp = RREG32(RADEON_RBBM_STATUS);
	DRM_ERROR("Failed to reset GA ! (RBBM_STATUS=0x%08X)\n", tmp);
	return -1;
}

bool r300_gpu_is_lockup(struct radeon_device *rdev)
bool r300_gpu_is_lockup(struct radeon_device *rdev)
{
{
	u32 rbbm_status;
	u32 rbbm_status;
@@ -451,37 +403,69 @@ bool r300_gpu_is_lockup(struct radeon_device *rdev)


int r300_asic_reset(struct radeon_device *rdev)
int r300_asic_reset(struct radeon_device *rdev)
{
{
	uint32_t status;
	struct r100_mc_save save;
	u32 status, tmp;


	/* reset order likely matter */
	r100_mc_stop(rdev, &save);
	status = RREG32(RADEON_RBBM_STATUS);
	status = RREG32(R_000E40_RBBM_STATUS);
	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
	if (!G_000E40_GUI_ACTIVE(status)) {
	/* reset HDP */
		return 0;
	r100_hdp_reset(rdev);
	/* reset rb2d */
	if (status & ((1 << 17) | (1 << 18) | (1 << 27))) {
		r100_rb2d_reset(rdev);
	}
	/* reset GA */
	if (status & ((1 << 20) | (1 << 26))) {
		r300_ga_reset(rdev);
	}
	/* reset CP */
	status = RREG32(RADEON_RBBM_STATUS);
	if (status & (1 << 16)) {
		r100_cp_reset(rdev);
	}
	}
	status = RREG32(R_000E40_RBBM_STATUS);
	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
	/* stop CP */
	WREG32(RADEON_CP_CSQ_CNTL, 0);
	tmp = RREG32(RADEON_CP_RB_CNTL);
	WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA);
	WREG32(RADEON_CP_RB_RPTR_WR, 0);
	WREG32(RADEON_CP_RB_WPTR, 0);
	WREG32(RADEON_CP_RB_CNTL, tmp);
	/* save PCI state */
	pci_save_state(rdev->pdev);
	/* disable bus mastering */
	r100_bm_disable(rdev);
	WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_VAP(1) |
					S_0000F0_SOFT_RESET_GA(1));
	RREG32(R_0000F0_RBBM_SOFT_RESET);
	mdelay(500);
	WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
	mdelay(1);
	status = RREG32(R_000E40_RBBM_STATUS);
	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
	/* resetting the CP seems to be problematic sometimes it end up
	 * hard locking the computer, but it's necessary for successfull
	 * reset more test & playing is needed on R3XX/R4XX to find a
	 * reliable (if any solution)
	 */
	WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_CP(1));
	RREG32(R_0000F0_RBBM_SOFT_RESET);
	mdelay(500);
	WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
	mdelay(1);
	status = RREG32(R_000E40_RBBM_STATUS);
	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
	/* reset MC */
	WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_MC(1));
	RREG32(R_0000F0_RBBM_SOFT_RESET);
	mdelay(500);
	WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
	mdelay(1);
	status = RREG32(R_000E40_RBBM_STATUS);
	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
	/* restore PCI & busmastering */
	pci_restore_state(rdev->pdev);
	r100_enable_bm(rdev);
	/* Check if GPU is idle */
	/* Check if GPU is idle */
	status = RREG32(RADEON_RBBM_STATUS);
	if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) {
	if (status & RADEON_RBBM_ACTIVE) {
		dev_err(rdev->dev, "failed to reset GPU\n");
		DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status);
		rdev->gpu_lockup = true;
		return -1;
		return -1;
	}
	}
	DRM_INFO("GPU reset succeed (RBBM_STATUS=0x%08X)\n", status);
	r100_mc_resume(rdev, &save);
	dev_info(rdev->dev, "GPU reset succeed\n");
	return 0;
	return 0;
}
}



/*
/*
 * r300,r350,rv350,rv380 VRAM info
 * r300,r350,rv350,rv380 VRAM info
 */
 */
+46 −1
Original line number Original line Diff line number Diff line
@@ -209,7 +209,52 @@
#define   S_000E40_GUI_ACTIVE(x)                       (((x) & 0x1) << 31)
#define   S_000E40_GUI_ACTIVE(x)                       (((x) & 0x1) << 31)
#define   G_000E40_GUI_ACTIVE(x)                       (((x) >> 31) & 0x1)
#define   G_000E40_GUI_ACTIVE(x)                       (((x) >> 31) & 0x1)
#define   C_000E40_GUI_ACTIVE                          0x7FFFFFFF
#define   C_000E40_GUI_ACTIVE                          0x7FFFFFFF

#define R_0000F0_RBBM_SOFT_RESET                     0x0000F0
#define   S_0000F0_SOFT_RESET_CP(x)                    (((x) & 0x1) << 0)
#define   G_0000F0_SOFT_RESET_CP(x)                    (((x) >> 0) & 0x1)
#define   C_0000F0_SOFT_RESET_CP                       0xFFFFFFFE
#define   S_0000F0_SOFT_RESET_HI(x)                    (((x) & 0x1) << 1)
#define   G_0000F0_SOFT_RESET_HI(x)                    (((x) >> 1) & 0x1)
#define   C_0000F0_SOFT_RESET_HI                       0xFFFFFFFD
#define   S_0000F0_SOFT_RESET_VAP(x)                   (((x) & 0x1) << 2)
#define   G_0000F0_SOFT_RESET_VAP(x)                   (((x) >> 2) & 0x1)
#define   C_0000F0_SOFT_RESET_VAP                      0xFFFFFFFB
#define   S_0000F0_SOFT_RESET_RE(x)                    (((x) & 0x1) << 3)
#define   G_0000F0_SOFT_RESET_RE(x)                    (((x) >> 3) & 0x1)
#define   C_0000F0_SOFT_RESET_RE                       0xFFFFFFF7
#define   S_0000F0_SOFT_RESET_PP(x)                    (((x) & 0x1) << 4)
#define   G_0000F0_SOFT_RESET_PP(x)                    (((x) >> 4) & 0x1)
#define   C_0000F0_SOFT_RESET_PP                       0xFFFFFFEF
#define   S_0000F0_SOFT_RESET_E2(x)                    (((x) & 0x1) << 5)
#define   G_0000F0_SOFT_RESET_E2(x)                    (((x) >> 5) & 0x1)
#define   C_0000F0_SOFT_RESET_E2                       0xFFFFFFDF
#define   S_0000F0_SOFT_RESET_RB(x)                    (((x) & 0x1) << 6)
#define   G_0000F0_SOFT_RESET_RB(x)                    (((x) >> 6) & 0x1)
#define   C_0000F0_SOFT_RESET_RB                       0xFFFFFFBF
#define   S_0000F0_SOFT_RESET_HDP(x)                   (((x) & 0x1) << 7)
#define   G_0000F0_SOFT_RESET_HDP(x)                   (((x) >> 7) & 0x1)
#define   C_0000F0_SOFT_RESET_HDP                      0xFFFFFF7F
#define   S_0000F0_SOFT_RESET_MC(x)                    (((x) & 0x1) << 8)
#define   G_0000F0_SOFT_RESET_MC(x)                    (((x) >> 8) & 0x1)
#define   C_0000F0_SOFT_RESET_MC                       0xFFFFFEFF
#define   S_0000F0_SOFT_RESET_AIC(x)                   (((x) & 0x1) << 9)
#define   G_0000F0_SOFT_RESET_AIC(x)                   (((x) >> 9) & 0x1)
#define   C_0000F0_SOFT_RESET_AIC                      0xFFFFFDFF
#define   S_0000F0_SOFT_RESET_VIP(x)                   (((x) & 0x1) << 10)
#define   G_0000F0_SOFT_RESET_VIP(x)                   (((x) >> 10) & 0x1)
#define   C_0000F0_SOFT_RESET_VIP                      0xFFFFFBFF
#define   S_0000F0_SOFT_RESET_DISP(x)                  (((x) & 0x1) << 11)
#define   G_0000F0_SOFT_RESET_DISP(x)                  (((x) >> 11) & 0x1)
#define   C_0000F0_SOFT_RESET_DISP                     0xFFFFF7FF
#define   S_0000F0_SOFT_RESET_CG(x)                    (((x) & 0x1) << 12)
#define   G_0000F0_SOFT_RESET_CG(x)                    (((x) >> 12) & 0x1)
#define   C_0000F0_SOFT_RESET_CG                       0xFFFFEFFF
#define   S_0000F0_SOFT_RESET_GA(x)                    (((x) & 0x1) << 13)
#define   G_0000F0_SOFT_RESET_GA(x)                    (((x) >> 13) & 0x1)
#define   C_0000F0_SOFT_RESET_GA                       0xFFFFDFFF
#define   S_0000F0_SOFT_RESET_IDCT(x)                  (((x) & 0x1) << 14)
#define   G_0000F0_SOFT_RESET_IDCT(x)                  (((x) >> 14) & 0x1)
#define   C_0000F0_SOFT_RESET_IDCT                     0xFFFFBFFF


#define R_00000D_SCLK_CNTL                           0x00000D
#define R_00000D_SCLK_CNTL                           0x00000D
#define   S_00000D_SCLK_SRC_SEL(x)                     (((x) & 0x7) << 0)
#define   S_00000D_SCLK_SRC_SEL(x)                     (((x) & 0x7) << 0)
+0 −1
Original line number Original line Diff line number Diff line
@@ -53,7 +53,6 @@ static void r520_gpu_init(struct radeon_device *rdev)
{
{
	unsigned pipe_select_current, gb_pipe_select, tmp;
	unsigned pipe_select_current, gb_pipe_select, tmp;


	r100_hdp_reset(rdev);
	rv515_vga_render_disable(rdev);
	rv515_vga_render_disable(rdev);
	/*
	/*
	 * DST_PIPE_CONFIG		0x170C
	 * DST_PIPE_CONFIG		0x170C
Loading