diff options
Diffstat (limited to 'drivers/crypto/stm32/stm32-crc32.c')
-rw-r--r-- | drivers/crypto/stm32/stm32-crc32.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/drivers/crypto/stm32/stm32-crc32.c b/drivers/crypto/stm32/stm32-crc32.c index 3ba41148c2a4..75867c0b0017 100644 --- a/drivers/crypto/stm32/stm32-crc32.c +++ b/drivers/crypto/stm32/stm32-crc32.c @@ -6,7 +6,10 @@ #include <linux/bitrev.h> #include <linux/clk.h> +#include <linux/crc32.h> #include <linux/crc32poly.h> +#include <linux/io.h> +#include <linux/kernel.h> #include <linux/module.h> #include <linux/mod_devicetable.h> #include <linux/platform_device.h> @@ -147,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) @@ -155,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 @@ -195,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); @@ -216,9 +227,8 @@ static int stm32_crc_update(struct shash_desc *desc, const u8 *d8, return burst_update(desc, d8, length); /* Digest first bytes not 32bit aligned at first pass in the loop */ - size = min(length, - burst_sz + (unsigned int)d8 - ALIGN_DOWN((unsigned int)d8, - sizeof(u32))); + size = min_t(size_t, length, burst_sz + (size_t)d8 - + ALIGN_DOWN((size_t)d8, sizeof(u32))); for (rem_sz = length, cur = d8; rem_sz; rem_sz -= size, cur += size, size = min(rem_sz, burst_sz)) { ret = burst_update(desc, cur, size); |