spi: rockchip: Resolve unbalanced runtime PM / system PM handling
BugLink: https://bugs.launchpad.net/bugs/2085849 commit be721b451affbecc4ba4eaac3b71cdbdcade1b1b upstream. Commite882575efc("spi: rockchip: Suspend and resume the bus during NOIRQ_SYSTEM_SLEEP_PM ops") stopped respecting runtime PM status and simply disabled clocks unconditionally when suspending the system. This causes problems when the device is already runtime suspended when we go to sleep -- in which case we double-disable clocks and produce a WARNing. Switch back to pm_runtime_force_{suspend,resume}(), because that still seems like the right thing to do, and the aforementioned commit makes no explanation why it stopped using it. Also, refactor some of the resume() error handling, because it's not actually a good idea to re-disable clocks on failure. Fixes:e882575efc("spi: rockchip: Suspend and resume the bus during NOIRQ_SYSTEM_SLEEP_PM ops") Cc: stable@vger.kernel.org Reported-by: Ondřej Jirman <megi@xff.cz> Closes: https://lore.kernel.org/lkml/20220621154218.sau54jeij4bunf56@core/ Signed-off-by: Brian Norris <briannorris@chromium.org> Link: https://patch.msgid.link/20240827171126.1115748-1-briannorris@chromium.org Signed-off-by: Mark Brown <broonie@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> CVE-2024-46846 Signed-off-by: Manuel Diewald <manuel.diewald@canonical.com> Signed-off-by: Roxana Nicolescu <roxana.nicolescu@canonical.com>
This commit is contained in:
committed by
Mehmet Basaran
parent
eac9f5584e
commit
76cf283715
@@ -954,14 +954,16 @@ static int rockchip_spi_suspend(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct spi_controller *ctlr = dev_get_drvdata(dev);
|
||||
struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
|
||||
|
||||
ret = spi_controller_suspend(ctlr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
clk_disable_unprepare(rs->spiclk);
|
||||
clk_disable_unprepare(rs->apb_pclk);
|
||||
ret = pm_runtime_force_suspend(dev);
|
||||
if (ret < 0) {
|
||||
spi_controller_resume(ctlr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pinctrl_pm_select_sleep_state(dev);
|
||||
|
||||
@@ -972,25 +974,14 @@ static int rockchip_spi_resume(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct spi_controller *ctlr = dev_get_drvdata(dev);
|
||||
struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
|
||||
|
||||
pinctrl_pm_select_default_state(dev);
|
||||
|
||||
ret = clk_prepare_enable(rs->apb_pclk);
|
||||
ret = pm_runtime_force_resume(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(rs->spiclk);
|
||||
if (ret < 0)
|
||||
clk_disable_unprepare(rs->apb_pclk);
|
||||
|
||||
ret = spi_controller_resume(ctlr);
|
||||
if (ret < 0) {
|
||||
clk_disable_unprepare(rs->spiclk);
|
||||
clk_disable_unprepare(rs->apb_pclk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return spi_controller_resume(ctlr);
|
||||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user