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

Commit 724c80e1 authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie
Browse files

drm/radeon/kms: enable writeback (v2)



When writeback is enabled, the GPU shadows writes to certain
registers into a buffer in memory.  The driver can then read
the values from the shadow rather than reading back from the
register across the bus.  Writeback can be disabled by setting
the no_wb module param to 1.

On r6xx/r7xx/evergreen, the following registers are shadowed:
- CP scratch registers
- CP read pointer
- IH write pointer
On r1xx-rr5xx, the following registers are shadowed:
- CP scratch registers
- CP read pointer

v2:
- Combine wb patches for r6xx-evergreen and r1xx-r5xx
- Writeback is disabled on AGP boards since it tends to be
unreliable on AGP using the gart.
- Check radeon_wb_init return values properly.

Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent b70d6bb3
Loading
Loading
Loading
Loading
+26 −10
Original line number Diff line number Diff line
@@ -731,7 +731,7 @@ int evergreen_cp_resume(struct radeon_device *rdev)

	/* Set ring buffer size */
	rb_bufsz = drm_order(rdev->cp.ring_size / 8);
	tmp = RB_NO_UPDATE | (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
	tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
#ifdef __BIG_ENDIAN
	tmp |= BUF_SWAP_32BIT;
#endif
@@ -745,8 +745,19 @@ int evergreen_cp_resume(struct radeon_device *rdev)
	WREG32(CP_RB_CNTL, tmp | RB_RPTR_WR_ENA);
	WREG32(CP_RB_RPTR_WR, 0);
	WREG32(CP_RB_WPTR, 0);
	WREG32(CP_RB_RPTR_ADDR, rdev->cp.gpu_addr & 0xFFFFFFFF);
	WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->cp.gpu_addr));

	/* set the wb address wether it's enabled or not */
	WREG32(CP_RB_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC);
	WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
	WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);

	if (rdev->wb.enabled)
		WREG32(SCRATCH_UMSK, 0xff);
	else {
		tmp |= RB_NO_UPDATE;
		WREG32(SCRATCH_UMSK, 0);
	}

	mdelay(1);
	WREG32(CP_RB_CNTL, tmp);

@@ -1759,7 +1770,9 @@ static inline u32 evergreen_get_ih_wptr(struct radeon_device *rdev)
{
	u32 wptr, tmp;

	/* XXX use writeback */
	if (rdev->wb.enabled)
		wptr = rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4];
	else
		wptr = RREG32(IH_RB_WPTR);

	if (wptr & RB_OVERFLOW) {
@@ -2068,6 +2081,11 @@ static int evergreen_startup(struct radeon_device *rdev)
	}
#endif

	/* allocate wb buffer */
	r = radeon_wb_init(rdev);
	if (r)
		return r;

	/* Enable IRQ */
	r = r600_irq_init(rdev);
	if (r) {
@@ -2086,8 +2104,6 @@ static int evergreen_startup(struct radeon_device *rdev)
	r = evergreen_cp_resume(rdev);
	if (r)
		return r;
	/* write back buffer are not vital so don't worry about failure */
	r600_wb_enable(rdev);

	return 0;
}
@@ -2128,7 +2144,7 @@ int evergreen_suspend(struct radeon_device *rdev)
	r700_cp_stop(rdev);
	rdev->cp.ready = false;
	evergreen_irq_suspend(rdev);
	r600_wb_disable(rdev);
	radeon_wb_disable(rdev);
	evergreen_pcie_gart_disable(rdev);
#if 0
	/* unpin shaders bo */
@@ -2245,8 +2261,8 @@ int evergreen_init(struct radeon_device *rdev)
	if (r) {
		dev_err(rdev->dev, "disabling GPU acceleration\n");
		r700_cp_fini(rdev);
		r600_wb_fini(rdev);
		r600_irq_fini(rdev);
		radeon_wb_fini(rdev);
		radeon_irq_kms_fini(rdev);
		evergreen_pcie_gart_fini(rdev);
		rdev->accel_working = false;
@@ -2270,8 +2286,8 @@ void evergreen_fini(struct radeon_device *rdev)
{
	/*r600_blit_fini(rdev);*/
	r700_cp_fini(rdev);
	r600_wb_fini(rdev);
	r600_irq_fini(rdev);
	radeon_wb_fini(rdev);
	radeon_irq_kms_fini(rdev);
	evergreen_pcie_gart_fini(rdev);
	radeon_gem_fini(rdev);
+26 −71
Original line number Diff line number Diff line
@@ -675,67 +675,6 @@ void r100_fence_ring_emit(struct radeon_device *rdev,
	radeon_ring_write(rdev, RADEON_SW_INT_FIRE);
}

int r100_wb_init(struct radeon_device *rdev)
{
	int r;

	if (rdev->wb.wb_obj == NULL) {
		r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, true,
					RADEON_GEM_DOMAIN_GTT,
					&rdev->wb.wb_obj);
		if (r) {
			dev_err(rdev->dev, "(%d) create WB buffer failed\n", r);
			return r;
		}
		r = radeon_bo_reserve(rdev->wb.wb_obj, false);
		if (unlikely(r != 0))
			return r;
		r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT,
					&rdev->wb.gpu_addr);
		if (r) {
			dev_err(rdev->dev, "(%d) pin WB buffer failed\n", r);
			radeon_bo_unreserve(rdev->wb.wb_obj);
			return r;
		}
		r = radeon_bo_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb);
		radeon_bo_unreserve(rdev->wb.wb_obj);
		if (r) {
			dev_err(rdev->dev, "(%d) map WB buffer failed\n", r);
			return r;
		}
	}
	WREG32(R_000774_SCRATCH_ADDR, rdev->wb.gpu_addr);
	WREG32(R_00070C_CP_RB_RPTR_ADDR,
		S_00070C_RB_RPTR_ADDR((rdev->wb.gpu_addr + 1024) >> 2));
	WREG32(R_000770_SCRATCH_UMSK, 0xff);
	return 0;
}

void r100_wb_disable(struct radeon_device *rdev)
{
	WREG32(R_000770_SCRATCH_UMSK, 0);
}

void r100_wb_fini(struct radeon_device *rdev)
{
	int r;

	r100_wb_disable(rdev);
	if (rdev->wb.wb_obj) {
		r = radeon_bo_reserve(rdev->wb.wb_obj, false);
		if (unlikely(r != 0)) {
			dev_err(rdev->dev, "(%d) can't finish WB\n", r);
			return;
		}
		radeon_bo_kunmap(rdev->wb.wb_obj);
		radeon_bo_unpin(rdev->wb.wb_obj);
		radeon_bo_unreserve(rdev->wb.wb_obj);
		radeon_bo_unref(&rdev->wb.wb_obj);
		rdev->wb.wb = NULL;
		rdev->wb.wb_obj = NULL;
	}
}

int r100_copy_blit(struct radeon_device *rdev,
		   uint64_t src_offset,
		   uint64_t dst_offset,
@@ -996,20 +935,32 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
	WREG32(0x718, pre_write_timer | (pre_write_limit << 28));
	tmp = (REG_SET(RADEON_RB_BUFSZ, rb_bufsz) |
	       REG_SET(RADEON_RB_BLKSZ, rb_blksz) |
	       REG_SET(RADEON_MAX_FETCH, max_fetch) |
	       RADEON_RB_NO_UPDATE);
	       REG_SET(RADEON_MAX_FETCH, max_fetch));
#ifdef __BIG_ENDIAN
	tmp |= RADEON_BUF_SWAP_32BIT;
#endif
	WREG32(RADEON_CP_RB_CNTL, tmp);
	WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_NO_UPDATE);

	/* Set ring address */
	DRM_INFO("radeon: ring at 0x%016lX\n", (unsigned long)rdev->cp.gpu_addr);
	WREG32(RADEON_CP_RB_BASE, rdev->cp.gpu_addr);
	/* Force read & write ptr to 0 */
	WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA);
	WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA | RADEON_RB_NO_UPDATE);
	WREG32(RADEON_CP_RB_RPTR_WR, 0);
	WREG32(RADEON_CP_RB_WPTR, 0);

	/* set the wb address whether it's enabled or not */
	WREG32(R_00070C_CP_RB_RPTR_ADDR,
		S_00070C_RB_RPTR_ADDR((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) >> 2));
	WREG32(R_000774_SCRATCH_ADDR, rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET);

	if (rdev->wb.enabled)
		WREG32(R_000770_SCRATCH_UMSK, 0xff);
	else {
		tmp |= RADEON_RB_NO_UPDATE;
		WREG32(R_000770_SCRATCH_UMSK, 0);
	}

	WREG32(RADEON_CP_RB_CNTL, tmp);
	udelay(10);
	rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR);
@@ -1050,6 +1001,7 @@ void r100_cp_disable(struct radeon_device *rdev)
	rdev->cp.ready = false;
	WREG32(RADEON_CP_CSQ_MODE, 0);
	WREG32(RADEON_CP_CSQ_CNTL, 0);
	WREG32(R_000770_SCRATCH_UMSK, 0);
	if (r100_gui_wait_for_idle(rdev)) {
		printk(KERN_WARNING "Failed to wait GUI idle while "
		       "programming pipes. Bad things might happen.\n");
@@ -3734,6 +3686,12 @@ static int r100_startup(struct radeon_device *rdev)
		if (r)
			return r;
	}

	/* allocate wb buffer */
	r = radeon_wb_init(rdev);
	if (r)
		return r;

	/* Enable IRQ */
	r100_irq_set(rdev);
	rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
@@ -3743,9 +3701,6 @@ static int r100_startup(struct radeon_device *rdev)
		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
		return r;
	}
	r = r100_wb_init(rdev);
	if (r)
		dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
	r = r100_ib_init(rdev);
	if (r) {
		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
@@ -3779,7 +3734,7 @@ int r100_resume(struct radeon_device *rdev)
int r100_suspend(struct radeon_device *rdev)
{
	r100_cp_disable(rdev);
	r100_wb_disable(rdev);
	radeon_wb_disable(rdev);
	r100_irq_disable(rdev);
	if (rdev->flags & RADEON_IS_PCI)
		r100_pci_gart_disable(rdev);
@@ -3789,7 +3744,7 @@ int r100_suspend(struct radeon_device *rdev)
void r100_fini(struct radeon_device *rdev)
{
	r100_cp_fini(rdev);
	r100_wb_fini(rdev);
	radeon_wb_fini(rdev);
	r100_ib_fini(rdev);
	radeon_gem_fini(rdev);
	if (rdev->flags & RADEON_IS_PCI)
@@ -3902,7 +3857,7 @@ int r100_init(struct radeon_device *rdev)
		/* Somethings want wront with the accel init stop accel */
		dev_err(rdev->dev, "Disabling GPU acceleration\n");
		r100_cp_fini(rdev);
		r100_wb_fini(rdev);
		radeon_wb_fini(rdev);
		r100_ib_fini(rdev);
		radeon_irq_kms_fini(rdev);
		if (rdev->flags & RADEON_IS_PCI)
+9 −6
Original line number Diff line number Diff line
@@ -1332,6 +1332,12 @@ static int r300_startup(struct radeon_device *rdev)
		if (r)
			return r;
	}

	/* allocate wb buffer */
	r = radeon_wb_init(rdev);
	if (r)
		return r;

	/* Enable IRQ */
	r100_irq_set(rdev);
	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
@@ -1341,9 +1347,6 @@ static int r300_startup(struct radeon_device *rdev)
		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
		return r;
	}
	r = r100_wb_init(rdev);
	if (r)
		dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
	r = r100_ib_init(rdev);
	if (r) {
		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
@@ -1379,7 +1382,7 @@ int r300_resume(struct radeon_device *rdev)
int r300_suspend(struct radeon_device *rdev)
{
	r100_cp_disable(rdev);
	r100_wb_disable(rdev);
	radeon_wb_disable(rdev);
	r100_irq_disable(rdev);
	if (rdev->flags & RADEON_IS_PCIE)
		rv370_pcie_gart_disable(rdev);
@@ -1391,7 +1394,7 @@ int r300_suspend(struct radeon_device *rdev)
void r300_fini(struct radeon_device *rdev)
{
	r100_cp_fini(rdev);
	r100_wb_fini(rdev);
	radeon_wb_fini(rdev);
	r100_ib_fini(rdev);
	radeon_gem_fini(rdev);
	if (rdev->flags & RADEON_IS_PCIE)
@@ -1484,7 +1487,7 @@ int r300_init(struct radeon_device *rdev)
		/* Somethings want wront with the accel init stop accel */
		dev_err(rdev->dev, "Disabling GPU acceleration\n");
		r100_cp_fini(rdev);
		r100_wb_fini(rdev);
		radeon_wb_fini(rdev);
		r100_ib_fini(rdev);
		radeon_irq_kms_fini(rdev);
		if (rdev->flags & RADEON_IS_PCIE)
+9 −7
Original line number Diff line number Diff line
@@ -248,6 +248,12 @@ static int r420_startup(struct radeon_device *rdev)
			return r;
	}
	r420_pipes_init(rdev);

	/* allocate wb buffer */
	r = radeon_wb_init(rdev);
	if (r)
		return r;

	/* Enable IRQ */
	r100_irq_set(rdev);
	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
@@ -258,10 +264,6 @@ static int r420_startup(struct radeon_device *rdev)
		return r;
	}
	r420_cp_errata_init(rdev);
	r = r100_wb_init(rdev);
	if (r) {
		dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
	}
	r = r100_ib_init(rdev);
	if (r) {
		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
@@ -302,7 +304,7 @@ int r420_suspend(struct radeon_device *rdev)
{
	r420_cp_errata_fini(rdev);
	r100_cp_disable(rdev);
	r100_wb_disable(rdev);
	radeon_wb_disable(rdev);
	r100_irq_disable(rdev);
	if (rdev->flags & RADEON_IS_PCIE)
		rv370_pcie_gart_disable(rdev);
@@ -314,7 +316,7 @@ int r420_suspend(struct radeon_device *rdev)
void r420_fini(struct radeon_device *rdev)
{
	r100_cp_fini(rdev);
	r100_wb_fini(rdev);
	radeon_wb_fini(rdev);
	r100_ib_fini(rdev);
	radeon_gem_fini(rdev);
	if (rdev->flags & RADEON_IS_PCIE)
@@ -418,7 +420,7 @@ int r420_init(struct radeon_device *rdev)
		/* Somethings want wront with the accel init stop accel */
		dev_err(rdev->dev, "Disabling GPU acceleration\n");
		r100_cp_fini(rdev);
		r100_wb_fini(rdev);
		radeon_wb_fini(rdev);
		r100_ib_fini(rdev);
		radeon_irq_kms_fini(rdev);
		if (rdev->flags & RADEON_IS_PCIE)
+7 −4
Original line number Diff line number Diff line
@@ -181,6 +181,12 @@ static int r520_startup(struct radeon_device *rdev)
		if (r)
			return r;
	}

	/* allocate wb buffer */
	r = radeon_wb_init(rdev);
	if (r)
		return r;

	/* Enable IRQ */
	rs600_irq_set(rdev);
	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
@@ -190,9 +196,6 @@ static int r520_startup(struct radeon_device *rdev)
		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
		return r;
	}
	r = r100_wb_init(rdev);
	if (r)
		dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
	r = r100_ib_init(rdev);
	if (r) {
		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
@@ -295,7 +298,7 @@ int r520_init(struct radeon_device *rdev)
		/* Somethings want wront with the accel init stop accel */
		dev_err(rdev->dev, "Disabling GPU acceleration\n");
		r100_cp_fini(rdev);
		r100_wb_fini(rdev);
		radeon_wb_fini(rdev);
		r100_ib_fini(rdev);
		radeon_irq_kms_fini(rdev);
		rv370_pcie_gart_fini(rdev);
Loading