[PATCH 5.10 403/663] pwm: rockchip: Eliminate potential race condition when probing
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Date: 2021-03-02 04:08:55
Also in:
lkml
Subsystem:
arm/rockchip soc support, pwm subsystem, the rest · Maintainers:
Heiko Stuebner, Uwe Kleine-König, Linus Torvalds
From: Simon South <redacted>
[ Upstream commit d21ba5d6217bd5a6a696678385906ed1994b380b ]
Commit 48cf973cae33 ("pwm: rockchip: Avoid glitches on already running
PWMs") introduced a potential race condition in rockchip_pwm_probe(): A
consumer could enable an inactive PWM, or disable a running one, between
rockchip_pwm_probe() registering the device via pwmchip_add() and checking
whether it is enabled (to determine whether it was started by a
bootloader). This could result in a device's PWM clock being either enabled
once more than necessary, potentially causing it to continue running when
no longer needed, or disabled once more than necessary, producing a warning
from the kernel.
Eliminate these possibilities by modifying rockchip_pwm_probe() so it
checks whether a device is enabled before registering it rather than after.
Fixes: 48cf973cae33 ("pwm: rockchip: Avoid glitches on already running PWMs")
Reported-by: Trent Piepho <redacted>
Signed-off-by: Simon South <redacted>
Signed-off-by: Thierry Reding <redacted>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/pwm/pwm-rockchip.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
index ede027fbf2bb4..3b8da7b0091b1 100644
--- a/drivers/pwm/pwm-rockchip.c
+++ b/drivers/pwm/pwm-rockchip.c@@ -289,6 +289,7 @@ static int rockchip_pwm_probe(struct platform_device *pdev) struct rockchip_pwm_chip *pc; struct resource *r; u32 enable_conf, ctrl; + bool enabled; int ret, count; id = of_match_device(rockchip_pwm_dt_ids, &pdev->dev);
@@ -351,6 +352,10 @@ static int rockchip_pwm_probe(struct platform_device *pdev) pc->chip.of_pwm_n_cells = 3; } + enable_conf = pc->data->enable_conf; + ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); + enabled = (ctrl & enable_conf) == enable_conf; + ret = pwmchip_add(&pc->chip); if (ret < 0) { dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
@@ -358,9 +363,7 @@ static int rockchip_pwm_probe(struct platform_device *pdev) } /* Keep the PWM clk enabled if the PWM appears to be up and running. */ - enable_conf = pc->data->enable_conf; - ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); - if ((ctrl & enable_conf) != enable_conf) + if (!enabled) clk_disable(pc->clk); clk_disable(pc->pclk);
--
2.27.0