]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
iommu/dma: Centralise iommu_setup_dma_ops()
authorRobin Murphy <robin.murphy@arm.com>
Fri, 19 Apr 2024 16:54:45 +0000 (17:54 +0100)
committerJoerg Roedel <jroedel@suse.de>
Fri, 26 Apr 2024 10:07:26 +0000 (12:07 +0200)
It's somewhat hard to see, but arm64's arch_setup_dma_ops() should only
ever call iommu_setup_dma_ops() after a successful iommu_probe_device(),
which means there should be no harm in achieving the same order of
operations by running it off the back of iommu_probe_device() itself.
This then puts it in line with the x86 and s390 .probe_finalize bodges,
letting us pull it all into the main flow properly. As a bonus this lets
us fold in and de-scope the PCI workaround setup as well.

At this point we can also then pull the call up inside the group mutex,
and avoid having to think about whether iommu_group_store_type() could
theoretically race and free the domain if iommu_setup_dma_ops() ran just
*before* iommu_device_use_default_domain() claims it... Furthermore we
replace one .probe_finalize call completely, since the only remaining
implementations are now one which only needs to run once for the initial
boot-time probe, and two which themselves render that path unreachable.

This leaves us a big step closer to realistically being able to unpick
the variety of different things that iommu_setup_dma_ops() has been
muddling together, and further streamline iommu-dma into core API flows
in future.

Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com> # For Intel IOMMU
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Tested-by: Hanjun Guo <guohanjun@huawei.com>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Link: https://lore.kernel.org/r/bebea331c1d688b34d9862eefd5ede47503961b8.1713523152.git.robin.murphy@arm.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
arch/arm64/mm/dma-mapping.c
drivers/iommu/amd/iommu.c
drivers/iommu/dma-iommu.c
drivers/iommu/dma-iommu.h
drivers/iommu/intel/iommu.c
drivers/iommu/iommu.c
drivers/iommu/s390-iommu.c
drivers/iommu/virtio-iommu.c
include/linux/iommu.h

index 61886e43e3a10fe8c84ce6febffc5d65703a2cce..313d8938a2f03a2fa5e0eef9e0765ceaf2347dea 100644 (file)
@@ -58,8 +58,6 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
                   ARCH_DMA_MINALIGN, cls);
 
        dev->dma_coherent = coherent;
-       if (device_iommu_mapped(dev))
-               iommu_setup_dma_ops(dev, dma_base, dma_base + size - 1);
 
        xen_setup_dma_ops(dev);
 }
index d35c1b8c8e65ce5a9c6f6ae3aae555d91eb4d3d0..085abf098fa9a20e0e6ba3b4cd3fad9886422d32 100644 (file)
@@ -2175,13 +2175,6 @@ static struct iommu_device *amd_iommu_probe_device(struct device *dev)
        return iommu_dev;
 }
 
-static void amd_iommu_probe_finalize(struct device *dev)
-{
-       /* Domains are initialized for this device - have a look what we ended up with */
-       set_dma_ops(dev, NULL);
-       iommu_setup_dma_ops(dev, 0, U64_MAX);
-}
-
 static void amd_iommu_release_device(struct device *dev)
 {
        struct amd_iommu *iommu;
@@ -2784,7 +2777,6 @@ const struct iommu_ops amd_iommu_ops = {
        .domain_alloc_user = amd_iommu_domain_alloc_user,
        .probe_device = amd_iommu_probe_device,
        .release_device = amd_iommu_release_device,
-       .probe_finalize = amd_iommu_probe_finalize,
        .device_group = amd_iommu_device_group,
        .get_resv_regions = amd_iommu_get_resv_regions,
        .is_attach_deferred = amd_iommu_is_attach_deferred,
index c827ed690f1fbd7401ec15a4aed92d00c7ec4c15..bc1490bd4f7a9ec7941b596d61ee979b28e21357 100644 (file)
@@ -1741,25 +1741,20 @@ static const struct dma_map_ops iommu_dma_ops = {
        .max_mapping_size       = iommu_dma_max_mapping_size,
 };
 
-/*
- * The IOMMU core code allocates the default DMA domain, which the underlying
- * IOMMU driver needs to support via the dma-iommu layer.
- */
-void iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 dma_limit)
+void iommu_setup_dma_ops(struct device *dev)
 {
        struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
 
-       if (!domain)
-               goto out_err;
+       if (dev_is_pci(dev))
+               dev->iommu->pci_32bit_workaround = !iommu_dma_forcedac;
 
-       /*
-        * The IOMMU core code allocates the default DMA domain, which the
-        * underlying IOMMU driver needs to support via the dma-iommu layer.
-        */
        if (iommu_is_dma_domain(domain)) {
                if (iommu_dma_init_domain(domain, dev))
                        goto out_err;
                dev->dma_ops = &iommu_dma_ops;
+       } else if (dev->dma_ops == &iommu_dma_ops) {
+               /* Clean up if we've switched *from* a DMA domain */
+               dev->dma_ops = NULL;
        }
 
        return;
@@ -1767,7 +1762,6 @@ out_err:
         pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n",
                 dev_name(dev));
 }
-EXPORT_SYMBOL_GPL(iommu_setup_dma_ops);
 
 static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
                phys_addr_t msi_addr, struct iommu_domain *domain)
index c829f1f82a991c63d8901f65f25c73c2af2f1bb2..c12d63457c76466d20afa325b34193f68a435f4b 100644 (file)
@@ -9,6 +9,8 @@
 
 #ifdef CONFIG_IOMMU_DMA
 
+void iommu_setup_dma_ops(struct device *dev);
+
 int iommu_get_dma_cookie(struct iommu_domain *domain);
 void iommu_put_dma_cookie(struct iommu_domain *domain);
 
@@ -17,13 +19,13 @@ int iommu_dma_init_fq(struct iommu_domain *domain);
 void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list);
 
 extern bool iommu_dma_forcedac;
-static inline void iommu_dma_set_pci_32bit_workaround(struct device *dev)
-{
-       dev->iommu->pci_32bit_workaround = !iommu_dma_forcedac;
-}
 
 #else /* CONFIG_IOMMU_DMA */
 
+static inline void iommu_setup_dma_ops(struct device *dev)
+{
+}
+
 static inline int iommu_dma_init_fq(struct iommu_domain *domain)
 {
        return -EINVAL;
@@ -42,9 +44,5 @@ static inline void iommu_dma_get_resv_regions(struct device *dev, struct list_he
 {
 }
 
-static inline void iommu_dma_set_pci_32bit_workaround(struct device *dev)
-{
-}
-
 #endif /* CONFIG_IOMMU_DMA */
 #endif /* __DMA_IOMMU_H */
index 45c75a8a0ef567178ff7cb8b26856c8726c1e84b..64adfdadeb4960c73bd7e01446f700b3ab979218 100644 (file)
@@ -4349,12 +4349,6 @@ static void intel_iommu_release_device(struct device *dev)
        set_dma_ops(dev, NULL);
 }
 
-static void intel_iommu_probe_finalize(struct device *dev)
-{
-       set_dma_ops(dev, NULL);
-       iommu_setup_dma_ops(dev, 0, U64_MAX);
-}
-
 static void intel_iommu_get_resv_regions(struct device *device,
                                         struct list_head *head)
 {
@@ -4834,7 +4828,6 @@ const struct iommu_ops intel_iommu_ops = {
        .domain_alloc           = intel_iommu_domain_alloc,
        .domain_alloc_user      = intel_iommu_domain_alloc_user,
        .probe_device           = intel_iommu_probe_device,
-       .probe_finalize         = intel_iommu_probe_finalize,
        .release_device         = intel_iommu_release_device,
        .get_resv_regions       = intel_iommu_get_resv_regions,
        .device_group           = intel_iommu_device_group,
index 3183b0ed4cdb921611de6c12ad44ac055f3f24d3..9df7cc75c1bc57c93b4991439088b6605e359ce8 100644 (file)
@@ -581,10 +581,11 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
                if (list_empty(&group->entry))
                        list_add_tail(&group->entry, group_list);
        }
-       mutex_unlock(&group->mutex);
 
-       if (dev_is_pci(dev))
-               iommu_dma_set_pci_32bit_workaround(dev);
+       if (group->default_domain)
+               iommu_setup_dma_ops(dev);
+
+       mutex_unlock(&group->mutex);
 
        return 0;
 
@@ -1828,6 +1829,8 @@ int bus_iommu_probe(const struct bus_type *bus)
                        mutex_unlock(&group->mutex);
                        return ret;
                }
+               for_each_group_device(group, gdev)
+                       iommu_setup_dma_ops(gdev->dev);
                mutex_unlock(&group->mutex);
 
                /*
@@ -3066,18 +3069,9 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
        if (ret)
                goto out_unlock;
 
-       /*
-        * Release the mutex here because ops->probe_finalize() call-back of
-        * some vendor IOMMU drivers calls arm_iommu_attach_device() which
-        * in-turn might call back into IOMMU core code, where it tries to take
-        * group->mutex, resulting in a deadlock.
-        */
-       mutex_unlock(&group->mutex);
-
        /* Make sure dma_ops is appropriatley set */
        for_each_group_device(group, gdev)
-               iommu_group_do_probe_finalize(gdev->dev);
-       return count;
+               iommu_setup_dma_ops(gdev->dev);
 
 out_unlock:
        mutex_unlock(&group->mutex);
index 9a5196f523de5f0f8902f054b1b3722d14b18cd2..d8eaa7ea380bb0f5086c50ad4e82cb88c0c378a8 100644 (file)
@@ -695,11 +695,6 @@ static size_t s390_iommu_unmap_pages(struct iommu_domain *domain,
        return size;
 }
 
-static void s390_iommu_probe_finalize(struct device *dev)
-{
-       iommu_setup_dma_ops(dev, 0, U64_MAX);
-}
-
 struct zpci_iommu_ctrs *zpci_get_iommu_ctrs(struct zpci_dev *zdev)
 {
        if (!zdev || !zdev->s390_domain)
@@ -785,7 +780,6 @@ static const struct iommu_ops s390_iommu_ops = {
        .capable = s390_iommu_capable,
        .domain_alloc_paging = s390_domain_alloc_paging,
        .probe_device = s390_iommu_probe_device,
-       .probe_finalize = s390_iommu_probe_finalize,
        .release_device = s390_iommu_release_device,
        .device_group = generic_device_group,
        .pgsize_bitmap = SZ_4K,
index 04048f64a2c0f436df56791e88eba6f9ba3e3f1f..8e776f6c6e35bcb756a6081f18fbb7a2e378d6a8 100644 (file)
@@ -1025,15 +1025,6 @@ err_free_dev:
        return ERR_PTR(ret);
 }
 
-static void viommu_probe_finalize(struct device *dev)
-{
-#ifndef CONFIG_ARCH_HAS_SETUP_DMA_OPS
-       /* First clear the DMA ops in case we're switching from a DMA domain */
-       set_dma_ops(dev, NULL);
-       iommu_setup_dma_ops(dev, 0, U64_MAX);
-#endif
-}
-
 static void viommu_release_device(struct device *dev)
 {
        struct viommu_endpoint *vdev = dev_iommu_priv_get(dev);
@@ -1073,7 +1064,6 @@ static struct iommu_ops viommu_ops = {
        .capable                = viommu_capable,
        .domain_alloc           = viommu_domain_alloc,
        .probe_device           = viommu_probe_device,
-       .probe_finalize         = viommu_probe_finalize,
        .release_device         = viommu_release_device,
        .device_group           = viommu_device_group,
        .get_resv_regions       = viommu_get_resv_regions,
index 40dd439307e8327314f6d6209804846092d0d5e5..86f0bff3cc95fbc78df99471b801fc8c529e8c5f 100644 (file)
@@ -1446,9 +1446,6 @@ static inline void iommu_debugfs_setup(void) {}
 #ifdef CONFIG_IOMMU_DMA
 #include <linux/msi.h>
 
-/* Setup call for arch DMA mapping code */
-void iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 dma_limit);
-
 int iommu_get_msi_cookie(struct iommu_domain *domain, dma_addr_t base);
 
 int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr);
@@ -1459,10 +1456,6 @@ void iommu_dma_compose_msi_msg(struct msi_desc *desc, struct msi_msg *msg);
 struct msi_desc;
 struct msi_msg;
 
-static inline void iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 dma_limit)
-{
-}
-
 static inline int iommu_get_msi_cookie(struct iommu_domain *domain, dma_addr_t base)
 {
        return -ENODEV;