blob: 9f17571eea629757ea9e8d100d40e069e576387e [file] [log] [blame]
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001/*
2 * Copyright 2008 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 */
Alex Deucher40e2a5c2010-06-04 18:41:42 -040028#include <linux/kernel.h>
Jerome Glisse3ce0a232009-09-08 10:10:24 +100029#include "drmP.h"
30#include "radeon.h"
Jerome Glisse3ce0a232009-09-08 10:10:24 +100031#include "r600d.h"
Jerome Glisse961fb592010-02-10 22:30:05 +000032#include "r600_reg_safe.h"
Jerome Glisse3ce0a232009-09-08 10:10:24 +100033
34static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
35 struct radeon_cs_reloc **cs_reloc);
36static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
37 struct radeon_cs_reloc **cs_reloc);
38typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**);
39static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm;
Jerome Glisse961fb592010-02-10 22:30:05 +000040extern void r600_cs_legacy_get_tiling_conf(struct drm_device *dev, u32 *npipes, u32 *nbanks, u32 *group_size);
41
Jerome Glisse3ce0a232009-09-08 10:10:24 +100042
Jerome Glissec8c15ff2010-01-18 13:01:36 +010043struct r600_cs_track {
Jerome Glisse961fb592010-02-10 22:30:05 +000044 /* configuration we miror so that we use same code btw kms/ums */
45 u32 group_size;
46 u32 nbanks;
47 u32 npipes;
48 /* value we track */
Alex Deucher5f77df32010-03-26 14:52:32 -040049 u32 sq_config;
Jerome Glisse961fb592010-02-10 22:30:05 +000050 u32 nsamples;
51 u32 cb_color_base_last[8];
52 struct radeon_bo *cb_color_bo[8];
Alex Deucher16790562010-11-14 20:24:35 -050053 u64 cb_color_bo_mc[8];
Jerome Glisse961fb592010-02-10 22:30:05 +000054 u32 cb_color_bo_offset[8];
55 struct radeon_bo *cb_color_frag_bo[8];
56 struct radeon_bo *cb_color_tile_bo[8];
57 u32 cb_color_info[8];
58 u32 cb_color_size_idx[8];
59 u32 cb_target_mask;
60 u32 cb_shader_mask;
61 u32 cb_color_size[8];
62 u32 vgt_strmout_en;
63 u32 vgt_strmout_buffer_en;
Marek Olšákdd220a02012-01-27 12:17:59 -050064 struct radeon_bo *vgt_strmout_bo[4];
65 u64 vgt_strmout_bo_mc[4];
66 u32 vgt_strmout_bo_offset[4];
67 u32 vgt_strmout_size[4];
Jerome Glisse961fb592010-02-10 22:30:05 +000068 u32 db_depth_control;
69 u32 db_depth_info;
70 u32 db_depth_size_idx;
71 u32 db_depth_view;
72 u32 db_depth_size;
73 u32 db_offset;
74 struct radeon_bo *db_bo;
Alex Deucher16790562010-11-14 20:24:35 -050075 u64 db_bo_mc;
Jerome Glissec8c15ff2010-01-18 13:01:36 +010076};
77
Marek Olšákfe6f0bd2011-05-07 01:09:57 +020078#define FMT_8_BIT(fmt, vc) [fmt] = { 1, 1, 1, vc, CHIP_R600 }
79#define FMT_16_BIT(fmt, vc) [fmt] = { 1, 1, 2, vc, CHIP_R600 }
80#define FMT_24_BIT(fmt) [fmt] = { 1, 1, 3, 0, CHIP_R600 }
81#define FMT_32_BIT(fmt, vc) [fmt] = { 1, 1, 4, vc, CHIP_R600 }
82#define FMT_48_BIT(fmt) [fmt] = { 1, 1, 6, 0, CHIP_R600 }
83#define FMT_64_BIT(fmt, vc) [fmt] = { 1, 1, 8, vc, CHIP_R600 }
84#define FMT_96_BIT(fmt) [fmt] = { 1, 1, 12, 0, CHIP_R600 }
85#define FMT_128_BIT(fmt, vc) [fmt] = { 1, 1, 16,vc, CHIP_R600 }
Dave Airlie60b212f2011-02-18 05:51:58 +000086
87struct gpu_formats {
88 unsigned blockwidth;
89 unsigned blockheight;
90 unsigned blocksize;
91 unsigned valid_color;
Marek Olšákfe6f0bd2011-05-07 01:09:57 +020092 enum radeon_family min_family;
Dave Airlie60b212f2011-02-18 05:51:58 +000093};
94
95static const struct gpu_formats color_formats_table[] = {
96 /* 8 bit */
97 FMT_8_BIT(V_038004_COLOR_8, 1),
98 FMT_8_BIT(V_038004_COLOR_4_4, 1),
99 FMT_8_BIT(V_038004_COLOR_3_3_2, 1),
100 FMT_8_BIT(V_038004_FMT_1, 0),
101
102 /* 16-bit */
103 FMT_16_BIT(V_038004_COLOR_16, 1),
104 FMT_16_BIT(V_038004_COLOR_16_FLOAT, 1),
105 FMT_16_BIT(V_038004_COLOR_8_8, 1),
106 FMT_16_BIT(V_038004_COLOR_5_6_5, 1),
107 FMT_16_BIT(V_038004_COLOR_6_5_5, 1),
108 FMT_16_BIT(V_038004_COLOR_1_5_5_5, 1),
109 FMT_16_BIT(V_038004_COLOR_4_4_4_4, 1),
110 FMT_16_BIT(V_038004_COLOR_5_5_5_1, 1),
111
112 /* 24-bit */
113 FMT_24_BIT(V_038004_FMT_8_8_8),
114
115 /* 32-bit */
116 FMT_32_BIT(V_038004_COLOR_32, 1),
117 FMT_32_BIT(V_038004_COLOR_32_FLOAT, 1),
118 FMT_32_BIT(V_038004_COLOR_16_16, 1),
119 FMT_32_BIT(V_038004_COLOR_16_16_FLOAT, 1),
120 FMT_32_BIT(V_038004_COLOR_8_24, 1),
121 FMT_32_BIT(V_038004_COLOR_8_24_FLOAT, 1),
122 FMT_32_BIT(V_038004_COLOR_24_8, 1),
123 FMT_32_BIT(V_038004_COLOR_24_8_FLOAT, 1),
124 FMT_32_BIT(V_038004_COLOR_10_11_11, 1),
125 FMT_32_BIT(V_038004_COLOR_10_11_11_FLOAT, 1),
126 FMT_32_BIT(V_038004_COLOR_11_11_10, 1),
127 FMT_32_BIT(V_038004_COLOR_11_11_10_FLOAT, 1),
128 FMT_32_BIT(V_038004_COLOR_2_10_10_10, 1),
129 FMT_32_BIT(V_038004_COLOR_8_8_8_8, 1),
130 FMT_32_BIT(V_038004_COLOR_10_10_10_2, 1),
131 FMT_32_BIT(V_038004_FMT_5_9_9_9_SHAREDEXP, 0),
132 FMT_32_BIT(V_038004_FMT_32_AS_8, 0),
133 FMT_32_BIT(V_038004_FMT_32_AS_8_8, 0),
134
135 /* 48-bit */
136 FMT_48_BIT(V_038004_FMT_16_16_16),
137 FMT_48_BIT(V_038004_FMT_16_16_16_FLOAT),
138
139 /* 64-bit */
140 FMT_64_BIT(V_038004_COLOR_X24_8_32_FLOAT, 1),
141 FMT_64_BIT(V_038004_COLOR_32_32, 1),
142 FMT_64_BIT(V_038004_COLOR_32_32_FLOAT, 1),
143 FMT_64_BIT(V_038004_COLOR_16_16_16_16, 1),
144 FMT_64_BIT(V_038004_COLOR_16_16_16_16_FLOAT, 1),
145
146 FMT_96_BIT(V_038004_FMT_32_32_32),
147 FMT_96_BIT(V_038004_FMT_32_32_32_FLOAT),
148
149 /* 128-bit */
150 FMT_128_BIT(V_038004_COLOR_32_32_32_32, 1),
151 FMT_128_BIT(V_038004_COLOR_32_32_32_32_FLOAT, 1),
152
153 [V_038004_FMT_GB_GR] = { 2, 1, 4, 0 },
154 [V_038004_FMT_BG_RG] = { 2, 1, 4, 0 },
155
156 /* block compressed formats */
157 [V_038004_FMT_BC1] = { 4, 4, 8, 0 },
158 [V_038004_FMT_BC2] = { 4, 4, 16, 0 },
159 [V_038004_FMT_BC3] = { 4, 4, 16, 0 },
160 [V_038004_FMT_BC4] = { 4, 4, 8, 0 },
161 [V_038004_FMT_BC5] = { 4, 4, 16, 0},
Marek Olšákfe6f0bd2011-05-07 01:09:57 +0200162 [V_038004_FMT_BC6] = { 4, 4, 16, 0, CHIP_CEDAR}, /* Evergreen-only */
163 [V_038004_FMT_BC7] = { 4, 4, 16, 0, CHIP_CEDAR}, /* Evergreen-only */
Dave Airlie60b212f2011-02-18 05:51:58 +0000164
Marek Olšákfe6f0bd2011-05-07 01:09:57 +0200165 /* The other Evergreen formats */
166 [V_038004_FMT_32_AS_32_32_32_32] = { 1, 1, 4, 0, CHIP_CEDAR},
Dave Airlie60b212f2011-02-18 05:51:58 +0000167};
168
Andi Kleen488479e2011-10-13 16:08:41 -0700169static bool fmt_is_valid_color(u32 format)
Dave Airlie60b212f2011-02-18 05:51:58 +0000170{
Dan Carpentercf8a47d2011-02-26 04:48:18 +0300171 if (format >= ARRAY_SIZE(color_formats_table))
Dave Airlie60b212f2011-02-18 05:51:58 +0000172 return false;
173
174 if (color_formats_table[format].valid_color)
175 return true;
176
177 return false;
178}
179
Andi Kleen488479e2011-10-13 16:08:41 -0700180static bool fmt_is_valid_texture(u32 format, enum radeon_family family)
Dave Airlie60b212f2011-02-18 05:51:58 +0000181{
Dan Carpentercf8a47d2011-02-26 04:48:18 +0300182 if (format >= ARRAY_SIZE(color_formats_table))
Dave Airlie60b212f2011-02-18 05:51:58 +0000183 return false;
184
Marek Olšákfe6f0bd2011-05-07 01:09:57 +0200185 if (family < color_formats_table[format].min_family)
186 return false;
187
Dave Airlie60b212f2011-02-18 05:51:58 +0000188 if (color_formats_table[format].blockwidth > 0)
189 return true;
190
191 return false;
192}
193
Andi Kleen488479e2011-10-13 16:08:41 -0700194static int fmt_get_blocksize(u32 format)
Dave Airlie60b212f2011-02-18 05:51:58 +0000195{
Dan Carpentercf8a47d2011-02-26 04:48:18 +0300196 if (format >= ARRAY_SIZE(color_formats_table))
Dave Airlie60b212f2011-02-18 05:51:58 +0000197 return 0;
198
199 return color_formats_table[format].blocksize;
200}
201
Andi Kleen488479e2011-10-13 16:08:41 -0700202static int fmt_get_nblocksx(u32 format, u32 w)
Dave Airlie60b212f2011-02-18 05:51:58 +0000203{
204 unsigned bw;
Dan Carpentercf8a47d2011-02-26 04:48:18 +0300205
206 if (format >= ARRAY_SIZE(color_formats_table))
Dave Airlie60b212f2011-02-18 05:51:58 +0000207 return 0;
208
209 bw = color_formats_table[format].blockwidth;
210 if (bw == 0)
211 return 0;
212
213 return (w + bw - 1) / bw;
214}
215
Andi Kleen488479e2011-10-13 16:08:41 -0700216static int fmt_get_nblocksy(u32 format, u32 h)
Dave Airlie60b212f2011-02-18 05:51:58 +0000217{
218 unsigned bh;
Dan Carpentercf8a47d2011-02-26 04:48:18 +0300219
220 if (format >= ARRAY_SIZE(color_formats_table))
Dave Airlie60b212f2011-02-18 05:51:58 +0000221 return 0;
222
223 bh = color_formats_table[format].blockheight;
224 if (bh == 0)
225 return 0;
226
227 return (h + bh - 1) / bh;
228}
229
Alex Deucher16790562010-11-14 20:24:35 -0500230struct array_mode_checker {
231 int array_mode;
232 u32 group_size;
233 u32 nbanks;
234 u32 npipes;
235 u32 nsamples;
Dave Airlie60b212f2011-02-18 05:51:58 +0000236 u32 blocksize;
Alex Deucher16790562010-11-14 20:24:35 -0500237};
238
239/* returns alignment in pixels for pitch/height/depth and bytes for base */
Andi Kleen488479e2011-10-13 16:08:41 -0700240static int r600_get_array_mode_alignment(struct array_mode_checker *values,
Alex Deucher16790562010-11-14 20:24:35 -0500241 u32 *pitch_align,
242 u32 *height_align,
243 u32 *depth_align,
244 u64 *base_align)
245{
246 u32 tile_width = 8;
247 u32 tile_height = 8;
248 u32 macro_tile_width = values->nbanks;
249 u32 macro_tile_height = values->npipes;
Dave Airlie60b212f2011-02-18 05:51:58 +0000250 u32 tile_bytes = tile_width * tile_height * values->blocksize * values->nsamples;
Alex Deucher16790562010-11-14 20:24:35 -0500251 u32 macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes;
252
253 switch (values->array_mode) {
254 case ARRAY_LINEAR_GENERAL:
255 /* technically tile_width/_height for pitch/height */
256 *pitch_align = 1; /* tile_width */
257 *height_align = 1; /* tile_height */
258 *depth_align = 1;
259 *base_align = 1;
260 break;
261 case ARRAY_LINEAR_ALIGNED:
Dave Airlie60b212f2011-02-18 05:51:58 +0000262 *pitch_align = max((u32)64, (u32)(values->group_size / values->blocksize));
Alex Deucher16790562010-11-14 20:24:35 -0500263 *height_align = tile_height;
264 *depth_align = 1;
265 *base_align = values->group_size;
266 break;
267 case ARRAY_1D_TILED_THIN1:
268 *pitch_align = max((u32)tile_width,
269 (u32)(values->group_size /
Dave Airlie60b212f2011-02-18 05:51:58 +0000270 (tile_height * values->blocksize * values->nsamples)));
Alex Deucher16790562010-11-14 20:24:35 -0500271 *height_align = tile_height;
272 *depth_align = 1;
273 *base_align = values->group_size;
274 break;
275 case ARRAY_2D_TILED_THIN1:
276 *pitch_align = max((u32)macro_tile_width,
277 (u32)(((values->group_size / tile_height) /
Dave Airlie60b212f2011-02-18 05:51:58 +0000278 (values->blocksize * values->nsamples)) *
Alex Deucher16790562010-11-14 20:24:35 -0500279 values->nbanks)) * tile_width;
280 *height_align = macro_tile_height * tile_height;
281 *depth_align = 1;
282 *base_align = max(macro_tile_bytes,
Dave Airlie60b212f2011-02-18 05:51:58 +0000283 (*pitch_align) * values->blocksize * (*height_align) * values->nsamples);
Alex Deucher16790562010-11-14 20:24:35 -0500284 break;
285 default:
286 return -EINVAL;
287 }
288
289 return 0;
290}
291
Jerome Glisse961fb592010-02-10 22:30:05 +0000292static void r600_cs_track_init(struct r600_cs_track *track)
293{
294 int i;
295
Alex Deucher5f77df32010-03-26 14:52:32 -0400296 /* assume DX9 mode */
297 track->sq_config = DX9_CONSTS;
Jerome Glisse961fb592010-02-10 22:30:05 +0000298 for (i = 0; i < 8; i++) {
299 track->cb_color_base_last[i] = 0;
300 track->cb_color_size[i] = 0;
301 track->cb_color_size_idx[i] = 0;
302 track->cb_color_info[i] = 0;
303 track->cb_color_bo[i] = NULL;
304 track->cb_color_bo_offset[i] = 0xFFFFFFFF;
Alex Deucher16790562010-11-14 20:24:35 -0500305 track->cb_color_bo_mc[i] = 0xFFFFFFFF;
Jerome Glisse961fb592010-02-10 22:30:05 +0000306 }
307 track->cb_target_mask = 0xFFFFFFFF;
308 track->cb_shader_mask = 0xFFFFFFFF;
309 track->db_bo = NULL;
Alex Deucher16790562010-11-14 20:24:35 -0500310 track->db_bo_mc = 0xFFFFFFFF;
Jerome Glisse961fb592010-02-10 22:30:05 +0000311 /* assume the biggest format and that htile is enabled */
312 track->db_depth_info = 7 | (1 << 25);
313 track->db_depth_view = 0xFFFFC000;
314 track->db_depth_size = 0xFFFFFFFF;
315 track->db_depth_size_idx = 0;
316 track->db_depth_control = 0xFFFFFFFF;
Marek Olšákdd220a02012-01-27 12:17:59 -0500317
318 for (i = 0; i < 4; i++) {
319 track->vgt_strmout_size[i] = 0;
320 track->vgt_strmout_bo[i] = NULL;
321 track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
322 track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF;
323 }
Jerome Glisse961fb592010-02-10 22:30:05 +0000324}
325
Andi Kleen488479e2011-10-13 16:08:41 -0700326static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
Jerome Glisse961fb592010-02-10 22:30:05 +0000327{
328 struct r600_cs_track *track = p->track;
Dave Airlie60b212f2011-02-18 05:51:58 +0000329 u32 slice_tile_max, size, tmp;
Alex Deucher16790562010-11-14 20:24:35 -0500330 u32 height, height_align, pitch, pitch_align, depth_align;
331 u64 base_offset, base_align;
332 struct array_mode_checker array_check;
Jerome Glisse961fb592010-02-10 22:30:05 +0000333 volatile u32 *ib = p->ib->ptr;
Dave Airlief30df2f2010-10-21 13:55:40 +1000334 unsigned array_mode;
Dave Airlie60b212f2011-02-18 05:51:58 +0000335 u32 format;
Jerome Glisse961fb592010-02-10 22:30:05 +0000336 if (G_0280A0_TILE_MODE(track->cb_color_info[i])) {
337 dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n");
338 return -EINVAL;
339 }
Alex Deucher1729dd32010-08-06 02:54:05 -0400340 size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i];
Dave Airlie60b212f2011-02-18 05:51:58 +0000341 format = G_0280A0_FORMAT(track->cb_color_info[i]);
342 if (!fmt_is_valid_color(format)) {
Jerome Glisse961fb592010-02-10 22:30:05 +0000343 dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n",
Dave Airlie60b212f2011-02-18 05:51:58 +0000344 __func__, __LINE__, format,
Jerome Glisse961fb592010-02-10 22:30:05 +0000345 i, track->cb_color_info[i]);
346 return -EINVAL;
347 }
Alex Deucher16790562010-11-14 20:24:35 -0500348 /* pitch in pixels */
349 pitch = (G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1) * 8;
Jerome Glisse961fb592010-02-10 22:30:05 +0000350 slice_tile_max = G_028060_SLICE_TILE_MAX(track->cb_color_size[i]) + 1;
Dave Airlief30df2f2010-10-21 13:55:40 +1000351 slice_tile_max *= 64;
Alex Deucher16790562010-11-14 20:24:35 -0500352 height = slice_tile_max / pitch;
Jerome Glisse961fb592010-02-10 22:30:05 +0000353 if (height > 8192)
354 height = 8192;
Dave Airlief30df2f2010-10-21 13:55:40 +1000355 array_mode = G_0280A0_ARRAY_MODE(track->cb_color_info[i]);
Alex Deucher16790562010-11-14 20:24:35 -0500356
357 base_offset = track->cb_color_bo_mc[i] + track->cb_color_bo_offset[i];
358 array_check.array_mode = array_mode;
359 array_check.group_size = track->group_size;
360 array_check.nbanks = track->nbanks;
361 array_check.npipes = track->npipes;
362 array_check.nsamples = track->nsamples;
Dave Airlie60b212f2011-02-18 05:51:58 +0000363 array_check.blocksize = fmt_get_blocksize(format);
Alex Deucher16790562010-11-14 20:24:35 -0500364 if (r600_get_array_mode_alignment(&array_check,
365 &pitch_align, &height_align, &depth_align, &base_align)) {
366 dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
367 G_0280A0_ARRAY_MODE(track->cb_color_info[i]), i,
368 track->cb_color_info[i]);
369 return -EINVAL;
370 }
Dave Airlief30df2f2010-10-21 13:55:40 +1000371 switch (array_mode) {
Jerome Glisse961fb592010-02-10 22:30:05 +0000372 case V_0280A0_ARRAY_LINEAR_GENERAL:
Alex Deucher40e2a5c2010-06-04 18:41:42 -0400373 break;
Jerome Glisse961fb592010-02-10 22:30:05 +0000374 case V_0280A0_ARRAY_LINEAR_ALIGNED:
Jerome Glisse961fb592010-02-10 22:30:05 +0000375 break;
376 case V_0280A0_ARRAY_1D_TILED_THIN1:
Alex Deucher8f895da2010-10-26 20:22:42 -0400377 /* avoid breaking userspace */
378 if (height > 7)
379 height &= ~0x7;
Jerome Glisse961fb592010-02-10 22:30:05 +0000380 break;
381 case V_0280A0_ARRAY_2D_TILED_THIN1:
Jerome Glisse961fb592010-02-10 22:30:05 +0000382 break;
383 default:
384 dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
385 G_0280A0_ARRAY_MODE(track->cb_color_info[i]), i,
386 track->cb_color_info[i]);
387 return -EINVAL;
388 }
Alex Deucher16790562010-11-14 20:24:35 -0500389
390 if (!IS_ALIGNED(pitch, pitch_align)) {
Alex Deucherc2049b32011-02-13 18:42:41 -0500391 dev_warn(p->dev, "%s:%d cb pitch (%d, 0x%x, %d) invalid\n",
392 __func__, __LINE__, pitch, pitch_align, array_mode);
Alex Deucher16790562010-11-14 20:24:35 -0500393 return -EINVAL;
394 }
395 if (!IS_ALIGNED(height, height_align)) {
Alex Deucherc2049b32011-02-13 18:42:41 -0500396 dev_warn(p->dev, "%s:%d cb height (%d, 0x%x, %d) invalid\n",
397 __func__, __LINE__, height, height_align, array_mode);
Alex Deucher16790562010-11-14 20:24:35 -0500398 return -EINVAL;
399 }
400 if (!IS_ALIGNED(base_offset, base_align)) {
Alex Deucherc2049b32011-02-13 18:42:41 -0500401 dev_warn(p->dev, "%s offset[%d] 0x%llx 0x%llx, %d not aligned\n", __func__, i,
402 base_offset, base_align, array_mode);
Alex Deucher16790562010-11-14 20:24:35 -0500403 return -EINVAL;
404 }
405
Jerome Glisse961fb592010-02-10 22:30:05 +0000406 /* check offset */
Dave Airlie60b212f2011-02-18 05:51:58 +0000407 tmp = fmt_get_nblocksy(format, height) * fmt_get_nblocksx(format, pitch) * fmt_get_blocksize(format);
Jerome Glisse961fb592010-02-10 22:30:05 +0000408 if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
Dave Airlief30df2f2010-10-21 13:55:40 +1000409 if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) {
410 /* the initial DDX does bad things with the CB size occasionally */
411 /* it rounds up height too far for slice tile max but the BO is smaller */
Alex Deuchera1a82132010-12-13 14:03:09 -0500412 /* r600c,g also seem to flush at bad times in some apps resulting in
413 * bogus values here. So for linear just allow anything to avoid breaking
414 * broken userspace.
415 */
Dave Airlief30df2f2010-10-21 13:55:40 +1000416 } else {
Alex Deucherc2049b32011-02-13 18:42:41 -0500417 dev_warn(p->dev, "%s offset[%d] %d %d %d %lu too big\n", __func__, i,
418 array_mode,
419 track->cb_color_bo_offset[i], tmp,
420 radeon_bo_size(track->cb_color_bo[i]));
Dave Airlief30df2f2010-10-21 13:55:40 +1000421 return -EINVAL;
422 }
Alex Deucher40e2a5c2010-06-04 18:41:42 -0400423 }
Jerome Glisse961fb592010-02-10 22:30:05 +0000424 /* limit max tile */
Alex Deucher16790562010-11-14 20:24:35 -0500425 tmp = (height * pitch) >> 6;
Jerome Glisse961fb592010-02-10 22:30:05 +0000426 if (tmp < slice_tile_max)
427 slice_tile_max = tmp;
Alex Deucher16790562010-11-14 20:24:35 -0500428 tmp = S_028060_PITCH_TILE_MAX((pitch / 8) - 1) |
Jerome Glisse961fb592010-02-10 22:30:05 +0000429 S_028060_SLICE_TILE_MAX(slice_tile_max - 1);
430 ib[track->cb_color_size_idx[i]] = tmp;
431 return 0;
432}
433
434static int r600_cs_track_check(struct radeon_cs_parser *p)
435{
436 struct r600_cs_track *track = p->track;
437 u32 tmp;
438 int r, i;
439 volatile u32 *ib = p->ib->ptr;
440
441 /* on legacy kernel we don't perform advanced check */
442 if (p->rdev == NULL)
443 return 0;
Marek Olšákdd220a02012-01-27 12:17:59 -0500444
445 /* check streamout */
446 if (track->vgt_strmout_en) {
447 for (i = 0; i < 4; i++) {
448 if (track->vgt_strmout_buffer_en & (1 << i)) {
449 if (track->vgt_strmout_bo[i]) {
450 u64 offset = (u64)track->vgt_strmout_bo_offset[i] +
451 (u64)track->vgt_strmout_size[i];
452 if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) {
453 DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n",
454 i, offset,
455 radeon_bo_size(track->vgt_strmout_bo[i]));
456 return -EINVAL;
457 }
458 } else {
459 dev_warn(p->dev, "No buffer for streamout %d\n", i);
460 return -EINVAL;
461 }
462 }
463 }
Jerome Glisse961fb592010-02-10 22:30:05 +0000464 }
Marek Olšákdd220a02012-01-27 12:17:59 -0500465
Jerome Glisse961fb592010-02-10 22:30:05 +0000466 /* check that we have a cb for each enabled target, we don't check
467 * shader_mask because it seems mesa isn't always setting it :(
468 */
469 tmp = track->cb_target_mask;
470 for (i = 0; i < 8; i++) {
471 if ((tmp >> (i * 4)) & 0xF) {
472 /* at least one component is enabled */
473 if (track->cb_color_bo[i] == NULL) {
474 dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n",
475 __func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i);
476 return -EINVAL;
477 }
478 /* perform rewrite of CB_COLOR[0-7]_SIZE */
479 r = r600_cs_track_validate_cb(p, i);
480 if (r)
481 return r;
482 }
483 }
484 /* Check depth buffer */
485 if (G_028800_STENCIL_ENABLE(track->db_depth_control) ||
486 G_028800_Z_ENABLE(track->db_depth_control)) {
Alex Deucher16790562010-11-14 20:24:35 -0500487 u32 nviews, bpe, ntiles, size, slice_tile_max;
488 u32 height, height_align, pitch, pitch_align, depth_align;
489 u64 base_offset, base_align;
490 struct array_mode_checker array_check;
491 int array_mode;
492
Jerome Glisse961fb592010-02-10 22:30:05 +0000493 if (track->db_bo == NULL) {
494 dev_warn(p->dev, "z/stencil with no depth buffer\n");
495 return -EINVAL;
496 }
497 if (G_028010_TILE_SURFACE_ENABLE(track->db_depth_info)) {
498 dev_warn(p->dev, "this kernel doesn't support z/stencil htile\n");
499 return -EINVAL;
500 }
501 switch (G_028010_FORMAT(track->db_depth_info)) {
502 case V_028010_DEPTH_16:
503 bpe = 2;
504 break;
505 case V_028010_DEPTH_X8_24:
506 case V_028010_DEPTH_8_24:
507 case V_028010_DEPTH_X8_24_FLOAT:
508 case V_028010_DEPTH_8_24_FLOAT:
509 case V_028010_DEPTH_32_FLOAT:
510 bpe = 4;
511 break;
512 case V_028010_DEPTH_X24_8_32_FLOAT:
513 bpe = 8;
514 break;
515 default:
516 dev_warn(p->dev, "z/stencil with invalid format %d\n", G_028010_FORMAT(track->db_depth_info));
517 return -EINVAL;
518 }
519 if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) {
520 if (!track->db_depth_size_idx) {
521 dev_warn(p->dev, "z/stencil buffer size not set\n");
522 return -EINVAL;
523 }
Jerome Glisse961fb592010-02-10 22:30:05 +0000524 tmp = radeon_bo_size(track->db_bo) - track->db_offset;
525 tmp = (tmp / bpe) >> 6;
526 if (!tmp) {
527 dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %ld)\n",
528 track->db_depth_size, bpe, track->db_offset,
529 radeon_bo_size(track->db_bo));
530 return -EINVAL;
531 }
532 ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF);
533 } else {
Alex Deucher40e2a5c2010-06-04 18:41:42 -0400534 size = radeon_bo_size(track->db_bo);
Alex Deucher16790562010-11-14 20:24:35 -0500535 /* pitch in pixels */
536 pitch = (G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1) * 8;
Alex Deucher2c7d81a2010-10-27 01:44:35 -0400537 slice_tile_max = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
538 slice_tile_max *= 64;
Alex Deucher16790562010-11-14 20:24:35 -0500539 height = slice_tile_max / pitch;
Alex Deucher2c7d81a2010-10-27 01:44:35 -0400540 if (height > 8192)
541 height = 8192;
Alex Deucher16790562010-11-14 20:24:35 -0500542 base_offset = track->db_bo_mc + track->db_offset;
543 array_mode = G_028010_ARRAY_MODE(track->db_depth_info);
544 array_check.array_mode = array_mode;
545 array_check.group_size = track->group_size;
546 array_check.nbanks = track->nbanks;
547 array_check.npipes = track->npipes;
548 array_check.nsamples = track->nsamples;
Dave Airlie60b212f2011-02-18 05:51:58 +0000549 array_check.blocksize = bpe;
Alex Deucher16790562010-11-14 20:24:35 -0500550 if (r600_get_array_mode_alignment(&array_check,
551 &pitch_align, &height_align, &depth_align, &base_align)) {
552 dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
553 G_028010_ARRAY_MODE(track->db_depth_info),
554 track->db_depth_info);
555 return -EINVAL;
556 }
557 switch (array_mode) {
Alex Deucher40e2a5c2010-06-04 18:41:42 -0400558 case V_028010_ARRAY_1D_TILED_THIN1:
Alex Deucher2c7d81a2010-10-27 01:44:35 -0400559 /* don't break userspace */
560 height &= ~0x7;
Alex Deucher40e2a5c2010-06-04 18:41:42 -0400561 break;
562 case V_028010_ARRAY_2D_TILED_THIN1:
Alex Deucher40e2a5c2010-06-04 18:41:42 -0400563 break;
564 default:
565 dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
566 G_028010_ARRAY_MODE(track->db_depth_info),
567 track->db_depth_info);
568 return -EINVAL;
569 }
Alex Deucher16790562010-11-14 20:24:35 -0500570
571 if (!IS_ALIGNED(pitch, pitch_align)) {
Alex Deucherc2049b32011-02-13 18:42:41 -0500572 dev_warn(p->dev, "%s:%d db pitch (%d, 0x%x, %d) invalid\n",
573 __func__, __LINE__, pitch, pitch_align, array_mode);
Alex Deucher40e2a5c2010-06-04 18:41:42 -0400574 return -EINVAL;
575 }
Alex Deucher16790562010-11-14 20:24:35 -0500576 if (!IS_ALIGNED(height, height_align)) {
Alex Deucherc2049b32011-02-13 18:42:41 -0500577 dev_warn(p->dev, "%s:%d db height (%d, 0x%x, %d) invalid\n",
578 __func__, __LINE__, height, height_align, array_mode);
Alex Deucher16790562010-11-14 20:24:35 -0500579 return -EINVAL;
580 }
581 if (!IS_ALIGNED(base_offset, base_align)) {
Alex Deucherc2049b32011-02-13 18:42:41 -0500582 dev_warn(p->dev, "%s offset[%d] 0x%llx, 0x%llx, %d not aligned\n", __func__, i,
583 base_offset, base_align, array_mode);
Alex Deucher16790562010-11-14 20:24:35 -0500584 return -EINVAL;
585 }
586
Jerome Glisse961fb592010-02-10 22:30:05 +0000587 ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
588 nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1;
589 tmp = ntiles * bpe * 64 * nviews;
590 if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {
Alex Deucherc2049b32011-02-13 18:42:41 -0500591 dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n",
592 array_mode,
593 track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
594 radeon_bo_size(track->db_bo));
Jerome Glisse961fb592010-02-10 22:30:05 +0000595 return -EINVAL;
596 }
597 }
598 }
599 return 0;
600}
601
Jerome Glisse3ce0a232009-09-08 10:10:24 +1000602/**
603 * r600_cs_packet_parse() - parse cp packet and point ib index to next packet
604 * @parser: parser structure holding parsing context.
605 * @pkt: where to store packet informations
606 *
607 * Assume that chunk_ib_index is properly set. Will return -EINVAL
608 * if packet is bigger than remaining ib size. or if packets is unknown.
609 **/
610int r600_cs_packet_parse(struct radeon_cs_parser *p,
611 struct radeon_cs_packet *pkt,
612 unsigned idx)
613{
614 struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
615 uint32_t header;
616
617 if (idx >= ib_chunk->length_dw) {
618 DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
619 idx, ib_chunk->length_dw);
620 return -EINVAL;
621 }
Dave Airlie513bcb42009-09-23 16:56:27 +1000622 header = radeon_get_ib_value(p, idx);
Jerome Glisse3ce0a232009-09-08 10:10:24 +1000623 pkt->idx = idx;
624 pkt->type = CP_PACKET_GET_TYPE(header);
625 pkt->count = CP_PACKET_GET_COUNT(header);
626 pkt->one_reg_wr = 0;
627 switch (pkt->type) {
628 case PACKET_TYPE0:
629 pkt->reg = CP_PACKET0_GET_REG(header);
630 break;
631 case PACKET_TYPE3:
632 pkt->opcode = CP_PACKET3_GET_OPCODE(header);
633 break;
634 case PACKET_TYPE2:
635 pkt->count = -1;
636 break;
637 default:
638 DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
639 return -EINVAL;
640 }
641 if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
642 DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
643 pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
644 return -EINVAL;
645 }
646 return 0;
647}
648
649/**
650 * r600_cs_packet_next_reloc_mm() - parse next packet which should be reloc packet3
651 * @parser: parser structure holding parsing context.
652 * @data: pointer to relocation data
653 * @offset_start: starting offset
654 * @offset_mask: offset mask (to align start offset on)
655 * @reloc: reloc informations
656 *
657 * Check next packet is relocation packet3, do bo validation and compute
658 * GPU offset using the provided start.
659 **/
660static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
661 struct radeon_cs_reloc **cs_reloc)
662{
Jerome Glisse3ce0a232009-09-08 10:10:24 +1000663 struct radeon_cs_chunk *relocs_chunk;
664 struct radeon_cs_packet p3reloc;
665 unsigned idx;
666 int r;
667
668 if (p->chunk_relocs_idx == -1) {
669 DRM_ERROR("No relocation chunk !\n");
670 return -EINVAL;
671 }
672 *cs_reloc = NULL;
Jerome Glisse3ce0a232009-09-08 10:10:24 +1000673 relocs_chunk = &p->chunks[p->chunk_relocs_idx];
674 r = r600_cs_packet_parse(p, &p3reloc, p->idx);
675 if (r) {
676 return r;
677 }
678 p->idx += p3reloc.count + 2;
679 if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
680 DRM_ERROR("No packet3 for relocation for packet at %d.\n",
681 p3reloc.idx);
682 return -EINVAL;
683 }
Dave Airlie513bcb42009-09-23 16:56:27 +1000684 idx = radeon_get_ib_value(p, p3reloc.idx + 1);
Jerome Glisse3ce0a232009-09-08 10:10:24 +1000685 if (idx >= relocs_chunk->length_dw) {
686 DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
687 idx, relocs_chunk->length_dw);
688 return -EINVAL;
689 }
690 /* FIXME: we assume reloc size is 4 dwords */
691 *cs_reloc = p->relocs_ptr[(idx / 4)];
692 return 0;
693}
694
695/**
696 * r600_cs_packet_next_reloc_nomm() - parse next packet which should be reloc packet3
697 * @parser: parser structure holding parsing context.
698 * @data: pointer to relocation data
699 * @offset_start: starting offset
700 * @offset_mask: offset mask (to align start offset on)
701 * @reloc: reloc informations
702 *
703 * Check next packet is relocation packet3, do bo validation and compute
704 * GPU offset using the provided start.
705 **/
706static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
707 struct radeon_cs_reloc **cs_reloc)
708{
Jerome Glisse3ce0a232009-09-08 10:10:24 +1000709 struct radeon_cs_chunk *relocs_chunk;
710 struct radeon_cs_packet p3reloc;
711 unsigned idx;
712 int r;
713
714 if (p->chunk_relocs_idx == -1) {
715 DRM_ERROR("No relocation chunk !\n");
716 return -EINVAL;
717 }
718 *cs_reloc = NULL;
Jerome Glisse3ce0a232009-09-08 10:10:24 +1000719 relocs_chunk = &p->chunks[p->chunk_relocs_idx];
720 r = r600_cs_packet_parse(p, &p3reloc, p->idx);
721 if (r) {
722 return r;
723 }
724 p->idx += p3reloc.count + 2;
725 if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
726 DRM_ERROR("No packet3 for relocation for packet at %d.\n",
727 p3reloc.idx);
728 return -EINVAL;
729 }
Dave Airlie513bcb42009-09-23 16:56:27 +1000730 idx = radeon_get_ib_value(p, p3reloc.idx + 1);
Jerome Glisse3ce0a232009-09-08 10:10:24 +1000731 if (idx >= relocs_chunk->length_dw) {
732 DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
733 idx, relocs_chunk->length_dw);
734 return -EINVAL;
735 }
Julia Lawalle265f39e2009-12-19 08:16:33 +0100736 *cs_reloc = p->relocs;
Jerome Glisse3ce0a232009-09-08 10:10:24 +1000737 (*cs_reloc)->lobj.gpu_offset = (u64)relocs_chunk->kdata[idx + 3] << 32;
738 (*cs_reloc)->lobj.gpu_offset |= relocs_chunk->kdata[idx + 0];
739 return 0;
740}
741
Alex Deucher2f67c6e2009-09-25 16:35:11 -0400742/**
Jerome Glissec8c15ff2010-01-18 13:01:36 +0100743 * r600_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc
744 * @parser: parser structure holding parsing context.
745 *
746 * Check next packet is relocation packet3, do bo validation and compute
747 * GPU offset using the provided start.
748 **/
Andi Kleen488479e2011-10-13 16:08:41 -0700749static int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
Jerome Glissec8c15ff2010-01-18 13:01:36 +0100750{
751 struct radeon_cs_packet p3reloc;
752 int r;
753
754 r = r600_cs_packet_parse(p, &p3reloc, p->idx);
755 if (r) {
756 return 0;
757 }
758 if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
759 return 0;
760 }
761 return 1;
762}
763
764/**
Alex Deucher2f67c6e2009-09-25 16:35:11 -0400765 * r600_cs_packet_next_vline() - parse userspace VLINE packet
766 * @parser: parser structure holding parsing context.
767 *
768 * Userspace sends a special sequence for VLINE waits.
769 * PACKET0 - VLINE_START_END + value
770 * PACKET3 - WAIT_REG_MEM poll vline status reg
771 * RELOC (P3) - crtc_id in reloc.
772 *
773 * This function parses this and relocates the VLINE START END
774 * and WAIT_REG_MEM packets to the correct crtc.
775 * It also detects a switched off crtc and nulls out the
776 * wait in that case.
777 */
778static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
779{
780 struct drm_mode_object *obj;
781 struct drm_crtc *crtc;
782 struct radeon_crtc *radeon_crtc;
783 struct radeon_cs_packet p3reloc, wait_reg_mem;
784 int crtc_id;
785 int r;
786 uint32_t header, h_idx, reg, wait_reg_mem_info;
787 volatile uint32_t *ib;
788
789 ib = p->ib->ptr;
790
791 /* parse the WAIT_REG_MEM */
792 r = r600_cs_packet_parse(p, &wait_reg_mem, p->idx);
793 if (r)
794 return r;
795
796 /* check its a WAIT_REG_MEM */
797 if (wait_reg_mem.type != PACKET_TYPE3 ||
798 wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
799 DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
Paul Bollea3a88a62011-03-16 22:10:06 +0100800 return -EINVAL;
Alex Deucher2f67c6e2009-09-25 16:35:11 -0400801 }
802
803 wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
804 /* bit 4 is reg (0) or mem (1) */
805 if (wait_reg_mem_info & 0x10) {
806 DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
Paul Bollea3a88a62011-03-16 22:10:06 +0100807 return -EINVAL;
Alex Deucher2f67c6e2009-09-25 16:35:11 -0400808 }
809 /* waiting for value to be equal */
810 if ((wait_reg_mem_info & 0x7) != 0x3) {
811 DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
Paul Bollea3a88a62011-03-16 22:10:06 +0100812 return -EINVAL;
Alex Deucher2f67c6e2009-09-25 16:35:11 -0400813 }
814 if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != AVIVO_D1MODE_VLINE_STATUS) {
815 DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
Paul Bollea3a88a62011-03-16 22:10:06 +0100816 return -EINVAL;
Alex Deucher2f67c6e2009-09-25 16:35:11 -0400817 }
818
819 if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != AVIVO_D1MODE_VLINE_STAT) {
820 DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
Paul Bollea3a88a62011-03-16 22:10:06 +0100821 return -EINVAL;
Alex Deucher2f67c6e2009-09-25 16:35:11 -0400822 }
823
824 /* jump over the NOP */
825 r = r600_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
826 if (r)
827 return r;
828
829 h_idx = p->idx - 2;
830 p->idx += wait_reg_mem.count + 2;
831 p->idx += p3reloc.count + 2;
832
833 header = radeon_get_ib_value(p, h_idx);
834 crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
Dave Airlied4ac6a02009-10-08 11:32:49 +1000835 reg = CP_PACKET0_GET_REG(header);
Dave Airlie29508eb2010-07-22 09:57:13 +1000836
Alex Deucher2f67c6e2009-09-25 16:35:11 -0400837 obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
838 if (!obj) {
839 DRM_ERROR("cannot find crtc %d\n", crtc_id);
Paul Bollea3a88a62011-03-16 22:10:06 +0100840 return -EINVAL;
Alex Deucher2f67c6e2009-09-25 16:35:11 -0400841 }
842 crtc = obj_to_crtc(obj);
843 radeon_crtc = to_radeon_crtc(crtc);
844 crtc_id = radeon_crtc->crtc_id;
845
846 if (!crtc->enabled) {
847 /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
848 ib[h_idx + 2] = PACKET2(0);
849 ib[h_idx + 3] = PACKET2(0);
850 ib[h_idx + 4] = PACKET2(0);
851 ib[h_idx + 5] = PACKET2(0);
852 ib[h_idx + 6] = PACKET2(0);
853 ib[h_idx + 7] = PACKET2(0);
854 ib[h_idx + 8] = PACKET2(0);
855 } else if (crtc_id == 1) {
856 switch (reg) {
857 case AVIVO_D1MODE_VLINE_START_END:
858 header &= ~R600_CP_PACKET0_REG_MASK;
859 header |= AVIVO_D2MODE_VLINE_START_END >> 2;
860 break;
861 default:
862 DRM_ERROR("unknown crtc reloc\n");
Paul Bollea3a88a62011-03-16 22:10:06 +0100863 return -EINVAL;
Alex Deucher2f67c6e2009-09-25 16:35:11 -0400864 }
865 ib[h_idx] = header;
866 ib[h_idx + 4] = AVIVO_D2MODE_VLINE_STATUS >> 2;
867 }
Paul Bollea3a88a62011-03-16 22:10:06 +0100868
869 return 0;
Alex Deucher2f67c6e2009-09-25 16:35:11 -0400870}
871
Jerome Glisse3ce0a232009-09-08 10:10:24 +1000872static int r600_packet0_check(struct radeon_cs_parser *p,
873 struct radeon_cs_packet *pkt,
874 unsigned idx, unsigned reg)
875{
Alex Deucher2f67c6e2009-09-25 16:35:11 -0400876 int r;
877
Jerome Glisse3ce0a232009-09-08 10:10:24 +1000878 switch (reg) {
879 case AVIVO_D1MODE_VLINE_START_END:
Alex Deucher2f67c6e2009-09-25 16:35:11 -0400880 r = r600_cs_packet_parse_vline(p);
881 if (r) {
882 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
883 idx, reg);
884 return r;
885 }
Jerome Glisse3ce0a232009-09-08 10:10:24 +1000886 break;
887 default:
888 printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
889 reg, idx);
890 return -EINVAL;
891 }
892 return 0;
893}
894
895static int r600_cs_parse_packet0(struct radeon_cs_parser *p,
896 struct radeon_cs_packet *pkt)
897{
898 unsigned reg, i;
899 unsigned idx;
900 int r;
901
902 idx = pkt->idx + 1;
903 reg = pkt->reg;
904 for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
905 r = r600_packet0_check(p, pkt, idx, reg);
906 if (r) {
907 return r;
908 }
909 }
910 return 0;
911}
912
Jerome Glisse961fb592010-02-10 22:30:05 +0000913/**
914 * r600_cs_check_reg() - check if register is authorized or not
915 * @parser: parser structure holding parsing context
916 * @reg: register we are testing
917 * @idx: index into the cs buffer
918 *
919 * This function will test against r600_reg_safe_bm and return 0
920 * if register is safe. If register is not flag as safe this function
921 * will test it against a list of register needind special handling.
922 */
Andi Kleen488479e2011-10-13 16:08:41 -0700923static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
Jerome Glisse961fb592010-02-10 22:30:05 +0000924{
925 struct r600_cs_track *track = (struct r600_cs_track *)p->track;
926 struct radeon_cs_reloc *reloc;
Jerome Glisse961fb592010-02-10 22:30:05 +0000927 u32 m, i, tmp, *ib;
928 int r;
929
930 i = (reg >> 7);
Dan Carpenter88498832011-07-27 09:53:40 +0000931 if (i >= ARRAY_SIZE(r600_reg_safe_bm)) {
Jerome Glisse961fb592010-02-10 22:30:05 +0000932 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
933 return -EINVAL;
934 }
935 m = 1 << ((reg >> 2) & 31);
936 if (!(r600_reg_safe_bm[i] & m))
937 return 0;
938 ib = p->ib->ptr;
939 switch (reg) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300940 /* force following reg to 0 in an attempt to disable out buffer
Jerome Glisse961fb592010-02-10 22:30:05 +0000941 * which will need us to better understand how it works to perform
942 * security check on it (Jerome)
943 */
944 case R_0288A8_SQ_ESGS_RING_ITEMSIZE:
945 case R_008C44_SQ_ESGS_RING_SIZE:
946 case R_0288B0_SQ_ESTMP_RING_ITEMSIZE:
947 case R_008C54_SQ_ESTMP_RING_SIZE:
948 case R_0288C0_SQ_FBUF_RING_ITEMSIZE:
949 case R_008C74_SQ_FBUF_RING_SIZE:
950 case R_0288B4_SQ_GSTMP_RING_ITEMSIZE:
951 case R_008C5C_SQ_GSTMP_RING_SIZE:
952 case R_0288AC_SQ_GSVS_RING_ITEMSIZE:
953 case R_008C4C_SQ_GSVS_RING_SIZE:
954 case R_0288BC_SQ_PSTMP_RING_ITEMSIZE:
955 case R_008C6C_SQ_PSTMP_RING_SIZE:
956 case R_0288C4_SQ_REDUC_RING_ITEMSIZE:
957 case R_008C7C_SQ_REDUC_RING_SIZE:
958 case R_0288B8_SQ_VSTMP_RING_ITEMSIZE:
959 case R_008C64_SQ_VSTMP_RING_SIZE:
960 case R_0288C8_SQ_GS_VERT_ITEMSIZE:
961 /* get value to populate the IB don't remove */
962 tmp =radeon_get_ib_value(p, idx);
963 ib[idx] = 0;
964 break;
Alex Deucher5f77df32010-03-26 14:52:32 -0400965 case SQ_CONFIG:
966 track->sq_config = radeon_get_ib_value(p, idx);
967 break;
Jerome Glisse961fb592010-02-10 22:30:05 +0000968 case R_028800_DB_DEPTH_CONTROL:
969 track->db_depth_control = radeon_get_ib_value(p, idx);
970 break;
971 case R_028010_DB_DEPTH_INFO:
Jerome Glisse721604a2012-01-05 22:11:05 -0500972 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) &&
Marek Olšáke70f2242011-10-25 01:38:45 +0200973 r600_cs_packet_next_is_pkt3_nop(p)) {
Alex Deucher7f813372010-05-20 12:43:52 -0400974 r = r600_cs_packet_next_reloc(p, &reloc);
975 if (r) {
976 dev_warn(p->dev, "bad SET_CONTEXT_REG "
977 "0x%04X\n", reg);
978 return -EINVAL;
979 }
980 track->db_depth_info = radeon_get_ib_value(p, idx);
981 ib[idx] &= C_028010_ARRAY_MODE;
982 track->db_depth_info &= C_028010_ARRAY_MODE;
983 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
984 ib[idx] |= S_028010_ARRAY_MODE(V_028010_ARRAY_2D_TILED_THIN1);
985 track->db_depth_info |= S_028010_ARRAY_MODE(V_028010_ARRAY_2D_TILED_THIN1);
986 } else {
987 ib[idx] |= S_028010_ARRAY_MODE(V_028010_ARRAY_1D_TILED_THIN1);
988 track->db_depth_info |= S_028010_ARRAY_MODE(V_028010_ARRAY_1D_TILED_THIN1);
989 }
990 } else
991 track->db_depth_info = radeon_get_ib_value(p, idx);
Jerome Glisse961fb592010-02-10 22:30:05 +0000992 break;
993 case R_028004_DB_DEPTH_VIEW:
994 track->db_depth_view = radeon_get_ib_value(p, idx);
995 break;
996 case R_028000_DB_DEPTH_SIZE:
997 track->db_depth_size = radeon_get_ib_value(p, idx);
998 track->db_depth_size_idx = idx;
999 break;
1000 case R_028AB0_VGT_STRMOUT_EN:
1001 track->vgt_strmout_en = radeon_get_ib_value(p, idx);
1002 break;
1003 case R_028B20_VGT_STRMOUT_BUFFER_EN:
1004 track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx);
1005 break;
Marek Olšákdd220a02012-01-27 12:17:59 -05001006 case VGT_STRMOUT_BUFFER_BASE_0:
1007 case VGT_STRMOUT_BUFFER_BASE_1:
1008 case VGT_STRMOUT_BUFFER_BASE_2:
1009 case VGT_STRMOUT_BUFFER_BASE_3:
1010 r = r600_cs_packet_next_reloc(p, &reloc);
1011 if (r) {
1012 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1013 "0x%04X\n", reg);
1014 return -EINVAL;
1015 }
1016 tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
1017 track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
1018 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1019 track->vgt_strmout_bo[tmp] = reloc->robj;
1020 track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset;
1021 break;
1022 case VGT_STRMOUT_BUFFER_SIZE_0:
1023 case VGT_STRMOUT_BUFFER_SIZE_1:
1024 case VGT_STRMOUT_BUFFER_SIZE_2:
1025 case VGT_STRMOUT_BUFFER_SIZE_3:
1026 tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
1027 /* size in register is DWs, convert to bytes */
1028 track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4;
1029 break;
1030 case CP_COHER_BASE:
1031 r = r600_cs_packet_next_reloc(p, &reloc);
1032 if (r) {
1033 dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
1034 "0x%04X\n", reg);
1035 return -EINVAL;
1036 }
1037 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1038 break;
Jerome Glisse961fb592010-02-10 22:30:05 +00001039 case R_028238_CB_TARGET_MASK:
1040 track->cb_target_mask = radeon_get_ib_value(p, idx);
1041 break;
1042 case R_02823C_CB_SHADER_MASK:
1043 track->cb_shader_mask = radeon_get_ib_value(p, idx);
1044 break;
1045 case R_028C04_PA_SC_AA_CONFIG:
1046 tmp = G_028C04_MSAA_NUM_SAMPLES(radeon_get_ib_value(p, idx));
1047 track->nsamples = 1 << tmp;
1048 break;
1049 case R_0280A0_CB_COLOR0_INFO:
1050 case R_0280A4_CB_COLOR1_INFO:
1051 case R_0280A8_CB_COLOR2_INFO:
1052 case R_0280AC_CB_COLOR3_INFO:
1053 case R_0280B0_CB_COLOR4_INFO:
1054 case R_0280B4_CB_COLOR5_INFO:
1055 case R_0280B8_CB_COLOR6_INFO:
1056 case R_0280BC_CB_COLOR7_INFO:
Jerome Glisse721604a2012-01-05 22:11:05 -05001057 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) &&
Marek Olšáke70f2242011-10-25 01:38:45 +02001058 r600_cs_packet_next_is_pkt3_nop(p)) {
Alex Deucher7f813372010-05-20 12:43:52 -04001059 r = r600_cs_packet_next_reloc(p, &reloc);
1060 if (r) {
1061 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
1062 return -EINVAL;
1063 }
1064 tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4;
1065 track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
1066 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
1067 ib[idx] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_2D_TILED_THIN1);
1068 track->cb_color_info[tmp] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_2D_TILED_THIN1);
1069 } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
1070 ib[idx] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_1D_TILED_THIN1);
1071 track->cb_color_info[tmp] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_1D_TILED_THIN1);
1072 }
1073 } else {
1074 tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4;
1075 track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
1076 }
Jerome Glisse961fb592010-02-10 22:30:05 +00001077 break;
1078 case R_028060_CB_COLOR0_SIZE:
1079 case R_028064_CB_COLOR1_SIZE:
1080 case R_028068_CB_COLOR2_SIZE:
1081 case R_02806C_CB_COLOR3_SIZE:
1082 case R_028070_CB_COLOR4_SIZE:
1083 case R_028074_CB_COLOR5_SIZE:
1084 case R_028078_CB_COLOR6_SIZE:
1085 case R_02807C_CB_COLOR7_SIZE:
1086 tmp = (reg - R_028060_CB_COLOR0_SIZE) / 4;
1087 track->cb_color_size[tmp] = radeon_get_ib_value(p, idx);
1088 track->cb_color_size_idx[tmp] = idx;
1089 break;
1090 /* This register were added late, there is userspace
1091 * which does provide relocation for those but set
1092 * 0 offset. In order to avoid breaking old userspace
1093 * we detect this and set address to point to last
1094 * CB_COLOR0_BASE, note that if userspace doesn't set
1095 * CB_COLOR0_BASE before this register we will report
1096 * error. Old userspace always set CB_COLOR0_BASE
1097 * before any of this.
1098 */
1099 case R_0280E0_CB_COLOR0_FRAG:
1100 case R_0280E4_CB_COLOR1_FRAG:
1101 case R_0280E8_CB_COLOR2_FRAG:
1102 case R_0280EC_CB_COLOR3_FRAG:
1103 case R_0280F0_CB_COLOR4_FRAG:
1104 case R_0280F4_CB_COLOR5_FRAG:
1105 case R_0280F8_CB_COLOR6_FRAG:
1106 case R_0280FC_CB_COLOR7_FRAG:
1107 tmp = (reg - R_0280E0_CB_COLOR0_FRAG) / 4;
1108 if (!r600_cs_packet_next_is_pkt3_nop(p)) {
1109 if (!track->cb_color_base_last[tmp]) {
1110 dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
1111 return -EINVAL;
1112 }
1113 ib[idx] = track->cb_color_base_last[tmp];
Jerome Glisse961fb592010-02-10 22:30:05 +00001114 track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp];
1115 } else {
1116 r = r600_cs_packet_next_reloc(p, &reloc);
1117 if (r) {
1118 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
1119 return -EINVAL;
1120 }
1121 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1122 track->cb_color_frag_bo[tmp] = reloc->robj;
1123 }
1124 break;
1125 case R_0280C0_CB_COLOR0_TILE:
1126 case R_0280C4_CB_COLOR1_TILE:
1127 case R_0280C8_CB_COLOR2_TILE:
1128 case R_0280CC_CB_COLOR3_TILE:
1129 case R_0280D0_CB_COLOR4_TILE:
1130 case R_0280D4_CB_COLOR5_TILE:
1131 case R_0280D8_CB_COLOR6_TILE:
1132 case R_0280DC_CB_COLOR7_TILE:
1133 tmp = (reg - R_0280C0_CB_COLOR0_TILE) / 4;
1134 if (!r600_cs_packet_next_is_pkt3_nop(p)) {
1135 if (!track->cb_color_base_last[tmp]) {
1136 dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
1137 return -EINVAL;
1138 }
1139 ib[idx] = track->cb_color_base_last[tmp];
Jerome Glisse961fb592010-02-10 22:30:05 +00001140 track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp];
1141 } else {
1142 r = r600_cs_packet_next_reloc(p, &reloc);
1143 if (r) {
1144 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
1145 return -EINVAL;
1146 }
1147 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1148 track->cb_color_tile_bo[tmp] = reloc->robj;
1149 }
1150 break;
1151 case CB_COLOR0_BASE:
1152 case CB_COLOR1_BASE:
1153 case CB_COLOR2_BASE:
1154 case CB_COLOR3_BASE:
1155 case CB_COLOR4_BASE:
1156 case CB_COLOR5_BASE:
1157 case CB_COLOR6_BASE:
1158 case CB_COLOR7_BASE:
1159 r = r600_cs_packet_next_reloc(p, &reloc);
1160 if (r) {
1161 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1162 "0x%04X\n", reg);
1163 return -EINVAL;
1164 }
Jerome Glisse7cb72ef2010-02-11 12:44:32 +01001165 tmp = (reg - CB_COLOR0_BASE) / 4;
Alex Deucher1729dd32010-08-06 02:54:05 -04001166 track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
Jerome Glisse961fb592010-02-10 22:30:05 +00001167 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
Jerome Glisse961fb592010-02-10 22:30:05 +00001168 track->cb_color_base_last[tmp] = ib[idx];
1169 track->cb_color_bo[tmp] = reloc->robj;
Alex Deucher16790562010-11-14 20:24:35 -05001170 track->cb_color_bo_mc[tmp] = reloc->lobj.gpu_offset;
Jerome Glisse961fb592010-02-10 22:30:05 +00001171 break;
1172 case DB_DEPTH_BASE:
1173 r = r600_cs_packet_next_reloc(p, &reloc);
1174 if (r) {
1175 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1176 "0x%04X\n", reg);
1177 return -EINVAL;
1178 }
Alex Deucher1729dd32010-08-06 02:54:05 -04001179 track->db_offset = radeon_get_ib_value(p, idx) << 8;
Jerome Glisse961fb592010-02-10 22:30:05 +00001180 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1181 track->db_bo = reloc->robj;
Alex Deucher16790562010-11-14 20:24:35 -05001182 track->db_bo_mc = reloc->lobj.gpu_offset;
Jerome Glisse961fb592010-02-10 22:30:05 +00001183 break;
1184 case DB_HTILE_DATA_BASE:
1185 case SQ_PGM_START_FS:
1186 case SQ_PGM_START_ES:
1187 case SQ_PGM_START_VS:
1188 case SQ_PGM_START_GS:
1189 case SQ_PGM_START_PS:
Alex Deucher5f77df32010-03-26 14:52:32 -04001190 case SQ_ALU_CONST_CACHE_GS_0:
1191 case SQ_ALU_CONST_CACHE_GS_1:
1192 case SQ_ALU_CONST_CACHE_GS_2:
1193 case SQ_ALU_CONST_CACHE_GS_3:
1194 case SQ_ALU_CONST_CACHE_GS_4:
1195 case SQ_ALU_CONST_CACHE_GS_5:
1196 case SQ_ALU_CONST_CACHE_GS_6:
1197 case SQ_ALU_CONST_CACHE_GS_7:
1198 case SQ_ALU_CONST_CACHE_GS_8:
1199 case SQ_ALU_CONST_CACHE_GS_9:
1200 case SQ_ALU_CONST_CACHE_GS_10:
1201 case SQ_ALU_CONST_CACHE_GS_11:
1202 case SQ_ALU_CONST_CACHE_GS_12:
1203 case SQ_ALU_CONST_CACHE_GS_13:
1204 case SQ_ALU_CONST_CACHE_GS_14:
1205 case SQ_ALU_CONST_CACHE_GS_15:
1206 case SQ_ALU_CONST_CACHE_PS_0:
1207 case SQ_ALU_CONST_CACHE_PS_1:
1208 case SQ_ALU_CONST_CACHE_PS_2:
1209 case SQ_ALU_CONST_CACHE_PS_3:
1210 case SQ_ALU_CONST_CACHE_PS_4:
1211 case SQ_ALU_CONST_CACHE_PS_5:
1212 case SQ_ALU_CONST_CACHE_PS_6:
1213 case SQ_ALU_CONST_CACHE_PS_7:
1214 case SQ_ALU_CONST_CACHE_PS_8:
1215 case SQ_ALU_CONST_CACHE_PS_9:
1216 case SQ_ALU_CONST_CACHE_PS_10:
1217 case SQ_ALU_CONST_CACHE_PS_11:
1218 case SQ_ALU_CONST_CACHE_PS_12:
1219 case SQ_ALU_CONST_CACHE_PS_13:
1220 case SQ_ALU_CONST_CACHE_PS_14:
1221 case SQ_ALU_CONST_CACHE_PS_15:
1222 case SQ_ALU_CONST_CACHE_VS_0:
1223 case SQ_ALU_CONST_CACHE_VS_1:
1224 case SQ_ALU_CONST_CACHE_VS_2:
1225 case SQ_ALU_CONST_CACHE_VS_3:
1226 case SQ_ALU_CONST_CACHE_VS_4:
1227 case SQ_ALU_CONST_CACHE_VS_5:
1228 case SQ_ALU_CONST_CACHE_VS_6:
1229 case SQ_ALU_CONST_CACHE_VS_7:
1230 case SQ_ALU_CONST_CACHE_VS_8:
1231 case SQ_ALU_CONST_CACHE_VS_9:
1232 case SQ_ALU_CONST_CACHE_VS_10:
1233 case SQ_ALU_CONST_CACHE_VS_11:
1234 case SQ_ALU_CONST_CACHE_VS_12:
1235 case SQ_ALU_CONST_CACHE_VS_13:
1236 case SQ_ALU_CONST_CACHE_VS_14:
1237 case SQ_ALU_CONST_CACHE_VS_15:
Jerome Glisse961fb592010-02-10 22:30:05 +00001238 r = r600_cs_packet_next_reloc(p, &reloc);
1239 if (r) {
1240 dev_warn(p->dev, "bad SET_CONTEXT_REG "
1241 "0x%04X\n", reg);
1242 return -EINVAL;
1243 }
1244 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1245 break;
Alex Deucher033b5652011-06-08 15:26:45 -04001246 case SX_MEMORY_EXPORT_BASE:
1247 r = r600_cs_packet_next_reloc(p, &reloc);
1248 if (r) {
1249 dev_warn(p->dev, "bad SET_CONFIG_REG "
1250 "0x%04X\n", reg);
1251 return -EINVAL;
1252 }
1253 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1254 break;
Jerome Glisse961fb592010-02-10 22:30:05 +00001255 default:
1256 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
1257 return -EINVAL;
1258 }
1259 return 0;
1260}
1261
Andi Kleen488479e2011-10-13 16:08:41 -07001262static unsigned mip_minify(unsigned size, unsigned level)
Jerome Glisse961fb592010-02-10 22:30:05 +00001263{
Dave Airlie60b212f2011-02-18 05:51:58 +00001264 unsigned val;
1265
1266 val = max(1U, size >> level);
1267 if (level > 0)
1268 val = roundup_pow_of_two(val);
1269 return val;
Jerome Glisse961fb592010-02-10 22:30:05 +00001270}
1271
Dave Airlie60b212f2011-02-18 05:51:58 +00001272static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel,
1273 unsigned w0, unsigned h0, unsigned d0, unsigned format,
1274 unsigned block_align, unsigned height_align, unsigned base_align,
Alex Deucher40e2a5c2010-06-04 18:41:42 -04001275 unsigned *l0_size, unsigned *mipmap_size)
Jerome Glisse961fb592010-02-10 22:30:05 +00001276{
Dave Airlie60b212f2011-02-18 05:51:58 +00001277 unsigned offset, i, level;
1278 unsigned width, height, depth, size;
1279 unsigned blocksize;
1280 unsigned nbx, nby;
1281 unsigned nlevels = llevel - blevel + 1;
Jerome Glisse961fb592010-02-10 22:30:05 +00001282
Dave Airlie60b212f2011-02-18 05:51:58 +00001283 *l0_size = -1;
1284 blocksize = fmt_get_blocksize(format);
1285
1286 w0 = mip_minify(w0, 0);
1287 h0 = mip_minify(h0, 0);
1288 d0 = mip_minify(d0, 0);
Jerome Glisse961fb592010-02-10 22:30:05 +00001289 for(i = 0, offset = 0, level = blevel; i < nlevels; i++, level++) {
Dave Airlie60b212f2011-02-18 05:51:58 +00001290 width = mip_minify(w0, i);
1291 nbx = fmt_get_nblocksx(format, width);
1292
1293 nbx = round_up(nbx, block_align);
1294
1295 height = mip_minify(h0, i);
1296 nby = fmt_get_nblocksy(format, height);
1297 nby = round_up(nby, height_align);
1298
1299 depth = mip_minify(d0, i);
1300
1301 size = nbx * nby * blocksize;
1302 if (nfaces)
1303 size *= nfaces;
1304 else
1305 size *= depth;
1306
1307 if (i == 0)
1308 *l0_size = size;
1309
1310 if (i == 0 || i == 1)
1311 offset = round_up(offset, base_align);
1312
1313 offset += size;
Jerome Glisse961fb592010-02-10 22:30:05 +00001314 }
Jerome Glisse961fb592010-02-10 22:30:05 +00001315 *mipmap_size = offset;
Dave Airlie60b212f2011-02-18 05:51:58 +00001316 if (llevel == 0)
Jerome Glisse961fb592010-02-10 22:30:05 +00001317 *mipmap_size = *l0_size;
Alex Deucher1729dd32010-08-06 02:54:05 -04001318 if (!blevel)
1319 *mipmap_size -= *l0_size;
Jerome Glisse961fb592010-02-10 22:30:05 +00001320}
1321
1322/**
1323 * r600_check_texture_resource() - check if register is authorized or not
1324 * @p: parser structure holding parsing context
1325 * @idx: index into the cs buffer
1326 * @texture: texture's bo structure
1327 * @mipmap: mipmap's bo structure
1328 *
1329 * This function will check that the resource has valid field and that
1330 * the texture and mipmap bo object are big enough to cover this resource.
1331 */
Andi Kleen488479e2011-10-13 16:08:41 -07001332static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx,
Alex Deucher7f813372010-05-20 12:43:52 -04001333 struct radeon_bo *texture,
1334 struct radeon_bo *mipmap,
Alex Deucher16790562010-11-14 20:24:35 -05001335 u64 base_offset,
1336 u64 mip_offset,
Alex Deucher7f813372010-05-20 12:43:52 -04001337 u32 tiling_flags)
Jerome Glisse961fb592010-02-10 22:30:05 +00001338{
Alex Deucher40e2a5c2010-06-04 18:41:42 -04001339 struct r600_cs_track *track = p->track;
Dave Airlie60b212f2011-02-18 05:51:58 +00001340 u32 nfaces, llevel, blevel, w0, h0, d0;
Dave Airlieaf506212011-02-28 14:27:03 +10001341 u32 word0, word1, l0_size, mipmap_size, word2, word3;
Alex Deucher16790562010-11-14 20:24:35 -05001342 u32 height_align, pitch, pitch_align, depth_align;
Dave Airlie60b212f2011-02-18 05:51:58 +00001343 u32 array, barray, larray;
Alex Deucher16790562010-11-14 20:24:35 -05001344 u64 base_align;
1345 struct array_mode_checker array_check;
Dave Airlie60b212f2011-02-18 05:51:58 +00001346 u32 format;
Jerome Glisse961fb592010-02-10 22:30:05 +00001347
1348 /* on legacy kernel we don't perform advanced check */
1349 if (p->rdev == NULL)
1350 return 0;
Alex Deucher7f813372010-05-20 12:43:52 -04001351
Alex Deucher16790562010-11-14 20:24:35 -05001352 /* convert to bytes */
1353 base_offset <<= 8;
1354 mip_offset <<= 8;
1355
Jerome Glisse961fb592010-02-10 22:30:05 +00001356 word0 = radeon_get_ib_value(p, idx + 0);
Jerome Glisse721604a2012-01-05 22:11:05 -05001357 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
Marek Olšáke70f2242011-10-25 01:38:45 +02001358 if (tiling_flags & RADEON_TILING_MACRO)
1359 word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
1360 else if (tiling_flags & RADEON_TILING_MICRO)
1361 word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
1362 }
Jerome Glisse961fb592010-02-10 22:30:05 +00001363 word1 = radeon_get_ib_value(p, idx + 1);
1364 w0 = G_038000_TEX_WIDTH(word0) + 1;
1365 h0 = G_038004_TEX_HEIGHT(word1) + 1;
1366 d0 = G_038004_TEX_DEPTH(word1);
1367 nfaces = 1;
1368 switch (G_038000_DIM(word0)) {
1369 case V_038000_SQ_TEX_DIM_1D:
1370 case V_038000_SQ_TEX_DIM_2D:
1371 case V_038000_SQ_TEX_DIM_3D:
1372 break;
1373 case V_038000_SQ_TEX_DIM_CUBEMAP:
Dave Airlie60b212f2011-02-18 05:51:58 +00001374 if (p->family >= CHIP_RV770)
1375 nfaces = 8;
1376 else
1377 nfaces = 6;
Jerome Glisse961fb592010-02-10 22:30:05 +00001378 break;
1379 case V_038000_SQ_TEX_DIM_1D_ARRAY:
1380 case V_038000_SQ_TEX_DIM_2D_ARRAY:
Dave Airlie60b212f2011-02-18 05:51:58 +00001381 array = 1;
1382 break;
Jerome Glisse961fb592010-02-10 22:30:05 +00001383 case V_038000_SQ_TEX_DIM_2D_MSAA:
1384 case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA:
1385 default:
1386 dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0));
1387 return -EINVAL;
1388 }
Dave Airlie60b212f2011-02-18 05:51:58 +00001389 format = G_038004_DATA_FORMAT(word1);
Marek Olšákfe6f0bd2011-05-07 01:09:57 +02001390 if (!fmt_is_valid_texture(format, p->family)) {
Jerome Glisse961fb592010-02-10 22:30:05 +00001391 dev_warn(p->dev, "%s:%d texture invalid format %d\n",
Dave Airlie60b212f2011-02-18 05:51:58 +00001392 __func__, __LINE__, format);
Jerome Glisse961fb592010-02-10 22:30:05 +00001393 return -EINVAL;
1394 }
Alex Deucher40e2a5c2010-06-04 18:41:42 -04001395
Alex Deucher16790562010-11-14 20:24:35 -05001396 /* pitch in texels */
1397 pitch = (G_038000_PITCH(word0) + 1) * 8;
1398 array_check.array_mode = G_038000_TILE_MODE(word0);
1399 array_check.group_size = track->group_size;
1400 array_check.nbanks = track->nbanks;
1401 array_check.npipes = track->npipes;
1402 array_check.nsamples = 1;
Dave Airlie60b212f2011-02-18 05:51:58 +00001403 array_check.blocksize = fmt_get_blocksize(format);
Alex Deucher16790562010-11-14 20:24:35 -05001404 if (r600_get_array_mode_alignment(&array_check,
1405 &pitch_align, &height_align, &depth_align, &base_align)) {
1406 dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n",
1407 __func__, __LINE__, G_038000_TILE_MODE(word0));
Alex Deucher40e2a5c2010-06-04 18:41:42 -04001408 return -EINVAL;
1409 }
Alex Deucher16790562010-11-14 20:24:35 -05001410
1411 /* XXX check height as well... */
1412
1413 if (!IS_ALIGNED(pitch, pitch_align)) {
Alex Deucherc2049b32011-02-13 18:42:41 -05001414 dev_warn(p->dev, "%s:%d tex pitch (%d, 0x%x, %d) invalid\n",
1415 __func__, __LINE__, pitch, pitch_align, G_038000_TILE_MODE(word0));
Alex Deucher16790562010-11-14 20:24:35 -05001416 return -EINVAL;
1417 }
1418 if (!IS_ALIGNED(base_offset, base_align)) {
Alex Deucherc2049b32011-02-13 18:42:41 -05001419 dev_warn(p->dev, "%s:%d tex base offset (0x%llx, 0x%llx, %d) invalid\n",
1420 __func__, __LINE__, base_offset, base_align, G_038000_TILE_MODE(word0));
Alex Deucher16790562010-11-14 20:24:35 -05001421 return -EINVAL;
1422 }
1423 if (!IS_ALIGNED(mip_offset, base_align)) {
Alex Deucherc2049b32011-02-13 18:42:41 -05001424 dev_warn(p->dev, "%s:%d tex mip offset (0x%llx, 0x%llx, %d) invalid\n",
1425 __func__, __LINE__, mip_offset, base_align, G_038000_TILE_MODE(word0));
Alex Deucher16790562010-11-14 20:24:35 -05001426 return -EINVAL;
1427 }
Alex Deucher40e2a5c2010-06-04 18:41:42 -04001428
Dave Airlieaf506212011-02-28 14:27:03 +10001429 word2 = radeon_get_ib_value(p, idx + 2) << 8;
1430 word3 = radeon_get_ib_value(p, idx + 3) << 8;
1431
Jerome Glisse961fb592010-02-10 22:30:05 +00001432 word0 = radeon_get_ib_value(p, idx + 4);
1433 word1 = radeon_get_ib_value(p, idx + 5);
1434 blevel = G_038010_BASE_LEVEL(word0);
Dave Airlie60b212f2011-02-18 05:51:58 +00001435 llevel = G_038014_LAST_LEVEL(word1);
1436 if (array == 1) {
1437 barray = G_038014_BASE_ARRAY(word1);
1438 larray = G_038014_LAST_ARRAY(word1);
1439
1440 nfaces = larray - barray + 1;
1441 }
1442 r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, format,
1443 pitch_align, height_align, base_align,
Alex Deucher40e2a5c2010-06-04 18:41:42 -04001444 &l0_size, &mipmap_size);
Jerome Glisse961fb592010-02-10 22:30:05 +00001445 /* using get ib will give us the offset into the texture bo */
Dave Airlieaf506212011-02-28 14:27:03 +10001446 if ((l0_size + word2) > radeon_bo_size(texture)) {
Jerome Glisse961fb592010-02-10 22:30:05 +00001447 dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n",
Dave Airlieaf506212011-02-28 14:27:03 +10001448 w0, h0, format, word2, l0_size, radeon_bo_size(texture));
Dave Airlie60b212f2011-02-18 05:51:58 +00001449 dev_warn(p->dev, "alignments %d %d %d %lld\n", pitch, pitch_align, height_align, base_align);
Jerome Glisse961fb592010-02-10 22:30:05 +00001450 return -EINVAL;
1451 }
1452 /* using get ib will give us the offset into the mipmap bo */
Dave Airlieaf506212011-02-28 14:27:03 +10001453 word3 = radeon_get_ib_value(p, idx + 3) << 8;
1454 if ((mipmap_size + word3) > radeon_bo_size(mipmap)) {
Alex Deucherfe725d42010-09-14 10:10:47 -04001455 /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n",
Dave Airlieaf506212011-02-28 14:27:03 +10001456 w0, h0, format, blevel, nlevels, word3, mipmap_size, radeon_bo_size(texture));*/
Jerome Glisse961fb592010-02-10 22:30:05 +00001457 }
1458 return 0;
1459}
1460
Marek Olšákdd220a02012-01-27 12:17:59 -05001461static bool r600_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
1462{
1463 u32 m, i;
1464
1465 i = (reg >> 7);
1466 if (i >= ARRAY_SIZE(r600_reg_safe_bm)) {
1467 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
1468 return false;
1469 }
1470 m = 1 << ((reg >> 2) & 31);
1471 if (!(r600_reg_safe_bm[i] & m))
1472 return true;
1473 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
1474 return false;
1475}
1476
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001477static int r600_packet3_check(struct radeon_cs_parser *p,
1478 struct radeon_cs_packet *pkt)
1479{
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001480 struct radeon_cs_reloc *reloc;
Jerome Glissec8c15ff2010-01-18 13:01:36 +01001481 struct r600_cs_track *track;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001482 volatile u32 *ib;
1483 unsigned idx;
1484 unsigned i;
1485 unsigned start_reg, end_reg, reg;
1486 int r;
Dave Airlieadea4792009-09-25 14:23:47 +10001487 u32 idx_value;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001488
Jerome Glissec8c15ff2010-01-18 13:01:36 +01001489 track = (struct r600_cs_track *)p->track;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001490 ib = p->ib->ptr;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001491 idx = pkt->idx + 1;
Dave Airlieadea4792009-09-25 14:23:47 +10001492 idx_value = radeon_get_ib_value(p, idx);
Dave Airlie513bcb42009-09-23 16:56:27 +10001493
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001494 switch (pkt->opcode) {
Dave Airlie2a19cac2011-02-28 16:11:48 +10001495 case PACKET3_SET_PREDICATION:
1496 {
1497 int pred_op;
1498 int tmp;
1499 if (pkt->count != 1) {
1500 DRM_ERROR("bad SET PREDICATION\n");
1501 return -EINVAL;
1502 }
1503
1504 tmp = radeon_get_ib_value(p, idx + 1);
1505 pred_op = (tmp >> 16) & 0x7;
1506
1507 /* for the clear predicate operation */
1508 if (pred_op == 0)
1509 return 0;
1510
1511 if (pred_op > 2) {
1512 DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op);
1513 return -EINVAL;
1514 }
1515
1516 r = r600_cs_packet_next_reloc(p, &reloc);
1517 if (r) {
1518 DRM_ERROR("bad SET PREDICATION\n");
1519 return -EINVAL;
1520 }
1521
1522 ib[idx + 0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1523 ib[idx + 1] = tmp + (upper_32_bits(reloc->lobj.gpu_offset) & 0xff);
1524 }
1525 break;
1526
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001527 case PACKET3_START_3D_CMDBUF:
1528 if (p->family >= CHIP_RV770 || pkt->count) {
1529 DRM_ERROR("bad START_3D\n");
1530 return -EINVAL;
1531 }
1532 break;
1533 case PACKET3_CONTEXT_CONTROL:
1534 if (pkt->count != 1) {
1535 DRM_ERROR("bad CONTEXT_CONTROL\n");
1536 return -EINVAL;
1537 }
1538 break;
1539 case PACKET3_INDEX_TYPE:
1540 case PACKET3_NUM_INSTANCES:
1541 if (pkt->count) {
1542 DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES\n");
1543 return -EINVAL;
1544 }
1545 break;
1546 case PACKET3_DRAW_INDEX:
1547 if (pkt->count != 3) {
1548 DRM_ERROR("bad DRAW_INDEX\n");
1549 return -EINVAL;
1550 }
1551 r = r600_cs_packet_next_reloc(p, &reloc);
1552 if (r) {
1553 DRM_ERROR("bad DRAW_INDEX\n");
1554 return -EINVAL;
1555 }
Dave Airlieadea4792009-09-25 14:23:47 +10001556 ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
Alex Deucher210bed82009-09-25 18:33:08 -04001557 ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
Jerome Glisse961fb592010-02-10 22:30:05 +00001558 r = r600_cs_track_check(p);
1559 if (r) {
1560 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
1561 return r;
1562 }
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001563 break;
1564 case PACKET3_DRAW_INDEX_AUTO:
1565 if (pkt->count != 1) {
1566 DRM_ERROR("bad DRAW_INDEX_AUTO\n");
1567 return -EINVAL;
1568 }
Jerome Glisse961fb592010-02-10 22:30:05 +00001569 r = r600_cs_track_check(p);
1570 if (r) {
1571 dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
1572 return r;
1573 }
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001574 break;
1575 case PACKET3_DRAW_INDEX_IMMD_BE:
1576 case PACKET3_DRAW_INDEX_IMMD:
1577 if (pkt->count < 2) {
1578 DRM_ERROR("bad DRAW_INDEX_IMMD\n");
1579 return -EINVAL;
1580 }
Jerome Glisse961fb592010-02-10 22:30:05 +00001581 r = r600_cs_track_check(p);
1582 if (r) {
1583 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
1584 return r;
1585 }
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001586 break;
1587 case PACKET3_WAIT_REG_MEM:
1588 if (pkt->count != 5) {
1589 DRM_ERROR("bad WAIT_REG_MEM\n");
1590 return -EINVAL;
1591 }
1592 /* bit 4 is reg (0) or mem (1) */
Dave Airlieadea4792009-09-25 14:23:47 +10001593 if (idx_value & 0x10) {
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001594 r = r600_cs_packet_next_reloc(p, &reloc);
1595 if (r) {
1596 DRM_ERROR("bad WAIT_REG_MEM\n");
1597 return -EINVAL;
1598 }
1599 ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
Alex Deucher210bed82009-09-25 18:33:08 -04001600 ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001601 }
1602 break;
1603 case PACKET3_SURFACE_SYNC:
1604 if (pkt->count != 3) {
1605 DRM_ERROR("bad SURFACE_SYNC\n");
1606 return -EINVAL;
1607 }
1608 /* 0xffffffff/0x0 is flush all cache flag */
Dave Airlie513bcb42009-09-23 16:56:27 +10001609 if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
1610 radeon_get_ib_value(p, idx + 2) != 0) {
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001611 r = r600_cs_packet_next_reloc(p, &reloc);
1612 if (r) {
1613 DRM_ERROR("bad SURFACE_SYNC\n");
1614 return -EINVAL;
1615 }
1616 ib[idx+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1617 }
1618 break;
1619 case PACKET3_EVENT_WRITE:
1620 if (pkt->count != 2 && pkt->count != 0) {
1621 DRM_ERROR("bad EVENT_WRITE\n");
1622 return -EINVAL;
1623 }
1624 if (pkt->count) {
1625 r = r600_cs_packet_next_reloc(p, &reloc);
1626 if (r) {
1627 DRM_ERROR("bad EVENT_WRITE\n");
1628 return -EINVAL;
1629 }
1630 ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
Alex Deucher210bed82009-09-25 18:33:08 -04001631 ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001632 }
1633 break;
1634 case PACKET3_EVENT_WRITE_EOP:
1635 if (pkt->count != 4) {
1636 DRM_ERROR("bad EVENT_WRITE_EOP\n");
1637 return -EINVAL;
1638 }
1639 r = r600_cs_packet_next_reloc(p, &reloc);
1640 if (r) {
1641 DRM_ERROR("bad EVENT_WRITE\n");
1642 return -EINVAL;
1643 }
1644 ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
Alex Deucher210bed82009-09-25 18:33:08 -04001645 ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001646 break;
1647 case PACKET3_SET_CONFIG_REG:
Dave Airlieadea4792009-09-25 14:23:47 +10001648 start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_OFFSET;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001649 end_reg = 4 * pkt->count + start_reg - 4;
1650 if ((start_reg < PACKET3_SET_CONFIG_REG_OFFSET) ||
1651 (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
1652 (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
1653 DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
1654 return -EINVAL;
1655 }
1656 for (i = 0; i < pkt->count; i++) {
1657 reg = start_reg + (4 * i);
Jerome Glisse961fb592010-02-10 22:30:05 +00001658 r = r600_cs_check_reg(p, reg, idx+1+i);
1659 if (r)
1660 return r;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001661 }
1662 break;
1663 case PACKET3_SET_CONTEXT_REG:
Dave Airlieadea4792009-09-25 14:23:47 +10001664 start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_OFFSET;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001665 end_reg = 4 * pkt->count + start_reg - 4;
1666 if ((start_reg < PACKET3_SET_CONTEXT_REG_OFFSET) ||
1667 (start_reg >= PACKET3_SET_CONTEXT_REG_END) ||
1668 (end_reg >= PACKET3_SET_CONTEXT_REG_END)) {
1669 DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n");
1670 return -EINVAL;
1671 }
1672 for (i = 0; i < pkt->count; i++) {
1673 reg = start_reg + (4 * i);
Jerome Glisse961fb592010-02-10 22:30:05 +00001674 r = r600_cs_check_reg(p, reg, idx+1+i);
1675 if (r)
1676 return r;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001677 }
1678 break;
1679 case PACKET3_SET_RESOURCE:
1680 if (pkt->count % 7) {
1681 DRM_ERROR("bad SET_RESOURCE\n");
1682 return -EINVAL;
1683 }
Dave Airlieadea4792009-09-25 14:23:47 +10001684 start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_OFFSET;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001685 end_reg = 4 * pkt->count + start_reg - 4;
1686 if ((start_reg < PACKET3_SET_RESOURCE_OFFSET) ||
1687 (start_reg >= PACKET3_SET_RESOURCE_END) ||
1688 (end_reg >= PACKET3_SET_RESOURCE_END)) {
1689 DRM_ERROR("bad SET_RESOURCE\n");
1690 return -EINVAL;
1691 }
1692 for (i = 0; i < (pkt->count / 7); i++) {
Jerome Glisse961fb592010-02-10 22:30:05 +00001693 struct radeon_bo *texture, *mipmap;
Alex Deucher1729dd32010-08-06 02:54:05 -04001694 u32 size, offset, base_offset, mip_offset;
Jerome Glisse961fb592010-02-10 22:30:05 +00001695
Dave Airlieadea4792009-09-25 14:23:47 +10001696 switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) {
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001697 case SQ_TEX_VTX_VALID_TEXTURE:
1698 /* tex base */
1699 r = r600_cs_packet_next_reloc(p, &reloc);
1700 if (r) {
1701 DRM_ERROR("bad SET_RESOURCE\n");
1702 return -EINVAL;
1703 }
Alex Deucher1729dd32010-08-06 02:54:05 -04001704 base_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
Jerome Glisse721604a2012-01-05 22:11:05 -05001705 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
Marek Olšáke70f2242011-10-25 01:38:45 +02001706 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
1707 ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
1708 else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
1709 ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
1710 }
Jerome Glisse961fb592010-02-10 22:30:05 +00001711 texture = reloc->robj;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001712 /* tex mip base */
1713 r = r600_cs_packet_next_reloc(p, &reloc);
1714 if (r) {
1715 DRM_ERROR("bad SET_RESOURCE\n");
1716 return -EINVAL;
1717 }
Alex Deucher1729dd32010-08-06 02:54:05 -04001718 mip_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
Jerome Glisse961fb592010-02-10 22:30:05 +00001719 mipmap = reloc->robj;
1720 r = r600_check_texture_resource(p, idx+(i*7)+1,
Alex Deucher16790562010-11-14 20:24:35 -05001721 texture, mipmap,
1722 base_offset + radeon_get_ib_value(p, idx+1+(i*7)+2),
1723 mip_offset + radeon_get_ib_value(p, idx+1+(i*7)+3),
1724 reloc->lobj.tiling_flags);
Jerome Glisse961fb592010-02-10 22:30:05 +00001725 if (r)
1726 return r;
Alex Deucher1729dd32010-08-06 02:54:05 -04001727 ib[idx+1+(i*7)+2] += base_offset;
1728 ib[idx+1+(i*7)+3] += mip_offset;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001729 break;
1730 case SQ_TEX_VTX_VALID_BUFFER:
1731 /* vtx base */
1732 r = r600_cs_packet_next_reloc(p, &reloc);
1733 if (r) {
1734 DRM_ERROR("bad SET_RESOURCE\n");
1735 return -EINVAL;
1736 }
Jerome Glisse961fb592010-02-10 22:30:05 +00001737 offset = radeon_get_ib_value(p, idx+1+(i*7)+0);
Alex Deucher1729dd32010-08-06 02:54:05 -04001738 size = radeon_get_ib_value(p, idx+1+(i*7)+1) + 1;
Jerome Glisse961fb592010-02-10 22:30:05 +00001739 if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
1740 /* force size to size of the buffer */
Alex Deucher1729dd32010-08-06 02:54:05 -04001741 dev_warn(p->dev, "vbo resource seems too big (%d) for the bo (%ld)\n",
1742 size + offset, radeon_bo_size(reloc->robj));
Jerome Glisse961fb592010-02-10 22:30:05 +00001743 ib[idx+1+(i*7)+1] = radeon_bo_size(reloc->robj);
1744 }
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001745 ib[idx+1+(i*7)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff);
Alex Deucher210bed82009-09-25 18:33:08 -04001746 ib[idx+1+(i*7)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001747 break;
1748 case SQ_TEX_VTX_INVALID_TEXTURE:
1749 case SQ_TEX_VTX_INVALID_BUFFER:
1750 default:
1751 DRM_ERROR("bad SET_RESOURCE\n");
1752 return -EINVAL;
1753 }
1754 }
1755 break;
1756 case PACKET3_SET_ALU_CONST:
Alex Deucher5f77df32010-03-26 14:52:32 -04001757 if (track->sq_config & DX9_CONSTS) {
1758 start_reg = (idx_value << 2) + PACKET3_SET_ALU_CONST_OFFSET;
1759 end_reg = 4 * pkt->count + start_reg - 4;
1760 if ((start_reg < PACKET3_SET_ALU_CONST_OFFSET) ||
1761 (start_reg >= PACKET3_SET_ALU_CONST_END) ||
1762 (end_reg >= PACKET3_SET_ALU_CONST_END)) {
1763 DRM_ERROR("bad SET_ALU_CONST\n");
1764 return -EINVAL;
1765 }
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001766 }
1767 break;
1768 case PACKET3_SET_BOOL_CONST:
Dave Airlieadea4792009-09-25 14:23:47 +10001769 start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_OFFSET;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001770 end_reg = 4 * pkt->count + start_reg - 4;
1771 if ((start_reg < PACKET3_SET_BOOL_CONST_OFFSET) ||
1772 (start_reg >= PACKET3_SET_BOOL_CONST_END) ||
1773 (end_reg >= PACKET3_SET_BOOL_CONST_END)) {
1774 DRM_ERROR("bad SET_BOOL_CONST\n");
1775 return -EINVAL;
1776 }
1777 break;
1778 case PACKET3_SET_LOOP_CONST:
Dave Airlieadea4792009-09-25 14:23:47 +10001779 start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_OFFSET;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001780 end_reg = 4 * pkt->count + start_reg - 4;
1781 if ((start_reg < PACKET3_SET_LOOP_CONST_OFFSET) ||
1782 (start_reg >= PACKET3_SET_LOOP_CONST_END) ||
1783 (end_reg >= PACKET3_SET_LOOP_CONST_END)) {
1784 DRM_ERROR("bad SET_LOOP_CONST\n");
1785 return -EINVAL;
1786 }
1787 break;
1788 case PACKET3_SET_CTL_CONST:
Dave Airlieadea4792009-09-25 14:23:47 +10001789 start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_OFFSET;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001790 end_reg = 4 * pkt->count + start_reg - 4;
1791 if ((start_reg < PACKET3_SET_CTL_CONST_OFFSET) ||
1792 (start_reg >= PACKET3_SET_CTL_CONST_END) ||
1793 (end_reg >= PACKET3_SET_CTL_CONST_END)) {
1794 DRM_ERROR("bad SET_CTL_CONST\n");
1795 return -EINVAL;
1796 }
1797 break;
1798 case PACKET3_SET_SAMPLER:
1799 if (pkt->count % 3) {
1800 DRM_ERROR("bad SET_SAMPLER\n");
1801 return -EINVAL;
1802 }
Dave Airlieadea4792009-09-25 14:23:47 +10001803 start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_OFFSET;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001804 end_reg = 4 * pkt->count + start_reg - 4;
1805 if ((start_reg < PACKET3_SET_SAMPLER_OFFSET) ||
1806 (start_reg >= PACKET3_SET_SAMPLER_END) ||
1807 (end_reg >= PACKET3_SET_SAMPLER_END)) {
1808 DRM_ERROR("bad SET_SAMPLER\n");
1809 return -EINVAL;
1810 }
1811 break;
1812 case PACKET3_SURFACE_BASE_UPDATE:
1813 if (p->family >= CHIP_RV770 || p->family == CHIP_R600) {
1814 DRM_ERROR("bad SURFACE_BASE_UPDATE\n");
1815 return -EINVAL;
1816 }
1817 if (pkt->count) {
1818 DRM_ERROR("bad SURFACE_BASE_UPDATE\n");
1819 return -EINVAL;
1820 }
1821 break;
Marek Olšákdd220a02012-01-27 12:17:59 -05001822 case PACKET3_STRMOUT_BUFFER_UPDATE:
1823 if (pkt->count != 4) {
1824 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
1825 return -EINVAL;
1826 }
1827 /* Updating memory at DST_ADDRESS. */
1828 if (idx_value & 0x1) {
1829 u64 offset;
1830 r = r600_cs_packet_next_reloc(p, &reloc);
1831 if (r) {
1832 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n");
1833 return -EINVAL;
1834 }
1835 offset = radeon_get_ib_value(p, idx+1);
1836 offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
1837 if ((offset + 4) > radeon_bo_size(reloc->robj)) {
1838 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%llx, 0x%lx\n",
1839 offset + 4, radeon_bo_size(reloc->robj));
1840 return -EINVAL;
1841 }
1842 ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1843 ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1844 }
1845 /* Reading data from SRC_ADDRESS. */
1846 if (((idx_value >> 1) & 0x3) == 2) {
1847 u64 offset;
1848 r = r600_cs_packet_next_reloc(p, &reloc);
1849 if (r) {
1850 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n");
1851 return -EINVAL;
1852 }
1853 offset = radeon_get_ib_value(p, idx+3);
1854 offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
1855 if ((offset + 4) > radeon_bo_size(reloc->robj)) {
1856 DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%llx, 0x%lx\n",
1857 offset + 4, radeon_bo_size(reloc->robj));
1858 return -EINVAL;
1859 }
1860 ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1861 ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1862 }
1863 break;
1864 case PACKET3_COPY_DW:
1865 if (pkt->count != 4) {
1866 DRM_ERROR("bad COPY_DW (invalid count)\n");
1867 return -EINVAL;
1868 }
1869 if (idx_value & 0x1) {
1870 u64 offset;
1871 /* SRC is memory. */
1872 r = r600_cs_packet_next_reloc(p, &reloc);
1873 if (r) {
1874 DRM_ERROR("bad COPY_DW (missing src reloc)\n");
1875 return -EINVAL;
1876 }
1877 offset = radeon_get_ib_value(p, idx+1);
1878 offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
1879 if ((offset + 4) > radeon_bo_size(reloc->robj)) {
1880 DRM_ERROR("bad COPY_DW src bo too small: 0x%llx, 0x%lx\n",
1881 offset + 4, radeon_bo_size(reloc->robj));
1882 return -EINVAL;
1883 }
1884 ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1885 ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1886 } else {
1887 /* SRC is a reg. */
1888 reg = radeon_get_ib_value(p, idx+1) << 2;
1889 if (!r600_is_safe_reg(p, reg, idx+1))
1890 return -EINVAL;
1891 }
1892 if (idx_value & 0x2) {
1893 u64 offset;
1894 /* DST is memory. */
1895 r = r600_cs_packet_next_reloc(p, &reloc);
1896 if (r) {
1897 DRM_ERROR("bad COPY_DW (missing dst reloc)\n");
1898 return -EINVAL;
1899 }
1900 offset = radeon_get_ib_value(p, idx+3);
1901 offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
1902 if ((offset + 4) > radeon_bo_size(reloc->robj)) {
1903 DRM_ERROR("bad COPY_DW dst bo too small: 0x%llx, 0x%lx\n",
1904 offset + 4, radeon_bo_size(reloc->robj));
1905 return -EINVAL;
1906 }
1907 ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1908 ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1909 } else {
1910 /* DST is a reg. */
1911 reg = radeon_get_ib_value(p, idx+3) << 2;
1912 if (!r600_is_safe_reg(p, reg, idx+3))
1913 return -EINVAL;
1914 }
1915 break;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001916 case PACKET3_NOP:
1917 break;
1918 default:
1919 DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
1920 return -EINVAL;
1921 }
1922 return 0;
1923}
1924
1925int r600_cs_parse(struct radeon_cs_parser *p)
1926{
1927 struct radeon_cs_packet pkt;
Jerome Glissec8c15ff2010-01-18 13:01:36 +01001928 struct r600_cs_track *track;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001929 int r;
1930
Jerome Glisse961fb592010-02-10 22:30:05 +00001931 if (p->track == NULL) {
1932 /* initialize tracker, we are in kms */
1933 track = kzalloc(sizeof(*track), GFP_KERNEL);
1934 if (track == NULL)
1935 return -ENOMEM;
1936 r600_cs_track_init(track);
1937 if (p->rdev->family < CHIP_RV770) {
1938 track->npipes = p->rdev->config.r600.tiling_npipes;
1939 track->nbanks = p->rdev->config.r600.tiling_nbanks;
1940 track->group_size = p->rdev->config.r600.tiling_group_size;
1941 } else if (p->rdev->family <= CHIP_RV740) {
1942 track->npipes = p->rdev->config.rv770.tiling_npipes;
1943 track->nbanks = p->rdev->config.rv770.tiling_nbanks;
1944 track->group_size = p->rdev->config.rv770.tiling_group_size;
1945 }
1946 p->track = track;
1947 }
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001948 do {
1949 r = r600_cs_packet_parse(p, &pkt, p->idx);
1950 if (r) {
Jerome Glisse7cb72ef2010-02-11 12:44:32 +01001951 kfree(p->track);
1952 p->track = NULL;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001953 return r;
1954 }
1955 p->idx += pkt.count + 2;
1956 switch (pkt.type) {
1957 case PACKET_TYPE0:
1958 r = r600_cs_parse_packet0(p, &pkt);
1959 break;
1960 case PACKET_TYPE2:
1961 break;
1962 case PACKET_TYPE3:
1963 r = r600_packet3_check(p, &pkt);
1964 break;
1965 default:
1966 DRM_ERROR("Unknown packet type %d !\n", pkt.type);
Jerome Glisse961fb592010-02-10 22:30:05 +00001967 kfree(p->track);
Jerome Glisse7cb72ef2010-02-11 12:44:32 +01001968 p->track = NULL;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001969 return -EINVAL;
1970 }
1971 if (r) {
Jerome Glisse961fb592010-02-10 22:30:05 +00001972 kfree(p->track);
Jerome Glisse7cb72ef2010-02-11 12:44:32 +01001973 p->track = NULL;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001974 return r;
1975 }
1976 } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
1977#if 0
1978 for (r = 0; r < p->ib->length_dw; r++) {
1979 printk(KERN_INFO "%05d 0x%08X\n", r, p->ib->ptr[r]);
1980 mdelay(1);
1981 }
1982#endif
Jerome Glisse961fb592010-02-10 22:30:05 +00001983 kfree(p->track);
Jerome Glisse7cb72ef2010-02-11 12:44:32 +01001984 p->track = NULL;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001985 return 0;
1986}
1987
1988static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p)
1989{
1990 if (p->chunk_relocs_idx == -1) {
1991 return 0;
1992 }
Julia Lawalle265f39e2009-12-19 08:16:33 +01001993 p->relocs = kzalloc(sizeof(struct radeon_cs_reloc), GFP_KERNEL);
Jerome Glisse3ce0a232009-09-08 10:10:24 +10001994 if (p->relocs == NULL) {
1995 return -ENOMEM;
1996 }
1997 return 0;
1998}
1999
2000/**
2001 * cs_parser_fini() - clean parser states
2002 * @parser: parser structure holding parsing context.
2003 * @error: error number
2004 *
2005 * If error is set than unvalidate buffer, otherwise just free memory
2006 * used by parsing context.
2007 **/
2008static void r600_cs_parser_fini(struct radeon_cs_parser *parser, int error)
2009{
2010 unsigned i;
2011
2012 kfree(parser->relocs);
2013 for (i = 0; i < parser->nchunks; i++) {
2014 kfree(parser->chunks[i].kdata);
Dave Airlie4c57edba2009-09-28 15:37:25 +10002015 kfree(parser->chunks[i].kpage[0]);
2016 kfree(parser->chunks[i].kpage[1]);
Jerome Glisse3ce0a232009-09-08 10:10:24 +10002017 }
2018 kfree(parser->chunks);
2019 kfree(parser->chunks_array);
2020}
2021
2022int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
2023 unsigned family, u32 *ib, int *l)
2024{
2025 struct radeon_cs_parser parser;
2026 struct radeon_cs_chunk *ib_chunk;
Jerome Glisse961fb592010-02-10 22:30:05 +00002027 struct radeon_ib fake_ib;
2028 struct r600_cs_track *track;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10002029 int r;
2030
Jerome Glisse961fb592010-02-10 22:30:05 +00002031 /* initialize tracker */
2032 track = kzalloc(sizeof(*track), GFP_KERNEL);
2033 if (track == NULL)
2034 return -ENOMEM;
2035 r600_cs_track_init(track);
2036 r600_cs_legacy_get_tiling_conf(dev, &track->npipes, &track->nbanks, &track->group_size);
Jerome Glisse3ce0a232009-09-08 10:10:24 +10002037 /* initialize parser */
2038 memset(&parser, 0, sizeof(struct radeon_cs_parser));
2039 parser.filp = filp;
Jerome Glissec8c15ff2010-01-18 13:01:36 +01002040 parser.dev = &dev->pdev->dev;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10002041 parser.rdev = NULL;
2042 parser.family = family;
2043 parser.ib = &fake_ib;
Jerome Glisse961fb592010-02-10 22:30:05 +00002044 parser.track = track;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10002045 fake_ib.ptr = ib;
2046 r = radeon_cs_parser_init(&parser, data);
2047 if (r) {
2048 DRM_ERROR("Failed to initialize parser !\n");
2049 r600_cs_parser_fini(&parser, r);
2050 return r;
2051 }
2052 r = r600_cs_parser_relocs_legacy(&parser);
2053 if (r) {
2054 DRM_ERROR("Failed to parse relocation !\n");
2055 r600_cs_parser_fini(&parser, r);
2056 return r;
2057 }
2058 /* Copy the packet into the IB, the parser will read from the
2059 * input memory (cached) and write to the IB (which can be
2060 * uncached). */
2061 ib_chunk = &parser.chunks[parser.chunk_ib_idx];
2062 parser.ib->length_dw = ib_chunk->length_dw;
Jerome Glisse3ce0a232009-09-08 10:10:24 +10002063 *l = parser.ib->length_dw;
2064 r = r600_cs_parse(&parser);
2065 if (r) {
2066 DRM_ERROR("Invalid command stream !\n");
2067 r600_cs_parser_fini(&parser, r);
2068 return r;
2069 }
Dave Airlie513bcb42009-09-23 16:56:27 +10002070 r = radeon_cs_finish_pages(&parser);
2071 if (r) {
2072 DRM_ERROR("Invalid command stream !\n");
2073 r600_cs_parser_fini(&parser, r);
2074 return r;
2075 }
Jerome Glisse3ce0a232009-09-08 10:10:24 +10002076 r600_cs_parser_fini(&parser, r);
2077 return r;
2078}
2079
2080void r600_cs_legacy_init(void)
2081{
2082 r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_nomm;
2083}