iommu: Retire bus ops
authorRobin Murphy <robin.murphy@arm.com>
Tue, 21 Nov 2023 18:04:02 +0000 (18:04 +0000)
committerJoerg Roedel <jroedel@suse.de>
Mon, 27 Nov 2023 10:03:15 +0000 (11:03 +0100)
With the rest of the API internals converted, it's time to finally
tackle probe_device and how we bootstrap the per-device ops association
to begin with. This ends up being disappointingly straightforward, since
fwspec users are already doing it in order to find their of_xlate
callback, and it works out that we can easily do the equivalent for
other drivers too. Then shuffle the remaining awareness of iommu_ops
into the couple of core headers that still need it, and breathe a sigh
of relief.

Ding dong the bus ops are gone!

CC: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Christoph Hellwig <hch@lst.de>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Link: https://lore.kernel.org/r/a59011ef65b4b6657cb0b7a388d786b779b61305.1700589539.git.robin.murphy@arm.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/iommu.c
include/acpi/acpi_bus.h
include/linux/device.h
include/linux/device/bus.h
include/linux/dma-map-ops.h

index 88aeae0..254f42b 100644 (file)
@@ -148,7 +148,7 @@ struct iommu_group_attribute iommu_group_attr_##_name =             \
 static LIST_HEAD(iommu_device_list);
 static DEFINE_SPINLOCK(iommu_device_lock);
 
-static struct bus_type * const iommu_buses[] = {
+static const struct bus_type * const iommu_buses[] = {
        &platform_bus_type,
 #ifdef CONFIG_PCI
        &pci_bus_type,
@@ -257,13 +257,6 @@ int iommu_device_register(struct iommu_device *iommu,
        /* We need to be able to take module references appropriately */
        if (WARN_ON(is_module_address((unsigned long)ops) && !ops->owner))
                return -EINVAL;
-       /*
-        * Temporarily enforce global restriction to a single driver. This was
-        * already the de-facto behaviour, since any possible combination of
-        * existing drivers would compete for at least the PCI or platform bus.
-        */
-       if (iommu_buses[0]->iommu_ops && iommu_buses[0]->iommu_ops != ops)
-               return -EBUSY;
 
        iommu->ops = ops;
        if (hwdev)
@@ -273,10 +266,8 @@ int iommu_device_register(struct iommu_device *iommu,
        list_add_tail(&iommu->list, &iommu_device_list);
        spin_unlock(&iommu_device_lock);
 
-       for (int i = 0; i < ARRAY_SIZE(iommu_buses) && !err; i++) {
-               iommu_buses[i]->iommu_ops = ops;
+       for (int i = 0; i < ARRAY_SIZE(iommu_buses) && !err; i++)
                err = bus_iommu_probe(iommu_buses[i]);
-       }
        if (err)
                iommu_device_unregister(iommu);
        return err;
@@ -329,7 +320,6 @@ int iommu_device_register_bus(struct iommu_device *iommu,
        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);
@@ -496,12 +486,27 @@ static void iommu_deinit_device(struct device *dev)
 
 static int __iommu_probe_device(struct device *dev, struct list_head *group_list)
 {
-       const struct iommu_ops *ops = dev->bus->iommu_ops;
+       const struct iommu_ops *ops;
+       struct iommu_fwspec *fwspec;
        struct iommu_group *group;
        static DEFINE_MUTEX(iommu_probe_device_lock);
        struct group_device *gdev;
        int ret;
 
+       /*
+        * For FDT-based systems and ACPI IORT/VIOT, drivers register IOMMU
+        * instances with non-NULL fwnodes, and client devices should have been
+        * identified with a fwspec by this point. Otherwise, we can currently
+        * assume that only one of Intel, AMD, s390, PAMU or legacy SMMUv2 can
+        * be present, and that any of their registered instances has suitable
+        * ops for probing, and thus cheekily co-opt the same mechanism.
+        */
+       fwspec = dev_iommu_fwspec_get(dev);
+       if (fwspec && fwspec->ops)
+               ops = fwspec->ops;
+       else
+               ops = iommu_ops_from_fwnode(NULL);
+
        if (!ops)
                return -ENODEV;
        /*
index 1216d72..8907978 100644 (file)
@@ -627,6 +627,8 @@ struct acpi_pci_root {
 
 /* helper */
 
+struct iommu_ops;
+
 bool acpi_dma_supported(const struct acpi_device *adev);
 enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev);
 int acpi_iommu_fwspec_init(struct device *dev, u32 id,
index d7a72a8..0314dbb 100644 (file)
@@ -42,7 +42,6 @@ struct class;
 struct subsys_private;
 struct device_node;
 struct fwnode_handle;
-struct iommu_ops;
 struct iommu_group;
 struct dev_pin_info;
 struct dev_iommu;
index ae10c43..e25aab0 100644 (file)
@@ -62,9 +62,6 @@ struct fwnode_handle;
  *                     this bus.
  * @pm:                Power management operations of this bus, callback the specific
  *             device driver's pm-ops.
- * @iommu_ops:  IOMMU specific operations for this bus, used to attach IOMMU
- *              driver implementations to a bus and allow the driver to do
- *              bus-specific setup
  * @need_parent_lock:  When probing or removing a device on this bus, the
  *                     device core should lock the device's parent.
  *
@@ -104,8 +101,6 @@ struct bus_type {
 
        const struct dev_pm_ops *pm;
 
-       const struct iommu_ops *iommu_ops;
-
        bool need_parent_lock;
 };
 
index f2fc203..a52e508 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/slab.h>
 
 struct cma;
+struct iommu_ops;
 
 /*
  * Values for struct dma_map_ops.flags: