aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r600_cs.c
diff options
context:
space:
mode:
authorJerome Glisse <jglisse@redhat.com>2010-02-10 17:30:05 -0500
committerDave Airlie <airlied@redhat.com>2010-02-11 04:03:45 -0500
commit961fb597c17e2e4f55407d56b7211c188ab41eff (patch)
tree14ec50b2d934c3dafac313b5adf53df1e32be107 /drivers/gpu/drm/radeon/r600_cs.c
parent4c36b678a23d33b82d614afe4f958a9d244ede5d (diff)
drm/radeon/kms: r600/r700 command stream checker
This patch add cs checker to r600/r700 hw. Command stream checking will rewrite some of the cs value in order to restrict GPU access to BO size. This doesn't break old userspace but just enforce safe value. It should break any things that was using the r600/r700 cs ioctl to do forbidden things (malicious software), though we are not aware of such things. Here is the list of thing we check : - enforcing resource size - enforcing color buffer slice tile max, will restrict cb access - enforcing db buffer slice tile max, will restrict db access We don't check for shader bigger than the BO in which they are supposed to be, such use would lead to GPU lockup and is harmless from security POV, as far as we can tell (note that even checking for this wouldn't prevent someone to write bogus shader that lead to lockup). This patch has received as much testing as humanly possible with old userspace to check that it didn't break such configuration. However not all the applications out there were tested, thus it might broke some odd, rare applications. [airlied: fix rules for cs checker for parallel builds] Signed-off-by: Jerome Glisse <jglisse@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/r600_cs.c')
-rw-r--r--drivers/gpu/drm/radeon/r600_cs.c826
1 files changed, 698 insertions, 128 deletions
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index e4c45ec16507..ac67d6488a95 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -28,6 +28,7 @@
28#include "drmP.h" 28#include "drmP.h"
29#include "radeon.h" 29#include "radeon.h"
30#include "r600d.h" 30#include "r600d.h"
31#include "r600_reg_safe.h"
31 32
32static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p, 33static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
33 struct radeon_cs_reloc **cs_reloc); 34 struct radeon_cs_reloc **cs_reloc);
@@ -35,11 +36,313 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
35 struct radeon_cs_reloc **cs_reloc); 36 struct radeon_cs_reloc **cs_reloc);
36typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**); 37typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**);
37static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm; 38static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm;
39extern void r600_cs_legacy_get_tiling_conf(struct drm_device *dev, u32 *npipes, u32 *nbanks, u32 *group_size);
40
38 41
39struct r600_cs_track { 42struct r600_cs_track {
40 u32 cb_color0_base_last; 43 /* configuration we miror so that we use same code btw kms/ums */
44 u32 group_size;
45 u32 nbanks;
46 u32 npipes;
47 /* value we track */
48 u32 nsamples;
49 u32 cb_color_base_last[8];
50 struct radeon_bo *cb_color_bo[8];
51 u32 cb_color_bo_offset[8];
52 struct radeon_bo *cb_color_frag_bo[8];
53 struct radeon_bo *cb_color_tile_bo[8];
54 u32 cb_color_info[8];
55 u32 cb_color_size_idx[8];
56 u32 cb_target_mask;
57 u32 cb_shader_mask;
58 u32 cb_color_size[8];
59 u32 vgt_strmout_en;
60 u32 vgt_strmout_buffer_en;
61 u32 db_depth_control;
62 u32 db_depth_info;
63 u32 db_depth_size_idx;
64 u32 db_depth_view;
65 u32 db_depth_size;
66 u32 db_offset;
67 struct radeon_bo *db_bo;
41}; 68};
42 69
70static inline int r600_bpe_from_format(u32 *bpe, u32 format)
71{
72 switch (format) {
73 case V_038004_COLOR_8:
74 case V_038004_COLOR_4_4:
75 case V_038004_COLOR_3_3_2:
76 case V_038004_FMT_1:
77 *bpe = 1;
78 break;
79 case V_038004_COLOR_16:
80 case V_038004_COLOR_16_FLOAT:
81 case V_038004_COLOR_8_8:
82 case V_038004_COLOR_5_6_5:
83 case V_038004_COLOR_6_5_5:
84 case V_038004_COLOR_1_5_5_5:
85 case V_038004_COLOR_4_4_4_4:
86 case V_038004_COLOR_5_5_5_1:
87 *bpe = 2;
88 break;
89 case V_038004_FMT_8_8_8:
90 *bpe = 3;
91 break;
92 case V_038004_COLOR_32:
93 case V_038004_COLOR_32_FLOAT:
94 case V_038004_COLOR_16_16:
95 case V_038004_COLOR_16_16_FLOAT:
96 case V_038004_COLOR_8_24:
97 case V_038004_COLOR_8_24_FLOAT:
98 case V_038004_COLOR_24_8:
99 case V_038004_COLOR_24_8_FLOAT:
100 case V_038004_COLOR_10_11_11:
101 case V_038004_COLOR_10_11_11_FLOAT:
102 case V_038004_COLOR_11_11_10:
103 case V_038004_COLOR_11_11_10_FLOAT:
104 case V_038004_COLOR_2_10_10_10:
105 case V_038004_COLOR_8_8_8_8:
106 case V_038004_COLOR_10_10_10_2:
107 case V_038004_FMT_5_9_9_9_SHAREDEXP:
108 case V_038004_FMT_32_AS_8:
109 case V_038004_FMT_32_AS_8_8:
110 *bpe = 4;
111 break;
112 case V_038004_COLOR_X24_8_32_FLOAT:
113 case V_038004_COLOR_32_32:
114 case V_038004_COLOR_32_32_FLOAT:
115 case V_038004_COLOR_16_16_16_16:
116 case V_038004_COLOR_16_16_16_16_FLOAT:
117 *bpe = 8;
118 break;
119 case V_038004_FMT_16_16_16:
120 case V_038004_FMT_16_16_16_FLOAT:
121 *bpe = 6;
122 break;
123 case V_038004_FMT_32_32_32:
124 case V_038004_FMT_32_32_32_FLOAT:
125 *bpe = 12;
126 break;
127 case V_038004_COLOR_32_32_32_32:
128 case V_038004_COLOR_32_32_32_32_FLOAT:
129 *bpe = 16;
130 break;
131 case V_038004_FMT_GB_GR:
132 case V_038004_FMT_BG_RG:
133 case V_038004_COLOR_INVALID:
134 *bpe = 16;
135 return -EINVAL;
136 }
137 return 0;
138}
139
140static void r600_cs_track_init(struct r600_cs_track *track)
141{
142 int i;
143
144 for (i = 0; i < 8; i++) {
145 track->cb_color_base_last[i] = 0;
146 track->cb_color_size[i] = 0;
147 track->cb_color_size_idx[i] = 0;
148 track->cb_color_info[i] = 0;
149 track->cb_color_bo[i] = NULL;
150 track->cb_color_bo_offset[i] = 0xFFFFFFFF;
151 }
152 track->cb_target_mask = 0xFFFFFFFF;
153 track->cb_shader_mask = 0xFFFFFFFF;
154 track->db_bo = NULL;
155 /* assume the biggest format and that htile is enabled */
156 track->db_depth_info = 7 | (1 << 25);
157 track->db_depth_view = 0xFFFFC000;
158 track->db_depth_size = 0xFFFFFFFF;
159 track->db_depth_size_idx = 0;
160 track->db_depth_control = 0xFFFFFFFF;
161}
162
163static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
164{
165 struct r600_cs_track *track = p->track;
166 u32 bpe, pitch, slice_tile_max, size, tmp, height;
167 volatile u32 *ib = p->ib->ptr;
168
169 if (G_0280A0_TILE_MODE(track->cb_color_info[i])) {
170 dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n");
171 return -EINVAL;
172 }
173 size = radeon_bo_size(track->cb_color_bo[i]);
174 if (r600_bpe_from_format(&bpe, G_0280A0_FORMAT(track->cb_color_info[i]))) {
175 dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n",
176 __func__, __LINE__, G_0280A0_FORMAT(track->cb_color_info[i]),
177 i, track->cb_color_info[i]);
178 return -EINVAL;
179 }
180 pitch = (G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1) << 3;
181 slice_tile_max = G_028060_SLICE_TILE_MAX(track->cb_color_size[i]) + 1;
182 if (!pitch) {
183 dev_warn(p->dev, "%s:%d cb pitch (%d) for %d invalid (0x%08X)\n",
184 __func__, __LINE__, pitch, i, track->cb_color_size[i]);
185 return -EINVAL;
186 }
187 height = size / (pitch * bpe);
188 if (height > 8192)
189 height = 8192;
190 switch (G_0280A0_ARRAY_MODE(track->cb_color_info[i])) {
191 case V_0280A0_ARRAY_LINEAR_GENERAL:
192 case V_0280A0_ARRAY_LINEAR_ALIGNED:
193 if (pitch & 0x3f) {
194 dev_warn(p->dev, "%s:%d cb pitch (%d x %d = %d) invalid\n",
195 __func__, __LINE__, pitch, bpe, pitch * bpe);
196 return -EINVAL;
197 }
198 if ((pitch * bpe) & (track->group_size - 1)) {
199 dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
200 __func__, __LINE__, pitch);
201 return -EINVAL;
202 }
203 break;
204 case V_0280A0_ARRAY_1D_TILED_THIN1:
205 if ((pitch * 8 * bpe * track->nsamples) & (track->group_size - 1)) {
206 dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
207 __func__, __LINE__, pitch);
208 return -EINVAL;
209 }
210 height &= ~0x7;
211 if (!height)
212 height = 8;
213 break;
214 case V_0280A0_ARRAY_2D_TILED_THIN1:
215 if (pitch & ((8 * track->nbanks) - 1)) {
216 dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
217 __func__, __LINE__, pitch);
218 return -EINVAL;
219 }
220 tmp = pitch * 8 * bpe * track->nsamples;
221 tmp = tmp / track->nbanks;
222 if (tmp & (track->group_size - 1)) {
223 dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
224 __func__, __LINE__, pitch);
225 return -EINVAL;
226 }
227 height &= ~((16 * track->npipes) - 1);
228 if (!height)
229 height = 16 * track->npipes;
230 break;
231 default:
232 dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
233 G_0280A0_ARRAY_MODE(track->cb_color_info[i]), i,
234 track->cb_color_info[i]);
235 return -EINVAL;
236 }
237 /* check offset */
238 tmp = height * pitch;
239 if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
240 dev_warn(p->dev, "%s offset[%d] %d to big\n", __func__, i, track->cb_color_bo_offset[i]);
241 return -EINVAL;
242 }
243 /* limit max tile */
244 tmp = (height * pitch) >> 6;
245 if (tmp < slice_tile_max)
246 slice_tile_max = tmp;
247 tmp = S_028060_PITCH_TILE_MAX((pitch >> 3) - 1) |
248 S_028060_SLICE_TILE_MAX(slice_tile_max - 1);
249 ib[track->cb_color_size_idx[i]] = tmp;
250 return 0;
251}
252
253static int r600_cs_track_check(struct radeon_cs_parser *p)
254{
255 struct r600_cs_track *track = p->track;
256 u32 tmp;
257 int r, i;
258 volatile u32 *ib = p->ib->ptr;
259
260 /* on legacy kernel we don't perform advanced check */
261 if (p->rdev == NULL)
262 return 0;
263 /* we don't support out buffer yet */
264 if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) {
265 dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
266 return -EINVAL;
267 }
268 /* check that we have a cb for each enabled target, we don't check
269 * shader_mask because it seems mesa isn't always setting it :(
270 */
271 tmp = track->cb_target_mask;
272 for (i = 0; i < 8; i++) {
273 if ((tmp >> (i * 4)) & 0xF) {
274 /* at least one component is enabled */
275 if (track->cb_color_bo[i] == NULL) {
276 dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n",
277 __func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i);
278 return -EINVAL;
279 }
280 /* perform rewrite of CB_COLOR[0-7]_SIZE */
281 r = r600_cs_track_validate_cb(p, i);
282 if (r)
283 return r;
284 }
285 }
286 /* Check depth buffer */
287 if (G_028800_STENCIL_ENABLE(track->db_depth_control) ||
288 G_028800_Z_ENABLE(track->db_depth_control)) {
289 u32 nviews, bpe, ntiles;
290 if (track->db_bo == NULL) {
291 dev_warn(p->dev, "z/stencil with no depth buffer\n");
292 return -EINVAL;
293 }
294 if (G_028010_TILE_SURFACE_ENABLE(track->db_depth_info)) {
295 dev_warn(p->dev, "this kernel doesn't support z/stencil htile\n");
296 return -EINVAL;
297 }
298 switch (G_028010_FORMAT(track->db_depth_info)) {
299 case V_028010_DEPTH_16:
300 bpe = 2;
301 break;
302 case V_028010_DEPTH_X8_24:
303 case V_028010_DEPTH_8_24:
304 case V_028010_DEPTH_X8_24_FLOAT:
305 case V_028010_DEPTH_8_24_FLOAT:
306 case V_028010_DEPTH_32_FLOAT:
307 bpe = 4;
308 break;
309 case V_028010_DEPTH_X24_8_32_FLOAT:
310 bpe = 8;
311 break;
312 default:
313 dev_warn(p->dev, "z/stencil with invalid format %d\n", G_028010_FORMAT(track->db_depth_info));
314 return -EINVAL;
315 }
316 if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) {
317 if (!track->db_depth_size_idx) {
318 dev_warn(p->dev, "z/stencil buffer size not set\n");
319 return -EINVAL;
320 }
321 printk_once(KERN_WARNING "You have old & broken userspace please consider updating mesa\n");
322 tmp = radeon_bo_size(track->db_bo) - track->db_offset;
323 tmp = (tmp / bpe) >> 6;
324 if (!tmp) {
325 dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %ld)\n",
326 track->db_depth_size, bpe, track->db_offset,
327 radeon_bo_size(track->db_bo));
328 return -EINVAL;
329 }
330 ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF);
331 } else {
332 ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
333 nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1;
334 tmp = ntiles * bpe * 64 * nviews;
335 if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {
336 dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %d -> %d have %ld)\n",
337 track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
338 radeon_bo_size(track->db_bo));
339 return -EINVAL;
340 }
341 }
342 }
343 return 0;
344}
345
43/** 346/**
44 * r600_cs_packet_parse() - parse cp packet and point ib index to next packet 347 * r600_cs_packet_parse() - parse cp packet and point ib index to next packet
45 * @parser: parser structure holding parsing context. 348 * @parser: parser structure holding parsing context.
@@ -359,6 +662,334 @@ static int r600_cs_parse_packet0(struct radeon_cs_parser *p,
359 return 0; 662 return 0;
360} 663}
361 664
665/**
666 * r600_cs_check_reg() - check if register is authorized or not
667 * @parser: parser structure holding parsing context
668 * @reg: register we are testing
669 * @idx: index into the cs buffer
670 *
671 * This function will test against r600_reg_safe_bm and return 0
672 * if register is safe. If register is not flag as safe this function
673 * will test it against a list of register needind special handling.
674 */
675static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
676{
677 struct r600_cs_track *track = (struct r600_cs_track *)p->track;
678 struct radeon_cs_reloc *reloc;
679 u32 last_reg = ARRAY_SIZE(r600_reg_safe_bm);
680 u32 m, i, tmp, *ib;
681 int r;
682
683 i = (reg >> 7);
684 if (i > last_reg) {
685 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
686 return -EINVAL;
687 }
688 m = 1 << ((reg >> 2) & 31);
689 if (!(r600_reg_safe_bm[i] & m))
690 return 0;
691 ib = p->ib->ptr;
692 switch (reg) {
693 /* force following reg to 0 in an attemp to disable out buffer
694 * which will need us to better understand how it works to perform
695 * security check on it (Jerome)
696 */
697 case R_0288A8_SQ_ESGS_RING_ITEMSIZE:
698 case R_008C44_SQ_ESGS_RING_SIZE:
699 case R_0288B0_SQ_ESTMP_RING_ITEMSIZE:
700 case R_008C54_SQ_ESTMP_RING_SIZE:
701 case R_0288C0_SQ_FBUF_RING_ITEMSIZE:
702 case R_008C74_SQ_FBUF_RING_SIZE:
703 case R_0288B4_SQ_GSTMP_RING_ITEMSIZE:
704 case R_008C5C_SQ_GSTMP_RING_SIZE:
705 case R_0288AC_SQ_GSVS_RING_ITEMSIZE:
706 case R_008C4C_SQ_GSVS_RING_SIZE:
707 case R_0288BC_SQ_PSTMP_RING_ITEMSIZE:
708 case R_008C6C_SQ_PSTMP_RING_SIZE:
709 case R_0288C4_SQ_REDUC_RING_ITEMSIZE:
710 case R_008C7C_SQ_REDUC_RING_SIZE:
711 case R_0288B8_SQ_VSTMP_RING_ITEMSIZE:
712 case R_008C64_SQ_VSTMP_RING_SIZE:
713 case R_0288C8_SQ_GS_VERT_ITEMSIZE:
714 /* get value to populate the IB don't remove */
715 tmp =radeon_get_ib_value(p, idx);
716 ib[idx] = 0;
717 break;
718 case R_028800_DB_DEPTH_CONTROL:
719 track->db_depth_control = radeon_get_ib_value(p, idx);
720 break;
721 case R_028010_DB_DEPTH_INFO:
722 track->db_depth_info = radeon_get_ib_value(p, idx);
723 break;
724 case R_028004_DB_DEPTH_VIEW:
725 track->db_depth_view = radeon_get_ib_value(p, idx);
726 break;
727 case R_028000_DB_DEPTH_SIZE:
728 track->db_depth_size = radeon_get_ib_value(p, idx);
729 track->db_depth_size_idx = idx;
730 break;
731 case R_028AB0_VGT_STRMOUT_EN:
732 track->vgt_strmout_en = radeon_get_ib_value(p, idx);
733 break;
734 case R_028B20_VGT_STRMOUT_BUFFER_EN:
735 track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx);
736 break;
737 case R_028238_CB_TARGET_MASK:
738 track->cb_target_mask = radeon_get_ib_value(p, idx);
739 break;
740 case R_02823C_CB_SHADER_MASK:
741 track->cb_shader_mask = radeon_get_ib_value(p, idx);
742 break;
743 case R_028C04_PA_SC_AA_CONFIG:
744 tmp = G_028C04_MSAA_NUM_SAMPLES(radeon_get_ib_value(p, idx));
745 track->nsamples = 1 << tmp;
746 break;
747 case R_0280A0_CB_COLOR0_INFO:
748 case R_0280A4_CB_COLOR1_INFO:
749 case R_0280A8_CB_COLOR2_INFO:
750 case R_0280AC_CB_COLOR3_INFO:
751 case R_0280B0_CB_COLOR4_INFO:
752 case R_0280B4_CB_COLOR5_INFO:
753 case R_0280B8_CB_COLOR6_INFO:
754 case R_0280BC_CB_COLOR7_INFO:
755 tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4;
756 track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
757 break;
758 case R_028060_CB_COLOR0_SIZE:
759 case R_028064_CB_COLOR1_SIZE:
760 case R_028068_CB_COLOR2_SIZE:
761 case R_02806C_CB_COLOR3_SIZE:
762 case R_028070_CB_COLOR4_SIZE:
763 case R_028074_CB_COLOR5_SIZE:
764 case R_028078_CB_COLOR6_SIZE:
765 case R_02807C_CB_COLOR7_SIZE:
766 tmp = (reg - R_028060_CB_COLOR0_SIZE) / 4;
767 track->cb_color_size[tmp] = radeon_get_ib_value(p, idx);
768 track->cb_color_size_idx[tmp] = idx;
769 break;
770 /* This register were added late, there is userspace
771 * which does provide relocation for those but set
772 * 0 offset. In order to avoid breaking old userspace
773 * we detect this and set address to point to last
774 * CB_COLOR0_BASE, note that if userspace doesn't set
775 * CB_COLOR0_BASE before this register we will report
776 * error. Old userspace always set CB_COLOR0_BASE
777 * before any of this.
778 */
779 case R_0280E0_CB_COLOR0_FRAG:
780 case R_0280E4_CB_COLOR1_FRAG:
781 case R_0280E8_CB_COLOR2_FRAG:
782 case R_0280EC_CB_COLOR3_FRAG:
783 case R_0280F0_CB_COLOR4_FRAG:
784 case R_0280F4_CB_COLOR5_FRAG:
785 case R_0280F8_CB_COLOR6_FRAG:
786 case R_0280FC_CB_COLOR7_FRAG:
787 tmp = (reg - R_0280E0_CB_COLOR0_FRAG) / 4;
788 if (!r600_cs_packet_next_is_pkt3_nop(p)) {
789 if (!track->cb_color_base_last[tmp]) {
790 dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
791 return -EINVAL;
792 }
793 ib[idx] = track->cb_color_base_last[tmp];
794 printk_once(KERN_WARNING "You have old & broken userspace "
795 "please consider updating mesa & xf86-video-ati\n");
796 track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp];
797 } else {
798 r = r600_cs_packet_next_reloc(p, &reloc);
799 if (r) {
800 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
801 return -EINVAL;
802 }
803 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
804 track->cb_color_frag_bo[tmp] = reloc->robj;
805 }
806 break;
807 case R_0280C0_CB_COLOR0_TILE:
808 case R_0280C4_CB_COLOR1_TILE:
809 case R_0280C8_CB_COLOR2_TILE:
810 case R_0280CC_CB_COLOR3_TILE:
811 case R_0280D0_CB_COLOR4_TILE:
812 case R_0280D4_CB_COLOR5_TILE:
813 case R_0280D8_CB_COLOR6_TILE:
814 case R_0280DC_CB_COLOR7_TILE:
815 tmp = (reg - R_0280C0_CB_COLOR0_TILE) / 4;
816 if (!r600_cs_packet_next_is_pkt3_nop(p)) {
817 if (!track->cb_color_base_last[tmp]) {
818 dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
819 return -EINVAL;
820 }
821 ib[idx] = track->cb_color_base_last[tmp];
822 printk_once(KERN_WARNING "You have old & broken userspace "
823 "please consider updating mesa & xf86-video-ati\n");
824 track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp];
825 } else {
826 r = r600_cs_packet_next_reloc(p, &reloc);
827 if (r) {
828 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
829 return -EINVAL;
830 }
831 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
832 track->cb_color_tile_bo[tmp] = reloc->robj;
833 }
834 break;
835 case CB_COLOR0_BASE:
836 case CB_COLOR1_BASE:
837 case CB_COLOR2_BASE:
838 case CB_COLOR3_BASE:
839 case CB_COLOR4_BASE:
840 case CB_COLOR5_BASE:
841 case CB_COLOR6_BASE:
842 case CB_COLOR7_BASE:
843 r = r600_cs_packet_next_reloc(p, &reloc);
844 if (r) {
845 dev_warn(p->dev, "bad SET_CONTEXT_REG "
846 "0x%04X\n", reg);
847 return -EINVAL;
848 }
849 track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
850 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
851 tmp = (reg - CB_COLOR0_BASE) / 4;
852 track->cb_color_base_last[tmp] = ib[idx];
853 track->cb_color_bo[tmp] = reloc->robj;
854 break;
855 case DB_DEPTH_BASE:
856 r = r600_cs_packet_next_reloc(p, &reloc);
857 if (r) {
858 dev_warn(p->dev, "bad SET_CONTEXT_REG "
859 "0x%04X\n", reg);
860 return -EINVAL;
861 }
862 track->db_offset = radeon_get_ib_value(p, idx);
863 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
864 track->db_bo = reloc->robj;
865 break;
866 case DB_HTILE_DATA_BASE:
867 case SQ_PGM_START_FS:
868 case SQ_PGM_START_ES:
869 case SQ_PGM_START_VS:
870 case SQ_PGM_START_GS:
871 case SQ_PGM_START_PS:
872 r = r600_cs_packet_next_reloc(p, &reloc);
873 if (r) {
874 dev_warn(p->dev, "bad SET_CONTEXT_REG "
875 "0x%04X\n", reg);
876 return -EINVAL;
877 }
878 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
879 break;
880 default:
881 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
882 return -EINVAL;
883 }
884 return 0;
885}
886
887static inline unsigned minify(unsigned size, unsigned levels)
888{
889 size = size >> levels;
890 if (size < 1)
891 size = 1;
892 return size;
893}
894
895static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels,
896 unsigned w0, unsigned h0, unsigned d0, unsigned bpe,
897 unsigned *l0_size, unsigned *mipmap_size)
898{
899 unsigned offset, i, level, face;
900 unsigned width, height, depth, rowstride, size;
901
902 w0 = minify(w0, 0);
903 h0 = minify(h0, 0);
904 d0 = minify(d0, 0);
905 for(i = 0, offset = 0, level = blevel; i < nlevels; i++, level++) {
906 width = minify(w0, i);
907 height = minify(h0, i);
908 depth = minify(d0, i);
909 for(face = 0; face < nfaces; face++) {
910 rowstride = ((width * bpe) + 255) & ~255;
911 size = height * rowstride * depth;
912 offset += size;
913 offset = (offset + 0x1f) & ~0x1f;
914 }
915 }
916 *l0_size = (((w0 * bpe) + 255) & ~255) * h0 * d0;
917 *mipmap_size = offset;
918 if (!blevel)
919 *mipmap_size -= *l0_size;
920 if (!nlevels)
921 *mipmap_size = *l0_size;
922}
923
924/**
925 * r600_check_texture_resource() - check if register is authorized or not
926 * @p: parser structure holding parsing context
927 * @idx: index into the cs buffer
928 * @texture: texture's bo structure
929 * @mipmap: mipmap's bo structure
930 *
931 * This function will check that the resource has valid field and that
932 * the texture and mipmap bo object are big enough to cover this resource.
933 */
934static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx,
935 struct radeon_bo *texture,
936 struct radeon_bo *mipmap)
937{
938 u32 nfaces, nlevels, blevel, w0, h0, d0, bpe;
939 u32 word0, word1, l0_size, mipmap_size;
940
941 /* on legacy kernel we don't perform advanced check */
942 if (p->rdev == NULL)
943 return 0;
944 word0 = radeon_get_ib_value(p, idx + 0);
945 word1 = radeon_get_ib_value(p, idx + 1);
946 w0 = G_038000_TEX_WIDTH(word0) + 1;
947 h0 = G_038004_TEX_HEIGHT(word1) + 1;
948 d0 = G_038004_TEX_DEPTH(word1);
949 nfaces = 1;
950 switch (G_038000_DIM(word0)) {
951 case V_038000_SQ_TEX_DIM_1D:
952 case V_038000_SQ_TEX_DIM_2D:
953 case V_038000_SQ_TEX_DIM_3D:
954 break;
955 case V_038000_SQ_TEX_DIM_CUBEMAP:
956 nfaces = 6;
957 break;
958 case V_038000_SQ_TEX_DIM_1D_ARRAY:
959 case V_038000_SQ_TEX_DIM_2D_ARRAY:
960 case V_038000_SQ_TEX_DIM_2D_MSAA:
961 case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA:
962 default:
963 dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0));
964 return -EINVAL;
965 }
966 if (r600_bpe_from_format(&bpe, G_038004_DATA_FORMAT(word1))) {
967 dev_warn(p->dev, "%s:%d texture invalid format %d\n",
968 __func__, __LINE__, G_038004_DATA_FORMAT(word1));
969 return -EINVAL;
970 }
971 word0 = radeon_get_ib_value(p, idx + 4);
972 word1 = radeon_get_ib_value(p, idx + 5);
973 blevel = G_038010_BASE_LEVEL(word0);
974 nlevels = G_038014_LAST_LEVEL(word1);
975 r600_texture_size(nfaces, blevel, nlevels, w0, h0, d0, bpe, &l0_size, &mipmap_size);
976 /* using get ib will give us the offset into the texture bo */
977 word0 = radeon_get_ib_value(p, idx + 2);
978 if ((l0_size + word0) > radeon_bo_size(texture)) {
979 dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n",
980 w0, h0, bpe, word0, l0_size, radeon_bo_size(texture));
981 return -EINVAL;
982 }
983 /* using get ib will give us the offset into the mipmap bo */
984 word0 = radeon_get_ib_value(p, idx + 3);
985 if ((mipmap_size + word0) > radeon_bo_size(mipmap)) {
986 dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n",
987 w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));
988 return -EINVAL;
989 }
990 return 0;
991}
992
362static int r600_packet3_check(struct radeon_cs_parser *p, 993static int r600_packet3_check(struct radeon_cs_parser *p,
363 struct radeon_cs_packet *pkt) 994 struct radeon_cs_packet *pkt)
364{ 995{
@@ -408,12 +1039,22 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
408 } 1039 }
409 ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); 1040 ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
410 ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; 1041 ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1042 r = r600_cs_track_check(p);
1043 if (r) {
1044 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
1045 return r;
1046 }
411 break; 1047 break;
412 case PACKET3_DRAW_INDEX_AUTO: 1048 case PACKET3_DRAW_INDEX_AUTO:
413 if (pkt->count != 1) { 1049 if (pkt->count != 1) {
414 DRM_ERROR("bad DRAW_INDEX_AUTO\n"); 1050 DRM_ERROR("bad DRAW_INDEX_AUTO\n");
415 return -EINVAL; 1051 return -EINVAL;
416 } 1052 }
1053 r = r600_cs_track_check(p);
1054 if (r) {
1055 dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
1056 return r;
1057 }
417 break; 1058 break;
418 case PACKET3_DRAW_INDEX_IMMD_BE: 1059 case PACKET3_DRAW_INDEX_IMMD_BE:
419 case PACKET3_DRAW_INDEX_IMMD: 1060 case PACKET3_DRAW_INDEX_IMMD:
@@ -421,6 +1062,11 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
421 DRM_ERROR("bad DRAW_INDEX_IMMD\n"); 1062 DRM_ERROR("bad DRAW_INDEX_IMMD\n");
422 return -EINVAL; 1063 return -EINVAL;
423 } 1064 }
1065 r = r600_cs_track_check(p);
1066 if (r) {
1067 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
1068 return r;
1069 }
424 break; 1070 break;
425 case PACKET3_WAIT_REG_MEM: 1071 case PACKET3_WAIT_REG_MEM:
426 if (pkt->count != 5) { 1072 if (pkt->count != 5) {
@@ -493,30 +1139,9 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
493 } 1139 }
494 for (i = 0; i < pkt->count; i++) { 1140 for (i = 0; i < pkt->count; i++) {
495 reg = start_reg + (4 * i); 1141 reg = start_reg + (4 * i);
496 switch (reg) { 1142 r = r600_cs_check_reg(p, reg, idx+1+i);
497 case SQ_ESGS_RING_BASE: 1143 if (r)
498 case SQ_GSVS_RING_BASE: 1144 return r;
499 case SQ_ESTMP_RING_BASE:
500 case SQ_GSTMP_RING_BASE:
501 case SQ_VSTMP_RING_BASE:
502 case SQ_PSTMP_RING_BASE:
503 case SQ_FBUF_RING_BASE:
504 case SQ_REDUC_RING_BASE:
505 case SX_MEMORY_EXPORT_BASE:
506 r = r600_cs_packet_next_reloc(p, &reloc);
507 if (r) {
508 DRM_ERROR("bad SET_CONFIG_REG "
509 "0x%04X\n", reg);
510 return -EINVAL;
511 }
512 ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
513 break;
514 case CP_COHER_BASE:
515 /* use PACKET3_SURFACE_SYNC */
516 return -EINVAL;
517 default:
518 break;
519 }
520 } 1145 }
521 break; 1146 break;
522 case PACKET3_SET_CONTEXT_REG: 1147 case PACKET3_SET_CONTEXT_REG:
@@ -530,106 +1155,9 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
530 } 1155 }
531 for (i = 0; i < pkt->count; i++) { 1156 for (i = 0; i < pkt->count; i++) {
532 reg = start_reg + (4 * i); 1157 reg = start_reg + (4 * i);
533 switch (reg) { 1158 r = r600_cs_check_reg(p, reg, idx+1+i);
534 /* This register were added late, there is userspace 1159 if (r)
535 * which does provide relocation for those but set 1160 return r;
536 * 0 offset. In order to avoid breaking old userspace
537 * we detect this and set address to point to last
538 * CB_COLOR0_BASE, note that if userspace doesn't set
539 * CB_COLOR0_BASE before this register we will report
540 * error. Old userspace always set CB_COLOR0_BASE
541 * before any of this.
542 */
543 case R_0280E0_CB_COLOR0_FRAG:
544 case R_0280E4_CB_COLOR1_FRAG:
545 case R_0280E8_CB_COLOR2_FRAG:
546 case R_0280EC_CB_COLOR3_FRAG:
547 case R_0280F0_CB_COLOR4_FRAG:
548 case R_0280F4_CB_COLOR5_FRAG:
549 case R_0280F8_CB_COLOR6_FRAG:
550 case R_0280FC_CB_COLOR7_FRAG:
551 case R_0280C0_CB_COLOR0_TILE:
552 case R_0280C4_CB_COLOR1_TILE:
553 case R_0280C8_CB_COLOR2_TILE:
554 case R_0280CC_CB_COLOR3_TILE:
555 case R_0280D0_CB_COLOR4_TILE:
556 case R_0280D4_CB_COLOR5_TILE:
557 case R_0280D8_CB_COLOR6_TILE:
558 case R_0280DC_CB_COLOR7_TILE:
559 if (!r600_cs_packet_next_is_pkt3_nop(p)) {
560 if (!track->cb_color0_base_last) {
561 dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
562 return -EINVAL;
563 }
564 ib[idx+1+i] = track->cb_color0_base_last;
565 printk_once(KERN_WARNING "radeon: You have old & broken userspace "
566 "please consider updating mesa & xf86-video-ati\n");
567 } else {
568 r = r600_cs_packet_next_reloc(p, &reloc);
569 if (r) {
570 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
571 return -EINVAL;
572 }
573 ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
574 }
575 break;
576 case DB_DEPTH_BASE:
577 case DB_HTILE_DATA_BASE:
578 case CB_COLOR0_BASE:
579 r = r600_cs_packet_next_reloc(p, &reloc);
580 if (r) {
581 DRM_ERROR("bad SET_CONTEXT_REG "
582 "0x%04X\n", reg);
583 return -EINVAL;
584 }
585 ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
586 track->cb_color0_base_last = ib[idx+1+i];
587 break;
588 case CB_COLOR1_BASE:
589 case CB_COLOR2_BASE:
590 case CB_COLOR3_BASE:
591 case CB_COLOR4_BASE:
592 case CB_COLOR5_BASE:
593 case CB_COLOR6_BASE:
594 case CB_COLOR7_BASE:
595 case SQ_PGM_START_FS:
596 case SQ_PGM_START_ES:
597 case SQ_PGM_START_VS:
598 case SQ_PGM_START_GS:
599 case SQ_PGM_START_PS:
600 r = r600_cs_packet_next_reloc(p, &reloc);
601 if (r) {
602 DRM_ERROR("bad SET_CONTEXT_REG "
603 "0x%04X\n", reg);
604 return -EINVAL;
605 }
606 ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
607 break;
608 case VGT_DMA_BASE:
609 case VGT_DMA_BASE_HI:
610 /* These should be handled by DRAW_INDEX packet 3 */
611 case VGT_STRMOUT_BASE_OFFSET_0:
612 case VGT_STRMOUT_BASE_OFFSET_1:
613 case VGT_STRMOUT_BASE_OFFSET_2:
614 case VGT_STRMOUT_BASE_OFFSET_3:
615 case VGT_STRMOUT_BASE_OFFSET_HI_0:
616 case VGT_STRMOUT_BASE_OFFSET_HI_1:
617 case VGT_STRMOUT_BASE_OFFSET_HI_2:
618 case VGT_STRMOUT_BASE_OFFSET_HI_3:
619 case VGT_STRMOUT_BUFFER_BASE_0:
620 case VGT_STRMOUT_BUFFER_BASE_1:
621 case VGT_STRMOUT_BUFFER_BASE_2:
622 case VGT_STRMOUT_BUFFER_BASE_3:
623 case VGT_STRMOUT_BUFFER_OFFSET_0:
624 case VGT_STRMOUT_BUFFER_OFFSET_1:
625 case VGT_STRMOUT_BUFFER_OFFSET_2:
626 case VGT_STRMOUT_BUFFER_OFFSET_3:
627 /* These should be handled by STRMOUT_BUFFER packet 3 */
628 DRM_ERROR("bad context reg: 0x%08x\n", reg);
629 return -EINVAL;
630 default:
631 break;
632 }
633 } 1161 }
634 break; 1162 break;
635 case PACKET3_SET_RESOURCE: 1163 case PACKET3_SET_RESOURCE:
@@ -646,6 +1174,9 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
646 return -EINVAL; 1174 return -EINVAL;
647 } 1175 }
648 for (i = 0; i < (pkt->count / 7); i++) { 1176 for (i = 0; i < (pkt->count / 7); i++) {
1177 struct radeon_bo *texture, *mipmap;
1178 u32 size, offset;
1179
649 switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) { 1180 switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) {
650 case SQ_TEX_VTX_VALID_TEXTURE: 1181 case SQ_TEX_VTX_VALID_TEXTURE:
651 /* tex base */ 1182 /* tex base */
@@ -655,6 +1186,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
655 return -EINVAL; 1186 return -EINVAL;
656 } 1187 }
657 ib[idx+1+(i*7)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 1188 ib[idx+1+(i*7)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1189 texture = reloc->robj;
658 /* tex mip base */ 1190 /* tex mip base */
659 r = r600_cs_packet_next_reloc(p, &reloc); 1191 r = r600_cs_packet_next_reloc(p, &reloc);
660 if (r) { 1192 if (r) {
@@ -662,6 +1194,11 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
662 return -EINVAL; 1194 return -EINVAL;
663 } 1195 }
664 ib[idx+1+(i*7)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); 1196 ib[idx+1+(i*7)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1197 mipmap = reloc->robj;
1198 r = r600_check_texture_resource(p, idx+(i*7)+1,
1199 texture, mipmap);
1200 if (r)
1201 return r;
665 break; 1202 break;
666 case SQ_TEX_VTX_VALID_BUFFER: 1203 case SQ_TEX_VTX_VALID_BUFFER:
667 /* vtx base */ 1204 /* vtx base */
@@ -670,6 +1207,13 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
670 DRM_ERROR("bad SET_RESOURCE\n"); 1207 DRM_ERROR("bad SET_RESOURCE\n");
671 return -EINVAL; 1208 return -EINVAL;
672 } 1209 }
1210 offset = radeon_get_ib_value(p, idx+1+(i*7)+0);
1211 size = radeon_get_ib_value(p, idx+1+(i*7)+1);
1212 if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
1213 /* force size to size of the buffer */
1214 dev_warn(p->dev, "vbo resource seems too big for the bo\n");
1215 ib[idx+1+(i*7)+1] = radeon_bo_size(reloc->robj);
1216 }
673 ib[idx+1+(i*7)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff); 1217 ib[idx+1+(i*7)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff);
674 ib[idx+1+(i*7)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; 1218 ib[idx+1+(i*7)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
675 break; 1219 break;
@@ -760,8 +1304,23 @@ int r600_cs_parse(struct radeon_cs_parser *p)
760 struct r600_cs_track *track; 1304 struct r600_cs_track *track;
761 int r; 1305 int r;
762 1306
763 track = kzalloc(sizeof(*track), GFP_KERNEL); 1307 if (p->track == NULL) {
764 p->track = track; 1308 /* initialize tracker, we are in kms */
1309 track = kzalloc(sizeof(*track), GFP_KERNEL);
1310 if (track == NULL)
1311 return -ENOMEM;
1312 r600_cs_track_init(track);
1313 if (p->rdev->family < CHIP_RV770) {
1314 track->npipes = p->rdev->config.r600.tiling_npipes;
1315 track->nbanks = p->rdev->config.r600.tiling_nbanks;
1316 track->group_size = p->rdev->config.r600.tiling_group_size;
1317 } else if (p->rdev->family <= CHIP_RV740) {
1318 track->npipes = p->rdev->config.rv770.tiling_npipes;
1319 track->nbanks = p->rdev->config.rv770.tiling_nbanks;
1320 track->group_size = p->rdev->config.rv770.tiling_group_size;
1321 }
1322 p->track = track;
1323 }
765 do { 1324 do {
766 r = r600_cs_packet_parse(p, &pkt, p->idx); 1325 r = r600_cs_packet_parse(p, &pkt, p->idx);
767 if (r) { 1326 if (r) {
@@ -779,9 +1338,11 @@ int r600_cs_parse(struct radeon_cs_parser *p)
779 break; 1338 break;
780 default: 1339 default:
781 DRM_ERROR("Unknown packet type %d !\n", pkt.type); 1340 DRM_ERROR("Unknown packet type %d !\n", pkt.type);
1341 kfree(p->track);
782 return -EINVAL; 1342 return -EINVAL;
783 } 1343 }
784 if (r) { 1344 if (r) {
1345 kfree(p->track);
785 return r; 1346 return r;
786 } 1347 }
787 } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); 1348 } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
@@ -791,6 +1352,7 @@ int r600_cs_parse(struct radeon_cs_parser *p)
791 mdelay(1); 1352 mdelay(1);
792 } 1353 }
793#endif 1354#endif
1355 kfree(p->track);
794 return 0; 1356 return 0;
795} 1357}
796 1358
@@ -833,9 +1395,16 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
833{ 1395{
834 struct radeon_cs_parser parser; 1396 struct radeon_cs_parser parser;
835 struct radeon_cs_chunk *ib_chunk; 1397 struct radeon_cs_chunk *ib_chunk;
836 struct radeon_ib fake_ib; 1398 struct radeon_ib fake_ib;
1399 struct r600_cs_track *track;
837 int r; 1400 int r;
838 1401
1402 /* initialize tracker */
1403 track = kzalloc(sizeof(*track), GFP_KERNEL);
1404 if (track == NULL)
1405 return -ENOMEM;
1406 r600_cs_track_init(track);
1407 r600_cs_legacy_get_tiling_conf(dev, &track->npipes, &track->nbanks, &track->group_size);
839 /* initialize parser */ 1408 /* initialize parser */
840 memset(&parser, 0, sizeof(struct radeon_cs_parser)); 1409 memset(&parser, 0, sizeof(struct radeon_cs_parser));
841 parser.filp = filp; 1410 parser.filp = filp;
@@ -843,6 +1412,7 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
843 parser.rdev = NULL; 1412 parser.rdev = NULL;
844 parser.family = family; 1413 parser.family = family;
845 parser.ib = &fake_ib; 1414 parser.ib = &fake_ib;
1415 parser.track = track;
846 fake_ib.ptr = ib; 1416 fake_ib.ptr = ib;
847 r = radeon_cs_parser_init(&parser, data); 1417 r = radeon_cs_parser_init(&parser, data);
848 if (r) { 1418 if (r) {