summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2017-09-15 13:05:08 +0200
committerJoerg Roedel <jroedel@suse.de>2017-09-19 14:48:01 +0200
commit7a974b29fe5d3704eafec707ba6390c3288c80fe (patch)
tree310253af9d51cbce016e3e414e8b5f171484f3bc
parentLinux 4.14-rc1 (diff)
downloadlinux-7a974b29fe5d3704eafec707ba6390c3288c80fe.tar.xz
linux-7a974b29fe5d3704eafec707ba6390c3288c80fe.zip
iommu/exynos: Rework runtime PM links management
add_device is a bit more suitable for establishing runtime PM links than the xlate callback. This change also makes it possible to implement proper cleanup - in remove_device callback. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/iommu/exynos-iommu.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index f596fcc32898..91c548d49b92 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -263,6 +263,7 @@ struct exynos_iommu_domain {
struct sysmmu_drvdata {
struct device *sysmmu; /* SYSMMU controller device */
struct device *master; /* master device (owner) */
+ struct device_link *link; /* runtime PM link to master */
void __iomem *sfrbase; /* our registers */
struct clk *clk; /* SYSMMU's clock */
struct clk *aclk; /* SYSMMU's aclk clock */
@@ -1250,6 +1251,8 @@ static struct iommu_group *get_device_iommu_group(struct device *dev)
static int exynos_iommu_add_device(struct device *dev)
{
+ struct exynos_iommu_owner *owner = dev->archdata.iommu;
+ struct sysmmu_drvdata *data;
struct iommu_group *group;
if (!has_sysmmu(dev))
@@ -1260,6 +1263,15 @@ static int exynos_iommu_add_device(struct device *dev)
if (IS_ERR(group))
return PTR_ERR(group);
+ 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_PM_RUNTIME);
+ }
iommu_group_put(group);
return 0;
@@ -1268,6 +1280,7 @@ static int exynos_iommu_add_device(struct device *dev)
static void exynos_iommu_remove_device(struct device *dev)
{
struct exynos_iommu_owner *owner = dev->archdata.iommu;
+ struct sysmmu_drvdata *data;
if (!has_sysmmu(dev))
return;
@@ -1283,6 +1296,9 @@ static void exynos_iommu_remove_device(struct device *dev)
}
}
iommu_group_remove_device(dev);
+
+ list_for_each_entry(data, &owner->controllers, owner_node)
+ device_link_del(data->link);
}
static int exynos_iommu_of_xlate(struct device *dev,
@@ -1316,13 +1332,6 @@ static int exynos_iommu_of_xlate(struct device *dev,
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.
- */
- device_link_add(dev, data->sysmmu, DL_FLAG_PM_RUNTIME);
-
return 0;
}