@@ -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
@@ -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),)
@@ -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
@@ -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;
@@ -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;
@@ -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;
}
@@ -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");
@@ -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 */
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@gmail.com> Cc: Chris Healy <cphealy@gmail.com> Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Horia Geantă <horia.geanta@nxp.com> Cc: Herbert Xu <herbert@gondor.apana.org.au> Cc: Iuliana Prodan <iuliana.prodan@nxp.com> Cc: linux-imx@nxp.com Cc: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- 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(-)