--- /dev/null
+From 247bd153905085c18ff9006cca1ccb96dfd18e7f Mon Sep 17 00:00:00 2001
+From: Mark Rutland <mark.rutland@arm.com>
+Date: Wed, 3 Jun 2026 12:06:12 +0100
+Subject: arm64: fpsimd: Fix type mismatch in sme_{save,load}_state()
+
+From: Mark Rutland <mark.rutland@arm.com>
+
+commit 247bd153905085c18ff9006cca1ccb96dfd18e7f upstream.
+
+The sme_save_state() and sme_load_state() functions take a 32-bit int
+argument that describes whether to save/restore ZT0. Their assembly
+implementations consume the entire 64-bit register containing this
+32-bit value, and will attempt to save/restore ZT0 if any bit of
+that 64-bit register is non-zero.
+
+Per the AAPCS64 parameter passing rules, the callee is responsible for
+any necessary widening, and the upper 32-bits are permitted to contain
+arbitrary values. If the upper 32 bits are non-zero, this could result
+in an unexpected attempt to save/restore ZT0, and consequently could
+lead to unexpected traps/undefs/faults.
+
+In practice compilers are very unlikely to generate code where the upper
+32-bits would be non-zero, but they are permitted to do so.
+
+Fix this by only consuming the low 32 bits of the register, and update
+comments accordingly.
+
+Fixes: 95fcec713259 ("arm64/sme: Implement context switching for ZT0")
+Signed-off-by: Mark Rutland <mark.rutland@arm.com>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Fuad Tabba <tabba@google.com>
+Cc: James Morse <james.morse@arm.com>
+Cc: Marc Zyngier <maz@kernel.org>
+Cc: Mark Brown <broonie@kernel.org>
+Cc: Oliver Upton <oupton@kernel.org>
+Cc: Vladimir Murzin <vladimir.murzin@arm.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kernel/entry-fpsimd.S | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/arch/arm64/kernel/entry-fpsimd.S
++++ b/arch/arm64/kernel/entry-fpsimd.S
+@@ -103,13 +103,13 @@ SYM_FUNC_END(sme_set_vq)
+ * Save the ZA and ZT state
+ *
+ * x0 - pointer to buffer for state
+- * x1 - number of ZT registers to save
++ * w1 - number of ZT registers to save
+ */
+ SYM_FUNC_START(sme_save_state)
+ _sme_rdsvl 2, 1 // x2 = VL/8
+ sme_save_za 0, x2, 12 // Leaves x0 pointing to the end of ZA
+
+- cbz x1, 1f
++ cbz w1, 1f
+ _str_zt 0
+ 1:
+ ret
+@@ -119,13 +119,13 @@ SYM_FUNC_END(sme_save_state)
+ * Load the ZA and ZT state
+ *
+ * x0 - pointer to buffer for state
+- * x1 - number of ZT registers to save
++ * w1 - number of ZT registers to save
+ */
+ SYM_FUNC_START(sme_load_state)
+ _sme_rdsvl 2, 1 // x2 = VL/8
+ sme_load_za 0, x2, 12 // Leaves x0 pointing to the end of ZA
+
+- cbz x1, 1f
++ cbz w1, 1f
+ _ldr_zt 0
+ 1:
+ ret
--- /dev/null
+From f126384ed55279c3b676f89d5ab547b8de8df782 Mon Sep 17 00:00:00 2001
+From: Paul Louvel <paul.louvel@bootlin.com>
+Date: Thu, 7 May 2026 16:41:48 +0200
+Subject: crypto: talitos - add chaining of arbitrary number of descriptor for the SEC1
+
+From: Paul Louvel <paul.louvel@bootlin.com>
+
+commit f126384ed55279c3b676f89d5ab547b8de8df782 upstream.
+
+The SEC1 hardware can process a chain of descriptors without host
+intervention. Only the hash implementation currently use this feature,
+but with a chain of at most 2 descriptors added in commit 37b5e8897eb5
+("crypto: talitos - chain in buffered data for ahash on SEC1").
+
+Add supports for chaining an arbitrary number of descriptors in a chain.
+
+Adapt the ahash implementation to make it compatible.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/talitos.c | 180 +++++++++++++++++++++++++++++++----------------
+ drivers/crypto/talitos.h | 2
+ 2 files changed, 124 insertions(+), 58 deletions(-)
+
+--- a/drivers/crypto/talitos.c
++++ b/drivers/crypto/talitos.c
+@@ -273,7 +273,10 @@ static int talitos_submit(struct device
+ void *context, int error),
+ void *context)
+ {
++ struct talitos_edesc *edesc = container_of(desc, struct talitos_edesc, desc);
+ struct talitos_private *priv = dev_get_drvdata(dev);
++ dma_addr_t dma_desc, prev_dma_desc;
++ struct talitos_edesc *prev_edesc = NULL;
+ struct talitos_request *request;
+ unsigned long flags;
+ int head;
+@@ -292,10 +295,31 @@ static int talitos_submit(struct device
+
+ /* map descriptor and save caller data */
+ if (is_sec1) {
+- desc->hdr1 = desc->hdr;
+- request->dma_desc = dma_map_single(dev, &desc->hdr1,
++ while (edesc) {
++ edesc->desc.hdr1 = edesc->desc.hdr;
++
++ dma_desc = dma_map_single(dev, &edesc->desc.hdr1,
++ TALITOS_DESC_SIZE,
++ DMA_BIDIRECTIONAL);
++
++ if (!prev_edesc) {
++ request->dma_desc = dma_desc;
++ goto next;
++ }
++
++ /* Chain in any previous descriptors. */
++
++ prev_edesc->desc.next_desc = cpu_to_be32(dma_desc);
++
++ dma_sync_single_for_device(dev, prev_dma_desc,
+ TALITOS_DESC_SIZE,
+- DMA_BIDIRECTIONAL);
++ DMA_TO_DEVICE);
++
++next:
++ prev_edesc = edesc;
++ prev_dma_desc = dma_desc;
++ edesc = edesc->next_desc;
++ }
+ } else {
+ request->dma_desc = dma_map_single(dev, desc,
+ TALITOS_DESC_SIZE,
+@@ -326,6 +350,7 @@ static __be32 get_request_hdr(struct dev
+ struct talitos_request *request, bool is_sec1)
+ {
+ struct talitos_edesc *edesc;
++ dma_addr_t dma_desc;
+
+ if (!is_sec1) {
+ dma_sync_single_for_cpu(dev, request->dma_desc,
+@@ -334,19 +359,17 @@ static __be32 get_request_hdr(struct dev
+ return request->desc->hdr;
+ }
+
+- if (!request->desc->next_desc) {
+- dma_sync_single_for_cpu(dev, request->dma_desc,
+- TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
+- return request->desc->hdr1;
+- } else {
+- dma_sync_single_for_cpu(dev,
+- be32_to_cpu(request->desc->next_desc),
+- TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
+- edesc = container_of(request->desc, struct talitos_edesc, desc);
+-
+- return ((struct talitos_desc *)(edesc->buf + edesc->dma_len))
+- ->hdr1;
++ edesc = container_of(request->desc, struct talitos_edesc, desc);
++ dma_desc = request->dma_desc;
++ while (edesc->next_desc) {
++ dma_desc = be32_to_cpu(edesc->desc.next_desc);
++ edesc = edesc->next_desc;
+ }
++
++ dma_sync_single_for_cpu(dev, dma_desc, TALITOS_DESC_SIZE,
++ DMA_BIDIRECTIONAL);
++
++ return edesc->desc.hdr1;
+ }
+
+ /*
+@@ -356,6 +379,7 @@ static void flush_channel(struct device
+ {
+ struct talitos_private *priv = dev_get_drvdata(dev);
+ struct talitos_request *request, saved_req;
++ struct talitos_edesc *edesc;
+ unsigned long flags;
+ int tail, status;
+ bool is_sec1 = has_ftr_sec1(priv);
+@@ -380,9 +404,22 @@ static void flush_channel(struct device
+ else
+ status = error;
+
+- dma_unmap_single(dev, request->dma_desc,
+- TALITOS_DESC_SIZE,
+- DMA_BIDIRECTIONAL);
++ if (is_sec1) {
++ dma_unmap_single(dev, request->dma_desc,
++ TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
++ edesc = container_of(request->desc,
++ struct talitos_edesc, desc);
++ while (edesc->next_desc) {
++ dma_unmap_single(
++ dev, be32_to_cpu(edesc->desc.next_desc),
++ TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
++ edesc = edesc->next_desc;
++ }
++ } else {
++ dma_unmap_single(dev, request->dma_desc,
++ TALITOS_DESC_SIZE,
++ DMA_BIDIRECTIONAL);
++ }
+
+ /* copy entries so we can call callback outside lock */
+ saved_req.desc = request->desc;
+@@ -477,8 +514,12 @@ DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH
+ static __be32 current_desc_hdr(struct device *dev, int ch)
+ {
+ struct talitos_private *priv = dev_get_drvdata(dev);
++ bool is_sec1 = has_ftr_sec1(priv);
++ struct talitos_request *request;
++ struct talitos_edesc *edesc;
+ int tail, iter;
+ dma_addr_t cur_desc;
++ __be32 hdr = 0;
+
+ cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
+ cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
+@@ -489,27 +530,35 @@ static __be32 current_desc_hdr(struct de
+ }
+
+ tail = priv->chan[ch].tail;
+-
+ iter = tail;
+- while (priv->chan[ch].fifo[iter].dma_desc != cur_desc &&
+- priv->chan[ch].fifo[iter].desc->next_desc != cpu_to_be32(cur_desc)) {
+- iter = (iter + 1) & (priv->fifo_len - 1);
+- if (iter == tail) {
+- dev_err(dev, "couldn't locate current descriptor\n");
+- return 0;
++ do {
++ request = &priv->chan[ch].fifo[iter];
++
++ if (request->dma_desc == cur_desc) {
++ hdr = request->desc->hdr;
++ } else if (is_sec1) {
++ edesc = container_of(request->desc,
++ struct talitos_edesc, desc);
++ while (edesc->next_desc) {
++ if (edesc->desc.next_desc ==
++ cpu_to_be32(cur_desc)) {
++ hdr = edesc->next_desc->desc.hdr1;
++ break;
++ }
++ edesc = edesc->next_desc;
++ }
+ }
+- }
+
+- if (priv->chan[ch].fifo[iter].desc->next_desc == cpu_to_be32(cur_desc)) {
+- struct talitos_edesc *edesc;
++ if (hdr)
++ break;
+
+- edesc = container_of(priv->chan[ch].fifo[iter].desc,
+- struct talitos_edesc, desc);
+- return ((struct talitos_desc *)
+- (edesc->buf + edesc->dma_len))->hdr;
+- }
++ iter = (iter + 1) & (priv->fifo_len - 1);
++ } while (iter != tail);
++
++ if (!hdr)
++ dev_err(dev, "couldn't locate current descriptor\n");
+
+- return priv->chan[ch].fifo[iter].desc->hdr;
++ return hdr;
+ }
+
+ /*
+@@ -1408,10 +1457,6 @@ static struct talitos_edesc *talitos_ede
+ dma_len = 0;
+ }
+ alloc_len += icv_stashing ? authsize : 0;
+-
+- /* if its a ahash, add space for a second desc next to the first one */
+- if (is_sec1 && !dst)
+- alloc_len += sizeof(struct talitos_desc);
+ alloc_len += ivsize;
+
+ edesc = kmalloc(ALIGN(alloc_len, dma_get_cache_alignment()), flags);
+@@ -1427,6 +1472,7 @@ static struct talitos_edesc *talitos_ede
+ edesc->dst_nents = dst_nents;
+ edesc->iv_dma = iv_dma;
+ edesc->dma_len = dma_len;
++ edesc->next_desc = NULL;
+ if (dma_len)
+ edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0],
+ edesc->dma_len,
+@@ -1727,8 +1773,10 @@ static void common_nonsnoop_hash_unmap(s
+ struct talitos_private *priv = dev_get_drvdata(dev);
+ bool is_sec1 = has_ftr_sec1(priv);
+ struct talitos_desc *desc = &edesc->desc;
+- struct talitos_desc *desc2 = (struct talitos_desc *)
+- (edesc->buf + edesc->dma_len);
++ struct talitos_desc *desc2;
++
++ if (desc->next_desc)
++ desc2 = &edesc->next_desc->desc;
+
+ unmap_single_talitos_ptr(dev, &desc->ptr[5], DMA_FROM_DEVICE);
+ if (desc->next_desc &&
+@@ -1756,10 +1804,17 @@ static void common_nonsnoop_hash_unmap(s
+ if (edesc->dma_len)
+ dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
+ DMA_BIDIRECTIONAL);
++}
+
+- if (desc->next_desc)
+- dma_unmap_single(dev, be32_to_cpu(desc->next_desc),
+- TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
++static void free_edesc_list_from(struct talitos_edesc *edesc)
++{
++ struct talitos_edesc *next;
++
++ while (edesc) {
++ next = edesc->next_desc;
++ kfree(edesc);
++ edesc = next;
++ }
+ }
+
+ static void ahash_done(struct device *dev,
+@@ -1778,7 +1833,7 @@ static void ahash_done(struct device *de
+ }
+ common_nonsnoop_hash_unmap(dev, edesc, areq);
+
+- kfree(edesc);
++ free_edesc_list_from(edesc);
+
+ if (err) {
+ ahash_request_complete(areq, err);
+@@ -1894,14 +1949,23 @@ static int common_nonsnoop_hash(struct t
+ talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
+
+ if (is_sec1 && req_ctx->nbuf && length) {
+- struct talitos_desc *desc2 = (struct talitos_desc *)
+- (edesc->buf + edesc->dma_len);
+- dma_addr_t next_desc;
++ struct talitos_edesc *edesc2;
++ struct talitos_desc *desc2;
++
++ edesc2 = kzalloc(sizeof(*edesc2),
++ areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
++ GFP_KERNEL :
++ GFP_ATOMIC);
++ if (!edesc2) {
++ ret = -ENOMEM;
++ goto err;
++ }
++ edesc->next_desc = edesc2;
++
++ desc2 = &edesc2->desc;
+
+- memset(desc2, 0, sizeof(*desc2));
+ desc2->hdr = desc->hdr;
+ desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT;
+- desc2->hdr1 = desc2->hdr;
+ desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
+ desc->hdr |= DESC_HDR_MODE0_MDEU_CONT;
+ desc->hdr &= ~DESC_HDR_DONE_NOTIFY;
+@@ -1925,21 +1989,21 @@ static int common_nonsnoop_hash(struct t
+ req_ctx->hw_context_size,
+ req_ctx->hw_context,
+ DMA_FROM_DEVICE);
+-
+- next_desc = dma_map_single(dev, &desc2->hdr1, TALITOS_DESC_SIZE,
+- DMA_BIDIRECTIONAL);
+- desc->next_desc = cpu_to_be32(next_desc);
+ }
+
+ if (sync_needed)
+ dma_sync_single_for_device(dev, edesc->dma_link_tbl,
+ edesc->dma_len, DMA_BIDIRECTIONAL);
+
+- ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
+- if (ret != -EINPROGRESS) {
+- common_nonsnoop_hash_unmap(dev, edesc, areq);
+- kfree(edesc);
+- }
++ ret = talitos_submit(dev, ctx->ch, desc, callback,
++ areq);
++ if (ret != -EINPROGRESS)
++ goto err;
++
++ return -EINPROGRESS;
++err:
++ common_nonsnoop_hash_unmap(dev, edesc, areq);
++ kfree(edesc);
+ return ret;
+ }
+
+--- a/drivers/crypto/talitos.h
++++ b/drivers/crypto/talitos.h
+@@ -49,6 +49,7 @@ struct talitos_desc {
+ * @iv_dma: dma address of iv for checking continuity and link table
+ * @dma_len: length of dma mapped link_tbl space
+ * @dma_link_tbl: bus physical address of link_tbl/buf
++ * @next_desc: next descriptor
+ * @desc: h/w descriptor
+ * @link_tbl: input and output h/w link tables (if {src,dst}_nents > 1) (SEC2)
+ * @buf: input and output buffeur (if {src,dst}_nents > 1) (SEC1)
+@@ -63,6 +64,7 @@ struct talitos_edesc {
+ dma_addr_t iv_dma;
+ int dma_len;
+ dma_addr_t dma_link_tbl;
++ struct talitos_edesc *next_desc;
+ struct talitos_desc desc;
+ union {
+ DECLARE_FLEX_ARRAY(struct talitos_ptr, link_tbl);
--- /dev/null
+From be4802afb1700534e48cb776d0d1e772c27de130 Mon Sep 17 00:00:00 2001
+From: Paul Louvel <paul.louvel@bootlin.com>
+Date: Thu, 7 May 2026 16:41:54 +0200
+Subject: crypto: talitos/hash - drop workqueue mechanism for SEC1
+
+From: Paul Louvel <paul.louvel@bootlin.com>
+
+commit be4802afb1700534e48cb776d0d1e772c27de130 upstream.
+
+Now that SEC1 hash uses hardware descriptor chaining instead of a
+workqueue to process requests exceeding TALITOS1_MAX_DATA_LEN, the
+workqueue code is no longer needed.
+
+Remove sec1_ahash_process_remaining(), the related fields from
+talitos_ahash_req_ctx (request_bufsl, areq, request_sl,
+remaining_ahash_request_bytes, current_ahash_request_bytes,
+sec1_ahash_process_remaining), the dead code in ahash_done(), and
+simplify ahash_process_req() to call ahash_process_req_one() directly
+with the original areq->src and areq->nbytes.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/talitos.c | 80 ++++-------------------------------------------
+ 1 file changed, 7 insertions(+), 73 deletions(-)
+
+--- a/drivers/crypto/talitos.c
++++ b/drivers/crypto/talitos.c
+@@ -12,7 +12,6 @@
+ * All rights reserved.
+ */
+
+-#include <linux/workqueue.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/mod_devicetable.h>
+@@ -952,13 +951,6 @@ struct talitos_ahash_req_ctx {
+ unsigned int nbuf;
+ struct scatterlist bufsl[2];
+ struct scatterlist *psrc;
+-
+- struct scatterlist request_bufsl[2];
+- struct ahash_request *areq;
+- struct scatterlist *request_sl;
+- unsigned int remaining_ahash_request_bytes;
+- unsigned int current_ahash_request_bytes;
+- struct work_struct sec1_ahash_process_remaining;
+ };
+
+ struct talitos_export_state {
+@@ -1840,18 +1832,6 @@ static void ahash_done(struct device *de
+ free_edesc_list_from(areq, edesc);
+
+ ahash_request_complete(areq, err);
+-
+- return;
+-
+- req_ctx->remaining_ahash_request_bytes -=
+- req_ctx->current_ahash_request_bytes;
+-
+- if (!req_ctx->remaining_ahash_request_bytes) {
+- ahash_request_complete(areq, 0);
+- return;
+- }
+-
+- schedule_work(&req_ctx->sec1_ahash_process_remaining);
+ }
+
+ /*
+@@ -2044,12 +2024,12 @@ static int ahash_process_req_one(struct
+
+ if (!req_ctx->last_request && (nbytes + req_ctx->nbuf <= blocksize)) {
+ /* Buffer up to one whole block */
+- nents = sg_nents_for_len(req_ctx->request_sl, nbytes);
++ nents = sg_nents_for_len(areq->src, nbytes);
+ if (nents < 0) {
+ dev_err(dev, "Invalid number of src SG.\n");
+ return nents;
+ }
+- sg_copy_to_buffer(req_ctx->request_sl, nents,
++ sg_copy_to_buffer(areq->src, nents,
+ ctx_buf + req_ctx->nbuf, nbytes);
+ req_ctx->nbuf += nbytes;
+ return 0;
+@@ -2076,18 +2056,18 @@ static int ahash_process_req_one(struct
+ sg_init_table(req_ctx->bufsl, nsg);
+ sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf);
+ if (nsg > 1)
+- sg_chain(req_ctx->bufsl, 2, req_ctx->request_sl);
++ sg_chain(req_ctx->bufsl, 2, areq->src);
+ req_ctx->psrc = req_ctx->bufsl;
+ } else
+- req_ctx->psrc = req_ctx->request_sl;
++ req_ctx->psrc = areq->src;
+
+ if (to_hash_later) {
+- nents = sg_nents_for_len(req_ctx->request_sl, nbytes);
++ nents = sg_nents_for_len(areq->src, nbytes);
+ if (nents < 0) {
+ dev_err(dev, "Invalid number of src SG.\n");
+ return nents;
+ }
+- sg_pcopy_to_buffer(req_ctx->request_sl, nents,
++ sg_pcopy_to_buffer(areq->src, nents,
+ req_ctx->buf[(req_ctx->buf_idx + 1) & 1],
+ to_hash_later,
+ nbytes - to_hash_later);
+@@ -2106,54 +2086,9 @@ static int ahash_process_req_one(struct
+ return ret;
+ }
+
+-static void sec1_ahash_process_remaining(struct work_struct *work)
+-{
+- struct talitos_ahash_req_ctx *req_ctx =
+- container_of(work, struct talitos_ahash_req_ctx,
+- sec1_ahash_process_remaining);
+- int err = 0;
+-
+- req_ctx->request_sl = scatterwalk_ffwd(req_ctx->request_bufsl,
+- req_ctx->request_sl, TALITOS1_MAX_DATA_LEN);
+-
+- if (req_ctx->remaining_ahash_request_bytes > TALITOS1_MAX_DATA_LEN)
+- req_ctx->current_ahash_request_bytes = TALITOS1_MAX_DATA_LEN;
+- else {
+- req_ctx->current_ahash_request_bytes =
+- req_ctx->remaining_ahash_request_bytes;
+-
+- if (req_ctx->last_request)
+- req_ctx->last_desc = 1;
+- }
+-
+- err = ahash_process_req_one(req_ctx->areq,
+- req_ctx->current_ahash_request_bytes);
+-
+- if (err != -EINPROGRESS)
+- ahash_request_complete(req_ctx->areq, err);
+-}
+-
+ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
+ {
+- struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
+- struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
+- struct device *dev = ctx->dev;
+- struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
+- struct talitos_private *priv = dev_get_drvdata(dev);
+- bool is_sec1 = has_ftr_sec1(priv);
+-
+- req_ctx->areq = areq;
+- req_ctx->request_sl = areq->src;
+- req_ctx->remaining_ahash_request_bytes = nbytes;
+-
+- if (is_sec1) {
+- if (req_ctx->last_request)
+- req_ctx->last_desc = 1;
+- }
+-
+- req_ctx->current_ahash_request_bytes = nbytes;
+-
+- return ahash_process_req_one(req_ctx->areq, nbytes);
++ return ahash_process_req_one(areq, nbytes);
+ }
+
+ static int ahash_init(struct ahash_request *areq)
+@@ -2176,7 +2111,6 @@ static int ahash_init(struct ahash_reque
+ req_ctx->hw_context_size = size;
+ req_ctx->last_request = 0;
+ req_ctx->last_desc = 0;
+- INIT_WORK(&req_ctx->sec1_ahash_process_remaining, sec1_ahash_process_remaining);
+
+ dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
+ DMA_TO_DEVICE);
--- /dev/null
+From 6e12daff6ec125102a6fdcafc5aa7199f7ce8933 Mon Sep 17 00:00:00 2001
+From: Paul Louvel <paul.louvel@bootlin.com>
+Date: Thu, 7 May 2026 16:41:57 +0200
+Subject: crypto: talitos/hash - fix SEC2 64k - 1 ahash request limitation
+
+From: Paul Louvel <paul.louvel@bootlin.com>
+
+commit 6e12daff6ec125102a6fdcafc5aa7199f7ce8933 upstream.
+
+The problem described in commit 655ef638a2bc ("crypto: talitos - fix
+SEC1 32k ahash request limitation") also apply for the SEC2 hardware,
+but with a limitation of 64k - 1 bytes.
+
+Split ahash_done() into SEC1 and SEC2 paths: SEC1 continues to free the
+whole descriptor list at once, while SEC2 now iterates through
+descriptors one by one, submitting the next only after the previous
+completes, which is required since SEC2 cannot chain descriptors in
+hardware.
+
+Cc: stable@vger.kernel.org
+Fixes: c662b043cdca ("crypto: af_alg/hash: Support MSG_SPLICE_PAGES")
+Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/talitos.c | 49 ++++++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 40 insertions(+), 9 deletions(-)
+
+--- a/drivers/crypto/talitos.c
++++ b/drivers/crypto/talitos.c
+@@ -1820,16 +1820,46 @@ static void ahash_done(struct device *de
+ struct talitos_edesc *edesc =
+ container_of(desc, struct talitos_edesc, desc);
+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
++ bool is_sec1 = has_ftr_sec1(dev_get_drvdata(dev));
++ struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
++ struct talitos_edesc *next;
+
+- if (!req_ctx->last_request && req_ctx->to_hash_later) {
+- /* Position any partial block for next update/final/finup */
+- req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1;
+- req_ctx->nbuf = req_ctx->to_hash_later;
++ if (is_sec1) {
++ if (!req_ctx->last_request && req_ctx->to_hash_later) {
++ /* Position any partial block for next update/final/finup */
++ req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1;
++ req_ctx->nbuf = req_ctx->to_hash_later;
++ }
++
++ free_edesc_list_from(areq, edesc);
++ ahash_request_complete(areq, err);
++ } else {
++ next = edesc->next_desc;
++
++ common_nonsnoop_hash_unmap(dev, edesc, areq);
++ kfree(edesc);
++
++ if (err)
++ goto out;
++
++ if (next) {
++ err = talitos_submit(dev, ctx->ch, &next->desc,
++ ahash_done, areq);
++ if (err != -EINPROGRESS)
++ goto out;
++ return;
++ }
++out:
++ if (!req_ctx->last_request && req_ctx->to_hash_later) {
++ /* Position any partial block for next update/final/finup */
++ req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1;
++ req_ctx->nbuf = req_ctx->to_hash_later;
++ }
++ if (err && next)
++ free_edesc_list_from(areq, next);
++ ahash_request_complete(areq, err);
+ }
+-
+- free_edesc_list_from(areq, edesc);
+-
+- ahash_request_complete(areq, err);
+ }
+
+ /*
+@@ -1940,7 +1970,8 @@ ahash_process_req_prepare(struct ahash_r
+ struct talitos_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
+ struct talitos_edesc *first = NULL, *prev_edesc = NULL, *edesc;
+- size_t desc_max = is_sec1 ? TALITOS1_MAX_DATA_LEN : SIZE_MAX;
++ size_t desc_max = is_sec1 ? TALITOS1_MAX_DATA_LEN :
++ TALITOS2_MAX_DATA_LEN;
+ struct scatterlist tmp[2];
+ size_t to_hash_this_desc;
+ struct scatterlist *src;
--- /dev/null
+From 59b5d899e33701665f18abe6bebf987427876e3e Mon Sep 17 00:00:00 2001
+From: Paul Louvel <paul.louvel@bootlin.com>
+Date: Thu, 7 May 2026 16:41:52 +0200
+Subject: crypto: talitos/hash - prepare SEC1 descriptor chaining, remove additional descriptor
+
+From: Paul Louvel <paul.louvel@bootlin.com>
+
+commit 59b5d899e33701665f18abe6bebf987427876e3e upstream.
+
+Currently, when SEC1 has buffered data (nbuf != 0), the ahash code
+creates an additional descriptor on the fly inside
+common_nonsnoop_hash() to handle the remainder of the data. This
+approach is incompatible with the arbitrary-length descriptor chaining
+that follows.
+
+Remove the "additional descriptor" logic from common_nonsnoop_hash()
+and common_nonsnoop_hash_unmap().
+
+Also remove the nbytes adjustment for SEC1 in ahash_edesc_alloc()
+that subtracted nbuf.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/talitos.c | 101 ++---------------------------------------------
+ 1 file changed, 6 insertions(+), 95 deletions(-)
+
+--- a/drivers/crypto/talitos.c
++++ b/drivers/crypto/talitos.c
+@@ -1788,15 +1788,9 @@ static void common_nonsnoop_hash_unmap(s
+ struct talitos_private *priv = dev_get_drvdata(dev);
+ bool is_sec1 = has_ftr_sec1(priv);
+ struct talitos_desc *desc = &edesc->desc;
+- struct talitos_desc *desc2;
+-
+- if (desc->next_desc)
+- desc2 = &edesc->next_desc->desc;
+
+ unmap_single_talitos_ptr(dev, &desc->ptr[5], DMA_FROM_DEVICE);
+- if (desc->next_desc &&
+- desc->ptr[5].ptr != desc2->ptr[5].ptr)
+- unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE);
++
+ if (req_ctx->last_desc)
+ memcpy(areq->result, req_ctx->hw_context,
+ crypto_ahash_digestsize(tfm));
+@@ -1808,13 +1802,6 @@ static void common_nonsnoop_hash_unmap(s
+ if (from_talitos_ptr_len(&desc->ptr[1], is_sec1))
+ unmap_single_talitos_ptr(dev, &desc->ptr[1],
+ DMA_TO_DEVICE);
+- else if (desc->next_desc)
+- unmap_single_talitos_ptr(dev, &desc2->ptr[1],
+- DMA_TO_DEVICE);
+-
+- if (is_sec1 && req_ctx->nbuf)
+- unmap_single_talitos_ptr(dev, &desc->ptr[3],
+- DMA_TO_DEVICE);
+
+ if (edesc->dma_len)
+ dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
+@@ -1922,9 +1909,6 @@ static int common_nonsnoop_hash(struct t
+ to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen,
+ is_sec1);
+
+- if (is_sec1 && req_ctx->nbuf)
+- length -= req_ctx->nbuf;
+-
+ sg_count = edesc->src_nents ?: 1;
+ if (is_sec1 && sg_count > 1)
+ sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->buf, length);
+@@ -1934,16 +1918,10 @@ static int common_nonsnoop_hash(struct t
+ /*
+ * data in
+ */
+- if (is_sec1 && req_ctx->nbuf) {
+- map_single_talitos_ptr(dev, &desc->ptr[3], req_ctx->nbuf,
+- req_ctx->buf[req_ctx->buf_idx],
+- DMA_TO_DEVICE);
+- } else {
+- sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
+- &desc->ptr[3], sg_count, 0, 0);
+- if (sg_count > 1)
+- sync_needed = true;
+- }
++ sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
++ &desc->ptr[3], sg_count, 0, 0);
++ if (sg_count > 1)
++ sync_needed = true;
+
+ /* fifth DWORD empty */
+
+@@ -1963,49 +1941,6 @@ static int common_nonsnoop_hash(struct t
+ if (is_sec1 && from_talitos_ptr_len(&desc->ptr[3], true) == 0)
+ talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
+
+- if (is_sec1 && req_ctx->nbuf && length) {
+- struct talitos_edesc *edesc2;
+- struct talitos_desc *desc2;
+-
+- edesc2 = kzalloc(sizeof(*edesc2),
+- areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
+- GFP_KERNEL :
+- GFP_ATOMIC);
+- if (!edesc2) {
+- ret = -ENOMEM;
+- goto err;
+- }
+- edesc->next_desc = edesc2;
+-
+- desc2 = &edesc2->desc;
+-
+- desc2->hdr = desc->hdr;
+- desc2->hdr &= ~DESC_HDR_MODE0_MDEU_INIT;
+- desc->hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
+- desc->hdr |= DESC_HDR_MODE0_MDEU_CONT;
+- desc->hdr &= ~DESC_HDR_DONE_NOTIFY;
+-
+- if (desc->ptr[1].ptr)
+- copy_talitos_ptr(&desc2->ptr[1], &desc->ptr[1],
+- is_sec1);
+- else
+- map_single_talitos_ptr_nosync(dev, &desc2->ptr[1],
+- req_ctx->hw_context_size,
+- req_ctx->hw_context,
+- DMA_TO_DEVICE);
+- copy_talitos_ptr(&desc2->ptr[2], &desc->ptr[2], is_sec1);
+- sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
+- &desc2->ptr[3], sg_count, 0, 0);
+- if (sg_count > 1)
+- sync_needed = true;
+- copy_talitos_ptr(&desc2->ptr[5], &desc->ptr[5], is_sec1);
+- if (req_ctx->last_desc)
+- map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
+- req_ctx->hw_context_size,
+- req_ctx->hw_context,
+- DMA_FROM_DEVICE);
+- }
+-
+ if (sync_needed)
+ dma_sync_single_for_device(dev, edesc->dma_link_tbl,
+ edesc->dma_len, DMA_BIDIRECTIONAL);
+@@ -2028,11 +1963,6 @@ static struct talitos_edesc *ahash_edesc
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
+ struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
+- struct talitos_private *priv = dev_get_drvdata(ctx->dev);
+- bool is_sec1 = has_ftr_sec1(priv);
+-
+- if (is_sec1)
+- nbytes -= req_ctx->nbuf;
+
+ return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
+ nbytes, 0, 0, 0, areq->base.flags, false);
+@@ -2051,8 +1981,6 @@ static int ahash_process_req_one(struct
+ unsigned int nsg;
+ int nents;
+ struct device *dev = ctx->dev;
+- struct talitos_private *priv = dev_get_drvdata(dev);
+- bool is_sec1 = has_ftr_sec1(priv);
+ u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx];
+
+ if (!req_ctx->last_desc && (nbytes + req_ctx->nbuf <= blocksize)) {
+@@ -2084,30 +2012,13 @@ static int ahash_process_req_one(struct
+ }
+
+ /* Chain in any previously buffered data */
+- if (!is_sec1 && req_ctx->nbuf) {
++ if (req_ctx->nbuf) {
+ nsg = (req_ctx->nbuf < nbytes_to_hash) ? 2 : 1;
+ sg_init_table(req_ctx->bufsl, nsg);
+ sg_set_buf(req_ctx->bufsl, ctx_buf, req_ctx->nbuf);
+ if (nsg > 1)
+ sg_chain(req_ctx->bufsl, 2, req_ctx->request_sl);
+ req_ctx->psrc = req_ctx->bufsl;
+- } else if (is_sec1 && req_ctx->nbuf && req_ctx->nbuf < blocksize) {
+- int offset;
+-
+- if (nbytes_to_hash > blocksize)
+- offset = blocksize - req_ctx->nbuf;
+- else
+- offset = nbytes_to_hash - req_ctx->nbuf;
+- nents = sg_nents_for_len(req_ctx->request_sl, offset);
+- if (nents < 0) {
+- dev_err(dev, "Invalid number of src SG.\n");
+- return nents;
+- }
+- sg_copy_to_buffer(req_ctx->request_sl, nents,
+- ctx_buf + req_ctx->nbuf, offset);
+- req_ctx->nbuf += offset;
+- req_ctx->psrc = scatterwalk_ffwd(req_ctx->bufsl, req_ctx->request_sl,
+- offset);
+ } else
+ req_ctx->psrc = req_ctx->request_sl;
+
--- /dev/null
+From 907ae6088c82c9abae2d26477fddd60df6ad003b Mon Sep 17 00:00:00 2001
+From: Paul Louvel <paul.louvel@bootlin.com>
+Date: Thu, 7 May 2026 16:41:56 +0200
+Subject: crypto: talitos/hash - remove useless wrapper
+
+From: Paul Louvel <paul.louvel@bootlin.com>
+
+commit 907ae6088c82c9abae2d26477fddd60df6ad003b upstream.
+
+ahash_process_req() was a wrapper used in commit 655ef638a2bc ("crypto:
+talitos - fix SEC1 32k ahash request limitation"). Rename
+ahash_process_req_one() to ahash_process_req() and remove the wrapper.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/talitos.c | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+--- a/drivers/crypto/talitos.c
++++ b/drivers/crypto/talitos.c
+@@ -2003,7 +2003,7 @@ ahash_process_req_prepare(struct ahash_r
+ return first;
+ }
+
+-static int ahash_process_req_one(struct ahash_request *areq, unsigned int nbytes)
++static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
+ {
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
+ struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
+@@ -2084,11 +2084,6 @@ static int ahash_process_req_one(struct
+ return ret;
+ }
+
+-static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
+-{
+- return ahash_process_req_one(areq, nbytes);
+-}
+-
+ static int ahash_init(struct ahash_request *areq)
+ {
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
--- /dev/null
+From 8bcf00671400ac3b3a4cc3011e6c1496dbd880fd Mon Sep 17 00:00:00 2001
+From: Paul Louvel <paul.louvel@bootlin.com>
+Date: Thu, 7 May 2026 16:41:55 +0200
+Subject: crypto: talitos/hash - rename first_desc/last_desc to first_request/last_request
+
+From: Paul Louvel <paul.louvel@bootlin.com>
+
+commit 8bcf00671400ac3b3a4cc3011e6c1496dbd880fd upstream.
+
+In talitos_ahash_req_ctx and talitos_export_state, the fields
+first_desc and last_desc describe request-level (not descriptor-level)
+state. Rename them to first_request and last_request for clarity.
+last_desc is also removed from talitos_ahash_req_ctx as it is no
+longer used.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/talitos.c | 29 +++++++++++++----------------
+ 1 file changed, 13 insertions(+), 16 deletions(-)
+
+--- a/drivers/crypto/talitos.c
++++ b/drivers/crypto/talitos.c
+@@ -944,8 +944,7 @@ struct talitos_ahash_req_ctx {
+ u8 buf[2][HASH_MAX_BLOCK_SIZE];
+ int buf_idx;
+ unsigned int swinit;
+- unsigned int first_desc;
+- unsigned int last_desc;
++ unsigned int first_request;
+ unsigned int last_request;
+ unsigned int to_hash_later;
+ unsigned int nbuf;
+@@ -957,8 +956,8 @@ struct talitos_export_state {
+ u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
+ u8 buf[HASH_MAX_BLOCK_SIZE];
+ unsigned int swinit;
+- unsigned int first_desc;
+- unsigned int last_desc;
++ unsigned int first_request;
++ unsigned int last_request;
+ unsigned int to_hash_later;
+ unsigned int nbuf;
+ };
+@@ -1822,8 +1821,7 @@ static void ahash_done(struct device *de
+ container_of(desc, struct talitos_edesc, desc);
+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
+
+-
+- if (!req_ctx->last_desc && req_ctx->to_hash_later) {
++ if (!req_ctx->last_request && req_ctx->to_hash_later) {
+ /* Position any partial block for next update/final/finup */
+ req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1;
+ req_ctx->nbuf = req_ctx->to_hash_later;
+@@ -1872,7 +1870,7 @@ static void common_nonsnoop_hash(struct
+ /* first DWORD empty */
+
+ /* hash context in */
+- if (!edesc->first || !req_ctx->first_desc || req_ctx->swinit) {
++ if (!edesc->first || !req_ctx->first_request || req_ctx->swinit) {
+ map_single_talitos_ptr_nosync(dev, &desc->ptr[1],
+ req_ctx->hw_context_size,
+ req_ctx->hw_context,
+@@ -1880,7 +1878,7 @@ static void common_nonsnoop_hash(struct
+ req_ctx->swinit = 0;
+ }
+ /* Indicate next op is not the first. */
+- req_ctx->first_desc = 0;
++ req_ctx->first_request = 0;
+
+ /* HMAC key */
+ if (ctx->keylen)
+@@ -1975,14 +1973,14 @@ ahash_process_req_prepare(struct ahash_r
+ edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
+
+ /* request SEC to INIT hash. */
+- if (req_ctx->first_desc && edesc->first && !req_ctx->swinit)
++ if (req_ctx->first_request && edesc->first && !req_ctx->swinit)
+ edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
+
+ /*
+ * When the tfm context has a keylen, it's an HMAC.
+ * A first or last (ie. not middle) descriptor must request HMAC.
+ */
+- if (ctx->keylen && ((req_ctx->first_desc && edesc->first) ||
++ if (ctx->keylen && ((req_ctx->first_request && edesc->first) ||
+ (req_ctx->last_request && edesc->last)))
+ edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
+
+@@ -2103,14 +2101,13 @@ static int ahash_init(struct ahash_reque
+ /* Initialize the context */
+ req_ctx->buf_idx = 0;
+ req_ctx->nbuf = 0;
+- req_ctx->first_desc = 1; /* first_desc indicates h/w must init its context */
++ req_ctx->first_request = 1;
+ req_ctx->swinit = 0; /* assume h/w init of context */
+ size = (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
+ ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
+ : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
+ req_ctx->hw_context_size = size;
+ req_ctx->last_request = 0;
+- req_ctx->last_desc = 0;
+
+ dma = dma_map_single(dev, req_ctx->hw_context, req_ctx->hw_context_size,
+ DMA_TO_DEVICE);
+@@ -2202,8 +2199,8 @@ static int ahash_export(struct ahash_req
+ req_ctx->hw_context_size);
+ memcpy(export->buf, req_ctx->buf[req_ctx->buf_idx], req_ctx->nbuf);
+ export->swinit = req_ctx->swinit;
+- export->first_desc = req_ctx->first_desc;
+- export->last_desc = req_ctx->last_desc;
++ export->first_request = req_ctx->first_request;
++ export->last_request = req_ctx->last_request;
+ export->to_hash_later = req_ctx->to_hash_later;
+ export->nbuf = req_ctx->nbuf;
+
+@@ -2228,8 +2225,8 @@ static int ahash_import(struct ahash_req
+ memcpy(req_ctx->hw_context, export->hw_context, size);
+ memcpy(req_ctx->buf[0], export->buf, export->nbuf);
+ req_ctx->swinit = export->swinit;
+- req_ctx->first_desc = export->first_desc;
+- req_ctx->last_desc = export->last_desc;
++ req_ctx->first_request = export->first_request;
++ req_ctx->last_request = export->last_request;
+ req_ctx->to_hash_later = export->to_hash_later;
+ req_ctx->nbuf = export->nbuf;
+
--- /dev/null
+From f1ede6d95d8ad3b32c6a552d2baab805bd00fc38 Mon Sep 17 00:00:00 2001
+From: Paul Louvel <paul.louvel@bootlin.com>
+Date: Thu, 7 May 2026 16:41:53 +0200
+Subject: crypto: talitos/hash - use descriptor chaining for SEC1 instead of workqueue
+
+From: Paul Louvel <paul.louvel@bootlin.com>
+
+commit f1ede6d95d8ad3b32c6a552d2baab805bd00fc38 upstream.
+
+Rework the SEC1 ahash implementation to build a chain of hardware
+descriptors, replacing the previous approach of submitting one
+descriptor at a time via a workqueue, introduced by commit 655ef638a2bc
+("crypto: talitos - fix SEC1 32k ahash request limitation").
+
+Introduce ahash_process_req_prepare() which iterates over the request
+data, allocating enough descriptors to cover the entire ahash request.
+The new fields (bufsl, src, first, last) are added to talitos_edesc for
+this purpose.
+
+common_nonsnoop_hash() no longer calls talitos_submit(); it only
+maps and sets up the descriptor. Submission is now done by the caller
+after the chain is built.
+
+ahash_free_desc_list_from() takes over calling
+common_nonsnoop_hash_unmap() for each descriptor during cleanup.
+
+Compared to the workqueue based solution, request are slightly faster
+since there is no more scheduling latency induced by the workqueue, and
+only one interrupt is generated by the device at the end of a chain.
+
+Commit 655ef638a2bc ("crypto: talitos - fix SEC1 32k ahash request
+limitation") :
+
+$ /usr/libexec/libkcapi/sha256sum ./test_5M.bin
+013c5609d63c... ./test_5M.bin
+real 0m 0.41s
+user 0m 0.01s
+sys 0m 0.07s
+
+Now :
+
+$ /usr/libexec/libkcapi/sha256sum ./test_5M.bin
+013c5609d63c... ./test_5M.bin
+real 0m 0.33s
+user 0m 0.01s
+sys 0m 0.20s
+
+Tested on a system with an MPC885 SoC featuring the SEC1 Lite.
+
+The increase in sys time is due to the fact that commit 37b5e8897eb5
+("crypto: talitos - chain in buffered data for ahash on SEC1") can no
+longer be applied.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/talitos.c | 168 +++++++++++++++++++++++++++++------------------
+ drivers/crypto/talitos.h | 10 ++
+ 2 files changed, 115 insertions(+), 63 deletions(-)
+
+--- a/drivers/crypto/talitos.c
++++ b/drivers/crypto/talitos.c
+@@ -1791,12 +1791,12 @@ static void common_nonsnoop_hash_unmap(s
+
+ unmap_single_talitos_ptr(dev, &desc->ptr[5], DMA_FROM_DEVICE);
+
+- if (req_ctx->last_desc)
++ if (edesc->last && req_ctx->last_request)
+ memcpy(areq->result, req_ctx->hw_context,
+ crypto_ahash_digestsize(tfm));
+
+- if (req_ctx->psrc)
+- talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0);
++ if (edesc->src)
++ talitos_sg_unmap(dev, edesc, edesc->src, NULL, 0, 0);
+
+ /* When using hashctx-in, must unmap it. */
+ if (from_talitos_ptr_len(&desc->ptr[1], is_sec1))
+@@ -1808,12 +1808,14 @@ static void common_nonsnoop_hash_unmap(s
+ DMA_BIDIRECTIONAL);
+ }
+
+-static void free_edesc_list_from(struct talitos_edesc *edesc)
++static void free_edesc_list_from(struct ahash_request *areq, struct talitos_edesc *edesc)
+ {
++ struct talitos_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
+ struct talitos_edesc *next;
+
+ while (edesc) {
+ next = edesc->next_desc;
++ common_nonsnoop_hash_unmap(ctx->dev, edesc, areq);
+ kfree(edesc);
+ edesc = next;
+ }
+@@ -1828,19 +1830,18 @@ static void ahash_done(struct device *de
+ container_of(desc, struct talitos_edesc, desc);
+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
+
++
+ if (!req_ctx->last_desc && req_ctx->to_hash_later) {
+ /* Position any partial block for next update/final/finup */
+ req_ctx->buf_idx = (req_ctx->buf_idx + 1) & 1;
+ req_ctx->nbuf = req_ctx->to_hash_later;
+ }
+- common_nonsnoop_hash_unmap(dev, edesc, areq);
+
+- free_edesc_list_from(edesc);
++ free_edesc_list_from(areq, edesc);
+
+- if (err) {
+- ahash_request_complete(areq, err);
+- return;
+- }
++ ahash_request_complete(areq, err);
++
++ return;
+
+ req_ctx->remaining_ahash_request_bytes -=
+ req_ctx->current_ahash_request_bytes;
+@@ -1874,18 +1875,15 @@ static void talitos_handle_buggy_hash(st
+ (char *)padded_hash, DMA_TO_DEVICE);
+ }
+
+-static int common_nonsnoop_hash(struct talitos_edesc *edesc,
+- struct ahash_request *areq, unsigned int length,
+- void (*callback) (struct device *dev,
+- struct talitos_desc *desc,
+- void *context, int error))
++static void common_nonsnoop_hash(struct talitos_edesc *edesc,
++ struct ahash_request *areq,
++ unsigned int length)
+ {
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
+ struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
+ struct device *dev = ctx->dev;
+ struct talitos_desc *desc = &edesc->desc;
+- int ret;
+ bool sync_needed = false;
+ struct talitos_private *priv = dev_get_drvdata(dev);
+ bool is_sec1 = has_ftr_sec1(priv);
+@@ -1894,7 +1892,7 @@ static int common_nonsnoop_hash(struct t
+ /* first DWORD empty */
+
+ /* hash context in */
+- if (!req_ctx->first_desc || req_ctx->swinit) {
++ if (!edesc->first || !req_ctx->first_desc || req_ctx->swinit) {
+ map_single_talitos_ptr_nosync(dev, &desc->ptr[1],
+ req_ctx->hw_context_size,
+ req_ctx->hw_context,
+@@ -1911,22 +1909,22 @@ static int common_nonsnoop_hash(struct t
+
+ sg_count = edesc->src_nents ?: 1;
+ if (is_sec1 && sg_count > 1)
+- sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->buf, length);
++ sg_copy_to_buffer(edesc->src, sg_count, edesc->buf, length);
+ else if (length)
+- sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count,
+- DMA_TO_DEVICE);
++ sg_count = dma_map_sg(dev, edesc->src, sg_count, DMA_TO_DEVICE);
++
+ /*
+ * data in
+ */
+- sg_count = talitos_sg_map(dev, req_ctx->psrc, length, edesc,
+- &desc->ptr[3], sg_count, 0, 0);
++ sg_count = talitos_sg_map(dev, edesc->src, length, edesc, &desc->ptr[3],
++ sg_count, 0, 0);
+ if (sg_count > 1)
+ sync_needed = true;
+
+ /* fifth DWORD empty */
+
+ /* hash/HMAC out -or- hash context out */
+- if (req_ctx->last_desc)
++ if (edesc->last && req_ctx->last_request)
+ map_single_talitos_ptr(dev, &desc->ptr[5],
+ crypto_ahash_digestsize(tfm),
+ req_ctx->hw_context, DMA_FROM_DEVICE);
+@@ -1944,30 +1942,89 @@ static int common_nonsnoop_hash(struct t
+ if (sync_needed)
+ dma_sync_single_for_device(dev, edesc->dma_link_tbl,
+ edesc->dma_len, DMA_BIDIRECTIONAL);
+-
+- ret = talitos_submit(dev, ctx->ch, desc, callback,
+- areq);
+- if (ret != -EINPROGRESS)
+- goto err;
+-
+- return -EINPROGRESS;
+-err:
+- common_nonsnoop_hash_unmap(dev, edesc, areq);
+- kfree(edesc);
+- return ret;
+ }
+
+ static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
++ struct scatterlist *src,
+ unsigned int nbytes)
+ {
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
+ struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
+- struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
+
+- return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
++ return talitos_edesc_alloc(ctx->dev, src, NULL, NULL, 0,
+ nbytes, 0, 0, 0, areq->base.flags, false);
+ }
+
++static struct talitos_edesc *
++ahash_process_req_prepare(struct ahash_request *areq, unsigned int nbytes,
++ unsigned int blocksize, bool is_sec1)
++{
++ struct talitos_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
++ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
++ struct talitos_edesc *first = NULL, *prev_edesc = NULL, *edesc;
++ size_t desc_max = is_sec1 ? TALITOS1_MAX_DATA_LEN : SIZE_MAX;
++ struct scatterlist tmp[2];
++ size_t to_hash_this_desc;
++ struct scatterlist *src;
++ size_t offset = 0;
++
++ do {
++ src = scatterwalk_ffwd(tmp, req_ctx->psrc, offset);
++
++ to_hash_this_desc =
++ min(nbytes, ALIGN_DOWN(desc_max, blocksize));
++
++ /* Allocate extended descriptor */
++ edesc = ahash_edesc_alloc(areq, src, to_hash_this_desc);
++ if (IS_ERR(edesc)) {
++ if (first)
++ free_edesc_list_from(areq, first);
++ return edesc;
++ }
++
++ edesc->src =
++ scatterwalk_ffwd(edesc->bufsl, req_ctx->psrc, offset);
++ edesc->desc.hdr = ctx->desc_hdr_template;
++ edesc->first = offset == 0;
++ edesc->last = nbytes - to_hash_this_desc == 0;
++
++ /* On last one, request SEC to pad; otherwise continue */
++ if (req_ctx->last_request && edesc->last)
++ edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
++ else
++ edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
++
++ /* request SEC to INIT hash. */
++ if (req_ctx->first_desc && edesc->first && !req_ctx->swinit)
++ edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
++
++ /*
++ * When the tfm context has a keylen, it's an HMAC.
++ * A first or last (ie. not middle) descriptor must request HMAC.
++ */
++ if (ctx->keylen && ((req_ctx->first_desc && edesc->first) ||
++ (req_ctx->last_request && edesc->last)))
++ edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
++
++ /* clear the DN bit */
++ if (is_sec1 && !edesc->last)
++ edesc->desc.hdr &= ~DESC_HDR_DONE_NOTIFY;
++
++ common_nonsnoop_hash(edesc, areq, to_hash_this_desc);
++
++ offset += to_hash_this_desc;
++ nbytes -= to_hash_this_desc;
++
++ if (!prev_edesc)
++ first = edesc;
++ else
++ prev_edesc->next_desc = edesc;
++ prev_edesc = edesc;
++ } while (nbytes);
++
++ return first;
++}
++
+ static int ahash_process_req_one(struct ahash_request *areq, unsigned int nbytes)
+ {
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
+@@ -1976,14 +2033,16 @@ static int ahash_process_req_one(struct
+ struct talitos_edesc *edesc;
+ unsigned int blocksize =
+ crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
++ bool is_sec1 = has_ftr_sec1(dev_get_drvdata(ctx->dev));
+ unsigned int nbytes_to_hash;
+ unsigned int to_hash_later;
+ unsigned int nsg;
+ int nents;
+ struct device *dev = ctx->dev;
+ u8 *ctx_buf = req_ctx->buf[req_ctx->buf_idx];
++ int ret;
+
+- if (!req_ctx->last_desc && (nbytes + req_ctx->nbuf <= blocksize)) {
++ if (!req_ctx->last_request && (nbytes + req_ctx->nbuf <= blocksize)) {
+ /* Buffer up to one whole block */
+ nents = sg_nents_for_len(req_ctx->request_sl, nbytes);
+ if (nents < 0) {
+@@ -2000,7 +2059,7 @@ static int ahash_process_req_one(struct
+ nbytes_to_hash = nbytes + req_ctx->nbuf;
+ to_hash_later = nbytes_to_hash & (blocksize - 1);
+
+- if (req_ctx->last_desc)
++ if (req_ctx->last_request)
+ to_hash_later = 0;
+ else if (to_hash_later)
+ /* There is a partial block. Hash the full block(s) now */
+@@ -2035,30 +2094,16 @@ static int ahash_process_req_one(struct
+ }
+ req_ctx->to_hash_later = to_hash_later;
+
+- /* Allocate extended descriptor */
+- edesc = ahash_edesc_alloc(req_ctx->areq, nbytes_to_hash);
++ edesc = ahash_process_req_prepare(areq, nbytes_to_hash, blocksize,
++ is_sec1);
+ if (IS_ERR(edesc))
+ return PTR_ERR(edesc);
+
+- edesc->desc.hdr = ctx->desc_hdr_template;
+-
+- /* On last one, request SEC to pad; otherwise continue */
+- if (req_ctx->last_desc)
+- edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_PAD;
+- else
+- edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
+-
+- /* request SEC to INIT hash. */
+- if (req_ctx->first_desc && !req_ctx->swinit)
+- edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
+-
+- /* When the tfm context has a keylen, it's an HMAC.
+- * A first or last (ie. not middle) descriptor must request HMAC.
+- */
+- if (ctx->keylen && (req_ctx->first_desc || req_ctx->last_desc))
+- edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
++ ret = talitos_submit(dev, ctx->ch, &edesc->desc, ahash_done, areq);
++ if (ret != -EINPROGRESS)
++ free_edesc_list_from(areq, edesc);
+
+- return common_nonsnoop_hash(edesc, req_ctx->areq, nbytes_to_hash, ahash_done);
++ return ret;
+ }
+
+ static void sec1_ahash_process_remaining(struct work_struct *work)
+@@ -2102,16 +2147,13 @@ static int ahash_process_req(struct ahas
+ req_ctx->remaining_ahash_request_bytes = nbytes;
+
+ if (is_sec1) {
+- if (nbytes > TALITOS1_MAX_DATA_LEN)
+- nbytes = TALITOS1_MAX_DATA_LEN;
+- else if (req_ctx->last_request)
++ if (req_ctx->last_request)
+ req_ctx->last_desc = 1;
+ }
+
+ req_ctx->current_ahash_request_bytes = nbytes;
+
+- return ahash_process_req_one(req_ctx->areq,
+- req_ctx->current_ahash_request_bytes);
++ return ahash_process_req_one(req_ctx->areq, nbytes);
+ }
+
+ static int ahash_init(struct ahash_request *areq)
+--- a/drivers/crypto/talitos.h
++++ b/drivers/crypto/talitos.h
+@@ -44,6 +44,11 @@ struct talitos_desc {
+
+ /*
+ * talitos_edesc - s/w-extended descriptor
++ * @bufsl: scatterlist buffer
++ * @src: pointer to input scatterlist
++ * @first: first descriptor of a chain
++ * @last: last descriptor of a chain
++ *
+ * @src_nents: number of segments in input scatterlist
+ * @dst_nents: number of segments in output scatterlist
+ * @iv_dma: dma address of iv for checking continuity and link table
+@@ -59,6 +64,11 @@ struct talitos_desc {
+ * of link_tbl data
+ */
+ struct talitos_edesc {
++ struct scatterlist bufsl[2];
++ struct scatterlist *src;
++ int first;
++ int last;
++
+ int src_nents;
+ int dst_nents;
+ dma_addr_t iv_dma;
--- /dev/null
+From f8713d9e6091755dd30f7f1cfa25f8440cddf81b Mon Sep 17 00:00:00 2001
+From: Paul Louvel <paul.louvel@bootlin.com>
+Date: Thu, 7 May 2026 16:41:51 +0200
+Subject: crypto: talitos - move code in current_desc_hdr() into a standalone function
+
+From: Paul Louvel <paul.louvel@bootlin.com>
+
+commit f8713d9e6091755dd30f7f1cfa25f8440cddf81b upstream.
+
+Previously added code in current_desc_hdr() in order to add support for
+searching an offending descriptor inside a descriptor chain.
+
+Move that code into a standalone function to improve readability.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/talitos.c | 35 +++++++++++++++++++----------------
+ 1 file changed, 19 insertions(+), 16 deletions(-)
+
+--- a/drivers/crypto/talitos.c
++++ b/drivers/crypto/talitos.c
+@@ -520,6 +520,24 @@ DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0
+ DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
+ DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
+
++static __be32 search_desc_hdr_in_request(struct talitos_request *request,
++ dma_addr_t cur_desc, bool is_sec1)
++{
++ struct talitos_edesc *edesc;
++
++ if (request->dma_desc == cur_desc) {
++ return request->desc->hdr;
++ } else if (is_sec1) {
++ edesc = container_of(request->desc, struct talitos_edesc, desc);
++ while (edesc->next_desc) {
++ if (edesc->desc.next_desc == cpu_to_be32(cur_desc))
++ return edesc->next_desc->desc.hdr1;
++ edesc = edesc->next_desc;
++ }
++ }
++ return 0;
++}
++
+ /*
+ * locate current (offending) descriptor
+ */
+@@ -528,7 +546,6 @@ static __be32 current_desc_hdr(struct de
+ struct talitos_private *priv = dev_get_drvdata(dev);
+ bool is_sec1 = has_ftr_sec1(priv);
+ struct talitos_request *request;
+- struct talitos_edesc *edesc;
+ int tail, iter;
+ dma_addr_t cur_desc;
+ __be32 hdr = 0;
+@@ -546,21 +563,7 @@ static __be32 current_desc_hdr(struct de
+ do {
+ request = &priv->chan[ch].fifo[iter];
+
+- if (request->dma_desc == cur_desc) {
+- hdr = request->desc->hdr;
+- } else if (is_sec1) {
+- edesc = container_of(request->desc,
+- struct talitos_edesc, desc);
+- while (edesc->next_desc) {
+- if (edesc->desc.next_desc ==
+- cpu_to_be32(cur_desc)) {
+- hdr = edesc->next_desc->desc.hdr1;
+- break;
+- }
+- edesc = edesc->next_desc;
+- }
+- }
+-
++ hdr = search_desc_hdr_in_request(request, cur_desc, is_sec1);
+ if (hdr)
+ break;
+
--- /dev/null
+From 5c0aa8cad7745505297103f05dda3fa06e8ac670 Mon Sep 17 00:00:00 2001
+From: Paul Louvel <paul.louvel@bootlin.com>
+Date: Thu, 7 May 2026 16:41:50 +0200
+Subject: crypto: talitos - move dma mapping code in talitos_submit() into a standalone dma_map_request() function
+
+From: Paul Louvel <paul.louvel@bootlin.com>
+
+commit 5c0aa8cad7745505297103f05dda3fa06e8ac670 upstream.
+
+Previously added code to talitos_submit() in order to map an entire
+descriptor chain.
+
+Move that code into a standalone function to improve readability.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/talitos.c | 75 +++++++++++++++++++++++++----------------------
+ 1 file changed, 41 insertions(+), 34 deletions(-)
+
+--- a/drivers/crypto/talitos.c
++++ b/drivers/crypto/talitos.c
+@@ -255,6 +255,46 @@ static int init_device(struct device *de
+ return 0;
+ }
+
++static void dma_map_request(struct device *dev, struct talitos_request *request,
++ struct talitos_desc *desc, bool is_sec1)
++{
++ struct talitos_edesc *edesc =
++ container_of(desc, struct talitos_edesc, desc);
++ dma_addr_t dma_desc, prev_dma_desc;
++ struct talitos_edesc *prev_edesc = NULL;
++
++ if (is_sec1) {
++ while (edesc) {
++ edesc->desc.hdr1 = edesc->desc.hdr;
++
++ dma_desc = dma_map_single(dev, &edesc->desc.hdr1,
++ TALITOS_DESC_SIZE,
++ DMA_BIDIRECTIONAL);
++
++ if (!prev_edesc) {
++ request->dma_desc = dma_desc;
++ goto next;
++ }
++
++ /* Chain in any previous descriptors. */
++
++ prev_edesc->desc.next_desc = cpu_to_be32(dma_desc);
++
++ dma_sync_single_for_device(dev, prev_dma_desc,
++ TALITOS_DESC_SIZE,
++ DMA_TO_DEVICE);
++
++next:
++ prev_edesc = edesc;
++ prev_dma_desc = dma_desc;
++ edesc = edesc->next_desc;
++ }
++ } else {
++ request->dma_desc = dma_map_single(dev, desc, TALITOS_DESC_SIZE,
++ DMA_BIDIRECTIONAL);
++ }
++}
++
+ /**
+ * talitos_submit - submits a descriptor to the device for processing
+ * @dev: the SEC device to be used
+@@ -273,10 +313,7 @@ static int talitos_submit(struct device
+ void *context, int error),
+ void *context)
+ {
+- struct talitos_edesc *edesc = container_of(desc, struct talitos_edesc, desc);
+ struct talitos_private *priv = dev_get_drvdata(dev);
+- dma_addr_t dma_desc, prev_dma_desc;
+- struct talitos_edesc *prev_edesc = NULL;
+ struct talitos_request *request;
+ unsigned long flags;
+ int head;
+@@ -294,37 +331,7 @@ static int talitos_submit(struct device
+ request = &priv->chan[ch].fifo[head];
+
+ /* map descriptor and save caller data */
+- if (is_sec1) {
+- while (edesc) {
+- edesc->desc.hdr1 = edesc->desc.hdr;
+-
+- dma_desc = dma_map_single(dev, &edesc->desc.hdr1,
+- TALITOS_DESC_SIZE,
+- DMA_BIDIRECTIONAL);
+-
+- if (!prev_edesc) {
+- request->dma_desc = dma_desc;
+- goto next;
+- }
+-
+- /* Chain in any previous descriptors. */
+-
+- prev_edesc->desc.next_desc = cpu_to_be32(dma_desc);
+-
+- dma_sync_single_for_device(dev, prev_dma_desc,
+- TALITOS_DESC_SIZE,
+- DMA_TO_DEVICE);
+-
+-next:
+- prev_edesc = edesc;
+- prev_dma_desc = dma_desc;
+- edesc = edesc->next_desc;
+- }
+- } else {
+- request->dma_desc = dma_map_single(dev, desc,
+- TALITOS_DESC_SIZE,
+- DMA_BIDIRECTIONAL);
+- }
++ dma_map_request(dev, request, desc, is_sec1);
+ request->callback = callback;
+ request->context = context;
+
--- /dev/null
+From 4d9b0b7415b9e79a3d54d18b5ff230974ea78740 Mon Sep 17 00:00:00 2001
+From: Paul Louvel <paul.louvel@bootlin.com>
+Date: Thu, 7 May 2026 16:41:49 +0200
+Subject: crypto: talitos - move dma unmapping code in flush_channel() into a standalone dma_unmap_request() function
+
+From: Paul Louvel <paul.louvel@bootlin.com>
+
+commit 4d9b0b7415b9e79a3d54d18b5ff230974ea78740 upstream.
+
+Previously added code to flush_channel() in order to unmap an entire
+descriptor.
+
+Move that code into a standalone function to improve readability.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/talitos.c | 39 ++++++++++++++++++++++-----------------
+ 1 file changed, 22 insertions(+), 17 deletions(-)
+
+--- a/drivers/crypto/talitos.c
++++ b/drivers/crypto/talitos.c
+@@ -372,6 +372,27 @@ static __be32 get_request_hdr(struct dev
+ return edesc->desc.hdr1;
+ }
+
++static void dma_unmap_request(struct device *dev,
++ struct talitos_request *request, bool is_sec1)
++{
++ struct talitos_edesc *edesc;
++
++ if (is_sec1) {
++ dma_unmap_single(dev, request->dma_desc, TALITOS_DESC_SIZE,
++ DMA_BIDIRECTIONAL);
++ edesc = container_of(request->desc, struct talitos_edesc, desc);
++ while (edesc->next_desc) {
++ dma_unmap_single(dev,
++ be32_to_cpu(edesc->desc.next_desc),
++ TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
++ edesc = edesc->next_desc;
++ }
++ } else {
++ dma_unmap_single(dev, request->dma_desc, TALITOS_DESC_SIZE,
++ DMA_BIDIRECTIONAL);
++ }
++}
++
+ /*
+ * process what was done, notify callback of error if not
+ */
+@@ -379,7 +400,6 @@ static void flush_channel(struct device
+ {
+ struct talitos_private *priv = dev_get_drvdata(dev);
+ struct talitos_request *request, saved_req;
+- struct talitos_edesc *edesc;
+ unsigned long flags;
+ int tail, status;
+ bool is_sec1 = has_ftr_sec1(priv);
+@@ -404,22 +424,7 @@ static void flush_channel(struct device
+ else
+ status = error;
+
+- if (is_sec1) {
+- dma_unmap_single(dev, request->dma_desc,
+- TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
+- edesc = container_of(request->desc,
+- struct talitos_edesc, desc);
+- while (edesc->next_desc) {
+- dma_unmap_single(
+- dev, be32_to_cpu(edesc->desc.next_desc),
+- TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
+- edesc = edesc->next_desc;
+- }
+- } else {
+- dma_unmap_single(dev, request->dma_desc,
+- TALITOS_DESC_SIZE,
+- DMA_BIDIRECTIONAL);
+- }
++ dma_unmap_request(dev, request, is_sec1);
+
+ /* copy entries so we can call callback outside lock */
+ saved_req.desc = request->desc;
--- /dev/null
+From e17ff3d6ff907dc8406261e8fd3e1fc8a908f0f6 Mon Sep 17 00:00:00 2001
+From: Paul Louvel <paul.louvel@bootlin.com>
+Date: Thu, 7 May 2026 16:41:47 +0200
+Subject: crypto: talitos - use dma_sync_single_for_cpu() before reading descriptor header
+
+From: Paul Louvel <paul.louvel@bootlin.com>
+
+commit e17ff3d6ff907dc8406261e8fd3e1fc8a908f0f6 upstream.
+
+In order to know if a descriptor has been processed by the device,
+the driver polls the FIFO to see if DESC_HDR_DONE is set on a descriptor
+header to confirm completion.
+The current code does not make sure that the CPU gets up to date data
+before reading the descriptor.
+
+Fix this by calling dma_sync_single_for_cpu() before reading memory
+written by the device.
+
+Cc: stable@vger.kernel.org
+Fixes: 58cdbc6d2263 ("crypto: talitos - fix hash on SEC1.")
+Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/talitos.c | 28 ++++++++++++++++++++--------
+ 1 file changed, 20 insertions(+), 8 deletions(-)
+
+--- a/drivers/crypto/talitos.c
++++ b/drivers/crypto/talitos.c
+@@ -322,19 +322,31 @@ static int talitos_submit(struct device
+ return -EINPROGRESS;
+ }
+
+-static __be32 get_request_hdr(struct talitos_request *request, bool is_sec1)
++static __be32 get_request_hdr(struct device *dev,
++ struct talitos_request *request, bool is_sec1)
+ {
+ struct talitos_edesc *edesc;
+
+- if (!is_sec1)
++ if (!is_sec1) {
++ dma_sync_single_for_cpu(dev, request->dma_desc,
++ TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
++
+ return request->desc->hdr;
++ }
+
+- if (!request->desc->next_desc)
++ if (!request->desc->next_desc) {
++ dma_sync_single_for_cpu(dev, request->dma_desc,
++ TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
+ return request->desc->hdr1;
+-
+- edesc = container_of(request->desc, struct talitos_edesc, desc);
+-
+- return ((struct talitos_desc *)(edesc->buf + edesc->dma_len))->hdr1;
++ } else {
++ dma_sync_single_for_cpu(dev,
++ be32_to_cpu(request->desc->next_desc),
++ TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
++ edesc = container_of(request->desc, struct talitos_edesc, desc);
++
++ return ((struct talitos_desc *)(edesc->buf + edesc->dma_len))
++ ->hdr1;
++ }
+ }
+
+ /*
+@@ -358,7 +370,7 @@ static void flush_channel(struct device
+
+ /* descriptors with their done bits set don't get the error */
+ rmb();
+- hdr = get_request_hdr(request, is_sec1);
++ hdr = get_request_hdr(dev, request, is_sec1);
+
+ if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
+ status = 0;
--- /dev/null
+From e360a6d65bb46c527a5909430a31d640cdd5036e Mon Sep 17 00:00:00 2001
+From: Vasily Khoruzhick <vasilykh@arista.com>
+Date: Tue, 14 Apr 2026 11:17:16 -0700
+Subject: EDAC/i10nm: Don't fail probing if ADXL is missing
+
+From: Vasily Khoruzhick <vasilykh@arista.com>
+
+commit e360a6d65bb46c527a5909430a31d640cdd5036e upstream.
+
+ADXL is not present in Coreboot- or Slimbootloader-based BIOSes and as
+result, the driver fails to probe there.
+
+Since commit 2738c69a8813 ("EDAC/i10nm: Add driver decoder for Ice Lake
+and Tremont CPUs"), i10nm_edac supports driver decoder. Switch to driver
+decoding when ADXL is not present.
+
+Signed-off-by: Vasily Khoruzhick <vasilykh@arista.com>
+Signed-off-by: Tony Luck <tony.luck@intel.com>
+Reviewed-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
+Cc: stable@vger.kernel.org # v6.1+
+Link: https://patch.msgid.link/20260414181735.87023-1-anarsoul@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/edac/i10nm_base.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+--- a/drivers/edac/i10nm_base.c
++++ b/drivers/edac/i10nm_base.c
+@@ -84,6 +84,7 @@ static struct res_config *res_cfg;
+ static int retry_rd_err_log;
+ static int decoding_via_mca;
+ static bool mem_cfg_2lm;
++static bool no_adxl;
+
+ static u32 offsets_scrub_icx[] = {0x22c60, 0x22c54, 0x22c5c, 0x22c58, 0x22c28, 0x20ed8};
+ static u32 offsets_scrub_spr[] = {0x22c60, 0x22c54, 0x22f08, 0x22c58, 0x22c28, 0x20ed8};
+@@ -1121,8 +1122,14 @@ static int __init i10nm_init(void)
+ }
+
+ rc = skx_adxl_get();
+- if (rc)
+- goto fail;
++ if (rc) {
++ /* Decoding errors via MCA banks for 2LM isn't supported yet */
++ if (rc != -ENODEV || mem_cfg_2lm)
++ goto fail;
++ i10nm_printk(KERN_INFO, "ADXL not found, falling back to MCA-based decoding.\n");
++ no_adxl = true;
++ decoding_via_mca = true;
++ }
+
+ opstate_init();
+ mce_register_decode_chain(&i10nm_mce_dec);
+@@ -1156,7 +1163,8 @@ static void __exit i10nm_exit(void)
+
+ skx_teardown_debug();
+ mce_unregister_decode_chain(&i10nm_mce_dec);
+- skx_adxl_put();
++ if (!no_adxl)
++ skx_adxl_put();
+ skx_remove();
+ }
+
--- /dev/null
+From 3c7e164344e5bcf6f274bbf59a3274f5caad9bc1 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 11 May 2026 16:37:07 +0200
+Subject: i2c: core: fix hang on adapter registration failure
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 3c7e164344e5bcf6f274bbf59a3274f5caad9bc1 upstream.
+
+Clients may be registered from bus notifier callbacks when the adapter
+is registered. On a subsequent error during registration, the adapter
+references taken by such clients prevent the wait for the references to
+be released from ever completing.
+
+Fix this by refactoring client deregistration and deregistering also on
+late adapter registration failures.
+
+Fixes: f8756c67b3de ("i2c: core: call of_i2c_setup_smbus_alert in i2c_register_adapter")
+Cc: stable@vger.kernel.org # 4.15
+Cc: Phil Reid <preid@electromag.com.au>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/i2c-core-base.c | 49 ++++++++++++++++++++++++++------------------
+ 1 file changed, 29 insertions(+), 20 deletions(-)
+
+--- a/drivers/i2c/i2c-core-base.c
++++ b/drivers/i2c/i2c-core-base.c
+@@ -63,6 +63,7 @@
+ static DEFINE_MUTEX(core_lock);
+ static DEFINE_IDR(i2c_adapter_idr);
+
++static void i2c_deregister_clients(struct i2c_adapter *adap);
+ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
+
+ static DEFINE_STATIC_KEY_FALSE(i2c_trace_msg_key);
+@@ -1598,6 +1599,7 @@ static int i2c_register_adapter(struct i
+ return 0;
+
+ out_reg:
++ i2c_deregister_clients(adap);
+ debugfs_remove_recursive(adap->debugfs);
+ init_completion(&adap->dev_released);
+ device_unregister(&adap->dev);
+@@ -1739,29 +1741,10 @@ static int __process_removed_adapter(str
+ return 0;
+ }
+
+-/**
+- * i2c_del_adapter - unregister I2C adapter
+- * @adap: the adapter being unregistered
+- * Context: can sleep
+- *
+- * This unregisters an I2C adapter which was previously registered
+- * by @i2c_add_adapter or @i2c_add_numbered_adapter.
+- */
+-void i2c_del_adapter(struct i2c_adapter *adap)
++static void i2c_deregister_clients(struct i2c_adapter *adap)
+ {
+- struct i2c_adapter *found;
+ struct i2c_client *client, *next;
+
+- /* First make sure that this adapter was ever added */
+- mutex_lock(&core_lock);
+- found = idr_find(&i2c_adapter_idr, adap->nr);
+- mutex_unlock(&core_lock);
+- if (found != adap) {
+- pr_debug("attempting to delete unregistered adapter [%s]\n", adap->name);
+- return;
+- }
+-
+- i2c_acpi_remove_space_handler(adap);
+ /* Tell drivers about this removal */
+ mutex_lock(&core_lock);
+ bus_for_each_drv(&i2c_bus_type, NULL, adap,
+@@ -1787,6 +1770,32 @@ void i2c_del_adapter(struct i2c_adapter
+ * them up properly, so we give them a chance to do that first. */
+ device_for_each_child(&adap->dev, NULL, __unregister_client);
+ device_for_each_child(&adap->dev, NULL, __unregister_dummy);
++}
++
++/**
++ * i2c_del_adapter - unregister I2C adapter
++ * @adap: the adapter being unregistered
++ * Context: can sleep
++ *
++ * This unregisters an I2C adapter which was previously registered
++ * by @i2c_add_adapter or @i2c_add_numbered_adapter.
++ */
++void i2c_del_adapter(struct i2c_adapter *adap)
++{
++ struct i2c_adapter *found;
++
++ /* First make sure that this adapter was ever added */
++ mutex_lock(&core_lock);
++ found = idr_find(&i2c_adapter_idr, adap->nr);
++ mutex_unlock(&core_lock);
++ if (found != adap) {
++ pr_debug("attempting to delete unregistered adapter [%s]\n", adap->name);
++ return;
++ }
++
++ i2c_acpi_remove_space_handler(adap);
++
++ i2c_deregister_clients(adap);
+
+ /* device name is gone after device_unregister */
+ dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
--- /dev/null
+From fa11039d6cdff84584a3ef8cc1f5e1b56e045da2 Mon Sep 17 00:00:00 2001
+From: Wentao Liang <vulab@iscas.ac.cn>
+Date: Wed, 27 May 2026 10:48:50 +0000
+Subject: regulator: scmi: fix of_node refcount leak in scmi_regulator_probe()
+
+From: Wentao Liang <vulab@iscas.ac.cn>
+
+commit fa11039d6cdff84584a3ef8cc1f5e1b56e045da2 upstream.
+
+scmi_regulator_probe() calls of_find_node_by_name() which takes a
+reference on the returned device node. On the error path where
+process_scmi_regulator_of_node() fails, the function returns without
+calling of_node_put() on the child node, leaking the reference.
+
+Add of_node_put(np) on the error path to properly release the
+reference.
+
+Cc: stable@vger.kernel.org
+Fixes: 0fbeae70ee7c ("regulator: add SCMI driver")
+Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
+Link: https://patch.msgid.link/20260527104850.872415-1-vulab@iscas.ac.cn
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/regulator/scmi-regulator.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/regulator/scmi-regulator.c
++++ b/drivers/regulator/scmi-regulator.c
+@@ -345,8 +345,10 @@ static int scmi_regulator_probe(struct s
+ for_each_child_of_node_scoped(np, child) {
+ ret = process_scmi_regulator_of_node(sdev, ph, child, rinfo);
+ /* abort on any mem issue */
+- if (ret == -ENOMEM)
++ if (ret == -ENOMEM) {
++ of_node_put(np);
+ return ret;
++ }
+ }
+ of_node_put(np);
+ /*
crypto-qat-notify-fatal-error-before-aer-reset-preparation.patch
crypto-qat-protect-service-table-iterations-with-service_lock.patch
crypto-qat-validate-rsa-crt-component-lengths.patch
+crypto-talitos-use-dma_sync_single_for_cpu-before-reading-descriptor-header.patch
+crypto-talitos-add-chaining-of-arbitrary-number-of-descriptor-for-the-sec1.patch
+crypto-talitos-move-dma-unmapping-code-in-flush_channel-into-a-standalone-dma_unmap_request-function.patch
+crypto-talitos-move-dma-mapping-code-in-talitos_submit-into-a-standalone-dma_map_request-function.patch
+crypto-talitos-move-code-in-current_desc_hdr-into-a-standalone-function.patch
+crypto-talitos-hash-prepare-sec1-descriptor-chaining-remove-additional-descriptor.patch
+crypto-talitos-hash-use-descriptor-chaining-for-sec1-instead-of-workqueue.patch
+crypto-talitos-hash-drop-workqueue-mechanism-for-sec1.patch
+crypto-talitos-hash-rename-first_desc-last_desc-to-first_request-last_request.patch
+crypto-talitos-hash-remove-useless-wrapper.patch
+crypto-talitos-hash-fix-sec2-64k-1-ahash-request-limitation.patch
+arm64-fpsimd-fix-type-mismatch-in-sme_-save-load-_state.patch
+spi-fsl-lpspi-replace-dmaengine_terminate_all-with-dmaengine_terminate_sync.patch
+spi-fsl-lpspi-terminate-the-rx-channel-on-tx-prepare-failure-path.patch
+edac-i10nm-don-t-fail-probing-if-adxl-is-missing.patch
+watchdog-apple-add-apple-t8103-wdt-compatible.patch
+regulator-scmi-fix-of_node-refcount-leak-in-scmi_regulator_probe.patch
+i2c-core-fix-hang-on-adapter-registration-failure.patch
--- /dev/null
+From e703ce47691b967fe9b4057fb1d062273211afa9 Mon Sep 17 00:00:00 2001
+From: Carlos Song <carlos.song@nxp.com>
+Date: Mon, 25 May 2026 14:23:56 +0800
+Subject: spi: fsl-lpspi: replace dmaengine_terminate_all() with dmaengine_terminate_sync()
+
+From: Carlos Song <carlos.song@nxp.com>
+
+commit e703ce47691b967fe9b4057fb1d062273211afa9 upstream.
+
+dmaengine_terminate_all() has been deprecated, so replace it with
+dmaengine_terminate_sync().
+
+Fixes: 09c04466ce7e ("spi: lpspi: add dma mode support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Carlos Song <carlos.song@nxp.com>
+Link: https://patch.msgid.link/20260525062357.3191349-2-carlos.song@oss.nxp.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-fsl-lpspi.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/drivers/spi/spi-fsl-lpspi.c
++++ b/drivers/spi/spi-fsl-lpspi.c
+@@ -603,7 +603,7 @@ static int fsl_lpspi_dma_transfer(struct
+ tx->sgl, tx->nents, DMA_MEM_TO_DEV,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc_tx) {
+- dmaengine_terminate_all(controller->dma_tx);
++ dmaengine_terminate_sync(controller->dma_tx);
+ return -EINVAL;
+ }
+
+@@ -624,8 +624,8 @@ static int fsl_lpspi_dma_transfer(struct
+ transfer_timeout);
+ if (!time_left) {
+ dev_err(fsl_lpspi->dev, "I/O Error in DMA TX\n");
+- dmaengine_terminate_all(controller->dma_tx);
+- dmaengine_terminate_all(controller->dma_rx);
++ dmaengine_terminate_sync(controller->dma_tx);
++ dmaengine_terminate_sync(controller->dma_rx);
+ fsl_lpspi_reset(fsl_lpspi);
+ return -ETIMEDOUT;
+ }
+@@ -634,8 +634,8 @@ static int fsl_lpspi_dma_transfer(struct
+ transfer_timeout);
+ if (!time_left) {
+ dev_err(fsl_lpspi->dev, "I/O Error in DMA RX\n");
+- dmaengine_terminate_all(controller->dma_tx);
+- dmaengine_terminate_all(controller->dma_rx);
++ dmaengine_terminate_sync(controller->dma_tx);
++ dmaengine_terminate_sync(controller->dma_rx);
+ fsl_lpspi_reset(fsl_lpspi);
+ return -ETIMEDOUT;
+ }
+@@ -644,8 +644,8 @@ static int fsl_lpspi_dma_transfer(struct
+ fsl_lpspi->target_aborted) {
+ dev_dbg(fsl_lpspi->dev,
+ "I/O Error in DMA TX interrupted\n");
+- dmaengine_terminate_all(controller->dma_tx);
+- dmaengine_terminate_all(controller->dma_rx);
++ dmaengine_terminate_sync(controller->dma_tx);
++ dmaengine_terminate_sync(controller->dma_rx);
+ fsl_lpspi_reset(fsl_lpspi);
+ return -EINTR;
+ }
+@@ -654,8 +654,8 @@ static int fsl_lpspi_dma_transfer(struct
+ fsl_lpspi->target_aborted) {
+ dev_dbg(fsl_lpspi->dev,
+ "I/O Error in DMA RX interrupted\n");
+- dmaengine_terminate_all(controller->dma_tx);
+- dmaengine_terminate_all(controller->dma_rx);
++ dmaengine_terminate_sync(controller->dma_tx);
++ dmaengine_terminate_sync(controller->dma_rx);
+ fsl_lpspi_reset(fsl_lpspi);
+ return -EINTR;
+ }
--- /dev/null
+From 01980b5da56e573d62798d0ff6c86bcaa2b22cbe Mon Sep 17 00:00:00 2001
+From: Carlos Song <carlos.song@nxp.com>
+Date: Mon, 25 May 2026 14:23:57 +0800
+Subject: spi: fsl-lpspi: terminate the RX channel on TX prepare failure path
+
+From: Carlos Song <carlos.song@nxp.com>
+
+commit 01980b5da56e573d62798d0ff6c86bcaa2b22cbe upstream.
+
+When dmaengine_prep_slave_sg() fails for the TX channel, the error path
+terminates the TX DMA channel but leaves the RX channel running. Since
+the RX channel was already submitted and issued prior to preparing
+the TX descriptor, returning -EINVAL causes the SPI core to unmap the
+DMA buffers while the RX DMA engine continues writing to them, leading
+to potential memory corruption or use-after-free.
+
+Terminate the RX channel before returning on the TX prepare failure path.
+
+Fixes: 09c04466ce7e ("spi: lpspi: add dma mode support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Carlos Song <carlos.song@nxp.com>
+Link: https://patch.msgid.link/20260525062357.3191349-3-carlos.song@oss.nxp.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-fsl-lpspi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/spi/spi-fsl-lpspi.c
++++ b/drivers/spi/spi-fsl-lpspi.c
+@@ -603,7 +603,7 @@ static int fsl_lpspi_dma_transfer(struct
+ tx->sgl, tx->nents, DMA_MEM_TO_DEV,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc_tx) {
+- dmaengine_terminate_sync(controller->dma_tx);
++ dmaengine_terminate_sync(controller->dma_rx);
+ return -EINVAL;
+ }
+
--- /dev/null
+From 14ca4868886f2188401fe06cd7bf01a330b3fb99 Mon Sep 17 00:00:00 2001
+From: Janne Grunau <j@jannau.net>
+Date: Wed, 31 Dec 2025 13:07:21 +0100
+Subject: watchdog: apple: Add "apple,t8103-wdt" compatible
+
+From: Janne Grunau <j@jannau.net>
+
+commit 14ca4868886f2188401fe06cd7bf01a330b3fb99 upstream.
+
+After discussion with the devicetree maintainers we agreed to not extend
+lists with the generic compatible "apple,wdt" anymore [1]. Use
+"apple,t8103-wdt" as base compatible as it is the SoC the driver and
+bindings were written for.
+
+[1]: https://lore.kernel.org/asahi/12ab93b7-1fc2-4ce0-926e-c8141cfe81bf@kernel.org/
+
+Fixes: 4ed224aeaf66 ("watchdog: Add Apple SoC watchdog driver")
+Cc: stable@vger.kernel.org
+Reviewed-by: Neal Gompa <neal@gompa.dev>
+Signed-off-by: Janne Grunau <j@jannau.net>
+Link: https://lore.kernel.org/r/20251231-watchdog-apple-t8103-base-compat-v1-1-1702a02e0c45@jannau.net
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/watchdog/apple_wdt.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/watchdog/apple_wdt.c
++++ b/drivers/watchdog/apple_wdt.c
+@@ -215,6 +215,7 @@ static int apple_wdt_suspend(struct devi
+ static DEFINE_SIMPLE_DEV_PM_OPS(apple_wdt_pm_ops, apple_wdt_suspend, apple_wdt_resume);
+
+ static const struct of_device_id apple_wdt_of_match[] = {
++ { .compatible = "apple,t8103-wdt" },
+ { .compatible = "apple,wdt" },
+ {},
+ };