[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200409140928.1403-1-m.szyprowski@samsung.com>
Date: Thu, 9 Apr 2020 16:09:28 +0200
From: Marek Szyprowski <m.szyprowski@...sung.com>
To: Joerg Roedel <joro@...tes.org>
Cc: Marek Szyprowski <m.szyprowski@...sung.com>,
Will Deacon <will@...nel.org>,
Robin Murphy <robin.murphy@....com>,
Kukjin Kim <kgene@...nel.org>,
Krzysztof Kozlowski <krzk@...nel.org>,
David Woodhouse <dwmw2@...radead.org>,
Lu Baolu <baolu.lu@...ux.intel.com>,
Andy Gross <agross@...nel.org>,
Bjorn Andersson <bjorn.andersson@...aro.org>,
Matthias Brugger <matthias.bgg@...il.com>,
Rob Clark <robdclark@...il.com>,
Heiko Stuebner <heiko@...ech.de>,
Gerald Schaefer <gerald.schaefer@...ibm.com>,
Thierry Reding <thierry.reding@...il.com>,
Jonathan Hunter <jonathanh@...dia.com>,
Jean-Philippe Brucker <jean-philippe@...aro.org>,
iommu@...ts.linux-foundation.org, linux-kernel@...r.kernel.org,
linux-samsung-soc@...r.kernel.org, linux-arm-msm@...r.kernel.org,
linux-mediatek@...ts.infradead.org,
linux-rockchip@...ts.infradead.org, linux-s390@...r.kernel.org,
linux-tegra@...r.kernel.org,
virtualization@...ts.linux-foundation.org,
Joerg Roedel <jroedel@...e.de>
Subject: [PATCH] iommu/exynos: Rework intialization
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.szyprowski@...sung.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
Powered by blists - more mailing lists