Commit f30df2fa authored by Dave Airlie's avatar Dave Airlie

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: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent e3ce8a0b
...@@ -170,6 +170,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) ...@@ -170,6 +170,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
struct r600_cs_track *track = p->track; struct r600_cs_track *track = p->track;
u32 bpe = 0, pitch, slice_tile_max, size, tmp, height, pitch_align; u32 bpe = 0, pitch, slice_tile_max, size, tmp, height, pitch_align;
volatile u32 *ib = p->ib->ptr; volatile u32 *ib = p->ib->ptr;
unsigned array_mode;
if (G_0280A0_TILE_MODE(track->cb_color_info[i])) { if (G_0280A0_TILE_MODE(track->cb_color_info[i])) {
dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n"); 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,12 +186,12 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
/* pitch is the number of 8x8 tiles per row */ /* pitch is the number of 8x8 tiles per row */
pitch = G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1; pitch = G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1;
slice_tile_max = G_028060_SLICE_TILE_MAX(track->cb_color_size[i]) + 1; slice_tile_max = G_028060_SLICE_TILE_MAX(track->cb_color_size[i]) + 1;
height = size / (pitch * 8 * bpe); slice_tile_max *= 64;
height = slice_tile_max / (pitch * 8);
if (height > 8192) if (height > 8192)
height = 8192; height = 8192;
if (height > 7) array_mode = G_0280A0_ARRAY_MODE(track->cb_color_info[i]);
height &= ~0x7; switch (array_mode) {
switch (G_0280A0_ARRAY_MODE(track->cb_color_info[i])) {
case V_0280A0_ARRAY_LINEAR_GENERAL: case V_0280A0_ARRAY_LINEAR_GENERAL:
/* technically height & 0x7 */ /* technically height & 0x7 */
break; break;
...@@ -222,7 +223,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) ...@@ -222,7 +223,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
break; break;
case V_0280A0_ARRAY_2D_TILED_THIN1: case V_0280A0_ARRAY_2D_TILED_THIN1:
pitch_align = max((u32)track->nbanks, pitch_align = max((u32)track->nbanks,
(u32)(((track->group_size / 8) / (bpe * track->nsamples)) * track->nbanks)); (u32)(((track->group_size / 8) / (bpe * track->nsamples)) * track->nbanks)) / 8;
if (!IS_ALIGNED(pitch, pitch_align)) { if (!IS_ALIGNED(pitch, pitch_align)) {
dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n", dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
__func__, __LINE__, pitch); __func__, __LINE__, pitch);
...@@ -243,8 +244,18 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) ...@@ -243,8 +244,18 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
/* check offset */ /* check offset */
tmp = height * pitch * 8 * bpe; tmp = height * pitch * 8 * bpe;
if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) { if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
dev_warn(p->dev, "%s offset[%d] %d too big\n", __func__, i, track->cb_color_bo_offset[i]); if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) {
return -EINVAL; /* the initial DDX does bad things with the CB size occasionally */
/* it rounds up height too far for slice tile max but the BO is smaller */
tmp = (height - 7) * 8 * bpe;
if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
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]));
return -EINVAL;
}
} else {
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]));
return -EINVAL;
}
} }
if (!IS_ALIGNED(track->cb_color_bo_offset[i], track->group_size)) { if (!IS_ALIGNED(track->cb_color_bo_offset[i], track->group_size)) {
dev_warn(p->dev, "%s offset[%d] %d not aligned\n", __func__, i, track->cb_color_bo_offset[i]); 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,7 +372,7 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
break; break;
case V_028010_ARRAY_2D_TILED_THIN1: case V_028010_ARRAY_2D_TILED_THIN1:
pitch_align = max((u32)track->nbanks, pitch_align = max((u32)track->nbanks,
(u32)(((track->group_size / 8) / bpe) * track->nbanks)); (u32)(((track->group_size / 8) / bpe) * track->nbanks)) / 8;
if (!IS_ALIGNED(pitch, pitch_align)) { if (!IS_ALIGNED(pitch, pitch_align)) {
dev_warn(p->dev, "%s:%d db pitch (%d) invalid\n", dev_warn(p->dev, "%s:%d db pitch (%d) invalid\n",
__func__, __LINE__, pitch); __func__, __LINE__, pitch);
...@@ -1138,7 +1149,7 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i ...@@ -1138,7 +1149,7 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i
break; break;
case V_038000_ARRAY_2D_TILED_THIN1: case V_038000_ARRAY_2D_TILED_THIN1:
pitch_align = max((u32)track->nbanks, pitch_align = max((u32)track->nbanks,
(u32)(((track->group_size / 8) / bpe) * track->nbanks)); (u32)(((track->group_size / 8) / bpe) * track->nbanks)) / 8;
if (!IS_ALIGNED(pitch, pitch_align)) { if (!IS_ALIGNED(pitch, pitch_align)) {
dev_warn(p->dev, "%s:%d tex pitch (%d) invalid\n", dev_warn(p->dev, "%s:%d tex pitch (%d) invalid\n",
__func__, __LINE__, pitch); __func__, __LINE__, pitch);
......
...@@ -47,9 +47,10 @@ ...@@ -47,9 +47,10 @@
* - 2.4.0 - add crtc id query * - 2.4.0 - add crtc id query
* - 2.5.0 - add get accel 2 to work around ddx breakage for evergreen * - 2.5.0 - add get accel 2 to work around ddx breakage for evergreen
* - 2.6.0 - add tiling config query (r6xx+), add initial HiZ support (r300->r500) * - 2.6.0 - add tiling config query (r6xx+), add initial HiZ support (r300->r500)
* 2.7.0 - fixups for r600 2D tiling support. (no external ABI change)
*/ */
#define KMS_DRIVER_MAJOR 2 #define KMS_DRIVER_MAJOR 2
#define KMS_DRIVER_MINOR 6 #define KMS_DRIVER_MINOR 7
#define KMS_DRIVER_PATCHLEVEL 0 #define KMS_DRIVER_PATCHLEVEL 0
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
int radeon_driver_unload_kms(struct drm_device *dev); int radeon_driver_unload_kms(struct drm_device *dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment