From: Greg Kroah-Hartman Date: Mon, 2 Jun 2025 12:27:34 +0000 (+0200) Subject: 6.14-stable patches X-Git-Tag: v5.4.294~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=80e250bf38d6d436bea2dab45c556cf2335f956d;p=thirdparty%2Fkernel%2Fstable-queue.git 6.14-stable patches added patches: iommu-handle-yet-another-race-around-registration.patch --- diff --git a/queue-6.14/iommu-handle-yet-another-race-around-registration.patch b/queue-6.14/iommu-handle-yet-another-race-around-registration.patch new file mode 100644 index 0000000000..783b5b0edd --- /dev/null +++ b/queue-6.14/iommu-handle-yet-another-race-around-registration.patch @@ -0,0 +1,119 @@ +From da33e87bd2bfc63531cf7448a3cd7a3d42182f08 Mon Sep 17 00:00:00 2001 +From: Robin Murphy +Date: Thu, 24 Apr 2025 18:41:28 +0100 +Subject: iommu: Handle yet another race around registration + +From: Robin Murphy + +commit da33e87bd2bfc63531cf7448a3cd7a3d42182f08 upstream. + +Next up on our list of race windows to close is another one during +iommu_device_register() - it's now OK again for multiple instances to +run their bus_iommu_probe() in parallel, but an iommu_probe_device() can +still also race against a running bus_iommu_probe(). As Johan has +managed to prove, this has now become a lot more visible on DT platforms +wth driver_async_probe where a client driver is attempting to probe in +parallel with its IOMMU driver - although commit b46064a18810 ("iommu: +Handle race with default domain setup") resolves this from the client +driver's point of view, this isn't before of_iommu_configure() has had +the chance to attempt to "replay" a probe that the bus walk hasn't even +tried yet, and so still cause the out-of-order group allocation +behaviour that we're trying to clean up (and now warning about). + +The most reliable thing to do here is to explicitly keep track of the +"iommu_device_register() is still running" state, so we can then +special-case the ops lookup for the replay path (based on dev->iommu +again) to let that think it's still waiting for the IOMMU driver to +appear at all. This still leaves the longstanding theoretical case of +iommu_bus_notifier() being triggered during bus_iommu_probe(), but it's +not so simple to defer a notifier, and nobody's ever reported that being +a visible issue, so let's quietly kick that can down the road for now... + +Reported-by: Johan Hovold +Fixes: bcb81ac6ae3c ("iommu: Get DT/ACPI parsing into the proper probe path") +Signed-off-by: Robin Murphy +Link: https://lore.kernel.org/r/88d54c1b48fed8279aa47d30f3d75173685bb26a.1745516488.git.robin.murphy@arm.com +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/iommu.c | 26 ++++++++++++++++++-------- + include/linux/iommu.h | 2 ++ + 2 files changed, 20 insertions(+), 8 deletions(-) + +--- a/drivers/iommu/iommu.c ++++ b/drivers/iommu/iommu.c +@@ -273,6 +273,8 @@ int iommu_device_register(struct iommu_d + err = bus_iommu_probe(iommu_buses[i]); + if (err) + iommu_device_unregister(iommu); ++ else ++ WRITE_ONCE(iommu->ready, true); + return err; + } + EXPORT_SYMBOL_GPL(iommu_device_register); +@@ -2801,31 +2803,39 @@ bool iommu_default_passthrough(void) + } + EXPORT_SYMBOL_GPL(iommu_default_passthrough); + +-const struct iommu_ops *iommu_ops_from_fwnode(const struct fwnode_handle *fwnode) ++static const struct iommu_device *iommu_from_fwnode(const struct fwnode_handle *fwnode) + { +- const struct iommu_ops *ops = NULL; +- struct iommu_device *iommu; ++ const struct iommu_device *iommu, *ret = NULL; + + spin_lock(&iommu_device_lock); + list_for_each_entry(iommu, &iommu_device_list, list) + if (iommu->fwnode == fwnode) { +- ops = iommu->ops; ++ ret = iommu; + break; + } + spin_unlock(&iommu_device_lock); +- return ops; ++ return ret; ++} ++ ++const struct iommu_ops *iommu_ops_from_fwnode(const struct fwnode_handle *fwnode) ++{ ++ const struct iommu_device *iommu = iommu_from_fwnode(fwnode); ++ ++ return iommu ? iommu->ops : NULL; + } + + int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode) + { +- const struct iommu_ops *ops = iommu_ops_from_fwnode(iommu_fwnode); ++ const struct iommu_device *iommu = iommu_from_fwnode(iommu_fwnode); + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + +- if (!ops) ++ if (!iommu) + return driver_deferred_probe_check_state(dev); ++ if (!dev->iommu && !READ_ONCE(iommu->ready)) ++ return -EPROBE_DEFER; + + if (fwspec) +- return ops == iommu_fwspec_ops(fwspec) ? 0 : -EINVAL; ++ return iommu->ops == iommu_fwspec_ops(fwspec) ? 0 : -EINVAL; + + if (!dev_iommu_get(dev)) + return -ENOMEM; +--- a/include/linux/iommu.h ++++ b/include/linux/iommu.h +@@ -735,6 +735,7 @@ struct iommu_domain_ops { + * @dev: struct device for sysfs handling + * @singleton_group: Used internally for drivers that have only one group + * @max_pasids: number of supported PASIDs ++ * @ready: set once iommu_device_register() has completed successfully + */ + struct iommu_device { + struct list_head list; +@@ -743,6 +744,7 @@ struct iommu_device { + struct device *dev; + struct iommu_group *singleton_group; + u32 max_pasids; ++ bool ready; + }; + + /** diff --git a/queue-6.14/series b/queue-6.14/series index 7935f5a92e..f249d23d45 100644 --- a/queue-6.14/series +++ b/queue-6.14/series @@ -42,3 +42,4 @@ net_sched-hfsc-address-reentrant-enqueue-adding-class-to-eltree-twice.patch perf-arm-cmn-fix-req2-snp2-mixup.patch perf-arm-cmn-initialise-cmn-cpu-earlier.patch perf-arm-cmn-add-cmn-s3-acpi-binding.patch +iommu-handle-yet-another-race-around-registration.patch