mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Rosen Penev <rosenp@gmail.com>
To: linux-crypto@vger.kernel.org
Cc: Srujana Challa <schalla@marvell.com>,
	Bharat Bhushan <bbhushan2@marvell.com>,
	Herbert Xu <herbert@gondor.apana.org.au>,
	"David S. Miller" <davem@davemloft.net>,
	linux-kernel@vger.kernel.org (open list)
Subject: [PATCHv2] crypto: cesa: complete pending requests on device remove
Date: Thu, 24 Sep 2026 16:59:37 -0700	[thread overview]
Message-ID: <20260924235937.148475-1-rosenp@gmail.com> (raw)

mv_cesa_remove() unregisters the algorithms but never drains the engine
queues.  Each engine can still hold outstanding requests in three
places: engine->req (currently in flight), engine->queue (queued but
not started), and engine->complete_queue (processed but not yet
reported).  After unregistration those waiters never receive their
completion callback and block indefinitely, leaking the request and its
scatterlist buffers.

In mv_cesa_remove() stop each engine (mask interrupts, clear the CMD and
TDMA control registers, then wait for the engine to report idle), quiesce
the threaded IRQ with disable_irq()/synchronize_irq(), and drain the
three queues, completing every outstanding request with -ENOENT.  The
completion callbacks unmap DMA buffers through the global cesa_dev
pointer, so keep it valid until the engines are drained, and mark the
engines aborted under their lock so a racing submitter cannot restart a
halted engine.

Assisted-by: LLM
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
 v2: fix a bunch of sashiko errors
 drivers/crypto/marvell/cesa/cesa.c | 80 ++++++++++++++++++++++++++++++
 drivers/crypto/marvell/cesa/cesa.h |  4 ++
 2 files changed, 84 insertions(+)

diff --git a/drivers/crypto/marvell/cesa/cesa.c b/drivers/crypto/marvell/cesa/cesa.c
index 564b09773507..d91e1af0fe9c 100644
--- a/drivers/crypto/marvell/cesa/cesa.c
+++ b/drivers/crypto/marvell/cesa/cesa.c
@@ -52,6 +52,14 @@ static void mv_cesa_rearm_engine(struct mv_cesa_engine *engine)
 
 	spin_lock_bh(&engine->lock);
 	if (!engine->req) {
+		if (engine->aborted) {
+			/*
+			 * The device is being removed: do not restart the
+			 * engine nor fetch any new request.
+			 */
+			spin_unlock_bh(&engine->lock);
+			return;
+		}
 		req = mv_cesa_dequeue_req_locked(engine, &backlog);
 		engine->req = req;
 	}
@@ -542,9 +550,81 @@ static int mv_cesa_probe(struct platform_device *pdev)
 static void mv_cesa_remove(struct platform_device *pdev)
 {
 	struct mv_cesa_dev *cesa = platform_get_drvdata(pdev);
+	struct mv_cesa_engine *engine;
+	struct crypto_async_request *req;
+	unsigned int i;
+	unsigned int timeout;
 
 	mv_cesa_remove_algs(cesa);
 
+	for (i = 0; i < cesa->caps->nengines; i++) {
+		engine = &cesa->engines[i];
+
+		/*
+		 * Stop the engine so it no longer issues DMA to the SRAM
+		 * region or to request scatterlists that are about to be
+		 * unmapped.
+		 */
+		writel(0, engine->regs + CESA_SA_INT_MSK);
+		writel(0, engine->regs + CESA_SA_CMD);
+		writel(0, engine->regs + CESA_TDMA_CONTROL);
+
+		/*
+		 * Flush the posted writes above and wait for the engine to
+		 * report that it is stopped before any buffer is released.
+		 */
+		timeout = CESA_ENGINE_STOP_TIMEOUT_US;
+		while ((readl(engine->regs + CESA_SA_CMD) &
+			CESA_SA_CMD_EN_CESA_SA_ACCL0) && --timeout)
+			udelay(1);
+
+		/*
+		 * Synchronize with the threaded IRQ handler so that it cannot
+		 * run while the queues below are drained.
+		 */
+		disable_irq(engine->irq);
+		synchronize_irq(engine->irq);
+
+		spin_lock_bh(&engine->lock);
+		engine->aborted = true;
+
+		/*
+		 * Complete the request currently in flight and drain the
+		 * pending and already-processed queues with an error so that
+		 * waiters do not block indefinitely when the device is unbound
+		 * while requests are still outstanding.
+		 */
+		if (engine->req) {
+			req = engine->req;
+			engine->req = NULL;
+			spin_unlock_bh(&engine->lock);
+			mv_cesa_complete_req(crypto_tfm_ctx(req->tfm), req,
+					     -ENOENT);
+			spin_lock_bh(&engine->lock);
+		}
+
+		while ((req = crypto_dequeue_request(&engine->queue)) != NULL) {
+			spin_unlock_bh(&engine->lock);
+			mv_cesa_complete_req(crypto_tfm_ctx(req->tfm), req,
+					     -ENOENT);
+			spin_lock_bh(&engine->lock);
+		}
+
+		while ((req = mv_cesa_engine_dequeue_complete_request(engine))
+		       != NULL) {
+			spin_unlock_bh(&engine->lock);
+			mv_cesa_complete_req(crypto_tfm_ctx(req->tfm), req,
+					     -ENOENT);
+			spin_lock_bh(&engine->lock);
+		}
+		spin_unlock_bh(&engine->lock);
+	}
+
+	/*
+	 * The completion callbacks above (and any concurrent submitter) rely
+	 * on the global cesa_dev pointer: only clear it once the engines are
+	 * fully drained.
+	 */
 	cesa_dev = NULL;
 }
 
diff --git a/drivers/crypto/marvell/cesa/cesa.h b/drivers/crypto/marvell/cesa/cesa.h
index 44351b252861..56c0dd6f5772 100644
--- a/drivers/crypto/marvell/cesa/cesa.h
+++ b/drivers/crypto/marvell/cesa/cesa.h
@@ -10,6 +10,9 @@
 
 #define CESA_ENGINE_OFF(i)			(((i) * 0x2000))
 
+/* Max time in microseconds to wait for the engine to stop */
+#define CESA_ENGINE_STOP_TIMEOUT_US		1000
+
 #define CESA_TDMA_BYTE_CNT			0x800
 #define CESA_TDMA_SRC_ADDR			0x810
 #define CESA_TDMA_DST_ADDR			0x820
@@ -450,6 +453,7 @@ struct mv_cesa_engine {
 	struct mv_cesa_tdma_chain chain_sw;
 	struct list_head complete_queue;
 	int irq;
+	bool aborted;
 };
 
 /**
-- 
2.55.0


             reply	other threads:[~2026-09-24 23:59 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-24 23:59 Rosen Penev [this message]
2026-09-25  0:15 ` Robert Lovrinovic

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260924235937.148475-1-rosenp@gmail.com \
    --to=rosenp@gmail.com \
    --cc=bbhushan2@marvell.com \
    --cc=davem@davemloft.net \
    --cc=herbert@gondor.apana.org.au \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=schalla@marvell.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®