iommu: Introduce new 'struct iommu_device'
authorJoerg Roedel <jroedel@suse.de>
Wed, 1 Feb 2017 12:23:08 +0000 (13:23 +0100)
committerJoerg Roedel <jroedel@suse.de>
Fri, 10 Feb 2017 12:44:57 +0000 (13:44 +0100)
This struct represents one hardware iommu in the iommu core
code. For now it only has the iommu-ops associated with it,
but that will be extended soon.

The register/unregister interface is also added, as well as
making use of it in the Intel and AMD IOMMU drivers.

Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/amd_iommu_types.h
drivers/iommu/dmar.c
drivers/iommu/intel-iommu.c
drivers/iommu/iommu.c
include/linux/intel-iommu.h
include/linux/iommu.h

index 019e02707cd5e3c893b3b6602a1847260b3ba401..689d88fa29a6b57deec73c590d84bdf70845a082 100644 (file)
@@ -112,7 +112,7 @@ static struct timer_list queue_timer;
  * Domain for untranslated devices - only allocated
  * if iommu=pt passed on kernel cmd line.
  */
-static const struct iommu_ops amd_iommu_ops;
+const struct iommu_ops amd_iommu_ops;
 
 static ATOMIC_NOTIFIER_HEAD(ppr_notifier);
 int amd_iommu_max_glx_val = -1;
@@ -3217,7 +3217,7 @@ static void amd_iommu_apply_dm_region(struct device *dev,
        WARN_ON_ONCE(reserve_iova(&dma_dom->iovad, start, end) == NULL);
 }
 
-static const struct iommu_ops amd_iommu_ops = {
+const struct iommu_ops amd_iommu_ops = {
        .capable = amd_iommu_capable,
        .domain_alloc = amd_iommu_domain_alloc,
        .domain_free  = amd_iommu_domain_free,
index 6799cf9713f77f460f990e6bc0f38b31422c0745..b7ccfb21b271d14e896b4575c3c93e4dde6dc936 100644 (file)
@@ -94,6 +94,8 @@
  * out of it.
  */
 
+extern const struct iommu_ops amd_iommu_ops;
+
 /*
  * structure describing one IOMMU in the ACPI table. Typically followed by one
  * or more ivhd_entrys.
@@ -1639,6 +1641,9 @@ static int iommu_init_pci(struct amd_iommu *iommu)
                                               amd_iommu_groups, "ivhd%d",
                                               iommu->index);
 
+       iommu_device_set_ops(&iommu->iommu, &amd_iommu_ops);
+       iommu_device_register(&iommu->iommu);
+
        return pci_enable_device(iommu->dev);
 }
 
index 0d91785ebdc34accca7c4e9ed45da300ddbb68a7..0683505a498af1afae5a56929e7992d5bdbb94bc 100644 (file)
@@ -538,6 +538,9 @@ struct amd_iommu {
        /* IOMMU sysfs device */
        struct device *iommu_dev;
 
+       /* Handle for IOMMU core code */
+       struct iommu_device iommu;
+
        /*
         * We can't rely on the BIOS to restore all values on reinit, so we
         * need to stash them
index a88576d50740b2dbdbe6e65b2bfe1985f01c81ca..83fee0e8cf437b6d14f8f92b0c72609afa4fc393 100644 (file)
@@ -74,6 +74,8 @@ static unsigned long dmar_seq_ids[BITS_TO_LONGS(DMAR_UNITS_SUPPORTED)];
 static int alloc_iommu(struct dmar_drhd_unit *drhd);
 static void free_iommu(struct intel_iommu *iommu);
 
+extern const struct iommu_ops intel_iommu_ops;
+
 static void dmar_register_drhd_unit(struct dmar_drhd_unit *drhd)
 {
        /*
@@ -1084,6 +1086,12 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
                        err = PTR_ERR(iommu->iommu_dev);
                        goto err_unmap;
                }
+
+               iommu_device_set_ops(&iommu->iommu, &intel_iommu_ops);
+
+               err = iommu_device_register(&iommu->iommu);
+               if (err)
+                       goto err_unmap;
        }
 
        drhd->iommu = iommu;
@@ -1102,6 +1110,7 @@ error:
 static void free_iommu(struct intel_iommu *iommu)
 {
        iommu_device_destroy(iommu->iommu_dev);
+       iommu_device_unregister(&iommu->iommu);
 
        if (iommu->irq) {
                if (iommu->pr_irq) {
index c66c273dfd8ab1058030433961fcfaaf2046f846..e6e8f5bf3a8f0ad4145b7d821835f83a8086b54d 100644 (file)
@@ -547,7 +547,7 @@ EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
 static DEFINE_SPINLOCK(device_domain_lock);
 static LIST_HEAD(device_domain_list);
 
-static const struct iommu_ops intel_iommu_ops;
+const struct iommu_ops intel_iommu_ops;
 
 static bool translation_pre_enabled(struct intel_iommu *iommu)
 {
@@ -5292,7 +5292,7 @@ struct intel_iommu *intel_svm_device_to_iommu(struct device *dev)
 }
 #endif /* CONFIG_INTEL_IOMMU_SVM */
 
-static const struct iommu_ops intel_iommu_ops = {
+const struct iommu_ops intel_iommu_ops = {
        .capable        = intel_iommu_capable,
        .domain_alloc   = intel_iommu_domain_alloc,
        .domain_free    = intel_iommu_domain_free,
index cc569b1b66a22882f044b627327ae54ec4ad207b..1dfd70ea27e4f90a0174e5472035416ae5000b61 100644 (file)
@@ -77,6 +77,25 @@ struct iommu_group_attribute iommu_group_attr_##_name =              \
 #define to_iommu_group(_kobj)          \
        container_of(_kobj, struct iommu_group, kobj)
 
+static LIST_HEAD(iommu_device_list);
+static DEFINE_SPINLOCK(iommu_device_lock);
+
+int iommu_device_register(struct iommu_device *iommu)
+{
+       spin_lock(&iommu_device_lock);
+       list_add_tail(&iommu->list, &iommu_device_list);
+       spin_unlock(&iommu_device_lock);
+
+       return 0;
+}
+
+void iommu_device_unregister(struct iommu_device *iommu)
+{
+       spin_lock(&iommu_device_lock);
+       list_del(&iommu->list);
+       spin_unlock(&iommu_device_lock);
+}
+
 static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,
                                                 unsigned type);
 static int __iommu_attach_device(struct iommu_domain *domain,
index d49e26c6cdc7b5e48e41591f7c73e74d200441a8..99a65a39786109343e84ff0da088122ea5c5ea31 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/dma_remapping.h>
 #include <linux/mmu_notifier.h>
 #include <linux/list.h>
+#include <linux/iommu.h>
 #include <asm/cacheflush.h>
 #include <asm/iommu.h>
 
@@ -440,6 +441,7 @@ struct intel_iommu {
        struct irq_domain *ir_msi_domain;
 #endif
        struct device   *iommu_dev; /* IOMMU-sysfs device */
+       struct iommu_device iommu;  /* IOMMU core code handle */
        int             node;
        u32             flags;      /* Software defined flags */
 };
index 085e1f0e6c0760a5b9cde77fc2201c12618d6aaf..900ddd2123645e9bdfb86a947d7868cc47986ba3 100644 (file)
@@ -204,6 +204,26 @@ struct iommu_ops {
        unsigned long pgsize_bitmap;
 };
 
+/**
+ * struct iommu_device - IOMMU core representation of one IOMMU hardware
+ *                      instance
+ * @list: Used by the iommu-core to keep a list of registered iommus
+ * @ops: iommu-ops for talking to this iommu
+ */
+struct iommu_device {
+       struct list_head list;
+       const struct iommu_ops *ops;
+};
+
+int  iommu_device_register(struct iommu_device *iommu);
+void iommu_device_unregister(struct iommu_device *iommu);
+
+static inline void iommu_device_set_ops(struct iommu_device *iommu,
+                                       const struct iommu_ops *ops)
+{
+       iommu->ops = ops;
+}
+
 #define IOMMU_GROUP_NOTIFY_ADD_DEVICE          1 /* Device added */
 #define IOMMU_GROUP_NOTIFY_DEL_DEVICE          2 /* Pre Device removed */
 #define IOMMU_GROUP_NOTIFY_BIND_DRIVER         3 /* Pre Driver bind */
@@ -361,6 +381,7 @@ const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode);
 struct iommu_ops {};
 struct iommu_group {};
 struct iommu_fwspec {};
+struct iommu_device {};
 
 static inline bool iommu_present(struct bus_type *bus)
 {
@@ -558,6 +579,20 @@ static inline void iommu_device_destroy(struct device *dev)
 {
 }
 
+static inline int  iommu_device_register(struct iommu_device *iommu)
+{
+       return -ENODEV;
+}
+
+static inline void iommu_device_set_ops(struct iommu_device *iommu,
+                                       const struct iommu_ops *ops)
+{
+}
+
+static inline void iommu_device_unregister(struct iommu_device *iommu)
+{
+}
+
 static inline int iommu_device_link(struct device *dev, struct device *link)
 {
        return -EINVAL;