From 38835f9cd2b44cfb6587a52ba1bfe292b958d0e1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 28 Jul 2008 15:21:13 +1000 Subject: radeon command submission start take code from Jerome munge into a TTM IB re-use --- shared-core/radeon_cs.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 shared-core/radeon_cs.c (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c new file mode 100644 index 00000000..61fef79d --- /dev/null +++ b/shared-core/radeon_cs.c @@ -0,0 +1,181 @@ +/* + * Copyright 2008 Jerome Glisse. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Jerome Glisse + */ +#include "drmP.h" +#include "radeon_drm.h" +#include "radeon_drv.h" +#include "r300_reg.h" + +int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) +{ + struct drm_radeon_private *radeon = dev->dev_private; + struct drm_radeon_cs *cs = data; + uint32_t *packets = NULL; + uint32_t cs_id; + void *ib = NULL; + long size; + int r; + + /* set command stream id to 0 which is fake id */ + cs_id = 0; + DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); + + if (radeon == NULL) { + DRM_ERROR("called with no initialization\n"); + return -EINVAL; + } + if (!cs->dwords) { + return 0; + } + /* limit cs to 64K ib */ + if (cs->dwords > (16 * 1024)) { + return -EINVAL; + } + /* copy cs from userspace maybe we should copy into ib to save + * one copy but ib will be mapped wc so not good for cmd checking + * somethings worth testing i guess (Jerome) + */ + size = cs->dwords * sizeof(uint32_t); + packets = drm_alloc(size, DRM_MEM_DRIVER); + if (packets == NULL) { + return -ENOMEM; + } + if (DRM_COPY_FROM_USER(packets, (void __user *)(unsigned long)cs->packets, size)) { + r = -EFAULT; + goto out; + } + /* get ib */ + r = radeon->cs.ib_get(dev, &ib, cs->dwords); + if (r) { + goto out; + } + + /* now parse command stream */ + r = radeon->cs.parse(dev, ib, packets, cs->dwords); + if (r) { + goto out; + } + + /* emit cs id sequence */ + radeon->cs.id_emit(dev, &cs_id); + DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); +out: + radeon->cs.ib_free(dev, ib, cs->dwords); + drm_free(packets, size, DRM_MEM_DRIVER); + return r; +} + +int radeon_cs_parse(struct drm_device *dev, void *ib, + uint32_t *packets, uint32_t dwords) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + volatile int rb; + + /* copy the packet into the IB */ + memcpy(ib, packets, dwords * sizeof(uint32_t)); + + /* read back last byte to flush WC buffers */ + rb = readl((ib + (dwords-1) * sizeof(uint32_t))); + + return 0; +} + +uint32_t radeon_cs_id_get(struct drm_radeon_private *radeon) +{ + /* FIXME: protect with a spinlock */ + /* FIXME: check if wrap affect last reported wrap & sequence */ + radeon->cs.id_scnt = (radeon->cs.id_scnt + 1) & 0x00FFFFFF; + if (!radeon->cs.id_scnt) { + /* increment wrap counter */ + radeon->cs.id_wcnt += 0x01000000; + /* valid sequence counter start at 1 */ + radeon->cs.id_scnt = 1; + } + return (radeon->cs.id_scnt | radeon->cs.id_wcnt); +} + +void r100_cs_id_emit(struct drm_device *dev, uint32_t *id) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + /* ISYNC_CNTL should have CPSCRACTH bit set */ + *id = radeon_cs_id_get(dev_priv); + /* emit id in SCRATCH4 (not used yet in old drm) */ + BEGIN_RING(2); + OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG4, 0)); + OUT_RING(*id); + ADVANCE_RING(); +} + +void r300_cs_id_emit(struct drm_device *dev, uint32_t *id) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + /* ISYNC_CNTL should not have CPSCRACTH bit set */ + *id = radeon_cs_id_get(dev_priv); + /* emit id in SCRATCH6 */ + BEGIN_RING(6); + OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 0)); + OUT_RING(6); + OUT_RING(CP_PACKET0(R300_CP_RESYNC_DATA, 0)); + OUT_RING(*id); + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + OUT_RING(R300_RB3D_DC_FINISH); + ADVANCE_RING(); +} + +uint32_t r100_cs_id_last_get(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + return RADEON_READ(RADEON_SCRATCH_REG4); +} + +uint32_t r300_cs_id_last_get(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + return RADEON_READ(RADEON_SCRATCH_REG6); +} + +int radeon_cs_init(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + if (dev_priv->chip_family < CHIP_RV280) { + dev_priv->cs.id_emit = r100_cs_id_emit; + dev_priv->cs.id_last_get = r100_cs_id_last_get; + } else if (dev_priv->chip_family < CHIP_R600) { + dev_priv->cs.id_emit = r300_cs_id_emit; + dev_priv->cs.id_last_get = r300_cs_id_last_get; + } + + dev_priv->cs.parse = radeon_cs_parse; + /* ib get depends on memory manager or not so memory manager */ + return 0; +} -- cgit v1.2.3 From dc3a7c023dd089150ee2dc40755fde348252bedb Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 28 Jul 2008 17:27:24 +1000 Subject: r300: initial command stream parser for packet 0. this at least parses the DDX stream and lets me run gnome-terminal/metacity --- shared-core/radeon_cs.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index 61fef79d..8c2aea89 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -88,11 +88,84 @@ out: return r; } +int radeon_cs_packet0(struct drm_device *dev, uint32_t *packets, + uint32_t offset_dw) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + int hdr = packets[offset_dw]; + int num_dw = ((hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2; + int need_reloc = 0; + int reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2; + int count_dw = 1; + int ret; + + while (count_dw < num_dw) { + /* need to have something like the r300 validation here - + list of allowed registers */ + int flags; + + ret = r300_check_range(reg, 1); + switch(ret) { + case -1: + DRM_ERROR("Illegal register %x\n", reg); + break; + case 0: + break; + case 1: + flags = r300_get_reg_flags(reg); + if (flags == MARK_CHECK_OFFSET) + DRM_DEBUG("need to relocate %x %d\n", reg, flags); + 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); + return -EINVAL; + } + break; + } + count_dw++; + reg += 4; + } + return 0; +} + int radeon_cs_parse(struct drm_device *dev, void *ib, uint32_t *packets, uint32_t dwords) { drm_radeon_private_t *dev_priv = dev->dev_private; volatile int rb; + int size_dw = dwords; + /* scan the packet for various things */ + int count_dw = 0; + int ret = 0; + + while (count_dw < size_dw && ret == 0) { + int hdr = packets[count_dw]; + int num_dw = (hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16; + int reg; + + switch (hdr & RADEON_CP_PACKET_MASK) { + case RADEON_CP_PACKET0: + ret = radeon_cs_packet0(dev, packets, count_dw); + break; + case RADEON_CP_PACKET1: + case RADEON_CP_PACKET2: + reg = hdr & RADEON_CP_PACKET0_REG_MASK; + DRM_DEBUG("Packet 1/2: %d %x\n", num_dw, reg); + break; + + case RADEON_CP_PACKET3: + reg = hdr & 0xff00; + DRM_DEBUG("Packet 3: %d %x\n", num_dw, reg); + break; + } + + count_dw += num_dw+2; + } + + if (ret) + return ret; + /* copy the packet into the IB */ memcpy(ib, packets, dwords * sizeof(uint32_t)); -- cgit v1.2.3 From 87520347b45e2f40a2d84831538a38d6a8d92439 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 28 Jul 2008 17:42:53 +1000 Subject: r300: add some packet 3 decodes --- shared-core/radeon_cs.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index 8c2aea89..00860c2e 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -156,7 +156,25 @@ int radeon_cs_parse(struct drm_device *dev, void *ib, case RADEON_CP_PACKET3: reg = hdr & 0xff00; - DRM_DEBUG("Packet 3: %d %x\n", num_dw, reg); + + switch(reg) { + case RADEON_CNTL_HOSTDATA_BLT: + 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); + break; + + case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ + case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ + case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ + case RADEON_WAIT_FOR_IDLE: + case RADEON_CP_NOP: + break; + default: + DRM_ERROR("unknown packet 3 %x\n", reg); + ret = -EINVAL; + } break; } -- cgit v1.2.3 From 42e373e903d960b38c605229ab102933b18cff73 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 28 Jul 2008 18:18:28 +1000 Subject: radeon_cs: extract some offsets from packet data --- shared-core/radeon_cs.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index 00860c2e..5cfe85be 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -88,6 +88,31 @@ out: return r; } +static __inline__ int radeon_cs_check_offset(struct drm_device *dev, + uint32_t reg, uint32_t val) +{ + uint32_t offset; + + switch(reg) { + case RADEON_DST_PITCH_OFFSET: + case RADEON_SRC_PITCH_OFFSET: + offset = val & ((1 << 22) - 1); + offset <<= 10; + break; + case R300_RB3D_COLOROFFSET0: + case R300_RB3D_DEPTHOFFSET: + offset = val; + break; + case R300_TX_OFFSET_0: + case R300_TX_OFFSET_0+4: + offset = val & 0xffffffe0; + break; + } + + DRM_ERROR("Offset check %x %x\n", reg, offset); + return 0; +} + int radeon_cs_packet0(struct drm_device *dev, uint32_t *packets, uint32_t offset_dw) { @@ -113,9 +138,11 @@ int radeon_cs_packet0(struct drm_device *dev, uint32_t *packets, break; case 1: flags = r300_get_reg_flags(reg); - if (flags == MARK_CHECK_OFFSET) + if (flags == MARK_CHECK_OFFSET) { + radeon_cs_check_offset(dev, reg, packets[offset_dw+count_dw]); + DRM_DEBUG("need to relocate %x %d\n", reg, flags); - else if (flags == MARK_CHECK_SCISSOR) { + } 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); @@ -159,6 +186,13 @@ int radeon_cs_parse(struct drm_device *dev, void *ib, switch(reg) { case RADEON_CNTL_HOSTDATA_BLT: + { + uint32_t offset; + offset = packets[count_dw+2] & ((1 << 22) - 1); + offset <<= 10; + DRM_ERROR("Offset check for Packet 3 %x %x\n", reg, offset); + break; + } case RADEON_CNTL_BITBLT_MULTI: case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */ case RADEON_CP_INDX_BUFFER: -- cgit v1.2.3 From 4234f82acc70f41e005d8cc301da56634352425c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 29 Jul 2008 16:51:47 +1000 Subject: radeon_cs: add relocate hook for mm and non-mm relocations --- shared-core/radeon_cs.c | 90 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 9 deletions(-) (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index 5cfe85be..f01334bc 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -74,7 +74,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) } /* now parse command stream */ - r = radeon->cs.parse(dev, ib, packets, cs->dwords); + r = radeon->cs.parse(dev, fpriv, ib, packets, cs->dwords); if (r) { goto out; } @@ -88,6 +88,69 @@ out: return r; } +/* for non-mm */ +static int radeon_nomm_relocate(struct drm_device *dev, struct drm_file *file_priv, uint32_t *reloc, uint32_t *offset) +{ + *offset = reloc[1]; + return 0; +} +#define RELOC_SIZE 2 +#define RADEON_2D_OFFSET_MASK 0x3fffff + +static __inline__ int radeon_cs_relocate_offset(struct drm_device *dev, struct drm_file *file_priv, + uint32_t *packets, uint32_t offset_dw) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + uint32_t hdr = packets[offset_dw]; + uint32_t reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2; + uint32_t val = packets[offset_dw + 1]; + uint32_t packet3_hdr = packets[offset_dw+2]; + uint32_t tmp, offset; + int ret; + + /* this is too strict we may want to expand the length in the future and have + old kernels ignore it. */ + if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16))) { + DRM_ERROR("Packet 3 was %x should have been %x\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16)); + return -EINVAL; + } + + switch(reg) { + case RADEON_DST_PITCH_OFFSET: + case RADEON_SRC_PITCH_OFFSET: + /* pass in the start of the reloc */ + ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + 2, &offset); + if (ret) + return ret; + tmp = (val & RADEON_2D_OFFSET_MASK) << 10; + val &= ~RADEON_2D_OFFSET_MASK; + offset += tmp; + offset >>= 10; + val |= offset; + break; + case R300_RB3D_COLOROFFSET0: + case R300_RB3D_DEPTHOFFSET: + case R300_TX_OFFSET_0: + case R300_TX_OFFSET_0+4: + offset = packets[offset_dw + 3]; + + ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + 2, &offset); + if (ret) + return ret; + + offset &= 0xffffffe0; + val += offset; + break; + default: + break; + } + + + DRM_ERROR("New offset %x %x %x\n", packets[offset_dw+1], val, offset); + packets[offset_dw + 1] = val; + + return 0; +} static __inline__ int radeon_cs_check_offset(struct drm_device *dev, uint32_t reg, uint32_t val) { @@ -113,11 +176,11 @@ static __inline__ int radeon_cs_check_offset(struct drm_device *dev, return 0; } -int radeon_cs_packet0(struct drm_device *dev, uint32_t *packets, - uint32_t offset_dw) +int radeon_cs_packet0(struct drm_device *dev, struct drm_file *file_priv, + uint32_t *packets, uint32_t offset_dw) { drm_radeon_private_t *dev_priv = dev->dev_private; - int hdr = packets[offset_dw]; + uint32_t hdr = packets[offset_dw]; int num_dw = ((hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2; int need_reloc = 0; int reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2; @@ -139,9 +202,16 @@ int radeon_cs_packet0(struct drm_device *dev, uint32_t *packets, case 1: flags = r300_get_reg_flags(reg); if (flags == MARK_CHECK_OFFSET) { - radeon_cs_check_offset(dev, reg, packets[offset_dw+count_dw]); - + if (num_dw > 2) { + DRM_ERROR("Cannot relocate inside type stream of reg0 packets\n"); + return -EINVAL; + } + + ret = radeon_cs_relocate_offset(dev, file_priv, packets, offset_dw); + if (ret) + return ret; DRM_DEBUG("need to relocate %x %d\n", reg, flags); + /* okay it should be followed by a NOP */ } else if (flags == MARK_CHECK_SCISSOR) { DRM_DEBUG("need to validate scissor %x %d\n", reg, flags); } else { @@ -156,8 +226,8 @@ int radeon_cs_packet0(struct drm_device *dev, uint32_t *packets, return 0; } -int radeon_cs_parse(struct drm_device *dev, void *ib, - uint32_t *packets, uint32_t dwords) +int radeon_cs_parse(struct drm_device *dev, struct drm_file *file_priv, + void *ib, uint32_t *packets, uint32_t dwords) { drm_radeon_private_t *dev_priv = dev->dev_private; volatile int rb; @@ -173,7 +243,7 @@ int radeon_cs_parse(struct drm_device *dev, void *ib, switch (hdr & RADEON_CP_PACKET_MASK) { case RADEON_CP_PACKET0: - ret = radeon_cs_packet0(dev, packets, count_dw); + ret = radeon_cs_packet0(dev, file_priv, packets, count_dw); break; case RADEON_CP_PACKET1: case RADEON_CP_PACKET2: @@ -191,6 +261,7 @@ int radeon_cs_parse(struct drm_device *dev, void *ib, offset = packets[count_dw+2] & ((1 << 22) - 1); offset <<= 10; DRM_ERROR("Offset check for Packet 3 %x %x\n", reg, offset); + /* okay it should be followed by a NOP */ break; } case RADEON_CNTL_BITBLT_MULTI: @@ -302,5 +373,6 @@ int radeon_cs_init(struct drm_device *dev) dev_priv->cs.parse = radeon_cs_parse; /* ib get depends on memory manager or not so memory manager */ + dev_priv->cs.relocate = radeon_nomm_relocate; return 0; } -- cgit v1.2.3 From 0452be882607f2d1601f4e592a11ccf543f5f9ca Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 29 Jul 2008 18:05:11 +1000 Subject: radeon: move code around putting emit into cs --- shared-core/radeon_cs.c | 76 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 57 insertions(+), 19 deletions(-) (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index f01334bc..33a8ccd4 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -31,19 +31,21 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) { - struct drm_radeon_private *radeon = dev->dev_private; + struct drm_radeon_private *dev_priv = dev->dev_private; struct drm_radeon_cs *cs = data; uint32_t *packets = NULL; uint32_t cs_id; + uint32_t card_offset; void *ib = NULL; long size; int r; + RING_LOCALS; /* set command stream id to 0 which is fake id */ cs_id = 0; DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); - if (radeon == NULL) { + if (dev_priv == NULL) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -68,22 +70,31 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) goto out; } /* get ib */ - r = radeon->cs.ib_get(dev, &ib, cs->dwords); + r = dev_priv->cs.ib_get(dev, &ib, cs->dwords, &card_offset); if (r) { goto out; } /* now parse command stream */ - r = radeon->cs.parse(dev, fpriv, ib, packets, cs->dwords); + r = dev_priv->cs.parse(dev, fpriv, ib, packets, cs->dwords); if (r) { goto out; } + BEGIN_RING(4); + OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); + OUT_RING(card_offset); + OUT_RING(cs->dwords); + OUT_RING(CP_PACKET2()); + ADVANCE_RING(); + /* emit cs id sequence */ - radeon->cs.id_emit(dev, &cs_id); + dev_priv->cs.id_emit(dev, &cs_id); + COMMIT_RING(); + DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); out: - radeon->cs.ib_free(dev, ib, cs->dwords); + dev_priv->cs.ib_free(dev, ib, cs->dwords); drm_free(packets, size, DRM_MEM_DRIVER); return r; } @@ -97,8 +108,8 @@ static int radeon_nomm_relocate(struct drm_device *dev, struct drm_file *file_pr #define RELOC_SIZE 2 #define RADEON_2D_OFFSET_MASK 0x3fffff -static __inline__ int radeon_cs_relocate_offset(struct drm_device *dev, struct drm_file *file_priv, - uint32_t *packets, uint32_t offset_dw) +static __inline__ int radeon_cs_relocate_packet0(struct drm_device *dev, struct drm_file *file_priv, + uint32_t *packets, uint32_t offset_dw) { drm_radeon_private_t *dev_priv = dev->dev_private; uint32_t hdr = packets[offset_dw]; @@ -107,7 +118,7 @@ static __inline__ int radeon_cs_relocate_offset(struct drm_device *dev, struct d uint32_t packet3_hdr = packets[offset_dw+2]; uint32_t tmp, offset; int ret; - + /* this is too strict we may want to expand the length in the future and have old kernels ignore it. */ if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16))) { @@ -132,8 +143,6 @@ static __inline__ int radeon_cs_relocate_offset(struct drm_device *dev, struct d case R300_RB3D_DEPTHOFFSET: case R300_TX_OFFSET_0: case R300_TX_OFFSET_0+4: - offset = packets[offset_dw + 3]; - ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + 2, &offset); if (ret) return ret; @@ -151,6 +160,40 @@ static __inline__ int radeon_cs_relocate_offset(struct drm_device *dev, struct d return 0; } + +static int radeon_cs_relocate_packet3(struct drm_device *dev, struct drm_file *file_priv, + uint32_t *packets, uint32_t offset_dw) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + uint32_t hdr = packets[offset_dw]; + int num_dw = (hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16; + uint32_t reg = hdr & 0xff00; + uint32_t offset, val, tmp; + int ret; + + switch(reg) { + case RADEON_CNTL_HOSTDATA_BLT: + { + val = packets[offset_dw + 2]; + ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + num_dw + 2, &offset); + if (ret) + return ret; + + tmp = (val & RADEON_2D_OFFSET_MASK) << 10; + val &= ~RADEON_2D_OFFSET_MASK; + offset += tmp; + offset >>= 10; + val |= offset; + + DRM_ERROR("New offset %x %x %x\n", packets[offset_dw+2], val, offset); + packets[offset_dw + 2] = val; + } + default: + return -EINVAL; + } + return 0; +} + static __inline__ int radeon_cs_check_offset(struct drm_device *dev, uint32_t reg, uint32_t val) { @@ -207,7 +250,7 @@ int radeon_cs_packet0(struct drm_device *dev, struct drm_file *file_priv, return -EINVAL; } - ret = radeon_cs_relocate_offset(dev, file_priv, packets, offset_dw); + ret = radeon_cs_relocate_packet0(dev, file_priv, packets, offset_dw); if (ret) return ret; DRM_DEBUG("need to relocate %x %d\n", reg, flags); @@ -256,14 +299,9 @@ int radeon_cs_parse(struct drm_device *dev, struct drm_file *file_priv, switch(reg) { case RADEON_CNTL_HOSTDATA_BLT: - { - uint32_t offset; - offset = packets[count_dw+2] & ((1 << 22) - 1); - offset <<= 10; - DRM_ERROR("Offset check for Packet 3 %x %x\n", reg, offset); - /* okay it should be followed by a NOP */ + radeon_cs_relocate_packet3(dev, file_priv, packets, count_dw); break; - } + case RADEON_CNTL_BITBLT_MULTI: case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */ case RADEON_CP_INDX_BUFFER: -- cgit v1.2.3 From 58df2fa0ecc7e4dac83b4e7a72d70c3ea41c7ed2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 14 Aug 2008 09:14:56 +1000 Subject: radeon: remove debugging --- shared-core/radeon_cs.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index 33a8ccd4..d961189e 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -154,10 +154,7 @@ static __inline__ int radeon_cs_relocate_packet0(struct drm_device *dev, struct break; } - - DRM_ERROR("New offset %x %x %x\n", packets[offset_dw+1], val, offset); packets[offset_dw + 1] = val; - return 0; } @@ -185,7 +182,6 @@ static int radeon_cs_relocate_packet3(struct drm_device *dev, struct drm_file *f offset >>= 10; val |= offset; - DRM_ERROR("New offset %x %x %x\n", packets[offset_dw+2], val, offset); packets[offset_dw + 2] = val; } default: @@ -215,7 +211,6 @@ static __inline__ int radeon_cs_check_offset(struct drm_device *dev, break; } - DRM_ERROR("Offset check %x %x\n", reg, offset); return 0; } -- cgit v1.2.3 From 3a497db7862dc091a8582d8ea3ebfd7fe0f16b58 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 18 Sep 2008 10:22:23 +1000 Subject: radeon: fixup buffer and cs bits --- shared-core/radeon_cs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index b0c4abe8..a00ec21b 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -368,13 +368,14 @@ void r300_cs_id_emit(struct drm_device *dev, uint32_t *id) /* ISYNC_CNTL should not have CPSCRACTH bit set */ *id = radeon_cs_id_get(dev_priv); /* emit id in SCRATCH6 */ - BEGIN_RING(6); + BEGIN_RING(8); OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 0)); OUT_RING(6); OUT_RING(CP_PACKET0(R300_CP_RESYNC_DATA, 0)); OUT_RING(*id); OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); OUT_RING(R300_RB3D_DC_FINISH); + RADEON_WAIT_UNTIL_3D_IDLE(); ADVANCE_RING(); } -- cgit v1.2.3 From 8d9a11c55cf3692bd537c68044b4378aba53f438 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 16 Oct 2008 10:57:31 +1000 Subject: radeon: add CS support for r100/r200 in 2D driver --- shared-core/radeon_cs.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index a00ec21b..f9147136 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -139,10 +139,15 @@ static __inline__ int radeon_cs_relocate_packet0(struct drm_device *dev, struct offset >>= 10; val |= offset; break; + case RADEON_RB3D_COLOROFFSET: case R300_RB3D_COLOROFFSET0: case R300_ZB_DEPTHOFFSET: case R300_TX_OFFSET_0: case R300_TX_OFFSET_0+4: + case R200_PP_TXOFFSET_0: + case R200_PP_TXOFFSET_1: + case RADEON_PP_TXOFFSET_0: + case RADEON_PP_TXOFFSET_1: ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + 2, &offset); if (ret) return ret; -- cgit v1.2.3 From b09cb93e2d188228e26135149786ee231cd9b11d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Nov 2008 09:23:19 +1000 Subject: radeon: add some more r100 support to test AGP --- shared-core/radeon_cs.c | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index f9147136..3e47ad12 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -122,7 +122,7 @@ static __inline__ int radeon_cs_relocate_packet0(struct drm_device *dev, struct /* this is too strict we may want to expand the length in the future and have old kernels ignore it. */ if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16))) { - DRM_ERROR("Packet 3 was %x should have been %x\n", 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); return -EINVAL; } @@ -195,30 +195,6 @@ static int radeon_cs_relocate_packet3(struct drm_device *dev, struct drm_file *f return 0; } -static __inline__ int radeon_cs_check_offset(struct drm_device *dev, - uint32_t reg, uint32_t val) -{ - uint32_t offset; - - switch(reg) { - case RADEON_DST_PITCH_OFFSET: - case RADEON_SRC_PITCH_OFFSET: - offset = val & ((1 << 22) - 1); - offset <<= 10; - break; - case R300_RB3D_COLOROFFSET0: - case R300_ZB_DEPTHOFFSET: - offset = val; - break; - case R300_TX_OFFSET_0: - case R300_TX_OFFSET_0+4: - offset = val & 0xffffffe0; - break; - } - - return 0; -} - int radeon_cs_packet0(struct drm_device *dev, struct drm_file *file_priv, uint32_t *packets, uint32_t offset_dw) { @@ -308,6 +284,7 @@ int radeon_cs_parse(struct drm_device *dev, struct drm_file *file_priv, DRM_ERROR("need relocate packet 3 for %x\n", reg); break; + case RADEON_3D_DRAW_IMMD: /* triggers drawing using in-packet vertex data */ case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ -- cgit v1.2.3 From 3fd0e1483ebe640b69da888e286ea85d11539b46 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Nov 2008 09:29:22 +1000 Subject: radeon: fixup scratch register interactions properly --- shared-core/radeon_cs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index 3e47ad12..b5982894 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -365,14 +365,14 @@ uint32_t r100_cs_id_last_get(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; - return RADEON_READ(RADEON_SCRATCH_REG4); + return GET_SCRATCH(4); } uint32_t r300_cs_id_last_get(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; - return RADEON_READ(RADEON_SCRATCH_REG6); + return GET_SCRATCH(6); } int radeon_cs_init(struct drm_device *dev) -- cgit v1.2.3 From 8b2925468d326ab6fa31a312e845a3bc71343106 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Nov 2008 09:39:53 +1000 Subject: radeon: make new CS2 command submission interface port older interface to this --- shared-core/radeon_cs.c | 257 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 217 insertions(+), 40 deletions(-) (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index b5982894..452f04b4 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -29,16 +29,163 @@ #include "radeon_drv.h" #include "r300_reg.h" +int radeon_cs2_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) +{ + struct drm_radeon_cs_parser parser; + struct drm_radeon_private *dev_priv = dev->dev_private; + struct drm_radeon_cs2 *cs = data; + uint32_t cs_id; + struct drm_radeon_cs_chunk __user **chunk_ptr = NULL; + uint64_t *chunk_array; + uint64_t *chunk_array_ptr; + uint32_t card_offset; + long size; + int r, i; + RING_LOCALS; + + /* set command stream id to 0 which is fake id */ + cs_id = 0; + DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); + + if (dev_priv == NULL) { + DRM_ERROR("called with no initialization\n"); + return -EINVAL; + } + if (!cs->num_chunks) { + return 0; + } + + + chunk_array = drm_calloc(cs->num_chunks, sizeof(uint64_t), DRM_MEM_DRIVER); + if (!chunk_array) { + return -ENOMEM; + } + + chunk_array_ptr = (uint64_t *)(unsigned long)(cs->chunks); + + if (DRM_COPY_FROM_USER(chunk_array, chunk_array_ptr, sizeof(uint64_t)*cs->num_chunks)) { + r = -EFAULT; + goto out; + } + + parser.reloc_index = -1; + parser.ib_index = -1; + parser.num_chunks = cs->num_chunks; + /* copy out the chunk headers */ + parser.chunks = drm_calloc(parser.num_chunks, sizeof(struct drm_radeon_kernel_chunk), DRM_MEM_DRIVER); + if (!parser.chunks) { + return -ENOMEM; + } + + for (i = 0; i < parser.num_chunks; i++) { + struct drm_radeon_cs_chunk user_chunk; + + chunk_ptr = (void __user *)(unsigned long)chunk_array[i]; + + if (DRM_COPY_FROM_USER(&user_chunk, chunk_ptr, sizeof(struct drm_radeon_cs_chunk))){ + r = -EFAULT; + goto out; + } + parser.chunks[i].chunk_id = user_chunk.chunk_id; + + if (parser.chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS) + parser.reloc_index = i; + + if (parser.chunks[i].chunk_id == RADEON_CHUNK_ID_IB) + parser.ib_index = i; + + if (parser.chunks[i].chunk_id == RADEON_CHUNK_ID_OLD) { + parser.ib_index = i; + parser.reloc_index = -1; + } + + parser.chunks[i].length_dw = user_chunk.length_dw; + parser.chunks[i].chunk_data = (uint32_t *)(unsigned long)user_chunk.chunk_data; + + parser.chunks[i].kdata = NULL; + + switch(parser.chunks[i].chunk_id) { + case RADEON_CHUNK_ID_RELOCS: + case RADEON_CHUNK_ID_IB: + case RADEON_CHUNK_ID_OLD: { + /* copy from user the relocs chunk */ + int size = parser.chunks[i].length_dw * sizeof(uint32_t); + parser.chunks[i].kdata = drm_alloc(size, DRM_MEM_DRIVER); + if (!parser.chunks[i].kdata) { + r = -ENOMEM; + goto out; + } + + if (DRM_COPY_FROM_USER(parser.chunks[i].kdata, parser.chunks[i].chunk_data, size)) { + r = -EFAULT; + goto out; + } + } + break; + default: + break; + } + DRM_DEBUG("chunk %d %d %d %p\n", i, parser.chunks[i].chunk_id, parser.chunks[i].length_dw, + parser.chunks[i].chunk_data); + } + + + if (parser.chunks[parser.ib_index].length_dw > (16 * 1024)) { + DRM_ERROR("cs->dwords too big: %d\n", parser.chunks[parser.ib_index].length_dw); + r = -EINVAL; + goto out; + } + + /* get ib */ + r = dev_priv->cs.ib_get(&parser, &card_offset); + if (r) { + DRM_ERROR("ib_get failed\n"); + goto out; + } + + /* now parse command stream */ + r = dev_priv->cs.parse(&parser); + if (r) { + goto out; + } + + BEGIN_RING(4); + OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); + OUT_RING(card_offset); + OUT_RING(parser.chunks[parser.ib_index].length_dw); + OUT_RING(CP_PACKET2()); + ADVANCE_RING(); + + /* emit cs id sequence */ + dev_priv->cs.id_emit(dev, &cs_id); + COMMIT_RING(); + + DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); +out: + dev_priv->cs.ib_free(&parser); + + for (i = 0; i < parser.num_chunks; i++) { + if (parser.chunks[i].kdata) + drm_free(parser.chunks[i].kdata, parser.chunks[i].length_dw * sizeof(uint32_t), DRM_MEM_DRIVER); + } + + drm_free(parser.chunks, sizeof(struct drm_radeon_kernel_chunk)*parser.num_chunks, DRM_MEM_DRIVER); + drm_free(chunk_array, sizeof(uint64_t)*parser.num_chunks, DRM_MEM_DRIVER); + + return r; +} + int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) { + struct drm_radeon_cs_parser parser; struct drm_radeon_private *dev_priv = dev->dev_private; struct drm_radeon_cs *cs = data; uint32_t *packets = NULL; uint32_t cs_id; uint32_t card_offset; - void *ib = NULL; long size; int r; + struct drm_radeon_kernel_chunk chunk_fake[1]; RING_LOCALS; /* set command stream id to 0 which is fake id */ @@ -69,14 +216,26 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) r = -EFAULT; goto out; } + + chunk_fake[0].chunk_id = RADEON_CHUNK_ID_OLD; + chunk_fake[0].length_dw = cs->dwords; + chunk_fake[0].kdata = packets; + + parser.dev = dev; + parser.file_priv = fpriv; + parser.num_chunks = 1; + parser.chunks = chunk_fake; + parser.ib_index = 0; + parser.reloc_index = -1; + /* get ib */ - r = dev_priv->cs.ib_get(dev, &ib, cs->dwords, &card_offset); + r = dev_priv->cs.ib_get(&parser, &card_offset); if (r) { goto out; } /* now parse command stream */ - r = dev_priv->cs.parse(dev, fpriv, ib, packets, cs->dwords); + r = dev_priv->cs.parse(&parser); if (r) { goto out; } @@ -94,13 +253,13 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); out: - dev_priv->cs.ib_free(dev, ib, cs->dwords); + dev_priv->cs.ib_free(&parser); drm_free(packets, size, DRM_MEM_DRIVER); return r; } /* for non-mm */ -static int radeon_nomm_relocate(struct drm_device *dev, struct drm_file *file_priv, uint32_t *reloc, uint32_t *offset) +static int radeon_nomm_relocate(struct drm_radeon_cs_parser *parser, uint32_t *reloc, uint32_t *offset) { *offset = reloc[1]; return 0; @@ -108,17 +267,24 @@ static int radeon_nomm_relocate(struct drm_device *dev, struct drm_file *file_pr #define RELOC_SIZE 2 #define RADEON_2D_OFFSET_MASK 0x3fffff -static __inline__ int radeon_cs_relocate_packet0(struct drm_device *dev, struct drm_file *file_priv, - uint32_t *packets, uint32_t offset_dw) +static __inline__ int radeon_cs_relocate_packet0(struct drm_radeon_cs_parser *parser, uint32_t offset_dw) { + struct drm_device *dev = parser->dev; drm_radeon_private_t *dev_priv = dev->dev_private; - uint32_t hdr = packets[offset_dw]; - uint32_t reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2; - uint32_t val = packets[offset_dw + 1]; - uint32_t packet3_hdr = packets[offset_dw+2]; + uint32_t hdr, reg, val, packet3_hdr; uint32_t tmp, offset; + struct drm_radeon_kernel_chunk *ib_chunk; int ret; + ib_chunk = &parser->chunks[parser->ib_index]; +// if (parser->reloc_index == -1) +// is_old = 1; + + hdr = ib_chunk->kdata[offset_dw]; + reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2; + val = ib_chunk->kdata[offset_dw + 1]; + packet3_hdr = ib_chunk->kdata[offset_dw + 2]; + /* this is too strict we may want to expand the length in the future and have old kernels ignore it. */ if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16))) { @@ -130,7 +296,7 @@ static __inline__ int radeon_cs_relocate_packet0(struct drm_device *dev, struct case RADEON_DST_PITCH_OFFSET: case RADEON_SRC_PITCH_OFFSET: /* pass in the start of the reloc */ - ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + 2, &offset); + ret = dev_priv->cs.relocate(parser, ib_chunk->kdata + offset_dw + 2, &offset); if (ret) return ret; tmp = (val & RADEON_2D_OFFSET_MASK) << 10; @@ -148,7 +314,7 @@ static __inline__ int radeon_cs_relocate_packet0(struct drm_device *dev, struct case R200_PP_TXOFFSET_1: case RADEON_PP_TXOFFSET_0: case RADEON_PP_TXOFFSET_1: - ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + 2, &offset); + ret = dev_priv->cs.relocate(parser. ib_chunk->kdata + offset_dw + 2, &offset); if (ret) return ret; @@ -159,25 +325,32 @@ static __inline__ int radeon_cs_relocate_packet0(struct drm_device *dev, struct break; } - packets[offset_dw + 1] = val; + ib_chunk->kdata[offset_dw + 1] = val; return 0; } -static int radeon_cs_relocate_packet3(struct drm_device *dev, struct drm_file *file_priv, - uint32_t *packets, uint32_t offset_dw) +static int radeon_cs_relocate_packet3(struct drm_radeon_cs_parser *parser, + uint32_t offset_dw) { - drm_radeon_private_t *dev_priv = dev->dev_private; - uint32_t hdr = packets[offset_dw]; - int num_dw = (hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16; - uint32_t reg = hdr & 0xff00; + drm_radeon_private_t *dev_priv = parser->dev->dev_private; + uint32_t hdr, num_dw, reg; uint32_t offset, val, tmp; int ret; + struct drm_radeon_kernel_chunk *ib_chunk; + + ib_chunk = &parser->chunks[parser->ib_index]; +// if (parser->reloc_index == -1) +// is_old = 1; + + hdr = ib_chunk->kdata[offset_dw]; + num_dw = (hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16; + reg = hdr & 0xff00; switch(reg) { case RADEON_CNTL_HOSTDATA_BLT: { - val = packets[offset_dw + 2]; - ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + num_dw + 2, &offset); + val = ib_chunk->kdata[offset_dw + 2]; + ret = dev_priv->cs.relocate(parser, ib_chunk->kdata + offset_dw + num_dw + 2, &offset); if (ret) return ret; @@ -187,7 +360,7 @@ static int radeon_cs_relocate_packet3(struct drm_device *dev, struct drm_file *f offset >>= 10; val |= offset; - packets[offset_dw + 2] = val; + ib_chunk->kdata[offset_dw + 2] = val; } default: return -EINVAL; @@ -195,17 +368,18 @@ static int radeon_cs_relocate_packet3(struct drm_device *dev, struct drm_file *f return 0; } -int radeon_cs_packet0(struct drm_device *dev, struct drm_file *file_priv, - uint32_t *packets, uint32_t offset_dw) +int radeon_cs_packet0(struct drm_radeon_cs_parser *parser, uint32_t offset_dw) { - drm_radeon_private_t *dev_priv = dev->dev_private; - uint32_t hdr = packets[offset_dw]; - int num_dw = ((hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2; + drm_radeon_private_t *dev_priv = parser->dev->dev_private; + uint32_t hdr, num_dw, reg; int need_reloc = 0; - int reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2; int count_dw = 1; int ret; + hdr = parser->chunks[parser->ib_index].kdata[offset_dw]; + num_dw = ((hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2; + reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2; + while (count_dw < num_dw) { /* need to have something like the r300 validation here - list of allowed registers */ @@ -226,7 +400,7 @@ int radeon_cs_packet0(struct drm_device *dev, struct drm_file *file_priv, return -EINVAL; } - ret = radeon_cs_relocate_packet0(dev, file_priv, packets, offset_dw); + ret = radeon_cs_relocate_packet0(parser, offset_dw); if (ret) return ret; DRM_DEBUG("need to relocate %x %d\n", reg, flags); @@ -245,24 +419,27 @@ int radeon_cs_packet0(struct drm_device *dev, struct drm_file *file_priv, return 0; } -int radeon_cs_parse(struct drm_device *dev, struct drm_file *file_priv, - void *ib, uint32_t *packets, uint32_t dwords) +int radeon_cs_parse(struct drm_radeon_cs_parser *parser) { - drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_device *dev = parser->dev; + drm_radeon_private_t *dev_priv = parser->dev->dev_private; volatile int rb; - int size_dw = dwords; + struct drm_radeon_kernel_chunk *ib_chunk; /* scan the packet for various things */ - int count_dw = 0; + int count_dw = 0, size_dw; int ret = 0; + ib_chunk = &parser->chunks[parser->ib_index]; + size_dw = ib_chunk->length_dw; + while (count_dw < size_dw && ret == 0) { - int hdr = packets[count_dw]; + int hdr = ib_chunk->kdata[count_dw]; int num_dw = (hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16; int reg; switch (hdr & RADEON_CP_PACKET_MASK) { case RADEON_CP_PACKET0: - ret = radeon_cs_packet0(dev, file_priv, packets, count_dw); + ret = radeon_cs_packet0(parser, count_dw); break; case RADEON_CP_PACKET1: case RADEON_CP_PACKET2: @@ -275,7 +452,7 @@ int radeon_cs_parse(struct drm_device *dev, struct drm_file *file_priv, switch(reg) { case RADEON_CNTL_HOSTDATA_BLT: - radeon_cs_relocate_packet3(dev, file_priv, packets, count_dw); + radeon_cs_relocate_packet3(parser, count_dw); break; case RADEON_CNTL_BITBLT_MULTI: @@ -306,10 +483,10 @@ int radeon_cs_parse(struct drm_device *dev, struct drm_file *file_priv, /* copy the packet into the IB */ - memcpy(ib, packets, dwords * sizeof(uint32_t)); + memcpy(parser->ib, ib_chunk->kdata, ib_chunk->length_dw * sizeof(uint32_t)); /* read back last byte to flush WC buffers */ - rb = readl((ib + (dwords-1) * sizeof(uint32_t))); + rb = readl((parser->ib + (ib_chunk->length_dw-1) * sizeof(uint32_t))); return 0; } -- cgit v1.2.3 From 35f080559287ebf30f417337fa124d827709503b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Nov 2008 09:40:24 +1000 Subject: radeon: don't copy to user the cs ids --- shared-core/radeon_cs.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index 452f04b4..14f3dcd9 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -45,7 +45,7 @@ int radeon_cs2_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) /* set command stream id to 0 which is fake id */ cs_id = 0; - DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); + cs->cs_id = cs_id; if (dev_priv == NULL) { DRM_ERROR("called with no initialization\n"); @@ -160,7 +160,8 @@ int radeon_cs2_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) dev_priv->cs.id_emit(dev, &cs_id); COMMIT_RING(); - DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); + cs->cs_id = cs_id; + out: dev_priv->cs.ib_free(&parser); @@ -190,7 +191,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) /* set command stream id to 0 which is fake id */ cs_id = 0; - DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); + cs->cs_id = cs_id; if (dev_priv == NULL) { DRM_ERROR("called with no initialization\n"); @@ -251,7 +252,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) dev_priv->cs.id_emit(dev, &cs_id); COMMIT_RING(); - DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); + cs->cs_id = cs_id; out: dev_priv->cs.ib_free(&parser); drm_free(packets, size, DRM_MEM_DRIVER); -- cgit v1.2.3 From 6000fa686294019e93f815433a1a9b44db511a69 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Nov 2008 09:40:52 +1000 Subject: radeon: CS2 make it all work with new relocs style --- shared-core/radeon_cs.c | 52 ++++++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 20 deletions(-) (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index 14f3dcd9..31cd53db 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -68,6 +68,8 @@ int radeon_cs2_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) goto out; } + parser.dev = dev; + parser.file_priv = fpriv; parser.reloc_index = -1; parser.ib_index = -1; parser.num_chunks = cs->num_chunks; @@ -103,24 +105,29 @@ int radeon_cs2_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) parser.chunks[i].chunk_data = (uint32_t *)(unsigned long)user_chunk.chunk_data; parser.chunks[i].kdata = NULL; + size = parser.chunks[i].length_dw * sizeof(uint32_t); switch(parser.chunks[i].chunk_id) { - case RADEON_CHUNK_ID_RELOCS: case RADEON_CHUNK_ID_IB: - case RADEON_CHUNK_ID_OLD: { - /* copy from user the relocs chunk */ - int size = parser.chunks[i].length_dw * sizeof(uint32_t); - parser.chunks[i].kdata = drm_alloc(size, DRM_MEM_DRIVER); - if (!parser.chunks[i].kdata) { - r = -ENOMEM; + case RADEON_CHUNK_ID_OLD: + if (size == 0) { + r = -EINVAL; goto out; } - - if (DRM_COPY_FROM_USER(parser.chunks[i].kdata, parser.chunks[i].chunk_data, size)) { - r = -EFAULT; - goto out; - } - } + case RADEON_CHUNK_ID_RELOCS: + if (size) { + parser.chunks[i].kdata = drm_alloc(size, DRM_MEM_DRIVER); + if (!parser.chunks[i].kdata) { + r = -ENOMEM; + goto out; + } + + if (DRM_COPY_FROM_USER(parser.chunks[i].kdata, parser.chunks[i].chunk_data, size)) { + r = -EFAULT; + goto out; + } + } else + parser.chunks[i].kdata = NULL; break; default: break; @@ -266,6 +273,7 @@ static int radeon_nomm_relocate(struct drm_radeon_cs_parser *parser, uint32_t *r return 0; } #define RELOC_SIZE 2 +#define RELOC_SIZE_NEW 0 #define RADEON_2D_OFFSET_MASK 0x3fffff static __inline__ int radeon_cs_relocate_packet0(struct drm_radeon_cs_parser *parser, uint32_t offset_dw) @@ -288,9 +296,17 @@ static __inline__ int radeon_cs_relocate_packet0(struct drm_radeon_cs_parser *pa /* this is too strict we may want to expand the length in the future and have old kernels ignore it. */ - 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); - return -EINVAL; + 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); + 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); + return -EINVAL; + + } } switch(reg) { @@ -371,9 +387,7 @@ static int radeon_cs_relocate_packet3(struct drm_radeon_cs_parser *parser, int radeon_cs_packet0(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; - int need_reloc = 0; int count_dw = 1; int ret; @@ -422,8 +436,6 @@ int radeon_cs_packet0(struct drm_radeon_cs_parser *parser, uint32_t offset_dw) int radeon_cs_parse(struct drm_radeon_cs_parser *parser) { - struct drm_device *dev = parser->dev; - drm_radeon_private_t *dev_priv = parser->dev->dev_private; volatile int rb; struct drm_radeon_kernel_chunk *ib_chunk; /* scan the packet for various things */ -- cgit v1.2.3 From 31b8a640db9b55638bf9967f0d78ec665fa8839f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Nov 2008 09:46:54 +1000 Subject: radeon: overhaul ring interactions emit in 16-dword blocks, emit irqs at same time as everything else --- shared-core/radeon_cs.c | 84 ++++++++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 32 deletions(-) (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index 31cd53db..4a231962 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -38,10 +38,8 @@ int radeon_cs2_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) struct drm_radeon_cs_chunk __user **chunk_ptr = NULL; uint64_t *chunk_array; uint64_t *chunk_array_ptr; - uint32_t card_offset; long size; int r, i; - RING_LOCALS; /* set command stream id to 0 which is fake id */ cs_id = 0; @@ -144,7 +142,7 @@ int radeon_cs2_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) } /* get ib */ - r = dev_priv->cs.ib_get(&parser, &card_offset); + r = dev_priv->cs.ib_get(&parser); if (r) { DRM_ERROR("ib_get failed\n"); goto out; @@ -156,16 +154,8 @@ int radeon_cs2_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) goto out; } - BEGIN_RING(4); - OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); - OUT_RING(card_offset); - OUT_RING(parser.chunks[parser.ib_index].length_dw); - OUT_RING(CP_PACKET2()); - ADVANCE_RING(); - /* emit cs id sequence */ - dev_priv->cs.id_emit(dev, &cs_id); - COMMIT_RING(); + dev_priv->cs.id_emit(&parser, &cs_id); cs->cs_id = cs_id; @@ -194,7 +184,6 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) long size; int r; struct drm_radeon_kernel_chunk chunk_fake[1]; - RING_LOCALS; /* set command stream id to 0 which is fake id */ cs_id = 0; @@ -237,7 +226,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) parser.reloc_index = -1; /* get ib */ - r = dev_priv->cs.ib_get(&parser, &card_offset); + r = dev_priv->cs.ib_get(&parser); if (r) { goto out; } @@ -248,15 +237,8 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) goto out; } - BEGIN_RING(4); - OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); - OUT_RING(card_offset); - OUT_RING(cs->dwords); - OUT_RING(CP_PACKET2()); - ADVANCE_RING(); - /* emit cs id sequence */ - dev_priv->cs.id_emit(dev, &cs_id); + dev_priv->cs.id_emit(&parser, &cs_id); COMMIT_RING(); cs->cs_id = cs_id; @@ -518,37 +500,75 @@ uint32_t radeon_cs_id_get(struct drm_radeon_private *radeon) return (radeon->cs.id_scnt | radeon->cs.id_wcnt); } -void r100_cs_id_emit(struct drm_device *dev, uint32_t *id) +void r100_cs_id_emit(struct drm_radeon_cs_parser *parser, uint32_t *id) { - drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_private_t *dev_priv = parser->dev->dev_private; RING_LOCALS; + dev_priv->irq_emitted = radeon_update_breadcrumb(parser->dev); /* ISYNC_CNTL should have CPSCRACTH bit set */ *id = radeon_cs_id_get(dev_priv); /* emit id in SCRATCH4 (not used yet in old drm) */ - BEGIN_RING(2); + BEGIN_RING(10); + OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); + OUT_RING(parser->card_offset); + OUT_RING(parser->chunks[parser->ib_index].length_dw); + OUT_RING(CP_PACKET2()); OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG4, 0)); OUT_RING(*id); + OUT_RING_REG(RADEON_LAST_SWI_REG, dev_priv->irq_emitted); + OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE); ADVANCE_RING(); + COMMIT_RING(); + } -void r300_cs_id_emit(struct drm_device *dev, uint32_t *id) +void r300_cs_id_emit(struct drm_radeon_cs_parser *parser, uint32_t *id) { - drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_private_t *dev_priv = parser->dev->dev_private; + int i; RING_LOCALS; + dev_priv->irq_emitted = radeon_update_breadcrumb(parser->dev); + /* ISYNC_CNTL should not have CPSCRACTH bit set */ *id = radeon_cs_id_get(dev_priv); + /* emit id in SCRATCH6 */ - BEGIN_RING(8); - OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 0)); + BEGIN_RING(16); + OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); + OUT_RING(parser->card_offset); + OUT_RING(parser->chunks[parser->ib_index].length_dw); + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + OUT_RING(0); + for (i = 0; i < 11; i++) /* emit fillers like fglrx */ + OUT_RING(CP_PACKET2()); + ADVANCE_RING(); + COMMIT_RING(); + + BEGIN_RING(16); + OUT_RING_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_RB3D_DC_FLUSH); + OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 1)); OUT_RING(6); - OUT_RING(CP_PACKET0(R300_CP_RESYNC_DATA, 0)); OUT_RING(*id); - OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); - OUT_RING(R300_RB3D_DC_FINISH); + OUT_RING_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_RB3D_DC_FINISH|R300_RB3D_DC_FLUSH); + /* emit inline breadcrumb for TTM fencing */ +#if 1 RADEON_WAIT_UNTIL_3D_IDLE(); + OUT_RING_REG(RADEON_LAST_SWI_REG, dev_priv->irq_emitted); +#else + OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 1)); + OUT_RING(3); /* breadcrumb register */ + OUT_RING(dev_priv->irq_emitted); + OUT_RING(CP_PACKET2()); +#endif + OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE); + OUT_RING(CP_PACKET2()); + OUT_RING(CP_PACKET2()); + OUT_RING(CP_PACKET2()); ADVANCE_RING(); + COMMIT_RING(); + } uint32_t r100_cs_id_last_get(struct drm_device *dev) -- cgit v1.2.3 From 68fcb7770efc20b9e27b1724e2fb5ac112a5330e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Nov 2008 09:58:12 +1000 Subject: radeon: make build again --- shared-core/radeon_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index 4a231962..3dde321d 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -313,7 +313,7 @@ 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); + ret = dev_priv->cs.relocate(parser, ib_chunk->kdata + offset_dw + 2, &offset); if (ret) return ret; -- cgit v1.2.3 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 From 7270731a8b7ebe11fe6df4f368c2ed613a530b52 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Sun, 16 Nov 2008 18:11:00 +0100 Subject: radeon: protect cs ioctl atomic part with a mutex A small subset of CS need to be atomic (relocation+IB commit to ring) right now, because of the way relocation are handled, we need to protect the whole ioctl. --- shared-core/radeon_cs.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'shared-core/radeon_cs.c') diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c index 56f6cbac..9227a011 100644 --- a/shared-core/radeon_cs.c +++ b/shared-core/radeon_cs.c @@ -41,21 +41,25 @@ int radeon_cs2_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) long size; int r, i; + mutex_lock(&dev_priv->cs.cs_mutex); /* set command stream id to 0 which is fake id */ cs_id = 0; cs->cs_id = cs_id; if (dev_priv == NULL) { DRM_ERROR("called with no initialization\n"); + mutex_unlock(&dev_priv->cs.cs_mutex); return -EINVAL; } if (!cs->num_chunks) { + mutex_unlock(&dev_priv->cs.cs_mutex); return 0; } chunk_array = drm_calloc(cs->num_chunks, sizeof(uint64_t), DRM_MEM_DRIVER); if (!chunk_array) { + mutex_unlock(&dev_priv->cs.cs_mutex); return -ENOMEM; } @@ -161,6 +165,7 @@ int radeon_cs2_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) out: dev_priv->cs.ib_free(&parser); + mutex_unlock(&dev_priv->cs.cs_mutex); for (i = 0; i < parser.num_chunks; i++) { if (parser.chunks[i].kdata) @@ -646,6 +651,7 @@ int radeon_cs_init(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; + mutex_init(&dev_priv->cs.cs_mutex); if (dev_priv->chip_family < CHIP_RV280) { dev_priv->cs.id_emit = r100_cs_id_emit; dev_priv->cs.id_last_get = r100_cs_id_last_get; -- cgit v1.2.3