blob: 1ba4ca38f4f9fd06e5d30311eea4a4b15cf33edd [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/**
Marek Olšák61051af2012-09-25 03:34:01 +02001058 * evergreen_cs_packet_next_is_pkt3_nop() - test if the next packet is NOP
1059 * @p: structure holding the parser context.
1060 *
1061 * Check if the next packet is a relocation packet3.
1062 **/
1063static bool evergreen_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
1064{
1065 struct radeon_cs_packet p3reloc;
1066 int r;
1067
Ilija Hadzicc38f34b2013-01-02 18:27:41 -05001068 r = radeon_cs_packet_parse(p, &p3reloc, p->idx);
Marek Olšák61051af2012-09-25 03:34:01 +02001069 if (r) {
1070 return false;
1071 }
1072 if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
1073 return false;
1074 }
1075 return true;
1076}
1077
1078/**
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001079 * evergreen_cs_packet_next_vline() - parse userspace VLINE packet
1080 * @parser: parser structure holding parsing context.
1081 *
1082 * Userspace sends a special sequence for VLINE waits.
1083 * PACKET0 - VLINE_START_END + value
1084 * PACKET3 - WAIT_REG_MEM poll vline status reg
1085 * RELOC (P3) - crtc_id in reloc.
1086 *
1087 * This function parses this and relocates the VLINE START END
1088 * and WAIT_REG_MEM packets to the correct crtc.
1089 * It also detects a switched off crtc and nulls out the
1090 * wait in that case.
1091 */
1092static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
1093{
1094 struct drm_mode_object *obj;
1095 struct drm_crtc *crtc;
1096 struct radeon_crtc *radeon_crtc;
1097 struct radeon_cs_packet p3reloc, wait_reg_mem;
1098 int crtc_id;
1099 int r;
1100 uint32_t header, h_idx, reg, wait_reg_mem_info;
1101 volatile uint32_t *ib;
1102
Jerome Glissef2e39222012-05-09 15:35:02 +02001103 ib = p->ib.ptr;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001104
1105 /* parse the WAIT_REG_MEM */
Ilija Hadzicc38f34b2013-01-02 18:27:41 -05001106 r = radeon_cs_packet_parse(p, &wait_reg_mem, p->idx);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001107 if (r)
1108 return r;
1109
1110 /* check its a WAIT_REG_MEM */
1111 if (wait_reg_mem.type != PACKET_TYPE3 ||
1112 wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
1113 DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
Paul Bollea3a88a62011-03-16 22:10:06 +01001114 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001115 }
1116
1117 wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
1118 /* bit 4 is reg (0) or mem (1) */
1119 if (wait_reg_mem_info & 0x10) {
1120 DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
Paul Bollea3a88a62011-03-16 22:10:06 +01001121 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001122 }
1123 /* waiting for value to be equal */
1124 if ((wait_reg_mem_info & 0x7) != 0x3) {
1125 DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
Paul Bollea3a88a62011-03-16 22:10:06 +01001126 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001127 }
1128 if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != EVERGREEN_VLINE_STATUS) {
1129 DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
Paul Bollea3a88a62011-03-16 22:10:06 +01001130 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001131 }
1132
1133 if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != EVERGREEN_VLINE_STAT) {
1134 DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
Paul Bollea3a88a62011-03-16 22:10:06 +01001135 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001136 }
1137
1138 /* jump over the NOP */
Ilija Hadzicc38f34b2013-01-02 18:27:41 -05001139 r = radeon_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001140 if (r)
1141 return r;
1142
1143 h_idx = p->idx - 2;
1144 p->idx += wait_reg_mem.count + 2;
1145 p->idx += p3reloc.count + 2;
1146
1147 header = radeon_get_ib_value(p, h_idx);
1148 crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
1149 reg = CP_PACKET0_GET_REG(header);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001150 obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
1151 if (!obj) {
1152 DRM_ERROR("cannot find crtc %d\n", crtc_id);
Paul Bollea3a88a62011-03-16 22:10:06 +01001153 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001154 }
1155 crtc = obj_to_crtc(obj);
1156 radeon_crtc = to_radeon_crtc(crtc);
1157 crtc_id = radeon_crtc->crtc_id;
1158
1159 if (!crtc->enabled) {
1160 /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
1161 ib[h_idx + 2] = PACKET2(0);
1162 ib[h_idx + 3] = PACKET2(0);
1163 ib[h_idx + 4] = PACKET2(0);
1164 ib[h_idx + 5] = PACKET2(0);
1165 ib[h_idx + 6] = PACKET2(0);
1166 ib[h_idx + 7] = PACKET2(0);
1167 ib[h_idx + 8] = PACKET2(0);
1168 } else {
1169 switch (reg) {
1170 case EVERGREEN_VLINE_START_END:
1171 header &= ~R600_CP_PACKET0_REG_MASK;
1172 header |= (EVERGREEN_VLINE_START_END + radeon_crtc->crtc_offset) >> 2;
1173 ib[h_idx] = header;
1174 ib[h_idx + 4] = (EVERGREEN_VLINE_STATUS + radeon_crtc->crtc_offset) >> 2;
1175 break;
1176 default:
1177 DRM_ERROR("unknown crtc reloc\n");
Paul Bollea3a88a62011-03-16 22:10:06 +01001178 return -EINVAL;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001179 }
1180 }
Paul Bollea3a88a62011-03-16 22:10:06 +01001181 return 0;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001182}
1183
1184static int evergreen_packet0_check(struct radeon_cs_parser *p,
1185 struct radeon_cs_packet *pkt,
1186 unsigned idx, unsigned reg)
1187{
1188 int r;
1189
1190 switch (reg) {
1191 case EVERGREEN_VLINE_START_END:
1192 r = evergreen_cs_packet_parse_vline(p);
1193 if (r) {
1194 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
1195 idx, reg);
1196 return r;
1197 }
1198 break;
1199 default:
1200 printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
1201 reg, idx);
1202 return -EINVAL;
1203 }
1204 return 0;
1205}
1206
1207static int evergreen_cs_parse_packet0(struct radeon_cs_parser *p,
1208 struct radeon_cs_packet *pkt)
1209{
1210 unsigned reg, i;
1211 unsigned idx;
1212 int r;
1213
1214 idx = pkt->idx + 1;
1215 reg = pkt->reg;
1216 for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
1217 r = evergreen_packet0_check(p, pkt, idx, reg);
1218 if (r) {
1219 return r;
1220 }
1221 }
1222 return 0;
1223}
1224
1225/**
1226 * evergreen_cs_check_reg() - check if register is authorized or not
1227 * @parser: parser structure holding parsing context
1228 * @reg: register we are testing
1229 * @idx: index into the cs buffer
1230 *
1231 * This function will test against evergreen_reg_safe_bm and return 0
1232 * if register is safe. If register is not flag as safe this function
1233 * will test it against a list of register needind special handling.
1234 */
Andi Kleen488479e2011-10-13 16:08:41 -07001235static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001236{
1237 struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track;
1238 struct radeon_cs_reloc *reloc;
Alex Deucherc175ca92011-03-02 20:07:37 -05001239 u32 last_reg;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001240 u32 m, i, tmp, *ib;
1241 int r;
1242
Alex Deucherc175ca92011-03-02 20:07:37 -05001243 if (p->rdev->family >= CHIP_CAYMAN)
1244 last_reg = ARRAY_SIZE(cayman_reg_safe_bm);
1245 else
1246 last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
1247
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001248 i = (reg >> 7);
Dan Carpenter88498832011-07-27 09:53:40 +00001249 if (i >= last_reg) {
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001250 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
1251 return -EINVAL;
1252 }
1253 m = 1 << ((reg >> 2) & 31);
Alex Deucherc175ca92011-03-02 20:07:37 -05001254 if (p->rdev->family >= CHIP_CAYMAN) {
1255 if (!(cayman_reg_safe_bm[i] & m))
1256 return 0;
1257 } else {
1258 if (!(evergreen_reg_safe_bm[i] & m))
1259 return 0;
1260 }
Jerome Glissef2e39222012-05-09 15:35:02 +02001261 ib = p->ib.ptr;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001262 switch (reg) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001263 /* force following reg to 0 in an attempt to disable out buffer
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001264 * which will need us to better understand how it works to perform
1265 * security check on it (Jerome)
1266 */
1267 case SQ_ESGS_RING_SIZE:
1268 case SQ_GSVS_RING_SIZE:
1269 case SQ_ESTMP_RING_SIZE:
1270 case SQ_GSTMP_RING_SIZE:
1271 case SQ_HSTMP_RING_SIZE:
1272 case SQ_LSTMP_RING_SIZE:
1273 case SQ_PSTMP_RING_SIZE:
1274 case SQ_VSTMP_RING_SIZE:
1275 case SQ_ESGS_RING_ITEMSIZE:
1276 case SQ_ESTMP_RING_ITEMSIZE:
1277 case SQ_GSTMP_RING_ITEMSIZE:
1278 case SQ_GSVS_RING_ITEMSIZE:
1279 case SQ_GS_VERT_ITEMSIZE:
1280 case SQ_GS_VERT_ITEMSIZE_1:
1281 case SQ_GS_VERT_ITEMSIZE_2:
1282 case SQ_GS_VERT_ITEMSIZE_3:
1283 case SQ_GSVS_RING_OFFSET_1:
1284 case SQ_GSVS_RING_OFFSET_2:
1285 case SQ_GSVS_RING_OFFSET_3:
1286 case SQ_HSTMP_RING_ITEMSIZE:
1287 case SQ_LSTMP_RING_ITEMSIZE:
1288 case SQ_PSTMP_RING_ITEMSIZE:
1289 case SQ_VSTMP_RING_ITEMSIZE:
1290 case VGT_TF_RING_SIZE:
1291 /* get value to populate the IB don't remove */
Alex Deucher8aa75002011-03-02 20:07:40 -05001292 /*tmp =radeon_get_ib_value(p, idx);
1293 ib[idx] = 0;*/
1294 break;
1295 case SQ_ESGS_RING_BASE:
1296 case SQ_GSVS_RING_BASE:
1297 case SQ_ESTMP_RING_BASE:
1298 case SQ_GSTMP_RING_BASE:
1299 case SQ_HSTMP_RING_BASE:
1300 case SQ_LSTMP_RING_BASE:
1301 case SQ_PSTMP_RING_BASE:
1302 case SQ_VSTMP_RING_BASE:
1303 r = evergreen_cs_packet_next_reloc(p, &reloc);
1304 if (r) {
1305 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1306 "0x%04X\n", reg);
1307 return -EINVAL;
1308 }
1309 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001310 break;
1311 case DB_DEPTH_CONTROL:
1312 track->db_depth_control = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001313 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001314 break;
Alex Deucherc175ca92011-03-02 20:07:37 -05001315 case CAYMAN_DB_EQAA:
1316 if (p->rdev->family < CHIP_CAYMAN) {
1317 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1318 "0x%04X\n", reg);
1319 return -EINVAL;
1320 }
1321 break;
1322 case CAYMAN_DB_DEPTH_INFO:
1323 if (p->rdev->family < CHIP_CAYMAN) {
1324 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1325 "0x%04X\n", reg);
1326 return -EINVAL;
1327 }
1328 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001329 case DB_Z_INFO:
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001330 track->db_z_info = radeon_get_ib_value(p, idx);
Jerome Glisse721604a2012-01-05 22:11:05 -05001331 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
Marek Olšáke70f2242011-10-25 01:38:45 +02001332 r = evergreen_cs_packet_next_reloc(p, &reloc);
1333 if (r) {
1334 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1335 "0x%04X\n", reg);
1336 return -EINVAL;
1337 }
1338 ib[idx] &= ~Z_ARRAY_MODE(0xf);
1339 track->db_z_info &= ~Z_ARRAY_MODE(0xf);
Alex Deucherf3a71df2011-11-28 14:49:28 -05001340 ib[idx] |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
1341 track->db_z_info |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
Marek Olšáke70f2242011-10-25 01:38:45 +02001342 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
Jerome Glisse285484e2011-12-16 17:03:42 -05001343 unsigned bankw, bankh, mtaspect, tile_split;
1344
1345 evergreen_tiling_fields(reloc->lobj.tiling_flags,
1346 &bankw, &bankh, &mtaspect,
1347 &tile_split);
Alex Deucherf3a71df2011-11-28 14:49:28 -05001348 ib[idx] |= DB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
Jerome Glisse285484e2011-12-16 17:03:42 -05001349 ib[idx] |= DB_TILE_SPLIT(tile_split) |
1350 DB_BANK_WIDTH(bankw) |
1351 DB_BANK_HEIGHT(bankh) |
1352 DB_MACRO_TILE_ASPECT(mtaspect);
Marek Olšáke70f2242011-10-25 01:38:45 +02001353 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001354 }
Marek Olšák30838572012-03-19 03:09:35 +01001355 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001356 break;
1357 case DB_STENCIL_INFO:
1358 track->db_s_info = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001359 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001360 break;
1361 case DB_DEPTH_VIEW:
1362 track->db_depth_view = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001363 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001364 break;
1365 case DB_DEPTH_SIZE:
1366 track->db_depth_size = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001367 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001368 break;
Jerome Glisse285484e2011-12-16 17:03:42 -05001369 case R_02805C_DB_DEPTH_SLICE:
1370 track->db_depth_slice = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001371 track->db_dirty = true;
Jerome Glisse285484e2011-12-16 17:03:42 -05001372 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001373 case DB_Z_READ_BASE:
1374 r = evergreen_cs_packet_next_reloc(p, &reloc);
1375 if (r) {
1376 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1377 "0x%04X\n", reg);
1378 return -EINVAL;
1379 }
1380 track->db_z_read_offset = radeon_get_ib_value(p, idx);
1381 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1382 track->db_z_read_bo = reloc->robj;
Marek Olšák30838572012-03-19 03:09:35 +01001383 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001384 break;
1385 case DB_Z_WRITE_BASE:
1386 r = evergreen_cs_packet_next_reloc(p, &reloc);
1387 if (r) {
1388 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1389 "0x%04X\n", reg);
1390 return -EINVAL;
1391 }
1392 track->db_z_write_offset = radeon_get_ib_value(p, idx);
1393 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1394 track->db_z_write_bo = reloc->robj;
Marek Olšák30838572012-03-19 03:09:35 +01001395 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001396 break;
1397 case DB_STENCIL_READ_BASE:
1398 r = evergreen_cs_packet_next_reloc(p, &reloc);
1399 if (r) {
1400 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1401 "0x%04X\n", reg);
1402 return -EINVAL;
1403 }
1404 track->db_s_read_offset = radeon_get_ib_value(p, idx);
1405 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1406 track->db_s_read_bo = reloc->robj;
Marek Olšák30838572012-03-19 03:09:35 +01001407 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001408 break;
1409 case DB_STENCIL_WRITE_BASE:
1410 r = evergreen_cs_packet_next_reloc(p, &reloc);
1411 if (r) {
1412 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1413 "0x%04X\n", reg);
1414 return -EINVAL;
1415 }
1416 track->db_s_write_offset = radeon_get_ib_value(p, idx);
1417 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1418 track->db_s_write_bo = reloc->robj;
Marek Olšák30838572012-03-19 03:09:35 +01001419 track->db_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001420 break;
1421 case VGT_STRMOUT_CONFIG:
1422 track->vgt_strmout_config = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001423 track->streamout_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001424 break;
1425 case VGT_STRMOUT_BUFFER_CONFIG:
1426 track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001427 track->streamout_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001428 break;
Marek Olšákdd220a02012-01-27 12:17:59 -05001429 case VGT_STRMOUT_BUFFER_BASE_0:
1430 case VGT_STRMOUT_BUFFER_BASE_1:
1431 case VGT_STRMOUT_BUFFER_BASE_2:
1432 case VGT_STRMOUT_BUFFER_BASE_3:
1433 r = evergreen_cs_packet_next_reloc(p, &reloc);
1434 if (r) {
1435 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1436 "0x%04X\n", reg);
1437 return -EINVAL;
1438 }
1439 tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
1440 track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
1441 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1442 track->vgt_strmout_bo[tmp] = reloc->robj;
Marek Olšák30838572012-03-19 03:09:35 +01001443 track->streamout_dirty = true;
Marek Olšákdd220a02012-01-27 12:17:59 -05001444 break;
1445 case VGT_STRMOUT_BUFFER_SIZE_0:
1446 case VGT_STRMOUT_BUFFER_SIZE_1:
1447 case VGT_STRMOUT_BUFFER_SIZE_2:
1448 case VGT_STRMOUT_BUFFER_SIZE_3:
1449 tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
1450 /* size in register is DWs, convert to bytes */
1451 track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4;
Marek Olšák30838572012-03-19 03:09:35 +01001452 track->streamout_dirty = true;
Marek Olšákdd220a02012-01-27 12:17:59 -05001453 break;
1454 case CP_COHER_BASE:
1455 r = evergreen_cs_packet_next_reloc(p, &reloc);
1456 if (r) {
1457 dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
1458 "0x%04X\n", reg);
1459 return -EINVAL;
1460 }
1461 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001462 case CB_TARGET_MASK:
1463 track->cb_target_mask = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001464 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001465 break;
1466 case CB_SHADER_MASK:
1467 track->cb_shader_mask = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001468 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001469 break;
1470 case PA_SC_AA_CONFIG:
Alex Deucherc175ca92011-03-02 20:07:37 -05001471 if (p->rdev->family >= CHIP_CAYMAN) {
1472 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1473 "0x%04X\n", reg);
1474 return -EINVAL;
1475 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001476 tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK;
1477 track->nsamples = 1 << tmp;
1478 break;
Alex Deucherc175ca92011-03-02 20:07:37 -05001479 case CAYMAN_PA_SC_AA_CONFIG:
1480 if (p->rdev->family < CHIP_CAYMAN) {
1481 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1482 "0x%04X\n", reg);
1483 return -EINVAL;
1484 }
1485 tmp = radeon_get_ib_value(p, idx) & CAYMAN_MSAA_NUM_SAMPLES_MASK;
1486 track->nsamples = 1 << tmp;
1487 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001488 case CB_COLOR0_VIEW:
1489 case CB_COLOR1_VIEW:
1490 case CB_COLOR2_VIEW:
1491 case CB_COLOR3_VIEW:
1492 case CB_COLOR4_VIEW:
1493 case CB_COLOR5_VIEW:
1494 case CB_COLOR6_VIEW:
1495 case CB_COLOR7_VIEW:
1496 tmp = (reg - CB_COLOR0_VIEW) / 0x3c;
1497 track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001498 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001499 break;
1500 case CB_COLOR8_VIEW:
1501 case CB_COLOR9_VIEW:
1502 case CB_COLOR10_VIEW:
1503 case CB_COLOR11_VIEW:
1504 tmp = ((reg - CB_COLOR8_VIEW) / 0x1c) + 8;
1505 track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001506 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001507 break;
1508 case CB_COLOR0_INFO:
1509 case CB_COLOR1_INFO:
1510 case CB_COLOR2_INFO:
1511 case CB_COLOR3_INFO:
1512 case CB_COLOR4_INFO:
1513 case CB_COLOR5_INFO:
1514 case CB_COLOR6_INFO:
1515 case CB_COLOR7_INFO:
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001516 tmp = (reg - CB_COLOR0_INFO) / 0x3c;
1517 track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
Jerome Glisse721604a2012-01-05 22:11:05 -05001518 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
Marek Olšáke70f2242011-10-25 01:38:45 +02001519 r = evergreen_cs_packet_next_reloc(p, &reloc);
1520 if (r) {
1521 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1522 "0x%04X\n", reg);
1523 return -EINVAL;
1524 }
Alex Deucherf3a71df2011-11-28 14:49:28 -05001525 ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
1526 track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001527 }
Marek Olšák30838572012-03-19 03:09:35 +01001528 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001529 break;
1530 case CB_COLOR8_INFO:
1531 case CB_COLOR9_INFO:
1532 case CB_COLOR10_INFO:
1533 case CB_COLOR11_INFO:
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001534 tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;
1535 track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
Jerome Glisse721604a2012-01-05 22:11:05 -05001536 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
Marek Olšáke70f2242011-10-25 01:38:45 +02001537 r = evergreen_cs_packet_next_reloc(p, &reloc);
1538 if (r) {
1539 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1540 "0x%04X\n", reg);
1541 return -EINVAL;
1542 }
Alex Deucherf3a71df2011-11-28 14:49:28 -05001543 ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
1544 track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001545 }
Marek Olšák30838572012-03-19 03:09:35 +01001546 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001547 break;
1548 case CB_COLOR0_PITCH:
1549 case CB_COLOR1_PITCH:
1550 case CB_COLOR2_PITCH:
1551 case CB_COLOR3_PITCH:
1552 case CB_COLOR4_PITCH:
1553 case CB_COLOR5_PITCH:
1554 case CB_COLOR6_PITCH:
1555 case CB_COLOR7_PITCH:
1556 tmp = (reg - CB_COLOR0_PITCH) / 0x3c;
1557 track->cb_color_pitch[tmp] = radeon_get_ib_value(p, 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_PITCH:
1561 case CB_COLOR9_PITCH:
1562 case CB_COLOR10_PITCH:
1563 case CB_COLOR11_PITCH:
1564 tmp = ((reg - CB_COLOR8_PITCH) / 0x1c) + 8;
1565 track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
Marek Olšák30838572012-03-19 03:09:35 +01001566 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001567 break;
1568 case CB_COLOR0_SLICE:
1569 case CB_COLOR1_SLICE:
1570 case CB_COLOR2_SLICE:
1571 case CB_COLOR3_SLICE:
1572 case CB_COLOR4_SLICE:
1573 case CB_COLOR5_SLICE:
1574 case CB_COLOR6_SLICE:
1575 case CB_COLOR7_SLICE:
1576 tmp = (reg - CB_COLOR0_SLICE) / 0x3c;
1577 track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
Jerome Glissed2609872012-06-09 10:57:41 -04001578 track->cb_color_slice_idx[tmp] = idx;
Marek Olšák30838572012-03-19 03:09:35 +01001579 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001580 break;
1581 case CB_COLOR8_SLICE:
1582 case CB_COLOR9_SLICE:
1583 case CB_COLOR10_SLICE:
1584 case CB_COLOR11_SLICE:
1585 tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8;
1586 track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
Jerome Glissed2609872012-06-09 10:57:41 -04001587 track->cb_color_slice_idx[tmp] = idx;
Marek Olšák30838572012-03-19 03:09:35 +01001588 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001589 break;
1590 case CB_COLOR0_ATTRIB:
1591 case CB_COLOR1_ATTRIB:
1592 case CB_COLOR2_ATTRIB:
1593 case CB_COLOR3_ATTRIB:
1594 case CB_COLOR4_ATTRIB:
1595 case CB_COLOR5_ATTRIB:
1596 case CB_COLOR6_ATTRIB:
1597 case CB_COLOR7_ATTRIB:
Jerome Glisse285484e2011-12-16 17:03:42 -05001598 r = evergreen_cs_packet_next_reloc(p, &reloc);
1599 if (r) {
1600 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1601 "0x%04X\n", reg);
1602 return -EINVAL;
1603 }
1604 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
1605 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
1606 unsigned bankw, bankh, mtaspect, tile_split;
1607
1608 evergreen_tiling_fields(reloc->lobj.tiling_flags,
1609 &bankw, &bankh, &mtaspect,
1610 &tile_split);
1611 ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
1612 ib[idx] |= CB_TILE_SPLIT(tile_split) |
1613 CB_BANK_WIDTH(bankw) |
1614 CB_BANK_HEIGHT(bankh) |
1615 CB_MACRO_TILE_ASPECT(mtaspect);
1616 }
1617 }
1618 tmp = ((reg - CB_COLOR0_ATTRIB) / 0x3c);
1619 track->cb_color_attrib[tmp] = ib[idx];
Marek Olšák30838572012-03-19 03:09:35 +01001620 track->cb_dirty = true;
Jerome Glisse285484e2011-12-16 17:03:42 -05001621 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001622 case CB_COLOR8_ATTRIB:
1623 case CB_COLOR9_ATTRIB:
1624 case CB_COLOR10_ATTRIB:
1625 case CB_COLOR11_ATTRIB:
Alex Deucherf3a71df2011-11-28 14:49:28 -05001626 r = evergreen_cs_packet_next_reloc(p, &reloc);
1627 if (r) {
1628 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1629 "0x%04X\n", reg);
1630 return -EINVAL;
1631 }
Jerome Glisse285484e2011-12-16 17:03:42 -05001632 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
1633 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
1634 unsigned bankw, bankh, mtaspect, tile_split;
1635
1636 evergreen_tiling_fields(reloc->lobj.tiling_flags,
1637 &bankw, &bankh, &mtaspect,
1638 &tile_split);
1639 ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
1640 ib[idx] |= CB_TILE_SPLIT(tile_split) |
1641 CB_BANK_WIDTH(bankw) |
1642 CB_BANK_HEIGHT(bankh) |
1643 CB_MACRO_TILE_ASPECT(mtaspect);
1644 }
Alex Deucherf3a71df2011-11-28 14:49:28 -05001645 }
Jerome Glisse285484e2011-12-16 17:03:42 -05001646 tmp = ((reg - CB_COLOR8_ATTRIB) / 0x1c) + 8;
1647 track->cb_color_attrib[tmp] = ib[idx];
Marek Olšák30838572012-03-19 03:09:35 +01001648 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001649 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001650 case CB_COLOR0_FMASK:
1651 case CB_COLOR1_FMASK:
1652 case CB_COLOR2_FMASK:
1653 case CB_COLOR3_FMASK:
1654 case CB_COLOR4_FMASK:
1655 case CB_COLOR5_FMASK:
1656 case CB_COLOR6_FMASK:
1657 case CB_COLOR7_FMASK:
1658 tmp = (reg - CB_COLOR0_FMASK) / 0x3c;
1659 r = evergreen_cs_packet_next_reloc(p, &reloc);
1660 if (r) {
1661 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
1662 return -EINVAL;
1663 }
1664 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1665 track->cb_color_fmask_bo[tmp] = reloc->robj;
1666 break;
1667 case CB_COLOR0_CMASK:
1668 case CB_COLOR1_CMASK:
1669 case CB_COLOR2_CMASK:
1670 case CB_COLOR3_CMASK:
1671 case CB_COLOR4_CMASK:
1672 case CB_COLOR5_CMASK:
1673 case CB_COLOR6_CMASK:
1674 case CB_COLOR7_CMASK:
1675 tmp = (reg - CB_COLOR0_CMASK) / 0x3c;
1676 r = evergreen_cs_packet_next_reloc(p, &reloc);
1677 if (r) {
1678 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
1679 return -EINVAL;
1680 }
1681 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1682 track->cb_color_cmask_bo[tmp] = reloc->robj;
1683 break;
1684 case CB_COLOR0_FMASK_SLICE:
1685 case CB_COLOR1_FMASK_SLICE:
1686 case CB_COLOR2_FMASK_SLICE:
1687 case CB_COLOR3_FMASK_SLICE:
1688 case CB_COLOR4_FMASK_SLICE:
1689 case CB_COLOR5_FMASK_SLICE:
1690 case CB_COLOR6_FMASK_SLICE:
1691 case CB_COLOR7_FMASK_SLICE:
1692 tmp = (reg - CB_COLOR0_FMASK_SLICE) / 0x3c;
1693 track->cb_color_fmask_slice[tmp] = radeon_get_ib_value(p, idx);
1694 break;
1695 case CB_COLOR0_CMASK_SLICE:
1696 case CB_COLOR1_CMASK_SLICE:
1697 case CB_COLOR2_CMASK_SLICE:
1698 case CB_COLOR3_CMASK_SLICE:
1699 case CB_COLOR4_CMASK_SLICE:
1700 case CB_COLOR5_CMASK_SLICE:
1701 case CB_COLOR6_CMASK_SLICE:
1702 case CB_COLOR7_CMASK_SLICE:
1703 tmp = (reg - CB_COLOR0_CMASK_SLICE) / 0x3c;
1704 track->cb_color_cmask_slice[tmp] = radeon_get_ib_value(p, idx);
1705 break;
1706 case CB_COLOR0_BASE:
1707 case CB_COLOR1_BASE:
1708 case CB_COLOR2_BASE:
1709 case CB_COLOR3_BASE:
1710 case CB_COLOR4_BASE:
1711 case CB_COLOR5_BASE:
1712 case CB_COLOR6_BASE:
1713 case CB_COLOR7_BASE:
1714 r = evergreen_cs_packet_next_reloc(p, &reloc);
1715 if (r) {
1716 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1717 "0x%04X\n", reg);
1718 return -EINVAL;
1719 }
1720 tmp = (reg - CB_COLOR0_BASE) / 0x3c;
1721 track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
1722 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001723 track->cb_color_bo[tmp] = reloc->robj;
Marek Olšák30838572012-03-19 03:09:35 +01001724 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001725 break;
1726 case CB_COLOR8_BASE:
1727 case CB_COLOR9_BASE:
1728 case CB_COLOR10_BASE:
1729 case CB_COLOR11_BASE:
1730 r = evergreen_cs_packet_next_reloc(p, &reloc);
1731 if (r) {
1732 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1733 "0x%04X\n", reg);
1734 return -EINVAL;
1735 }
1736 tmp = ((reg - CB_COLOR8_BASE) / 0x1c) + 8;
1737 track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
1738 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001739 track->cb_color_bo[tmp] = reloc->robj;
Marek Olšák30838572012-03-19 03:09:35 +01001740 track->cb_dirty = true;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001741 break;
Jerome Glisse88f50c82012-03-21 19:18:21 -04001742 case DB_HTILE_DATA_BASE:
1743 r = evergreen_cs_packet_next_reloc(p, &reloc);
1744 if (r) {
1745 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1746 "0x%04X\n", reg);
1747 return -EINVAL;
1748 }
1749 track->htile_offset = radeon_get_ib_value(p, idx);
1750 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1751 track->htile_bo = reloc->robj;
1752 track->db_dirty = true;
1753 break;
1754 case DB_HTILE_SURFACE:
1755 /* 8x8 only */
1756 track->htile_surface = radeon_get_ib_value(p, idx);
Jerome Glisse4ac05332012-12-13 12:08:11 -05001757 /* force 8x8 htile width and height */
1758 ib[idx] |= 3;
Jerome Glisse88f50c82012-03-21 19:18:21 -04001759 track->db_dirty = true;
1760 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001761 case CB_IMMED0_BASE:
1762 case CB_IMMED1_BASE:
1763 case CB_IMMED2_BASE:
1764 case CB_IMMED3_BASE:
1765 case CB_IMMED4_BASE:
1766 case CB_IMMED5_BASE:
1767 case CB_IMMED6_BASE:
1768 case CB_IMMED7_BASE:
1769 case CB_IMMED8_BASE:
1770 case CB_IMMED9_BASE:
1771 case CB_IMMED10_BASE:
1772 case CB_IMMED11_BASE:
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001773 case SQ_PGM_START_FS:
1774 case SQ_PGM_START_ES:
1775 case SQ_PGM_START_VS:
1776 case SQ_PGM_START_GS:
1777 case SQ_PGM_START_PS:
1778 case SQ_PGM_START_HS:
1779 case SQ_PGM_START_LS:
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001780 case SQ_CONST_MEM_BASE:
1781 case SQ_ALU_CONST_CACHE_GS_0:
1782 case SQ_ALU_CONST_CACHE_GS_1:
1783 case SQ_ALU_CONST_CACHE_GS_2:
1784 case SQ_ALU_CONST_CACHE_GS_3:
1785 case SQ_ALU_CONST_CACHE_GS_4:
1786 case SQ_ALU_CONST_CACHE_GS_5:
1787 case SQ_ALU_CONST_CACHE_GS_6:
1788 case SQ_ALU_CONST_CACHE_GS_7:
1789 case SQ_ALU_CONST_CACHE_GS_8:
1790 case SQ_ALU_CONST_CACHE_GS_9:
1791 case SQ_ALU_CONST_CACHE_GS_10:
1792 case SQ_ALU_CONST_CACHE_GS_11:
1793 case SQ_ALU_CONST_CACHE_GS_12:
1794 case SQ_ALU_CONST_CACHE_GS_13:
1795 case SQ_ALU_CONST_CACHE_GS_14:
1796 case SQ_ALU_CONST_CACHE_GS_15:
1797 case SQ_ALU_CONST_CACHE_PS_0:
1798 case SQ_ALU_CONST_CACHE_PS_1:
1799 case SQ_ALU_CONST_CACHE_PS_2:
1800 case SQ_ALU_CONST_CACHE_PS_3:
1801 case SQ_ALU_CONST_CACHE_PS_4:
1802 case SQ_ALU_CONST_CACHE_PS_5:
1803 case SQ_ALU_CONST_CACHE_PS_6:
1804 case SQ_ALU_CONST_CACHE_PS_7:
1805 case SQ_ALU_CONST_CACHE_PS_8:
1806 case SQ_ALU_CONST_CACHE_PS_9:
1807 case SQ_ALU_CONST_CACHE_PS_10:
1808 case SQ_ALU_CONST_CACHE_PS_11:
1809 case SQ_ALU_CONST_CACHE_PS_12:
1810 case SQ_ALU_CONST_CACHE_PS_13:
1811 case SQ_ALU_CONST_CACHE_PS_14:
1812 case SQ_ALU_CONST_CACHE_PS_15:
1813 case SQ_ALU_CONST_CACHE_VS_0:
1814 case SQ_ALU_CONST_CACHE_VS_1:
1815 case SQ_ALU_CONST_CACHE_VS_2:
1816 case SQ_ALU_CONST_CACHE_VS_3:
1817 case SQ_ALU_CONST_CACHE_VS_4:
1818 case SQ_ALU_CONST_CACHE_VS_5:
1819 case SQ_ALU_CONST_CACHE_VS_6:
1820 case SQ_ALU_CONST_CACHE_VS_7:
1821 case SQ_ALU_CONST_CACHE_VS_8:
1822 case SQ_ALU_CONST_CACHE_VS_9:
1823 case SQ_ALU_CONST_CACHE_VS_10:
1824 case SQ_ALU_CONST_CACHE_VS_11:
1825 case SQ_ALU_CONST_CACHE_VS_12:
1826 case SQ_ALU_CONST_CACHE_VS_13:
1827 case SQ_ALU_CONST_CACHE_VS_14:
1828 case SQ_ALU_CONST_CACHE_VS_15:
1829 case SQ_ALU_CONST_CACHE_HS_0:
1830 case SQ_ALU_CONST_CACHE_HS_1:
1831 case SQ_ALU_CONST_CACHE_HS_2:
1832 case SQ_ALU_CONST_CACHE_HS_3:
1833 case SQ_ALU_CONST_CACHE_HS_4:
1834 case SQ_ALU_CONST_CACHE_HS_5:
1835 case SQ_ALU_CONST_CACHE_HS_6:
1836 case SQ_ALU_CONST_CACHE_HS_7:
1837 case SQ_ALU_CONST_CACHE_HS_8:
1838 case SQ_ALU_CONST_CACHE_HS_9:
1839 case SQ_ALU_CONST_CACHE_HS_10:
1840 case SQ_ALU_CONST_CACHE_HS_11:
1841 case SQ_ALU_CONST_CACHE_HS_12:
1842 case SQ_ALU_CONST_CACHE_HS_13:
1843 case SQ_ALU_CONST_CACHE_HS_14:
1844 case SQ_ALU_CONST_CACHE_HS_15:
1845 case SQ_ALU_CONST_CACHE_LS_0:
1846 case SQ_ALU_CONST_CACHE_LS_1:
1847 case SQ_ALU_CONST_CACHE_LS_2:
1848 case SQ_ALU_CONST_CACHE_LS_3:
1849 case SQ_ALU_CONST_CACHE_LS_4:
1850 case SQ_ALU_CONST_CACHE_LS_5:
1851 case SQ_ALU_CONST_CACHE_LS_6:
1852 case SQ_ALU_CONST_CACHE_LS_7:
1853 case SQ_ALU_CONST_CACHE_LS_8:
1854 case SQ_ALU_CONST_CACHE_LS_9:
1855 case SQ_ALU_CONST_CACHE_LS_10:
1856 case SQ_ALU_CONST_CACHE_LS_11:
1857 case SQ_ALU_CONST_CACHE_LS_12:
1858 case SQ_ALU_CONST_CACHE_LS_13:
1859 case SQ_ALU_CONST_CACHE_LS_14:
1860 case SQ_ALU_CONST_CACHE_LS_15:
1861 r = evergreen_cs_packet_next_reloc(p, &reloc);
1862 if (r) {
1863 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1864 "0x%04X\n", reg);
1865 return -EINVAL;
1866 }
1867 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1868 break;
Alex Deucher033b5652011-06-08 15:26:45 -04001869 case SX_MEMORY_EXPORT_BASE:
1870 if (p->rdev->family >= CHIP_CAYMAN) {
1871 dev_warn(p->dev, "bad SET_CONFIG_REG "
1872 "0x%04X\n", reg);
1873 return -EINVAL;
1874 }
1875 r = evergreen_cs_packet_next_reloc(p, &reloc);
1876 if (r) {
1877 dev_warn(p->dev, "bad SET_CONFIG_REG "
1878 "0x%04X\n", reg);
1879 return -EINVAL;
1880 }
1881 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1882 break;
1883 case CAYMAN_SX_SCATTER_EXPORT_BASE:
1884 if (p->rdev->family < CHIP_CAYMAN) {
1885 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1886 "0x%04X\n", reg);
1887 return -EINVAL;
1888 }
1889 r = evergreen_cs_packet_next_reloc(p, &reloc);
1890 if (r) {
1891 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1892 "0x%04X\n", reg);
1893 return -EINVAL;
1894 }
1895 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1896 break;
Marek Olšák779923b2012-03-08 00:56:00 +01001897 case SX_MISC:
1898 track->sx_misc_kill_all_prims = (radeon_get_ib_value(p, idx) & 0x1) != 0;
1899 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001900 default:
1901 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
1902 return -EINVAL;
1903 }
1904 return 0;
1905}
1906
Marek Olšákdd220a02012-01-27 12:17:59 -05001907static bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
1908{
1909 u32 last_reg, m, i;
1910
1911 if (p->rdev->family >= CHIP_CAYMAN)
1912 last_reg = ARRAY_SIZE(cayman_reg_safe_bm);
1913 else
1914 last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
1915
1916 i = (reg >> 7);
1917 if (i >= last_reg) {
1918 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
1919 return false;
1920 }
1921 m = 1 << ((reg >> 2) & 31);
1922 if (p->rdev->family >= CHIP_CAYMAN) {
1923 if (!(cayman_reg_safe_bm[i] & m))
1924 return true;
1925 } else {
1926 if (!(evergreen_reg_safe_bm[i] & m))
1927 return true;
1928 }
1929 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
1930 return false;
1931}
1932
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001933static int evergreen_packet3_check(struct radeon_cs_parser *p,
1934 struct radeon_cs_packet *pkt)
1935{
1936 struct radeon_cs_reloc *reloc;
1937 struct evergreen_cs_track *track;
1938 volatile u32 *ib;
1939 unsigned idx;
1940 unsigned i;
1941 unsigned start_reg, end_reg, reg;
1942 int r;
1943 u32 idx_value;
1944
1945 track = (struct evergreen_cs_track *)p->track;
Jerome Glissef2e39222012-05-09 15:35:02 +02001946 ib = p->ib.ptr;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001947 idx = pkt->idx + 1;
1948 idx_value = radeon_get_ib_value(p, idx);
1949
1950 switch (pkt->opcode) {
Dave Airlie2a19cac2011-02-28 16:11:48 +10001951 case PACKET3_SET_PREDICATION:
1952 {
1953 int pred_op;
1954 int tmp;
Marek Olšák78857132012-03-19 03:09:33 +01001955 uint64_t offset;
1956
Dave Airlie2a19cac2011-02-28 16:11:48 +10001957 if (pkt->count != 1) {
1958 DRM_ERROR("bad SET PREDICATION\n");
1959 return -EINVAL;
1960 }
1961
1962 tmp = radeon_get_ib_value(p, idx + 1);
1963 pred_op = (tmp >> 16) & 0x7;
1964
1965 /* for the clear predicate operation */
1966 if (pred_op == 0)
1967 return 0;
1968
1969 if (pred_op > 2) {
1970 DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op);
1971 return -EINVAL;
1972 }
1973
1974 r = evergreen_cs_packet_next_reloc(p, &reloc);
1975 if (r) {
1976 DRM_ERROR("bad SET PREDICATION\n");
1977 return -EINVAL;
1978 }
1979
Marek Olšák78857132012-03-19 03:09:33 +01001980 offset = reloc->lobj.gpu_offset +
1981 (idx_value & 0xfffffff0) +
1982 ((u64)(tmp & 0xff) << 32);
1983
1984 ib[idx + 0] = offset;
1985 ib[idx + 1] = (tmp & 0xffffff00) | (upper_32_bits(offset) & 0xff);
Dave Airlie2a19cac2011-02-28 16:11:48 +10001986 }
1987 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04001988 case PACKET3_CONTEXT_CONTROL:
1989 if (pkt->count != 1) {
1990 DRM_ERROR("bad CONTEXT_CONTROL\n");
1991 return -EINVAL;
1992 }
1993 break;
1994 case PACKET3_INDEX_TYPE:
1995 case PACKET3_NUM_INSTANCES:
1996 case PACKET3_CLEAR_STATE:
1997 if (pkt->count) {
1998 DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");
1999 return -EINVAL;
2000 }
2001 break;
Alex Deucherc175ca92011-03-02 20:07:37 -05002002 case CAYMAN_PACKET3_DEALLOC_STATE:
2003 if (p->rdev->family < CHIP_CAYMAN) {
2004 DRM_ERROR("bad PACKET3_DEALLOC_STATE\n");
2005 return -EINVAL;
2006 }
2007 if (pkt->count) {
2008 DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");
2009 return -EINVAL;
2010 }
2011 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002012 case PACKET3_INDEX_BASE:
Marek Olšák78857132012-03-19 03:09:33 +01002013 {
2014 uint64_t offset;
2015
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002016 if (pkt->count != 1) {
2017 DRM_ERROR("bad INDEX_BASE\n");
2018 return -EINVAL;
2019 }
2020 r = evergreen_cs_packet_next_reloc(p, &reloc);
2021 if (r) {
2022 DRM_ERROR("bad INDEX_BASE\n");
2023 return -EINVAL;
2024 }
Marek Olšák78857132012-03-19 03:09:33 +01002025
2026 offset = reloc->lobj.gpu_offset +
2027 idx_value +
2028 ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32);
2029
2030 ib[idx+0] = offset;
2031 ib[idx+1] = upper_32_bits(offset) & 0xff;
2032
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002033 r = evergreen_cs_track_check(p);
2034 if (r) {
2035 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
2036 return r;
2037 }
2038 break;
Marek Olšák78857132012-03-19 03:09:33 +01002039 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002040 case PACKET3_DRAW_INDEX:
Marek Olšák78857132012-03-19 03:09:33 +01002041 {
2042 uint64_t offset;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002043 if (pkt->count != 3) {
2044 DRM_ERROR("bad DRAW_INDEX\n");
2045 return -EINVAL;
2046 }
2047 r = evergreen_cs_packet_next_reloc(p, &reloc);
2048 if (r) {
2049 DRM_ERROR("bad DRAW_INDEX\n");
2050 return -EINVAL;
2051 }
Marek Olšák78857132012-03-19 03:09:33 +01002052
2053 offset = reloc->lobj.gpu_offset +
2054 idx_value +
2055 ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32);
2056
2057 ib[idx+0] = offset;
2058 ib[idx+1] = upper_32_bits(offset) & 0xff;
2059
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002060 r = evergreen_cs_track_check(p);
2061 if (r) {
2062 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
2063 return r;
2064 }
2065 break;
Marek Olšák78857132012-03-19 03:09:33 +01002066 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002067 case PACKET3_DRAW_INDEX_2:
Marek Olšák78857132012-03-19 03:09:33 +01002068 {
2069 uint64_t offset;
2070
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002071 if (pkt->count != 4) {
2072 DRM_ERROR("bad DRAW_INDEX_2\n");
2073 return -EINVAL;
2074 }
2075 r = evergreen_cs_packet_next_reloc(p, &reloc);
2076 if (r) {
2077 DRM_ERROR("bad DRAW_INDEX_2\n");
2078 return -EINVAL;
2079 }
Marek Olšák78857132012-03-19 03:09:33 +01002080
2081 offset = reloc->lobj.gpu_offset +
2082 radeon_get_ib_value(p, idx+1) +
2083 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
2084
2085 ib[idx+1] = offset;
2086 ib[idx+2] = upper_32_bits(offset) & 0xff;
2087
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002088 r = evergreen_cs_track_check(p);
2089 if (r) {
2090 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
2091 return r;
2092 }
2093 break;
Marek Olšák78857132012-03-19 03:09:33 +01002094 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002095 case PACKET3_DRAW_INDEX_AUTO:
2096 if (pkt->count != 1) {
2097 DRM_ERROR("bad DRAW_INDEX_AUTO\n");
2098 return -EINVAL;
2099 }
2100 r = evergreen_cs_track_check(p);
2101 if (r) {
2102 dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
2103 return r;
2104 }
2105 break;
2106 case PACKET3_DRAW_INDEX_MULTI_AUTO:
2107 if (pkt->count != 2) {
2108 DRM_ERROR("bad DRAW_INDEX_MULTI_AUTO\n");
2109 return -EINVAL;
2110 }
2111 r = evergreen_cs_track_check(p);
2112 if (r) {
2113 dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
2114 return r;
2115 }
2116 break;
2117 case PACKET3_DRAW_INDEX_IMMD:
2118 if (pkt->count < 2) {
2119 DRM_ERROR("bad DRAW_INDEX_IMMD\n");
2120 return -EINVAL;
2121 }
2122 r = evergreen_cs_track_check(p);
2123 if (r) {
2124 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
2125 return r;
2126 }
2127 break;
2128 case PACKET3_DRAW_INDEX_OFFSET:
2129 if (pkt->count != 2) {
2130 DRM_ERROR("bad DRAW_INDEX_OFFSET\n");
2131 return -EINVAL;
2132 }
2133 r = evergreen_cs_track_check(p);
2134 if (r) {
2135 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
2136 return r;
2137 }
2138 break;
2139 case PACKET3_DRAW_INDEX_OFFSET_2:
2140 if (pkt->count != 3) {
2141 DRM_ERROR("bad DRAW_INDEX_OFFSET_2\n");
2142 return -EINVAL;
2143 }
2144 r = evergreen_cs_track_check(p);
2145 if (r) {
2146 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
2147 return r;
2148 }
2149 break;
Alex Deucher033b5652011-06-08 15:26:45 -04002150 case PACKET3_DISPATCH_DIRECT:
2151 if (pkt->count != 3) {
2152 DRM_ERROR("bad DISPATCH_DIRECT\n");
2153 return -EINVAL;
2154 }
2155 r = evergreen_cs_track_check(p);
2156 if (r) {
2157 dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
2158 return r;
2159 }
2160 break;
2161 case PACKET3_DISPATCH_INDIRECT:
2162 if (pkt->count != 1) {
2163 DRM_ERROR("bad DISPATCH_INDIRECT\n");
2164 return -EINVAL;
2165 }
2166 r = evergreen_cs_packet_next_reloc(p, &reloc);
2167 if (r) {
2168 DRM_ERROR("bad DISPATCH_INDIRECT\n");
2169 return -EINVAL;
2170 }
2171 ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
2172 r = evergreen_cs_track_check(p);
2173 if (r) {
2174 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
2175 return r;
2176 }
2177 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002178 case PACKET3_WAIT_REG_MEM:
2179 if (pkt->count != 5) {
2180 DRM_ERROR("bad WAIT_REG_MEM\n");
2181 return -EINVAL;
2182 }
2183 /* bit 4 is reg (0) or mem (1) */
2184 if (idx_value & 0x10) {
Marek Olšák78857132012-03-19 03:09:33 +01002185 uint64_t offset;
2186
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002187 r = evergreen_cs_packet_next_reloc(p, &reloc);
2188 if (r) {
2189 DRM_ERROR("bad WAIT_REG_MEM\n");
2190 return -EINVAL;
2191 }
Marek Olšák78857132012-03-19 03:09:33 +01002192
2193 offset = reloc->lobj.gpu_offset +
2194 (radeon_get_ib_value(p, idx+1) & 0xfffffffc) +
2195 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
2196
2197 ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffffc);
2198 ib[idx+2] = upper_32_bits(offset) & 0xff;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002199 }
2200 break;
Alex Deucher8770b862012-12-03 19:18:30 -05002201 case PACKET3_CP_DMA:
2202 {
2203 u32 command, size, info;
2204 u64 offset, tmp;
2205 if (pkt->count != 4) {
2206 DRM_ERROR("bad CP DMA\n");
2207 return -EINVAL;
2208 }
2209 command = radeon_get_ib_value(p, idx+4);
2210 size = command & 0x1fffff;
2211 info = radeon_get_ib_value(p, idx+1);
Alex Deucher9d89d782012-12-14 00:23:06 -05002212 if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */
2213 (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */
2214 ((((info & 0x00300000) >> 20) == 0) &&
2215 (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */
2216 ((((info & 0x60000000) >> 29) == 0) &&
2217 (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */
2218 /* non mem to mem copies requires dw aligned count */
2219 if (size % 4) {
2220 DRM_ERROR("CP DMA command requires dw count alignment\n");
2221 return -EINVAL;
2222 }
2223 }
Alex Deucher8770b862012-12-03 19:18:30 -05002224 if (command & PACKET3_CP_DMA_CMD_SAS) {
2225 /* src address space is register */
2226 /* GDS is ok */
2227 if (((info & 0x60000000) >> 29) != 1) {
2228 DRM_ERROR("CP DMA SAS not supported\n");
2229 return -EINVAL;
2230 }
2231 } else {
2232 if (command & PACKET3_CP_DMA_CMD_SAIC) {
2233 DRM_ERROR("CP DMA SAIC only supported for registers\n");
2234 return -EINVAL;
2235 }
2236 /* src address space is memory */
2237 if (((info & 0x60000000) >> 29) == 0) {
2238 r = evergreen_cs_packet_next_reloc(p, &reloc);
2239 if (r) {
2240 DRM_ERROR("bad CP DMA SRC\n");
2241 return -EINVAL;
2242 }
2243
2244 tmp = radeon_get_ib_value(p, idx) +
2245 ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32);
2246
2247 offset = reloc->lobj.gpu_offset + tmp;
2248
2249 if ((tmp + size) > radeon_bo_size(reloc->robj)) {
2250 dev_warn(p->dev, "CP DMA src buffer too small (%llu %lu)\n",
2251 tmp + size, radeon_bo_size(reloc->robj));
2252 return -EINVAL;
2253 }
2254
2255 ib[idx] = offset;
2256 ib[idx+1] = (ib[idx+1] & 0xffffff00) | (upper_32_bits(offset) & 0xff);
2257 } else if (((info & 0x60000000) >> 29) != 2) {
2258 DRM_ERROR("bad CP DMA SRC_SEL\n");
2259 return -EINVAL;
2260 }
2261 }
2262 if (command & PACKET3_CP_DMA_CMD_DAS) {
2263 /* dst address space is register */
2264 /* GDS is ok */
2265 if (((info & 0x00300000) >> 20) != 1) {
2266 DRM_ERROR("CP DMA DAS not supported\n");
2267 return -EINVAL;
2268 }
2269 } else {
2270 /* dst address space is memory */
2271 if (command & PACKET3_CP_DMA_CMD_DAIC) {
2272 DRM_ERROR("CP DMA DAIC only supported for registers\n");
2273 return -EINVAL;
2274 }
2275 if (((info & 0x00300000) >> 20) == 0) {
2276 r = evergreen_cs_packet_next_reloc(p, &reloc);
2277 if (r) {
2278 DRM_ERROR("bad CP DMA DST\n");
2279 return -EINVAL;
2280 }
2281
2282 tmp = radeon_get_ib_value(p, idx+2) +
2283 ((u64)(radeon_get_ib_value(p, idx+3) & 0xff) << 32);
2284
2285 offset = reloc->lobj.gpu_offset + tmp;
2286
2287 if ((tmp + size) > radeon_bo_size(reloc->robj)) {
2288 dev_warn(p->dev, "CP DMA dst buffer too small (%llu %lu)\n",
2289 tmp + size, radeon_bo_size(reloc->robj));
2290 return -EINVAL;
2291 }
2292
2293 ib[idx+2] = offset;
2294 ib[idx+3] = upper_32_bits(offset) & 0xff;
2295 } else {
2296 DRM_ERROR("bad CP DMA DST_SEL\n");
2297 return -EINVAL;
2298 }
2299 }
2300 break;
2301 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002302 case PACKET3_SURFACE_SYNC:
2303 if (pkt->count != 3) {
2304 DRM_ERROR("bad SURFACE_SYNC\n");
2305 return -EINVAL;
2306 }
2307 /* 0xffffffff/0x0 is flush all cache flag */
2308 if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
2309 radeon_get_ib_value(p, idx + 2) != 0) {
2310 r = evergreen_cs_packet_next_reloc(p, &reloc);
2311 if (r) {
2312 DRM_ERROR("bad SURFACE_SYNC\n");
2313 return -EINVAL;
2314 }
2315 ib[idx+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
2316 }
2317 break;
2318 case PACKET3_EVENT_WRITE:
2319 if (pkt->count != 2 && pkt->count != 0) {
2320 DRM_ERROR("bad EVENT_WRITE\n");
2321 return -EINVAL;
2322 }
2323 if (pkt->count) {
Marek Olšák78857132012-03-19 03:09:33 +01002324 uint64_t offset;
2325
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002326 r = evergreen_cs_packet_next_reloc(p, &reloc);
2327 if (r) {
2328 DRM_ERROR("bad EVENT_WRITE\n");
2329 return -EINVAL;
2330 }
Marek Olšák78857132012-03-19 03:09:33 +01002331 offset = reloc->lobj.gpu_offset +
2332 (radeon_get_ib_value(p, idx+1) & 0xfffffff8) +
2333 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
2334
2335 ib[idx+1] = offset & 0xfffffff8;
2336 ib[idx+2] = upper_32_bits(offset) & 0xff;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002337 }
2338 break;
2339 case PACKET3_EVENT_WRITE_EOP:
Marek Olšák78857132012-03-19 03:09:33 +01002340 {
2341 uint64_t offset;
2342
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002343 if (pkt->count != 4) {
2344 DRM_ERROR("bad EVENT_WRITE_EOP\n");
2345 return -EINVAL;
2346 }
2347 r = evergreen_cs_packet_next_reloc(p, &reloc);
2348 if (r) {
2349 DRM_ERROR("bad EVENT_WRITE_EOP\n");
2350 return -EINVAL;
2351 }
Marek Olšák78857132012-03-19 03:09:33 +01002352
2353 offset = reloc->lobj.gpu_offset +
2354 (radeon_get_ib_value(p, idx+1) & 0xfffffffc) +
2355 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
2356
2357 ib[idx+1] = offset & 0xfffffffc;
2358 ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002359 break;
Marek Olšák78857132012-03-19 03:09:33 +01002360 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002361 case PACKET3_EVENT_WRITE_EOS:
Marek Olšák78857132012-03-19 03:09:33 +01002362 {
2363 uint64_t offset;
2364
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002365 if (pkt->count != 3) {
2366 DRM_ERROR("bad EVENT_WRITE_EOS\n");
2367 return -EINVAL;
2368 }
2369 r = evergreen_cs_packet_next_reloc(p, &reloc);
2370 if (r) {
2371 DRM_ERROR("bad EVENT_WRITE_EOS\n");
2372 return -EINVAL;
2373 }
Marek Olšák78857132012-03-19 03:09:33 +01002374
2375 offset = reloc->lobj.gpu_offset +
2376 (radeon_get_ib_value(p, idx+1) & 0xfffffffc) +
2377 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
2378
2379 ib[idx+1] = offset & 0xfffffffc;
2380 ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002381 break;
Marek Olšák78857132012-03-19 03:09:33 +01002382 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002383 case PACKET3_SET_CONFIG_REG:
2384 start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START;
2385 end_reg = 4 * pkt->count + start_reg - 4;
2386 if ((start_reg < PACKET3_SET_CONFIG_REG_START) ||
2387 (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
2388 (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
2389 DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
2390 return -EINVAL;
2391 }
2392 for (i = 0; i < pkt->count; i++) {
2393 reg = start_reg + (4 * i);
2394 r = evergreen_cs_check_reg(p, reg, idx+1+i);
2395 if (r)
2396 return r;
2397 }
2398 break;
2399 case PACKET3_SET_CONTEXT_REG:
2400 start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_START;
2401 end_reg = 4 * pkt->count + start_reg - 4;
2402 if ((start_reg < PACKET3_SET_CONTEXT_REG_START) ||
2403 (start_reg >= PACKET3_SET_CONTEXT_REG_END) ||
2404 (end_reg >= PACKET3_SET_CONTEXT_REG_END)) {
2405 DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n");
2406 return -EINVAL;
2407 }
2408 for (i = 0; i < pkt->count; i++) {
2409 reg = start_reg + (4 * i);
2410 r = evergreen_cs_check_reg(p, reg, idx+1+i);
2411 if (r)
2412 return r;
2413 }
2414 break;
2415 case PACKET3_SET_RESOURCE:
2416 if (pkt->count % 8) {
2417 DRM_ERROR("bad SET_RESOURCE\n");
2418 return -EINVAL;
2419 }
2420 start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_START;
2421 end_reg = 4 * pkt->count + start_reg - 4;
2422 if ((start_reg < PACKET3_SET_RESOURCE_START) ||
2423 (start_reg >= PACKET3_SET_RESOURCE_END) ||
2424 (end_reg >= PACKET3_SET_RESOURCE_END)) {
2425 DRM_ERROR("bad SET_RESOURCE\n");
2426 return -EINVAL;
2427 }
2428 for (i = 0; i < (pkt->count / 8); i++) {
2429 struct radeon_bo *texture, *mipmap;
Jerome Glisse285484e2011-12-16 17:03:42 -05002430 u32 toffset, moffset;
Marek Olšák61051af2012-09-25 03:34:01 +02002431 u32 size, offset, mip_address, tex_dim;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002432
2433 switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) {
2434 case SQ_TEX_VTX_VALID_TEXTURE:
2435 /* tex base */
2436 r = evergreen_cs_packet_next_reloc(p, &reloc);
2437 if (r) {
2438 DRM_ERROR("bad SET_RESOURCE (tex)\n");
2439 return -EINVAL;
2440 }
Jerome Glisse721604a2012-01-05 22:11:05 -05002441 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
Alex Deucherf3a71df2011-11-28 14:49:28 -05002442 ib[idx+1+(i*8)+1] |=
2443 TEX_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));
2444 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
Jerome Glisse285484e2011-12-16 17:03:42 -05002445 unsigned bankw, bankh, mtaspect, tile_split;
2446
2447 evergreen_tiling_fields(reloc->lobj.tiling_flags,
2448 &bankw, &bankh, &mtaspect,
2449 &tile_split);
2450 ib[idx+1+(i*8)+6] |= TEX_TILE_SPLIT(tile_split);
Alex Deucherf3a71df2011-11-28 14:49:28 -05002451 ib[idx+1+(i*8)+7] |=
Jerome Glisse285484e2011-12-16 17:03:42 -05002452 TEX_BANK_WIDTH(bankw) |
2453 TEX_BANK_HEIGHT(bankh) |
2454 MACRO_TILE_ASPECT(mtaspect) |
Alex Deucherf3a71df2011-11-28 14:49:28 -05002455 TEX_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks));
2456 }
Marek Olšáke70f2242011-10-25 01:38:45 +02002457 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002458 texture = reloc->robj;
Jerome Glisse285484e2011-12-16 17:03:42 -05002459 toffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
Marek Olšák61051af2012-09-25 03:34:01 +02002460
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002461 /* tex mip base */
Marek Olšák61051af2012-09-25 03:34:01 +02002462 tex_dim = ib[idx+1+(i*8)+0] & 0x7;
2463 mip_address = ib[idx+1+(i*8)+3];
2464
2465 if ((tex_dim == SQ_TEX_DIM_2D_MSAA || tex_dim == SQ_TEX_DIM_2D_ARRAY_MSAA) &&
2466 !mip_address &&
2467 !evergreen_cs_packet_next_is_pkt3_nop(p)) {
2468 /* MIP_ADDRESS should point to FMASK for an MSAA texture.
2469 * It should be 0 if FMASK is disabled. */
2470 moffset = 0;
2471 mipmap = NULL;
2472 } else {
2473 r = evergreen_cs_packet_next_reloc(p, &reloc);
2474 if (r) {
2475 DRM_ERROR("bad SET_RESOURCE (tex)\n");
2476 return -EINVAL;
2477 }
2478 moffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
2479 mipmap = reloc->robj;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002480 }
Marek Olšák61051af2012-09-25 03:34:01 +02002481
Jerome Glisse285484e2011-12-16 17:03:42 -05002482 r = evergreen_cs_track_validate_texture(p, texture, mipmap, idx+1+(i*8));
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002483 if (r)
2484 return r;
Jerome Glisse285484e2011-12-16 17:03:42 -05002485 ib[idx+1+(i*8)+2] += toffset;
2486 ib[idx+1+(i*8)+3] += moffset;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002487 break;
2488 case SQ_TEX_VTX_VALID_BUFFER:
Marek Olšák78857132012-03-19 03:09:33 +01002489 {
2490 uint64_t offset64;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002491 /* vtx base */
2492 r = evergreen_cs_packet_next_reloc(p, &reloc);
2493 if (r) {
2494 DRM_ERROR("bad SET_RESOURCE (vtx)\n");
2495 return -EINVAL;
2496 }
2497 offset = radeon_get_ib_value(p, idx+1+(i*8)+0);
2498 size = radeon_get_ib_value(p, idx+1+(i*8)+1);
2499 if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
2500 /* force size to size of the buffer */
2501 dev_warn(p->dev, "vbo resource seems too big for the bo\n");
Marek Olšák78857132012-03-19 03:09:33 +01002502 ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj) - offset;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002503 }
Marek Olšák78857132012-03-19 03:09:33 +01002504
2505 offset64 = reloc->lobj.gpu_offset + offset;
2506 ib[idx+1+(i*8)+0] = offset64;
2507 ib[idx+1+(i*8)+2] = (ib[idx+1+(i*8)+2] & 0xffffff00) |
2508 (upper_32_bits(offset64) & 0xff);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002509 break;
Marek Olšák78857132012-03-19 03:09:33 +01002510 }
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002511 case SQ_TEX_VTX_INVALID_TEXTURE:
2512 case SQ_TEX_VTX_INVALID_BUFFER:
2513 default:
2514 DRM_ERROR("bad SET_RESOURCE\n");
2515 return -EINVAL;
2516 }
2517 }
2518 break;
2519 case PACKET3_SET_ALU_CONST:
2520 /* XXX fix me ALU const buffers only */
2521 break;
2522 case PACKET3_SET_BOOL_CONST:
2523 start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_START;
2524 end_reg = 4 * pkt->count + start_reg - 4;
2525 if ((start_reg < PACKET3_SET_BOOL_CONST_START) ||
2526 (start_reg >= PACKET3_SET_BOOL_CONST_END) ||
2527 (end_reg >= PACKET3_SET_BOOL_CONST_END)) {
2528 DRM_ERROR("bad SET_BOOL_CONST\n");
2529 return -EINVAL;
2530 }
2531 break;
2532 case PACKET3_SET_LOOP_CONST:
2533 start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_START;
2534 end_reg = 4 * pkt->count + start_reg - 4;
2535 if ((start_reg < PACKET3_SET_LOOP_CONST_START) ||
2536 (start_reg >= PACKET3_SET_LOOP_CONST_END) ||
2537 (end_reg >= PACKET3_SET_LOOP_CONST_END)) {
2538 DRM_ERROR("bad SET_LOOP_CONST\n");
2539 return -EINVAL;
2540 }
2541 break;
2542 case PACKET3_SET_CTL_CONST:
2543 start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_START;
2544 end_reg = 4 * pkt->count + start_reg - 4;
2545 if ((start_reg < PACKET3_SET_CTL_CONST_START) ||
2546 (start_reg >= PACKET3_SET_CTL_CONST_END) ||
2547 (end_reg >= PACKET3_SET_CTL_CONST_END)) {
2548 DRM_ERROR("bad SET_CTL_CONST\n");
2549 return -EINVAL;
2550 }
2551 break;
2552 case PACKET3_SET_SAMPLER:
2553 if (pkt->count % 3) {
2554 DRM_ERROR("bad SET_SAMPLER\n");
2555 return -EINVAL;
2556 }
2557 start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_START;
2558 end_reg = 4 * pkt->count + start_reg - 4;
2559 if ((start_reg < PACKET3_SET_SAMPLER_START) ||
2560 (start_reg >= PACKET3_SET_SAMPLER_END) ||
2561 (end_reg >= PACKET3_SET_SAMPLER_END)) {
2562 DRM_ERROR("bad SET_SAMPLER\n");
2563 return -EINVAL;
2564 }
2565 break;
Marek Olšákdd220a02012-01-27 12:17:59 -05002566 case PACKET3_STRMOUT_BUFFER_UPDATE:
2567 if (pkt->count != 4) {
2568 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
2569 return -EINVAL;
2570 }
2571 /* Updating memory at DST_ADDRESS. */
2572 if (idx_value & 0x1) {
2573 u64 offset;
2574 r = evergreen_cs_packet_next_reloc(p, &reloc);
2575 if (r) {
2576 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n");
2577 return -EINVAL;
2578 }
2579 offset = radeon_get_ib_value(p, idx+1);
2580 offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
2581 if ((offset + 4) > radeon_bo_size(reloc->robj)) {
2582 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%llx, 0x%lx\n",
2583 offset + 4, radeon_bo_size(reloc->robj));
2584 return -EINVAL;
2585 }
Marek Olšák78857132012-03-19 03:09:33 +01002586 offset += reloc->lobj.gpu_offset;
2587 ib[idx+1] = offset;
2588 ib[idx+2] = upper_32_bits(offset) & 0xff;
Marek Olšákdd220a02012-01-27 12:17:59 -05002589 }
2590 /* Reading data from SRC_ADDRESS. */
2591 if (((idx_value >> 1) & 0x3) == 2) {
2592 u64 offset;
2593 r = evergreen_cs_packet_next_reloc(p, &reloc);
2594 if (r) {
2595 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n");
2596 return -EINVAL;
2597 }
2598 offset = radeon_get_ib_value(p, idx+3);
2599 offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
2600 if ((offset + 4) > radeon_bo_size(reloc->robj)) {
2601 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%llx, 0x%lx\n",
2602 offset + 4, radeon_bo_size(reloc->robj));
2603 return -EINVAL;
2604 }
Marek Olšák78857132012-03-19 03:09:33 +01002605 offset += reloc->lobj.gpu_offset;
2606 ib[idx+3] = offset;
2607 ib[idx+4] = upper_32_bits(offset) & 0xff;
Marek Olšákdd220a02012-01-27 12:17:59 -05002608 }
2609 break;
Jerome Glisse4613ca12012-12-19 12:26:45 -05002610 case PACKET3_MEM_WRITE:
2611 {
2612 u64 offset;
2613
2614 if (pkt->count != 3) {
2615 DRM_ERROR("bad MEM_WRITE (invalid count)\n");
2616 return -EINVAL;
2617 }
2618 r = evergreen_cs_packet_next_reloc(p, &reloc);
2619 if (r) {
2620 DRM_ERROR("bad MEM_WRITE (missing reloc)\n");
2621 return -EINVAL;
2622 }
2623 offset = radeon_get_ib_value(p, idx+0);
2624 offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL;
2625 if (offset & 0x7) {
2626 DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n");
2627 return -EINVAL;
2628 }
2629 if ((offset + 8) > radeon_bo_size(reloc->robj)) {
2630 DRM_ERROR("bad MEM_WRITE bo too small: 0x%llx, 0x%lx\n",
2631 offset + 8, radeon_bo_size(reloc->robj));
2632 return -EINVAL;
2633 }
2634 offset += reloc->lobj.gpu_offset;
2635 ib[idx+0] = offset;
2636 ib[idx+1] = upper_32_bits(offset) & 0xff;
2637 break;
2638 }
Marek Olšákdd220a02012-01-27 12:17:59 -05002639 case PACKET3_COPY_DW:
2640 if (pkt->count != 4) {
2641 DRM_ERROR("bad COPY_DW (invalid count)\n");
2642 return -EINVAL;
2643 }
2644 if (idx_value & 0x1) {
2645 u64 offset;
2646 /* SRC is memory. */
2647 r = evergreen_cs_packet_next_reloc(p, &reloc);
2648 if (r) {
2649 DRM_ERROR("bad COPY_DW (missing src reloc)\n");
2650 return -EINVAL;
2651 }
2652 offset = radeon_get_ib_value(p, idx+1);
2653 offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
2654 if ((offset + 4) > radeon_bo_size(reloc->robj)) {
2655 DRM_ERROR("bad COPY_DW src bo too small: 0x%llx, 0x%lx\n",
2656 offset + 4, radeon_bo_size(reloc->robj));
2657 return -EINVAL;
2658 }
Marek Olšák78857132012-03-19 03:09:33 +01002659 offset += reloc->lobj.gpu_offset;
2660 ib[idx+1] = offset;
2661 ib[idx+2] = upper_32_bits(offset) & 0xff;
Marek Olšákdd220a02012-01-27 12:17:59 -05002662 } else {
2663 /* SRC is a reg. */
2664 reg = radeon_get_ib_value(p, idx+1) << 2;
2665 if (!evergreen_is_safe_reg(p, reg, idx+1))
2666 return -EINVAL;
2667 }
2668 if (idx_value & 0x2) {
2669 u64 offset;
2670 /* DST is memory. */
2671 r = evergreen_cs_packet_next_reloc(p, &reloc);
2672 if (r) {
2673 DRM_ERROR("bad COPY_DW (missing dst reloc)\n");
2674 return -EINVAL;
2675 }
2676 offset = radeon_get_ib_value(p, idx+3);
2677 offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
2678 if ((offset + 4) > radeon_bo_size(reloc->robj)) {
2679 DRM_ERROR("bad COPY_DW dst bo too small: 0x%llx, 0x%lx\n",
2680 offset + 4, radeon_bo_size(reloc->robj));
2681 return -EINVAL;
2682 }
Marek Olšák78857132012-03-19 03:09:33 +01002683 offset += reloc->lobj.gpu_offset;
2684 ib[idx+3] = offset;
2685 ib[idx+4] = upper_32_bits(offset) & 0xff;
Marek Olšákdd220a02012-01-27 12:17:59 -05002686 } else {
2687 /* DST is a reg. */
2688 reg = radeon_get_ib_value(p, idx+3) << 2;
2689 if (!evergreen_is_safe_reg(p, reg, idx+3))
2690 return -EINVAL;
2691 }
2692 break;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002693 case PACKET3_NOP:
2694 break;
2695 default:
2696 DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
2697 return -EINVAL;
2698 }
2699 return 0;
2700}
2701
2702int evergreen_cs_parse(struct radeon_cs_parser *p)
2703{
2704 struct radeon_cs_packet pkt;
2705 struct evergreen_cs_track *track;
Alex Deucherf3a71df2011-11-28 14:49:28 -05002706 u32 tmp;
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002707 int r;
2708
2709 if (p->track == NULL) {
2710 /* initialize tracker, we are in kms */
2711 track = kzalloc(sizeof(*track), GFP_KERNEL);
2712 if (track == NULL)
2713 return -ENOMEM;
2714 evergreen_cs_track_init(track);
Alex Deucherf3a71df2011-11-28 14:49:28 -05002715 if (p->rdev->family >= CHIP_CAYMAN)
2716 tmp = p->rdev->config.cayman.tile_config;
2717 else
2718 tmp = p->rdev->config.evergreen.tile_config;
2719
2720 switch (tmp & 0xf) {
2721 case 0:
2722 track->npipes = 1;
2723 break;
2724 case 1:
2725 default:
2726 track->npipes = 2;
2727 break;
2728 case 2:
2729 track->npipes = 4;
2730 break;
2731 case 3:
2732 track->npipes = 8;
2733 break;
2734 }
2735
2736 switch ((tmp & 0xf0) >> 4) {
2737 case 0:
2738 track->nbanks = 4;
2739 break;
2740 case 1:
2741 default:
2742 track->nbanks = 8;
2743 break;
2744 case 2:
2745 track->nbanks = 16;
2746 break;
2747 }
2748
2749 switch ((tmp & 0xf00) >> 8) {
2750 case 0:
2751 track->group_size = 256;
2752 break;
2753 case 1:
2754 default:
2755 track->group_size = 512;
2756 break;
2757 }
2758
2759 switch ((tmp & 0xf000) >> 12) {
2760 case 0:
2761 track->row_size = 1;
2762 break;
2763 case 1:
2764 default:
2765 track->row_size = 2;
2766 break;
2767 case 2:
2768 track->row_size = 4;
2769 break;
2770 }
2771
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002772 p->track = track;
2773 }
2774 do {
Ilija Hadzicc38f34b2013-01-02 18:27:41 -05002775 r = radeon_cs_packet_parse(p, &pkt, p->idx);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002776 if (r) {
2777 kfree(p->track);
2778 p->track = NULL;
2779 return r;
2780 }
2781 p->idx += pkt.count + 2;
2782 switch (pkt.type) {
2783 case PACKET_TYPE0:
2784 r = evergreen_cs_parse_packet0(p, &pkt);
2785 break;
2786 case PACKET_TYPE2:
2787 break;
2788 case PACKET_TYPE3:
2789 r = evergreen_packet3_check(p, &pkt);
2790 break;
2791 default:
2792 DRM_ERROR("Unknown packet type %d !\n", pkt.type);
2793 kfree(p->track);
2794 p->track = NULL;
2795 return -EINVAL;
2796 }
2797 if (r) {
2798 kfree(p->track);
2799 p->track = NULL;
2800 return r;
2801 }
2802 } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
2803#if 0
Jerome Glissef2e39222012-05-09 15:35:02 +02002804 for (r = 0; r < p->ib.length_dw; r++) {
2805 printk(KERN_INFO "%05d 0x%08X\n", r, p->ib.ptr[r]);
Alex Deuchercb5fcbd2010-05-28 19:01:35 -04002806 mdelay(1);
2807 }
2808#endif
2809 kfree(p->track);
2810 p->track = NULL;
2811 return 0;
2812}
2813
Alex Deucherd2ead3e2012-12-13 09:55:45 -05002814/*
2815 * DMA
2816 */
2817
2818#define GET_DMA_CMD(h) (((h) & 0xf0000000) >> 28)
2819#define GET_DMA_COUNT(h) ((h) & 0x000fffff)
2820#define GET_DMA_T(h) (((h) & 0x00800000) >> 23)
2821#define GET_DMA_NEW(h) (((h) & 0x04000000) >> 26)
2822#define GET_DMA_MISC(h) (((h) & 0x0700000) >> 20)
2823
2824/**
2825 * evergreen_dma_cs_parse() - parse the DMA IB
2826 * @p: parser structure holding parsing context.
2827 *
2828 * Parses the DMA IB from the CS ioctl and updates
2829 * the GPU addresses based on the reloc information and
2830 * checks for errors. (Evergreen-Cayman)
2831 * Returns 0 for success and an error on failure.
2832 **/
2833int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
2834{
2835 struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
2836 struct radeon_cs_reloc *src_reloc, *dst_reloc, *dst2_reloc;
2837 u32 header, cmd, count, tiled, new_cmd, misc;
2838 volatile u32 *ib = p->ib.ptr;
2839 u32 idx, idx_value;
2840 u64 src_offset, dst_offset, dst2_offset;
2841 int r;
2842
2843 do {
2844 if (p->idx >= ib_chunk->length_dw) {
2845 DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
2846 p->idx, ib_chunk->length_dw);
2847 return -EINVAL;
2848 }
2849 idx = p->idx;
2850 header = radeon_get_ib_value(p, idx);
2851 cmd = GET_DMA_CMD(header);
2852 count = GET_DMA_COUNT(header);
2853 tiled = GET_DMA_T(header);
2854 new_cmd = GET_DMA_NEW(header);
2855 misc = GET_DMA_MISC(header);
2856
2857 switch (cmd) {
2858 case DMA_PACKET_WRITE:
2859 r = r600_dma_cs_next_reloc(p, &dst_reloc);
2860 if (r) {
2861 DRM_ERROR("bad DMA_PACKET_WRITE\n");
2862 return -EINVAL;
2863 }
2864 if (tiled) {
2865 dst_offset = ib[idx+1];
2866 dst_offset <<= 8;
2867
2868 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
2869 p->idx += count + 7;
2870 } else {
2871 dst_offset = ib[idx+1];
2872 dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32;
2873
2874 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
2875 ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
2876 p->idx += count + 3;
2877 }
2878 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
2879 dev_warn(p->dev, "DMA write buffer too small (%llu %lu)\n",
2880 dst_offset, radeon_bo_size(dst_reloc->robj));
2881 return -EINVAL;
2882 }
2883 break;
2884 case DMA_PACKET_COPY:
2885 r = r600_dma_cs_next_reloc(p, &src_reloc);
2886 if (r) {
2887 DRM_ERROR("bad DMA_PACKET_COPY\n");
2888 return -EINVAL;
2889 }
2890 r = r600_dma_cs_next_reloc(p, &dst_reloc);
2891 if (r) {
2892 DRM_ERROR("bad DMA_PACKET_COPY\n");
2893 return -EINVAL;
2894 }
2895 if (tiled) {
2896 idx_value = radeon_get_ib_value(p, idx + 2);
2897 if (new_cmd) {
2898 switch (misc) {
2899 case 0:
2900 /* L2T, frame to fields */
2901 if (idx_value & (1 << 31)) {
2902 DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
2903 return -EINVAL;
2904 }
2905 r = r600_dma_cs_next_reloc(p, &dst2_reloc);
2906 if (r) {
2907 DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
2908 return -EINVAL;
2909 }
2910 dst_offset = ib[idx+1];
2911 dst_offset <<= 8;
2912 dst2_offset = ib[idx+2];
2913 dst2_offset <<= 8;
2914 src_offset = ib[idx+8];
2915 src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
2916 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
2917 dev_warn(p->dev, "DMA L2T, frame to fields src buffer too small (%llu %lu)\n",
2918 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
2919 return -EINVAL;
2920 }
2921 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
2922 dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n",
2923 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
2924 return -EINVAL;
2925 }
2926 if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
2927 dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n",
2928 dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
2929 return -EINVAL;
2930 }
2931 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
2932 ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
2933 ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
2934 ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
2935 p->idx += 10;
2936 break;
2937 case 1:
2938 /* L2T, T2L partial */
2939 if (p->family < CHIP_CAYMAN) {
2940 DRM_ERROR("L2T, T2L Partial is cayman only !\n");
2941 return -EINVAL;
2942 }
2943 /* detile bit */
2944 if (idx_value & (1 << 31)) {
2945 /* tiled src, linear dst */
2946 ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
2947
2948 ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
2949 ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
2950 } else {
2951 /* linear src, tiled dst */
2952 ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
2953 ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
2954
2955 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
2956 }
2957 p->idx += 12;
2958 break;
2959 case 3:
2960 /* L2T, broadcast */
2961 if (idx_value & (1 << 31)) {
2962 DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
2963 return -EINVAL;
2964 }
2965 r = r600_dma_cs_next_reloc(p, &dst2_reloc);
2966 if (r) {
2967 DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
2968 return -EINVAL;
2969 }
2970 dst_offset = ib[idx+1];
2971 dst_offset <<= 8;
2972 dst2_offset = ib[idx+2];
2973 dst2_offset <<= 8;
2974 src_offset = ib[idx+8];
2975 src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
2976 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
2977 dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
2978 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
2979 return -EINVAL;
2980 }
2981 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
2982 dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
2983 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
2984 return -EINVAL;
2985 }
2986 if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
2987 dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n",
2988 dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
2989 return -EINVAL;
2990 }
2991 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
2992 ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
2993 ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
2994 ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
2995 p->idx += 10;
2996 break;
2997 case 4:
2998 /* L2T, T2L */
2999 /* detile bit */
3000 if (idx_value & (1 << 31)) {
3001 /* tiled src, linear dst */
3002 src_offset = ib[idx+1];
3003 src_offset <<= 8;
3004 ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
3005
3006 dst_offset = ib[idx+7];
3007 dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
3008 ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
3009 ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
3010 } else {
3011 /* linear src, tiled dst */
3012 src_offset = ib[idx+7];
3013 src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
3014 ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
3015 ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3016
3017 dst_offset = ib[idx+1];
3018 dst_offset <<= 8;
3019 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
3020 }
3021 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
3022 dev_warn(p->dev, "DMA L2T, T2L src buffer too small (%llu %lu)\n",
3023 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
3024 return -EINVAL;
3025 }
3026 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3027 dev_warn(p->dev, "DMA L2T, T2L dst buffer too small (%llu %lu)\n",
3028 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
3029 return -EINVAL;
3030 }
3031 p->idx += 9;
3032 break;
3033 case 5:
3034 /* T2T partial */
3035 if (p->family < CHIP_CAYMAN) {
3036 DRM_ERROR("L2T, T2L Partial is cayman only !\n");
3037 return -EINVAL;
3038 }
3039 ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
3040 ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
3041 p->idx += 13;
3042 break;
3043 case 7:
3044 /* L2T, broadcast */
3045 if (idx_value & (1 << 31)) {
3046 DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
3047 return -EINVAL;
3048 }
3049 r = r600_dma_cs_next_reloc(p, &dst2_reloc);
3050 if (r) {
3051 DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
3052 return -EINVAL;
3053 }
3054 dst_offset = ib[idx+1];
3055 dst_offset <<= 8;
3056 dst2_offset = ib[idx+2];
3057 dst2_offset <<= 8;
3058 src_offset = ib[idx+8];
3059 src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
3060 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
3061 dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
3062 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
3063 return -EINVAL;
3064 }
3065 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3066 dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
3067 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
3068 return -EINVAL;
3069 }
3070 if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
3071 dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n",
3072 dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
3073 return -EINVAL;
3074 }
3075 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
3076 ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
3077 ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
3078 ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3079 p->idx += 10;
3080 break;
3081 default:
3082 DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
3083 return -EINVAL;
3084 }
3085 } else {
3086 switch (misc) {
3087 case 0:
3088 /* detile bit */
3089 if (idx_value & (1 << 31)) {
3090 /* tiled src, linear dst */
3091 src_offset = ib[idx+1];
3092 src_offset <<= 8;
3093 ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
3094
3095 dst_offset = ib[idx+7];
3096 dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
3097 ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
3098 ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
3099 } else {
3100 /* linear src, tiled dst */
3101 src_offset = ib[idx+7];
3102 src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
3103 ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
3104 ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3105
3106 dst_offset = ib[idx+1];
3107 dst_offset <<= 8;
3108 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
3109 }
3110 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
3111 dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
3112 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
3113 return -EINVAL;
3114 }
3115 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3116 dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
3117 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
3118 return -EINVAL;
3119 }
3120 p->idx += 9;
3121 break;
3122 default:
3123 DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
3124 return -EINVAL;
3125 }
3126 }
3127 } else {
3128 if (new_cmd) {
3129 switch (misc) {
3130 case 0:
3131 /* L2L, byte */
3132 src_offset = ib[idx+2];
3133 src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
3134 dst_offset = ib[idx+1];
3135 dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
3136 if ((src_offset + count) > radeon_bo_size(src_reloc->robj)) {
3137 dev_warn(p->dev, "DMA L2L, byte src buffer too small (%llu %lu)\n",
3138 src_offset + count, radeon_bo_size(src_reloc->robj));
3139 return -EINVAL;
3140 }
3141 if ((dst_offset + count) > radeon_bo_size(dst_reloc->robj)) {
3142 dev_warn(p->dev, "DMA L2L, byte dst buffer too small (%llu %lu)\n",
3143 dst_offset + count, radeon_bo_size(dst_reloc->robj));
3144 return -EINVAL;
3145 }
3146 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff);
3147 ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff);
3148 ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
3149 ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3150 p->idx += 5;
3151 break;
3152 case 1:
3153 /* L2L, partial */
3154 if (p->family < CHIP_CAYMAN) {
3155 DRM_ERROR("L2L Partial is cayman only !\n");
3156 return -EINVAL;
3157 }
3158 ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff);
3159 ib[idx+2] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3160 ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff);
3161 ib[idx+5] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
3162
3163 p->idx += 9;
3164 break;
3165 case 4:
3166 /* L2L, dw, broadcast */
3167 r = r600_dma_cs_next_reloc(p, &dst2_reloc);
3168 if (r) {
3169 DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n");
3170 return -EINVAL;
3171 }
3172 dst_offset = ib[idx+1];
3173 dst_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
3174 dst2_offset = ib[idx+2];
3175 dst2_offset |= ((u64)(ib[idx+5] & 0xff)) << 32;
3176 src_offset = ib[idx+3];
3177 src_offset |= ((u64)(ib[idx+6] & 0xff)) << 32;
3178 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
3179 dev_warn(p->dev, "DMA L2L, dw, broadcast src buffer too small (%llu %lu)\n",
3180 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
3181 return -EINVAL;
3182 }
3183 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3184 dev_warn(p->dev, "DMA L2L, dw, broadcast dst buffer too small (%llu %lu)\n",
3185 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
3186 return -EINVAL;
3187 }
3188 if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
3189 dev_warn(p->dev, "DMA L2L, dw, broadcast dst2 buffer too small (%llu %lu)\n",
3190 dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
3191 return -EINVAL;
3192 }
3193 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
3194 ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset & 0xfffffffc);
3195 ib[idx+3] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
3196 ib[idx+4] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
3197 ib[idx+5] += upper_32_bits(dst2_reloc->lobj.gpu_offset) & 0xff;
3198 ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3199 p->idx += 7;
3200 break;
3201 default:
3202 DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
3203 return -EINVAL;
3204 }
3205 } else {
3206 /* L2L, dw */
3207 src_offset = ib[idx+2];
3208 src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
3209 dst_offset = ib[idx+1];
3210 dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
3211 if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
3212 dev_warn(p->dev, "DMA L2L, dw src buffer too small (%llu %lu)\n",
3213 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
3214 return -EINVAL;
3215 }
3216 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3217 dev_warn(p->dev, "DMA L2L, dw dst buffer too small (%llu %lu)\n",
3218 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
3219 return -EINVAL;
3220 }
3221 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
3222 ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
3223 ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
3224 ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
3225 p->idx += 5;
3226 }
3227 }
3228 break;
3229 case DMA_PACKET_CONSTANT_FILL:
3230 r = r600_dma_cs_next_reloc(p, &dst_reloc);
3231 if (r) {
3232 DRM_ERROR("bad DMA_PACKET_CONSTANT_FILL\n");
3233 return -EINVAL;
3234 }
3235 dst_offset = ib[idx+1];
3236 dst_offset |= ((u64)(ib[idx+3] & 0x00ff0000)) << 16;
3237 if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
3238 dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n",
3239 dst_offset, radeon_bo_size(dst_reloc->robj));
3240 return -EINVAL;
3241 }
3242 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
3243 ib[idx+3] += (upper_32_bits(dst_reloc->lobj.gpu_offset) << 16) & 0x00ff0000;
3244 p->idx += 4;
3245 break;
3246 case DMA_PACKET_NOP:
3247 p->idx += 1;
3248 break;
3249 default:
3250 DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx);
3251 return -EINVAL;
3252 }
3253 } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
3254#if 0
3255 for (r = 0; r < p->ib->length_dw; r++) {
3256 printk(KERN_INFO "%05d 0x%08X\n", r, p->ib.ptr[r]);
3257 mdelay(1);
3258 }
3259#endif
3260 return 0;
3261}
3262
Jerome Glisse721604a2012-01-05 22:11:05 -05003263/* vm parser */
3264static bool evergreen_vm_reg_valid(u32 reg)
3265{
3266 /* context regs are fine */
3267 if (reg >= 0x28000)
3268 return true;
3269
3270 /* check config regs */
3271 switch (reg) {
Alex Deucher668bbc82012-12-20 21:19:32 -05003272 case WAIT_UNTIL:
Jerome Glisse721604a2012-01-05 22:11:05 -05003273 case GRBM_GFX_INDEX:
Alex Deucher860fe2f2012-11-08 10:08:04 -05003274 case CP_STRMOUT_CNTL:
3275 case CP_COHER_CNTL:
3276 case CP_COHER_SIZE:
Jerome Glisse721604a2012-01-05 22:11:05 -05003277 case VGT_VTX_VECT_EJECT_REG:
3278 case VGT_CACHE_INVALIDATION:
3279 case VGT_GS_VERTEX_REUSE:
3280 case VGT_PRIMITIVE_TYPE:
3281 case VGT_INDEX_TYPE:
3282 case VGT_NUM_INDICES:
3283 case VGT_NUM_INSTANCES:
3284 case VGT_COMPUTE_DIM_X:
3285 case VGT_COMPUTE_DIM_Y:
3286 case VGT_COMPUTE_DIM_Z:
3287 case VGT_COMPUTE_START_X:
3288 case VGT_COMPUTE_START_Y:
3289 case VGT_COMPUTE_START_Z:
3290 case VGT_COMPUTE_INDEX:
3291 case VGT_COMPUTE_THREAD_GROUP_SIZE:
3292 case VGT_HS_OFFCHIP_PARAM:
3293 case PA_CL_ENHANCE:
3294 case PA_SU_LINE_STIPPLE_VALUE:
3295 case PA_SC_LINE_STIPPLE_STATE:
3296 case PA_SC_ENHANCE:
3297 case SQ_DYN_GPR_CNTL_PS_FLUSH_REQ:
3298 case SQ_DYN_GPR_SIMD_LOCK_EN:
3299 case SQ_CONFIG:
3300 case SQ_GPR_RESOURCE_MGMT_1:
3301 case SQ_GLOBAL_GPR_RESOURCE_MGMT_1:
3302 case SQ_GLOBAL_GPR_RESOURCE_MGMT_2:
3303 case SQ_CONST_MEM_BASE:
3304 case SQ_STATIC_THREAD_MGMT_1:
3305 case SQ_STATIC_THREAD_MGMT_2:
3306 case SQ_STATIC_THREAD_MGMT_3:
3307 case SPI_CONFIG_CNTL:
3308 case SPI_CONFIG_CNTL_1:
3309 case TA_CNTL_AUX:
3310 case DB_DEBUG:
3311 case DB_DEBUG2:
3312 case DB_DEBUG3:
3313 case DB_DEBUG4:
3314 case DB_WATERMARKS:
3315 case TD_PS_BORDER_COLOR_INDEX:
3316 case TD_PS_BORDER_COLOR_RED:
3317 case TD_PS_BORDER_COLOR_GREEN:
3318 case TD_PS_BORDER_COLOR_BLUE:
3319 case TD_PS_BORDER_COLOR_ALPHA:
3320 case TD_VS_BORDER_COLOR_INDEX:
3321 case TD_VS_BORDER_COLOR_RED:
3322 case TD_VS_BORDER_COLOR_GREEN:
3323 case TD_VS_BORDER_COLOR_BLUE:
3324 case TD_VS_BORDER_COLOR_ALPHA:
3325 case TD_GS_BORDER_COLOR_INDEX:
3326 case TD_GS_BORDER_COLOR_RED:
3327 case TD_GS_BORDER_COLOR_GREEN:
3328 case TD_GS_BORDER_COLOR_BLUE:
3329 case TD_GS_BORDER_COLOR_ALPHA:
3330 case TD_HS_BORDER_COLOR_INDEX:
3331 case TD_HS_BORDER_COLOR_RED:
3332 case TD_HS_BORDER_COLOR_GREEN:
3333 case TD_HS_BORDER_COLOR_BLUE:
3334 case TD_HS_BORDER_COLOR_ALPHA:
3335 case TD_LS_BORDER_COLOR_INDEX:
3336 case TD_LS_BORDER_COLOR_RED:
3337 case TD_LS_BORDER_COLOR_GREEN:
3338 case TD_LS_BORDER_COLOR_BLUE:
3339 case TD_LS_BORDER_COLOR_ALPHA:
3340 case TD_CS_BORDER_COLOR_INDEX:
3341 case TD_CS_BORDER_COLOR_RED:
3342 case TD_CS_BORDER_COLOR_GREEN:
3343 case TD_CS_BORDER_COLOR_BLUE:
3344 case TD_CS_BORDER_COLOR_ALPHA:
3345 case SQ_ESGS_RING_SIZE:
3346 case SQ_GSVS_RING_SIZE:
3347 case SQ_ESTMP_RING_SIZE:
3348 case SQ_GSTMP_RING_SIZE:
3349 case SQ_HSTMP_RING_SIZE:
3350 case SQ_LSTMP_RING_SIZE:
3351 case SQ_PSTMP_RING_SIZE:
3352 case SQ_VSTMP_RING_SIZE:
3353 case SQ_ESGS_RING_ITEMSIZE:
3354 case SQ_ESTMP_RING_ITEMSIZE:
3355 case SQ_GSTMP_RING_ITEMSIZE:
3356 case SQ_GSVS_RING_ITEMSIZE:
3357 case SQ_GS_VERT_ITEMSIZE:
3358 case SQ_GS_VERT_ITEMSIZE_1:
3359 case SQ_GS_VERT_ITEMSIZE_2:
3360 case SQ_GS_VERT_ITEMSIZE_3:
3361 case SQ_GSVS_RING_OFFSET_1:
3362 case SQ_GSVS_RING_OFFSET_2:
3363 case SQ_GSVS_RING_OFFSET_3:
3364 case SQ_HSTMP_RING_ITEMSIZE:
3365 case SQ_LSTMP_RING_ITEMSIZE:
3366 case SQ_PSTMP_RING_ITEMSIZE:
3367 case SQ_VSTMP_RING_ITEMSIZE:
3368 case VGT_TF_RING_SIZE:
3369 case SQ_ESGS_RING_BASE:
3370 case SQ_GSVS_RING_BASE:
3371 case SQ_ESTMP_RING_BASE:
3372 case SQ_GSTMP_RING_BASE:
3373 case SQ_HSTMP_RING_BASE:
3374 case SQ_LSTMP_RING_BASE:
3375 case SQ_PSTMP_RING_BASE:
3376 case SQ_VSTMP_RING_BASE:
3377 case CAYMAN_VGT_OFFCHIP_LDS_BASE:
3378 case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS:
3379 return true;
3380 default:
Alex Deucherc7172132012-10-19 13:27:04 -04003381 DRM_ERROR("Invalid register 0x%x in CS\n", reg);
Jerome Glisse721604a2012-01-05 22:11:05 -05003382 return false;
3383 }
3384}
3385
3386static int evergreen_vm_packet3_check(struct radeon_device *rdev,
3387 u32 *ib, struct radeon_cs_packet *pkt)
3388{
3389 u32 idx = pkt->idx + 1;
3390 u32 idx_value = ib[idx];
3391 u32 start_reg, end_reg, reg, i;
Alex Deucher94e014e2012-12-03 19:32:54 -05003392 u32 command, info;
Jerome Glisse721604a2012-01-05 22:11:05 -05003393
3394 switch (pkt->opcode) {
3395 case PACKET3_NOP:
3396 case PACKET3_SET_BASE:
3397 case PACKET3_CLEAR_STATE:
3398 case PACKET3_INDEX_BUFFER_SIZE:
3399 case PACKET3_DISPATCH_DIRECT:
3400 case PACKET3_DISPATCH_INDIRECT:
3401 case PACKET3_MODE_CONTROL:
3402 case PACKET3_SET_PREDICATION:
3403 case PACKET3_COND_EXEC:
3404 case PACKET3_PRED_EXEC:
3405 case PACKET3_DRAW_INDIRECT:
3406 case PACKET3_DRAW_INDEX_INDIRECT:
3407 case PACKET3_INDEX_BASE:
3408 case PACKET3_DRAW_INDEX_2:
3409 case PACKET3_CONTEXT_CONTROL:
3410 case PACKET3_DRAW_INDEX_OFFSET:
3411 case PACKET3_INDEX_TYPE:
3412 case PACKET3_DRAW_INDEX:
3413 case PACKET3_DRAW_INDEX_AUTO:
3414 case PACKET3_DRAW_INDEX_IMMD:
3415 case PACKET3_NUM_INSTANCES:
3416 case PACKET3_DRAW_INDEX_MULTI_AUTO:
3417 case PACKET3_STRMOUT_BUFFER_UPDATE:
3418 case PACKET3_DRAW_INDEX_OFFSET_2:
3419 case PACKET3_DRAW_INDEX_MULTI_ELEMENT:
3420 case PACKET3_MPEG_INDEX:
3421 case PACKET3_WAIT_REG_MEM:
3422 case PACKET3_MEM_WRITE:
3423 case PACKET3_SURFACE_SYNC:
3424 case PACKET3_EVENT_WRITE:
3425 case PACKET3_EVENT_WRITE_EOP:
3426 case PACKET3_EVENT_WRITE_EOS:
3427 case PACKET3_SET_CONTEXT_REG:
3428 case PACKET3_SET_BOOL_CONST:
3429 case PACKET3_SET_LOOP_CONST:
3430 case PACKET3_SET_RESOURCE:
3431 case PACKET3_SET_SAMPLER:
3432 case PACKET3_SET_CTL_CONST:
3433 case PACKET3_SET_RESOURCE_OFFSET:
3434 case PACKET3_SET_CONTEXT_REG_INDIRECT:
3435 case PACKET3_SET_RESOURCE_INDIRECT:
3436 case CAYMAN_PACKET3_DEALLOC_STATE:
3437 break;
3438 case PACKET3_COND_WRITE:
3439 if (idx_value & 0x100) {
3440 reg = ib[idx + 5] * 4;
3441 if (!evergreen_vm_reg_valid(reg))
3442 return -EINVAL;
3443 }
3444 break;
3445 case PACKET3_COPY_DW:
3446 if (idx_value & 0x2) {
3447 reg = ib[idx + 3] * 4;
3448 if (!evergreen_vm_reg_valid(reg))
3449 return -EINVAL;
3450 }
3451 break;
3452 case PACKET3_SET_CONFIG_REG:
3453 start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START;
3454 end_reg = 4 * pkt->count + start_reg - 4;
3455 if ((start_reg < PACKET3_SET_CONFIG_REG_START) ||
3456 (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
3457 (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
3458 DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
3459 return -EINVAL;
3460 }
3461 for (i = 0; i < pkt->count; i++) {
3462 reg = start_reg + (4 * i);
3463 if (!evergreen_vm_reg_valid(reg))
3464 return -EINVAL;
3465 }
3466 break;
Alex Deucher94e014e2012-12-03 19:32:54 -05003467 case PACKET3_CP_DMA:
3468 command = ib[idx + 4];
3469 info = ib[idx + 1];
Alex Deucher9d89d782012-12-14 00:23:06 -05003470 if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */
3471 (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */
3472 ((((info & 0x00300000) >> 20) == 0) &&
3473 (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */
3474 ((((info & 0x60000000) >> 29) == 0) &&
3475 (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */
3476 /* non mem to mem copies requires dw aligned count */
3477 if ((command & 0x1fffff) % 4) {
3478 DRM_ERROR("CP DMA command requires dw count alignment\n");
3479 return -EINVAL;
3480 }
3481 }
Alex Deucher94e014e2012-12-03 19:32:54 -05003482 if (command & PACKET3_CP_DMA_CMD_SAS) {
3483 /* src address space is register */
3484 if (((info & 0x60000000) >> 29) == 0) {
3485 start_reg = idx_value << 2;
3486 if (command & PACKET3_CP_DMA_CMD_SAIC) {
3487 reg = start_reg;
3488 if (!evergreen_vm_reg_valid(reg)) {
3489 DRM_ERROR("CP DMA Bad SRC 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 SRC register\n");
3497 return -EINVAL;
3498 }
3499 }
3500 }
3501 }
3502 }
3503 if (command & PACKET3_CP_DMA_CMD_DAS) {
3504 /* dst address space is register */
3505 if (((info & 0x00300000) >> 20) == 0) {
3506 start_reg = ib[idx + 2];
3507 if (command & PACKET3_CP_DMA_CMD_DAIC) {
3508 reg = start_reg;
3509 if (!evergreen_vm_reg_valid(reg)) {
3510 DRM_ERROR("CP DMA Bad DST register\n");
3511 return -EINVAL;
3512 }
3513 } else {
3514 for (i = 0; i < (command & 0x1fffff); i++) {
3515 reg = start_reg + (4 * i);
3516 if (!evergreen_vm_reg_valid(reg)) {
3517 DRM_ERROR("CP DMA Bad DST register\n");
3518 return -EINVAL;
3519 }
3520 }
3521 }
3522 }
3523 }
3524 break;
Jerome Glisse721604a2012-01-05 22:11:05 -05003525 default:
3526 return -EINVAL;
3527 }
3528 return 0;
3529}
3530
3531int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
3532{
3533 int ret = 0;
3534 u32 idx = 0;
3535 struct radeon_cs_packet pkt;
3536
3537 do {
3538 pkt.idx = idx;
3539 pkt.type = CP_PACKET_GET_TYPE(ib->ptr[idx]);
3540 pkt.count = CP_PACKET_GET_COUNT(ib->ptr[idx]);
3541 pkt.one_reg_wr = 0;
3542 switch (pkt.type) {
3543 case PACKET_TYPE0:
3544 dev_err(rdev->dev, "Packet0 not allowed!\n");
3545 ret = -EINVAL;
3546 break;
3547 case PACKET_TYPE2:
Alex Deucher0b41da62012-01-12 15:42:37 -05003548 idx += 1;
Jerome Glisse721604a2012-01-05 22:11:05 -05003549 break;
3550 case PACKET_TYPE3:
3551 pkt.opcode = CP_PACKET3_GET_OPCODE(ib->ptr[idx]);
3552 ret = evergreen_vm_packet3_check(rdev, ib->ptr, &pkt);
Alex Deucher0b41da62012-01-12 15:42:37 -05003553 idx += pkt.count + 2;
Jerome Glisse721604a2012-01-05 22:11:05 -05003554 break;
3555 default:
3556 dev_err(rdev->dev, "Unknown packet type %d !\n", pkt.type);
3557 ret = -EINVAL;
3558 break;
3559 }
3560 if (ret)
3561 break;
Jerome Glisse721604a2012-01-05 22:11:05 -05003562 } while (idx < ib->length_dw);
3563
3564 return ret;
3565}
Alex Deuchercd459e52012-12-13 12:17:38 -05003566
3567/**
3568 * evergreen_dma_ib_parse() - parse the DMA IB for VM
3569 * @rdev: radeon_device pointer
3570 * @ib: radeon_ib pointer
3571 *
3572 * Parses the DMA IB from the VM CS ioctl
3573 * checks for errors. (Cayman-SI)
3574 * Returns 0 for success and an error on failure.
3575 **/
3576int evergreen_dma_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
3577{
3578 u32 idx = 0;
3579 u32 header, cmd, count, tiled, new_cmd, misc;
3580
3581 do {
3582 header = ib->ptr[idx];
3583 cmd = GET_DMA_CMD(header);
3584 count = GET_DMA_COUNT(header);
3585 tiled = GET_DMA_T(header);
3586 new_cmd = GET_DMA_NEW(header);
3587 misc = GET_DMA_MISC(header);
3588
3589 switch (cmd) {
3590 case DMA_PACKET_WRITE:
3591 if (tiled)
3592 idx += count + 7;
3593 else
3594 idx += count + 3;
3595 break;
3596 case DMA_PACKET_COPY:
3597 if (tiled) {
3598 if (new_cmd) {
3599 switch (misc) {
3600 case 0:
3601 /* L2T, frame to fields */
3602 idx += 10;
3603 break;
3604 case 1:
3605 /* L2T, T2L partial */
3606 idx += 12;
3607 break;
3608 case 3:
3609 /* L2T, broadcast */
3610 idx += 10;
3611 break;
3612 case 4:
3613 /* L2T, T2L */
3614 idx += 9;
3615 break;
3616 case 5:
3617 /* T2T partial */
3618 idx += 13;
3619 break;
3620 case 7:
3621 /* L2T, broadcast */
3622 idx += 10;
3623 break;
3624 default:
3625 DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
3626 return -EINVAL;
3627 }
3628 } else {
3629 switch (misc) {
3630 case 0:
3631 idx += 9;
3632 break;
3633 default:
3634 DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
3635 return -EINVAL;
3636 }
3637 }
3638 } else {
3639 if (new_cmd) {
3640 switch (misc) {
3641 case 0:
3642 /* L2L, byte */
3643 idx += 5;
3644 break;
3645 case 1:
3646 /* L2L, partial */
3647 idx += 9;
3648 break;
3649 case 4:
3650 /* L2L, dw, broadcast */
3651 idx += 7;
3652 break;
3653 default:
3654 DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
3655 return -EINVAL;
3656 }
3657 } else {
3658 /* L2L, dw */
3659 idx += 5;
3660 }
3661 }
3662 break;
3663 case DMA_PACKET_CONSTANT_FILL:
3664 idx += 4;
3665 break;
3666 case DMA_PACKET_NOP:
3667 idx += 1;
3668 break;
3669 default:
3670 DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx);
3671 return -EINVAL;
3672 }
3673 } while (idx < ib->length_dw);
3674
3675 return 0;
3676}