crypto: octeontx2 - add LF reset on queue disable
authorSrujana Challa <schalla@marvell.com>
Wed, 13 Dec 2023 07:30:51 +0000 (13:00 +0530)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 29 Dec 2023 03:25:38 +0000 (11:25 +0800)
CPT LF must be reset and follow CPT LF disable sequence
suggested by HW team, when driver exits.
This patch adds code for the same.

Signed-off-by: Srujana Challa <schalla@marvell.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/marvell/octeontx2/otx2_cpt_common.h
drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c
drivers/crypto/marvell/octeontx2/otx2_cptlf.h
drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c
drivers/crypto/marvell/octeontx2/otx2_cptvf_mbox.c

index ba1682a213e3756e60664c6d39a23b2887b7ba09..807db0da52cc2a1dee8ee8ecaa95f33d261e4d51 100644 (file)
@@ -218,5 +218,6 @@ int otx2_cpt_attach_rscrs_msg(struct otx2_cptlfs_info *lfs);
 int otx2_cpt_detach_rsrcs_msg(struct otx2_cptlfs_info *lfs);
 int otx2_cpt_msix_offset_msg(struct otx2_cptlfs_info *lfs);
 int otx2_cpt_sync_mbox_msg(struct otx2_mbox *mbox);
+int otx2_cpt_lf_reset_msg(struct otx2_cptlfs_info *lfs, int slot);
 
 #endif /* __OTX2_CPT_COMMON_H */
index 273ee5352a50b49b9916e95e16b279212953b6d1..5be0103c1fb8175e5addc33f3f9f59675283d54f 100644 (file)
@@ -229,3 +229,29 @@ int otx2_cpt_sync_mbox_msg(struct otx2_mbox *mbox)
        return otx2_mbox_check_rsp_msgs(mbox, 0);
 }
 EXPORT_SYMBOL_NS_GPL(otx2_cpt_sync_mbox_msg, CRYPTO_DEV_OCTEONTX2_CPT);
+
+int otx2_cpt_lf_reset_msg(struct otx2_cptlfs_info *lfs, int slot)
+{
+       struct otx2_mbox *mbox = lfs->mbox;
+       struct pci_dev *pdev = lfs->pdev;
+       struct cpt_lf_rst_req *req;
+       int ret;
+
+       req = (struct cpt_lf_rst_req *)otx2_mbox_alloc_msg_rsp(mbox, 0, sizeof(*req),
+                                                              sizeof(struct msg_rsp));
+       if (!req) {
+               dev_err(&pdev->dev, "RVU MBOX failed to get message.\n");
+               return -EFAULT;
+       }
+
+       req->hdr.id = MBOX_MSG_CPT_LF_RESET;
+       req->hdr.sig = OTX2_MBOX_REQ_SIG;
+       req->hdr.pcifunc = 0;
+       req->slot = slot;
+       ret = otx2_cpt_send_mbox_msg(mbox, pdev);
+       if (ret)
+               return ret;
+
+       return ret;
+}
+EXPORT_SYMBOL_NS_GPL(otx2_cpt_lf_reset_msg, CRYPTO_DEV_OCTEONTX2_CPT);
index 679b0f7b70c324dbe4c95868baa6581b6cacf0c5..f68631ec88610acc549eac22608d209b3b7dab6b 100644 (file)
@@ -5,6 +5,7 @@
 #define __OTX2_CPTLF_H
 
 #include <linux/soc/marvell/octeontx2/asm.h>
+#include <linux/bitfield.h>
 #include <mbox.h>
 #include <rvu.h>
 #include "otx2_cpt_common.h"
@@ -119,6 +120,7 @@ struct otx2_cptlfs_info {
        u8 kvf_limits;          /* Kernel crypto limits */
        atomic_t state;         /* LF's state. started/reset */
        int blkaddr;            /* CPT blkaddr: BLKADDR_CPT0/BLKADDR_CPT1 */
+       int global_slot;        /* Global slot across the blocks */
 };
 
 static inline void otx2_cpt_free_instruction_queues(
@@ -206,48 +208,71 @@ static inline void otx2_cptlf_set_iqueues_size(struct otx2_cptlfs_info *lfs)
                otx2_cptlf_do_set_iqueue_size(&lfs->lf[slot]);
 }
 
+#define INFLIGHT   GENMASK_ULL(8, 0)
+#define GRB_CNT    GENMASK_ULL(39, 32)
+#define GWB_CNT    GENMASK_ULL(47, 40)
+#define XQ_XOR     GENMASK_ULL(63, 63)
+#define DQPTR      GENMASK_ULL(19, 0)
+#define NQPTR      GENMASK_ULL(51, 32)
+
 static inline void otx2_cptlf_do_disable_iqueue(struct otx2_cptlf_info *lf)
 {
-       union otx2_cptx_lf_ctl lf_ctl = { .u = 0x0 };
-       union otx2_cptx_lf_inprog lf_inprog;
+       void __iomem *reg_base = lf->lfs->reg_base;
+       struct pci_dev *pdev = lf->lfs->pdev;
        u8 blkaddr = lf->lfs->blkaddr;
-       int timeout = 20;
+       int timeout = 1000000;
+       u64 inprog, inst_ptr;
+       u64 slot = lf->slot;
+       u64 qsize, pending;
+       int i = 0;
 
        /* Disable instructions enqueuing */
-       otx2_cpt_write64(lf->lfs->reg_base, blkaddr, lf->slot,
-                        OTX2_CPT_LF_CTL, lf_ctl.u);
+       otx2_cpt_write64(reg_base, blkaddr, slot, OTX2_CPT_LF_CTL, 0x0);
 
-       /* Wait for instruction queue to become empty */
+       inprog = otx2_cpt_read64(reg_base, blkaddr, slot, OTX2_CPT_LF_INPROG);
+       inprog |= BIT_ULL(16);
+       otx2_cpt_write64(reg_base, blkaddr, slot, OTX2_CPT_LF_INPROG, inprog);
+
+       qsize = otx2_cpt_read64(reg_base, blkaddr, slot, OTX2_CPT_LF_Q_SIZE) & 0x7FFF;
+       do {
+               inst_ptr = otx2_cpt_read64(reg_base, blkaddr, slot, OTX2_CPT_LF_Q_INST_PTR);
+               pending = (FIELD_GET(XQ_XOR, inst_ptr) * qsize * 40) +
+                         FIELD_GET(NQPTR, inst_ptr) - FIELD_GET(DQPTR, inst_ptr);
+               udelay(1);
+               timeout--;
+       } while ((pending != 0) && (timeout != 0));
+
+       if (timeout == 0)
+               dev_warn(&pdev->dev, "TIMEOUT: CPT poll on pending instructions\n");
+
+       timeout = 1000000;
+       /* Wait for CPT queue to become execution-quiescent */
        do {
-               lf_inprog.u = otx2_cpt_read64(lf->lfs->reg_base, blkaddr,
-                                             lf->slot, OTX2_CPT_LF_INPROG);
-               if (!lf_inprog.s.inflight)
-                       break;
-
-               usleep_range(10000, 20000);
-               if (timeout-- < 0) {
-                       dev_err(&lf->lfs->pdev->dev,
-                               "Error LF %d is still busy.\n", lf->slot);
-                       break;
+               inprog = otx2_cpt_read64(reg_base, blkaddr, slot, OTX2_CPT_LF_INPROG);
+
+               if ((FIELD_GET(INFLIGHT, inprog) == 0) &&
+                   (FIELD_GET(GRB_CNT, inprog) == 0)) {
+                       i++;
+               } else {
+                       i = 0;
+                       timeout--;
                }
+       } while ((timeout != 0) && (i < 10));
 
-       } while (1);
-
-       /*
-        * Disable executions in the LF's queue,
-        * the queue should be empty at this point
-        */
-       lf_inprog.s.eena = 0x0;
-       otx2_cpt_write64(lf->lfs->reg_base, blkaddr, lf->slot,
-                        OTX2_CPT_LF_INPROG, lf_inprog.u);
+       if (timeout == 0)
+               dev_warn(&pdev->dev, "TIMEOUT: CPT poll on inflight count\n");
+       /* Wait for 2 us to flush all queue writes to memory */
+       udelay(2);
 }
 
 static inline void otx2_cptlf_disable_iqueues(struct otx2_cptlfs_info *lfs)
 {
        int slot;
 
-       for (slot = 0; slot < lfs->lfs_num; slot++)
+       for (slot = 0; slot < lfs->lfs_num; slot++) {
                otx2_cptlf_do_disable_iqueue(&lfs->lf[slot]);
+               otx2_cpt_lf_reset_msg(lfs, lfs->global_slot + slot);
+       }
 }
 
 static inline void otx2_cptlf_set_iqueue_enq(struct otx2_cptlf_info *lf,
index 390ed146d30994edaccb8253635b67ea96d9001b..a6f16438bd4af892fbd2f23121c4ead4dc6d5a4c 100644 (file)
@@ -201,8 +201,8 @@ static int handle_msg_rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf,
                                             struct mbox_msghdr *req)
 {
        struct otx2_cpt_rx_inline_lf_cfg *cfg_req;
+       int num_lfs = 1, ret;
        u8 egrp;
-       int ret;
 
        cfg_req = (struct otx2_cpt_rx_inline_lf_cfg *)req;
        if (cptpf->lfs.lfs_num) {
@@ -223,8 +223,9 @@ static int handle_msg_rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf,
 
        otx2_cptlf_set_dev_info(&cptpf->lfs, cptpf->pdev, cptpf->reg_base,
                                &cptpf->afpf_mbox, BLKADDR_CPT0);
+       cptpf->lfs.global_slot = 0;
        ret = otx2_cptlf_init(&cptpf->lfs, 1 << egrp, OTX2_CPT_QUEUE_HI_PRIO,
-                             1);
+                             num_lfs);
        if (ret) {
                dev_err(&cptpf->pdev->dev,
                        "LF configuration failed for RX inline ipsec.\n");
@@ -236,8 +237,9 @@ static int handle_msg_rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf,
                otx2_cptlf_set_dev_info(&cptpf->cpt1_lfs, cptpf->pdev,
                                        cptpf->reg_base, &cptpf->afpf_mbox,
                                        BLKADDR_CPT1);
+               cptpf->cpt1_lfs.global_slot = num_lfs;
                ret = otx2_cptlf_init(&cptpf->cpt1_lfs, 1 << egrp,
-                                     OTX2_CPT_QUEUE_HI_PRIO, 1);
+                                     OTX2_CPT_QUEUE_HI_PRIO, num_lfs);
                if (ret) {
                        dev_err(&cptpf->pdev->dev,
                                "LF configuration failed for RX inline ipsec.\n");
@@ -449,6 +451,7 @@ static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf,
                break;
        case MBOX_MSG_CPT_INLINE_IPSEC_CFG:
        case MBOX_MSG_NIX_INLINE_IPSEC_CFG:
+       case MBOX_MSG_CPT_LF_RESET:
                break;
 
        default:
index f68da1d08fdf5fee925dec6e92c300020a983674..d9fa5f6e204d2e01af8e35d5fef920b831819011 100644 (file)
@@ -133,6 +133,8 @@ static void process_pfvf_mbox_mbox_msg(struct otx2_cptvf_dev *cptvf,
                memcpy(cptvf->eng_caps, eng_caps->eng_caps,
                       sizeof(cptvf->eng_caps));
                break;
+       case MBOX_MSG_CPT_LF_RESET:
+               break;
        default:
                dev_err(&cptvf->pdev->dev, "Unsupported msg %d received.\n",
                        msg->id);