From: Dave Airlie <airlied@xxxxxxxxxx> 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. Signed-off-by: Dave Airlie <airlied@xxxxxxxxxx> --- drivers/gpu/drm/radeon/r600_cs.c | 29 ++++++++++++++++++++--------- drivers/gpu/drm/radeon/radeon_drv.c | 3 ++- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 820c121..8c82e43 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) struct r600_cs_track *track = p->track; u32 bpe = 0, pitch, slice_tile_max, size, tmp, height, pitch_align; volatile u32 *ib = p->ib->ptr; + unsigned array_mode; 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"); @@ -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 = 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; - height = size / (pitch * 8 * bpe); + slice_tile_max *= 64; + height = slice_tile_max / (pitch * 8); if (height > 8192) height = 8192; - if (height > 7) - height &= ~0x7; - switch (G_0280A0_ARRAY_MODE(track->cb_color_info[i])) { + array_mode = G_0280A0_ARRAY_MODE(track->cb_color_info[i]); + switch (array_mode) { case V_0280A0_ARRAY_LINEAR_GENERAL: /* technically height & 0x7 */ break; @@ -222,7 +223,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) break; case V_0280A0_ARRAY_2D_TILED_THIN1: 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)) { dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n", __func__, __LINE__, pitch); @@ -243,8 +244,18 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) /* check offset */ tmp = height * pitch * 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 too big\n", __func__, i, track->cb_color_bo_offset[i]); - return -EINVAL; + if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) { + /* 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 %d 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 %d 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)) { 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) break; case V_028010_ARRAY_2D_TILED_THIN1: 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)) { dev_warn(p->dev, "%s:%d db pitch (%d) invalid\n", __func__, __LINE__, pitch); @@ -1139,7 +1150,7 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i break; case V_038000_ARRAY_2D_TILED_THIN1: 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)) { dev_warn(p->dev, "%s:%d tex pitch (%d) invalid\n", __func__, __LINE__, pitch); diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index f29a269..f9e2286 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -47,9 +47,10 @@ * - 2.4.0 - add crtc id query * - 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.7.0 - fixups for r600 2D tiling support. (no external ABI change) */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 6 +#define KMS_DRIVER_MINOR 7 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); -- 1.7.2.3 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel