Commit b0119e87 authored by Joerg Roedel's avatar Joerg Roedel

iommu: Introduce new 'struct iommu_device'

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: default avatarJoerg Roedel <jroedel@suse.de>
parent c09e22d5
...@@ -112,7 +112,7 @@ static struct timer_list queue_timer; ...@@ -112,7 +112,7 @@ static struct timer_list queue_timer;
* Domain for untranslated devices - only allocated * Domain for untranslated devices - only allocated
* if iommu=pt passed on kernel cmd line. * 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); static ATOMIC_NOTIFIER_HEAD(ppr_notifier);
int amd_iommu_max_glx_val = -1; int amd_iommu_max_glx_val = -1;
...@@ -3217,7 +3217,7 @@ static void amd_iommu_apply_dm_region(struct device *dev, ...@@ -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); 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, .capable = amd_iommu_capable,
.domain_alloc = amd_iommu_domain_alloc, .domain_alloc = amd_iommu_domain_alloc,
.domain_free = amd_iommu_domain_free, .domain_free = amd_iommu_domain_free,
......
...@@ -94,6 +94,8 @@ ...@@ -94,6 +94,8 @@
* out of it. * out of it.
*/ */
extern const struct iommu_ops amd_iommu_ops;
/* /*
* structure describing one IOMMU in the ACPI table. Typically followed by one * structure describing one IOMMU in the ACPI table. Typically followed by one
* or more ivhd_entrys. * or more ivhd_entrys.
...@@ -1639,6 +1641,9 @@ static int iommu_init_pci(struct amd_iommu *iommu) ...@@ -1639,6 +1641,9 @@ static int iommu_init_pci(struct amd_iommu *iommu)
amd_iommu_groups, "ivhd%d", amd_iommu_groups, "ivhd%d",
iommu->index); iommu->index);
iommu_device_set_ops(&iommu->iommu, &amd_iommu_ops);
iommu_device_register(&iommu->iommu);
return pci_enable_device(iommu->dev); return pci_enable_device(iommu->dev);
} }
......
...@@ -538,6 +538,9 @@ struct amd_iommu { ...@@ -538,6 +538,9 @@ struct amd_iommu {
/* IOMMU sysfs device */ /* IOMMU sysfs device */
struct device *iommu_dev; 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 * We can't rely on the BIOS to restore all values on reinit, so we
* need to stash them * need to stash them
......
...@@ -74,6 +74,8 @@ static unsigned long dmar_seq_ids[BITS_TO_LONGS(DMAR_UNITS_SUPPORTED)]; ...@@ -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 int alloc_iommu(struct dmar_drhd_unit *drhd);
static void free_iommu(struct intel_iommu *iommu); 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) static void dmar_register_drhd_unit(struct dmar_drhd_unit *drhd)
{ {
/* /*
...@@ -1084,6 +1086,12 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) ...@@ -1084,6 +1086,12 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
err = PTR_ERR(iommu->iommu_dev); err = PTR_ERR(iommu->iommu_dev);
goto err_unmap; 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; drhd->iommu = iommu;
...@@ -1102,6 +1110,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) ...@@ -1102,6 +1110,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
static void free_iommu(struct intel_iommu *iommu) static void free_iommu(struct intel_iommu *iommu)
{ {
iommu_device_destroy(iommu->iommu_dev); iommu_device_destroy(iommu->iommu_dev);
iommu_device_unregister(&iommu->iommu);
if (iommu->irq) { if (iommu->irq) {
if (iommu->pr_irq) { if (iommu->pr_irq) {
......
...@@ -547,7 +547,7 @@ EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped); ...@@ -547,7 +547,7 @@ EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
static DEFINE_SPINLOCK(device_domain_lock); static DEFINE_SPINLOCK(device_domain_lock);
static LIST_HEAD(device_domain_list); 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) static bool translation_pre_enabled(struct intel_iommu *iommu)
{ {
...@@ -5292,7 +5292,7 @@ struct intel_iommu *intel_svm_device_to_iommu(struct device *dev) ...@@ -5292,7 +5292,7 @@ struct intel_iommu *intel_svm_device_to_iommu(struct device *dev)
} }
#endif /* CONFIG_INTEL_IOMMU_SVM */ #endif /* CONFIG_INTEL_IOMMU_SVM */
static const struct iommu_ops intel_iommu_ops = { const struct iommu_ops intel_iommu_ops = {
.capable = intel_iommu_capable, .capable = intel_iommu_capable,
.domain_alloc = intel_iommu_domain_alloc, .domain_alloc = intel_iommu_domain_alloc,
.domain_free = intel_iommu_domain_free, .domain_free = intel_iommu_domain_free,
......
...@@ -77,6 +77,25 @@ struct iommu_group_attribute iommu_group_attr_##_name = \ ...@@ -77,6 +77,25 @@ struct iommu_group_attribute iommu_group_attr_##_name = \
#define to_iommu_group(_kobj) \ #define to_iommu_group(_kobj) \
container_of(_kobj, struct 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, static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,
unsigned type); unsigned type);
static int __iommu_attach_device(struct iommu_domain *domain, static int __iommu_attach_device(struct iommu_domain *domain,
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/dma_remapping.h> #include <linux/dma_remapping.h>
#include <linux/mmu_notifier.h> #include <linux/mmu_notifier.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/iommu.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/iommu.h> #include <asm/iommu.h>
...@@ -440,6 +441,7 @@ struct intel_iommu { ...@@ -440,6 +441,7 @@ struct intel_iommu {
struct irq_domain *ir_msi_domain; struct irq_domain *ir_msi_domain;
#endif #endif
struct device *iommu_dev; /* IOMMU-sysfs device */ struct device *iommu_dev; /* IOMMU-sysfs device */
struct iommu_device iommu; /* IOMMU core code handle */
int node; int node;
u32 flags; /* Software defined flags */ u32 flags; /* Software defined flags */
}; };
......
...@@ -204,6 +204,26 @@ struct iommu_ops { ...@@ -204,6 +204,26 @@ struct iommu_ops {
unsigned long pgsize_bitmap; 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_ADD_DEVICE 1 /* Device added */
#define IOMMU_GROUP_NOTIFY_DEL_DEVICE 2 /* Pre Device removed */ #define IOMMU_GROUP_NOTIFY_DEL_DEVICE 2 /* Pre Device removed */
#define IOMMU_GROUP_NOTIFY_BIND_DRIVER 3 /* Pre Driver bind */ #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); ...@@ -361,6 +381,7 @@ const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode);
struct iommu_ops {}; struct iommu_ops {};
struct iommu_group {}; struct iommu_group {};
struct iommu_fwspec {}; struct iommu_fwspec {};
struct iommu_device {};
static inline bool iommu_present(struct bus_type *bus) static inline bool iommu_present(struct bus_type *bus)
{ {
...@@ -558,6 +579,20 @@ static inline void iommu_device_destroy(struct device *dev) ...@@ -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) static inline int iommu_device_link(struct device *dev, struct device *link)
{ {
return -EINVAL; return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment