diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/evergreen_cs.c')
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen_cs.c | 61 |
1 files changed, 53 insertions, 8 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 101acd618f67..573ed1bc6cf7 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -846,6 +846,16 @@ static int evergreen_cs_track_validate_texture(struct radeon_cs_parser *p, return -EINVAL; } + if (!mipmap) { + if (llevel) { + dev_warn(p->dev, "%s:%i got NULL MIP_ADDRESS relocation\n", + __func__, __LINE__); + return -EINVAL; + } else { + return 0; /* everything's ok */ + } + } + /* check mipmap size */ for (i = 1; i <= llevel; i++) { unsigned w, h, d; @@ -995,7 +1005,7 @@ static int evergreen_cs_track_check(struct radeon_cs_parser *p) * Assume that chunk_ib_index is properly set. Will return -EINVAL * if packet is bigger than remaining ib size. or if packets is unknown. **/ -int evergreen_cs_packet_parse(struct radeon_cs_parser *p, +static int evergreen_cs_packet_parse(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt, unsigned idx) { @@ -1081,6 +1091,27 @@ static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p, } /** + * evergreen_cs_packet_next_is_pkt3_nop() - test if the next packet is NOP + * @p: structure holding the parser context. + * + * Check if the next packet is a relocation packet3. + **/ +static bool evergreen_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p) +{ + struct radeon_cs_packet p3reloc; + int r; + + r = evergreen_cs_packet_parse(p, &p3reloc, p->idx); + if (r) { + return false; + } + if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { + return false; + } + return true; +} + +/** * evergreen_cs_packet_next_vline() - parse userspace VLINE packet * @parser: parser structure holding parsing context. * @@ -2330,7 +2361,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, for (i = 0; i < (pkt->count / 8); i++) { struct radeon_bo *texture, *mipmap; u32 toffset, moffset; - u32 size, offset; + u32 size, offset, mip_address, tex_dim; switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) { case SQ_TEX_VTX_VALID_TEXTURE: @@ -2359,14 +2390,28 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, } texture = reloc->robj; toffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + /* tex mip base */ - r = evergreen_cs_packet_next_reloc(p, &reloc); - if (r) { - DRM_ERROR("bad SET_RESOURCE (tex)\n"); - return -EINVAL; + tex_dim = ib[idx+1+(i*8)+0] & 0x7; + mip_address = ib[idx+1+(i*8)+3]; + + if ((tex_dim == SQ_TEX_DIM_2D_MSAA || tex_dim == SQ_TEX_DIM_2D_ARRAY_MSAA) && + !mip_address && + !evergreen_cs_packet_next_is_pkt3_nop(p)) { + /* MIP_ADDRESS should point to FMASK for an MSAA texture. + * It should be 0 if FMASK is disabled. */ + moffset = 0; + mipmap = NULL; + } else { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad SET_RESOURCE (tex)\n"); + return -EINVAL; + } + moffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + mipmap = reloc->robj; } - moffset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); - mipmap = reloc->robj; + r = evergreen_cs_track_validate_texture(p, texture, mipmap, idx+1+(i*8)); if (r) return r; |