From: Greg Kroah-Hartman Date: Wed, 15 Jul 2026 10:35:22 +0000 (+0200) Subject: 6.18-stable patches X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e72f09c402c866ce4540196ea5f9d5b4d87a5da7;p=thirdparty%2Fkernel%2Fstable-queue.git 6.18-stable patches added patches: arm64-fpsimd-fix-type-mismatch-in-sme_-save-load-_state.patch crypto-talitos-add-chaining-of-arbitrary-number-of-descriptor-for-the-sec1.patch crypto-talitos-hash-drop-workqueue-mechanism-for-sec1.patch crypto-talitos-hash-fix-sec2-64k-1-ahash-request-limitation.patch crypto-talitos-hash-prepare-sec1-descriptor-chaining-remove-additional-descriptor.patch crypto-talitos-hash-remove-useless-wrapper.patch crypto-talitos-hash-rename-first_desc-last_desc-to-first_request-last_request.patch crypto-talitos-hash-use-descriptor-chaining-for-sec1-instead-of-workqueue.patch crypto-talitos-move-code-in-current_desc_hdr-into-a-standalone-function.patch crypto-talitos-move-dma-mapping-code-in-talitos_submit-into-a-standalone-dma_map_request-function.patch crypto-talitos-move-dma-unmapping-code-in-flush_channel-into-a-standalone-dma_unmap_request-function.patch crypto-talitos-use-dma_sync_single_for_cpu-before-reading-descriptor-header.patch edac-i10nm-don-t-fail-probing-if-adxl-is-missing.patch i2c-core-fix-hang-on-adapter-registration-failure.patch regulator-scmi-fix-of_node-refcount-leak-in-scmi_regulator_probe.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 watchdog-apple-add-apple-t8103-wdt-compatible.patch x86-mm-fix-freeing-of-pmd-sized-vmemmap-pages.patch --- diff --git a/queue-6.18/arm64-fpsimd-fix-type-mismatch-in-sme_-save-load-_state.patch b/queue-6.18/arm64-fpsimd-fix-type-mismatch-in-sme_-save-load-_state.patch new file mode 100644 index 0000000000..5fbc2565ee --- /dev/null +++ b/queue-6.18/arm64-fpsimd-fix-type-mismatch-in-sme_-save-load-_state.patch @@ -0,0 +1,78 @@ +From 247bd153905085c18ff9006cca1ccb96dfd18e7f Mon Sep 17 00:00:00 2001 +From: Mark Rutland +Date: Wed, 3 Jun 2026 12:06:12 +0100 +Subject: arm64: fpsimd: Fix type mismatch in sme_{save,load}_state() + +From: Mark Rutland + +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 +Cc: Catalin Marinas +Cc: Fuad Tabba +Cc: James Morse +Cc: Marc Zyngier +Cc: Mark Brown +Cc: Oliver Upton +Cc: Vladimir Murzin +Cc: Will Deacon +Cc: stable@vger.kernel.org +Signed-off-by: Will Deacon +Signed-off-by: Greg Kroah-Hartman +--- + 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 diff --git a/queue-6.18/crypto-talitos-add-chaining-of-arbitrary-number-of-descriptor-for-the-sec1.patch b/queue-6.18/crypto-talitos-add-chaining-of-arbitrary-number-of-descriptor-for-the-sec1.patch new file mode 100644 index 0000000000..98c3fc224e --- /dev/null +++ b/queue-6.18/crypto-talitos-add-chaining-of-arbitrary-number-of-descriptor-for-the-sec1.patch @@ -0,0 +1,352 @@ +From f126384ed55279c3b676f89d5ab547b8de8df782 Mon Sep 17 00:00:00 2001 +From: Paul Louvel +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 + +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 +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-6.18/crypto-talitos-hash-drop-workqueue-mechanism-for-sec1.patch b/queue-6.18/crypto-talitos-hash-drop-workqueue-mechanism-for-sec1.patch new file mode 100644 index 0000000000..00bcf066b0 --- /dev/null +++ b/queue-6.18/crypto-talitos-hash-drop-workqueue-mechanism-for-sec1.patch @@ -0,0 +1,173 @@ +From be4802afb1700534e48cb776d0d1e772c27de130 Mon Sep 17 00:00:00 2001 +From: Paul Louvel +Date: Thu, 7 May 2026 16:41:54 +0200 +Subject: crypto: talitos/hash - drop workqueue mechanism for SEC1 + +From: Paul Louvel + +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 +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include + #include +@@ -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); diff --git a/queue-6.18/crypto-talitos-hash-fix-sec2-64k-1-ahash-request-limitation.patch b/queue-6.18/crypto-talitos-hash-fix-sec2-64k-1-ahash-request-limitation.patch new file mode 100644 index 0000000000..3d95ebd873 --- /dev/null +++ b/queue-6.18/crypto-talitos-hash-fix-sec2-64k-1-ahash-request-limitation.patch @@ -0,0 +1,95 @@ +From 6e12daff6ec125102a6fdcafc5aa7199f7ce8933 Mon Sep 17 00:00:00 2001 +From: Paul Louvel +Date: Thu, 7 May 2026 16:41:57 +0200 +Subject: crypto: talitos/hash - fix SEC2 64k - 1 ahash request limitation + +From: Paul Louvel + +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 +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-6.18/crypto-talitos-hash-prepare-sec1-descriptor-chaining-remove-additional-descriptor.patch b/queue-6.18/crypto-talitos-hash-prepare-sec1-descriptor-chaining-remove-additional-descriptor.patch new file mode 100644 index 0000000000..999fc9b09e --- /dev/null +++ b/queue-6.18/crypto-talitos-hash-prepare-sec1-descriptor-chaining-remove-additional-descriptor.patch @@ -0,0 +1,196 @@ +From 59b5d899e33701665f18abe6bebf987427876e3e Mon Sep 17 00:00:00 2001 +From: Paul Louvel +Date: Thu, 7 May 2026 16:41:52 +0200 +Subject: crypto: talitos/hash - prepare SEC1 descriptor chaining, remove additional descriptor + +From: Paul Louvel + +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 +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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; + diff --git a/queue-6.18/crypto-talitos-hash-remove-useless-wrapper.patch b/queue-6.18/crypto-talitos-hash-remove-useless-wrapper.patch new file mode 100644 index 0000000000..919fa03ac5 --- /dev/null +++ b/queue-6.18/crypto-talitos-hash-remove-useless-wrapper.patch @@ -0,0 +1,44 @@ +From 907ae6088c82c9abae2d26477fddd60df6ad003b Mon Sep 17 00:00:00 2001 +From: Paul Louvel +Date: Thu, 7 May 2026 16:41:56 +0200 +Subject: crypto: talitos/hash - remove useless wrapper + +From: Paul Louvel + +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 +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-6.18/crypto-talitos-hash-rename-first_desc-last_desc-to-first_request-last_request.patch b/queue-6.18/crypto-talitos-hash-rename-first_desc-last_desc-to-first_request-last_request.patch new file mode 100644 index 0000000000..29322465ac --- /dev/null +++ b/queue-6.18/crypto-talitos-hash-rename-first_desc-last_desc-to-first_request-last_request.patch @@ -0,0 +1,129 @@ +From 8bcf00671400ac3b3a4cc3011e6c1496dbd880fd Mon Sep 17 00:00:00 2001 +From: Paul Louvel +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 + +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 +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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; + diff --git a/queue-6.18/crypto-talitos-hash-use-descriptor-chaining-for-sec1-instead-of-workqueue.patch b/queue-6.18/crypto-talitos-hash-use-descriptor-chaining-for-sec1-instead-of-workqueue.patch new file mode 100644 index 0000000000..2f835ca792 --- /dev/null +++ b/queue-6.18/crypto-talitos-hash-use-descriptor-chaining-for-sec1-instead-of-workqueue.patch @@ -0,0 +1,393 @@ +From f1ede6d95d8ad3b32c6a552d2baab805bd00fc38 Mon Sep 17 00:00:00 2001 +From: Paul Louvel +Date: Thu, 7 May 2026 16:41:53 +0200 +Subject: crypto: talitos/hash - use descriptor chaining for SEC1 instead of workqueue + +From: Paul Louvel + +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 +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-6.18/crypto-talitos-move-code-in-current_desc_hdr-into-a-standalone-function.patch b/queue-6.18/crypto-talitos-move-code-in-current_desc_hdr-into-a-standalone-function.patch new file mode 100644 index 0000000000..7698fbd3be --- /dev/null +++ b/queue-6.18/crypto-talitos-move-code-in-current_desc_hdr-into-a-standalone-function.patch @@ -0,0 +1,80 @@ +From f8713d9e6091755dd30f7f1cfa25f8440cddf81b Mon Sep 17 00:00:00 2001 +From: Paul Louvel +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 + +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 +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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; + diff --git a/queue-6.18/crypto-talitos-move-dma-mapping-code-in-talitos_submit-into-a-standalone-dma_map_request-function.patch b/queue-6.18/crypto-talitos-move-dma-mapping-code-in-talitos_submit-into-a-standalone-dma_map_request-function.patch new file mode 100644 index 0000000000..ff99b71f8a --- /dev/null +++ b/queue-6.18/crypto-talitos-move-dma-mapping-code-in-talitos_submit-into-a-standalone-dma_map_request-function.patch @@ -0,0 +1,121 @@ +From 5c0aa8cad7745505297103f05dda3fa06e8ac670 Mon Sep 17 00:00:00 2001 +From: Paul Louvel +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 + +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 +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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; + diff --git a/queue-6.18/crypto-talitos-move-dma-unmapping-code-in-flush_channel-into-a-standalone-dma_unmap_request-function.patch b/queue-6.18/crypto-talitos-move-dma-unmapping-code-in-flush_channel-into-a-standalone-dma_unmap_request-function.patch new file mode 100644 index 0000000000..0dc41826f9 --- /dev/null +++ b/queue-6.18/crypto-talitos-move-dma-unmapping-code-in-flush_channel-into-a-standalone-dma_unmap_request-function.patch @@ -0,0 +1,84 @@ +From 4d9b0b7415b9e79a3d54d18b5ff230974ea78740 Mon Sep 17 00:00:00 2001 +From: Paul Louvel +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 + +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 +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-6.18/crypto-talitos-use-dma_sync_single_for_cpu-before-reading-descriptor-header.patch b/queue-6.18/crypto-talitos-use-dma_sync_single_for_cpu-before-reading-descriptor-header.patch new file mode 100644 index 0000000000..f5ee51c4c5 --- /dev/null +++ b/queue-6.18/crypto-talitos-use-dma_sync_single_for_cpu-before-reading-descriptor-header.patch @@ -0,0 +1,77 @@ +From e17ff3d6ff907dc8406261e8fd3e1fc8a908f0f6 Mon Sep 17 00:00:00 2001 +From: Paul Louvel +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 + +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 +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-6.18/edac-i10nm-don-t-fail-probing-if-adxl-is-missing.patch b/queue-6.18/edac-i10nm-don-t-fail-probing-if-adxl-is-missing.patch new file mode 100644 index 0000000000..20b5fb18d8 --- /dev/null +++ b/queue-6.18/edac-i10nm-don-t-fail-probing-if-adxl-is-missing.patch @@ -0,0 +1,63 @@ +From e360a6d65bb46c527a5909430a31d640cdd5036e Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Tue, 14 Apr 2026 11:17:16 -0700 +Subject: EDAC/i10nm: Don't fail probing if ADXL is missing + +From: Vasily Khoruzhick + +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 +Signed-off-by: Tony Luck +Reviewed-by: Qiuxu Zhuo +Cc: stable@vger.kernel.org # v6.1+ +Link: https://patch.msgid.link/20260414181735.87023-1-anarsoul@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -79,6 +79,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 struct reg_rrl icx_reg_rrl_ddr = { + .set_num = 2, +@@ -1207,8 +1208,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); +@@ -1242,7 +1249,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(); + } + diff --git a/queue-6.18/i2c-core-fix-hang-on-adapter-registration-failure.patch b/queue-6.18/i2c-core-fix-hang-on-adapter-registration-failure.patch new file mode 100644 index 0000000000..7e0c6b4e68 --- /dev/null +++ b/queue-6.18/i2c-core-fix-hang-on-adapter-registration-failure.patch @@ -0,0 +1,109 @@ +From 3c7e164344e5bcf6f274bbf59a3274f5caad9bc1 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 11 May 2026 16:37:07 +0200 +Subject: i2c: core: fix hang on adapter registration failure + +From: Johan Hovold + +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 +Signed-off-by: Johan Hovold +Signed-off-by: Wolfram Sang +Signed-off-by: Greg Kroah-Hartman +--- + 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); +@@ -1609,6 +1610,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); +@@ -1748,29 +1750,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, +@@ -1796,6 +1779,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); diff --git a/queue-6.18/regulator-scmi-fix-of_node-refcount-leak-in-scmi_regulator_probe.patch b/queue-6.18/regulator-scmi-fix-of_node-refcount-leak-in-scmi_regulator_probe.patch new file mode 100644 index 0000000000..a90336027d --- /dev/null +++ b/queue-6.18/regulator-scmi-fix-of_node-refcount-leak-in-scmi_regulator_probe.patch @@ -0,0 +1,41 @@ +From fa11039d6cdff84584a3ef8cc1f5e1b56e045da2 Mon Sep 17 00:00:00 2001 +From: Wentao Liang +Date: Wed, 27 May 2026 10:48:50 +0000 +Subject: regulator: scmi: fix of_node refcount leak in scmi_regulator_probe() + +From: Wentao Liang + +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 +Link: https://patch.msgid.link/20260527104850.872415-1-vulab@iscas.ac.cn +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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); + /* diff --git a/queue-6.18/series b/queue-6.18/series index a3a0884d05..da49ef64ea 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -368,4 +368,23 @@ crypto-qat-protect-service-table-iterations-with-service_lock.patch crypto-qat-skip-restart-for-down-devices.patch crypto-qat-validate-rsa-crt-component-lengths.patch crypto-qat-factor-out-aer-reset-helpers.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 +x86-mm-fix-freeing-of-pmd-sized-vmemmap-pages.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 crypto-loongson-remove-broken-and-unused-loongson-rng.patch diff --git a/queue-6.18/spi-fsl-lpspi-replace-dmaengine_terminate_all-with-dmaengine_terminate_sync.patch b/queue-6.18/spi-fsl-lpspi-replace-dmaengine_terminate_all-with-dmaengine_terminate_sync.patch new file mode 100644 index 0000000000..5a83988389 --- /dev/null +++ b/queue-6.18/spi-fsl-lpspi-replace-dmaengine_terminate_all-with-dmaengine_terminate_sync.patch @@ -0,0 +1,77 @@ +From e703ce47691b967fe9b4057fb1d062273211afa9 Mon Sep 17 00:00:00 2001 +From: Carlos Song +Date: Mon, 25 May 2026 14:23:56 +0800 +Subject: spi: fsl-lpspi: replace dmaengine_terminate_all() with dmaengine_terminate_sync() + +From: Carlos Song + +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 +Link: https://patch.msgid.link/20260525062357.3191349-2-carlos.song@oss.nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -619,7 +619,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; + } + +@@ -640,8 +640,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; + } +@@ -650,8 +650,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; + } +@@ -660,8 +660,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; + } +@@ -670,8 +670,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; + } diff --git a/queue-6.18/spi-fsl-lpspi-terminate-the-rx-channel-on-tx-prepare-failure-path.patch b/queue-6.18/spi-fsl-lpspi-terminate-the-rx-channel-on-tx-prepare-failure-path.patch new file mode 100644 index 0000000000..6e3295c098 --- /dev/null +++ b/queue-6.18/spi-fsl-lpspi-terminate-the-rx-channel-on-tx-prepare-failure-path.patch @@ -0,0 +1,39 @@ +From 01980b5da56e573d62798d0ff6c86bcaa2b22cbe Mon Sep 17 00:00:00 2001 +From: Carlos Song +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 + +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 +Link: https://patch.msgid.link/20260525062357.3191349-3-carlos.song@oss.nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -619,7 +619,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; + } + diff --git a/queue-6.18/watchdog-apple-add-apple-t8103-wdt-compatible.patch b/queue-6.18/watchdog-apple-add-apple-t8103-wdt-compatible.patch new file mode 100644 index 0000000000..f77c3be403 --- /dev/null +++ b/queue-6.18/watchdog-apple-add-apple-t8103-wdt-compatible.patch @@ -0,0 +1,37 @@ +From 14ca4868886f2188401fe06cd7bf01a330b3fb99 Mon Sep 17 00:00:00 2001 +From: Janne Grunau +Date: Wed, 31 Dec 2025 13:07:21 +0100 +Subject: watchdog: apple: Add "apple,t8103-wdt" compatible + +From: Janne Grunau + +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 +Signed-off-by: Janne Grunau +Link: https://lore.kernel.org/r/20251231-watchdog-apple-t8103-base-compat-v1-1-1702a02e0c45@jannau.net +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman +--- + drivers/watchdog/apple_wdt.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/watchdog/apple_wdt.c ++++ b/drivers/watchdog/apple_wdt.c +@@ -218,6 +218,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" }, + {}, + }; diff --git a/queue-6.18/x86-mm-fix-freeing-of-pmd-sized-vmemmap-pages.patch b/queue-6.18/x86-mm-fix-freeing-of-pmd-sized-vmemmap-pages.patch new file mode 100644 index 0000000000..c99dd699c7 --- /dev/null +++ b/queue-6.18/x86-mm-fix-freeing-of-pmd-sized-vmemmap-pages.patch @@ -0,0 +1,128 @@ +From 39406c05f8f150f1685839acd38ffdd69ff92031 Mon Sep 17 00:00:00 2001 +From: "David Hildenbrand (Arm)" +Date: Wed, 29 Apr 2026 12:49:14 +0200 +Subject: x86/mm: Fix freeing of PMD-sized vmemmap pages + +From: David Hildenbrand (Arm) + +commit 39406c05f8f150f1685839acd38ffdd69ff92031 upstream. + +Commit bf9e4e30f353 ("x86/mm: use pagetable_free()"), switched from +freeing non-boot page tables through __free_pages() to +pagetable_free(). + +However, the function is also called to free vmemmap pages. + +Given that vmemmap pages are not page tables, already the page_ptdesc(page) +is wrong. But worse, pagetable_free() calls: + + __free_pages(page, compound_order(page)); + +Since vmemmap pages are not compound pages (see vmemmap_alloc_block()) +-- except for HVO, which doesn't apply here -- only first page of a +PMD-sized vmemmap page is freed, leaking the other ones. + +Fix it by properly decoupling pagetable and vmemmap freeing. +free_pagetable() no longer has to mess with SECTION_INFO, as only the +vmemmap is marked like that in register_page_bootmem_memmap(). + +The indentation in remove_pmd_table() is messed up. Fix that while +touching it. + +Bootmem info handling will soon be fixed up. For now, handle it +similar to free_pagetable(), just avoiding the ifdef. + +[ dhansen: changelog munging. More imperative voice ] + +Fixes: bf9e4e30f353 ("x86/mm: use pagetable_free()") +Signed-off-by: David Hildenbrand (Arm) +Signed-off-by: Andrew Morton +Signed-off-by: Dave Hansen +Acked-by: Mike Rapoport (Microsoft) +Tested-by: Lance Yang +Link: https://lore.kernel.org/20260429-vmemmap-v2-1-8dfcacffd877@kernel.org +Link: https://patch.msgid.link/20260429-vmemmap-v2-1-8dfcacffd877@kernel.org +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/mm/init_64.c | 40 ++++++++++++++++++++++++++-------------- + 1 file changed, 26 insertions(+), 14 deletions(-) + +--- a/arch/x86/mm/init_64.c ++++ b/arch/x86/mm/init_64.c +@@ -1021,7 +1021,7 @@ static void __meminit free_pagetable(str + #ifdef CONFIG_HAVE_BOOTMEM_INFO_NODE + enum bootmem_type type = bootmem_type(page); + +- if (type == SECTION_INFO || type == MIX_SECTION_INFO) { ++ if (type == MIX_SECTION_INFO) { + while (nr_pages--) + put_page_bootmem(page++); + } else { +@@ -1035,13 +1035,24 @@ static void __meminit free_pagetable(str + } + } + +-static void __meminit free_hugepage_table(struct page *page, ++static void __meminit free_vmemmap_pages(struct page *page, unsigned int order, + struct vmem_altmap *altmap) + { +- if (altmap) +- vmem_altmap_free(altmap, PMD_SIZE / PAGE_SIZE); +- else +- free_pagetable(page, get_order(PMD_SIZE)); ++ unsigned long nr_pages = 1u << order; ++ ++ if (altmap) { ++ vmem_altmap_free(altmap, nr_pages); ++ } else if (PageReserved(page)) { ++ if (IS_ENABLED(CONFIG_HAVE_BOOTMEM_INFO_NODE) && ++ bootmem_type(page) == SECTION_INFO) { ++ while (nr_pages--) ++ put_page_bootmem(page++); ++ } else { ++ free_reserved_pages(page, nr_pages); ++ } ++ } else { ++ __free_pages(page, order); ++ } + } + + static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd) +@@ -1125,7 +1136,8 @@ remove_pte_table(pte_t *pte_start, unsig + return; + + if (!direct) +- free_pagetable(pte_page(*pte), 0); ++ /* We never populate base pages from the altmap. */ ++ free_vmemmap_pages(pte_page(*pte), 0, NULL); + + spin_lock(&init_mm.page_table_lock); + pte_clear(&init_mm, addr, pte); +@@ -1160,19 +1172,19 @@ remove_pmd_table(pmd_t *pmd_start, unsig + if (IS_ALIGNED(addr, PMD_SIZE) && + IS_ALIGNED(next, PMD_SIZE)) { + if (!direct) +- free_hugepage_table(pmd_page(*pmd), +- altmap); ++ free_vmemmap_pages(pmd_page(*pmd), ++ PMD_ORDER, altmap); + + spin_lock(&init_mm.page_table_lock); + pmd_clear(pmd); + spin_unlock(&init_mm.page_table_lock); + pages++; + } else if (vmemmap_pmd_is_unused(addr, next)) { +- free_hugepage_table(pmd_page(*pmd), +- altmap); +- spin_lock(&init_mm.page_table_lock); +- pmd_clear(pmd); +- spin_unlock(&init_mm.page_table_lock); ++ free_vmemmap_pages(pmd_page(*pmd), PMD_ORDER, ++ altmap); ++ spin_lock(&init_mm.page_table_lock); ++ pmd_clear(pmd); ++ spin_unlock(&init_mm.page_table_lock); + } + continue; + }