From 9163d613740272f344fddc2dee60deefb153df55 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Mon, 21 Oct 2019 15:03:14 +0800 Subject: [PATCH] soc: rockchip: power-domain: Add dmcfreq lock when pd on/off In order to fix deadlock between dmcfreq and vop on/off, When change vop status and ddr frequency at the same time, the following deadlock will happen: vop no/off dmcfreq vop_crtc_disable update_devfreq ->mutex_lock(&vop->vop_lock); ->mutex_lock(&pd->pmu->mutex); ->pm_runtime_put(vop->dev); ->mutex_lock(&vop->vop_lock); ->mutex_lock(&pd->pmu->mutex); ... Change-Id: I56a4ee944200826d2a09e3ae8d2f4837f6f769d6 Signed-off-by: Finley Xiao Signed-off-by: Elaine Zhang --- drivers/soc/rockchip/pm_domains.c | 37 +++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index f95c255ede90..e70753a325fc 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -93,6 +94,18 @@ struct rockchip_pmu { static struct rockchip_pmu *g_pmu; +static void rockchip_pmu_lock(struct rockchip_pm_domain *pd) +{ + mutex_lock(&pd->pmu->mutex); + rockchip_dmcfreq_lock_nested(); +} + +static void rockchip_pmu_unlock(struct rockchip_pm_domain *pd) +{ + rockchip_dmcfreq_unlock(); + mutex_unlock(&pd->pmu->mutex); +} + #define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd) #define DOMAIN(pwr, status, req, idle, ack, wakeup, keepon) \ @@ -238,9 +251,9 @@ int rockchip_pmu_idle_request(struct device *dev, bool idle) genpd = pd_to_genpd(dev->pm_domain); pd = to_rockchip_pd(genpd); - mutex_lock(&pd->pmu->mutex); + rockchip_pmu_lock(pd); ret = rockchip_pmu_set_idle_request(pd, idle); - mutex_unlock(&pd->pmu->mutex); + rockchip_pmu_unlock(pd); return ret; } @@ -310,9 +323,9 @@ int rockchip_save_qos(struct device *dev) genpd = pd_to_genpd(dev->pm_domain); pd = to_rockchip_pd(genpd); - mutex_lock(&pd->pmu->mutex); + rockchip_pmu_lock(pd); ret = rockchip_pmu_save_qos(pd); - mutex_unlock(&pd->pmu->mutex); + rockchip_pmu_unlock(pd); return ret; } @@ -333,9 +346,9 @@ int rockchip_restore_qos(struct device *dev) genpd = pd_to_genpd(dev->pm_domain); pd = to_rockchip_pd(genpd); - mutex_lock(&pd->pmu->mutex); + rockchip_pmu_lock(pd); ret = rockchip_pmu_restore_qos(pd); - mutex_unlock(&pd->pmu->mutex); + rockchip_pmu_unlock(pd); return ret; } @@ -397,7 +410,7 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on) int ret = 0; struct generic_pm_domain *genpd = &pd->genpd; - mutex_lock(&pmu->mutex); + rockchip_pmu_lock(pd); if (rockchip_pmu_domain_is_on(pd) != power_on) { if (IS_ERR_OR_NULL(pd->supply) && @@ -410,7 +423,7 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on) if (ret < 0) { dev_err(pd->pmu->dev, "failed to set vdd supply enable '%s',\n", genpd->name); - mutex_unlock(&pmu->mutex); + rockchip_pmu_unlock(pd); return ret; } } @@ -418,7 +431,7 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on) ret = clk_bulk_enable(pd->num_clks, pd->clks); if (ret < 0) { dev_err(pmu->dev, "failed to enable clocks\n"); - mutex_unlock(&pmu->mutex); + rockchip_pmu_unlock(pd); return ret; } @@ -462,7 +475,7 @@ out: ret = regulator_disable(pd->supply); } - mutex_unlock(&pmu->mutex); + rockchip_pmu_unlock(pd); return ret; } @@ -696,9 +709,9 @@ static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd) clk_bulk_put(pd->num_clks, pd->clks); /* protect the zeroing of pm->num_clks */ - mutex_lock(&pd->pmu->mutex); + rockchip_pmu_lock(pd); pd->num_clks = 0; - mutex_unlock(&pd->pmu->mutex); + rockchip_pmu_unlock(pd); /* devm will free our memory */ }