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.main
parent
6e38fd3576
commit
d6af902ff7
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue