Skip to content

Commit 7ab6c93

Browse files
srestorulf
authored andcommitted
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 <[email protected]> Tested-by: Heiko Stuebner <[email protected]> Tested-by: Adrian Larumbe <[email protected]> # On Rock 5B Signed-off-by: Sebastian Reichel <[email protected]> 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 <[email protected]>
1 parent 83b2fba commit 7ab6c93

File tree

1 file changed

+23
-12
lines changed

1 file changed

+23
-12
lines changed

drivers/pmdomain/rockchip/pm-domains.c

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -535,17 +535,18 @@ static int rockchip_pmu_domain_mem_reset(struct rockchip_pm_domain *pd)
535535
return ret;
536536
}
537537

538-
static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
539-
bool on)
538+
static int rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
539+
bool on)
540540
{
541541
struct rockchip_pmu *pmu = pd->pmu;
542542
struct generic_pm_domain *genpd = &pd->genpd;
543543
u32 pd_pwr_offset = pd->info->pwr_offset;
544544
bool is_on, is_mem_on = false;
545545
struct arm_smccc_res res;
546+
int ret;
546547

547548
if (pd->info->pwr_mask == 0)
548-
return;
549+
return 0;
549550

550551
if (on && pd->info->mem_status_mask)
551552
is_mem_on = rockchip_pmu_domain_is_mem_on(pd);
@@ -560,22 +561,28 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
560561

561562
wmb();
562563

563-
if (is_mem_on && rockchip_pmu_domain_mem_reset(pd))
564-
return;
564+
if (is_mem_on) {
565+
ret = rockchip_pmu_domain_mem_reset(pd);
566+
if (ret)
567+
return ret;
568+
}
569+
565570

566-
if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on,
567-
is_on == on, 0, 10000)) {
568-
dev_err(pmu->dev,
569-
"failed to set domain '%s', val=%d\n",
570-
genpd->name, is_on);
571-
return;
571+
ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on,
572+
is_on == on, 0, 10000);
573+
if (ret) {
574+
dev_err(pmu->dev, "failed to set domain '%s' %s, val=%d\n",
575+
genpd->name, on ? "on" : "off", is_on);
576+
return ret;
572577
}
573578

574579
/* Inform firmware to keep this pd on or off */
575580
if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_NONE)
576581
arm_smccc_smc(ROCKCHIP_SIP_SUSPEND_MODE, ROCKCHIP_SLEEP_PD_CONFIG,
577582
pmu->info->pwr_offset + pd_pwr_offset,
578583
pd->info->pwr_mask, on, 0, 0, 0, &res);
584+
585+
return 0;
579586
}
580587

581588
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)
601608
rockchip_pmu_set_idle_request(pd, true);
602609
}
603610

604-
rockchip_do_pmu_set_power_domain(pd, power_on);
611+
ret = rockchip_do_pmu_set_power_domain(pd, power_on);
612+
if (ret < 0) {
613+
clk_bulk_disable(pd->num_clks, pd->clks);
614+
return ret;
615+
}
605616

606617
if (power_on) {
607618
/* if powering up, leave idle mode */

0 commit comments

Comments
 (0)