>From 7c1de3201bd4e965da7c1d542c46d8b2725bf42d Mon Sep 17 00:00:00 2001
From: Corbin Simpson <mostawesomed...@gmail.com>
Date: Fri, 18 Dec 2009 01:00:57 -0800
Subject: [PATCH] drivers/radeon/kms: Workaround RV410/R420 CP errata.

Long story short, this fixes sporadic hardlocks with my rv410 during
times of intense 2D acceleration (Flash on Fx3).

Signed-off-by: Corbin Simpson <mostawesomed...@gmail.com>
---
 drivers/gpu/drm/radeon/r420.c   |   35 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/radeon.h |    1 +
 2 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c
index 5c7fe52..6f096a6 100644
--- a/drivers/gpu/drm/radeon/r420.c
+++ b/drivers/gpu/drm/radeon/r420.c
@@ -30,6 +30,7 @@
 #include "radeon_reg.h"
 #include "radeon.h"
 #include "atom.h"
+#include "r100d.h"
 #include "r420d.h"

 int r420_mc_init(struct radeon_device *rdev)
@@ -165,6 +166,36 @@ static void r420_clock_resume(struct radeon_device *rdev)
        WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl);
 }

+static void r420_cp_errata_init(struct radeon_device *rdev)
+{
+    /* RV410 and R420 can lock up if CP DMA to host memory happens while the
+     * 2D engine is busy.
+     *
+     * The proper workaround is to queue a RESYNC at the beginning of the CP
+     * init, apparently.
+     */
+    radeon_scratch_get(rdev, &rdev->resync_scratch);
+
+    radeon_ring_lock(rdev, 8);
+    radeon_ring_write(rdev, PACKET0(R300_CP_RESYNC_ADDR, 1));
+    radeon_ring_write(rdev, rdev->resync_scratch);
+    radeon_ring_write(rdev, 0xDEADBEEF);
+    radeon_ring_unlock_commit(rdev);
+}
+
+static void r420_cp_errata_fini(struct radeon_device *rdev)
+{
+    /* Catch the RESYNC we dispatched all the way back, at the very beginning
+     * of the CP init.
+     */
+    radeon_ring_lock(rdev, 8);
+    radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+    radeon_ring_write(rdev, R300_RB3D_DC_FINISH);
+    radeon_ring_unlock_commit(rdev);
+
+    radeon_scratch_free(rdev, rdev->resync_scratch);
+}
+
 static int r420_startup(struct radeon_device *rdev)
 {
        int r;
@@ -194,6 +225,9 @@ static int r420_startup(struct radeon_device *rdev)
                dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
                return r;
        }
+    /* Handle CP errata. */
+    r420_cp_errata_init(rdev);
+
        r = r100_wb_init(rdev);
        if (r) {
                dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
@@ -247,6 +281,7 @@ int r420_suspend(struct radeon_device *rdev)

 void r420_fini(struct radeon_device *rdev)
 {
+    r420_cp_errata_fini(rdev);
        r100_cp_fini(rdev);
        r100_wb_fini(rdev);
        r100_ib_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 5ab35b8..0da50a2 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -771,6 +771,7 @@ struct radeon_device {
        struct radeon_gem               gem;
        struct radeon_pm                pm;
        uint32_t                        bios_scratch[RADEON_BIOS_NUM_SCRATCH];
+    uint32_t resync_scratch;
        struct mutex                    cs_mutex;
        struct radeon_wb                wb;
        struct radeon_dummy_page        dummy_page;
-- 
1.6.5.2

------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to