This interface allows removal of IOMMU from a bus if needed. For example, when the IOMMU driver fails to initialize, it should unassociate itself from the bus (i.e. removing IOMMU groups and unregister bus notifier block).
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpa...@amd.com> --- drivers/iommu/iommu.c | 22 ++++++++++++++++++++++ include/linux/device.h | 1 + include/linux/iommu.h | 1 + 3 files changed, 24 insertions(+) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index d2aa2320..56691ab 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1165,6 +1165,7 @@ static int iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops) if (err) goto out_err; + bus->iommu_nb = nb; return 0; @@ -1179,6 +1180,27 @@ static int iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops) return err; } +void bus_unset_iommu(struct bus_type *bus, const struct iommu_ops *ops) +{ + struct iommu_callback_data cb = { + .ops = ops, + }; + + if (!bus->iommu_ops) + return; + + bus_for_each_dev(bus, NULL, &cb, remove_iommu_group); + + if (bus->iommu_nb) { + bus_unregister_notifier(bus, bus->iommu_nb); + kfree(bus->iommu_nb); + bus->iommu_nb = NULL; + } + + bus->iommu_ops = NULL; +} +EXPORT_SYMBOL_GPL(bus_unset_iommu); + /** * bus_set_iommu - set iommu-callbacks for the bus * @bus: bus. diff --git a/include/linux/device.h b/include/linux/device.h index 4779569..cac7baf 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -133,6 +133,7 @@ struct bus_type { const struct dev_pm_ops *pm; const struct iommu_ops *iommu_ops; + struct notifier_block *iommu_nb; struct subsys_private *p; struct lock_class_key lock_key; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 19938ee..65f998e 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -287,6 +287,7 @@ static inline struct iommu_device *dev_to_iommu_device(struct device *dev) #define IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER 6 /* Post Driver unbind */ extern int bus_set_iommu(struct bus_type *bus, const struct iommu_ops *ops); +extern void bus_unset_iommu(struct bus_type *bus, const struct iommu_ops *ops); extern bool iommu_present(struct bus_type *bus); extern bool iommu_capable(struct bus_type *bus, enum iommu_cap cap); extern struct iommu_domain *iommu_domain_alloc(struct bus_type *bus); -- 2.7.4 _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu