release_mem_region(iommu->mmio_phys, iommu->mmio_phys_end);
 }
 
+static inline u32 get_ivhd_header_size(struct ivhd_header *h)
+{
+       u32 size = 0;
+
+       switch (h->type) {
+       case 0x10:
+               size = 24;
+               break;
+       case 0x11:
+       case 0x40:
+               size = 40;
+               break;
+       }
+       return size;
+}
+
 /****************************************************************************
  *
  * The functions below belong to the first pass of AMD IOMMU ACPI table
        u8 *p = (void *)h, *end = (void *)h;
        struct ivhd_entry *dev;
 
-       p += sizeof(*h);
+       u32 ivhd_size = get_ivhd_header_size(h);
+
+       if (!ivhd_size) {
+               pr_err("AMD-Vi: Unsupported IVHD type %#x\n", h->type);
+               return -EINVAL;
+       }
+
+       p += ivhd_size;
        end += h->length;
 
        while (p < end) {
        u32 dev_i, ext_flags = 0;
        bool alias = false;
        struct ivhd_entry *e;
+       u32 ivhd_size;
        int ret;
 
 
        /*
         * Done. Now parse the device entries
         */
-       p += sizeof(struct ivhd_header);
+       ivhd_size = get_ivhd_header_size(h);
+       if (!ivhd_size) {
+               pr_err("AMD-Vi: Unsupported IVHD type %#x\n", h->type);
+               return -EINVAL;
+       }
+
+       p += ivhd_size;
+
        end += h->length;