If SMMU probe failed, master should use swiotlb as dma ops.
SMMU may probe failed with specified environment, so there
are not any iommu resources in iommu_device_list.

The master will always get EPROBE_DEFER from really_probe
(dma_configure) but in fact SMMU has probe failed. The issue
causes all of masters failed to be driven.

Signed-off-by: Wang Dongsheng <dongsheng.w...@hxt-semitech.com>
---
 drivers/acpi/arm64/iort.c | 39 +++++++++++++++++++++++++++++++++------
 1 file changed, 33 insertions(+), 6 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index e2f7bdd..a6f4c27 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -774,17 +774,45 @@ static int arm_smmu_iort_xlate(struct device *dev, u32 
streamid,
        return ret;
 }
 
-static inline bool iort_iommu_driver_enabled(u8 type)
+static int iort_check_dev_dl_status(struct device *dev, void *data)
 {
+       struct fwnode_handle *fwnode = data;
+
+       if (dev->fwnode != fwnode)
+               return 0;
+
+       if (dev->links.status == DL_DEV_PROBE_FAILED)
+               return -ENODEV;
+
+       return -EPROBE_DEFER;
+}
+
+static int iort_iommu_driver_enabled(u8 type, struct fwnode_handle *fwnode)
+{
+       bool buildin;
+       int ret;
+
        switch (type) {
        case ACPI_IORT_NODE_SMMU_V3:
-               return IS_BUILTIN(CONFIG_ARM_SMMU_V3);
+               buildin = IS_BUILTIN(CONFIG_ARM_SMMU_V3);
+               break;
        case ACPI_IORT_NODE_SMMU:
-               return IS_BUILTIN(CONFIG_ARM_SMMU);
+               buildin = IS_BUILTIN(CONFIG_ARM_SMMU);
+               break;
        default:
                pr_warn("IORT node type %u does not describe an SMMU\n", type);
-               return false;
+               buildin = false;
        }
+
+       if (!buildin)
+               return -ENODEV;
+
+       ret = bus_for_each_dev(&platform_bus_type, NULL, fwnode,
+                              iort_check_dev_dl_status);
+       if (!ret)
+               return -EPROBE_DEFER;
+
+       return ret;
 }
 
 #ifdef CONFIG_IOMMU_API
@@ -919,8 +947,7 @@ static int iort_iommu_xlate(struct device *dev, struct 
acpi_iort_node *node,
         */
        ops = iommu_ops_from_fwnode(iort_fwnode);
        if (!ops)
-               return iort_iommu_driver_enabled(node->type) ?
-                      -EPROBE_DEFER : -ENODEV;
+               return iort_iommu_driver_enabled(node->type, iort_fwnode);
 
        return arm_smmu_iort_xlate(dev, streamid, iort_fwnode, ops);
 }
-- 
2.7.4

Reply via email to