lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Fri, 19 Mar 2021 02:22:57 +0200 From: "Dragos Rosioru (OSS)" <dragos.rosioru@....nxp.com> To: Herbert Xu <herbert@...dor.apana.org.au>, "David S . Miller" <davem@...emloft.net>, Shawn Guo <shawnguo@...nel.org>, Sascha Hauer <s.hauer@...gutronix.de>, Fabio Estevam <festevam@...il.com>, "Rafael J . Wysocki" <rafael.j.wysocki@...el.com>, Petr Mladek <pmladek@...e.com>, Jiri Kosina <jikos@...nel.org>, Luis Chamberlain <mcgrof@...nel.org> Cc: Marek Vasut <marex@...x.de>, Horia Geanta <horia.geanta@....com>, Pengutronix Kernel Team <kernel@...gutronix.de>, NXP Linux Team <linux-imx@....com>, linux-crypto@...r.kernel.org, linux-arm-kernel@...ts.infradead.org, linux-kernel@...r.kernel.org Subject: [RFC 1/1] crypto: dcp - add power management support From: Dragos Rosioru <dragos.rosioru@....com> Added suspend/resume operations for PM support in the DCP driver. After a suspend/resume cycle DCP would still be in a low-power mode and have its clocks gated, thus requiring state to be saved beforehand: - Control register value(DCP_CTRL) - Channel control register value(DCP_CHANNELCTRL) Signed-off-by: Dragos Rosioru <dragos.rosioru@....com> --- drivers/crypto/mxs-dcp.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c index d6a7784..6748a4a 100644 --- a/drivers/crypto/mxs-dcp.c +++ b/drivers/crypto/mxs-dcp.c @@ -23,6 +23,10 @@ #include <crypto/internal/skcipher.h> #include <crypto/scatterwalk.h> +#ifdef CONFIG_PM_SLEEP +#include <linux/freezer.h> +#endif + #define DCP_MAX_CHANS 4 #define DCP_BUF_SZ PAGE_SIZE #define DCP_SHA_PAY_SZ 64 @@ -124,7 +128,10 @@ struct dcp_export_state { * design of Linux Crypto API. */ static struct dcp *global_sdcp; - +#ifdef CONFIG_PM_SLEEP +static uint32_t ctrl_bak; +static int dcp_vmi_irq_bak, dcp_irq_bak; +#endif /* DCP register layout. */ #define MXS_DCP_CTRL 0x00 #define MXS_DCP_CTRL_GATHER_RESIDUAL_WRITES (1 << 23) @@ -398,9 +405,15 @@ static int dcp_chan_thread_aes(void *data) int ret; +#ifdef CONFIG_PM_SLEEP + set_freezable(); +#endif while (!kthread_should_stop()) { set_current_state(TASK_INTERRUPTIBLE); +#ifdef CONFIG_PM_SLEEP + try_to_freeze(); +#endif spin_lock(&sdcp->lock[chan]); backlog = crypto_get_backlog(&sdcp->queue[chan]); arq = crypto_dequeue_request(&sdcp->queue[chan]); @@ -438,6 +451,10 @@ static int mxs_dcp_block_fallback(struct skcipher_request *req, int enc) skcipher_request_set_crypt(&rctx->fallback_req, req->src, req->dst, req->cryptlen, req->iv); +#ifdef CONFIG_PM_SLEEP + set_freezable(); + try_to_freeze(); +#endif if (enc) ret = crypto_skcipher_encrypt(&rctx->fallback_req); else @@ -686,9 +703,15 @@ static int dcp_chan_thread_sha(void *data) struct crypto_async_request *arq; int ret; +#ifdef CONFIG_PM_SLEEP + set_freezable(); +#endif while (!kthread_should_stop()) { set_current_state(TASK_INTERRUPTIBLE); +#ifdef CONFIG_PM_SLEEP + try_to_freeze(); +#endif spin_lock(&sdcp->lock[chan]); backlog = crypto_get_backlog(&sdcp->queue[chan]); arq = crypto_dequeue_request(&sdcp->queue[chan]); @@ -961,6 +984,49 @@ static irqreturn_t mxs_dcp_irq(int irq, void *context) return IRQ_HANDLED; } +#ifdef CONFIG_PM_SLEEP +static int mxs_dcp_resume(struct device *dev) +{ + struct dcp *sdcp = global_sdcp; + int ret; + + /* Restart the DCP block */ + ret = stmp_reset_block(sdcp->base); + if (ret) { + dev_err(dev, "Failed reset\n"); + clk_disable_unprepare(sdcp->dcp_clk); + return ret; + } + + /* Restore control register */ + writel(ctrl_bak, sdcp->base + MXS_DCP_CTRL); + /* Enable all DCP DMA channels */ + writel(MXS_DCP_CHANNELCTRL_ENABLE_CHANNEL_MASK, + sdcp->base + MXS_DCP_CHANNELCTRL); + + /* Re-enable DCP interrupts */ + enable_irq(dcp_irq_bak); + enable_irq(dcp_vmi_irq_bak); + + return 0; +} + +static int mxs_dcp_suspend(struct device *dev) +{ + struct dcp *sdcp = global_sdcp; + + /* Backup control register */ + ctrl_bak = readl(sdcp->base + MXS_DCP_CTRL); + /* Temporarily disable DCP interrupts */ + disable_irq(dcp_irq_bak); + disable_irq(dcp_vmi_irq_bak); + + return 0; +} + +SIMPLE_DEV_PM_OPS(mxs_dcp_pm_ops, mxs_dcp_suspend, mxs_dcp_resume); +#endif + static int mxs_dcp_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -980,7 +1046,10 @@ static int mxs_dcp_probe(struct platform_device *pdev) dcp_irq = platform_get_irq(pdev, 1); if (dcp_irq < 0) return dcp_irq; - +#ifdef CONFIG_PM_SLEEP + dcp_vmi_irq_bak = dcp_vmi_irq; + dcp_irq_bak = dcp_irq; +#endif sdcp = devm_kzalloc(dev, sizeof(*sdcp), GFP_KERNEL); if (!sdcp) return -ENOMEM; @@ -1172,6 +1241,9 @@ static struct platform_driver mxs_dcp_driver = { .driver = { .name = "mxs-dcp", .of_match_table = mxs_dcp_dt_ids, +#ifdef CONFIG_PM_SLEEP + .pm = &mxs_dcp_pm_ops +#endif }, }; -- 2.7.4
Powered by blists - more mailing lists