diff options
author | Nicolas Toromanoff <nicolas.toromanoff@st.com> | 2020-05-12 17:11:12 +0300 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2020-05-22 17:08:21 +0300 |
commit | 100f84beee4874234d04a1ea642b8c9738d7020d (patch) | |
tree | 16b8fcab355ad087e0b241ad288f8bd53eba0a57 /drivers/crypto/stm32 | |
parent | 10b89c43a64eb0d236903b79a3bc9d8f6cbfd9c7 (diff) | |
download | linux-100f84beee4874234d04a1ea642b8c9738d7020d.tar.xz |
crypto: stm32/crc32 - don't sleep in runtime pm
Ensure stm32_crc_update() and stm32_crc_init() can be called
in atomic context and can't sleep.
Add pm_runtime_irq_safe() to make pm_runtime_get_sync() atomic.
Change runtime pm to call clk_enable()/clk_disable() and change
system pm to unprepare/prepare the clock and force runtime pm
suspend/resume.
Signed-off-by: Nicolas Toromanoff <nicolas.toromanoff@st.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto/stm32')
-rw-r--r-- | drivers/crypto/stm32/stm32-crc32.c | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/drivers/crypto/stm32/stm32-crc32.c b/drivers/crypto/stm32/stm32-crc32.c index 10304511f9b4..413415c216ef 100644 --- a/drivers/crypto/stm32/stm32-crc32.c +++ b/drivers/crypto/stm32/stm32-crc32.c @@ -297,6 +297,7 @@ static int stm32_crc_probe(struct platform_device *pdev) pm_runtime_get_noresume(dev); pm_runtime_set_active(dev); + pm_runtime_irq_safe(dev); pm_runtime_enable(dev); platform_set_drvdata(pdev, crc); @@ -350,34 +351,60 @@ static int stm32_crc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int stm32_crc_runtime_suspend(struct device *dev) +static int __maybe_unused stm32_crc_suspend(struct device *dev) { struct stm32_crc *crc = dev_get_drvdata(dev); + int ret; - clk_disable_unprepare(crc->clk); + ret = pm_runtime_force_suspend(dev); + if (ret) + return ret; + + clk_unprepare(crc->clk); return 0; } -static int stm32_crc_runtime_resume(struct device *dev) +static int __maybe_unused stm32_crc_resume(struct device *dev) { struct stm32_crc *crc = dev_get_drvdata(dev); int ret; - ret = clk_prepare_enable(crc->clk); + ret = clk_prepare(crc->clk); if (ret) { - dev_err(crc->dev, "Failed to prepare_enable clock\n"); + dev_err(crc->dev, "Failed to prepare clock\n"); + return ret; + } + + return pm_runtime_force_resume(dev); +} + +static int __maybe_unused stm32_crc_runtime_suspend(struct device *dev) +{ + struct stm32_crc *crc = dev_get_drvdata(dev); + + clk_disable(crc->clk); + + return 0; +} + +static int __maybe_unused stm32_crc_runtime_resume(struct device *dev) +{ + struct stm32_crc *crc = dev_get_drvdata(dev); + int ret; + + ret = clk_enable(crc->clk); + if (ret) { + dev_err(crc->dev, "Failed to enable clock\n"); return ret; } return 0; } -#endif static const struct dev_pm_ops stm32_crc_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + SET_SYSTEM_SLEEP_PM_OPS(stm32_crc_suspend, + stm32_crc_resume) SET_RUNTIME_PM_OPS(stm32_crc_runtime_suspend, stm32_crc_runtime_resume, NULL) }; |