Skip to content

Commit aadd4e1

Browse files
agd5fairlied
authored andcommitted
drm/radeon: some r420s have a CP race with the DMA engine.
This patch makes sure the CP doesn't DMA do VRAM while 2D is active by inserting a CP resync token. todo: port to kms. Signed-off-by: Dave Airlie <airlied@redhat.com>
1 parent 5a6e9f9 commit aadd4e1

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

drivers/gpu/drm/radeon/radeon_cp.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,18 @@ static void radeon_do_cp_start(drm_radeon_private_t * dev_priv)
616616

617617
dev_priv->cp_running = 1;
618618

619+
/* on r420, any DMA from CP to system memory while 2D is active
620+
* can cause a hang. workaround is to queue a CP RESYNC token
621+
*/
622+
if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) {
623+
BEGIN_RING(3);
624+
OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 1));
625+
OUT_RING(5); /* scratch reg 5 */
626+
OUT_RING(0xdeadbeef);
627+
ADVANCE_RING();
628+
COMMIT_RING();
629+
}
630+
619631
BEGIN_RING(8);
620632
/* isync can only be written through cp on r5xx write it here */
621633
OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 0));
@@ -653,8 +665,19 @@ static void radeon_do_cp_reset(drm_radeon_private_t * dev_priv)
653665
*/
654666
static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv)
655667
{
668+
RING_LOCALS;
656669
DRM_DEBUG("\n");
657670

671+
/* finish the pending CP_RESYNC token */
672+
if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) {
673+
BEGIN_RING(2);
674+
OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
675+
OUT_RING(R300_RB3D_DC_FINISH);
676+
ADVANCE_RING();
677+
COMMIT_RING();
678+
radeon_do_wait_for_idle(dev_priv);
679+
}
680+
658681
RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS);
659682

660683
dev_priv->cp_running = 0;

drivers/gpu/drm/radeon/radeon_drv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,6 +1099,9 @@ extern u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index);
10991099
# define RADEON_CSQ_PRIBM_INDBM (4 << 28)
11001100
# define RADEON_CSQ_PRIPIO_INDPIO (15 << 28)
11011101

1102+
#define R300_CP_RESYNC_ADDR 0x0778
1103+
#define R300_CP_RESYNC_DATA 0x077c
1104+
11021105
#define RADEON_AIC_CNTL 0x01d0
11031106
# define RADEON_PCIGART_TRANSLATE_EN (1 << 0)
11041107
# define RS400_MSI_REARM (1 << 3)

0 commit comments

Comments
 (0)