1254885Sdumbbell/* 2254885Sdumbbell * Copyright 2010 Advanced Micro Devices, Inc. 3254885Sdumbbell * Copyright 2008 Red Hat Inc. 4254885Sdumbbell * Copyright 2009 Jerome Glisse. 5254885Sdumbbell * 6254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a 7254885Sdumbbell * copy of this software and associated documentation files (the "Software"), 8254885Sdumbbell * to deal in the Software without restriction, including without limitation 9254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the 11254885Sdumbbell * Software is furnished to do so, subject to the following conditions: 12254885Sdumbbell * 13254885Sdumbbell * The above copyright notice and this permission notice shall be included in 14254885Sdumbbell * all copies or substantial portions of the Software. 15254885Sdumbbell * 16254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19254885Sdumbbell * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22254885Sdumbbell * OTHER DEALINGS IN THE SOFTWARE. 23254885Sdumbbell * 24254885Sdumbbell * Authors: Dave Airlie 25254885Sdumbbell * Alex Deucher 26254885Sdumbbell * Jerome Glisse 27254885Sdumbbell */ 28254885Sdumbbell 29254885Sdumbbell#include <sys/cdefs.h> 30254885Sdumbbell__FBSDID("$FreeBSD$"); 31254885Sdumbbell 32254885Sdumbbell#include <dev/drm2/drmP.h> 33254885Sdumbbell#include "radeon.h" 34254885Sdumbbell#include "radeon_asic.h" 35254885Sdumbbell#include "evergreend.h" 36254885Sdumbbell#include "evergreen_reg_safe.h" 37254885Sdumbbell#include "cayman_reg_safe.h" 38254885Sdumbbell#include "r600_cs.h" 39254885Sdumbbell 40254885Sdumbbell#define MAX(a,b) (((a)>(b))?(a):(b)) 41254885Sdumbbell#define MIN(a,b) (((a)<(b))?(a):(b)) 42254885Sdumbbell 43254885Sdumbbellstatic int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p, 44254885Sdumbbell struct radeon_cs_reloc **cs_reloc); 45254885Sdumbbell 46254885Sdumbbellstruct evergreen_cs_track { 47254885Sdumbbell u32 group_size; 48254885Sdumbbell u32 nbanks; 49254885Sdumbbell u32 npipes; 50254885Sdumbbell u32 row_size; 51254885Sdumbbell /* value we track */ 52254885Sdumbbell u32 nsamples; /* unused */ 53254885Sdumbbell struct radeon_bo *cb_color_bo[12]; 54254885Sdumbbell u32 cb_color_bo_offset[12]; 55254885Sdumbbell struct radeon_bo *cb_color_fmask_bo[8]; /* unused */ 56254885Sdumbbell struct radeon_bo *cb_color_cmask_bo[8]; /* unused */ 57254885Sdumbbell u32 cb_color_info[12]; 58254885Sdumbbell u32 cb_color_view[12]; 59254885Sdumbbell u32 cb_color_pitch[12]; 60254885Sdumbbell u32 cb_color_slice[12]; 61254885Sdumbbell u32 cb_color_slice_idx[12]; 62254885Sdumbbell u32 cb_color_attrib[12]; 63254885Sdumbbell u32 cb_color_cmask_slice[8];/* unused */ 64254885Sdumbbell u32 cb_color_fmask_slice[8];/* unused */ 65254885Sdumbbell u32 cb_target_mask; 66254885Sdumbbell u32 cb_shader_mask; /* unused */ 67254885Sdumbbell u32 vgt_strmout_config; 68254885Sdumbbell u32 vgt_strmout_buffer_config; 69254885Sdumbbell struct radeon_bo *vgt_strmout_bo[4]; 70254885Sdumbbell u32 vgt_strmout_bo_offset[4]; 71254885Sdumbbell u32 vgt_strmout_size[4]; 72254885Sdumbbell u32 db_depth_control; 73254885Sdumbbell u32 db_depth_view; 74254885Sdumbbell u32 db_depth_slice; 75254885Sdumbbell u32 db_depth_size; 76254885Sdumbbell u32 db_z_info; 77254885Sdumbbell u32 db_z_read_offset; 78254885Sdumbbell u32 db_z_write_offset; 79254885Sdumbbell struct radeon_bo *db_z_read_bo; 80254885Sdumbbell struct radeon_bo *db_z_write_bo; 81254885Sdumbbell u32 db_s_info; 82254885Sdumbbell u32 db_s_read_offset; 83254885Sdumbbell u32 db_s_write_offset; 84254885Sdumbbell struct radeon_bo *db_s_read_bo; 85254885Sdumbbell struct radeon_bo *db_s_write_bo; 86254885Sdumbbell bool sx_misc_kill_all_prims; 87254885Sdumbbell bool cb_dirty; 88254885Sdumbbell bool db_dirty; 89254885Sdumbbell bool streamout_dirty; 90254885Sdumbbell u32 htile_offset; 91254885Sdumbbell u32 htile_surface; 92254885Sdumbbell struct radeon_bo *htile_bo; 93254885Sdumbbell}; 94254885Sdumbbell 95254885Sdumbbellstatic u32 evergreen_cs_get_aray_mode(u32 tiling_flags) 96254885Sdumbbell{ 97254885Sdumbbell if (tiling_flags & RADEON_TILING_MACRO) 98254885Sdumbbell return ARRAY_2D_TILED_THIN1; 99254885Sdumbbell else if (tiling_flags & RADEON_TILING_MICRO) 100254885Sdumbbell return ARRAY_1D_TILED_THIN1; 101254885Sdumbbell else 102254885Sdumbbell return ARRAY_LINEAR_GENERAL; 103254885Sdumbbell} 104254885Sdumbbell 105254885Sdumbbellstatic u32 evergreen_cs_get_num_banks(u32 nbanks) 106254885Sdumbbell{ 107254885Sdumbbell switch (nbanks) { 108254885Sdumbbell case 2: 109254885Sdumbbell return ADDR_SURF_2_BANK; 110254885Sdumbbell case 4: 111254885Sdumbbell return ADDR_SURF_4_BANK; 112254885Sdumbbell case 8: 113254885Sdumbbell default: 114254885Sdumbbell return ADDR_SURF_8_BANK; 115254885Sdumbbell case 16: 116254885Sdumbbell return ADDR_SURF_16_BANK; 117254885Sdumbbell } 118254885Sdumbbell} 119254885Sdumbbell 120254885Sdumbbellstatic void evergreen_cs_track_init(struct evergreen_cs_track *track) 121254885Sdumbbell{ 122254885Sdumbbell int i; 123254885Sdumbbell 124254885Sdumbbell for (i = 0; i < 8; i++) { 125254885Sdumbbell track->cb_color_fmask_bo[i] = NULL; 126254885Sdumbbell track->cb_color_cmask_bo[i] = NULL; 127254885Sdumbbell track->cb_color_cmask_slice[i] = 0; 128254885Sdumbbell track->cb_color_fmask_slice[i] = 0; 129254885Sdumbbell } 130254885Sdumbbell 131254885Sdumbbell for (i = 0; i < 12; i++) { 132254885Sdumbbell track->cb_color_bo[i] = NULL; 133254885Sdumbbell track->cb_color_bo_offset[i] = 0xFFFFFFFF; 134254885Sdumbbell track->cb_color_info[i] = 0; 135254885Sdumbbell track->cb_color_view[i] = 0xFFFFFFFF; 136254885Sdumbbell track->cb_color_pitch[i] = 0; 137254885Sdumbbell track->cb_color_slice[i] = 0xfffffff; 138254885Sdumbbell track->cb_color_slice_idx[i] = 0; 139254885Sdumbbell } 140254885Sdumbbell track->cb_target_mask = 0xFFFFFFFF; 141254885Sdumbbell track->cb_shader_mask = 0xFFFFFFFF; 142254885Sdumbbell track->cb_dirty = true; 143254885Sdumbbell 144254885Sdumbbell track->db_depth_slice = 0xffffffff; 145254885Sdumbbell track->db_depth_view = 0xFFFFC000; 146254885Sdumbbell track->db_depth_size = 0xFFFFFFFF; 147254885Sdumbbell track->db_depth_control = 0xFFFFFFFF; 148254885Sdumbbell track->db_z_info = 0xFFFFFFFF; 149254885Sdumbbell track->db_z_read_offset = 0xFFFFFFFF; 150254885Sdumbbell track->db_z_write_offset = 0xFFFFFFFF; 151254885Sdumbbell track->db_z_read_bo = NULL; 152254885Sdumbbell track->db_z_write_bo = NULL; 153254885Sdumbbell track->db_s_info = 0xFFFFFFFF; 154254885Sdumbbell track->db_s_read_offset = 0xFFFFFFFF; 155254885Sdumbbell track->db_s_write_offset = 0xFFFFFFFF; 156254885Sdumbbell track->db_s_read_bo = NULL; 157254885Sdumbbell track->db_s_write_bo = NULL; 158254885Sdumbbell track->db_dirty = true; 159254885Sdumbbell track->htile_bo = NULL; 160254885Sdumbbell track->htile_offset = 0xFFFFFFFF; 161254885Sdumbbell track->htile_surface = 0; 162254885Sdumbbell 163254885Sdumbbell for (i = 0; i < 4; i++) { 164254885Sdumbbell track->vgt_strmout_size[i] = 0; 165254885Sdumbbell track->vgt_strmout_bo[i] = NULL; 166254885Sdumbbell track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; 167254885Sdumbbell } 168254885Sdumbbell track->streamout_dirty = true; 169254885Sdumbbell track->sx_misc_kill_all_prims = false; 170254885Sdumbbell} 171254885Sdumbbell 172254885Sdumbbellstruct eg_surface { 173254885Sdumbbell /* value gathered from cs */ 174254885Sdumbbell unsigned nbx; 175254885Sdumbbell unsigned nby; 176254885Sdumbbell unsigned format; 177254885Sdumbbell unsigned mode; 178254885Sdumbbell unsigned nbanks; 179254885Sdumbbell unsigned bankw; 180254885Sdumbbell unsigned bankh; 181254885Sdumbbell unsigned tsplit; 182254885Sdumbbell unsigned mtilea; 183254885Sdumbbell unsigned nsamples; 184254885Sdumbbell /* output value */ 185254885Sdumbbell unsigned bpe; 186254885Sdumbbell unsigned layer_size; 187254885Sdumbbell unsigned palign; 188254885Sdumbbell unsigned halign; 189254885Sdumbbell unsigned long base_align; 190254885Sdumbbell}; 191254885Sdumbbell 192254885Sdumbbellstatic int evergreen_surface_check_linear(struct radeon_cs_parser *p, 193254885Sdumbbell struct eg_surface *surf, 194254885Sdumbbell const char *prefix) 195254885Sdumbbell{ 196254885Sdumbbell surf->layer_size = surf->nbx * surf->nby * surf->bpe * surf->nsamples; 197254885Sdumbbell surf->base_align = surf->bpe; 198254885Sdumbbell surf->palign = 1; 199254885Sdumbbell surf->halign = 1; 200254885Sdumbbell return 0; 201254885Sdumbbell} 202254885Sdumbbell 203254885Sdumbbellstatic int evergreen_surface_check_linear_aligned(struct radeon_cs_parser *p, 204254885Sdumbbell struct eg_surface *surf, 205254885Sdumbbell const char *prefix) 206254885Sdumbbell{ 207254885Sdumbbell struct evergreen_cs_track *track = p->track; 208254885Sdumbbell unsigned palign; 209254885Sdumbbell 210254885Sdumbbell palign = MAX(64, track->group_size / surf->bpe); 211254885Sdumbbell surf->layer_size = surf->nbx * surf->nby * surf->bpe * surf->nsamples; 212254885Sdumbbell surf->base_align = track->group_size; 213254885Sdumbbell surf->palign = palign; 214254885Sdumbbell surf->halign = 1; 215254885Sdumbbell if (surf->nbx & (palign - 1)) { 216254885Sdumbbell if (prefix) { 217254885Sdumbbell dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d\n", 218254885Sdumbbell __func__, __LINE__, prefix, surf->nbx, palign); 219254885Sdumbbell } 220254885Sdumbbell return -EINVAL; 221254885Sdumbbell } 222254885Sdumbbell return 0; 223254885Sdumbbell} 224254885Sdumbbell 225254885Sdumbbellstatic int evergreen_surface_check_1d(struct radeon_cs_parser *p, 226254885Sdumbbell struct eg_surface *surf, 227254885Sdumbbell const char *prefix) 228254885Sdumbbell{ 229254885Sdumbbell struct evergreen_cs_track *track = p->track; 230254885Sdumbbell unsigned palign; 231254885Sdumbbell 232254885Sdumbbell palign = track->group_size / (8 * surf->bpe * surf->nsamples); 233254885Sdumbbell palign = MAX(8, palign); 234254885Sdumbbell surf->layer_size = surf->nbx * surf->nby * surf->bpe; 235254885Sdumbbell surf->base_align = track->group_size; 236254885Sdumbbell surf->palign = palign; 237254885Sdumbbell surf->halign = 8; 238254885Sdumbbell if ((surf->nbx & (palign - 1))) { 239254885Sdumbbell if (prefix) { 240254885Sdumbbell dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d (%d %d %d)\n", 241254885Sdumbbell __func__, __LINE__, prefix, surf->nbx, palign, 242254885Sdumbbell track->group_size, surf->bpe, surf->nsamples); 243254885Sdumbbell } 244254885Sdumbbell return -EINVAL; 245254885Sdumbbell } 246254885Sdumbbell if ((surf->nby & (8 - 1))) { 247254885Sdumbbell if (prefix) { 248254885Sdumbbell dev_warn(p->dev, "%s:%d %s height %d invalid must be aligned with 8\n", 249254885Sdumbbell __func__, __LINE__, prefix, surf->nby); 250254885Sdumbbell } 251254885Sdumbbell return -EINVAL; 252254885Sdumbbell } 253254885Sdumbbell return 0; 254254885Sdumbbell} 255254885Sdumbbell 256254885Sdumbbellstatic int evergreen_surface_check_2d(struct radeon_cs_parser *p, 257254885Sdumbbell struct eg_surface *surf, 258254885Sdumbbell const char *prefix) 259254885Sdumbbell{ 260254885Sdumbbell struct evergreen_cs_track *track = p->track; 261254885Sdumbbell unsigned palign, halign, tileb, slice_pt; 262254885Sdumbbell unsigned mtile_pr, mtile_ps, mtileb; 263254885Sdumbbell 264254885Sdumbbell tileb = 64 * surf->bpe * surf->nsamples; 265254885Sdumbbell slice_pt = 1; 266254885Sdumbbell if (tileb > surf->tsplit) { 267254885Sdumbbell slice_pt = tileb / surf->tsplit; 268254885Sdumbbell } 269254885Sdumbbell tileb = tileb / slice_pt; 270254885Sdumbbell /* macro tile width & height */ 271254885Sdumbbell palign = (8 * surf->bankw * track->npipes) * surf->mtilea; 272254885Sdumbbell halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea; 273254885Sdumbbell mtileb = (palign / 8) * (halign / 8) * tileb; 274254885Sdumbbell mtile_pr = surf->nbx / palign; 275254885Sdumbbell mtile_ps = (mtile_pr * surf->nby) / halign; 276254885Sdumbbell surf->layer_size = mtile_ps * mtileb * slice_pt; 277254885Sdumbbell surf->base_align = (palign / 8) * (halign / 8) * tileb; 278254885Sdumbbell surf->palign = palign; 279254885Sdumbbell surf->halign = halign; 280254885Sdumbbell 281254885Sdumbbell if ((surf->nbx & (palign - 1))) { 282254885Sdumbbell if (prefix) { 283254885Sdumbbell dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d\n", 284254885Sdumbbell __func__, __LINE__, prefix, surf->nbx, palign); 285254885Sdumbbell } 286254885Sdumbbell return -EINVAL; 287254885Sdumbbell } 288254885Sdumbbell if ((surf->nby & (halign - 1))) { 289254885Sdumbbell if (prefix) { 290254885Sdumbbell dev_warn(p->dev, "%s:%d %s height %d invalid must be aligned with %d\n", 291254885Sdumbbell __func__, __LINE__, prefix, surf->nby, halign); 292254885Sdumbbell } 293254885Sdumbbell return -EINVAL; 294254885Sdumbbell } 295254885Sdumbbell 296254885Sdumbbell return 0; 297254885Sdumbbell} 298254885Sdumbbell 299254885Sdumbbellstatic int evergreen_surface_check(struct radeon_cs_parser *p, 300254885Sdumbbell struct eg_surface *surf, 301254885Sdumbbell const char *prefix) 302254885Sdumbbell{ 303254885Sdumbbell /* some common value computed here */ 304254885Sdumbbell surf->bpe = r600_fmt_get_blocksize(surf->format); 305254885Sdumbbell 306254885Sdumbbell switch (surf->mode) { 307254885Sdumbbell case ARRAY_LINEAR_GENERAL: 308254885Sdumbbell return evergreen_surface_check_linear(p, surf, prefix); 309254885Sdumbbell case ARRAY_LINEAR_ALIGNED: 310254885Sdumbbell return evergreen_surface_check_linear_aligned(p, surf, prefix); 311254885Sdumbbell case ARRAY_1D_TILED_THIN1: 312254885Sdumbbell return evergreen_surface_check_1d(p, surf, prefix); 313254885Sdumbbell case ARRAY_2D_TILED_THIN1: 314254885Sdumbbell return evergreen_surface_check_2d(p, surf, prefix); 315254885Sdumbbell default: 316254885Sdumbbell dev_warn(p->dev, "%s:%d %s invalid array mode %d\n", 317254885Sdumbbell __func__, __LINE__, prefix, surf->mode); 318254885Sdumbbell return -EINVAL; 319254885Sdumbbell } 320254885Sdumbbell return -EINVAL; 321254885Sdumbbell} 322254885Sdumbbell 323254885Sdumbbellstatic int evergreen_surface_value_conv_check(struct radeon_cs_parser *p, 324254885Sdumbbell struct eg_surface *surf, 325254885Sdumbbell const char *prefix) 326254885Sdumbbell{ 327254885Sdumbbell switch (surf->mode) { 328254885Sdumbbell case ARRAY_2D_TILED_THIN1: 329254885Sdumbbell break; 330254885Sdumbbell case ARRAY_LINEAR_GENERAL: 331254885Sdumbbell case ARRAY_LINEAR_ALIGNED: 332254885Sdumbbell case ARRAY_1D_TILED_THIN1: 333254885Sdumbbell return 0; 334254885Sdumbbell default: 335254885Sdumbbell dev_warn(p->dev, "%s:%d %s invalid array mode %d\n", 336254885Sdumbbell __func__, __LINE__, prefix, surf->mode); 337254885Sdumbbell return -EINVAL; 338254885Sdumbbell } 339254885Sdumbbell 340254885Sdumbbell switch (surf->nbanks) { 341254885Sdumbbell case 0: surf->nbanks = 2; break; 342254885Sdumbbell case 1: surf->nbanks = 4; break; 343254885Sdumbbell case 2: surf->nbanks = 8; break; 344254885Sdumbbell case 3: surf->nbanks = 16; break; 345254885Sdumbbell default: 346254885Sdumbbell dev_warn(p->dev, "%s:%d %s invalid number of banks %d\n", 347254885Sdumbbell __func__, __LINE__, prefix, surf->nbanks); 348254885Sdumbbell return -EINVAL; 349254885Sdumbbell } 350254885Sdumbbell switch (surf->bankw) { 351254885Sdumbbell case 0: surf->bankw = 1; break; 352254885Sdumbbell case 1: surf->bankw = 2; break; 353254885Sdumbbell case 2: surf->bankw = 4; break; 354254885Sdumbbell case 3: surf->bankw = 8; break; 355254885Sdumbbell default: 356254885Sdumbbell dev_warn(p->dev, "%s:%d %s invalid bankw %d\n", 357254885Sdumbbell __func__, __LINE__, prefix, surf->bankw); 358254885Sdumbbell return -EINVAL; 359254885Sdumbbell } 360254885Sdumbbell switch (surf->bankh) { 361254885Sdumbbell case 0: surf->bankh = 1; break; 362254885Sdumbbell case 1: surf->bankh = 2; break; 363254885Sdumbbell case 2: surf->bankh = 4; break; 364254885Sdumbbell case 3: surf->bankh = 8; break; 365254885Sdumbbell default: 366254885Sdumbbell dev_warn(p->dev, "%s:%d %s invalid bankh %d\n", 367254885Sdumbbell __func__, __LINE__, prefix, surf->bankh); 368254885Sdumbbell return -EINVAL; 369254885Sdumbbell } 370254885Sdumbbell switch (surf->mtilea) { 371254885Sdumbbell case 0: surf->mtilea = 1; break; 372254885Sdumbbell case 1: surf->mtilea = 2; break; 373254885Sdumbbell case 2: surf->mtilea = 4; break; 374254885Sdumbbell case 3: surf->mtilea = 8; break; 375254885Sdumbbell default: 376254885Sdumbbell dev_warn(p->dev, "%s:%d %s invalid macro tile aspect %d\n", 377254885Sdumbbell __func__, __LINE__, prefix, surf->mtilea); 378254885Sdumbbell return -EINVAL; 379254885Sdumbbell } 380254885Sdumbbell switch (surf->tsplit) { 381254885Sdumbbell case 0: surf->tsplit = 64; break; 382254885Sdumbbell case 1: surf->tsplit = 128; break; 383254885Sdumbbell case 2: surf->tsplit = 256; break; 384254885Sdumbbell case 3: surf->tsplit = 512; break; 385254885Sdumbbell case 4: surf->tsplit = 1024; break; 386254885Sdumbbell case 5: surf->tsplit = 2048; break; 387254885Sdumbbell case 6: surf->tsplit = 4096; break; 388254885Sdumbbell default: 389254885Sdumbbell dev_warn(p->dev, "%s:%d %s invalid tile split %d\n", 390254885Sdumbbell __func__, __LINE__, prefix, surf->tsplit); 391254885Sdumbbell return -EINVAL; 392254885Sdumbbell } 393254885Sdumbbell return 0; 394254885Sdumbbell} 395254885Sdumbbell 396254885Sdumbbellstatic int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned id) 397254885Sdumbbell{ 398254885Sdumbbell struct evergreen_cs_track *track = p->track; 399254885Sdumbbell struct eg_surface surf; 400254885Sdumbbell unsigned pitch, slice, mslice; 401254885Sdumbbell unsigned long offset; 402254885Sdumbbell int r; 403254885Sdumbbell 404254885Sdumbbell mslice = G_028C6C_SLICE_MAX(track->cb_color_view[id]) + 1; 405254885Sdumbbell pitch = track->cb_color_pitch[id]; 406254885Sdumbbell slice = track->cb_color_slice[id]; 407254885Sdumbbell surf.nbx = (pitch + 1) * 8; 408254885Sdumbbell surf.nby = ((slice + 1) * 64) / surf.nbx; 409254885Sdumbbell surf.mode = G_028C70_ARRAY_MODE(track->cb_color_info[id]); 410254885Sdumbbell surf.format = G_028C70_FORMAT(track->cb_color_info[id]); 411254885Sdumbbell surf.tsplit = G_028C74_TILE_SPLIT(track->cb_color_attrib[id]); 412254885Sdumbbell surf.nbanks = G_028C74_NUM_BANKS(track->cb_color_attrib[id]); 413254885Sdumbbell surf.bankw = G_028C74_BANK_WIDTH(track->cb_color_attrib[id]); 414254885Sdumbbell surf.bankh = G_028C74_BANK_HEIGHT(track->cb_color_attrib[id]); 415254885Sdumbbell surf.mtilea = G_028C74_MACRO_TILE_ASPECT(track->cb_color_attrib[id]); 416254885Sdumbbell surf.nsamples = 1; 417254885Sdumbbell 418254885Sdumbbell if (!r600_fmt_is_valid_color(surf.format)) { 419254885Sdumbbell dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08x)\n", 420254885Sdumbbell __func__, __LINE__, surf.format, 421254885Sdumbbell id, track->cb_color_info[id]); 422254885Sdumbbell return -EINVAL; 423254885Sdumbbell } 424254885Sdumbbell 425254885Sdumbbell r = evergreen_surface_value_conv_check(p, &surf, "cb"); 426254885Sdumbbell if (r) { 427254885Sdumbbell return r; 428254885Sdumbbell } 429254885Sdumbbell 430254885Sdumbbell r = evergreen_surface_check(p, &surf, "cb"); 431254885Sdumbbell if (r) { 432254885Sdumbbell dev_warn(p->dev, "%s:%d cb[%d] invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", 433254885Sdumbbell __func__, __LINE__, id, track->cb_color_pitch[id], 434254885Sdumbbell track->cb_color_slice[id], track->cb_color_attrib[id], 435254885Sdumbbell track->cb_color_info[id]); 436254885Sdumbbell return r; 437254885Sdumbbell } 438254885Sdumbbell 439254885Sdumbbell offset = track->cb_color_bo_offset[id] << 8; 440254885Sdumbbell if (offset & (surf.base_align - 1)) { 441254885Sdumbbell dev_warn(p->dev, "%s:%d cb[%d] bo base %ld not aligned with %ld\n", 442254885Sdumbbell __func__, __LINE__, id, offset, surf.base_align); 443254885Sdumbbell return -EINVAL; 444254885Sdumbbell } 445254885Sdumbbell 446254885Sdumbbell offset += surf.layer_size * mslice; 447254885Sdumbbell if (offset > radeon_bo_size(track->cb_color_bo[id])) { 448254885Sdumbbell /* old ddx are broken they allocate bo with w*h*bpp but 449254885Sdumbbell * program slice with ALIGN(h, 8), catch this and patch 450254885Sdumbbell * command stream. 451254885Sdumbbell */ 452254885Sdumbbell if (!surf.mode) { 453254885Sdumbbell volatile u32 *ib = p->ib.ptr; 454254885Sdumbbell unsigned long tmp, nby, bsize, size, min = 0; 455254885Sdumbbell 456254885Sdumbbell /* find the height the ddx wants */ 457254885Sdumbbell if (surf.nby > 8) { 458254885Sdumbbell min = surf.nby - 8; 459254885Sdumbbell } 460254885Sdumbbell bsize = radeon_bo_size(track->cb_color_bo[id]); 461254885Sdumbbell tmp = track->cb_color_bo_offset[id] << 8; 462254885Sdumbbell for (nby = surf.nby; nby > min; nby--) { 463254885Sdumbbell size = nby * surf.nbx * surf.bpe * surf.nsamples; 464254885Sdumbbell if ((tmp + size * mslice) <= bsize) { 465254885Sdumbbell break; 466254885Sdumbbell } 467254885Sdumbbell } 468254885Sdumbbell if (nby > min) { 469254885Sdumbbell surf.nby = nby; 470254885Sdumbbell slice = ((nby * surf.nbx) / 64) - 1; 471254885Sdumbbell if (!evergreen_surface_check(p, &surf, "cb")) { 472254885Sdumbbell /* check if this one works */ 473254885Sdumbbell tmp += surf.layer_size * mslice; 474254885Sdumbbell if (tmp <= bsize) { 475254885Sdumbbell ib[track->cb_color_slice_idx[id]] = slice; 476254885Sdumbbell goto old_ddx_ok; 477254885Sdumbbell } 478254885Sdumbbell } 479254885Sdumbbell } 480254885Sdumbbell } 481254885Sdumbbell dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d, " 482254885Sdumbbell "offset %d, max layer %d, bo size %ld, slice %d)\n", 483254885Sdumbbell __func__, __LINE__, id, surf.layer_size, 484254885Sdumbbell track->cb_color_bo_offset[id] << 8, mslice, 485254885Sdumbbell radeon_bo_size(track->cb_color_bo[id]), slice); 486254885Sdumbbell dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n", 487254885Sdumbbell __func__, __LINE__, surf.nbx, surf.nby, 488254885Sdumbbell surf.mode, surf.bpe, surf.nsamples, 489254885Sdumbbell surf.bankw, surf.bankh, 490254885Sdumbbell surf.tsplit, surf.mtilea); 491254885Sdumbbell return -EINVAL; 492254885Sdumbbell } 493254885Sdumbbellold_ddx_ok: 494254885Sdumbbell 495254885Sdumbbell return 0; 496254885Sdumbbell} 497254885Sdumbbell 498254885Sdumbbellstatic int evergreen_cs_track_validate_htile(struct radeon_cs_parser *p, 499254885Sdumbbell unsigned nbx, unsigned nby) 500254885Sdumbbell{ 501254885Sdumbbell struct evergreen_cs_track *track = p->track; 502254885Sdumbbell unsigned long size; 503254885Sdumbbell 504254885Sdumbbell if (track->htile_bo == NULL) { 505254885Sdumbbell dev_warn(p->dev, "%s:%d htile enabled without htile surface 0x%08x\n", 506254885Sdumbbell __func__, __LINE__, track->db_z_info); 507254885Sdumbbell return -EINVAL; 508254885Sdumbbell } 509254885Sdumbbell 510254885Sdumbbell if (G_028ABC_LINEAR(track->htile_surface)) { 511254885Sdumbbell /* pitch must be 16 htiles aligned == 16 * 8 pixel aligned */ 512254885Sdumbbell nbx = roundup(nbx, 16 * 8); 513254885Sdumbbell /* height is npipes htiles aligned == npipes * 8 pixel aligned */ 514254885Sdumbbell nby = roundup(nby, track->npipes * 8); 515254885Sdumbbell } else { 516254885Sdumbbell /* always assume 8x8 htile */ 517254885Sdumbbell /* align is htile align * 8, htile align vary according to 518254885Sdumbbell * number of pipe and tile width and nby 519254885Sdumbbell */ 520254885Sdumbbell switch (track->npipes) { 521254885Sdumbbell case 8: 522254885Sdumbbell /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ 523254885Sdumbbell nbx = roundup(nbx, 64 * 8); 524254885Sdumbbell nby = roundup(nby, 64 * 8); 525254885Sdumbbell break; 526254885Sdumbbell case 4: 527254885Sdumbbell /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ 528254885Sdumbbell nbx = roundup(nbx, 64 * 8); 529254885Sdumbbell nby = roundup(nby, 32 * 8); 530254885Sdumbbell break; 531254885Sdumbbell case 2: 532254885Sdumbbell /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ 533254885Sdumbbell nbx = roundup(nbx, 32 * 8); 534254885Sdumbbell nby = roundup(nby, 32 * 8); 535254885Sdumbbell break; 536254885Sdumbbell case 1: 537254885Sdumbbell /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ 538254885Sdumbbell nbx = roundup(nbx, 32 * 8); 539254885Sdumbbell nby = roundup(nby, 16 * 8); 540254885Sdumbbell break; 541254885Sdumbbell default: 542254885Sdumbbell dev_warn(p->dev, "%s:%d invalid num pipes %d\n", 543254885Sdumbbell __func__, __LINE__, track->npipes); 544254885Sdumbbell return -EINVAL; 545254885Sdumbbell } 546254885Sdumbbell } 547254885Sdumbbell /* compute number of htile */ 548254885Sdumbbell nbx = nbx >> 3; 549254885Sdumbbell nby = nby >> 3; 550254885Sdumbbell /* size must be aligned on npipes * 2K boundary */ 551254885Sdumbbell size = roundup(nbx * nby * 4, track->npipes * (2 << 10)); 552254885Sdumbbell size += track->htile_offset; 553254885Sdumbbell 554254885Sdumbbell if (size > radeon_bo_size(track->htile_bo)) { 555254885Sdumbbell dev_warn(p->dev, "%s:%d htile surface too small %ld for %ld (%d %d)\n", 556254885Sdumbbell __func__, __LINE__, radeon_bo_size(track->htile_bo), 557254885Sdumbbell size, nbx, nby); 558254885Sdumbbell return -EINVAL; 559254885Sdumbbell } 560254885Sdumbbell return 0; 561254885Sdumbbell} 562254885Sdumbbell 563254885Sdumbbellstatic int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p) 564254885Sdumbbell{ 565254885Sdumbbell struct evergreen_cs_track *track = p->track; 566254885Sdumbbell struct eg_surface surf; 567254885Sdumbbell unsigned pitch, slice, mslice; 568254885Sdumbbell unsigned long offset; 569254885Sdumbbell int r; 570254885Sdumbbell 571254885Sdumbbell mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1; 572254885Sdumbbell pitch = G_028058_PITCH_TILE_MAX(track->db_depth_size); 573254885Sdumbbell slice = track->db_depth_slice; 574254885Sdumbbell surf.nbx = (pitch + 1) * 8; 575254885Sdumbbell surf.nby = ((slice + 1) * 64) / surf.nbx; 576254885Sdumbbell surf.mode = G_028040_ARRAY_MODE(track->db_z_info); 577254885Sdumbbell surf.format = G_028044_FORMAT(track->db_s_info); 578254885Sdumbbell surf.tsplit = G_028044_TILE_SPLIT(track->db_s_info); 579254885Sdumbbell surf.nbanks = G_028040_NUM_BANKS(track->db_z_info); 580254885Sdumbbell surf.bankw = G_028040_BANK_WIDTH(track->db_z_info); 581254885Sdumbbell surf.bankh = G_028040_BANK_HEIGHT(track->db_z_info); 582254885Sdumbbell surf.mtilea = G_028040_MACRO_TILE_ASPECT(track->db_z_info); 583254885Sdumbbell surf.nsamples = 1; 584254885Sdumbbell 585254885Sdumbbell if (surf.format != 1) { 586254885Sdumbbell dev_warn(p->dev, "%s:%d stencil invalid format %d\n", 587254885Sdumbbell __func__, __LINE__, surf.format); 588254885Sdumbbell return -EINVAL; 589254885Sdumbbell } 590254885Sdumbbell /* replace by color format so we can use same code */ 591254885Sdumbbell surf.format = V_028C70_COLOR_8; 592254885Sdumbbell 593254885Sdumbbell r = evergreen_surface_value_conv_check(p, &surf, "stencil"); 594254885Sdumbbell if (r) { 595254885Sdumbbell return r; 596254885Sdumbbell } 597254885Sdumbbell 598254885Sdumbbell r = evergreen_surface_check(p, &surf, NULL); 599254885Sdumbbell if (r) { 600254885Sdumbbell /* old userspace doesn't compute proper depth/stencil alignment 601254885Sdumbbell * check that alignment against a bigger byte per elements and 602254885Sdumbbell * only report if that alignment is wrong too. 603254885Sdumbbell */ 604254885Sdumbbell surf.format = V_028C70_COLOR_8_8_8_8; 605254885Sdumbbell r = evergreen_surface_check(p, &surf, "stencil"); 606254885Sdumbbell if (r) { 607254885Sdumbbell dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", 608254885Sdumbbell __func__, __LINE__, track->db_depth_size, 609254885Sdumbbell track->db_depth_slice, track->db_s_info, track->db_z_info); 610254885Sdumbbell } 611254885Sdumbbell return r; 612254885Sdumbbell } 613254885Sdumbbell 614254885Sdumbbell offset = track->db_s_read_offset << 8; 615254885Sdumbbell if (offset & (surf.base_align - 1)) { 616254885Sdumbbell dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n", 617254885Sdumbbell __func__, __LINE__, offset, surf.base_align); 618254885Sdumbbell return -EINVAL; 619254885Sdumbbell } 620254885Sdumbbell offset += surf.layer_size * mslice; 621254885Sdumbbell if (offset > radeon_bo_size(track->db_s_read_bo)) { 622254885Sdumbbell dev_warn(p->dev, "%s:%d stencil read bo too small (layer size %d, " 623254885Sdumbbell "offset %ld, max layer %d, bo size %ld)\n", 624254885Sdumbbell __func__, __LINE__, surf.layer_size, 625254885Sdumbbell (unsigned long)track->db_s_read_offset << 8, mslice, 626254885Sdumbbell radeon_bo_size(track->db_s_read_bo)); 627254885Sdumbbell dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", 628254885Sdumbbell __func__, __LINE__, track->db_depth_size, 629254885Sdumbbell track->db_depth_slice, track->db_s_info, track->db_z_info); 630254885Sdumbbell return -EINVAL; 631254885Sdumbbell } 632254885Sdumbbell 633254885Sdumbbell offset = track->db_s_write_offset << 8; 634254885Sdumbbell if (offset & (surf.base_align - 1)) { 635254885Sdumbbell dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n", 636254885Sdumbbell __func__, __LINE__, offset, surf.base_align); 637254885Sdumbbell return -EINVAL; 638254885Sdumbbell } 639254885Sdumbbell offset += surf.layer_size * mslice; 640254885Sdumbbell if (offset > radeon_bo_size(track->db_s_write_bo)) { 641254885Sdumbbell dev_warn(p->dev, "%s:%d stencil write bo too small (layer size %d, " 642254885Sdumbbell "offset %ld, max layer %d, bo size %ld)\n", 643254885Sdumbbell __func__, __LINE__, surf.layer_size, 644254885Sdumbbell (unsigned long)track->db_s_write_offset << 8, mslice, 645254885Sdumbbell radeon_bo_size(track->db_s_write_bo)); 646254885Sdumbbell return -EINVAL; 647254885Sdumbbell } 648254885Sdumbbell 649254885Sdumbbell /* hyperz */ 650254885Sdumbbell if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) { 651254885Sdumbbell r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby); 652254885Sdumbbell if (r) { 653254885Sdumbbell return r; 654254885Sdumbbell } 655254885Sdumbbell } 656254885Sdumbbell 657254885Sdumbbell return 0; 658254885Sdumbbell} 659254885Sdumbbell 660254885Sdumbbellstatic int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p) 661254885Sdumbbell{ 662254885Sdumbbell struct evergreen_cs_track *track = p->track; 663254885Sdumbbell struct eg_surface surf; 664254885Sdumbbell unsigned pitch, slice, mslice; 665254885Sdumbbell unsigned long offset; 666254885Sdumbbell int r; 667254885Sdumbbell 668254885Sdumbbell mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1; 669254885Sdumbbell pitch = G_028058_PITCH_TILE_MAX(track->db_depth_size); 670254885Sdumbbell slice = track->db_depth_slice; 671254885Sdumbbell surf.nbx = (pitch + 1) * 8; 672254885Sdumbbell surf.nby = ((slice + 1) * 64) / surf.nbx; 673254885Sdumbbell surf.mode = G_028040_ARRAY_MODE(track->db_z_info); 674254885Sdumbbell surf.format = G_028040_FORMAT(track->db_z_info); 675254885Sdumbbell surf.tsplit = G_028040_TILE_SPLIT(track->db_z_info); 676254885Sdumbbell surf.nbanks = G_028040_NUM_BANKS(track->db_z_info); 677254885Sdumbbell surf.bankw = G_028040_BANK_WIDTH(track->db_z_info); 678254885Sdumbbell surf.bankh = G_028040_BANK_HEIGHT(track->db_z_info); 679254885Sdumbbell surf.mtilea = G_028040_MACRO_TILE_ASPECT(track->db_z_info); 680254885Sdumbbell surf.nsamples = 1; 681254885Sdumbbell 682254885Sdumbbell switch (surf.format) { 683254885Sdumbbell case V_028040_Z_16: 684254885Sdumbbell surf.format = V_028C70_COLOR_16; 685254885Sdumbbell break; 686254885Sdumbbell case V_028040_Z_24: 687254885Sdumbbell case V_028040_Z_32_FLOAT: 688254885Sdumbbell surf.format = V_028C70_COLOR_8_8_8_8; 689254885Sdumbbell break; 690254885Sdumbbell default: 691254885Sdumbbell dev_warn(p->dev, "%s:%d depth invalid format %d\n", 692254885Sdumbbell __func__, __LINE__, surf.format); 693254885Sdumbbell return -EINVAL; 694254885Sdumbbell } 695254885Sdumbbell 696254885Sdumbbell r = evergreen_surface_value_conv_check(p, &surf, "depth"); 697254885Sdumbbell if (r) { 698254885Sdumbbell dev_warn(p->dev, "%s:%d depth invalid (0x%08x 0x%08x 0x%08x)\n", 699254885Sdumbbell __func__, __LINE__, track->db_depth_size, 700254885Sdumbbell track->db_depth_slice, track->db_z_info); 701254885Sdumbbell return r; 702254885Sdumbbell } 703254885Sdumbbell 704254885Sdumbbell r = evergreen_surface_check(p, &surf, "depth"); 705254885Sdumbbell if (r) { 706254885Sdumbbell dev_warn(p->dev, "%s:%d depth invalid (0x%08x 0x%08x 0x%08x)\n", 707254885Sdumbbell __func__, __LINE__, track->db_depth_size, 708254885Sdumbbell track->db_depth_slice, track->db_z_info); 709254885Sdumbbell return r; 710254885Sdumbbell } 711254885Sdumbbell 712254885Sdumbbell offset = track->db_z_read_offset << 8; 713254885Sdumbbell if (offset & (surf.base_align - 1)) { 714254885Sdumbbell dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n", 715254885Sdumbbell __func__, __LINE__, offset, surf.base_align); 716254885Sdumbbell return -EINVAL; 717254885Sdumbbell } 718254885Sdumbbell offset += surf.layer_size * mslice; 719254885Sdumbbell if (offset > radeon_bo_size(track->db_z_read_bo)) { 720254885Sdumbbell dev_warn(p->dev, "%s:%d depth read bo too small (layer size %d, " 721254885Sdumbbell "offset %ld, max layer %d, bo size %ld)\n", 722254885Sdumbbell __func__, __LINE__, surf.layer_size, 723254885Sdumbbell (unsigned long)track->db_z_read_offset << 8, mslice, 724254885Sdumbbell radeon_bo_size(track->db_z_read_bo)); 725254885Sdumbbell return -EINVAL; 726254885Sdumbbell } 727254885Sdumbbell 728254885Sdumbbell offset = track->db_z_write_offset << 8; 729254885Sdumbbell if (offset & (surf.base_align - 1)) { 730254885Sdumbbell dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n", 731254885Sdumbbell __func__, __LINE__, offset, surf.base_align); 732254885Sdumbbell return -EINVAL; 733254885Sdumbbell } 734254885Sdumbbell offset += surf.layer_size * mslice; 735254885Sdumbbell if (offset > radeon_bo_size(track->db_z_write_bo)) { 736254885Sdumbbell dev_warn(p->dev, "%s:%d depth write bo too small (layer size %d, " 737254885Sdumbbell "offset %ld, max layer %d, bo size %ld)\n", 738254885Sdumbbell __func__, __LINE__, surf.layer_size, 739254885Sdumbbell (unsigned long)track->db_z_write_offset << 8, mslice, 740254885Sdumbbell radeon_bo_size(track->db_z_write_bo)); 741254885Sdumbbell return -EINVAL; 742254885Sdumbbell } 743254885Sdumbbell 744254885Sdumbbell /* hyperz */ 745254885Sdumbbell if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) { 746254885Sdumbbell r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby); 747254885Sdumbbell if (r) { 748254885Sdumbbell return r; 749254885Sdumbbell } 750254885Sdumbbell } 751254885Sdumbbell 752254885Sdumbbell return 0; 753254885Sdumbbell} 754254885Sdumbbell 755254885Sdumbbellstatic int evergreen_cs_track_validate_texture(struct radeon_cs_parser *p, 756254885Sdumbbell struct radeon_bo *texture, 757254885Sdumbbell struct radeon_bo *mipmap, 758254885Sdumbbell unsigned idx) 759254885Sdumbbell{ 760254885Sdumbbell struct eg_surface surf; 761254885Sdumbbell unsigned long toffset, moffset; 762254885Sdumbbell unsigned dim, llevel, mslice, width, height, depth, i; 763254885Sdumbbell u32 texdw[8]; 764254885Sdumbbell int r; 765254885Sdumbbell 766254885Sdumbbell texdw[0] = radeon_get_ib_value(p, idx + 0); 767254885Sdumbbell texdw[1] = radeon_get_ib_value(p, idx + 1); 768254885Sdumbbell texdw[2] = radeon_get_ib_value(p, idx + 2); 769254885Sdumbbell texdw[3] = radeon_get_ib_value(p, idx + 3); 770254885Sdumbbell texdw[4] = radeon_get_ib_value(p, idx + 4); 771254885Sdumbbell texdw[5] = radeon_get_ib_value(p, idx + 5); 772254885Sdumbbell texdw[6] = radeon_get_ib_value(p, idx + 6); 773254885Sdumbbell texdw[7] = radeon_get_ib_value(p, idx + 7); 774254885Sdumbbell dim = G_030000_DIM(texdw[0]); 775254885Sdumbbell llevel = G_030014_LAST_LEVEL(texdw[5]); 776254885Sdumbbell mslice = G_030014_LAST_ARRAY(texdw[5]) + 1; 777254885Sdumbbell width = G_030000_TEX_WIDTH(texdw[0]) + 1; 778254885Sdumbbell height = G_030004_TEX_HEIGHT(texdw[1]) + 1; 779254885Sdumbbell depth = G_030004_TEX_DEPTH(texdw[1]) + 1; 780254885Sdumbbell surf.format = G_03001C_DATA_FORMAT(texdw[7]); 781254885Sdumbbell surf.nbx = (G_030000_PITCH(texdw[0]) + 1) * 8; 782254885Sdumbbell surf.nbx = r600_fmt_get_nblocksx(surf.format, surf.nbx); 783254885Sdumbbell surf.nby = r600_fmt_get_nblocksy(surf.format, height); 784254885Sdumbbell surf.mode = G_030004_ARRAY_MODE(texdw[1]); 785254885Sdumbbell surf.tsplit = G_030018_TILE_SPLIT(texdw[6]); 786254885Sdumbbell surf.nbanks = G_03001C_NUM_BANKS(texdw[7]); 787254885Sdumbbell surf.bankw = G_03001C_BANK_WIDTH(texdw[7]); 788254885Sdumbbell surf.bankh = G_03001C_BANK_HEIGHT(texdw[7]); 789254885Sdumbbell surf.mtilea = G_03001C_MACRO_TILE_ASPECT(texdw[7]); 790254885Sdumbbell surf.nsamples = 1; 791254885Sdumbbell toffset = texdw[2] << 8; 792254885Sdumbbell moffset = texdw[3] << 8; 793254885Sdumbbell 794254885Sdumbbell if (!r600_fmt_is_valid_texture(surf.format, p->family)) { 795254885Sdumbbell dev_warn(p->dev, "%s:%d texture invalid format %d\n", 796254885Sdumbbell __func__, __LINE__, surf.format); 797254885Sdumbbell return -EINVAL; 798254885Sdumbbell } 799254885Sdumbbell switch (dim) { 800254885Sdumbbell case V_030000_SQ_TEX_DIM_1D: 801254885Sdumbbell case V_030000_SQ_TEX_DIM_2D: 802254885Sdumbbell case V_030000_SQ_TEX_DIM_CUBEMAP: 803254885Sdumbbell case V_030000_SQ_TEX_DIM_1D_ARRAY: 804254885Sdumbbell case V_030000_SQ_TEX_DIM_2D_ARRAY: 805254885Sdumbbell depth = 1; 806254885Sdumbbell break; 807254885Sdumbbell case V_030000_SQ_TEX_DIM_2D_MSAA: 808254885Sdumbbell case V_030000_SQ_TEX_DIM_2D_ARRAY_MSAA: 809254885Sdumbbell surf.nsamples = 1 << llevel; 810254885Sdumbbell llevel = 0; 811254885Sdumbbell depth = 1; 812254885Sdumbbell break; 813254885Sdumbbell case V_030000_SQ_TEX_DIM_3D: 814254885Sdumbbell break; 815254885Sdumbbell default: 816254885Sdumbbell dev_warn(p->dev, "%s:%d texture invalid dimension %d\n", 817254885Sdumbbell __func__, __LINE__, dim); 818254885Sdumbbell return -EINVAL; 819254885Sdumbbell } 820254885Sdumbbell 821254885Sdumbbell r = evergreen_surface_value_conv_check(p, &surf, "texture"); 822254885Sdumbbell if (r) { 823254885Sdumbbell return r; 824254885Sdumbbell } 825254885Sdumbbell 826254885Sdumbbell /* align height */ 827254885Sdumbbell evergreen_surface_check(p, &surf, NULL); 828254885Sdumbbell surf.nby = roundup(surf.nby, surf.halign); 829254885Sdumbbell 830254885Sdumbbell r = evergreen_surface_check(p, &surf, "texture"); 831254885Sdumbbell if (r) { 832254885Sdumbbell dev_warn(p->dev, "%s:%d texture invalid 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", 833254885Sdumbbell __func__, __LINE__, texdw[0], texdw[1], texdw[4], 834254885Sdumbbell texdw[5], texdw[6], texdw[7]); 835254885Sdumbbell return r; 836254885Sdumbbell } 837254885Sdumbbell 838254885Sdumbbell /* check texture size */ 839254885Sdumbbell if (toffset & (surf.base_align - 1)) { 840254885Sdumbbell dev_warn(p->dev, "%s:%d texture bo base %ld not aligned with %ld\n", 841254885Sdumbbell __func__, __LINE__, toffset, surf.base_align); 842254885Sdumbbell return -EINVAL; 843254885Sdumbbell } 844254885Sdumbbell if (moffset & (surf.base_align - 1)) { 845254885Sdumbbell dev_warn(p->dev, "%s:%d mipmap bo base %ld not aligned with %ld\n", 846254885Sdumbbell __func__, __LINE__, moffset, surf.base_align); 847254885Sdumbbell return -EINVAL; 848254885Sdumbbell } 849254885Sdumbbell if (dim == SQ_TEX_DIM_3D) { 850254885Sdumbbell toffset += surf.layer_size * depth; 851254885Sdumbbell } else { 852254885Sdumbbell toffset += surf.layer_size * mslice; 853254885Sdumbbell } 854254885Sdumbbell if (toffset > radeon_bo_size(texture)) { 855254885Sdumbbell dev_warn(p->dev, "%s:%d texture bo too small (layer size %d, " 856254885Sdumbbell "offset %ld, max layer %d, depth %d, bo size %ld) (%d %d)\n", 857254885Sdumbbell __func__, __LINE__, surf.layer_size, 858254885Sdumbbell (unsigned long)texdw[2] << 8, mslice, 859254885Sdumbbell depth, radeon_bo_size(texture), 860254885Sdumbbell surf.nbx, surf.nby); 861254885Sdumbbell return -EINVAL; 862254885Sdumbbell } 863254885Sdumbbell 864254885Sdumbbell if (!mipmap) { 865254885Sdumbbell if (llevel) { 866254885Sdumbbell dev_warn(p->dev, "%s:%i got NULL MIP_ADDRESS relocation\n", 867254885Sdumbbell __func__, __LINE__); 868254885Sdumbbell return -EINVAL; 869254885Sdumbbell } else { 870254885Sdumbbell return 0; /* everything's ok */ 871254885Sdumbbell } 872254885Sdumbbell } 873254885Sdumbbell 874254885Sdumbbell /* check mipmap size */ 875254885Sdumbbell for (i = 1; i <= llevel; i++) { 876254885Sdumbbell unsigned w, h, d; 877254885Sdumbbell 878254885Sdumbbell w = r600_mip_minify(width, i); 879254885Sdumbbell h = r600_mip_minify(height, i); 880254885Sdumbbell d = r600_mip_minify(depth, i); 881254885Sdumbbell surf.nbx = r600_fmt_get_nblocksx(surf.format, w); 882254885Sdumbbell surf.nby = r600_fmt_get_nblocksy(surf.format, h); 883254885Sdumbbell 884254885Sdumbbell switch (surf.mode) { 885254885Sdumbbell case ARRAY_2D_TILED_THIN1: 886254885Sdumbbell if (surf.nbx < surf.palign || surf.nby < surf.halign) { 887254885Sdumbbell surf.mode = ARRAY_1D_TILED_THIN1; 888254885Sdumbbell } 889254885Sdumbbell /* recompute alignment */ 890254885Sdumbbell evergreen_surface_check(p, &surf, NULL); 891254885Sdumbbell break; 892254885Sdumbbell case ARRAY_LINEAR_GENERAL: 893254885Sdumbbell case ARRAY_LINEAR_ALIGNED: 894254885Sdumbbell case ARRAY_1D_TILED_THIN1: 895254885Sdumbbell break; 896254885Sdumbbell default: 897254885Sdumbbell dev_warn(p->dev, "%s:%d invalid array mode %d\n", 898254885Sdumbbell __func__, __LINE__, surf.mode); 899254885Sdumbbell return -EINVAL; 900254885Sdumbbell } 901254885Sdumbbell surf.nbx = roundup(surf.nbx, surf.palign); 902254885Sdumbbell surf.nby = roundup(surf.nby, surf.halign); 903254885Sdumbbell 904254885Sdumbbell r = evergreen_surface_check(p, &surf, "mipmap"); 905254885Sdumbbell if (r) { 906254885Sdumbbell return r; 907254885Sdumbbell } 908254885Sdumbbell 909254885Sdumbbell if (dim == SQ_TEX_DIM_3D) { 910254885Sdumbbell moffset += surf.layer_size * d; 911254885Sdumbbell } else { 912254885Sdumbbell moffset += surf.layer_size * mslice; 913254885Sdumbbell } 914254885Sdumbbell if (moffset > radeon_bo_size(mipmap)) { 915254885Sdumbbell dev_warn(p->dev, "%s:%d mipmap [%d] bo too small (layer size %d, " 916254885Sdumbbell "offset %ld, coffset %ld, max layer %d, depth %d, " 917254885Sdumbbell "bo size %ld) level0 (%d %d %d)\n", 918254885Sdumbbell __func__, __LINE__, i, surf.layer_size, 919254885Sdumbbell (unsigned long)texdw[3] << 8, moffset, mslice, 920254885Sdumbbell d, radeon_bo_size(mipmap), 921254885Sdumbbell width, height, depth); 922254885Sdumbbell dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n", 923254885Sdumbbell __func__, __LINE__, surf.nbx, surf.nby, 924254885Sdumbbell surf.mode, surf.bpe, surf.nsamples, 925254885Sdumbbell surf.bankw, surf.bankh, 926254885Sdumbbell surf.tsplit, surf.mtilea); 927254885Sdumbbell return -EINVAL; 928254885Sdumbbell } 929254885Sdumbbell } 930254885Sdumbbell 931254885Sdumbbell return 0; 932254885Sdumbbell} 933254885Sdumbbell 934254885Sdumbbellstatic int evergreen_cs_track_check(struct radeon_cs_parser *p) 935254885Sdumbbell{ 936254885Sdumbbell struct evergreen_cs_track *track = p->track; 937254885Sdumbbell unsigned tmp, i; 938254885Sdumbbell int r; 939254885Sdumbbell unsigned buffer_mask = 0; 940254885Sdumbbell 941254885Sdumbbell /* check streamout */ 942254885Sdumbbell if (track->streamout_dirty && track->vgt_strmout_config) { 943254885Sdumbbell for (i = 0; i < 4; i++) { 944254885Sdumbbell if (track->vgt_strmout_config & (1 << i)) { 945254885Sdumbbell buffer_mask |= (track->vgt_strmout_buffer_config >> (i * 4)) & 0xf; 946254885Sdumbbell } 947254885Sdumbbell } 948254885Sdumbbell 949254885Sdumbbell for (i = 0; i < 4; i++) { 950254885Sdumbbell if (buffer_mask & (1 << i)) { 951254885Sdumbbell if (track->vgt_strmout_bo[i]) { 952254885Sdumbbell u64 offset = (u64)track->vgt_strmout_bo_offset[i] + 953254885Sdumbbell (u64)track->vgt_strmout_size[i]; 954254885Sdumbbell if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) { 955254885Sdumbbell DRM_ERROR("streamout %d bo too small: 0x%jx, 0x%lx\n", 956254885Sdumbbell i, (uintmax_t)offset, 957254885Sdumbbell radeon_bo_size(track->vgt_strmout_bo[i])); 958254885Sdumbbell return -EINVAL; 959254885Sdumbbell } 960254885Sdumbbell } else { 961254885Sdumbbell dev_warn(p->dev, "No buffer for streamout %d\n", i); 962254885Sdumbbell return -EINVAL; 963254885Sdumbbell } 964254885Sdumbbell } 965254885Sdumbbell } 966254885Sdumbbell track->streamout_dirty = false; 967254885Sdumbbell } 968254885Sdumbbell 969254885Sdumbbell if (track->sx_misc_kill_all_prims) 970254885Sdumbbell return 0; 971254885Sdumbbell 972254885Sdumbbell /* check that we have a cb for each enabled target 973254885Sdumbbell */ 974254885Sdumbbell if (track->cb_dirty) { 975254885Sdumbbell tmp = track->cb_target_mask; 976254885Sdumbbell for (i = 0; i < 8; i++) { 977254885Sdumbbell if ((tmp >> (i * 4)) & 0xF) { 978254885Sdumbbell /* at least one component is enabled */ 979254885Sdumbbell if (track->cb_color_bo[i] == NULL) { 980254885Sdumbbell dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n", 981254885Sdumbbell __func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i); 982254885Sdumbbell return -EINVAL; 983254885Sdumbbell } 984254885Sdumbbell /* check cb */ 985254885Sdumbbell r = evergreen_cs_track_validate_cb(p, i); 986254885Sdumbbell if (r) { 987254885Sdumbbell return r; 988254885Sdumbbell } 989254885Sdumbbell } 990254885Sdumbbell } 991254885Sdumbbell track->cb_dirty = false; 992254885Sdumbbell } 993254885Sdumbbell 994254885Sdumbbell if (track->db_dirty) { 995254885Sdumbbell /* Check stencil buffer */ 996254885Sdumbbell if (G_028044_FORMAT(track->db_s_info) != V_028044_STENCIL_INVALID && 997254885Sdumbbell G_028800_STENCIL_ENABLE(track->db_depth_control)) { 998254885Sdumbbell r = evergreen_cs_track_validate_stencil(p); 999254885Sdumbbell if (r) 1000254885Sdumbbell return r; 1001254885Sdumbbell } 1002254885Sdumbbell /* Check depth buffer */ 1003254885Sdumbbell if (G_028040_FORMAT(track->db_z_info) != V_028040_Z_INVALID && 1004254885Sdumbbell G_028800_Z_ENABLE(track->db_depth_control)) { 1005254885Sdumbbell r = evergreen_cs_track_validate_depth(p); 1006254885Sdumbbell if (r) 1007254885Sdumbbell return r; 1008254885Sdumbbell } 1009254885Sdumbbell track->db_dirty = false; 1010254885Sdumbbell } 1011254885Sdumbbell 1012254885Sdumbbell return 0; 1013254885Sdumbbell} 1014254885Sdumbbell 1015254885Sdumbbell/** 1016254885Sdumbbell * evergreen_cs_packet_parse() - parse cp packet and point ib index to next packet 1017254885Sdumbbell * @parser: parser structure holding parsing context. 1018254885Sdumbbell * @pkt: where to store packet informations 1019254885Sdumbbell * 1020254885Sdumbbell * Assume that chunk_ib_index is properly set. Will return -EINVAL 1021254885Sdumbbell * if packet is bigger than remaining ib size. or if packets is unknown. 1022254885Sdumbbell **/ 1023254885Sdumbbellstatic int evergreen_cs_packet_parse(struct radeon_cs_parser *p, 1024254885Sdumbbell struct radeon_cs_packet *pkt, 1025254885Sdumbbell unsigned idx) 1026254885Sdumbbell{ 1027254885Sdumbbell struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; 1028254885Sdumbbell uint32_t header; 1029254885Sdumbbell 1030254885Sdumbbell if (idx >= ib_chunk->length_dw) { 1031254885Sdumbbell DRM_ERROR("Can not parse packet at %d after CS end %d !\n", 1032254885Sdumbbell idx, ib_chunk->length_dw); 1033254885Sdumbbell return -EINVAL; 1034254885Sdumbbell } 1035254885Sdumbbell header = radeon_get_ib_value(p, idx); 1036254885Sdumbbell pkt->idx = idx; 1037254885Sdumbbell pkt->type = CP_PACKET_GET_TYPE(header); 1038254885Sdumbbell pkt->count = CP_PACKET_GET_COUNT(header); 1039254885Sdumbbell pkt->one_reg_wr = 0; 1040254885Sdumbbell switch (pkt->type) { 1041254885Sdumbbell case PACKET_TYPE0: 1042254885Sdumbbell pkt->reg = CP_PACKET0_GET_REG(header); 1043254885Sdumbbell break; 1044254885Sdumbbell case PACKET_TYPE3: 1045254885Sdumbbell pkt->opcode = CP_PACKET3_GET_OPCODE(header); 1046254885Sdumbbell break; 1047254885Sdumbbell case PACKET_TYPE2: 1048254885Sdumbbell pkt->count = -1; 1049254885Sdumbbell break; 1050254885Sdumbbell default: 1051254885Sdumbbell DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx); 1052254885Sdumbbell return -EINVAL; 1053254885Sdumbbell } 1054254885Sdumbbell if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) { 1055254885Sdumbbell DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n", 1056254885Sdumbbell pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw); 1057254885Sdumbbell return -EINVAL; 1058254885Sdumbbell } 1059254885Sdumbbell return 0; 1060254885Sdumbbell} 1061254885Sdumbbell 1062254885Sdumbbell/** 1063254885Sdumbbell * evergreen_cs_packet_next_reloc() - parse next packet which should be reloc packet3 1064254885Sdumbbell * @parser: parser structure holding parsing context. 1065254885Sdumbbell * @data: pointer to relocation data 1066254885Sdumbbell * @offset_start: starting offset 1067254885Sdumbbell * @offset_mask: offset mask (to align start offset on) 1068254885Sdumbbell * @reloc: reloc informations 1069254885Sdumbbell * 1070254885Sdumbbell * Check next packet is relocation packet3, do bo validation and compute 1071254885Sdumbbell * GPU offset using the provided start. 1072254885Sdumbbell **/ 1073254885Sdumbbellstatic int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p, 1074254885Sdumbbell struct radeon_cs_reloc **cs_reloc) 1075254885Sdumbbell{ 1076254885Sdumbbell struct radeon_cs_chunk *relocs_chunk; 1077254885Sdumbbell struct radeon_cs_packet p3reloc; 1078254885Sdumbbell unsigned idx; 1079254885Sdumbbell int r; 1080254885Sdumbbell 1081254885Sdumbbell if (p->chunk_relocs_idx == -1) { 1082254885Sdumbbell DRM_ERROR("No relocation chunk !\n"); 1083254885Sdumbbell return -EINVAL; 1084254885Sdumbbell } 1085254885Sdumbbell *cs_reloc = NULL; 1086254885Sdumbbell relocs_chunk = &p->chunks[p->chunk_relocs_idx]; 1087254885Sdumbbell r = evergreen_cs_packet_parse(p, &p3reloc, p->idx); 1088254885Sdumbbell if (r) { 1089254885Sdumbbell return r; 1090254885Sdumbbell } 1091254885Sdumbbell p->idx += p3reloc.count + 2; 1092254885Sdumbbell if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { 1093254885Sdumbbell DRM_ERROR("No packet3 for relocation for packet at %d.\n", 1094254885Sdumbbell p3reloc.idx); 1095254885Sdumbbell return -EINVAL; 1096254885Sdumbbell } 1097254885Sdumbbell idx = radeon_get_ib_value(p, p3reloc.idx + 1); 1098254885Sdumbbell if (idx >= relocs_chunk->length_dw) { 1099254885Sdumbbell DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", 1100254885Sdumbbell idx, relocs_chunk->length_dw); 1101254885Sdumbbell return -EINVAL; 1102254885Sdumbbell } 1103254885Sdumbbell /* FIXME: we assume reloc size is 4 dwords */ 1104254885Sdumbbell *cs_reloc = p->relocs_ptr[(idx / 4)]; 1105254885Sdumbbell return 0; 1106254885Sdumbbell} 1107254885Sdumbbell 1108254885Sdumbbell/** 1109254885Sdumbbell * evergreen_cs_packet_next_is_pkt3_nop() - test if the next packet is NOP 1110254885Sdumbbell * @p: structure holding the parser context. 1111254885Sdumbbell * 1112254885Sdumbbell * Check if the next packet is a relocation packet3. 1113254885Sdumbbell **/ 1114254885Sdumbbellstatic bool evergreen_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p) 1115254885Sdumbbell{ 1116254885Sdumbbell struct radeon_cs_packet p3reloc; 1117254885Sdumbbell int r; 1118254885Sdumbbell 1119254885Sdumbbell r = evergreen_cs_packet_parse(p, &p3reloc, p->idx); 1120254885Sdumbbell if (r) { 1121254885Sdumbbell return false; 1122254885Sdumbbell } 1123254885Sdumbbell if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { 1124254885Sdumbbell return false; 1125254885Sdumbbell } 1126254885Sdumbbell return true; 1127254885Sdumbbell} 1128254885Sdumbbell 1129254885Sdumbbell/** 1130254885Sdumbbell * evergreen_cs_packet_next_vline() - parse userspace VLINE packet 1131254885Sdumbbell * @parser: parser structure holding parsing context. 1132254885Sdumbbell * 1133254885Sdumbbell * Userspace sends a special sequence for VLINE waits. 1134254885Sdumbbell * PACKET0 - VLINE_START_END + value 1135254885Sdumbbell * PACKET3 - WAIT_REG_MEM poll vline status reg 1136254885Sdumbbell * RELOC (P3) - crtc_id in reloc. 1137254885Sdumbbell * 1138254885Sdumbbell * This function parses this and relocates the VLINE START END 1139254885Sdumbbell * and WAIT_REG_MEM packets to the correct crtc. 1140254885Sdumbbell * It also detects a switched off crtc and nulls out the 1141254885Sdumbbell * wait in that case. 1142254885Sdumbbell */ 1143254885Sdumbbellstatic int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p) 1144254885Sdumbbell{ 1145254885Sdumbbell struct drm_mode_object *obj; 1146254885Sdumbbell struct drm_crtc *crtc; 1147254885Sdumbbell struct radeon_crtc *radeon_crtc; 1148254885Sdumbbell struct radeon_cs_packet p3reloc, wait_reg_mem; 1149254885Sdumbbell int crtc_id; 1150254885Sdumbbell int r; 1151254885Sdumbbell uint32_t header, h_idx, reg, wait_reg_mem_info; 1152254885Sdumbbell volatile uint32_t *ib; 1153254885Sdumbbell 1154254885Sdumbbell ib = p->ib.ptr; 1155254885Sdumbbell 1156254885Sdumbbell /* parse the WAIT_REG_MEM */ 1157254885Sdumbbell r = evergreen_cs_packet_parse(p, &wait_reg_mem, p->idx); 1158254885Sdumbbell if (r) 1159254885Sdumbbell return r; 1160254885Sdumbbell 1161254885Sdumbbell /* check its a WAIT_REG_MEM */ 1162254885Sdumbbell if (wait_reg_mem.type != PACKET_TYPE3 || 1163254885Sdumbbell wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) { 1164254885Sdumbbell DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n"); 1165254885Sdumbbell return -EINVAL; 1166254885Sdumbbell } 1167254885Sdumbbell 1168254885Sdumbbell wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1); 1169254885Sdumbbell /* bit 4 is reg (0) or mem (1) */ 1170254885Sdumbbell if (wait_reg_mem_info & 0x10) { 1171254885Sdumbbell DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n"); 1172254885Sdumbbell return -EINVAL; 1173254885Sdumbbell } 1174254885Sdumbbell /* waiting for value to be equal */ 1175254885Sdumbbell if ((wait_reg_mem_info & 0x7) != 0x3) { 1176254885Sdumbbell DRM_ERROR("vline WAIT_REG_MEM function not equal\n"); 1177254885Sdumbbell return -EINVAL; 1178254885Sdumbbell } 1179254885Sdumbbell if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != EVERGREEN_VLINE_STATUS) { 1180254885Sdumbbell DRM_ERROR("vline WAIT_REG_MEM bad reg\n"); 1181254885Sdumbbell return -EINVAL; 1182254885Sdumbbell } 1183254885Sdumbbell 1184254885Sdumbbell if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != EVERGREEN_VLINE_STAT) { 1185254885Sdumbbell DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n"); 1186254885Sdumbbell return -EINVAL; 1187254885Sdumbbell } 1188254885Sdumbbell 1189254885Sdumbbell /* jump over the NOP */ 1190254885Sdumbbell r = evergreen_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2); 1191254885Sdumbbell if (r) 1192254885Sdumbbell return r; 1193254885Sdumbbell 1194254885Sdumbbell h_idx = p->idx - 2; 1195254885Sdumbbell p->idx += wait_reg_mem.count + 2; 1196254885Sdumbbell p->idx += p3reloc.count + 2; 1197254885Sdumbbell 1198254885Sdumbbell header = radeon_get_ib_value(p, h_idx); 1199254885Sdumbbell crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1); 1200254885Sdumbbell reg = CP_PACKET0_GET_REG(header); 1201254885Sdumbbell obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC); 1202254885Sdumbbell if (!obj) { 1203254885Sdumbbell DRM_ERROR("cannot find crtc %d\n", crtc_id); 1204254885Sdumbbell return -EINVAL; 1205254885Sdumbbell } 1206254885Sdumbbell crtc = obj_to_crtc(obj); 1207254885Sdumbbell radeon_crtc = to_radeon_crtc(crtc); 1208254885Sdumbbell crtc_id = radeon_crtc->crtc_id; 1209254885Sdumbbell 1210254885Sdumbbell if (!crtc->enabled) { 1211254885Sdumbbell /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */ 1212254885Sdumbbell ib[h_idx + 2] = PACKET2(0); 1213254885Sdumbbell ib[h_idx + 3] = PACKET2(0); 1214254885Sdumbbell ib[h_idx + 4] = PACKET2(0); 1215254885Sdumbbell ib[h_idx + 5] = PACKET2(0); 1216254885Sdumbbell ib[h_idx + 6] = PACKET2(0); 1217254885Sdumbbell ib[h_idx + 7] = PACKET2(0); 1218254885Sdumbbell ib[h_idx + 8] = PACKET2(0); 1219254885Sdumbbell } else { 1220254885Sdumbbell switch (reg) { 1221254885Sdumbbell case EVERGREEN_VLINE_START_END: 1222254885Sdumbbell header &= ~R600_CP_PACKET0_REG_MASK; 1223254885Sdumbbell header |= (EVERGREEN_VLINE_START_END + radeon_crtc->crtc_offset) >> 2; 1224254885Sdumbbell ib[h_idx] = header; 1225254885Sdumbbell ib[h_idx + 4] = (EVERGREEN_VLINE_STATUS + radeon_crtc->crtc_offset) >> 2; 1226254885Sdumbbell break; 1227254885Sdumbbell default: 1228254885Sdumbbell DRM_ERROR("unknown crtc reloc\n"); 1229254885Sdumbbell return -EINVAL; 1230254885Sdumbbell } 1231254885Sdumbbell } 1232254885Sdumbbell return 0; 1233254885Sdumbbell} 1234254885Sdumbbell 1235254885Sdumbbellstatic int evergreen_packet0_check(struct radeon_cs_parser *p, 1236254885Sdumbbell struct radeon_cs_packet *pkt, 1237254885Sdumbbell unsigned idx, unsigned reg) 1238254885Sdumbbell{ 1239254885Sdumbbell int r; 1240254885Sdumbbell 1241254885Sdumbbell switch (reg) { 1242254885Sdumbbell case EVERGREEN_VLINE_START_END: 1243254885Sdumbbell r = evergreen_cs_packet_parse_vline(p); 1244254885Sdumbbell if (r) { 1245254885Sdumbbell DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1246254885Sdumbbell idx, reg); 1247254885Sdumbbell return r; 1248254885Sdumbbell } 1249254885Sdumbbell break; 1250254885Sdumbbell default: 1251254885Sdumbbell DRM_ERROR("Forbidden register 0x%04X in cs at %d\n", 1252254885Sdumbbell reg, idx); 1253254885Sdumbbell return -EINVAL; 1254254885Sdumbbell } 1255254885Sdumbbell return 0; 1256254885Sdumbbell} 1257254885Sdumbbell 1258254885Sdumbbellstatic int evergreen_cs_parse_packet0(struct radeon_cs_parser *p, 1259254885Sdumbbell struct radeon_cs_packet *pkt) 1260254885Sdumbbell{ 1261254885Sdumbbell unsigned reg, i; 1262254885Sdumbbell unsigned idx; 1263254885Sdumbbell int r; 1264254885Sdumbbell 1265254885Sdumbbell idx = pkt->idx + 1; 1266254885Sdumbbell reg = pkt->reg; 1267254885Sdumbbell for (i = 0; i <= pkt->count; i++, idx++, reg += 4) { 1268254885Sdumbbell r = evergreen_packet0_check(p, pkt, idx, reg); 1269254885Sdumbbell if (r) { 1270254885Sdumbbell return r; 1271254885Sdumbbell } 1272254885Sdumbbell } 1273254885Sdumbbell return 0; 1274254885Sdumbbell} 1275254885Sdumbbell 1276254885Sdumbbell/** 1277254885Sdumbbell * evergreen_cs_check_reg() - check if register is authorized or not 1278254885Sdumbbell * @parser: parser structure holding parsing context 1279254885Sdumbbell * @reg: register we are testing 1280254885Sdumbbell * @idx: index into the cs buffer 1281254885Sdumbbell * 1282254885Sdumbbell * This function will test against evergreen_reg_safe_bm and return 0 1283254885Sdumbbell * if register is safe. If register is not flag as safe this function 1284254885Sdumbbell * will test it against a list of register needind special handling. 1285254885Sdumbbell */ 1286254885Sdumbbellstatic int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) 1287254885Sdumbbell{ 1288254885Sdumbbell struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track; 1289254885Sdumbbell struct radeon_cs_reloc *reloc; 1290254885Sdumbbell u32 last_reg; 1291254885Sdumbbell u32 m, i, tmp, *ib; 1292254885Sdumbbell int r; 1293254885Sdumbbell 1294254885Sdumbbell if (p->rdev->family >= CHIP_CAYMAN) 1295254885Sdumbbell last_reg = DRM_ARRAY_SIZE(cayman_reg_safe_bm); 1296254885Sdumbbell else 1297254885Sdumbbell last_reg = DRM_ARRAY_SIZE(evergreen_reg_safe_bm); 1298254885Sdumbbell 1299254885Sdumbbell i = (reg >> 7); 1300254885Sdumbbell if (i >= last_reg) { 1301254885Sdumbbell dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); 1302254885Sdumbbell return -EINVAL; 1303254885Sdumbbell } 1304254885Sdumbbell m = 1 << ((reg >> 2) & 31); 1305254885Sdumbbell if (p->rdev->family >= CHIP_CAYMAN) { 1306254885Sdumbbell if (!(cayman_reg_safe_bm[i] & m)) 1307254885Sdumbbell return 0; 1308254885Sdumbbell } else { 1309254885Sdumbbell if (!(evergreen_reg_safe_bm[i] & m)) 1310254885Sdumbbell return 0; 1311254885Sdumbbell } 1312254885Sdumbbell ib = p->ib.ptr; 1313254885Sdumbbell switch (reg) { 1314254885Sdumbbell /* force following reg to 0 in an attempt to disable out buffer 1315254885Sdumbbell * which will need us to better understand how it works to perform 1316254885Sdumbbell * security check on it (Jerome) 1317254885Sdumbbell */ 1318254885Sdumbbell case SQ_ESGS_RING_SIZE: 1319254885Sdumbbell case SQ_GSVS_RING_SIZE: 1320254885Sdumbbell case SQ_ESTMP_RING_SIZE: 1321254885Sdumbbell case SQ_GSTMP_RING_SIZE: 1322254885Sdumbbell case SQ_HSTMP_RING_SIZE: 1323254885Sdumbbell case SQ_LSTMP_RING_SIZE: 1324254885Sdumbbell case SQ_PSTMP_RING_SIZE: 1325254885Sdumbbell case SQ_VSTMP_RING_SIZE: 1326254885Sdumbbell case SQ_ESGS_RING_ITEMSIZE: 1327254885Sdumbbell case SQ_ESTMP_RING_ITEMSIZE: 1328254885Sdumbbell case SQ_GSTMP_RING_ITEMSIZE: 1329254885Sdumbbell case SQ_GSVS_RING_ITEMSIZE: 1330254885Sdumbbell case SQ_GS_VERT_ITEMSIZE: 1331254885Sdumbbell case SQ_GS_VERT_ITEMSIZE_1: 1332254885Sdumbbell case SQ_GS_VERT_ITEMSIZE_2: 1333254885Sdumbbell case SQ_GS_VERT_ITEMSIZE_3: 1334254885Sdumbbell case SQ_GSVS_RING_OFFSET_1: 1335254885Sdumbbell case SQ_GSVS_RING_OFFSET_2: 1336254885Sdumbbell case SQ_GSVS_RING_OFFSET_3: 1337254885Sdumbbell case SQ_HSTMP_RING_ITEMSIZE: 1338254885Sdumbbell case SQ_LSTMP_RING_ITEMSIZE: 1339254885Sdumbbell case SQ_PSTMP_RING_ITEMSIZE: 1340254885Sdumbbell case SQ_VSTMP_RING_ITEMSIZE: 1341254885Sdumbbell case VGT_TF_RING_SIZE: 1342254885Sdumbbell /* get value to populate the IB don't remove */ 1343254885Sdumbbell /*tmp =radeon_get_ib_value(p, idx); 1344254885Sdumbbell ib[idx] = 0;*/ 1345254885Sdumbbell break; 1346254885Sdumbbell case SQ_ESGS_RING_BASE: 1347254885Sdumbbell case SQ_GSVS_RING_BASE: 1348254885Sdumbbell case SQ_ESTMP_RING_BASE: 1349254885Sdumbbell case SQ_GSTMP_RING_BASE: 1350254885Sdumbbell case SQ_HSTMP_RING_BASE: 1351254885Sdumbbell case SQ_LSTMP_RING_BASE: 1352254885Sdumbbell case SQ_PSTMP_RING_BASE: 1353254885Sdumbbell case SQ_VSTMP_RING_BASE: 1354254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1355254885Sdumbbell if (r) { 1356254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1357254885Sdumbbell "0x%04X\n", reg); 1358254885Sdumbbell return -EINVAL; 1359254885Sdumbbell } 1360254885Sdumbbell ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 1361254885Sdumbbell break; 1362254885Sdumbbell case DB_DEPTH_CONTROL: 1363254885Sdumbbell track->db_depth_control = radeon_get_ib_value(p, idx); 1364254885Sdumbbell track->db_dirty = true; 1365254885Sdumbbell break; 1366254885Sdumbbell case CAYMAN_DB_EQAA: 1367254885Sdumbbell if (p->rdev->family < CHIP_CAYMAN) { 1368254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1369254885Sdumbbell "0x%04X\n", reg); 1370254885Sdumbbell return -EINVAL; 1371254885Sdumbbell } 1372254885Sdumbbell break; 1373254885Sdumbbell case CAYMAN_DB_DEPTH_INFO: 1374254885Sdumbbell if (p->rdev->family < CHIP_CAYMAN) { 1375254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1376254885Sdumbbell "0x%04X\n", reg); 1377254885Sdumbbell return -EINVAL; 1378254885Sdumbbell } 1379254885Sdumbbell break; 1380254885Sdumbbell case DB_Z_INFO: 1381254885Sdumbbell track->db_z_info = radeon_get_ib_value(p, idx); 1382254885Sdumbbell if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 1383254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1384254885Sdumbbell if (r) { 1385254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1386254885Sdumbbell "0x%04X\n", reg); 1387254885Sdumbbell return -EINVAL; 1388254885Sdumbbell } 1389254885Sdumbbell ib[idx] &= ~Z_ARRAY_MODE(0xf); 1390254885Sdumbbell track->db_z_info &= ~Z_ARRAY_MODE(0xf); 1391254885Sdumbbell ib[idx] |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); 1392254885Sdumbbell track->db_z_info |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); 1393254885Sdumbbell if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { 1394254885Sdumbbell unsigned bankw, bankh, mtaspect, tile_split; 1395254885Sdumbbell 1396254885Sdumbbell evergreen_tiling_fields(reloc->lobj.tiling_flags, 1397254885Sdumbbell &bankw, &bankh, &mtaspect, 1398254885Sdumbbell &tile_split); 1399254885Sdumbbell ib[idx] |= DB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); 1400254885Sdumbbell ib[idx] |= DB_TILE_SPLIT(tile_split) | 1401254885Sdumbbell DB_BANK_WIDTH(bankw) | 1402254885Sdumbbell DB_BANK_HEIGHT(bankh) | 1403254885Sdumbbell DB_MACRO_TILE_ASPECT(mtaspect); 1404254885Sdumbbell } 1405254885Sdumbbell } 1406254885Sdumbbell track->db_dirty = true; 1407254885Sdumbbell break; 1408254885Sdumbbell case DB_STENCIL_INFO: 1409254885Sdumbbell track->db_s_info = radeon_get_ib_value(p, idx); 1410254885Sdumbbell track->db_dirty = true; 1411254885Sdumbbell break; 1412254885Sdumbbell case DB_DEPTH_VIEW: 1413254885Sdumbbell track->db_depth_view = radeon_get_ib_value(p, idx); 1414254885Sdumbbell track->db_dirty = true; 1415254885Sdumbbell break; 1416254885Sdumbbell case DB_DEPTH_SIZE: 1417254885Sdumbbell track->db_depth_size = radeon_get_ib_value(p, idx); 1418254885Sdumbbell track->db_dirty = true; 1419254885Sdumbbell break; 1420254885Sdumbbell case R_02805C_DB_DEPTH_SLICE: 1421254885Sdumbbell track->db_depth_slice = radeon_get_ib_value(p, idx); 1422254885Sdumbbell track->db_dirty = true; 1423254885Sdumbbell break; 1424254885Sdumbbell case DB_Z_READ_BASE: 1425254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1426254885Sdumbbell if (r) { 1427254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1428254885Sdumbbell "0x%04X\n", reg); 1429254885Sdumbbell return -EINVAL; 1430254885Sdumbbell } 1431254885Sdumbbell track->db_z_read_offset = radeon_get_ib_value(p, idx); 1432254885Sdumbbell ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 1433254885Sdumbbell track->db_z_read_bo = reloc->robj; 1434254885Sdumbbell track->db_dirty = true; 1435254885Sdumbbell break; 1436254885Sdumbbell case DB_Z_WRITE_BASE: 1437254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1438254885Sdumbbell if (r) { 1439254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1440254885Sdumbbell "0x%04X\n", reg); 1441254885Sdumbbell return -EINVAL; 1442254885Sdumbbell } 1443254885Sdumbbell track->db_z_write_offset = radeon_get_ib_value(p, idx); 1444254885Sdumbbell ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 1445254885Sdumbbell track->db_z_write_bo = reloc->robj; 1446254885Sdumbbell track->db_dirty = true; 1447254885Sdumbbell break; 1448254885Sdumbbell case DB_STENCIL_READ_BASE: 1449254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1450254885Sdumbbell if (r) { 1451254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1452254885Sdumbbell "0x%04X\n", reg); 1453254885Sdumbbell return -EINVAL; 1454254885Sdumbbell } 1455254885Sdumbbell track->db_s_read_offset = radeon_get_ib_value(p, idx); 1456254885Sdumbbell ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 1457254885Sdumbbell track->db_s_read_bo = reloc->robj; 1458254885Sdumbbell track->db_dirty = true; 1459254885Sdumbbell break; 1460254885Sdumbbell case DB_STENCIL_WRITE_BASE: 1461254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1462254885Sdumbbell if (r) { 1463254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1464254885Sdumbbell "0x%04X\n", reg); 1465254885Sdumbbell return -EINVAL; 1466254885Sdumbbell } 1467254885Sdumbbell track->db_s_write_offset = radeon_get_ib_value(p, idx); 1468254885Sdumbbell ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 1469254885Sdumbbell track->db_s_write_bo = reloc->robj; 1470254885Sdumbbell track->db_dirty = true; 1471254885Sdumbbell break; 1472254885Sdumbbell case VGT_STRMOUT_CONFIG: 1473254885Sdumbbell track->vgt_strmout_config = radeon_get_ib_value(p, idx); 1474254885Sdumbbell track->streamout_dirty = true; 1475254885Sdumbbell break; 1476254885Sdumbbell case VGT_STRMOUT_BUFFER_CONFIG: 1477254885Sdumbbell track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); 1478254885Sdumbbell track->streamout_dirty = true; 1479254885Sdumbbell break; 1480254885Sdumbbell case VGT_STRMOUT_BUFFER_BASE_0: 1481254885Sdumbbell case VGT_STRMOUT_BUFFER_BASE_1: 1482254885Sdumbbell case VGT_STRMOUT_BUFFER_BASE_2: 1483254885Sdumbbell case VGT_STRMOUT_BUFFER_BASE_3: 1484254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1485254885Sdumbbell if (r) { 1486254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1487254885Sdumbbell "0x%04X\n", reg); 1488254885Sdumbbell return -EINVAL; 1489254885Sdumbbell } 1490254885Sdumbbell tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; 1491254885Sdumbbell track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; 1492254885Sdumbbell ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 1493254885Sdumbbell track->vgt_strmout_bo[tmp] = reloc->robj; 1494254885Sdumbbell track->streamout_dirty = true; 1495254885Sdumbbell break; 1496254885Sdumbbell case VGT_STRMOUT_BUFFER_SIZE_0: 1497254885Sdumbbell case VGT_STRMOUT_BUFFER_SIZE_1: 1498254885Sdumbbell case VGT_STRMOUT_BUFFER_SIZE_2: 1499254885Sdumbbell case VGT_STRMOUT_BUFFER_SIZE_3: 1500254885Sdumbbell tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; 1501254885Sdumbbell /* size in register is DWs, convert to bytes */ 1502254885Sdumbbell track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4; 1503254885Sdumbbell track->streamout_dirty = true; 1504254885Sdumbbell break; 1505254885Sdumbbell case CP_COHER_BASE: 1506254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1507254885Sdumbbell if (r) { 1508254885Sdumbbell dev_warn(p->dev, "missing reloc for CP_COHER_BASE " 1509254885Sdumbbell "0x%04X\n", reg); 1510254885Sdumbbell return -EINVAL; 1511254885Sdumbbell } 1512254885Sdumbbell ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 1513254885Sdumbbell case CB_TARGET_MASK: 1514254885Sdumbbell track->cb_target_mask = radeon_get_ib_value(p, idx); 1515254885Sdumbbell track->cb_dirty = true; 1516254885Sdumbbell break; 1517254885Sdumbbell case CB_SHADER_MASK: 1518254885Sdumbbell track->cb_shader_mask = radeon_get_ib_value(p, idx); 1519254885Sdumbbell track->cb_dirty = true; 1520254885Sdumbbell break; 1521254885Sdumbbell case PA_SC_AA_CONFIG: 1522254885Sdumbbell if (p->rdev->family >= CHIP_CAYMAN) { 1523254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1524254885Sdumbbell "0x%04X\n", reg); 1525254885Sdumbbell return -EINVAL; 1526254885Sdumbbell } 1527254885Sdumbbell tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK; 1528254885Sdumbbell track->nsamples = 1 << tmp; 1529254885Sdumbbell break; 1530254885Sdumbbell case CAYMAN_PA_SC_AA_CONFIG: 1531254885Sdumbbell if (p->rdev->family < CHIP_CAYMAN) { 1532254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1533254885Sdumbbell "0x%04X\n", reg); 1534254885Sdumbbell return -EINVAL; 1535254885Sdumbbell } 1536254885Sdumbbell tmp = radeon_get_ib_value(p, idx) & CAYMAN_MSAA_NUM_SAMPLES_MASK; 1537254885Sdumbbell track->nsamples = 1 << tmp; 1538254885Sdumbbell break; 1539254885Sdumbbell case CB_COLOR0_VIEW: 1540254885Sdumbbell case CB_COLOR1_VIEW: 1541254885Sdumbbell case CB_COLOR2_VIEW: 1542254885Sdumbbell case CB_COLOR3_VIEW: 1543254885Sdumbbell case CB_COLOR4_VIEW: 1544254885Sdumbbell case CB_COLOR5_VIEW: 1545254885Sdumbbell case CB_COLOR6_VIEW: 1546254885Sdumbbell case CB_COLOR7_VIEW: 1547254885Sdumbbell tmp = (reg - CB_COLOR0_VIEW) / 0x3c; 1548254885Sdumbbell track->cb_color_view[tmp] = radeon_get_ib_value(p, idx); 1549254885Sdumbbell track->cb_dirty = true; 1550254885Sdumbbell break; 1551254885Sdumbbell case CB_COLOR8_VIEW: 1552254885Sdumbbell case CB_COLOR9_VIEW: 1553254885Sdumbbell case CB_COLOR10_VIEW: 1554254885Sdumbbell case CB_COLOR11_VIEW: 1555254885Sdumbbell tmp = ((reg - CB_COLOR8_VIEW) / 0x1c) + 8; 1556254885Sdumbbell track->cb_color_view[tmp] = radeon_get_ib_value(p, idx); 1557254885Sdumbbell track->cb_dirty = true; 1558254885Sdumbbell break; 1559254885Sdumbbell case CB_COLOR0_INFO: 1560254885Sdumbbell case CB_COLOR1_INFO: 1561254885Sdumbbell case CB_COLOR2_INFO: 1562254885Sdumbbell case CB_COLOR3_INFO: 1563254885Sdumbbell case CB_COLOR4_INFO: 1564254885Sdumbbell case CB_COLOR5_INFO: 1565254885Sdumbbell case CB_COLOR6_INFO: 1566254885Sdumbbell case CB_COLOR7_INFO: 1567254885Sdumbbell tmp = (reg - CB_COLOR0_INFO) / 0x3c; 1568254885Sdumbbell track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); 1569254885Sdumbbell if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 1570254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1571254885Sdumbbell if (r) { 1572254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1573254885Sdumbbell "0x%04X\n", reg); 1574254885Sdumbbell return -EINVAL; 1575254885Sdumbbell } 1576254885Sdumbbell ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); 1577254885Sdumbbell track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); 1578254885Sdumbbell } 1579254885Sdumbbell track->cb_dirty = true; 1580254885Sdumbbell break; 1581254885Sdumbbell case CB_COLOR8_INFO: 1582254885Sdumbbell case CB_COLOR9_INFO: 1583254885Sdumbbell case CB_COLOR10_INFO: 1584254885Sdumbbell case CB_COLOR11_INFO: 1585254885Sdumbbell tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8; 1586254885Sdumbbell track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); 1587254885Sdumbbell if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 1588254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1589254885Sdumbbell if (r) { 1590254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1591254885Sdumbbell "0x%04X\n", reg); 1592254885Sdumbbell return -EINVAL; 1593254885Sdumbbell } 1594254885Sdumbbell ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); 1595254885Sdumbbell track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); 1596254885Sdumbbell } 1597254885Sdumbbell track->cb_dirty = true; 1598254885Sdumbbell break; 1599254885Sdumbbell case CB_COLOR0_PITCH: 1600254885Sdumbbell case CB_COLOR1_PITCH: 1601254885Sdumbbell case CB_COLOR2_PITCH: 1602254885Sdumbbell case CB_COLOR3_PITCH: 1603254885Sdumbbell case CB_COLOR4_PITCH: 1604254885Sdumbbell case CB_COLOR5_PITCH: 1605254885Sdumbbell case CB_COLOR6_PITCH: 1606254885Sdumbbell case CB_COLOR7_PITCH: 1607254885Sdumbbell tmp = (reg - CB_COLOR0_PITCH) / 0x3c; 1608254885Sdumbbell track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx); 1609254885Sdumbbell track->cb_dirty = true; 1610254885Sdumbbell break; 1611254885Sdumbbell case CB_COLOR8_PITCH: 1612254885Sdumbbell case CB_COLOR9_PITCH: 1613254885Sdumbbell case CB_COLOR10_PITCH: 1614254885Sdumbbell case CB_COLOR11_PITCH: 1615254885Sdumbbell tmp = ((reg - CB_COLOR8_PITCH) / 0x1c) + 8; 1616254885Sdumbbell track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx); 1617254885Sdumbbell track->cb_dirty = true; 1618254885Sdumbbell break; 1619254885Sdumbbell case CB_COLOR0_SLICE: 1620254885Sdumbbell case CB_COLOR1_SLICE: 1621254885Sdumbbell case CB_COLOR2_SLICE: 1622254885Sdumbbell case CB_COLOR3_SLICE: 1623254885Sdumbbell case CB_COLOR4_SLICE: 1624254885Sdumbbell case CB_COLOR5_SLICE: 1625254885Sdumbbell case CB_COLOR6_SLICE: 1626254885Sdumbbell case CB_COLOR7_SLICE: 1627254885Sdumbbell tmp = (reg - CB_COLOR0_SLICE) / 0x3c; 1628254885Sdumbbell track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); 1629254885Sdumbbell track->cb_color_slice_idx[tmp] = idx; 1630254885Sdumbbell track->cb_dirty = true; 1631254885Sdumbbell break; 1632254885Sdumbbell case CB_COLOR8_SLICE: 1633254885Sdumbbell case CB_COLOR9_SLICE: 1634254885Sdumbbell case CB_COLOR10_SLICE: 1635254885Sdumbbell case CB_COLOR11_SLICE: 1636254885Sdumbbell tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8; 1637254885Sdumbbell track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); 1638254885Sdumbbell track->cb_color_slice_idx[tmp] = idx; 1639254885Sdumbbell track->cb_dirty = true; 1640254885Sdumbbell break; 1641254885Sdumbbell case CB_COLOR0_ATTRIB: 1642254885Sdumbbell case CB_COLOR1_ATTRIB: 1643254885Sdumbbell case CB_COLOR2_ATTRIB: 1644254885Sdumbbell case CB_COLOR3_ATTRIB: 1645254885Sdumbbell case CB_COLOR4_ATTRIB: 1646254885Sdumbbell case CB_COLOR5_ATTRIB: 1647254885Sdumbbell case CB_COLOR6_ATTRIB: 1648254885Sdumbbell case CB_COLOR7_ATTRIB: 1649254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1650254885Sdumbbell if (r) { 1651254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1652254885Sdumbbell "0x%04X\n", reg); 1653254885Sdumbbell return -EINVAL; 1654254885Sdumbbell } 1655254885Sdumbbell if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 1656254885Sdumbbell if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { 1657254885Sdumbbell unsigned bankw, bankh, mtaspect, tile_split; 1658254885Sdumbbell 1659254885Sdumbbell evergreen_tiling_fields(reloc->lobj.tiling_flags, 1660254885Sdumbbell &bankw, &bankh, &mtaspect, 1661254885Sdumbbell &tile_split); 1662254885Sdumbbell ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); 1663254885Sdumbbell ib[idx] |= CB_TILE_SPLIT(tile_split) | 1664254885Sdumbbell CB_BANK_WIDTH(bankw) | 1665254885Sdumbbell CB_BANK_HEIGHT(bankh) | 1666254885Sdumbbell CB_MACRO_TILE_ASPECT(mtaspect); 1667254885Sdumbbell } 1668254885Sdumbbell } 1669254885Sdumbbell tmp = ((reg - CB_COLOR0_ATTRIB) / 0x3c); 1670254885Sdumbbell track->cb_color_attrib[tmp] = ib[idx]; 1671254885Sdumbbell track->cb_dirty = true; 1672254885Sdumbbell break; 1673254885Sdumbbell case CB_COLOR8_ATTRIB: 1674254885Sdumbbell case CB_COLOR9_ATTRIB: 1675254885Sdumbbell case CB_COLOR10_ATTRIB: 1676254885Sdumbbell case CB_COLOR11_ATTRIB: 1677254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1678254885Sdumbbell if (r) { 1679254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1680254885Sdumbbell "0x%04X\n", reg); 1681254885Sdumbbell return -EINVAL; 1682254885Sdumbbell } 1683254885Sdumbbell if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 1684254885Sdumbbell if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { 1685254885Sdumbbell unsigned bankw, bankh, mtaspect, tile_split; 1686254885Sdumbbell 1687254885Sdumbbell evergreen_tiling_fields(reloc->lobj.tiling_flags, 1688254885Sdumbbell &bankw, &bankh, &mtaspect, 1689254885Sdumbbell &tile_split); 1690254885Sdumbbell ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); 1691254885Sdumbbell ib[idx] |= CB_TILE_SPLIT(tile_split) | 1692254885Sdumbbell CB_BANK_WIDTH(bankw) | 1693254885Sdumbbell CB_BANK_HEIGHT(bankh) | 1694254885Sdumbbell CB_MACRO_TILE_ASPECT(mtaspect); 1695254885Sdumbbell } 1696254885Sdumbbell } 1697254885Sdumbbell tmp = ((reg - CB_COLOR8_ATTRIB) / 0x1c) + 8; 1698254885Sdumbbell track->cb_color_attrib[tmp] = ib[idx]; 1699254885Sdumbbell track->cb_dirty = true; 1700254885Sdumbbell break; 1701254885Sdumbbell case CB_COLOR0_FMASK: 1702254885Sdumbbell case CB_COLOR1_FMASK: 1703254885Sdumbbell case CB_COLOR2_FMASK: 1704254885Sdumbbell case CB_COLOR3_FMASK: 1705254885Sdumbbell case CB_COLOR4_FMASK: 1706254885Sdumbbell case CB_COLOR5_FMASK: 1707254885Sdumbbell case CB_COLOR6_FMASK: 1708254885Sdumbbell case CB_COLOR7_FMASK: 1709254885Sdumbbell tmp = (reg - CB_COLOR0_FMASK) / 0x3c; 1710254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1711254885Sdumbbell if (r) { 1712254885Sdumbbell dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); 1713254885Sdumbbell return -EINVAL; 1714254885Sdumbbell } 1715254885Sdumbbell ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 1716254885Sdumbbell track->cb_color_fmask_bo[tmp] = reloc->robj; 1717254885Sdumbbell break; 1718254885Sdumbbell case CB_COLOR0_CMASK: 1719254885Sdumbbell case CB_COLOR1_CMASK: 1720254885Sdumbbell case CB_COLOR2_CMASK: 1721254885Sdumbbell case CB_COLOR3_CMASK: 1722254885Sdumbbell case CB_COLOR4_CMASK: 1723254885Sdumbbell case CB_COLOR5_CMASK: 1724254885Sdumbbell case CB_COLOR6_CMASK: 1725254885Sdumbbell case CB_COLOR7_CMASK: 1726254885Sdumbbell tmp = (reg - CB_COLOR0_CMASK) / 0x3c; 1727254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1728254885Sdumbbell if (r) { 1729254885Sdumbbell dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); 1730254885Sdumbbell return -EINVAL; 1731254885Sdumbbell } 1732254885Sdumbbell ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 1733254885Sdumbbell track->cb_color_cmask_bo[tmp] = reloc->robj; 1734254885Sdumbbell break; 1735254885Sdumbbell case CB_COLOR0_FMASK_SLICE: 1736254885Sdumbbell case CB_COLOR1_FMASK_SLICE: 1737254885Sdumbbell case CB_COLOR2_FMASK_SLICE: 1738254885Sdumbbell case CB_COLOR3_FMASK_SLICE: 1739254885Sdumbbell case CB_COLOR4_FMASK_SLICE: 1740254885Sdumbbell case CB_COLOR5_FMASK_SLICE: 1741254885Sdumbbell case CB_COLOR6_FMASK_SLICE: 1742254885Sdumbbell case CB_COLOR7_FMASK_SLICE: 1743254885Sdumbbell tmp = (reg - CB_COLOR0_FMASK_SLICE) / 0x3c; 1744254885Sdumbbell track->cb_color_fmask_slice[tmp] = radeon_get_ib_value(p, idx); 1745254885Sdumbbell break; 1746254885Sdumbbell case CB_COLOR0_CMASK_SLICE: 1747254885Sdumbbell case CB_COLOR1_CMASK_SLICE: 1748254885Sdumbbell case CB_COLOR2_CMASK_SLICE: 1749254885Sdumbbell case CB_COLOR3_CMASK_SLICE: 1750254885Sdumbbell case CB_COLOR4_CMASK_SLICE: 1751254885Sdumbbell case CB_COLOR5_CMASK_SLICE: 1752254885Sdumbbell case CB_COLOR6_CMASK_SLICE: 1753254885Sdumbbell case CB_COLOR7_CMASK_SLICE: 1754254885Sdumbbell tmp = (reg - CB_COLOR0_CMASK_SLICE) / 0x3c; 1755254885Sdumbbell track->cb_color_cmask_slice[tmp] = radeon_get_ib_value(p, idx); 1756254885Sdumbbell break; 1757254885Sdumbbell case CB_COLOR0_BASE: 1758254885Sdumbbell case CB_COLOR1_BASE: 1759254885Sdumbbell case CB_COLOR2_BASE: 1760254885Sdumbbell case CB_COLOR3_BASE: 1761254885Sdumbbell case CB_COLOR4_BASE: 1762254885Sdumbbell case CB_COLOR5_BASE: 1763254885Sdumbbell case CB_COLOR6_BASE: 1764254885Sdumbbell case CB_COLOR7_BASE: 1765254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1766254885Sdumbbell if (r) { 1767254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1768254885Sdumbbell "0x%04X\n", reg); 1769254885Sdumbbell return -EINVAL; 1770254885Sdumbbell } 1771254885Sdumbbell tmp = (reg - CB_COLOR0_BASE) / 0x3c; 1772254885Sdumbbell track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx); 1773254885Sdumbbell ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 1774254885Sdumbbell track->cb_color_bo[tmp] = reloc->robj; 1775254885Sdumbbell track->cb_dirty = true; 1776254885Sdumbbell break; 1777254885Sdumbbell case CB_COLOR8_BASE: 1778254885Sdumbbell case CB_COLOR9_BASE: 1779254885Sdumbbell case CB_COLOR10_BASE: 1780254885Sdumbbell case CB_COLOR11_BASE: 1781254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1782254885Sdumbbell if (r) { 1783254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1784254885Sdumbbell "0x%04X\n", reg); 1785254885Sdumbbell return -EINVAL; 1786254885Sdumbbell } 1787254885Sdumbbell tmp = ((reg - CB_COLOR8_BASE) / 0x1c) + 8; 1788254885Sdumbbell track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx); 1789254885Sdumbbell ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 1790254885Sdumbbell track->cb_color_bo[tmp] = reloc->robj; 1791254885Sdumbbell track->cb_dirty = true; 1792254885Sdumbbell break; 1793254885Sdumbbell case DB_HTILE_DATA_BASE: 1794254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1795254885Sdumbbell if (r) { 1796254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1797254885Sdumbbell "0x%04X\n", reg); 1798254885Sdumbbell return -EINVAL; 1799254885Sdumbbell } 1800254885Sdumbbell track->htile_offset = radeon_get_ib_value(p, idx); 1801254885Sdumbbell ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 1802254885Sdumbbell track->htile_bo = reloc->robj; 1803254885Sdumbbell track->db_dirty = true; 1804254885Sdumbbell break; 1805254885Sdumbbell case DB_HTILE_SURFACE: 1806254885Sdumbbell /* 8x8 only */ 1807254885Sdumbbell track->htile_surface = radeon_get_ib_value(p, idx); 1808254885Sdumbbell /* force 8x8 htile width and height */ 1809254885Sdumbbell ib[idx] |= 3; 1810254885Sdumbbell track->db_dirty = true; 1811254885Sdumbbell break; 1812254885Sdumbbell case CB_IMMED0_BASE: 1813254885Sdumbbell case CB_IMMED1_BASE: 1814254885Sdumbbell case CB_IMMED2_BASE: 1815254885Sdumbbell case CB_IMMED3_BASE: 1816254885Sdumbbell case CB_IMMED4_BASE: 1817254885Sdumbbell case CB_IMMED5_BASE: 1818254885Sdumbbell case CB_IMMED6_BASE: 1819254885Sdumbbell case CB_IMMED7_BASE: 1820254885Sdumbbell case CB_IMMED8_BASE: 1821254885Sdumbbell case CB_IMMED9_BASE: 1822254885Sdumbbell case CB_IMMED10_BASE: 1823254885Sdumbbell case CB_IMMED11_BASE: 1824254885Sdumbbell case SQ_PGM_START_FS: 1825254885Sdumbbell case SQ_PGM_START_ES: 1826254885Sdumbbell case SQ_PGM_START_VS: 1827254885Sdumbbell case SQ_PGM_START_GS: 1828254885Sdumbbell case SQ_PGM_START_PS: 1829254885Sdumbbell case SQ_PGM_START_HS: 1830254885Sdumbbell case SQ_PGM_START_LS: 1831254885Sdumbbell case SQ_CONST_MEM_BASE: 1832254885Sdumbbell case SQ_ALU_CONST_CACHE_GS_0: 1833254885Sdumbbell case SQ_ALU_CONST_CACHE_GS_1: 1834254885Sdumbbell case SQ_ALU_CONST_CACHE_GS_2: 1835254885Sdumbbell case SQ_ALU_CONST_CACHE_GS_3: 1836254885Sdumbbell case SQ_ALU_CONST_CACHE_GS_4: 1837254885Sdumbbell case SQ_ALU_CONST_CACHE_GS_5: 1838254885Sdumbbell case SQ_ALU_CONST_CACHE_GS_6: 1839254885Sdumbbell case SQ_ALU_CONST_CACHE_GS_7: 1840254885Sdumbbell case SQ_ALU_CONST_CACHE_GS_8: 1841254885Sdumbbell case SQ_ALU_CONST_CACHE_GS_9: 1842254885Sdumbbell case SQ_ALU_CONST_CACHE_GS_10: 1843254885Sdumbbell case SQ_ALU_CONST_CACHE_GS_11: 1844254885Sdumbbell case SQ_ALU_CONST_CACHE_GS_12: 1845254885Sdumbbell case SQ_ALU_CONST_CACHE_GS_13: 1846254885Sdumbbell case SQ_ALU_CONST_CACHE_GS_14: 1847254885Sdumbbell case SQ_ALU_CONST_CACHE_GS_15: 1848254885Sdumbbell case SQ_ALU_CONST_CACHE_PS_0: 1849254885Sdumbbell case SQ_ALU_CONST_CACHE_PS_1: 1850254885Sdumbbell case SQ_ALU_CONST_CACHE_PS_2: 1851254885Sdumbbell case SQ_ALU_CONST_CACHE_PS_3: 1852254885Sdumbbell case SQ_ALU_CONST_CACHE_PS_4: 1853254885Sdumbbell case SQ_ALU_CONST_CACHE_PS_5: 1854254885Sdumbbell case SQ_ALU_CONST_CACHE_PS_6: 1855254885Sdumbbell case SQ_ALU_CONST_CACHE_PS_7: 1856254885Sdumbbell case SQ_ALU_CONST_CACHE_PS_8: 1857254885Sdumbbell case SQ_ALU_CONST_CACHE_PS_9: 1858254885Sdumbbell case SQ_ALU_CONST_CACHE_PS_10: 1859254885Sdumbbell case SQ_ALU_CONST_CACHE_PS_11: 1860254885Sdumbbell case SQ_ALU_CONST_CACHE_PS_12: 1861254885Sdumbbell case SQ_ALU_CONST_CACHE_PS_13: 1862254885Sdumbbell case SQ_ALU_CONST_CACHE_PS_14: 1863254885Sdumbbell case SQ_ALU_CONST_CACHE_PS_15: 1864254885Sdumbbell case SQ_ALU_CONST_CACHE_VS_0: 1865254885Sdumbbell case SQ_ALU_CONST_CACHE_VS_1: 1866254885Sdumbbell case SQ_ALU_CONST_CACHE_VS_2: 1867254885Sdumbbell case SQ_ALU_CONST_CACHE_VS_3: 1868254885Sdumbbell case SQ_ALU_CONST_CACHE_VS_4: 1869254885Sdumbbell case SQ_ALU_CONST_CACHE_VS_5: 1870254885Sdumbbell case SQ_ALU_CONST_CACHE_VS_6: 1871254885Sdumbbell case SQ_ALU_CONST_CACHE_VS_7: 1872254885Sdumbbell case SQ_ALU_CONST_CACHE_VS_8: 1873254885Sdumbbell case SQ_ALU_CONST_CACHE_VS_9: 1874254885Sdumbbell case SQ_ALU_CONST_CACHE_VS_10: 1875254885Sdumbbell case SQ_ALU_CONST_CACHE_VS_11: 1876254885Sdumbbell case SQ_ALU_CONST_CACHE_VS_12: 1877254885Sdumbbell case SQ_ALU_CONST_CACHE_VS_13: 1878254885Sdumbbell case SQ_ALU_CONST_CACHE_VS_14: 1879254885Sdumbbell case SQ_ALU_CONST_CACHE_VS_15: 1880254885Sdumbbell case SQ_ALU_CONST_CACHE_HS_0: 1881254885Sdumbbell case SQ_ALU_CONST_CACHE_HS_1: 1882254885Sdumbbell case SQ_ALU_CONST_CACHE_HS_2: 1883254885Sdumbbell case SQ_ALU_CONST_CACHE_HS_3: 1884254885Sdumbbell case SQ_ALU_CONST_CACHE_HS_4: 1885254885Sdumbbell case SQ_ALU_CONST_CACHE_HS_5: 1886254885Sdumbbell case SQ_ALU_CONST_CACHE_HS_6: 1887254885Sdumbbell case SQ_ALU_CONST_CACHE_HS_7: 1888254885Sdumbbell case SQ_ALU_CONST_CACHE_HS_8: 1889254885Sdumbbell case SQ_ALU_CONST_CACHE_HS_9: 1890254885Sdumbbell case SQ_ALU_CONST_CACHE_HS_10: 1891254885Sdumbbell case SQ_ALU_CONST_CACHE_HS_11: 1892254885Sdumbbell case SQ_ALU_CONST_CACHE_HS_12: 1893254885Sdumbbell case SQ_ALU_CONST_CACHE_HS_13: 1894254885Sdumbbell case SQ_ALU_CONST_CACHE_HS_14: 1895254885Sdumbbell case SQ_ALU_CONST_CACHE_HS_15: 1896254885Sdumbbell case SQ_ALU_CONST_CACHE_LS_0: 1897254885Sdumbbell case SQ_ALU_CONST_CACHE_LS_1: 1898254885Sdumbbell case SQ_ALU_CONST_CACHE_LS_2: 1899254885Sdumbbell case SQ_ALU_CONST_CACHE_LS_3: 1900254885Sdumbbell case SQ_ALU_CONST_CACHE_LS_4: 1901254885Sdumbbell case SQ_ALU_CONST_CACHE_LS_5: 1902254885Sdumbbell case SQ_ALU_CONST_CACHE_LS_6: 1903254885Sdumbbell case SQ_ALU_CONST_CACHE_LS_7: 1904254885Sdumbbell case SQ_ALU_CONST_CACHE_LS_8: 1905254885Sdumbbell case SQ_ALU_CONST_CACHE_LS_9: 1906254885Sdumbbell case SQ_ALU_CONST_CACHE_LS_10: 1907254885Sdumbbell case SQ_ALU_CONST_CACHE_LS_11: 1908254885Sdumbbell case SQ_ALU_CONST_CACHE_LS_12: 1909254885Sdumbbell case SQ_ALU_CONST_CACHE_LS_13: 1910254885Sdumbbell case SQ_ALU_CONST_CACHE_LS_14: 1911254885Sdumbbell case SQ_ALU_CONST_CACHE_LS_15: 1912254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1913254885Sdumbbell if (r) { 1914254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1915254885Sdumbbell "0x%04X\n", reg); 1916254885Sdumbbell return -EINVAL; 1917254885Sdumbbell } 1918254885Sdumbbell ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 1919254885Sdumbbell break; 1920254885Sdumbbell case SX_MEMORY_EXPORT_BASE: 1921254885Sdumbbell if (p->rdev->family >= CHIP_CAYMAN) { 1922254885Sdumbbell dev_warn(p->dev, "bad SET_CONFIG_REG " 1923254885Sdumbbell "0x%04X\n", reg); 1924254885Sdumbbell return -EINVAL; 1925254885Sdumbbell } 1926254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1927254885Sdumbbell if (r) { 1928254885Sdumbbell dev_warn(p->dev, "bad SET_CONFIG_REG " 1929254885Sdumbbell "0x%04X\n", reg); 1930254885Sdumbbell return -EINVAL; 1931254885Sdumbbell } 1932254885Sdumbbell ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 1933254885Sdumbbell break; 1934254885Sdumbbell case CAYMAN_SX_SCATTER_EXPORT_BASE: 1935254885Sdumbbell if (p->rdev->family < CHIP_CAYMAN) { 1936254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1937254885Sdumbbell "0x%04X\n", reg); 1938254885Sdumbbell return -EINVAL; 1939254885Sdumbbell } 1940254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 1941254885Sdumbbell if (r) { 1942254885Sdumbbell dev_warn(p->dev, "bad SET_CONTEXT_REG " 1943254885Sdumbbell "0x%04X\n", reg); 1944254885Sdumbbell return -EINVAL; 1945254885Sdumbbell } 1946254885Sdumbbell ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 1947254885Sdumbbell break; 1948254885Sdumbbell case SX_MISC: 1949254885Sdumbbell track->sx_misc_kill_all_prims = (radeon_get_ib_value(p, idx) & 0x1) != 0; 1950254885Sdumbbell break; 1951254885Sdumbbell default: 1952254885Sdumbbell dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); 1953254885Sdumbbell return -EINVAL; 1954254885Sdumbbell } 1955254885Sdumbbell return 0; 1956254885Sdumbbell} 1957254885Sdumbbell 1958254885Sdumbbellstatic bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) 1959254885Sdumbbell{ 1960254885Sdumbbell u32 last_reg, m, i; 1961254885Sdumbbell 1962254885Sdumbbell if (p->rdev->family >= CHIP_CAYMAN) 1963254885Sdumbbell last_reg = DRM_ARRAY_SIZE(cayman_reg_safe_bm); 1964254885Sdumbbell else 1965254885Sdumbbell last_reg = DRM_ARRAY_SIZE(evergreen_reg_safe_bm); 1966254885Sdumbbell 1967254885Sdumbbell i = (reg >> 7); 1968254885Sdumbbell if (i >= last_reg) { 1969254885Sdumbbell dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); 1970254885Sdumbbell return false; 1971254885Sdumbbell } 1972254885Sdumbbell m = 1 << ((reg >> 2) & 31); 1973254885Sdumbbell if (p->rdev->family >= CHIP_CAYMAN) { 1974254885Sdumbbell if (!(cayman_reg_safe_bm[i] & m)) 1975254885Sdumbbell return true; 1976254885Sdumbbell } else { 1977254885Sdumbbell if (!(evergreen_reg_safe_bm[i] & m)) 1978254885Sdumbbell return true; 1979254885Sdumbbell } 1980254885Sdumbbell dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); 1981254885Sdumbbell return false; 1982254885Sdumbbell} 1983254885Sdumbbell 1984254885Sdumbbellstatic int evergreen_packet3_check(struct radeon_cs_parser *p, 1985254885Sdumbbell struct radeon_cs_packet *pkt) 1986254885Sdumbbell{ 1987254885Sdumbbell struct radeon_cs_reloc *reloc; 1988254885Sdumbbell struct evergreen_cs_track *track; 1989254885Sdumbbell volatile u32 *ib; 1990254885Sdumbbell unsigned idx; 1991254885Sdumbbell unsigned i; 1992254885Sdumbbell unsigned start_reg, end_reg, reg; 1993254885Sdumbbell int r; 1994254885Sdumbbell u32 idx_value; 1995254885Sdumbbell 1996254885Sdumbbell track = (struct evergreen_cs_track *)p->track; 1997254885Sdumbbell ib = p->ib.ptr; 1998254885Sdumbbell idx = pkt->idx + 1; 1999254885Sdumbbell idx_value = radeon_get_ib_value(p, idx); 2000254885Sdumbbell 2001254885Sdumbbell switch (pkt->opcode) { 2002254885Sdumbbell case PACKET3_SET_PREDICATION: 2003254885Sdumbbell { 2004254885Sdumbbell int pred_op; 2005254885Sdumbbell int tmp; 2006254885Sdumbbell uint64_t offset; 2007254885Sdumbbell 2008254885Sdumbbell if (pkt->count != 1) { 2009254885Sdumbbell DRM_ERROR("bad SET PREDICATION\n"); 2010254885Sdumbbell return -EINVAL; 2011254885Sdumbbell } 2012254885Sdumbbell 2013254885Sdumbbell tmp = radeon_get_ib_value(p, idx + 1); 2014254885Sdumbbell pred_op = (tmp >> 16) & 0x7; 2015254885Sdumbbell 2016254885Sdumbbell /* for the clear predicate operation */ 2017254885Sdumbbell if (pred_op == 0) 2018254885Sdumbbell return 0; 2019254885Sdumbbell 2020254885Sdumbbell if (pred_op > 2) { 2021254885Sdumbbell DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op); 2022254885Sdumbbell return -EINVAL; 2023254885Sdumbbell } 2024254885Sdumbbell 2025254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2026254885Sdumbbell if (r) { 2027254885Sdumbbell DRM_ERROR("bad SET PREDICATION\n"); 2028254885Sdumbbell return -EINVAL; 2029254885Sdumbbell } 2030254885Sdumbbell 2031254885Sdumbbell offset = reloc->lobj.gpu_offset + 2032254885Sdumbbell (idx_value & 0xfffffff0) + 2033254885Sdumbbell ((u64)(tmp & 0xff) << 32); 2034254885Sdumbbell 2035254885Sdumbbell ib[idx + 0] = offset; 2036254885Sdumbbell ib[idx + 1] = (tmp & 0xffffff00) | (upper_32_bits(offset) & 0xff); 2037254885Sdumbbell } 2038254885Sdumbbell break; 2039254885Sdumbbell case PACKET3_CONTEXT_CONTROL: 2040254885Sdumbbell if (pkt->count != 1) { 2041254885Sdumbbell DRM_ERROR("bad CONTEXT_CONTROL\n"); 2042254885Sdumbbell return -EINVAL; 2043254885Sdumbbell } 2044254885Sdumbbell break; 2045254885Sdumbbell case PACKET3_INDEX_TYPE: 2046254885Sdumbbell case PACKET3_NUM_INSTANCES: 2047254885Sdumbbell case PACKET3_CLEAR_STATE: 2048254885Sdumbbell if (pkt->count) { 2049254885Sdumbbell DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n"); 2050254885Sdumbbell return -EINVAL; 2051254885Sdumbbell } 2052254885Sdumbbell break; 2053254885Sdumbbell case CAYMAN_PACKET3_DEALLOC_STATE: 2054254885Sdumbbell if (p->rdev->family < CHIP_CAYMAN) { 2055254885Sdumbbell DRM_ERROR("bad PACKET3_DEALLOC_STATE\n"); 2056254885Sdumbbell return -EINVAL; 2057254885Sdumbbell } 2058254885Sdumbbell if (pkt->count) { 2059254885Sdumbbell DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n"); 2060254885Sdumbbell return -EINVAL; 2061254885Sdumbbell } 2062254885Sdumbbell break; 2063254885Sdumbbell case PACKET3_INDEX_BASE: 2064254885Sdumbbell { 2065254885Sdumbbell uint64_t offset; 2066254885Sdumbbell 2067254885Sdumbbell if (pkt->count != 1) { 2068254885Sdumbbell DRM_ERROR("bad INDEX_BASE\n"); 2069254885Sdumbbell return -EINVAL; 2070254885Sdumbbell } 2071254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2072254885Sdumbbell if (r) { 2073254885Sdumbbell DRM_ERROR("bad INDEX_BASE\n"); 2074254885Sdumbbell return -EINVAL; 2075254885Sdumbbell } 2076254885Sdumbbell 2077254885Sdumbbell offset = reloc->lobj.gpu_offset + 2078254885Sdumbbell idx_value + 2079254885Sdumbbell ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); 2080254885Sdumbbell 2081254885Sdumbbell ib[idx+0] = offset; 2082254885Sdumbbell ib[idx+1] = upper_32_bits(offset) & 0xff; 2083254885Sdumbbell 2084254885Sdumbbell r = evergreen_cs_track_check(p); 2085254885Sdumbbell if (r) { 2086254885Sdumbbell dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 2087254885Sdumbbell return r; 2088254885Sdumbbell } 2089254885Sdumbbell break; 2090254885Sdumbbell } 2091254885Sdumbbell case PACKET3_DRAW_INDEX: 2092254885Sdumbbell { 2093254885Sdumbbell uint64_t offset; 2094254885Sdumbbell if (pkt->count != 3) { 2095254885Sdumbbell DRM_ERROR("bad DRAW_INDEX\n"); 2096254885Sdumbbell return -EINVAL; 2097254885Sdumbbell } 2098254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2099254885Sdumbbell if (r) { 2100254885Sdumbbell DRM_ERROR("bad DRAW_INDEX\n"); 2101254885Sdumbbell return -EINVAL; 2102254885Sdumbbell } 2103254885Sdumbbell 2104254885Sdumbbell offset = reloc->lobj.gpu_offset + 2105254885Sdumbbell idx_value + 2106254885Sdumbbell ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); 2107254885Sdumbbell 2108254885Sdumbbell ib[idx+0] = offset; 2109254885Sdumbbell ib[idx+1] = upper_32_bits(offset) & 0xff; 2110254885Sdumbbell 2111254885Sdumbbell r = evergreen_cs_track_check(p); 2112254885Sdumbbell if (r) { 2113254885Sdumbbell dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 2114254885Sdumbbell return r; 2115254885Sdumbbell } 2116254885Sdumbbell break; 2117254885Sdumbbell } 2118254885Sdumbbell case PACKET3_DRAW_INDEX_2: 2119254885Sdumbbell { 2120254885Sdumbbell uint64_t offset; 2121254885Sdumbbell 2122254885Sdumbbell if (pkt->count != 4) { 2123254885Sdumbbell DRM_ERROR("bad DRAW_INDEX_2\n"); 2124254885Sdumbbell return -EINVAL; 2125254885Sdumbbell } 2126254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2127254885Sdumbbell if (r) { 2128254885Sdumbbell DRM_ERROR("bad DRAW_INDEX_2\n"); 2129254885Sdumbbell return -EINVAL; 2130254885Sdumbbell } 2131254885Sdumbbell 2132254885Sdumbbell offset = reloc->lobj.gpu_offset + 2133254885Sdumbbell radeon_get_ib_value(p, idx+1) + 2134254885Sdumbbell ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); 2135254885Sdumbbell 2136254885Sdumbbell ib[idx+1] = offset; 2137254885Sdumbbell ib[idx+2] = upper_32_bits(offset) & 0xff; 2138254885Sdumbbell 2139254885Sdumbbell r = evergreen_cs_track_check(p); 2140254885Sdumbbell if (r) { 2141254885Sdumbbell dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 2142254885Sdumbbell return r; 2143254885Sdumbbell } 2144254885Sdumbbell break; 2145254885Sdumbbell } 2146254885Sdumbbell case PACKET3_DRAW_INDEX_AUTO: 2147254885Sdumbbell if (pkt->count != 1) { 2148254885Sdumbbell DRM_ERROR("bad DRAW_INDEX_AUTO\n"); 2149254885Sdumbbell return -EINVAL; 2150254885Sdumbbell } 2151254885Sdumbbell r = evergreen_cs_track_check(p); 2152254885Sdumbbell if (r) { 2153254885Sdumbbell dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx); 2154254885Sdumbbell return r; 2155254885Sdumbbell } 2156254885Sdumbbell break; 2157254885Sdumbbell case PACKET3_DRAW_INDEX_MULTI_AUTO: 2158254885Sdumbbell if (pkt->count != 2) { 2159254885Sdumbbell DRM_ERROR("bad DRAW_INDEX_MULTI_AUTO\n"); 2160254885Sdumbbell return -EINVAL; 2161254885Sdumbbell } 2162254885Sdumbbell r = evergreen_cs_track_check(p); 2163254885Sdumbbell if (r) { 2164254885Sdumbbell dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx); 2165254885Sdumbbell return r; 2166254885Sdumbbell } 2167254885Sdumbbell break; 2168254885Sdumbbell case PACKET3_DRAW_INDEX_IMMD: 2169254885Sdumbbell if (pkt->count < 2) { 2170254885Sdumbbell DRM_ERROR("bad DRAW_INDEX_IMMD\n"); 2171254885Sdumbbell return -EINVAL; 2172254885Sdumbbell } 2173254885Sdumbbell r = evergreen_cs_track_check(p); 2174254885Sdumbbell if (r) { 2175254885Sdumbbell dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 2176254885Sdumbbell return r; 2177254885Sdumbbell } 2178254885Sdumbbell break; 2179254885Sdumbbell case PACKET3_DRAW_INDEX_OFFSET: 2180254885Sdumbbell if (pkt->count != 2) { 2181254885Sdumbbell DRM_ERROR("bad DRAW_INDEX_OFFSET\n"); 2182254885Sdumbbell return -EINVAL; 2183254885Sdumbbell } 2184254885Sdumbbell r = evergreen_cs_track_check(p); 2185254885Sdumbbell if (r) { 2186254885Sdumbbell dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 2187254885Sdumbbell return r; 2188254885Sdumbbell } 2189254885Sdumbbell break; 2190254885Sdumbbell case PACKET3_DRAW_INDEX_OFFSET_2: 2191254885Sdumbbell if (pkt->count != 3) { 2192254885Sdumbbell DRM_ERROR("bad DRAW_INDEX_OFFSET_2\n"); 2193254885Sdumbbell return -EINVAL; 2194254885Sdumbbell } 2195254885Sdumbbell r = evergreen_cs_track_check(p); 2196254885Sdumbbell if (r) { 2197254885Sdumbbell dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 2198254885Sdumbbell return r; 2199254885Sdumbbell } 2200254885Sdumbbell break; 2201254885Sdumbbell case PACKET3_DISPATCH_DIRECT: 2202254885Sdumbbell if (pkt->count != 3) { 2203254885Sdumbbell DRM_ERROR("bad DISPATCH_DIRECT\n"); 2204254885Sdumbbell return -EINVAL; 2205254885Sdumbbell } 2206254885Sdumbbell r = evergreen_cs_track_check(p); 2207254885Sdumbbell if (r) { 2208254885Sdumbbell dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx); 2209254885Sdumbbell return r; 2210254885Sdumbbell } 2211254885Sdumbbell break; 2212254885Sdumbbell case PACKET3_DISPATCH_INDIRECT: 2213254885Sdumbbell if (pkt->count != 1) { 2214254885Sdumbbell DRM_ERROR("bad DISPATCH_INDIRECT\n"); 2215254885Sdumbbell return -EINVAL; 2216254885Sdumbbell } 2217254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2218254885Sdumbbell if (r) { 2219254885Sdumbbell DRM_ERROR("bad DISPATCH_INDIRECT\n"); 2220254885Sdumbbell return -EINVAL; 2221254885Sdumbbell } 2222254885Sdumbbell ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); 2223254885Sdumbbell r = evergreen_cs_track_check(p); 2224254885Sdumbbell if (r) { 2225254885Sdumbbell dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 2226254885Sdumbbell return r; 2227254885Sdumbbell } 2228254885Sdumbbell break; 2229254885Sdumbbell case PACKET3_WAIT_REG_MEM: 2230254885Sdumbbell if (pkt->count != 5) { 2231254885Sdumbbell DRM_ERROR("bad WAIT_REG_MEM\n"); 2232254885Sdumbbell return -EINVAL; 2233254885Sdumbbell } 2234254885Sdumbbell /* bit 4 is reg (0) or mem (1) */ 2235254885Sdumbbell if (idx_value & 0x10) { 2236254885Sdumbbell uint64_t offset; 2237254885Sdumbbell 2238254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2239254885Sdumbbell if (r) { 2240254885Sdumbbell DRM_ERROR("bad WAIT_REG_MEM\n"); 2241254885Sdumbbell return -EINVAL; 2242254885Sdumbbell } 2243254885Sdumbbell 2244254885Sdumbbell offset = reloc->lobj.gpu_offset + 2245254885Sdumbbell (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + 2246254885Sdumbbell ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); 2247254885Sdumbbell 2248254885Sdumbbell ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffffc); 2249254885Sdumbbell ib[idx+2] = upper_32_bits(offset) & 0xff; 2250254885Sdumbbell } 2251254885Sdumbbell break; 2252254885Sdumbbell case PACKET3_CP_DMA: 2253254885Sdumbbell { 2254254885Sdumbbell u32 command, size, info; 2255254885Sdumbbell u64 offset, tmp; 2256254885Sdumbbell if (pkt->count != 4) { 2257254885Sdumbbell DRM_ERROR("bad CP DMA\n"); 2258254885Sdumbbell return -EINVAL; 2259254885Sdumbbell } 2260254885Sdumbbell command = radeon_get_ib_value(p, idx+4); 2261254885Sdumbbell size = command & 0x1fffff; 2262254885Sdumbbell info = radeon_get_ib_value(p, idx+1); 2263254885Sdumbbell if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */ 2264254885Sdumbbell (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */ 2265254885Sdumbbell ((((info & 0x00300000) >> 20) == 0) && 2266254885Sdumbbell (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */ 2267254885Sdumbbell ((((info & 0x60000000) >> 29) == 0) && 2268254885Sdumbbell (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */ 2269254885Sdumbbell /* non mem to mem copies requires dw aligned count */ 2270254885Sdumbbell if (size % 4) { 2271254885Sdumbbell DRM_ERROR("CP DMA command requires dw count alignment\n"); 2272254885Sdumbbell return -EINVAL; 2273254885Sdumbbell } 2274254885Sdumbbell } 2275254885Sdumbbell if (command & PACKET3_CP_DMA_CMD_SAS) { 2276254885Sdumbbell /* src address space is register */ 2277254885Sdumbbell /* GDS is ok */ 2278254885Sdumbbell if (((info & 0x60000000) >> 29) != 1) { 2279254885Sdumbbell DRM_ERROR("CP DMA SAS not supported\n"); 2280254885Sdumbbell return -EINVAL; 2281254885Sdumbbell } 2282254885Sdumbbell } else { 2283254885Sdumbbell if (command & PACKET3_CP_DMA_CMD_SAIC) { 2284254885Sdumbbell DRM_ERROR("CP DMA SAIC only supported for registers\n"); 2285254885Sdumbbell return -EINVAL; 2286254885Sdumbbell } 2287254885Sdumbbell /* src address space is memory */ 2288254885Sdumbbell if (((info & 0x60000000) >> 29) == 0) { 2289254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2290254885Sdumbbell if (r) { 2291254885Sdumbbell DRM_ERROR("bad CP DMA SRC\n"); 2292254885Sdumbbell return -EINVAL; 2293254885Sdumbbell } 2294254885Sdumbbell 2295254885Sdumbbell tmp = radeon_get_ib_value(p, idx) + 2296254885Sdumbbell ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); 2297254885Sdumbbell 2298254885Sdumbbell offset = reloc->lobj.gpu_offset + tmp; 2299254885Sdumbbell 2300254885Sdumbbell if ((tmp + size) > radeon_bo_size(reloc->robj)) { 2301254885Sdumbbell dev_warn(p->dev, "CP DMA src buffer too small (%ju %lu)\n", 2302254885Sdumbbell (uintmax_t)tmp + size, radeon_bo_size(reloc->robj)); 2303254885Sdumbbell return -EINVAL; 2304254885Sdumbbell } 2305254885Sdumbbell 2306254885Sdumbbell ib[idx] = offset; 2307254885Sdumbbell ib[idx+1] = (ib[idx+1] & 0xffffff00) | (upper_32_bits(offset) & 0xff); 2308254885Sdumbbell } else if (((info & 0x60000000) >> 29) != 2) { 2309254885Sdumbbell DRM_ERROR("bad CP DMA SRC_SEL\n"); 2310254885Sdumbbell return -EINVAL; 2311254885Sdumbbell } 2312254885Sdumbbell } 2313254885Sdumbbell if (command & PACKET3_CP_DMA_CMD_DAS) { 2314254885Sdumbbell /* dst address space is register */ 2315254885Sdumbbell /* GDS is ok */ 2316254885Sdumbbell if (((info & 0x00300000) >> 20) != 1) { 2317254885Sdumbbell DRM_ERROR("CP DMA DAS not supported\n"); 2318254885Sdumbbell return -EINVAL; 2319254885Sdumbbell } 2320254885Sdumbbell } else { 2321254885Sdumbbell /* dst address space is memory */ 2322254885Sdumbbell if (command & PACKET3_CP_DMA_CMD_DAIC) { 2323254885Sdumbbell DRM_ERROR("CP DMA DAIC only supported for registers\n"); 2324254885Sdumbbell return -EINVAL; 2325254885Sdumbbell } 2326254885Sdumbbell if (((info & 0x00300000) >> 20) == 0) { 2327254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2328254885Sdumbbell if (r) { 2329254885Sdumbbell DRM_ERROR("bad CP DMA DST\n"); 2330254885Sdumbbell return -EINVAL; 2331254885Sdumbbell } 2332254885Sdumbbell 2333254885Sdumbbell tmp = radeon_get_ib_value(p, idx+2) + 2334254885Sdumbbell ((u64)(radeon_get_ib_value(p, idx+3) & 0xff) << 32); 2335254885Sdumbbell 2336254885Sdumbbell offset = reloc->lobj.gpu_offset + tmp; 2337254885Sdumbbell 2338254885Sdumbbell if ((tmp + size) > radeon_bo_size(reloc->robj)) { 2339254885Sdumbbell dev_warn(p->dev, "CP DMA dst buffer too small (%ju %lu)\n", 2340254885Sdumbbell (uintmax_t)tmp + size, radeon_bo_size(reloc->robj)); 2341254885Sdumbbell return -EINVAL; 2342254885Sdumbbell } 2343254885Sdumbbell 2344254885Sdumbbell ib[idx+2] = offset; 2345254885Sdumbbell ib[idx+3] = upper_32_bits(offset) & 0xff; 2346254885Sdumbbell } else { 2347254885Sdumbbell DRM_ERROR("bad CP DMA DST_SEL\n"); 2348254885Sdumbbell return -EINVAL; 2349254885Sdumbbell } 2350254885Sdumbbell } 2351254885Sdumbbell break; 2352254885Sdumbbell } 2353254885Sdumbbell case PACKET3_SURFACE_SYNC: 2354254885Sdumbbell if (pkt->count != 3) { 2355254885Sdumbbell DRM_ERROR("bad SURFACE_SYNC\n"); 2356254885Sdumbbell return -EINVAL; 2357254885Sdumbbell } 2358254885Sdumbbell /* 0xffffffff/0x0 is flush all cache flag */ 2359254885Sdumbbell if (radeon_get_ib_value(p, idx + 1) != 0xffffffff || 2360254885Sdumbbell radeon_get_ib_value(p, idx + 2) != 0) { 2361254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2362254885Sdumbbell if (r) { 2363254885Sdumbbell DRM_ERROR("bad SURFACE_SYNC\n"); 2364254885Sdumbbell return -EINVAL; 2365254885Sdumbbell } 2366254885Sdumbbell ib[idx+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 2367254885Sdumbbell } 2368254885Sdumbbell break; 2369254885Sdumbbell case PACKET3_EVENT_WRITE: 2370254885Sdumbbell if (pkt->count != 2 && pkt->count != 0) { 2371254885Sdumbbell DRM_ERROR("bad EVENT_WRITE\n"); 2372254885Sdumbbell return -EINVAL; 2373254885Sdumbbell } 2374254885Sdumbbell if (pkt->count) { 2375254885Sdumbbell uint64_t offset; 2376254885Sdumbbell 2377254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2378254885Sdumbbell if (r) { 2379254885Sdumbbell DRM_ERROR("bad EVENT_WRITE\n"); 2380254885Sdumbbell return -EINVAL; 2381254885Sdumbbell } 2382254885Sdumbbell offset = reloc->lobj.gpu_offset + 2383254885Sdumbbell (radeon_get_ib_value(p, idx+1) & 0xfffffff8) + 2384254885Sdumbbell ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); 2385254885Sdumbbell 2386254885Sdumbbell ib[idx+1] = offset & 0xfffffff8; 2387254885Sdumbbell ib[idx+2] = upper_32_bits(offset) & 0xff; 2388254885Sdumbbell } 2389254885Sdumbbell break; 2390254885Sdumbbell case PACKET3_EVENT_WRITE_EOP: 2391254885Sdumbbell { 2392254885Sdumbbell uint64_t offset; 2393254885Sdumbbell 2394254885Sdumbbell if (pkt->count != 4) { 2395254885Sdumbbell DRM_ERROR("bad EVENT_WRITE_EOP\n"); 2396254885Sdumbbell return -EINVAL; 2397254885Sdumbbell } 2398254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2399254885Sdumbbell if (r) { 2400254885Sdumbbell DRM_ERROR("bad EVENT_WRITE_EOP\n"); 2401254885Sdumbbell return -EINVAL; 2402254885Sdumbbell } 2403254885Sdumbbell 2404254885Sdumbbell offset = reloc->lobj.gpu_offset + 2405254885Sdumbbell (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + 2406254885Sdumbbell ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); 2407254885Sdumbbell 2408254885Sdumbbell ib[idx+1] = offset & 0xfffffffc; 2409254885Sdumbbell ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff); 2410254885Sdumbbell break; 2411254885Sdumbbell } 2412254885Sdumbbell case PACKET3_EVENT_WRITE_EOS: 2413254885Sdumbbell { 2414254885Sdumbbell uint64_t offset; 2415254885Sdumbbell 2416254885Sdumbbell if (pkt->count != 3) { 2417254885Sdumbbell DRM_ERROR("bad EVENT_WRITE_EOS\n"); 2418254885Sdumbbell return -EINVAL; 2419254885Sdumbbell } 2420254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2421254885Sdumbbell if (r) { 2422254885Sdumbbell DRM_ERROR("bad EVENT_WRITE_EOS\n"); 2423254885Sdumbbell return -EINVAL; 2424254885Sdumbbell } 2425254885Sdumbbell 2426254885Sdumbbell offset = reloc->lobj.gpu_offset + 2427254885Sdumbbell (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + 2428254885Sdumbbell ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); 2429254885Sdumbbell 2430254885Sdumbbell ib[idx+1] = offset & 0xfffffffc; 2431254885Sdumbbell ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff); 2432254885Sdumbbell break; 2433254885Sdumbbell } 2434254885Sdumbbell case PACKET3_SET_CONFIG_REG: 2435254885Sdumbbell start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START; 2436254885Sdumbbell end_reg = 4 * pkt->count + start_reg - 4; 2437254885Sdumbbell if ((start_reg < PACKET3_SET_CONFIG_REG_START) || 2438254885Sdumbbell (start_reg >= PACKET3_SET_CONFIG_REG_END) || 2439254885Sdumbbell (end_reg >= PACKET3_SET_CONFIG_REG_END)) { 2440254885Sdumbbell DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n"); 2441254885Sdumbbell return -EINVAL; 2442254885Sdumbbell } 2443254885Sdumbbell for (i = 0; i < pkt->count; i++) { 2444254885Sdumbbell reg = start_reg + (4 * i); 2445254885Sdumbbell r = evergreen_cs_check_reg(p, reg, idx+1+i); 2446254885Sdumbbell if (r) 2447254885Sdumbbell return r; 2448254885Sdumbbell } 2449254885Sdumbbell break; 2450254885Sdumbbell case PACKET3_SET_CONTEXT_REG: 2451254885Sdumbbell start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_START; 2452254885Sdumbbell end_reg = 4 * pkt->count + start_reg - 4; 2453254885Sdumbbell if ((start_reg < PACKET3_SET_CONTEXT_REG_START) || 2454254885Sdumbbell (start_reg >= PACKET3_SET_CONTEXT_REG_END) || 2455254885Sdumbbell (end_reg >= PACKET3_SET_CONTEXT_REG_END)) { 2456254885Sdumbbell DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n"); 2457254885Sdumbbell return -EINVAL; 2458254885Sdumbbell } 2459254885Sdumbbell for (i = 0; i < pkt->count; i++) { 2460254885Sdumbbell reg = start_reg + (4 * i); 2461254885Sdumbbell r = evergreen_cs_check_reg(p, reg, idx+1+i); 2462254885Sdumbbell if (r) 2463254885Sdumbbell return r; 2464254885Sdumbbell } 2465254885Sdumbbell break; 2466254885Sdumbbell case PACKET3_SET_RESOURCE: 2467254885Sdumbbell if (pkt->count % 8) { 2468254885Sdumbbell DRM_ERROR("bad SET_RESOURCE\n"); 2469254885Sdumbbell return -EINVAL; 2470254885Sdumbbell } 2471254885Sdumbbell start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_START; 2472254885Sdumbbell end_reg = 4 * pkt->count + start_reg - 4; 2473254885Sdumbbell if ((start_reg < PACKET3_SET_RESOURCE_START) || 2474254885Sdumbbell (start_reg >= PACKET3_SET_RESOURCE_END) || 2475254885Sdumbbell (end_reg >= PACKET3_SET_RESOURCE_END)) { 2476254885Sdumbbell DRM_ERROR("bad SET_RESOURCE\n"); 2477254885Sdumbbell return -EINVAL; 2478254885Sdumbbell } 2479254885Sdumbbell for (i = 0; i < (pkt->count / 8); i++) { 2480254885Sdumbbell struct radeon_bo *texture, *mipmap; 2481254885Sdumbbell u32 toffset, moffset; 2482254885Sdumbbell u32 size, offset, mip_address, tex_dim; 2483254885Sdumbbell 2484254885Sdumbbell switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) { 2485254885Sdumbbell case SQ_TEX_VTX_VALID_TEXTURE: 2486254885Sdumbbell /* tex base */ 2487254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2488254885Sdumbbell if (r) { 2489254885Sdumbbell DRM_ERROR("bad SET_RESOURCE (tex)\n"); 2490254885Sdumbbell return -EINVAL; 2491254885Sdumbbell } 2492254885Sdumbbell if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 2493254885Sdumbbell ib[idx+1+(i*8)+1] |= 2494254885Sdumbbell TEX_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); 2495254885Sdumbbell if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { 2496254885Sdumbbell unsigned bankw, bankh, mtaspect, tile_split; 2497254885Sdumbbell 2498254885Sdumbbell evergreen_tiling_fields(reloc->lobj.tiling_flags, 2499254885Sdumbbell &bankw, &bankh, &mtaspect, 2500254885Sdumbbell &tile_split); 2501254885Sdumbbell ib[idx+1+(i*8)+6] |= TEX_TILE_SPLIT(tile_split); 2502254885Sdumbbell ib[idx+1+(i*8)+7] |= 2503254885Sdumbbell TEX_BANK_WIDTH(bankw) | 2504254885Sdumbbell TEX_BANK_HEIGHT(bankh) | 2505254885Sdumbbell MACRO_TILE_ASPECT(mtaspect) | 2506254885Sdumbbell TEX_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); 2507254885Sdumbbell } 2508254885Sdumbbell } 2509254885Sdumbbell texture = reloc->robj; 2510254885Sdumbbell toffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 2511254885Sdumbbell 2512254885Sdumbbell /* tex mip base */ 2513254885Sdumbbell tex_dim = ib[idx+1+(i*8)+0] & 0x7; 2514254885Sdumbbell mip_address = ib[idx+1+(i*8)+3]; 2515254885Sdumbbell 2516254885Sdumbbell if ((tex_dim == SQ_TEX_DIM_2D_MSAA || tex_dim == SQ_TEX_DIM_2D_ARRAY_MSAA) && 2517254885Sdumbbell !mip_address && 2518254885Sdumbbell !evergreen_cs_packet_next_is_pkt3_nop(p)) { 2519254885Sdumbbell /* MIP_ADDRESS should point to FMASK for an MSAA texture. 2520254885Sdumbbell * It should be 0 if FMASK is disabled. */ 2521254885Sdumbbell moffset = 0; 2522254885Sdumbbell mipmap = NULL; 2523254885Sdumbbell } else { 2524254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2525254885Sdumbbell if (r) { 2526254885Sdumbbell DRM_ERROR("bad SET_RESOURCE (tex)\n"); 2527254885Sdumbbell return -EINVAL; 2528254885Sdumbbell } 2529254885Sdumbbell moffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 2530254885Sdumbbell mipmap = reloc->robj; 2531254885Sdumbbell } 2532254885Sdumbbell 2533254885Sdumbbell r = evergreen_cs_track_validate_texture(p, texture, mipmap, idx+1+(i*8)); 2534254885Sdumbbell if (r) 2535254885Sdumbbell return r; 2536254885Sdumbbell ib[idx+1+(i*8)+2] += toffset; 2537254885Sdumbbell ib[idx+1+(i*8)+3] += moffset; 2538254885Sdumbbell break; 2539254885Sdumbbell case SQ_TEX_VTX_VALID_BUFFER: 2540254885Sdumbbell { 2541254885Sdumbbell uint64_t offset64; 2542254885Sdumbbell /* vtx base */ 2543254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2544254885Sdumbbell if (r) { 2545254885Sdumbbell DRM_ERROR("bad SET_RESOURCE (vtx)\n"); 2546254885Sdumbbell return -EINVAL; 2547254885Sdumbbell } 2548254885Sdumbbell offset = radeon_get_ib_value(p, idx+1+(i*8)+0); 2549254885Sdumbbell size = radeon_get_ib_value(p, idx+1+(i*8)+1); 2550254885Sdumbbell if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) { 2551254885Sdumbbell /* force size to size of the buffer */ 2552254885Sdumbbell dev_warn(p->dev, "vbo resource seems too big for the bo\n"); 2553254885Sdumbbell ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj) - offset; 2554254885Sdumbbell } 2555254885Sdumbbell 2556254885Sdumbbell offset64 = reloc->lobj.gpu_offset + offset; 2557254885Sdumbbell ib[idx+1+(i*8)+0] = offset64; 2558254885Sdumbbell ib[idx+1+(i*8)+2] = (ib[idx+1+(i*8)+2] & 0xffffff00) | 2559254885Sdumbbell (upper_32_bits(offset64) & 0xff); 2560254885Sdumbbell break; 2561254885Sdumbbell } 2562254885Sdumbbell case SQ_TEX_VTX_INVALID_TEXTURE: 2563254885Sdumbbell case SQ_TEX_VTX_INVALID_BUFFER: 2564254885Sdumbbell default: 2565254885Sdumbbell DRM_ERROR("bad SET_RESOURCE\n"); 2566254885Sdumbbell return -EINVAL; 2567254885Sdumbbell } 2568254885Sdumbbell } 2569254885Sdumbbell break; 2570254885Sdumbbell case PACKET3_SET_ALU_CONST: 2571254885Sdumbbell /* XXX fix me ALU const buffers only */ 2572254885Sdumbbell break; 2573254885Sdumbbell case PACKET3_SET_BOOL_CONST: 2574254885Sdumbbell start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_START; 2575254885Sdumbbell end_reg = 4 * pkt->count + start_reg - 4; 2576254885Sdumbbell if ((start_reg < PACKET3_SET_BOOL_CONST_START) || 2577254885Sdumbbell (start_reg >= PACKET3_SET_BOOL_CONST_END) || 2578254885Sdumbbell (end_reg >= PACKET3_SET_BOOL_CONST_END)) { 2579254885Sdumbbell DRM_ERROR("bad SET_BOOL_CONST\n"); 2580254885Sdumbbell return -EINVAL; 2581254885Sdumbbell } 2582254885Sdumbbell break; 2583254885Sdumbbell case PACKET3_SET_LOOP_CONST: 2584254885Sdumbbell start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_START; 2585254885Sdumbbell end_reg = 4 * pkt->count + start_reg - 4; 2586254885Sdumbbell if ((start_reg < PACKET3_SET_LOOP_CONST_START) || 2587254885Sdumbbell (start_reg >= PACKET3_SET_LOOP_CONST_END) || 2588254885Sdumbbell (end_reg >= PACKET3_SET_LOOP_CONST_END)) { 2589254885Sdumbbell DRM_ERROR("bad SET_LOOP_CONST\n"); 2590254885Sdumbbell return -EINVAL; 2591254885Sdumbbell } 2592254885Sdumbbell break; 2593254885Sdumbbell case PACKET3_SET_CTL_CONST: 2594254885Sdumbbell start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_START; 2595254885Sdumbbell end_reg = 4 * pkt->count + start_reg - 4; 2596254885Sdumbbell if ((start_reg < PACKET3_SET_CTL_CONST_START) || 2597254885Sdumbbell (start_reg >= PACKET3_SET_CTL_CONST_END) || 2598254885Sdumbbell (end_reg >= PACKET3_SET_CTL_CONST_END)) { 2599254885Sdumbbell DRM_ERROR("bad SET_CTL_CONST\n"); 2600254885Sdumbbell return -EINVAL; 2601254885Sdumbbell } 2602254885Sdumbbell break; 2603254885Sdumbbell case PACKET3_SET_SAMPLER: 2604254885Sdumbbell if (pkt->count % 3) { 2605254885Sdumbbell DRM_ERROR("bad SET_SAMPLER\n"); 2606254885Sdumbbell return -EINVAL; 2607254885Sdumbbell } 2608254885Sdumbbell start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_START; 2609254885Sdumbbell end_reg = 4 * pkt->count + start_reg - 4; 2610254885Sdumbbell if ((start_reg < PACKET3_SET_SAMPLER_START) || 2611254885Sdumbbell (start_reg >= PACKET3_SET_SAMPLER_END) || 2612254885Sdumbbell (end_reg >= PACKET3_SET_SAMPLER_END)) { 2613254885Sdumbbell DRM_ERROR("bad SET_SAMPLER\n"); 2614254885Sdumbbell return -EINVAL; 2615254885Sdumbbell } 2616254885Sdumbbell break; 2617254885Sdumbbell case PACKET3_STRMOUT_BUFFER_UPDATE: 2618254885Sdumbbell if (pkt->count != 4) { 2619254885Sdumbbell DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); 2620254885Sdumbbell return -EINVAL; 2621254885Sdumbbell } 2622254885Sdumbbell /* Updating memory at DST_ADDRESS. */ 2623254885Sdumbbell if (idx_value & 0x1) { 2624254885Sdumbbell u64 offset; 2625254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2626254885Sdumbbell if (r) { 2627254885Sdumbbell DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n"); 2628254885Sdumbbell return -EINVAL; 2629254885Sdumbbell } 2630254885Sdumbbell offset = radeon_get_ib_value(p, idx+1); 2631254885Sdumbbell offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; 2632254885Sdumbbell if ((offset + 4) > radeon_bo_size(reloc->robj)) { 2633254885Sdumbbell DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%jx, 0x%lx\n", 2634254885Sdumbbell (uintmax_t)offset + 4, radeon_bo_size(reloc->robj)); 2635254885Sdumbbell return -EINVAL; 2636254885Sdumbbell } 2637254885Sdumbbell offset += reloc->lobj.gpu_offset; 2638254885Sdumbbell ib[idx+1] = offset; 2639254885Sdumbbell ib[idx+2] = upper_32_bits(offset) & 0xff; 2640254885Sdumbbell } 2641254885Sdumbbell /* Reading data from SRC_ADDRESS. */ 2642254885Sdumbbell if (((idx_value >> 1) & 0x3) == 2) { 2643254885Sdumbbell u64 offset; 2644254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2645254885Sdumbbell if (r) { 2646254885Sdumbbell DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n"); 2647254885Sdumbbell return -EINVAL; 2648254885Sdumbbell } 2649254885Sdumbbell offset = radeon_get_ib_value(p, idx+3); 2650254885Sdumbbell offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; 2651254885Sdumbbell if ((offset + 4) > radeon_bo_size(reloc->robj)) { 2652254885Sdumbbell DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%jx, 0x%lx\n", 2653254885Sdumbbell (uintmax_t)offset + 4, radeon_bo_size(reloc->robj)); 2654254885Sdumbbell return -EINVAL; 2655254885Sdumbbell } 2656254885Sdumbbell offset += reloc->lobj.gpu_offset; 2657254885Sdumbbell ib[idx+3] = offset; 2658254885Sdumbbell ib[idx+4] = upper_32_bits(offset) & 0xff; 2659254885Sdumbbell } 2660254885Sdumbbell break; 2661254885Sdumbbell case PACKET3_MEM_WRITE: 2662254885Sdumbbell { 2663254885Sdumbbell u64 offset; 2664254885Sdumbbell 2665254885Sdumbbell if (pkt->count != 3) { 2666254885Sdumbbell DRM_ERROR("bad MEM_WRITE (invalid count)\n"); 2667254885Sdumbbell return -EINVAL; 2668254885Sdumbbell } 2669254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2670254885Sdumbbell if (r) { 2671254885Sdumbbell DRM_ERROR("bad MEM_WRITE (missing reloc)\n"); 2672254885Sdumbbell return -EINVAL; 2673254885Sdumbbell } 2674254885Sdumbbell offset = radeon_get_ib_value(p, idx+0); 2675254885Sdumbbell offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL; 2676254885Sdumbbell if (offset & 0x7) { 2677254885Sdumbbell DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n"); 2678254885Sdumbbell return -EINVAL; 2679254885Sdumbbell } 2680254885Sdumbbell if ((offset + 8) > radeon_bo_size(reloc->robj)) { 2681254885Sdumbbell DRM_ERROR("bad MEM_WRITE bo too small: 0x%jx, 0x%lx\n", 2682254885Sdumbbell (uintmax_t)offset + 8, radeon_bo_size(reloc->robj)); 2683254885Sdumbbell return -EINVAL; 2684254885Sdumbbell } 2685254885Sdumbbell offset += reloc->lobj.gpu_offset; 2686254885Sdumbbell ib[idx+0] = offset; 2687254885Sdumbbell ib[idx+1] = upper_32_bits(offset) & 0xff; 2688254885Sdumbbell break; 2689254885Sdumbbell } 2690254885Sdumbbell case PACKET3_COPY_DW: 2691254885Sdumbbell if (pkt->count != 4) { 2692254885Sdumbbell DRM_ERROR("bad COPY_DW (invalid count)\n"); 2693254885Sdumbbell return -EINVAL; 2694254885Sdumbbell } 2695254885Sdumbbell if (idx_value & 0x1) { 2696254885Sdumbbell u64 offset; 2697254885Sdumbbell /* SRC is memory. */ 2698254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2699254885Sdumbbell if (r) { 2700254885Sdumbbell DRM_ERROR("bad COPY_DW (missing src reloc)\n"); 2701254885Sdumbbell return -EINVAL; 2702254885Sdumbbell } 2703254885Sdumbbell offset = radeon_get_ib_value(p, idx+1); 2704254885Sdumbbell offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; 2705254885Sdumbbell if ((offset + 4) > radeon_bo_size(reloc->robj)) { 2706254885Sdumbbell DRM_ERROR("bad COPY_DW src bo too small: 0x%jx, 0x%lx\n", 2707254885Sdumbbell (uintmax_t)offset + 4, radeon_bo_size(reloc->robj)); 2708254885Sdumbbell return -EINVAL; 2709254885Sdumbbell } 2710254885Sdumbbell offset += reloc->lobj.gpu_offset; 2711254885Sdumbbell ib[idx+1] = offset; 2712254885Sdumbbell ib[idx+2] = upper_32_bits(offset) & 0xff; 2713254885Sdumbbell } else { 2714254885Sdumbbell /* SRC is a reg. */ 2715254885Sdumbbell reg = radeon_get_ib_value(p, idx+1) << 2; 2716254885Sdumbbell if (!evergreen_is_safe_reg(p, reg, idx+1)) 2717254885Sdumbbell return -EINVAL; 2718254885Sdumbbell } 2719254885Sdumbbell if (idx_value & 0x2) { 2720254885Sdumbbell u64 offset; 2721254885Sdumbbell /* DST is memory. */ 2722254885Sdumbbell r = evergreen_cs_packet_next_reloc(p, &reloc); 2723254885Sdumbbell if (r) { 2724254885Sdumbbell DRM_ERROR("bad COPY_DW (missing dst reloc)\n"); 2725254885Sdumbbell return -EINVAL; 2726254885Sdumbbell } 2727254885Sdumbbell offset = radeon_get_ib_value(p, idx+3); 2728254885Sdumbbell offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; 2729254885Sdumbbell if ((offset + 4) > radeon_bo_size(reloc->robj)) { 2730254885Sdumbbell DRM_ERROR("bad COPY_DW dst bo too small: 0x%jx, 0x%lx\n", 2731254885Sdumbbell (uintmax_t)offset + 4, radeon_bo_size(reloc->robj)); 2732254885Sdumbbell return -EINVAL; 2733254885Sdumbbell } 2734254885Sdumbbell offset += reloc->lobj.gpu_offset; 2735254885Sdumbbell ib[idx+3] = offset; 2736254885Sdumbbell ib[idx+4] = upper_32_bits(offset) & 0xff; 2737254885Sdumbbell } else { 2738254885Sdumbbell /* DST is a reg. */ 2739254885Sdumbbell reg = radeon_get_ib_value(p, idx+3) << 2; 2740254885Sdumbbell if (!evergreen_is_safe_reg(p, reg, idx+3)) 2741254885Sdumbbell return -EINVAL; 2742254885Sdumbbell } 2743254885Sdumbbell break; 2744254885Sdumbbell case PACKET3_NOP: 2745254885Sdumbbell break; 2746254885Sdumbbell default: 2747254885Sdumbbell DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode); 2748254885Sdumbbell return -EINVAL; 2749254885Sdumbbell } 2750254885Sdumbbell return 0; 2751254885Sdumbbell} 2752254885Sdumbbell 2753254885Sdumbbellint evergreen_cs_parse(struct radeon_cs_parser *p) 2754254885Sdumbbell{ 2755254885Sdumbbell struct radeon_cs_packet pkt; 2756254885Sdumbbell struct evergreen_cs_track *track; 2757254885Sdumbbell u32 tmp; 2758254885Sdumbbell int r; 2759254885Sdumbbell 2760254885Sdumbbell if (p->track == NULL) { 2761254885Sdumbbell /* initialize tracker, we are in kms */ 2762254885Sdumbbell track = malloc(sizeof(*track), DRM_MEM_DRIVER, M_ZERO | M_WAITOK); 2763254885Sdumbbell if (track == NULL) 2764254885Sdumbbell return -ENOMEM; 2765254885Sdumbbell evergreen_cs_track_init(track); 2766254885Sdumbbell if (p->rdev->family >= CHIP_CAYMAN) 2767254885Sdumbbell tmp = p->rdev->config.cayman.tile_config; 2768254885Sdumbbell else 2769254885Sdumbbell tmp = p->rdev->config.evergreen.tile_config; 2770254885Sdumbbell 2771254885Sdumbbell switch (tmp & 0xf) { 2772254885Sdumbbell case 0: 2773254885Sdumbbell track->npipes = 1; 2774254885Sdumbbell break; 2775254885Sdumbbell case 1: 2776254885Sdumbbell default: 2777254885Sdumbbell track->npipes = 2; 2778254885Sdumbbell break; 2779254885Sdumbbell case 2: 2780254885Sdumbbell track->npipes = 4; 2781254885Sdumbbell break; 2782254885Sdumbbell case 3: 2783254885Sdumbbell track->npipes = 8; 2784254885Sdumbbell break; 2785254885Sdumbbell } 2786254885Sdumbbell 2787254885Sdumbbell switch ((tmp & 0xf0) >> 4) { 2788254885Sdumbbell case 0: 2789254885Sdumbbell track->nbanks = 4; 2790254885Sdumbbell break; 2791254885Sdumbbell case 1: 2792254885Sdumbbell default: 2793254885Sdumbbell track->nbanks = 8; 2794254885Sdumbbell break; 2795254885Sdumbbell case 2: 2796254885Sdumbbell track->nbanks = 16; 2797254885Sdumbbell break; 2798254885Sdumbbell } 2799254885Sdumbbell 2800254885Sdumbbell switch ((tmp & 0xf00) >> 8) { 2801254885Sdumbbell case 0: 2802254885Sdumbbell track->group_size = 256; 2803254885Sdumbbell break; 2804254885Sdumbbell case 1: 2805254885Sdumbbell default: 2806254885Sdumbbell track->group_size = 512; 2807254885Sdumbbell break; 2808254885Sdumbbell } 2809254885Sdumbbell 2810254885Sdumbbell switch ((tmp & 0xf000) >> 12) { 2811254885Sdumbbell case 0: 2812254885Sdumbbell track->row_size = 1; 2813254885Sdumbbell break; 2814254885Sdumbbell case 1: 2815254885Sdumbbell default: 2816254885Sdumbbell track->row_size = 2; 2817254885Sdumbbell break; 2818254885Sdumbbell case 2: 2819254885Sdumbbell track->row_size = 4; 2820254885Sdumbbell break; 2821254885Sdumbbell } 2822254885Sdumbbell 2823254885Sdumbbell p->track = track; 2824254885Sdumbbell } 2825254885Sdumbbell do { 2826254885Sdumbbell r = evergreen_cs_packet_parse(p, &pkt, p->idx); 2827254885Sdumbbell if (r) { 2828254885Sdumbbell free(p->track, DRM_MEM_DRIVER); 2829254885Sdumbbell p->track = NULL; 2830254885Sdumbbell return r; 2831254885Sdumbbell } 2832254885Sdumbbell p->idx += pkt.count + 2; 2833254885Sdumbbell switch (pkt.type) { 2834254885Sdumbbell case PACKET_TYPE0: 2835254885Sdumbbell r = evergreen_cs_parse_packet0(p, &pkt); 2836254885Sdumbbell break; 2837254885Sdumbbell case PACKET_TYPE2: 2838254885Sdumbbell break; 2839254885Sdumbbell case PACKET_TYPE3: 2840254885Sdumbbell r = evergreen_packet3_check(p, &pkt); 2841254885Sdumbbell break; 2842254885Sdumbbell default: 2843254885Sdumbbell DRM_ERROR("Unknown packet type %d !\n", pkt.type); 2844254885Sdumbbell free(p->track, DRM_MEM_DRIVER); 2845254885Sdumbbell p->track = NULL; 2846254885Sdumbbell return -EINVAL; 2847254885Sdumbbell } 2848254885Sdumbbell if (r) { 2849254885Sdumbbell free(p->track, DRM_MEM_DRIVER); 2850254885Sdumbbell p->track = NULL; 2851254885Sdumbbell return r; 2852254885Sdumbbell } 2853254885Sdumbbell } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); 2854254885Sdumbbell#if 0 2855254885Sdumbbell for (r = 0; r < p->ib.length_dw; r++) { 2856254885Sdumbbell DRM_INFO("%05d 0x%08X\n", r, p->ib.ptr[r]); 2857254885Sdumbbell mdelay(1); 2858254885Sdumbbell } 2859254885Sdumbbell#endif 2860254885Sdumbbell free(p->track, DRM_MEM_DRIVER); 2861254885Sdumbbell p->track = NULL; 2862254885Sdumbbell return 0; 2863254885Sdumbbell} 2864254885Sdumbbell 2865254885Sdumbbell/* 2866254885Sdumbbell * DMA 2867254885Sdumbbell */ 2868254885Sdumbbell 2869254885Sdumbbell#define GET_DMA_CMD(h) (((h) & 0xf0000000) >> 28) 2870254885Sdumbbell#define GET_DMA_COUNT(h) ((h) & 0x000fffff) 2871254885Sdumbbell#define GET_DMA_T(h) (((h) & 0x00800000) >> 23) 2872254885Sdumbbell#define GET_DMA_NEW(h) (((h) & 0x04000000) >> 26) 2873254885Sdumbbell#define GET_DMA_MISC(h) (((h) & 0x0700000) >> 20) 2874254885Sdumbbell 2875254885Sdumbbell/** 2876254885Sdumbbell * evergreen_dma_cs_parse() - parse the DMA IB 2877254885Sdumbbell * @p: parser structure holding parsing context. 2878254885Sdumbbell * 2879254885Sdumbbell * Parses the DMA IB from the CS ioctl and updates 2880254885Sdumbbell * the GPU addresses based on the reloc information and 2881254885Sdumbbell * checks for errors. (Evergreen-Cayman) 2882254885Sdumbbell * Returns 0 for success and an error on failure. 2883254885Sdumbbell **/ 2884254885Sdumbbellint evergreen_dma_cs_parse(struct radeon_cs_parser *p) 2885254885Sdumbbell{ 2886254885Sdumbbell struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; 2887254885Sdumbbell struct radeon_cs_reloc *src_reloc, *dst_reloc, *dst2_reloc; 2888254885Sdumbbell u32 header, cmd, count, tiled, new_cmd, misc; 2889254885Sdumbbell volatile u32 *ib = p->ib.ptr; 2890254885Sdumbbell u32 idx, idx_value; 2891254885Sdumbbell u64 src_offset, dst_offset, dst2_offset; 2892254885Sdumbbell int r; 2893254885Sdumbbell 2894254885Sdumbbell do { 2895254885Sdumbbell if (p->idx >= ib_chunk->length_dw) { 2896254885Sdumbbell DRM_ERROR("Can not parse packet at %d after CS end %d !\n", 2897254885Sdumbbell p->idx, ib_chunk->length_dw); 2898254885Sdumbbell return -EINVAL; 2899254885Sdumbbell } 2900254885Sdumbbell idx = p->idx; 2901254885Sdumbbell header = radeon_get_ib_value(p, idx); 2902254885Sdumbbell cmd = GET_DMA_CMD(header); 2903254885Sdumbbell count = GET_DMA_COUNT(header); 2904254885Sdumbbell tiled = GET_DMA_T(header); 2905254885Sdumbbell new_cmd = GET_DMA_NEW(header); 2906254885Sdumbbell misc = GET_DMA_MISC(header); 2907254885Sdumbbell 2908254885Sdumbbell switch (cmd) { 2909254885Sdumbbell case DMA_PACKET_WRITE: 2910254885Sdumbbell r = r600_dma_cs_next_reloc(p, &dst_reloc); 2911254885Sdumbbell if (r) { 2912254885Sdumbbell DRM_ERROR("bad DMA_PACKET_WRITE\n"); 2913254885Sdumbbell return -EINVAL; 2914254885Sdumbbell } 2915254885Sdumbbell if (tiled) { 2916254885Sdumbbell dst_offset = radeon_get_ib_value(p, idx+1); 2917254885Sdumbbell dst_offset <<= 8; 2918254885Sdumbbell 2919254885Sdumbbell ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); 2920254885Sdumbbell p->idx += count + 7; 2921254885Sdumbbell } else { 2922254885Sdumbbell dst_offset = radeon_get_ib_value(p, idx+1); 2923254885Sdumbbell dst_offset |= ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; 2924254885Sdumbbell 2925254885Sdumbbell ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); 2926254885Sdumbbell ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; 2927254885Sdumbbell p->idx += count + 3; 2928254885Sdumbbell } 2929254885Sdumbbell if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 2930254885Sdumbbell dev_warn(p->dev, "DMA write buffer too small (%ju %lu)\n", 2931254885Sdumbbell (uintmax_t)dst_offset, radeon_bo_size(dst_reloc->robj)); 2932254885Sdumbbell return -EINVAL; 2933254885Sdumbbell } 2934254885Sdumbbell break; 2935254885Sdumbbell case DMA_PACKET_COPY: 2936254885Sdumbbell r = r600_dma_cs_next_reloc(p, &src_reloc); 2937254885Sdumbbell if (r) { 2938254885Sdumbbell DRM_ERROR("bad DMA_PACKET_COPY\n"); 2939254885Sdumbbell return -EINVAL; 2940254885Sdumbbell } 2941254885Sdumbbell r = r600_dma_cs_next_reloc(p, &dst_reloc); 2942254885Sdumbbell if (r) { 2943254885Sdumbbell DRM_ERROR("bad DMA_PACKET_COPY\n"); 2944254885Sdumbbell return -EINVAL; 2945254885Sdumbbell } 2946254885Sdumbbell if (tiled) { 2947254885Sdumbbell idx_value = radeon_get_ib_value(p, idx + 2); 2948254885Sdumbbell if (new_cmd) { 2949254885Sdumbbell switch (misc) { 2950254885Sdumbbell case 0: 2951254885Sdumbbell /* L2T, frame to fields */ 2952254885Sdumbbell if (idx_value & (1 << 31)) { 2953254885Sdumbbell DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n"); 2954254885Sdumbbell return -EINVAL; 2955254885Sdumbbell } 2956254885Sdumbbell r = r600_dma_cs_next_reloc(p, &dst2_reloc); 2957254885Sdumbbell if (r) { 2958254885Sdumbbell DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n"); 2959254885Sdumbbell return -EINVAL; 2960254885Sdumbbell } 2961254885Sdumbbell dst_offset = radeon_get_ib_value(p, idx+1); 2962254885Sdumbbell dst_offset <<= 8; 2963254885Sdumbbell dst2_offset = radeon_get_ib_value(p, idx+2); 2964254885Sdumbbell dst2_offset <<= 8; 2965254885Sdumbbell src_offset = radeon_get_ib_value(p, idx+8); 2966254885Sdumbbell src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32; 2967254885Sdumbbell if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 2968254885Sdumbbell dev_warn(p->dev, "DMA L2T, frame to fields src buffer too small (%ju %lu)\n", 2969254885Sdumbbell (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 2970254885Sdumbbell return -EINVAL; 2971254885Sdumbbell } 2972254885Sdumbbell if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 2973254885Sdumbbell dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%ju %lu)\n", 2974254885Sdumbbell (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 2975254885Sdumbbell return -EINVAL; 2976254885Sdumbbell } 2977254885Sdumbbell if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { 2978254885Sdumbbell dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%ju %lu)\n", 2979254885Sdumbbell (uintmax_t)dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); 2980254885Sdumbbell return -EINVAL; 2981254885Sdumbbell } 2982254885Sdumbbell ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); 2983254885Sdumbbell ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8); 2984254885Sdumbbell ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); 2985254885Sdumbbell ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; 2986254885Sdumbbell p->idx += 10; 2987254885Sdumbbell break; 2988254885Sdumbbell case 1: 2989254885Sdumbbell /* L2T, T2L partial */ 2990254885Sdumbbell if (p->family < CHIP_CAYMAN) { 2991254885Sdumbbell DRM_ERROR("L2T, T2L Partial is cayman only !\n"); 2992254885Sdumbbell return -EINVAL; 2993254885Sdumbbell } 2994254885Sdumbbell /* detile bit */ 2995254885Sdumbbell if (idx_value & (1 << 31)) { 2996254885Sdumbbell /* tiled src, linear dst */ 2997254885Sdumbbell ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); 2998254885Sdumbbell 2999254885Sdumbbell ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); 3000254885Sdumbbell ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; 3001254885Sdumbbell } else { 3002254885Sdumbbell /* linear src, tiled dst */ 3003254885Sdumbbell ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); 3004254885Sdumbbell ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; 3005254885Sdumbbell 3006254885Sdumbbell ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); 3007254885Sdumbbell } 3008254885Sdumbbell p->idx += 12; 3009254885Sdumbbell break; 3010254885Sdumbbell case 3: 3011254885Sdumbbell /* L2T, broadcast */ 3012254885Sdumbbell if (idx_value & (1 << 31)) { 3013254885Sdumbbell DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); 3014254885Sdumbbell return -EINVAL; 3015254885Sdumbbell } 3016254885Sdumbbell r = r600_dma_cs_next_reloc(p, &dst2_reloc); 3017254885Sdumbbell if (r) { 3018254885Sdumbbell DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); 3019254885Sdumbbell return -EINVAL; 3020254885Sdumbbell } 3021254885Sdumbbell dst_offset = radeon_get_ib_value(p, idx+1); 3022254885Sdumbbell dst_offset <<= 8; 3023254885Sdumbbell dst2_offset = radeon_get_ib_value(p, idx+2); 3024254885Sdumbbell dst2_offset <<= 8; 3025254885Sdumbbell src_offset = radeon_get_ib_value(p, idx+8); 3026254885Sdumbbell src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32; 3027254885Sdumbbell if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 3028254885Sdumbbell dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%ju %lu)\n", 3029254885Sdumbbell (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 3030254885Sdumbbell return -EINVAL; 3031254885Sdumbbell } 3032254885Sdumbbell if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 3033254885Sdumbbell dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%ju %lu)\n", 3034254885Sdumbbell (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 3035254885Sdumbbell return -EINVAL; 3036254885Sdumbbell } 3037254885Sdumbbell if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { 3038254885Sdumbbell dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%ju %lu)\n", 3039254885Sdumbbell (uintmax_t)dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); 3040254885Sdumbbell return -EINVAL; 3041254885Sdumbbell } 3042254885Sdumbbell ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); 3043254885Sdumbbell ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8); 3044254885Sdumbbell ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); 3045254885Sdumbbell ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; 3046254885Sdumbbell p->idx += 10; 3047254885Sdumbbell break; 3048254885Sdumbbell case 4: 3049254885Sdumbbell /* L2T, T2L */ 3050254885Sdumbbell /* detile bit */ 3051254885Sdumbbell if (idx_value & (1 << 31)) { 3052254885Sdumbbell /* tiled src, linear dst */ 3053254885Sdumbbell src_offset = radeon_get_ib_value(p, idx+1); 3054254885Sdumbbell src_offset <<= 8; 3055254885Sdumbbell ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); 3056254885Sdumbbell 3057254885Sdumbbell dst_offset = radeon_get_ib_value(p, idx+7); 3058254885Sdumbbell dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; 3059254885Sdumbbell ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); 3060254885Sdumbbell ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; 3061254885Sdumbbell } else { 3062254885Sdumbbell /* linear src, tiled dst */ 3063254885Sdumbbell src_offset = radeon_get_ib_value(p, idx+7); 3064254885Sdumbbell src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; 3065254885Sdumbbell ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); 3066254885Sdumbbell ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; 3067254885Sdumbbell 3068254885Sdumbbell dst_offset = radeon_get_ib_value(p, idx+1); 3069254885Sdumbbell dst_offset <<= 8; 3070254885Sdumbbell ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); 3071254885Sdumbbell } 3072254885Sdumbbell if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 3073254885Sdumbbell dev_warn(p->dev, "DMA L2T, T2L src buffer too small (%ju %lu)\n", 3074254885Sdumbbell (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 3075254885Sdumbbell return -EINVAL; 3076254885Sdumbbell } 3077254885Sdumbbell if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 3078254885Sdumbbell dev_warn(p->dev, "DMA L2T, T2L dst buffer too small (%ju %lu)\n", 3079254885Sdumbbell (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 3080254885Sdumbbell return -EINVAL; 3081254885Sdumbbell } 3082254885Sdumbbell p->idx += 9; 3083254885Sdumbbell break; 3084254885Sdumbbell case 5: 3085254885Sdumbbell /* T2T partial */ 3086254885Sdumbbell if (p->family < CHIP_CAYMAN) { 3087254885Sdumbbell DRM_ERROR("L2T, T2L Partial is cayman only !\n"); 3088254885Sdumbbell return -EINVAL; 3089254885Sdumbbell } 3090254885Sdumbbell ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); 3091254885Sdumbbell ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset >> 8); 3092254885Sdumbbell p->idx += 13; 3093254885Sdumbbell break; 3094254885Sdumbbell case 7: 3095254885Sdumbbell /* L2T, broadcast */ 3096254885Sdumbbell if (idx_value & (1 << 31)) { 3097254885Sdumbbell DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); 3098254885Sdumbbell return -EINVAL; 3099254885Sdumbbell } 3100254885Sdumbbell r = r600_dma_cs_next_reloc(p, &dst2_reloc); 3101254885Sdumbbell if (r) { 3102254885Sdumbbell DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); 3103254885Sdumbbell return -EINVAL; 3104254885Sdumbbell } 3105254885Sdumbbell dst_offset = radeon_get_ib_value(p, idx+1); 3106254885Sdumbbell dst_offset <<= 8; 3107254885Sdumbbell dst2_offset = radeon_get_ib_value(p, idx+2); 3108254885Sdumbbell dst2_offset <<= 8; 3109254885Sdumbbell src_offset = radeon_get_ib_value(p, idx+8); 3110254885Sdumbbell src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32; 3111254885Sdumbbell if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 3112254885Sdumbbell dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%ju %lu)\n", 3113254885Sdumbbell (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 3114254885Sdumbbell return -EINVAL; 3115254885Sdumbbell } 3116254885Sdumbbell if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 3117254885Sdumbbell dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%ju %lu)\n", 3118254885Sdumbbell (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 3119254885Sdumbbell return -EINVAL; 3120254885Sdumbbell } 3121254885Sdumbbell if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { 3122254885Sdumbbell dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%ju %lu)\n", 3123254885Sdumbbell (uintmax_t)dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); 3124254885Sdumbbell return -EINVAL; 3125254885Sdumbbell } 3126254885Sdumbbell ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); 3127254885Sdumbbell ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8); 3128254885Sdumbbell ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); 3129254885Sdumbbell ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; 3130254885Sdumbbell p->idx += 10; 3131254885Sdumbbell break; 3132254885Sdumbbell default: 3133254885Sdumbbell DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); 3134254885Sdumbbell return -EINVAL; 3135254885Sdumbbell } 3136254885Sdumbbell } else { 3137254885Sdumbbell switch (misc) { 3138254885Sdumbbell case 0: 3139254885Sdumbbell /* detile bit */ 3140254885Sdumbbell if (idx_value & (1 << 31)) { 3141254885Sdumbbell /* tiled src, linear dst */ 3142254885Sdumbbell src_offset = radeon_get_ib_value(p, idx+1); 3143254885Sdumbbell src_offset <<= 8; 3144254885Sdumbbell ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); 3145254885Sdumbbell 3146254885Sdumbbell dst_offset = radeon_get_ib_value(p, idx+7); 3147254885Sdumbbell dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; 3148254885Sdumbbell ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); 3149254885Sdumbbell ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; 3150254885Sdumbbell } else { 3151254885Sdumbbell /* linear src, tiled dst */ 3152254885Sdumbbell src_offset = radeon_get_ib_value(p, idx+7); 3153254885Sdumbbell src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; 3154254885Sdumbbell ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); 3155254885Sdumbbell ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; 3156254885Sdumbbell 3157254885Sdumbbell dst_offset = radeon_get_ib_value(p, idx+1); 3158254885Sdumbbell dst_offset <<= 8; 3159254885Sdumbbell ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); 3160254885Sdumbbell } 3161254885Sdumbbell if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 3162254885Sdumbbell dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%ju %lu)\n", 3163254885Sdumbbell (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 3164254885Sdumbbell return -EINVAL; 3165254885Sdumbbell } 3166254885Sdumbbell if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 3167254885Sdumbbell dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%ju %lu)\n", 3168254885Sdumbbell (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 3169254885Sdumbbell return -EINVAL; 3170254885Sdumbbell } 3171254885Sdumbbell p->idx += 9; 3172254885Sdumbbell break; 3173254885Sdumbbell default: 3174254885Sdumbbell DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); 3175254885Sdumbbell return -EINVAL; 3176254885Sdumbbell } 3177254885Sdumbbell } 3178254885Sdumbbell } else { 3179254885Sdumbbell if (new_cmd) { 3180254885Sdumbbell switch (misc) { 3181254885Sdumbbell case 0: 3182254885Sdumbbell /* L2L, byte */ 3183254885Sdumbbell src_offset = radeon_get_ib_value(p, idx+2); 3184254885Sdumbbell src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; 3185254885Sdumbbell dst_offset = radeon_get_ib_value(p, idx+1); 3186254885Sdumbbell dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32; 3187254885Sdumbbell if ((src_offset + count) > radeon_bo_size(src_reloc->robj)) { 3188254885Sdumbbell dev_warn(p->dev, "DMA L2L, byte src buffer too small (%ju %lu)\n", 3189254885Sdumbbell (uintmax_t)src_offset + count, radeon_bo_size(src_reloc->robj)); 3190254885Sdumbbell return -EINVAL; 3191254885Sdumbbell } 3192254885Sdumbbell if ((dst_offset + count) > radeon_bo_size(dst_reloc->robj)) { 3193254885Sdumbbell dev_warn(p->dev, "DMA L2L, byte dst buffer too small (%ju %lu)\n", 3194254885Sdumbbell (uintmax_t)dst_offset + count, radeon_bo_size(dst_reloc->robj)); 3195254885Sdumbbell return -EINVAL; 3196254885Sdumbbell } 3197254885Sdumbbell ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff); 3198254885Sdumbbell ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff); 3199254885Sdumbbell ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; 3200254885Sdumbbell ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; 3201254885Sdumbbell p->idx += 5; 3202254885Sdumbbell break; 3203254885Sdumbbell case 1: 3204254885Sdumbbell /* L2L, partial */ 3205254885Sdumbbell if (p->family < CHIP_CAYMAN) { 3206254885Sdumbbell DRM_ERROR("L2L Partial is cayman only !\n"); 3207254885Sdumbbell return -EINVAL; 3208254885Sdumbbell } 3209254885Sdumbbell ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff); 3210254885Sdumbbell ib[idx+2] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; 3211254885Sdumbbell ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff); 3212254885Sdumbbell ib[idx+5] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; 3213254885Sdumbbell 3214254885Sdumbbell p->idx += 9; 3215254885Sdumbbell break; 3216254885Sdumbbell case 4: 3217254885Sdumbbell /* L2L, dw, broadcast */ 3218254885Sdumbbell r = r600_dma_cs_next_reloc(p, &dst2_reloc); 3219254885Sdumbbell if (r) { 3220254885Sdumbbell DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n"); 3221254885Sdumbbell return -EINVAL; 3222254885Sdumbbell } 3223254885Sdumbbell dst_offset = radeon_get_ib_value(p, idx+1); 3224254885Sdumbbell dst_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; 3225254885Sdumbbell dst2_offset = radeon_get_ib_value(p, idx+2); 3226254885Sdumbbell dst2_offset |= ((u64)(radeon_get_ib_value(p, idx+5) & 0xff)) << 32; 3227254885Sdumbbell src_offset = radeon_get_ib_value(p, idx+3); 3228254885Sdumbbell src_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32; 3229254885Sdumbbell if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 3230254885Sdumbbell dev_warn(p->dev, "DMA L2L, dw, broadcast src buffer too small (%ju %lu)\n", 3231254885Sdumbbell (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 3232254885Sdumbbell return -EINVAL; 3233254885Sdumbbell } 3234254885Sdumbbell if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 3235254885Sdumbbell dev_warn(p->dev, "DMA L2L, dw, broadcast dst buffer too small (%ju %lu)\n", 3236254885Sdumbbell (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 3237254885Sdumbbell return -EINVAL; 3238254885Sdumbbell } 3239254885Sdumbbell if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { 3240254885Sdumbbell dev_warn(p->dev, "DMA L2L, dw, broadcast dst2 buffer too small (%ju %lu)\n", 3241254885Sdumbbell (uintmax_t)dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); 3242254885Sdumbbell return -EINVAL; 3243254885Sdumbbell } 3244254885Sdumbbell ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); 3245254885Sdumbbell ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset & 0xfffffffc); 3246254885Sdumbbell ib[idx+3] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); 3247254885Sdumbbell ib[idx+4] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; 3248254885Sdumbbell ib[idx+5] += upper_32_bits(dst2_reloc->lobj.gpu_offset) & 0xff; 3249254885Sdumbbell ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; 3250254885Sdumbbell p->idx += 7; 3251254885Sdumbbell break; 3252254885Sdumbbell default: 3253254885Sdumbbell DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); 3254254885Sdumbbell return -EINVAL; 3255254885Sdumbbell } 3256254885Sdumbbell } else { 3257254885Sdumbbell /* L2L, dw */ 3258254885Sdumbbell src_offset = radeon_get_ib_value(p, idx+2); 3259254885Sdumbbell src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; 3260254885Sdumbbell dst_offset = radeon_get_ib_value(p, idx+1); 3261254885Sdumbbell dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32; 3262254885Sdumbbell if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 3263254885Sdumbbell dev_warn(p->dev, "DMA L2L, dw src buffer too small (%ju %lu)\n", 3264254885Sdumbbell (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 3265254885Sdumbbell return -EINVAL; 3266254885Sdumbbell } 3267254885Sdumbbell if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 3268254885Sdumbbell dev_warn(p->dev, "DMA L2L, dw dst buffer too small (%ju %lu)\n", 3269254885Sdumbbell (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 3270254885Sdumbbell return -EINVAL; 3271254885Sdumbbell } 3272254885Sdumbbell ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); 3273254885Sdumbbell ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); 3274254885Sdumbbell ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; 3275254885Sdumbbell ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; 3276254885Sdumbbell p->idx += 5; 3277254885Sdumbbell } 3278254885Sdumbbell } 3279254885Sdumbbell break; 3280254885Sdumbbell case DMA_PACKET_CONSTANT_FILL: 3281254885Sdumbbell r = r600_dma_cs_next_reloc(p, &dst_reloc); 3282254885Sdumbbell if (r) { 3283254885Sdumbbell DRM_ERROR("bad DMA_PACKET_CONSTANT_FILL\n"); 3284254885Sdumbbell return -EINVAL; 3285254885Sdumbbell } 3286254885Sdumbbell dst_offset = radeon_get_ib_value(p, idx+1); 3287254885Sdumbbell dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0x00ff0000)) << 16; 3288254885Sdumbbell if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 3289254885Sdumbbell dev_warn(p->dev, "DMA constant fill buffer too small (%ju %lu)\n", 3290254885Sdumbbell (uintmax_t)dst_offset, radeon_bo_size(dst_reloc->robj)); 3291254885Sdumbbell return -EINVAL; 3292254885Sdumbbell } 3293254885Sdumbbell ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); 3294254885Sdumbbell ib[idx+3] += (upper_32_bits(dst_reloc->lobj.gpu_offset) << 16) & 0x00ff0000; 3295254885Sdumbbell p->idx += 4; 3296254885Sdumbbell break; 3297254885Sdumbbell case DMA_PACKET_NOP: 3298254885Sdumbbell p->idx += 1; 3299254885Sdumbbell break; 3300254885Sdumbbell default: 3301254885Sdumbbell DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx); 3302254885Sdumbbell return -EINVAL; 3303254885Sdumbbell } 3304254885Sdumbbell } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); 3305254885Sdumbbell#if 0 3306254885Sdumbbell for (r = 0; r < p->ib->length_dw; r++) { 3307254885Sdumbbell DRM_INFO("%05d 0x%08X\n", r, p->ib.ptr[r]); 3308254885Sdumbbell mdelay(1); 3309254885Sdumbbell } 3310254885Sdumbbell#endif 3311254885Sdumbbell return 0; 3312254885Sdumbbell} 3313254885Sdumbbell 3314254885Sdumbbell/* vm parser */ 3315254885Sdumbbellstatic bool evergreen_vm_reg_valid(u32 reg) 3316254885Sdumbbell{ 3317254885Sdumbbell /* context regs are fine */ 3318254885Sdumbbell if (reg >= 0x28000) 3319254885Sdumbbell return true; 3320254885Sdumbbell 3321254885Sdumbbell /* check config regs */ 3322254885Sdumbbell switch (reg) { 3323254885Sdumbbell case WAIT_UNTIL: 3324254885Sdumbbell case GRBM_GFX_INDEX: 3325254885Sdumbbell case CP_STRMOUT_CNTL: 3326254885Sdumbbell case CP_COHER_CNTL: 3327254885Sdumbbell case CP_COHER_SIZE: 3328254885Sdumbbell case VGT_VTX_VECT_EJECT_REG: 3329254885Sdumbbell case VGT_CACHE_INVALIDATION: 3330254885Sdumbbell case VGT_GS_VERTEX_REUSE: 3331254885Sdumbbell case VGT_PRIMITIVE_TYPE: 3332254885Sdumbbell case VGT_INDEX_TYPE: 3333254885Sdumbbell case VGT_NUM_INDICES: 3334254885Sdumbbell case VGT_NUM_INSTANCES: 3335254885Sdumbbell case VGT_COMPUTE_DIM_X: 3336254885Sdumbbell case VGT_COMPUTE_DIM_Y: 3337254885Sdumbbell case VGT_COMPUTE_DIM_Z: 3338254885Sdumbbell case VGT_COMPUTE_START_X: 3339254885Sdumbbell case VGT_COMPUTE_START_Y: 3340254885Sdumbbell case VGT_COMPUTE_START_Z: 3341254885Sdumbbell case VGT_COMPUTE_INDEX: 3342254885Sdumbbell case VGT_COMPUTE_THREAD_GROUP_SIZE: 3343254885Sdumbbell case VGT_HS_OFFCHIP_PARAM: 3344254885Sdumbbell case PA_CL_ENHANCE: 3345254885Sdumbbell case PA_SU_LINE_STIPPLE_VALUE: 3346254885Sdumbbell case PA_SC_LINE_STIPPLE_STATE: 3347254885Sdumbbell case PA_SC_ENHANCE: 3348254885Sdumbbell case SQ_DYN_GPR_CNTL_PS_FLUSH_REQ: 3349254885Sdumbbell case SQ_DYN_GPR_SIMD_LOCK_EN: 3350254885Sdumbbell case SQ_CONFIG: 3351254885Sdumbbell case SQ_GPR_RESOURCE_MGMT_1: 3352254885Sdumbbell case SQ_GLOBAL_GPR_RESOURCE_MGMT_1: 3353254885Sdumbbell case SQ_GLOBAL_GPR_RESOURCE_MGMT_2: 3354254885Sdumbbell case SQ_CONST_MEM_BASE: 3355254885Sdumbbell case SQ_STATIC_THREAD_MGMT_1: 3356254885Sdumbbell case SQ_STATIC_THREAD_MGMT_2: 3357254885Sdumbbell case SQ_STATIC_THREAD_MGMT_3: 3358254885Sdumbbell case SPI_CONFIG_CNTL: 3359254885Sdumbbell case SPI_CONFIG_CNTL_1: 3360254885Sdumbbell case TA_CNTL_AUX: 3361254885Sdumbbell case DB_DEBUG: 3362254885Sdumbbell case DB_DEBUG2: 3363254885Sdumbbell case DB_DEBUG3: 3364254885Sdumbbell case DB_DEBUG4: 3365254885Sdumbbell case DB_WATERMARKS: 3366254885Sdumbbell case TD_PS_BORDER_COLOR_INDEX: 3367254885Sdumbbell case TD_PS_BORDER_COLOR_RED: 3368254885Sdumbbell case TD_PS_BORDER_COLOR_GREEN: 3369254885Sdumbbell case TD_PS_BORDER_COLOR_BLUE: 3370254885Sdumbbell case TD_PS_BORDER_COLOR_ALPHA: 3371254885Sdumbbell case TD_VS_BORDER_COLOR_INDEX: 3372254885Sdumbbell case TD_VS_BORDER_COLOR_RED: 3373254885Sdumbbell case TD_VS_BORDER_COLOR_GREEN: 3374254885Sdumbbell case TD_VS_BORDER_COLOR_BLUE: 3375254885Sdumbbell case TD_VS_BORDER_COLOR_ALPHA: 3376254885Sdumbbell case TD_GS_BORDER_COLOR_INDEX: 3377254885Sdumbbell case TD_GS_BORDER_COLOR_RED: 3378254885Sdumbbell case TD_GS_BORDER_COLOR_GREEN: 3379254885Sdumbbell case TD_GS_BORDER_COLOR_BLUE: 3380254885Sdumbbell case TD_GS_BORDER_COLOR_ALPHA: 3381254885Sdumbbell case TD_HS_BORDER_COLOR_INDEX: 3382254885Sdumbbell case TD_HS_BORDER_COLOR_RED: 3383254885Sdumbbell case TD_HS_BORDER_COLOR_GREEN: 3384254885Sdumbbell case TD_HS_BORDER_COLOR_BLUE: 3385254885Sdumbbell case TD_HS_BORDER_COLOR_ALPHA: 3386254885Sdumbbell case TD_LS_BORDER_COLOR_INDEX: 3387254885Sdumbbell case TD_LS_BORDER_COLOR_RED: 3388254885Sdumbbell case TD_LS_BORDER_COLOR_GREEN: 3389254885Sdumbbell case TD_LS_BORDER_COLOR_BLUE: 3390254885Sdumbbell case TD_LS_BORDER_COLOR_ALPHA: 3391254885Sdumbbell case TD_CS_BORDER_COLOR_INDEX: 3392254885Sdumbbell case TD_CS_BORDER_COLOR_RED: 3393254885Sdumbbell case TD_CS_BORDER_COLOR_GREEN: 3394254885Sdumbbell case TD_CS_BORDER_COLOR_BLUE: 3395254885Sdumbbell case TD_CS_BORDER_COLOR_ALPHA: 3396254885Sdumbbell case SQ_ESGS_RING_SIZE: 3397254885Sdumbbell case SQ_GSVS_RING_SIZE: 3398254885Sdumbbell case SQ_ESTMP_RING_SIZE: 3399254885Sdumbbell case SQ_GSTMP_RING_SIZE: 3400254885Sdumbbell case SQ_HSTMP_RING_SIZE: 3401254885Sdumbbell case SQ_LSTMP_RING_SIZE: 3402254885Sdumbbell case SQ_PSTMP_RING_SIZE: 3403254885Sdumbbell case SQ_VSTMP_RING_SIZE: 3404254885Sdumbbell case SQ_ESGS_RING_ITEMSIZE: 3405254885Sdumbbell case SQ_ESTMP_RING_ITEMSIZE: 3406254885Sdumbbell case SQ_GSTMP_RING_ITEMSIZE: 3407254885Sdumbbell case SQ_GSVS_RING_ITEMSIZE: 3408254885Sdumbbell case SQ_GS_VERT_ITEMSIZE: 3409254885Sdumbbell case SQ_GS_VERT_ITEMSIZE_1: 3410254885Sdumbbell case SQ_GS_VERT_ITEMSIZE_2: 3411254885Sdumbbell case SQ_GS_VERT_ITEMSIZE_3: 3412254885Sdumbbell case SQ_GSVS_RING_OFFSET_1: 3413254885Sdumbbell case SQ_GSVS_RING_OFFSET_2: 3414254885Sdumbbell case SQ_GSVS_RING_OFFSET_3: 3415254885Sdumbbell case SQ_HSTMP_RING_ITEMSIZE: 3416254885Sdumbbell case SQ_LSTMP_RING_ITEMSIZE: 3417254885Sdumbbell case SQ_PSTMP_RING_ITEMSIZE: 3418254885Sdumbbell case SQ_VSTMP_RING_ITEMSIZE: 3419254885Sdumbbell case VGT_TF_RING_SIZE: 3420254885Sdumbbell case SQ_ESGS_RING_BASE: 3421254885Sdumbbell case SQ_GSVS_RING_BASE: 3422254885Sdumbbell case SQ_ESTMP_RING_BASE: 3423254885Sdumbbell case SQ_GSTMP_RING_BASE: 3424254885Sdumbbell case SQ_HSTMP_RING_BASE: 3425254885Sdumbbell case SQ_LSTMP_RING_BASE: 3426254885Sdumbbell case SQ_PSTMP_RING_BASE: 3427254885Sdumbbell case SQ_VSTMP_RING_BASE: 3428254885Sdumbbell case CAYMAN_VGT_OFFCHIP_LDS_BASE: 3429254885Sdumbbell case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS: 3430254885Sdumbbell return true; 3431254885Sdumbbell default: 3432254885Sdumbbell DRM_ERROR("Invalid register 0x%x in CS\n", reg); 3433254885Sdumbbell return false; 3434254885Sdumbbell } 3435254885Sdumbbell} 3436254885Sdumbbell 3437254885Sdumbbellstatic int evergreen_vm_packet3_check(struct radeon_device *rdev, 3438254885Sdumbbell u32 *ib, struct radeon_cs_packet *pkt) 3439254885Sdumbbell{ 3440254885Sdumbbell u32 idx = pkt->idx + 1; 3441254885Sdumbbell u32 idx_value = ib[idx]; 3442254885Sdumbbell u32 start_reg, end_reg, reg, i; 3443254885Sdumbbell u32 command, info; 3444254885Sdumbbell 3445254885Sdumbbell switch (pkt->opcode) { 3446254885Sdumbbell case PACKET3_NOP: 3447254885Sdumbbell case PACKET3_SET_BASE: 3448254885Sdumbbell case PACKET3_CLEAR_STATE: 3449254885Sdumbbell case PACKET3_INDEX_BUFFER_SIZE: 3450254885Sdumbbell case PACKET3_DISPATCH_DIRECT: 3451254885Sdumbbell case PACKET3_DISPATCH_INDIRECT: 3452254885Sdumbbell case PACKET3_MODE_CONTROL: 3453254885Sdumbbell case PACKET3_SET_PREDICATION: 3454254885Sdumbbell case PACKET3_COND_EXEC: 3455254885Sdumbbell case PACKET3_PRED_EXEC: 3456254885Sdumbbell case PACKET3_DRAW_INDIRECT: 3457254885Sdumbbell case PACKET3_DRAW_INDEX_INDIRECT: 3458254885Sdumbbell case PACKET3_INDEX_BASE: 3459254885Sdumbbell case PACKET3_DRAW_INDEX_2: 3460254885Sdumbbell case PACKET3_CONTEXT_CONTROL: 3461254885Sdumbbell case PACKET3_DRAW_INDEX_OFFSET: 3462254885Sdumbbell case PACKET3_INDEX_TYPE: 3463254885Sdumbbell case PACKET3_DRAW_INDEX: 3464254885Sdumbbell case PACKET3_DRAW_INDEX_AUTO: 3465254885Sdumbbell case PACKET3_DRAW_INDEX_IMMD: 3466254885Sdumbbell case PACKET3_NUM_INSTANCES: 3467254885Sdumbbell case PACKET3_DRAW_INDEX_MULTI_AUTO: 3468254885Sdumbbell case PACKET3_STRMOUT_BUFFER_UPDATE: 3469254885Sdumbbell case PACKET3_DRAW_INDEX_OFFSET_2: 3470254885Sdumbbell case PACKET3_DRAW_INDEX_MULTI_ELEMENT: 3471254885Sdumbbell case PACKET3_MPEG_INDEX: 3472254885Sdumbbell case PACKET3_WAIT_REG_MEM: 3473254885Sdumbbell case PACKET3_MEM_WRITE: 3474254885Sdumbbell case PACKET3_SURFACE_SYNC: 3475254885Sdumbbell case PACKET3_EVENT_WRITE: 3476254885Sdumbbell case PACKET3_EVENT_WRITE_EOP: 3477254885Sdumbbell case PACKET3_EVENT_WRITE_EOS: 3478254885Sdumbbell case PACKET3_SET_CONTEXT_REG: 3479254885Sdumbbell case PACKET3_SET_BOOL_CONST: 3480254885Sdumbbell case PACKET3_SET_LOOP_CONST: 3481254885Sdumbbell case PACKET3_SET_RESOURCE: 3482254885Sdumbbell case PACKET3_SET_SAMPLER: 3483254885Sdumbbell case PACKET3_SET_CTL_CONST: 3484254885Sdumbbell case PACKET3_SET_RESOURCE_OFFSET: 3485254885Sdumbbell case PACKET3_SET_CONTEXT_REG_INDIRECT: 3486254885Sdumbbell case PACKET3_SET_RESOURCE_INDIRECT: 3487254885Sdumbbell case CAYMAN_PACKET3_DEALLOC_STATE: 3488254885Sdumbbell break; 3489254885Sdumbbell case PACKET3_COND_WRITE: 3490254885Sdumbbell if (idx_value & 0x100) { 3491254885Sdumbbell reg = ib[idx + 5] * 4; 3492254885Sdumbbell if (!evergreen_vm_reg_valid(reg)) 3493254885Sdumbbell return -EINVAL; 3494254885Sdumbbell } 3495254885Sdumbbell break; 3496254885Sdumbbell case PACKET3_COPY_DW: 3497254885Sdumbbell if (idx_value & 0x2) { 3498254885Sdumbbell reg = ib[idx + 3] * 4; 3499254885Sdumbbell if (!evergreen_vm_reg_valid(reg)) 3500254885Sdumbbell return -EINVAL; 3501254885Sdumbbell } 3502254885Sdumbbell break; 3503254885Sdumbbell case PACKET3_SET_CONFIG_REG: 3504254885Sdumbbell start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START; 3505254885Sdumbbell end_reg = 4 * pkt->count + start_reg - 4; 3506254885Sdumbbell if ((start_reg < PACKET3_SET_CONFIG_REG_START) || 3507254885Sdumbbell (start_reg >= PACKET3_SET_CONFIG_REG_END) || 3508254885Sdumbbell (end_reg >= PACKET3_SET_CONFIG_REG_END)) { 3509254885Sdumbbell DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n"); 3510254885Sdumbbell return -EINVAL; 3511254885Sdumbbell } 3512254885Sdumbbell for (i = 0; i < pkt->count; i++) { 3513254885Sdumbbell reg = start_reg + (4 * i); 3514254885Sdumbbell if (!evergreen_vm_reg_valid(reg)) 3515254885Sdumbbell return -EINVAL; 3516254885Sdumbbell } 3517254885Sdumbbell break; 3518254885Sdumbbell case PACKET3_CP_DMA: 3519254885Sdumbbell command = ib[idx + 4]; 3520254885Sdumbbell info = ib[idx + 1]; 3521254885Sdumbbell if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */ 3522254885Sdumbbell (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */ 3523254885Sdumbbell ((((info & 0x00300000) >> 20) == 0) && 3524254885Sdumbbell (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */ 3525254885Sdumbbell ((((info & 0x60000000) >> 29) == 0) && 3526254885Sdumbbell (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */ 3527254885Sdumbbell /* non mem to mem copies requires dw aligned count */ 3528254885Sdumbbell if ((command & 0x1fffff) % 4) { 3529254885Sdumbbell DRM_ERROR("CP DMA command requires dw count alignment\n"); 3530254885Sdumbbell return -EINVAL; 3531254885Sdumbbell } 3532254885Sdumbbell } 3533254885Sdumbbell if (command & PACKET3_CP_DMA_CMD_SAS) { 3534254885Sdumbbell /* src address space is register */ 3535254885Sdumbbell if (((info & 0x60000000) >> 29) == 0) { 3536254885Sdumbbell start_reg = idx_value << 2; 3537254885Sdumbbell if (command & PACKET3_CP_DMA_CMD_SAIC) { 3538254885Sdumbbell reg = start_reg; 3539254885Sdumbbell if (!evergreen_vm_reg_valid(reg)) { 3540254885Sdumbbell DRM_ERROR("CP DMA Bad SRC register\n"); 3541254885Sdumbbell return -EINVAL; 3542254885Sdumbbell } 3543254885Sdumbbell } else { 3544254885Sdumbbell for (i = 0; i < (command & 0x1fffff); i++) { 3545254885Sdumbbell reg = start_reg + (4 * i); 3546254885Sdumbbell if (!evergreen_vm_reg_valid(reg)) { 3547254885Sdumbbell DRM_ERROR("CP DMA Bad SRC register\n"); 3548254885Sdumbbell return -EINVAL; 3549254885Sdumbbell } 3550254885Sdumbbell } 3551254885Sdumbbell } 3552254885Sdumbbell } 3553254885Sdumbbell } 3554254885Sdumbbell if (command & PACKET3_CP_DMA_CMD_DAS) { 3555254885Sdumbbell /* dst address space is register */ 3556254885Sdumbbell if (((info & 0x00300000) >> 20) == 0) { 3557254885Sdumbbell start_reg = ib[idx + 2]; 3558254885Sdumbbell if (command & PACKET3_CP_DMA_CMD_DAIC) { 3559254885Sdumbbell reg = start_reg; 3560254885Sdumbbell if (!evergreen_vm_reg_valid(reg)) { 3561254885Sdumbbell DRM_ERROR("CP DMA Bad DST register\n"); 3562254885Sdumbbell return -EINVAL; 3563254885Sdumbbell } 3564254885Sdumbbell } else { 3565254885Sdumbbell for (i = 0; i < (command & 0x1fffff); i++) { 3566254885Sdumbbell reg = start_reg + (4 * i); 3567254885Sdumbbell if (!evergreen_vm_reg_valid(reg)) { 3568254885Sdumbbell DRM_ERROR("CP DMA Bad DST register\n"); 3569254885Sdumbbell return -EINVAL; 3570254885Sdumbbell } 3571254885Sdumbbell } 3572254885Sdumbbell } 3573254885Sdumbbell } 3574254885Sdumbbell } 3575254885Sdumbbell break; 3576254885Sdumbbell default: 3577254885Sdumbbell return -EINVAL; 3578254885Sdumbbell } 3579254885Sdumbbell return 0; 3580254885Sdumbbell} 3581254885Sdumbbell 3582254885Sdumbbellint evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) 3583254885Sdumbbell{ 3584254885Sdumbbell int ret = 0; 3585254885Sdumbbell u32 idx = 0; 3586254885Sdumbbell struct radeon_cs_packet pkt; 3587254885Sdumbbell 3588254885Sdumbbell do { 3589254885Sdumbbell pkt.idx = idx; 3590254885Sdumbbell pkt.type = CP_PACKET_GET_TYPE(ib->ptr[idx]); 3591254885Sdumbbell pkt.count = CP_PACKET_GET_COUNT(ib->ptr[idx]); 3592254885Sdumbbell pkt.one_reg_wr = 0; 3593254885Sdumbbell switch (pkt.type) { 3594254885Sdumbbell case PACKET_TYPE0: 3595254885Sdumbbell dev_err(rdev->dev, "Packet0 not allowed!\n"); 3596254885Sdumbbell ret = -EINVAL; 3597254885Sdumbbell break; 3598254885Sdumbbell case PACKET_TYPE2: 3599254885Sdumbbell idx += 1; 3600254885Sdumbbell break; 3601254885Sdumbbell case PACKET_TYPE3: 3602254885Sdumbbell pkt.opcode = CP_PACKET3_GET_OPCODE(ib->ptr[idx]); 3603254885Sdumbbell ret = evergreen_vm_packet3_check(rdev, ib->ptr, &pkt); 3604254885Sdumbbell idx += pkt.count + 2; 3605254885Sdumbbell break; 3606254885Sdumbbell default: 3607254885Sdumbbell dev_err(rdev->dev, "Unknown packet type %d !\n", pkt.type); 3608254885Sdumbbell ret = -EINVAL; 3609254885Sdumbbell break; 3610254885Sdumbbell } 3611254885Sdumbbell if (ret) 3612254885Sdumbbell break; 3613254885Sdumbbell } while (idx < ib->length_dw); 3614254885Sdumbbell 3615254885Sdumbbell return ret; 3616254885Sdumbbell} 3617254885Sdumbbell 3618254885Sdumbbell/** 3619254885Sdumbbell * evergreen_dma_ib_parse() - parse the DMA IB for VM 3620254885Sdumbbell * @rdev: radeon_device pointer 3621254885Sdumbbell * @ib: radeon_ib pointer 3622254885Sdumbbell * 3623254885Sdumbbell * Parses the DMA IB from the VM CS ioctl 3624254885Sdumbbell * checks for errors. (Cayman-SI) 3625254885Sdumbbell * Returns 0 for success and an error on failure. 3626254885Sdumbbell **/ 3627254885Sdumbbellint evergreen_dma_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) 3628254885Sdumbbell{ 3629254885Sdumbbell u32 idx = 0; 3630254885Sdumbbell u32 header, cmd, count, tiled, new_cmd, misc; 3631254885Sdumbbell 3632254885Sdumbbell do { 3633254885Sdumbbell header = ib->ptr[idx]; 3634254885Sdumbbell cmd = GET_DMA_CMD(header); 3635254885Sdumbbell count = GET_DMA_COUNT(header); 3636254885Sdumbbell tiled = GET_DMA_T(header); 3637254885Sdumbbell new_cmd = GET_DMA_NEW(header); 3638254885Sdumbbell misc = GET_DMA_MISC(header); 3639254885Sdumbbell 3640254885Sdumbbell switch (cmd) { 3641254885Sdumbbell case DMA_PACKET_WRITE: 3642254885Sdumbbell if (tiled) 3643254885Sdumbbell idx += count + 7; 3644254885Sdumbbell else 3645254885Sdumbbell idx += count + 3; 3646254885Sdumbbell break; 3647254885Sdumbbell case DMA_PACKET_COPY: 3648254885Sdumbbell if (tiled) { 3649254885Sdumbbell if (new_cmd) { 3650254885Sdumbbell switch (misc) { 3651254885Sdumbbell case 0: 3652254885Sdumbbell /* L2T, frame to fields */ 3653254885Sdumbbell idx += 10; 3654254885Sdumbbell break; 3655254885Sdumbbell case 1: 3656254885Sdumbbell /* L2T, T2L partial */ 3657254885Sdumbbell idx += 12; 3658254885Sdumbbell break; 3659254885Sdumbbell case 3: 3660254885Sdumbbell /* L2T, broadcast */ 3661254885Sdumbbell idx += 10; 3662254885Sdumbbell break; 3663254885Sdumbbell case 4: 3664254885Sdumbbell /* L2T, T2L */ 3665254885Sdumbbell idx += 9; 3666254885Sdumbbell break; 3667254885Sdumbbell case 5: 3668254885Sdumbbell /* T2T partial */ 3669254885Sdumbbell idx += 13; 3670254885Sdumbbell break; 3671254885Sdumbbell case 7: 3672254885Sdumbbell /* L2T, broadcast */ 3673254885Sdumbbell idx += 10; 3674254885Sdumbbell break; 3675254885Sdumbbell default: 3676254885Sdumbbell DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); 3677254885Sdumbbell return -EINVAL; 3678254885Sdumbbell } 3679254885Sdumbbell } else { 3680254885Sdumbbell switch (misc) { 3681254885Sdumbbell case 0: 3682254885Sdumbbell idx += 9; 3683254885Sdumbbell break; 3684254885Sdumbbell default: 3685254885Sdumbbell DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); 3686254885Sdumbbell return -EINVAL; 3687254885Sdumbbell } 3688254885Sdumbbell } 3689254885Sdumbbell } else { 3690254885Sdumbbell if (new_cmd) { 3691254885Sdumbbell switch (misc) { 3692254885Sdumbbell case 0: 3693254885Sdumbbell /* L2L, byte */ 3694254885Sdumbbell idx += 5; 3695254885Sdumbbell break; 3696254885Sdumbbell case 1: 3697254885Sdumbbell /* L2L, partial */ 3698254885Sdumbbell idx += 9; 3699254885Sdumbbell break; 3700254885Sdumbbell case 4: 3701254885Sdumbbell /* L2L, dw, broadcast */ 3702254885Sdumbbell idx += 7; 3703254885Sdumbbell break; 3704254885Sdumbbell default: 3705254885Sdumbbell DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); 3706254885Sdumbbell return -EINVAL; 3707254885Sdumbbell } 3708254885Sdumbbell } else { 3709254885Sdumbbell /* L2L, dw */ 3710254885Sdumbbell idx += 5; 3711254885Sdumbbell } 3712254885Sdumbbell } 3713254885Sdumbbell break; 3714254885Sdumbbell case DMA_PACKET_CONSTANT_FILL: 3715254885Sdumbbell idx += 4; 3716254885Sdumbbell break; 3717254885Sdumbbell case DMA_PACKET_NOP: 3718254885Sdumbbell idx += 1; 3719254885Sdumbbell break; 3720254885Sdumbbell default: 3721254885Sdumbbell DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx); 3722254885Sdumbbell return -EINVAL; 3723254885Sdumbbell } 3724254885Sdumbbell } while (idx < ib->length_dw); 3725254885Sdumbbell 3726254885Sdumbbell return 0; 3727254885Sdumbbell} 3728