Skip to content

Commit 9b26553

Browse files
mszyprowjoergroedel
authored andcommitted
iommu/exynos: Add runtime pm support
This patch adds runtime pm implementation, which is based on previous suspend/resume code. SYSMMU controller is now being enabled/disabled mainly from the runtime pm callbacks. System sleep callbacks relies on generic pm_runtime_force_suspend/pm_runtime_force_resume helpers. To ensure internal state consistency, additional lock for runtime pm transitions was introduced. Signed-off-by: Marek Szyprowski <[email protected]> Signed-off-by: Joerg Roedel <[email protected]>
1 parent e117230 commit 9b26553

File tree

1 file changed

+36
-9
lines changed

1 file changed

+36
-9
lines changed

drivers/iommu/exynos-iommu.c

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ static const struct sysmmu_fault_info sysmmu_v5_faults[] = {
237237
struct exynos_iommu_owner {
238238
struct list_head controllers; /* list of sysmmu_drvdata.owner_node */
239239
struct iommu_domain *domain; /* domain this device is attached */
240+
struct mutex rpm_lock; /* for runtime pm of all sysmmus */
240241
};
241242

242243
/*
@@ -632,40 +633,46 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev)
632633
return 0;
633634
}
634635

635-
#ifdef CONFIG_PM_SLEEP
636-
static int exynos_sysmmu_suspend(struct device *dev)
636+
static int __maybe_unused exynos_sysmmu_suspend(struct device *dev)
637637
{
638638
struct sysmmu_drvdata *data = dev_get_drvdata(dev);
639639
struct device *master = data->master;
640640

641641
if (master) {
642-
pm_runtime_put(dev);
642+
struct exynos_iommu_owner *owner = master->archdata.iommu;
643+
644+
mutex_lock(&owner->rpm_lock);
643645
if (data->domain) {
644646
dev_dbg(data->sysmmu, "saving state\n");
645647
__sysmmu_disable(data);
646648
}
649+
mutex_unlock(&owner->rpm_lock);
647650
}
648651
return 0;
649652
}
650653

651-
static int exynos_sysmmu_resume(struct device *dev)
654+
static int __maybe_unused exynos_sysmmu_resume(struct device *dev)
652655
{
653656
struct sysmmu_drvdata *data = dev_get_drvdata(dev);
654657
struct device *master = data->master;
655658

656659
if (master) {
657-
pm_runtime_get_sync(dev);
660+
struct exynos_iommu_owner *owner = master->archdata.iommu;
661+
662+
mutex_lock(&owner->rpm_lock);
658663
if (data->domain) {
659664
dev_dbg(data->sysmmu, "restoring state\n");
660665
__sysmmu_enable(data);
661666
}
667+
mutex_unlock(&owner->rpm_lock);
662668
}
663669
return 0;
664670
}
665-
#endif
666671

667672
static const struct dev_pm_ops sysmmu_pm_ops = {
668-
SET_LATE_SYSTEM_SLEEP_PM_OPS(exynos_sysmmu_suspend, exynos_sysmmu_resume)
673+
SET_RUNTIME_PM_OPS(exynos_sysmmu_suspend, exynos_sysmmu_resume, NULL)
674+
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
675+
pm_runtime_force_resume)
669676
};
670677

671678
static const struct of_device_id sysmmu_of_match[] __initconst = {
@@ -813,7 +820,15 @@ static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain,
813820
return;
814821

815822
list_for_each_entry(data, &owner->controllers, owner_node) {
816-
__sysmmu_disable(data);
823+
pm_runtime_put_sync(data->sysmmu);
824+
}
825+
826+
mutex_lock(&owner->rpm_lock);
827+
828+
list_for_each_entry(data, &owner->controllers, owner_node) {
829+
pm_runtime_get_noresume(data->sysmmu);
830+
if (pm_runtime_active(data->sysmmu))
831+
__sysmmu_disable(data);
817832
pm_runtime_put(data->sysmmu);
818833
}
819834

@@ -828,6 +843,7 @@ static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain,
828843
owner->domain = NULL;
829844
spin_unlock_irqrestore(&domain->lock, flags);
830845

846+
mutex_unlock(&owner->rpm_lock);
831847

832848
dev_dbg(dev, "%s: Detached IOMMU with pgtable %pa\n", __func__,
833849
&pagetable);
@@ -848,6 +864,8 @@ static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain,
848864
if (owner->domain)
849865
exynos_iommu_detach_device(owner->domain, dev);
850866

867+
mutex_lock(&owner->rpm_lock);
868+
851869
spin_lock_irqsave(&domain->lock, flags);
852870
list_for_each_entry(data, &owner->controllers, owner_node) {
853871
spin_lock(&data->lock);
@@ -859,9 +877,17 @@ static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain,
859877
owner->domain = iommu_domain;
860878
spin_unlock_irqrestore(&domain->lock, flags);
861879

880+
list_for_each_entry(data, &owner->controllers, owner_node) {
881+
pm_runtime_get_noresume(data->sysmmu);
882+
if (pm_runtime_active(data->sysmmu))
883+
__sysmmu_enable(data);
884+
pm_runtime_put(data->sysmmu);
885+
}
886+
887+
mutex_unlock(&owner->rpm_lock);
888+
862889
list_for_each_entry(data, &owner->controllers, owner_node) {
863890
pm_runtime_get_sync(data->sysmmu);
864-
__sysmmu_enable(data);
865891
}
866892

867893
dev_dbg(dev, "%s: Attached IOMMU with pgtable %pa\n", __func__,
@@ -1239,6 +1265,7 @@ static int exynos_iommu_of_xlate(struct device *dev,
12391265
return -ENOMEM;
12401266

12411267
INIT_LIST_HEAD(&owner->controllers);
1268+
mutex_init(&owner->rpm_lock);
12421269
dev->archdata.iommu = owner;
12431270
}
12441271

0 commit comments

Comments
 (0)