Merge branch 'drm-radeon-testing' of /ssd/git/drm-radeon-next into drm-next-stage
[sfrench/cifs-2.6.git] / drivers / gpu / drm / radeon / radeon_state.c
index 067167cb39cafa8444b2358cde28d5bc9e96f167..3c32f840dcd2294b3ee5d0af9407f21c9354209e 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "drmP.h"
 #include "drm.h"
+#include "drm_buffer.h"
 #include "drm_sarea.h"
 #include "radeon_drm.h"
 #include "radeon_drv.h"
@@ -91,21 +92,27 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
 static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
                                                     dev_priv,
                                                     struct drm_file *file_priv,
-                                                    int id, u32 *data)
+                                                    int id, struct drm_buffer *buf)
 {
+       u32 *data;
        switch (id) {
 
        case RADEON_EMIT_PP_MISC:
-               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-                   &data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) {
+               data = drm_buffer_pointer_to_dword(buf,
+                       (RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4);
+
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
                        DRM_ERROR("Invalid depth buffer offset\n");
                        return -EINVAL;
                }
+               dev_priv->have_z_offset = 1;
                break;
 
        case RADEON_EMIT_PP_CNTL:
-               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-                   &data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) {
+               data = drm_buffer_pointer_to_dword(buf,
+                       (RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4);
+
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
                        DRM_ERROR("Invalid colour buffer offset\n");
                        return -EINVAL;
                }
@@ -117,8 +124,8 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
        case R200_EMIT_PP_TXOFFSET_3:
        case R200_EMIT_PP_TXOFFSET_4:
        case R200_EMIT_PP_TXOFFSET_5:
-               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-                                                 &data[0])) {
+               data = drm_buffer_pointer_to_dword(buf, 0);
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
                        DRM_ERROR("Invalid R200 texture offset\n");
                        return -EINVAL;
                }
@@ -127,8 +134,9 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
        case RADEON_EMIT_PP_TXFILTER_0:
        case RADEON_EMIT_PP_TXFILTER_1:
        case RADEON_EMIT_PP_TXFILTER_2:
-               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-                   &data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) {
+               data = drm_buffer_pointer_to_dword(buf,
+                       (RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4);
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
                        DRM_ERROR("Invalid R100 texture offset\n");
                        return -EINVAL;
                }
@@ -142,9 +150,10 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
        case R200_EMIT_PP_CUBIC_OFFSETS_5:{
                        int i;
                        for (i = 0; i < 5; i++) {
+                               data = drm_buffer_pointer_to_dword(buf, i);
                                if (radeon_check_and_fixup_offset(dev_priv,
                                                                  file_priv,
-                                                                 &data[i])) {
+                                                                 data)) {
                                        DRM_ERROR
                                            ("Invalid R200 cubic texture offset\n");
                                        return -EINVAL;
@@ -158,9 +167,10 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
        case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{
                        int i;
                        for (i = 0; i < 5; i++) {
+                               data = drm_buffer_pointer_to_dword(buf, i);
                                if (radeon_check_and_fixup_offset(dev_priv,
                                                                  file_priv,
-                                                                 &data[i])) {
+                                                                 data)) {
                                        DRM_ERROR
                                            ("Invalid R100 cubic texture offset\n");
                                        return -EINVAL;
@@ -269,23 +279,24 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
                                                     cmdbuf,
                                                     unsigned int *cmdsz)
 {
-       u32 *cmd = (u32 *) cmdbuf->buf;
+       u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
        u32 offset, narrays;
        int count, i, k;
 
-       *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
+       count = ((*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16);
+       *cmdsz = 2 + count;
 
-       if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) {
+       if ((*cmd & 0xc0000000) != RADEON_CP_PACKET3) {
                DRM_ERROR("Not a type 3 packet\n");
                return -EINVAL;
        }
 
-       if (4 * *cmdsz > cmdbuf->bufsz) {
+       if (4 * *cmdsz > drm_buffer_unprocessed(cmdbuf->buffer)) {
                DRM_ERROR("Packet size larger than size of data provided\n");
                return -EINVAL;
        }
 
-       switch(cmd[0] & 0xff00) {
+       switch (*cmd & 0xff00) {
        /* XXX Are there old drivers needing other packets? */
 
        case RADEON_3D_DRAW_IMMD:
@@ -312,7 +323,6 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
                break;
 
        case RADEON_3D_LOAD_VBPNTR:
-               count = (cmd[0] >> 16) & 0x3fff;
 
                if (count > 18) { /* 12 arrays max */
                        DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
@@ -321,13 +331,16 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
                }
 
                /* carefully check packet contents */
-               narrays = cmd[1] & ~0xc000;
+               cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
+
+               narrays = *cmd & ~0xc000;
                k = 0;
                i = 2;
                while ((k < narrays) && (i < (count + 2))) {
                        i++;            /* skip attribute field */
+                       cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
                        if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-                                                         &cmd[i])) {
+                                                         cmd)) {
                                DRM_ERROR
                                    ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
                                     k, i);
@@ -338,8 +351,10 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
                        if (k == narrays)
                                break;
                        /* have one more to process, they come in pairs */
+                       cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
+
                        if (radeon_check_and_fixup_offset(dev_priv,
-                                                         file_priv, &cmd[i]))
+                                                         file_priv, cmd))
                        {
                                DRM_ERROR
                                    ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
@@ -363,7 +378,9 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
                        DRM_ERROR("Invalid 3d packet for r200-class chip\n");
                        return -EINVAL;
                }
-               if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[1])) {
+
+               cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv, cmd)) {
                                DRM_ERROR("Invalid rndr_gen_indx offset\n");
                                return -EINVAL;
                }
@@ -374,12 +391,15 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
                        DRM_ERROR("Invalid 3d packet for r100-class chip\n");
                        return -EINVAL;
                }
-               if ((cmd[1] & 0x8000ffff) != 0x80000810) {
-                       DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
+
+               cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
+               if ((*cmd & 0x8000ffff) != 0x80000810) {
+                       DRM_ERROR("Invalid indx_buffer reg address %08X\n", *cmd);
                        return -EINVAL;
                }
-               if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[2])) {
-                       DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
+               cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv, cmd)) {
+                       DRM_ERROR("Invalid indx_buffer offset is %08X\n", *cmd);
                        return -EINVAL;
                }
                break;
@@ -388,31 +408,34 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
        case RADEON_CNTL_PAINT_MULTI:
        case RADEON_CNTL_BITBLT_MULTI:
                /* MSB of opcode: next DWORD GUI_CNTL */
-               if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
+               cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
+               if (*cmd & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
                              | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
-                       offset = cmd[2] << 10;
+                       u32 *cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
+                       offset = *cmd2 << 10;
                        if (radeon_check_and_fixup_offset
                            (dev_priv, file_priv, &offset)) {
                                DRM_ERROR("Invalid first packet offset\n");
                                return -EINVAL;
                        }
-                       cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10;
+                       *cmd2 = (*cmd2 & 0xffc00000) | offset >> 10;
                }
 
-               if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
-                   (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
-                       offset = cmd[3] << 10;
+               if ((*cmd & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
+                   (*cmd & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
+                       u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3);
+                       offset = *cmd << 10;
                        if (radeon_check_and_fixup_offset
                            (dev_priv, file_priv, &offset)) {
                                DRM_ERROR("Invalid second packet offset\n");
                                return -EINVAL;
                        }
-                       cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10;
+                       *cmd3 = (*cmd3 & 0xffc00000) | offset >> 10;
                }
                break;
 
        default:
-               DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00);
+               DRM_ERROR("Invalid packet type %x\n", *cmd & 0xff00);
                return -EINVAL;
        }
 
@@ -876,6 +899,11 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
                if (tmp & RADEON_BACK)
                        flags |= RADEON_FRONT;
        }
+       if (flags & (RADEON_DEPTH|RADEON_STENCIL)) {
+               if (!dev_priv->have_z_offset)
+                       printk_once(KERN_ERR "radeon: illegal depth clear request. Buggy mesa detected - please update.\n");
+               flags &= ~(RADEON_DEPTH | RADEON_STENCIL);
+       }
 
        if (flags & (RADEON_FRONT | RADEON_BACK)) {
 
@@ -2611,7 +2639,6 @@ static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
 {
        int id = (int)header.packet.packet_id;
        int sz, reg;
-       int *data = (int *)cmdbuf->buf;
        RING_LOCALS;
 
        if (id >= RADEON_MAX_STATE_PACKETS)
@@ -2620,23 +2647,22 @@ static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
        sz = packet[id].len;
        reg = packet[id].start;
 
-       if (sz * sizeof(int) > cmdbuf->bufsz) {
+       if (sz * sizeof(u32) > drm_buffer_unprocessed(cmdbuf->buffer)) {
                DRM_ERROR("Packet size provided larger than data provided\n");
                return -EINVAL;
        }
 
-       if (radeon_check_and_fixup_packets(dev_priv, file_priv, id, data)) {
+       if (radeon_check_and_fixup_packets(dev_priv, file_priv, id,
+                               cmdbuf->buffer)) {
                DRM_ERROR("Packet verification failed\n");
                return -EINVAL;
        }
 
        BEGIN_RING(sz + 1);
        OUT_RING(CP_PACKET0(reg, (sz - 1)));
-       OUT_RING_TABLE(data, sz);
+       OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
        ADVANCE_RING();
 
-       cmdbuf->buf += sz * sizeof(int);
-       cmdbuf->bufsz -= sz * sizeof(int);
        return 0;
 }
 
@@ -2653,10 +2679,8 @@ static __inline__ int radeon_emit_scalars(drm_radeon_private_t *dev_priv,
        OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
        OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
        OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
-       OUT_RING_TABLE(cmdbuf->buf, sz);
+       OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
        ADVANCE_RING();
-       cmdbuf->buf += sz * sizeof(int);
-       cmdbuf->bufsz -= sz * sizeof(int);
        return 0;
 }
 
@@ -2675,10 +2699,8 @@ static __inline__ int radeon_emit_scalars2(drm_radeon_private_t *dev_priv,
        OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
        OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
        OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
-       OUT_RING_TABLE(cmdbuf->buf, sz);
+       OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
        ADVANCE_RING();
-       cmdbuf->buf += sz * sizeof(int);
-       cmdbuf->bufsz -= sz * sizeof(int);
        return 0;
 }
 
@@ -2696,11 +2718,9 @@ static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv,
        OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
        OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
        OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
-       OUT_RING_TABLE(cmdbuf->buf, sz);
+       OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
        ADVANCE_RING();
 
-       cmdbuf->buf += sz * sizeof(int);
-       cmdbuf->bufsz -= sz * sizeof(int);
        return 0;
 }
 
@@ -2714,7 +2734,7 @@ static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
 
         if (!sz)
                 return 0;
-        if (sz * 4 > cmdbuf->bufsz)
+       if (sz * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
                 return -EINVAL;
 
        BEGIN_RING(5 + sz);
@@ -2722,11 +2742,9 @@ static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
        OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
        OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
        OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
-       OUT_RING_TABLE(cmdbuf->buf, sz);
+       OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
        ADVANCE_RING();
 
-       cmdbuf->buf += sz * sizeof(int);
-       cmdbuf->bufsz -= sz * sizeof(int);
        return 0;
 }
 
@@ -2748,11 +2766,9 @@ static int radeon_emit_packet3(struct drm_device * dev,
        }
 
        BEGIN_RING(cmdsz);
-       OUT_RING_TABLE(cmdbuf->buf, cmdsz);
+       OUT_RING_DRM_BUFFER(cmdbuf->buffer, cmdsz);
        ADVANCE_RING();
 
-       cmdbuf->buf += cmdsz * 4;
-       cmdbuf->bufsz -= cmdsz * 4;
        return 0;
 }
 
@@ -2805,16 +2821,16 @@ static int radeon_emit_packet3_cliprect(struct drm_device *dev,
                }
 
                BEGIN_RING(cmdsz);
-               OUT_RING_TABLE(cmdbuf->buf, cmdsz);
+               OUT_RING_DRM_BUFFER(cmdbuf->buffer, cmdsz);
                ADVANCE_RING();
 
        } while (++i < cmdbuf->nbox);
        if (cmdbuf->nbox == 1)
                cmdbuf->nbox = 0;
 
+       return 0;
       out:
-       cmdbuf->buf += cmdsz * 4;
-       cmdbuf->bufsz -= cmdsz * 4;
+       drm_buffer_advance(cmdbuf->buffer, cmdsz * 4);
        return 0;
 }
 
@@ -2847,16 +2863,16 @@ static int radeon_emit_wait(struct drm_device * dev, int flags)
        return 0;
 }
 
-static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int radeon_cp_cmdbuf(struct drm_device *dev, void *data,
+               struct drm_file *file_priv)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        struct drm_device_dma *dma = dev->dma;
        struct drm_buf *buf = NULL;
+       drm_radeon_cmd_header_t stack_header;
        int idx;
        drm_radeon_kcmd_buffer_t *cmdbuf = data;
-       drm_radeon_cmd_header_t header;
-       int orig_nbox, orig_bufsz;
-       char *kbuf = NULL;
+       int orig_nbox;
 
        LOCK_TEST_WITH_RETURN(dev, file_priv);
 
@@ -2871,17 +2887,16 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
         * races between checking values and using those values in other code,
         * and simply to avoid a lot of function calls to copy in data.
         */
-       orig_bufsz = cmdbuf->bufsz;
-       if (orig_bufsz != 0) {
-               kbuf = kmalloc(cmdbuf->bufsz, GFP_KERNEL);
-               if (kbuf == NULL)
-                       return -ENOMEM;
-               if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf->buf,
-                                      cmdbuf->bufsz)) {
-                       kfree(kbuf);
-                       return -EFAULT;
-               }
-               cmdbuf->buf = kbuf;
+       if (cmdbuf->bufsz != 0) {
+               int rv;
+               void __user *buffer = cmdbuf->buffer;
+               rv = drm_buffer_alloc(&cmdbuf->buffer, cmdbuf->bufsz);
+               if (rv)
+                       return rv;
+               rv = drm_buffer_copy_from_user(cmdbuf->buffer, buffer,
+                                               cmdbuf->bufsz);
+               if (rv)
+                       return rv;
        }
 
        orig_nbox = cmdbuf->nbox;
@@ -2890,24 +2905,24 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
                int temp;
                temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf);
 
-               if (orig_bufsz != 0)
-                       kfree(kbuf);
+               if (cmdbuf->bufsz != 0)
+                       drm_buffer_free(cmdbuf->buffer);
 
                return temp;
        }
 
        /* microcode_version != r300 */
-       while (cmdbuf->bufsz >= sizeof(header)) {
+       while (drm_buffer_unprocessed(cmdbuf->buffer) >= sizeof(stack_header)) {
 
-               header.i = *(int *)cmdbuf->buf;
-               cmdbuf->buf += sizeof(header);
-               cmdbuf->bufsz -= sizeof(header);
+               drm_radeon_cmd_header_t *header;
+               header = drm_buffer_read_object(cmdbuf->buffer,
+                               sizeof(stack_header), &stack_header);
 
-               switch (header.header.cmd_type) {
+               switch (header->header.cmd_type) {
                case RADEON_CMD_PACKET:
                        DRM_DEBUG("RADEON_CMD_PACKET\n");
                        if (radeon_emit_packets
-                           (dev_priv, file_priv, header, cmdbuf)) {
+                           (dev_priv, file_priv, *header, cmdbuf)) {
                                DRM_ERROR("radeon_emit_packets failed\n");
                                goto err;
                        }
@@ -2915,7 +2930,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
 
                case RADEON_CMD_SCALARS:
                        DRM_DEBUG("RADEON_CMD_SCALARS\n");
-                       if (radeon_emit_scalars(dev_priv, header, cmdbuf)) {
+                       if (radeon_emit_scalars(dev_priv, *header, cmdbuf)) {
                                DRM_ERROR("radeon_emit_scalars failed\n");
                                goto err;
                        }
@@ -2923,7 +2938,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
 
                case RADEON_CMD_VECTORS:
                        DRM_DEBUG("RADEON_CMD_VECTORS\n");
-                       if (radeon_emit_vectors(dev_priv, header, cmdbuf)) {
+                       if (radeon_emit_vectors(dev_priv, *header, cmdbuf)) {
                                DRM_ERROR("radeon_emit_vectors failed\n");
                                goto err;
                        }
@@ -2931,7 +2946,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
 
                case RADEON_CMD_DMA_DISCARD:
                        DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
-                       idx = header.dma.buf_idx;
+                       idx = header->dma.buf_idx;
                        if (idx < 0 || idx >= dma->buf_count) {
                                DRM_ERROR("buffer index %d (of %d max)\n",
                                          idx, dma->buf_count - 1);
@@ -2968,7 +2983,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
 
                case RADEON_CMD_SCALARS2:
                        DRM_DEBUG("RADEON_CMD_SCALARS2\n");
-                       if (radeon_emit_scalars2(dev_priv, header, cmdbuf)) {
+                       if (radeon_emit_scalars2(dev_priv, *header, cmdbuf)) {
                                DRM_ERROR("radeon_emit_scalars2 failed\n");
                                goto err;
                        }
@@ -2976,37 +2991,37 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
 
                case RADEON_CMD_WAIT:
                        DRM_DEBUG("RADEON_CMD_WAIT\n");
-                       if (radeon_emit_wait(dev, header.wait.flags)) {
+                       if (radeon_emit_wait(dev, header->wait.flags)) {
                                DRM_ERROR("radeon_emit_wait failed\n");
                                goto err;
                        }
                        break;
                case RADEON_CMD_VECLINEAR:
                        DRM_DEBUG("RADEON_CMD_VECLINEAR\n");
-                       if (radeon_emit_veclinear(dev_priv, header, cmdbuf)) {
+                       if (radeon_emit_veclinear(dev_priv, *header, cmdbuf)) {
                                DRM_ERROR("radeon_emit_veclinear failed\n");
                                goto err;
                        }
                        break;
 
                default:
-                       DRM_ERROR("bad cmd_type %d at %p\n",
-                                 header.header.cmd_type,
-                                 cmdbuf->buf - sizeof(header));
+                       DRM_ERROR("bad cmd_type %d at byte %d\n",
+                                 header->header.cmd_type,
+                                 cmdbuf->buffer->iterator);
                        goto err;
                }
        }
 
-       if (orig_bufsz != 0)
-               kfree(kbuf);
+       if (cmdbuf->bufsz != 0)
+               drm_buffer_free(cmdbuf->buffer);
 
        DRM_DEBUG("DONE\n");
        COMMIT_RING();
        return 0;
 
       err:
-       if (orig_bufsz != 0)
-               kfree(kbuf);
+       if (cmdbuf->bufsz != 0)
+               drm_buffer_free(cmdbuf->buffer);
        return -EINVAL;
 }