/* * Copyright 2010 Advanced Micro Devices, Inc. * Copyright 2008 Red Hat Inc. * Copyright 2009 Jerome Glisse. * * 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 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 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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: Dave Airlie * Alex Deucher * Jerome Glisse
*/
if ((surf->nbx & (palign - 1))) { if (prefix) {
dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d\n",
__func__, __LINE__, prefix, surf->nbx, palign);
} return -EINVAL;
} if ((surf->nby & (halign - 1))) { if (prefix) {
dev_warn(p->dev, "%s:%d %s height %d invalid must be aligned with %d\n",
__func__, __LINE__, prefix, surf->nby, halign);
} return -EINVAL;
}
return 0;
}
staticint evergreen_surface_check(struct radeon_cs_parser *p, struct eg_surface *surf, constchar *prefix)
{ /* some common value computed here */
surf->bpe = r600_fmt_get_blocksize(surf->format);
offset = (u64)track->cb_color_bo_offset[id] << 8; if (offset & (surf.base_align - 1)) {
dev_warn(p->dev, "%s:%d cb[%d] bo base %llu not aligned with %ld\n",
__func__, __LINE__, id, offset, surf.base_align); return -EINVAL;
}
offset += (u64)surf.layer_size * mslice; if (offset > radeon_bo_size(track->cb_color_bo[id])) { /* old ddx are broken they allocate bo with w*h*bpp but * program slice with ALIGN(h, 8), catch this and patch * command stream.
*/ if (!surf.mode) {
uint32_t *ib = p->ib.ptr;
u64 tmp, nby, bsize, size, min = 0;
/* find the height the ddx wants */ if (surf.nby > 8) {
min = surf.nby - 8;
}
bsize = radeon_bo_size(track->cb_color_bo[id]);
tmp = (u64)track->cb_color_bo_offset[id] << 8; for (nby = surf.nby; nby > min; nby--) {
size = nby * surf.nbx * surf.bpe * surf.nsamples; if ((tmp + size * mslice) <= bsize) { break;
}
} if (nby > min) {
surf.nby = nby;
slice = ((nby * surf.nbx) / 64) - 1; if (!evergreen_surface_check(p, &surf, "cb")) { /* check if this one works */
tmp += (u64)surf.layer_size * mslice; if (tmp <= bsize) {
ib[track->cb_color_slice_idx[id]] = slice; goto old_ddx_ok;
}
}
}
}
dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d, " "offset %llu, max layer %d, bo size %ld, slice %d)\n",
__func__, __LINE__, id, surf.layer_size,
(u64)track->cb_color_bo_offset[id] << 8, mslice,
radeon_bo_size(track->cb_color_bo[id]), slice);
dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n",
__func__, __LINE__, surf.nbx, surf.nby,
surf.mode, surf.bpe, surf.nsamples,
surf.bankw, surf.bankh,
surf.tsplit, surf.mtilea); return -EINVAL;
}
old_ddx_ok:
if (surf.format != 1) {
dev_warn(p->dev, "%s:%d stencil invalid format %d\n",
__func__, __LINE__, surf.format); return -EINVAL;
} /* replace by color format so we can use same code */
surf.format = V_028C70_COLOR_8;
r = evergreen_surface_value_conv_check(p, &surf, "stencil"); if (r) { return r;
}
r = evergreen_surface_check(p, &surf, NULL); if (r) { /* old userspace doesn't compute proper depth/stencil alignment * check that alignment against a bigger byte per elements and * only report if that alignment is wrong too.
*/
surf.format = V_028C70_COLOR_8_8_8_8;
r = evergreen_surface_check(p, &surf, "stencil"); if (r) {
dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n",
__func__, __LINE__, track->db_depth_size,
track->db_depth_slice, track->db_s_info, track->db_z_info);
} return r;
}
offset = (u64)track->db_s_read_offset << 8; if (offset & (surf.base_align - 1)) {
dev_warn(p->dev, "%s:%d stencil read bo base %llu not aligned with %ld\n",
__func__, __LINE__, offset, surf.base_align); return -EINVAL;
}
offset += (u64)surf.layer_size * mslice; if (offset > radeon_bo_size(track->db_s_read_bo)) {
dev_warn(p->dev, "%s:%d stencil read bo too small (layer size %d, " "offset %llu, max layer %d, bo size %ld)\n",
__func__, __LINE__, surf.layer_size,
(u64)track->db_s_read_offset << 8, mslice,
radeon_bo_size(track->db_s_read_bo));
dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n",
__func__, __LINE__, track->db_depth_size,
track->db_depth_slice, track->db_s_info, track->db_z_info); return -EINVAL;
}
offset = (u64)track->db_s_write_offset << 8; if (offset & (surf.base_align - 1)) {
dev_warn(p->dev, "%s:%d stencil write bo base %llu not aligned with %ld\n",
__func__, __LINE__, offset, surf.base_align); return -EINVAL;
}
offset += (u64)surf.layer_size * mslice; if (offset > radeon_bo_size(track->db_s_write_bo)) {
dev_warn(p->dev, "%s:%d stencil write bo too small (layer size %d, " "offset %llu, max layer %d, bo size %ld)\n",
__func__, __LINE__, surf.layer_size,
(u64)track->db_s_write_offset << 8, mslice,
radeon_bo_size(track->db_s_write_bo)); return -EINVAL;
}
/* hyperz */ if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) {
r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby); if (r) { return r;
}
}
/* check streamout */ if (track->streamout_dirty && track->vgt_strmout_config) { for (i = 0; i < 4; i++) { if (track->vgt_strmout_config & (1 << i)) {
buffer_mask |= (track->vgt_strmout_buffer_config >> (i * 4)) & 0xf;
}
}
for (i = 0; i < 4; i++) { if (buffer_mask & (1 << i)) { if (track->vgt_strmout_bo[i]) {
u64 offset = (u64)track->vgt_strmout_bo_offset[i] +
(u64)track->vgt_strmout_size[i]; if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) {
DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n",
i, offset,
radeon_bo_size(track->vgt_strmout_bo[i])); return -EINVAL;
}
} else {
dev_warn(p->dev, "No buffer for streamout %d\n", i); return -EINVAL;
}
}
}
track->streamout_dirty = false;
}
if (track->sx_misc_kill_all_prims) return 0;
/* check that we have a cb for each enabled target
*/ if (track->cb_dirty) {
tmp = track->cb_target_mask; for (i = 0; i < 8; i++) {
u32 format = G_028C70_FORMAT(track->cb_color_info[i]);
if (format != V_028C70_COLOR_INVALID &&
(tmp >> (i * 4)) & 0xF) { /* at least one component is enabled */ if (track->cb_color_bo[i] == NULL) {
dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n",
__func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i); return -EINVAL;
} /* check cb */
r = evergreen_cs_track_validate_cb(p, i); if (r) { return r;
}
}
}
track->cb_dirty = false;
}
if (track->db_dirty) { /* Check stencil buffer */ if (G_028044_FORMAT(track->db_s_info) != V_028044_STENCIL_INVALID &&
G_028800_STENCIL_ENABLE(track->db_depth_control)) {
r = evergreen_cs_track_validate_stencil(p); if (r) return r;
} /* Check depth buffer */ if (G_028040_FORMAT(track->db_z_info) != V_028040_Z_INVALID &&
G_028800_Z_ENABLE(track->db_depth_control)) {
r = evergreen_cs_track_validate_depth(p); if (r) return r;
}
track->db_dirty = false;
}
return 0;
}
/** * evergreen_cs_packet_parse_vline() - parse userspace VLINE packet * @p: parser structure holding parsing context. * * This is an Evergreen(+)-specific function for parsing VLINE packets. * Real work is done by r600_cs_common_vline_parse function. * Here we just set up ASIC-specific register table and call * the common implementation function.
*/ staticint evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
{
idx = pkt->idx + 1;
reg = pkt->reg; for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
r = evergreen_packet0_check(p, pkt, idx, reg); if (r) { return r;
}
} return 0;
}
/** * evergreen_cs_handle_reg() - process registers that need special handling. * @p: parser structure holding parsing context * @reg: register we are testing * @idx: index into the cs buffer
*/ staticint evergreen_cs_handle_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
{ struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track; struct radeon_bo_list *reloc;
u32 tmp, *ib; int r;
ib = p->ib.ptr; switch (reg) { /* force following reg to 0 in an attempt to disable out buffer * which will need us to better understand how it works to perform * security check on it (Jerome)
*/ case SQ_ESGS_RING_SIZE: case SQ_GSVS_RING_SIZE: case SQ_ESTMP_RING_SIZE: case SQ_GSTMP_RING_SIZE: case SQ_HSTMP_RING_SIZE: case SQ_LSTMP_RING_SIZE: case SQ_PSTMP_RING_SIZE: case SQ_VSTMP_RING_SIZE: case SQ_ESGS_RING_ITEMSIZE: case SQ_ESTMP_RING_ITEMSIZE: case SQ_GSTMP_RING_ITEMSIZE: case SQ_GSVS_RING_ITEMSIZE: case SQ_GS_VERT_ITEMSIZE: case SQ_GS_VERT_ITEMSIZE_1: case SQ_GS_VERT_ITEMSIZE_2: case SQ_GS_VERT_ITEMSIZE_3: case SQ_GSVS_RING_OFFSET_1: case SQ_GSVS_RING_OFFSET_2: case SQ_GSVS_RING_OFFSET_3: case SQ_HSTMP_RING_ITEMSIZE: case SQ_LSTMP_RING_ITEMSIZE: case SQ_PSTMP_RING_ITEMSIZE: case SQ_VSTMP_RING_ITEMSIZE: case VGT_TF_RING_SIZE: /* get value to populate the IB don't remove */ /*tmp =radeon_get_ib_value(p, idx);
ib[idx] = 0;*/ break; case SQ_ESGS_RING_BASE: case SQ_GSVS_RING_BASE: case SQ_ESTMP_RING_BASE: case SQ_GSTMP_RING_BASE: case SQ_HSTMP_RING_BASE: case SQ_LSTMP_RING_BASE: case SQ_PSTMP_RING_BASE: case SQ_VSTMP_RING_BASE:
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); break; case DB_DEPTH_CONTROL:
track->db_depth_control = radeon_get_ib_value(p, idx);
track->db_dirty = true; break; case CAYMAN_DB_EQAA: if (p->rdev->family < CHIP_CAYMAN) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
} break; case CAYMAN_DB_DEPTH_INFO: if (p->rdev->family < CHIP_CAYMAN) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
} break; case DB_Z_INFO:
track->db_z_info = radeon_get_ib_value(p, idx); if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
ib[idx] &= ~Z_ARRAY_MODE(0xf);
track->db_z_info &= ~Z_ARRAY_MODE(0xf);
ib[idx] |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags));
track->db_z_info |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags)); if (reloc->tiling_flags & RADEON_TILING_MACRO) { unsigned bankw, bankh, mtaspect, tile_split;
evergreen_tiling_fields(reloc->tiling_flags,
&bankw, &bankh, &mtaspect,
&tile_split);
ib[idx] |= DB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
ib[idx] |= DB_TILE_SPLIT(tile_split) |
DB_BANK_WIDTH(bankw) |
DB_BANK_HEIGHT(bankh) |
DB_MACRO_TILE_ASPECT(mtaspect);
}
}
track->db_dirty = true; break; case DB_STENCIL_INFO:
track->db_s_info = radeon_get_ib_value(p, idx);
track->db_dirty = true; break; case DB_DEPTH_VIEW:
track->db_depth_view = radeon_get_ib_value(p, idx);
track->db_dirty = true; break; case DB_DEPTH_SIZE:
track->db_depth_size = radeon_get_ib_value(p, idx);
track->db_dirty = true; break; case R_02805C_DB_DEPTH_SLICE:
track->db_depth_slice = radeon_get_ib_value(p, idx);
track->db_dirty = true; break; case DB_Z_READ_BASE:
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
track->db_z_read_offset = radeon_get_ib_value(p, idx);
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
track->db_z_read_bo = reloc->robj;
track->db_dirty = true; break; case DB_Z_WRITE_BASE:
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
track->db_z_write_offset = radeon_get_ib_value(p, idx);
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
track->db_z_write_bo = reloc->robj;
track->db_dirty = true; break; case DB_STENCIL_READ_BASE:
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
track->db_s_read_offset = radeon_get_ib_value(p, idx);
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
track->db_s_read_bo = reloc->robj;
track->db_dirty = true; break; case DB_STENCIL_WRITE_BASE:
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
track->db_s_write_offset = radeon_get_ib_value(p, idx);
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
track->db_s_write_bo = reloc->robj;
track->db_dirty = true; break; case VGT_STRMOUT_CONFIG:
track->vgt_strmout_config = radeon_get_ib_value(p, idx);
track->streamout_dirty = true; break; case VGT_STRMOUT_BUFFER_CONFIG:
track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx);
track->streamout_dirty = true; break; case VGT_STRMOUT_BUFFER_BASE_0: case VGT_STRMOUT_BUFFER_BASE_1: case VGT_STRMOUT_BUFFER_BASE_2: case VGT_STRMOUT_BUFFER_BASE_3:
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
track->vgt_strmout_bo[tmp] = reloc->robj;
track->streamout_dirty = true; break; case VGT_STRMOUT_BUFFER_SIZE_0: case VGT_STRMOUT_BUFFER_SIZE_1: case VGT_STRMOUT_BUFFER_SIZE_2: case VGT_STRMOUT_BUFFER_SIZE_3:
tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; /* size in register is DWs, convert to bytes */
track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4;
track->streamout_dirty = true; break; case CP_COHER_BASE:
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "missing reloc for CP_COHER_BASE " "0x%04X\n", reg); return -EINVAL;
}
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); break; case CB_TARGET_MASK:
track->cb_target_mask = radeon_get_ib_value(p, idx);
track->cb_dirty = true; break; case CB_SHADER_MASK:
track->cb_shader_mask = radeon_get_ib_value(p, idx);
track->cb_dirty = true; break; case PA_SC_AA_CONFIG: if (p->rdev->family >= CHIP_CAYMAN) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK;
track->nsamples = 1 << tmp; break; case CAYMAN_PA_SC_AA_CONFIG: if (p->rdev->family < CHIP_CAYMAN) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
tmp = radeon_get_ib_value(p, idx) & CAYMAN_MSAA_NUM_SAMPLES_MASK;
track->nsamples = 1 << tmp; break; case CB_COLOR0_VIEW: case CB_COLOR1_VIEW: case CB_COLOR2_VIEW: case CB_COLOR3_VIEW: case CB_COLOR4_VIEW: case CB_COLOR5_VIEW: case CB_COLOR6_VIEW: case CB_COLOR7_VIEW:
tmp = (reg - CB_COLOR0_VIEW) / 0x3c;
track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
track->cb_dirty = true; break; case CB_COLOR8_VIEW: case CB_COLOR9_VIEW: case CB_COLOR10_VIEW: case CB_COLOR11_VIEW:
tmp = ((reg - CB_COLOR8_VIEW) / 0x1c) + 8;
track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
track->cb_dirty = true; break; case CB_COLOR0_INFO: case CB_COLOR1_INFO: case CB_COLOR2_INFO: case CB_COLOR3_INFO: case CB_COLOR4_INFO: case CB_COLOR5_INFO: case CB_COLOR6_INFO: case CB_COLOR7_INFO:
tmp = (reg - CB_COLOR0_INFO) / 0x3c;
track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags));
track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags));
}
track->cb_dirty = true; break; case CB_COLOR8_INFO: case CB_COLOR9_INFO: case CB_COLOR10_INFO: case CB_COLOR11_INFO:
tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;
track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags));
track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags));
}
track->cb_dirty = true; break; case CB_COLOR0_PITCH: case CB_COLOR1_PITCH: case CB_COLOR2_PITCH: case CB_COLOR3_PITCH: case CB_COLOR4_PITCH: case CB_COLOR5_PITCH: case CB_COLOR6_PITCH: case CB_COLOR7_PITCH:
tmp = (reg - CB_COLOR0_PITCH) / 0x3c;
track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
track->cb_dirty = true; break; case CB_COLOR8_PITCH: case CB_COLOR9_PITCH: case CB_COLOR10_PITCH: case CB_COLOR11_PITCH:
tmp = ((reg - CB_COLOR8_PITCH) / 0x1c) + 8;
track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
track->cb_dirty = true; break; case CB_COLOR0_SLICE: case CB_COLOR1_SLICE: case CB_COLOR2_SLICE: case CB_COLOR3_SLICE: case CB_COLOR4_SLICE: case CB_COLOR5_SLICE: case CB_COLOR6_SLICE: case CB_COLOR7_SLICE:
tmp = (reg - CB_COLOR0_SLICE) / 0x3c;
track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
track->cb_color_slice_idx[tmp] = idx;
track->cb_dirty = true; break; case CB_COLOR8_SLICE: case CB_COLOR9_SLICE: case CB_COLOR10_SLICE: case CB_COLOR11_SLICE:
tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8;
track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
track->cb_color_slice_idx[tmp] = idx;
track->cb_dirty = true; break; case CB_COLOR0_ATTRIB: case CB_COLOR1_ATTRIB: case CB_COLOR2_ATTRIB: case CB_COLOR3_ATTRIB: case CB_COLOR4_ATTRIB: case CB_COLOR5_ATTRIB: case CB_COLOR6_ATTRIB: case CB_COLOR7_ATTRIB:
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
} if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { if (reloc->tiling_flags & RADEON_TILING_MACRO) { unsigned bankw, bankh, mtaspect, tile_split;
evergreen_tiling_fields(reloc->tiling_flags,
&bankw, &bankh, &mtaspect,
&tile_split);
ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
ib[idx] |= CB_TILE_SPLIT(tile_split) |
CB_BANK_WIDTH(bankw) |
CB_BANK_HEIGHT(bankh) |
CB_MACRO_TILE_ASPECT(mtaspect);
}
}
tmp = ((reg - CB_COLOR0_ATTRIB) / 0x3c);
track->cb_color_attrib[tmp] = ib[idx];
track->cb_dirty = true; break; case CB_COLOR8_ATTRIB: case CB_COLOR9_ATTRIB: case CB_COLOR10_ATTRIB: case CB_COLOR11_ATTRIB:
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
} if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { if (reloc->tiling_flags & RADEON_TILING_MACRO) { unsigned bankw, bankh, mtaspect, tile_split;
evergreen_tiling_fields(reloc->tiling_flags,
&bankw, &bankh, &mtaspect,
&tile_split);
ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
ib[idx] |= CB_TILE_SPLIT(tile_split) |
CB_BANK_WIDTH(bankw) |
CB_BANK_HEIGHT(bankh) |
CB_MACRO_TILE_ASPECT(mtaspect);
}
}
tmp = ((reg - CB_COLOR8_ATTRIB) / 0x1c) + 8;
track->cb_color_attrib[tmp] = ib[idx];
track->cb_dirty = true; break; case CB_COLOR0_FMASK: case CB_COLOR1_FMASK: case CB_COLOR2_FMASK: case CB_COLOR3_FMASK: case CB_COLOR4_FMASK: case CB_COLOR5_FMASK: case CB_COLOR6_FMASK: case CB_COLOR7_FMASK:
tmp = (reg - CB_COLOR0_FMASK) / 0x3c;
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); return -EINVAL;
}
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
track->cb_color_fmask_bo[tmp] = reloc->robj; break; case CB_COLOR0_CMASK: case CB_COLOR1_CMASK: case CB_COLOR2_CMASK: case CB_COLOR3_CMASK: case CB_COLOR4_CMASK: case CB_COLOR5_CMASK: case CB_COLOR6_CMASK: case CB_COLOR7_CMASK:
tmp = (reg - CB_COLOR0_CMASK) / 0x3c;
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); return -EINVAL;
}
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
track->cb_color_cmask_bo[tmp] = reloc->robj; break; case CB_COLOR0_FMASK_SLICE: case CB_COLOR1_FMASK_SLICE: case CB_COLOR2_FMASK_SLICE: case CB_COLOR3_FMASK_SLICE: case CB_COLOR4_FMASK_SLICE: case CB_COLOR5_FMASK_SLICE: case CB_COLOR6_FMASK_SLICE: case CB_COLOR7_FMASK_SLICE:
tmp = (reg - CB_COLOR0_FMASK_SLICE) / 0x3c;
track->cb_color_fmask_slice[tmp] = radeon_get_ib_value(p, idx); break; case CB_COLOR0_CMASK_SLICE: case CB_COLOR1_CMASK_SLICE: case CB_COLOR2_CMASK_SLICE: case CB_COLOR3_CMASK_SLICE: case CB_COLOR4_CMASK_SLICE: case CB_COLOR5_CMASK_SLICE: case CB_COLOR6_CMASK_SLICE: case CB_COLOR7_CMASK_SLICE:
tmp = (reg - CB_COLOR0_CMASK_SLICE) / 0x3c;
track->cb_color_cmask_slice[tmp] = radeon_get_ib_value(p, idx); break; case CB_COLOR0_BASE: case CB_COLOR1_BASE: case CB_COLOR2_BASE: case CB_COLOR3_BASE: case CB_COLOR4_BASE: case CB_COLOR5_BASE: case CB_COLOR6_BASE: case CB_COLOR7_BASE:
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
tmp = (reg - CB_COLOR0_BASE) / 0x3c;
track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
track->cb_color_bo[tmp] = reloc->robj;
track->cb_dirty = true; break; case CB_COLOR8_BASE: case CB_COLOR9_BASE: case CB_COLOR10_BASE: case CB_COLOR11_BASE:
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
tmp = ((reg - CB_COLOR8_BASE) / 0x1c) + 8;
track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
track->cb_color_bo[tmp] = reloc->robj;
track->cb_dirty = true; break; case DB_HTILE_DATA_BASE:
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
track->htile_offset = radeon_get_ib_value(p, idx);
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
track->htile_bo = reloc->robj;
track->db_dirty = true; break; case DB_HTILE_SURFACE: /* 8x8 only */
track->htile_surface = radeon_get_ib_value(p, idx); /* force 8x8 htile width and height */
ib[idx] |= 3;
track->db_dirty = true; break; case CB_IMMED0_BASE: case CB_IMMED1_BASE: case CB_IMMED2_BASE: case CB_IMMED3_BASE: case CB_IMMED4_BASE: case CB_IMMED5_BASE: case CB_IMMED6_BASE: case CB_IMMED7_BASE: case CB_IMMED8_BASE: case CB_IMMED9_BASE: case CB_IMMED10_BASE: case CB_IMMED11_BASE: case SQ_PGM_START_FS: case SQ_PGM_START_ES: case SQ_PGM_START_VS: case SQ_PGM_START_GS: case SQ_PGM_START_PS: case SQ_PGM_START_HS: case SQ_PGM_START_LS: case SQ_CONST_MEM_BASE: case SQ_ALU_CONST_CACHE_GS_0: case SQ_ALU_CONST_CACHE_GS_1: case SQ_ALU_CONST_CACHE_GS_2: case SQ_ALU_CONST_CACHE_GS_3: case SQ_ALU_CONST_CACHE_GS_4: case SQ_ALU_CONST_CACHE_GS_5: case SQ_ALU_CONST_CACHE_GS_6: case SQ_ALU_CONST_CACHE_GS_7: case SQ_ALU_CONST_CACHE_GS_8: case SQ_ALU_CONST_CACHE_GS_9: case SQ_ALU_CONST_CACHE_GS_10: case SQ_ALU_CONST_CACHE_GS_11: case SQ_ALU_CONST_CACHE_GS_12: case SQ_ALU_CONST_CACHE_GS_13: case SQ_ALU_CONST_CACHE_GS_14: case SQ_ALU_CONST_CACHE_GS_15: case SQ_ALU_CONST_CACHE_PS_0: case SQ_ALU_CONST_CACHE_PS_1: case SQ_ALU_CONST_CACHE_PS_2: case SQ_ALU_CONST_CACHE_PS_3: case SQ_ALU_CONST_CACHE_PS_4: case SQ_ALU_CONST_CACHE_PS_5: case SQ_ALU_CONST_CACHE_PS_6: case SQ_ALU_CONST_CACHE_PS_7: case SQ_ALU_CONST_CACHE_PS_8: case SQ_ALU_CONST_CACHE_PS_9: case SQ_ALU_CONST_CACHE_PS_10: case SQ_ALU_CONST_CACHE_PS_11: case SQ_ALU_CONST_CACHE_PS_12: case SQ_ALU_CONST_CACHE_PS_13: case SQ_ALU_CONST_CACHE_PS_14: case SQ_ALU_CONST_CACHE_PS_15: case SQ_ALU_CONST_CACHE_VS_0: case SQ_ALU_CONST_CACHE_VS_1: case SQ_ALU_CONST_CACHE_VS_2: case SQ_ALU_CONST_CACHE_VS_3: case SQ_ALU_CONST_CACHE_VS_4: case SQ_ALU_CONST_CACHE_VS_5: case SQ_ALU_CONST_CACHE_VS_6: case SQ_ALU_CONST_CACHE_VS_7: case SQ_ALU_CONST_CACHE_VS_8: case SQ_ALU_CONST_CACHE_VS_9: case SQ_ALU_CONST_CACHE_VS_10: case SQ_ALU_CONST_CACHE_VS_11: case SQ_ALU_CONST_CACHE_VS_12: case SQ_ALU_CONST_CACHE_VS_13: case SQ_ALU_CONST_CACHE_VS_14: case SQ_ALU_CONST_CACHE_VS_15: case SQ_ALU_CONST_CACHE_HS_0: case SQ_ALU_CONST_CACHE_HS_1: case SQ_ALU_CONST_CACHE_HS_2: case SQ_ALU_CONST_CACHE_HS_3: case SQ_ALU_CONST_CACHE_HS_4: case SQ_ALU_CONST_CACHE_HS_5: case SQ_ALU_CONST_CACHE_HS_6: case SQ_ALU_CONST_CACHE_HS_7: case SQ_ALU_CONST_CACHE_HS_8: case SQ_ALU_CONST_CACHE_HS_9: case SQ_ALU_CONST_CACHE_HS_10: case SQ_ALU_CONST_CACHE_HS_11: case SQ_ALU_CONST_CACHE_HS_12: case SQ_ALU_CONST_CACHE_HS_13: case SQ_ALU_CONST_CACHE_HS_14: case SQ_ALU_CONST_CACHE_HS_15: case SQ_ALU_CONST_CACHE_LS_0: case SQ_ALU_CONST_CACHE_LS_1: case SQ_ALU_CONST_CACHE_LS_2: case SQ_ALU_CONST_CACHE_LS_3: case SQ_ALU_CONST_CACHE_LS_4: case SQ_ALU_CONST_CACHE_LS_5: case SQ_ALU_CONST_CACHE_LS_6: case SQ_ALU_CONST_CACHE_LS_7: case SQ_ALU_CONST_CACHE_LS_8: case SQ_ALU_CONST_CACHE_LS_9: case SQ_ALU_CONST_CACHE_LS_10: case SQ_ALU_CONST_CACHE_LS_11: case SQ_ALU_CONST_CACHE_LS_12: case SQ_ALU_CONST_CACHE_LS_13: case SQ_ALU_CONST_CACHE_LS_14: case SQ_ALU_CONST_CACHE_LS_15:
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); break; case SX_MEMORY_EXPORT_BASE: if (p->rdev->family >= CHIP_CAYMAN) {
dev_warn(p->dev, "bad SET_CONFIG_REG " "0x%04X\n", reg); return -EINVAL;
}
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONFIG_REG " "0x%04X\n", reg); return -EINVAL;
}
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); break; case CAYMAN_SX_SCATTER_EXPORT_BASE: if (p->rdev->family < CHIP_CAYMAN) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); break; case SX_MISC:
track->sx_misc_kill_all_prims = (radeon_get_ib_value(p, idx) & 0x1) != 0; break; default:
dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); return -EINVAL;
} return 0;
}
/** * evergreen_is_safe_reg() - check if register is authorized or not * @p: parser structure holding parsing context * @reg: register we are testing * * This function will test against reg_safe_bm and return true * if register is safe or false otherwise.
*/ staticinlinebool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg)
{ struct evergreen_cs_track *track = p->track;
u32 m, i;
i = (reg >> 7); if (unlikely(i >= REG_SAFE_BM_SIZE)) { returnfalse;
}
m = 1 << ((reg >> 2) & 31); if (!(track->reg_safe_bm[i] & m)) returntrue;
break;
} case PACKET3_DRAW_INDIRECT: case PACKET3_DRAW_INDEX_INDIRECT:
{
u64 size = pkt->opcode == PACKET3_DRAW_INDIRECT ? 16 : 20;
/* DW 1 HEADER 2 DATA_OFFSET Bits [31:0] + byte aligned offset where the required data structure starts. Bits 1:0 are zero 3 DRAW_INITIATOR Draw Initiator Register. Written to the VGT_DRAW_INITIATOR register for the assigned context
*/ if (pkt->count != 1) {
DRM_ERROR("bad DRAW_INDIRECT\n"); return -EINVAL;
}
if (idx_value + size > track->indirect_draw_buffer_size) {
dev_warn(p->dev, "DRAW_INDIRECT buffer too small %u + %llu > %lu\n",
idx_value, size, track->indirect_draw_buffer_size); return -EINVAL;
}
r = evergreen_cs_track_check(p); if (r) {
dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); return r;
} break;
} case PACKET3_DISPATCH_DIRECT: if (pkt->count != 3) {
DRM_ERROR("bad DISPATCH_DIRECT\n"); return -EINVAL;
}
r = evergreen_cs_track_check(p); if (r) {
dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx); return r;
} break; case PACKET3_DISPATCH_INDIRECT: if (pkt->count != 1) {
DRM_ERROR("bad DISPATCH_INDIRECT\n"); return -EINVAL;
}
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
DRM_ERROR("bad DISPATCH_INDIRECT\n"); return -EINVAL;
}
ib[idx+0] = idx_value + (u32)(reloc->gpu_offset & 0xffffffff);
r = evergreen_cs_track_check(p); if (r) {
dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); return r;
} break; case PACKET3_WAIT_REG_MEM: if (pkt->count != 5) {
DRM_ERROR("bad WAIT_REG_MEM\n"); return -EINVAL;
} /* bit 4 is reg (0) or mem (1) */ if (idx_value & 0x10) {
uint64_t offset;
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
DRM_ERROR("bad WAIT_REG_MEM\n"); return -EINVAL;
}
switch ((tmp & 0xf000) >> 12) { case 0:
track->row_size = 1; break; case 1: default:
track->row_size = 2; break; case 2:
track->row_size = 4; break;
}
p->track = track;
} do {
r = radeon_cs_packet_parse(p, &pkt, p->idx); if (r) {
kfree(p->track);
p->track = NULL; return r;
}
p->idx += pkt.count + 2; switch (pkt.type) { case RADEON_PACKET_TYPE0:
r = evergreen_cs_parse_packet0(p, &pkt); break; case RADEON_PACKET_TYPE2: break; case RADEON_PACKET_TYPE3:
r = evergreen_packet3_check(p, &pkt); break; default:
DRM_ERROR("Unknown packet type %d !\n", pkt.type);
kfree(p->track);
p->track = NULL; return -EINVAL;
} if (r) {
kfree(p->track);
p->track = NULL; return r;
}
} while (p->idx < p->chunk_ib->length_dw); #if 0 for (r = 0; r < p->ib.length_dw; r++) {
pr_info("%05d 0x%08X\n", r, p->ib.ptr[r]);
mdelay(1);
} #endif
kfree(p->track);
p->track = NULL; return 0;
}
/** * evergreen_dma_cs_parse() - parse the DMA IB * @p: parser structure holding parsing context. * * Parses the DMA IB from the CS ioctl and updates * the GPU addresses based on the reloc information and * checks for errors. (Evergreen-Cayman) * Returns 0 for success and an error on failure.
**/ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
{ struct radeon_cs_chunk *ib_chunk = p->chunk_ib; struct radeon_bo_list *src_reloc, *dst_reloc, *dst2_reloc;
u32 header, cmd, count, sub_cmd;
uint32_t *ib = p->ib.ptr;
u32 idx;
u64 src_offset, dst_offset, dst2_offset; int r;
do { if (p->idx >= ib_chunk->length_dw) {
DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
p->idx, ib_chunk->length_dw); return -EINVAL;
}
idx = p->idx;
header = radeon_get_ib_value(p, idx);
cmd = GET_DMA_CMD(header);
count = GET_DMA_COUNT(header);
sub_cmd = GET_DMA_SUB_CMD(header);
switch (cmd) { case DMA_PACKET_WRITE:
r = r600_dma_cs_next_reloc(p, &dst_reloc); if (r) {
DRM_ERROR("bad DMA_PACKET_WRITE\n"); return -EINVAL;
} switch (sub_cmd) { /* tiled */ case 8:
dst_offset = radeon_get_ib_value(p, idx+1);
dst_offset <<= 8;
/* vm parser */ staticbool evergreen_vm_reg_valid(u32 reg)
{ /* context regs are fine */ if (reg >= 0x28000) returntrue;
/* check config regs */ switch (reg) { case WAIT_UNTIL: case GRBM_GFX_INDEX: case CP_STRMOUT_CNTL: case CP_COHER_CNTL: case CP_COHER_SIZE: case VGT_VTX_VECT_EJECT_REG: case VGT_CACHE_INVALIDATION: case VGT_GS_VERTEX_REUSE: case VGT_PRIMITIVE_TYPE: case VGT_INDEX_TYPE: case VGT_NUM_INDICES: case VGT_NUM_INSTANCES: case VGT_COMPUTE_DIM_X: case VGT_COMPUTE_DIM_Y: case VGT_COMPUTE_DIM_Z: case VGT_COMPUTE_START_X: case VGT_COMPUTE_START_Y: case VGT_COMPUTE_START_Z: case VGT_COMPUTE_INDEX: case VGT_COMPUTE_THREAD_GROUP_SIZE: case VGT_HS_OFFCHIP_PARAM: case PA_CL_ENHANCE: case PA_SU_LINE_STIPPLE_VALUE: case PA_SC_LINE_STIPPLE_STATE: case PA_SC_ENHANCE: case SQ_DYN_GPR_CNTL_PS_FLUSH_REQ: case SQ_DYN_GPR_SIMD_LOCK_EN: case SQ_CONFIG: case SQ_GPR_RESOURCE_MGMT_1: case SQ_GLOBAL_GPR_RESOURCE_MGMT_1: case SQ_GLOBAL_GPR_RESOURCE_MGMT_2: case SQ_CONST_MEM_BASE: case SQ_STATIC_THREAD_MGMT_1: case SQ_STATIC_THREAD_MGMT_2: case SQ_STATIC_THREAD_MGMT_3: case SPI_CONFIG_CNTL: case SPI_CONFIG_CNTL_1: case TA_CNTL_AUX: case DB_DEBUG: case DB_DEBUG2: case DB_DEBUG3: case DB_DEBUG4: case DB_WATERMARKS: case TD_PS_BORDER_COLOR_INDEX: case TD_PS_BORDER_COLOR_RED: case TD_PS_BORDER_COLOR_GREEN: case TD_PS_BORDER_COLOR_BLUE: case TD_PS_BORDER_COLOR_ALPHA: case TD_VS_BORDER_COLOR_INDEX: case TD_VS_BORDER_COLOR_RED: case TD_VS_BORDER_COLOR_GREEN: case TD_VS_BORDER_COLOR_BLUE: case TD_VS_BORDER_COLOR_ALPHA: case TD_GS_BORDER_COLOR_INDEX: case TD_GS_BORDER_COLOR_RED: case TD_GS_BORDER_COLOR_GREEN: case TD_GS_BORDER_COLOR_BLUE: case TD_GS_BORDER_COLOR_ALPHA: case TD_HS_BORDER_COLOR_INDEX: case TD_HS_BORDER_COLOR_RED: case TD_HS_BORDER_COLOR_GREEN: case TD_HS_BORDER_COLOR_BLUE: case TD_HS_BORDER_COLOR_ALPHA: case TD_LS_BORDER_COLOR_INDEX: case TD_LS_BORDER_COLOR_RED: case TD_LS_BORDER_COLOR_GREEN: case TD_LS_BORDER_COLOR_BLUE: case TD_LS_BORDER_COLOR_ALPHA: case TD_CS_BORDER_COLOR_INDEX: case TD_CS_BORDER_COLOR_RED: case TD_CS_BORDER_COLOR_GREEN: case TD_CS_BORDER_COLOR_BLUE: case TD_CS_BORDER_COLOR_ALPHA: case SQ_ESGS_RING_SIZE: case SQ_GSVS_RING_SIZE: case SQ_ESTMP_RING_SIZE: case SQ_GSTMP_RING_SIZE: case SQ_HSTMP_RING_SIZE: case SQ_LSTMP_RING_SIZE: case SQ_PSTMP_RING_SIZE: case SQ_VSTMP_RING_SIZE: case SQ_ESGS_RING_ITEMSIZE: case SQ_ESTMP_RING_ITEMSIZE: case SQ_GSTMP_RING_ITEMSIZE: case SQ_GSVS_RING_ITEMSIZE: case SQ_GS_VERT_ITEMSIZE: case SQ_GS_VERT_ITEMSIZE_1: case SQ_GS_VERT_ITEMSIZE_2: case SQ_GS_VERT_ITEMSIZE_3: case SQ_GSVS_RING_OFFSET_1: case SQ_GSVS_RING_OFFSET_2: case SQ_GSVS_RING_OFFSET_3: case SQ_HSTMP_RING_ITEMSIZE: case SQ_LSTMP_RING_ITEMSIZE: case SQ_PSTMP_RING_ITEMSIZE: case SQ_VSTMP_RING_ITEMSIZE: case VGT_TF_RING_SIZE: case SQ_ESGS_RING_BASE: case SQ_GSVS_RING_BASE: case SQ_ESTMP_RING_BASE: case SQ_GSTMP_RING_BASE: case SQ_HSTMP_RING_BASE: case SQ_LSTMP_RING_BASE: case SQ_PSTMP_RING_BASE: case SQ_VSTMP_RING_BASE: case CAYMAN_VGT_OFFCHIP_LDS_BASE: case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS: returntrue; default:
DRM_ERROR("Invalid register 0x%x in CS\n", reg); returnfalse;
}
}
int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
{ int ret = 0;
u32 idx = 0; struct radeon_cs_packet pkt;
do {
pkt.idx = idx;
pkt.type = RADEON_CP_PACKET_GET_TYPE(ib->ptr[idx]);
pkt.count = RADEON_CP_PACKET_GET_COUNT(ib->ptr[idx]);
pkt.one_reg_wr = 0; switch (pkt.type) { case RADEON_PACKET_TYPE0:
dev_err(rdev->dev, "Packet0 not allowed!\n");
ret = -EINVAL; break; case RADEON_PACKET_TYPE2:
idx += 1; break; case RADEON_PACKET_TYPE3:
pkt.opcode = RADEON_CP_PACKET3_GET_OPCODE(ib->ptr[idx]);
ret = evergreen_vm_packet3_check(rdev, ib->ptr, &pkt);
idx += pkt.count + 2; break; default:
dev_err(rdev->dev, "Unknown packet type %d !\n", pkt.type);
ret = -EINVAL; break;
} if (ret) break;
} while (idx < ib->length_dw);
return ret;
}
/** * evergreen_dma_ib_parse() - parse the DMA IB for VM * @rdev: radeon_device pointer * @ib: radeon_ib pointer * * Parses the DMA IB from the VM CS ioctl * checks for errors. (Cayman-SI) * Returns 0 for success and an error on failure.
**/ int evergreen_dma_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
{
u32 idx = 0;
u32 header, cmd, count, sub_cmd;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.