]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/iommu/intel-iommu.c
Merge branches 'iommu/page-sizes' and 'iommu/group-id' into next
[karo-tx-linux.git] / drivers / iommu / intel-iommu.c
index 9ef16d664a993702b5671c2af79319296d581a6d..77e3b917c8da8a6767e47fae9bf9532394c1190d 100644 (file)
 #define LEVEL_STRIDE           (9)
 #define LEVEL_MASK             (((u64)1 << LEVEL_STRIDE) - 1)
 
+/*
+ * This bitmap is used to advertise the page sizes our hardware support
+ * to the IOMMU core, which will then use this information to split
+ * physically contiguous memory regions it is mapping into page sizes
+ * that we support.
+ *
+ * Traditionally the IOMMU core just handed us the mappings directly,
+ * after making sure the size is an order of a 4KiB page and that the
+ * mapping has natural alignment.
+ *
+ * To retain this behavior, we currently advertise that we support
+ * all page sizes that are an order of 4KiB.
+ *
+ * If at some point we'd like to utilize the IOMMU core's new behavior,
+ * we could change this to advertise the real page sizes we support.
+ */
+#define INTEL_IOMMU_PGSIZES    (~0xFFFUL)
+
 static inline int agaw_to_level(int agaw)
 {
        return agaw + 2;
@@ -405,6 +423,9 @@ int dmar_disabled = 0;
 int dmar_disabled = 1;
 #endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/
 
+int intel_iommu_enabled = 0;
+EXPORT_SYMBOL_GPL(intel_iommu_enabled);
+
 static int dmar_map_gfx = 1;
 static int dmar_forcedac;
 static int intel_iommu_strict;
@@ -3524,7 +3545,7 @@ found:
        return 0;
 }
 
-int dmar_parse_rmrr_atsr_dev(void)
+int __init dmar_parse_rmrr_atsr_dev(void)
 {
        struct dmar_rmrr_unit *rmrr, *rmrr_n;
        struct dmar_atsr_unit *atsr, *atsr_n;
@@ -3647,6 +3668,8 @@ int __init intel_iommu_init(void)
 
        bus_register_notifier(&pci_bus_type, &device_nb);
 
+       intel_iommu_enabled = 1;
+
        return 0;
 }
 
@@ -3979,12 +4002,11 @@ static void intel_iommu_detach_device(struct iommu_domain *domain,
 
 static int intel_iommu_map(struct iommu_domain *domain,
                           unsigned long iova, phys_addr_t hpa,
-                          int gfp_order, int iommu_prot)
+                          size_t size, int iommu_prot)
 {
        struct dmar_domain *dmar_domain = domain->priv;
        u64 max_addr;
        int prot = 0;
-       size_t size;
        int ret;
 
        if (iommu_prot & IOMMU_READ)
@@ -3994,7 +4016,6 @@ static int intel_iommu_map(struct iommu_domain *domain,
        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) {
                u64 end;
@@ -4017,11 +4038,10 @@ static int intel_iommu_map(struct iommu_domain *domain,
        return ret;
 }
 
-static int intel_iommu_unmap(struct iommu_domain *domain,
-                            unsigned long iova, int gfp_order)
+static size_t intel_iommu_unmap(struct iommu_domain *domain,
+                            unsigned long iova, size_t size)
 {
        struct dmar_domain *dmar_domain = domain->priv;
-       size_t size = PAGE_SIZE << gfp_order;
        int order;
 
        order = dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT,
@@ -4030,7 +4050,7 @@ static int intel_iommu_unmap(struct iommu_domain *domain,
        if (dmar_domain->max_addr == iova + size)
                dmar_domain->max_addr = iova;
 
-       return order;
+       return PAGE_SIZE << order;
 }
 
 static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
@@ -4118,6 +4138,7 @@ static struct iommu_ops intel_iommu_ops = {
        .iova_to_phys   = intel_iommu_iova_to_phys,
        .domain_has_cap = intel_iommu_domain_has_cap,
        .device_group   = intel_iommu_device_group,
+       .pgsize_bitmap  = INTEL_IOMMU_PGSIZES,
 };
 
 static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)