The two callers coming from bus_tye -> dma_configure() already have the device_lock held for the device being probed. Mark this in the API so that the core code doesn't attempt to re-acquire the same lock and deadlock. __iommu_probe_device from iommu_probe_device+0x10/0x40 iommu_probe_device from of_iommu_configure+0xf8/0x1c8 of_iommu_configure from of_dma_configure_id+0x188/0x450 of_dma_configure_id from platform_dma_configure+0x24/0x60 platform_dma_configure from really_probe+0xac/0x3d4 really_probe from __driver_probe_device+0xa0/0x1e8 __driver_probe_device from driver_probe_device+0x30/0xd0 driver_probe_device from __driver_attach+0x10c/0x190 __driver_attach from bus_for_each_dev+0x60/0xb4 bus_for_each_dev from bus_add_driver+0xe0/0x208 bus_add_driver from driver_register+0x7c/0x118 driver_register from exynos_drm_init+0xe0/0x14c exynos_drm_init from do_one_initcall+0x6c/0x318 do_one_initcall from kernel_init_freeable+0x1c4/0x214 kernel_init_freeable from kernel_init+0x18/0x12c kernel_init from ret_from_fork+0x14/0x2c Internally make __iommu_probe_device() require the caller to get the device_lock(). The three remaining callers of iommu_probe_device() don't seem to hold the device_lock(): powerpc/kernel/iommu.c: iommu_add_device() iommu/iommu.c: iommu_bus_notifier()/BUS_NOTIFY_ADD_DEVICE/ intel/iommu.c: probe_acpi_namespace_devices() Fixes: a2dde836050f ("iommu: Complete the locking for dev->iommu_group") Reported-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx> Closes: https://lore.kernel.org/linux-iommu/bc5d6aa8-e8ca-c896-2f39-af074d55e436@xxxxxxxxxxx Tested-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx> Signed-off-by: Jason Gunthorpe <jgg@xxxxxxxxxx> --- drivers/acpi/scan.c | 5 +++-- drivers/iommu/iommu.c | 34 ++++++++++++++++++++++------------ drivers/iommu/of_iommu.c | 2 +- include/linux/iommu.h | 1 + 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index daa64dd687524b..3771164af60279 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1579,10 +1579,11 @@ static const struct iommu_ops *acpi_iommu_configure_id(struct device *dev, /* * If we have reason to believe the IOMMU driver missed the initial - * iommu_probe_device() call for dev, replay it to get things in order. + * iommu_probe_device_locked() call for dev, replay it to get things in + * order. */ if (!err && dev->bus) - err = iommu_probe_device(dev); + err = iommu_probe_device_locked(dev); /* Ignore all other errors apart from EPROBE_DEFER */ if (err == -EPROBE_DEFER) { diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 25d7327e8013e7..ecf61bd3cfb076 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -452,24 +452,23 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list struct group_device *gdev; int ret; - if (!ops) - return -ENODEV; /* * Allow __iommu_probe_device() to be safely called in parallel, * both dev->iommu_group and the initial setup of dev->iommu are * protected this way. */ - device_lock(dev); + device_lock_assert(dev); + + if (!ops) + return -ENODEV; /* Device is probed already if in a group */ - if (dev->iommu_group) { - ret = 0; - goto out_unlock; - } + if (dev->iommu_group) + return 0; ret = iommu_init_device(dev, ops); if (ret) - goto out_unlock; + return ret; group = dev->iommu_group; gdev = iommu_group_alloc_device(group, dev); @@ -505,7 +504,6 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list list_add_tail(&group->entry, group_list); } mutex_unlock(&group->mutex); - device_unlock(dev); if (dev_is_pci(dev)) iommu_dma_set_pci_32bit_workaround(dev); @@ -519,16 +517,16 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list iommu_deinit_device(dev); mutex_unlock(&group->mutex); iommu_group_put(group); -out_unlock: - device_unlock(dev); return ret; } -int iommu_probe_device(struct device *dev) +int iommu_probe_device_locked(struct device *dev) { const struct iommu_ops *ops; int ret; + device_lock_assert(dev); + ret = __iommu_probe_device(dev, NULL); if (ret) return ret; @@ -540,6 +538,16 @@ int iommu_probe_device(struct device *dev) return 0; } +int iommu_probe_device(struct device *dev) +{ + int ret; + + device_lock(dev); + ret = iommu_probe_device_locked(dev); + device_unlock(dev); + return ret; +} + static void __iommu_group_free_device(struct iommu_group *group, struct group_device *grp_dev) { @@ -1789,7 +1797,9 @@ static int probe_iommu_group(struct device *dev, void *data) struct list_head *group_list = data; int ret; + device_lock(dev); ret = __iommu_probe_device(dev, group_list); + device_unlock(dev); if (ret == -ENODEV) ret = 0; diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index 157b286e36bf3a..b5b7d4bd2cefb9 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -160,7 +160,7 @@ const struct iommu_ops *of_iommu_configure(struct device *dev, * probe for dev, replay it to get things in order. */ if (!err && dev->bus) - err = iommu_probe_device(dev); + err = iommu_probe_device_locked(dev); /* Ignore all other errors apart from EPROBE_DEFER */ if (err == -EPROBE_DEFER) { diff --git a/include/linux/iommu.h b/include/linux/iommu.h index f1e18e81fca78b..cb4fc518797039 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -709,6 +709,7 @@ static inline void dev_iommu_priv_set(struct device *dev, void *priv) } int iommu_probe_device(struct device *dev); +int iommu_probe_device_locked(struct device *dev); int iommu_dev_enable_feature(struct device *dev, enum iommu_dev_features f); int iommu_dev_disable_feature(struct device *dev, enum iommu_dev_features f); -- 2.41.0