summaryrefslogtreecommitdiff
path: root/drivers/crypto/stm32/stm32-crc32.c
diff options
context:
space:
mode:
authorNicolas Toromanoff <nicolas.toromanoff@st.com>2020-09-16 08:33:44 +0200
committerHerbert Xu <herbert@gondor.apana.org.au>2020-09-25 17:48:14 +1000
commitbbf2cb1ea1e1428589d7f4d652bed15b265ce92d (patch)
treecec14bb4328b0a7f435453ad1a9cfdb515a0af98 /drivers/crypto/stm32/stm32-crc32.c
parentc4c75fcbd8b9cc9c9fcddcb8ee68ab680d486c01 (diff)
downloadlwn-bbf2cb1ea1e1428589d7f4d652bed15b265ce92d.tar.gz
lwn-bbf2cb1ea1e1428589d7f4d652bed15b265ce92d.zip
crypto: stm32/crc32 - Avoid lock if hardware is already used
If STM32 CRC device is already in use, calculate CRC by software. This will release CPU constraint for a concurrent access to the hardware, and avoid masking irqs during the whole block processing. Fixes: 7795c0baf5ac ("crypto: stm32/crc32 - protect from concurrent accesses") 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/stm32-crc32.c')
-rw-r--r--drivers/crypto/stm32/stm32-crc32.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/drivers/crypto/stm32/stm32-crc32.c b/drivers/crypto/stm32/stm32-crc32.c
index 783a64f3f635..75867c0b0017 100644
--- a/drivers/crypto/stm32/stm32-crc32.c
+++ b/drivers/crypto/stm32/stm32-crc32.c
@@ -6,6 +6,7 @@
#include <linux/bitrev.h>
#include <linux/clk.h>
+#include <linux/crc32.h>
#include <linux/crc32poly.h>
#include <linux/io.h>
#include <linux/kernel.h>
@@ -149,7 +150,6 @@ static int burst_update(struct shash_desc *desc, const u8 *d8,
struct stm32_crc_desc_ctx *ctx = shash_desc_ctx(desc);
struct stm32_crc_ctx *mctx = crypto_shash_ctx(desc->tfm);
struct stm32_crc *crc;
- unsigned long flags;
crc = stm32_crc_get_next_crc();
if (!crc)
@@ -157,7 +157,15 @@ static int burst_update(struct shash_desc *desc, const u8 *d8,
pm_runtime_get_sync(crc->dev);
- spin_lock_irqsave(&crc->lock, flags);
+ if (!spin_trylock(&crc->lock)) {
+ /* Hardware is busy, calculate crc32 by software */
+ if (mctx->poly == CRC32_POLY_LE)
+ ctx->partial = crc32_le(ctx->partial, d8, length);
+ else
+ ctx->partial = __crc32c_le(ctx->partial, d8, length);
+
+ goto pm_out;
+ }
/*
* Restore previously calculated CRC for this context as init value
@@ -197,8 +205,9 @@ static int burst_update(struct shash_desc *desc, const u8 *d8,
/* Store partial result */
ctx->partial = readl_relaxed(crc->regs + CRC_DR);
- spin_unlock_irqrestore(&crc->lock, flags);
+ spin_unlock(&crc->lock);
+pm_out:
pm_runtime_mark_last_busy(crc->dev);
pm_runtime_put_autosuspend(crc->dev);