Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
[cascardo/linux.git] / drivers / gpu / drm / radeon / evergreen_cs.c
index 101acd6..573ed1b 100644 (file)
@@ -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)
 {
@@ -1080,6 +1090,27 @@ static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
        return 0;
 }
 
+/**
+ * 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;