drm/radeon/r600: fix tiling issues in CS checker.
authorDave Airlie <airlied@redhat.com>
Thu, 21 Oct 2010 03:55:40 +0000 (13:55 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 26 Oct 2010 00:26:35 +0000 (10:26 +1000)
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>
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/radeon_drv.c

index 250a3a918193e9821aa6f5836d463553cf6f903d..f82832780a7e7d8d1d6508c118deb1e3fce821ca 100644 (file)
@@ -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 %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)) {
                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);
@@ -1138,7 +1149,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);
index f29a2695d96119a3371399e97579dcbc082cea86..f9e228661119ac062a1827e1dea6e3a869c6d074 100644 (file)
  * - 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);