drivers: crypto: caam/jr - Allow quiesce when quiesced
authorHoria Geanta <horia.geanta@nxp.com>
Tue, 28 Feb 2023 18:37:58 +0000 (00:07 +0530)
committerHerbert Xu <herbert@gondor.apana.org.au>
Tue, 14 Mar 2023 09:06:45 +0000 (17:06 +0800)
Issues:
- Job ring device is busy when do kexec reboot
- Failed to flush job ring when do system suspend-resume

Fix:
Flush the job ring to stop the running jobs.

Signed-off-by: Horia Geanta <horia.geanta@nxp.com>
Signed-off-by: Franck LENORMAND <franck.lenormand@nxp.com>
Reviewed-by: Pankaj Gupta <pankaj.gupta@nxp.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/caam/jr.c

index 724fdec18bf9782083bd7ce7215844dc15a07398..eb3b9a7e9a353196106dc7b72d4b0143cbaeee43 100644 (file)
@@ -4,7 +4,7 @@
  * JobR backend functionality
  *
  * Copyright 2008-2012 Freescale Semiconductor, Inc.
- * Copyright 2019 NXP
+ * Copyright 2019, 2023 NXP
  */
 
 #include <linux/of_irq.h>
@@ -72,19 +72,27 @@ static void caam_jr_crypto_engine_exit(void *data)
        crypto_engine_exit(jrpriv->engine);
 }
 
-static int caam_reset_hw_jr(struct device *dev)
+/*
+ * Put the CAAM in quiesce, ie stop
+ *
+ * Must be called with itr disabled
+ */
+static int caam_jr_stop_processing(struct device *dev, u32 jrcr_bits)
 {
        struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
        unsigned int timeout = 100000;
 
-       /*
-        * mask interrupts since we are going to poll
-        * for reset completion status
-        */
-       clrsetbits_32(&jrp->rregs->rconfig_lo, 0, JRCFG_IMSK);
+       /* Check the current status */
+       if (rd_reg32(&jrp->rregs->jrintstatus) & JRINT_ERR_HALT_INPROGRESS)
+               goto wait_quiesce_completion;
 
-       /* initiate flush (required prior to reset) */
-       wr_reg32(&jrp->rregs->jrcommand, JRCR_RESET);
+       /* Reset the field */
+       clrsetbits_32(&jrp->rregs->jrintstatus, JRINT_ERR_HALT_MASK, 0);
+
+       /* initiate flush / park (required prior to reset) */
+       wr_reg32(&jrp->rregs->jrcommand, jrcr_bits);
+
+wait_quiesce_completion:
        while (((rd_reg32(&jrp->rregs->jrintstatus) & JRINT_ERR_HALT_MASK) ==
                JRINT_ERR_HALT_INPROGRESS) && --timeout)
                cpu_relax();
@@ -95,8 +103,35 @@ static int caam_reset_hw_jr(struct device *dev)
                return -EIO;
        }
 
+       return 0;
+}
+
+/*
+ * Flush the job ring, so the jobs running will be stopped, jobs queued will be
+ * invalidated and the CAAM will no longer fetch fron input ring.
+ *
+ * Must be called with itr disabled
+ */
+static int caam_jr_flush(struct device *dev)
+{
+       return caam_jr_stop_processing(dev, JRCR_RESET);
+}
+
+static int caam_reset_hw_jr(struct device *dev)
+{
+       struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
+       unsigned int timeout = 100000;
+       int err;
+       /*
+        * mask interrupts since we are going to poll
+        * for reset completion status
+        */
+       clrsetbits_32(&jrp->rregs->rconfig_lo, 0, JRCFG_IMSK);
+       err = caam_jr_flush(dev);
+       if (err)
+               return err;
+
        /* initiate reset */
-       timeout = 100000;
        wr_reg32(&jrp->rregs->jrcommand, JRCR_RESET);
        while ((rd_reg32(&jrp->rregs->jrcommand) & JRCR_RESET) && --timeout)
                cpu_relax();