]> git.ipfire.org Git - thirdparty/linux.git/blobdiff - drivers/iommu/iommu.c
Merge tag 'iommu-updates-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/joro...
[thirdparty/linux.git] / drivers / iommu / iommu.c
index 39601fbfd0e0ca82162f7dff6c747dec9d53acdf..3bfc56df4f781cbb15f6cad090681f8327b8dde4 100644 (file)
 #include <linux/msi.h>
 
 #include "dma-iommu.h"
+#include "iommu-priv.h"
 
 #include "iommu-sva.h"
+#include "iommu-priv.h"
 
 static struct kset *iommu_group_kset;
 static DEFINE_IDA(iommu_group_ida);
@@ -291,6 +293,48 @@ void iommu_device_unregister(struct iommu_device *iommu)
 }
 EXPORT_SYMBOL_GPL(iommu_device_unregister);
 
+#if IS_ENABLED(CONFIG_IOMMUFD_TEST)
+void iommu_device_unregister_bus(struct iommu_device *iommu,
+                                struct bus_type *bus,
+                                struct notifier_block *nb)
+{
+       bus_unregister_notifier(bus, nb);
+       iommu_device_unregister(iommu);
+}
+EXPORT_SYMBOL_GPL(iommu_device_unregister_bus);
+
+/*
+ * Register an iommu driver against a single bus. This is only used by iommufd
+ * selftest to create a mock iommu driver. The caller must provide
+ * some memory to hold a notifier_block.
+ */
+int iommu_device_register_bus(struct iommu_device *iommu,
+                             const struct iommu_ops *ops, struct bus_type *bus,
+                             struct notifier_block *nb)
+{
+       int err;
+
+       iommu->ops = ops;
+       nb->notifier_call = iommu_bus_notifier;
+       err = bus_register_notifier(bus, nb);
+       if (err)
+               return err;
+
+       spin_lock(&iommu_device_lock);
+       list_add_tail(&iommu->list, &iommu_device_list);
+       spin_unlock(&iommu_device_lock);
+
+       bus->iommu_ops = ops;
+       err = bus_iommu_probe(bus);
+       if (err) {
+               iommu_device_unregister_bus(iommu, bus, nb);
+               return err;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(iommu_device_register_bus);
+#endif
+
 static struct dev_iommu *dev_iommu_get(struct device *dev)
 {
        struct dev_iommu *param = dev->iommu;
@@ -2131,6 +2175,32 @@ int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group)
 }
 EXPORT_SYMBOL_GPL(iommu_attach_group);
 
+/**
+ * iommu_group_replace_domain - replace the domain that a group is attached to
+ * @new_domain: new IOMMU domain to replace with
+ * @group: IOMMU group that will be attached to the new domain
+ *
+ * This API allows the group to switch domains without being forced to go to
+ * the blocking domain in-between.
+ *
+ * If the currently attached domain is a core domain (e.g. a default_domain),
+ * it will act just like the iommu_attach_group().
+ */
+int iommu_group_replace_domain(struct iommu_group *group,
+                              struct iommu_domain *new_domain)
+{
+       int ret;
+
+       if (!new_domain)
+               return -EINVAL;
+
+       mutex_lock(&group->mutex);
+       ret = __iommu_group_set_domain(group, new_domain);
+       mutex_unlock(&group->mutex);
+       return ret;
+}
+EXPORT_SYMBOL_NS_GPL(iommu_group_replace_domain, IOMMUFD_INTERNAL);
+
 static int __iommu_device_set_domain(struct iommu_group *group,
                                     struct device *dev,
                                     struct iommu_domain *new_domain,
@@ -2674,6 +2744,14 @@ int iommu_set_pgtable_quirks(struct iommu_domain *domain,
 }
 EXPORT_SYMBOL_GPL(iommu_set_pgtable_quirks);
 
+/**
+ * iommu_get_resv_regions - get reserved regions
+ * @dev: device for which to get reserved regions
+ * @list: reserved region list for device
+ *
+ * This returns a list of reserved IOVA regions specific to this device.
+ * A domain user should not map IOVA in these ranges.
+ */
 void iommu_get_resv_regions(struct device *dev, struct list_head *list)
 {
        const struct iommu_ops *ops = dev_iommu_ops(dev);
@@ -2681,9 +2759,10 @@ void iommu_get_resv_regions(struct device *dev, struct list_head *list)
        if (ops->get_resv_regions)
                ops->get_resv_regions(dev, list);
 }
+EXPORT_SYMBOL_GPL(iommu_get_resv_regions);
 
 /**
- * iommu_put_resv_regions - release resered regions
+ * iommu_put_resv_regions - release reserved regions
  * @dev: device for which to free reserved regions
  * @list: reserved region list for device
  *