This is preparation for the next patch. Each iommu driver is associated with a 'struct iommu_device' handle. Pass in the iommu_device to bus_iommu_probe() and all the way through to probe_iommu_group(). omap is weird, it has a whole bunch of iommu devices that it creates a struct omap_iommu for, but it only registers some of them with the subsystem. In the case it doesn't register then it has to open code the call to bus_iommu_probe() as it's omap_iommu_probe_device() function is sensitive. Pass in the unregistered iommu_device struct and move this code into an else block since there is no sense in calling bus_iommu_probe() twice in a row. Reviewed-by: Kevin Tian <kevin.tian@xxxxxxxxx> Tested-by: Chen-Yu Tsai <wenst@xxxxxxxxxxxx> Signed-off-by: Jason Gunthorpe <jgg@xxxxxxxxxx> --- drivers/iommu/iommu.c | 18 +++++++++++++----- drivers/iommu/omap-iommu.c | 11 ++++++++--- include/linux/iommu.h | 3 ++- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index ecf61bd3cfb076..19fdb1a220240f 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -273,7 +273,7 @@ int iommu_device_register(struct iommu_device *iommu, for (int i = 0; i < ARRAY_SIZE(iommu_buses) && !err; i++) { iommu_buses[i]->iommu_ops = ops; - err = bus_iommu_probe(iommu_buses[i]); + err = bus_iommu_probe(iommu_buses[i], iommu); } if (err) iommu_device_unregister(iommu); @@ -1792,13 +1792,18 @@ struct iommu_domain *iommu_group_default_domain(struct iommu_group *group) return group->default_domain; } +struct probe_iommu_args { + struct list_head *group_list; + struct iommu_device *iommu; +}; + static int probe_iommu_group(struct device *dev, void *data) { - struct list_head *group_list = data; + struct probe_iommu_args *args = data; int ret; device_lock(dev); - ret = __iommu_probe_device(dev, group_list); + ret = __iommu_probe_device(dev, args->group_list); device_unlock(dev); if (ret == -ENODEV) ret = 0; @@ -1868,13 +1873,16 @@ static void iommu_group_do_probe_finalize(struct device *dev) ops->probe_finalize(dev); } -int bus_iommu_probe(const struct bus_type *bus) +int bus_iommu_probe(const struct bus_type *bus, struct iommu_device *iommu) { + struct probe_iommu_args args = {}; struct iommu_group *group, *next; LIST_HEAD(group_list); int ret; - ret = bus_for_each_dev(bus, NULL, &group_list, probe_iommu_group); + args.group_list = &group_list; + args.iommu = iommu; + ret = bus_for_each_dev(bus, NULL, &args, probe_iommu_group); if (ret) return ret; diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index 97c45f50bf4332..1e4a90ec64322b 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -1234,6 +1234,14 @@ static int omap_iommu_probe(struct platform_device *pdev) if (err) goto out_sysfs; obj->has_iommu_driver = true; + } else { + /* + * omap_iommu_probe_device() requires all the iommus associated + * with a device to have been probed to succeed. We just created + * an iommu without registering it, so re-run probe again to try + * to match any devices that are waiting for this iommu. + */ + bus_iommu_probe(&platform_bus_type, &obj->iommu); } pm_runtime_enable(obj->dev); @@ -1242,9 +1250,6 @@ static int omap_iommu_probe(struct platform_device *pdev) dev_info(&pdev->dev, "%s registered\n", obj->name); - /* Re-probe bus to probe device attached to this IOMMU */ - bus_iommu_probe(&platform_bus_type); - return 0; out_sysfs: diff --git a/include/linux/iommu.h b/include/linux/iommu.h index cb4fc518797039..cc47e4086d69ec 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -465,7 +465,8 @@ static inline const struct iommu_ops *dev_iommu_ops(struct device *dev) return dev->iommu->iommu_dev->ops; } -extern int bus_iommu_probe(const struct bus_type *bus); +extern int bus_iommu_probe(const struct bus_type *bus, + struct iommu_device *iommu); extern bool iommu_present(const struct bus_type *bus); extern bool device_iommu_capable(struct device *dev, enum iommu_cap cap); extern bool iommu_group_has_isolated_msi(struct iommu_group *group); -- 2.41.0