From: Janghyuck Kim Date: Tue, 31 Oct 2017 02:15:16 +0000 (+0900) Subject: [COMMON] iommu/exynos: add condition for no_rpm_control X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=08e30335995f16446af74796bd61563a6bc92117;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [COMMON] iommu/exynos: add condition for no_rpm_control If device has no_rpm_control attribute, it is not controlled by runtime pm and controlled explicitly by exynos_sysmmu_control() API. However, no_rpm_control attribute is also used for condition checking of TLB invalidation or showing status API. It always made condition false, and TLB invalidation or showing status API were skipped. This patch added condition to prcess these operation if SysMMU has no_rpm_control attribute and it is enabled by explicit API. Change-Id: Idaa5789b1616227eae5c162330d3ff41c5cde761 Signed-off-by: Janghyuck Kim --- diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 13acf336240f..c38f2a1525ea 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -112,8 +112,8 @@ void exynos_sysmmu_tlb_invalidate(struct iommu_domain *iommu_domain, struct sysmmu_drvdata *drvdata = dev_get_drvdata(list->sysmmu); spin_lock(&drvdata->lock); - if (!is_sysmmu_active(drvdata) || - !is_sysmmu_runtime_active(drvdata)) { + if (!is_runtime_active_or_enabled(drvdata) || + !is_sysmmu_active(drvdata)) { spin_unlock(&drvdata->lock); dev_dbg(drvdata->sysmmu, "Skip TLB invalidation %#zx@%#x\n", @@ -467,7 +467,7 @@ static int __init sysmmu_parse_dt(struct device *sysmmu, drvdata->hold_rpm_on_boot = true; if (of_property_read_bool(sysmmu->of_node, "sysmmu,no-rpm-control")) - drvdata->no_rpm_control = true; + drvdata->no_rpm_control = SYSMMU_STATE_DISABLED; if (IS_TLB_WAY_TYPE(drvdata)) { ret = sysmmu_parse_tlb_way_dt(sysmmu, drvdata); @@ -700,12 +700,19 @@ void exynos_sysmmu_control(struct device *master, bool enable) spin_lock_irqsave(&owner->lock, flags); list_for_each_entry(list, &owner->sysmmu_list, node) { drvdata = dev_get_drvdata(list->sysmmu); - if (!drvdata->no_rpm_control) + spin_lock(&drvdata->lock); + if (!drvdata->no_rpm_control) { + spin_unlock(&drvdata->lock); continue; - if (enable) + } + if (enable) { __sysmmu_enable_nocount(drvdata); - else + drvdata->no_rpm_control = SYSMMU_STATE_ENABLED; + } else { __sysmmu_disable_nocount(drvdata); + drvdata->no_rpm_control = SYSMMU_STATE_DISABLED; + } + spin_unlock(&drvdata->lock); } spin_unlock_irqrestore(&owner->lock, flags); } @@ -1309,7 +1316,7 @@ void exynos_sysmmu_show_status(struct device *master) spin_lock_irqsave(&drvdata->lock, flags); if (!is_sysmmu_active(drvdata) || - !is_sysmmu_runtime_active(drvdata)) { + !is_runtime_active_or_enabled(drvdata)) { dev_info(drvdata->sysmmu, "%s: SysMMU is not active\n", __func__); spin_unlock_irqrestore(&drvdata->lock, flags); diff --git a/drivers/iommu/exynos-iommu.h b/drivers/iommu/exynos-iommu.h index 998aa3411d31..583ec0c0b500 100644 --- a/drivers/iommu/exynos-iommu.h +++ b/drivers/iommu/exynos-iommu.h @@ -324,6 +324,12 @@ struct tlb_props { }; }; +enum { + SYSMMU_USE_RUNTIME_ACTIVE = 0, + SYSMMU_STATE_DISABLED, + SYSMMU_STATE_ENABLED, +}; + /* * This structure hold all data of a single SYSMMU controller, this includes * hw resources like registers and clocks, pointers and list nodes to connect @@ -402,6 +408,12 @@ static inline bool is_sysmmu_runtime_active(struct sysmmu_drvdata *data) return data->runtime_active > 0 && !data->no_rpm_control; } +static inline bool is_runtime_active_or_enabled(struct sysmmu_drvdata *data) +{ + return is_sysmmu_runtime_active(data) || + data->no_rpm_control == SYSMMU_STATE_ENABLED; +} + static inline bool set_sysmmu_active(struct sysmmu_drvdata *data) { /* return true if the System MMU was not active previously