Hi Iulia, On 11/17/19 11:30 PM, Iuliana Prodan wrote: > Integrate crypto_engine into CAAM, to make use of the engine queue. > Add support for SKCIPHER algorithms. > > This is intended to be used for CAAM backlogging support. > The requests, with backlog flag (e.g. from dm-crypt) will be listed > into crypto-engine queue and processed by CAAM when free. > This changes the return codes for caam_jr_enqueue: > -EINPROGRESS if OK, -EBUSY if request is backlogged, > -ENOSPC if the queue is full, -EIO if it cannot map the caller's > descriptor, -EINVAL if crypto_tfm not supported by crypto_engine. > > Signed-off-by: Iuliana Prodan <iuliana.prodan@xxxxxxx> > Signed-off-by: Franck LENORMAND <franck.lenormand@xxxxxxx> > Reviewed-by: Horia Geantă <horia.geanta@xxxxxxx> > --- > drivers/crypto/caam/Kconfig | 1 + > drivers/crypto/caam/caamalg.c | 84 +++++++++++++++++++++++++++++++++++-------- > drivers/crypto/caam/intern.h | 2 ++ > drivers/crypto/caam/jr.c | 51 ++++++++++++++++++++++++-- > 4 files changed, 122 insertions(+), 16 deletions(-) > > diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig > index 87053e4..1930e19 100644 > --- a/drivers/crypto/caam/Kconfig > +++ b/drivers/crypto/caam/Kconfig > @@ -33,6 +33,7 @@ config CRYPTO_DEV_FSL_CAAM_DEBUG > > menuconfig CRYPTO_DEV_FSL_CAAM_JR > tristate "Freescale CAAM Job Ring driver backend" > + select CRYPTO_ENGINE > default y > help > Enables the driver module for Job Rings which are part of > diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c > index abebcfc..23de94d 100644 > --- a/drivers/crypto/caam/caamalg.c > +++ b/drivers/crypto/caam/caamalg.c > @@ -56,6 +56,7 @@ > #include "sg_sw_sec4.h" > #include "key_gen.h" > #include "caamalg_desc.h" > +#include <crypto/engine.h> > > /* > * crypto alg > @@ -101,6 +102,7 @@ struct caam_skcipher_alg { > * per-session context > */ > struct caam_ctx { > + struct crypto_engine_ctx enginectx; > u32 sh_desc_enc[DESC_MAX_USED_LEN]; > u32 sh_desc_dec[DESC_MAX_USED_LEN]; > u8 key[CAAM_MAX_KEY_SIZE]; > @@ -114,6 +116,12 @@ struct caam_ctx { > unsigned int authsize; > }; > > +struct caam_skcipher_req_ctx { > + struct skcipher_edesc *edesc; > + void (*skcipher_op_done)(struct device *jrdev, u32 *desc, u32 err, > + void *context); > +}; > + > static int aead_null_set_sh_desc(struct crypto_aead *aead) > { > struct caam_ctx *ctx = crypto_aead_ctx(aead); > @@ -992,13 +1000,15 @@ static void skcipher_crypt_done(struct device *jrdev, u32 *desc, u32 err, > struct caam_jr_request_entry *jrentry = context; > struct skcipher_request *req = skcipher_request_cast(jrentry->base); > struct skcipher_edesc *edesc; > + struct caam_skcipher_req_ctx *rctx = skcipher_request_ctx(req); > struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); > + struct caam_drv_private_jr *jrp = dev_get_drvdata(jrdev); > int ivsize = crypto_skcipher_ivsize(skcipher); > int ecode = 0; > > dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); > > - edesc = container_of(desc, struct skcipher_edesc, hw_desc[0]); > + edesc = rctx->edesc; > if (err) > ecode = caam_jr_strstatus(jrdev, err); > > @@ -1024,7 +1034,14 @@ static void skcipher_crypt_done(struct device *jrdev, u32 *desc, u32 err, > > kfree(edesc); > > - skcipher_request_complete(req, ecode); > + /* > + * If no backlog flag, the completion of the request is done > + * by CAAM, not crypto engine. > + */ > + if (!jrentry->bklog) > + skcipher_request_complete(req, ecode); > + else > + crypto_finalize_skcipher_request(jrp->engine, req, ecode); > } > > /* > @@ -1553,6 +1570,7 @@ static struct skcipher_edesc *skcipher_edesc_alloc(struct skcipher_request *req, > { > struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); > struct caam_ctx *ctx = crypto_skcipher_ctx(skcipher); > + struct caam_skcipher_req_ctx *rctx = skcipher_request_ctx(req); > struct device *jrdev = ctx->jrdev; > gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? > GFP_KERNEL : GFP_ATOMIC; > @@ -1653,6 +1671,9 @@ static struct skcipher_edesc *skcipher_edesc_alloc(struct skcipher_request *req, > desc_bytes); > edesc->jrentry.base = &req->base; > > + rctx->edesc = edesc; > + rctx->skcipher_op_done = skcipher_crypt_done; > + > /* Make sure IV is located in a DMAable area */ > if (ivsize) { > iv = (u8 *)edesc->sec4_sg + sec4_sg_bytes; > @@ -1707,13 +1728,37 @@ static struct skcipher_edesc *skcipher_edesc_alloc(struct skcipher_request *req, > return edesc; > } > > +static int skcipher_do_one_req(struct crypto_engine *engine, void *areq) > +{ > + struct skcipher_request *req = skcipher_request_cast(areq); > + struct caam_ctx *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req)); > + struct caam_skcipher_req_ctx *rctx = skcipher_request_ctx(req); > + struct caam_jr_request_entry *jrentry; > + u32 *desc = rctx->edesc->hw_desc; > + int ret; > + > + jrentry = &rctx->edesc->jrentry; > + jrentry->bklog = true; > + > + ret = caam_jr_enqueue_no_bklog(ctx->jrdev, desc, > + rctx->skcipher_op_done, jrentry); > + > + if (ret != -EINPROGRESS) { > + skcipher_unmap(ctx->jrdev, rctx->edesc, req); > + kfree(rctx->edesc); > + } else { > + ret = 0; > + } > + > + return ret; While testing this on a i.MX6 DualLite I see -ENOSPC being returned here after a couple of GiB of data being encrypted (via dm-crypt with LUKS extension). This results in these messages from crypto_engine: caam_jr 2101000.jr0: Failed to do one request from queue: -28 And later.. Buffer I/O error on device dm-0, logical block 59392 JBD2: Detected IO errors while flushing file data on dm-0-8 Reproducible with something like this: echo "testkey" | cryptsetup luksFormat \ --cipher=aes-cbc-essiv:sha256 \ --key-file=- \ --key-size=256 \ /dev/mmcblk1p8 echo "testkey" | cryptsetup open \ --type luks \ --key-file=- \ /dev/mmcblk1p8 data mkfs.ext4 /dev/mapper/data mount /dev/mapper/data /mnt set -x while [ true ]; do dd if=/dev/zero of=/mnt/big_file bs=1M count=1024 sync done Any ideas? Regards, Bastian > +} > + > static inline int skcipher_crypt(struct skcipher_request *req, bool encrypt) > { > struct skcipher_edesc *edesc; > struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); > struct caam_ctx *ctx = crypto_skcipher_ctx(skcipher); > struct device *jrdev = ctx->jrdev; > - struct caam_jr_request_entry *jrentry; > u32 *desc; > int ret = 0; > > @@ -1727,16 +1772,15 @@ static inline int skcipher_crypt(struct skcipher_request *req, bool encrypt) > > /* Create and submit job descriptor*/ > init_skcipher_job(req, edesc, encrypt); > + desc = edesc->hw_desc; > > print_hex_dump_debug("skcipher jobdesc@" __stringify(__LINE__)": ", > - DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc, > - desc_bytes(edesc->hw_desc), 1); > - > - desc = edesc->hw_desc; > - jrentry = &edesc->jrentry; > + DUMP_PREFIX_ADDRESS, 16, 4, desc, > + desc_bytes(desc), 1); > > - ret = caam_jr_enqueue(jrdev, desc, skcipher_crypt_done, jrentry); > - if (ret != -EINPROGRESS) { > + ret = caam_jr_enqueue(jrdev, desc, skcipher_crypt_done, > + &edesc->jrentry); > + if ((ret != -EINPROGRESS) && (ret != -EBUSY)) { > skcipher_unmap(jrdev, edesc, req); > kfree(edesc); > } > @@ -3272,7 +3316,9 @@ static int caam_init_common(struct caam_ctx *ctx, struct caam_alg_entry *caam, > > dma_addr = dma_map_single_attrs(ctx->jrdev, ctx->sh_desc_enc, > offsetof(struct caam_ctx, > - sh_desc_enc_dma), > + sh_desc_enc_dma) - > + offsetof(struct caam_ctx, > + sh_desc_enc), > ctx->dir, DMA_ATTR_SKIP_CPU_SYNC); > if (dma_mapping_error(ctx->jrdev, dma_addr)) { > dev_err(ctx->jrdev, "unable to map key, shared descriptors\n"); > @@ -3282,8 +3328,12 @@ static int caam_init_common(struct caam_ctx *ctx, struct caam_alg_entry *caam, > > ctx->sh_desc_enc_dma = dma_addr; > ctx->sh_desc_dec_dma = dma_addr + offsetof(struct caam_ctx, > - sh_desc_dec); > - ctx->key_dma = dma_addr + offsetof(struct caam_ctx, key); > + sh_desc_dec) - > + offsetof(struct caam_ctx, > + sh_desc_enc); > + ctx->key_dma = dma_addr + offsetof(struct caam_ctx, key) - > + offsetof(struct caam_ctx, > + sh_desc_enc); > > /* copy descriptor header template value */ > ctx->cdata.algtype = OP_TYPE_CLASS1_ALG | caam->class1_alg_type; > @@ -3297,6 +3347,11 @@ static int caam_cra_init(struct crypto_skcipher *tfm) > struct skcipher_alg *alg = crypto_skcipher_alg(tfm); > struct caam_skcipher_alg *caam_alg = > container_of(alg, typeof(*caam_alg), skcipher); > + struct caam_ctx *ctx = crypto_skcipher_ctx(tfm); > + > + crypto_skcipher_set_reqsize(tfm, sizeof(struct caam_skcipher_req_ctx)); > + > + ctx->enginectx.op.do_one_request = skcipher_do_one_req; > > return caam_init_common(crypto_skcipher_ctx(tfm), &caam_alg->caam, > false); > @@ -3315,7 +3370,8 @@ static int caam_aead_init(struct crypto_aead *tfm) > static void caam_exit_common(struct caam_ctx *ctx) > { > dma_unmap_single_attrs(ctx->jrdev, ctx->sh_desc_enc_dma, > - offsetof(struct caam_ctx, sh_desc_enc_dma), > + offsetof(struct caam_ctx, sh_desc_enc_dma) - > + offsetof(struct caam_ctx, sh_desc_enc), > ctx->dir, DMA_ATTR_SKIP_CPU_SYNC); > caam_jr_free(ctx->jrdev); > } > diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h > index 58be66c..31abb94 100644 > --- a/drivers/crypto/caam/intern.h > +++ b/drivers/crypto/caam/intern.h > @@ -12,6 +12,7 @@ > > #include "ctrl.h" > #include "regs.h" > +#include <crypto/engine.h> > > /* Currently comes from Kconfig param as a ^2 (driver-required) */ > #define JOBR_DEPTH (1 << CONFIG_CRYPTO_DEV_FSL_CAAM_RINGSIZE) > @@ -61,6 +62,7 @@ struct caam_drv_private_jr { > int out_ring_read_index; /* Output index "tail" */ > int tail; /* entinfo (s/w ring) tail index */ > void *outring; /* Base of output ring, DMA-safe */ > + struct crypto_engine *engine; > }; > > /* > diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c > index 544cafa..5c55d3d 100644 > --- a/drivers/crypto/caam/jr.c > +++ b/drivers/crypto/caam/jr.c > @@ -62,6 +62,15 @@ static void unregister_algs(void) > mutex_unlock(&algs_lock); > } > > +static void caam_jr_crypto_engine_exit(void *data) > +{ > + struct device *jrdev = data; > + struct caam_drv_private_jr *jrpriv = dev_get_drvdata(jrdev); > + > + /* Free the resources of crypto-engine */ > + crypto_engine_exit(jrpriv->engine); > +} > + > static int caam_reset_hw_jr(struct device *dev) > { > struct caam_drv_private_jr *jrp = dev_get_drvdata(dev); > @@ -418,10 +427,23 @@ int caam_jr_enqueue_no_bklog(struct device *dev, u32 *desc, > } > EXPORT_SYMBOL(caam_jr_enqueue_no_bklog); > > +static int transfer_request_to_engine(struct crypto_engine *engine, > + struct crypto_async_request *req) > +{ > + switch (crypto_tfm_alg_type(req->tfm)) { > + case CRYPTO_ALG_TYPE_SKCIPHER: > + return crypto_transfer_skcipher_request_to_engine(engine, > + skcipher_request_cast(req)); > + default: > + return -EINVAL; > + } > +} > + > /** > * caam_jr_enqueue() - Enqueue a job descriptor head. Returns -EINPROGRESS > - * if OK, -ENOSPC if the queue is full, -EIO if it cannot map the caller's > - * descriptor. > + * if OK, -EBUSY if request is backlogged, -ENOSPC if the queue is full, > + * -EIO if it cannot map the caller's descriptor, -EINVAL if crypto_tfm > + * not supported by crypto_engine. > * @dev: device of the job ring to be used. This device should have > * been assigned prior by caam_jr_register(). > * @desc: points to a job descriptor that execute our request. All > @@ -451,7 +473,12 @@ int caam_jr_enqueue(struct device *dev, u32 *desc, > u32 status, void *areq), > void *areq) > { > + struct caam_drv_private_jr *jrpriv = dev_get_drvdata(dev); > struct caam_jr_request_entry *jrentry = areq; > + struct crypto_async_request *req = jrentry->base; > + > + if (req->flags & CRYPTO_TFM_REQ_MAY_BACKLOG) > + return transfer_request_to_engine(jrpriv->engine, req); > > return caam_jr_enqueue_no_bklog(dev, desc, cbk, jrentry); > } > @@ -577,6 +604,26 @@ static int caam_jr_probe(struct platform_device *pdev) > return error; > } > > + /* Initialize crypto engine */ > + jrpriv->engine = crypto_engine_alloc_init(jrdev, false); > + if (!jrpriv->engine) { > + dev_err(jrdev, "Could not init crypto-engine\n"); > + return -ENOMEM; > + } > + > + /* Start crypto engine */ > + error = crypto_engine_start(jrpriv->engine); > + if (error) { > + dev_err(jrdev, "Could not start crypto-engine\n"); > + crypto_engine_exit(jrpriv->engine); > + return error; > + } > + > + error = devm_add_action_or_reset(jrdev, caam_jr_crypto_engine_exit, > + jrdev); > + if (error) > + return error; > + > /* Identify the interrupt */ > jrpriv->irq = irq_of_parse_and_map(nprop, 0); > if (!jrpriv->irq) { > -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |