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