From e4f10ffe4c9b500e545b874b816ffea5e8659b05 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 21 Nov 2016 10:01:36 +0000 Subject: iommu: Make of_iommu_set/get_ops() DT agnostic The of_iommu_{set/get}_ops() API is used to associate a device tree node with a specific set of IOMMU operations. The same kernel interface is required on systems booting with ACPI, where devices are not associated with a device tree node, therefore the interface requires generalization. The struct device fwnode member represents the fwnode token associated with the device and the struct it points at is firmware specific; regardless, it is initialized on both ACPI and DT systems and makes an ideal candidate to use it to associate a set of IOMMU operations to a given device, through its struct device.fwnode member pointer, paving the way for representing per-device iommu_ops (ie an iommu instance associated with a device). Convert the DT specific of_iommu_{set/get}_ops() interface to use struct device.fwnode as a look-up token, making the interface usable on ACPI systems and rename the data structures and the registration API so that they are made to represent their usage more clearly. Signed-off-by: Lorenzo Pieralisi Acked-by: Will Deacon Reviewed-by: Robin Murphy Reviewed-by: Tomasz Nowicki Tested-by: Hanjun Guo Tested-by: Tomasz Nowicki Cc: Will Deacon Cc: Hanjun Guo Cc: Robin Murphy Cc: Joerg Roedel Signed-off-by: Will Deacon --- drivers/iommu/iommu.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'drivers/iommu/iommu.c') diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 9a2f1960873b..8d3e847d4845 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1615,6 +1615,46 @@ out: return ret; } +struct iommu_instance { + struct list_head list; + struct fwnode_handle *fwnode; + const struct iommu_ops *ops; +}; +static LIST_HEAD(iommu_instance_list); +static DEFINE_SPINLOCK(iommu_instance_lock); + +void iommu_register_instance(struct fwnode_handle *fwnode, + const struct iommu_ops *ops) +{ + struct iommu_instance *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); + + if (WARN_ON(!iommu)) + return; + + of_node_get(to_of_node(fwnode)); + INIT_LIST_HEAD(&iommu->list); + iommu->fwnode = fwnode; + iommu->ops = ops; + spin_lock(&iommu_instance_lock); + list_add_tail(&iommu->list, &iommu_instance_list); + spin_unlock(&iommu_instance_lock); +} + +const struct iommu_ops *iommu_get_instance(struct fwnode_handle *fwnode) +{ + struct iommu_instance *instance; + const struct iommu_ops *ops = NULL; + + spin_lock(&iommu_instance_lock); + list_for_each_entry(instance, &iommu_instance_list, list) + if (instance->fwnode == fwnode) { + ops = instance->ops; + break; + } + spin_unlock(&iommu_instance_lock); + return ops; +} + int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode, const struct iommu_ops *ops) { -- cgit v1.2.3