Skip to content

Commit 3f7c320

Browse files
rmurphy-armwilldeacon
authored andcommitted
iommu: Resolve fwspec ops automatically
There's no real need for callers to resolve ops from a fwnode in order to then pass both to iommu_fwspec_init() - it's simpler and more sensible for that to resolve the ops itself. This in turn means we can centralise the notion of checking for a present driver, and enforce that fwspecs aren't allocated unless and until we know they will be usable. Also use this opportunity to modernise with some "new" helpers that arrived shortly after this code was first written; the generic fwnode_handle_get() clears up that ugly get/put mismatch, while of_fwnode_handle() can now abstract those open-coded dereferences. Tested-by: Jean-Philippe Brucker <[email protected]> Signed-off-by: Robin Murphy <[email protected]> Link: https://lore.kernel.org/r/0e2727adeb8cd73274425322f2f793561bdc927e.1719919669.git.robin.murphy@arm.com Signed-off-by: Will Deacon <[email protected]>
1 parent e7acc36 commit 3f7c320

File tree

11 files changed

+30
-61
lines changed

11 files changed

+30
-61
lines changed

drivers/acpi/arm64/iort.c

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,30 +1221,21 @@ static bool iort_pci_rc_supports_ats(struct acpi_iort_node *node)
12211221
static int iort_iommu_xlate(struct device *dev, struct acpi_iort_node *node,
12221222
u32 streamid)
12231223
{
1224-
const struct iommu_ops *ops;
12251224
struct fwnode_handle *iort_fwnode;
12261225

1227-
if (!node)
1226+
/* If there's no SMMU driver at all, give up now */
1227+
if (!node || !iort_iommu_driver_enabled(node->type))
12281228
return -ENODEV;
12291229

12301230
iort_fwnode = iort_get_fwnode(node);
12311231
if (!iort_fwnode)
12321232
return -ENODEV;
12331233

12341234
/*
1235-
* If the ops look-up fails, this means that either
1236-
* the SMMU drivers have not been probed yet or that
1237-
* the SMMU drivers are not built in the kernel;
1238-
* Depending on whether the SMMU drivers are built-in
1239-
* in the kernel or not, defer the IOMMU configuration
1240-
* or just abort it.
1235+
* If the SMMU drivers are enabled but not loaded/probed
1236+
* yet, this will defer.
12411237
*/
1242-
ops = iommu_ops_from_fwnode(iort_fwnode);
1243-
if (!ops)
1244-
return iort_iommu_driver_enabled(node->type) ?
1245-
-EPROBE_DEFER : -ENODEV;
1246-
1247-
return acpi_iommu_fwspec_init(dev, streamid, iort_fwnode, ops);
1238+
return acpi_iommu_fwspec_init(dev, streamid, iort_fwnode);
12481239
}
12491240

12501241
struct iort_pci_alias_info {

drivers/acpi/scan.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1577,12 +1577,11 @@ int acpi_dma_get_range(struct device *dev, const struct bus_dma_region **map)
15771577

15781578
#ifdef CONFIG_IOMMU_API
15791579
int acpi_iommu_fwspec_init(struct device *dev, u32 id,
1580-
struct fwnode_handle *fwnode,
1581-
const struct iommu_ops *ops)
1580+
struct fwnode_handle *fwnode)
15821581
{
15831582
int ret;
15841583

1585-
ret = iommu_fwspec_init(dev, fwnode, ops);
1584+
ret = iommu_fwspec_init(dev, fwnode);
15861585
if (ret)
15871586
return ret;
15881587

@@ -1639,8 +1638,7 @@ static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in)
16391638
#else /* !CONFIG_IOMMU_API */
16401639

16411640
int acpi_iommu_fwspec_init(struct device *dev, u32 id,
1642-
struct fwnode_handle *fwnode,
1643-
const struct iommu_ops *ops)
1641+
struct fwnode_handle *fwnode)
16441642
{
16451643
return -ENODEV;
16461644
}

drivers/acpi/viot.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -307,21 +307,14 @@ void __init acpi_viot_init(void)
307307
static int viot_dev_iommu_init(struct device *dev, struct viot_iommu *viommu,
308308
u32 epid)
309309
{
310-
const struct iommu_ops *ops;
311-
312-
if (!viommu)
310+
if (!viommu || !IS_ENABLED(CONFIG_VIRTIO_IOMMU))
313311
return -ENODEV;
314312

315313
/* We're not translating ourself */
316314
if (device_match_fwnode(dev, viommu->fwnode))
317315
return -EINVAL;
318316

319-
ops = iommu_ops_from_fwnode(viommu->fwnode);
320-
if (!ops)
321-
return IS_ENABLED(CONFIG_VIRTIO_IOMMU) ?
322-
-EPROBE_DEFER : -ENODEV;
323-
324-
return acpi_iommu_fwspec_init(dev, epid, viommu->fwnode, ops);
317+
return acpi_iommu_fwspec_init(dev, epid, viommu->fwnode);
325318
}
326319

327320
static int viot_pci_dev_iommu_init(struct pci_dev *pdev, u16 dev_id, void *data)

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,7 @@ static int arm_smmu_register_legacy_master(struct device *dev,
178178
it.cur_count = 1;
179179
}
180180

181-
err = iommu_fwspec_init(dev, &smmu_dev->of_node->fwnode,
182-
&arm_smmu_ops);
181+
err = iommu_fwspec_init(dev, NULL);
183182
if (err)
184183
return err;
185184

drivers/iommu/iommu-priv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ static inline const struct iommu_ops *dev_iommu_ops(struct device *dev)
1717
return dev->iommu->iommu_dev->ops;
1818
}
1919

20+
const struct iommu_ops *iommu_ops_from_fwnode(const struct fwnode_handle *fwnode);
21+
2022
int iommu_group_replace_domain(struct iommu_group *group,
2123
struct iommu_domain *new_domain);
2224

drivers/iommu/iommu.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2822,11 +2822,14 @@ const struct iommu_ops *iommu_ops_from_fwnode(const struct fwnode_handle *fwnode
28222822
return ops;
28232823
}
28242824

2825-
int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
2826-
const struct iommu_ops *ops)
2825+
int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode)
28272826
{
2827+
const struct iommu_ops *ops = iommu_ops_from_fwnode(iommu_fwnode);
28282828
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
28292829

2830+
if (!ops)
2831+
return -EPROBE_DEFER;
2832+
28302833
if (fwspec)
28312834
return ops == fwspec->ops ? 0 : -EINVAL;
28322835

@@ -2838,7 +2841,7 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
28382841
if (!fwspec)
28392842
return -ENOMEM;
28402843

2841-
of_node_get(to_of_node(iommu_fwnode));
2844+
fwnode_handle_get(iommu_fwnode);
28422845
fwspec->iommu_fwnode = iommu_fwnode;
28432846
fwspec->ops = ops;
28442847
dev_iommu_fwspec_set(dev, fwspec);

drivers/iommu/mtk_iommu_v1.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ static int mtk_iommu_v1_create_mapping(struct device *dev,
412412
return -EINVAL;
413413
}
414414

415-
ret = iommu_fwspec_init(dev, &args->np->fwnode, &mtk_iommu_v1_ops);
415+
ret = iommu_fwspec_init(dev, of_fwnode_handle(args->np));
416416
if (ret)
417417
return ret;
418418

drivers/iommu/of_iommu.c

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,19 @@ static int of_iommu_xlate(struct device *dev,
2121
struct of_phandle_args *iommu_spec)
2222
{
2323
const struct iommu_ops *ops;
24-
struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;
2524
int ret;
2625

27-
ops = iommu_ops_from_fwnode(fwnode);
28-
if ((ops && !ops->of_xlate) ||
29-
!of_device_is_available(iommu_spec->np))
26+
if (!of_device_is_available(iommu_spec->np))
3027
return -ENODEV;
3128

32-
ret = iommu_fwspec_init(dev, fwnode, ops);
29+
ret = iommu_fwspec_init(dev, of_fwnode_handle(iommu_spec->np));
30+
if (ret == -EPROBE_DEFER)
31+
return driver_deferred_probe_check_state(dev);
3332
if (ret)
3433
return ret;
35-
/*
36-
* The otherwise-empty fwspec handily serves to indicate the specific
37-
* IOMMU device we're waiting for, which will be useful if we ever get
38-
* a proper probe-ordering dependency mechanism in future.
39-
*/
40-
if (!ops)
41-
return driver_deferred_probe_check_state(dev);
4234

43-
if (!try_module_get(ops->owner))
35+
ops = dev_iommu_fwspec_get(dev)->ops;
36+
if (!ops->of_xlate || !try_module_get(ops->owner))
4437
return -ENODEV;
4538

4639
ret = ops->of_xlate(dev, iommu_spec);

drivers/iommu/tegra-smmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ static int tegra_smmu_configure(struct tegra_smmu *smmu, struct device *dev,
837837
const struct iommu_ops *ops = smmu->iommu.ops;
838838
int err;
839839

840-
err = iommu_fwspec_init(dev, &dev->of_node->fwnode, ops);
840+
err = iommu_fwspec_init(dev, of_fwnode_handle(dev->of_node));
841841
if (err < 0) {
842842
dev_err(dev, "failed to initialize fwspec: %d\n", err);
843843
return err;

include/acpi/acpi_bus.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -736,8 +736,7 @@ struct iommu_ops;
736736
bool acpi_dma_supported(const struct acpi_device *adev);
737737
enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev);
738738
int acpi_iommu_fwspec_init(struct device *dev, u32 id,
739-
struct fwnode_handle *fwnode,
740-
const struct iommu_ops *ops);
739+
struct fwnode_handle *fwnode);
741740
int acpi_dma_get_range(struct device *dev, const struct bus_dma_region **map);
742741
int acpi_dma_configure_id(struct device *dev, enum dev_dma_attr attr,
743742
const u32 *input_id);

0 commit comments

Comments
 (0)