drm/radeon: some r420s have a CP race with the DMA engine.
Alex Deucher [Mon, 21 Sep 2009 04:48:45 +0000 (14:48 +1000)]
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>

drivers/gpu/drm/radeon/radeon_cp.c
drivers/gpu/drm/radeon/radeon_drv.h

index fa063d0..4f7afc7 100644 (file)
@@ -616,6 +616,18 @@ static void radeon_do_cp_start(drm_radeon_private_t * dev_priv)
 
        dev_priv->cp_running = 1;
 
+       /* on r420, any DMA from CP to system memory while 2D is active
+        * can cause a hang.  workaround is to queue a CP RESYNC token
+        */
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) {
+               BEGIN_RING(3);
+               OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 1));
+               OUT_RING(5); /* scratch reg 5 */
+               OUT_RING(0xdeadbeef);
+               ADVANCE_RING();
+               COMMIT_RING();
+       }
+
        BEGIN_RING(8);
        /* isync can only be written through cp on r5xx write it here */
        OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 0));
@@ -653,8 +665,19 @@ static void radeon_do_cp_reset(drm_radeon_private_t * dev_priv)
  */
 static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv)
 {
+       RING_LOCALS;
        DRM_DEBUG("\n");
 
+       /* finish the pending CP_RESYNC token */
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) {
+               BEGIN_RING(2);
+               OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+               OUT_RING(R300_RB3D_DC_FINISH);
+               ADVANCE_RING();
+               COMMIT_RING();
+               radeon_do_wait_for_idle(dev_priv);
+       }
+
        RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS);
 
        dev_priv->cp_running = 0;
index bc79ad6..cb0cfe4 100644 (file)
@@ -1099,6 +1099,9 @@ extern u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index);
 #      define RADEON_CSQ_PRIBM_INDBM           (4 << 28)
 #      define RADEON_CSQ_PRIPIO_INDPIO         (15 << 28)
 
+#define R300_CP_RESYNC_ADDR            0x0778
+#define R300_CP_RESYNC_DATA            0x077c
+
 #define RADEON_AIC_CNTL                        0x01d0
 #      define RADEON_PCIGART_TRANSLATE_EN      (1 << 0)
 #      define RS400_MSI_REARM                  (1 << 3)