summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2010-07-26 18:51:53 -0400
committerDave Airlie <airlied@redhat.com>2010-08-02 10:06:18 +1000
commit812d046915f48236657f02c06d7dc47140e9ceda (patch)
tree77a9c724a2316593fa22f7442d5c4a8d00c9af32
parent833ee5c4ab36937a99e63935d7f06bc2c1f9343b (diff)
drm/radeon/kms/r7xx: add workaround for hw issue with HDP flush
Use of HDP_*_COHERENCY_FLUSH_CNTL can cause a hang in certain situations. Add workaround. Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Cc: stable@kernel.org Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/radeon/r600.c24
-rw-r--r--drivers/gpu/drm/radeon/r600d.h1
-rw-r--r--drivers/gpu/drm/radeon/rv770.c5
-rw-r--r--drivers/gpu/drm/radeon/rv770d.h1
4 files changed, 28 insertions, 3 deletions
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index e1e59e1b318..28e39bc6768 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -884,7 +884,17 @@ void r600_pcie_gart_tlb_flush(struct radeon_device *rdev)
u32 tmp;
/* flush hdp cache so updates hit vram */
- WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
+ if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) {
+ void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+ u32 tmp;
+
+ /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read
+ * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
+ */
+ WREG32(HDP_DEBUG1, 0);
+ tmp = readl((void __iomem *)ptr);
+ } else
+ WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
WREG32(VM_CONTEXT0_INVALIDATION_LOW_ADDR, rdev->mc.gtt_start >> 12);
WREG32(VM_CONTEXT0_INVALIDATION_HIGH_ADDR, (rdev->mc.gtt_end - 1) >> 12);
@@ -3527,5 +3537,15 @@ int r600_debugfs_mc_info_init(struct radeon_device *rdev)
*/
void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo)
{
- WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
+ /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read
+ * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
+ */
+ if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) {
+ void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+ u32 tmp;
+
+ WREG32(HDP_DEBUG1, 0);
+ tmp = readl((void __iomem *)ptr);
+ } else
+ WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
}
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
index b7318ac4f84..858a1920c0d 100644
--- a/drivers/gpu/drm/radeon/r600d.h
+++ b/drivers/gpu/drm/radeon/r600d.h
@@ -250,6 +250,7 @@
#define HDP_NONSURFACE_SIZE 0x2C0C
#define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0
#define HDP_TILING_CONFIG 0x2F3C
+#define HDP_DEBUG1 0x2F34
#define MC_VM_AGP_TOP 0x2184
#define MC_VM_AGP_BOT 0x2188
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 236fe668192..f1c79681011 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -204,7 +204,10 @@ static void rv770_mc_program(struct radeon_device *rdev)
WREG32((0x2c20 + j), 0x00000000);
WREG32((0x2c24 + j), 0x00000000);
}
- WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0);
+ /* r7xx hw bug. Read from HDP_DEBUG1 rather
+ * than writing to HDP_REG_COHERENCY_FLUSH_CNTL
+ */
+ tmp = RREG32(HDP_DEBUG1);
rv515_mc_stop(rdev, &save);
if (r600_mc_wait_for_idle(rdev)) {
diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h
index fd733f268e3..b7a5a20e81d 100644
--- a/drivers/gpu/drm/radeon/rv770d.h
+++ b/drivers/gpu/drm/radeon/rv770d.h
@@ -133,6 +133,7 @@
#define HDP_NONSURFACE_SIZE 0x2C0C
#define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0
#define HDP_TILING_CONFIG 0x2F3C
+#define HDP_DEBUG1 0x2F34
#define MC_SHARED_CHMAP 0x2004
#define NOOFCHAN_SHIFT 12