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: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
c09e22d537
commit
b0119e8708
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue