Path: blob/master/drivers/gpu/drm/radeon/evergreen_cs.c
15113 views
/*1* Copyright 2010 Advanced Micro Devices, Inc.2* Copyright 2008 Red Hat Inc.3* Copyright 2009 Jerome Glisse.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the "Software"),7* to deal in the Software without restriction, including without limitation8* the rights to use, copy, modify, merge, publish, distribute, sublicense,9* and/or sell copies of the Software, and to permit persons to whom the10* Software is furnished to do so, subject to the following conditions:11*12* The above copyright notice and this permission notice shall be included in13* all copies or substantial portions of the Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL18* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR19* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,20* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR21* OTHER DEALINGS IN THE SOFTWARE.22*23* Authors: Dave Airlie24* Alex Deucher25* Jerome Glisse26*/27#include "drmP.h"28#include "radeon.h"29#include "evergreend.h"30#include "evergreen_reg_safe.h"31#include "cayman_reg_safe.h"3233static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,34struct radeon_cs_reloc **cs_reloc);3536struct evergreen_cs_track {37u32 group_size;38u32 nbanks;39u32 npipes;40/* value we track */41u32 nsamples;42u32 cb_color_base_last[12];43struct radeon_bo *cb_color_bo[12];44u32 cb_color_bo_offset[12];45struct radeon_bo *cb_color_fmask_bo[8];46struct radeon_bo *cb_color_cmask_bo[8];47u32 cb_color_info[12];48u32 cb_color_view[12];49u32 cb_color_pitch_idx[12];50u32 cb_color_slice_idx[12];51u32 cb_color_dim_idx[12];52u32 cb_color_dim[12];53u32 cb_color_pitch[12];54u32 cb_color_slice[12];55u32 cb_color_cmask_slice[8];56u32 cb_color_fmask_slice[8];57u32 cb_target_mask;58u32 cb_shader_mask;59u32 vgt_strmout_config;60u32 vgt_strmout_buffer_config;61u32 db_depth_control;62u32 db_depth_view;63u32 db_depth_size;64u32 db_depth_size_idx;65u32 db_z_info;66u32 db_z_idx;67u32 db_z_read_offset;68u32 db_z_write_offset;69struct radeon_bo *db_z_read_bo;70struct radeon_bo *db_z_write_bo;71u32 db_s_info;72u32 db_s_idx;73u32 db_s_read_offset;74u32 db_s_write_offset;75struct radeon_bo *db_s_read_bo;76struct radeon_bo *db_s_write_bo;77};7879static void evergreen_cs_track_init(struct evergreen_cs_track *track)80{81int i;8283for (i = 0; i < 8; i++) {84track->cb_color_fmask_bo[i] = NULL;85track->cb_color_cmask_bo[i] = NULL;86track->cb_color_cmask_slice[i] = 0;87track->cb_color_fmask_slice[i] = 0;88}8990for (i = 0; i < 12; i++) {91track->cb_color_base_last[i] = 0;92track->cb_color_bo[i] = NULL;93track->cb_color_bo_offset[i] = 0xFFFFFFFF;94track->cb_color_info[i] = 0;95track->cb_color_view[i] = 0;96track->cb_color_pitch_idx[i] = 0;97track->cb_color_slice_idx[i] = 0;98track->cb_color_dim[i] = 0;99track->cb_color_pitch[i] = 0;100track->cb_color_slice[i] = 0;101track->cb_color_dim[i] = 0;102}103track->cb_target_mask = 0xFFFFFFFF;104track->cb_shader_mask = 0xFFFFFFFF;105106track->db_depth_view = 0xFFFFC000;107track->db_depth_size = 0xFFFFFFFF;108track->db_depth_size_idx = 0;109track->db_depth_control = 0xFFFFFFFF;110track->db_z_info = 0xFFFFFFFF;111track->db_z_idx = 0xFFFFFFFF;112track->db_z_read_offset = 0xFFFFFFFF;113track->db_z_write_offset = 0xFFFFFFFF;114track->db_z_read_bo = NULL;115track->db_z_write_bo = NULL;116track->db_s_info = 0xFFFFFFFF;117track->db_s_idx = 0xFFFFFFFF;118track->db_s_read_offset = 0xFFFFFFFF;119track->db_s_write_offset = 0xFFFFFFFF;120track->db_s_read_bo = NULL;121track->db_s_write_bo = NULL;122}123124static inline int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, int i)125{126/* XXX fill in */127return 0;128}129130static int evergreen_cs_track_check(struct radeon_cs_parser *p)131{132struct evergreen_cs_track *track = p->track;133134/* we don't support stream out buffer yet */135if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) {136dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");137return -EINVAL;138}139140/* XXX fill in */141return 0;142}143144/**145* evergreen_cs_packet_parse() - parse cp packet and point ib index to next packet146* @parser: parser structure holding parsing context.147* @pkt: where to store packet informations148*149* Assume that chunk_ib_index is properly set. Will return -EINVAL150* if packet is bigger than remaining ib size. or if packets is unknown.151**/152int evergreen_cs_packet_parse(struct radeon_cs_parser *p,153struct radeon_cs_packet *pkt,154unsigned idx)155{156struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];157uint32_t header;158159if (idx >= ib_chunk->length_dw) {160DRM_ERROR("Can not parse packet at %d after CS end %d !\n",161idx, ib_chunk->length_dw);162return -EINVAL;163}164header = radeon_get_ib_value(p, idx);165pkt->idx = idx;166pkt->type = CP_PACKET_GET_TYPE(header);167pkt->count = CP_PACKET_GET_COUNT(header);168pkt->one_reg_wr = 0;169switch (pkt->type) {170case PACKET_TYPE0:171pkt->reg = CP_PACKET0_GET_REG(header);172break;173case PACKET_TYPE3:174pkt->opcode = CP_PACKET3_GET_OPCODE(header);175break;176case PACKET_TYPE2:177pkt->count = -1;178break;179default:180DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);181return -EINVAL;182}183if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {184DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",185pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);186return -EINVAL;187}188return 0;189}190191/**192* evergreen_cs_packet_next_reloc() - parse next packet which should be reloc packet3193* @parser: parser structure holding parsing context.194* @data: pointer to relocation data195* @offset_start: starting offset196* @offset_mask: offset mask (to align start offset on)197* @reloc: reloc informations198*199* Check next packet is relocation packet3, do bo validation and compute200* GPU offset using the provided start.201**/202static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,203struct radeon_cs_reloc **cs_reloc)204{205struct radeon_cs_chunk *relocs_chunk;206struct radeon_cs_packet p3reloc;207unsigned idx;208int r;209210if (p->chunk_relocs_idx == -1) {211DRM_ERROR("No relocation chunk !\n");212return -EINVAL;213}214*cs_reloc = NULL;215relocs_chunk = &p->chunks[p->chunk_relocs_idx];216r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);217if (r) {218return r;219}220p->idx += p3reloc.count + 2;221if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {222DRM_ERROR("No packet3 for relocation for packet at %d.\n",223p3reloc.idx);224return -EINVAL;225}226idx = radeon_get_ib_value(p, p3reloc.idx + 1);227if (idx >= relocs_chunk->length_dw) {228DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",229idx, relocs_chunk->length_dw);230return -EINVAL;231}232/* FIXME: we assume reloc size is 4 dwords */233*cs_reloc = p->relocs_ptr[(idx / 4)];234return 0;235}236237/**238* evergreen_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc239* @parser: parser structure holding parsing context.240*241* Check next packet is relocation packet3, do bo validation and compute242* GPU offset using the provided start.243**/244static inline int evergreen_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)245{246struct radeon_cs_packet p3reloc;247int r;248249r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);250if (r) {251return 0;252}253if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {254return 0;255}256return 1;257}258259/**260* evergreen_cs_packet_next_vline() - parse userspace VLINE packet261* @parser: parser structure holding parsing context.262*263* Userspace sends a special sequence for VLINE waits.264* PACKET0 - VLINE_START_END + value265* PACKET3 - WAIT_REG_MEM poll vline status reg266* RELOC (P3) - crtc_id in reloc.267*268* This function parses this and relocates the VLINE START END269* and WAIT_REG_MEM packets to the correct crtc.270* It also detects a switched off crtc and nulls out the271* wait in that case.272*/273static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)274{275struct drm_mode_object *obj;276struct drm_crtc *crtc;277struct radeon_crtc *radeon_crtc;278struct radeon_cs_packet p3reloc, wait_reg_mem;279int crtc_id;280int r;281uint32_t header, h_idx, reg, wait_reg_mem_info;282volatile uint32_t *ib;283284ib = p->ib->ptr;285286/* parse the WAIT_REG_MEM */287r = evergreen_cs_packet_parse(p, &wait_reg_mem, p->idx);288if (r)289return r;290291/* check its a WAIT_REG_MEM */292if (wait_reg_mem.type != PACKET_TYPE3 ||293wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {294DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");295return -EINVAL;296}297298wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);299/* bit 4 is reg (0) or mem (1) */300if (wait_reg_mem_info & 0x10) {301DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");302return -EINVAL;303}304/* waiting for value to be equal */305if ((wait_reg_mem_info & 0x7) != 0x3) {306DRM_ERROR("vline WAIT_REG_MEM function not equal\n");307return -EINVAL;308}309if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != EVERGREEN_VLINE_STATUS) {310DRM_ERROR("vline WAIT_REG_MEM bad reg\n");311return -EINVAL;312}313314if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != EVERGREEN_VLINE_STAT) {315DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");316return -EINVAL;317}318319/* jump over the NOP */320r = evergreen_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);321if (r)322return r;323324h_idx = p->idx - 2;325p->idx += wait_reg_mem.count + 2;326p->idx += p3reloc.count + 2;327328header = radeon_get_ib_value(p, h_idx);329crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);330reg = CP_PACKET0_GET_REG(header);331obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);332if (!obj) {333DRM_ERROR("cannot find crtc %d\n", crtc_id);334return -EINVAL;335}336crtc = obj_to_crtc(obj);337radeon_crtc = to_radeon_crtc(crtc);338crtc_id = radeon_crtc->crtc_id;339340if (!crtc->enabled) {341/* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */342ib[h_idx + 2] = PACKET2(0);343ib[h_idx + 3] = PACKET2(0);344ib[h_idx + 4] = PACKET2(0);345ib[h_idx + 5] = PACKET2(0);346ib[h_idx + 6] = PACKET2(0);347ib[h_idx + 7] = PACKET2(0);348ib[h_idx + 8] = PACKET2(0);349} else {350switch (reg) {351case EVERGREEN_VLINE_START_END:352header &= ~R600_CP_PACKET0_REG_MASK;353header |= (EVERGREEN_VLINE_START_END + radeon_crtc->crtc_offset) >> 2;354ib[h_idx] = header;355ib[h_idx + 4] = (EVERGREEN_VLINE_STATUS + radeon_crtc->crtc_offset) >> 2;356break;357default:358DRM_ERROR("unknown crtc reloc\n");359return -EINVAL;360}361}362return 0;363}364365static int evergreen_packet0_check(struct radeon_cs_parser *p,366struct radeon_cs_packet *pkt,367unsigned idx, unsigned reg)368{369int r;370371switch (reg) {372case EVERGREEN_VLINE_START_END:373r = evergreen_cs_packet_parse_vline(p);374if (r) {375DRM_ERROR("No reloc for ib[%d]=0x%04X\n",376idx, reg);377return r;378}379break;380default:381printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",382reg, idx);383return -EINVAL;384}385return 0;386}387388static int evergreen_cs_parse_packet0(struct radeon_cs_parser *p,389struct radeon_cs_packet *pkt)390{391unsigned reg, i;392unsigned idx;393int r;394395idx = pkt->idx + 1;396reg = pkt->reg;397for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {398r = evergreen_packet0_check(p, pkt, idx, reg);399if (r) {400return r;401}402}403return 0;404}405406/**407* evergreen_cs_check_reg() - check if register is authorized or not408* @parser: parser structure holding parsing context409* @reg: register we are testing410* @idx: index into the cs buffer411*412* This function will test against evergreen_reg_safe_bm and return 0413* if register is safe. If register is not flag as safe this function414* will test it against a list of register needind special handling.415*/416static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)417{418struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track;419struct radeon_cs_reloc *reloc;420u32 last_reg;421u32 m, i, tmp, *ib;422int r;423424if (p->rdev->family >= CHIP_CAYMAN)425last_reg = ARRAY_SIZE(cayman_reg_safe_bm);426else427last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);428429i = (reg >> 7);430if (i > last_reg) {431dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);432return -EINVAL;433}434m = 1 << ((reg >> 2) & 31);435if (p->rdev->family >= CHIP_CAYMAN) {436if (!(cayman_reg_safe_bm[i] & m))437return 0;438} else {439if (!(evergreen_reg_safe_bm[i] & m))440return 0;441}442ib = p->ib->ptr;443switch (reg) {444/* force following reg to 0 in an attempt to disable out buffer445* which will need us to better understand how it works to perform446* security check on it (Jerome)447*/448case SQ_ESGS_RING_SIZE:449case SQ_GSVS_RING_SIZE:450case SQ_ESTMP_RING_SIZE:451case SQ_GSTMP_RING_SIZE:452case SQ_HSTMP_RING_SIZE:453case SQ_LSTMP_RING_SIZE:454case SQ_PSTMP_RING_SIZE:455case SQ_VSTMP_RING_SIZE:456case SQ_ESGS_RING_ITEMSIZE:457case SQ_ESTMP_RING_ITEMSIZE:458case SQ_GSTMP_RING_ITEMSIZE:459case SQ_GSVS_RING_ITEMSIZE:460case SQ_GS_VERT_ITEMSIZE:461case SQ_GS_VERT_ITEMSIZE_1:462case SQ_GS_VERT_ITEMSIZE_2:463case SQ_GS_VERT_ITEMSIZE_3:464case SQ_GSVS_RING_OFFSET_1:465case SQ_GSVS_RING_OFFSET_2:466case SQ_GSVS_RING_OFFSET_3:467case SQ_HSTMP_RING_ITEMSIZE:468case SQ_LSTMP_RING_ITEMSIZE:469case SQ_PSTMP_RING_ITEMSIZE:470case SQ_VSTMP_RING_ITEMSIZE:471case VGT_TF_RING_SIZE:472/* get value to populate the IB don't remove */473/*tmp =radeon_get_ib_value(p, idx);474ib[idx] = 0;*/475break;476case SQ_ESGS_RING_BASE:477case SQ_GSVS_RING_BASE:478case SQ_ESTMP_RING_BASE:479case SQ_GSTMP_RING_BASE:480case SQ_HSTMP_RING_BASE:481case SQ_LSTMP_RING_BASE:482case SQ_PSTMP_RING_BASE:483case SQ_VSTMP_RING_BASE:484r = evergreen_cs_packet_next_reloc(p, &reloc);485if (r) {486dev_warn(p->dev, "bad SET_CONTEXT_REG "487"0x%04X\n", reg);488return -EINVAL;489}490ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);491break;492case DB_DEPTH_CONTROL:493track->db_depth_control = radeon_get_ib_value(p, idx);494break;495case CAYMAN_DB_EQAA:496if (p->rdev->family < CHIP_CAYMAN) {497dev_warn(p->dev, "bad SET_CONTEXT_REG "498"0x%04X\n", reg);499return -EINVAL;500}501break;502case CAYMAN_DB_DEPTH_INFO:503if (p->rdev->family < CHIP_CAYMAN) {504dev_warn(p->dev, "bad SET_CONTEXT_REG "505"0x%04X\n", reg);506return -EINVAL;507}508break;509case DB_Z_INFO:510r = evergreen_cs_packet_next_reloc(p, &reloc);511if (r) {512dev_warn(p->dev, "bad SET_CONTEXT_REG "513"0x%04X\n", reg);514return -EINVAL;515}516track->db_z_info = radeon_get_ib_value(p, idx);517ib[idx] &= ~Z_ARRAY_MODE(0xf);518track->db_z_info &= ~Z_ARRAY_MODE(0xf);519if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {520ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);521track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);522} else {523ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);524track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);525}526break;527case DB_STENCIL_INFO:528track->db_s_info = radeon_get_ib_value(p, idx);529break;530case DB_DEPTH_VIEW:531track->db_depth_view = radeon_get_ib_value(p, idx);532break;533case DB_DEPTH_SIZE:534track->db_depth_size = radeon_get_ib_value(p, idx);535track->db_depth_size_idx = idx;536break;537case DB_Z_READ_BASE:538r = evergreen_cs_packet_next_reloc(p, &reloc);539if (r) {540dev_warn(p->dev, "bad SET_CONTEXT_REG "541"0x%04X\n", reg);542return -EINVAL;543}544track->db_z_read_offset = radeon_get_ib_value(p, idx);545ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);546track->db_z_read_bo = reloc->robj;547break;548case DB_Z_WRITE_BASE:549r = evergreen_cs_packet_next_reloc(p, &reloc);550if (r) {551dev_warn(p->dev, "bad SET_CONTEXT_REG "552"0x%04X\n", reg);553return -EINVAL;554}555track->db_z_write_offset = radeon_get_ib_value(p, idx);556ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);557track->db_z_write_bo = reloc->robj;558break;559case DB_STENCIL_READ_BASE:560r = evergreen_cs_packet_next_reloc(p, &reloc);561if (r) {562dev_warn(p->dev, "bad SET_CONTEXT_REG "563"0x%04X\n", reg);564return -EINVAL;565}566track->db_s_read_offset = radeon_get_ib_value(p, idx);567ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);568track->db_s_read_bo = reloc->robj;569break;570case DB_STENCIL_WRITE_BASE:571r = evergreen_cs_packet_next_reloc(p, &reloc);572if (r) {573dev_warn(p->dev, "bad SET_CONTEXT_REG "574"0x%04X\n", reg);575return -EINVAL;576}577track->db_s_write_offset = radeon_get_ib_value(p, idx);578ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);579track->db_s_write_bo = reloc->robj;580break;581case VGT_STRMOUT_CONFIG:582track->vgt_strmout_config = radeon_get_ib_value(p, idx);583break;584case VGT_STRMOUT_BUFFER_CONFIG:585track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx);586break;587case CB_TARGET_MASK:588track->cb_target_mask = radeon_get_ib_value(p, idx);589break;590case CB_SHADER_MASK:591track->cb_shader_mask = radeon_get_ib_value(p, idx);592break;593case PA_SC_AA_CONFIG:594if (p->rdev->family >= CHIP_CAYMAN) {595dev_warn(p->dev, "bad SET_CONTEXT_REG "596"0x%04X\n", reg);597return -EINVAL;598}599tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK;600track->nsamples = 1 << tmp;601break;602case CAYMAN_PA_SC_AA_CONFIG:603if (p->rdev->family < CHIP_CAYMAN) {604dev_warn(p->dev, "bad SET_CONTEXT_REG "605"0x%04X\n", reg);606return -EINVAL;607}608tmp = radeon_get_ib_value(p, idx) & CAYMAN_MSAA_NUM_SAMPLES_MASK;609track->nsamples = 1 << tmp;610break;611case CB_COLOR0_VIEW:612case CB_COLOR1_VIEW:613case CB_COLOR2_VIEW:614case CB_COLOR3_VIEW:615case CB_COLOR4_VIEW:616case CB_COLOR5_VIEW:617case CB_COLOR6_VIEW:618case CB_COLOR7_VIEW:619tmp = (reg - CB_COLOR0_VIEW) / 0x3c;620track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);621break;622case CB_COLOR8_VIEW:623case CB_COLOR9_VIEW:624case CB_COLOR10_VIEW:625case CB_COLOR11_VIEW:626tmp = ((reg - CB_COLOR8_VIEW) / 0x1c) + 8;627track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);628break;629case CB_COLOR0_INFO:630case CB_COLOR1_INFO:631case CB_COLOR2_INFO:632case CB_COLOR3_INFO:633case CB_COLOR4_INFO:634case CB_COLOR5_INFO:635case CB_COLOR6_INFO:636case CB_COLOR7_INFO:637r = evergreen_cs_packet_next_reloc(p, &reloc);638if (r) {639dev_warn(p->dev, "bad SET_CONTEXT_REG "640"0x%04X\n", reg);641return -EINVAL;642}643tmp = (reg - CB_COLOR0_INFO) / 0x3c;644track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);645if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {646ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);647track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);648} else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {649ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);650track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);651}652break;653case CB_COLOR8_INFO:654case CB_COLOR9_INFO:655case CB_COLOR10_INFO:656case CB_COLOR11_INFO:657r = evergreen_cs_packet_next_reloc(p, &reloc);658if (r) {659dev_warn(p->dev, "bad SET_CONTEXT_REG "660"0x%04X\n", reg);661return -EINVAL;662}663tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;664track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);665if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {666ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);667track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);668} else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {669ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);670track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);671}672break;673case CB_COLOR0_PITCH:674case CB_COLOR1_PITCH:675case CB_COLOR2_PITCH:676case CB_COLOR3_PITCH:677case CB_COLOR4_PITCH:678case CB_COLOR5_PITCH:679case CB_COLOR6_PITCH:680case CB_COLOR7_PITCH:681tmp = (reg - CB_COLOR0_PITCH) / 0x3c;682track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);683track->cb_color_pitch_idx[tmp] = idx;684break;685case CB_COLOR8_PITCH:686case CB_COLOR9_PITCH:687case CB_COLOR10_PITCH:688case CB_COLOR11_PITCH:689tmp = ((reg - CB_COLOR8_PITCH) / 0x1c) + 8;690track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);691track->cb_color_pitch_idx[tmp] = idx;692break;693case CB_COLOR0_SLICE:694case CB_COLOR1_SLICE:695case CB_COLOR2_SLICE:696case CB_COLOR3_SLICE:697case CB_COLOR4_SLICE:698case CB_COLOR5_SLICE:699case CB_COLOR6_SLICE:700case CB_COLOR7_SLICE:701tmp = (reg - CB_COLOR0_SLICE) / 0x3c;702track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);703track->cb_color_slice_idx[tmp] = idx;704break;705case CB_COLOR8_SLICE:706case CB_COLOR9_SLICE:707case CB_COLOR10_SLICE:708case CB_COLOR11_SLICE:709tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8;710track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);711track->cb_color_slice_idx[tmp] = idx;712break;713case CB_COLOR0_ATTRIB:714case CB_COLOR1_ATTRIB:715case CB_COLOR2_ATTRIB:716case CB_COLOR3_ATTRIB:717case CB_COLOR4_ATTRIB:718case CB_COLOR5_ATTRIB:719case CB_COLOR6_ATTRIB:720case CB_COLOR7_ATTRIB:721case CB_COLOR8_ATTRIB:722case CB_COLOR9_ATTRIB:723case CB_COLOR10_ATTRIB:724case CB_COLOR11_ATTRIB:725break;726case CB_COLOR0_DIM:727case CB_COLOR1_DIM:728case CB_COLOR2_DIM:729case CB_COLOR3_DIM:730case CB_COLOR4_DIM:731case CB_COLOR5_DIM:732case CB_COLOR6_DIM:733case CB_COLOR7_DIM:734tmp = (reg - CB_COLOR0_DIM) / 0x3c;735track->cb_color_dim[tmp] = radeon_get_ib_value(p, idx);736track->cb_color_dim_idx[tmp] = idx;737break;738case CB_COLOR8_DIM:739case CB_COLOR9_DIM:740case CB_COLOR10_DIM:741case CB_COLOR11_DIM:742tmp = ((reg - CB_COLOR8_DIM) / 0x1c) + 8;743track->cb_color_dim[tmp] = radeon_get_ib_value(p, idx);744track->cb_color_dim_idx[tmp] = idx;745break;746case CB_COLOR0_FMASK:747case CB_COLOR1_FMASK:748case CB_COLOR2_FMASK:749case CB_COLOR3_FMASK:750case CB_COLOR4_FMASK:751case CB_COLOR5_FMASK:752case CB_COLOR6_FMASK:753case CB_COLOR7_FMASK:754tmp = (reg - CB_COLOR0_FMASK) / 0x3c;755r = evergreen_cs_packet_next_reloc(p, &reloc);756if (r) {757dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);758return -EINVAL;759}760ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);761track->cb_color_fmask_bo[tmp] = reloc->robj;762break;763case CB_COLOR0_CMASK:764case CB_COLOR1_CMASK:765case CB_COLOR2_CMASK:766case CB_COLOR3_CMASK:767case CB_COLOR4_CMASK:768case CB_COLOR5_CMASK:769case CB_COLOR6_CMASK:770case CB_COLOR7_CMASK:771tmp = (reg - CB_COLOR0_CMASK) / 0x3c;772r = evergreen_cs_packet_next_reloc(p, &reloc);773if (r) {774dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);775return -EINVAL;776}777ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);778track->cb_color_cmask_bo[tmp] = reloc->robj;779break;780case CB_COLOR0_FMASK_SLICE:781case CB_COLOR1_FMASK_SLICE:782case CB_COLOR2_FMASK_SLICE:783case CB_COLOR3_FMASK_SLICE:784case CB_COLOR4_FMASK_SLICE:785case CB_COLOR5_FMASK_SLICE:786case CB_COLOR6_FMASK_SLICE:787case CB_COLOR7_FMASK_SLICE:788tmp = (reg - CB_COLOR0_FMASK_SLICE) / 0x3c;789track->cb_color_fmask_slice[tmp] = radeon_get_ib_value(p, idx);790break;791case CB_COLOR0_CMASK_SLICE:792case CB_COLOR1_CMASK_SLICE:793case CB_COLOR2_CMASK_SLICE:794case CB_COLOR3_CMASK_SLICE:795case CB_COLOR4_CMASK_SLICE:796case CB_COLOR5_CMASK_SLICE:797case CB_COLOR6_CMASK_SLICE:798case CB_COLOR7_CMASK_SLICE:799tmp = (reg - CB_COLOR0_CMASK_SLICE) / 0x3c;800track->cb_color_cmask_slice[tmp] = radeon_get_ib_value(p, idx);801break;802case CB_COLOR0_BASE:803case CB_COLOR1_BASE:804case CB_COLOR2_BASE:805case CB_COLOR3_BASE:806case CB_COLOR4_BASE:807case CB_COLOR5_BASE:808case CB_COLOR6_BASE:809case CB_COLOR7_BASE:810r = evergreen_cs_packet_next_reloc(p, &reloc);811if (r) {812dev_warn(p->dev, "bad SET_CONTEXT_REG "813"0x%04X\n", reg);814return -EINVAL;815}816tmp = (reg - CB_COLOR0_BASE) / 0x3c;817track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);818ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);819track->cb_color_base_last[tmp] = ib[idx];820track->cb_color_bo[tmp] = reloc->robj;821break;822case CB_COLOR8_BASE:823case CB_COLOR9_BASE:824case CB_COLOR10_BASE:825case CB_COLOR11_BASE:826r = evergreen_cs_packet_next_reloc(p, &reloc);827if (r) {828dev_warn(p->dev, "bad SET_CONTEXT_REG "829"0x%04X\n", reg);830return -EINVAL;831}832tmp = ((reg - CB_COLOR8_BASE) / 0x1c) + 8;833track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);834ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);835track->cb_color_base_last[tmp] = ib[idx];836track->cb_color_bo[tmp] = reloc->robj;837break;838case CB_IMMED0_BASE:839case CB_IMMED1_BASE:840case CB_IMMED2_BASE:841case CB_IMMED3_BASE:842case CB_IMMED4_BASE:843case CB_IMMED5_BASE:844case CB_IMMED6_BASE:845case CB_IMMED7_BASE:846case CB_IMMED8_BASE:847case CB_IMMED9_BASE:848case CB_IMMED10_BASE:849case CB_IMMED11_BASE:850case DB_HTILE_DATA_BASE:851case SQ_PGM_START_FS:852case SQ_PGM_START_ES:853case SQ_PGM_START_VS:854case SQ_PGM_START_GS:855case SQ_PGM_START_PS:856case SQ_PGM_START_HS:857case SQ_PGM_START_LS:858case GDS_ADDR_BASE:859case SQ_CONST_MEM_BASE:860case SQ_ALU_CONST_CACHE_GS_0:861case SQ_ALU_CONST_CACHE_GS_1:862case SQ_ALU_CONST_CACHE_GS_2:863case SQ_ALU_CONST_CACHE_GS_3:864case SQ_ALU_CONST_CACHE_GS_4:865case SQ_ALU_CONST_CACHE_GS_5:866case SQ_ALU_CONST_CACHE_GS_6:867case SQ_ALU_CONST_CACHE_GS_7:868case SQ_ALU_CONST_CACHE_GS_8:869case SQ_ALU_CONST_CACHE_GS_9:870case SQ_ALU_CONST_CACHE_GS_10:871case SQ_ALU_CONST_CACHE_GS_11:872case SQ_ALU_CONST_CACHE_GS_12:873case SQ_ALU_CONST_CACHE_GS_13:874case SQ_ALU_CONST_CACHE_GS_14:875case SQ_ALU_CONST_CACHE_GS_15:876case SQ_ALU_CONST_CACHE_PS_0:877case SQ_ALU_CONST_CACHE_PS_1:878case SQ_ALU_CONST_CACHE_PS_2:879case SQ_ALU_CONST_CACHE_PS_3:880case SQ_ALU_CONST_CACHE_PS_4:881case SQ_ALU_CONST_CACHE_PS_5:882case SQ_ALU_CONST_CACHE_PS_6:883case SQ_ALU_CONST_CACHE_PS_7:884case SQ_ALU_CONST_CACHE_PS_8:885case SQ_ALU_CONST_CACHE_PS_9:886case SQ_ALU_CONST_CACHE_PS_10:887case SQ_ALU_CONST_CACHE_PS_11:888case SQ_ALU_CONST_CACHE_PS_12:889case SQ_ALU_CONST_CACHE_PS_13:890case SQ_ALU_CONST_CACHE_PS_14:891case SQ_ALU_CONST_CACHE_PS_15:892case SQ_ALU_CONST_CACHE_VS_0:893case SQ_ALU_CONST_CACHE_VS_1:894case SQ_ALU_CONST_CACHE_VS_2:895case SQ_ALU_CONST_CACHE_VS_3:896case SQ_ALU_CONST_CACHE_VS_4:897case SQ_ALU_CONST_CACHE_VS_5:898case SQ_ALU_CONST_CACHE_VS_6:899case SQ_ALU_CONST_CACHE_VS_7:900case SQ_ALU_CONST_CACHE_VS_8:901case SQ_ALU_CONST_CACHE_VS_9:902case SQ_ALU_CONST_CACHE_VS_10:903case SQ_ALU_CONST_CACHE_VS_11:904case SQ_ALU_CONST_CACHE_VS_12:905case SQ_ALU_CONST_CACHE_VS_13:906case SQ_ALU_CONST_CACHE_VS_14:907case SQ_ALU_CONST_CACHE_VS_15:908case SQ_ALU_CONST_CACHE_HS_0:909case SQ_ALU_CONST_CACHE_HS_1:910case SQ_ALU_CONST_CACHE_HS_2:911case SQ_ALU_CONST_CACHE_HS_3:912case SQ_ALU_CONST_CACHE_HS_4:913case SQ_ALU_CONST_CACHE_HS_5:914case SQ_ALU_CONST_CACHE_HS_6:915case SQ_ALU_CONST_CACHE_HS_7:916case SQ_ALU_CONST_CACHE_HS_8:917case SQ_ALU_CONST_CACHE_HS_9:918case SQ_ALU_CONST_CACHE_HS_10:919case SQ_ALU_CONST_CACHE_HS_11:920case SQ_ALU_CONST_CACHE_HS_12:921case SQ_ALU_CONST_CACHE_HS_13:922case SQ_ALU_CONST_CACHE_HS_14:923case SQ_ALU_CONST_CACHE_HS_15:924case SQ_ALU_CONST_CACHE_LS_0:925case SQ_ALU_CONST_CACHE_LS_1:926case SQ_ALU_CONST_CACHE_LS_2:927case SQ_ALU_CONST_CACHE_LS_3:928case SQ_ALU_CONST_CACHE_LS_4:929case SQ_ALU_CONST_CACHE_LS_5:930case SQ_ALU_CONST_CACHE_LS_6:931case SQ_ALU_CONST_CACHE_LS_7:932case SQ_ALU_CONST_CACHE_LS_8:933case SQ_ALU_CONST_CACHE_LS_9:934case SQ_ALU_CONST_CACHE_LS_10:935case SQ_ALU_CONST_CACHE_LS_11:936case SQ_ALU_CONST_CACHE_LS_12:937case SQ_ALU_CONST_CACHE_LS_13:938case SQ_ALU_CONST_CACHE_LS_14:939case SQ_ALU_CONST_CACHE_LS_15:940r = evergreen_cs_packet_next_reloc(p, &reloc);941if (r) {942dev_warn(p->dev, "bad SET_CONTEXT_REG "943"0x%04X\n", reg);944return -EINVAL;945}946ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);947break;948default:949dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);950return -EINVAL;951}952return 0;953}954955/**956* evergreen_check_texture_resource() - check if register is authorized or not957* @p: parser structure holding parsing context958* @idx: index into the cs buffer959* @texture: texture's bo structure960* @mipmap: mipmap's bo structure961*962* This function will check that the resource has valid field and that963* the texture and mipmap bo object are big enough to cover this resource.964*/965static inline int evergreen_check_texture_resource(struct radeon_cs_parser *p, u32 idx,966struct radeon_bo *texture,967struct radeon_bo *mipmap)968{969/* XXX fill in */970return 0;971}972973static int evergreen_packet3_check(struct radeon_cs_parser *p,974struct radeon_cs_packet *pkt)975{976struct radeon_cs_reloc *reloc;977struct evergreen_cs_track *track;978volatile u32 *ib;979unsigned idx;980unsigned i;981unsigned start_reg, end_reg, reg;982int r;983u32 idx_value;984985track = (struct evergreen_cs_track *)p->track;986ib = p->ib->ptr;987idx = pkt->idx + 1;988idx_value = radeon_get_ib_value(p, idx);989990switch (pkt->opcode) {991case PACKET3_SET_PREDICATION:992{993int pred_op;994int tmp;995if (pkt->count != 1) {996DRM_ERROR("bad SET PREDICATION\n");997return -EINVAL;998}9991000tmp = radeon_get_ib_value(p, idx + 1);1001pred_op = (tmp >> 16) & 0x7;10021003/* for the clear predicate operation */1004if (pred_op == 0)1005return 0;10061007if (pred_op > 2) {1008DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op);1009return -EINVAL;1010}10111012r = evergreen_cs_packet_next_reloc(p, &reloc);1013if (r) {1014DRM_ERROR("bad SET PREDICATION\n");1015return -EINVAL;1016}10171018ib[idx + 0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);1019ib[idx + 1] = tmp + (upper_32_bits(reloc->lobj.gpu_offset) & 0xff);1020}1021break;1022case PACKET3_CONTEXT_CONTROL:1023if (pkt->count != 1) {1024DRM_ERROR("bad CONTEXT_CONTROL\n");1025return -EINVAL;1026}1027break;1028case PACKET3_INDEX_TYPE:1029case PACKET3_NUM_INSTANCES:1030case PACKET3_CLEAR_STATE:1031if (pkt->count) {1032DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");1033return -EINVAL;1034}1035break;1036case CAYMAN_PACKET3_DEALLOC_STATE:1037if (p->rdev->family < CHIP_CAYMAN) {1038DRM_ERROR("bad PACKET3_DEALLOC_STATE\n");1039return -EINVAL;1040}1041if (pkt->count) {1042DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");1043return -EINVAL;1044}1045break;1046case PACKET3_INDEX_BASE:1047if (pkt->count != 1) {1048DRM_ERROR("bad INDEX_BASE\n");1049return -EINVAL;1050}1051r = evergreen_cs_packet_next_reloc(p, &reloc);1052if (r) {1053DRM_ERROR("bad INDEX_BASE\n");1054return -EINVAL;1055}1056ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);1057ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;1058r = evergreen_cs_track_check(p);1059if (r) {1060dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);1061return r;1062}1063break;1064case PACKET3_DRAW_INDEX:1065if (pkt->count != 3) {1066DRM_ERROR("bad DRAW_INDEX\n");1067return -EINVAL;1068}1069r = evergreen_cs_packet_next_reloc(p, &reloc);1070if (r) {1071DRM_ERROR("bad DRAW_INDEX\n");1072return -EINVAL;1073}1074ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);1075ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;1076r = evergreen_cs_track_check(p);1077if (r) {1078dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);1079return r;1080}1081break;1082case PACKET3_DRAW_INDEX_2:1083if (pkt->count != 4) {1084DRM_ERROR("bad DRAW_INDEX_2\n");1085return -EINVAL;1086}1087r = evergreen_cs_packet_next_reloc(p, &reloc);1088if (r) {1089DRM_ERROR("bad DRAW_INDEX_2\n");1090return -EINVAL;1091}1092ib[idx+1] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);1093ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;1094r = evergreen_cs_track_check(p);1095if (r) {1096dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);1097return r;1098}1099break;1100case PACKET3_DRAW_INDEX_AUTO:1101if (pkt->count != 1) {1102DRM_ERROR("bad DRAW_INDEX_AUTO\n");1103return -EINVAL;1104}1105r = evergreen_cs_track_check(p);1106if (r) {1107dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);1108return r;1109}1110break;1111case PACKET3_DRAW_INDEX_MULTI_AUTO:1112if (pkt->count != 2) {1113DRM_ERROR("bad DRAW_INDEX_MULTI_AUTO\n");1114return -EINVAL;1115}1116r = evergreen_cs_track_check(p);1117if (r) {1118dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);1119return r;1120}1121break;1122case PACKET3_DRAW_INDEX_IMMD:1123if (pkt->count < 2) {1124DRM_ERROR("bad DRAW_INDEX_IMMD\n");1125return -EINVAL;1126}1127r = evergreen_cs_track_check(p);1128if (r) {1129dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);1130return r;1131}1132break;1133case PACKET3_DRAW_INDEX_OFFSET:1134if (pkt->count != 2) {1135DRM_ERROR("bad DRAW_INDEX_OFFSET\n");1136return -EINVAL;1137}1138r = evergreen_cs_track_check(p);1139if (r) {1140dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);1141return r;1142}1143break;1144case PACKET3_DRAW_INDEX_OFFSET_2:1145if (pkt->count != 3) {1146DRM_ERROR("bad DRAW_INDEX_OFFSET_2\n");1147return -EINVAL;1148}1149r = evergreen_cs_track_check(p);1150if (r) {1151dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);1152return r;1153}1154break;1155case PACKET3_WAIT_REG_MEM:1156if (pkt->count != 5) {1157DRM_ERROR("bad WAIT_REG_MEM\n");1158return -EINVAL;1159}1160/* bit 4 is reg (0) or mem (1) */1161if (idx_value & 0x10) {1162r = evergreen_cs_packet_next_reloc(p, &reloc);1163if (r) {1164DRM_ERROR("bad WAIT_REG_MEM\n");1165return -EINVAL;1166}1167ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);1168ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;1169}1170break;1171case PACKET3_SURFACE_SYNC:1172if (pkt->count != 3) {1173DRM_ERROR("bad SURFACE_SYNC\n");1174return -EINVAL;1175}1176/* 0xffffffff/0x0 is flush all cache flag */1177if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||1178radeon_get_ib_value(p, idx + 2) != 0) {1179r = evergreen_cs_packet_next_reloc(p, &reloc);1180if (r) {1181DRM_ERROR("bad SURFACE_SYNC\n");1182return -EINVAL;1183}1184ib[idx+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);1185}1186break;1187case PACKET3_EVENT_WRITE:1188if (pkt->count != 2 && pkt->count != 0) {1189DRM_ERROR("bad EVENT_WRITE\n");1190return -EINVAL;1191}1192if (pkt->count) {1193r = evergreen_cs_packet_next_reloc(p, &reloc);1194if (r) {1195DRM_ERROR("bad EVENT_WRITE\n");1196return -EINVAL;1197}1198ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);1199ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;1200}1201break;1202case PACKET3_EVENT_WRITE_EOP:1203if (pkt->count != 4) {1204DRM_ERROR("bad EVENT_WRITE_EOP\n");1205return -EINVAL;1206}1207r = evergreen_cs_packet_next_reloc(p, &reloc);1208if (r) {1209DRM_ERROR("bad EVENT_WRITE_EOP\n");1210return -EINVAL;1211}1212ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);1213ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;1214break;1215case PACKET3_EVENT_WRITE_EOS:1216if (pkt->count != 3) {1217DRM_ERROR("bad EVENT_WRITE_EOS\n");1218return -EINVAL;1219}1220r = evergreen_cs_packet_next_reloc(p, &reloc);1221if (r) {1222DRM_ERROR("bad EVENT_WRITE_EOS\n");1223return -EINVAL;1224}1225ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);1226ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;1227break;1228case PACKET3_SET_CONFIG_REG:1229start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START;1230end_reg = 4 * pkt->count + start_reg - 4;1231if ((start_reg < PACKET3_SET_CONFIG_REG_START) ||1232(start_reg >= PACKET3_SET_CONFIG_REG_END) ||1233(end_reg >= PACKET3_SET_CONFIG_REG_END)) {1234DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");1235return -EINVAL;1236}1237for (i = 0; i < pkt->count; i++) {1238reg = start_reg + (4 * i);1239r = evergreen_cs_check_reg(p, reg, idx+1+i);1240if (r)1241return r;1242}1243break;1244case PACKET3_SET_CONTEXT_REG:1245start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_START;1246end_reg = 4 * pkt->count + start_reg - 4;1247if ((start_reg < PACKET3_SET_CONTEXT_REG_START) ||1248(start_reg >= PACKET3_SET_CONTEXT_REG_END) ||1249(end_reg >= PACKET3_SET_CONTEXT_REG_END)) {1250DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n");1251return -EINVAL;1252}1253for (i = 0; i < pkt->count; i++) {1254reg = start_reg + (4 * i);1255r = evergreen_cs_check_reg(p, reg, idx+1+i);1256if (r)1257return r;1258}1259break;1260case PACKET3_SET_RESOURCE:1261if (pkt->count % 8) {1262DRM_ERROR("bad SET_RESOURCE\n");1263return -EINVAL;1264}1265start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_START;1266end_reg = 4 * pkt->count + start_reg - 4;1267if ((start_reg < PACKET3_SET_RESOURCE_START) ||1268(start_reg >= PACKET3_SET_RESOURCE_END) ||1269(end_reg >= PACKET3_SET_RESOURCE_END)) {1270DRM_ERROR("bad SET_RESOURCE\n");1271return -EINVAL;1272}1273for (i = 0; i < (pkt->count / 8); i++) {1274struct radeon_bo *texture, *mipmap;1275u32 size, offset;12761277switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) {1278case SQ_TEX_VTX_VALID_TEXTURE:1279/* tex base */1280r = evergreen_cs_packet_next_reloc(p, &reloc);1281if (r) {1282DRM_ERROR("bad SET_RESOURCE (tex)\n");1283return -EINVAL;1284}1285ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);1286if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)1287ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1);1288else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)1289ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1);1290texture = reloc->robj;1291/* tex mip base */1292r = evergreen_cs_packet_next_reloc(p, &reloc);1293if (r) {1294DRM_ERROR("bad SET_RESOURCE (tex)\n");1295return -EINVAL;1296}1297ib[idx+1+(i*8)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);1298mipmap = reloc->robj;1299r = evergreen_check_texture_resource(p, idx+1+(i*8),1300texture, mipmap);1301if (r)1302return r;1303break;1304case SQ_TEX_VTX_VALID_BUFFER:1305/* vtx base */1306r = evergreen_cs_packet_next_reloc(p, &reloc);1307if (r) {1308DRM_ERROR("bad SET_RESOURCE (vtx)\n");1309return -EINVAL;1310}1311offset = radeon_get_ib_value(p, idx+1+(i*8)+0);1312size = radeon_get_ib_value(p, idx+1+(i*8)+1);1313if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {1314/* force size to size of the buffer */1315dev_warn(p->dev, "vbo resource seems too big for the bo\n");1316ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj);1317}1318ib[idx+1+(i*8)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff);1319ib[idx+1+(i*8)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;1320break;1321case SQ_TEX_VTX_INVALID_TEXTURE:1322case SQ_TEX_VTX_INVALID_BUFFER:1323default:1324DRM_ERROR("bad SET_RESOURCE\n");1325return -EINVAL;1326}1327}1328break;1329case PACKET3_SET_ALU_CONST:1330/* XXX fix me ALU const buffers only */1331break;1332case PACKET3_SET_BOOL_CONST:1333start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_START;1334end_reg = 4 * pkt->count + start_reg - 4;1335if ((start_reg < PACKET3_SET_BOOL_CONST_START) ||1336(start_reg >= PACKET3_SET_BOOL_CONST_END) ||1337(end_reg >= PACKET3_SET_BOOL_CONST_END)) {1338DRM_ERROR("bad SET_BOOL_CONST\n");1339return -EINVAL;1340}1341break;1342case PACKET3_SET_LOOP_CONST:1343start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_START;1344end_reg = 4 * pkt->count + start_reg - 4;1345if ((start_reg < PACKET3_SET_LOOP_CONST_START) ||1346(start_reg >= PACKET3_SET_LOOP_CONST_END) ||1347(end_reg >= PACKET3_SET_LOOP_CONST_END)) {1348DRM_ERROR("bad SET_LOOP_CONST\n");1349return -EINVAL;1350}1351break;1352case PACKET3_SET_CTL_CONST:1353start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_START;1354end_reg = 4 * pkt->count + start_reg - 4;1355if ((start_reg < PACKET3_SET_CTL_CONST_START) ||1356(start_reg >= PACKET3_SET_CTL_CONST_END) ||1357(end_reg >= PACKET3_SET_CTL_CONST_END)) {1358DRM_ERROR("bad SET_CTL_CONST\n");1359return -EINVAL;1360}1361break;1362case PACKET3_SET_SAMPLER:1363if (pkt->count % 3) {1364DRM_ERROR("bad SET_SAMPLER\n");1365return -EINVAL;1366}1367start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_START;1368end_reg = 4 * pkt->count + start_reg - 4;1369if ((start_reg < PACKET3_SET_SAMPLER_START) ||1370(start_reg >= PACKET3_SET_SAMPLER_END) ||1371(end_reg >= PACKET3_SET_SAMPLER_END)) {1372DRM_ERROR("bad SET_SAMPLER\n");1373return -EINVAL;1374}1375break;1376case PACKET3_NOP:1377break;1378default:1379DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);1380return -EINVAL;1381}1382return 0;1383}13841385int evergreen_cs_parse(struct radeon_cs_parser *p)1386{1387struct radeon_cs_packet pkt;1388struct evergreen_cs_track *track;1389int r;13901391if (p->track == NULL) {1392/* initialize tracker, we are in kms */1393track = kzalloc(sizeof(*track), GFP_KERNEL);1394if (track == NULL)1395return -ENOMEM;1396evergreen_cs_track_init(track);1397track->npipes = p->rdev->config.evergreen.tiling_npipes;1398track->nbanks = p->rdev->config.evergreen.tiling_nbanks;1399track->group_size = p->rdev->config.evergreen.tiling_group_size;1400p->track = track;1401}1402do {1403r = evergreen_cs_packet_parse(p, &pkt, p->idx);1404if (r) {1405kfree(p->track);1406p->track = NULL;1407return r;1408}1409p->idx += pkt.count + 2;1410switch (pkt.type) {1411case PACKET_TYPE0:1412r = evergreen_cs_parse_packet0(p, &pkt);1413break;1414case PACKET_TYPE2:1415break;1416case PACKET_TYPE3:1417r = evergreen_packet3_check(p, &pkt);1418break;1419default:1420DRM_ERROR("Unknown packet type %d !\n", pkt.type);1421kfree(p->track);1422p->track = NULL;1423return -EINVAL;1424}1425if (r) {1426kfree(p->track);1427p->track = NULL;1428return r;1429}1430} while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);1431#if 01432for (r = 0; r < p->ib->length_dw; r++) {1433printk(KERN_INFO "%05d 0x%08X\n", r, p->ib->ptr[r]);1434mdelay(1);1435}1436#endif1437kfree(p->track);1438p->track = NULL;1439return 0;1440}1441144214431444