Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
[linux-3.10.git] / drivers / gpu / drm / radeon / r600_cs.c
index e61a013..01a3ec8 100644 (file)
 #include "r600d.h"
 #include "r600_reg_safe.h"
 
-static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
-                                       struct radeon_cs_reloc **cs_reloc);
-static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
-                                       struct radeon_cs_reloc **cs_reloc);
-typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**);
-static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm;
+static int r600_nomm;
 extern void r600_cs_legacy_get_tiling_conf(struct drm_device *dev, u32 *npipes, u32 *nbanks, u32 *group_size);
 
 
@@ -784,99 +779,6 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
 }
 
 /**
- * r600_cs_packet_next_reloc_mm() - parse next packet which should be reloc packet3
- * @parser:            parser structure holding parsing context.
- * @data:              pointer to relocation data
- * @offset_start:      starting offset
- * @offset_mask:       offset mask (to align start offset on)
- * @reloc:             reloc informations
- *
- * Check next packet is relocation packet3, do bo validation and compute
- * GPU offset using the provided start.
- **/
-static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
-                                       struct radeon_cs_reloc **cs_reloc)
-{
-       struct radeon_cs_chunk *relocs_chunk;
-       struct radeon_cs_packet p3reloc;
-       unsigned idx;
-       int r;
-
-       if (p->chunk_relocs_idx == -1) {
-               DRM_ERROR("No relocation chunk !\n");
-               return -EINVAL;
-       }
-       *cs_reloc = NULL;
-       relocs_chunk = &p->chunks[p->chunk_relocs_idx];
-       r = radeon_cs_packet_parse(p, &p3reloc, p->idx);
-       if (r) {
-               return r;
-       }
-       p->idx += p3reloc.count + 2;
-       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
-               DRM_ERROR("No packet3 for relocation for packet at %d.\n",
-                         p3reloc.idx);
-               return -EINVAL;
-       }
-       idx = radeon_get_ib_value(p, p3reloc.idx + 1);
-       if (idx >= relocs_chunk->length_dw) {
-               DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
-                         idx, relocs_chunk->length_dw);
-               return -EINVAL;
-       }
-       /* FIXME: we assume reloc size is 4 dwords */
-       *cs_reloc = p->relocs_ptr[(idx / 4)];
-       return 0;
-}
-
-/**
- * r600_cs_packet_next_reloc_nomm() - parse next packet which should be reloc packet3
- * @parser:            parser structure holding parsing context.
- * @data:              pointer to relocation data
- * @offset_start:      starting offset
- * @offset_mask:       offset mask (to align start offset on)
- * @reloc:             reloc informations
- *
- * Check next packet is relocation packet3, do bo validation and compute
- * GPU offset using the provided start.
- **/
-static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
-                                       struct radeon_cs_reloc **cs_reloc)
-{
-       struct radeon_cs_chunk *relocs_chunk;
-       struct radeon_cs_packet p3reloc;
-       unsigned idx;
-       int r;
-
-       if (p->chunk_relocs_idx == -1) {
-               DRM_ERROR("No relocation chunk !\n");
-               return -EINVAL;
-       }
-       *cs_reloc = NULL;
-       relocs_chunk = &p->chunks[p->chunk_relocs_idx];
-       r = radeon_cs_packet_parse(p, &p3reloc, p->idx);
-       if (r) {
-               return r;
-       }
-       p->idx += p3reloc.count + 2;
-       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
-               DRM_ERROR("No packet3 for relocation for packet at %d.\n",
-                         p3reloc.idx);
-               return -EINVAL;
-       }
-       idx = radeon_get_ib_value(p, p3reloc.idx + 1);
-       if (idx >= relocs_chunk->length_dw) {
-               DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
-                         idx, relocs_chunk->length_dw);
-               return -EINVAL;
-       }
-       *cs_reloc = p->relocs;
-       (*cs_reloc)->lobj.gpu_offset = (u64)relocs_chunk->kdata[idx + 3] << 32;
-       (*cs_reloc)->lobj.gpu_offset |= relocs_chunk->kdata[idx + 0];
-       return 0;
-}
-
-/**
  * r600_cs_packet_parse_vline() - parse userspace VLINE packet
  * @parser:            parser structure holding parsing context.
  *
@@ -937,7 +839,7 @@ int r600_cs_common_vline_parse(struct radeon_cs_parser *p,
                return r;
 
        /* check its a WAIT_REG_MEM */
-       if (wait_reg_mem.type != PACKET_TYPE3 ||
+       if (wait_reg_mem.type != RADEON_PACKET_TYPE3 ||
            wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
                DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
                return -EINVAL;
@@ -949,6 +851,11 @@ int r600_cs_common_vline_parse(struct radeon_cs_parser *p,
                DRM_ERROR("vline WAIT_REG_MEM waiting on MEM instead of REG\n");
                return -EINVAL;
        }
+       /* bit 8 is me (0) or pfp (1) */
+       if (wait_reg_mem_info & 0x100) {
+               DRM_ERROR("vline WAIT_REG_MEM waiting on PFP instead of ME\n");
+               return -EINVAL;
+       }
        /* waiting for value to be equal */
        if ((wait_reg_mem_info & 0x7) != 0x3) {
                DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
@@ -975,7 +882,7 @@ int r600_cs_common_vline_parse(struct radeon_cs_parser *p,
 
        header = radeon_get_ib_value(p, h_idx);
        crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
-       reg = CP_PACKET0_GET_REG(header);
+       reg = R600_CP_PACKET0_GET_REG(header);
 
        obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
        if (!obj) {
@@ -1110,7 +1017,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case R_028010_DB_DEPTH_INFO:
                if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) &&
                    radeon_cs_packet_next_is_pkt3_nop(p)) {
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                         "0x%04X\n", reg);
@@ -1152,7 +1059,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case VGT_STRMOUT_BUFFER_BASE_1:
        case VGT_STRMOUT_BUFFER_BASE_2:
        case VGT_STRMOUT_BUFFER_BASE_3:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1175,7 +1082,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->streamout_dirty = true;
                break;
        case CP_COHER_BASE:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
                                        "0x%04X\n", reg);
@@ -1211,7 +1118,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case R_0280BC_CB_COLOR7_INFO:
                if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) &&
                     radeon_cs_packet_next_is_pkt3_nop(p)) {
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
                                return -EINVAL;
@@ -1283,7 +1190,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                        track->cb_color_frag_offset[tmp] = track->cb_color_bo_offset[tmp];
                        ib[idx] = track->cb_color_base_last[tmp];
                } else {
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
                                return -EINVAL;
@@ -1314,7 +1221,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                        track->cb_color_tile_offset[tmp] = track->cb_color_bo_offset[tmp];
                        ib[idx] = track->cb_color_base_last[tmp];
                } else {
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
                                return -EINVAL;
@@ -1349,7 +1256,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case CB_COLOR5_BASE:
        case CB_COLOR6_BASE:
        case CB_COLOR7_BASE:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1364,7 +1271,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->cb_dirty = true;
                break;
        case DB_DEPTH_BASE:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1377,7 +1284,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->db_dirty = true;
                break;
        case DB_HTILE_DATA_BASE:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1447,7 +1354,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case SQ_ALU_CONST_CACHE_VS_13:
        case SQ_ALU_CONST_CACHE_VS_14:
        case SQ_ALU_CONST_CACHE_VS_15:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1456,7 +1363,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
                break;
        case SX_MEMORY_EXPORT_BASE:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONFIG_REG "
                                        "0x%04X\n", reg);
@@ -1742,7 +1649,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                        return -EINVAL;
                }
 
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        DRM_ERROR("bad SET PREDICATION\n");
                        return -EINVAL;
@@ -1783,7 +1690,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                        DRM_ERROR("bad DRAW_INDEX\n");
                        return -EINVAL;
                }
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        DRM_ERROR("bad DRAW_INDEX\n");
                        return -EINVAL;
@@ -1835,7 +1742,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                if (idx_value & 0x10) {
                        uint64_t offset;
 
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad WAIT_REG_MEM\n");
                                return -EINVAL;
@@ -1847,6 +1754,9 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
 
                        ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffff0);
                        ib[idx+2] = upper_32_bits(offset) & 0xff;
+               } else if (idx_value & 0x100) {
+                       DRM_ERROR("cannot use PFP on REG wait\n");
+                       return -EINVAL;
                }
                break;
        case PACKET3_CP_DMA:
@@ -1869,7 +1779,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                                return -EINVAL;
                        }
                        /* src address space is memory */
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad CP DMA SRC\n");
                                return -EINVAL;
@@ -1899,7 +1809,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                                DRM_ERROR("CP DMA DAIC only supported for registers\n");
                                return -EINVAL;
                        }
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad CP DMA DST\n");
                                return -EINVAL;
@@ -1929,7 +1839,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                /* 0xffffffff/0x0 is flush all cache flag */
                if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
                    radeon_get_ib_value(p, idx + 2) != 0) {
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad SURFACE_SYNC\n");
                                return -EINVAL;
@@ -1945,7 +1855,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                if (pkt->count) {
                        uint64_t offset;
 
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad EVENT_WRITE\n");
                                return -EINVAL;
@@ -1966,7 +1876,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                        DRM_ERROR("bad EVENT_WRITE_EOP\n");
                        return -EINVAL;
                }
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        DRM_ERROR("bad EVENT_WRITE\n");
                        return -EINVAL;
@@ -2032,7 +1942,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                        switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) {
                        case SQ_TEX_VTX_VALID_TEXTURE:
                                /* tex base */
-                               r = r600_cs_packet_next_reloc(p, &reloc);
+                               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                                if (r) {
                                        DRM_ERROR("bad SET_RESOURCE\n");
                                        return -EINVAL;
@@ -2046,7 +1956,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                                }
                                texture = reloc->robj;
                                /* tex mip base */
-                               r = r600_cs_packet_next_reloc(p, &reloc);
+                               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                                if (r) {
                                        DRM_ERROR("bad SET_RESOURCE\n");
                                        return -EINVAL;
@@ -2067,7 +1977,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                        {
                                uint64_t offset64;
                                /* vtx base */
-                               r = r600_cs_packet_next_reloc(p, &reloc);
+                               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                                if (r) {
                                        DRM_ERROR("bad SET_RESOURCE\n");
                                        return -EINVAL;
@@ -2168,7 +2078,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                {
                        u64 offset;
 
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad STRMOUT_BASE_UPDATE reloc\n");
                                return -EINVAL;
@@ -2212,7 +2122,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                /* Updating memory at DST_ADDRESS. */
                if (idx_value & 0x1) {
                        u64 offset;
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n");
                                return -EINVAL;
@@ -2231,7 +2141,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                /* Reading data from SRC_ADDRESS. */
                if (((idx_value >> 1) & 0x3) == 2) {
                        u64 offset;
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n");
                                return -EINVAL;
@@ -2256,7 +2166,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                        DRM_ERROR("bad MEM_WRITE (invalid count)\n");
                        return -EINVAL;
                }
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        DRM_ERROR("bad MEM_WRITE (missing reloc)\n");
                        return -EINVAL;
@@ -2285,7 +2195,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                if (idx_value & 0x1) {
                        u64 offset;
                        /* SRC is memory. */
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad COPY_DW (missing src reloc)\n");
                                return -EINVAL;
@@ -2309,7 +2219,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                if (idx_value & 0x2) {
                        u64 offset;
                        /* DST is memory. */
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad COPY_DW (missing dst reloc)\n");
                                return -EINVAL;
@@ -2372,12 +2282,12 @@ int r600_cs_parse(struct radeon_cs_parser *p)
                }
                p->idx += pkt.count + 2;
                switch (pkt.type) {
-               case PACKET_TYPE0:
+               case RADEON_PACKET_TYPE0:
                        r = r600_cs_parse_packet0(p, &pkt);
                        break;
-               case PACKET_TYPE2:
+               case RADEON_PACKET_TYPE2:
                        break;
-               case PACKET_TYPE3:
+               case RADEON_PACKET_TYPE3:
                        r = r600_packet3_check(p, &pkt);
                        break;
                default:
@@ -2403,17 +2313,7 @@ int r600_cs_parse(struct radeon_cs_parser *p)
        return 0;
 }
 
-static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p)
-{
-       if (p->chunk_relocs_idx == -1) {
-               return 0;
-       }
-       p->relocs = kzalloc(sizeof(struct radeon_cs_reloc), GFP_KERNEL);
-       if (p->relocs == NULL) {
-               return -ENOMEM;
-       }
-       return 0;
-}
+#ifdef CONFIG_DRM_RADEON_UMS
 
 /**
  * cs_parser_fini() - clean parser states
@@ -2439,6 +2339,18 @@ static void r600_cs_parser_fini(struct radeon_cs_parser *parser, int error)
        kfree(parser->chunks_array);
 }
 
+static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p)
+{
+       if (p->chunk_relocs_idx == -1) {
+               return 0;
+       }
+       p->relocs = kzalloc(sizeof(struct radeon_cs_reloc), GFP_KERNEL);
+       if (p->relocs == NULL) {
+               return -ENOMEM;
+       }
+       return 0;
+}
+
 int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
                        unsigned family, u32 *ib, int *l)
 {
@@ -2497,9 +2409,11 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
 
 void r600_cs_legacy_init(void)
 {
-       r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_nomm;
+       r600_nomm = 1;
 }
 
+#endif
+
 /*
  *  DMA
  */
@@ -2577,14 +2491,14 @@ int r600_dma_cs_parse(struct radeon_cs_parser *p)
                                return -EINVAL;
                        }
                        if (tiled) {
-                               dst_offset = ib[idx+1];
+                               dst_offset = radeon_get_ib_value(p, idx+1);
                                dst_offset <<= 8;
 
                                ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
                                p->idx += count + 5;
                        } else {
-                               dst_offset = ib[idx+1];
-                               dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32;
+                               dst_offset = radeon_get_ib_value(p, idx+1);
+                               dst_offset |= ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
 
                                ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
                                ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
@@ -2612,32 +2526,32 @@ int r600_dma_cs_parse(struct radeon_cs_parser *p)
                                /* detile bit */
                                if (idx_value & (1 << 31)) {
                                        /* tiled src, linear dst */
-                                       src_offset = ib[idx+1];
+                                       src_offset = radeon_get_ib_value(p, idx+1);
                                        src_offset <<= 8;
                                        ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
 
-                                       dst_offset = ib[idx+5];
-                                       dst_offset |= ((u64)(ib[idx+6] & 0xff)) << 32;
+                                       dst_offset = radeon_get_ib_value(p, idx+5);
+                                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32;
                                        ib[idx+5] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
                                        ib[idx+6] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
                                } else {
                                        /* linear src, tiled dst */
-                                       src_offset = ib[idx+5];
-                                       src_offset |= ((u64)(ib[idx+6] & 0xff)) << 32;
+                                       src_offset = radeon_get_ib_value(p, idx+5);
+                                       src_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32;
                                        ib[idx+5] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
                                        ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
 
-                                       dst_offset = ib[idx+1];
+                                       dst_offset = radeon_get_ib_value(p, idx+1);
                                        dst_offset <<= 8;
                                        ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
                                }
                                p->idx += 7;
                        } else {
                                if (p->family >= CHIP_RV770) {
-                                       src_offset = ib[idx+2];
-                                       src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
-                                       dst_offset = ib[idx+1];
-                                       dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
+                                       src_offset = radeon_get_ib_value(p, idx+2);
+                                       src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
+                                       dst_offset = radeon_get_ib_value(p, idx+1);
+                                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
 
                                        ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
                                        ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
@@ -2645,10 +2559,10 @@ int r600_dma_cs_parse(struct radeon_cs_parser *p)
                                        ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
                                        p->idx += 5;
                                } else {
-                                       src_offset = ib[idx+2];
-                                       src_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
-                                       dst_offset = ib[idx+1];
-                                       dst_offset |= ((u64)(ib[idx+3] & 0xff0000)) << 16;
+                                       src_offset = radeon_get_ib_value(p, idx+2);
+                                       src_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
+                                       dst_offset = radeon_get_ib_value(p, idx+1);
+                                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff0000)) << 16;
 
                                        ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
                                        ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
@@ -2678,8 +2592,8 @@ int r600_dma_cs_parse(struct radeon_cs_parser *p)
                                DRM_ERROR("bad DMA_PACKET_WRITE\n");
                                return -EINVAL;
                        }
-                       dst_offset = ib[idx+1];
-                       dst_offset |= ((u64)(ib[idx+3] & 0x00ff0000)) << 16;
+                       dst_offset = radeon_get_ib_value(p, idx+1);
+                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0x00ff0000)) << 16;
                        if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
                                dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n",
                                         dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));