Fix initialization after driver conversion to
probe_device()/release_device(). Prepared on top of:
https://git.kernel.org/pub/scm/linux/kernel/git/joro/linux.git/log/?h=iommu-probe-device

Signed-off-by: Marek Szyprowski <m.szyprow...@samsung.com>
---
 drivers/iommu/exynos-iommu.c | 80 +++++++++++++++++++++++++-------------------
 1 file changed, 46 insertions(+), 34 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index f865c90..53c784f 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -565,6 +565,7 @@ static void sysmmu_tlb_invalidate_entry(struct 
sysmmu_drvdata *data,
 }
 
 static const struct iommu_ops exynos_iommu_ops;
+static int exynos_iommu_initialize_owner(struct device *sysmmu);
 
 static int exynos_sysmmu_probe(struct platform_device *pdev)
 {
@@ -573,6 +574,8 @@ static int exynos_sysmmu_probe(struct platform_device *pdev)
        struct sysmmu_drvdata *data;
        struct resource *res;
 
+       dev_info(dev, "%s %d\n", __func__, __LINE__);
+
        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
@@ -649,6 +652,8 @@ static int exynos_sysmmu_probe(struct platform_device *pdev)
 
        pm_runtime_enable(dev);
 
+       exynos_iommu_initialize_owner(dev);
+
        return 0;
 }
 
@@ -1225,24 +1230,8 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct 
iommu_domain *iommu_domain,
 
 static struct iommu_device *exynos_iommu_probe_device(struct device *dev)
 {
-       struct exynos_iommu_owner *owner = dev->archdata.iommu;
-       struct sysmmu_drvdata *data;
-
-       if (!has_sysmmu(dev))
-               return ERR_PTR(-ENODEV);
-
-       list_for_each_entry(data, &owner->controllers, owner_node) {
-               /*
-                * SYSMMU will be runtime activated via device link
-                * (dependency) to its master device, so there are no
-                * direct calls to pm_runtime_get/put in this driver.
-                */
-               data->link = device_link_add(dev, data->sysmmu,
-                                            DL_FLAG_STATELESS |
-                                            DL_FLAG_PM_RUNTIME);
-       }
-
-       return &owner->iommu;
+       /* this is called too early on ARM 32bit to do anything usefull */
+       return ERR_PTR(-ENODEV);
 }
 
 static void exynos_iommu_release_device(struct device *dev)
@@ -1268,7 +1257,8 @@ static void exynos_iommu_release_device(struct device 
*dev)
                device_link_del(data->link);
 }
 
-static int exynos_iommu_device_init(struct exynos_iommu_owner *owner)
+static int exynos_iommu_device_init(struct device *dev,
+                                   struct exynos_iommu_owner *owner)
 {
        static u32 counter = 0;
        int ret;
@@ -1287,6 +1277,12 @@ static int exynos_iommu_device_init(struct 
exynos_iommu_owner *owner)
 
        iommu_device_set_ops(&owner->iommu, &exynos_iommu_ops);
 
+       /*
+        * the above iommu_device_set_ops is not enough, initializing fwspec
+        * is also required
+        */
+       iommu_fwspec_init(dev, &dev->of_node->fwnode, &exynos_iommu_ops);
+
        return 0;
 }
 
@@ -1308,7 +1304,7 @@ static int exynos_owner_init(struct device *dev)
        if (!owner)
                return -ENOMEM;
 
-       ret = exynos_iommu_device_init(owner);
+       ret = exynos_iommu_device_init(dev, owner);
        if (ret)
                goto out_free_owner;
 
@@ -1330,34 +1326,51 @@ static int exynos_owner_init(struct device *dev)
        return ret;
 }
 
-static int exynos_iommu_of_xlate(struct device *dev,
-                                struct of_phandle_args *spec)
+static int exynos_iommu_dev_match_owner(struct device *dev, const void *data)
+{
+       const struct device *sysmmu = data;
+       struct device_node *np;
+       int idx = 0;
+
+       do {
+               np = of_parse_phandle(dev->of_node, "iommus", idx++);
+               if (np == sysmmu->of_node)
+                       return true;
+       } while (np);
+
+       return false;
+}
+
+static int exynos_iommu_initialize_owner(struct device *sysmmu)
 {
-       struct platform_device *sysmmu = of_find_device_by_node(spec->np);
-       struct sysmmu_drvdata *data, *entry;
+       struct sysmmu_drvdata *data = dev_get_drvdata(sysmmu);
        struct exynos_iommu_owner *owner;
+       struct device *dev;
        int ret;
 
-       if (!sysmmu)
+       dev = bus_find_device(&platform_bus_type, NULL, sysmmu,
+                             exynos_iommu_dev_match_owner);
+       if (!dev)
                return -ENODEV;
 
-       data = platform_get_drvdata(sysmmu);
-       if (!data)
-               return -ENODEV;
+       dev_info(sysmmu, "found master device %s\n", dev_name(dev));
 
        ret = exynos_owner_init(dev);
        if (ret)
                return ret;
 
        owner = dev->archdata.iommu;
-
-       list_for_each_entry(entry, &owner->controllers, owner_node)
-               if (entry == data)
-                       return 0;
-
        list_add_tail(&data->owner_node, &owner->controllers);
        data->master = dev;
 
+       /*
+        * SYSMMU will be runtime activated via device link
+        * (dependency) to its master device, so there are no
+        * direct calls to pm_runtime_get/put in this driver.
+        */
+       data->link = device_link_add(dev, data->sysmmu,
+                                    DL_FLAG_STATELESS |
+                                    DL_FLAG_PM_RUNTIME);
        return 0;
 }
 
@@ -1373,7 +1386,6 @@ static int exynos_iommu_of_xlate(struct device *dev,
        .probe_device = exynos_iommu_probe_device,
        .release_device = exynos_iommu_release_device,
        .pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE,
-       .of_xlate = exynos_iommu_of_xlate,
 };
 
 static int __init exynos_iommu_init(void)
-- 
1.9.1

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to