Commit 16790569 authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie

drm/radeon/kms: fix and unify tiled buffer alignment checking for r6xx/7xx

Tiled buffers have the same alignment requirements regardless of
whether the surface is for db, cb, or textures.  Previously, the
calculations where inconsistent for each buffer type.

- Unify the alignment calculations in a common function
- Standardize the alignment units (pixels for pitch/height/depth,
bytes for base)
- properly check the buffer base alignments
Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 0143832c
...@@ -50,6 +50,7 @@ struct r600_cs_track { ...@@ -50,6 +50,7 @@ struct r600_cs_track {
u32 nsamples; u32 nsamples;
u32 cb_color_base_last[8]; u32 cb_color_base_last[8];
struct radeon_bo *cb_color_bo[8]; struct radeon_bo *cb_color_bo[8];
u64 cb_color_bo_mc[8];
u32 cb_color_bo_offset[8]; u32 cb_color_bo_offset[8];
struct radeon_bo *cb_color_frag_bo[8]; struct radeon_bo *cb_color_frag_bo[8];
struct radeon_bo *cb_color_tile_bo[8]; struct radeon_bo *cb_color_tile_bo[8];
...@@ -67,6 +68,7 @@ struct r600_cs_track { ...@@ -67,6 +68,7 @@ struct r600_cs_track {
u32 db_depth_size; u32 db_depth_size;
u32 db_offset; u32 db_offset;
struct radeon_bo *db_bo; struct radeon_bo *db_bo;
u64 db_bo_mc;
}; };
static inline int r600_bpe_from_format(u32 *bpe, u32 format) static inline int r600_bpe_from_format(u32 *bpe, u32 format)
...@@ -140,6 +142,68 @@ static inline int r600_bpe_from_format(u32 *bpe, u32 format) ...@@ -140,6 +142,68 @@ static inline int r600_bpe_from_format(u32 *bpe, u32 format)
return 0; return 0;
} }
struct array_mode_checker {
int array_mode;
u32 group_size;
u32 nbanks;
u32 npipes;
u32 nsamples;
u32 bpe;
};
/* returns alignment in pixels for pitch/height/depth and bytes for base */
static inline int r600_get_array_mode_alignment(struct array_mode_checker *values,
u32 *pitch_align,
u32 *height_align,
u32 *depth_align,
u64 *base_align)
{
u32 tile_width = 8;
u32 tile_height = 8;
u32 macro_tile_width = values->nbanks;
u32 macro_tile_height = values->npipes;
u32 tile_bytes = tile_width * tile_height * values->bpe * values->nsamples;
u32 macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes;
switch (values->array_mode) {
case ARRAY_LINEAR_GENERAL:
/* technically tile_width/_height for pitch/height */
*pitch_align = 1; /* tile_width */
*height_align = 1; /* tile_height */
*depth_align = 1;
*base_align = 1;
break;
case ARRAY_LINEAR_ALIGNED:
*pitch_align = max((u32)64, (u32)(values->group_size / values->bpe));
*height_align = tile_height;
*depth_align = 1;
*base_align = values->group_size;
break;
case ARRAY_1D_TILED_THIN1:
*pitch_align = max((u32)tile_width,
(u32)(values->group_size /
(tile_height * values->bpe * values->nsamples)));
*height_align = tile_height;
*depth_align = 1;
*base_align = values->group_size;
break;
case ARRAY_2D_TILED_THIN1:
*pitch_align = max((u32)macro_tile_width,
(u32)(((values->group_size / tile_height) /
(values->bpe * values->nsamples)) *
values->nbanks)) * tile_width;
*height_align = macro_tile_height * tile_height;
*depth_align = 1;
*base_align = max(macro_tile_bytes,
(*pitch_align) * values->bpe * (*height_align) * values->nsamples);
break;
default:
return -EINVAL;
}
return 0;
}
static void r600_cs_track_init(struct r600_cs_track *track) static void r600_cs_track_init(struct r600_cs_track *track)
{ {
int i; int i;
...@@ -153,10 +217,12 @@ static void r600_cs_track_init(struct r600_cs_track *track) ...@@ -153,10 +217,12 @@ static void r600_cs_track_init(struct r600_cs_track *track)
track->cb_color_info[i] = 0; track->cb_color_info[i] = 0;
track->cb_color_bo[i] = NULL; track->cb_color_bo[i] = NULL;
track->cb_color_bo_offset[i] = 0xFFFFFFFF; track->cb_color_bo_offset[i] = 0xFFFFFFFF;
track->cb_color_bo_mc[i] = 0xFFFFFFFF;
} }
track->cb_target_mask = 0xFFFFFFFF; track->cb_target_mask = 0xFFFFFFFF;
track->cb_shader_mask = 0xFFFFFFFF; track->cb_shader_mask = 0xFFFFFFFF;
track->db_bo = NULL; track->db_bo = NULL;
track->db_bo_mc = 0xFFFFFFFF;
/* assume the biggest format and that htile is enabled */ /* assume the biggest format and that htile is enabled */
track->db_depth_info = 7 | (1 << 25); track->db_depth_info = 7 | (1 << 25);
track->db_depth_view = 0xFFFFC000; track->db_depth_view = 0xFFFFC000;
...@@ -168,7 +234,10 @@ static void r600_cs_track_init(struct r600_cs_track *track) ...@@ -168,7 +234,10 @@ static void r600_cs_track_init(struct r600_cs_track *track)
static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) 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, slice_tile_max, size, tmp;
u32 height, height_align, pitch, pitch_align, depth_align;
u64 base_offset, base_align;
struct array_mode_checker array_check;
volatile u32 *ib = p->ib->ptr; volatile u32 *ib = p->ib->ptr;
unsigned array_mode; unsigned array_mode;
...@@ -183,60 +252,40 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) ...@@ -183,60 +252,40 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
i, track->cb_color_info[i]); i, track->cb_color_info[i]);
return -EINVAL; return -EINVAL;
} }
/* pitch is the number of 8x8 tiles per row */ /* pitch in pixels */
pitch = G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1; pitch = (G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1) * 8;
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;
slice_tile_max *= 64; slice_tile_max *= 64;
height = slice_tile_max / (pitch * 8); height = slice_tile_max / pitch;
if (height > 8192) if (height > 8192)
height = 8192; height = 8192;
array_mode = G_0280A0_ARRAY_MODE(track->cb_color_info[i]); array_mode = G_0280A0_ARRAY_MODE(track->cb_color_info[i]);
base_offset = track->cb_color_bo_mc[i] + track->cb_color_bo_offset[i];
array_check.array_mode = array_mode;
array_check.group_size = track->group_size;
array_check.nbanks = track->nbanks;
array_check.npipes = track->npipes;
array_check.nsamples = track->nsamples;
array_check.bpe = bpe;
if (r600_get_array_mode_alignment(&array_check,
&pitch_align, &height_align, &depth_align, &base_align)) {
dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
G_0280A0_ARRAY_MODE(track->cb_color_info[i]), i,
track->cb_color_info[i]);
return -EINVAL;
}
switch (array_mode) { switch (array_mode) {
case V_0280A0_ARRAY_LINEAR_GENERAL: case V_0280A0_ARRAY_LINEAR_GENERAL:
/* technically height & 0x7 */
break; break;
case V_0280A0_ARRAY_LINEAR_ALIGNED: case V_0280A0_ARRAY_LINEAR_ALIGNED:
pitch_align = max((u32)64, (u32)(track->group_size / bpe)) / 8;
if (!IS_ALIGNED(pitch, pitch_align)) {
dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
__func__, __LINE__, pitch);
return -EINVAL;
}
if (!IS_ALIGNED(height, 8)) {
dev_warn(p->dev, "%s:%d cb height (%d) invalid\n",
__func__, __LINE__, height);
return -EINVAL;
}
break; break;
case V_0280A0_ARRAY_1D_TILED_THIN1: case V_0280A0_ARRAY_1D_TILED_THIN1:
pitch_align = max((u32)8, (u32)(track->group_size / (8 * bpe * track->nsamples))) / 8;
if (!IS_ALIGNED(pitch, pitch_align)) {
dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
__func__, __LINE__, pitch);
return -EINVAL;
}
/* avoid breaking userspace */ /* avoid breaking userspace */
if (height > 7) if (height > 7)
height &= ~0x7; height &= ~0x7;
if (!IS_ALIGNED(height, 8)) {
dev_warn(p->dev, "%s:%d cb height (%d) invalid\n",
__func__, __LINE__, height);
return -EINVAL;
}
break; break;
case V_0280A0_ARRAY_2D_TILED_THIN1: case V_0280A0_ARRAY_2D_TILED_THIN1:
pitch_align = max((u32)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);
return -EINVAL;
}
if (!IS_ALIGNED((height / 8), track->npipes)) {
dev_warn(p->dev, "%s:%d cb height (%d) invalid\n",
__func__, __LINE__, height);
return -EINVAL;
}
break; break;
default: default:
dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__, dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
...@@ -244,8 +293,24 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) ...@@ -244,8 +293,24 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
track->cb_color_info[i]); track->cb_color_info[i]);
return -EINVAL; return -EINVAL;
} }
if (!IS_ALIGNED(pitch, pitch_align)) {
dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
__func__, __LINE__, pitch);
return -EINVAL;
}
if (!IS_ALIGNED(height, height_align)) {
dev_warn(p->dev, "%s:%d cb height (%d) invalid\n",
__func__, __LINE__, height);
return -EINVAL;
}
if (!IS_ALIGNED(base_offset, base_align)) {
dev_warn(p->dev, "%s offset[%d] 0x%llx not aligned\n", __func__, i, base_offset);
return -EINVAL;
}
/* check offset */ /* check offset */
tmp = height * pitch * 8 * bpe; tmp = height * pitch * 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])) {
if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) { if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) {
/* the initial DDX does bad things with the CB size occasionally */ /* the initial DDX does bad things with the CB size occasionally */
...@@ -260,15 +325,11 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) ...@@ -260,15 +325,11 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
return -EINVAL; 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]);
return -EINVAL;
}
/* limit max tile */ /* limit max tile */
tmp = (height * pitch * 8) >> 6; tmp = (height * pitch) >> 6;
if (tmp < slice_tile_max) if (tmp < slice_tile_max)
slice_tile_max = tmp; slice_tile_max = tmp;
tmp = S_028060_PITCH_TILE_MAX(pitch - 1) | tmp = S_028060_PITCH_TILE_MAX((pitch / 8) - 1) |
S_028060_SLICE_TILE_MAX(slice_tile_max - 1); S_028060_SLICE_TILE_MAX(slice_tile_max - 1);
ib[track->cb_color_size_idx[i]] = tmp; ib[track->cb_color_size_idx[i]] = tmp;
return 0; return 0;
...@@ -310,7 +371,12 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) ...@@ -310,7 +371,12 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
/* Check depth buffer */ /* Check depth buffer */
if (G_028800_STENCIL_ENABLE(track->db_depth_control) || if (G_028800_STENCIL_ENABLE(track->db_depth_control) ||
G_028800_Z_ENABLE(track->db_depth_control)) { G_028800_Z_ENABLE(track->db_depth_control)) {
u32 nviews, bpe, ntiles, pitch, pitch_align, height, size, slice_tile_max; u32 nviews, bpe, ntiles, size, slice_tile_max;
u32 height, height_align, pitch, pitch_align, depth_align;
u64 base_offset, base_align;
struct array_mode_checker array_check;
int array_mode;
if (track->db_bo == NULL) { if (track->db_bo == NULL) {
dev_warn(p->dev, "z/stencil with no depth buffer\n"); dev_warn(p->dev, "z/stencil with no depth buffer\n");
return -EINVAL; return -EINVAL;
...@@ -353,41 +419,34 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) ...@@ -353,41 +419,34 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF); ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF);
} else { } else {
size = radeon_bo_size(track->db_bo); size = radeon_bo_size(track->db_bo);
pitch = G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1; /* pitch in pixels */
pitch = (G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1) * 8;
slice_tile_max = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1; slice_tile_max = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
slice_tile_max *= 64; slice_tile_max *= 64;
height = slice_tile_max / (pitch * 8); height = slice_tile_max / pitch;
if (height > 8192) if (height > 8192)
height = 8192; height = 8192;
switch (G_028010_ARRAY_MODE(track->db_depth_info)) { base_offset = track->db_bo_mc + track->db_offset;
array_mode = G_028010_ARRAY_MODE(track->db_depth_info);
array_check.array_mode = array_mode;
array_check.group_size = track->group_size;
array_check.nbanks = track->nbanks;
array_check.npipes = track->npipes;
array_check.nsamples = track->nsamples;
array_check.bpe = bpe;
if (r600_get_array_mode_alignment(&array_check,
&pitch_align, &height_align, &depth_align, &base_align)) {
dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
G_028010_ARRAY_MODE(track->db_depth_info),
track->db_depth_info);
return -EINVAL;
}
switch (array_mode) {
case V_028010_ARRAY_1D_TILED_THIN1: case V_028010_ARRAY_1D_TILED_THIN1:
pitch_align = (max((u32)8, (u32)(track->group_size / (8 * bpe))) / 8);
if (!IS_ALIGNED(pitch, pitch_align)) {
dev_warn(p->dev, "%s:%d db pitch (%d) invalid\n",
__func__, __LINE__, pitch);
return -EINVAL;
}
/* don't break userspace */ /* don't break userspace */
height &= ~0x7; height &= ~0x7;
if (!IS_ALIGNED(height, 8)) {
dev_warn(p->dev, "%s:%d db height (%d) invalid\n",
__func__, __LINE__, height);
return -EINVAL;
}
break; break;
case V_028010_ARRAY_2D_TILED_THIN1: case V_028010_ARRAY_2D_TILED_THIN1:
pitch_align = max((u32)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);
return -EINVAL;
}
if (!IS_ALIGNED((height / 8), track->npipes)) {
dev_warn(p->dev, "%s:%d db height (%d) invalid\n",
__func__, __LINE__, height);
return -EINVAL;
}
break; break;
default: default:
dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__, dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
...@@ -395,15 +454,27 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) ...@@ -395,15 +454,27 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
track->db_depth_info); track->db_depth_info);
return -EINVAL; return -EINVAL;
} }
if (!IS_ALIGNED(track->db_offset, track->group_size)) {
dev_warn(p->dev, "%s offset[%d] %d not aligned\n", __func__, i, track->db_offset); if (!IS_ALIGNED(pitch, pitch_align)) {
dev_warn(p->dev, "%s:%d db pitch (%d) invalid\n",
__func__, __LINE__, pitch);
return -EINVAL;
}
if (!IS_ALIGNED(height, height_align)) {
dev_warn(p->dev, "%s:%d db height (%d) invalid\n",
__func__, __LINE__, height);
return -EINVAL; return -EINVAL;
} }
if (!IS_ALIGNED(base_offset, base_align)) {
dev_warn(p->dev, "%s offset[%d] 0x%llx not aligned\n", __func__, i, base_offset);
return -EINVAL;
}
ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1; ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1; nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1;
tmp = ntiles * bpe * 64 * nviews; tmp = ntiles * bpe * 64 * nviews;
if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) { if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {
dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %d -> %d have %ld)\n", dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %d -> %u have %lu)\n",
track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset, track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
radeon_bo_size(track->db_bo)); radeon_bo_size(track->db_bo));
return -EINVAL; return -EINVAL;
...@@ -954,6 +1025,7 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx ...@@ -954,6 +1025,7 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
track->cb_color_base_last[tmp] = ib[idx]; track->cb_color_base_last[tmp] = ib[idx];
track->cb_color_bo[tmp] = reloc->robj; track->cb_color_bo[tmp] = reloc->robj;
track->cb_color_bo_mc[tmp] = reloc->lobj.gpu_offset;
break; break;
case DB_DEPTH_BASE: case DB_DEPTH_BASE:
r = r600_cs_packet_next_reloc(p, &reloc); r = r600_cs_packet_next_reloc(p, &reloc);
...@@ -965,6 +1037,7 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx ...@@ -965,6 +1037,7 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
track->db_offset = radeon_get_ib_value(p, idx) << 8; track->db_offset = radeon_get_ib_value(p, idx) << 8;
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
track->db_bo = reloc->robj; track->db_bo = reloc->robj;
track->db_bo_mc = reloc->lobj.gpu_offset;
break; break;
case DB_HTILE_DATA_BASE: case DB_HTILE_DATA_BASE:
case SQ_PGM_START_FS: case SQ_PGM_START_FS:
...@@ -1086,16 +1159,25 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels ...@@ -1086,16 +1159,25 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels
static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx,
struct radeon_bo *texture, struct radeon_bo *texture,
struct radeon_bo *mipmap, struct radeon_bo *mipmap,
u64 base_offset,
u64 mip_offset,
u32 tiling_flags) u32 tiling_flags)
{ {
struct r600_cs_track *track = p->track; struct r600_cs_track *track = p->track;
u32 nfaces, nlevels, blevel, w0, h0, d0, bpe = 0; u32 nfaces, nlevels, blevel, w0, h0, d0, bpe = 0;
u32 word0, word1, l0_size, mipmap_size, pitch, pitch_align; u32 word0, word1, l0_size, mipmap_size;
u32 height_align, pitch, pitch_align, depth_align;
u64 base_align;
struct array_mode_checker array_check;
/* on legacy kernel we don't perform advanced check */ /* on legacy kernel we don't perform advanced check */
if (p->rdev == NULL) if (p->rdev == NULL)
return 0; return 0;
/* convert to bytes */
base_offset <<= 8;
mip_offset <<= 8;
word0 = radeon_get_ib_value(p, idx + 0); word0 = radeon_get_ib_value(p, idx + 0);
if (tiling_flags & RADEON_TILING_MACRO) if (tiling_flags & RADEON_TILING_MACRO)
word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
...@@ -1128,46 +1210,38 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i ...@@ -1128,46 +1210,38 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i
return -EINVAL; return -EINVAL;
} }
pitch = G_038000_PITCH(word0) + 1; /* pitch in texels */
switch (G_038000_TILE_MODE(word0)) { pitch = (G_038000_PITCH(word0) + 1) * 8;
case V_038000_ARRAY_LINEAR_GENERAL: array_check.array_mode = G_038000_TILE_MODE(word0);
pitch_align = 1; array_check.group_size = track->group_size;
/* XXX check height align */ array_check.nbanks = track->nbanks;
break; array_check.npipes = track->npipes;
case V_038000_ARRAY_LINEAR_ALIGNED: array_check.nsamples = 1;
pitch_align = max((u32)64, (u32)(track->group_size / bpe)) / 8; array_check.bpe = bpe;
if (!IS_ALIGNED(pitch, pitch_align)) { if (r600_get_array_mode_alignment(&array_check,
dev_warn(p->dev, "%s:%d tex pitch (%d) invalid\n", &pitch_align, &height_align, &depth_align, &base_align)) {
__func__, __LINE__, pitch); dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n",
return -EINVAL; __func__, __LINE__, G_038000_TILE_MODE(word0));
} return -EINVAL;
/* XXX check height align */ }
break;
case V_038000_ARRAY_1D_TILED_THIN1: /* XXX check height as well... */
pitch_align = max((u32)8, (u32)(track->group_size / (8 * bpe))) / 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);
return -EINVAL; return -EINVAL;
} }
/* XXX check height align */ if (!IS_ALIGNED(base_offset, base_align)) {
break; dev_warn(p->dev, "%s:%d tex base offset (0x%llx) invalid\n",
case V_038000_ARRAY_2D_TILED_THIN1: __func__, __LINE__, base_offset);
pitch_align = max((u32)track->nbanks, return -EINVAL;
(u32)(((track->group_size / 8) / bpe) * track->nbanks)) / 8; }
if (!IS_ALIGNED(pitch, pitch_align)) { if (!IS_ALIGNED(mip_offset, base_align)) {
dev_warn(p->dev, "%s:%d tex pitch (%d) invalid\n", dev_warn(p->dev, "%s:%d tex mip offset (0x%llx) invalid\n",
__func__, __LINE__, pitch); __func__, __LINE__, mip_offset);
return -EINVAL;
}
/* XXX check height align */
break;
default:
dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
G_038000_TILE_MODE(word0), word0);
return -EINVAL; return -EINVAL;
} }
/* XXX check offset align */
word0 = radeon_get_ib_value(p, idx + 4); word0 = radeon_get_ib_value(p, idx + 4);
word1 = radeon_get_ib_value(p, idx + 5); word1 = radeon_get_ib_value(p, idx + 5);
...@@ -1402,7 +1476,10 @@ static int r600_packet3_check(struct radeon_cs_parser *p, ...@@ -1402,7 +1476,10 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
mip_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); mip_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
mipmap = reloc->robj; mipmap = reloc->robj;
r = r600_check_texture_resource(p, idx+(i*7)+1, r = r600_check_texture_resource(p, idx+(i*7)+1,
texture, mipmap, reloc->lobj.tiling_flags); texture, mipmap,
base_offset + radeon_get_ib_value(p, idx+1+(i*7)+2),
mip_offset + radeon_get_ib_value(p, idx+1+(i*7)+3),
reloc->lobj.tiling_flags);
if (r) if (r)
return r; return r;
ib[idx+1+(i*7)+2] += base_offset; ib[idx+1+(i*7)+2] += base_offset;
......
...@@ -51,6 +51,12 @@ ...@@ -51,6 +51,12 @@
#define PTE_READABLE (1 << 5) #define PTE_READABLE (1 << 5)
#define PTE_WRITEABLE (1 << 6) #define PTE_WRITEABLE (1 << 6)
/* tiling bits */
#define ARRAY_LINEAR_GENERAL 0x00000000
#define ARRAY_LINEAR_ALIGNED 0x00000001
#define ARRAY_1D_TILED_THIN1 0x00000002
#define ARRAY_2D_TILED_THIN1 0x00000004
/* Registers */ /* Registers */
#define ARB_POP 0x2418 #define ARB_POP 0x2418
#define ENABLE_TC128 (1 << 30) #define ENABLE_TC128 (1 << 30)
......
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