]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge tag 'iommu-fixes-v4.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 10 Jun 2017 05:30:55 +0000 (22:30 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 10 Jun 2017 05:30:55 +0000 (22:30 -0700)
Pull IOMMU fixes from Joerg Roedel:

 - another compile-fix for my header cleanup

 - a couple of fixes for the recently merged IOMMU probe deferal code

 - fixes for ACPI/IORT code necessary with IOMMU probe deferal

* tag 'iommu-fixes-v4.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
  arm: dma-mapping: Reset the device's dma_ops
  ACPI/IORT: Move the check to get iommu_ops from translated fwspec
  ARM: dma-mapping: Don't tear down third-party mappings
  ACPI/IORT: Ignore all errors except EPROBE_DEFER
  iommu/of: Ignore all errors except EPROBE_DEFER
  iommu/of: Fix check for returning EPROBE_DEFER
  iommu/dma: Fix function declaration

arch/arm/include/asm/device.h
arch/arm/mm/dma-mapping.c
drivers/acpi/arm64/iort.c
drivers/acpi/scan.c
drivers/iommu/of_iommu.c
drivers/of/device.c
include/linux/dma-iommu.h

index 36ec9c8f6e161d59d56caafbbe92fe0d2239d3f9..3234fe9bba6e76196d8a852db8c26d078150d989 100644 (file)
@@ -19,7 +19,8 @@ struct dev_archdata {
 #ifdef CONFIG_XEN
        const struct dma_map_ops *dev_dma_ops;
 #endif
-       bool dma_coherent;
+       unsigned int dma_coherent:1;
+       unsigned int dma_ops_setup:1;
 };
 
 struct omap_device;
index c742dfd2967bcae6057c3ea59b81979fcf60aa55..bd83c531828a7349eecf233b5c213a65388e9567 100644 (file)
@@ -2311,7 +2311,14 @@ int arm_iommu_attach_device(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(arm_iommu_attach_device);
 
-static void __arm_iommu_detach_device(struct device *dev)
+/**
+ * arm_iommu_detach_device
+ * @dev: valid struct device pointer
+ *
+ * Detaches the provided device from a previously attached map.
+ * This voids the dma operations (dma_map_ops pointer)
+ */
+void arm_iommu_detach_device(struct device *dev)
 {
        struct dma_iommu_mapping *mapping;
 
@@ -2324,22 +2331,10 @@ static void __arm_iommu_detach_device(struct device *dev)
        iommu_detach_device(mapping->domain, dev);
        kref_put(&mapping->kref, release_iommu_mapping);
        to_dma_iommu_mapping(dev) = NULL;
+       set_dma_ops(dev, NULL);
 
        pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev));
 }
-
-/**
- * arm_iommu_detach_device
- * @dev: valid struct device pointer
- *
- * Detaches the provided device from a previously attached map.
- * This voids the dma operations (dma_map_ops pointer)
- */
-void arm_iommu_detach_device(struct device *dev)
-{
-       __arm_iommu_detach_device(dev);
-       set_dma_ops(dev, NULL);
-}
 EXPORT_SYMBOL_GPL(arm_iommu_detach_device);
 
 static const struct dma_map_ops *arm_get_iommu_dma_map_ops(bool coherent)
@@ -2379,7 +2374,7 @@ static void arm_teardown_iommu_dma_ops(struct device *dev)
        if (!mapping)
                return;
 
-       __arm_iommu_detach_device(dev);
+       arm_iommu_detach_device(dev);
        arm_iommu_release_mapping(mapping);
 }
 
@@ -2430,9 +2425,13 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
                dev->dma_ops = xen_dma_ops;
        }
 #endif
+       dev->archdata.dma_ops_setup = true;
 }
 
 void arch_teardown_dma_ops(struct device *dev)
 {
+       if (!dev->archdata.dma_ops_setup)
+               return;
+
        arm_teardown_iommu_dma_ops(dev);
 }
index c5fecf97ee2f52bd11188a0cd2295bd82d5d02db..797b28dc7b3410cda1e775e55d2e1d2362254dd9 100644 (file)
@@ -666,14 +666,6 @@ static const struct iommu_ops *iort_iommu_xlate(struct device *dev,
        int ret = -ENODEV;
        struct fwnode_handle *iort_fwnode;
 
-       /*
-        * If we already translated the fwspec there
-        * is nothing left to do, return the iommu_ops.
-        */
-       ops = iort_fwspec_iommu_ops(dev->iommu_fwspec);
-       if (ops)
-               return ops;
-
        if (node) {
                iort_fwnode = iort_get_fwnode(node);
                if (!iort_fwnode)
@@ -735,6 +727,14 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev)
        u32 streamid = 0;
        int err;
 
+       /*
+        * If we already translated the fwspec there
+        * is nothing left to do, return the iommu_ops.
+        */
+       ops = iort_fwspec_iommu_ops(dev->iommu_fwspec);
+       if (ops)
+               return ops;
+
        if (dev_is_pci(dev)) {
                struct pci_bus *bus = to_pci_dev(dev)->bus;
                u32 rid;
@@ -782,6 +782,12 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev)
        if (err)
                ops = ERR_PTR(err);
 
+       /* Ignore all other errors apart from EPROBE_DEFER */
+       if (IS_ERR(ops) && (PTR_ERR(ops) != -EPROBE_DEFER)) {
+               dev_dbg(dev, "Adding to IOMMU failed: %ld\n", PTR_ERR(ops));
+               ops = NULL;
+       }
+
        return ops;
 }
 
index e39ec7b7cb674fbad3cab60f4e5139d7e06a1f09..3a10d7573477e7dea0139c5f885e9514a1886a7a 100644 (file)
@@ -1371,8 +1371,8 @@ int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
        iort_set_dma_mask(dev);
 
        iommu = iort_iommu_configure(dev);
-       if (IS_ERR(iommu))
-               return PTR_ERR(iommu);
+       if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
+               return -EPROBE_DEFER;
 
        size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
        /*
index 9f44ee8ea1bc8a10a6ff4c0dad297b78b8c2f57a..19779b88a47973eef332b88b05d1ac76193f788d 100644 (file)
@@ -118,6 +118,7 @@ static const struct iommu_ops
 
        ops = iommu_ops_from_fwnode(fwnode);
        if ((ops && !ops->of_xlate) ||
+           !of_device_is_available(iommu_spec->np) ||
            (!ops && !of_iommu_driver_present(iommu_spec->np)))
                return NULL;
 
@@ -236,6 +237,12 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
                        ops = ERR_PTR(err);
        }
 
+       /* Ignore all other errors apart from EPROBE_DEFER */
+       if (IS_ERR(ops) && (PTR_ERR(ops) != -EPROBE_DEFER)) {
+               dev_dbg(dev, "Adding to IOMMU failed: %ld\n", PTR_ERR(ops));
+               ops = NULL;
+       }
+
        return ops;
 }
 
index 9416d052cb89474e811d8c4e8ca5ca3a81732fbb..28c38c756f92858906ca2aee54a9c922522f9253 100644 (file)
@@ -144,8 +144,8 @@ int of_dma_configure(struct device *dev, struct device_node *np)
                coherent ? " " : " not ");
 
        iommu = of_iommu_configure(dev, np);
-       if (IS_ERR(iommu))
-               return PTR_ERR(iommu);
+       if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
+               return -EPROBE_DEFER;
 
        dev_dbg(dev, "device is%sbehind an iommu\n",
                iommu ? " " : " not ");
index 4eac2670bfa1a016679971f36ad698fe1d9f6a4e..92f20832fd28770c16ab9d34c5560efce2a888c6 100644 (file)
@@ -78,6 +78,7 @@ void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list);
 
 struct iommu_domain;
 struct msi_msg;
+struct device;
 
 static inline int iommu_dma_init(void)
 {