iommu: Retire bus ops
Subsystems (12)
Robin Murphy
reviewerv6 cover iommu: Retire bus ops
v5: https://lore.kernel.org/linux-iommu/[email protected]/
Yet another rebase, this time just tweaking patch #3 for the new domain_alloc_user() sites, and picking up reviews/acks.
Thanks,
Robin.
Robin Murphy (7):
iommu: Factor out some helpers
iommu: Decouple iommu_present() from bus ops
iommu: Validate that devices match domains
iommu: Decouple iommu_domain_alloc() from bus ops iommu/arm-smmu: Don't register fwnode for legacy binding
iommu: Retire bus ops
iommu: Clean up open-coded ownership checks
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 3 - drivers/iommu/arm/arm-smmu/arm-smmu.c | 12 +- drivers/iommu/arm/arm-smmu/qcom_iommu.c | 16 +-- drivers/iommu/iommu.c | 143 +++++++++++++------- drivers/iommu/iommufd/hw_pagetable.c | 2 + drivers/iommu/mtk_iommu.c | 7 +- drivers/iommu/mtk_iommu_v1.c | 3 - drivers/iommu/sprd-iommu.c | 8 +- drivers/iommu/virtio-iommu.c | 3 - include/acpi/acpi_bus.h | 2 + include/linux/device.h | 1 - include/linux/device/bus.h | 5 - include/linux/dma-map-ops.h | 1 + include/linux/iommu.h | 2 +- 14 files changed, 110 insertions(+), 98 deletions(-)
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
Robin Murphy
reviewerPATCH v6 1/7 iommu: Factor out some helpers
The pattern for picking the first device out of the group list is repeated a few times now, so it's clearly worth factoring out, which also helps hide the iommu_group_dev detail from places that don't need to know. Similarly, the safety check for dev_iommu_ops() at certain public interfaces starts looking a bit repetitive, and might not be completely obvious at first glance, so let's factor that out for clarity as well, in preparation for more uses of both.
---
v3: Rename dev_iommu_ops_valid() to reflect what it's actually checking,
rather than an implied consequence.
v4: Rebase, also catch the sneaky one in iommu_get_group_resv_regions()
which wasn't the full pattern (but really should be since it guards the dev_iommu_ops() invocation in iommu_get_resv_regions()).
--- drivers/iommu/iommu.c | 56 ++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 30 deletions(-)
drivers/iommu/iommu.c +26 -30
@@ -368,6 +368,15 @@ static void dev_iommu_free(struct device *dev)kfree (param); } +/* +* Internal equivalent of device_iommu_mapped() for when we care that a device +* actually has API ops, and don't want false positives from VFIO-only groups. +*/ +static bool dev_has_iommu (struct device *dev) +{ +return dev->iommu && dev->iommu->iommu_dev; +} +static u32 dev_iommu_get_max_pasids (struct device *dev) {u32 max_pasids =0 , bits =0 ;
@@ -620,7 +629,7 @@ static void __iommu_group_remove_device(struct device *dev)list_del (&device->list);__iommu_group_free_device (group, device); -if (dev->iommu && dev->iommu->iommu_dev) +if (dev_has_iommu (dev))iommu_deinit_device (dev);else dev->iommu_group =NULL ;
@@ -819,7 +828,7 @@ int iommu_get_group_resv_regions(struct iommu_group *group,* Non-API groups still expose reserved_regions in sysfs, * so filter out calls that get here that way. */ -if (!device->dev->iommu) +if (!dev_has_iommu (device->dev))break ;INIT_LIST_HEAD (&dev_resv_regions);
@@ -1225,6 +1234,12 @@ void iommu_group_remove_device(struct device *dev) }EXPORT_SYMBOL_GPL (iommu_group_remove_device); +static struct device *iommu_group_first_dev (struct iommu_group *group) +{ +lockdep_assert_held (&group->mutex); + return list_first_entry(&group->devices, struct group_device, list)->dev; +} +/** * iommu_group_for_each_dev - iterate over each device in the group * @group: the group
@@ -1752,23 +1767,6 @@ __iommu_group_alloc_default_domain(struct iommu_group *group, int req_type)return __iommu_group_domain_alloc (group, req_type); } -/* -* Returns the iommu_ops for the devices in an iommu group. -* -* It is assumed that all devices in an iommu group are managed by a single -* IOMMU unit. Therefore, this returns the dev_iommu_ops of the first device -* in the group. -*/ -static const struct iommu_ops *group_iommu_ops (struct iommu_group *group) -{ -struct group_device *device = - list_first_entry(&group->devices, struct group_device, list); - -lockdep_assert_held (&group->mutex); - -return dev_iommu_ops (device->dev); -} -/* * req_type of 0 means "auto" which means to select a domain based on * iommu_def_domain_type or what the driver actually supports.
@@ -1776,7 +1774,7 @@ static const struct iommu_ops *group_iommu_ops(struct iommu_group *group)static struct iommu_domain *iommu_group_alloc_default_domain (struct iommu_group *group,int req_type) { -const struct iommu_ops *ops =group_iommu_ops (group); +const struct iommu_ops *ops =dev_iommu_ops (iommu_group_first_dev (group));struct iommu_domain *dom;lockdep_assert_held (&group->mutex);
@@ -1854,7 +1852,7 @@ static int iommu_bus_notifier(struct notifier_block *nb,static int iommu_get_def_domain_type (struct iommu_group *group,struct device *dev,int cur_type) { -const struct iommu_ops *ops =group_iommu_ops (group); +const struct iommu_ops *ops =dev_iommu_ops (dev);int type;if (!ops->def_domain_type)
@@ -2021,7 +2019,7 @@ bool device_iommu_capable(struct device *dev, enum iommu_cap cap) {const struct iommu_ops *ops; -if (!dev->iommu || !dev->iommu->iommu_dev) +if (!dev_has_iommu (dev))return false; ops =dev_iommu_ops (dev);
@@ -2120,11 +2118,9 @@ static struct iommu_domain *__iommu_domain_alloc(const struct iommu_ops *ops,static struct iommu_domain *__iommu_group_domain_alloc (struct iommu_group *group,unsigned int type) { -struct device *dev = - list_first_entry(&group->devices, struct group_device, list) - ->dev; +struct device *dev =iommu_group_first_dev (group); -return __iommu_domain_alloc (group_iommu_ops (group), dev, type); +return __iommu_domain_alloc (dev_iommu_ops (dev), dev, type); }struct iommu_domain *iommu_domain_alloc (const struct bus_type *bus)
@@ -2987,8 +2983,8 @@ EXPORT_SYMBOL_GPL(iommu_fwspec_add_ids);*/ int iommu_dev_enable_feature (struct device *dev,enum iommu_dev_features feat) { -if (dev->iommu && dev->iommu->iommu_dev) { -const struct iommu_ops *ops = dev->iommu->iommu_dev->ops; +if (dev_has_iommu (dev)) { +const struct iommu_ops *ops =dev_iommu_ops (dev);if (ops->dev_enable_feat)return ops->dev_enable_feat (dev, feat);
@@ -3003,8 +2999,8 @@ EXPORT_SYMBOL_GPL(iommu_dev_enable_feature);*/ int iommu_dev_disable_feature (struct device *dev,enum iommu_dev_features feat) { -if (dev->iommu && dev->iommu->iommu_dev) { -const struct iommu_ops *ops = dev->iommu->iommu_dev->ops; +if (dev_has_iommu (dev)) { +const struct iommu_ops *ops =dev_iommu_ops (dev);if (ops->dev_disable_feat)return ops->dev_disable_feat (dev, feat);
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
Robin Murphy
reviewerPATCH v6 2/7 iommu: Decouple iommu_present() from bus ops
In reply to Robin MurphyMuch as I'd like to remove iommu_present(), the final remaining users are proving stubbornly difficult to clean up, so kick that can down the road and just rework it to preserve the current behaviour without depending on bus ops. Since commit 57365a04c921 ("iommu: Move bus setup to IOMMU device registration"), any registered IOMMU instance is already considered "present" for every entry in iommu_buses, so it's simply a case of validating the bus and checking we have at least once IOMMU.
---
v3: Tweak to use the ops-based check rather than group-based, to
properly match the existing behaviour
v4: Just look for IOMMU instances instead of managed devices
--- drivers/iommu/iommu.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)
drivers/iommu/iommu.c +20 -1
@@ -2001,9 +2001,28 @@ int bus_iommu_probe(const struct bus_type *bus)return 0 ; } +/** +* iommu_present() - make platform-specific assumptions about an IOMMU +* @bus: bus to check +* +* Do not use this function. You want device_iommu_mapped() instead. +* +* Return: true if some IOMMU is present and aware of devices on the given bus; +* in general it may not be the only IOMMU, and it may not have anything to do +* with whatever device you are ultimately interested in. +*/ bool iommu_present (const struct bus_type *bus) { -return bus->iommu_ops !=NULL ; +bool ret = false; + +for (int i =0 ; i <ARRAY_SIZE (iommu_buses); i++) { +if (iommu_buses[i] == bus) { +spin_lock (&iommu_device_lock); + ret = !list_empty (&iommu_device_list); +spin_unlock (&iommu_device_lock); + } + } +return ret; }EXPORT_SYMBOL_GPL (iommu_present);
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
Robin Murphy
reviewerPATCH v6 3/7 iommu: Validate that devices match domains
In reply to Robin MurphyBefore we can allow drivers to coexist, we need to make sure that one driver's domain ops can't misinterpret another driver's dev_iommu_priv data. To that end, add a token to the domain so we can remember how it was allocated - for now this may as well be the device ops, since they still correlate 1:1 with drivers. We can trust ourselves for internal default domain attachment, so add checks to cover all the public attach interfaces.
---
v4: Cover iommu_attach_device_pasid() as well, and improve robustness
against theoretical attempts to attach a noiommu group.
v6: Cover new iommu_domain_alloc_user() sites as well. I don't entirely
dislike the idea of tying this into the domain ops, but I'd rather do the simple thing for now and revisit that in future, since domain ops also deserve some other cleanup.
--- drivers/iommu/iommu.c | 10 ++++++++++ drivers/iommu/iommufd/hw_pagetable.c | 2 ++ include/linux/iommu.h | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-)
drivers/iommu/iommu.c +10 -0
@@ -2117,6 +2117,7 @@ static struct iommu_domain *__iommu_domain_alloc(const struct iommu_ops *ops,return NULL ; domain->type = type; + domain->owner = ops;/* * If not already set, assume all sizes by default; the driver * may override this later
@@ -2282,10 +2283,16 @@ struct iommu_domain *iommu_get_dma_domain(struct device *dev)static int __iommu_attach_group (struct iommu_domain *domain,struct iommu_group *group) { +struct device *dev; +if (group->domain && group->domain != group->default_domain && group->domain != group->blocking_domain)return -EBUSY ; + dev =iommu_group_first_dev (group); +if (!dev_has_iommu (dev) ||dev_iommu_ops (dev) != domain->owner) +return -EINVAL ; +return __iommu_group_set_domain (group, domain); }
@@ -3477,6 +3484,9 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,if (!group)return -ENODEV ; +if (!dev_has_iommu (dev) ||dev_iommu_ops (dev) != domain->owner) +return -EINVAL ; +mutex_lock (&group->mutex); curr =xa_cmpxchg (&group->pasid_array, pasid,NULL , domain,GFP_KERNEL );if (curr) {
drivers/iommu/iommufd/hw_pagetable.c +2 -0
@@ -135,6 +135,7 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas, hwpt->domain =NULL ; goto out_abort; } + hwpt->domain->owner = ops; }else { hwpt->domain =iommu_domain_alloc (idev->dev->bus);if (!hwpt->domain) {
@@ -233,6 +234,7 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx, hwpt->domain =NULL ; goto out_abort; } + hwpt->domain->owner = ops;if (WARN_ON_ONCE (hwpt->domain->type !=IOMMU_DOMAIN_NESTED )) { rc = -EINVAL ;
include/linux/iommu.h +1 -1
@@ -106,7 +106,7 @@ struct iommu_domain {unsigned type;const struct iommu_domain_ops *ops;const struct iommu_dirty_ops *dirty_ops; - +const struct iommu_ops *owner;/* Whose domain_alloc we came from */ unsigned long pgsize_bitmap;/* Bitmap of page sizes in use */ struct iommu_domain_geometry geometry;struct iommu_dma_cookie *iova_cookie;
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
Jason Gunthorpe
maintainerRe: [PATCH v6 3/7] iommu: Validate that devices match domains
Quoted 13 lines · Robin Murphy
Before we can allow drivers to coexist, we need to make sure that one driver's domain ops can't misinterpret another driver's
dev_iommu_privdata. To that end, add a token to the domain so we can remember how it was allocated - for now this may as well be the device ops, since they still correlate 1:1 with drivers. We can trust ourselves for internal default domain attachment, so add checks to cover all the public attach interfaces.Reviewed-by Lu Baolu <[email protected]>Reviewed-by Jason Gunthorpe <[email protected]>Reviewed-by Jerry Snitselaar <[email protected]>Signed-off-by Robin Murphy <[email protected]>
Quoted 8 lines
---
v4: Cover
iommu_attach_device_pasid()as well, and improve robustness
against theoretical attempts to attach a noiommu group.
v6: Cover newiommu_domain_alloc_user()sites as well. I don't entirely
dislike the idea of tying this into the domain ops, but I'd rather do the simple thing for now and revisit that in future, since domain ops also deserve some other cleanup.
Looks good
Jason
Robin Murphy
reviewerPATCH v6 4/7 iommu: Decouple iommu_domain_alloc() from bus ops
In reply to Robin MurphyAs the final remaining piece of bus-dependent API, iommu_domain_alloc() can now take responsibility for the "one iommu_ops per bus" rule for itself. It turns out we can't safely make the internal allocation call any more group-based or device-based yet - that will have to wait until the external callers can pass the right thing - but we can at least get as far as deriving "bus ops" based on which driver is actually managing devices on the given bus, rather than whichever driver won the race to register first.
This will then leave us able to convert the last of the core internals over to the IOMMU-instance model, allow multiple drivers to register and actually coexist (modulo the above limitation for unmanaged domain users in the short term), and start trying to solve the long-standing iommu_probe_device() mess.
---
v5: Rewrite, de-scoping to just retrieve ops under the same assumptions
as the existing code.
--- drivers/iommu/iommu.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-)
drivers/iommu/iommu.c +22 -3
@@ -2143,12 +2143,31 @@ __iommu_group_domain_alloc(struct iommu_group *group, unsigned int type)return __iommu_domain_alloc (dev_iommu_ops (dev), dev, type); } +static int __iommu_domain_alloc_dev (struct device *dev,void *data) +{ +const struct iommu_ops **ops = data; + +if (!dev_has_iommu (dev)) +return 0 ; + +if (WARN_ONCE (*ops && *ops !=dev_iommu_ops (dev), +"Multiple IOMMU drivers present for bus %s, which the public IOMMU API can't fully support yet. You will still need to disable one or more for this to work, sorry!\n" , +dev_bus_name (dev))) +return -EBUSY ; + + *ops =dev_iommu_ops (dev); +return 0 ; +} +struct iommu_domain *iommu_domain_alloc (const struct bus_type *bus) { -if (bus ==NULL || bus->iommu_ops ==NULL ) +const struct iommu_ops *ops =NULL ; +int err =bus_for_each_dev (bus,NULL , &ops, __iommu_domain_alloc_dev); + +if (err || !ops)return NULL ; -return __iommu_domain_alloc (bus->iommu_ops,NULL , -IOMMU_DOMAIN_UNMANAGED ); + +return __iommu_domain_alloc (ops,NULL ,IOMMU_DOMAIN_UNMANAGED ); }EXPORT_SYMBOL_GPL (iommu_domain_alloc);
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
Re: [PATCH v6 4/7] iommu: Decouple iommu_domain_alloc() from bus ops
Quoted 19 lines · Robin Murphy
As the final remaining piece of bus-dependent API,
iommu_domain_alloc()can now take responsibility for the "oneiommu_opsper bus" rule for itself. It turns out we can't safely make the internal allocation call any more group-based or device-based yet - that will have to wait until the external callers can pass the right thing - but we can at least get as far as deriving "bus ops" based on which driver is actually managing devices on the given bus, rather than whichever driver won the race to register first.This will then leave us able to convert the last of the core internals over to the IOMMU-instance model, allow multiple drivers to register and actually coexist (modulo the above limitation for unmanaged domain users in the short term), and start trying to solve the long-standing
iommu_probe_device()mess.Reviewed-by Jason Gunthorpe<[email protected]>Reviewed-by Jerry Snitselaar<[email protected]>Signed-off-by Robin Murphy<[email protected]>
Quoted 7 lines
---
v5: Rewrite, de-scoping to just retrieve ops under the same assumptions
as the existing code.--- drivers/iommu/iommu.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-)
Best regards,
baolu
Robin Murphy
reviewerPATCH v6 5/7 iommu/arm-smmu: Don't register fwnode for legacy binding
In reply to Robin MurphyWhen using the legacy binding we bypass the of_xlate mechanism, so avoid registering the instance fwnodes which act as keys for that. This will help __iommu_probe_device() to retrieve the registered ops the same way as for x86 etc. when no fwspec has previously been set up by of_xlate.
--- drivers/iommu/arm/arm-smmu/arm-smmu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/iommu/arm/arm-smmu/arm-smmu.c +2 -1
@@ -2161,7 +2161,8 @@ static int arm_smmu_device_probe(struct platform_device *pdev)return err; } - err =iommu_device_register (&smmu->iommu, &arm_smmu_ops, dev); + err =iommu_device_register (&smmu->iommu, &arm_smmu_ops, + using_legacy_binding ?NULL : dev);if (err) {dev_err (dev,"Failed to register iommu\n" );iommu_device_sysfs_remove (&smmu->iommu);
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
Robin Murphy
reviewerPATCH v6 6/7 iommu: Retire bus ops
In reply to Robin MurphyWith the rest of the API internals converted, it's time to finally tackle probe_device and how we bootstrap the per-device ops association to begin with. This ends up being disappointingly straightforward, since fwspec users are already doing it in order to find their of_xlate callback, and it works out that we can easily do the equivalent for other drivers too. Then shuffle the remaining awareness of iommu_ops into the couple of core headers that still need it, and breathe a sigh of relief.
Ding dong the bus ops are gone!
---
v4: Don't forget new reference in iommu_device_register_bus()
--- drivers/iommu/iommu.c | 31 ++++++++++++++++++------------- include/acpi/acpi_bus.h | 2 ++ include/linux/device.h | 1 - include/linux/device/bus.h | 5 ----- include/linux/dma-map-ops.h | 1 + 5 files changed, 21 insertions(+), 19 deletions(-)
drivers/iommu/iommu.c +18 -13
@@ -148,7 +148,7 @@ struct iommu_group_attribute iommu_group_attr_##_name = \static LIST_HEAD (iommu_device_list);static DEFINE_SPINLOCK (iommu_device_lock); -static struct bus_type *const iommu_buses[] = { +static const struct bus_type *const iommu_buses[] = { &platform_bus_type, #ifdef CONFIG_PCI &pci_bus_type,
@@ -257,13 +257,6 @@ int iommu_device_register(struct iommu_device *iommu,/* We need to be able to take module references appropriately */ if (WARN_ON (is_module_address ((unsigned long )ops) && !ops->owner))return -EINVAL ; -/* -* Temporarily enforce global restriction to a single driver. This was -* already the de-facto behaviour, since any possible combination of -* existing drivers would compete for at least the PCI or platform bus. -*/ -if (iommu_buses[0 ]->iommu_ops && iommu_buses[0 ]->iommu_ops != ops) -return -EBUSY ; iommu->ops = ops;if (hwdev)
@@ -273,10 +266,8 @@ int iommu_device_register(struct iommu_device *iommu,list_add_tail (&iommu->list, &iommu_device_list);spin_unlock (&iommu_device_lock); -for (int i =0 ; i <ARRAY_SIZE (iommu_buses) && !err; i++) { - iommu_buses[i]->iommu_ops = ops; +for (int i =0 ; i <ARRAY_SIZE (iommu_buses) && !err; i++) err =bus_iommu_probe (iommu_buses[i]); - }if (err)iommu_device_unregister (iommu);return err;
@@ -329,7 +320,6 @@ int iommu_device_register_bus(struct iommu_device *iommu,list_add_tail (&iommu->list, &iommu_device_list);spin_unlock (&iommu_device_lock); - bus->iommu_ops = ops; err =bus_iommu_probe (bus);if (err) {iommu_device_unregister_bus (iommu, bus, nb);
@@ -496,12 +486,27 @@ static void iommu_deinit_device(struct device *dev)static int __iommu_probe_device (struct device *dev,struct list_head *group_list) { -const struct iommu_ops *ops = dev->bus->iommu_ops; +const struct iommu_ops *ops; +struct iommu_fwspec *fwspec;struct iommu_group *group;static DEFINE_MUTEX (iommu_probe_device_lock);struct group_device *gdev;int ret; +/* +* For FDT-based systems and ACPI IORT/VIOT, drivers register IOMMU +* instances with non-NULL fwnodes, and client devices should have been +* identified with a fwspec by this point. Otherwise, we can currently +* assume that only one of Intel, AMD, s390, PAMU or legacy SMMUv2 can +* be present, and that any of their registered instances has suitable +* ops for probing, and thus cheekily co-opt the same mechanism. +*/ + fwspec =dev_iommu_fwspec_get (dev); +if (fwspec && fwspec->ops) + ops = fwspec->ops; +else + ops =iommu_ops_from_fwnode (NULL ); +if (!ops)return -ENODEV ;/*
include/acpi/acpi_bus.h +2 -0
@@ -626,6 +626,8 @@ struct acpi_pci_root {/* helper */ +struct iommu_ops ; +bool acpi_dma_supported (const struct acpi_device *adev);enum dev_dma_attr acpi_get_dma_attr (struct acpi_device *adev); int acpi_iommu_fwspec_init(struct device *dev, u32 id,
include/linux/device.h +0 -1
@@ -42,7 +42,6 @@ struct class;struct subsys_private ;struct device_node ;struct fwnode_handle ; -struct iommu_ops ;struct iommu_group ;struct dev_pin_info ;struct dev_iommu ;
include/linux/device/bus.h +0 -5
@@ -62,9 +62,6 @@ struct fwnode_handle;* this bus. * @pm: Power management operations of this bus, callback the specific * device driver's pm-ops. -* @iommu_ops: IOMMU specific operations for this bus, used to attach IOMMU -* driver implementations to a bus and allow the driver to do -* bus-specific setup * @need_parent_lock: When probing or removing a device on this bus, the * device core should lock the device's parent. *
@@ -104,8 +101,6 @@ struct bus_type {const struct dev_pm_ops *pm; -const struct iommu_ops *iommu_ops; -bool need_parent_lock; };
include/linux/dma-map-ops.h +1 -0
@@ -11,6 +11,7 @@#include <linux/slab.h> struct cma ; +struct iommu_ops ;/* * Values for struct dma_map_ops.flags:
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
Robin Murphy
reviewerPATCH v6 7/7 iommu: Clean up open-coded ownership checks
In reply to Robin MurphySome drivers already implement their own defence against the possibility of being given someone else's device. Since this is now taken care of by the core code (and via a slightly different path from the original fwspec-based idea), let's clean them up.
--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 3 --- drivers/iommu/arm/arm-smmu/arm-smmu.c | 9 +-------- drivers/iommu/arm/arm-smmu/qcom_iommu.c | 16 +++------------- drivers/iommu/mtk_iommu.c | 7 +------ drivers/iommu/mtk_iommu_v1.c | 3 --- drivers/iommu/sprd-iommu.c | 8 +------- drivers/iommu/virtio-iommu.c | 3 --- 7 files changed, 6 insertions(+), 43 deletions(-)
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +0 -3
@@ -2649,9 +2649,6 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)struct arm_smmu_master *master;struct iommu_fwspec *fwspec =dev_iommu_fwspec_get (dev); -if (!fwspec || fwspec->ops != &arm_smmu_ops) -return ERR_PTR (-ENODEV ); -if (WARN_ON_ONCE (dev_iommu_priv_get (dev)))return ERR_PTR (-EBUSY );
drivers/iommu/arm/arm-smmu/arm-smmu.c +1 -8
@@ -1116,11 +1116,6 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)struct arm_smmu_device *smmu;int ret; -if (!fwspec || fwspec->ops != &arm_smmu_ops) { -dev_err (dev,"cannot attach to SMMU, is it on the same bus?\n" ); -return -ENXIO ; - } -/* * FIXME: The arch/arm DMA API code tries to attach devices to its own * domains between of_xlate() and probe_device() - we have no way to cope
@@ -1357,10 +1352,8 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev) fwspec =dev_iommu_fwspec_get (dev);if (ret) goto out_free; - }else if (fwspec && fwspec->ops == &arm_smmu_ops) { - smmu =arm_smmu_get_by_fwnode (fwspec->iommu_fwnode); }else { -return ERR_PTR (-ENODEV ); + smmu =arm_smmu_get_by_fwnode (fwspec->iommu_fwnode); } ret = -EINVAL ;
drivers/iommu/arm/arm-smmu/qcom_iommu.c +3 -13
@@ -79,16 +79,6 @@ static struct qcom_iommu_domain *to_qcom_iommu_domain(struct iommu_domain *dom)static const struct iommu_ops qcom_iommu_ops; -static struct qcom_iommu_dev *to_iommu (struct device *dev) -{ -struct iommu_fwspec *fwspec =dev_iommu_fwspec_get (dev); - -if (!fwspec || fwspec->ops != &qcom_iommu_ops) -return NULL ; - -return dev_iommu_priv_get (dev); -} -static struct qcom_iommu_ctx *to_ctx (struct qcom_iommu_domain *d,unsigned asid) {struct qcom_iommu_dev *qcom_iommu = d->iommu;
@@ -372,7 +362,7 @@ static void qcom_iommu_domain_free(struct iommu_domain *domain)static int qcom_iommu_attach_dev (struct iommu_domain *domain,struct device *dev) { -struct qcom_iommu_dev *qcom_iommu =to_iommu (dev); +struct qcom_iommu_dev *qcom_iommu =dev_iommu_priv_get (dev);struct qcom_iommu_domain *qcom_domain =to_qcom_iommu_domain (domain);int ret;
@@ -404,7 +394,7 @@ static int qcom_iommu_identity_attach(struct iommu_domain *identity_domain,struct iommu_domain *domain =iommu_get_domain_for_dev (dev);struct qcom_iommu_domain *qcom_domain;struct iommu_fwspec *fwspec =dev_iommu_fwspec_get (dev); -struct qcom_iommu_dev *qcom_iommu =to_iommu (dev); +struct qcom_iommu_dev *qcom_iommu =dev_iommu_priv_get (dev);unsigned int i;if (domain == identity_domain || !domain)
@@ -535,7 +525,7 @@ static bool qcom_iommu_capable(struct device *dev, enum iommu_cap cap)static struct iommu_device *qcom_iommu_probe_device (struct device *dev) { -struct qcom_iommu_dev *qcom_iommu =to_iommu (dev); +struct qcom_iommu_dev *qcom_iommu =dev_iommu_priv_get (dev);struct device_link *link;if (!qcom_iommu)
drivers/iommu/mtk_iommu.c +1 -6
@@ -863,16 +863,11 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,static struct iommu_device *mtk_iommu_probe_device (struct device *dev) {struct iommu_fwspec *fwspec =dev_iommu_fwspec_get (dev); -struct mtk_iommu_data *data; +struct mtk_iommu_data *data =dev_iommu_priv_get (dev);struct device_link *link;struct device *larbdev;unsigned int larbid, larbidx, i; -if (!fwspec || fwspec->ops != &mtk_iommu_ops) -return ERR_PTR (-ENODEV );/* Not a iommu client device */ - - data =dev_iommu_priv_get (dev); -if (!MTK_IOMMU_IS_TYPE (data->plat_data,MTK_IOMMU_TYPE_MM ))return &data->iommu;
drivers/iommu/mtk_iommu_v1.c +0 -3
@@ -481,9 +481,6 @@ static struct iommu_device *mtk_iommu_v1_probe_device(struct device *dev) idx++; } -if (!fwspec || fwspec->ops != &mtk_iommu_v1_ops) -return ERR_PTR (-ENODEV );/* Not a iommu client device */ - data =dev_iommu_priv_get (dev);/* Link the consumer device with the smi-larb device(supplier) */
drivers/iommu/sprd-iommu.c +1 -7
@@ -385,13 +385,7 @@ static phys_addr_t sprd_iommu_iova_to_phys(struct iommu_domain *domain,static struct iommu_device *sprd_iommu_probe_device (struct device *dev) { -struct iommu_fwspec *fwspec =dev_iommu_fwspec_get (dev); -struct sprd_iommu_device *sdev; - -if (!fwspec || fwspec->ops != &sprd_iommu_ops) -return ERR_PTR (-ENODEV ); - - sdev =dev_iommu_priv_get (dev); +struct sprd_iommu_device *sdev =dev_iommu_priv_get (dev);return &sdev->iommu; }
drivers/iommu/virtio-iommu.c +0 -3
@@ -969,9 +969,6 @@ static struct iommu_device *viommu_probe_device(struct device *dev)struct viommu_dev *viommu =NULL ;struct iommu_fwspec *fwspec =dev_iommu_fwspec_get (dev); -if (!fwspec || fwspec->ops != &viommu_ops) -return ERR_PTR (-ENODEV ); - viommu =viommu_get_by_fwnode (fwspec->iommu_fwnode);if (!viommu)return ERR_PTR (-ENODEV );
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
Quoted 8 lines · Robin Murphy
Robin Murphy (7):
iommu: Factor out some helpers
iommu: Decoupleiommu_present()from bus ops
iommu: Validate that devices match domains
iommu: Decoupleiommu_domain_alloc()from bus ops iommu/arm-smmu: Don't register fwnode for legacy binding
iommu: Retire bus ops
iommu: Clean up open-coded ownership checks
Applied, thanks.