]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00215945-3: caam: Improve error recovery on failed RNG4 kickstart
authorSteve Cornelius <steve.cornelius@freescale.com>
Wed, 11 Jul 2012 21:48:09 +0000 (14:48 -0700)
committerOliver Wendt <ow@karo-electronics.de>
Mon, 30 Sep 2013 12:12:26 +0000 (14:12 +0200)
RNG4 requires a kickstart process to transition into running mode.
In the case that this kickstart process errors, the driver is shut
back down (under the assumption that internal random padding of keys
or data cannot occur).

In an isolated case, the kickstart failed to start the RNG, an error
was returned, and the driver attempted to de-register an RNG function
that never completed, causing a crash. (This is difficult to test for
without manual intervention).

Therefore, amended the driver shutdown process to only de-register
the hardware RNG when an instance kickstarted without error.

This does NOT correct the kickstart problem, only the consequences.

Signed-off-by: Steve Cornelius <steve.cornelius@freescale.com>
Signed-off-by: Terry Lv <r65388@freescale.com>
drivers/crypto/caam/caamrng.c
drivers/crypto/caam/ctrl.c
drivers/crypto/caam/intern.h

index f992c10b657b0d73728ce07e527c6523abb491fd..a4b4a3871bdf7ce319e81a7b96265deb671aa64e 100644 (file)
@@ -327,7 +327,7 @@ int caam_rng_startup(struct platform_device *pdev)
        ctrldev = &pdev->dev;
        priv = dev_get_drvdata(ctrldev);
 
-       /* Check instantiated RNG before registration */
+       /* Check RNG present in hardware before registration */
        if (!(rd_reg64(&priv->ctrl->perfmon.cha_num) & CHA_ID_RNG_MASK))
                return -ENODEV;
 
index d7374aad06e8099ba46e0378872f80cdda37dd13..28828b9e559cedbd4c4a0105a8f2907abf442f05 100644 (file)
@@ -25,16 +25,18 @@ static int caam_remove(struct platform_device *pdev)
        topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
 
 #ifndef CONFIG_OF
-       caam_algapi_shutdown(pdev);
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API
+       if (ctrlpriv->rng_inst)
+               caam_rng_shutdown();
+#endif
 
 #ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API
        caam_algapi_hash_shutdown(pdev);
 #endif
 
-#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API
-       caam_rng_shutdown();
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API
+       caam_algapi_shutdown(pdev);
 #endif
-
 #endif
        /* shut down JobRs */
        for (ring = 0; ring < ctrlpriv->total_jobrs; ring++) {
@@ -125,7 +127,10 @@ static int instantiate_rng(struct device *jrdev)
 
        build_instantiation_desc(desc);
        desc_dma = dma_map_single(jrdev, desc, desc_bytes(desc), DMA_TO_DEVICE);
+       dma_sync_single_for_device(jrdev, desc_dma, desc_bytes(desc),
+                                  DMA_TO_DEVICE);
        init_completion(&instantiation.completion);
+
        ret = caam_jr_enqueue(jrdev, desc, rng4_init_done, &instantiation);
        if (!ret) {
                wait_for_completion_interruptible(&instantiation.completion);
@@ -357,7 +362,10 @@ static int caam_probe(struct platform_device *pdev)
 
        /*
         * RNG4 based SECs (v5+ | >= i.MX6) need special initialization prior
-        * to executing any descriptors
+        * to executing any descriptors. If there's a problem with init,
+        * remove other subsystems and return; internal padding functions
+        * cannot run without an RNG. This procedure assumes a single RNG4
+        * instance.
         */
        if ((rd_reg64(&topregs->ctrl.perfmon.cha_id) & CHA_ID_RNG_MASK)
            == CHA_ID_RNG_4) {
@@ -365,8 +373,9 @@ static int caam_probe(struct platform_device *pdev)
                ret = instantiate_rng(ctrlpriv->jrdev[0]);
                if (ret) {
                        caam_remove(pdev);
-                       return ret;
+                       return -ENODEV;
                }
+               ctrlpriv->rng_inst++;
        }
 
        /* NOTE: RTIC detection ought to go here, around Si time */
@@ -468,15 +477,18 @@ static int caam_probe(struct platform_device *pdev)
  * start up the API code explicitly, and forego modularization
  */
 #ifndef CONFIG_OF
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API
        /* FIXME: check status */
        caam_algapi_startup(pdev);
+#endif
 
 #ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API
        caam_algapi_hash_startup(pdev);
 #endif
 
 #ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API
-       caam_rng_startup(pdev);
+       if (ctrlpriv->rng_inst)
+               caam_rng_startup(pdev);
 #endif
 #endif /* CONFIG_OF */
        return 0;
index 8550598870455b55643a738045edc5acff95a886..18e7385fb2d8a56d47875a67f9ad1901e5b3ab53 100644 (file)
@@ -100,6 +100,7 @@ struct caam_drv_private {
        u8 total_jobrs;         /* Total Job Rings in device */
        u8 qi_present;          /* Nonzero if QI present in device */
        int secvio_irq;         /* Security violation interrupt number */
+       int rng_inst;           /* Total instantiated RNGs */
 
        /* which jr allocated to scatterlist crypto */
        atomic_t tfm_count ____cacheline_aligned;