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: 7795c0baf5 ("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>
This commit is contained in:
Nicolas Toromanoff 2020-09-16 08:33:44 +02:00 committed by Herbert Xu
parent c4c75fcbd8
commit bbf2cb1ea1
2 changed files with 13 additions and 3 deletions

View file

@ -3,6 +3,7 @@ config CRYPTO_DEV_STM32_CRC
tristate "Support for STM32 crc accelerators" tristate "Support for STM32 crc accelerators"
depends on ARCH_STM32 depends on ARCH_STM32
select CRYPTO_HASH select CRYPTO_HASH
select CRC32
help help
This enables support for the CRC32 hw accelerator which can be found This enables support for the CRC32 hw accelerator which can be found
on STMicroelectronics STM32 SOC. on STMicroelectronics STM32 SOC.

View file

@ -6,6 +6,7 @@
#include <linux/bitrev.h> #include <linux/bitrev.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/crc32.h>
#include <linux/crc32poly.h> #include <linux/crc32poly.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/kernel.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_desc_ctx *ctx = shash_desc_ctx(desc);
struct stm32_crc_ctx *mctx = crypto_shash_ctx(desc->tfm); struct stm32_crc_ctx *mctx = crypto_shash_ctx(desc->tfm);
struct stm32_crc *crc; struct stm32_crc *crc;
unsigned long flags;
crc = stm32_crc_get_next_crc(); crc = stm32_crc_get_next_crc();
if (!crc) if (!crc)
@ -157,7 +157,15 @@ static int burst_update(struct shash_desc *desc, const u8 *d8,
pm_runtime_get_sync(crc->dev); 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 * 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 */ /* Store partial result */
ctx->partial = readl_relaxed(crc->regs + CRC_DR); 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_mark_last_busy(crc->dev);
pm_runtime_put_autosuspend(crc->dev); pm_runtime_put_autosuspend(crc->dev);