提交 62cdc0c2 编写于 作者: C Corbin Simpson 提交者: Dave Airlie

drm/radeon/kms: Workaround RV410/R420 CP errata (V3)

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

V2: Fix indentation and move errata_fini to suspend function so we
don't leak scratch register over suspend/resume cycle.
V3: Move scratch_reg to asic specific structure (aim is to slowly
    move stuff to asic specific structure and avoid poluting
    radeon_device struct with asic specific variables)
Signed-off-by: NCorbin Simpson <MostAwesomeDude@gmail.com>
Signed-off-by: NJerome Glisse <jglisse@redhat.com>
Signed-off-by: NDave Airlie <airlied@redhat.com>
上级 06b6476d
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "radeon_reg.h" #include "radeon_reg.h"
#include "radeon.h" #include "radeon.h"
#include "atom.h" #include "atom.h"
#include "r100d.h"
#include "r420d.h" #include "r420d.h"
int r420_mc_init(struct radeon_device *rdev) int r420_mc_init(struct radeon_device *rdev)
...@@ -165,6 +166,34 @@ static void r420_clock_resume(struct radeon_device *rdev) ...@@ -165,6 +166,34 @@ static void r420_clock_resume(struct radeon_device *rdev)
WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl); 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->config.r300.resync_scratch);
radeon_ring_lock(rdev, 8);
radeon_ring_write(rdev, PACKET0(R300_CP_RESYNC_ADDR, 1));
radeon_ring_write(rdev, rdev->config.r300.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->config.r300.resync_scratch);
}
static int r420_startup(struct radeon_device *rdev) static int r420_startup(struct radeon_device *rdev)
{ {
int r; int r;
...@@ -196,6 +225,7 @@ static int r420_startup(struct radeon_device *rdev) ...@@ -196,6 +225,7 @@ static int r420_startup(struct radeon_device *rdev)
dev_err(rdev->dev, "failled initializing CP (%d).\n", r); dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
return r; return r;
} }
r420_cp_errata_init(rdev);
r = r100_wb_init(rdev); r = r100_wb_init(rdev);
if (r) { if (r) {
dev_err(rdev->dev, "failled initializing WB (%d).\n", r); dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
...@@ -238,6 +268,7 @@ int r420_resume(struct radeon_device *rdev) ...@@ -238,6 +268,7 @@ int r420_resume(struct radeon_device *rdev)
int r420_suspend(struct radeon_device *rdev) int r420_suspend(struct radeon_device *rdev)
{ {
r420_cp_errata_fini(rdev);
r100_cp_disable(rdev); r100_cp_disable(rdev);
r100_wb_disable(rdev); r100_wb_disable(rdev);
r100_irq_disable(rdev); r100_irq_disable(rdev);
......
...@@ -674,6 +674,7 @@ struct r100_asic { ...@@ -674,6 +674,7 @@ struct r100_asic {
struct r300_asic { struct r300_asic {
const unsigned *reg_safe_bm; const unsigned *reg_safe_bm;
unsigned reg_safe_bm_size; unsigned reg_safe_bm_size;
u32 resync_scratch;
}; };
struct r600_asic { struct r600_asic {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册