From d6af902ff74d4a384c2dd9acb9540d637f588bc6 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Sun, 9 Jan 2005 19:49:21 +0000 Subject: [PATCH] Improved workaround for Savage3D DMA lockup to emit NOPs only before the 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 | 7 +++++-- shared-core/savage_state.c | 10 +++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/shared-core/savage_drv.h b/shared-core/savage_drv.h index 9af1247..726c54f 100644 --- a/shared-core/savage_drv.h +++ b/shared-core/savage_drv.h @@ -30,11 +30,11 @@ #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); diff --git a/shared-core/savage_state.c b/shared-core/savage_state.c index e623f80..44034a1 100644 --- a/shared-core/savage_state.c +++ b/shared-core/savage_state.c @@ -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) { -- 2.7.4