aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r600_cs.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2010-10-20 23:55:40 -0400
committerDave Airlie <airlied@redhat.com>2010-10-25 20:26:35 -0400
commitf30df2fad0c901e74ac9a52a488a54c69a373a41 (patch)
tree8f7ab96e9cbc373b20833e764a07f78091b41fb6 /drivers/gpu/drm/radeon/r600_cs.c
parente3ce8a0b277438591844847ac7c89a980b4cfa6d (diff)
drm/radeon/r600: fix tiling issues in CS checker.
The CS checker had some incorrect alignment requirements for 2D surfaces, this made rendering to mipmap levels that were 2D broken. Also the CB height was being worked out from the BO size, this doesn't work at all when rendering mipmap levels, instead we work out what height userspace wanted from slice max and use that to check it fits inside the BO, however the DDX send the wrong slice max for an unaligned buffer so we have to workaround for that even though its a userspace bug. Reviewed-by: Alex Deucher <alexdeucher@gmail.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.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index 250a3a918193..f82832780a7e 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -170,6 +170,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
170 struct r600_cs_track *track = p->track; 170 struct r600_cs_track *track = p->track;
171 u32 bpe = 0, pitch, slice_tile_max, size, tmp, height, pitch_align; 171 u32 bpe = 0, pitch, slice_tile_max, size, tmp, height, pitch_align;
172 volatile u32 *ib = p->ib->ptr; 172 volatile u32 *ib = p->ib->ptr;
173 unsigned array_mode;
173 174
174 if (G_0280A0_TILE_MODE(track->cb_color_info[i])) { 175 if (G_0280A0_TILE_MODE(track->cb_color_info[i])) {
175 dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n"); 176 dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n");
@@ -185,12 +186,12 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
185 /* pitch is the number of 8x8 tiles per row */ 186 /* pitch is the number of 8x8 tiles per row */
186 pitch = G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1; 187 pitch = G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1;
187 slice_tile_max = G_028060_SLICE_TILE_MAX(track->cb_color_size[i]) + 1; 188 slice_tile_max = G_028060_SLICE_TILE_MAX(track->cb_color_size[i]) + 1;
188 height = size / (pitch * 8 * bpe); 189 slice_tile_max *= 64;
190 height = slice_tile_max / (pitch * 8);
189 if (height > 8192) 191 if (height > 8192)
190 height = 8192; 192 height = 8192;
191 if (height > 7) 193 array_mode = G_0280A0_ARRAY_MODE(track->cb_color_info[i]);
192 height &= ~0x7; 194 switch (array_mode) {
193 switch (G_0280A0_ARRAY_MODE(track->cb_color_info[i])) {
194 case V_0280A0_ARRAY_LINEAR_GENERAL: 195 case V_0280A0_ARRAY_LINEAR_GENERAL:
195 /* technically height & 0x7 */ 196 /* technically height & 0x7 */
196 break; 197 break;
@@ -222,7 +223,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
222 break; 223 break;
223 case V_0280A0_ARRAY_2D_TILED_THIN1: 224 case V_0280A0_ARRAY_2D_TILED_THIN1:
224 pitch_align = max((u32)track->nbanks, 225 pitch_align = max((u32)track->nbanks,
225 (u32)(((track->group_size / 8) / (bpe * track->nsamples)) * track->nbanks)); 226 (u32)(((track->group_size / 8) / (bpe * track->nsamples)) * track->nbanks)) / 8;
226 if (!IS_ALIGNED(pitch, pitch_align)) { 227 if (!IS_ALIGNED(pitch, pitch_align)) {
227 dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n", 228 dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
228 __func__, __LINE__, pitch); 229 __func__, __LINE__, pitch);
@@ -243,8 +244,18 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
243 /* check offset */ 244 /* check offset */
244 tmp = height * pitch * 8 * bpe; 245 tmp = height * pitch * 8 * bpe;
245 if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) { 246 if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
246 dev_warn(p->dev, "%s offset[%d] %d too big\n", __func__, i, track->cb_color_bo_offset[i]); 247 if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) {
247 return -EINVAL; 248 /* the initial DDX does bad things with the CB size occasionally */
249 /* it rounds up height too far for slice tile max but the BO is smaller */
250 tmp = (height - 7) * 8 * bpe;
251 if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
252 dev_warn(p->dev, "%s offset[%d] %d %d %lu too big\n", __func__, i, track->cb_color_bo_offset[i], tmp, radeon_bo_size(track->cb_color_bo[i]));
253 return -EINVAL;
254 }
255 } else {
256 dev_warn(p->dev, "%s offset[%d] %d %d %lu too big\n", __func__, i, track->cb_color_bo_offset[i], tmp, radeon_bo_size(track->cb_color_bo[i]));
257 return -EINVAL;
258 }
248 } 259 }
249 if (!IS_ALIGNED(track->cb_color_bo_offset[i], track->group_size)) { 260 if (!IS_ALIGNED(track->cb_color_bo_offset[i], track->group_size)) {
250 dev_warn(p->dev, "%s offset[%d] %d not aligned\n", __func__, i, track->cb_color_bo_offset[i]); 261 dev_warn(p->dev, "%s offset[%d] %d not aligned\n", __func__, i, track->cb_color_bo_offset[i]);
@@ -361,7 +372,7 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
361 break; 372 break;
362 case V_028010_ARRAY_2D_TILED_THIN1: 373 case V_028010_ARRAY_2D_TILED_THIN1:
363 pitch_align = max((u32)track->nbanks, 374 pitch_align = max((u32)track->nbanks,
364 (u32)(((track->group_size / 8) / bpe) * track->nbanks)); 375 (u32)(((track->group_size / 8) / bpe) * track->nbanks)) / 8;
365 if (!IS_ALIGNED(pitch, pitch_align)) { 376 if (!IS_ALIGNED(pitch, pitch_align)) {
366 dev_warn(p->dev, "%s:%d db pitch (%d) invalid\n", 377 dev_warn(p->dev, "%s:%d db pitch (%d) invalid\n",
367 __func__, __LINE__, pitch); 378 __func__, __LINE__, pitch);
@@ -1138,7 +1149,7 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i
1138 break; 1149 break;
1139 case V_038000_ARRAY_2D_TILED_THIN1: 1150 case V_038000_ARRAY_2D_TILED_THIN1:
1140 pitch_align = max((u32)track->nbanks, 1151 pitch_align = max((u32)track->nbanks,
1141 (u32)(((track->group_size / 8) / bpe) * track->nbanks)); 1152 (u32)(((track->group_size / 8) / bpe) * track->nbanks)) / 8;
1142 if (!IS_ALIGNED(pitch, pitch_align)) { 1153 if (!IS_ALIGNED(pitch, pitch_align)) {
1143 dev_warn(p->dev, "%s:%d tex pitch (%d) invalid\n", 1154 dev_warn(p->dev, "%s:%d tex pitch (%d) invalid\n",
1144 __func__, __LINE__, pitch); 1155 __func__, __LINE__, pitch);