Improved workaround for Savage3D DMA lockup to emit NOPs only before the
authorFelix Kuehling <fxkuehl@gmx.de>
Sun, 9 Jan 2005 19:49:21 +0000 (19:49 +0000)
committerFelix Kuehling <fxkuehl@gmx.de>
Sun, 9 Jan 2005 19:49:21 +0000 (19:49 +0000)
    first indexed drawing command of a cmdbuf or if a wait command was
    emitted since the last indexed drawing command.

shared-core/savage_drv.h
shared-core/savage_state.c

index 9af1247..726c54f 100644 (file)
 
 #define DRIVER_NAME    "savage"
 #define DRIVER_DESC    "Savage3D/MX/IX, Savage4, SuperSavage, Twister, ProSavage[DDR]"
-#define DRIVER_DATE    "20050106"
+#define DRIVER_DATE    "20050109"
 
 #define DRIVER_MAJOR           2
 #define DRIVER_MINOR           1
-#define DRIVER_PATCHLEVEL      0
+#define DRIVER_PATCHLEVEL      1
 /* Interface history:
  *
  * 1.x   The DRM driver from the VIA/S3 code drop, basically a dummy
@@ -153,6 +153,9 @@ typedef struct drm_savage_private {
 
        drm_savage_state_t state;
 
+       /* after emitting a wait cmd Savage3D needs 63 nops before next DMA */
+       unsigned int waiting;
+
        /* config/hardware-dependent function pointers */
        int (*wait_fifo)(struct drm_savage_private *dev_priv, unsigned int n);
        int (*wait_evnt)(struct drm_savage_private *dev_priv, uint16_t e);
index e623f80..44034a1 100644 (file)
@@ -47,6 +47,7 @@ void savage_emit_clip_rect_s3d(drm_savage_private_t *dev_priv,
                BCI_WRITE(scend);
                dev_priv->state.s3d.scstart = scstart;
                dev_priv->state.s3d.scend   = scend;
+               dev_priv->waiting = 1;
        }
 }
 
@@ -71,6 +72,7 @@ void savage_emit_clip_rect_s4(drm_savage_private_t *dev_priv,
                BCI_WRITE(drawctrl1);
                dev_priv->state.s4.drawctrl0 = drawctrl0;
                dev_priv->state.s4.drawctrl1 = drawctrl1;
+               dev_priv->waiting = 1;
        }
 }
 
@@ -244,6 +246,7 @@ static int savage_dispatch_state(drm_savage_private_t *dev_priv,
        if (cmd_header->state.global) {
                BEGIN_BCI(bci_size+1);
                BCI_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D);
+               dev_priv->waiting = 1;
        } else {
                BEGIN_BCI(bci_size);
        }
@@ -338,7 +341,7 @@ static int savage_dispatch_dma_prim(drm_savage_private_t *dev_priv,
                BCI_WRITE(dmabuf->bus_address | dev_priv->dma_type);
                dev_priv->state.common.vbaddr = dmabuf->bus_address;
        }
-       if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+       if (S3_SAVAGE3D_SERIES(dev_priv->chipset) && dev_priv->waiting) {
                /* Workaround for what looks like a hardware bug. If a
                 * WAIT_3D_IDLE was emitted some time before the
                 * indexed drawing command then the engine will lock
@@ -347,6 +350,7 @@ static int savage_dispatch_dma_prim(drm_savage_private_t *dev_priv,
                BEGIN_BCI(63);
                for (i = 0; i < 63; ++i)
                        BCI_WRITE(BCI_CMD_WAIT);
+               dev_priv->waiting = 0;
        }
 
        prim <<= 25;
@@ -727,6 +731,10 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
         * DMA commands to the graphics hardware. */
        DRM_MEMORYBARRIER();
 
+       /* Coming from user space. Don't know if the Xserver has
+        * emitted wait commands. Assuming the worst. */
+       dev_priv->waiting = 1;
+
        i = 0;
        first_draw_cmd = NULL;
        while (i < cmdbuf.size) {