[PATCH v2 26/30] crypto: sa2ul - use a mempool for security contexts

From: Manorit Chawdhry

Date: Wed Nov 04 2026 - 00:54:37 EST


The SA2UL engine is a DMA master, so any memory it accesses must either
be allocated coherent or be explicitly synced with the CPU cache around
each access.

The security context buffer is currently allocated from a DMA pool via
dma_pool_alloc(), which assumes coherent memory, which is untrue at a
bus level for many of our SoCs. This causes any fetch issues from SA2UL
to end up getting some stale or unsynced data, causing failures for any
crypto operations.

To remove this, allocate the security context from a kmalloc-backed
mempool instead. Since this memory is now ordinary cacheable kernel
memory, explicitly call dma_map_single()/dma_unmap_single() for
DMA-related operations.

Signed-off-by: Manorit Chawdhry <m-chawdhry@xxxxxx>
---
drivers/crypto/sa2ul.c | 36 +++++++++++++++++++++++++-----------
drivers/crypto/sa2ul.h | 2 +-
2 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/drivers/crypto/sa2ul.c b/drivers/crypto/sa2ul.c
index d4c0e5b836ac..ae3889695dfe 100644
--- a/drivers/crypto/sa2ul.c
+++ b/drivers/crypto/sa2ul.c
@@ -13,6 +13,7 @@
#include <linux/dmaengine.h>
#include <linux/dmapool.h>
#include <linux/kernel.h>
+#include <linux/mempool.h>
#include <linux/module.h>
#include <linux/unaligned.h>
#include <linux/of.h>
@@ -629,12 +630,16 @@ int sa_init_sc(struct sa_ctx_info *ctx, const struct sa_match_data *match_data,
const u8 *auth_key, unsigned int auth_key_sz,
struct algo_data *ad, u8 enc, u32 *swinfo)
{
+ struct sa_crypto_data *data = dev_get_drvdata(sa_k3_dev);
+ struct device *dev = &data->pdev->dev;
+
int enc_sc_offset = 0;
int auth_sc_offset = 0;
u8 *sc_buf = ctx->sc;
u16 sc_id = ctx->sc_id;
u8 first_engine = 0;

+ dma_sync_single_for_cpu(dev, ctx->sc_phys, SA_CTX_MAX_SZ, DMA_BIDIRECTIONAL);
memzero_explicit(sc_buf, SA_CTX_MAX_SZ);

if (ad->auth_eng.eng_id) {
@@ -682,11 +687,13 @@ int sa_init_sc(struct sa_ctx_info *ctx, const struct sa_match_data *match_data,
/* swizzle the security context */
sa_swiz_128(sc_buf, SA_CTX_MAX_SZ);

+ sa_dump_sc(sc_buf, ctx->sc_phys);
+
+ dma_sync_single_for_device(dev, ctx->sc_phys, SA_CTX_MAX_SZ, DMA_BIDIRECTIONAL);
+
sa_set_swinfo(first_engine, ctx->sc_id, ctx->sc_phys, 1, 0,
SA_SW_INFO_FLAG_EVICT, roundup(ad->hash_size, 8), swinfo);

- sa_dump_sc(sc_buf, ctx->sc_phys);
-
return 0;
}

@@ -694,6 +701,7 @@ int sa_init_sc(struct sa_ctx_info *ctx, const struct sa_match_data *match_data,
static void sa_free_ctx_info(struct sa_ctx_info *ctx,
struct sa_crypto_data *data)
{
+ struct device *dev = &data->pdev->dev;
unsigned long bn;

bn = ctx->sc_id;
@@ -703,8 +711,9 @@ static void sa_free_ctx_info(struct sa_ctx_info *ctx,
spin_unlock(&data->scid_lock);

if (ctx->sc) {
+ dma_unmap_single(dev, ctx->sc_phys, SA_CTX_MAX_SZ, DMA_BIDIRECTIONAL);
memzero_explicit(ctx->sc, SA_CTX_MAX_SZ);
- dma_pool_free(data->sc_pool, ctx->sc, ctx->sc_phys);
+ mempool_free(ctx->sc, data->sc_pool);
ctx->sc = NULL;
}
}
@@ -713,7 +722,8 @@ static int sa_init_ctx_info(struct sa_ctx_info *ctx,
struct sa_crypto_data *data)
{
unsigned long bn;
- int err;
+ int err = 0;
+ struct device *dev = &data->pdev->dev;

spin_lock(&data->scid_lock);
bn = find_first_zero_bit(data->ctx_bm, SA_MAX_NUM_CTX);
@@ -726,10 +736,15 @@ static int sa_init_ctx_info(struct sa_ctx_info *ctx,
spin_unlock(&data->scid_lock);

ctx->sc_id = (u16)bn;
+ ctx->sc_phys = 0;

- ctx->sc = dma_pool_alloc(data->sc_pool, GFP_KERNEL, &ctx->sc_phys);
- if (!ctx->sc) {
- dev_err(&data->pdev->dev, "Failed to allocate SC memory\n");
+ ctx->sc = mempool_alloc(data->sc_pool, GFP_KERNEL);
+
+ ctx->sc_phys = dma_map_single(dev, ctx->sc, SA_CTX_MAX_SZ, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(dev, ctx->sc_phys)) {
+ dev_err(dev, "Failed to map SC DMA\n");
+ mempool_free(ctx->sc, data->sc_pool);
+ ctx->sc = NULL;
err = -ENOMEM;
goto scid_rollback;
}
@@ -2153,8 +2168,7 @@ static int sa_init_mem(struct sa_crypto_data *dev_data)
{
struct device *dev = &dev_data->pdev->dev;
/* Setup dma pool for security context buffers */
- dev_data->sc_pool = dma_pool_create("keystone-sc", dev,
- SA_CTX_MAX_SZ, 64, 0);
+ dev_data->sc_pool = mempool_create_kmalloc_pool(64, SA_CTX_MAX_SZ);
if (!dev_data->sc_pool) {
dev_err(dev, "Failed to create dma pool");
return -ENOMEM;
@@ -2348,7 +2362,7 @@ static int sa_ul_probe(struct platform_device *pdev)
dma_release_channel(dev_data->dma_tx);

destroy_dma_pool:
- dma_pool_destroy(dev_data->sc_pool);
+ mempool_destroy(dev_data->sc_pool);

disable_pm:
pm_runtime_put_sync(dev);
@@ -2369,7 +2383,7 @@ static void sa_ul_remove(struct platform_device *pdev)
dma_release_channel(dev_data->dma_rx1);
dma_release_channel(dev_data->dma_tx);

- dma_pool_destroy(dev_data->sc_pool);
+ mempool_destroy(dev_data->sc_pool);

platform_set_drvdata(pdev, NULL);

diff --git a/drivers/crypto/sa2ul.h b/drivers/crypto/sa2ul.h
index 67bc722a1170..775f3939be68 100644
--- a/drivers/crypto/sa2ul.h
+++ b/drivers/crypto/sa2ul.h
@@ -163,7 +163,7 @@ struct sa_match_data;
struct sa_crypto_data {
const struct sa_match_data *match_data;
struct platform_device *pdev;
- struct dma_pool *sc_pool;
+ mempool_t *sc_pool;
struct device *dev;
spinlock_t scid_lock; /* lock for SC-ID allocation */
/* Security context data */

--
2.43.0