[PATCH 06/13] iommu: Introduce new 'struct iommu_device'
Manoj Iyer
manoj.iyer at canonical.com
Tue May 16 20:11:29 UTC 2017
From: Joerg Roedel <jroedel at suse.de>
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.
BugLink: http://bugs.launchpad.net/bugs/1688158
Signed-off-by: Joerg Roedel <jroedel at suse.de>
(cherry picked from commit b0119e870837dcd15a207b4701542ebac5d19b45)
Signed-off-by: Manoj Iyer <manoj.iyer at canonical.com>
---
drivers/iommu/amd_iommu.c | 4 ++--
drivers/iommu/amd_iommu_init.c | 5 +++++
drivers/iommu/amd_iommu_types.h | 3 +++
drivers/iommu/dmar.c | 9 +++++++++
drivers/iommu/intel-iommu.c | 4 ++--
drivers/iommu/iommu.c | 19 +++++++++++++++++++
include/linux/intel-iommu.h | 2 ++
include/linux/iommu.h | 35 +++++++++++++++++++++++++++++++++++
8 files changed, 77 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index d109e41204e8..c9420a62efda 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -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;
@@ -3233,7 +3233,7 @@ static void amd_iommu_apply_resv_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,
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 6799cf9713f7..b7ccfb21b271 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -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);
}
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 0d91785ebdc3..0683505a498a 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -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
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 8ccbd7023194..8e8a48ef9d82 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -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)
{
/*
@@ -1086,6 +1088,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;
@@ -1104,6 +1112,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
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) {
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 2c93e4caf826..ca5749eb74c5 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -548,7 +548,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)
{
@@ -4128,7 +4128,7 @@ static int init_iommu_hw(void)
iommu_disable_protect_mem_regions(iommu);
continue;
}
-
+
iommu_flush_write_buffer(iommu);
iommu_set_root_entry(iommu);
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 3b8c4299ca51..d1b3634f4166 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -83,6 +83,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,
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 23e129ef6726..7dde001ec3e2 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -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 */
};
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index ded067b805c9..07d41eef3219 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -212,6 +212,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 */
@@ -373,6 +393,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)
{
@@ -576,6 +597,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;
--
2.11.0
More information about the kernel-team
mailing list