aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorSebastian Reichel <sebastian.reichel@collabora.com>2025-02-20 19:58:06 +0100
committerUlf Hansson <ulf.hansson@linaro.org>2025-02-28 13:04:50 +0100
commit7ab6c930b92378ab86ed05bbe78877ef578c7fea (patch)
treefcc504638251d6df93e2cb0ca6425aa2f8a08fb5
parentpmdomain: rockchip: cleanup mutex handling in rockchip_pd_power (diff)
downloadwireguard-linux-7ab6c930b92378ab86ed05bbe78877ef578c7fea.tar.xz
wireguard-linux-7ab6c930b92378ab86ed05bbe78877ef578c7fea.zip
pmdomain: rockchip: forward rockchip_do_pmu_set_power_domain errors
Currently rockchip_do_pmu_set_power_domain prints a warning if there have been errors turning on the power domain, but it does not return any errors and rockchip_pd_power() tries to continue setting up the QOS registers. This usually results in accessing unpowered registers, which triggers an SError and a full system hang. This improves the error handling by forwarding the error to avoid kernel panics. Reviewed-by: Heiko Stuebner <heiko@sntech.de> Tested-by: Heiko Stuebner <heiko@sntech.de> Tested-by: Adrian Larumbe <adrian.larumbe@collabora.com> # On Rock 5B Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> Link: https://lore.kernel.org/r/20250220-rk3588-gpu-pwr-domain-regulator-v6-3-a4f9c24e5b81@kernel.org [Ulf: Fixed conflict when applying] Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/pmdomain/rockchip/pm-domains.c35
1 files changed, 23 insertions, 12 deletions
diff --git a/drivers/pmdomain/rockchip/pm-domains.c b/drivers/pmdomain/rockchip/pm-domains.c
index 8b15e57aa27f..5f03da348fe3 100644
--- a/drivers/pmdomain/rockchip/pm-domains.c
+++ b/drivers/pmdomain/rockchip/pm-domains.c
@@ -535,17 +535,18 @@ error:
return ret;
}
-static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
- bool on)
+static int rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
+ bool on)
{
struct rockchip_pmu *pmu = pd->pmu;
struct generic_pm_domain *genpd = &pd->genpd;
u32 pd_pwr_offset = pd->info->pwr_offset;
bool is_on, is_mem_on = false;
struct arm_smccc_res res;
+ int ret;
if (pd->info->pwr_mask == 0)
- return;
+ return 0;
if (on && pd->info->mem_status_mask)
is_mem_on = rockchip_pmu_domain_is_mem_on(pd);
@@ -560,15 +561,19 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
wmb();
- if (is_mem_on && rockchip_pmu_domain_mem_reset(pd))
- return;
+ if (is_mem_on) {
+ ret = rockchip_pmu_domain_mem_reset(pd);
+ if (ret)
+ return ret;
+ }
+
- if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on,
- is_on == on, 0, 10000)) {
- dev_err(pmu->dev,
- "failed to set domain '%s', val=%d\n",
- genpd->name, is_on);
- return;
+ ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on,
+ is_on == on, 0, 10000);
+ if (ret) {
+ dev_err(pmu->dev, "failed to set domain '%s' %s, val=%d\n",
+ genpd->name, on ? "on" : "off", is_on);
+ return ret;
}
/* Inform firmware to keep this pd on or off */
@@ -576,6 +581,8 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
arm_smccc_smc(ROCKCHIP_SIP_SUSPEND_MODE, ROCKCHIP_SLEEP_PD_CONFIG,
pmu->info->pwr_offset + pd_pwr_offset,
pd->info->pwr_mask, on, 0, 0, 0, &res);
+
+ return 0;
}
static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
@@ -601,7 +608,11 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
rockchip_pmu_set_idle_request(pd, true);
}
- rockchip_do_pmu_set_power_domain(pd, power_on);
+ ret = rockchip_do_pmu_set_power_domain(pd, power_on);
+ if (ret < 0) {
+ clk_bulk_disable(pd->num_clks, pd->clks);
+ return ret;
+ }
if (power_on) {
/* if powering up, leave idle mode */