]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge git://git.infradead.org/iommu-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 22 May 2010 00:25:01 +0000 (17:25 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 22 May 2010 00:25:01 +0000 (17:25 -0700)
* git://git.infradead.org/iommu-2.6:
  intel-iommu: Set a more specific taint flag for invalid BIOS DMAR tables
  intel-iommu: Combine the BIOS DMAR table warning messages
  panic: Add taint flag TAINT_FIRMWARE_WORKAROUND ('I')
  panic: Allow warnings to set different taint flags
  intel-iommu: intel_iommu_map_range failed at very end of address space
  intel-iommu: errors with smaller iommu widths
  intel-iommu: Fix boot inside 64bit virtualbox with io-apic disabled
  intel-iommu: use physfn to search drhd for VF
  intel-iommu: Print out iommu seq_id
  intel-iommu: Don't complain that ACPI_DMAR_SCOPE_TYPE_IOAPIC is not supported
  intel-iommu: Avoid global flushes with caching mode.
  intel-iommu: Use correct domain ID when caching mode is enabled
  intel-iommu mistakenly uses offset_pfn when caching mode is enabled
  intel-iommu: use for_each_set_bit()
  intel-iommu: Fix section mismatch dmar_ir_support() uses dmar_tbl.

1  2 
drivers/pci/dmar.c
drivers/pci/intel-iommu.c
drivers/pci/intr_remapping.c
include/linux/kernel.h

diff --combined drivers/pci/dmar.c
index 33ead97f0c4b24e2e030ae913bef26cdf435d533,f4c51709d132db8fbd0316a257d1d603e3af0277..0a19708074c2b5265379ec816e777771823ab861
@@@ -35,7 -35,6 +35,7 @@@
  #include <linux/interrupt.h>
  #include <linux/tboot.h>
  #include <linux/dmi.h>
 +#include <linux/slab.h>
  
  #define PREFIX "DMAR: "
  
@@@ -131,9 -130,10 +131,10 @@@ static int __init dmar_parse_dev_scope(
                if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT ||
                    scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE)
                        (*cnt)++;
-               else
+               else if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC) {
                        printk(KERN_WARNING PREFIX
-                               "Unsupported device scope\n");
+                              "Unsupported device scope\n");
+               }
                start += scope->length;
        }
        if (*cnt == 0)
@@@ -309,6 -309,8 +310,8 @@@ int dmar_find_matched_atsr_unit(struct 
        struct acpi_dmar_atsr *atsr;
        struct dmar_atsr_unit *atsru;
  
+       dev = pci_physfn(dev);
        list_for_each_entry(atsru, &dmar_atsr_units, list) {
                atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
                if (atsr->segment == pci_domain_nr(dev->bus))
@@@ -358,12 -360,14 +361,14 @@@ dmar_parse_one_rhsa(struct acpi_dmar_he
                        return 0;
                }
        }
-       WARN(1, "Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n"
-            "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
-            drhd->reg_base_addr,
-            dmi_get_system_info(DMI_BIOS_VENDOR),
-            dmi_get_system_info(DMI_BIOS_VERSION),
-            dmi_get_system_info(DMI_PRODUCT_VERSION));
+       WARN_TAINT(
+               1, TAINT_FIRMWARE_WORKAROUND,
+               "Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n"
+               "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+               drhd->reg_base_addr,
+               dmi_get_system_info(DMI_BIOS_VENDOR),
+               dmi_get_system_info(DMI_BIOS_VERSION),
+               dmi_get_system_info(DMI_PRODUCT_VERSION));
  
        return 0;
  }
@@@ -507,7 -511,7 +512,7 @@@ parse_dmar_table(void
        return ret;
  }
  
- int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
static int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
                          struct pci_dev *dev)
  {
        int index;
@@@ -530,6 -534,8 +535,8 @@@ dmar_find_matched_drhd_unit(struct pci_
        struct dmar_drhd_unit *dmaru = NULL;
        struct acpi_dmar_hardware_unit *drhd;
  
+       dev = pci_physfn(dev);
        list_for_each_entry(dmaru, &dmar_drhd_units, list) {
                drhd = container_of(dmaru->hdr,
                                    struct acpi_dmar_hardware_unit,
@@@ -614,7 -620,17 +621,17 @@@ int __init dmar_table_init(void
        return 0;
  }
  
- static int bios_warned;
+ static void warn_invalid_dmar(u64 addr, const char *message)
+ {
+       WARN_TAINT_ONCE(
+               1, TAINT_FIRMWARE_WORKAROUND,
+               "Your BIOS is broken; DMAR reported at address %llx%s!\n"
+               "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+               addr, message,
+               dmi_get_system_info(DMI_BIOS_VENDOR),
+               dmi_get_system_info(DMI_BIOS_VERSION),
+               dmi_get_system_info(DMI_PRODUCT_VERSION));
+ }
  
  int __init check_zero_address(void)
  {
  
                        drhd = (void *)entry_header;
                        if (!drhd->address) {
-                               /* Promote an attitude of violence to a BIOS engineer today */
-                               WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n"
-                                    "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
-                                    dmi_get_system_info(DMI_BIOS_VENDOR),
-                                    dmi_get_system_info(DMI_BIOS_VERSION),
-                                    dmi_get_system_info(DMI_PRODUCT_VERSION));
-                               bios_warned = 1;
+                               warn_invalid_dmar(0, "");
                                goto failed;
                        }
  
                        ecap = dmar_readq(addr + DMAR_ECAP_REG);
                        early_iounmap(addr, VTD_PAGE_SIZE);
                        if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) {
-                               /* Promote an attitude of violence to a BIOS engineer today */
-                               WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n"
-                                    "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
-                                     drhd->address,
-                                     dmi_get_system_info(DMI_BIOS_VENDOR),
-                                     dmi_get_system_info(DMI_BIOS_VERSION),
-                                     dmi_get_system_info(DMI_PRODUCT_VERSION));
-                               bios_warned = 1;
+                               warn_invalid_dmar(drhd->address,
+                                                 " returns all ones");
                                goto failed;
                        }
                }
@@@ -731,14 -735,7 +736,7 @@@ int alloc_iommu(struct dmar_drhd_unit *
        int msagaw = 0;
  
        if (!drhd->reg_base_addr) {
-               if (!bios_warned) {
-                       WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n"
-                            "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
-                            dmi_get_system_info(DMI_BIOS_VENDOR),
-                            dmi_get_system_info(DMI_BIOS_VERSION),
-                            dmi_get_system_info(DMI_PRODUCT_VERSION));
-                       bios_warned = 1;
-               }
+               warn_invalid_dmar(0, "");
                return -EINVAL;
        }
  
        iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
  
        if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) {
-               if (!bios_warned) {
-                       /* Promote an attitude of violence to a BIOS engineer today */
-                       WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n"
-                            "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
-                            drhd->reg_base_addr,
-                            dmi_get_system_info(DMI_BIOS_VENDOR),
-                            dmi_get_system_info(DMI_BIOS_VERSION),
-                            dmi_get_system_info(DMI_PRODUCT_VERSION));
-                       bios_warned = 1;
-               }
+               warn_invalid_dmar(drhd->reg_base_addr, " returns all ones");
                goto err_unmap;
        }
  
        }
  
        ver = readl(iommu->reg + DMAR_VER_REG);
-       pr_info("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n",
+       pr_info("IOMMU %d: reg_base_addr %llx ver %d:%d cap %llx ecap %llx\n",
+               iommu->seq_id,
                (unsigned long long)drhd->reg_base_addr,
                DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
                (unsigned long long)iommu->cap,
@@@ -1457,9 -1446,11 +1447,11 @@@ int dmar_reenable_qi(struct intel_iomm
  /*
   * Check interrupt remapping support in DMAR table description.
   */
- int dmar_ir_support(void)
+ int __init dmar_ir_support(void)
  {
        struct acpi_table_dmar *dmar;
        dmar = (struct acpi_table_dmar *)dmar_tbl;
+       if (!dmar)
+               return 0;
        return dmar->flags & 0x1;
  }
index 371dc564e2e46c744ac48dc9fd08c361dee0c34b,65741dc491d68270aceaa90ea965a18cfb619572..796828fce34cb5b918a485de903d3af18971ed38
@@@ -491,13 -491,11 +491,11 @@@ static void domain_update_iommu_coheren
  
        domain->iommu_coherency = 1;
  
-       i = find_first_bit(&domain->iommu_bmp, g_num_of_iommus);
-       for (; i < g_num_of_iommus; ) {
+       for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) {
                if (!ecap_coherent(g_iommus[i]->ecap)) {
                        domain->iommu_coherency = 0;
                        break;
                }
-               i = find_next_bit(&domain->iommu_bmp, g_num_of_iommus, i+1);
        }
  }
  
@@@ -507,13 -505,11 +505,11 @@@ static void domain_update_iommu_snoopin
  
        domain->iommu_snooping = 1;
  
-       i = find_first_bit(&domain->iommu_bmp, g_num_of_iommus);
-       for (; i < g_num_of_iommus; ) {
+       for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) {
                if (!ecap_sc_support(g_iommus[i]->ecap)) {
                        domain->iommu_snooping = 0;
                        break;
                }
-               i = find_next_bit(&domain->iommu_bmp, g_num_of_iommus, i+1);
        }
  }
  
@@@ -1068,7 -1064,7 +1064,7 @@@ static void iommu_flush_dev_iotlb(struc
  }
  
  static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
-                                 unsigned long pfn, unsigned int pages)
+                                 unsigned long pfn, unsigned int pages, int map)
  {
        unsigned int mask = ilog2(__roundup_pow_of_two(pages));
        uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
                                                DMA_TLB_PSI_FLUSH);
  
        /*
-        * In caching mode, domain ID 0 is reserved for non-present to present
-        * mapping flush. Device IOTLB doesn't need to be flushed in this case.
+        * In caching mode, changes of pages from non-present to present require
+        * flush. However, device IOTLB doesn't need to be flushed in this case.
         */
-       if (!cap_caching_mode(iommu->cap) || did)
+       if (!cap_caching_mode(iommu->cap) || !map)
                iommu_flush_dev_iotlb(iommu->domains[did], addr, mask);
  }
  
@@@ -1154,7 -1150,8 +1150,8 @@@ static int iommu_init_domains(struct in
        unsigned long nlongs;
  
        ndomains = cap_ndoms(iommu->cap);
-       pr_debug("Number of Domains supportd <%ld>\n", ndomains);
+       pr_debug("IOMMU %d: Number of Domains supportd <%ld>\n", iommu->seq_id,
+                       ndomains);
        nlongs = BITS_TO_LONGS(ndomains);
  
        spin_lock_init(&iommu->lock);
@@@ -1194,8 -1191,7 +1191,7 @@@ void free_dmar_iommu(struct intel_iomm
        unsigned long flags;
  
        if ((iommu->domains) && (iommu->domain_ids)) {
-               i = find_first_bit(iommu->domain_ids, cap_ndoms(iommu->cap));
-               for (; i < cap_ndoms(iommu->cap); ) {
+               for_each_set_bit(i, iommu->domain_ids, cap_ndoms(iommu->cap)) {
                        domain = iommu->domains[i];
                        clear_bit(i, iommu->domain_ids);
  
                                        domain_exit(domain);
                        }
                        spin_unlock_irqrestore(&domain->iommu_lock, flags);
-                       i = find_next_bit(iommu->domain_ids,
-                               cap_ndoms(iommu->cap), i+1);
                }
        }
  
@@@ -1292,14 -1285,11 +1285,11 @@@ static void iommu_detach_domain(struct 
  
        spin_lock_irqsave(&iommu->lock, flags);
        ndomains = cap_ndoms(iommu->cap);
-       num = find_first_bit(iommu->domain_ids, ndomains);
-       for (; num < ndomains; ) {
+       for_each_set_bit(num, iommu->domain_ids, ndomains) {
                if (iommu->domains[num] == domain) {
                        found = 1;
                        break;
                }
-               num = find_next_bit(iommu->domain_ids,
-                                   cap_ndoms(iommu->cap), num+1);
        }
  
        if (found) {
@@@ -1485,15 -1475,12 +1475,12 @@@ static int domain_context_mapping_one(s
  
                /* find an available domain id for this device in iommu */
                ndomains = cap_ndoms(iommu->cap);
-               num = find_first_bit(iommu->domain_ids, ndomains);
-               for (; num < ndomains; ) {
+               for_each_set_bit(num, iommu->domain_ids, ndomains) {
                        if (iommu->domains[num] == domain) {
                                id = num;
                                found = 1;
                                break;
                        }
-                       num = find_next_bit(iommu->domain_ids,
-                                           cap_ndoms(iommu->cap), num+1);
                }
  
                if (found == 0) {
                                           (((u16)bus) << 8) | devfn,
                                           DMA_CCMD_MASK_NOBIT,
                                           DMA_CCMD_DEVICE_INVL);
-               iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_DSI_FLUSH);
+               iommu->flush.flush_iotlb(iommu, domain->id, 0, 0, DMA_TLB_DSI_FLUSH);
        } else {
                iommu_flush_write_buffer(iommu);
        }
@@@ -2333,14 -2320,16 +2320,16 @@@ int __init init_dmars(void
                         */
                        iommu->flush.flush_context = __iommu_flush_context;
                        iommu->flush.flush_iotlb = __iommu_flush_iotlb;
-                       printk(KERN_INFO "IOMMU 0x%Lx: using Register based "
+                       printk(KERN_INFO "IOMMU %d 0x%Lx: using Register based "
                               "invalidation\n",
+                               iommu->seq_id,
                               (unsigned long long)drhd->reg_base_addr);
                } else {
                        iommu->flush.flush_context = qi_flush_context;
                        iommu->flush.flush_iotlb = qi_flush_iotlb;
-                       printk(KERN_INFO "IOMMU 0x%Lx: using Queued "
+                       printk(KERN_INFO "IOMMU %d 0x%Lx: using Queued "
                               "invalidation\n",
+                               iommu->seq_id,
                               (unsigned long long)drhd->reg_base_addr);
                }
        }
@@@ -2621,7 -2610,7 +2610,7 @@@ static dma_addr_t __intel_map_single(st
  
        /* it's a non-present to present mapping. Only flush if caching mode */
        if (cap_caching_mode(iommu->cap))
-               iommu_flush_iotlb_psi(iommu, 0, mm_to_dma_pfn(iova->pfn_lo), size);
+               iommu_flush_iotlb_psi(iommu, domain->id, mm_to_dma_pfn(iova->pfn_lo), size, 1);
        else
                iommu_flush_write_buffer(iommu);
  
@@@ -2661,15 -2650,24 +2650,24 @@@ static void flush_unmaps(void
                if (!deferred_flush[i].next)
                        continue;
  
-               iommu->flush.flush_iotlb(iommu, 0, 0, 0,
+               /* In caching mode, global flushes turn emulation expensive */
+               if (!cap_caching_mode(iommu->cap))
+                       iommu->flush.flush_iotlb(iommu, 0, 0, 0,
                                         DMA_TLB_GLOBAL_FLUSH);
                for (j = 0; j < deferred_flush[i].next; j++) {
                        unsigned long mask;
                        struct iova *iova = deferred_flush[i].iova[j];
-                       mask = ilog2(mm_to_dma_pfn(iova->pfn_hi - iova->pfn_lo + 1));
-                       iommu_flush_dev_iotlb(deferred_flush[i].domain[j],
-                                       (uint64_t)iova->pfn_lo << PAGE_SHIFT, mask);
+                       struct dmar_domain *domain = deferred_flush[i].domain[j];
+                       /* On real hardware multiple invalidations are expensive */
+                       if (cap_caching_mode(iommu->cap))
+                               iommu_flush_iotlb_psi(iommu, domain->id,
+                               iova->pfn_lo, iova->pfn_hi - iova->pfn_lo + 1, 0);
+                       else {
+                               mask = ilog2(mm_to_dma_pfn(iova->pfn_hi - iova->pfn_lo + 1));
+                               iommu_flush_dev_iotlb(deferred_flush[i].domain[j],
+                                               (uint64_t)iova->pfn_lo << PAGE_SHIFT, mask);
+                       }
                        __free_iova(&deferred_flush[i].domain[j]->iovad, iova);
                }
                deferred_flush[i].next = 0;
@@@ -2750,7 -2748,7 +2748,7 @@@ static void intel_unmap_page(struct dev
  
        if (intel_iommu_strict) {
                iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
-                                     last_pfn - start_pfn + 1);
+                                     last_pfn - start_pfn + 1, 0);
                /* free iova */
                __free_iova(&domain->iovad, iova);
        } else {
@@@ -2840,7 -2838,7 +2838,7 @@@ static void intel_unmap_sg(struct devic
  
        if (intel_iommu_strict) {
                iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
-                                     last_pfn - start_pfn + 1);
+                                     last_pfn - start_pfn + 1, 0);
                /* free iova */
                __free_iova(&domain->iovad, iova);
        } else {
@@@ -2874,7 -2872,6 +2872,6 @@@ static int intel_map_sg(struct device *
        struct dmar_domain *domain;
        size_t size = 0;
        int prot = 0;
-       size_t offset_pfn = 0;
        struct iova *iova = NULL;
        int ret;
        struct scatterlist *sg;
  
        /* it's a non-present to present mapping. Only flush if caching mode */
        if (cap_caching_mode(iommu->cap))
-               iommu_flush_iotlb_psi(iommu, 0, start_vpfn, offset_pfn);
+               iommu_flush_iotlb_psi(iommu, domain->id, start_vpfn, size, 1);
        else
                iommu_flush_write_buffer(iommu);
  
@@@ -3436,22 -3433,6 +3433,6 @@@ static void vm_domain_remove_all_dev_in
  /* domain id for virtual machine, it won't be set in context */
  static unsigned long vm_domid;
  
- static int vm_domain_min_agaw(struct dmar_domain *domain)
- {
-       int i;
-       int min_agaw = domain->agaw;
-       i = find_first_bit(&domain->iommu_bmp, g_num_of_iommus);
-       for (; i < g_num_of_iommus; ) {
-               if (min_agaw > g_iommus[i]->agaw)
-                       min_agaw = g_iommus[i]->agaw;
-               i = find_next_bit(&domain->iommu_bmp, g_num_of_iommus, i+1);
-       }
-       return min_agaw;
- }
  static struct dmar_domain *iommu_alloc_vm_domain(void)
  {
        struct dmar_domain *domain;
@@@ -3512,8 -3493,7 +3493,7 @@@ static void iommu_free_vm_domain(struc
                iommu = drhd->iommu;
  
                ndomains = cap_ndoms(iommu->cap);
-               i = find_first_bit(iommu->domain_ids, ndomains);
-               for (; i < ndomains; ) {
+               for_each_set_bit(i, iommu->domain_ids, ndomains) {
                        if (iommu->domains[i] == domain) {
                                spin_lock_irqsave(&iommu->lock, flags);
                                clear_bit(i, iommu->domain_ids);
                                spin_unlock_irqrestore(&iommu->lock, flags);
                                break;
                        }
-                       i = find_next_bit(iommu->domain_ids, ndomains, i+1);
                }
        }
  }
@@@ -3582,7 -3561,6 +3561,6 @@@ static int intel_iommu_attach_device(st
        struct pci_dev *pdev = to_pci_dev(dev);
        struct intel_iommu *iommu;
        int addr_width;
-       u64 end;
  
        /* normally pdev is not mapped */
        if (unlikely(domain_context_mapped(pdev))) {
  
        /* check if this iommu agaw is sufficient for max mapped address */
        addr_width = agaw_to_width(iommu->agaw);
-       end = DOMAIN_MAX_ADDR(addr_width);
-       end = end & VTD_PAGE_MASK;
-       if (end < dmar_domain->max_addr) {
-               printk(KERN_ERR "%s: iommu agaw (%d) is not "
+       if (addr_width > cap_mgaw(iommu->cap))
+               addr_width = cap_mgaw(iommu->cap);
+       if (dmar_domain->max_addr > (1LL << addr_width)) {
+               printk(KERN_ERR "%s: iommu width (%d) is not "
                       "sufficient for the mapped address (%llx)\n",
-                      __func__, iommu->agaw, dmar_domain->max_addr);
+                      __func__, addr_width, dmar_domain->max_addr);
                return -EFAULT;
        }
+       dmar_domain->gaw = addr_width;
+       /*
+        * Knock out extra levels of page tables if necessary
+        */
+       while (iommu->agaw < dmar_domain->agaw) {
+               struct dma_pte *pte;
+               pte = dmar_domain->pgd;
+               if (dma_pte_present(pte)) {
+                       free_pgtable_page(dmar_domain->pgd);
+                       dmar_domain->pgd = (struct dma_pte *)dma_pte_addr(pte);
+               }
+               dmar_domain->agaw--;
+       }
  
        return domain_add_dev_info(dmar_domain, pdev, CONTEXT_TT_MULTI_LEVEL);
  }
@@@ -3626,15 -3620,13 +3620,14 @@@ static void intel_iommu_detach_device(s
        domain_remove_one_dev_info(dmar_domain, pdev);
  }
  
 -static int intel_iommu_map_range(struct iommu_domain *domain,
 -                               unsigned long iova, phys_addr_t hpa,
 -                               size_t size, int iommu_prot)
 +static int intel_iommu_map(struct iommu_domain *domain,
 +                         unsigned long iova, phys_addr_t hpa,
 +                         int gfp_order, int iommu_prot)
  {
        struct dmar_domain *dmar_domain = domain->priv;
        u64 max_addr;
-       int addr_width;
        int prot = 0;
 +      size_t size;
        int ret;
  
        if (iommu_prot & IOMMU_READ)
        if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
                prot |= DMA_PTE_SNP;
  
 +      size     = PAGE_SIZE << gfp_order;
        max_addr = iova + size;
        if (dmar_domain->max_addr < max_addr) {
-               int min_agaw;
                u64 end;
  
                /* check if minimum agaw is sufficient for mapped address */
-               min_agaw = vm_domain_min_agaw(dmar_domain);
-               addr_width = agaw_to_width(min_agaw);
-               end = DOMAIN_MAX_ADDR(addr_width);
-               end = end & VTD_PAGE_MASK;
+               end = __DOMAIN_MAX_ADDR(dmar_domain->gaw) + 1;
                if (end < max_addr) {
-                       printk(KERN_ERR "%s: iommu agaw (%d) is not "
+                       printk(KERN_ERR "%s: iommu width (%d) is not "
                               "sufficient for the mapped address (%llx)\n",
-                              __func__, min_agaw, max_addr);
+                              __func__, dmar_domain->gaw, max_addr);
                        return -EFAULT;
                }
                dmar_domain->max_addr = max_addr;
        return ret;
  }
  
 -static void intel_iommu_unmap_range(struct iommu_domain *domain,
 -                                  unsigned long iova, size_t size)
 +static int intel_iommu_unmap(struct iommu_domain *domain,
 +                           unsigned long iova, int gfp_order)
  {
        struct dmar_domain *dmar_domain = domain->priv;
 -
 -      if (!size)
 -              return;
 +      size_t size = PAGE_SIZE << gfp_order;
  
        dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT,
                            (iova + size - 1) >> VTD_PAGE_SHIFT);
  
        if (dmar_domain->max_addr == iova + size)
                dmar_domain->max_addr = iova;
 +
 +      return gfp_order;
  }
  
  static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
@@@ -3716,8 -3703,8 +3705,8 @@@ static struct iommu_ops intel_iommu_op
        .domain_destroy = intel_iommu_domain_destroy,
        .attach_dev     = intel_iommu_attach_device,
        .detach_dev     = intel_iommu_detach_device,
 -      .map            = intel_iommu_map_range,
 -      .unmap          = intel_iommu_unmap_range,
 +      .map            = intel_iommu_map,
 +      .unmap          = intel_iommu_unmap,
        .iova_to_phys   = intel_iommu_iova_to_phys,
        .domain_has_cap = intel_iommu_domain_has_cap,
  };
index 6ee98a56946fff4a887b80f39c281ac495eb479b,c13802a7e109d2709d4d46712f99d60b1438ea62..1315ac688aa267d9aa504f4d2874b9aa930b4bc8
@@@ -1,7 -1,6 +1,7 @@@
  #include <linux/interrupt.h>
  #include <linux/dmar.h>
  #include <linux/spinlock.h>
 +#include <linux/slab.h>
  #include <linux/jiffies.h>
  #include <linux/hpet.h>
  #include <linux/pci.h>
@@@ -832,9 -831,9 +832,9 @@@ static int ir_parse_ioapic_hpet_scope(s
                                return -1;
                        }
  
-                       printk(KERN_INFO "IOAPIC id %d under DRHD base"
-                              " 0x%Lx\n", scope->enumeration_id,
-                              drhd->address);
+                       printk(KERN_INFO "IOAPIC id %d under DRHD base "
+                              " 0x%Lx IOMMU %d\n", scope->enumeration_id,
+                              drhd->address, iommu->seq_id);
  
                        ir_parse_one_ioapic_scope(scope, iommu);
                } else if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_HPET) {
diff --combined include/linux/kernel.h
index fc33af9118520e6a04376fbe96b9d7a85d9e478d,7f2f7b34dd08ee566a3d46de9e84b2a1e84f1ab5..cc5e3ffe9fcea9fe0ebfcdda855cf00754e53b45
@@@ -4,8 -4,6 +4,8 @@@
  /*
   * 'kernel.h' contains some often-used function prototypes etc
   */
 +#define __ALIGN_KERNEL(x, a)          __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
 +#define __ALIGN_KERNEL_MASK(x, mask)  (((x) + (mask)) & ~(mask))
  
  #ifdef __KERNEL__
  
@@@ -39,8 -37,8 +39,8 @@@ extern const char linux_proc_banner[]
  
  #define STACK_MAGIC   0xdeadbeef
  
 -#define ALIGN(x,a)            __ALIGN_MASK(x,(typeof(x))(a)-1)
 -#define __ALIGN_MASK(x,mask)  (((x)+(mask))&~(mask))
 +#define ALIGN(x, a)           __ALIGN_KERNEL((x), (a))
 +#define __ALIGN_MASK(x, mask) __ALIGN_KERNEL_MASK((x), (mask))
  #define PTR_ALIGN(p, a)               ((typeof(p))ALIGN((unsigned long)(p), (a)))
  #define IS_ALIGNED(x, a)              (((x) & ((typeof(x))(a) - 1)) == 0)
  
@@@ -346,6 -344,7 +346,7 @@@ extern enum system_states 
  #define TAINT_OVERRIDDEN_ACPI_TABLE   8
  #define TAINT_WARN                    9
  #define TAINT_CRAP                    10
+ #define TAINT_FIRMWARE_WORKAROUND     11
  
  extern void dump_stack(void) __cold;
  
@@@ -428,7 -427,7 +429,7 @@@ static inline char *pack_hex_byte(char 
                .burst = DEFAULT_RATELIMIT_BURST,       \
        };                                              \
                                                        \
 -      if (!__ratelimit(&_rs))                         \
 +      if (__ratelimit(&_rs))                          \
                printk(fmt, ##__VA_ARGS__);             \
  })
  #else
@@@ -492,13 -491,6 +493,13 @@@ static inline void tracing_off(void) { 
  static inline void tracing_off_permanent(void) { }
  static inline int tracing_is_on(void) { return 0; }
  #endif
 +
 +enum ftrace_dump_mode {
 +      DUMP_NONE,
 +      DUMP_ALL,
 +      DUMP_ORIG,
 +};
 +
  #ifdef CONFIG_TRACING
  extern void tracing_start(void);
  extern void tracing_stop(void);
@@@ -580,7 -572,7 +581,7 @@@ __ftrace_vbprintk(unsigned long ip, con
  extern int
  __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap);
  
 -extern void ftrace_dump(void);
 +extern void ftrace_dump(enum ftrace_dump_mode oops_dump_mode);
  #else
  static inline void
  ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3) { }
@@@ -601,7 -593,7 +602,7 @@@ ftrace_vprintk(const char *fmt, va_lis
  {
        return 0;
  }
 -static inline void ftrace_dump(void) { }
 +static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
  #endif /* CONFIG_TRACING */
  
  /*