* Re: [PATCH v19 00/14] crypto/dmaengine: qce: introduce BAM locking and use DMA for register I/O
From: Bartosz Golaszewski @ 2026-06-04 11:50 UTC (permalink / raw)
To: Vinod Koul
Cc: Bartosz Golaszewski, Jonathan Corbet, Thara Gopinath, Herbert Xu,
David S. Miller, Udit Tiwari, Md Sadre Alam, Dmitry Baryshkov,
Manivannan Sadhasivam, Bjorn Andersson, Peter Ujfalusi,
Michal Simek, Frank Li, Andy Gross, Neil Armstrong, dmaengine,
linux-doc, linux-kernel, linux-arm-msm, linux-crypto,
linux-arm-kernel, brgl, Bartosz Golaszewski, Dmitry Baryshkov,
Konrad Dybcio, Stephan Gerhold
In-Reply-To: <aiFScCW_NEY3CsEf@vaman>
On Thu, 4 Jun 2026 12:24:48 +0200, Vinod Koul <vkoul@kernel.org> said:
> On 02-06-26, 18:38, Stephan Gerhold wrote:
>> On Tue, May 26, 2026 at 03:10:48PM +0200, Bartosz Golaszewski wrote:
>> > I feel like I fell into the trap of trying to address pre-existing
>> > issues reported by sashiko and in the process provoking more reports so
>> > let this be the last iteration where I do this. Vinod can we get this
>> > queued for v7.2 now and iron out any previously existing problems in
>> > tree?
>>
>> Thanks a lot for working on fixing all these issues!
>>
>> I agree there is no point addressing all the "pre-existing issues"
>> pointed out by Sashiko, but have you looked through the other comments
>> for new issues pointed out for your patches?
>
> I hope Bart and Qualcomm can fix these driver issues as well
>>
>> Out of curiosity, I was looking a bit at the comments for [PATCH v19
>> 06/14] dmaengine: qcom: bam_dma: add support for BAM locking [1]. There
>> are 8 open comments there (Critical: 1, High: 6 and Medium: 1). From a
>> quick look I would say most of these could be valid. The critical one
>> about the usage of dma_cookie_assign() sounds a bit concerning to me, if
>> it is true we would be basically breaking parts of the dmaengine API for
>> consumers by inserting the lock descriptor in front of everything else.
>
> Yes this seems to be a valid one. Attaching another descriptor for lock
> does not sound right to me, as in this case causes descriptor to be
> marked 'done' prematurely.
>
Yes, I have a fix for this queued.
> Honestly, I am not quite happy with the way lock is being handled here.
> I would hope we can have some better suggestions. Adding a descriptor
> for lock does not look right to me. We are adding odd hardware/firmware
> behaviour on engine apis.
>
> I had earlier suggested to lock always or lock only for hw/sw versions
> supported inside the driver, that might be simplist solution without the
> complexity added here
>
I'm not sure what you mean here. Several iterations ago it was deferred to
consumer drivers. Mani objected and Bjorn and you agreed. I reworked it to move
the locking logic into the DMA driver as requested.
Bart
^ permalink raw reply
* Re: [PATCH] rhashtable: Use irq work for shrinking
From: Mykyta Yatsenko @ 2026-06-04 10:47 UTC (permalink / raw)
To: Herbert Xu
Cc: bot+bpf-ci, bpf, ast, andrii, daniel, kafai, kernel-team, eddyz87,
memxor, yatsenko, martin.lau, yonghong.song, clm, ihor.solodrai,
Tejun Heo, Linux Crypto Mailing List
In-Reply-To: <aiDgUPXZUi-jnTdo@gondor.apana.org.au>
On 6/4/26 3:17 AM, Herbert Xu wrote:
> On Wed, Jun 03, 2026 at 02:08:25PM +0100, Mykyta Yatsenko wrote:
>>
>> For v7 I'm dropping automatic_shrinking, because it adds a risk of
>> calling schedule_work() on element deletion path (__rhashtable_remove_fast_one())
>> when hashtable size drops below 30% of the capacity.
>
> Now that expansion uses irq work I think shrinking should switch
> to that as well.
>
Makes sense, thanks, I'll include your patch below in this series then.
> ---8<---
> Use irq work for automatic shrinking so that this may be called
> in NMI context.
>
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
>
> diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
> index ef5230cece36..0693bce6f890 100644
> --- a/include/linux/rhashtable.h
> +++ b/include/linux/rhashtable.h
> @@ -1117,7 +1117,7 @@ static __always_inline int __rhashtable_remove_fast_one(
> atomic_dec(&ht->nelems);
> if (unlikely(ht->p.automatic_shrinking &&
> rht_shrink_below_30(ht, tbl)))
> - schedule_work(&ht->run_work);
> + irq_work_queue(&ht->run_irq_work);
> err = 0;
> }
>
> Cheers,
^ permalink raw reply
* [PATCH] crypto: tegra: fix refcount leak in tegra_se_host1x_submit()
From: Wentao Liang @ 2026-06-04 10:27 UTC (permalink / raw)
To: akhilrajeev, herbert, davem, thierry.reding, jonathanh
Cc: linux-crypto, linux-tegra, linux-kernel, Wentao Liang, stable
The timeout error path in tegra_se_host1x_submit() returns without
calling host1x_job_put(), while all other paths (success, submit
error, pin error) properly release the job reference through the
job_put label. Since host1x_job_alloc() initializes the reference
count and host1x_job_put() is required to drop it, omitting it on
timeout causes a permanent refcount leak.
Fix this by redirecting the timeout return to the existing job_put
label, ensuring the job reference and any associated syncpt
references are consistently released.
Cc: stable@vger.kernel.org
Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver")
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
---
drivers/crypto/tegra/tegra-se-main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/crypto/tegra/tegra-se-main.c b/drivers/crypto/tegra/tegra-se-main.c
index eb71113ed146..e8d8c3a23d7a 100644
--- a/drivers/crypto/tegra/tegra-se-main.c
+++ b/drivers/crypto/tegra/tegra-se-main.c
@@ -180,7 +180,7 @@ int tegra_se_host1x_submit(struct tegra_se *se, struct tegra_se_cmdbuf *cmdbuf,
MAX_SCHEDULE_TIMEOUT, NULL);
if (ret) {
dev_err(se->dev, "host1x job timed out\n");
- return ret;
+ goto job_put;
}
host1x_job_put(job);
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v19 00/14] crypto/dmaengine: qce: introduce BAM locking and use DMA for register I/O
From: Vinod Koul @ 2026-06-04 10:24 UTC (permalink / raw)
To: Stephan Gerhold
Cc: Bartosz Golaszewski, Jonathan Corbet, Thara Gopinath, Herbert Xu,
David S. Miller, Udit Tiwari, Md Sadre Alam, Dmitry Baryshkov,
Manivannan Sadhasivam, Bjorn Andersson, Peter Ujfalusi,
Michal Simek, Frank Li, Andy Gross, Neil Armstrong, dmaengine,
linux-doc, linux-kernel, linux-arm-msm, linux-crypto,
linux-arm-kernel, brgl, Bartosz Golaszewski, Dmitry Baryshkov,
Konrad Dybcio
In-Reply-To: <ah8G_ajPS1KhgPP_@linaro.org>
On 02-06-26, 18:38, Stephan Gerhold wrote:
> On Tue, May 26, 2026 at 03:10:48PM +0200, Bartosz Golaszewski wrote:
> > I feel like I fell into the trap of trying to address pre-existing
> > issues reported by sashiko and in the process provoking more reports so
> > let this be the last iteration where I do this. Vinod can we get this
> > queued for v7.2 now and iron out any previously existing problems in
> > tree?
>
> Thanks a lot for working on fixing all these issues!
>
> I agree there is no point addressing all the "pre-existing issues"
> pointed out by Sashiko, but have you looked through the other comments
> for new issues pointed out for your patches?
I hope Bart and Qualcomm can fix these driver issues as well
>
> Out of curiosity, I was looking a bit at the comments for [PATCH v19
> 06/14] dmaengine: qcom: bam_dma: add support for BAM locking [1]. There
> are 8 open comments there (Critical: 1, High: 6 and Medium: 1). From a
> quick look I would say most of these could be valid. The critical one
> about the usage of dma_cookie_assign() sounds a bit concerning to me, if
> it is true we would be basically breaking parts of the dmaengine API for
> consumers by inserting the lock descriptor in front of everything else.
Yes this seems to be a valid one. Attaching another descriptor for lock
does not sound right to me, as in this case causes descriptor to be
marked 'done' prematurely.
Honestly, I am not quite happy with the way lock is being handled here.
I would hope we can have some better suggestions. Adding a descriptor
for lock does not look right to me. We are adding odd hardware/firmware
behaviour on engine apis.
I had earlier suggested to lock always or lock only for hw/sw versions
supported inside the driver, that might be simplist solution without the
complexity added here
--
~Vinod
^ permalink raw reply
* [PATCH] crypto: chelsio: fix refcount leaks in ahash request functions
From: Wentao Liang @ 2026-06-04 10:13 UTC (permalink / raw)
To: ayush.sawal, herbert, davem
Cc: linux-crypto, linux-kernel, Wentao Liang, stable
When chcr_send_wr() fails in chcr_ahash_finup(), chcr_ahash_final(),
chcr_ahash_update(), or chcr_ahash_digest(), the function still returns
-EINPROGRESS to the crypto layer, claiming the request has been
submitted. No completion callback will be triggered because the work
request was not actually handed over to the hardware, so the
dev->inflight refcount that was incremented by chcr_inc_wrcount() is
never decremented. This permanently prevents device detach and leads
to a resource leak.
Check the return value of chcr_send_wr() and jump to the error unmap
path on failure so that the refcount is properly undone before
returning an error.
Cc: stable@vger.kernel.org
Fixes: 324429d74127 ("chcr: Support for Chelsio's Crypto Hardware")
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
---
drivers/crypto/chelsio/chcr_algo.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/crypto/chelsio/chcr_algo.c b/drivers/crypto/chelsio/chcr_algo.c
index 14a708defcd4..142eccaf82fe 100644
--- a/drivers/crypto/chelsio/chcr_algo.c
+++ b/drivers/crypto/chelsio/chcr_algo.c
@@ -1877,7 +1877,10 @@ static int chcr_ahash_finup(struct ahash_request *req)
req_ctx->hctx_wr.processed += params.sg_len;
skb->dev = u_ctx->lldi.ports[0];
set_wr_txq(skb, CPL_PRIORITY_DATA, req_ctx->txqidx);
- chcr_send_wr(skb);
+ if (chcr_send_wr(skb)) {
+ error = -EIO;
+ goto unmap;
+ }
return -EINPROGRESS;
unmap:
chcr_hash_dma_unmap(&u_ctx->lldi.pdev->dev, req);
--
2.34.1
^ permalink raw reply related
* Re: [PATCH 29/29] crypto: talitos - Remove TALITOS_DESC_SIZE macro
From: Christophe Leroy (CS GROUP) @ 2026-06-04 9:59 UTC (permalink / raw)
To: Paul Louvel, Herbert Xu, David S. Miller
Cc: Thomas Petazzoni, Herve Codina, linux-crypto, linux-kernel
In-Reply-To: <20260528-7-1-rc1_talitos_cleanup-v1-29-cb1ad6cdea49@bootlin.com>
Le 28/05/2026 à 11:08, Paul Louvel a écrit :
> Now that struct talitos_desc no longer has the SEC1-only next_desc field
> (it was moved into sec1_talitos_desc), TALITOS_DESC_SIZE is identical to
> sizeof(struct talitos_desc) and no longer serves any purpose. Remove it
> and use sizeof directly at each macro invocation.
It is still there ...
$ git grep TALITOS_DESC_SIZE drivers
drivers/crypto/talitos/talitos.h:#define TALITOS_DESC_SIZE
sizeof(struct talitos_desc)
>
> Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
> ---
> drivers/crypto/talitos/talitos-sec1.c | 10 +++++-----
> drivers/crypto/talitos/talitos-sec2.c | 6 +++---
> 2 files changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/crypto/talitos/talitos-sec1.c b/drivers/crypto/talitos/talitos-sec1.c
> index e4f482520372..504ce9e23e59 100644
> --- a/drivers/crypto/talitos/talitos-sec1.c
> +++ b/drivers/crypto/talitos/talitos-sec1.c
> @@ -190,7 +190,7 @@ static void sec1_dma_map_request(struct device *dev,
> while (edesc) {
>
> dma_desc = dma_map_single(dev, &edesc->desc.sec1.hdr,
> - TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
> + sizeof(struct talitos_desc), DMA_BIDIRECTIONAL);
>
> if (!prev_edesc) {
> request->dma_desc = dma_desc;
> @@ -202,7 +202,7 @@ static void sec1_dma_map_request(struct device *dev,
> prev_edesc->desc.sec1.next_desc = cpu_to_be32(dma_desc);
>
> dma_sync_single_for_device(dev, prev_dma_desc,
> - TALITOS_DESC_SIZE, DMA_TO_DEVICE);
> + sizeof(struct talitos_desc), DMA_TO_DEVICE);
>
> next:
> prev_edesc = edesc;
> @@ -216,12 +216,12 @@ static void sec1_dma_unmap_request(struct device *dev,
> {
> struct talitos_edesc *edesc;
>
> - dma_unmap_single(dev, request->dma_desc, TALITOS_DESC_SIZE,
> + dma_unmap_single(dev, request->dma_desc, sizeof(struct talitos_desc),
> DMA_BIDIRECTIONAL);
> edesc = container_of(request->desc, struct talitos_edesc, desc);
> while (edesc->next_desc) {
> dma_unmap_single(dev, be32_to_cpu(edesc->desc.sec1.next_desc),
> - TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
> + sizeof(struct talitos_desc), DMA_BIDIRECTIONAL);
> edesc = edesc->next_desc;
> }
> }
> @@ -239,7 +239,7 @@ static __be32 sec1_get_request_hdr(struct device *dev,
> edesc = edesc->next_desc;
> }
>
> - dma_sync_single_for_cpu(dev, dma_desc, TALITOS_DESC_SIZE,
> + dma_sync_single_for_cpu(dev, dma_desc, sizeof(struct talitos_desc),
> DMA_BIDIRECTIONAL);
>
> return edesc->desc.sec1.hdr;
> diff --git a/drivers/crypto/talitos/talitos-sec2.c b/drivers/crypto/talitos/talitos-sec2.c
> index 52f783ddc8b6..0df3b22510c7 100644
> --- a/drivers/crypto/talitos/talitos-sec2.c
> +++ b/drivers/crypto/talitos/talitos-sec2.c
> @@ -205,7 +205,7 @@ static void sec2_dma_map_request(struct device *dev,
> struct talitos_desc *desc)
> {
> request->dma_desc =
> - dma_map_single(dev, desc, TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
> + dma_map_single(dev, desc, sizeof(struct talitos_desc), DMA_BIDIRECTIONAL);
> }
>
> static int sec2_talitos_handle_error(struct device *dev, u32 isr, u32 isr_lo)
> @@ -346,14 +346,14 @@ static void sec2_init_task(struct device *dev)
> static void sec2_dma_unmap_request(struct device *dev,
> struct talitos_request *request)
> {
> - dma_unmap_single(dev, request->dma_desc, TALITOS_DESC_SIZE,
> + dma_unmap_single(dev, request->dma_desc, sizeof(struct talitos_desc),
> DMA_BIDIRECTIONAL);
> }
>
> static __be32 sec2_get_request_hdr(struct device *dev,
> struct talitos_request *request)
> {
> - dma_sync_single_for_cpu(dev, request->dma_desc, TALITOS_DESC_SIZE,
> + dma_sync_single_for_cpu(dev, request->dma_desc, sizeof(struct talitos_desc),
> DMA_BIDIRECTIONAL);
>
> return request->desc->sec2.hdr;
>
^ permalink raw reply
* Re: [PATCH 27/29] crypto: talitos - Introduce per-SEC-version descriptor structures and ops
From: Christophe Leroy (CS GROUP) @ 2026-06-04 9:57 UTC (permalink / raw)
To: Paul Louvel, Herbert Xu, David S. Miller
Cc: Thomas Petazzoni, Herve Codina, linux-crypto, linux-kernel
In-Reply-To: <20260528-7-1-rc1_talitos_cleanup-v1-27-cb1ad6cdea49@bootlin.com>
Le 28/05/2026 à 11:08, Paul Louvel a écrit :
> The driver used a single shared talitos_desc with overlapping union
> members and a SEC1-specific "hdr1" hack to handle differences between
> SEC1 and SEC2 descriptor layouts.
I'd call it a feature not a hack. We have the chance that allthough
different the structures are very close and can be kept common at the
low price of that copy from hdr to hdr1 in talitos submit.
>
> Introduce distinct sec1_talitos_desc/sec2_talitos_desc and
> sec1_talitos_ptr/sec2_talitos_ptr structures, nested inside a union
> in talitos_desc/talitos_ptr.
> Mark them packed to reflect that these structures are used directly by
> the hardware, even if the structure is naturally aligned.
>
> Abstract descriptor field access through a new talitos_desc_ops
> structure (set_hdr, get_hdr, get_hdr_lo, get_ptr), and add get_ptr_value
> to the existing talitos_ptr_ops.
Too much abstraction and opacity kills readability and maintainability.
Especially here your change increases the number of places you have to
break instructions in two lines or more. This really kills readability.
I really prefer reading
&edesc->desc.ptr[6]
over
ctx->desc_ops->get_ptr(&edesc->desc, 6)
>
> Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
> ---
> drivers/crypto/talitos/talitos-aead.c | 76 +++++++++++++++++++------------
> drivers/crypto/talitos/talitos-hash.c | 51 +++++++++++++--------
> drivers/crypto/talitos/talitos-sec1.c | 61 +++++++++++++++++++------
> drivers/crypto/talitos/talitos-sec2.c | 56 ++++++++++++++++++-----
> drivers/crypto/talitos/talitos-skcipher.c | 46 +++++++++++--------
> drivers/crypto/talitos/talitos.c | 4 +-
> drivers/crypto/talitos/talitos.h | 60 +++++++++++++++++-------
> 7 files changed, 244 insertions(+), 110 deletions(-)
>
> diff --git a/drivers/crypto/talitos/talitos-aead.c b/drivers/crypto/talitos/talitos-aead.c
> index b585abdd2275..d1cec7e4dd3f 100644
> --- a/drivers/crypto/talitos/talitos-aead.c
> +++ b/drivers/crypto/talitos/talitos-aead.c
> @@ -94,12 +94,15 @@ static void ipsec_esp_unmap(struct device *dev,
> unsigned int ivsize = crypto_aead_ivsize(aead);
> unsigned int authsize = crypto_aead_authsize(aead);
> unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
> - bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP;
> - struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3];
> + bool is_ipsec_esp = ctx->desc_ops->get_hdr(&edesc->desc) &
> + DESC_HDR_TYPE_IPSEC_ESP;
> + struct talitos_ptr *civ_ptr =
> + ctx->desc_ops->get_ptr(&edesc->desc, is_ipsec_esp ? 2 : 3);
>
> if (is_ipsec_esp)
> - unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6],
> - DMA_FROM_DEVICE);
> + unmap_single_talitos_ptr(
> + dev, ctx->desc_ops->get_ptr(&edesc->desc, 6),
> + DMA_FROM_DEVICE);
> unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE);
>
> talitos_sg_unmap(dev, edesc, areq->src, areq->dst,
> @@ -171,6 +174,7 @@ static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
> struct talitos_desc *desc,
> void *context, int err)
> {
> + struct talitos_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(context));
> struct aead_request *req = context;
> struct talitos_edesc *edesc;
>
> @@ -179,8 +183,8 @@ static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
> ipsec_esp_unmap(dev, edesc, req, false);
>
> /* check ICV auth status */
> - if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
> - DESC_HDR_LO_ICCR1_PASS))
> + if (!err && ((ctx->desc_ops->get_hdr_lo(desc) &
> + DESC_HDR_LO_ICCR1_MASK) != DESC_HDR_LO_ICCR1_PASS))
> err = -EBADMSG;
>
> kfree(edesc);
> @@ -210,13 +214,17 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
> bool sync_needed = false;
> struct talitos_private *priv = dev_get_drvdata(dev);
> bool is_sec1 = has_ftr_sec1(priv);
> - bool is_ipsec_esp = desc->hdr & DESC_HDR_TYPE_IPSEC_ESP;
> - struct talitos_ptr *civ_ptr = &desc->ptr[is_ipsec_esp ? 2 : 3];
> - struct talitos_ptr *ckey_ptr = &desc->ptr[is_ipsec_esp ? 3 : 2];
> + bool is_ipsec_esp = ctx->desc_ops->get_hdr(desc) &
> + DESC_HDR_TYPE_IPSEC_ESP;
> + struct talitos_ptr *civ_ptr =
> + ctx->desc_ops->get_ptr(desc, is_ipsec_esp ? 2 : 3);
> + struct talitos_ptr *ckey_ptr =
> + ctx->desc_ops->get_ptr(desc, is_ipsec_esp ? 3 : 2);
> dma_addr_t dma_icv = edesc->dma_link_tbl + edesc->dma_len - authsize;
>
> /* hmac key */
> - ctx->ptr_ops->to_talitos_ptr(&desc->ptr[0], ctx->dma_key, ctx->authkeylen);
> + ctx->ptr_ops->to_talitos_ptr(ctx->desc_ops->get_ptr(desc, 0),
> + ctx->dma_key, ctx->authkeylen);
>
> sg_count = edesc->src_nents ?: 1;
> if (is_sec1 && sg_count > 1)
> @@ -229,7 +237,8 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
>
> /* hmac data */
> ret = talitos_sg_map(dev, areq->src, areq->assoclen, edesc,
> - &desc->ptr[1], sg_count, 0, tbl_off);
> + ctx->desc_ops->get_ptr(desc, 1), sg_count, 0,
> + tbl_off);
>
> if (ret > 1) {
> tbl_off += ret;
> @@ -249,12 +258,13 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
> * extent is bytes of HMAC postpended to ciphertext,
> * typically 12 for ipsec
> */
> - if (is_ipsec_esp && (desc->hdr & DESC_HDR_MODE1_MDEU_CICV))
> + if (is_ipsec_esp &&
> + (ctx->desc_ops->get_hdr(desc) & DESC_HDR_MODE1_MDEU_CICV))
> elen = authsize;
>
> - ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4],
> - sg_count, areq->assoclen, tbl_off, elen,
> - false, 1);
> + ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc,
> + ctx->desc_ops->get_ptr(desc, 4), sg_count,
> + areq->assoclen, tbl_off, elen, false, 1);
>
> if (ret > 1) {
> tbl_off += ret;
> @@ -272,8 +282,9 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
> elen = authsize;
> else
> elen = 0;
> - ret = talitos_sg_map_ext(dev, areq->dst, cryptlen, edesc, &desc->ptr[5],
> - sg_count, areq->assoclen, tbl_off, elen,
> + ret = talitos_sg_map_ext(dev, areq->dst, cryptlen, edesc,
> + ctx->desc_ops->get_ptr(desc, 5), sg_count,
> + areq->assoclen, tbl_off, elen,
> is_ipsec_esp && !encrypt, 1);
> tbl_off += ret;
>
> @@ -286,20 +297,23 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
>
> /* icv data follows link tables */
> ctx->ptr_ops->to_talitos_ptr(tbl_ptr, dma_icv, authsize);
> - ctx->ptr_ops->to_talitos_ptr_ext_or(&desc->ptr[5], authsize);
> + ctx->ptr_ops->to_talitos_ptr_ext_or(
> + ctx->desc_ops->get_ptr(desc, 5), authsize);
> sync_needed = true;
> } else if (!encrypt) {
> - ctx->ptr_ops->to_talitos_ptr(&desc->ptr[6], dma_icv, authsize);
> + ctx->ptr_ops->to_talitos_ptr(ctx->desc_ops->get_ptr(desc, 6),
> + dma_icv, authsize);
> sync_needed = true;
> } else if (!is_ipsec_esp) {
> - talitos_sg_map(dev, areq->dst, authsize, edesc, &desc->ptr[6],
> - sg_count, areq->assoclen + cryptlen, tbl_off);
> + talitos_sg_map(dev, areq->dst, authsize, edesc,
> + ctx->desc_ops->get_ptr(desc, 6), sg_count,
> + areq->assoclen + cryptlen, tbl_off);
> }
>
> /* iv out */
> if (is_ipsec_esp)
> - map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
> - DMA_FROM_DEVICE);
> + map_single_talitos_ptr(dev, ctx->desc_ops->get_ptr(desc, 6),
> + ivsize, ctx->iv, DMA_FROM_DEVICE);
>
> if (sync_needed)
> dma_sync_single_for_device(dev, edesc->dma_link_tbl,
> @@ -341,7 +355,7 @@ static int aead_encrypt(struct aead_request *req)
> return PTR_ERR(edesc);
>
> /* set encrypt */
> - edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
> + ctx->desc_ops->set_hdr(&edesc->desc, ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT);
>
> return ipsec_esp(edesc, req, true, ipsec_esp_encrypt_done);
> }
> @@ -354,21 +368,24 @@ static int aead_decrypt(struct aead_request *req)
> struct talitos_private *priv = dev_get_drvdata(ctx->dev);
> struct talitos_edesc *edesc;
> void *icvdata;
> + __be32 hdr;
>
> /* allocate extended descriptor */
> edesc = aead_edesc_alloc(req, req->iv, 1, false);
> if (IS_ERR(edesc))
> return PTR_ERR(edesc);
>
> - if ((edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP) &&
> + hdr = ctx->desc_ops->get_hdr(&edesc->desc);
> + if ((hdr & DESC_HDR_TYPE_IPSEC_ESP) &&
> (priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
> ((!edesc->src_nents && !edesc->dst_nents) ||
> priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
>
> /* decrypt and check the ICV */
> - edesc->desc.hdr = ctx->desc_hdr_template |
> - DESC_HDR_DIR_INBOUND |
> - DESC_HDR_MODE1_MDEU_CICV;
> + ctx->desc_ops->set_hdr(&edesc->desc,
> + ctx->desc_hdr_template |
> + DESC_HDR_DIR_INBOUND |
> + DESC_HDR_MODE1_MDEU_CICV);
>
> /* reset integrity check result bits */
>
> @@ -377,7 +394,8 @@ static int aead_decrypt(struct aead_request *req)
> }
>
> /* Have to check the ICV with software */
> - edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
> + ctx->desc_ops->set_hdr(&edesc->desc,
> + ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND);
>
> /* stash incoming ICV for later cmp with ICV generated by the h/w */
> icvdata = edesc->buf + edesc->dma_len;
> diff --git a/drivers/crypto/talitos/talitos-hash.c b/drivers/crypto/talitos/talitos-hash.c
> index 026eebf037f5..fb4d53e2abf8 100644
> --- a/drivers/crypto/talitos/talitos-hash.c
> +++ b/drivers/crypto/talitos/talitos-hash.c
> @@ -44,7 +44,8 @@ static void common_nonsnoop_hash_unmap(struct talitos_ctx *ctx,
> struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
> struct talitos_desc *desc = &edesc->desc;
>
> - unmap_single_talitos_ptr(ctx->dev, &desc->ptr[5], DMA_FROM_DEVICE);
> + unmap_single_talitos_ptr(ctx->dev, ctx->desc_ops->get_ptr(desc, 5),
> + DMA_FROM_DEVICE);
>
> if (edesc->last && req_ctx->last_request)
> memcpy(areq->result, req_ctx->hw_context,
> @@ -54,8 +55,9 @@ static void common_nonsnoop_hash_unmap(struct talitos_ctx *ctx,
> talitos_sg_unmap(ctx->dev, edesc, edesc->src, NULL, 0, 0);
>
> /* When using hashctx-in, must unmap it. */
> - if (ctx->ptr_ops->from_talitos_ptr_len(&desc->ptr[1]))
> - unmap_single_talitos_ptr(ctx->dev, &desc->ptr[1],
> + if (ctx->ptr_ops->from_talitos_ptr_len(ctx->desc_ops->get_ptr(desc, 1)))
> + unmap_single_talitos_ptr(ctx->dev,
> + ctx->desc_ops->get_ptr(desc, 1),
> DMA_TO_DEVICE);
>
> if (edesc->dma_len)
> @@ -131,7 +133,9 @@ static void talitos_handle_buggy_hash(struct talitos_ctx *ctx,
> };
>
> pr_err_once("Bug in SEC1, padding ourself\n");
> - edesc->desc.hdr &= ~DESC_HDR_MODE0_MDEU_PAD;
> + ctx->desc_ops->set_hdr(&edesc->desc,
> + ctx->desc_ops->get_hdr(&edesc->desc) &
> + ~DESC_HDR_MODE0_MDEU_PAD);
> map_single_talitos_ptr(ctx->dev, ptr, sizeof(padded_hash),
> (char *)padded_hash, DMA_TO_DEVICE);
> }
> @@ -154,7 +158,8 @@ static void common_nonsnoop_hash(struct talitos_edesc *edesc,
>
> /* hash context in */
> if (!edesc->first || !req_ctx->first_request || req_ctx->swinit) {
> - map_single_talitos_ptr_nosync(dev, &desc->ptr[1],
> + map_single_talitos_ptr_nosync(dev,
> + ctx->desc_ops->get_ptr(desc, 1),
> req_ctx->hw_context_size,
> req_ctx->hw_context,
> DMA_TO_DEVICE);
> @@ -165,8 +170,8 @@ static void common_nonsnoop_hash(struct talitos_edesc *edesc,
>
> /* HMAC key */
> if (ctx->keylen)
> - ctx->ptr_ops->to_talitos_ptr(&desc->ptr[2], ctx->dma_key,
> - ctx->keylen);
> + ctx->ptr_ops->to_talitos_ptr(ctx->desc_ops->get_ptr(desc, 2),
> + ctx->dma_key, ctx->keylen);
>
> sg_count = edesc->src_nents ?: 1;
> if (is_sec1 && sg_count > 1)
> @@ -177,8 +182,10 @@ static void common_nonsnoop_hash(struct talitos_edesc *edesc,
> /*
> * data in
> */
> - sg_count = talitos_sg_map(dev, edesc->src, length, edesc, &desc->ptr[3],
> - sg_count, 0, 0);
> + sg_count = talitos_sg_map(dev, edesc->src, length, edesc,
> + ctx->desc_ops->get_ptr(desc, 3), sg_count, 0,
> + 0);
> +
> if (sg_count > 1)
> sync_needed = true;
>
> @@ -186,19 +193,22 @@ static void common_nonsnoop_hash(struct talitos_edesc *edesc,
>
> /* hash/HMAC out -or- hash context out */
> if (edesc->last && req_ctx->last_request)
> - map_single_talitos_ptr(dev, &desc->ptr[5],
> + map_single_talitos_ptr(dev, ctx->desc_ops->get_ptr(desc, 5),
> crypto_ahash_digestsize(tfm),
> req_ctx->hw_context, DMA_FROM_DEVICE);
> else
> - map_single_talitos_ptr_nosync(dev, &desc->ptr[5],
> + map_single_talitos_ptr_nosync(dev,
> + ctx->desc_ops->get_ptr(desc, 5),
> req_ctx->hw_context_size,
> req_ctx->hw_context,
> DMA_FROM_DEVICE);
>
> /* last DWORD empty */
>
> - if (is_sec1 && ctx->ptr_ops->from_talitos_ptr_len(&desc->ptr[3]) == 0)
> - talitos_handle_buggy_hash(ctx, edesc, &desc->ptr[3]);
> + if (is_sec1 && ctx->ptr_ops->from_talitos_ptr_len(
> + ctx->desc_ops->get_ptr(desc, 3)) == 0)
> + talitos_handle_buggy_hash(ctx, edesc,
> + ctx->desc_ops->get_ptr(desc, 3));
>
> if (sync_needed)
> dma_sync_single_for_device(dev, edesc->dma_link_tbl,
> @@ -229,6 +239,7 @@ ahash_process_req_prepare(struct ahash_request *areq, unsigned int nbytes,
> size_t to_hash_this_desc;
> struct scatterlist *src;
> size_t offset = 0;
> + __be32 hdr;
>
> do {
> src = scatterwalk_ffwd(tmp, areq->src, offset);
> @@ -245,19 +256,19 @@ ahash_process_req_prepare(struct ahash_request *areq, unsigned int nbytes,
> }
>
> edesc->src = scatterwalk_ffwd(edesc->bufsl, areq->src, offset);
> - edesc->desc.hdr = ctx->desc_hdr_template;
> + 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;
> + hdr |= DESC_HDR_MODE0_MDEU_PAD;
> else
> - edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_CONT;
> + hdr |= DESC_HDR_MODE0_MDEU_CONT;
>
> /* request SEC to INIT hash. */
> if (req_ctx->first_request && edesc->first && !req_ctx->swinit)
> - edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_INIT;
> + hdr |= DESC_HDR_MODE0_MDEU_INIT;
>
> /*
> * When the tfm context has a keylen, it's an HMAC.
> @@ -265,11 +276,13 @@ ahash_process_req_prepare(struct ahash_request *areq, unsigned int nbytes,
> */
> if (ctx->keylen && ((req_ctx->first_request && edesc->first) ||
> (req_ctx->last_request && edesc->last)))
> - edesc->desc.hdr |= DESC_HDR_MODE0_MDEU_HMAC;
> + hdr |= DESC_HDR_MODE0_MDEU_HMAC;
>
> /* clear the DN bit */
> if (is_sec1 && !edesc->last)
> - edesc->desc.hdr &= ~DESC_HDR_DONE_NOTIFY;
> + hdr &= ~DESC_HDR_DONE_NOTIFY;
> +
> + ctx->desc_ops->set_hdr(&edesc->desc, hdr);
>
> common_nonsnoop_hash(edesc, areq, to_hash_this_desc);
>
> diff --git a/drivers/crypto/talitos/talitos-sec1.c b/drivers/crypto/talitos/talitos-sec1.c
> index ef1bd19b6772..e4f482520372 100644
> --- a/drivers/crypto/talitos/talitos-sec1.c
> +++ b/drivers/crypto/talitos/talitos-sec1.c
> @@ -76,20 +76,20 @@ DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
> static void sec1_to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr,
> unsigned int len)
> {
> - ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr));
> - ptr->len1 = cpu_to_be16(len);
> + ptr->sec1.ptr = cpu_to_be32(lower_32_bits(dma_addr));
> + ptr->sec1.len = cpu_to_be16(len);
> }
>
> static void sec1_copy_talitos_ptr(struct talitos_ptr *dst_ptr,
> struct talitos_ptr *src_ptr)
> {
> - dst_ptr->ptr = src_ptr->ptr;
> - dst_ptr->len1 = src_ptr->len1;
> + dst_ptr->sec1.ptr = src_ptr->sec1.ptr;
> + dst_ptr->sec1.len = src_ptr->sec1.len;
> }
>
> static unsigned short sec1_from_talitos_ptr_len(struct talitos_ptr *ptr)
> {
> - return be16_to_cpu(ptr->len1);
> + return be16_to_cpu(ptr->sec1.len);
> }
>
> static void sec1_to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val)
> @@ -100,6 +100,31 @@ static void sec1_to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val)
> {
> }
>
> +static __be32 sec1_get_ptr_value(struct talitos_ptr *ptr)
> +{
> + return ptr->sec1.ptr;
> +}
> +
> +static __be32 sec1_get_hdr(struct talitos_desc *desc)
> +{
> + return desc->sec1.hdr;
> +}
> +
> +static __be32 sec1_get_hdr_lo(struct talitos_desc *desc)
> +{
> + return 0;
> +}
> +
> +static void sec1_set_hdr(struct talitos_desc *desc, __be32 val)
> +{
> + desc->sec1.hdr = val;
> +}
> +
> +static struct talitos_ptr *sec1_get_ptr(struct talitos_desc *desc, size_t idx)
> +{
> + return (struct talitos_ptr *)&desc->sec1.ptr[idx];
> +}
> +
> static int sec1_reset_device(struct device *dev)
> {
> struct talitos_private *priv = dev_get_drvdata(dev);
> @@ -163,9 +188,8 @@ static void sec1_dma_map_request(struct device *dev,
> struct talitos_edesc *prev_edesc = NULL;
>
> while (edesc) {
> - edesc->desc.hdr1 = edesc->desc.hdr;
>
> - dma_desc = dma_map_single(dev, &edesc->desc.hdr1,
> + dma_desc = dma_map_single(dev, &edesc->desc.sec1.hdr,
> TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
>
> if (!prev_edesc) {
> @@ -175,7 +199,7 @@ static void sec1_dma_map_request(struct device *dev,
>
> /* Chain in any previous descriptors. */
>
> - prev_edesc->desc.next_desc = cpu_to_be32(dma_desc);
> + prev_edesc->desc.sec1.next_desc = cpu_to_be32(dma_desc);
>
> dma_sync_single_for_device(dev, prev_dma_desc,
> TALITOS_DESC_SIZE, DMA_TO_DEVICE);
> @@ -196,7 +220,7 @@ static void sec1_dma_unmap_request(struct device *dev,
> 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),
> + dma_unmap_single(dev, be32_to_cpu(edesc->desc.sec1.next_desc),
> TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
> edesc = edesc->next_desc;
> }
> @@ -211,14 +235,14 @@ static __be32 sec1_get_request_hdr(struct device *dev,
> 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);
> + dma_desc = be32_to_cpu(edesc->desc.sec1.next_desc);
> edesc = edesc->next_desc;
> }
>
> dma_sync_single_for_cpu(dev, dma_desc, TALITOS_DESC_SIZE,
> DMA_BIDIRECTIONAL);
>
> - return edesc->desc.hdr1;
> + return edesc->desc.sec1.hdr;
> }
>
> static __be32 sec1_search_desc_hdr_in_request(struct talitos_request *request,
> @@ -228,12 +252,12 @@ static __be32 sec1_search_desc_hdr_in_request(struct talitos_request *request,
>
>
> if (request->dma_desc == cur_desc)
> - return request->desc->hdr;
> + return request->desc->sec1.hdr;
>
> 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;
> + if (edesc->desc.sec1.next_desc == cpu_to_be32(cur_desc))
> + return edesc->next_desc->desc.sec1.hdr;
> edesc = edesc->next_desc;
> }
>
> @@ -319,6 +343,14 @@ static const struct talitos_ptr_ops sec1_ptr_ops = {
> .from_talitos_ptr_len = sec1_from_talitos_ptr_len,
> .to_talitos_ptr_ext_set = sec1_to_talitos_ptr_ext_set,
> .to_talitos_ptr_ext_or = sec1_to_talitos_ptr_ext_or,
> + .get_ptr_value = sec1_get_ptr_value,
> +};
> +
> +static const struct talitos_desc_ops sec1_desc_ops = {
> + .set_hdr = sec1_set_hdr,
> + .get_hdr = sec1_get_hdr,
> + .get_hdr_lo = sec1_get_hdr_lo,
> + .get_ptr = sec1_get_ptr,
> };
>
> static const struct talitos_ops sec1_ops = {
> @@ -337,5 +369,6 @@ static const struct talitos_ops sec1_ops = {
> void talitos_register_sec1(struct talitos_private *priv)
> {
> priv->ops = &sec1_ops;
> + priv->desc_ops = &sec1_desc_ops;
> priv->ptr_ops = &sec1_ptr_ops;
> }
> diff --git a/drivers/crypto/talitos/talitos-sec2.c b/drivers/crypto/talitos/talitos-sec2.c
> index 14f0ca13e6e5..52f783ddc8b6 100644
> --- a/drivers/crypto/talitos/talitos-sec2.c
> +++ b/drivers/crypto/talitos/talitos-sec2.c
> @@ -82,32 +82,57 @@ DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
> static void sec2_to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr,
> unsigned int len)
> {
> - ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr));
> - ptr->len = cpu_to_be16(len);
> - ptr->eptr = upper_32_bits(dma_addr);
> + ptr->sec2.ptr = cpu_to_be32(lower_32_bits(dma_addr));
> + ptr->sec2.len = cpu_to_be16(len);
> + ptr->sec2.eptr = upper_32_bits(dma_addr);
> }
>
> static void sec2_copy_talitos_ptr(struct talitos_ptr *dst_ptr,
> struct talitos_ptr *src_ptr)
> {
> - dst_ptr->ptr = src_ptr->ptr;
> - dst_ptr->len = src_ptr->len;
> - dst_ptr->eptr = src_ptr->eptr;
> + dst_ptr->sec2.ptr = src_ptr->sec2.ptr;
> + dst_ptr->sec2.len = src_ptr->sec2.len;
> + dst_ptr->sec2.eptr = src_ptr->sec2.eptr;
> }
>
> static unsigned short sec2_from_talitos_ptr_len(struct talitos_ptr *ptr)
> {
> - return be16_to_cpu(ptr->len);
> + return be16_to_cpu(ptr->sec2.len);
> }
>
> static void sec2_to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val)
> {
> - ptr->j_extent = val;
> + ptr->sec2.j_extent = val;
> }
>
> static void sec2_to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val)
> {
> - ptr->j_extent |= val;
> + ptr->sec2.j_extent |= val;
> +}
> +
> +static __be32 sec2_get_ptr_value(struct talitos_ptr *ptr)
> +{
> + return ptr->sec2.ptr;
> +}
> +
> +static __be32 sec2_get_hdr(struct talitos_desc *desc)
> +{
> + return desc->sec2.hdr;
> +}
> +
> +static __be32 sec2_get_hdr_lo(struct talitos_desc *desc)
> +{
> + return desc->sec2.hdr_lo;
> +}
> +
> +static void sec2_set_hdr(struct talitos_desc *desc, __be32 val)
> +{
> + desc->sec2.hdr = val;
> +}
> +
> +static struct talitos_ptr *sec2_get_ptr(struct talitos_desc *desc, size_t idx)
> +{
> + return (struct talitos_ptr *)&desc->sec2.ptr[idx];
> }
>
> static int sec2_reset_channel(struct device *dev, int ch)
> @@ -331,14 +356,14 @@ static __be32 sec2_get_request_hdr(struct device *dev,
> dma_sync_single_for_cpu(dev, request->dma_desc, TALITOS_DESC_SIZE,
> DMA_BIDIRECTIONAL);
>
> - return request->desc->hdr;
> + return request->desc->sec2.hdr;
> }
>
> static __be32 sec2_search_desc_hdr_in_request(struct talitos_request *request,
> dma_addr_t cur_desc)
> {
> if (request->dma_desc == cur_desc)
> - return request->desc->hdr;
> + return request->desc->sec2.hdr;
> return 0;
> }
>
> @@ -348,6 +373,14 @@ static const struct talitos_ptr_ops sec2_ptr_ops = {
> .from_talitos_ptr_len = sec2_from_talitos_ptr_len,
> .to_talitos_ptr_ext_set = sec2_to_talitos_ptr_ext_set,
> .to_talitos_ptr_ext_or = sec2_to_talitos_ptr_ext_or,
> + .get_ptr_value = sec2_get_ptr_value,
> +};
> +
> +static const struct talitos_desc_ops sec2_desc_ops = {
> + .set_hdr = sec2_set_hdr,
> + .get_hdr = sec2_get_hdr,
> + .get_hdr_lo = sec2_get_hdr_lo,
> + .get_ptr = sec2_get_ptr,
> };
>
> static const struct talitos_ops sec2_ops = {
> @@ -366,5 +399,6 @@ static const struct talitos_ops sec2_ops = {
> void talitos_register_sec2(struct talitos_private *priv)
> {
> priv->ops = &sec2_ops;
> + priv->desc_ops = &sec2_desc_ops;
> priv->ptr_ops = &sec2_ptr_ops;
> }
> diff --git a/drivers/crypto/talitos/talitos-skcipher.c b/drivers/crypto/talitos/talitos-skcipher.c
> index a96f827c7b93..58ad931ff3a4 100644
> --- a/drivers/crypto/talitos/talitos-skcipher.c
> +++ b/drivers/crypto/talitos/talitos-skcipher.c
> @@ -11,17 +11,21 @@
>
> #include "talitos.h"
>
> -static void common_nonsnoop_unmap(struct device *dev,
> +static void common_nonsnoop_unmap(struct talitos_ctx *ctx,
> struct talitos_edesc *edesc,
> struct skcipher_request *areq)
> {
> - unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
> + unmap_single_talitos_ptr(ctx->dev,
> + ctx->desc_ops->get_ptr(&edesc->desc, 5),
> + DMA_FROM_DEVICE);
>
> - talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen, 0);
> - unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
> + talitos_sg_unmap(ctx->dev, edesc, areq->src, areq->dst, areq->cryptlen, 0);
> + unmap_single_talitos_ptr(ctx->dev,
> + ctx->desc_ops->get_ptr(&edesc->desc, 1),
> + DMA_TO_DEVICE);
>
> if (edesc->dma_len)
> - dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
> + dma_unmap_single(ctx->dev, edesc->dma_link_tbl, edesc->dma_len,
> DMA_BIDIRECTIONAL);
> }
>
> @@ -37,7 +41,7 @@ static void skcipher_done(struct device *dev,
>
> edesc = container_of(desc, struct talitos_edesc, desc);
>
> - common_nonsnoop_unmap(dev, edesc, areq);
> + common_nonsnoop_unmap(ctx, edesc, areq);
> memcpy(areq->iv, ctx->iv, ivsize);
>
> kfree(edesc);
> @@ -61,16 +65,18 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
> bool sync_needed = false;
> struct talitos_private *priv = dev_get_drvdata(dev);
> bool is_sec1 = has_ftr_sec1(priv);
> - bool is_ctr = (desc->hdr & DESC_HDR_SEL0_MASK) == DESC_HDR_SEL0_AESU &&
> - (desc->hdr & DESC_HDR_MODE0_AESU_MASK) == DESC_HDR_MODE0_AESU_CTR;
> + bool is_ctr = (ctx->desc_ops->get_hdr(desc) & DESC_HDR_SEL0_MASK) ==
> + DESC_HDR_SEL0_AESU &&
> + (ctx->desc_ops->get_hdr(desc) &
> + DESC_HDR_MODE0_AESU_MASK) == DESC_HDR_MODE0_AESU_CTR;
>
> /* first DWORD empty */
>
> /* cipher iv */
> - ctx->ptr_ops->to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, ivsize);
> + ctx->ptr_ops->to_talitos_ptr(ctx->desc_ops->get_ptr(desc, 1), edesc->iv_dma, ivsize);
>
> /* cipher key */
> - ctx->ptr_ops->to_talitos_ptr(&desc->ptr[2], ctx->dma_key, ctx->keylen);
> + ctx->ptr_ops->to_talitos_ptr(ctx->desc_ops->get_ptr(desc, 2), ctx->dma_key, ctx->keylen);
>
> sg_count = edesc->src_nents ?: 1;
> if (is_sec1 && sg_count > 1)
> @@ -83,8 +89,9 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
> /*
> * cipher in
> */
> - sg_count = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[3],
> - sg_count, 0, 0, 0, false, is_ctr ? 16 : 1);
> + sg_count = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc,
> + ctx->desc_ops->get_ptr(desc, 3), sg_count,
> + 0, 0, 0, false, is_ctr ? 16 : 1);
> if (sg_count > 1)
> sync_needed = true;
>
> @@ -95,14 +102,15 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
> dma_map_sg(dev, areq->dst, sg_count, DMA_FROM_DEVICE);
> }
>
> - ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc, &desc->ptr[4],
> - sg_count, 0, (edesc->src_nents + 1));
> + ret = talitos_sg_map(dev, areq->dst, cryptlen, edesc,
> + ctx->desc_ops->get_ptr(desc, 4), sg_count, 0,
> + (edesc->src_nents + 1));
> if (ret > 1)
> sync_needed = true;
>
> /* iv out */
> - map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv,
> - DMA_FROM_DEVICE);
> + map_single_talitos_ptr(dev, ctx->desc_ops->get_ptr(desc, 5), ivsize,
> + ctx->iv, DMA_FROM_DEVICE);
>
> /* last DWORD empty */
>
> @@ -112,7 +120,7 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
>
> ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
> if (ret != -EINPROGRESS) {
> - common_nonsnoop_unmap(dev, edesc, areq);
> + common_nonsnoop_unmap(ctx, edesc, areq);
> kfree(edesc);
> }
> return ret;
> @@ -191,7 +199,7 @@ static int skcipher_encrypt(struct skcipher_request *areq)
> return PTR_ERR(edesc);
>
> /* set encrypt */
> - edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
> + ctx->desc_ops->set_hdr(&edesc->desc, ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT);
>
> return common_nonsnoop(edesc, areq, skcipher_done);
> }
> @@ -215,7 +223,7 @@ static int skcipher_decrypt(struct skcipher_request *areq)
> if (IS_ERR(edesc))
> return PTR_ERR(edesc);
>
> - edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
> + ctx->desc_ops->set_hdr(&edesc->desc, ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND);
>
> return common_nonsnoop(edesc, areq, skcipher_done);
> }
> diff --git a/drivers/crypto/talitos/talitos.c b/drivers/crypto/talitos/talitos.c
> index 19e63ce6cc3e..a032907e900f 100644
> --- a/drivers/crypto/talitos/talitos.c
> +++ b/drivers/crypto/talitos/talitos.c
> @@ -81,7 +81,7 @@ void unmap_single_talitos_ptr(struct device *dev,
> {
> struct talitos_private *priv = dev_get_drvdata(dev);
>
> - dma_unmap_single(dev, be32_to_cpu(ptr->ptr),
> + dma_unmap_single(dev, be32_to_cpu(priv->ptr_ops->get_ptr_value(ptr)),
> priv->ptr_ops->from_talitos_ptr_len(ptr), dir);
> }
>
> @@ -625,6 +625,8 @@ int talitos_init_common(struct talitos_ctx *ctx,
>
> ctx->ptr_ops = priv->ptr_ops;
>
> + ctx->desc_ops = priv->desc_ops;
> +
> return 0;
> }
>
> diff --git a/drivers/crypto/talitos/talitos.h b/drivers/crypto/talitos/talitos.h
> index 54e33da03fd0..2107fb1ade5d 100644
> --- a/drivers/crypto/talitos/talitos.h
> +++ b/drivers/crypto/talitos/talitos.h
> @@ -36,33 +36,49 @@
> #define TALITOS_MAX_IV_LENGTH 16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
>
> /* descriptor pointer entry */
> +
> +struct sec1_talitos_ptr {
> + __be16 res;
> + __be16 len;
> + __be32 ptr;
> +} __packed;
> +
> +struct sec2_talitos_ptr {
> + __be16 len;
> + u8 j_extent;
> + u8 eptr;
> + __be32 ptr;
> +} __packed;
> +
> struct talitos_ptr {
> union {
> - struct { /* SEC2 format */
> - __be16 len; /* length */
> - u8 j_extent; /* jump to sg link table and/or extent*/
> - u8 eptr; /* extended address */
> - };
> - struct { /* SEC1 format */
> - __be16 res;
> - __be16 len1; /* length */
> - };
> + struct sec1_talitos_ptr sec1;
> + struct sec2_talitos_ptr sec2;
> };
> - __be32 ptr; /* address */
> };
>
> -/* descriptor */
> +/* descriptor format */
> +
> +struct sec1_talitos_desc {
> + __be32 hdr;
> + struct sec1_talitos_ptr ptr[7];
> + __be32 next_desc;
> +} __packed;
> +
> +struct sec2_talitos_desc {
> + __be32 hdr;
> + __be32 hdr_lo;
> + struct sec2_talitos_ptr ptr[7];
> +} __packed;
> +
> struct talitos_desc {
> - __be32 hdr; /* header high bits */
> union {
> - __be32 hdr_lo; /* header low bits */
> - __be32 hdr1; /* header for SEC1 */
> + struct sec1_talitos_desc sec1;
> + struct sec2_talitos_desc sec2;
> };
> - struct talitos_ptr ptr[7]; /* ptr/len pair array */
> - __be32 next_desc; /* next descriptor (SEC1) */
> };
>
> -#define TALITOS_DESC_SIZE (sizeof(struct talitos_desc) - sizeof(__be32))
> +#define TALITOS_DESC_SIZE sizeof(struct talitos_desc)
>
> /*
> * talitos_edesc - s/w-extended descriptor
> @@ -148,6 +164,14 @@ struct talitos_ptr_ops {
> unsigned short (*from_talitos_ptr_len)(struct talitos_ptr *ptr);
> void (*to_talitos_ptr_ext_set)(struct talitos_ptr *ptr, u8 val);
> void (*to_talitos_ptr_ext_or)(struct talitos_ptr *ptr, u8 val);
> + __be32 (*get_ptr_value)(struct talitos_ptr *ptr);
> +};
> +
> +struct talitos_desc_ops {
> + void (*set_hdr)(struct talitos_desc *desc, __be32 val);
> + __be32 (*get_hdr)(struct talitos_desc *desc);
> + __be32 (*get_hdr_lo)(struct talitos_desc *desc);
> + struct talitos_ptr *(*get_ptr)(struct talitos_desc *desc, size_t idx);
> };
>
> struct talitos_ops {
> @@ -194,6 +218,7 @@ struct talitos_private {
>
> const struct talitos_ops *ops;
> const struct talitos_ptr_ops *ptr_ops;
> + const struct talitos_desc_ops *desc_ops;
>
> /* SEC Compatibility info */
> unsigned long features;
> @@ -225,6 +250,7 @@ struct talitos_private {
> struct talitos_ctx {
> struct device *dev;
> const struct talitos_ptr_ops *ptr_ops;
> + const struct talitos_desc_ops *desc_ops;
> int ch;
> __be32 desc_hdr_template;
> u8 key[TALITOS_MAX_KEY_SIZE];
>
^ permalink raw reply
* Re: [PATCH 24/29] crypto: talitos - Introduce per-SEC-version pointer helper ops
From: Christophe Leroy (CS GROUP) @ 2026-06-04 9:48 UTC (permalink / raw)
To: Paul Louvel, Herbert Xu, David S. Miller
Cc: Thomas Petazzoni, Herve Codina, linux-crypto, linux-kernel
In-Reply-To: <20260528-7-1-rc1_talitos_cleanup-v1-24-cb1ad6cdea49@bootlin.com>
Le 28/05/2026 à 11:08, Paul Louvel a écrit :
> Introduce struct talitos_ptr_ops to abstract SEC1/SEC2 differences
> in pointer handling behind per-SEC-version ops. Add ptr_ops to
> struct talitos_private and struct talitos_ctx, and register the
> appropriate SEC1 or SEC2 implementation at probe time.
Those helpers are so small they deserve being inlined not called
indirectly. You should reconsider them using the is_sec1() helper I
proposed on patch 20.
00000000 <sec1_to_talitos_ptr>:
0: 90 83 00 04 stw r4,4(r3)
4: b0 a3 00 02 sth r5,2(r3)
8: 4e 80 00 20 blr
0000000c <sec1_copy_talitos_ptr>:
c: 81 24 00 04 lwz r9,4(r4)
10: 91 23 00 04 stw r9,4(r3)
14: a1 24 00 02 lhz r9,2(r4)
18: b1 23 00 02 sth r9,2(r3)
1c: 4e 80 00 20 blr
00000020 <sec1_from_talitos_ptr_len>:
20: a0 63 00 02 lhz r3,2(r3)
24: 4e 80 00 20 blr
00000028 <sec1_to_talitos_ptr_ext_set>:
28: 4e 80 00 20 blr
0000002c <sec1_get_ptr_value>:
2c: 80 63 00 04 lwz r3,4(r3)
30: 4e 80 00 20 blr
00000034 <sec1_get_hdr>:
34: 80 63 00 00 lwz r3,0(r3)
38: 4e 80 00 20 blr
0000003c <sec1_get_hdr_lo>:
3c: 38 60 00 00 li r3,0
40: 4e 80 00 20 blr
00000044 <sec1_set_hdr>:
44: 90 83 00 00 stw r4,0(r3)
48: 4e 80 00 20 blr
0000004c <sec1_get_ptr>:
4c: 54 84 18 38 slwi r4,r4,3
50: 38 84 00 04 addi r4,r4,4
54: 7c 63 22 14 add r3,r3,r4
58: 4e 80 00 20 blr
00000be8 <sec1_to_talitos_ptr_ext_or>:
be8: 4e 80 00 20 blr
>
> Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
> ---
> drivers/crypto/talitos/talitos-sec1.c | 36 +++++++++++++++++++++++++++++++
> drivers/crypto/talitos/talitos-sec2.c | 40 +++++++++++++++++++++++++++++++++++
> drivers/crypto/talitos/talitos.c | 2 ++
> drivers/crypto/talitos/talitos.h | 12 +++++++++++
> 4 files changed, 90 insertions(+)
>
> diff --git a/drivers/crypto/talitos/talitos-sec1.c b/drivers/crypto/talitos/talitos-sec1.c
> index 695d531aa7f4..ef1bd19b6772 100644
> --- a/drivers/crypto/talitos/talitos-sec1.c
> +++ b/drivers/crypto/talitos/talitos-sec1.c
> @@ -73,6 +73,33 @@ static irqreturn_t talitos1_interrupt_##name(int irq, void *data) \
>
> DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
>
> +static void sec1_to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr,
> + unsigned int len)
> +{
> + ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr));
> + ptr->len1 = cpu_to_be16(len);
> +}
> +
> +static void sec1_copy_talitos_ptr(struct talitos_ptr *dst_ptr,
> + struct talitos_ptr *src_ptr)
> +{
> + dst_ptr->ptr = src_ptr->ptr;
> + dst_ptr->len1 = src_ptr->len1;
> +}
> +
> +static unsigned short sec1_from_talitos_ptr_len(struct talitos_ptr *ptr)
> +{
> + return be16_to_cpu(ptr->len1);
> +}
> +
> +static void sec1_to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val)
> +{
> +}
> +
> +static void sec1_to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val)
> +{
> +}
> +
> static int sec1_reset_device(struct device *dev)
> {
> struct talitos_private *priv = dev_get_drvdata(dev);
> @@ -286,6 +313,14 @@ static void sec1_init_task(struct device *dev)
> (unsigned long)dev);
> }
>
> +static const struct talitos_ptr_ops sec1_ptr_ops = {
> + .to_talitos_ptr = sec1_to_talitos_ptr,
> + .copy_talitos_ptr = sec1_copy_talitos_ptr,
> + .from_talitos_ptr_len = sec1_from_talitos_ptr_len,
> + .to_talitos_ptr_ext_set = sec1_to_talitos_ptr_ext_set,
> + .to_talitos_ptr_ext_or = sec1_to_talitos_ptr_ext_or,
> +};
> +
> static const struct talitos_ops sec1_ops = {
> .probe_irq = sec1_talitos_probe_irq,
> .init_task = sec1_init_task,
> @@ -302,4 +337,5 @@ static const struct talitos_ops sec1_ops = {
> void talitos_register_sec1(struct talitos_private *priv)
> {
> priv->ops = &sec1_ops;
> + priv->ptr_ops = &sec1_ptr_ops;
> }
> diff --git a/drivers/crypto/talitos/talitos-sec2.c b/drivers/crypto/talitos/talitos-sec2.c
> index 962e7cd43631..14f0ca13e6e5 100644
> --- a/drivers/crypto/talitos/talitos-sec2.c
> +++ b/drivers/crypto/talitos/talitos-sec2.c
> @@ -79,6 +79,37 @@ DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE)
> DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
> DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
>
> +static void sec2_to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr,
> + unsigned int len)
> +{
> + ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr));
> + ptr->len = cpu_to_be16(len);
> + ptr->eptr = upper_32_bits(dma_addr);
> +}
> +
> +static void sec2_copy_talitos_ptr(struct talitos_ptr *dst_ptr,
> + struct talitos_ptr *src_ptr)
> +{
> + dst_ptr->ptr = src_ptr->ptr;
> + dst_ptr->len = src_ptr->len;
> + dst_ptr->eptr = src_ptr->eptr;
> +}
> +
> +static unsigned short sec2_from_talitos_ptr_len(struct talitos_ptr *ptr)
> +{
> + return be16_to_cpu(ptr->len);
> +}
> +
> +static void sec2_to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val)
> +{
> + ptr->j_extent = val;
> +}
> +
> +static void sec2_to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val)
> +{
> + ptr->j_extent |= val;
> +}
> +
> static int sec2_reset_channel(struct device *dev, int ch)
> {
> struct talitos_private *priv = dev_get_drvdata(dev);
> @@ -311,6 +342,14 @@ static __be32 sec2_search_desc_hdr_in_request(struct talitos_request *request,
> return 0;
> }
>
> +static const struct talitos_ptr_ops sec2_ptr_ops = {
> + .to_talitos_ptr = sec2_to_talitos_ptr,
> + .copy_talitos_ptr = sec2_copy_talitos_ptr,
> + .from_talitos_ptr_len = sec2_from_talitos_ptr_len,
> + .to_talitos_ptr_ext_set = sec2_to_talitos_ptr_ext_set,
> + .to_talitos_ptr_ext_or = sec2_to_talitos_ptr_ext_or,
> +};
> +
> static const struct talitos_ops sec2_ops = {
> .probe_irq = sec2_talitos_probe_irq,
> .init_task = sec2_init_task,
> @@ -327,4 +366,5 @@ static const struct talitos_ops sec2_ops = {
> void talitos_register_sec2(struct talitos_private *priv)
> {
> priv->ops = &sec2_ops;
> + priv->ptr_ops = &sec2_ptr_ops;
> }
> diff --git a/drivers/crypto/talitos/talitos.c b/drivers/crypto/talitos/talitos.c
> index 152618998819..0e4bd130ac6d 100644
> --- a/drivers/crypto/talitos/talitos.c
> +++ b/drivers/crypto/talitos/talitos.c
> @@ -668,6 +668,8 @@ int talitos_init_common(struct talitos_ctx *ctx,
> /* select done notification */
> ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
>
> + ctx->ptr_ops = priv->ptr_ops;
> +
> return 0;
> }
>
> diff --git a/drivers/crypto/talitos/talitos.h b/drivers/crypto/talitos/talitos.h
> index ae0bdb2ea78e..09d4e8fb0e62 100644
> --- a/drivers/crypto/talitos/talitos.h
> +++ b/drivers/crypto/talitos/talitos.h
> @@ -140,6 +140,16 @@ struct talitos_channel {
> int tail;
> };
>
> +struct talitos_ptr_ops {
> + void (*to_talitos_ptr)(struct talitos_ptr *ptr, dma_addr_t addr,
> + unsigned int len);
> + void (*copy_talitos_ptr)(struct talitos_ptr *dst_ptr,
> + struct talitos_ptr *src_ptr);
> + unsigned short (*from_talitos_ptr_len)(struct talitos_ptr *ptr);
> + void (*to_talitos_ptr_ext_set)(struct talitos_ptr *ptr, u8 val);
> + void (*to_talitos_ptr_ext_or)(struct talitos_ptr *ptr, u8 val);
> +};
> +
> struct talitos_ops {
> int (*probe_irq)(struct platform_device *ofdev);
> void (*init_task)(struct device *dev);
> @@ -183,6 +193,7 @@ struct talitos_private {
> unsigned int desc_types;
>
> const struct talitos_ops *ops;
> + const struct talitos_ptr_ops *ptr_ops;
>
> /* SEC Compatibility info */
> unsigned long features;
> @@ -213,6 +224,7 @@ struct talitos_private {
>
> struct talitos_ctx {
> struct device *dev;
> + const struct talitos_ptr_ops *ptr_ops;
> int ch;
> __be32 desc_hdr_template;
> u8 key[TALITOS_MAX_KEY_SIZE];
>
^ permalink raw reply
* Re: [PATCH 20/29] crypto: talitos - Replace SEC1/SEC2 conditionals with ops dispatch
From: Christophe Leroy (CS GROUP) @ 2026-06-04 9:37 UTC (permalink / raw)
To: Paul Louvel, Herbert Xu, David S. Miller
Cc: Thomas Petazzoni, Herve Codina, linux-crypto, linux-kernel
In-Reply-To: <20260528-7-1-rc1_talitos_cleanup-v1-20-cb1ad6cdea49@bootlin.com>
Le 28/05/2026 à 11:08, Paul Louvel a écrit :
> Replace the if/else is_sec1 dispatches in callers with indirect calls
> through priv->ops. Add static const sec1_ops and sec2_ops structs
> populated with the SEC1 and SEC2 function variants, and set priv->ops
> at probe time based on the detected hardware.
Why is that needed ?
I understand your objective at the end is to get rid of that is_sec1
boolean that is carried over the entire call chain but using ops for
that seems overkill.
What about changing it to a helper using static branches, something like
(untested) :
#if defined(CONFIG_CRYPTO_DEV_TALITOS1) &&
defined(CONFIG_CRYPTO_DEV_TALITOS2)
DECLARE_STATIC_KEY_FALSE(talitos_is_sec1);
static __always_inline bool is_sec1(void)
{
return static_branch_unlikely(&talitos_is_sec1);
}
static inline void talitos_init_branch(bool is_sec1)
{
if (is_sec1)
static_branch_enable(&talitos_is_sec1);
}
#else
static __always_inline bool is_sec1(void)
{
return IS_ENABLED(CONFIG_CRYPTO_DEV_TALITOS1);
}
static inline void talitos_init_branch(bool is_sec1)
{
BUILD_BUG_ON(is_sec1 && !IS_ENABLED(CONFIG_CRYPTO_DEV_TALITOS1));
}
#endif
>
>
> Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
> ---
> drivers/crypto/talitos/talitos.c | 88 +++++++++++++++++++---------------------
> 1 file changed, 41 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/crypto/talitos/talitos.c b/drivers/crypto/talitos/talitos.c
> index b6793d97735e..c4a311a8e7fd 100644
> --- a/drivers/crypto/talitos/talitos.c
> +++ b/drivers/crypto/talitos/talitos.c
> @@ -258,7 +258,6 @@ static int init_device(struct device *dev)
> {
> struct talitos_private *priv = dev_get_drvdata(dev);
> int ch, err;
> - bool is_sec1 = has_ftr_sec1(priv);
>
> /*
> * Master reset
> @@ -266,35 +265,23 @@ static int init_device(struct device *dev)
> * are not fully cleared by writing the MCR:SWR bit,
> * set bit twice to completely reset
> */
> - if (is_sec1)
> - err = sec1_reset_device(dev);
> - else
> - err = sec2_reset_device(dev);
> + err = priv->ops->reset_device(dev);
>
> if (err)
> return err;
>
> - if (is_sec1)
> - err = sec1_reset_device(dev);
> - else
> - err = sec2_reset_device(dev);
> + err = priv->ops->reset_device(dev);
> if (err)
> return err;
>
> /* reset channels */
> for (ch = 0; ch < priv->num_channels; ch++) {
> - if (is_sec1)
> - err = sec1_reset_channel(dev, ch);
> - else
> - err = sec2_reset_channel(dev, ch);
> + err = priv->ops->reset_channel(dev, ch);
> if (err)
> return err;
> }
>
> - if (is_sec1)
> - sec1_configure_device(dev);
> - else
> - sec2_configure_device(dev);
> + priv->ops->configure_device(dev);
>
> return 0;
> }
> @@ -363,7 +350,6 @@ int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
> struct talitos_request *request;
> unsigned long flags;
> int head;
> - bool is_sec1 = has_ftr_sec1(priv);
>
> spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
>
> @@ -377,10 +363,8 @@ int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
> request = &priv->chan[ch].fifo[head];
>
> /* map descriptor and save caller data */
> - if (is_sec1)
> - sec1_dma_map_request(dev, request, desc);
> - else
> - sec2_dma_map_request(dev, request, desc);
> + priv->ops->dma_map_request(dev, request, desc);
> +
> request->callback = callback;
> request->context = context;
>
> @@ -461,7 +445,6 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
> struct talitos_request *request, saved_req;
> unsigned long flags;
> int tail, status;
> - bool is_sec1 = has_ftr_sec1(priv);
>
> spin_lock_irqsave(&priv->chan[ch].tail_lock, flags);
>
> @@ -473,10 +456,7 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
>
> /* descriptors with their done bits set don't get the error */
> rmb();
> - if (is_sec1)
> - hdr = sec1_get_request_hdr(dev, request);
> - else
> - hdr = sec2_get_request_hdr(dev, request);
> + hdr = priv->ops->get_request_hdr(dev, request);
>
> if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
> status = 0;
> @@ -486,10 +466,7 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
> else
> status = error;
>
> - if (is_sec1)
> - sec1_dma_unmap_request(dev, request);
> - else
> - sec2_dma_unmap_request(dev, request);
> + priv->ops->dma_unmap_request(dev, request);
>
> /* copy entries so we can call callback outside lock */
> saved_req.desc = request->desc;
> @@ -611,7 +588,6 @@ static __be32 sec2_search_desc_hdr_in_request(struct talitos_request *request,
> 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;
> int tail, iter;
> dma_addr_t cur_desc;
> @@ -630,10 +606,7 @@ static __be32 current_desc_hdr(struct device *dev, int ch)
> do {
> request = &priv->chan[ch].fifo[iter];
>
> - if (is_sec1)
> - hdr = sec1_search_desc_hdr_in_request(request, cur_desc);
> - else
> - hdr = sec2_search_desc_hdr_in_request(request, cur_desc);
> + hdr = priv->ops->search_desc_hdr_in_request(request, cur_desc);
> if (hdr)
> break;
>
> @@ -833,13 +806,9 @@ static int sec2_talitos_handle_error(struct device *dev, u32 isr, u32 isr_lo)
> static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
> {
> struct talitos_private *priv = dev_get_drvdata(dev);
> - bool is_sec1 = has_ftr_sec1(priv);
> int ch, reset_dev;
>
> - if (is_sec1)
> - reset_dev = sec1_talitos_handle_error(dev, isr, isr_lo);
> - else
> - reset_dev = sec2_talitos_handle_error(dev, isr, isr_lo);
> + reset_dev = priv->ops->handle_error(dev, isr, isr_lo);
>
> if (reset_dev) {
> dev_err(dev,
> @@ -1391,6 +1360,32 @@ static void sec2_init_task(struct device *dev)
> }
> }
>
> +static const struct talitos_ops sec1_ops = {
> + .probe_irq = sec1_talitos_probe_irq,
> + .init_task = sec1_init_task,
> + .reset_device = sec1_reset_device,
> + .reset_channel = sec1_reset_channel,
> + .configure_device = sec1_configure_device,
> + .dma_map_request = sec1_dma_map_request,
> + .dma_unmap_request = sec1_dma_unmap_request,
> + .get_request_hdr = sec1_get_request_hdr,
> + .search_desc_hdr_in_request = sec1_search_desc_hdr_in_request,
> + .handle_error = sec1_talitos_handle_error,
> +};
> +
> +static const struct talitos_ops sec2_ops = {
> + .probe_irq = sec2_talitos_probe_irq,
> + .init_task = sec2_init_task,
> + .reset_device = sec2_reset_device,
> + .reset_channel = sec2_reset_channel,
> + .configure_device = sec2_configure_device,
> + .dma_map_request = sec2_dma_map_request,
> + .dma_unmap_request = sec2_dma_unmap_request,
> + .get_request_hdr = sec2_get_request_hdr,
> + .search_desc_hdr_in_request = sec2_search_desc_hdr_in_request,
> + .handle_error = sec2_talitos_handle_error,
> +};
> +
> static int talitos_probe(struct platform_device *ofdev)
> {
> struct device *dev = &ofdev->dev;
> @@ -1474,16 +1469,15 @@ static int talitos_probe(struct platform_device *ofdev)
> }
>
> if (has_ftr_sec1(priv))
> - err = sec1_talitos_probe_irq(ofdev);
> + priv->ops = &sec1_ops;
> else
> - err = sec2_talitos_probe_irq(ofdev);
> + priv->ops = &sec2_ops;
> +
> + err = priv->ops->probe_irq(ofdev);
> if (err)
> goto err_out;
>
> - if (has_ftr_sec1(priv))
> - sec1_init_task(dev);
> - else
> - sec2_init_task(dev);
> + priv->ops->init_task(dev);
>
> priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
>
>
^ permalink raw reply
* Re: [PATCH 1/1] crypto: atmel-ecc - fix use after free situation
From: Lothar Rubusch @ 2026-06-04 7:56 UTC (permalink / raw)
To: Thorsten Blum
Cc: herbert, davem, nicolas.ferre, alexandre.belloni, claudiu.beznea,
tudor.ambarus, krzk+dt, linux-crypto, linux-arm-kernel,
linux-kernel
In-Reply-To: <ah381bcuVfN8PQr0@linux.dev>
Hi Thorsten, thanks for the feedback. Pls, find my comment down below.
On Mon, Jun 1, 2026 at 11:42 PM Thorsten Blum <thorsten.blum@linux.dev> wrote:
>
> On Fri, May 29, 2026 at 09:27:03AM +0000, Lothar Rubusch wrote:
> > Fixes a possible race condition, when having multiple of such devices
> > attached (identified by sashiko feedback).
> >
> > The Scenario:
> > Thread A (Device 1 Probe): Successfully adds i2c_priv to the global
> > list (Line 324). The lock is released.
> > Thread B (An active crypto request): Concurrently calls
> > atmel_ecc_i2c_client_alloc(). It scans the global list, sees
> > Device 1, and assigns a crypto job to it.
> > Thread A: Moves to line 332. crypto_register_kpp() fails (e.g., out of
> > memory or name clash).
> > Thread A: Enters the error path. It removes Device 1 from the list and
> > frees the i2c_priv memory.
> > Thread B: Is still actively trying to talk to the I2C hardware using
> > the i2c_priv pointer it grabbed in Step 2. The memory is now
> > gone. Result: Kernel crash (Use-After-Free).
> >
> > Fixes: 11105693fa05 ("crypto: atmel-ecc - introduce Microchip / Atmel ECC driver")
> > Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
> > ---
> > drivers/crypto/atmel-ecc.c | 10 ++++++++++
> > drivers/crypto/atmel-i2c.h | 2 ++
> > 2 files changed, 12 insertions(+)
> >
> > diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
> > index 0ca02995a1de..d391fe1462f6 100644
> > --- a/drivers/crypto/atmel-ecc.c
> > +++ b/drivers/crypto/atmel-ecc.c
> > @@ -218,6 +218,8 @@ static struct i2c_client *atmel_ecc_i2c_client_alloc(void)
> >
> > list_for_each_entry(i2c_priv, &driver_data.i2c_client_list,
> > i2c_client_list_node) {
> > + if (!i2c_priv->ready)
> > + continue;
> > tfm_cnt = atomic_read(&i2c_priv->tfm_count);
> > if (tfm_cnt < min_tfm_cnt) {
> > min_tfm_cnt = tfm_cnt;
> > @@ -322,20 +324,24 @@ static int atmel_ecc_probe(struct i2c_client *client)
> > return ret;
> >
> > i2c_priv = i2c_get_clientdata(client);
> > + i2c_priv->ready = false;
> >
> > spin_lock(&driver_data.i2c_list_lock);
> > list_add_tail(&i2c_priv->i2c_client_list_node,
> > &driver_data.i2c_client_list);
> > + i2c_priv->ready = true;
> > spin_unlock(&driver_data.i2c_list_lock);
> >
> > ret = crypto_register_kpp(&atmel_ecdh_nist_p256);
> > if (ret) {
> > spin_lock(&driver_data.i2c_list_lock);
> > + i2c_priv->ready = false;
> > list_del(&i2c_priv->i2c_client_list_node);
> > spin_unlock(&driver_data.i2c_list_lock);
> >
> > dev_err(&client->dev, "%s alg registration failed\n",
> > atmel_ecdh_nist_p256.base.cra_driver_name);
> > + return ret;
> > } else {
> > dev_info(&client->dev, "atmel ecc algorithms registered in /proc/crypto\n");
> > }
> > @@ -347,6 +353,10 @@ static void atmel_ecc_remove(struct i2c_client *client)
> > {
> > struct atmel_i2c_client_priv *i2c_priv = i2c_get_clientdata(client);
> >
> > + spin_lock(&driver_data.i2c_list_lock);
> > + i2c_priv->ready = false;
> > + spin_unlock(&driver_data.i2c_list_lock);
> > +
> > /* Return EBUSY if i2c client already allocated. */
> > if (atomic_read(&i2c_priv->tfm_count)) {
> > /*
> > diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h
> > index 72f04c15682f..e3b12030f9c4 100644
> > --- a/drivers/crypto/atmel-i2c.h
> > +++ b/drivers/crypto/atmel-i2c.h
> > @@ -129,6 +129,7 @@ struct atmel_ecc_driver_data {
> > * @wake_token_sz : size in bytes of the wake_token
> > * @tfm_count : number of active crypto transformations on i2c client
> > * @hwrng : hold the hardware generated rng
> > + * @ready : hw client is ready to use
> > *
> > * Reads and writes from/to the i2c client are sequential. The first byte
> > * transmitted to the device is treated as the byte size. Any attempt to send
> > @@ -145,6 +146,7 @@ struct atmel_i2c_client_priv {
> > size_t wake_token_sz;
> > atomic_t tfm_count ____cacheline_aligned;
> > struct hwrng hwrng;
> > + bool ready;
> > };
>
> I don't think the ready flag fixes the race. A concurrent tfm can still
> bind to the shared I2C client after atmel_ecc_probe() adds it to the
> global list and marks it as ready, but before crypto_register_kpp()
> fails.
Argh... I see your point. The "ready" now is transparent to the
i2c_client_list usage and serves for nothing, that's nonsense. Going
some overengineering-steps back, my original idea (to satisfy a
sashiko complaint), in my own words:
Thread A:
1. probe()
V
2. probe(): add i2c_priv to i2c_client_list <-------------- Thread B requests
V
3. probe(): registers kpp
V
4. probe(): say, register kpp fails
V
5. probe(): remove i2c_priv from i2c_client_list <-----
Thread B:
Now if a crypto request/TFM comes in (thread B) and requests a client
from the i2c_client_list.
(Note, this is a case where the device must be, say, the second such
device so that kpp is already registered for any atmel driver).
If this happens before step 2 or after step 5, it's fine. This
instance is still not on the list. If it happens at step 2 through
step 4 this is problematic. A i2c_priv could be returned which is
actually (still) not ready. In the meanwhile i2c_priv will be removed,
but the TFM continues refering to this instance.
Question:
- Do you see the issue here, too? Or, is my understanding wrong? Can
this be problematic / lead to UAF?
- If true, my first idea was to set a "ready" state initially to
false, after kpp registered successfully, set it to true. The flag is
checked then, as in this patch. Then I probably messed it up. So,
could this approach solve the situation?
If you not answer I'll present this in the next days.
Best,
L
>
> Thanks,
> Thorsten
^ permalink raw reply
* Re: [PATCH 10/12] crypto: atmel - update workqueue flags and add flush on exit
From: Lothar Rubusch @ 2026-06-04 7:22 UTC (permalink / raw)
To: Marco Crivellari
Cc: alexandre.belloni, claudiu.beznea, davem, herbert,
linux-arm-kernel, linux-crypto, linux-kernel, nicolas.ferre,
thorsten.blum
In-Reply-To: <20260601090329.52616-1-marco.crivellari@suse.com>
Hi Marco,
On Mon, Jun 1, 2026 at 11:03 AM Marco Crivellari
<marco.crivellari@suse.com> wrote:
>
> Hi,
>
> > Update workqueue initialization to use WQ_MEM_RECLAIM instead of
> > WQ_PERCPU
>
> Not sure if you're working on this series right now, but this must keep
> the WQ_PERCPU flag. WQ_PERCPU has been added to mark explicitly mark
> workqueue that are per-CPU (it is the complement of WQ_UNBOUND).
>
Yes. I plan on splitting up the material presented in this series.
This particular patch was one of the things I was a unsure, if this
actually could be done.
Therefore it was already separted out. I highly appreciate your
feedback. I will drop this
change and leave WQ_PERCPU until I get there.
>
> Thanks!
>
^ permalink raw reply
* Re: [PATCH 3/4] crypto: qcom-rng - Remove crypto_rng interface
From: Eric Biggers @ 2026-06-04 5:42 UTC (permalink / raw)
To: Neeraj Soni
Cc: linux-crypto, linux-kernel, Om Prakash Singh, Bjorn Andersson,
Neil Armstrong, linux-arm-msm, Olivia Mackall, stable
In-Reply-To: <021127c9-baff-816d-e053-897a7d4043d8@oss.qualcomm.com>
On Thu, Jun 04, 2026 at 10:20:38AM +0530, Neeraj Soni wrote:
> On 5/30/2026 7:33 AM, Eric Biggers wrote:
> > qcom-rng.c exposes the same hardware through two completely separate
> > interfaces, crypto_rng and hwrng. However, the implementation of this
> > is buggy because it permits generation operations from these interfaces
> > to run concurrently with each other, accessing the same registers. That
> > is, qcom_rng_generate() synchronizes with itself but not with
> > qcom_hwrng_read(). This results in potential repetition of output from
> > the RNG, output of non-random values, etc.
> >
> > Fortunately, there's actually no point in hardware RNG drivers
> > implementing the crypto_rng interface. It's not actually used by
> > anything besides the "rng" algorithm type of AF_ALG, which in turn is
> > not actually used in practice. Other crypto_rng hardware drivers are
>
> How it was established that there are no active users/clints for qcom-rng
> using crypto_rng interface? If there is no concrete way to do then this
> patch breaks backward compatibility.
The only in-kernel user of crypto_rng uses it to access
"drbg_nopr_hmac_sha512" on "FIPS-enabled" systems. So, the only
possibility for a user of "qcom-rng" would be userspace via AF_ALG. But
I've never heard of that being done. It would be a really odd and
pointless thing to do when the much easier to use UAPIs /dev/random and
/dev/hwrng already exist. And broken too, as I pointed out.
AF_ALG as a whole is rarely used and is a mistake. It exposes a massive
amount of unused and broken functionality to userspace, including every
single implementation of every single crypto algorithm by name, which
never should have been done in the way it was. We don't have much
choice but to continue removing algorithms/drivers from it to keep Linux
maintainable, as has already been happening successfully for many years.
The AF_ALG hardware RNG support is especially pointless, given the
redundancy with /dev/random and /dev/hwrng. As far as I can tell the
main purpose of it is just to confuse RNG driver authors into thinking
that they are making Linux utilize their RNG.
Keep in mind that for AF_ALG there's also a compatibility trick
available to be implemented if it ever needs to: the kernel could
automatically remap requests for a particular driver name, like
"qcom-rng", to a different one like "drbg_nopr_hmac_sha512".
However, it's never actually been necessary to use that trick in *any*
of the times that crypto drivers have been removed or renamed. No one
has ever cared. There's some AF_ALG functionality we know that a few
programs use, but this isn't part of that.
So I think we can be quite confident in proceeding with this patch even
without proactively putting in the name remapping.
- Eric
^ permalink raw reply
* Re: [PATCH 3/4] crypto: qcom-rng - Remove crypto_rng interface
From: Neeraj Soni @ 2026-06-04 4:50 UTC (permalink / raw)
To: Eric Biggers, linux-crypto
Cc: linux-kernel, Om Prakash Singh, Bjorn Andersson, Neil Armstrong,
linux-arm-msm, Olivia Mackall, stable
In-Reply-To: <20260530020332.143058-4-ebiggers@kernel.org>
On 5/30/2026 7:33 AM, Eric Biggers wrote:
> qcom-rng.c exposes the same hardware through two completely separate
> interfaces, crypto_rng and hwrng. However, the implementation of this
> is buggy because it permits generation operations from these interfaces
> to run concurrently with each other, accessing the same registers. That
> is, qcom_rng_generate() synchronizes with itself but not with
> qcom_hwrng_read(). This results in potential repetition of output from
> the RNG, output of non-random values, etc.
>
> Fortunately, there's actually no point in hardware RNG drivers
> implementing the crypto_rng interface. It's not actually used by
> anything besides the "rng" algorithm type of AF_ALG, which in turn is
> not actually used in practice. Other crypto_rng hardware drivers are
How it was established that there are no active users/clints for qcom-rng
using crypto_rng interface? If there is no concrete way to do then this
patch breaks backward compatibility.
> likewise being phased out, leaving just the hwrng support.
>
> Thus, remove it to simplify the code and avoid conflict (and confusion)
> with the hwrng interface which is the one that actually matters.
>
> Note that while this means the driver stops supporting "qcom,prng" and
> "qcom,prng-ee", it didn't do anything useful on SoCs with those anyway.
>
> Fixes: f29cd5bb64c2 ("crypto: qcom-rng - Add hw_random interface support")
> Cc: stable@vger.kernel.org
> Signed-off-by: Eric Biggers <ebiggers@kernel.org>
> ---
> drivers/crypto/Kconfig | 1 -
> drivers/crypto/qcom-rng.c | 175 ++------------------------------------
> 2 files changed, 9 insertions(+), 167 deletions(-)
>
> diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
> index 3449b3c9c6ad..a12cd677467b 100644
> --- a/drivers/crypto/Kconfig
> +++ b/drivers/crypto/Kconfig
> @@ -658,11 +658,10 @@ config CRYPTO_DEV_QCE_SW_MAX_LEN
>
> config CRYPTO_DEV_QCOM_RNG
> tristate "Qualcomm Random Number Generator Driver"
> depends on ARCH_QCOM || COMPILE_TEST
> depends on HW_RANDOM
> - select CRYPTO_RNG
> help
> This driver provides support for the Random Number
> Generator hardware found on Qualcomm SoCs.
>
> To compile this driver as a module, choose M here. The
> diff --git a/drivers/crypto/qcom-rng.c b/drivers/crypto/qcom-rng.c
> index b7f3b9695dac..48b605687b28 100644
> --- a/drivers/crypto/qcom-rng.c
> +++ b/drivers/crypto/qcom-rng.c
> @@ -1,14 +1,11 @@
> // SPDX-License-Identifier: GPL-2.0
> // Copyright (c) 2017-18 Linaro Limited
> //
> // Based on msm-rng.c and downstream driver
>
> -#include <crypto/internal/rng.h>
> -#include <linux/acpi.h>
> #include <linux/clk.h>
> -#include <linux/crypto.h>
> #include <linux/hw_random.h>
> #include <linux/io.h>
> #include <linux/iopoll.h>
> #include <linux/kernel.h>
> #include <linux/module.h>
> @@ -30,28 +27,15 @@
> #define WORD_SZ 4
>
> #define QCOM_TRNG_QUALITY 1024
>
> struct qcom_rng {
> - struct mutex lock;
> void __iomem *base;
> struct clk *clk;
> struct hwrng hwrng;
> - struct qcom_rng_match_data *match_data;
> };
>
> -struct qcom_rng_ctx {
> - struct qcom_rng *rng;
> -};
> -
> -struct qcom_rng_match_data {
> - bool skip_init;
> - bool hwrng_support;
> -};
> -
> -static struct qcom_rng *qcom_rng_dev;
> -
> static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max)
> {
> unsigned int currsize = 0;
> u32 val;
> int ret;
> @@ -77,41 +61,10 @@ static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max)
> } while (currsize < max);
>
> return currsize;
> }
>
> -static int qcom_rng_generate(struct crypto_rng *tfm,
> - const u8 *src, unsigned int slen,
> - u8 *dstn, unsigned int dlen)
> -{
> - struct qcom_rng_ctx *ctx = crypto_rng_ctx(tfm);
> - struct qcom_rng *rng = ctx->rng;
> - int ret;
> -
> - ret = clk_prepare_enable(rng->clk);
> - if (ret)
> - return ret;
> -
> - mutex_lock(&rng->lock);
> -
> - ret = qcom_rng_read(rng, dstn, dlen);
> -
> - mutex_unlock(&rng->lock);
> - clk_disable_unprepare(rng->clk);
> -
> - if (ret >= 0)
> - ret = 0;
> -
> - return ret;
> -}
> -
> -static int qcom_rng_seed(struct crypto_rng *tfm, const u8 *seed,
> - unsigned int slen)
> -{
> - return 0;
> -}
> -
> static int qcom_hwrng_init(struct hwrng *hwrng)
> {
> struct qcom_rng *qrng = container_of(hwrng, struct qcom_rng, hwrng);
>
> return clk_prepare_enable(qrng->clk);
> @@ -129,159 +82,49 @@ static void qcom_hwrng_cleanup(struct hwrng *hwrng)
> struct qcom_rng *qrng = container_of(hwrng, struct qcom_rng, hwrng);
>
> clk_disable_unprepare(qrng->clk);
> }
>
> -static int qcom_rng_enable(struct qcom_rng *rng)
> -{
> - u32 val;
> - int ret;
> -
> - ret = clk_prepare_enable(rng->clk);
> - if (ret)
> - return ret;
> -
> - /* Enable PRNG only if it is not already enabled */
> - val = readl_relaxed(rng->base + PRNG_CONFIG);
> - if (val & PRNG_CONFIG_HW_ENABLE)
> - goto already_enabled;
> -
> - val = readl_relaxed(rng->base + PRNG_LFSR_CFG);
> - val &= ~PRNG_LFSR_CFG_MASK;
> - val |= PRNG_LFSR_CFG_CLOCKS;
> - writel(val, rng->base + PRNG_LFSR_CFG);
> -
> - val = readl_relaxed(rng->base + PRNG_CONFIG);
> - val |= PRNG_CONFIG_HW_ENABLE;
> - writel(val, rng->base + PRNG_CONFIG);
> -
> -already_enabled:
> - clk_disable_unprepare(rng->clk);
> -
> - return 0;
> -}
> -
> -static int qcom_rng_init(struct crypto_tfm *tfm)
> -{
> - struct qcom_rng_ctx *ctx = crypto_tfm_ctx(tfm);
> -
> - ctx->rng = qcom_rng_dev;
> -
> - if (!ctx->rng->match_data->skip_init)
> - return qcom_rng_enable(ctx->rng);
> -
> - return 0;
> -}
> -
> -static struct rng_alg qcom_rng_alg = {
> - .generate = qcom_rng_generate,
> - .seed = qcom_rng_seed,
> - .seedsize = 0,
> - .base = {
> - .cra_name = "stdrng",
> - .cra_driver_name = "qcom-rng",
> - .cra_flags = CRYPTO_ALG_TYPE_RNG,
> - .cra_priority = 300,
> - .cra_ctxsize = sizeof(struct qcom_rng_ctx),
> - .cra_module = THIS_MODULE,
> - .cra_init = qcom_rng_init,
> - }
> -};
> -
> static int qcom_rng_probe(struct platform_device *pdev)
> {
> struct qcom_rng *rng;
> int ret;
>
> rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
> if (!rng)
> return -ENOMEM;
>
> - platform_set_drvdata(pdev, rng);
> - mutex_init(&rng->lock);
> -
> rng->base = devm_platform_ioremap_resource(pdev, 0);
> if (IS_ERR(rng->base))
> return PTR_ERR(rng->base);
>
> rng->clk = devm_clk_get_optional(&pdev->dev, "core");
> if (IS_ERR(rng->clk))
> return PTR_ERR(rng->clk);
>
> - rng->match_data = (struct qcom_rng_match_data *)device_get_match_data(&pdev->dev);
> -
> - qcom_rng_dev = rng;
> - ret = crypto_register_rng(&qcom_rng_alg);
> - if (ret) {
> - dev_err(&pdev->dev, "Register crypto rng failed: %d\n", ret);
> - qcom_rng_dev = NULL;
> - return ret;
> - }
> -
> - if (rng->match_data->hwrng_support) {
> - rng->hwrng.name = "qcom_hwrng";
> - rng->hwrng.init = qcom_hwrng_init;
> - rng->hwrng.read = qcom_hwrng_read;
> - rng->hwrng.cleanup = qcom_hwrng_cleanup;
> - rng->hwrng.quality = QCOM_TRNG_QUALITY;
> - ret = devm_hwrng_register(&pdev->dev, &rng->hwrng);
> - if (ret) {
> - dev_err(&pdev->dev, "Register hwrng failed: %d\n", ret);
> - qcom_rng_dev = NULL;
> - goto fail;
> - }
> - }
> -
> - return ret;
> -fail:
> - crypto_unregister_rng(&qcom_rng_alg);
> + rng->hwrng.name = "qcom_hwrng";
> + rng->hwrng.init = qcom_hwrng_init;
> + rng->hwrng.read = qcom_hwrng_read;
> + rng->hwrng.cleanup = qcom_hwrng_cleanup;
> + rng->hwrng.quality = QCOM_TRNG_QUALITY;
> + ret = devm_hwrng_register(&pdev->dev, &rng->hwrng);
> + if (ret)
> + dev_err(&pdev->dev, "Register hwrng failed: %d\n", ret);
> return ret;
> }
>
> -static void qcom_rng_remove(struct platform_device *pdev)
> -{
> - crypto_unregister_rng(&qcom_rng_alg);
> -
> - qcom_rng_dev = NULL;
> -}
> -
> -static struct qcom_rng_match_data qcom_prng_match_data = {
> - .skip_init = false,
> - .hwrng_support = false,
> -};
> -
> -static struct qcom_rng_match_data qcom_prng_ee_match_data = {
> - .skip_init = true,
> - .hwrng_support = false,
> -};
> -
> -static struct qcom_rng_match_data qcom_trng_match_data = {
> - .skip_init = true,
> - .hwrng_support = true,
> -};
> -
> -static const struct acpi_device_id __maybe_unused qcom_rng_acpi_match[] = {
> - { .id = "QCOM8160", .driver_data = (kernel_ulong_t)&qcom_prng_ee_match_data },
> - {}
> -};
> -MODULE_DEVICE_TABLE(acpi, qcom_rng_acpi_match);
> -
> static const struct of_device_id __maybe_unused qcom_rng_of_match[] = {
> - { .compatible = "qcom,prng", .data = &qcom_prng_match_data },
> - { .compatible = "qcom,prng-ee", .data = &qcom_prng_ee_match_data },
> - { .compatible = "qcom,trng", .data = &qcom_trng_match_data },
> + { .compatible = "qcom,trng" },
> {}
> };
> MODULE_DEVICE_TABLE(of, qcom_rng_of_match);
>
> static struct platform_driver qcom_rng_driver = {
> .probe = qcom_rng_probe,
> - .remove = qcom_rng_remove,
> .driver = {
> .name = KBUILD_MODNAME,
> .of_match_table = qcom_rng_of_match,
> - .acpi_match_table = ACPI_PTR(qcom_rng_acpi_match),
> }
> };
> module_platform_driver(qcom_rng_driver);
>
> MODULE_ALIAS("platform:" KBUILD_MODNAME);
>
Regards,
Neeraj
^ permalink raw reply
* Re: [PATCH] crypto: talitos: replace in_be32/out_be32 with ioread32be/iowrite32be
From: Simon Richter @ 2026-06-04 4:26 UTC (permalink / raw)
To: Rosen Penev, linux-crypto; +Cc: Herbert Xu, David S. Miller, open list
In-Reply-To: <20260603193300.7695-1-rosenp@gmail.com>
Hi,
On 6/4/26 4:33 AM, Rosen Penev wrote:
> Convert ppc4xx-specific in_be32/out_be32 and the setbits32/clrbits32
> macros to the portable ioread32be/iowrite32be helpers.
It doesn't do that. The setbits32/clrbits32 macros are unchanged.
If they had been adapted, there would have been no need to inline the
macro definition before substituting the IO accessors.
This inlining makes the code harder to read, because it consists of
nested function calls (which have very specific and annoying indentation
requirements that you're not following), and also duplicates the address
calculation.
> Add COMPILE_TEST for extra compile coverage.
> Assisted-by: opencode:big-pickle
I suspect these two lines are related in a horrible way, and this code
has only been compile-tested on the wrong architecture as part of the
feedback loop. COMPILE_TEST is not necessary for compile-testing with a
cross compiler and an appropriate defconfig for the target platform.
> - setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
> - TALITOS1_CCCR_LO_RESET);
> + iowrite32be(ioread32be(priv->chan[ch].reg + TALITOS_CCCR_LO) |
> + (TALITOS1_CCCR_LO_RESET),
> + priv->chan[ch].reg + TALITOS_CCCR_LO);
Wrong formatting, and either the parentheses around
TALITOS1_CCCR_LO_RESET are unnecessary here, or
> - while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
> - TALITOS1_CCCR_LO_RESET) && --timeout)
> + while ((ioread32be(priv->chan[ch].reg + TALITOS_CCCR_LO) &
> + TALITOS1_CCCR_LO_RESET) &&
> + --timeout)
also needs them. The former is correct (macro definitions need to
include parentheses if using them inside a calculation would give you
unexpected operator precedence.
> /* set 36-bit addressing, done writeback enable and done IRQ enable */
> - setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
> - TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
> + iowrite32be(ioread32be(priv->chan[ch].reg + TALITOS_CCCR_LO) |
> + (TALITOS_CCCR_LO_EAE | TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE),
> + priv->chan[ch].reg + TALITOS_CCCR_LO);
These parentheses are likewise unnecessary. It's a big OR, no need to
group them.
\> +#define DEF_TALITOS1_DONE(name, ch_done_mask)
\
> + static void talitos1_done_##name(unsigned long data) \
Inconsistent backslashes, and does not improve the horribleness that was
there before, only makes it longer and harder to read.
> if (!desc_hdr)
> - desc_hdr = cpu_to_be32(in_be32(priv->chan[ch].reg + TALITOS_DESCBUF));
> + desc_hdr = cpu_to_be32(ioread32be(priv->chan[ch].reg + TALITOS_DESCBUF));
Likewise, this is bad and unreadable in the current state, and this
patch does nothing to improve that.
> - dev_err(dev, "AFEUISR 0x%08x_%08x\n",
> - in_be32(priv->reg_afeu + TALITOS_EUISR),
> - in_be32(priv->reg_afeu + TALITOS_EUISR_LO));
> + dev_err(dev, "AFEUISR 0x%08x_%08x\n", ioread32be(priv->reg_afeu + TALITOS_EUISR),
> + ioread32be(priv->reg_afeu + TALITOS_EUISR_LO));
You can probably see how the formatting is worse than before.
I'm not going to bother checking if this introduces any bugs, as I have
the strong suspicion that I would be the first person reading this code.
Simon
^ permalink raw reply
* [PATCH] crypto: rng - Free default RNG on module exit
From: Herbert Xu @ 2026-06-04 4:30 UTC (permalink / raw)
To: Linux Crypto Mailing List
When the rng module is removed the default RNG will be leaked.
Call crypto_del_default_rng to free it if possible.
Fixes: 7cecadb7cca8 ("crypto: rng - Do not free default RNG when it becomes unused")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
diff --git a/crypto/rng.c b/crypto/rng.c
index eec786c45bdd..828b0d807473 100644
--- a/crypto/rng.c
+++ b/crypto/rng.c
@@ -230,5 +230,16 @@ void crypto_unregister_rngs(struct rng_alg *algs, int count)
}
EXPORT_SYMBOL_GPL(crypto_unregister_rngs);
+static void __exit rng_exit(void)
+{
+ int err;
+
+ err = crypto_del_default_rng();
+ if (err)
+ pr_err("Failed delete default RNG: %d\n", err);
+}
+
+module_exit(rng_exit);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Random Number Generator");
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply related
* Re: [PATCH 0/2] HiSilicon TRNG fix and simplification
From: liulongfang @ 2026-06-04 3:32 UTC (permalink / raw)
To: Eric Biggers, linux-crypto, Herbert Xu
Cc: Olivia Mackall, Weili Qian, Wei Xu, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260530202624.20768-1-ebiggers@kernel.org>
On 2026/5/31 4:26, Eric Biggers wrote:
> This series fixes and greatly simplifies the HiSilicon TRNG driver by
> removing the gratuitous crypto_rng interface, leaving just hwrng which
> is the one that actually matters.
>
> Note that this mirrors similar changes in other drivers such as qcom-rng
> (https://lore.kernel.org/r/20260530020332.143058-1-ebiggers@kernel.org)
>
> Eric Biggers (2):
> crypto: hisi-trng - Remove crypto_rng interface
> hwrng: hisi-trng - Move hisi-trng into drivers/char/hw_random/
>
> MAINTAINERS | 2 +-
> arch/arm64/configs/defconfig | 2 +-
> drivers/char/hw_random/Kconfig | 10 +
> drivers/char/hw_random/Makefile | 1 +
> drivers/char/hw_random/hisi-trng-v2.c | 98 +++++++
> drivers/crypto/hisilicon/Kconfig | 8 -
> drivers/crypto/hisilicon/Makefile | 1 -
> drivers/crypto/hisilicon/trng/Makefile | 2 -
> drivers/crypto/hisilicon/trng/trng.c | 390 -------------------------
> 9 files changed, 111 insertions(+), 403 deletions(-)
> create mode 100644 drivers/char/hw_random/hisi-trng-v2.c
> delete mode 100644 drivers/crypto/hisilicon/trng/Makefile
> delete mode 100644 drivers/crypto/hisilicon/trng/trng.c
>
>
> base-commit: 5624ea54f3ba5c83d2e5503411a31a8be0278c1e
> prerequisite-patch-id: 07e982b663ac3f8312ca524f6b91b5b38661df5e
> prerequisite-patch-id: 72064361a8f36e015ab0b7e1fa4d364b40d90506
> prerequisite-patch-id: 8978b8e0db7f47935e5f6f0aff14a97f55d3073c
> prerequisite-patch-id: 6aa0e3e93a008279d71e535a3d0cf48643f55e19
>
Acked-by: Longfang Liu <liulongfang@huawei.com>
Thanks.
^ permalink raw reply
* [PATCH] rhashtable: Add workqueue/irq_work header inclusions
From: Herbert Xu @ 2026-06-04 2:21 UTC (permalink / raw)
To: Linux Crypto Mailing List
Add inclusions for irq_work.h and workqueue.h to rhashtable.c rather
than relying on indirect inclusions from elsewhere.
Remove workqueue.h from rhashtable.h now that it uses IRQ work only.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index ef5230cece36..b01d53c37a68 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -23,7 +23,6 @@
#include <linux/irq_work.h>
#include <linux/jhash.h>
#include <linux/list_nulls.h>
-#include <linux/workqueue.h>
#include <linux/rculist.h>
#include <linux/bit_spinlock.h>
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 04b3a808fca9..57751ee19faa 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -14,6 +14,7 @@
#include <linux/atomic.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/irq_work.h>
#include <linux/log2.h>
#include <linux/sched.h>
#include <linux/rculist.h>
@@ -25,6 +26,7 @@
#include <linux/rhashtable.h>
#include <linux/err.h>
#include <linux/export.h>
+#include <linux/workqueue.h>
#define HASH_DEFAULT_SIZE 64UL
#define HASH_MIN_SIZE 4U
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply related
* [PATCH] rhashtable: Use irq work for shrinking
From: Herbert Xu @ 2026-06-04 2:17 UTC (permalink / raw)
To: Mykyta Yatsenko
Cc: bot+bpf-ci, bpf, ast, andrii, daniel, kafai, kernel-team, eddyz87,
memxor, yatsenko, martin.lau, yonghong.song, clm, ihor.solodrai,
Tejun Heo, Linux Crypto Mailing List
In-Reply-To: <3960ffc3-78f3-46da-baaf-ce72b6495698@gmail.com>
On Wed, Jun 03, 2026 at 02:08:25PM +0100, Mykyta Yatsenko wrote:
>
> For v7 I'm dropping automatic_shrinking, because it adds a risk of
> calling schedule_work() on element deletion path (__rhashtable_remove_fast_one())
> when hashtable size drops below 30% of the capacity.
Now that expansion uses irq work I think shrinking should switch
to that as well.
---8<---
Use irq work for automatic shrinking so that this may be called
in NMI context.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index ef5230cece36..0693bce6f890 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -1117,7 +1117,7 @@ static __always_inline int __rhashtable_remove_fast_one(
atomic_dec(&ht->nelems);
if (unlikely(ht->p.automatic_shrinking &&
rht_shrink_below_30(ht, tbl)))
- schedule_work(&ht->run_work);
+ irq_work_queue(&ht->run_irq_work);
err = 0;
}
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply related
* Re: [PATCH v3] crypto/algapi: fix refcount leak in crypto_register_alg()
From: Herbert Xu @ 2026-06-04 2:01 UTC (permalink / raw)
To: Wentao Liang; +Cc: davem, linux-crypto, linux-kernel, stable
In-Reply-To: <20260603082140.3719314-1-vulab@iscas.ac.cn>
On Wed, Jun 03, 2026 at 08:21:40AM +0000, Wentao Liang wrote:
> When crypto_register_alg() calls crypto_check_alg() successfully,
> the algorithm's refcount is set to one. If the subsequent handling
The algorithm wasn't registered anywhere and the refcount isn't used.
I fail to see the point of your patch.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* [PATCH] crypto: omap - use min3 to simplify omap_crypto_copy_data
From: Thorsten Blum @ 2026-06-04 0:10 UTC (permalink / raw)
To: Herbert Xu, David S. Miller; +Cc: Thorsten Blum, linux-crypto, linux-kernel
Replace two consecutive min() calls with min3() to simplify the code.
Change the function parameters and local variables from int to size_t
since these represent unsigned values and to prevent a signedness error.
Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
---
drivers/crypto/omap-crypto.c | 12 ++++++------
drivers/crypto/omap-crypto.h | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/crypto/omap-crypto.c b/drivers/crypto/omap-crypto.c
index 0345c9383d50..c0400fbe313e 100644
--- a/drivers/crypto/omap-crypto.c
+++ b/drivers/crypto/omap-crypto.c
@@ -156,11 +157,11 @@ EXPORT_SYMBOL_GPL(omap_crypto_align_sg);
static void omap_crypto_copy_data(struct scatterlist *src,
struct scatterlist *dst,
- int offset, int len)
+ size_t offset, size_t len)
{
- int amt;
+ size_t amt;
void *srcb, *dstb;
- int srco = 0, dsto = offset;
+ size_t srco = 0, dsto = offset;
while (src && dst && len) {
if (srco >= src->length) {
@@ -175,8 +176,7 @@ static void omap_crypto_copy_data(struct scatterlist *src,
continue;
}
- amt = min(src->length - srco, dst->length - dsto);
- amt = min(len, amt);
+ amt = min3(src->length - srco, dst->length - dsto, len);
srcb = kmap_atomic(sg_page(src)) + srco + src->offset;
dstb = kmap_atomic(sg_page(dst)) + dsto + dst->offset;
@@ -195,7 +195,7 @@ static void omap_crypto_copy_data(struct scatterlist *src,
}
void omap_crypto_cleanup(struct scatterlist *sg, struct scatterlist *orig,
- int offset, int len, u8 flags_shift,
+ size_t offset, size_t len, u8 flags_shift,
unsigned long flags)
{
void *buf;
diff --git a/drivers/crypto/omap-crypto.h b/drivers/crypto/omap-crypto.h
index 506ccde6f380..436f45f3bb7d 100644
--- a/drivers/crypto/omap-crypto.h
+++ b/drivers/crypto/omap-crypto.h
@@ -28,7 +28,7 @@ int omap_crypto_align_sg(struct scatterlist **sg, int total, int bs,
struct scatterlist *new_sg, u16 flags,
u8 flags_shift, unsigned long *dd_flags);
void omap_crypto_cleanup(struct scatterlist *sg, struct scatterlist *orig,
- int offset, int len, u8 flags_shift,
+ size_t offset, size_t len, u8 flags_shift,
unsigned long flags);
#endif
^ permalink raw reply related
* [PATCH] crypto: talitos: replace in_be32/out_be32 with ioread32be/iowrite32be
From: Rosen Penev @ 2026-06-03 19:33 UTC (permalink / raw)
To: linux-crypto; +Cc: Herbert Xu, David S. Miller, open list
Convert ppc4xx-specific in_be32/out_be32 and the setbits32/clrbits32
macros to the portable ioread32be/iowrite32be helpers.
Add HAS_IOMEM dependency as these accessors need it.
Add COMPILE_TEST for extra compile coverage.
Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
drivers/crypto/Kconfig | 3 +-
drivers/crypto/talitos.c | 379 ++++++++++++++++++++-------------------
2 files changed, 192 insertions(+), 190 deletions(-)
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 3449b3c9c6ad..d5d2a663d171 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -262,7 +262,8 @@ config CRYPTO_DEV_TALITOS
select CRYPTO_HASH
select CRYPTO_LIB_DES
select HW_RANDOM
- depends on FSL_SOC
+ depends on FSL_SOC || COMPILE_TEST
+ depends on HAS_IOMEM
help
Say 'Y' here to use the Freescale Security Engine (SEC)
to offload cryptographic algorithm computation.
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 584508963241..583bfbe118b5 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -143,18 +143,20 @@ static int reset_channel(struct device *dev, int ch)
bool is_sec1 = has_ftr_sec1(priv);
if (is_sec1) {
- setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
- TALITOS1_CCCR_LO_RESET);
+ iowrite32be(ioread32be(priv->chan[ch].reg + TALITOS_CCCR_LO) |
+ (TALITOS1_CCCR_LO_RESET),
+ priv->chan[ch].reg + TALITOS_CCCR_LO);
- while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
- TALITOS1_CCCR_LO_RESET) && --timeout)
+ while ((ioread32be(priv->chan[ch].reg + TALITOS_CCCR_LO) &
+ TALITOS1_CCCR_LO_RESET) &&
+ --timeout)
cpu_relax();
} else {
- setbits32(priv->chan[ch].reg + TALITOS_CCCR,
- TALITOS2_CCCR_RESET);
+ iowrite32be(ioread32be(priv->chan[ch].reg + TALITOS_CCCR) | (TALITOS2_CCCR_RESET),
+ priv->chan[ch].reg + TALITOS_CCCR);
- while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
- TALITOS2_CCCR_RESET) && --timeout)
+ while ((ioread32be(priv->chan[ch].reg + TALITOS_CCCR) & TALITOS2_CCCR_RESET) &&
+ --timeout)
cpu_relax();
}
@@ -164,17 +166,19 @@ static int reset_channel(struct device *dev, int ch)
}
/* set 36-bit addressing, done writeback enable and done IRQ enable */
- setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
- TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
+ iowrite32be(ioread32be(priv->chan[ch].reg + TALITOS_CCCR_LO) |
+ (TALITOS_CCCR_LO_EAE | TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE),
+ priv->chan[ch].reg + TALITOS_CCCR_LO);
/* enable chaining descriptors */
if (is_sec1)
- setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
- TALITOS_CCCR_LO_NE);
+ iowrite32be(ioread32be(priv->chan[ch].reg + TALITOS_CCCR_LO) | (TALITOS_CCCR_LO_NE),
+ priv->chan[ch].reg + TALITOS_CCCR_LO);
/* and ICCR writeback, if available */
if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
- setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
- TALITOS_CCCR_LO_IWSE);
+ iowrite32be(ioread32be(priv->chan[ch].reg + TALITOS_CCCR_LO) |
+ (TALITOS_CCCR_LO_IWSE),
+ priv->chan[ch].reg + TALITOS_CCCR_LO);
return 0;
}
@@ -186,15 +190,14 @@ static int reset_device(struct device *dev)
bool is_sec1 = has_ftr_sec1(priv);
u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
- setbits32(priv->reg + TALITOS_MCR, mcr);
+ iowrite32be(ioread32be(priv->reg + TALITOS_MCR) | (mcr), priv->reg + TALITOS_MCR);
- while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
- && --timeout)
+ while ((ioread32be(priv->reg + TALITOS_MCR) & mcr) && --timeout)
cpu_relax();
if (priv->irq[1]) {
mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
- setbits32(priv->reg + TALITOS_MCR, mcr);
+ iowrite32be(ioread32be(priv->reg + TALITOS_MCR) | (mcr), priv->reg + TALITOS_MCR);
}
if (timeout == 0) {
@@ -237,19 +240,25 @@ static int init_device(struct device *dev)
/* enable channel done and error interrupts */
if (is_sec1) {
- clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
- clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR) & ~(TALITOS1_IMR_INIT),
+ priv->reg + TALITOS_IMR);
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR_LO) & ~(TALITOS1_IMR_LO_INIT),
+ priv->reg + TALITOS_IMR_LO);
/* disable parity error check in DEU (erroneous? test vect.) */
- setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
+ iowrite32be(ioread32be(priv->reg_deu + TALITOS_EUICR) | (TALITOS1_DEUICR_KPE),
+ priv->reg_deu + TALITOS_EUICR);
} else {
- setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
- setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR) | (TALITOS2_IMR_INIT),
+ priv->reg + TALITOS_IMR);
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR_LO) | (TALITOS2_IMR_LO_INIT),
+ priv->reg + TALITOS_IMR_LO);
}
/* disable integrity check error interrupts (use writeback instead) */
if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
- setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
- TALITOS_MDEUICR_LO_ICE);
+ iowrite32be(ioread32be(priv->reg_mdeu + TALITOS_EUICR_LO) |
+ (TALITOS_MDEUICR_LO_ICE),
+ priv->reg_mdeu + TALITOS_EUICR_LO);
return 0;
}
@@ -342,10 +351,8 @@ static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
/* GO! */
wmb();
- out_be32(priv->chan[ch].reg + TALITOS_FF,
- upper_32_bits(request->dma_desc));
- out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
- lower_32_bits(request->dma_desc));
+ iowrite32be(upper_32_bits(request->dma_desc), priv->chan[ch].reg + TALITOS_FF);
+ iowrite32be(lower_32_bits(request->dma_desc), priv->chan[ch].reg + TALITOS_FF_LO);
spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
@@ -463,56 +470,60 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
/*
* process completed requests for channels that have done status
*/
-#define DEF_TALITOS1_DONE(name, ch_done_mask) \
-static void talitos1_done_##name(unsigned long data) \
-{ \
- struct device *dev = (struct device *)data; \
- struct talitos_private *priv = dev_get_drvdata(dev); \
- unsigned long flags; \
- \
- if (ch_done_mask & 0x10000000) \
- flush_channel(dev, 0, 0, 0); \
- if (ch_done_mask & 0x40000000) \
- flush_channel(dev, 1, 0, 0); \
- if (ch_done_mask & 0x00010000) \
- flush_channel(dev, 2, 0, 0); \
- if (ch_done_mask & 0x00040000) \
- flush_channel(dev, 3, 0, 0); \
- \
- /* At this point, all completed channels have been processed */ \
- /* Unmask done interrupts for channels completed later on. */ \
- spin_lock_irqsave(&priv->reg_lock, flags); \
- clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
- clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT); \
- spin_unlock_irqrestore(&priv->reg_lock, flags); \
-}
+#define DEF_TALITOS1_DONE(name, ch_done_mask) \
+ static void talitos1_done_##name(unsigned long data) \
+ { \
+ struct device *dev = (struct device *)data; \
+ struct talitos_private *priv = dev_get_drvdata(dev); \
+ unsigned long flags; \
+ \
+ if (ch_done_mask & 0x10000000) \
+ flush_channel(dev, 0, 0, 0); \
+ if (ch_done_mask & 0x40000000) \
+ flush_channel(dev, 1, 0, 0); \
+ if (ch_done_mask & 0x00010000) \
+ flush_channel(dev, 2, 0, 0); \
+ if (ch_done_mask & 0x00040000) \
+ flush_channel(dev, 3, 0, 0); \
+ \
+ /* At this point, all completed channels have been processed */ \
+ /* Unmask done interrupts for channels completed later on. */ \
+ spin_lock_irqsave(&priv->reg_lock, flags); \
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR) & ~(ch_done_mask), \
+ priv->reg + TALITOS_IMR); \
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR_LO) & ~(TALITOS1_IMR_LO_INIT), \
+ priv->reg + TALITOS_IMR_LO); \
+ spin_unlock_irqrestore(&priv->reg_lock, flags); \
+ }
DEF_TALITOS1_DONE(4ch, TALITOS1_ISR_4CHDONE)
DEF_TALITOS1_DONE(ch0, TALITOS1_ISR_CH_0_DONE)
-#define DEF_TALITOS2_DONE(name, ch_done_mask) \
-static void talitos2_done_##name(unsigned long data) \
-{ \
- struct device *dev = (struct device *)data; \
- struct talitos_private *priv = dev_get_drvdata(dev); \
- unsigned long flags; \
- \
- if (ch_done_mask & 1) \
- flush_channel(dev, 0, 0, 0); \
- if (ch_done_mask & (1 << 2)) \
- flush_channel(dev, 1, 0, 0); \
- if (ch_done_mask & (1 << 4)) \
- flush_channel(dev, 2, 0, 0); \
- if (ch_done_mask & (1 << 6)) \
- flush_channel(dev, 3, 0, 0); \
- \
- /* At this point, all completed channels have been processed */ \
- /* Unmask done interrupts for channels completed later on. */ \
- spin_lock_irqsave(&priv->reg_lock, flags); \
- setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
- setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT); \
- spin_unlock_irqrestore(&priv->reg_lock, flags); \
-}
+#define DEF_TALITOS2_DONE(name, ch_done_mask) \
+ static void talitos2_done_##name(unsigned long data) \
+ { \
+ struct device *dev = (struct device *)data; \
+ struct talitos_private *priv = dev_get_drvdata(dev); \
+ unsigned long flags; \
+ \
+ if (ch_done_mask & 1) \
+ flush_channel(dev, 0, 0, 0); \
+ if (ch_done_mask & (1 << 2)) \
+ flush_channel(dev, 1, 0, 0); \
+ if (ch_done_mask & (1 << 4)) \
+ flush_channel(dev, 2, 0, 0); \
+ if (ch_done_mask & (1 << 6)) \
+ flush_channel(dev, 3, 0, 0); \
+ \
+ /* At this point, all completed channels have been processed */ \
+ /* Unmask done interrupts for channels completed later on. */ \
+ spin_lock_irqsave(&priv->reg_lock, flags); \
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR) | (ch_done_mask), \
+ priv->reg + TALITOS_IMR); \
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR_LO) | (TALITOS2_IMR_LO_INIT), \
+ priv->reg + TALITOS_IMR_LO); \
+ spin_unlock_irqrestore(&priv->reg_lock, flags); \
+ }
DEF_TALITOS2_DONE(4ch, TALITOS2_ISR_4CHDONE)
DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE)
@@ -549,8 +560,8 @@ static __be32 current_desc_hdr(struct device *dev, int ch)
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);
+ cur_desc = ((u64)ioread32be(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
+ cur_desc |= ioread32be(priv->chan[ch].reg + TALITOS_CDPR_LO);
if (!cur_desc) {
dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
@@ -584,70 +595,60 @@ static void report_eu_error(struct device *dev, int ch, __be32 desc_hdr)
int i;
if (!desc_hdr)
- desc_hdr = cpu_to_be32(in_be32(priv->chan[ch].reg + TALITOS_DESCBUF));
+ desc_hdr = cpu_to_be32(ioread32be(priv->chan[ch].reg + TALITOS_DESCBUF));
switch (desc_hdr & DESC_HDR_SEL0_MASK) {
case DESC_HDR_SEL0_AFEU:
- dev_err(dev, "AFEUISR 0x%08x_%08x\n",
- in_be32(priv->reg_afeu + TALITOS_EUISR),
- in_be32(priv->reg_afeu + TALITOS_EUISR_LO));
+ dev_err(dev, "AFEUISR 0x%08x_%08x\n", ioread32be(priv->reg_afeu + TALITOS_EUISR),
+ ioread32be(priv->reg_afeu + TALITOS_EUISR_LO));
break;
case DESC_HDR_SEL0_DEU:
- dev_err(dev, "DEUISR 0x%08x_%08x\n",
- in_be32(priv->reg_deu + TALITOS_EUISR),
- in_be32(priv->reg_deu + TALITOS_EUISR_LO));
+ dev_err(dev, "DEUISR 0x%08x_%08x\n", ioread32be(priv->reg_deu + TALITOS_EUISR),
+ ioread32be(priv->reg_deu + TALITOS_EUISR_LO));
break;
case DESC_HDR_SEL0_MDEUA:
case DESC_HDR_SEL0_MDEUB:
- dev_err(dev, "MDEUISR 0x%08x_%08x\n",
- in_be32(priv->reg_mdeu + TALITOS_EUISR),
- in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
+ dev_err(dev, "MDEUISR 0x%08x_%08x\n", ioread32be(priv->reg_mdeu + TALITOS_EUISR),
+ ioread32be(priv->reg_mdeu + TALITOS_EUISR_LO));
break;
case DESC_HDR_SEL0_RNG:
- dev_err(dev, "RNGUISR 0x%08x_%08x\n",
- in_be32(priv->reg_rngu + TALITOS_ISR),
- in_be32(priv->reg_rngu + TALITOS_ISR_LO));
+ dev_err(dev, "RNGUISR 0x%08x_%08x\n", ioread32be(priv->reg_rngu + TALITOS_ISR),
+ ioread32be(priv->reg_rngu + TALITOS_ISR_LO));
break;
case DESC_HDR_SEL0_PKEU:
- dev_err(dev, "PKEUISR 0x%08x_%08x\n",
- in_be32(priv->reg_pkeu + TALITOS_EUISR),
- in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
+ dev_err(dev, "PKEUISR 0x%08x_%08x\n", ioread32be(priv->reg_pkeu + TALITOS_EUISR),
+ ioread32be(priv->reg_pkeu + TALITOS_EUISR_LO));
break;
case DESC_HDR_SEL0_AESU:
- dev_err(dev, "AESUISR 0x%08x_%08x\n",
- in_be32(priv->reg_aesu + TALITOS_EUISR),
- in_be32(priv->reg_aesu + TALITOS_EUISR_LO));
+ dev_err(dev, "AESUISR 0x%08x_%08x\n", ioread32be(priv->reg_aesu + TALITOS_EUISR),
+ ioread32be(priv->reg_aesu + TALITOS_EUISR_LO));
break;
case DESC_HDR_SEL0_CRCU:
- dev_err(dev, "CRCUISR 0x%08x_%08x\n",
- in_be32(priv->reg_crcu + TALITOS_EUISR),
- in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
+ dev_err(dev, "CRCUISR 0x%08x_%08x\n", ioread32be(priv->reg_crcu + TALITOS_EUISR),
+ ioread32be(priv->reg_crcu + TALITOS_EUISR_LO));
break;
case DESC_HDR_SEL0_KEU:
- dev_err(dev, "KEUISR 0x%08x_%08x\n",
- in_be32(priv->reg_pkeu + TALITOS_EUISR),
- in_be32(priv->reg_pkeu + TALITOS_EUISR_LO));
+ dev_err(dev, "KEUISR 0x%08x_%08x\n", ioread32be(priv->reg_pkeu + TALITOS_EUISR),
+ ioread32be(priv->reg_pkeu + TALITOS_EUISR_LO));
break;
}
switch (desc_hdr & DESC_HDR_SEL1_MASK) {
case DESC_HDR_SEL1_MDEUA:
case DESC_HDR_SEL1_MDEUB:
- dev_err(dev, "MDEUISR 0x%08x_%08x\n",
- in_be32(priv->reg_mdeu + TALITOS_EUISR),
- in_be32(priv->reg_mdeu + TALITOS_EUISR_LO));
+ dev_err(dev, "MDEUISR 0x%08x_%08x\n", ioread32be(priv->reg_mdeu + TALITOS_EUISR),
+ ioread32be(priv->reg_mdeu + TALITOS_EUISR_LO));
break;
case DESC_HDR_SEL1_CRCU:
- dev_err(dev, "CRCUISR 0x%08x_%08x\n",
- in_be32(priv->reg_crcu + TALITOS_EUISR),
- in_be32(priv->reg_crcu + TALITOS_EUISR_LO));
+ dev_err(dev, "CRCUISR 0x%08x_%08x\n", ioread32be(priv->reg_crcu + TALITOS_EUISR),
+ ioread32be(priv->reg_crcu + TALITOS_EUISR_LO));
break;
}
for (i = 0; i < 8; i++)
dev_err(dev, "DESCBUF 0x%08x_%08x\n",
- in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
- in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
+ ioread32be(priv->chan[ch].reg + TALITOS_DESCBUF + 8 * i),
+ ioread32be(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8 * i));
}
/*
@@ -675,7 +676,7 @@ static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
error = -EINVAL;
- v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
+ v_lo = ioread32be(priv->chan[ch].reg + TALITOS_CCPSR_LO);
if (v_lo & TALITOS_CCPSR_LO_DOF) {
dev_err(dev, "double fetch fifo overflow error\n");
@@ -718,11 +719,14 @@ static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
if (reset_ch) {
reset_channel(dev, ch);
} else {
- setbits32(priv->chan[ch].reg + TALITOS_CCCR,
- TALITOS2_CCCR_CONT);
- setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
- while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
- TALITOS2_CCCR_CONT) && --timeout)
+ iowrite32be(ioread32be(priv->chan[ch].reg + TALITOS_CCCR) |
+ (TALITOS2_CCCR_CONT),
+ priv->chan[ch].reg + TALITOS_CCCR);
+ iowrite32be(ioread32be(priv->chan[ch].reg + TALITOS_CCCR_LO) | (0),
+ priv->chan[ch].reg + TALITOS_CCCR_LO);
+ while ((ioread32be(priv->chan[ch].reg + TALITOS_CCCR) &
+ TALITOS2_CCCR_CONT) &&
+ --timeout)
cpu_relax();
if (timeout == 0) {
dev_err(dev, "failed to restart channel %d\n",
@@ -749,73 +753,71 @@ static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
}
}
-#define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \
-static irqreturn_t talitos1_interrupt_##name(int irq, void *data) \
-{ \
- struct device *dev = data; \
- struct talitos_private *priv = dev_get_drvdata(dev); \
- u32 isr, isr_lo; \
- unsigned long flags; \
- \
- spin_lock_irqsave(&priv->reg_lock, flags); \
- isr = in_be32(priv->reg + TALITOS_ISR); \
- isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \
- /* Acknowledge interrupt */ \
- out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
- out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \
- \
- if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) { \
- spin_unlock_irqrestore(&priv->reg_lock, flags); \
- talitos_error(dev, isr & ch_err_mask, isr_lo); \
- } \
- else { \
- if (likely(isr & ch_done_mask)) { \
- /* mask further done interrupts. */ \
- setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
- /* done_task will unmask done interrupts at exit */ \
- tasklet_schedule(&priv->done_task[tlet]); \
- } \
- spin_unlock_irqrestore(&priv->reg_lock, flags); \
- } \
- \
- return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \
- IRQ_NONE; \
-}
+#define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \
+ static irqreturn_t talitos1_interrupt_##name(int irq, void *data) \
+ { \
+ struct device *dev = data; \
+ struct talitos_private *priv = dev_get_drvdata(dev); \
+ u32 isr, isr_lo; \
+ unsigned long flags; \
+ \
+ spin_lock_irqsave(&priv->reg_lock, flags); \
+ isr = ioread32be(priv->reg + TALITOS_ISR); \
+ isr_lo = ioread32be(priv->reg + TALITOS_ISR_LO); \
+ /* Acknowledge interrupt */ \
+ iowrite32be(isr & (ch_done_mask | ch_err_mask), priv->reg + TALITOS_ICR); \
+ iowrite32be(isr_lo, priv->reg + TALITOS_ICR_LO); \
+ \
+ if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) { \
+ spin_unlock_irqrestore(&priv->reg_lock, flags); \
+ talitos_error(dev, isr & ch_err_mask, isr_lo); \
+ } else { \
+ if (likely(isr & ch_done_mask)) { \
+ /* mask further done interrupts. */ \
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR) | (ch_done_mask), \
+ priv->reg + TALITOS_IMR); \
+ /* done_task will unmask done interrupts at exit */ \
+ tasklet_schedule(&priv->done_task[tlet]); \
+ } \
+ spin_unlock_irqrestore(&priv->reg_lock, flags); \
+ } \
+ \
+ return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : IRQ_NONE; \
+ }
DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0)
-#define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \
-static irqreturn_t talitos2_interrupt_##name(int irq, void *data) \
-{ \
- struct device *dev = data; \
- struct talitos_private *priv = dev_get_drvdata(dev); \
- u32 isr, isr_lo; \
- unsigned long flags; \
- \
- spin_lock_irqsave(&priv->reg_lock, flags); \
- isr = in_be32(priv->reg + TALITOS_ISR); \
- isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \
- /* Acknowledge interrupt */ \
- out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
- out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \
- \
- if (unlikely(isr & ch_err_mask || isr_lo)) { \
- spin_unlock_irqrestore(&priv->reg_lock, flags); \
- talitos_error(dev, isr & ch_err_mask, isr_lo); \
- } \
- else { \
- if (likely(isr & ch_done_mask)) { \
- /* mask further done interrupts. */ \
- clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
- /* done_task will unmask done interrupts at exit */ \
- tasklet_schedule(&priv->done_task[tlet]); \
- } \
- spin_unlock_irqrestore(&priv->reg_lock, flags); \
- } \
- \
- return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \
- IRQ_NONE; \
-}
+#define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \
+ static irqreturn_t talitos2_interrupt_##name(int irq, void *data) \
+ { \
+ struct device *dev = data; \
+ struct talitos_private *priv = dev_get_drvdata(dev); \
+ u32 isr, isr_lo; \
+ unsigned long flags; \
+ \
+ spin_lock_irqsave(&priv->reg_lock, flags); \
+ isr = ioread32be(priv->reg + TALITOS_ISR); \
+ isr_lo = ioread32be(priv->reg + TALITOS_ISR_LO); \
+ /* Acknowledge interrupt */ \
+ iowrite32be(isr & (ch_done_mask | ch_err_mask), priv->reg + TALITOS_ICR); \
+ iowrite32be(isr_lo, priv->reg + TALITOS_ICR_LO); \
+ \
+ if (unlikely(isr & ch_err_mask || isr_lo)) { \
+ spin_unlock_irqrestore(&priv->reg_lock, flags); \
+ talitos_error(dev, isr & ch_err_mask, isr_lo); \
+ } else { \
+ if (likely(isr & ch_done_mask)) { \
+ /* mask further done interrupts. */ \
+ iowrite32be(ioread32be(priv->reg + TALITOS_IMR) & ~(ch_done_mask), \
+ priv->reg + TALITOS_IMR); \
+ /* done_task will unmask done interrupts at exit */ \
+ tasklet_schedule(&priv->done_task[tlet]); \
+ } \
+ spin_unlock_irqrestore(&priv->reg_lock, flags); \
+ } \
+ \
+ return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : IRQ_NONE; \
+ }
DEF_TALITOS2_INTERRUPT(4ch, TALITOS2_ISR_4CHDONE, TALITOS2_ISR_4CHERR, 0)
DEF_TALITOS2_INTERRUPT(ch0_2, TALITOS2_ISR_CH_0_2_DONE, TALITOS2_ISR_CH_0_2_ERR,
@@ -834,8 +836,7 @@ static int talitos_rng_data_present(struct hwrng *rng, int wait)
int i;
for (i = 0; i < 20; i++) {
- ofl = in_be32(priv->reg_rngu + TALITOS_EUSR_LO) &
- TALITOS_RNGUSR_LO_OFL;
+ ofl = ioread32be(priv->reg_rngu + TALITOS_EUSR_LO) & TALITOS_RNGUSR_LO_OFL;
if (ofl || !wait)
break;
udelay(10);
@@ -850,8 +851,8 @@ static int talitos_rng_data_read(struct hwrng *rng, u32 *data)
struct talitos_private *priv = dev_get_drvdata(dev);
/* rng fifo requires 64-bit accesses */
- *data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO);
- *data = in_be32(priv->reg_rngu + TALITOS_EU_FIFO_LO);
+ *data = ioread32be(priv->reg_rngu + TALITOS_EU_FIFO);
+ *data = ioread32be(priv->reg_rngu + TALITOS_EU_FIFO_LO);
return sizeof(u32);
}
@@ -862,10 +863,9 @@ static int talitos_rng_init(struct hwrng *rng)
struct talitos_private *priv = dev_get_drvdata(dev);
unsigned int timeout = TALITOS_TIMEOUT;
- setbits32(priv->reg_rngu + TALITOS_EURCR_LO, TALITOS_RNGURCR_LO_SR);
- while (!(in_be32(priv->reg_rngu + TALITOS_EUSR_LO)
- & TALITOS_RNGUSR_LO_RD)
- && --timeout)
+ iowrite32be(ioread32be(priv->reg_rngu + TALITOS_EURCR_LO) | (TALITOS_RNGURCR_LO_SR),
+ priv->reg_rngu + TALITOS_EURCR_LO);
+ while (!(ioread32be(priv->reg_rngu + TALITOS_EUSR_LO) & TALITOS_RNGUSR_LO_RD) && --timeout)
cpu_relax();
if (timeout == 0) {
dev_err(dev, "failed to reset rng hw\n");
@@ -873,7 +873,8 @@ static int talitos_rng_init(struct hwrng *rng)
}
/* start generating */
- setbits32(priv->reg_rngu + TALITOS_EUDSR_LO, 0);
+ iowrite32be(ioread32be(priv->reg_rngu + TALITOS_EUDSR_LO) | (0),
+ priv->reg_rngu + TALITOS_EUDSR_LO);
return 0;
}
--
2.54.0
^ permalink raw reply related
* [PATCH 2/2] crypto: atmel-ecc - clean up and improve ECDH comments
From: Thorsten Blum @ 2026-06-03 19:27 UTC (permalink / raw)
To: Thorsten Blum, Herbert Xu, David S. Miller, Nicolas Ferre,
Alexandre Belloni, Claudiu Beznea
Cc: linux-crypto, linux-arm-kernel, linux-kernel
In-Reply-To: <20260603192708.1237715-4-thorsten.blum@linux.dev>
Improve the kerneldoc for struct atmel_ecdh_ctx by removing the stale
"unsupported curves" wording, since the device only supports a single
curve (P-256), and move the set_secret() constraint to the description.
In atmel_ecdh_set_secret(), clarify that the device generates the
private key, and drop the redundant "only supports NIST P256" comment.
In atmel_ecdh_done() and atmel_ecdh_generate_public_key(), clarify the
truncation comments. Also note that a P-256 public key consists of two
32-byte coordinates in atmel_ecdh_compute_shared_secret(), and remove
the unnecessary fall-through comment and other redundant comments.
Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
---
drivers/crypto/atmel-ecc.c | 37 ++++++++++++++-----------------------
1 file changed, 14 insertions(+), 23 deletions(-)
diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index 9387eea4513d..1443e18a9cee 100644
--- a/drivers/crypto/atmel-ecc.c
+++ b/drivers/crypto/atmel-ecc.c
@@ -27,15 +27,15 @@ static struct atmel_ecc_driver_data driver_data;
/**
* struct atmel_ecdh_ctx - transformation context
- * @client : pointer to i2c client device
- * @fallback : used for unsupported curves or when user wants to use its own
- * private key.
- * @public_key : generated when calling set_secret(). It's the responsibility
- * of the user to not call set_secret() while
- * generate_public_key() or compute_shared_secret() are in flight.
+ * @client : I2C client device
+ * @fallback : ECDH fallback used for caller-provided private keys
+ * @public_key : cached public key corresponding to the device-generated
+ * private key
* @curve_id : elliptic curve id
- * @do_fallback: true when the device doesn't support the curve or when the user
- * wants to use its own private key.
+ * @do_fallback: true when ECDH operations should use @fallback
+ *
+ * The caller must not invoke set_secret() while generate_public_key()
+ * or compute_shared_secret() are in flight.
*/
struct atmel_ecdh_ctx {
struct i2c_client *client;
@@ -55,7 +55,7 @@ static void atmel_ecdh_done(struct atmel_i2c_work_data *work_data, void *areq,
if (status)
goto free_work_data;
- /* might want less than we've got */
+ /* copy only as much as requested, capped at 32 bytes */
n_sz = min(ATMEL_ECC_NIST_P256_N_SIZE, req->dst_len);
/* copy the shared secret */
@@ -64,15 +64,15 @@ static void atmel_ecdh_done(struct atmel_i2c_work_data *work_data, void *areq,
if (copied != n_sz)
status = -EINVAL;
- /* fall through */
free_work_data:
kfree_sensitive(work_data);
kpp_request_complete(req, status);
}
/*
- * A random private key is generated and stored in the device. The device
- * returns the pair public key.
+ * If no private key is provided, generate one in the device and cache
+ * the corresponding public key. The generated private key never leaves
+ * the device.
*/
static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
unsigned int len)
@@ -83,9 +83,7 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
struct ecdh params;
int ret = -ENOMEM;
- /* free the old public key, if any */
kfree(ctx->public_key);
- /* make sure you don't free the old public key twice */
ctx->public_key = NULL;
if (crypto_ecdh_decode_key(buf, len, ¶ms) < 0) {
@@ -94,7 +92,6 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
}
if (params.key_size) {
- /* fallback to ecdh software implementation */
ctx->do_fallback = true;
return crypto_kpp_set_secret(ctx->fallback, buf, len);
}
@@ -103,11 +100,6 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
if (!cmd)
return -ENOMEM;
- /*
- * The device only supports NIST P256 ECC keys. The public key size will
- * always be the same. Use a macro for the key size to avoid unnecessary
- * computations.
- */
public_key = kmalloc(ATMEL_ECC_PUBKEY_SIZE, GFP_KERNEL);
if (!public_key)
goto free_cmd;
@@ -120,7 +112,6 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
if (ret)
goto free_public_key;
- /* save the public key */
memcpy(public_key, &cmd->data[RSP_DATA_IDX], ATMEL_ECC_PUBKEY_SIZE);
ctx->public_key = public_key;
@@ -149,7 +140,7 @@ static int atmel_ecdh_generate_public_key(struct kpp_request *req)
if (!ctx->public_key)
return -EINVAL;
- /* might want less than we've got */
+ /* copy only as much as requested, capped at 64 bytes */
nbytes = min(ATMEL_ECC_PUBKEY_SIZE, req->dst_len);
/* public key was saved at private key generation */
@@ -175,7 +166,7 @@ static int atmel_ecdh_compute_shared_secret(struct kpp_request *req)
return crypto_kpp_compute_shared_secret(req);
}
- /* must have exactly two points to be on the curve */
+ /* A P-256 public key must contain two 32-byte coordinates */
if (req->src_len != ATMEL_ECC_PUBKEY_SIZE)
return -EINVAL;
^ permalink raw reply related
* [PATCH 1/2] crypto: atmel-i2c - improve comment in atmel_i2c_init_ecdh_cmd
From: Thorsten Blum @ 2026-06-03 19:27 UTC (permalink / raw)
To: Herbert Xu, David S. Miller, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea
Cc: Thorsten Blum, linux-crypto, linux-arm-kernel, linux-kernel
Clarify that a P-256 public key is encoded as two 32-byte coordinates.
Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
---
drivers/crypto/atmel-i2c.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c
index ff19857894d0..24bded47a32b 100644
--- a/drivers/crypto/atmel-i2c.c
+++ b/drivers/crypto/atmel-i2c.c
@@ -138,9 +138,8 @@ int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd,
cmd->param2 = cpu_to_le16(DATA_SLOT_2);
/*
- * The device only supports NIST P256 ECC keys. The public key size will
- * always be the same. Use a macro for the key size to avoid unnecessary
- * computations.
+ * The device only supports P-256. Its public key is encoded as
+ * two 32-byte coordinates.
*/
copied = sg_copy_to_buffer(pubkey,
sg_nents_for_len(pubkey,
^ permalink raw reply related
* Re: [PATCH] crypto: testmgr - allow authenc(hmac(sha{256,384}),cts(cbc(aes))) in FIPS mode
From: Viacheslav Dubeyko @ 2026-06-03 17:12 UTC (permalink / raw)
To: Ilya Dryomov, Herbert Xu
Cc: David Howells, linux-crypto, ceph-devel, linux-kernel
In-Reply-To: <20260603155008.736872-1-idryomov@gmail.com>
On Wed, 2026-06-03 at 17:50 +0200, Ilya Dryomov wrote:
> hmac(sha256), hmac(sha384) and cts(cbc(aes)) algorithms have been
> marked as FIPS allowed for years. Mark the respective authenc()
> constructions per RFC 8009 ("AES Encryption with HMAC-SHA2 for
> Kerberos 5") as such as well.
>
> SP 800-57 Part 3 Rev. 1 from Jan 2015 [1] links the draft of what
> became RFC 8009 in Oct 2016 as approved in section 6.3 Procurement
> Guidance (item/recommendation 3).
>
> [1] https://csrc.nist.gov/pubs/sp/800/57/pt3/r1/final
>
> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
> ---
> crypto/testmgr.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/crypto/testmgr.c b/crypto/testmgr.c
> index 4d86efae65b2..7788e6fa80ce 100644
> --- a/crypto/testmgr.c
> +++ b/crypto/testmgr.c
> @@ -4215,6 +4215,7 @@ static const struct alg_test_desc
> alg_test_descs[] = {
> .alg = "authenc(hmac(sha256),cts(cbc(aes)))",
> .generic_driver = "authenc(hmac-sha256-
> lib,cts(cbc(aes-lib)))",
> .test = alg_test_aead,
> + .fips_allowed = 1,
> .suite = {
> .aead =
> __VECS(krb5_test_aes128_cts_hmac_sha256_128)
> }
> @@ -4256,6 +4257,7 @@ static const struct alg_test_desc
> alg_test_descs[] = {
> .alg = "authenc(hmac(sha384),cts(cbc(aes)))",
> .generic_driver = "authenc(hmac-sha384-
> lib,cts(cbc(aes-lib)))",
> .test = alg_test_aead,
> + .fips_allowed = 1,
> .suite = {
> .aead =
> __VECS(krb5_test_aes256_cts_hmac_sha384_192)
> }
Makes sense.
Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
Thanks,
Slava.
^ permalink raw reply
* [PATCH] crypto: testmgr - allow authenc(hmac(sha{256,384}),cts(cbc(aes))) in FIPS mode
From: Ilya Dryomov @ 2026-06-03 15:50 UTC (permalink / raw)
To: Herbert Xu; +Cc: David Howells, linux-crypto, ceph-devel, linux-kernel
hmac(sha256), hmac(sha384) and cts(cbc(aes)) algorithms have been
marked as FIPS allowed for years. Mark the respective authenc()
constructions per RFC 8009 ("AES Encryption with HMAC-SHA2 for
Kerberos 5") as such as well.
SP 800-57 Part 3 Rev. 1 from Jan 2015 [1] links the draft of what
became RFC 8009 in Oct 2016 as approved in section 6.3 Procurement
Guidance (item/recommendation 3).
[1] https://csrc.nist.gov/pubs/sp/800/57/pt3/r1/final
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
---
crypto/testmgr.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 4d86efae65b2..7788e6fa80ce 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -4215,6 +4215,7 @@ static const struct alg_test_desc alg_test_descs[] = {
.alg = "authenc(hmac(sha256),cts(cbc(aes)))",
.generic_driver = "authenc(hmac-sha256-lib,cts(cbc(aes-lib)))",
.test = alg_test_aead,
+ .fips_allowed = 1,
.suite = {
.aead = __VECS(krb5_test_aes128_cts_hmac_sha256_128)
}
@@ -4256,6 +4257,7 @@ static const struct alg_test_desc alg_test_descs[] = {
.alg = "authenc(hmac(sha384),cts(cbc(aes)))",
.generic_driver = "authenc(hmac-sha384-lib,cts(cbc(aes-lib)))",
.test = alg_test_aead,
+ .fips_allowed = 1,
.suite = {
.aead = __VECS(krb5_test_aes256_cts_hmac_sha384_192)
}
--
2.54.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox