crypto: starfive - RSA poll csr for done status

Hardware could not clear irq status without resetting the entire module.
Driver receives irq immediately when mask bit is cleared causing
intermittent errors in RSA calculations. Switch to use csr polling for
done status instead.

Signed-off-by: Jia Jie Ho <jiajie.ho@starfivetech.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
Jia Jie Ho 2023-11-15 01:12:14 +08:00 committed by Herbert Xu
parent 29ce1bce3a
commit ba6e3ee4f5
3 changed files with 22 additions and 45 deletions

View File

@ -109,12 +109,6 @@ static irqreturn_t starfive_cryp_irq(int irq, void *priv)
tasklet_schedule(&cryp->hash_done);
}
if (status & STARFIVE_IE_FLAG_PKA_DONE) {
mask |= STARFIVE_IE_MASK_PKA_DONE;
writel(mask, cryp->base + STARFIVE_IE_MASK_OFFSET);
complete(&cryp->pka_done);
}
return IRQ_HANDLED;
}
@ -159,8 +153,6 @@ static int starfive_cryp_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, PTR_ERR(cryp->rst),
"Error getting hardware reset line\n");
init_completion(&cryp->pka_done);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;

View File

@ -125,6 +125,15 @@ union starfive_pka_cacr {
};
};
union starfive_pka_casr {
u32 v;
struct {
#define STARFIVE_PKA_DONE BIT(0)
u32 done :1;
u32 rsvd_0 :31;
};
};
struct starfive_rsa_key {
u8 *n;
u8 *e;
@ -183,7 +192,6 @@ struct starfive_cryp_dev {
struct crypto_engine *engine;
struct tasklet_struct aes_done;
struct tasklet_struct hash_done;
struct completion pka_done;
size_t assoclen;
size_t total_in;
size_t total_out;

View File

@ -6,13 +6,7 @@
*/
#include <linux/crypto.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-direct.h>
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/io.h>
#include <linux/mod_devicetable.h>
#include <crypto/akcipher.h>
#include <crypto/algapi.h>
#include <crypto/internal/akcipher.h>
@ -28,13 +22,13 @@
#define STARFIVE_PKA_CAER_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x108)
#define STARFIVE_PKA_CANR_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x208)
// R^2 mod N and N0'
/* R ^ 2 mod N and N0' */
#define CRYPTO_CMD_PRE 0x0
// A * R mod N ==> A
/* A * R mod N ==> A */
#define CRYPTO_CMD_ARN 0x5
// A * E * R mod N ==> A
/* A * E * R mod N ==> A */
#define CRYPTO_CMD_AERN 0x6
// A * A * R mod N ==> A
/* A * A * R mod N ==> A */
#define CRYPTO_CMD_AARN 0x7
#define STARFIVE_RSA_MAX_KEYSZ 256
@ -43,21 +37,10 @@
static inline int starfive_pka_wait_done(struct starfive_cryp_ctx *ctx)
{
struct starfive_cryp_dev *cryp = ctx->cryp;
u32 status;
return wait_for_completion_timeout(&cryp->pka_done,
usecs_to_jiffies(100000));
}
static inline void starfive_pka_irq_mask_clear(struct starfive_cryp_ctx *ctx)
{
struct starfive_cryp_dev *cryp = ctx->cryp;
u32 stat;
stat = readl(cryp->base + STARFIVE_IE_MASK_OFFSET);
stat &= ~STARFIVE_IE_MASK_PKA_DONE;
writel(stat, cryp->base + STARFIVE_IE_MASK_OFFSET);
reinit_completion(&cryp->pka_done);
return readl_relaxed_poll_timeout(cryp->base + STARFIVE_PKA_CASR_OFFSET, status,
status & STARFIVE_PKA_DONE, 10, 100000);
}
static void starfive_rsa_free_key(struct starfive_rsa_key *key)
@ -114,10 +97,9 @@ static int starfive_rsa_montgomery_form(struct starfive_cryp_ctx *ctx,
rctx->csr.pka.not_r2 = 1;
rctx->csr.pka.ie = 1;
starfive_pka_irq_mask_clear(ctx);
writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
if (!starfive_pka_wait_done(ctx))
if (starfive_pka_wait_done(ctx))
return -ETIMEDOUT;
for (loop = 0; loop <= opsize; loop++)
@ -136,10 +118,9 @@ static int starfive_rsa_montgomery_form(struct starfive_cryp_ctx *ctx,
rctx->csr.pka.start = 1;
rctx->csr.pka.ie = 1;
starfive_pka_irq_mask_clear(ctx);
writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
if (!starfive_pka_wait_done(ctx))
if (starfive_pka_wait_done(ctx))
return -ETIMEDOUT;
} else {
rctx->csr.pka.v = 0;
@ -151,10 +132,9 @@ static int starfive_rsa_montgomery_form(struct starfive_cryp_ctx *ctx,
rctx->csr.pka.pre_expf = 1;
rctx->csr.pka.ie = 1;
starfive_pka_irq_mask_clear(ctx);
writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
if (!starfive_pka_wait_done(ctx))
if (starfive_pka_wait_done(ctx))
return -ETIMEDOUT;
for (loop = 0; loop <= count; loop++)
@ -172,10 +152,9 @@ static int starfive_rsa_montgomery_form(struct starfive_cryp_ctx *ctx,
rctx->csr.pka.start = 1;
rctx->csr.pka.ie = 1;
starfive_pka_irq_mask_clear(ctx);
writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
if (!starfive_pka_wait_done(ctx))
if (starfive_pka_wait_done(ctx))
return -ETIMEDOUT;
}
@ -226,11 +205,10 @@ static int starfive_rsa_cpu_start(struct starfive_cryp_ctx *ctx, u32 *result,
rctx->csr.pka.start = 1;
rctx->csr.pka.ie = 1;
starfive_pka_irq_mask_clear(ctx);
writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
ret = -ETIMEDOUT;
if (!starfive_pka_wait_done(ctx))
if (starfive_pka_wait_done(ctx))
goto rsa_err;
if (mlen) {
@ -242,10 +220,9 @@ static int starfive_rsa_cpu_start(struct starfive_cryp_ctx *ctx, u32 *result,
rctx->csr.pka.start = 1;
rctx->csr.pka.ie = 1;
starfive_pka_irq_mask_clear(ctx);
writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
if (!starfive_pka_wait_done(ctx))
if (starfive_pka_wait_done(ctx))
goto rsa_err;
}
}