Job rings are an integral part of underlying CAAM IP and treating them as independent devices means that we have to: 1. Properly maintain device reference counter via (get_device/put_device). Currently not implemented 2. Properly coordinate lifecycle of the underlying platform device (e.g. removal via 'unbind') with active users of that JR. Not implemented currently as well. 3. Have extra logic to initialize crypto algorithms after at least one JR has been registered (see register_algs() and related code) Instead of adding extra code to deal with #1 and #2 above and open up the possibility of simpliying #3, convert the driver to not create platform devices for available JR and instead treat them as internal implementation detail while providing same API to all of the original users. Signed-off-by: Andrey Smirnov <andrew.smirnov@xxxxxxxxx> Cc: Chris Healy <cphealy@xxxxxxxxx> Cc: Lucas Stach <l.stach@xxxxxxxxxxxxxx> Cc: Horia Geantă <horia.geanta@xxxxxxx> Cc: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx> Cc: Iuliana Prodan <iuliana.prodan@xxxxxxx> Cc: linux-imx@xxxxxxx Cc: linux-crypto@xxxxxxxxxxxxxxx Cc: linux-kernel@xxxxxxxxxxxxxxx --- drivers/crypto/caam/Kconfig | 5 +- drivers/crypto/caam/Makefile | 15 ++-- drivers/crypto/caam/caamalg.c | 10 +-- drivers/crypto/caam/caamalg_qi.c | 4 +- drivers/crypto/caam/caamhash.c | 6 +- drivers/crypto/caam/ctrl.c | 15 +++- drivers/crypto/caam/jr.c | 136 +++++++------------------------ drivers/crypto/caam/jr.h | 1 + 8 files changed, 62 insertions(+), 130 deletions(-) diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig index 137ed3df0c74..86ab869e4176 100644 --- a/drivers/crypto/caam/Kconfig +++ b/drivers/crypto/caam/Kconfig @@ -32,7 +32,7 @@ config CRYPTO_DEV_FSL_CAAM_DEBUG information in the CAAM driver. menuconfig CRYPTO_DEV_FSL_CAAM_JR - tristate "Freescale CAAM Job Ring driver backend" + bool "Freescale CAAM Job Ring driver backend" default y help Enables the driver module for Job Rings which are part of @@ -40,9 +40,6 @@ menuconfig CRYPTO_DEV_FSL_CAAM_JR and Assurance Module (CAAM). This module adds a job ring operation interface. - To compile this driver as a module, choose M here: the module - will be called caam_jr. - if CRYPTO_DEV_FSL_CAAM_JR config CRYPTO_DEV_FSL_CAAM_RINGSIZE diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile index 68d5cc0f28e2..ab6c094f8bd8 100644 --- a/drivers/crypto/caam/Makefile +++ b/drivers/crypto/caam/Makefile @@ -10,17 +10,18 @@ ccflags-y += -DVERSION=\"\" obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_COMMON) += error.o obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o -obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR) += caam_jr.o obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC) += caamalg_desc.o obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API_DESC) += caamhash_desc.o caam-y := ctrl.o -caam_jr-y := jr.o key_gen.o -caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o -caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += caamalg_qi.o -caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o -caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o -caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caampkc.o pkc_desc.o +ifneq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_JR),) +caam-y += jr.o key_gen.o +caam-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o +caam-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += caamalg_qi.o +caam-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o +caam-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o +caam-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caampkc.o pkc_desc.o +endif caam-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += qi.o ifneq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI),) diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 4cb7d5b281cc..f2230256ef9f 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -118,7 +118,7 @@ static int aead_null_set_sh_desc(struct crypto_aead *aead) { struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *jrdev = ctx->jr->dev; - struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev->parent); + struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev); u32 *desc; int rem_bytes = CAAM_DESC_BYTES_MAX - AEAD_DESC_JOB_IO_LEN - ctx->adata.keylen_pad; @@ -171,7 +171,7 @@ static int aead_set_sh_desc(struct crypto_aead *aead) unsigned int ivsize = crypto_aead_ivsize(aead); struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *jrdev = ctx->jr->dev; - struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev->parent); + struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev); u32 ctx1_iv_off = 0; u32 *desc, *nonce = NULL; u32 inl_mask; @@ -564,7 +564,7 @@ static int aead_setkey(struct crypto_aead *aead, { struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *jrdev = ctx->jr->dev; - struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev->parent); + struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev); struct crypto_authenc_keys keys; int ret = 0; @@ -1223,7 +1223,7 @@ static void init_authenc_job(struct aead_request *req, struct caam_aead_alg, aead); unsigned int ivsize = crypto_aead_ivsize(aead); struct caam_ctx *ctx = crypto_aead_ctx(aead); - struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctx->jr->dev->parent); + struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctx->jr->dev); const bool ctr_mode = ((ctx->cdata.algtype & OP_ALG_AAI_MASK) == OP_ALG_AAI_CTR_MOD128); const bool is_rfc3686 = alg->caam.rfc3686; @@ -3421,7 +3421,7 @@ static int caam_init_common(struct caam_ctx *ctx, struct caam_alg_entry *caam, return PTR_ERR(ctx->jr); } - priv = dev_get_drvdata(ctx->jr->dev->parent); + priv = dev_get_drvdata(ctx->jr->dev); if (priv->era >= 6 && uses_dkp) ctx->dir = DMA_BIDIRECTIONAL; else diff --git a/drivers/crypto/caam/caamalg_qi.c b/drivers/crypto/caam/caamalg_qi.c index 31bee401f9e5..b8905e3a9c80 100644 --- a/drivers/crypto/caam/caamalg_qi.c +++ b/drivers/crypto/caam/caamalg_qi.c @@ -82,7 +82,7 @@ static int aead_set_sh_desc(struct crypto_aead *aead) const bool ctr_mode = ((ctx->cdata.algtype & OP_ALG_AAI_MASK) == OP_ALG_AAI_CTR_MOD128); const bool is_rfc3686 = alg->caam.rfc3686; - struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctx->jrdev->parent); + struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctx->jrdev); if (!ctx->cdata.keylen || !ctx->authsize) return 0; @@ -189,7 +189,7 @@ static int aead_setkey(struct crypto_aead *aead, const u8 *key, { struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *jrdev = ctx->jrdev; - struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev->parent); + struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev); struct crypto_authenc_keys keys; int ret = 0; diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c index 6e4fd5eb833a..94ecad06a120 100644 --- a/drivers/crypto/caam/caamhash.c +++ b/drivers/crypto/caam/caamhash.c @@ -224,7 +224,7 @@ static int ahash_set_sh_desc(struct crypto_ahash *ahash) struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); int digestsize = crypto_ahash_digestsize(ahash); struct device *jrdev = ctx->jr->dev; - struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev->parent); + struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev); u32 *desc; ctx->adata.key_virt = ctx->key; @@ -447,7 +447,7 @@ static int ahash_setkey(struct crypto_ahash *ahash, struct device *jrdev = ctx->jr->dev; int blocksize = crypto_tfm_alg_blocksize(&ahash->base); int digestsize = crypto_ahash_digestsize(ahash); - struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev->parent); + struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev); int ret; u8 *hashed_key = NULL; @@ -1839,7 +1839,7 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm) return PTR_ERR(ctx->jr); } - priv = dev_get_drvdata(ctx->jr->dev->parent); + priv = dev_get_drvdata(ctx->jr->dev); if (is_xcbc_aes(caam_hash->alg_type)) { ctx->dir = DMA_TO_DEVICE; diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index d7c3c3805693..0fb39bcf638a 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -900,9 +900,18 @@ static int caam_probe(struct platform_device *pdev) &ctrlpriv->ctl_tdsk_wrap); #endif - ret = devm_of_platform_populate(dev); - if (ret) - dev_err(dev, "JR platform devices creation error\n"); + for_each_available_child_of_node(nprop, np) { + if (of_device_is_compatible(np, "fsl,sec-v4.0-job-ring") || + of_device_is_compatible(np, "fsl,sec4.0-job-ring")) { + ret = caam_jr_probe(dev, np); + if (ret) { + dev_err(dev, + "JR platform devices creation error\n"); + of_node_put(np); + break; + } + } + } return ret; } diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c index 1e2929b7c6b9..7f0d192b9276 100644 --- a/drivers/crypto/caam/jr.c +++ b/drivers/crypto/caam/jr.c @@ -65,9 +65,9 @@ static void unregister_algs(void) mutex_unlock(&algs_lock); } -static int caam_reset_hw_jr(struct device *dev) +static int caam_reset_hw_jr(struct caam_drv_private_jr *jrp) { - struct caam_drv_private_jr *jrp = dev_get_drvdata(dev); + struct device *dev = jrp->dev; unsigned int timeout = 100000; /* @@ -105,37 +105,11 @@ static int caam_reset_hw_jr(struct device *dev) return 0; } -/* - * Shutdown JobR independent of platform property code - */ -static int caam_jr_shutdown(struct device *dev) -{ - struct caam_drv_private_jr *jrp = dev_get_drvdata(dev); - int ret; - - ret = caam_reset_hw_jr(dev); - - tasklet_kill(&jrp->irqtask); - - return ret; -} - -static int caam_jr_remove(struct platform_device *pdev) +static void caam_jr_remove(void *data) { int ret; - struct device *jrdev; - struct caam_drv_private_jr *jrpriv; - - jrdev = &pdev->dev; - jrpriv = dev_get_drvdata(jrdev); - - /* - * Return EBUSY if job ring already allocated. - */ - if (atomic_read(&jrpriv->tfm_count)) { - dev_err(jrdev, "Device is busy\n"); - return -EBUSY; - } + struct caam_drv_private_jr *jrpriv = data; + struct device *jrdev = jrpriv->dev; /* Unregister JR-based RNG & crypto algorithms */ unregister_algs(); @@ -146,18 +120,18 @@ static int caam_jr_remove(struct platform_device *pdev) spin_unlock(&driver_data.jr_alloc_lock); /* Release ring */ - ret = caam_jr_shutdown(jrdev); + ret = caam_reset_hw_jr(jrpriv); if (ret) dev_err(jrdev, "Failed to shut down job ring\n"); - return ret; + tasklet_kill(&jrpriv->irqtask); } /* Main per-ring interrupt handler */ static irqreturn_t caam_jr_interrupt(int irq, void *st_dev) { - struct device *dev = st_dev; - struct caam_drv_private_jr *jrp = dev_get_drvdata(dev); + struct caam_drv_private_jr *jrp = st_dev; + struct device *dev = jrp->dev; u32 irqstate; /* @@ -195,8 +169,8 @@ static irqreturn_t caam_jr_interrupt(int irq, void *st_dev) static void caam_jr_dequeue(unsigned long devarg) { int hw_idx, sw_idx, i, head, tail; - struct device *dev = (struct device *)devarg; - struct caam_drv_private_jr *jrp = dev_get_drvdata(dev); + struct caam_drv_private_jr *jrp = (void *)devarg; + struct device *dev = jrp->dev; caam_jr_cbk usercall; u32 *userdesc, userstatus; void *userarg; @@ -418,15 +392,13 @@ EXPORT_SYMBOL(caam_jr_enqueue); /* * Init JobR independent of platform property detection */ -static int caam_jr_init(struct device *dev) +static int caam_jr_init(struct caam_drv_private_jr *jrp) { - struct caam_drv_private_jr *jrp; + struct device *dev = jrp->dev; dma_addr_t inpbusaddr, outbusaddr; int i, error; - jrp = dev_get_drvdata(dev); - - error = caam_reset_hw_jr(dev); + error = caam_reset_hw_jr(jrp); if (error) return error; @@ -469,11 +441,11 @@ static int caam_jr_init(struct device *dev) (JOBR_INTC_COUNT_THLD << JRCFG_ICDCT_SHIFT) | (JOBR_INTC_TIME_THLD << JRCFG_ICTT_SHIFT)); - tasklet_init(&jrp->irqtask, caam_jr_dequeue, (unsigned long)dev); + tasklet_init(&jrp->irqtask, caam_jr_dequeue, (unsigned long)jrp); /* Connect job ring interrupt handler. */ error = devm_request_irq(dev, jrp->irq, caam_jr_interrupt, IRQF_SHARED, - dev_name(dev), dev); + dev_name(dev), jrp); if (error) { dev_err(dev, "can't connect JobR %d interrupt (%d)\n", jrp->ridx, jrp->irq); @@ -491,36 +463,29 @@ static void caam_jr_irq_dispose_mapping(void *data) /* * Probe routine for each detected JobR subsystem. */ -static int caam_jr_probe(struct platform_device *pdev) +int caam_jr_probe(struct device *jrdev, struct device_node *nprop) { - struct device *jrdev; - struct device_node *nprop; struct caam_job_ring __iomem *ctrl; struct caam_drv_private_jr *jrpriv; static int total_jobrs; - struct resource *r; + struct resource r; int error; - jrdev = &pdev->dev; jrpriv = devm_kmalloc(jrdev, sizeof(*jrpriv), GFP_KERNEL); if (!jrpriv) return -ENOMEM; - dev_set_drvdata(jrdev, jrpriv); - /* save ring identity relative to detection */ jrpriv->ridx = total_jobrs++; + jrpriv->dev = jrdev; - nprop = pdev->dev.of_node; - /* Get configuration properties from device tree */ - /* First, get register page */ - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) { - dev_err(jrdev, "platform_get_resource() failed\n"); - return -ENOMEM; + error = of_address_to_resource(nprop, 0, &r); + if (error) { + dev_err(jrdev, "of_address_to_resource() failed\n"); + return error; } - ctrl = devm_ioremap(jrdev, r->start, resource_size(r)); + ctrl = devm_ioremap(jrdev, r.start, resource_size(&r)); if (!ctrl) { dev_err(jrdev, "devm_ioremap() failed\n"); return -ENOMEM; @@ -528,13 +493,6 @@ static int caam_jr_probe(struct platform_device *pdev) jrpriv->rregs = (struct caam_job_ring __iomem __force *)ctrl; - error = dma_set_mask_and_coherent(jrdev, caam_get_dma_mask(jrdev)); - if (error) { - dev_err(jrdev, "dma_set_mask_and_coherent failed (%d)\n", - error); - return error; - } - /* Identify the interrupt */ jrpriv->irq = irq_of_parse_and_map(nprop, 0); if (!jrpriv->irq) { @@ -548,55 +506,21 @@ static int caam_jr_probe(struct platform_device *pdev) return error; /* Now do the platform independent part */ - error = caam_jr_init(jrdev); /* now turn on hardware */ + error = caam_jr_init(jrpriv); /* now turn on hardware */ if (error) return error; - jrpriv->dev = jrdev; spin_lock(&driver_data.jr_alloc_lock); list_add_tail(&jrpriv->list_node, &driver_data.jr_list); spin_unlock(&driver_data.jr_alloc_lock); atomic_set(&jrpriv->tfm_count, 0); - register_algs(jrdev->parent); - - return 0; -} - -static const struct of_device_id caam_jr_match[] = { - { - .compatible = "fsl,sec-v4.0-job-ring", - }, - { - .compatible = "fsl,sec4.0-job-ring", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, caam_jr_match); - -static struct platform_driver caam_jr_driver = { - .driver = { - .name = "caam_jr", - .of_match_table = caam_jr_match, - }, - .probe = caam_jr_probe, - .remove = caam_jr_remove, -}; + error = devm_add_action_or_reset(jrdev, caam_jr_remove, jrpriv); + if (error) + return error; -static int __init jr_driver_init(void) -{ - return platform_driver_register(&caam_jr_driver); -} + register_algs(jrdev); -static void __exit jr_driver_exit(void) -{ - platform_driver_unregister(&caam_jr_driver); + return 0; } - -module_init(jr_driver_init); -module_exit(jr_driver_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("FSL CAAM JR request backend"); -MODULE_AUTHOR("Freescale Semiconductor - NMG/STC"); diff --git a/drivers/crypto/caam/jr.h b/drivers/crypto/caam/jr.h index f49caa0ac0ff..ee2aa1798605 100644 --- a/drivers/crypto/caam/jr.h +++ b/drivers/crypto/caam/jr.h @@ -18,5 +18,6 @@ struct caam_drv_private_jr *caam_jr_alloc(void); void caam_jr_free(struct caam_drv_private_jr *jr); int caam_jr_enqueue(struct caam_drv_private_jr *jr, u32 *desc, caam_jr_cbk cbk, void *areq); +int caam_jr_probe(struct device *jrdev, struct device_node *nprop); #endif /* JR_H */ -- 2.21.0