]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/arm64/mm/dma-mapping.c
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[karo-tx-linux.git] / arch / arm64 / mm / dma-mapping.c
index a6e757cbab7785ed411e919b95c6d13caaf21726..c566ec83719f6bb07fe909f02900a8ab885698de 100644 (file)
@@ -562,8 +562,8 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
                struct page **pages;
                pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, coherent);
 
-               pages = iommu_dma_alloc(dev, iosize, gfp, ioprot, handle,
-                                       flush_page);
+               pages = iommu_dma_alloc(dev, iosize, gfp, attrs, ioprot,
+                                       handle, flush_page);
                if (!pages)
                        return NULL;
 
@@ -804,57 +804,24 @@ struct iommu_dma_notifier_data {
 static LIST_HEAD(iommu_dma_masters);
 static DEFINE_MUTEX(iommu_dma_notifier_lock);
 
-/*
- * Temporarily "borrow" a domain feature flag to to tell if we had to resort
- * to creating our own domain here, in case we need to clean it up again.
- */
-#define __IOMMU_DOMAIN_FAKE_DEFAULT            (1U << 31)
-
 static bool do_iommu_attach(struct device *dev, const struct iommu_ops *ops,
                           u64 dma_base, u64 size)
 {
        struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
 
        /*
-        * Best case: The device is either part of a group which was
-        * already attached to a domain in a previous call, or it's
-        * been put in a default DMA domain by the IOMMU core.
+        * If the IOMMU driver has the DMA domain support that we require,
+        * then the IOMMU core will have already configured a group for this
+        * device, and allocated the default domain for that group.
         */
-       if (!domain) {
-               /*
-                * Urgh. The IOMMU core isn't going to do default domains
-                * for non-PCI devices anyway, until it has some means of
-                * abstracting the entirely implementation-specific
-                * sideband data/SoC topology/unicorn dust that may or
-                * may not differentiate upstream masters.
-                * So until then, HORRIBLE HACKS!
-                */
-               domain = ops->domain_alloc(IOMMU_DOMAIN_DMA);
-               if (!domain)
-                       goto out_no_domain;
-
-               domain->ops = ops;
-               domain->type = IOMMU_DOMAIN_DMA | __IOMMU_DOMAIN_FAKE_DEFAULT;
-
-               if (iommu_attach_device(domain, dev))
-                       goto out_put_domain;
+       if (!domain || iommu_dma_init_domain(domain, dma_base, size)) {
+               pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n",
+                       dev_name(dev));
+               return false;
        }
 
-       if (iommu_dma_init_domain(domain, dma_base, size))
-               goto out_detach;
-
        dev->archdata.dma_ops = &iommu_dma_ops;
        return true;
-
-out_detach:
-       iommu_detach_device(domain, dev);
-out_put_domain:
-       if (domain->type & __IOMMU_DOMAIN_FAKE_DEFAULT)
-               iommu_domain_free(domain);
-out_no_domain:
-       pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n",
-               dev_name(dev));
-       return false;
 }
 
 static void queue_iommu_attach(struct device *dev, const struct iommu_ops *ops,
@@ -933,6 +900,10 @@ static int __init __iommu_dma_init(void)
                ret = register_iommu_dma_ops_notifier(&platform_bus_type);
        if (!ret)
                ret = register_iommu_dma_ops_notifier(&amba_bustype);
+#ifdef CONFIG_PCI
+       if (!ret)
+               ret = register_iommu_dma_ops_notifier(&pci_bus_type);
+#endif
 
        /* handle devices queued before this arch_initcall */
        if (!ret)
@@ -967,11 +938,8 @@ void arch_teardown_dma_ops(struct device *dev)
 {
        struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
 
-       if (domain) {
+       if (WARN_ON(domain))
                iommu_detach_device(domain, dev);
-               if (domain->type & __IOMMU_DOMAIN_FAKE_DEFAULT)
-                       iommu_domain_free(domain);
-       }
 
        dev->archdata.dma_ops = NULL;
 }
@@ -979,13 +947,13 @@ void arch_teardown_dma_ops(struct device *dev)
 #else
 
 static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
-                                 struct iommu_ops *iommu)
+                                 const struct iommu_ops *iommu)
 { }
 
 #endif  /* CONFIG_IOMMU_DMA */
 
 void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
-                       struct iommu_ops *iommu, bool coherent)
+                       const struct iommu_ops *iommu, bool coherent)
 {
        if (!dev->archdata.dma_ops)
                dev->archdata.dma_ops = &swiotlb_dma_ops;