From 7abb8416a7fd8d69f1f2317cdac2baa8e640671e Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Sun, 9 Nov 2008 18:48:46 +0100 Subject: radeon: add more packet3 relocations handling --- shared-core/radeon_cs.c | 99 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 78 insertions(+), 21 deletions(-) (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index 3dde321d..56f6cbac 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -180,7 +180,6 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) struct drm_radeon_cs *cs = data; uint32_t *packets = NULL; uint32_t cs_id; - uint32_t card_offset; long size; int r; struct drm_radeon_kernel_chunk chunk_fake[1]; @@ -280,12 +279,11 @@ static __inline__ int radeon_cs_relocate_packet0(struct drm_radeon_cs_parser *pa old kernels ignore it. */ if (parser->reloc_index == -1) { if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16))) { - DRM_ERROR("Packet 3 was %x should have been %x: reg is %x\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16), reg); + DRM_ERROR("Packet 3 was %x should have been %x: reg is %x at %d\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16), reg, offset_dw); return -EINVAL; } - } else { if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE_NEW << 16))) { - DRM_ERROR("Packet 3 was %x should have been %x: reg is %x\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE_NEW << 16), reg); + DRM_ERROR("Packet 3 was %x should have been %x: reg is %x at %d\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE_NEW << 16), reg, offset_dw); return -EINVAL; } @@ -295,9 +293,11 @@ static __inline__ int radeon_cs_relocate_packet0(struct drm_radeon_cs_parser *pa case RADEON_DST_PITCH_OFFSET: case RADEON_SRC_PITCH_OFFSET: /* pass in the start of the reloc */ - ret = dev_priv->cs.relocate(parser, ib_chunk->kdata + offset_dw + 2, &offset); - if (ret) + ret = dev_priv->cs.relocate(parser, + ib_chunk->kdata + offset_dw + 2, &offset); + if (ret) { return ret; + } tmp = (val & RADEON_2D_OFFSET_MASK) << 10; val &= ~RADEON_2D_OFFSET_MASK; offset += tmp; @@ -313,9 +313,12 @@ static __inline__ int radeon_cs_relocate_packet0(struct drm_radeon_cs_parser *pa case R200_PP_TXOFFSET_1: case RADEON_PP_TXOFFSET_0: case RADEON_PP_TXOFFSET_1: - ret = dev_priv->cs.relocate(parser, ib_chunk->kdata + offset_dw + 2, &offset); - if (ret) + ret = dev_priv->cs.relocate(parser, + ib_chunk->kdata + offset_dw + 2, &offset); + if (ret) { + DRM_ERROR("Failed to relocate %d\n", offset_dw); return ret; + } offset &= 0xffffffe0; val += offset; @@ -332,8 +335,9 @@ static int radeon_cs_relocate_packet3(struct drm_radeon_cs_parser *parser, uint32_t offset_dw) { drm_radeon_private_t *dev_priv = parser->dev->dev_private; - uint32_t hdr, num_dw, reg; - uint32_t offset, val, tmp; + uint32_t hdr, num_dw, reg, i; + uint32_t offset, val, tmp, nptr, cptr; + uint32_t *reloc; int ret; struct drm_radeon_kernel_chunk *ib_chunk; @@ -347,11 +351,13 @@ static int radeon_cs_relocate_packet3(struct drm_radeon_cs_parser *parser, switch(reg) { case RADEON_CNTL_HOSTDATA_BLT: - { val = ib_chunk->kdata[offset_dw + 2]; - ret = dev_priv->cs.relocate(parser, ib_chunk->kdata + offset_dw + num_dw + 2, &offset); - if (ret) + ret = dev_priv->cs.relocate(parser, + ib_chunk->kdata + offset_dw + num_dw + 2, + &offset); + if (ret) { return ret; + } tmp = (val & RADEON_2D_OFFSET_MASK) << 10; val &= ~RADEON_2D_OFFSET_MASK; @@ -360,8 +366,48 @@ static int radeon_cs_relocate_packet3(struct drm_radeon_cs_parser *parser, val |= offset; ib_chunk->kdata[offset_dw + 2] = val; - } + break; + case RADEON_3D_LOAD_VBPNTR: + nptr = ib_chunk->kdata[offset_dw + 1]; + cptr = offset_dw + 3; + for (i = 0; i < (nptr & ~1); i+= 2) { + reloc = ib_chunk->kdata + offset_dw + num_dw + 2; + reloc += ((i + 0) * 2); + ret = dev_priv->cs.relocate(parser, reloc, &offset); + if (ret) { + return ret; + } + ib_chunk->kdata[cptr] += offset; + cptr += 1; + reloc = ib_chunk->kdata + offset_dw + num_dw + 2; + reloc += ((i + 1) * 2); + ret = dev_priv->cs.relocate(parser, reloc, &offset); + if (ret) { + return ret; + } + ib_chunk->kdata[cptr] += offset; + cptr += 2; + } + if (nptr & 1) { + reloc = ib_chunk->kdata + offset_dw + num_dw + 2; + reloc += ((nptr - 1) * 2); + ret = dev_priv->cs.relocate(parser, reloc, &offset); + if (ret) { + return ret; + } + ib_chunk->kdata[cptr] += offset; + } + break; + case RADEON_CP_INDX_BUFFER: + reloc = ib_chunk->kdata + offset_dw + num_dw + 2; + ret = dev_priv->cs.relocate(parser, reloc, &offset); + if (ret) { + return ret; + } + ib_chunk->kdata[offset_dw + 2] += offset; + break; default: + DRM_ERROR("Unknown packet3 0x%08X\n", hdr); return -EINVAL; } return 0; @@ -377,6 +423,12 @@ int radeon_cs_packet0(struct drm_radeon_cs_parser *parser, uint32_t offset_dw) num_dw = ((hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2; reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2; + if (hdr & (1 << 15)) { + if (reg == 0x2208) { + return 0; + } + } + while (count_dw < num_dw) { /* need to have something like the r300 validation here - list of allowed registers */ @@ -405,7 +457,8 @@ int radeon_cs_packet0(struct drm_radeon_cs_parser *parser, uint32_t offset_dw) } else if (flags == MARK_CHECK_SCISSOR) { DRM_DEBUG("need to validate scissor %x %d\n", reg, flags); } else { - DRM_DEBUG("illegal register %x %d\n", reg, flags); + + DRM_ERROR("illegal register 0x%x %d at %d\n", reg, flags, offset_dw); return -EINVAL; } break; @@ -435,6 +488,8 @@ int radeon_cs_parse(struct drm_radeon_cs_parser *parser) switch (hdr & RADEON_CP_PACKET_MASK) { case RADEON_CP_PACKET0: ret = radeon_cs_packet0(parser, count_dw); + if (ret) + return ret; break; case RADEON_CP_PACKET1: case RADEON_CP_PACKET2: @@ -446,14 +501,17 @@ int radeon_cs_parse(struct drm_radeon_cs_parser *parser) reg = hdr & 0xff00; switch(reg) { + case RADEON_3D_LOAD_VBPNTR: + case RADEON_CP_INDX_BUFFER: case RADEON_CNTL_HOSTDATA_BLT: - radeon_cs_relocate_packet3(parser, count_dw); + ret =radeon_cs_relocate_packet3(parser, + count_dw); + if (ret) + return ret; break; case RADEON_CNTL_BITBLT_MULTI: - case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */ - case RADEON_CP_INDX_BUFFER: - DRM_ERROR("need relocate packet 3 for %x\n", reg); + DRM_ERROR("need relocate packet 3 for %x %d\n", reg, count_dw); break; case RADEON_3D_DRAW_IMMD: /* triggers drawing using in-packet vertex data */ @@ -464,12 +522,11 @@ int radeon_cs_parse(struct drm_radeon_cs_parser *parser) case RADEON_CP_NOP: break; default: - DRM_ERROR("unknown packet 3 %x\n", reg); + DRM_ERROR("unknown packet 3 %x at %d\n", reg, count_dw); ret = -EINVAL; } break; } - count_dw += num_dw+2; } -- cgit v1.2.3