blob: 883b9f76a49596af6f82e682671628666c98af3e [file] [log] [blame]
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001/*
2 * Copyright 2010 Advanced Micro Devices, Inc.
3 * Copyright 2008 Red Hat Inc.
4 * Copyright 2009 Jerome Glisse.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: Dave Airlie
25 * Alex Deucher
26 * Jerome Glisse
27 */
David Howells760285e2012-10-02 18:01:07 +010028#include <drm/drmP.h>
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040029#include "radeon.h"
30#include "evergreend.h"
31#include "evergreen_reg_safe.h"
Alex Deucherc175ca92011-03-02 20:07:37 -050032#include "cayman_reg_safe.h"
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040033
Jerome Glisse285484e2011-12-16 17:03:42 -050034#define MAX(a,b) (((a)>(b))?(a):(b))
35#define MIN(a,b) (((a)<(b))?(a):(b))
36
Alex Deucherd2ead3e2012-12-13 09:55:45 -050037int r600_dma_cs_next_reloc(struct radeon_cs_parser *p,
38 struct radeon_cs_reloc **cs_reloc);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040039static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
40 struct radeon_cs_reloc **cs_reloc);
41
42struct evergreen_cs_track {
43 u32 group_size;
44 u32 nbanks;
45 u32 npipes;
Alex Deucherf3a71df2011-11-28 14:49:28 -050046 u32 row_size;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040047 /* value we track */
Marek Olšák747e42a102012-03-19 03:09:36 +010048 u32 nsamples; /* unused */
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040049 struct radeon_bo *cb_color_bo[12];
50 u32 cb_color_bo_offset[12];
Marek Olšák747e42a102012-03-19 03:09:36 +010051 struct radeon_bo *cb_color_fmask_bo[8]; /* unused */
52 struct radeon_bo *cb_color_cmask_bo[8]; /* unused */
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040053 u32 cb_color_info[12];
54 u32 cb_color_view[12];
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040055 u32 cb_color_pitch[12];
56 u32 cb_color_slice[12];
Jerome Glissed2609872012-06-09 10:57:41 -040057 u32 cb_color_slice_idx[12];
Jerome Glisse285484e2011-12-16 17:03:42 -050058 u32 cb_color_attrib[12];
Marek Olšák747e42a102012-03-19 03:09:36 +010059 u32 cb_color_cmask_slice[8];/* unused */
60 u32 cb_color_fmask_slice[8];/* unused */
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040061 u32 cb_target_mask;
Marek Olšák747e42a102012-03-19 03:09:36 +010062 u32 cb_shader_mask; /* unused */
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040063 u32 vgt_strmout_config;
64 u32 vgt_strmout_buffer_config;
Marek Olšákdd220a02012-01-27 12:17:59 -050065 struct radeon_bo *vgt_strmout_bo[4];
Marek Olšákdd220a02012-01-27 12:17:59 -050066 u32 vgt_strmout_bo_offset[4];
67 u32 vgt_strmout_size[4];
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040068 u32 db_depth_control;
69 u32 db_depth_view;
Jerome Glisse285484e2011-12-16 17:03:42 -050070 u32 db_depth_slice;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040071 u32 db_depth_size;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040072 u32 db_z_info;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040073 u32 db_z_read_offset;
74 u32 db_z_write_offset;
75 struct radeon_bo *db_z_read_bo;
76 struct radeon_bo *db_z_write_bo;
77 u32 db_s_info;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040078 u32 db_s_read_offset;
79 u32 db_s_write_offset;
80 struct radeon_bo *db_s_read_bo;
81 struct radeon_bo *db_s_write_bo;
Marek Olšák779923b2012-03-08 00:56:00 +010082 bool sx_misc_kill_all_prims;
Marek Olšák30838572012-03-19 03:09:35 +010083 bool cb_dirty;
84 bool db_dirty;
85 bool streamout_dirty;
Jerome Glisse88f50c82012-03-21 19:18:21 -040086 u32 htile_offset;
87 u32 htile_surface;
88 struct radeon_bo *htile_bo;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -040089};
90
Alex Deucherf3a71df2011-11-28 14:49:28 -050091static u32 evergreen_cs_get_aray_mode(u32 tiling_flags)
92{
93 if (tiling_flags & RADEON_TILING_MACRO)
94 return ARRAY_2D_TILED_THIN1;
95 else if (tiling_flags & RADEON_TILING_MICRO)
96 return ARRAY_1D_TILED_THIN1;
97 else
98 return ARRAY_LINEAR_GENERAL;
99}
100
101static u32 evergreen_cs_get_num_banks(u32 nbanks)
102{
103 switch (nbanks) {
104 case 2:
105 return ADDR_SURF_2_BANK;
106 case 4:
107 return ADDR_SURF_4_BANK;
108 case 8:
109 default:
110 return ADDR_SURF_8_BANK;
111 case 16:
112 return ADDR_SURF_16_BANK;
113 }
114}
115
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400116static void evergreen_cs_track_init(struct evergreen_cs_track *track)
117{
118 int i;
119
120 for (i = 0; i < 8; i++) {
121 track->cb_color_fmask_bo[i] = NULL;
122 track->cb_color_cmask_bo[i] = NULL;
123 track->cb_color_cmask_slice[i] = 0;
124 track->cb_color_fmask_slice[i] = 0;
125 }
126
127 for (i = 0; i < 12; i++) {
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400128 track->cb_color_bo[i] = NULL;
129 track->cb_color_bo_offset[i] = 0xFFFFFFFF;
130 track->cb_color_info[i] = 0;
Jerome Glisse285484e2011-12-16 17:03:42 -0500131 track->cb_color_view[i] = 0xFFFFFFFF;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400132 track->cb_color_pitch[i] = 0;
Jerome Glissed2609872012-06-09 10:57:41 -0400133 track->cb_color_slice[i] = 0xfffffff;
134 track->cb_color_slice_idx[i] = 0;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400135 }
136 track->cb_target_mask = 0xFFFFFFFF;
137 track->cb_shader_mask = 0xFFFFFFFF;
Marek Olšák30838572012-03-19 03:09:35 +0100138 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400139
Jerome Glissed2609872012-06-09 10:57:41 -0400140 track->db_depth_slice = 0xffffffff;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400141 track->db_depth_view = 0xFFFFC000;
142 track->db_depth_size = 0xFFFFFFFF;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400143 track->db_depth_control = 0xFFFFFFFF;
144 track->db_z_info = 0xFFFFFFFF;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400145 track->db_z_read_offset = 0xFFFFFFFF;
146 track->db_z_write_offset = 0xFFFFFFFF;
147 track->db_z_read_bo = NULL;
148 track->db_z_write_bo = NULL;
149 track->db_s_info = 0xFFFFFFFF;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400150 track->db_s_read_offset = 0xFFFFFFFF;
151 track->db_s_write_offset = 0xFFFFFFFF;
152 track->db_s_read_bo = NULL;
153 track->db_s_write_bo = NULL;
Marek Olšák30838572012-03-19 03:09:35 +0100154 track->db_dirty = true;
Jerome Glisse88f50c82012-03-21 19:18:21 -0400155 track->htile_bo = NULL;
156 track->htile_offset = 0xFFFFFFFF;
157 track->htile_surface = 0;
Marek Olšákdd220a02012-01-27 12:17:59 -0500158
159 for (i = 0; i < 4; i++) {
160 track->vgt_strmout_size[i] = 0;
161 track->vgt_strmout_bo[i] = NULL;
162 track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
Marek Olšákdd220a02012-01-27 12:17:59 -0500163 }
Marek Olšák30838572012-03-19 03:09:35 +0100164 track->streamout_dirty = true;
Marek Olšák779923b2012-03-08 00:56:00 +0100165 track->sx_misc_kill_all_prims = false;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400166}
167
Jerome Glisse285484e2011-12-16 17:03:42 -0500168struct eg_surface {
169 /* value gathered from cs */
170 unsigned nbx;
171 unsigned nby;
172 unsigned format;
173 unsigned mode;
174 unsigned nbanks;
175 unsigned bankw;
176 unsigned bankh;
177 unsigned tsplit;
178 unsigned mtilea;
179 unsigned nsamples;
180 /* output value */
181 unsigned bpe;
182 unsigned layer_size;
183 unsigned palign;
184 unsigned halign;
185 unsigned long base_align;
186};
187
188static int evergreen_surface_check_linear(struct radeon_cs_parser *p,
189 struct eg_surface *surf,
190 const char *prefix)
191{
192 surf->layer_size = surf->nbx * surf->nby * surf->bpe * surf->nsamples;
193 surf->base_align = surf->bpe;
194 surf->palign = 1;
195 surf->halign = 1;
196 return 0;
197}
198
199static int evergreen_surface_check_linear_aligned(struct radeon_cs_parser *p,
200 struct eg_surface *surf,
201 const char *prefix)
202{
203 struct evergreen_cs_track *track = p->track;
204 unsigned palign;
205
206 palign = MAX(64, track->group_size / surf->bpe);
207 surf->layer_size = surf->nbx * surf->nby * surf->bpe * surf->nsamples;
208 surf->base_align = track->group_size;
209 surf->palign = palign;
210 surf->halign = 1;
211 if (surf->nbx & (palign - 1)) {
212 if (prefix) {
213 dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d\n",
214 __func__, __LINE__, prefix, surf->nbx, palign);
215 }
216 return -EINVAL;
217 }
218 return 0;
219}
220
221static int evergreen_surface_check_1d(struct radeon_cs_parser *p,
222 struct eg_surface *surf,
223 const char *prefix)
224{
225 struct evergreen_cs_track *track = p->track;
226 unsigned palign;
227
228 palign = track->group_size / (8 * surf->bpe * surf->nsamples);
229 palign = MAX(8, palign);
230 surf->layer_size = surf->nbx * surf->nby * surf->bpe;
231 surf->base_align = track->group_size;
232 surf->palign = palign;
233 surf->halign = 8;
234 if ((surf->nbx & (palign - 1))) {
235 if (prefix) {
236 dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d (%d %d %d)\n",
237 __func__, __LINE__, prefix, surf->nbx, palign,
238 track->group_size, surf->bpe, surf->nsamples);
239 }
240 return -EINVAL;
241 }
242 if ((surf->nby & (8 - 1))) {
243 if (prefix) {
244 dev_warn(p->dev, "%s:%d %s height %d invalid must be aligned with 8\n",
245 __func__, __LINE__, prefix, surf->nby);
246 }
247 return -EINVAL;
248 }
249 return 0;
250}
251
252static int evergreen_surface_check_2d(struct radeon_cs_parser *p,
253 struct eg_surface *surf,
254 const char *prefix)
255{
256 struct evergreen_cs_track *track = p->track;
257 unsigned palign, halign, tileb, slice_pt;
Jerome Glissed2609872012-06-09 10:57:41 -0400258 unsigned mtile_pr, mtile_ps, mtileb;
Jerome Glisse285484e2011-12-16 17:03:42 -0500259
260 tileb = 64 * surf->bpe * surf->nsamples;
Jerome Glisse285484e2011-12-16 17:03:42 -0500261 slice_pt = 1;
262 if (tileb > surf->tsplit) {
263 slice_pt = tileb / surf->tsplit;
264 }
265 tileb = tileb / slice_pt;
266 /* macro tile width & height */
267 palign = (8 * surf->bankw * track->npipes) * surf->mtilea;
268 halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea;
Peter Senna Tschudin74e4ca32012-10-24 16:42:26 +0200269 mtileb = (palign / 8) * (halign / 8) * tileb;
Jerome Glissed2609872012-06-09 10:57:41 -0400270 mtile_pr = surf->nbx / palign;
271 mtile_ps = (mtile_pr * surf->nby) / halign;
272 surf->layer_size = mtile_ps * mtileb * slice_pt;
Jerome Glisse285484e2011-12-16 17:03:42 -0500273 surf->base_align = (palign / 8) * (halign / 8) * tileb;
274 surf->palign = palign;
275 surf->halign = halign;
276
277 if ((surf->nbx & (palign - 1))) {
278 if (prefix) {
279 dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d\n",
280 __func__, __LINE__, prefix, surf->nbx, palign);
281 }
282 return -EINVAL;
283 }
284 if ((surf->nby & (halign - 1))) {
285 if (prefix) {
286 dev_warn(p->dev, "%s:%d %s height %d invalid must be aligned with %d\n",
287 __func__, __LINE__, prefix, surf->nby, halign);
288 }
289 return -EINVAL;
290 }
291
292 return 0;
293}
294
295static int evergreen_surface_check(struct radeon_cs_parser *p,
296 struct eg_surface *surf,
297 const char *prefix)
298{
299 /* some common value computed here */
300 surf->bpe = r600_fmt_get_blocksize(surf->format);
301
302 switch (surf->mode) {
303 case ARRAY_LINEAR_GENERAL:
304 return evergreen_surface_check_linear(p, surf, prefix);
305 case ARRAY_LINEAR_ALIGNED:
306 return evergreen_surface_check_linear_aligned(p, surf, prefix);
307 case ARRAY_1D_TILED_THIN1:
308 return evergreen_surface_check_1d(p, surf, prefix);
309 case ARRAY_2D_TILED_THIN1:
310 return evergreen_surface_check_2d(p, surf, prefix);
311 default:
Marek Olšák7df7c542012-03-19 03:09:32 +0100312 dev_warn(p->dev, "%s:%d %s invalid array mode %d\n",
313 __func__, __LINE__, prefix, surf->mode);
Jerome Glisse285484e2011-12-16 17:03:42 -0500314 return -EINVAL;
315 }
316 return -EINVAL;
317}
318
319static int evergreen_surface_value_conv_check(struct radeon_cs_parser *p,
320 struct eg_surface *surf,
321 const char *prefix)
322{
323 switch (surf->mode) {
324 case ARRAY_2D_TILED_THIN1:
325 break;
326 case ARRAY_LINEAR_GENERAL:
327 case ARRAY_LINEAR_ALIGNED:
328 case ARRAY_1D_TILED_THIN1:
329 return 0;
330 default:
Marek Olšák7df7c542012-03-19 03:09:32 +0100331 dev_warn(p->dev, "%s:%d %s invalid array mode %d\n",
332 __func__, __LINE__, prefix, surf->mode);
Jerome Glisse285484e2011-12-16 17:03:42 -0500333 return -EINVAL;
334 }
335
336 switch (surf->nbanks) {
337 case 0: surf->nbanks = 2; break;
338 case 1: surf->nbanks = 4; break;
339 case 2: surf->nbanks = 8; break;
340 case 3: surf->nbanks = 16; break;
341 default:
342 dev_warn(p->dev, "%s:%d %s invalid number of banks %d\n",
343 __func__, __LINE__, prefix, surf->nbanks);
344 return -EINVAL;
345 }
346 switch (surf->bankw) {
347 case 0: surf->bankw = 1; break;
348 case 1: surf->bankw = 2; break;
349 case 2: surf->bankw = 4; break;
350 case 3: surf->bankw = 8; break;
351 default:
352 dev_warn(p->dev, "%s:%d %s invalid bankw %d\n",
353 __func__, __LINE__, prefix, surf->bankw);
354 return -EINVAL;
355 }
356 switch (surf->bankh) {
357 case 0: surf->bankh = 1; break;
358 case 1: surf->bankh = 2; break;
359 case 2: surf->bankh = 4; break;
360 case 3: surf->bankh = 8; break;
361 default:
362 dev_warn(p->dev, "%s:%d %s invalid bankh %d\n",
363 __func__, __LINE__, prefix, surf->bankh);
364 return -EINVAL;
365 }
366 switch (surf->mtilea) {
367 case 0: surf->mtilea = 1; break;
368 case 1: surf->mtilea = 2; break;
369 case 2: surf->mtilea = 4; break;
370 case 3: surf->mtilea = 8; break;
371 default:
372 dev_warn(p->dev, "%s:%d %s invalid macro tile aspect %d\n",
373 __func__, __LINE__, prefix, surf->mtilea);
374 return -EINVAL;
375 }
376 switch (surf->tsplit) {
377 case 0: surf->tsplit = 64; break;
378 case 1: surf->tsplit = 128; break;
379 case 2: surf->tsplit = 256; break;
380 case 3: surf->tsplit = 512; break;
381 case 4: surf->tsplit = 1024; break;
382 case 5: surf->tsplit = 2048; break;
383 case 6: surf->tsplit = 4096; break;
384 default:
385 dev_warn(p->dev, "%s:%d %s invalid tile split %d\n",
386 __func__, __LINE__, prefix, surf->tsplit);
387 return -EINVAL;
388 }
389 return 0;
390}
391
392static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned id)
393{
394 struct evergreen_cs_track *track = p->track;
395 struct eg_surface surf;
396 unsigned pitch, slice, mslice;
397 unsigned long offset;
398 int r;
399
400 mslice = G_028C6C_SLICE_MAX(track->cb_color_view[id]) + 1;
401 pitch = track->cb_color_pitch[id];
402 slice = track->cb_color_slice[id];
403 surf.nbx = (pitch + 1) * 8;
404 surf.nby = ((slice + 1) * 64) / surf.nbx;
405 surf.mode = G_028C70_ARRAY_MODE(track->cb_color_info[id]);
406 surf.format = G_028C70_FORMAT(track->cb_color_info[id]);
407 surf.tsplit = G_028C74_TILE_SPLIT(track->cb_color_attrib[id]);
408 surf.nbanks = G_028C74_NUM_BANKS(track->cb_color_attrib[id]);
409 surf.bankw = G_028C74_BANK_WIDTH(track->cb_color_attrib[id]);
410 surf.bankh = G_028C74_BANK_HEIGHT(track->cb_color_attrib[id]);
411 surf.mtilea = G_028C74_MACRO_TILE_ASPECT(track->cb_color_attrib[id]);
412 surf.nsamples = 1;
413
414 if (!r600_fmt_is_valid_color(surf.format)) {
415 dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08x)\n",
416 __func__, __LINE__, surf.format,
417 id, track->cb_color_info[id]);
418 return -EINVAL;
419 }
420
421 r = evergreen_surface_value_conv_check(p, &surf, "cb");
422 if (r) {
423 return r;
424 }
425
426 r = evergreen_surface_check(p, &surf, "cb");
427 if (r) {
428 dev_warn(p->dev, "%s:%d cb[%d] invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n",
429 __func__, __LINE__, id, track->cb_color_pitch[id],
430 track->cb_color_slice[id], track->cb_color_attrib[id],
431 track->cb_color_info[id]);
432 return r;
433 }
434
435 offset = track->cb_color_bo_offset[id] << 8;
436 if (offset & (surf.base_align - 1)) {
437 dev_warn(p->dev, "%s:%d cb[%d] bo base %ld not aligned with %ld\n",
438 __func__, __LINE__, id, offset, surf.base_align);
439 return -EINVAL;
440 }
441
442 offset += surf.layer_size * mslice;
443 if (offset > radeon_bo_size(track->cb_color_bo[id])) {
Jerome Glissed2609872012-06-09 10:57:41 -0400444 /* old ddx are broken they allocate bo with w*h*bpp but
445 * program slice with ALIGN(h, 8), catch this and patch
446 * command stream.
447 */
448 if (!surf.mode) {
449 volatile u32 *ib = p->ib.ptr;
450 unsigned long tmp, nby, bsize, size, min = 0;
451
452 /* find the height the ddx wants */
453 if (surf.nby > 8) {
454 min = surf.nby - 8;
455 }
456 bsize = radeon_bo_size(track->cb_color_bo[id]);
457 tmp = track->cb_color_bo_offset[id] << 8;
458 for (nby = surf.nby; nby > min; nby--) {
459 size = nby * surf.nbx * surf.bpe * surf.nsamples;
460 if ((tmp + size * mslice) <= bsize) {
461 break;
462 }
463 }
464 if (nby > min) {
465 surf.nby = nby;
466 slice = ((nby * surf.nbx) / 64) - 1;
467 if (!evergreen_surface_check(p, &surf, "cb")) {
468 /* check if this one works */
469 tmp += surf.layer_size * mslice;
470 if (tmp <= bsize) {
471 ib[track->cb_color_slice_idx[id]] = slice;
472 goto old_ddx_ok;
473 }
474 }
475 }
476 }
Jerome Glisse285484e2011-12-16 17:03:42 -0500477 dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d, "
478 "offset %d, max layer %d, bo size %ld, slice %d)\n",
479 __func__, __LINE__, id, surf.layer_size,
480 track->cb_color_bo_offset[id] << 8, mslice,
481 radeon_bo_size(track->cb_color_bo[id]), slice);
482 dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n",
483 __func__, __LINE__, surf.nbx, surf.nby,
484 surf.mode, surf.bpe, surf.nsamples,
485 surf.bankw, surf.bankh,
486 surf.tsplit, surf.mtilea);
487 return -EINVAL;
488 }
Jerome Glissed2609872012-06-09 10:57:41 -0400489old_ddx_ok:
Jerome Glisse285484e2011-12-16 17:03:42 -0500490
491 return 0;
492}
493
Jerome Glisse88f50c82012-03-21 19:18:21 -0400494static int evergreen_cs_track_validate_htile(struct radeon_cs_parser *p,
495 unsigned nbx, unsigned nby)
496{
497 struct evergreen_cs_track *track = p->track;
498 unsigned long size;
499
500 if (track->htile_bo == NULL) {
501 dev_warn(p->dev, "%s:%d htile enabled without htile surface 0x%08x\n",
502 __func__, __LINE__, track->db_z_info);
503 return -EINVAL;
504 }
505
506 if (G_028ABC_LINEAR(track->htile_surface)) {
507 /* pitch must be 16 htiles aligned == 16 * 8 pixel aligned */
508 nbx = round_up(nbx, 16 * 8);
509 /* height is npipes htiles aligned == npipes * 8 pixel aligned */
510 nby = round_up(nby, track->npipes * 8);
511 } else {
Jerome Glisse4ac05332012-12-13 12:08:11 -0500512 /* always assume 8x8 htile */
513 /* align is htile align * 8, htile align vary according to
514 * number of pipe and tile width and nby
515 */
Jerome Glisse88f50c82012-03-21 19:18:21 -0400516 switch (track->npipes) {
517 case 8:
Jerome Glisse4ac05332012-12-13 12:08:11 -0500518 /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
Jerome Glisse88f50c82012-03-21 19:18:21 -0400519 nbx = round_up(nbx, 64 * 8);
520 nby = round_up(nby, 64 * 8);
521 break;
522 case 4:
Jerome Glisse4ac05332012-12-13 12:08:11 -0500523 /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
Jerome Glisse88f50c82012-03-21 19:18:21 -0400524 nbx = round_up(nbx, 64 * 8);
525 nby = round_up(nby, 32 * 8);
526 break;
527 case 2:
Jerome Glisse4ac05332012-12-13 12:08:11 -0500528 /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
Jerome Glisse88f50c82012-03-21 19:18:21 -0400529 nbx = round_up(nbx, 32 * 8);
530 nby = round_up(nby, 32 * 8);
531 break;
532 case 1:
Jerome Glisse4ac05332012-12-13 12:08:11 -0500533 /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
Jerome Glisse88f50c82012-03-21 19:18:21 -0400534 nbx = round_up(nbx, 32 * 8);
535 nby = round_up(nby, 16 * 8);
536 break;
537 default:
538 dev_warn(p->dev, "%s:%d invalid num pipes %d\n",
539 __func__, __LINE__, track->npipes);
540 return -EINVAL;
541 }
542 }
543 /* compute number of htile */
Jerome Glisse4ac05332012-12-13 12:08:11 -0500544 nbx = nbx >> 3;
545 nby = nby >> 3;
546 /* size must be aligned on npipes * 2K boundary */
547 size = roundup(nbx * nby * 4, track->npipes * (2 << 10));
Jerome Glisse88f50c82012-03-21 19:18:21 -0400548 size += track->htile_offset;
549
550 if (size > radeon_bo_size(track->htile_bo)) {
551 dev_warn(p->dev, "%s:%d htile surface too small %ld for %ld (%d %d)\n",
552 __func__, __LINE__, radeon_bo_size(track->htile_bo),
553 size, nbx, nby);
554 return -EINVAL;
555 }
556 return 0;
557}
558
Jerome Glisse285484e2011-12-16 17:03:42 -0500559static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p)
560{
561 struct evergreen_cs_track *track = p->track;
562 struct eg_surface surf;
563 unsigned pitch, slice, mslice;
564 unsigned long offset;
565 int r;
566
567 mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1;
568 pitch = G_028058_PITCH_TILE_MAX(track->db_depth_size);
569 slice = track->db_depth_slice;
570 surf.nbx = (pitch + 1) * 8;
571 surf.nby = ((slice + 1) * 64) / surf.nbx;
572 surf.mode = G_028040_ARRAY_MODE(track->db_z_info);
573 surf.format = G_028044_FORMAT(track->db_s_info);
574 surf.tsplit = G_028044_TILE_SPLIT(track->db_s_info);
575 surf.nbanks = G_028040_NUM_BANKS(track->db_z_info);
576 surf.bankw = G_028040_BANK_WIDTH(track->db_z_info);
577 surf.bankh = G_028040_BANK_HEIGHT(track->db_z_info);
578 surf.mtilea = G_028040_MACRO_TILE_ASPECT(track->db_z_info);
579 surf.nsamples = 1;
580
581 if (surf.format != 1) {
582 dev_warn(p->dev, "%s:%d stencil invalid format %d\n",
583 __func__, __LINE__, surf.format);
584 return -EINVAL;
585 }
586 /* replace by color format so we can use same code */
587 surf.format = V_028C70_COLOR_8;
588
589 r = evergreen_surface_value_conv_check(p, &surf, "stencil");
590 if (r) {
591 return r;
592 }
593
594 r = evergreen_surface_check(p, &surf, NULL);
595 if (r) {
596 /* old userspace doesn't compute proper depth/stencil alignment
597 * check that alignment against a bigger byte per elements and
598 * only report if that alignment is wrong too.
599 */
600 surf.format = V_028C70_COLOR_8_8_8_8;
601 r = evergreen_surface_check(p, &surf, "stencil");
602 if (r) {
603 dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n",
604 __func__, __LINE__, track->db_depth_size,
605 track->db_depth_slice, track->db_s_info, track->db_z_info);
606 }
607 return r;
608 }
609
610 offset = track->db_s_read_offset << 8;
611 if (offset & (surf.base_align - 1)) {
612 dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n",
613 __func__, __LINE__, offset, surf.base_align);
614 return -EINVAL;
615 }
616 offset += surf.layer_size * mslice;
617 if (offset > radeon_bo_size(track->db_s_read_bo)) {
618 dev_warn(p->dev, "%s:%d stencil read bo too small (layer size %d, "
619 "offset %ld, max layer %d, bo size %ld)\n",
620 __func__, __LINE__, surf.layer_size,
621 (unsigned long)track->db_s_read_offset << 8, mslice,
622 radeon_bo_size(track->db_s_read_bo));
623 dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n",
624 __func__, __LINE__, track->db_depth_size,
625 track->db_depth_slice, track->db_s_info, track->db_z_info);
626 return -EINVAL;
627 }
628
629 offset = track->db_s_write_offset << 8;
630 if (offset & (surf.base_align - 1)) {
631 dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n",
632 __func__, __LINE__, offset, surf.base_align);
633 return -EINVAL;
634 }
635 offset += surf.layer_size * mslice;
636 if (offset > radeon_bo_size(track->db_s_write_bo)) {
637 dev_warn(p->dev, "%s:%d stencil write bo too small (layer size %d, "
638 "offset %ld, max layer %d, bo size %ld)\n",
639 __func__, __LINE__, surf.layer_size,
640 (unsigned long)track->db_s_write_offset << 8, mslice,
641 radeon_bo_size(track->db_s_write_bo));
642 return -EINVAL;
643 }
644
Jerome Glisse88f50c82012-03-21 19:18:21 -0400645 /* hyperz */
646 if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) {
647 r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby);
648 if (r) {
649 return r;
650 }
651 }
652
Jerome Glisse285484e2011-12-16 17:03:42 -0500653 return 0;
654}
655
656static int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p)
657{
658 struct evergreen_cs_track *track = p->track;
659 struct eg_surface surf;
660 unsigned pitch, slice, mslice;
661 unsigned long offset;
662 int r;
663
664 mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1;
665 pitch = G_028058_PITCH_TILE_MAX(track->db_depth_size);
666 slice = track->db_depth_slice;
667 surf.nbx = (pitch + 1) * 8;
668 surf.nby = ((slice + 1) * 64) / surf.nbx;
669 surf.mode = G_028040_ARRAY_MODE(track->db_z_info);
670 surf.format = G_028040_FORMAT(track->db_z_info);
671 surf.tsplit = G_028040_TILE_SPLIT(track->db_z_info);
672 surf.nbanks = G_028040_NUM_BANKS(track->db_z_info);
673 surf.bankw = G_028040_BANK_WIDTH(track->db_z_info);
674 surf.bankh = G_028040_BANK_HEIGHT(track->db_z_info);
675 surf.mtilea = G_028040_MACRO_TILE_ASPECT(track->db_z_info);
676 surf.nsamples = 1;
677
678 switch (surf.format) {
679 case V_028040_Z_16:
680 surf.format = V_028C70_COLOR_16;
681 break;
682 case V_028040_Z_24:
683 case V_028040_Z_32_FLOAT:
684 surf.format = V_028C70_COLOR_8_8_8_8;
685 break;
686 default:
687 dev_warn(p->dev, "%s:%d depth invalid format %d\n",
688 __func__, __LINE__, surf.format);
689 return -EINVAL;
690 }
691
692 r = evergreen_surface_value_conv_check(p, &surf, "depth");
693 if (r) {
694 dev_warn(p->dev, "%s:%d depth invalid (0x%08x 0x%08x 0x%08x)\n",
695 __func__, __LINE__, track->db_depth_size,
696 track->db_depth_slice, track->db_z_info);
697 return r;
698 }
699
700 r = evergreen_surface_check(p, &surf, "depth");
701 if (r) {
702 dev_warn(p->dev, "%s:%d depth invalid (0x%08x 0x%08x 0x%08x)\n",
703 __func__, __LINE__, track->db_depth_size,
704 track->db_depth_slice, track->db_z_info);
705 return r;
706 }
707
708 offset = track->db_z_read_offset << 8;
709 if (offset & (surf.base_align - 1)) {
710 dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n",
711 __func__, __LINE__, offset, surf.base_align);
712 return -EINVAL;
713 }
714 offset += surf.layer_size * mslice;
715 if (offset > radeon_bo_size(track->db_z_read_bo)) {
716 dev_warn(p->dev, "%s:%d depth read bo too small (layer size %d, "
717 "offset %ld, max layer %d, bo size %ld)\n",
718 __func__, __LINE__, surf.layer_size,
719 (unsigned long)track->db_z_read_offset << 8, mslice,
720 radeon_bo_size(track->db_z_read_bo));
721 return -EINVAL;
722 }
723
724 offset = track->db_z_write_offset << 8;
725 if (offset & (surf.base_align - 1)) {
726 dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n",
727 __func__, __LINE__, offset, surf.base_align);
728 return -EINVAL;
729 }
730 offset += surf.layer_size * mslice;
731 if (offset > radeon_bo_size(track->db_z_write_bo)) {
732 dev_warn(p->dev, "%s:%d depth write bo too small (layer size %d, "
733 "offset %ld, max layer %d, bo size %ld)\n",
734 __func__, __LINE__, surf.layer_size,
735 (unsigned long)track->db_z_write_offset << 8, mslice,
736 radeon_bo_size(track->db_z_write_bo));
737 return -EINVAL;
738 }
739
Jerome Glisse88f50c82012-03-21 19:18:21 -0400740 /* hyperz */
741 if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) {
742 r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby);
743 if (r) {
744 return r;
745 }
746 }
747
Jerome Glisse285484e2011-12-16 17:03:42 -0500748 return 0;
749}
750
751static int evergreen_cs_track_validate_texture(struct radeon_cs_parser *p,
752 struct radeon_bo *texture,
753 struct radeon_bo *mipmap,
754 unsigned idx)
755{
756 struct eg_surface surf;
757 unsigned long toffset, moffset;
758 unsigned dim, llevel, mslice, width, height, depth, i;
Dan Carpenter42b923b2012-02-14 10:38:11 +0300759 u32 texdw[8];
Jerome Glisse285484e2011-12-16 17:03:42 -0500760 int r;
761
762 texdw[0] = radeon_get_ib_value(p, idx + 0);
763 texdw[1] = radeon_get_ib_value(p, idx + 1);
764 texdw[2] = radeon_get_ib_value(p, idx + 2);
765 texdw[3] = radeon_get_ib_value(p, idx + 3);
766 texdw[4] = radeon_get_ib_value(p, idx + 4);
767 texdw[5] = radeon_get_ib_value(p, idx + 5);
768 texdw[6] = radeon_get_ib_value(p, idx + 6);
769 texdw[7] = radeon_get_ib_value(p, idx + 7);
770 dim = G_030000_DIM(texdw[0]);
771 llevel = G_030014_LAST_LEVEL(texdw[5]);
772 mslice = G_030014_LAST_ARRAY(texdw[5]) + 1;
773 width = G_030000_TEX_WIDTH(texdw[0]) + 1;
774 height = G_030004_TEX_HEIGHT(texdw[1]) + 1;
775 depth = G_030004_TEX_DEPTH(texdw[1]) + 1;
776 surf.format = G_03001C_DATA_FORMAT(texdw[7]);
777 surf.nbx = (G_030000_PITCH(texdw[0]) + 1) * 8;
778 surf.nbx = r600_fmt_get_nblocksx(surf.format, surf.nbx);
779 surf.nby = r600_fmt_get_nblocksy(surf.format, height);
780 surf.mode = G_030004_ARRAY_MODE(texdw[1]);
781 surf.tsplit = G_030018_TILE_SPLIT(texdw[6]);
782 surf.nbanks = G_03001C_NUM_BANKS(texdw[7]);
783 surf.bankw = G_03001C_BANK_WIDTH(texdw[7]);
784 surf.bankh = G_03001C_BANK_HEIGHT(texdw[7]);
785 surf.mtilea = G_03001C_MACRO_TILE_ASPECT(texdw[7]);
786 surf.nsamples = 1;
787 toffset = texdw[2] << 8;
788 moffset = texdw[3] << 8;
789
790 if (!r600_fmt_is_valid_texture(surf.format, p->family)) {
791 dev_warn(p->dev, "%s:%d texture invalid format %d\n",
792 __func__, __LINE__, surf.format);
793 return -EINVAL;
794 }
795 switch (dim) {
796 case V_030000_SQ_TEX_DIM_1D:
797 case V_030000_SQ_TEX_DIM_2D:
798 case V_030000_SQ_TEX_DIM_CUBEMAP:
799 case V_030000_SQ_TEX_DIM_1D_ARRAY:
800 case V_030000_SQ_TEX_DIM_2D_ARRAY:
801 depth = 1;
Marek Olšákb51ad122012-08-09 16:34:16 +0200802 break;
803 case V_030000_SQ_TEX_DIM_2D_MSAA:
804 case V_030000_SQ_TEX_DIM_2D_ARRAY_MSAA:
805 surf.nsamples = 1 << llevel;
806 llevel = 0;
807 depth = 1;
808 break;
Jerome Glisse285484e2011-12-16 17:03:42 -0500809 case V_030000_SQ_TEX_DIM_3D:
810 break;
811 default:
812 dev_warn(p->dev, "%s:%d texture invalid dimension %d\n",
813 __func__, __LINE__, dim);
814 return -EINVAL;
815 }
816
817 r = evergreen_surface_value_conv_check(p, &surf, "texture");
818 if (r) {
819 return r;
820 }
821
822 /* align height */
823 evergreen_surface_check(p, &surf, NULL);
824 surf.nby = ALIGN(surf.nby, surf.halign);
825
826 r = evergreen_surface_check(p, &surf, "texture");
827 if (r) {
828 dev_warn(p->dev, "%s:%d texture invalid 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
829 __func__, __LINE__, texdw[0], texdw[1], texdw[4],
830 texdw[5], texdw[6], texdw[7]);
831 return r;
832 }
833
834 /* check texture size */
835 if (toffset & (surf.base_align - 1)) {
836 dev_warn(p->dev, "%s:%d texture bo base %ld not aligned with %ld\n",
837 __func__, __LINE__, toffset, surf.base_align);
838 return -EINVAL;
839 }
840 if (moffset & (surf.base_align - 1)) {
841 dev_warn(p->dev, "%s:%d mipmap bo base %ld not aligned with %ld\n",
842 __func__, __LINE__, moffset, surf.base_align);
843 return -EINVAL;
844 }
845 if (dim == SQ_TEX_DIM_3D) {
846 toffset += surf.layer_size * depth;
847 } else {
848 toffset += surf.layer_size * mslice;
849 }
850 if (toffset > radeon_bo_size(texture)) {
851 dev_warn(p->dev, "%s:%d texture bo too small (layer size %d, "
852 "offset %ld, max layer %d, depth %d, bo size %ld) (%d %d)\n",
853 __func__, __LINE__, surf.layer_size,
854 (unsigned long)texdw[2] << 8, mslice,
855 depth, radeon_bo_size(texture),
856 surf.nbx, surf.nby);
857 return -EINVAL;
858 }
859
Marek Olšák61051af2012-09-25 03:34:01 +0200860 if (!mipmap) {
861 if (llevel) {
862 dev_warn(p->dev, "%s:%i got NULL MIP_ADDRESS relocation\n",
863 __func__, __LINE__);
864 return -EINVAL;
865 } else {
866 return 0; /* everything's ok */
867 }
868 }
869
Jerome Glisse285484e2011-12-16 17:03:42 -0500870 /* check mipmap size */
871 for (i = 1; i <= llevel; i++) {
872 unsigned w, h, d;
873
874 w = r600_mip_minify(width, i);
875 h = r600_mip_minify(height, i);
876 d = r600_mip_minify(depth, i);
877 surf.nbx = r600_fmt_get_nblocksx(surf.format, w);
878 surf.nby = r600_fmt_get_nblocksy(surf.format, h);
879
880 switch (surf.mode) {
881 case ARRAY_2D_TILED_THIN1:
882 if (surf.nbx < surf.palign || surf.nby < surf.halign) {
883 surf.mode = ARRAY_1D_TILED_THIN1;
884 }
885 /* recompute alignment */
886 evergreen_surface_check(p, &surf, NULL);
887 break;
888 case ARRAY_LINEAR_GENERAL:
889 case ARRAY_LINEAR_ALIGNED:
890 case ARRAY_1D_TILED_THIN1:
891 break;
892 default:
893 dev_warn(p->dev, "%s:%d invalid array mode %d\n",
894 __func__, __LINE__, surf.mode);
895 return -EINVAL;
896 }
897 surf.nbx = ALIGN(surf.nbx, surf.palign);
898 surf.nby = ALIGN(surf.nby, surf.halign);
899
900 r = evergreen_surface_check(p, &surf, "mipmap");
901 if (r) {
902 return r;
903 }
904
905 if (dim == SQ_TEX_DIM_3D) {
906 moffset += surf.layer_size * d;
907 } else {
908 moffset += surf.layer_size * mslice;
909 }
910 if (moffset > radeon_bo_size(mipmap)) {
911 dev_warn(p->dev, "%s:%d mipmap [%d] bo too small (layer size %d, "
912 "offset %ld, coffset %ld, max layer %d, depth %d, "
913 "bo size %ld) level0 (%d %d %d)\n",
914 __func__, __LINE__, i, surf.layer_size,
915 (unsigned long)texdw[3] << 8, moffset, mslice,
916 d, radeon_bo_size(mipmap),
917 width, height, depth);
918 dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n",
919 __func__, __LINE__, surf.nbx, surf.nby,
920 surf.mode, surf.bpe, surf.nsamples,
921 surf.bankw, surf.bankh,
922 surf.tsplit, surf.mtilea);
923 return -EINVAL;
924 }
925 }
926
927 return 0;
928}
929
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400930static int evergreen_cs_track_check(struct radeon_cs_parser *p)
931{
932 struct evergreen_cs_track *track = p->track;
Marek Olšák7e9fa5f2012-03-19 03:09:34 +0100933 unsigned tmp, i;
Jerome Glisse285484e2011-12-16 17:03:42 -0500934 int r;
Marek Olšák7e9fa5f2012-03-19 03:09:34 +0100935 unsigned buffer_mask = 0;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400936
Marek Olšákdd220a02012-01-27 12:17:59 -0500937 /* check streamout */
Marek Olšák30838572012-03-19 03:09:35 +0100938 if (track->streamout_dirty && track->vgt_strmout_config) {
Marek Olšák7e9fa5f2012-03-19 03:09:34 +0100939 for (i = 0; i < 4; i++) {
940 if (track->vgt_strmout_config & (1 << i)) {
941 buffer_mask |= (track->vgt_strmout_buffer_config >> (i * 4)) & 0xf;
942 }
943 }
944
945 for (i = 0; i < 4; i++) {
946 if (buffer_mask & (1 << i)) {
947 if (track->vgt_strmout_bo[i]) {
948 u64 offset = (u64)track->vgt_strmout_bo_offset[i] +
949 (u64)track->vgt_strmout_size[i];
950 if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) {
951 DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n",
952 i, offset,
953 radeon_bo_size(track->vgt_strmout_bo[i]));
Marek Olšákdd220a02012-01-27 12:17:59 -0500954 return -EINVAL;
955 }
Marek Olšák7e9fa5f2012-03-19 03:09:34 +0100956 } else {
957 dev_warn(p->dev, "No buffer for streamout %d\n", i);
958 return -EINVAL;
Marek Olšákdd220a02012-01-27 12:17:59 -0500959 }
960 }
961 }
Marek Olšák30838572012-03-19 03:09:35 +0100962 track->streamout_dirty = false;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -0400963 }
964
Marek Olšák779923b2012-03-08 00:56:00 +0100965 if (track->sx_misc_kill_all_prims)
966 return 0;
967
Jerome Glisse285484e2011-12-16 17:03:42 -0500968 /* check that we have a cb for each enabled target
969 */
Marek Olšák30838572012-03-19 03:09:35 +0100970 if (track->cb_dirty) {
971 tmp = track->cb_target_mask;
972 for (i = 0; i < 8; i++) {
973 if ((tmp >> (i * 4)) & 0xF) {
974 /* at least one component is enabled */
975 if (track->cb_color_bo[i] == NULL) {
976 dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n",
977 __func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i);
978 return -EINVAL;
979 }
980 /* check cb */
981 r = evergreen_cs_track_validate_cb(p, i);
982 if (r) {
983 return r;
984 }
Jerome Glisse285484e2011-12-16 17:03:42 -0500985 }
986 }
Marek Olšák30838572012-03-19 03:09:35 +0100987 track->cb_dirty = false;
Jerome Glisse285484e2011-12-16 17:03:42 -0500988 }
989
Marek Olšák30838572012-03-19 03:09:35 +0100990 if (track->db_dirty) {
991 /* Check stencil buffer */
Marek Olšák0f457e42012-07-29 16:24:57 +0200992 if (G_028044_FORMAT(track->db_s_info) != V_028044_STENCIL_INVALID &&
993 G_028800_STENCIL_ENABLE(track->db_depth_control)) {
Marek Olšák30838572012-03-19 03:09:35 +0100994 r = evergreen_cs_track_validate_stencil(p);
995 if (r)
996 return r;
997 }
998 /* Check depth buffer */
Marek Olšák0f457e42012-07-29 16:24:57 +0200999 if (G_028040_FORMAT(track->db_z_info) != V_028040_Z_INVALID &&
1000 G_028800_Z_ENABLE(track->db_depth_control)) {
Marek Olšák30838572012-03-19 03:09:35 +01001001 r = evergreen_cs_track_validate_depth(p);
1002 if (r)
1003 return r;
1004 }
1005 track->db_dirty = false;
Jerome Glisse285484e2011-12-16 17:03:42 -05001006 }
1007
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001008 return 0;
1009}
1010
1011/**
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001012 * evergreen_cs_packet_next_reloc() - parse next packet which should be reloc packet3
1013 * @parser: parser structure holding parsing context.
1014 * @data: pointer to relocation data
1015 * @offset_start: starting offset
1016 * @offset_mask: offset mask (to align start offset on)
1017 * @reloc: reloc informations
1018 *
1019 * Check next packet is relocation packet3, do bo validation and compute
1020 * GPU offset using the provided start.
1021 **/
1022static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
1023 struct radeon_cs_reloc **cs_reloc)
1024{
1025 struct radeon_cs_chunk *relocs_chunk;
1026 struct radeon_cs_packet p3reloc;
1027 unsigned idx;
1028 int r;
1029
1030 if (p->chunk_relocs_idx == -1) {
1031 DRM_ERROR("No relocation chunk !\n");
1032 return -EINVAL;
1033 }
1034 *cs_reloc = NULL;
1035 relocs_chunk = &p->chunks[p->chunk_relocs_idx];
Ilija Hadzicc38f34b2013-01-02 18:27:41 -05001036 r = radeon_cs_packet_parse(p, &p3reloc, p->idx);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001037 if (r) {
1038 return r;
1039 }
1040 p->idx += p3reloc.count + 2;
1041 if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
1042 DRM_ERROR("No packet3 for relocation for packet at %d.\n",
1043 p3reloc.idx);
1044 return -EINVAL;
1045 }
1046 idx = radeon_get_ib_value(p, p3reloc.idx + 1);
1047 if (idx >= relocs_chunk->length_dw) {
1048 DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
1049 idx, relocs_chunk->length_dw);
1050 return -EINVAL;
1051 }
1052 /* FIXME: we assume reloc size is 4 dwords */
1053 *cs_reloc = p->relocs_ptr[(idx / 4)];
1054 return 0;
1055}
1056
1057/**
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001058 * evergreen_cs_packet_next_vline() - parse userspace VLINE packet
1059 * @parser: parser structure holding parsing context.
1060 *
1061 * Userspace sends a special sequence for VLINE waits.
1062 * PACKET0 - VLINE_START_END + value
1063 * PACKET3 - WAIT_REG_MEM poll vline status reg
1064 * RELOC (P3) - crtc_id in reloc.
1065 *
1066 * This function parses this and relocates the VLINE START END
1067 * and WAIT_REG_MEM packets to the correct crtc.
1068 * It also detects a switched off crtc and nulls out the
1069 * wait in that case.
1070 */
1071static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
1072{
1073 struct drm_mode_object *obj;
1074 struct drm_crtc *crtc;
1075 struct radeon_crtc *radeon_crtc;
1076 struct radeon_cs_packet p3reloc, wait_reg_mem;
1077 int crtc_id;
1078 int r;
1079 uint32_t header, h_idx, reg, wait_reg_mem_info;
1080 volatile uint32_t *ib;
1081
Jerome Glissef2e39222012-05-09 15:35:02 +02001082 ib = p->ib.ptr;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001083
1084 /* parse the WAIT_REG_MEM */
Ilija Hadzicc38f34b2013-01-02 18:27:41 -05001085 r = radeon_cs_packet_parse(p, &wait_reg_mem, p->idx);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001086 if (r)
1087 return r;
1088
1089 /* check its a WAIT_REG_MEM */
1090 if (wait_reg_mem.type != PACKET_TYPE3 ||
1091 wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
1092 DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
Paul Bollea3a88a62011-03-16 22:10:06 +01001093 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001094 }
1095
1096 wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
1097 /* bit 4 is reg (0) or mem (1) */
1098 if (wait_reg_mem_info & 0x10) {
1099 DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
Paul Bollea3a88a62011-03-16 22:10:06 +01001100 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001101 }
1102 /* waiting for value to be equal */
1103 if ((wait_reg_mem_info & 0x7) != 0x3) {
1104 DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
Paul Bollea3a88a62011-03-16 22:10:06 +01001105 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001106 }
1107 if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != EVERGREEN_VLINE_STATUS) {
1108 DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
Paul Bollea3a88a62011-03-16 22:10:06 +01001109 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001110 }
1111
1112 if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != EVERGREEN_VLINE_STAT) {
1113 DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
Paul Bollea3a88a62011-03-16 22:10:06 +01001114 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001115 }
1116
1117 /* jump over the NOP */
Ilija Hadzicc38f34b2013-01-02 18:27:41 -05001118 r = radeon_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001119 if (r)
1120 return r;
1121
1122 h_idx = p->idx - 2;
1123 p->idx += wait_reg_mem.count + 2;
1124 p->idx += p3reloc.count + 2;
1125
1126 header = radeon_get_ib_value(p, h_idx);
1127 crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
1128 reg = CP_PACKET0_GET_REG(header);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001129 obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
1130 if (!obj) {
1131 DRM_ERROR("cannot find crtc %d\n", crtc_id);
Paul Bollea3a88a62011-03-16 22:10:06 +01001132 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001133 }
1134 crtc = obj_to_crtc(obj);
1135 radeon_crtc = to_radeon_crtc(crtc);
1136 crtc_id = radeon_crtc->crtc_id;
1137
1138 if (!crtc->enabled) {
1139 /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
1140 ib[h_idx + 2] = PACKET2(0);
1141 ib[h_idx + 3] = PACKET2(0);
1142 ib[h_idx + 4] = PACKET2(0);
1143 ib[h_idx + 5] = PACKET2(0);
1144 ib[h_idx + 6] = PACKET2(0);
1145 ib[h_idx + 7] = PACKET2(0);
1146 ib[h_idx + 8] = PACKET2(0);
1147 } else {
1148 switch (reg) {
1149 case EVERGREEN_VLINE_START_END:
1150 header &= ~R600_CP_PACKET0_REG_MASK;
1151 header |= (EVERGREEN_VLINE_START_END + radeon_crtc->crtc_offset) >> 2;
1152 ib[h_idx] = header;
1153 ib[h_idx + 4] = (EVERGREEN_VLINE_STATUS + radeon_crtc->crtc_offset) >> 2;
1154 break;
1155 default:
1156 DRM_ERROR("unknown crtc reloc\n");
Paul Bollea3a88a62011-03-16 22:10:06 +01001157 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001158 }
1159 }
Paul Bollea3a88a62011-03-16 22:10:06 +01001160 return 0;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001161}
1162
1163static int evergreen_packet0_check(struct radeon_cs_parser *p,
1164 struct radeon_cs_packet *pkt,
1165 unsigned idx, unsigned reg)
1166{
1167 int r;
1168
1169 switch (reg) {
1170 case EVERGREEN_VLINE_START_END:
1171 r = evergreen_cs_packet_parse_vline(p);
1172 if (r) {
1173 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
1174 idx, reg);
1175 return r;
1176 }
1177 break;
1178 default:
1179 printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
1180 reg, idx);
1181 return -EINVAL;
1182 }
1183 return 0;
1184}
1185
1186static int evergreen_cs_parse_packet0(struct radeon_cs_parser *p,
1187 struct radeon_cs_packet *pkt)
1188{
1189 unsigned reg, i;
1190 unsigned idx;
1191 int r;
1192
1193 idx = pkt->idx + 1;
1194 reg = pkt->reg;
1195 for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
1196 r = evergreen_packet0_check(p, pkt, idx, reg);
1197 if (r) {
1198 return r;
1199 }
1200 }
1201 return 0;
1202}
1203
1204/**
1205 * evergreen_cs_check_reg() - check if register is authorized or not
1206 * @parser: parser structure holding parsing context
1207 * @reg: register we are testing
1208 * @idx: index into the cs buffer
1209 *
1210 * This function will test against evergreen_reg_safe_bm and return 0
1211 * if register is safe. If register is not flag as safe this function
1212 * will test it against a list of register needind special handling.
1213 */
Andi Kleen488479e2011-10-13 16:08:41 -07001214static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001215{
1216 struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track;
1217 struct radeon_cs_reloc *reloc;
Alex Deucherc175ca92011-03-02 20:07:37 -05001218 u32 last_reg;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001219 u32 m, i, tmp, *ib;
1220 int r;
1221
Alex Deucherc175ca92011-03-02 20:07:37 -05001222 if (p->rdev->family >= CHIP_CAYMAN)
1223 last_reg = ARRAY_SIZE(cayman_reg_safe_bm);
1224 else
1225 last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
1226
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001227 i = (reg >> 7);
Dan Carpenter88498832011-07-27 09:53:40 +00001228 if (i >= last_reg) {
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001229 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
1230 return -EINVAL;
1231 }
1232 m = 1 << ((reg >> 2) & 31);
Alex Deucherc175ca92011-03-02 20:07:37 -05001233 if (p->rdev->family >= CHIP_CAYMAN) {
1234 if (!(cayman_reg_safe_bm[i] & m))
1235 return 0;
1236 } else {
1237 if (!(evergreen_reg_safe_bm[i] & m))
1238 return 0;
1239 }
Jerome Glissef2e39222012-05-09 15:35:02 +02001240 ib = p->ib.ptr;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001241 switch (reg) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001242 /* force following reg to 0 in an attempt to disable out buffer
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001243 * which will need us to better understand how it works to perform
1244 * security check on it (Jerome)
1245 */
1246 case SQ_ESGS_RING_SIZE:
1247 case SQ_GSVS_RING_SIZE:
1248 case SQ_ESTMP_RING_SIZE:
1249 case SQ_GSTMP_RING_SIZE:
1250 case SQ_HSTMP_RING_SIZE:
1251 case SQ_LSTMP_RING_SIZE:
1252 case SQ_PSTMP_RING_SIZE:
1253 case SQ_VSTMP_RING_SIZE:
1254 case SQ_ESGS_RING_ITEMSIZE:
1255 case SQ_ESTMP_RING_ITEMSIZE:
1256 case SQ_GSTMP_RING_ITEMSIZE:
1257 case SQ_GSVS_RING_ITEMSIZE:
1258 case SQ_GS_VERT_ITEMSIZE:
1259 case SQ_GS_VERT_ITEMSIZE_1:
1260 case SQ_GS_VERT_ITEMSIZE_2:
1261 case SQ_GS_VERT_ITEMSIZE_3:
1262 case SQ_GSVS_RING_OFFSET_1:
1263 case SQ_GSVS_RING_OFFSET_2:
1264 case SQ_GSVS_RING_OFFSET_3:
1265 case SQ_HSTMP_RING_ITEMSIZE:
1266 case SQ_LSTMP_RING_ITEMSIZE:
1267 case SQ_PSTMP_RING_ITEMSIZE:
1268 case SQ_VSTMP_RING_ITEMSIZE:
1269 case VGT_TF_RING_SIZE:
1270 /* get value to populate the IB don't remove */
Alex Deucher8aa75002011-03-02 20:07:40 -05001271 /*tmp =radeon_get_ib_value(p, idx);
1272 ib[idx] = 0;*/
1273 break;
1274 case SQ_ESGS_RING_BASE:
1275 case SQ_GSVS_RING_BASE:
1276 case SQ_ESTMP_RING_BASE:
1277 case SQ_GSTMP_RING_BASE:
1278 case SQ_HSTMP_RING_BASE:
1279 case SQ_LSTMP_RING_BASE:
1280 case SQ_PSTMP_RING_BASE:
1281 case SQ_VSTMP_RING_BASE:
1282 r = evergreen_cs_packet_next_reloc(p, &reloc);
1283 if (r) {
1284 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1285 "0x%04X\n", reg);
1286 return -EINVAL;
1287 }
1288 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001289 break;
1290 case DB_DEPTH_CONTROL:
1291 track->db_depth_control = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001292 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001293 break;
Alex Deucherc175ca92011-03-02 20:07:37 -05001294 case CAYMAN_DB_EQAA:
1295 if (p->rdev->family < CHIP_CAYMAN) {
1296 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1297 "0x%04X\n", reg);
1298 return -EINVAL;
1299 }
1300 break;
1301 case CAYMAN_DB_DEPTH_INFO:
1302 if (p->rdev->family < CHIP_CAYMAN) {
1303 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1304 "0x%04X\n", reg);
1305 return -EINVAL;
1306 }
1307 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001308 case DB_Z_INFO:
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001309 track->db_z_info = radeon_get_ib_value(p, idx);
Jerome Glisse721604a2012-01-05 22:11:05 -05001310 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
Marek Olšáke70f2242011-10-25 01:38:45 +02001311 r = evergreen_cs_packet_next_reloc(p, &reloc);
1312 if (r) {
1313 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1314 "0x%04X\n", reg);
1315 return -EINVAL;
1316 }
1317 ib[idx] &= ~Z_ARRAY_MODE(0xf);
1318 track->db_z_info &= ~Z_ARRAY_MODE(0xf);
Alex Deucherf3a71df2011-11-28 14:49:28 -05001319 ib[idx] |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
1320 track->db_z_info |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
Marek Olšáke70f2242011-10-25 01:38:45 +02001321 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
Jerome Glisse285484e2011-12-16 17:03:42 -05001322 unsigned bankw, bankh, mtaspect, tile_split;
1323
1324 evergreen_tiling_fields(reloc->lobj.tiling_flags,
1325 &bankw, &bankh, &mtaspect,
1326 &tile_split);
Alex Deucherf3a71df2011-11-28 14:49:28 -05001327 ib[idx] |= DB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
Jerome Glisse285484e2011-12-16 17:03:42 -05001328 ib[idx] |= DB_TILE_SPLIT(tile_split) |
1329 DB_BANK_WIDTH(bankw) |
1330 DB_BANK_HEIGHT(bankh) |
1331 DB_MACRO_TILE_ASPECT(mtaspect);
Marek Olšáke70f2242011-10-25 01:38:45 +02001332 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001333 }
Marek Olšák30838572012-03-19 03:09:35 +01001334 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001335 break;
1336 case DB_STENCIL_INFO:
1337 track->db_s_info = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001338 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001339 break;
1340 case DB_DEPTH_VIEW:
1341 track->db_depth_view = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001342 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001343 break;
1344 case DB_DEPTH_SIZE:
1345 track->db_depth_size = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001346 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001347 break;
Jerome Glisse285484e2011-12-16 17:03:42 -05001348 case R_02805C_DB_DEPTH_SLICE:
1349 track->db_depth_slice = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001350 track->db_dirty = true;
Jerome Glisse285484e2011-12-16 17:03:42 -05001351 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001352 case DB_Z_READ_BASE:
1353 r = evergreen_cs_packet_next_reloc(p, &reloc);
1354 if (r) {
1355 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1356 "0x%04X\n", reg);
1357 return -EINVAL;
1358 }
1359 track->db_z_read_offset = radeon_get_ib_value(p, idx);
1360 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1361 track->db_z_read_bo = reloc->robj;
Marek Olšák30838572012-03-19 03:09:35 +01001362 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001363 break;
1364 case DB_Z_WRITE_BASE:
1365 r = evergreen_cs_packet_next_reloc(p, &reloc);
1366 if (r) {
1367 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1368 "0x%04X\n", reg);
1369 return -EINVAL;
1370 }
1371 track->db_z_write_offset = radeon_get_ib_value(p, idx);
1372 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1373 track->db_z_write_bo = reloc->robj;
Marek Olšák30838572012-03-19 03:09:35 +01001374 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001375 break;
1376 case DB_STENCIL_READ_BASE:
1377 r = evergreen_cs_packet_next_reloc(p, &reloc);
1378 if (r) {
1379 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1380 "0x%04X\n", reg);
1381 return -EINVAL;
1382 }
1383 track->db_s_read_offset = radeon_get_ib_value(p, idx);
1384 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1385 track->db_s_read_bo = reloc->robj;
Marek Olšák30838572012-03-19 03:09:35 +01001386 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001387 break;
1388 case DB_STENCIL_WRITE_BASE:
1389 r = evergreen_cs_packet_next_reloc(p, &reloc);
1390 if (r) {
1391 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1392 "0x%04X\n", reg);
1393 return -EINVAL;
1394 }
1395 track->db_s_write_offset = radeon_get_ib_value(p, idx);
1396 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1397 track->db_s_write_bo = reloc->robj;
Marek Olšák30838572012-03-19 03:09:35 +01001398 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001399 break;
1400 case VGT_STRMOUT_CONFIG:
1401 track->vgt_strmout_config = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001402 track->streamout_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001403 break;
1404 case VGT_STRMOUT_BUFFER_CONFIG:
1405 track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001406 track->streamout_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001407 break;
Marek Olšákdd220a02012-01-27 12:17:59 -05001408 case VGT_STRMOUT_BUFFER_BASE_0:
1409 case VGT_STRMOUT_BUFFER_BASE_1:
1410 case VGT_STRMOUT_BUFFER_BASE_2:
1411 case VGT_STRMOUT_BUFFER_BASE_3:
1412 r = evergreen_cs_packet_next_reloc(p, &reloc);
1413 if (r) {
1414 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1415 "0x%04X\n", reg);
1416 return -EINVAL;
1417 }
1418 tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
1419 track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
1420 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1421 track->vgt_strmout_bo[tmp] = reloc->robj;
Marek Olšák30838572012-03-19 03:09:35 +01001422 track->streamout_dirty = true;
Marek Olšákdd220a02012-01-27 12:17:59 -05001423 break;
1424 case VGT_STRMOUT_BUFFER_SIZE_0:
1425 case VGT_STRMOUT_BUFFER_SIZE_1:
1426 case VGT_STRMOUT_BUFFER_SIZE_2:
1427 case VGT_STRMOUT_BUFFER_SIZE_3:
1428 tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
1429 /* size in register is DWs, convert to bytes */
1430 track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4;
Marek Olšák30838572012-03-19 03:09:35 +01001431 track->streamout_dirty = true;
Marek Olšákdd220a02012-01-27 12:17:59 -05001432 break;
1433 case CP_COHER_BASE:
1434 r = evergreen_cs_packet_next_reloc(p, &reloc);
1435 if (r) {
1436 dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
1437 "0x%04X\n", reg);
1438 return -EINVAL;
1439 }
1440 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001441 case CB_TARGET_MASK:
1442 track->cb_target_mask = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001443 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001444 break;
1445 case CB_SHADER_MASK:
1446 track->cb_shader_mask = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001447 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001448 break;
1449 case PA_SC_AA_CONFIG:
Alex Deucherc175ca92011-03-02 20:07:37 -05001450 if (p->rdev->family >= CHIP_CAYMAN) {
1451 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1452 "0x%04X\n", reg);
1453 return -EINVAL;
1454 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001455 tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK;
1456 track->nsamples = 1 << tmp;
1457 break;
Alex Deucherc175ca92011-03-02 20:07:37 -05001458 case CAYMAN_PA_SC_AA_CONFIG:
1459 if (p->rdev->family < CHIP_CAYMAN) {
1460 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1461 "0x%04X\n", reg);
1462 return -EINVAL;
1463 }
1464 tmp = radeon_get_ib_value(p, idx) & CAYMAN_MSAA_NUM_SAMPLES_MASK;
1465 track->nsamples = 1 << tmp;
1466 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001467 case CB_COLOR0_VIEW:
1468 case CB_COLOR1_VIEW:
1469 case CB_COLOR2_VIEW:
1470 case CB_COLOR3_VIEW:
1471 case CB_COLOR4_VIEW:
1472 case CB_COLOR5_VIEW:
1473 case CB_COLOR6_VIEW:
1474 case CB_COLOR7_VIEW:
1475 tmp = (reg - CB_COLOR0_VIEW) / 0x3c;
1476 track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001477 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001478 break;
1479 case CB_COLOR8_VIEW:
1480 case CB_COLOR9_VIEW:
1481 case CB_COLOR10_VIEW:
1482 case CB_COLOR11_VIEW:
1483 tmp = ((reg - CB_COLOR8_VIEW) / 0x1c) + 8;
1484 track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001485 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001486 break;
1487 case CB_COLOR0_INFO:
1488 case CB_COLOR1_INFO:
1489 case CB_COLOR2_INFO:
1490 case CB_COLOR3_INFO:
1491 case CB_COLOR4_INFO:
1492 case CB_COLOR5_INFO:
1493 case CB_COLOR6_INFO:
1494 case CB_COLOR7_INFO:
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001495 tmp = (reg - CB_COLOR0_INFO) / 0x3c;
1496 track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
Jerome Glisse721604a2012-01-05 22:11:05 -05001497 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
Marek Olšáke70f2242011-10-25 01:38:45 +02001498 r = evergreen_cs_packet_next_reloc(p, &reloc);
1499 if (r) {
1500 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1501 "0x%04X\n", reg);
1502 return -EINVAL;
1503 }
Alex Deucherf3a71df2011-11-28 14:49:28 -05001504 ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
1505 track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001506 }
Marek Olšák30838572012-03-19 03:09:35 +01001507 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001508 break;
1509 case CB_COLOR8_INFO:
1510 case CB_COLOR9_INFO:
1511 case CB_COLOR10_INFO:
1512 case CB_COLOR11_INFO:
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001513 tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;
1514 track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
Jerome Glisse721604a2012-01-05 22:11:05 -05001515 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
Marek Olšáke70f2242011-10-25 01:38:45 +02001516 r = evergreen_cs_packet_next_reloc(p, &reloc);
1517 if (r) {
1518 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1519 "0x%04X\n", reg);
1520 return -EINVAL;
1521 }
Alex Deucherf3a71df2011-11-28 14:49:28 -05001522 ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
1523 track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001524 }
Marek Olšák30838572012-03-19 03:09:35 +01001525 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001526 break;
1527 case CB_COLOR0_PITCH:
1528 case CB_COLOR1_PITCH:
1529 case CB_COLOR2_PITCH:
1530 case CB_COLOR3_PITCH:
1531 case CB_COLOR4_PITCH:
1532 case CB_COLOR5_PITCH:
1533 case CB_COLOR6_PITCH:
1534 case CB_COLOR7_PITCH:
1535 tmp = (reg - CB_COLOR0_PITCH) / 0x3c;
1536 track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001537 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001538 break;
1539 case CB_COLOR8_PITCH:
1540 case CB_COLOR9_PITCH:
1541 case CB_COLOR10_PITCH:
1542 case CB_COLOR11_PITCH:
1543 tmp = ((reg - CB_COLOR8_PITCH) / 0x1c) + 8;
1544 track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001545 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001546 break;
1547 case CB_COLOR0_SLICE:
1548 case CB_COLOR1_SLICE:
1549 case CB_COLOR2_SLICE:
1550 case CB_COLOR3_SLICE:
1551 case CB_COLOR4_SLICE:
1552 case CB_COLOR5_SLICE:
1553 case CB_COLOR6_SLICE:
1554 case CB_COLOR7_SLICE:
1555 tmp = (reg - CB_COLOR0_SLICE) / 0x3c;
1556 track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
Jerome Glissed2609872012-06-09 10:57:41 -04001557 track->cb_color_slice_idx[tmp] = idx;
Marek Olšák30838572012-03-19 03:09:35 +01001558 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001559 break;
1560 case CB_COLOR8_SLICE:
1561 case CB_COLOR9_SLICE:
1562 case CB_COLOR10_SLICE:
1563 case CB_COLOR11_SLICE:
1564 tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8;
1565 track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
Jerome Glissed2609872012-06-09 10:57:41 -04001566 track->cb_color_slice_idx[tmp] = idx;
Marek Olšák30838572012-03-19 03:09:35 +01001567 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001568 break;
1569 case CB_COLOR0_ATTRIB:
1570 case CB_COLOR1_ATTRIB:
1571 case CB_COLOR2_ATTRIB:
1572 case CB_COLOR3_ATTRIB:
1573 case CB_COLOR4_ATTRIB:
1574 case CB_COLOR5_ATTRIB:
1575 case CB_COLOR6_ATTRIB:
1576 case CB_COLOR7_ATTRIB:
Jerome Glisse285484e2011-12-16 17:03:42 -05001577 r = evergreen_cs_packet_next_reloc(p, &reloc);
1578 if (r) {
1579 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1580 "0x%04X\n", reg);
1581 return -EINVAL;
1582 }
1583 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
1584 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
1585 unsigned bankw, bankh, mtaspect, tile_split;
1586
1587 evergreen_tiling_fields(reloc->lobj.tiling_flags,
1588 &bankw, &bankh, &mtaspect,
1589 &tile_split);
1590 ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
1591 ib[idx] |= CB_TILE_SPLIT(tile_split) |
1592 CB_BANK_WIDTH(bankw) |
1593 CB_BANK_HEIGHT(bankh) |
1594 CB_MACRO_TILE_ASPECT(mtaspect);
1595 }
1596 }
1597 tmp = ((reg - CB_COLOR0_ATTRIB) / 0x3c);
1598 track->cb_color_attrib[tmp] = ib[idx];
Marek Olšák30838572012-03-19 03:09:35 +01001599 track->cb_dirty = true;
Jerome Glisse285484e2011-12-16 17:03:42 -05001600 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001601 case CB_COLOR8_ATTRIB:
1602 case CB_COLOR9_ATTRIB:
1603 case CB_COLOR10_ATTRIB:
1604 case CB_COLOR11_ATTRIB:
Alex Deucherf3a71df2011-11-28 14:49:28 -05001605 r = evergreen_cs_packet_next_reloc(p, &reloc);
1606 if (r) {
1607 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1608 "0x%04X\n", reg);
1609 return -EINVAL;
1610 }
Jerome Glisse285484e2011-12-16 17:03:42 -05001611 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
1612 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
1613 unsigned bankw, bankh, mtaspect, tile_split;
1614
1615 evergreen_tiling_fields(reloc->lobj.tiling_flags,
1616 &bankw, &bankh, &mtaspect,
1617 &tile_split);
1618 ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
1619 ib[idx] |= CB_TILE_SPLIT(tile_split) |
1620 CB_BANK_WIDTH(bankw) |
1621 CB_BANK_HEIGHT(bankh) |
1622 CB_MACRO_TILE_ASPECT(mtaspect);
1623 }
Alex Deucherf3a71df2011-11-28 14:49:28 -05001624 }
Jerome Glisse285484e2011-12-16 17:03:42 -05001625 tmp = ((reg - CB_COLOR8_ATTRIB) / 0x1c) + 8;
1626 track->cb_color_attrib[tmp] = ib[idx];
Marek Olšák30838572012-03-19 03:09:35 +01001627 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001628 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001629 case CB_COLOR0_FMASK:
1630 case CB_COLOR1_FMASK:
1631 case CB_COLOR2_FMASK:
1632 case CB_COLOR3_FMASK:
1633 case CB_COLOR4_FMASK:
1634 case CB_COLOR5_FMASK:
1635 case CB_COLOR6_FMASK:
1636 case CB_COLOR7_FMASK:
1637 tmp = (reg - CB_COLOR0_FMASK) / 0x3c;
1638 r = evergreen_cs_packet_next_reloc(p, &reloc);
1639 if (r) {
1640 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
1641 return -EINVAL;
1642 }
1643 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1644 track->cb_color_fmask_bo[tmp] = reloc->robj;
1645 break;
1646 case CB_COLOR0_CMASK:
1647 case CB_COLOR1_CMASK:
1648 case CB_COLOR2_CMASK:
1649 case CB_COLOR3_CMASK:
1650 case CB_COLOR4_CMASK:
1651 case CB_COLOR5_CMASK:
1652 case CB_COLOR6_CMASK:
1653 case CB_COLOR7_CMASK:
1654 tmp = (reg - CB_COLOR0_CMASK) / 0x3c;
1655 r = evergreen_cs_packet_next_reloc(p, &reloc);
1656 if (r) {
1657 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
1658 return -EINVAL;
1659 }
1660 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1661 track->cb_color_cmask_bo[tmp] = reloc->robj;
1662 break;
1663 case CB_COLOR0_FMASK_SLICE:
1664 case CB_COLOR1_FMASK_SLICE:
1665 case CB_COLOR2_FMASK_SLICE:
1666 case CB_COLOR3_FMASK_SLICE:
1667 case CB_COLOR4_FMASK_SLICE:
1668 case CB_COLOR5_FMASK_SLICE:
1669 case CB_COLOR6_FMASK_SLICE:
1670 case CB_COLOR7_FMASK_SLICE:
1671 tmp = (reg - CB_COLOR0_FMASK_SLICE) / 0x3c;
1672 track->cb_color_fmask_slice[tmp] = radeon_get_ib_value(p, idx);
1673 break;
1674 case CB_COLOR0_CMASK_SLICE:
1675 case CB_COLOR1_CMASK_SLICE:
1676 case CB_COLOR2_CMASK_SLICE:
1677 case CB_COLOR3_CMASK_SLICE:
1678 case CB_COLOR4_CMASK_SLICE:
1679 case CB_COLOR5_CMASK_SLICE:
1680 case CB_COLOR6_CMASK_SLICE:
1681 case CB_COLOR7_CMASK_SLICE:
1682 tmp = (reg - CB_COLOR0_CMASK_SLICE) / 0x3c;
1683 track->cb_color_cmask_slice[tmp] = radeon_get_ib_value(p, idx);
1684 break;
1685 case CB_COLOR0_BASE:
1686 case CB_COLOR1_BASE:
1687 case CB_COLOR2_BASE:
1688 case CB_COLOR3_BASE:
1689 case CB_COLOR4_BASE:
1690 case CB_COLOR5_BASE:
1691 case CB_COLOR6_BASE:
1692 case CB_COLOR7_BASE:
1693 r = evergreen_cs_packet_next_reloc(p, &reloc);
1694 if (r) {
1695 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1696 "0x%04X\n", reg);
1697 return -EINVAL;
1698 }
1699 tmp = (reg - CB_COLOR0_BASE) / 0x3c;
1700 track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
1701 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001702 track->cb_color_bo[tmp] = reloc->robj;
Marek Olšák30838572012-03-19 03:09:35 +01001703 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001704 break;
1705 case CB_COLOR8_BASE:
1706 case CB_COLOR9_BASE:
1707 case CB_COLOR10_BASE:
1708 case CB_COLOR11_BASE:
1709 r = evergreen_cs_packet_next_reloc(p, &reloc);
1710 if (r) {
1711 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1712 "0x%04X\n", reg);
1713 return -EINVAL;
1714 }
1715 tmp = ((reg - CB_COLOR8_BASE) / 0x1c) + 8;
1716 track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
1717 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001718 track->cb_color_bo[tmp] = reloc->robj;
Marek Olšák30838572012-03-19 03:09:35 +01001719 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001720 break;
Jerome Glisse88f50c82012-03-21 19:18:21 -04001721 case DB_HTILE_DATA_BASE:
1722 r = evergreen_cs_packet_next_reloc(p, &reloc);
1723 if (r) {
1724 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1725 "0x%04X\n", reg);
1726 return -EINVAL;
1727 }
1728 track->htile_offset = radeon_get_ib_value(p, idx);
1729 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1730 track->htile_bo = reloc->robj;
1731 track->db_dirty = true;
1732 break;
1733 case DB_HTILE_SURFACE:
1734 /* 8x8 only */
1735 track->htile_surface = radeon_get_ib_value(p, idx);
Jerome Glisse4ac05332012-12-13 12:08:11 -05001736 /* force 8x8 htile width and height */
1737 ib[idx] |= 3;
Jerome Glisse88f50c82012-03-21 19:18:21 -04001738 track->db_dirty = true;
1739 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001740 case CB_IMMED0_BASE:
1741 case CB_IMMED1_BASE:
1742 case CB_IMMED2_BASE:
1743 case CB_IMMED3_BASE:
1744 case CB_IMMED4_BASE:
1745 case CB_IMMED5_BASE:
1746 case CB_IMMED6_BASE:
1747 case CB_IMMED7_BASE:
1748 case CB_IMMED8_BASE:
1749 case CB_IMMED9_BASE:
1750 case CB_IMMED10_BASE:
1751 case CB_IMMED11_BASE:
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001752 case SQ_PGM_START_FS:
1753 case SQ_PGM_START_ES:
1754 case SQ_PGM_START_VS:
1755 case SQ_PGM_START_GS:
1756 case SQ_PGM_START_PS:
1757 case SQ_PGM_START_HS:
1758 case SQ_PGM_START_LS:
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001759 case SQ_CONST_MEM_BASE:
1760 case SQ_ALU_CONST_CACHE_GS_0:
1761 case SQ_ALU_CONST_CACHE_GS_1:
1762 case SQ_ALU_CONST_CACHE_GS_2:
1763 case SQ_ALU_CONST_CACHE_GS_3:
1764 case SQ_ALU_CONST_CACHE_GS_4:
1765 case SQ_ALU_CONST_CACHE_GS_5:
1766 case SQ_ALU_CONST_CACHE_GS_6:
1767 case SQ_ALU_CONST_CACHE_GS_7:
1768 case SQ_ALU_CONST_CACHE_GS_8:
1769 case SQ_ALU_CONST_CACHE_GS_9:
1770 case SQ_ALU_CONST_CACHE_GS_10:
1771 case SQ_ALU_CONST_CACHE_GS_11:
1772 case SQ_ALU_CONST_CACHE_GS_12:
1773 case SQ_ALU_CONST_CACHE_GS_13:
1774 case SQ_ALU_CONST_CACHE_GS_14:
1775 case SQ_ALU_CONST_CACHE_GS_15:
1776 case SQ_ALU_CONST_CACHE_PS_0:
1777 case SQ_ALU_CONST_CACHE_PS_1:
1778 case SQ_ALU_CONST_CACHE_PS_2:
1779 case SQ_ALU_CONST_CACHE_PS_3:
1780 case SQ_ALU_CONST_CACHE_PS_4:
1781 case SQ_ALU_CONST_CACHE_PS_5:
1782 case SQ_ALU_CONST_CACHE_PS_6:
1783 case SQ_ALU_CONST_CACHE_PS_7:
1784 case SQ_ALU_CONST_CACHE_PS_8:
1785 case SQ_ALU_CONST_CACHE_PS_9:
1786 case SQ_ALU_CONST_CACHE_PS_10:
1787 case SQ_ALU_CONST_CACHE_PS_11:
1788 case SQ_ALU_CONST_CACHE_PS_12:
1789 case SQ_ALU_CONST_CACHE_PS_13:
1790 case SQ_ALU_CONST_CACHE_PS_14:
1791 case SQ_ALU_CONST_CACHE_PS_15:
1792 case SQ_ALU_CONST_CACHE_VS_0:
1793 case SQ_ALU_CONST_CACHE_VS_1:
1794 case SQ_ALU_CONST_CACHE_VS_2:
1795 case SQ_ALU_CONST_CACHE_VS_3:
1796 case SQ_ALU_CONST_CACHE_VS_4:
1797 case SQ_ALU_CONST_CACHE_VS_5:
1798 case SQ_ALU_CONST_CACHE_VS_6:
1799 case SQ_ALU_CONST_CACHE_VS_7:
1800 case SQ_ALU_CONST_CACHE_VS_8:
1801 case SQ_ALU_CONST_CACHE_VS_9:
1802 case SQ_ALU_CONST_CACHE_VS_10:
1803 case SQ_ALU_CONST_CACHE_VS_11:
1804 case SQ_ALU_CONST_CACHE_VS_12:
1805 case SQ_ALU_CONST_CACHE_VS_13:
1806 case SQ_ALU_CONST_CACHE_VS_14:
1807 case SQ_ALU_CONST_CACHE_VS_15:
1808 case SQ_ALU_CONST_CACHE_HS_0:
1809 case SQ_ALU_CONST_CACHE_HS_1:
1810 case SQ_ALU_CONST_CACHE_HS_2:
1811 case SQ_ALU_CONST_CACHE_HS_3:
1812 case SQ_ALU_CONST_CACHE_HS_4:
1813 case SQ_ALU_CONST_CACHE_HS_5:
1814 case SQ_ALU_CONST_CACHE_HS_6:
1815 case SQ_ALU_CONST_CACHE_HS_7:
1816 case SQ_ALU_CONST_CACHE_HS_8:
1817 case SQ_ALU_CONST_CACHE_HS_9:
1818 case SQ_ALU_CONST_CACHE_HS_10:
1819 case SQ_ALU_CONST_CACHE_HS_11:
1820 case SQ_ALU_CONST_CACHE_HS_12:
1821 case SQ_ALU_CONST_CACHE_HS_13:
1822 case SQ_ALU_CONST_CACHE_HS_14:
1823 case SQ_ALU_CONST_CACHE_HS_15:
1824 case SQ_ALU_CONST_CACHE_LS_0:
1825 case SQ_ALU_CONST_CACHE_LS_1:
1826 case SQ_ALU_CONST_CACHE_LS_2:
1827 case SQ_ALU_CONST_CACHE_LS_3:
1828 case SQ_ALU_CONST_CACHE_LS_4:
1829 case SQ_ALU_CONST_CACHE_LS_5:
1830 case SQ_ALU_CONST_CACHE_LS_6:
1831 case SQ_ALU_CONST_CACHE_LS_7:
1832 case SQ_ALU_CONST_CACHE_LS_8:
1833 case SQ_ALU_CONST_CACHE_LS_9:
1834 case SQ_ALU_CONST_CACHE_LS_10:
1835 case SQ_ALU_CONST_CACHE_LS_11:
1836 case SQ_ALU_CONST_CACHE_LS_12:
1837 case SQ_ALU_CONST_CACHE_LS_13:
1838 case SQ_ALU_CONST_CACHE_LS_14:
1839 case SQ_ALU_CONST_CACHE_LS_15:
1840 r = evergreen_cs_packet_next_reloc(p, &reloc);
1841 if (r) {
1842 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1843 "0x%04X\n", reg);
1844 return -EINVAL;
1845 }
1846 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1847 break;
Alex Deucher033b5652011-06-08 15:26:45 -04001848 case SX_MEMORY_EXPORT_BASE:
1849 if (p->rdev->family >= CHIP_CAYMAN) {
1850 dev_warn(p->dev, "bad SET_CONFIG_REG "
1851 "0x%04X\n", reg);
1852 return -EINVAL;
1853 }
1854 r = evergreen_cs_packet_next_reloc(p, &reloc);
1855 if (r) {
1856 dev_warn(p->dev, "bad SET_CONFIG_REG "
1857 "0x%04X\n", reg);
1858 return -EINVAL;
1859 }
1860 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1861 break;
1862 case CAYMAN_SX_SCATTER_EXPORT_BASE:
1863 if (p->rdev->family < CHIP_CAYMAN) {
1864 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1865 "0x%04X\n", reg);
1866 return -EINVAL;
1867 }
1868 r = evergreen_cs_packet_next_reloc(p, &reloc);
1869 if (r) {
1870 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1871 "0x%04X\n", reg);
1872 return -EINVAL;
1873 }
1874 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1875 break;
Marek Olšák779923b2012-03-08 00:56:00 +01001876 case SX_MISC:
1877 track->sx_misc_kill_all_prims = (radeon_get_ib_value(p, idx) & 0x1) != 0;
1878 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001879 default:
1880 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
1881 return -EINVAL;
1882 }
1883 return 0;
1884}
1885
Marek Olšákdd220a02012-01-27 12:17:59 -05001886static bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
1887{
1888 u32 last_reg, m, i;
1889
1890 if (p->rdev->family >= CHIP_CAYMAN)
1891 last_reg = ARRAY_SIZE(cayman_reg_safe_bm);
1892 else
1893 last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
1894
1895 i = (reg >> 7);
1896 if (i >= last_reg) {
1897 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
1898 return false;
1899 }
1900 m = 1 << ((reg >> 2) & 31);
1901 if (p->rdev->family >= CHIP_CAYMAN) {
1902 if (!(cayman_reg_safe_bm[i] & m))
1903 return true;
1904 } else {
1905 if (!(evergreen_reg_safe_bm[i] & m))
1906 return true;
1907 }
1908 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
1909 return false;
1910}
1911
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001912static int evergreen_packet3_check(struct radeon_cs_parser *p,
1913 struct radeon_cs_packet *pkt)
1914{
1915 struct radeon_cs_reloc *reloc;
1916 struct evergreen_cs_track *track;
1917 volatile u32 *ib;
1918 unsigned idx;
1919 unsigned i;
1920 unsigned start_reg, end_reg, reg;
1921 int r;
1922 u32 idx_value;
1923
1924 track = (struct evergreen_cs_track *)p->track;
Jerome Glissef2e39222012-05-09 15:35:02 +02001925 ib = p->ib.ptr;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001926 idx = pkt->idx + 1;
1927 idx_value = radeon_get_ib_value(p, idx);
1928
1929 switch (pkt->opcode) {
Dave Airlie2a19cac2011-02-28 16:11:48 +10001930 case PACKET3_SET_PREDICATION:
1931 {
1932 int pred_op;
1933 int tmp;
Marek Olšák78857132012-03-19 03:09:33 +01001934 uint64_t offset;
1935
Dave Airlie2a19cac2011-02-28 16:11:48 +10001936 if (pkt->count != 1) {
1937 DRM_ERROR("bad SET PREDICATION\n");
1938 return -EINVAL;
1939 }
1940
1941 tmp = radeon_get_ib_value(p, idx + 1);
1942 pred_op = (tmp >> 16) & 0x7;
1943
1944 /* for the clear predicate operation */
1945 if (pred_op == 0)
1946 return 0;
1947
1948 if (pred_op > 2) {
1949 DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op);
1950 return -EINVAL;
1951 }
1952
1953 r = evergreen_cs_packet_next_reloc(p, &reloc);
1954 if (r) {
1955 DRM_ERROR("bad SET PREDICATION\n");
1956 return -EINVAL;
1957 }
1958
Marek Olšák78857132012-03-19 03:09:33 +01001959 offset = reloc->lobj.gpu_offset +
1960 (idx_value & 0xfffffff0) +
1961 ((u64)(tmp & 0xff) << 32);
1962
1963 ib[idx + 0] = offset;
1964 ib[idx + 1] = (tmp & 0xffffff00) | (upper_32_bits(offset) & 0xff);
Dave Airlie2a19cac2011-02-28 16:11:48 +10001965 }
1966 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001967 case PACKET3_CONTEXT_CONTROL:
1968 if (pkt->count != 1) {
1969 DRM_ERROR("bad CONTEXT_CONTROL\n");
1970 return -EINVAL;
1971 }
1972 break;
1973 case PACKET3_INDEX_TYPE:
1974 case PACKET3_NUM_INSTANCES:
1975 case PACKET3_CLEAR_STATE:
1976 if (pkt->count) {
1977 DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");
1978 return -EINVAL;
1979 }
1980 break;
Alex Deucherc175ca92011-03-02 20:07:37 -05001981 case CAYMAN_PACKET3_DEALLOC_STATE:
1982 if (p->rdev->family < CHIP_CAYMAN) {
1983 DRM_ERROR("bad PACKET3_DEALLOC_STATE\n");
1984 return -EINVAL;
1985 }
1986 if (pkt->count) {
1987 DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");
1988 return -EINVAL;
1989 }
1990 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001991 case PACKET3_INDEX_BASE:
Marek Olšák78857132012-03-19 03:09:33 +01001992 {
1993 uint64_t offset;
1994
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001995 if (pkt->count != 1) {
1996 DRM_ERROR("bad INDEX_BASE\n");
1997 return -EINVAL;
1998 }
1999 r = evergreen_cs_packet_next_reloc(p, &reloc);
2000 if (r) {
2001 DRM_ERROR("bad INDEX_BASE\n");
2002 return -EINVAL;
2003 }
Marek Olšák78857132012-03-19 03:09:33 +01002004
2005 offset = reloc->lobj.gpu_offset +
2006 idx_value +
2007 ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32);
2008
2009 ib[idx+0] = offset;
2010 ib[idx+1] = upper_32_bits(offset) & 0xff;
2011
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002012 r = evergreen_cs_track_check(p);
2013 if (r) {
2014 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
2015 return r;
2016 }
2017 break;
Marek Olšák78857132012-03-19 03:09:33 +01002018 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002019 case PACKET3_DRAW_INDEX:
Marek Olšák78857132012-03-19 03:09:33 +01002020 {
2021 uint64_t offset;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002022 if (pkt->count != 3) {
2023 DRM_ERROR("bad DRAW_INDEX\n");
2024 return -EINVAL;
2025 }
2026 r = evergreen_cs_packet_next_reloc(p, &reloc);
2027 if (r) {
2028 DRM_ERROR("bad DRAW_INDEX\n");
2029 return -EINVAL;
2030 }
Marek Olšák78857132012-03-19 03:09:33 +01002031
2032 offset = reloc->lobj.gpu_offset +
2033 idx_value +
2034 ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32);
2035
2036 ib[idx+0] = offset;
2037 ib[idx+1] = upper_32_bits(offset) & 0xff;
2038
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002039 r = evergreen_cs_track_check(p);
2040 if (r) {
2041 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
2042 return r;
2043 }
2044 break;
Marek Olšák78857132012-03-19 03:09:33 +01002045 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002046 case PACKET3_DRAW_INDEX_2:
Marek Olšák78857132012-03-19 03:09:33 +01002047 {
2048 uint64_t offset;
2049
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002050 if (pkt->count != 4) {
2051 DRM_ERROR("bad DRAW_INDEX_2\n");
2052 return -EINVAL;
2053 }
2054 r = evergreen_cs_packet_next_reloc(p, &reloc);
2055 if (r) {
2056 DRM_ERROR("bad DRAW_INDEX_2\n");
2057 return -EINVAL;
2058 }
Marek Olšák78857132012-03-19 03:09:33 +01002059
2060 offset = reloc->lobj.gpu_offset +
2061 radeon_get_ib_value(p, idx+1) +
2062 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
2063
2064 ib[idx+1] = offset;
2065 ib[idx+2] = upper_32_bits(offset) & 0xff;
2066
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002067 r = evergreen_cs_track_check(p);
2068 if (r) {
2069 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
2070 return r;
2071 }
2072 break;
Marek Olšák78857132012-03-19 03:09:33 +01002073 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002074 case PACKET3_DRAW_INDEX_AUTO:
2075 if (pkt->count != 1) {
2076 DRM_ERROR("bad DRAW_INDEX_AUTO\n");
2077 return -EINVAL;
2078 }
2079 r = evergreen_cs_track_check(p);
2080 if (r) {
2081 dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
2082 return r;
2083 }
2084 break;
2085 case PACKET3_DRAW_INDEX_MULTI_AUTO:
2086 if (pkt->count != 2) {
2087 DRM_ERROR("bad DRAW_INDEX_MULTI_AUTO\n");
2088 return -EINVAL;
2089 }
2090 r = evergreen_cs_track_check(p);
2091 if (r) {
2092 dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
2093 return r;
2094 }
2095 break;
2096 case PACKET3_DRAW_INDEX_IMMD:
2097 if (pkt->count < 2) {
2098 DRM_ERROR("bad DRAW_INDEX_IMMD\n");
2099 return -EINVAL;
2100 }
2101 r = evergreen_cs_track_check(p);
2102 if (r) {
2103 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
2104 return r;
2105 }
2106 break;
2107 case PACKET3_DRAW_INDEX_OFFSET:
2108 if (pkt->count != 2) {
2109 DRM_ERROR("bad DRAW_INDEX_OFFSET\n");
2110 return -EINVAL;
2111 }
2112 r = evergreen_cs_track_check(p);
2113 if (r) {
2114 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
2115 return r;
2116 }
2117 break;
2118 case PACKET3_DRAW_INDEX_OFFSET_2:
2119 if (pkt->count != 3) {
2120 DRM_ERROR("bad DRAW_INDEX_OFFSET_2\n");
2121 return -EINVAL;
2122 }
2123 r = evergreen_cs_track_check(p);
2124 if (r) {
2125 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
2126 return r;
2127 }
2128 break;
Alex Deucher033b5652011-06-08 15:26:45 -04002129 case PACKET3_DISPATCH_DIRECT:
2130 if (pkt->count != 3) {
2131 DRM_ERROR("bad DISPATCH_DIRECT\n");
2132 return -EINVAL;
2133 }
2134 r = evergreen_cs_track_check(p);
2135 if (r) {
2136 dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
2137 return r;
2138 }
2139 break;
2140 case PACKET3_DISPATCH_INDIRECT:
2141 if (pkt->count != 1) {
2142 DRM_ERROR("bad DISPATCH_INDIRECT\n");
2143 return -EINVAL;
2144 }
2145 r = evergreen_cs_packet_next_reloc(p, &reloc);
2146 if (r) {
2147 DRM_ERROR("bad DISPATCH_INDIRECT\n");
2148 return -EINVAL;
2149 }
2150 ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
2151 r = evergreen_cs_track_check(p);
2152 if (r) {
2153 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
2154 return r;
2155 }
2156 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002157 case PACKET3_WAIT_REG_MEM:
2158 if (pkt->count != 5) {
2159 DRM_ERROR("bad WAIT_REG_MEM\n");
2160 return -EINVAL;
2161 }
2162 /* bit 4 is reg (0) or mem (1) */
2163 if (idx_value & 0x10) {
Marek Olšák78857132012-03-19 03:09:33 +01002164 uint64_t offset;
2165
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002166 r = evergreen_cs_packet_next_reloc(p, &reloc);
2167 if (r) {
2168 DRM_ERROR("bad WAIT_REG_MEM\n");
2169 return -EINVAL;
2170 }
Marek Olšák78857132012-03-19 03:09:33 +01002171
2172 offset = reloc->lobj.gpu_offset +
2173 (radeon_get_ib_value(p, idx+1) & 0xfffffffc) +
2174 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
2175
2176 ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffffc);
2177 ib[idx+2] = upper_32_bits(offset) & 0xff;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002178 }
2179 break;
Alex Deucher8770b862012-12-03 19:18:30 -05002180 case PACKET3_CP_DMA:
2181 {
2182 u32 command, size, info;
2183 u64 offset, tmp;
2184 if (pkt->count != 4) {
2185 DRM_ERROR("bad CP DMA\n");
2186 return -EINVAL;
2187 }
2188 command = radeon_get_ib_value(p, idx+4);
2189 size = command & 0x1fffff;
2190 info = radeon_get_ib_value(p, idx+1);
Alex Deucher9d89d782012-12-14 00:23:06 -05002191 if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */
2192 (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */
2193 ((((info & 0x00300000) >> 20) == 0) &&
2194 (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */
2195 ((((info & 0x60000000) >> 29) == 0) &&
2196 (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */
2197 /* non mem to mem copies requires dw aligned count */
2198 if (size % 4) {
2199 DRM_ERROR("CP DMA command requires dw count alignment\n");
2200 return -EINVAL;
2201 }
2202 }
Alex Deucher8770b862012-12-03 19:18:30 -05002203 if (command & PACKET3_CP_DMA_CMD_SAS) {
2204 /* src address space is register */
2205 /* GDS is ok */
2206 if (((info & 0x60000000) >> 29) != 1) {
2207 DRM_ERROR("CP DMA SAS not supported\n");
2208 return -EINVAL;
2209 }
2210 } else {
2211 if (command & PACKET3_CP_DMA_CMD_SAIC) {
2212 DRM_ERROR("CP DMA SAIC only supported for registers\n");
2213 return -EINVAL;
2214 }
2215 /* src address space is memory */
2216 if (((info & 0x60000000) >> 29) == 0) {
2217 r = evergreen_cs_packet_next_reloc(p, &reloc);
2218 if (r) {
2219 DRM_ERROR("bad CP DMA SRC\n");
2220 return -EINVAL;
2221 }
2222
2223 tmp = radeon_get_ib_value(p, idx) +
2224 ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32);
2225
2226 offset = reloc->lobj.gpu_offset + tmp;
2227
2228 if ((tmp + size) > radeon_bo_size(reloc->robj)) {
2229 dev_warn(p->dev, "CP DMA src buffer too small (%llu %lu)\n",
2230 tmp + size, radeon_bo_size(reloc->robj));
2231 return -EINVAL;
2232 }
2233
2234 ib[idx] = offset;
2235 ib[idx+1] = (ib[idx+1] & 0xffffff00) | (upper_32_bits(offset) & 0xff);
2236 } else if (((info & 0x60000000) >> 29) != 2) {
2237 DRM_ERROR("bad CP DMA SRC_SEL\n");
2238 return -EINVAL;
2239 }
2240 }
2241 if (command & PACKET3_CP_DMA_CMD_DAS) {
2242 /* dst address space is register */
2243 /* GDS is ok */
2244 if (((info & 0x00300000) >> 20) != 1) {
2245 DRM_ERROR("CP DMA DAS not supported\n");
2246 return -EINVAL;
2247 }
2248 } else {
2249 /* dst address space is memory */
2250 if (command & PACKET3_CP_DMA_CMD_DAIC) {
2251 DRM_ERROR("CP DMA DAIC only supported for registers\n");
2252 return -EINVAL;
2253 }
2254 if (((info & 0x00300000) >> 20) == 0) {
2255 r = evergreen_cs_packet_next_reloc(p, &reloc);
2256 if (r) {
2257 DRM_ERROR("bad CP DMA DST\n");
2258 return -EINVAL;
2259 }
2260
2261 tmp = radeon_get_ib_value(p, idx+2) +
2262 ((u64)(radeon_get_ib_value(p, idx+3) & 0xff) << 32);
2263
2264 offset = reloc->lobj.gpu_offset + tmp;
2265
2266 if ((tmp + size) > radeon_bo_size(reloc->robj)) {
2267 dev_warn(p->dev, "CP DMA dst buffer too small (%llu %lu)\n",
2268 tmp + size, radeon_bo_size(reloc->robj));
2269 return -EINVAL;
2270 }
2271
2272 ib[idx+2] = offset;
2273 ib[idx+3] = upper_32_bits(offset) & 0xff;
2274 } else {
2275 DRM_ERROR("bad CP DMA DST_SEL\n");
2276 return -EINVAL;
2277 }
2278 }
2279 break;
2280 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002281 case PACKET3_SURFACE_SYNC:
2282 if (pkt->count != 3) {
2283 DRM_ERROR("bad SURFACE_SYNC\n");
2284 return -EINVAL;
2285 }
2286 /* 0xffffffff/0x0 is flush all cache flag */
2287 if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
2288 radeon_get_ib_value(p, idx + 2) != 0) {
2289 r = evergreen_cs_packet_next_reloc(p, &reloc);
2290 if (r) {
2291 DRM_ERROR("bad SURFACE_SYNC\n");
2292 return -EINVAL;
2293 }
2294 ib[idx+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
2295 }
2296 break;
2297 case PACKET3_EVENT_WRITE:
2298 if (pkt->count != 2 && pkt->count != 0) {
2299 DRM_ERROR("bad EVENT_WRITE\n");
2300 return -EINVAL;
2301 }
2302 if (pkt->count) {
Marek Olšák78857132012-03-19 03:09:33 +01002303 uint64_t offset;
2304
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002305 r = evergreen_cs_packet_next_reloc(p, &reloc);
2306 if (r) {
2307 DRM_ERROR("bad EVENT_WRITE\n");
2308 return -EINVAL;
2309 }
Marek Olšák78857132012-03-19 03:09:33 +01002310 offset = reloc->lobj.gpu_offset +
2311 (radeon_get_ib_value(p, idx+1) & 0xfffffff8) +
2312 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
2313
2314 ib[idx+1] = offset & 0xfffffff8;
2315 ib[idx+2] = upper_32_bits(offset) & 0xff;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002316 }
2317 break;
2318 case PACKET3_EVENT_WRITE_EOP:
Marek Olšák78857132012-03-19 03:09:33 +01002319 {
2320 uint64_t offset;
2321
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002322 if (pkt->count != 4) {
2323 DRM_ERROR("bad EVENT_WRITE_EOP\n");
2324 return -EINVAL;
2325 }
2326 r = evergreen_cs_packet_next_reloc(p, &reloc);
2327 if (r) {
2328 DRM_ERROR("bad EVENT_WRITE_EOP\n");
2329 return -EINVAL;
2330 }
Marek Olšák78857132012-03-19 03:09:33 +01002331
2332 offset = reloc->lobj.gpu_offset +
2333 (radeon_get_ib_value(p, idx+1) & 0xfffffffc) +
2334 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
2335
2336 ib[idx+1] = offset & 0xfffffffc;
2337 ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002338 break;
Marek Olšák78857132012-03-19 03:09:33 +01002339 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002340 case PACKET3_EVENT_WRITE_EOS:
Marek Olšák78857132012-03-19 03:09:33 +01002341 {
2342 uint64_t offset;
2343
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002344 if (pkt->count != 3) {
2345 DRM_ERROR("bad EVENT_WRITE_EOS\n");
2346 return -EINVAL;
2347 }
2348 r = evergreen_cs_packet_next_reloc(p, &reloc);
2349 if (r) {
2350 DRM_ERROR("bad EVENT_WRITE_EOS\n");
2351 return -EINVAL;
2352 }
Marek Olšák78857132012-03-19 03:09:33 +01002353
2354 offset = reloc->lobj.gpu_offset +
2355 (radeon_get_ib_value(p, idx+1) & 0xfffffffc) +
2356 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
2357
2358 ib[idx+1] = offset & 0xfffffffc;
2359 ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002360 break;
Marek Olšák78857132012-03-19 03:09:33 +01002361 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002362 case PACKET3_SET_CONFIG_REG:
2363 start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START;
2364 end_reg = 4 * pkt->count + start_reg - 4;
2365 if ((start_reg < PACKET3_SET_CONFIG_REG_START) ||
2366 (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
2367 (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
2368 DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
2369 return -EINVAL;
2370 }
2371 for (i = 0; i < pkt->count; i++) {
2372 reg = start_reg + (4 * i);
2373 r = evergreen_cs_check_reg(p, reg, idx+1+i);
2374 if (r)
2375 return r;
2376 }
2377 break;
2378 case PACKET3_SET_CONTEXT_REG:
2379 start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_START;
2380 end_reg = 4 * pkt->count + start_reg - 4;
2381 if ((start_reg < PACKET3_SET_CONTEXT_REG_START) ||
2382 (start_reg >= PACKET3_SET_CONTEXT_REG_END) ||
2383 (end_reg >= PACKET3_SET_CONTEXT_REG_END)) {
2384 DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n");
2385 return -EINVAL;
2386 }
2387 for (i = 0; i < pkt->count; i++) {
2388 reg = start_reg + (4 * i);
2389 r = evergreen_cs_check_reg(p, reg, idx+1+i);
2390 if (r)
2391 return r;
2392 }
2393 break;
2394 case PACKET3_SET_RESOURCE:
2395 if (pkt->count % 8) {
2396 DRM_ERROR("bad SET_RESOURCE\n");
2397 return -EINVAL;
2398 }
2399 start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_START;
2400 end_reg = 4 * pkt->count + start_reg - 4;
2401 if ((start_reg < PACKET3_SET_RESOURCE_START) ||
2402 (start_reg >= PACKET3_SET_RESOURCE_END) ||
2403 (end_reg >= PACKET3_SET_RESOURCE_END)) {
2404 DRM_ERROR("bad SET_RESOURCE\n");
2405 return -EINVAL;
2406 }
2407 for (i = 0; i < (pkt->count / 8); i++) {
2408 struct radeon_bo *texture, *mipmap;
Jerome Glisse285484e2011-12-16 17:03:42 -05002409 u32 toffset, moffset;
Marek Olšák61051af2012-09-25 03:34:01 +02002410 u32 size, offset, mip_address, tex_dim;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002411
2412 switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) {
2413 case SQ_TEX_VTX_VALID_TEXTURE:
2414 /* tex base */
2415 r = evergreen_cs_packet_next_reloc(p, &reloc);
2416 if (r) {
2417 DRM_ERROR("bad SET_RESOURCE (tex)\n");
2418 return -EINVAL;
2419 }
Jerome Glisse721604a2012-01-05 22:11:05 -05002420 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
Alex Deucherf3a71df2011-11-28 14:49:28 -05002421 ib[idx+1+(i*8)+1] |=
2422 TEX_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
2423 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
Jerome Glisse285484e2011-12-16 17:03:42 -05002424 unsigned bankw, bankh, mtaspect, tile_split;
2425
2426 evergreen_tiling_fields(reloc->lobj.tiling_flags,
2427 &bankw, &bankh, &mtaspect,
2428 &tile_split);
2429 ib[idx+1+(i*8)+6] |= TEX_TILE_SPLIT(tile_split);
Alex Deucherf3a71df2011-11-28 14:49:28 -05002430 ib[idx+1+(i*8)+7] |=
Jerome Glisse285484e2011-12-16 17:03:42 -05002431 TEX_BANK_WIDTH(bankw) |
2432 TEX_BANK_HEIGHT(bankh) |
2433 MACRO_TILE_ASPECT(mtaspect) |
Alex Deucherf3a71df2011-11-28 14:49:28 -05002434 TEX_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
2435 }
Marek Olšáke70f2242011-10-25 01:38:45 +02002436 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002437 texture = reloc->robj;
Jerome Glisse285484e2011-12-16 17:03:42 -05002438 toffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
Marek Olšák61051af2012-09-25 03:34:01 +02002439
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002440 /* tex mip base */
Marek Olšák61051af2012-09-25 03:34:01 +02002441 tex_dim = ib[idx+1+(i*8)+0] & 0x7;
2442 mip_address = ib[idx+1+(i*8)+3];
2443
2444 if ((tex_dim == SQ_TEX_DIM_2D_MSAA || tex_dim == SQ_TEX_DIM_2D_ARRAY_MSAA) &&
2445 !mip_address &&
Ilija Hadzic9ffb7a62013-01-02 18:27:42 -05002446 !radeon_cs_packet_next_is_pkt3_nop(p)) {
Marek Olšák61051af2012-09-25 03:34:01 +02002447 /* MIP_ADDRESS should point to FMASK for an MSAA texture.
2448 * It should be 0 if FMASK is disabled. */
2449 moffset = 0;
2450 mipmap = NULL;
2451 } else {
2452 r = evergreen_cs_packet_next_reloc(p, &reloc);
2453 if (r) {
2454 DRM_ERROR("bad SET_RESOURCE (tex)\n");
2455 return -EINVAL;
2456 }
2457 moffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
2458 mipmap = reloc->robj;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002459 }
Marek Olšák61051af2012-09-25 03:34:01 +02002460
Jerome Glisse285484e2011-12-16 17:03:42 -05002461 r = evergreen_cs_track_validate_texture(p, texture, mipmap, idx+1+(i*8));
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002462 if (r)
2463 return r;
Jerome Glisse285484e2011-12-16 17:03:42 -05002464 ib[idx+1+(i*8)+2] += toffset;
2465 ib[idx+1+(i*8)+3] += moffset;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002466 break;
2467 case SQ_TEX_VTX_VALID_BUFFER:
Marek Olšák78857132012-03-19 03:09:33 +01002468 {
2469 uint64_t offset64;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002470 /* vtx base */
2471 r = evergreen_cs_packet_next_reloc(p, &reloc);
2472 if (r) {
2473 DRM_ERROR("bad SET_RESOURCE (vtx)\n");
2474 return -EINVAL;
2475 }
2476 offset = radeon_get_ib_value(p, idx+1+(i*8)+0);
2477 size = radeon_get_ib_value(p, idx+1+(i*8)+1);
2478 if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
2479 /* force size to size of the buffer */
2480 dev_warn(p->dev, "vbo resource seems too big for the bo\n");
Marek Olšák78857132012-03-19 03:09:33 +01002481 ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj) - offset;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002482 }
Marek Olšák78857132012-03-19 03:09:33 +01002483
2484 offset64 = reloc->lobj.gpu_offset + offset;
2485 ib[idx+1+(i*8)+0] = offset64;
2486 ib[idx+1+(i*8)+2] = (ib[idx+1+(i*8)+2] & 0xffffff00) |
2487 (upper_32_bits(offset64) & 0xff);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002488 break;
Marek Olšák78857132012-03-19 03:09:33 +01002489 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002490 case SQ_TEX_VTX_INVALID_TEXTURE:
2491 case SQ_TEX_VTX_INVALID_BUFFER:
2492 default:
2493 DRM_ERROR("bad SET_RESOURCE\n");
2494 return -EINVAL;
2495 }
2496 }
2497 break;
2498 case PACKET3_SET_ALU_CONST:
2499 /* XXX fix me ALU const buffers only */
2500 break;
2501 case PACKET3_SET_BOOL_CONST:
2502 start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_START;
2503 end_reg = 4 * pkt->count + start_reg - 4;
2504 if ((start_reg < PACKET3_SET_BOOL_CONST_START) ||
2505 (start_reg >= PACKET3_SET_BOOL_CONST_END) ||
2506 (end_reg >= PACKET3_SET_BOOL_CONST_END)) {
2507 DRM_ERROR("bad SET_BOOL_CONST\n");
2508 return -EINVAL;
2509 }
2510 break;
2511 case PACKET3_SET_LOOP_CONST:
2512 start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_START;
2513 end_reg = 4 * pkt->count + start_reg - 4;
2514 if ((start_reg < PACKET3_SET_LOOP_CONST_START) ||
2515 (start_reg >= PACKET3_SET_LOOP_CONST_END) ||
2516 (end_reg >= PACKET3_SET_LOOP_CONST_END)) {
2517 DRM_ERROR("bad SET_LOOP_CONST\n");
2518 return -EINVAL;
2519 }
2520 break;
2521 case PACKET3_SET_CTL_CONST:
2522 start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_START;
2523 end_reg = 4 * pkt->count + start_reg - 4;
2524 if ((start_reg < PACKET3_SET_CTL_CONST_START) ||
2525 (start_reg >= PACKET3_SET_CTL_CONST_END) ||
2526 (end_reg >= PACKET3_SET_CTL_CONST_END)) {
2527 DRM_ERROR("bad SET_CTL_CONST\n");
2528 return -EINVAL;
2529 }
2530 break;
2531 case PACKET3_SET_SAMPLER:
2532 if (pkt->count % 3) {
2533 DRM_ERROR("bad SET_SAMPLER\n");
2534 return -EINVAL;
2535 }
2536 start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_START;
2537 end_reg = 4 * pkt->count + start_reg - 4;
2538 if ((start_reg < PACKET3_SET_SAMPLER_START) ||
2539 (start_reg >= PACKET3_SET_SAMPLER_END) ||
2540 (end_reg >= PACKET3_SET_SAMPLER_END)) {
2541 DRM_ERROR("bad SET_SAMPLER\n");
2542 return -EINVAL;
2543 }
2544 break;
Marek Olšákdd220a02012-01-27 12:17:59 -05002545 case PACKET3_STRMOUT_BUFFER_UPDATE:
2546 if (pkt->count != 4) {
2547 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
2548 return -EINVAL;
2549 }
2550 /* Updating memory at DST_ADDRESS. */
2551 if (idx_value & 0x1) {
2552 u64 offset;
2553 r = evergreen_cs_packet_next_reloc(p, &reloc);
2554 if (r) {
2555 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n");
2556 return -EINVAL;
2557 }
2558 offset = radeon_get_ib_value(p, idx+1);
2559 offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
2560 if ((offset + 4) > radeon_bo_size(reloc->robj)) {
2561 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%llx, 0x%lx\n",
2562 offset + 4, radeon_bo_size(reloc->robj));
2563 return -EINVAL;
2564 }
Marek Olšák78857132012-03-19 03:09:33 +01002565 offset += reloc->lobj.gpu_offset;
2566 ib[idx+1] = offset;
2567 ib[idx+2] = upper_32_bits(offset) & 0xff;
Marek Olšákdd220a02012-01-27 12:17:59 -05002568 }
2569 /* Reading data from SRC_ADDRESS. */
2570 if (((idx_value >> 1) & 0x3) == 2) {
2571 u64 offset;
2572 r = evergreen_cs_packet_next_reloc(p, &reloc);
2573 if (r) {
2574 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n");
2575 return -EINVAL;
2576 }
2577 offset = radeon_get_ib_value(p, idx+3);
2578 offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
2579 if ((offset + 4) > radeon_bo_size(reloc->robj)) {
2580 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%llx, 0x%lx\n",
2581 offset + 4, radeon_bo_size(reloc->robj));
2582 return -EINVAL;
2583 }
Marek Olšák78857132012-03-19 03:09:33 +01002584 offset += reloc->lobj.gpu_offset;
2585 ib[idx+3] = offset;
2586 ib[idx+4] = upper_32_bits(offset) & 0xff;
Marek Olšákdd220a02012-01-27 12:17:59 -05002587 }
2588 break;
Jerome Glisse4613ca12012-12-19 12:26:45 -05002589 case PACKET3_MEM_WRITE:
2590 {
2591 u64 offset;
2592
2593 if (pkt->count != 3) {
2594 DRM_ERROR("bad MEM_WRITE (invalid count)\n");
2595 return -EINVAL;
2596 }
2597 r = evergreen_cs_packet_next_reloc(p, &reloc);
2598 if (r) {
2599 DRM_ERROR("bad MEM_WRITE (missing reloc)\n");
2600 return -EINVAL;
2601 }
2602 offset = radeon_get_ib_value(p, idx+0);
2603 offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL;
2604 if (offset & 0x7) {
2605 DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n");
2606 return -EINVAL;
2607 }
2608 if ((offset + 8) > radeon_bo_size(reloc->robj)) {
2609 DRM_ERROR("bad MEM_WRITE bo too small: 0x%llx, 0x%lx\n",
2610 offset + 8, radeon_bo_size(reloc->robj));
2611 return -EINVAL;
2612 }
2613 offset += reloc->lobj.gpu_offset;
2614 ib[idx+0] = offset;
2615 ib[idx+1] = upper_32_bits(offset) & 0xff;
2616 break;
2617 }
Marek Olšákdd220a02012-01-27 12:17:59 -05002618 case PACKET3_COPY_DW:
2619 if (pkt->count != 4) {
2620 DRM_ERROR("bad COPY_DW (invalid count)\n");
2621 return -EINVAL;
2622 }
2623 if (idx_value & 0x1) {
2624 u64 offset;
2625 /* SRC is memory. */
2626 r = evergreen_cs_packet_next_reloc(p, &reloc);
2627 if (r) {
2628 DRM_ERROR("bad COPY_DW (missing src reloc)\n");
2629 return -EINVAL;
2630 }
2631 offset = radeon_get_ib_value(p, idx+1);
2632 offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
2633 if ((offset + 4) > radeon_bo_size(reloc->robj)) {
2634 DRM_ERROR("bad COPY_DW src bo too small: 0x%llx, 0x%lx\n",
2635 offset + 4, radeon_bo_size(reloc->robj));
2636 return -EINVAL;
2637 }
Marek Olšák78857132012-03-19 03:09:33 +01002638 offset += reloc->lobj.gpu_offset;
2639 ib[idx+1] = offset;
2640 ib[idx+2] = upper_32_bits(offset) & 0xff;
Marek Olšákdd220a02012-01-27 12:17:59 -05002641 } else {
2642 /* SRC is a reg. */
2643 reg = radeon_get_ib_value(p, idx+1) << 2;
2644 if (!evergreen_is_safe_reg(p, reg, idx+1))
2645 return -EINVAL;
2646 }
2647 if (idx_value & 0x2) {
2648 u64 offset;
2649 /* DST is memory. */
2650 r = evergreen_cs_packet_next_reloc(p, &reloc);
2651 if (r) {
2652 DRM_ERROR("bad COPY_DW (missing dst reloc)\n");
2653 return -EINVAL;
2654 }
2655 offset = radeon_get_ib_value(p, idx+3);
2656 offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
2657 if ((offset + 4) > radeon_bo_size(reloc->robj)) {
2658 DRM_ERROR("bad COPY_DW dst bo too small: 0x%llx, 0x%lx\n",
2659 offset + 4, radeon_bo_size(reloc->robj));
2660 return -EINVAL;
2661 }
Marek Olšák78857132012-03-19 03:09:33 +01002662 offset += reloc->lobj.gpu_offset;
2663 ib[idx+3] = offset;
2664 ib[idx+4] = upper_32_bits(offset) & 0xff;
Marek Olšákdd220a02012-01-27 12:17:59 -05002665 } else {
2666 /* DST is a reg. */
2667 reg = radeon_get_ib_value(p, idx+3) << 2;
2668 if (!evergreen_is_safe_reg(p, reg, idx+3))
2669 return -EINVAL;
2670 }
2671 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002672 case PACKET3_NOP:
2673 break;
2674 default:
2675 DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
2676 return -EINVAL;
2677 }
2678 return 0;
2679}
2680
2681int evergreen_cs_parse(struct radeon_cs_parser *p)
2682{
2683 struct radeon_cs_packet pkt;
2684 struct evergreen_cs_track *track;
Alex Deucherf3a71df2011-11-28 14:49:28 -05002685 u32 tmp;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002686 int r;
2687
2688 if (p->track == NULL) {
2689 /* initialize tracker, we are in kms */
2690 track = kzalloc(sizeof(*track), GFP_KERNEL);
2691 if (track == NULL)
2692 return -ENOMEM;
2693 evergreen_cs_track_init(track);
Alex Deucherf3a71df2011-11-28 14:49:28 -05002694 if (p->rdev->family >= CHIP_CAYMAN)
2695 tmp = p->rdev->config.cayman.tile_config;
2696 else
2697 tmp = p->rdev->config.evergreen.tile_config;
2698
2699 switch (tmp & 0xf) {
2700 case 0:
2701 track->npipes = 1;
2702 break;
2703 case 1:
2704 default:
2705 track->npipes = 2;
2706 break;
2707 case 2:
2708 track->npipes = 4;
2709 break;
2710 case 3:
2711 track->npipes = 8;
2712 break;
2713 }
2714
2715 switch ((tmp & 0xf0) >> 4) {
2716 case 0:
2717 track->nbanks = 4;
2718 break;
2719 case 1:
2720 default:
2721 track->nbanks = 8;
2722 break;
2723 case 2:
2724 track->nbanks = 16;
2725 break;
2726 }
2727
2728 switch ((tmp & 0xf00) >> 8) {
2729 case 0:
2730 track->group_size = 256;
2731 break;
2732 case 1:
2733 default:
2734 track->group_size = 512;
2735 break;
2736 }
2737
2738 switch ((tmp & 0xf000) >> 12) {
2739 case 0:
2740 track->row_size = 1;
2741 break;
2742 case 1:
2743 default:
2744 track->row_size = 2;
2745 break;
2746 case 2:
2747 track->row_size = 4;
2748 break;
2749 }
2750
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002751 p->track = track;
2752 }
2753 do {
Ilija Hadzicc38f34b2013-01-02 18:27:41 -05002754 r = radeon_cs_packet_parse(p, &pkt, p->idx);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002755 if (r) {
2756 kfree(p->track);
2757 p->track = NULL;
2758 return r;
2759 }
2760 p->idx += pkt.count + 2;
2761 switch (pkt.type) {
2762 case PACKET_TYPE0:
2763 r = evergreen_cs_parse_packet0(p, &pkt);
2764 break;
2765 case PACKET_TYPE2:
2766 break;
2767 case PACKET_TYPE3:
2768 r = evergreen_packet3_check(p, &pkt);
2769 break;
2770 default:
2771 DRM_ERROR("Unknown packet type %d !\n", pkt.type);
2772 kfree(p->track);
2773 p->track = NULL;
2774 return -EINVAL;
2775 }
2776 if (r) {
2777 kfree(p->track);
2778 p->track = NULL;
2779 return r;
2780 }
2781 } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
2782#if 0
Jerome Glissef2e39222012-05-09 15:35:02 +02002783 for (r = 0; r < p->ib.length_dw; r++) {
2784 printk(KERN_INFO "%05d 0x%08X\n", r, p->ib.ptr[r]);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002785 mdelay(1);
2786 }
2787#endif
2788 kfree(p->track);
2789 p->track = NULL;
2790 return 0;
2791}
2792
Alex Deucherd2ead3e2012-12-13 09:55:45 -05002793/*
2794 * DMA
2795 */
2796
2797#define GET_DMA_CMD(h) (((h) & 0xf0000000) >> 28)
2798#define GET_DMA_COUNT(h) ((h) & 0x000fffff)
2799#define GET_DMA_T(h) (((h) & 0x00800000) >> 23)
2800#define GET_DMA_NEW(h) (((h) & 0x04000000) >> 26)
2801#define GET_DMA_MISC(h) (((h) & 0x0700000) >> 20)
2802
2803/**
2804 * evergreen_dma_cs_parse() - parse the DMA IB
2805 * @p: parser structure holding parsing context.
2806 *
2807 * Parses the DMA IB from the CS ioctl and updates
2808 * the GPU addresses based on the reloc information and
2809 * checks for errors. (Evergreen-Cayman)
2810 * Returns 0 for success and an error on failure.
2811 **/
2812int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
2813{
2814 struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
2815 struct radeon_cs_reloc *src_reloc, *dst_reloc, *dst2_reloc;
2816 u32 header, cmd, count, tiled, new_cmd, misc;
2817 volatile u32 *ib = p->ib.ptr;
2818 u32 idx, idx_value;
2819 u64 src_offset, dst_offset, dst2_offset;
2820 int r;
2821
2822 do {
2823 if (p->idx >= ib_chunk->length_dw) {
2824 DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
2825 p->idx, ib_chunk->length_dw);
2826 return -EINVAL;
2827 }
2828 idx = p->idx;
2829 header = radeon_get_ib_value(p, idx);
2830 cmd = GET_DMA_CMD(header);
2831 count = GET_DMA_COUNT(header);
2832 tiled = GET_DMA_T(header);
2833 new_cmd = GET_DMA_NEW(header);
2834 misc = GET_DMA_MISC(header);
2835
2836 switch (cmd) {
2837 case DMA_PACKET_WRITE:
2838 r = r600_dma_cs_next_reloc(p, &dst_reloc);
2839 if (r) {
2840 DRM_ERROR("bad DMA_PACKET_WRITE\n");
2841 return -EINVAL;
2842 }
2843 if (tiled) {
2844 dst_offset = ib[idx+1];
2845 dst_offset <<= 8;
2846
2847 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
2848 p->idx += count + 7;
2849 } else {
2850 dst_offset = ib[idx+1];
2851 dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32;
2852
2853 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
2854 ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
2855 p->idx += count + 3;
2856 }
2857 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
2858 dev_warn(p->dev, "DMA write buffer too small (%llu %lu)\n",
2859 dst_offset, radeon_bo_size(dst_reloc->robj));
2860 return -EINVAL;
2861 }
2862 break;
2863 case DMA_PACKET_COPY:
2864 r = r600_dma_cs_next_reloc(p, &src_reloc);
2865 if (r) {
2866 DRM_ERROR("bad DMA_PACKET_COPY\n");
2867 return -EINVAL;
2868 }
2869 r = r600_dma_cs_next_reloc(p, &dst_reloc);
2870 if (r) {
2871 DRM_ERROR("bad DMA_PACKET_COPY\n");
2872 return -EINVAL;
2873 }
2874 if (tiled) {
2875 idx_value = radeon_get_ib_value(p, idx + 2);
2876 if (new_cmd) {
2877 switch (misc) {
2878 case 0:
2879 /* L2T, frame to fields */
2880 if (idx_value & (1 << 31)) {
2881 DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
2882 return -EINVAL;
2883 }
2884 r = r600_dma_cs_next_reloc(p, &dst2_reloc);
2885 if (r) {
2886 DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
2887 return -EINVAL;
2888 }
2889 dst_offset = ib[idx+1];
2890 dst_offset <<= 8;
2891 dst2_offset = ib[idx+2];
2892 dst2_offset <<= 8;
2893 src_offset = ib[idx+8];
2894 src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
2895 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
2896 dev_warn(p->dev, "DMA L2T, frame to fields src buffer too small (%llu %lu)\n",
2897 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
2898 return -EINVAL;
2899 }
2900 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
2901 dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n",
2902 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
2903 return -EINVAL;
2904 }
2905 if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
2906 dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n",
2907 dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
2908 return -EINVAL;
2909 }
2910 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
2911 ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
2912 ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
2913 ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
2914 p->idx += 10;
2915 break;
2916 case 1:
2917 /* L2T, T2L partial */
2918 if (p->family < CHIP_CAYMAN) {
2919 DRM_ERROR("L2T, T2L Partial is cayman only !\n");
2920 return -EINVAL;
2921 }
2922 /* detile bit */
2923 if (idx_value & (1 << 31)) {
2924 /* tiled src, linear dst */
2925 ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
2926
2927 ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
2928 ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
2929 } else {
2930 /* linear src, tiled dst */
2931 ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
2932 ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
2933
2934 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
2935 }
2936 p->idx += 12;
2937 break;
2938 case 3:
2939 /* L2T, broadcast */
2940 if (idx_value & (1 << 31)) {
2941 DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
2942 return -EINVAL;
2943 }
2944 r = r600_dma_cs_next_reloc(p, &dst2_reloc);
2945 if (r) {
2946 DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
2947 return -EINVAL;
2948 }
2949 dst_offset = ib[idx+1];
2950 dst_offset <<= 8;
2951 dst2_offset = ib[idx+2];
2952 dst2_offset <<= 8;
2953 src_offset = ib[idx+8];
2954 src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
2955 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
2956 dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
2957 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
2958 return -EINVAL;
2959 }
2960 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
2961 dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
2962 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
2963 return -EINVAL;
2964 }
2965 if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
2966 dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n",
2967 dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
2968 return -EINVAL;
2969 }
2970 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
2971 ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
2972 ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
2973 ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
2974 p->idx += 10;
2975 break;
2976 case 4:
2977 /* L2T, T2L */
2978 /* detile bit */
2979 if (idx_value & (1 << 31)) {
2980 /* tiled src, linear dst */
2981 src_offset = ib[idx+1];
2982 src_offset <<= 8;
2983 ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
2984
2985 dst_offset = ib[idx+7];
2986 dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
2987 ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
2988 ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
2989 } else {
2990 /* linear src, tiled dst */
2991 src_offset = ib[idx+7];
2992 src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
2993 ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
2994 ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
2995
2996 dst_offset = ib[idx+1];
2997 dst_offset <<= 8;
2998 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
2999 }
3000 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
3001 dev_warn(p->dev, "DMA L2T, T2L src buffer too small (%llu %lu)\n",
3002 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
3003 return -EINVAL;
3004 }
3005 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3006 dev_warn(p->dev, "DMA L2T, T2L dst buffer too small (%llu %lu)\n",
3007 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
3008 return -EINVAL;
3009 }
3010 p->idx += 9;
3011 break;
3012 case 5:
3013 /* T2T partial */
3014 if (p->family < CHIP_CAYMAN) {
3015 DRM_ERROR("L2T, T2L Partial is cayman only !\n");
3016 return -EINVAL;
3017 }
3018 ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
3019 ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
3020 p->idx += 13;
3021 break;
3022 case 7:
3023 /* L2T, broadcast */
3024 if (idx_value & (1 << 31)) {
3025 DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
3026 return -EINVAL;
3027 }
3028 r = r600_dma_cs_next_reloc(p, &dst2_reloc);
3029 if (r) {
3030 DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
3031 return -EINVAL;
3032 }
3033 dst_offset = ib[idx+1];
3034 dst_offset <<= 8;
3035 dst2_offset = ib[idx+2];
3036 dst2_offset <<= 8;
3037 src_offset = ib[idx+8];
3038 src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
3039 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
3040 dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
3041 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
3042 return -EINVAL;
3043 }
3044 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3045 dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
3046 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
3047 return -EINVAL;
3048 }
3049 if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
3050 dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n",
3051 dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
3052 return -EINVAL;
3053 }
3054 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
3055 ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
3056 ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
3057 ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3058 p->idx += 10;
3059 break;
3060 default:
3061 DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
3062 return -EINVAL;
3063 }
3064 } else {
3065 switch (misc) {
3066 case 0:
3067 /* detile bit */
3068 if (idx_value & (1 << 31)) {
3069 /* tiled src, linear dst */
3070 src_offset = ib[idx+1];
3071 src_offset <<= 8;
3072 ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
3073
3074 dst_offset = ib[idx+7];
3075 dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
3076 ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
3077 ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
3078 } else {
3079 /* linear src, tiled dst */
3080 src_offset = ib[idx+7];
3081 src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
3082 ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
3083 ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3084
3085 dst_offset = ib[idx+1];
3086 dst_offset <<= 8;
3087 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
3088 }
3089 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
3090 dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
3091 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
3092 return -EINVAL;
3093 }
3094 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3095 dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
3096 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
3097 return -EINVAL;
3098 }
3099 p->idx += 9;
3100 break;
3101 default:
3102 DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
3103 return -EINVAL;
3104 }
3105 }
3106 } else {
3107 if (new_cmd) {
3108 switch (misc) {
3109 case 0:
3110 /* L2L, byte */
3111 src_offset = ib[idx+2];
3112 src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
3113 dst_offset = ib[idx+1];
3114 dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
3115 if ((src_offset + count) > radeon_bo_size(src_reloc->robj)) {
3116 dev_warn(p->dev, "DMA L2L, byte src buffer too small (%llu %lu)\n",
3117 src_offset + count, radeon_bo_size(src_reloc->robj));
3118 return -EINVAL;
3119 }
3120 if ((dst_offset + count) > radeon_bo_size(dst_reloc->robj)) {
3121 dev_warn(p->dev, "DMA L2L, byte dst buffer too small (%llu %lu)\n",
3122 dst_offset + count, radeon_bo_size(dst_reloc->robj));
3123 return -EINVAL;
3124 }
3125 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff);
3126 ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff);
3127 ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
3128 ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3129 p->idx += 5;
3130 break;
3131 case 1:
3132 /* L2L, partial */
3133 if (p->family < CHIP_CAYMAN) {
3134 DRM_ERROR("L2L Partial is cayman only !\n");
3135 return -EINVAL;
3136 }
3137 ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff);
3138 ib[idx+2] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3139 ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff);
3140 ib[idx+5] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
3141
3142 p->idx += 9;
3143 break;
3144 case 4:
3145 /* L2L, dw, broadcast */
3146 r = r600_dma_cs_next_reloc(p, &dst2_reloc);
3147 if (r) {
3148 DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n");
3149 return -EINVAL;
3150 }
3151 dst_offset = ib[idx+1];
3152 dst_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
3153 dst2_offset = ib[idx+2];
3154 dst2_offset |= ((u64)(ib[idx+5] & 0xff)) << 32;
3155 src_offset = ib[idx+3];
3156 src_offset |= ((u64)(ib[idx+6] & 0xff)) << 32;
3157 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
3158 dev_warn(p->dev, "DMA L2L, dw, broadcast src buffer too small (%llu %lu)\n",
3159 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
3160 return -EINVAL;
3161 }
3162 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3163 dev_warn(p->dev, "DMA L2L, dw, broadcast dst buffer too small (%llu %lu)\n",
3164 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
3165 return -EINVAL;
3166 }
3167 if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
3168 dev_warn(p->dev, "DMA L2L, dw, broadcast dst2 buffer too small (%llu %lu)\n",
3169 dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
3170 return -EINVAL;
3171 }
3172 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
3173 ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset & 0xfffffffc);
3174 ib[idx+3] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
3175 ib[idx+4] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
3176 ib[idx+5] += upper_32_bits(dst2_reloc->lobj.gpu_offset) & 0xff;
3177 ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3178 p->idx += 7;
3179 break;
3180 default:
3181 DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
3182 return -EINVAL;
3183 }
3184 } else {
3185 /* L2L, dw */
3186 src_offset = ib[idx+2];
3187 src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
3188 dst_offset = ib[idx+1];
3189 dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
3190 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
3191 dev_warn(p->dev, "DMA L2L, dw src buffer too small (%llu %lu)\n",
3192 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
3193 return -EINVAL;
3194 }
3195 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3196 dev_warn(p->dev, "DMA L2L, dw dst buffer too small (%llu %lu)\n",
3197 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
3198 return -EINVAL;
3199 }
3200 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
3201 ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
3202 ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
3203 ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3204 p->idx += 5;
3205 }
3206 }
3207 break;
3208 case DMA_PACKET_CONSTANT_FILL:
3209 r = r600_dma_cs_next_reloc(p, &dst_reloc);
3210 if (r) {
3211 DRM_ERROR("bad DMA_PACKET_CONSTANT_FILL\n");
3212 return -EINVAL;
3213 }
3214 dst_offset = ib[idx+1];
3215 dst_offset |= ((u64)(ib[idx+3] & 0x00ff0000)) << 16;
3216 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3217 dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n",
3218 dst_offset, radeon_bo_size(dst_reloc->robj));
3219 return -EINVAL;
3220 }
3221 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
3222 ib[idx+3] += (upper_32_bits(dst_reloc->lobj.gpu_offset) << 16) & 0x00ff0000;
3223 p->idx += 4;
3224 break;
3225 case DMA_PACKET_NOP:
3226 p->idx += 1;
3227 break;
3228 default:
3229 DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx);
3230 return -EINVAL;
3231 }
3232 } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
3233#if 0
3234 for (r = 0; r < p->ib->length_dw; r++) {
3235 printk(KERN_INFO "%05d 0x%08X\n", r, p->ib.ptr[r]);
3236 mdelay(1);
3237 }
3238#endif
3239 return 0;
3240}
3241
Jerome Glisse721604a2012-01-05 22:11:05 -05003242/* vm parser */
3243static bool evergreen_vm_reg_valid(u32 reg)
3244{
3245 /* context regs are fine */
3246 if (reg >= 0x28000)
3247 return true;
3248
3249 /* check config regs */
3250 switch (reg) {
Alex Deucher668bbc82012-12-20 21:19:32 -05003251 case WAIT_UNTIL:
Jerome Glisse721604a2012-01-05 22:11:05 -05003252 case GRBM_GFX_INDEX:
Alex Deucher860fe2f2012-11-08 10:08:04 -05003253 case CP_STRMOUT_CNTL:
3254 case CP_COHER_CNTL:
3255 case CP_COHER_SIZE:
Jerome Glisse721604a2012-01-05 22:11:05 -05003256 case VGT_VTX_VECT_EJECT_REG:
3257 case VGT_CACHE_INVALIDATION:
3258 case VGT_GS_VERTEX_REUSE:
3259 case VGT_PRIMITIVE_TYPE:
3260 case VGT_INDEX_TYPE:
3261 case VGT_NUM_INDICES:
3262 case VGT_NUM_INSTANCES:
3263 case VGT_COMPUTE_DIM_X:
3264 case VGT_COMPUTE_DIM_Y:
3265 case VGT_COMPUTE_DIM_Z:
3266 case VGT_COMPUTE_START_X:
3267 case VGT_COMPUTE_START_Y:
3268 case VGT_COMPUTE_START_Z:
3269 case VGT_COMPUTE_INDEX:
3270 case VGT_COMPUTE_THREAD_GROUP_SIZE:
3271 case VGT_HS_OFFCHIP_PARAM:
3272 case PA_CL_ENHANCE:
3273 case PA_SU_LINE_STIPPLE_VALUE:
3274 case PA_SC_LINE_STIPPLE_STATE:
3275 case PA_SC_ENHANCE:
3276 case SQ_DYN_GPR_CNTL_PS_FLUSH_REQ:
3277 case SQ_DYN_GPR_SIMD_LOCK_EN:
3278 case SQ_CONFIG:
3279 case SQ_GPR_RESOURCE_MGMT_1:
3280 case SQ_GLOBAL_GPR_RESOURCE_MGMT_1:
3281 case SQ_GLOBAL_GPR_RESOURCE_MGMT_2:
3282 case SQ_CONST_MEM_BASE:
3283 case SQ_STATIC_THREAD_MGMT_1:
3284 case SQ_STATIC_THREAD_MGMT_2:
3285 case SQ_STATIC_THREAD_MGMT_3:
3286 case SPI_CONFIG_CNTL:
3287 case SPI_CONFIG_CNTL_1:
3288 case TA_CNTL_AUX:
3289 case DB_DEBUG:
3290 case DB_DEBUG2:
3291 case DB_DEBUG3:
3292 case DB_DEBUG4:
3293 case DB_WATERMARKS:
3294 case TD_PS_BORDER_COLOR_INDEX:
3295 case TD_PS_BORDER_COLOR_RED:
3296 case TD_PS_BORDER_COLOR_GREEN:
3297 case TD_PS_BORDER_COLOR_BLUE:
3298 case TD_PS_BORDER_COLOR_ALPHA:
3299 case TD_VS_BORDER_COLOR_INDEX:
3300 case TD_VS_BORDER_COLOR_RED:
3301 case TD_VS_BORDER_COLOR_GREEN:
3302 case TD_VS_BORDER_COLOR_BLUE:
3303 case TD_VS_BORDER_COLOR_ALPHA:
3304 case TD_GS_BORDER_COLOR_INDEX:
3305 case TD_GS_BORDER_COLOR_RED:
3306 case TD_GS_BORDER_COLOR_GREEN:
3307 case TD_GS_BORDER_COLOR_BLUE:
3308 case TD_GS_BORDER_COLOR_ALPHA:
3309 case TD_HS_BORDER_COLOR_INDEX:
3310 case TD_HS_BORDER_COLOR_RED:
3311 case TD_HS_BORDER_COLOR_GREEN:
3312 case TD_HS_BORDER_COLOR_BLUE:
3313 case TD_HS_BORDER_COLOR_ALPHA:
3314 case TD_LS_BORDER_COLOR_INDEX:
3315 case TD_LS_BORDER_COLOR_RED:
3316 case TD_LS_BORDER_COLOR_GREEN:
3317 case TD_LS_BORDER_COLOR_BLUE:
3318 case TD_LS_BORDER_COLOR_ALPHA:
3319 case TD_CS_BORDER_COLOR_INDEX:
3320 case TD_CS_BORDER_COLOR_RED:
3321 case TD_CS_BORDER_COLOR_GREEN:
3322 case TD_CS_BORDER_COLOR_BLUE:
3323 case TD_CS_BORDER_COLOR_ALPHA:
3324 case SQ_ESGS_RING_SIZE:
3325 case SQ_GSVS_RING_SIZE:
3326 case SQ_ESTMP_RING_SIZE:
3327 case SQ_GSTMP_RING_SIZE:
3328 case SQ_HSTMP_RING_SIZE:
3329 case SQ_LSTMP_RING_SIZE:
3330 case SQ_PSTMP_RING_SIZE:
3331 case SQ_VSTMP_RING_SIZE:
3332 case SQ_ESGS_RING_ITEMSIZE:
3333 case SQ_ESTMP_RING_ITEMSIZE:
3334 case SQ_GSTMP_RING_ITEMSIZE:
3335 case SQ_GSVS_RING_ITEMSIZE:
3336 case SQ_GS_VERT_ITEMSIZE:
3337 case SQ_GS_VERT_ITEMSIZE_1:
3338 case SQ_GS_VERT_ITEMSIZE_2:
3339 case SQ_GS_VERT_ITEMSIZE_3:
3340 case SQ_GSVS_RING_OFFSET_1:
3341 case SQ_GSVS_RING_OFFSET_2:
3342 case SQ_GSVS_RING_OFFSET_3:
3343 case SQ_HSTMP_RING_ITEMSIZE:
3344 case SQ_LSTMP_RING_ITEMSIZE:
3345 case SQ_PSTMP_RING_ITEMSIZE:
3346 case SQ_VSTMP_RING_ITEMSIZE:
3347 case VGT_TF_RING_SIZE:
3348 case SQ_ESGS_RING_BASE:
3349 case SQ_GSVS_RING_BASE:
3350 case SQ_ESTMP_RING_BASE:
3351 case SQ_GSTMP_RING_BASE:
3352 case SQ_HSTMP_RING_BASE:
3353 case SQ_LSTMP_RING_BASE:
3354 case SQ_PSTMP_RING_BASE:
3355 case SQ_VSTMP_RING_BASE:
3356 case CAYMAN_VGT_OFFCHIP_LDS_BASE:
3357 case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS:
3358 return true;
3359 default:
Alex Deucherc7172132012-10-19 13:27:04 -04003360 DRM_ERROR("Invalid register 0x%x in CS\n", reg);
Jerome Glisse721604a2012-01-05 22:11:05 -05003361 return false;
3362 }
3363}
3364
3365static int evergreen_vm_packet3_check(struct radeon_device *rdev,
3366 u32 *ib, struct radeon_cs_packet *pkt)
3367{
3368 u32 idx = pkt->idx + 1;
3369 u32 idx_value = ib[idx];
3370 u32 start_reg, end_reg, reg, i;
Alex Deucher94e014e2012-12-03 19:32:54 -05003371 u32 command, info;
Jerome Glisse721604a2012-01-05 22:11:05 -05003372
3373 switch (pkt->opcode) {
3374 case PACKET3_NOP:
3375 case PACKET3_SET_BASE:
3376 case PACKET3_CLEAR_STATE:
3377 case PACKET3_INDEX_BUFFER_SIZE:
3378 case PACKET3_DISPATCH_DIRECT:
3379 case PACKET3_DISPATCH_INDIRECT:
3380 case PACKET3_MODE_CONTROL:
3381 case PACKET3_SET_PREDICATION:
3382 case PACKET3_COND_EXEC:
3383 case PACKET3_PRED_EXEC:
3384 case PACKET3_DRAW_INDIRECT:
3385 case PACKET3_DRAW_INDEX_INDIRECT:
3386 case PACKET3_INDEX_BASE:
3387 case PACKET3_DRAW_INDEX_2:
3388 case PACKET3_CONTEXT_CONTROL:
3389 case PACKET3_DRAW_INDEX_OFFSET:
3390 case PACKET3_INDEX_TYPE:
3391 case PACKET3_DRAW_INDEX:
3392 case PACKET3_DRAW_INDEX_AUTO:
3393 case PACKET3_DRAW_INDEX_IMMD:
3394 case PACKET3_NUM_INSTANCES:
3395 case PACKET3_DRAW_INDEX_MULTI_AUTO:
3396 case PACKET3_STRMOUT_BUFFER_UPDATE:
3397 case PACKET3_DRAW_INDEX_OFFSET_2:
3398 case PACKET3_DRAW_INDEX_MULTI_ELEMENT:
3399 case PACKET3_MPEG_INDEX:
3400 case PACKET3_WAIT_REG_MEM:
3401 case PACKET3_MEM_WRITE:
3402 case PACKET3_SURFACE_SYNC:
3403 case PACKET3_EVENT_WRITE:
3404 case PACKET3_EVENT_WRITE_EOP:
3405 case PACKET3_EVENT_WRITE_EOS:
3406 case PACKET3_SET_CONTEXT_REG:
3407 case PACKET3_SET_BOOL_CONST:
3408 case PACKET3_SET_LOOP_CONST:
3409 case PACKET3_SET_RESOURCE:
3410 case PACKET3_SET_SAMPLER:
3411 case PACKET3_SET_CTL_CONST:
3412 case PACKET3_SET_RESOURCE_OFFSET:
3413 case PACKET3_SET_CONTEXT_REG_INDIRECT:
3414 case PACKET3_SET_RESOURCE_INDIRECT:
3415 case CAYMAN_PACKET3_DEALLOC_STATE:
3416 break;
3417 case PACKET3_COND_WRITE:
3418 if (idx_value & 0x100) {
3419 reg = ib[idx + 5] * 4;
3420 if (!evergreen_vm_reg_valid(reg))
3421 return -EINVAL;
3422 }
3423 break;
3424 case PACKET3_COPY_DW:
3425 if (idx_value & 0x2) {
3426 reg = ib[idx + 3] * 4;
3427 if (!evergreen_vm_reg_valid(reg))
3428 return -EINVAL;
3429 }
3430 break;
3431 case PACKET3_SET_CONFIG_REG:
3432 start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START;
3433 end_reg = 4 * pkt->count + start_reg - 4;
3434 if ((start_reg < PACKET3_SET_CONFIG_REG_START) ||
3435 (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
3436 (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
3437 DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
3438 return -EINVAL;
3439 }
3440 for (i = 0; i < pkt->count; i++) {
3441 reg = start_reg + (4 * i);
3442 if (!evergreen_vm_reg_valid(reg))
3443 return -EINVAL;
3444 }
3445 break;
Alex Deucher94e014e2012-12-03 19:32:54 -05003446 case PACKET3_CP_DMA:
3447 command = ib[idx + 4];
3448 info = ib[idx + 1];
Alex Deucher9d89d782012-12-14 00:23:06 -05003449 if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */
3450 (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */
3451 ((((info & 0x00300000) >> 20) == 0) &&
3452 (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */
3453 ((((info & 0x60000000) >> 29) == 0) &&
3454 (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */
3455 /* non mem to mem copies requires dw aligned count */
3456 if ((command & 0x1fffff) % 4) {
3457 DRM_ERROR("CP DMA command requires dw count alignment\n");
3458 return -EINVAL;
3459 }
3460 }
Alex Deucher94e014e2012-12-03 19:32:54 -05003461 if (command & PACKET3_CP_DMA_CMD_SAS) {
3462 /* src address space is register */
3463 if (((info & 0x60000000) >> 29) == 0) {
3464 start_reg = idx_value << 2;
3465 if (command & PACKET3_CP_DMA_CMD_SAIC) {
3466 reg = start_reg;
3467 if (!evergreen_vm_reg_valid(reg)) {
3468 DRM_ERROR("CP DMA Bad SRC register\n");
3469 return -EINVAL;
3470 }
3471 } else {
3472 for (i = 0; i < (command & 0x1fffff); i++) {
3473 reg = start_reg + (4 * i);
3474 if (!evergreen_vm_reg_valid(reg)) {
3475 DRM_ERROR("CP DMA Bad SRC register\n");
3476 return -EINVAL;
3477 }
3478 }
3479 }
3480 }
3481 }
3482 if (command & PACKET3_CP_DMA_CMD_DAS) {
3483 /* dst address space is register */
3484 if (((info & 0x00300000) >> 20) == 0) {
3485 start_reg = ib[idx + 2];
3486 if (command & PACKET3_CP_DMA_CMD_DAIC) {
3487 reg = start_reg;
3488 if (!evergreen_vm_reg_valid(reg)) {
3489 DRM_ERROR("CP DMA Bad DST register\n");
3490 return -EINVAL;
3491 }
3492 } else {
3493 for (i = 0; i < (command & 0x1fffff); i++) {
3494 reg = start_reg + (4 * i);
3495 if (!evergreen_vm_reg_valid(reg)) {
3496 DRM_ERROR("CP DMA Bad DST register\n");
3497 return -EINVAL;
3498 }
3499 }
3500 }
3501 }
3502 }
3503 break;
Jerome Glisse721604a2012-01-05 22:11:05 -05003504 default:
3505 return -EINVAL;
3506 }
3507 return 0;
3508}
3509
3510int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
3511{
3512 int ret = 0;
3513 u32 idx = 0;
3514 struct radeon_cs_packet pkt;
3515
3516 do {
3517 pkt.idx = idx;
3518 pkt.type = CP_PACKET_GET_TYPE(ib->ptr[idx]);
3519 pkt.count = CP_PACKET_GET_COUNT(ib->ptr[idx]);
3520 pkt.one_reg_wr = 0;
3521 switch (pkt.type) {
3522 case PACKET_TYPE0:
3523 dev_err(rdev->dev, "Packet0 not allowed!\n");
3524 ret = -EINVAL;
3525 break;
3526 case PACKET_TYPE2:
Alex Deucher0b41da62012-01-12 15:42:37 -05003527 idx += 1;
Jerome Glisse721604a2012-01-05 22:11:05 -05003528 break;
3529 case PACKET_TYPE3:
3530 pkt.opcode = CP_PACKET3_GET_OPCODE(ib->ptr[idx]);
3531 ret = evergreen_vm_packet3_check(rdev, ib->ptr, &pkt);
Alex Deucher0b41da62012-01-12 15:42:37 -05003532 idx += pkt.count + 2;
Jerome Glisse721604a2012-01-05 22:11:05 -05003533 break;
3534 default:
3535 dev_err(rdev->dev, "Unknown packet type %d !\n", pkt.type);
3536 ret = -EINVAL;
3537 break;
3538 }
3539 if (ret)
3540 break;
Jerome Glisse721604a2012-01-05 22:11:05 -05003541 } while (idx < ib->length_dw);
3542
3543 return ret;
3544}
Alex Deuchercd459e52012-12-13 12:17:38 -05003545
3546/**
3547 * evergreen_dma_ib_parse() - parse the DMA IB for VM
3548 * @rdev: radeon_device pointer
3549 * @ib: radeon_ib pointer
3550 *
3551 * Parses the DMA IB from the VM CS ioctl
3552 * checks for errors. (Cayman-SI)
3553 * Returns 0 for success and an error on failure.
3554 **/
3555int evergreen_dma_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
3556{
3557 u32 idx = 0;
3558 u32 header, cmd, count, tiled, new_cmd, misc;
3559
3560 do {
3561 header = ib->ptr[idx];
3562 cmd = GET_DMA_CMD(header);
3563 count = GET_DMA_COUNT(header);
3564 tiled = GET_DMA_T(header);
3565 new_cmd = GET_DMA_NEW(header);
3566 misc = GET_DMA_MISC(header);
3567
3568 switch (cmd) {
3569 case DMA_PACKET_WRITE:
3570 if (tiled)
3571 idx += count + 7;
3572 else
3573 idx += count + 3;
3574 break;
3575 case DMA_PACKET_COPY:
3576 if (tiled) {
3577 if (new_cmd) {
3578 switch (misc) {
3579 case 0:
3580 /* L2T, frame to fields */
3581 idx += 10;
3582 break;
3583 case 1:
3584 /* L2T, T2L partial */
3585 idx += 12;
3586 break;
3587 case 3:
3588 /* L2T, broadcast */
3589 idx += 10;
3590 break;
3591 case 4:
3592 /* L2T, T2L */
3593 idx += 9;
3594 break;
3595 case 5:
3596 /* T2T partial */
3597 idx += 13;
3598 break;
3599 case 7:
3600 /* L2T, broadcast */
3601 idx += 10;
3602 break;
3603 default:
3604 DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
3605 return -EINVAL;
3606 }
3607 } else {
3608 switch (misc) {
3609 case 0:
3610 idx += 9;
3611 break;
3612 default:
3613 DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
3614 return -EINVAL;
3615 }
3616 }
3617 } else {
3618 if (new_cmd) {
3619 switch (misc) {
3620 case 0:
3621 /* L2L, byte */
3622 idx += 5;
3623 break;
3624 case 1:
3625 /* L2L, partial */
3626 idx += 9;
3627 break;
3628 case 4:
3629 /* L2L, dw, broadcast */
3630 idx += 7;
3631 break;
3632 default:
3633 DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
3634 return -EINVAL;
3635 }
3636 } else {
3637 /* L2L, dw */
3638 idx += 5;
3639 }
3640 }
3641 break;
3642 case DMA_PACKET_CONSTANT_FILL:
3643 idx += 4;
3644 break;
3645 case DMA_PACKET_NOP:
3646 idx += 1;
3647 break;
3648 default:
3649 DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx);
3650 return -EINVAL;
3651 }
3652 } while (idx < ib->length_dw);
3653
3654 return 0;
3655}