Skip to content

Commit 7d83513

Browse files
rmurphy-armwilldeacon
authored andcommitted
iommu/arm-smmu: Make instance lookup robust
Relying on the driver list was a cute idea for minimising the scope of our SMMU device lookups, however it turns out to have a subtle flaw. The SMMU device only gets added to that list after arm_smmu_device_probe() returns success, so there's actually no way the iommu_device_register() call from there could ever work as intended, even if it wasn't already hampered by the fwspec setup not happening early enough. Switch both arm_smmu_get_by_fwnode() implementations to use a platform bus lookup instead, which *will* reliably work. Also make sure that we don't register SMMUv2 instances until we've fully initialised them, to avoid similar consequences of the lookup now finding a device with no drvdata. Moving the error returns is also a perfect excuse to streamline them with dev_err_probe() in the process. Signed-off-by: Robin Murphy <robin.murphy@arm.com> Link: https://lore.kernel.org/r/6d7ce1dc31873abdb75c895fb8bd2097cce098b4.1733406914.git.robin.murphy@arm.com Signed-off-by: Will Deacon <will@kernel.org>
1 parent 9b640ae commit 7d83513

File tree

2 files changed

+15
-18
lines changed

2 files changed

+15
-18
lines changed

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3351,8 +3351,8 @@ static struct platform_driver arm_smmu_driver;
33513351
static
33523352
struct arm_smmu_device *arm_smmu_get_by_fwnode(struct fwnode_handle *fwnode)
33533353
{
3354-
struct device *dev = driver_find_device_by_fwnode(&arm_smmu_driver.driver,
3355-
fwnode);
3354+
struct device *dev = bus_find_device_by_fwnode(&platform_bus_type, fwnode);
3355+
33563356
put_device(dev);
33573357
return dev ? dev_get_drvdata(dev) : NULL;
33583358
}

drivers/iommu/arm/arm-smmu/arm-smmu.c

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,8 +1411,8 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)
14111411
static
14121412
struct arm_smmu_device *arm_smmu_get_by_fwnode(struct fwnode_handle *fwnode)
14131413
{
1414-
struct device *dev = driver_find_device_by_fwnode(&arm_smmu_driver.driver,
1415-
fwnode);
1414+
struct device *dev = bus_find_device_by_fwnode(&platform_bus_type, fwnode);
1415+
14161416
put_device(dev);
14171417
return dev ? dev_get_drvdata(dev) : NULL;
14181418
}
@@ -2227,29 +2227,26 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
22272227
i, irq);
22282228
}
22292229

2230+
platform_set_drvdata(pdev, smmu);
2231+
2232+
/* Check for RMRs and install bypass SMRs if any */
2233+
arm_smmu_rmr_install_bypass_smr(smmu);
2234+
2235+
arm_smmu_device_reset(smmu);
2236+
arm_smmu_test_smr_masks(smmu);
2237+
22302238
err = iommu_device_sysfs_add(&smmu->iommu, smmu->dev, NULL,
22312239
"smmu.%pa", &smmu->ioaddr);
2232-
if (err) {
2233-
dev_err(dev, "Failed to register iommu in sysfs\n");
2234-
return err;
2235-
}
2240+
if (err)
2241+
return dev_err_probe(dev, err, "Failed to register iommu in sysfs\n");
22362242

22372243
err = iommu_device_register(&smmu->iommu, &arm_smmu_ops,
22382244
using_legacy_binding ? NULL : dev);
22392245
if (err) {
2240-
dev_err(dev, "Failed to register iommu\n");
22412246
iommu_device_sysfs_remove(&smmu->iommu);
2242-
return err;
2247+
return dev_err_probe(dev, err, "Failed to register iommu\n");
22432248
}
22442249

2245-
platform_set_drvdata(pdev, smmu);
2246-
2247-
/* Check for RMRs and install bypass SMRs if any */
2248-
arm_smmu_rmr_install_bypass_smr(smmu);
2249-
2250-
arm_smmu_device_reset(smmu);
2251-
arm_smmu_test_smr_masks(smmu);
2252-
22532250
/*
22542251
* We want to avoid touching dev->power.lock in fastpaths unless
22552252
* it's really going to do something useful - pm_runtime_enabled()

0 commit comments

Comments
 (0)