of_iommu_configure_dev(master_np, dev);
}
------- const struct iommu_ops *of_iommu_configure(struct device *dev,
------- struct device_node *master_np,
------- const u32 *id)
+++++++ /*
+++++++ * Returns:
+++++++ * 0 on success, an iommu was configured
+++++++ * -ENODEV if the device does not have any IOMMU
+++++++ * -EPROBEDEFER if probing should be tried again
+++++++ * -errno fatal errors
+++++++ */
+++++++ int of_iommu_configure(struct device *dev, struct device_node *master_np,
+++++++ const u32 *id)
{
------- const struct iommu_ops *ops = NULL;
------ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
------ int err = NO_IOMMU;
++++++ struct iommu_fwspec *fwspec;
- int err = NO_IOMMU;
+++++++ int err;
if (!master_np)
------- return NULL;
+++++++ return -ENODEV;
++++++ /* Serialise to make dev->iommu stable under our potential fwspec */
++++++ mutex_lock(&iommu_probe_device_lock);
++++++ fwspec = dev_iommu_fwspec_get(dev);
if (fwspec) {
------ if (fwspec->ops)
------ return fwspec->ops;
------
++++++ if (fwspec->ops) {
++++++ mutex_unlock(&iommu_probe_device_lock);
- return fwspec->ops;
+++++++ return 0;
++++++ }
/* In the deferred case, start again from scratch */
iommu_fwspec_free(dev);
}
} else {
err = of_iommu_configure_device(master_np, dev, id);
}
-
- /*
- * Two success conditions can be represented by non-negative err here:
- * >0 : there is no IOMMU, or one was unavailable for non-fatal reasons
- * 0 : we found an IOMMU, and dev->fwspec is initialised appropriately
- * <0 : any actual error
- */
- if (!err) {
- /* The fwspec pointer changed, read it again */
- fwspec = dev_iommu_fwspec_get(dev);
- ops = fwspec->ops;
- }
++++++ mutex_unlock(&iommu_probe_device_lock);
------ /*
------ * Two success conditions can be represented by non-negative err here:
------ * >0 : there is no IOMMU, or one was unavailable for non-fatal reasons
------ * 0 : we found an IOMMU, and dev->fwspec is initialised appropriately
------ * <0 : any actual error
------ */
------ if (!err) {
------ /* The fwspec pointer changed, read it again */
------ fwspec = dev_iommu_fwspec_get(dev);
------ ops = fwspec->ops;
------ }
------- /*
------- * If we have reason to believe the IOMMU driver missed the initial
------- * probe for dev, replay it to get things in order.
------- */
------- if (!err && dev->bus)
------- err = iommu_probe_device(dev);
-------
------- /* Ignore all other errors apart from EPROBE_DEFER */
------- if (err == -EPROBE_DEFER) {
------- ops = ERR_PTR(err);
------- } else if (err < 0) {
------- dev_dbg(dev, "Adding to IOMMU failed: %d\n", err);
------- ops = NULL;
------- }
+++++++ if (err == -ENODEV || err == -EPROBE_DEFER)
+++++++ return err;
+++++++ if (err)
+++++++ goto err_log;
------- return ops;
+++++++ err = iommu_probe_device(dev);
+++++++ if (err)
+++++++ goto err_log;
+++++++ return 0;
+++++++
+++++++ err_log:
+++++++ dev_dbg(dev, "Adding to IOMMU failed: %pe\n", ERR_PTR(err));
+++++++ return err;
}
static enum iommu_resv_type __maybe_unused