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