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

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

drm/radeon/kms: Schedule host path read cache flush through the ring V2



R300 family will hard lockup if host path read cache flush is
done through MMIO to HOST_PATH_CNTL. But scheduling same flush
through ring seems harmless. This patch remove the hdp_flush
callback and add a flush after each fence emission which means
a flush after each IB schedule. Thus we should have same behavior
without the hard lockup.

Tested on R100,R200,R300,R400,R500,R600,R700 family.

V2: Adjust fence counts in r600_blit_prepare_copy()

Signed-off-by: default avatarJerome Glisse <jglisse@redhat.com>
Reviewed-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 62cdc0c2
Loading
Loading
Loading
Loading
+6 −8
Original line number Diff line number Diff line
@@ -356,6 +356,11 @@ void r100_fence_ring_emit(struct radeon_device *rdev,
	/* Wait until IDLE & CLEAN */
	radeon_ring_write(rdev, PACKET0(0x1720, 0));
	radeon_ring_write(rdev, (1 << 16) | (1 << 17));
	radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
	radeon_ring_write(rdev, rdev->config.r100.hdp_cntl |
				RADEON_HDP_READ_BUFFER_INVALIDATE);
	radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
	radeon_ring_write(rdev, rdev->config.r100.hdp_cntl);
	/* Emit fence sequence & fire IRQ */
	radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0));
	radeon_ring_write(rdev, fence->seq);
@@ -1713,14 +1718,6 @@ void r100_gpu_init(struct radeon_device *rdev)
	r100_hdp_reset(rdev);
}

void r100_hdp_flush(struct radeon_device *rdev)
{
	u32 tmp;
	tmp = RREG32(RADEON_HOST_PATH_CNTL);
	tmp |= RADEON_HDP_READ_BUFFER_INVALIDATE;
	WREG32(RADEON_HOST_PATH_CNTL, tmp);
}

void r100_hdp_reset(struct radeon_device *rdev)
{
	uint32_t tmp;
@@ -3313,6 +3310,7 @@ static int r100_startup(struct radeon_device *rdev)
	}
	/* Enable IRQ */
	r100_irq_set(rdev);
	rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
	/* 1M ring buffer */
	r = r100_cp_init(rdev, 1024 * 1024);
	if (r) {
+15 −1
Original line number Diff line number Diff line
@@ -36,7 +36,15 @@
#include "rv350d.h"
#include "r300_reg_safe.h"

/* This files gather functions specifics to: r300,r350,rv350,rv370,rv380 */
/* This files gather functions specifics to: r300,r350,rv350,rv370,rv380
 *
 * GPU Errata:
 * - HOST_PATH_CNTL: r300 family seems to dislike write to HOST_PATH_CNTL
 *   using MMIO to flush host path read cache, this lead to HARDLOCKUP.
 *   However, scheduling such write to the ring seems harmless, i suspect
 *   the CP read collide with the flush somehow, or maybe the MC, hard to
 *   tell. (Jerome Glisse)
 */

/*
 * rv370,rv380 PCIE GART
@@ -178,6 +186,11 @@ void r300_fence_ring_emit(struct radeon_device *rdev,
	/* Wait until IDLE & CLEAN */
	radeon_ring_write(rdev, PACKET0(0x1720, 0));
	radeon_ring_write(rdev, (1 << 17) | (1 << 16)  | (1 << 9));
	radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
	radeon_ring_write(rdev, rdev->config.r300.hdp_cntl |
				RADEON_HDP_READ_BUFFER_INVALIDATE);
	radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
	radeon_ring_write(rdev, rdev->config.r300.hdp_cntl);
	/* Emit fence sequence & fire IRQ */
	radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0));
	radeon_ring_write(rdev, fence->seq);
@@ -1258,6 +1271,7 @@ static int r300_startup(struct radeon_device *rdev)
	}
	/* Enable IRQ */
	r100_irq_set(rdev);
	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
	/* 1M ring buffer */
	r = r100_cp_init(rdev, 1024 * 1024);
	if (r) {
+1 −0
Original line number Diff line number Diff line
@@ -219,6 +219,7 @@ static int r420_startup(struct radeon_device *rdev)
	r420_pipes_init(rdev);
	/* Enable IRQ */
	r100_irq_set(rdev);
	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
	/* 1M ring buffer */
	r = r100_cp_init(rdev, 1024 * 1024);
	if (r) {
+1 −0
Original line number Diff line number Diff line
@@ -186,6 +186,7 @@ static int r520_startup(struct radeon_device *rdev)
	}
	/* Enable IRQ */
	rs600_irq_set(rdev);
	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
	/* 1M ring buffer */
	r = r100_cp_init(rdev, 1024 * 1024);
	if (r) {
+2 −5
Original line number Diff line number Diff line
@@ -1388,11 +1388,6 @@ void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v)
	(void)RREG32(PCIE_PORT_DATA);
}

void r600_hdp_flush(struct radeon_device *rdev)
{
	WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
}

/*
 * CP & Ring
 */
@@ -1789,6 +1784,8 @@ void r600_fence_ring_emit(struct radeon_device *rdev,
	radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
	radeon_ring_write(rdev, ((rdev->fence_drv.scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2));
	radeon_ring_write(rdev, fence->seq);
	radeon_ring_write(rdev, PACKET0(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0));
	radeon_ring_write(rdev, 1);
	/* CP_INTERRUPT packet 3 no longer exists, use packet 0 */
	radeon_ring_write(rdev, PACKET0(CP_INT_STATUS, 0));
	radeon_ring_write(rdev, RB_INT_STAT);
Loading