mirror of
https://github.com/torvalds/linux.git
synced 2024-11-28 23:21:31 +00:00
Merge branch 'drm-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: drm: don't set the signal blocker on the master process. drm: don't call the vblank tasklet with irqs disabled. r300: Fix cliprect emit drm/radeon: r300_cmdbuf: Always emit INDX_BUFFER immediately after DRAW_INDEX radeon: fix some hard lockups on r3/4/500s
This commit is contained in:
commit
2caf959966
@ -400,27 +400,31 @@ static void drm_locked_tasklet_func(unsigned long data)
|
|||||||
{
|
{
|
||||||
struct drm_device *dev = (struct drm_device *)data;
|
struct drm_device *dev = (struct drm_device *)data;
|
||||||
unsigned long irqflags;
|
unsigned long irqflags;
|
||||||
|
void (*tasklet_func)(struct drm_device *);
|
||||||
|
|
||||||
spin_lock_irqsave(&dev->tasklet_lock, irqflags);
|
spin_lock_irqsave(&dev->tasklet_lock, irqflags);
|
||||||
|
tasklet_func = dev->locked_tasklet_func;
|
||||||
|
spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
|
||||||
|
|
||||||
if (!dev->locked_tasklet_func ||
|
if (!tasklet_func ||
|
||||||
!drm_lock_take(&dev->lock,
|
!drm_lock_take(&dev->lock,
|
||||||
DRM_KERNEL_CONTEXT)) {
|
DRM_KERNEL_CONTEXT)) {
|
||||||
spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->lock.lock_time = jiffies;
|
dev->lock.lock_time = jiffies;
|
||||||
atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
|
atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
|
||||||
|
|
||||||
dev->locked_tasklet_func(dev);
|
spin_lock_irqsave(&dev->tasklet_lock, irqflags);
|
||||||
|
tasklet_func = dev->locked_tasklet_func;
|
||||||
|
dev->locked_tasklet_func = NULL;
|
||||||
|
spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
|
||||||
|
|
||||||
|
if (tasklet_func != NULL)
|
||||||
|
tasklet_func(dev);
|
||||||
|
|
||||||
drm_lock_free(&dev->lock,
|
drm_lock_free(&dev->lock,
|
||||||
DRM_KERNEL_CONTEXT);
|
DRM_KERNEL_CONTEXT);
|
||||||
|
|
||||||
dev->locked_tasklet_func = NULL;
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,14 +105,19 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||||||
ret ? "interrupted" : "has lock");
|
ret ? "interrupted" : "has lock");
|
||||||
if (ret) return ret;
|
if (ret) return ret;
|
||||||
|
|
||||||
sigemptyset(&dev->sigmask);
|
/* don't set the block all signals on the master process for now
|
||||||
sigaddset(&dev->sigmask, SIGSTOP);
|
* really probably not the correct answer but lets us debug xkb
|
||||||
sigaddset(&dev->sigmask, SIGTSTP);
|
* xserver for now */
|
||||||
sigaddset(&dev->sigmask, SIGTTIN);
|
if (!file_priv->master) {
|
||||||
sigaddset(&dev->sigmask, SIGTTOU);
|
sigemptyset(&dev->sigmask);
|
||||||
dev->sigdata.context = lock->context;
|
sigaddset(&dev->sigmask, SIGSTOP);
|
||||||
dev->sigdata.lock = dev->lock.hw_lock;
|
sigaddset(&dev->sigmask, SIGTSTP);
|
||||||
block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
|
sigaddset(&dev->sigmask, SIGTTIN);
|
||||||
|
sigaddset(&dev->sigmask, SIGTTOU);
|
||||||
|
dev->sigdata.context = lock->context;
|
||||||
|
dev->sigdata.lock = dev->lock.hw_lock;
|
||||||
|
block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
|
||||||
|
}
|
||||||
|
|
||||||
if (dev->driver->dma_ready && (lock->flags & _DRM_LOCK_READY))
|
if (dev->driver->dma_ready && (lock->flags & _DRM_LOCK_READY))
|
||||||
dev->driver->dma_ready(dev);
|
dev->driver->dma_ready(dev);
|
||||||
@ -150,6 +155,7 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||||||
{
|
{
|
||||||
struct drm_lock *lock = data;
|
struct drm_lock *lock = data;
|
||||||
unsigned long irqflags;
|
unsigned long irqflags;
|
||||||
|
void (*tasklet_func)(struct drm_device *);
|
||||||
|
|
||||||
if (lock->context == DRM_KERNEL_CONTEXT) {
|
if (lock->context == DRM_KERNEL_CONTEXT) {
|
||||||
DRM_ERROR("Process %d using kernel context %d\n",
|
DRM_ERROR("Process %d using kernel context %d\n",
|
||||||
@ -158,14 +164,11 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&dev->tasklet_lock, irqflags);
|
spin_lock_irqsave(&dev->tasklet_lock, irqflags);
|
||||||
|
tasklet_func = dev->locked_tasklet_func;
|
||||||
if (dev->locked_tasklet_func) {
|
dev->locked_tasklet_func = NULL;
|
||||||
dev->locked_tasklet_func(dev);
|
|
||||||
|
|
||||||
dev->locked_tasklet_func = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
|
spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
|
||||||
|
if (tasklet_func != NULL)
|
||||||
|
tasklet_func(dev);
|
||||||
|
|
||||||
atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
|
atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
|
||||||
|
|
||||||
|
@ -77,6 +77,9 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
|
|||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
box.x2--; /* Hardware expects inclusive bottom-right corner */
|
||||||
|
box.y2--;
|
||||||
|
|
||||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
|
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
|
||||||
box.x1 = (box.x1) &
|
box.x1 = (box.x1) &
|
||||||
R300_CLIPRECT_MASK;
|
R300_CLIPRECT_MASK;
|
||||||
@ -95,8 +98,8 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
|
|||||||
R300_CLIPRECT_MASK;
|
R300_CLIPRECT_MASK;
|
||||||
box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) &
|
box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) &
|
||||||
R300_CLIPRECT_MASK;
|
R300_CLIPRECT_MASK;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
|
OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
|
||||||
(box.y1 << R300_CLIPRECT_Y_SHIFT));
|
(box.y1 << R300_CLIPRECT_Y_SHIFT));
|
||||||
OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
|
OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
|
||||||
@ -136,6 +139,18 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
|
|||||||
ADVANCE_RING();
|
ADVANCE_RING();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* flus cache and wait idle clean after cliprect change */
|
||||||
|
BEGIN_RING(2);
|
||||||
|
OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
|
||||||
|
OUT_RING(R300_RB3D_DC_FLUSH);
|
||||||
|
ADVANCE_RING();
|
||||||
|
BEGIN_RING(2);
|
||||||
|
OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
|
||||||
|
OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
|
||||||
|
ADVANCE_RING();
|
||||||
|
/* set flush flag */
|
||||||
|
dev_priv->track_flush |= RADEON_FLUSH_EMITED;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,13 +181,13 @@ void r300_init_reg_flags(struct drm_device *dev)
|
|||||||
ADD_RANGE(0x21DC, 1);
|
ADD_RANGE(0x21DC, 1);
|
||||||
ADD_RANGE(R300_VAP_UNKNOWN_221C, 1);
|
ADD_RANGE(R300_VAP_UNKNOWN_221C, 1);
|
||||||
ADD_RANGE(R300_VAP_CLIP_X_0, 4);
|
ADD_RANGE(R300_VAP_CLIP_X_0, 4);
|
||||||
ADD_RANGE(R300_VAP_PVS_WAITIDLE, 1);
|
ADD_RANGE(R300_VAP_PVS_STATE_FLUSH_REG, 1);
|
||||||
ADD_RANGE(R300_VAP_UNKNOWN_2288, 1);
|
ADD_RANGE(R300_VAP_UNKNOWN_2288, 1);
|
||||||
ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
|
ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
|
||||||
ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
|
ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
|
||||||
ADD_RANGE(R300_GB_ENABLE, 1);
|
ADD_RANGE(R300_GB_ENABLE, 1);
|
||||||
ADD_RANGE(R300_GB_MSPOS0, 5);
|
ADD_RANGE(R300_GB_MSPOS0, 5);
|
||||||
ADD_RANGE(R300_TX_CNTL, 1);
|
ADD_RANGE(R300_TX_INVALTAGS, 1);
|
||||||
ADD_RANGE(R300_TX_ENABLE, 1);
|
ADD_RANGE(R300_TX_ENABLE, 1);
|
||||||
ADD_RANGE(0x4200, 4);
|
ADD_RANGE(0x4200, 4);
|
||||||
ADD_RANGE(0x4214, 1);
|
ADD_RANGE(0x4214, 1);
|
||||||
@ -388,15 +403,28 @@ static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,
|
|||||||
if (sz * 16 > cmdbuf->bufsz)
|
if (sz * 16 > cmdbuf->bufsz)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
BEGIN_RING(5 + sz * 4);
|
/* VAP is very sensitive so we purge cache before we program it
|
||||||
/* Wait for VAP to come to senses.. */
|
* and we also flush its state before & after */
|
||||||
/* there is no need to emit it multiple times, (only once before VAP is programmed,
|
BEGIN_RING(6);
|
||||||
but this optimization is for later */
|
OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
|
||||||
OUT_RING_REG(R300_VAP_PVS_WAITIDLE, 0);
|
OUT_RING(R300_RB3D_DC_FLUSH);
|
||||||
|
OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
|
||||||
|
OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
|
||||||
|
OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0));
|
||||||
|
OUT_RING(0);
|
||||||
|
ADVANCE_RING();
|
||||||
|
/* set flush flag */
|
||||||
|
dev_priv->track_flush |= RADEON_FLUSH_EMITED;
|
||||||
|
|
||||||
|
BEGIN_RING(3 + sz * 4);
|
||||||
OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr);
|
OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr);
|
||||||
OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1));
|
OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1));
|
||||||
OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4);
|
OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4);
|
||||||
|
ADVANCE_RING();
|
||||||
|
|
||||||
|
BEGIN_RING(2);
|
||||||
|
OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0));
|
||||||
|
OUT_RING(0);
|
||||||
ADVANCE_RING();
|
ADVANCE_RING();
|
||||||
|
|
||||||
cmdbuf->buf += sz * 16;
|
cmdbuf->buf += sz * 16;
|
||||||
@ -424,6 +452,15 @@ static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,
|
|||||||
OUT_RING_TABLE((int *)cmdbuf->buf, 8);
|
OUT_RING_TABLE((int *)cmdbuf->buf, 8);
|
||||||
ADVANCE_RING();
|
ADVANCE_RING();
|
||||||
|
|
||||||
|
BEGIN_RING(4);
|
||||||
|
OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
|
||||||
|
OUT_RING(R300_RB3D_DC_FLUSH);
|
||||||
|
OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
|
||||||
|
OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
|
||||||
|
ADVANCE_RING();
|
||||||
|
/* set flush flag */
|
||||||
|
dev_priv->track_flush |= RADEON_FLUSH_EMITED;
|
||||||
|
|
||||||
cmdbuf->buf += 8 * 4;
|
cmdbuf->buf += 8 * 4;
|
||||||
cmdbuf->bufsz -= 8 * 4;
|
cmdbuf->bufsz -= 8 * 4;
|
||||||
|
|
||||||
@ -543,22 +580,23 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv,
|
static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv,
|
||||||
drm_radeon_kcmd_buffer_t *cmdbuf)
|
drm_radeon_kcmd_buffer_t *cmdbuf)
|
||||||
{
|
{
|
||||||
u32 *cmd = (u32 *) cmdbuf->buf;
|
u32 *cmd;
|
||||||
int count, ret;
|
int count;
|
||||||
|
int expected_count;
|
||||||
RING_LOCALS;
|
RING_LOCALS;
|
||||||
|
|
||||||
count=(cmd[0]>>16) & 0x3fff;
|
cmd = (u32 *) cmdbuf->buf;
|
||||||
|
count = (cmd[0]>>16) & 0x3fff;
|
||||||
|
expected_count = cmd[1] >> 16;
|
||||||
|
if (!(cmd[1] & R300_VAP_VF_CNTL__INDEX_SIZE_32bit))
|
||||||
|
expected_count = (expected_count+1)/2;
|
||||||
|
|
||||||
if ((cmd[1] & 0x8000ffff) != 0x80000810) {
|
if (count && count != expected_count) {
|
||||||
DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
|
DRM_ERROR("3D_DRAW_INDX_2: packet size %i, expected %i\n",
|
||||||
return -EINVAL;
|
count, expected_count);
|
||||||
}
|
|
||||||
ret = !radeon_check_offset(dev_priv, cmd[2]);
|
|
||||||
if (ret) {
|
|
||||||
DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,6 +608,50 @@ static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv,
|
|||||||
cmdbuf->buf += (count+2)*4;
|
cmdbuf->buf += (count+2)*4;
|
||||||
cmdbuf->bufsz -= (count+2)*4;
|
cmdbuf->bufsz -= (count+2)*4;
|
||||||
|
|
||||||
|
if (!count) {
|
||||||
|
drm_r300_cmd_header_t header;
|
||||||
|
|
||||||
|
if (cmdbuf->bufsz < 4*4 + sizeof(header)) {
|
||||||
|
DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER, but stream is too short.\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.u = *(unsigned int *)cmdbuf->buf;
|
||||||
|
|
||||||
|
cmdbuf->buf += sizeof(header);
|
||||||
|
cmdbuf->bufsz -= sizeof(header);
|
||||||
|
cmd = (u32 *) cmdbuf->buf;
|
||||||
|
|
||||||
|
if (header.header.cmd_type != R300_CMD_PACKET3 ||
|
||||||
|
header.packet3.packet != R300_CMD_PACKET3_RAW ||
|
||||||
|
cmd[0] != CP_PACKET3(RADEON_CP_INDX_BUFFER, 2)) {
|
||||||
|
DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER.\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cmd[1] & 0x8000ffff) != 0x80000810) {
|
||||||
|
DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (!radeon_check_offset(dev_priv, cmd[2])) {
|
||||||
|
DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (cmd[3] != expected_count) {
|
||||||
|
DRM_ERROR("INDX_BUFFER: buffer size %i, expected %i\n",
|
||||||
|
cmd[3], expected_count);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN_RING(4);
|
||||||
|
OUT_RING(cmd[0]);
|
||||||
|
OUT_RING_TABLE((int *)(cmdbuf->buf + 4), 3);
|
||||||
|
ADVANCE_RING();
|
||||||
|
|
||||||
|
cmdbuf->buf += 4*4;
|
||||||
|
cmdbuf->bufsz -= 4*4;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -613,11 +695,22 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
|
|||||||
case RADEON_CNTL_BITBLT_MULTI:
|
case RADEON_CNTL_BITBLT_MULTI:
|
||||||
return r300_emit_bitblt_multi(dev_priv, cmdbuf);
|
return r300_emit_bitblt_multi(dev_priv, cmdbuf);
|
||||||
|
|
||||||
case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */
|
case RADEON_CP_INDX_BUFFER:
|
||||||
return r300_emit_indx_buffer(dev_priv, cmdbuf);
|
DRM_ERROR("packet3 INDX_BUFFER without preceding 3D_DRAW_INDX_2 is illegal.\n");
|
||||||
case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */
|
return -EINVAL;
|
||||||
case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */
|
case RADEON_CP_3D_DRAW_IMMD_2:
|
||||||
case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */
|
/* triggers drawing using in-packet vertex data */
|
||||||
|
case RADEON_CP_3D_DRAW_VBUF_2:
|
||||||
|
/* triggers drawing of vertex buffers setup elsewhere */
|
||||||
|
dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED |
|
||||||
|
RADEON_PURGE_EMITED);
|
||||||
|
break;
|
||||||
|
case RADEON_CP_3D_DRAW_INDX_2:
|
||||||
|
/* triggers drawing using indices to vertex buffer */
|
||||||
|
/* whenever we send vertex we clear flush & purge */
|
||||||
|
dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED |
|
||||||
|
RADEON_PURGE_EMITED);
|
||||||
|
return r300_emit_draw_indx_2(dev_priv, cmdbuf);
|
||||||
case RADEON_WAIT_FOR_IDLE:
|
case RADEON_WAIT_FOR_IDLE:
|
||||||
case RADEON_CP_NOP:
|
case RADEON_CP_NOP:
|
||||||
/* these packets are safe */
|
/* these packets are safe */
|
||||||
@ -713,17 +806,53 @@ static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
|
|||||||
*/
|
*/
|
||||||
static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
|
static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
|
||||||
{
|
{
|
||||||
|
uint32_t cache_z, cache_3d, cache_2d;
|
||||||
RING_LOCALS;
|
RING_LOCALS;
|
||||||
|
|
||||||
BEGIN_RING(6);
|
cache_z = R300_ZC_FLUSH;
|
||||||
OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
|
cache_2d = R300_RB2D_DC_FLUSH;
|
||||||
OUT_RING(R300_RB3D_DSTCACHE_UNKNOWN_0A);
|
cache_3d = R300_RB3D_DC_FLUSH;
|
||||||
|
if (!(dev_priv->track_flush & RADEON_PURGE_EMITED)) {
|
||||||
|
/* we can purge, primitive where draw since last purge */
|
||||||
|
cache_z |= R300_ZC_FREE;
|
||||||
|
cache_2d |= R300_RB2D_DC_FREE;
|
||||||
|
cache_3d |= R300_RB3D_DC_FREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* flush & purge zbuffer */
|
||||||
|
BEGIN_RING(2);
|
||||||
OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));
|
OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));
|
||||||
OUT_RING(R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE|
|
OUT_RING(cache_z);
|
||||||
R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE);
|
|
||||||
OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0));
|
|
||||||
OUT_RING(0x0);
|
|
||||||
ADVANCE_RING();
|
ADVANCE_RING();
|
||||||
|
/* flush & purge 3d */
|
||||||
|
BEGIN_RING(2);
|
||||||
|
OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
|
||||||
|
OUT_RING(cache_3d);
|
||||||
|
ADVANCE_RING();
|
||||||
|
/* flush & purge texture */
|
||||||
|
BEGIN_RING(2);
|
||||||
|
OUT_RING(CP_PACKET0(R300_TX_INVALTAGS, 0));
|
||||||
|
OUT_RING(0);
|
||||||
|
ADVANCE_RING();
|
||||||
|
/* FIXME: is this one really needed ? */
|
||||||
|
BEGIN_RING(2);
|
||||||
|
OUT_RING(CP_PACKET0(R300_RB3D_AARESOLVE_CTL, 0));
|
||||||
|
OUT_RING(0);
|
||||||
|
ADVANCE_RING();
|
||||||
|
BEGIN_RING(2);
|
||||||
|
OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
|
||||||
|
OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
|
||||||
|
ADVANCE_RING();
|
||||||
|
/* flush & purge 2d through E2 as RB2D will trigger lockup */
|
||||||
|
BEGIN_RING(4);
|
||||||
|
OUT_RING(CP_PACKET0(R300_DSTCACHE_CTLSTAT, 0));
|
||||||
|
OUT_RING(cache_2d);
|
||||||
|
OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
|
||||||
|
OUT_RING(RADEON_WAIT_2D_IDLECLEAN |
|
||||||
|
RADEON_WAIT_HOST_IDLECLEAN);
|
||||||
|
ADVANCE_RING();
|
||||||
|
/* set flush & purge flags */
|
||||||
|
dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -905,8 +1034,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
|
|||||||
|
|
||||||
DRM_DEBUG("\n");
|
DRM_DEBUG("\n");
|
||||||
|
|
||||||
/* See the comment above r300_emit_begin3d for why this call must be here,
|
/* pacify */
|
||||||
* and what the cleanup gotos are for. */
|
|
||||||
r300_pacify(dev_priv);
|
r300_pacify(dev_priv);
|
||||||
|
|
||||||
if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) {
|
if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) {
|
||||||
|
@ -317,7 +317,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||||||
* Therefore, I suspect writing zero to 0x2284 synchronizes the engine and
|
* Therefore, I suspect writing zero to 0x2284 synchronizes the engine and
|
||||||
* avoids bugs caused by still running shaders reading bad data from memory.
|
* avoids bugs caused by still running shaders reading bad data from memory.
|
||||||
*/
|
*/
|
||||||
#define R300_VAP_PVS_WAITIDLE 0x2284 /* GUESS */
|
#define R300_VAP_PVS_STATE_FLUSH_REG 0x2284
|
||||||
|
|
||||||
/* Absolutely no clue what this register is about. */
|
/* Absolutely no clue what this register is about. */
|
||||||
#define R300_VAP_UNKNOWN_2288 0x2288
|
#define R300_VAP_UNKNOWN_2288 0x2288
|
||||||
@ -513,7 +513,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||||||
/* gap */
|
/* gap */
|
||||||
|
|
||||||
/* Zero to flush caches. */
|
/* Zero to flush caches. */
|
||||||
#define R300_TX_CNTL 0x4100
|
#define R300_TX_INVALTAGS 0x4100
|
||||||
#define R300_TX_FLUSH 0x0
|
#define R300_TX_FLUSH 0x0
|
||||||
|
|
||||||
/* The upper enable bits are guessed, based on fglrx reported limits. */
|
/* The upper enable bits are guessed, based on fglrx reported limits. */
|
||||||
@ -1362,6 +1362,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||||||
#define R300_RB3D_COLORPITCH2 0x4E40 /* GUESS */
|
#define R300_RB3D_COLORPITCH2 0x4E40 /* GUESS */
|
||||||
#define R300_RB3D_COLORPITCH3 0x4E44 /* GUESS */
|
#define R300_RB3D_COLORPITCH3 0x4E44 /* GUESS */
|
||||||
|
|
||||||
|
#define R300_RB3D_AARESOLVE_CTL 0x4E88
|
||||||
/* gap */
|
/* gap */
|
||||||
|
|
||||||
/* Guess by Vladimir.
|
/* Guess by Vladimir.
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#define RADEON_FIFO_DEBUG 0
|
#define RADEON_FIFO_DEBUG 0
|
||||||
|
|
||||||
static int radeon_do_cleanup_cp(struct drm_device * dev);
|
static int radeon_do_cleanup_cp(struct drm_device * dev);
|
||||||
|
static void radeon_do_cp_start(drm_radeon_private_t * dev_priv);
|
||||||
|
|
||||||
static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
|
static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
|
||||||
{
|
{
|
||||||
@ -198,23 +199,8 @@ static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv)
|
|||||||
DRM_UDELAY(1);
|
DRM_UDELAY(1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* 3D */
|
/* don't flush or purge cache here or lockup */
|
||||||
tmp = RADEON_READ(R300_RB3D_DSTCACHE_CTLSTAT);
|
return 0;
|
||||||
tmp |= RADEON_RB3D_DC_FLUSH_ALL;
|
|
||||||
RADEON_WRITE(R300_RB3D_DSTCACHE_CTLSTAT, tmp);
|
|
||||||
|
|
||||||
/* 2D */
|
|
||||||
tmp = RADEON_READ(R300_DSTCACHE_CTLSTAT);
|
|
||||||
tmp |= RADEON_RB3D_DC_FLUSH_ALL;
|
|
||||||
RADEON_WRITE(R300_DSTCACHE_CTLSTAT, tmp);
|
|
||||||
|
|
||||||
for (i = 0; i < dev_priv->usec_timeout; i++) {
|
|
||||||
if (!(RADEON_READ(R300_DSTCACHE_CTLSTAT)
|
|
||||||
& RADEON_RB3D_DC_BUSY)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
DRM_UDELAY(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if RADEON_FIFO_DEBUG
|
#if RADEON_FIFO_DEBUG
|
||||||
@ -237,6 +223,9 @@ static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries)
|
|||||||
return 0;
|
return 0;
|
||||||
DRM_UDELAY(1);
|
DRM_UDELAY(1);
|
||||||
}
|
}
|
||||||
|
DRM_INFO("wait for fifo failed status : 0x%08X 0x%08X\n",
|
||||||
|
RADEON_READ(RADEON_RBBM_STATUS),
|
||||||
|
RADEON_READ(R300_VAP_CNTL_STATUS));
|
||||||
|
|
||||||
#if RADEON_FIFO_DEBUG
|
#if RADEON_FIFO_DEBUG
|
||||||
DRM_ERROR("failed!\n");
|
DRM_ERROR("failed!\n");
|
||||||
@ -263,6 +252,9 @@ static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv)
|
|||||||
}
|
}
|
||||||
DRM_UDELAY(1);
|
DRM_UDELAY(1);
|
||||||
}
|
}
|
||||||
|
DRM_INFO("wait idle failed status : 0x%08X 0x%08X\n",
|
||||||
|
RADEON_READ(RADEON_RBBM_STATUS),
|
||||||
|
RADEON_READ(R300_VAP_CNTL_STATUS));
|
||||||
|
|
||||||
#if RADEON_FIFO_DEBUG
|
#if RADEON_FIFO_DEBUG
|
||||||
DRM_ERROR("failed!\n");
|
DRM_ERROR("failed!\n");
|
||||||
@ -443,14 +435,20 @@ static void radeon_do_cp_start(drm_radeon_private_t * dev_priv)
|
|||||||
|
|
||||||
dev_priv->cp_running = 1;
|
dev_priv->cp_running = 1;
|
||||||
|
|
||||||
BEGIN_RING(6);
|
BEGIN_RING(8);
|
||||||
|
/* isync can only be written through cp on r5xx write it here */
|
||||||
|
OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 0));
|
||||||
|
OUT_RING(RADEON_ISYNC_ANY2D_IDLE3D |
|
||||||
|
RADEON_ISYNC_ANY3D_IDLE2D |
|
||||||
|
RADEON_ISYNC_WAIT_IDLEGUI |
|
||||||
|
RADEON_ISYNC_CPSCRATCH_IDLEGUI);
|
||||||
RADEON_PURGE_CACHE();
|
RADEON_PURGE_CACHE();
|
||||||
RADEON_PURGE_ZCACHE();
|
RADEON_PURGE_ZCACHE();
|
||||||
RADEON_WAIT_UNTIL_IDLE();
|
RADEON_WAIT_UNTIL_IDLE();
|
||||||
|
|
||||||
ADVANCE_RING();
|
ADVANCE_RING();
|
||||||
COMMIT_RING();
|
COMMIT_RING();
|
||||||
|
|
||||||
|
dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the Command Processor. This will not flush any pending
|
/* Reset the Command Processor. This will not flush any pending
|
||||||
|
@ -220,6 +220,9 @@ struct radeon_virt_surface {
|
|||||||
struct drm_file *file_priv;
|
struct drm_file *file_priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define RADEON_FLUSH_EMITED (1 < 0)
|
||||||
|
#define RADEON_PURGE_EMITED (1 < 1)
|
||||||
|
|
||||||
typedef struct drm_radeon_private {
|
typedef struct drm_radeon_private {
|
||||||
drm_radeon_ring_buffer_t ring;
|
drm_radeon_ring_buffer_t ring;
|
||||||
drm_radeon_sarea_t *sarea_priv;
|
drm_radeon_sarea_t *sarea_priv;
|
||||||
@ -311,6 +314,7 @@ typedef struct drm_radeon_private {
|
|||||||
unsigned long fb_aper_offset;
|
unsigned long fb_aper_offset;
|
||||||
|
|
||||||
int num_gb_pipes;
|
int num_gb_pipes;
|
||||||
|
int track_flush;
|
||||||
} drm_radeon_private_t;
|
} drm_radeon_private_t;
|
||||||
|
|
||||||
typedef struct drm_radeon_buf_priv {
|
typedef struct drm_radeon_buf_priv {
|
||||||
@ -693,7 +697,6 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev,
|
|||||||
#define R300_ZB_ZCACHE_CTLSTAT 0x4f18
|
#define R300_ZB_ZCACHE_CTLSTAT 0x4f18
|
||||||
# define R300_ZC_FLUSH (1 << 0)
|
# define R300_ZC_FLUSH (1 << 0)
|
||||||
# define R300_ZC_FREE (1 << 1)
|
# define R300_ZC_FREE (1 << 1)
|
||||||
# define R300_ZC_FLUSH_ALL 0x3
|
|
||||||
# define R300_ZC_BUSY (1 << 31)
|
# define R300_ZC_BUSY (1 << 31)
|
||||||
#define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325c
|
#define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325c
|
||||||
# define RADEON_RB3D_DC_FLUSH (3 << 0)
|
# define RADEON_RB3D_DC_FLUSH (3 << 0)
|
||||||
@ -701,6 +704,8 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev,
|
|||||||
# define RADEON_RB3D_DC_FLUSH_ALL 0xf
|
# define RADEON_RB3D_DC_FLUSH_ALL 0xf
|
||||||
# define RADEON_RB3D_DC_BUSY (1 << 31)
|
# define RADEON_RB3D_DC_BUSY (1 << 31)
|
||||||
#define R300_RB3D_DSTCACHE_CTLSTAT 0x4e4c
|
#define R300_RB3D_DSTCACHE_CTLSTAT 0x4e4c
|
||||||
|
# define R300_RB3D_DC_FLUSH (2 << 0)
|
||||||
|
# define R300_RB3D_DC_FREE (2 << 2)
|
||||||
# define R300_RB3D_DC_FINISH (1 << 4)
|
# define R300_RB3D_DC_FINISH (1 << 4)
|
||||||
#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c
|
#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c
|
||||||
# define RADEON_Z_TEST_MASK (7 << 4)
|
# define RADEON_Z_TEST_MASK (7 << 4)
|
||||||
@ -1246,17 +1251,17 @@ do { \
|
|||||||
OUT_RING(RADEON_RB3D_DC_FLUSH); \
|
OUT_RING(RADEON_RB3D_DC_FLUSH); \
|
||||||
} else { \
|
} else { \
|
||||||
OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \
|
OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \
|
||||||
OUT_RING(RADEON_RB3D_DC_FLUSH); \
|
OUT_RING(R300_RB3D_DC_FLUSH); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define RADEON_PURGE_CACHE() do { \
|
#define RADEON_PURGE_CACHE() do { \
|
||||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \
|
if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \
|
||||||
OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \
|
OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \
|
||||||
OUT_RING(RADEON_RB3D_DC_FLUSH_ALL); \
|
OUT_RING(RADEON_RB3D_DC_FLUSH | RADEON_RB3D_DC_FREE); \
|
||||||
} else { \
|
} else { \
|
||||||
OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \
|
OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \
|
||||||
OUT_RING(RADEON_RB3D_DC_FLUSH_ALL); \
|
OUT_RING(R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@ -1273,10 +1278,10 @@ do { \
|
|||||||
#define RADEON_PURGE_ZCACHE() do { \
|
#define RADEON_PURGE_ZCACHE() do { \
|
||||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \
|
if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \
|
||||||
OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); \
|
OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); \
|
||||||
OUT_RING(RADEON_RB3D_ZC_FLUSH_ALL); \
|
OUT_RING(RADEON_RB3D_ZC_FLUSH | RADEON_RB3D_ZC_FREE); \
|
||||||
} else { \
|
} else { \
|
||||||
OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \
|
OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); \
|
||||||
OUT_RING(R300_ZC_FLUSH_ALL); \
|
OUT_RING(R300_ZC_FLUSH | R300_ZC_FREE); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user