]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/iommu/intel-iommu.c
pinctrl: baytrail: Allocate IRQ chip dynamic
[linux.git] / drivers / iommu / intel-iommu.c
index 6db6d969e31c6adcc5202fa0ea97eabf347b7b63..0c8d81f56a306800ca0d065716e632f48ad3eec3 100644 (file)
@@ -2420,14 +2420,24 @@ static void domain_remove_dev_info(struct dmar_domain *domain)
        spin_unlock_irqrestore(&device_domain_lock, flags);
 }
 
-/*
- * find_domain
- * Note: we use struct device->archdata.iommu stores the info
- */
 static struct dmar_domain *find_domain(struct device *dev)
 {
        struct device_domain_info *info;
 
+       if (unlikely(dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO ||
+                    dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO))
+               return NULL;
+
+       /* No lock here, assumes no domain exit in normal case */
+       info = dev->archdata.iommu;
+       if (likely(info))
+               return info->domain;
+
+       return NULL;
+}
+
+static struct dmar_domain *deferred_attach_domain(struct device *dev)
+{
        if (unlikely(dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO)) {
                struct iommu_domain *domain;
 
@@ -2437,12 +2447,7 @@ static struct dmar_domain *find_domain(struct device *dev)
                        intel_iommu_attach_device(domain, dev);
        }
 
-       /* No lock here, assumes no domain exit in normal case */
-       info = dev->archdata.iommu;
-
-       if (likely(info))
-               return info->domain;
-       return NULL;
+       return find_domain(dev);
 }
 
 static inline struct device_domain_info *
@@ -3512,7 +3517,7 @@ static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,
 
        BUG_ON(dir == DMA_NONE);
 
-       domain = find_domain(dev);
+       domain = deferred_attach_domain(dev);
        if (!domain)
                return DMA_MAPPING_ERROR;
 
@@ -3732,7 +3737,7 @@ static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nele
        if (!iommu_need_mapping(dev))
                return dma_direct_map_sg(dev, sglist, nelems, dir, attrs);
 
-       domain = find_domain(dev);
+       domain = deferred_attach_domain(dev);
        if (!domain)
                return 0;
 
@@ -3827,7 +3832,7 @@ bounce_map_single(struct device *dev, phys_addr_t paddr, size_t size,
        int prot = 0;
        int ret;
 
-       domain = find_domain(dev);
+       domain = deferred_attach_domain(dev);
        if (WARN_ON(dir == DMA_NONE || !domain))
                return DMA_MAPPING_ERROR;
 
@@ -4314,13 +4319,19 @@ int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg)
 {
        struct acpi_dmar_reserved_memory *rmrr;
        struct dmar_rmrr_unit *rmrru;
+       int ret;
+
+       rmrr = (struct acpi_dmar_reserved_memory *)header;
+       ret = arch_rmrr_sanity_check(rmrr);
+       if (ret)
+               return ret;
 
        rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
        if (!rmrru)
                goto out;
 
        rmrru->hdr = header;
-       rmrr = (struct acpi_dmar_reserved_memory *)header;
+
        rmrru->base_address = rmrr->base_address;
        rmrru->end_address = rmrr->end_address;
 
@@ -4759,6 +4770,26 @@ static void intel_disable_iommus(void)
                iommu_disable_translation(iommu);
 }
 
+void intel_iommu_shutdown(void)
+{
+       struct dmar_drhd_unit *drhd;
+       struct intel_iommu *iommu = NULL;
+
+       if (no_iommu || dmar_disabled)
+               return;
+
+       down_write(&dmar_global_lock);
+
+       /* Disable PMRs explicitly here. */
+       for_each_iommu(iommu, drhd)
+               iommu_disable_protect_mem_regions(iommu);
+
+       /* Make sure the IOMMUs are switched off */
+       intel_disable_iommus();
+
+       up_write(&dmar_global_lock);
+}
+
 static inline struct intel_iommu *dev_to_intel_iommu(struct device *dev)
 {
        struct iommu_device *iommu_dev = dev_to_iommu_device(dev);
@@ -5440,7 +5471,7 @@ static void intel_iommu_aux_detach_device(struct iommu_domain *domain,
 
 static int intel_iommu_map(struct iommu_domain *domain,
                           unsigned long iova, phys_addr_t hpa,
-                          size_t size, int iommu_prot)
+                          size_t size, int iommu_prot, gfp_t gfp)
 {
        struct dmar_domain *dmar_domain = to_dmar_domain(domain);
        u64 max_addr;