drivers: remove direct access to interrupt handle
[dpdk.git] / drivers / common / cnxk / roc_cpt.c
index e723ee7..f0e52ae 100644 (file)
@@ -5,6 +5,281 @@
 #include "roc_api.h"
 #include "roc_priv.h"
 
+#define CPT_IQ_FC_LEN  128
+#define CPT_IQ_GRP_LEN 16
+
+#define CPT_IQ_NB_DESC_MULTIPLIER 40
+
+/* The effective queue size to software is (CPT_LF_Q_SIZE[SIZE_DIV40] - 1 - 8).
+ *
+ * CPT requires 320 free entries (+8). And 40 entries are required for
+ * allowing CPT to discard packet when the queues are full (+1).
+ */
+#define CPT_IQ_NB_DESC_SIZE_DIV40(nb_desc)                                     \
+       (PLT_DIV_CEIL(nb_desc, CPT_IQ_NB_DESC_MULTIPLIER) + 1 + 8)
+
+#define CPT_IQ_GRP_SIZE(nb_desc)                                               \
+       (CPT_IQ_NB_DESC_SIZE_DIV40(nb_desc) * CPT_IQ_GRP_LEN)
+
+#define CPT_LF_MAX_NB_DESC     128000
+#define CPT_LF_DEFAULT_NB_DESC 1024
+
+static void
+cpt_lf_misc_intr_enb_dis(struct roc_cpt_lf *lf, bool enb)
+{
+       /* Enable all cpt lf error irqs except RQ_DISABLED and CQ_DISABLED */
+       if (enb)
+               plt_write64((BIT_ULL(6) | BIT_ULL(5) | BIT_ULL(3) | BIT_ULL(2) |
+                            BIT_ULL(1)),
+                           lf->rbase + CPT_LF_MISC_INT_ENA_W1S);
+       else
+               plt_write64((BIT_ULL(6) | BIT_ULL(5) | BIT_ULL(3) | BIT_ULL(2) |
+                            BIT_ULL(1)),
+                           lf->rbase + CPT_LF_MISC_INT_ENA_W1C);
+}
+
+static void
+cpt_lf_misc_irq(void *param)
+{
+       struct roc_cpt_lf *lf = (struct roc_cpt_lf *)param;
+       struct dev *dev = lf->dev;
+       uint64_t intr;
+
+       intr = plt_read64(lf->rbase + CPT_LF_MISC_INT);
+       if (intr == 0)
+               return;
+
+       plt_err("Err_irq=0x%" PRIx64 " pf=%d, vf=%d", intr, dev->pf, dev->vf);
+
+       /* Dump lf registers */
+       cpt_lf_print(lf);
+
+       /* Clear interrupt */
+       plt_write64(intr, lf->rbase + CPT_LF_MISC_INT);
+}
+
+static int
+cpt_lf_register_misc_irq(struct roc_cpt_lf *lf)
+{
+       struct plt_pci_device *pci_dev = lf->pci_dev;
+       struct plt_intr_handle *handle;
+       int rc, vec;
+
+       handle = pci_dev->intr_handle;
+
+       vec = lf->msixoff + CPT_LF_INT_VEC_MISC;
+       /* Clear err interrupt */
+       cpt_lf_misc_intr_enb_dis(lf, false);
+       /* Set used interrupt vectors */
+       rc = dev_irq_register(handle, cpt_lf_misc_irq, lf, vec);
+       /* Enable all dev interrupt except for RQ_DISABLED */
+       cpt_lf_misc_intr_enb_dis(lf, true);
+
+       return rc;
+}
+
+static void
+cpt_lf_unregister_misc_irq(struct roc_cpt_lf *lf)
+{
+       struct plt_pci_device *pci_dev = lf->pci_dev;
+       struct plt_intr_handle *handle;
+       int vec;
+
+       handle = pci_dev->intr_handle;
+
+       vec = lf->msixoff + CPT_LF_INT_VEC_MISC;
+       /* Clear err interrupt */
+       cpt_lf_misc_intr_enb_dis(lf, false);
+       dev_irq_unregister(handle, cpt_lf_misc_irq, lf, vec);
+}
+
+static void
+cpt_lf_done_intr_enb_dis(struct roc_cpt_lf *lf, bool enb)
+{
+       if (enb)
+               plt_write64(0x1, lf->rbase + CPT_LF_DONE_INT_ENA_W1S);
+       else
+               plt_write64(0x1, lf->rbase + CPT_LF_DONE_INT_ENA_W1C);
+}
+
+static void
+cpt_lf_done_irq(void *param)
+{
+       struct roc_cpt_lf *lf = param;
+       uint64_t done_wait;
+       uint64_t intr;
+
+       /* Read the number of completed requests */
+       intr = plt_read64(lf->rbase + CPT_LF_DONE);
+       if (intr == 0)
+               return;
+
+       done_wait = plt_read64(lf->rbase + CPT_LF_DONE_WAIT);
+
+       /* Acknowledge the number of completed requests */
+       plt_write64(intr, lf->rbase + CPT_LF_DONE_ACK);
+
+       plt_write64(done_wait, lf->rbase + CPT_LF_DONE_WAIT);
+}
+
+static int
+cpt_lf_register_done_irq(struct roc_cpt_lf *lf)
+{
+       struct plt_pci_device *pci_dev = lf->pci_dev;
+       struct plt_intr_handle *handle;
+       int rc, vec;
+
+       handle = pci_dev->intr_handle;
+
+       vec = lf->msixoff + CPT_LF_INT_VEC_DONE;
+
+       /* Clear done interrupt */
+       cpt_lf_done_intr_enb_dis(lf, false);
+
+       /* Set used interrupt vectors */
+       rc = dev_irq_register(handle, cpt_lf_done_irq, lf, vec);
+
+       /* Enable done interrupt */
+       cpt_lf_done_intr_enb_dis(lf, true);
+
+       return rc;
+}
+
+static void
+cpt_lf_unregister_done_irq(struct roc_cpt_lf *lf)
+{
+       struct plt_pci_device *pci_dev = lf->pci_dev;
+       struct plt_intr_handle *handle;
+       int vec;
+
+       handle = pci_dev->intr_handle;
+
+       vec = lf->msixoff + CPT_LF_INT_VEC_DONE;
+
+       /* Clear done interrupt */
+       cpt_lf_done_intr_enb_dis(lf, false);
+       dev_irq_unregister(handle, cpt_lf_done_irq, lf, vec);
+}
+
+static int
+cpt_lf_register_irqs(struct roc_cpt_lf *lf)
+{
+       int rc;
+
+       if (lf->msixoff == MSIX_VECTOR_INVALID) {
+               plt_err("Invalid CPTLF MSIX vector offset vector: 0x%x",
+                       lf->msixoff);
+               return -EINVAL;
+       }
+
+       /* Register lf err interrupt */
+       rc = cpt_lf_register_misc_irq(lf);
+       if (rc)
+               plt_err("Error registering IRQs");
+
+       rc = cpt_lf_register_done_irq(lf);
+       if (rc)
+               plt_err("Error registering IRQs");
+
+       return rc;
+}
+
+static void
+cpt_lf_unregister_irqs(struct roc_cpt_lf *lf)
+{
+       cpt_lf_unregister_misc_irq(lf);
+       cpt_lf_unregister_done_irq(lf);
+}
+
+static void
+cpt_lf_dump(struct roc_cpt_lf *lf)
+{
+       plt_cpt_dbg("CPT LF");
+       plt_cpt_dbg("RBASE: 0x%016" PRIx64, lf->rbase);
+       plt_cpt_dbg("LMT_BASE: 0x%016" PRIx64, lf->lmt_base);
+       plt_cpt_dbg("MSIXOFF: 0x%x", lf->msixoff);
+       plt_cpt_dbg("LF_ID: 0x%x", lf->lf_id);
+       plt_cpt_dbg("NB DESC: %d", lf->nb_desc);
+       plt_cpt_dbg("FC_ADDR: 0x%016" PRIx64, (uintptr_t)lf->fc_addr);
+       plt_cpt_dbg("CQ.VADDR: 0x%016" PRIx64, (uintptr_t)lf->iq_vaddr);
+
+       plt_cpt_dbg("CPT LF REG:");
+       plt_cpt_dbg("LF_CTL[0x%016llx]: 0x%016" PRIx64, CPT_LF_CTL,
+                   plt_read64(lf->rbase + CPT_LF_CTL));
+       plt_cpt_dbg("LF_INPROG[0x%016llx]: 0x%016" PRIx64, CPT_LF_INPROG,
+                   plt_read64(lf->rbase + CPT_LF_INPROG));
+
+       plt_cpt_dbg("Q_BASE[0x%016llx]: 0x%016" PRIx64, CPT_LF_Q_BASE,
+                   plt_read64(lf->rbase + CPT_LF_Q_BASE));
+       plt_cpt_dbg("Q_SIZE[0x%016llx]: 0x%016" PRIx64, CPT_LF_Q_SIZE,
+                   plt_read64(lf->rbase + CPT_LF_Q_SIZE));
+       plt_cpt_dbg("Q_INST_PTR[0x%016llx]: 0x%016" PRIx64, CPT_LF_Q_INST_PTR,
+                   plt_read64(lf->rbase + CPT_LF_Q_INST_PTR));
+       plt_cpt_dbg("Q_GRP_PTR[0x%016llx]: 0x%016" PRIx64, CPT_LF_Q_GRP_PTR,
+                   plt_read64(lf->rbase + CPT_LF_Q_GRP_PTR));
+}
+
+int
+cpt_lf_outb_cfg(struct dev *dev, uint16_t sso_pf_func, uint16_t nix_pf_func,
+               uint8_t lf_id, bool ena)
+{
+       struct cpt_inline_ipsec_cfg_msg *req;
+       struct mbox *mbox = dev->mbox;
+
+       req = mbox_alloc_msg_cpt_inline_ipsec_cfg(mbox);
+       if (req == NULL)
+               return -ENOSPC;
+
+       req->dir = CPT_INLINE_OUTBOUND;
+       req->slot = lf_id;
+       if (ena) {
+               req->enable = 1;
+               req->sso_pf_func = sso_pf_func;
+               req->nix_pf_func = nix_pf_func;
+       } else {
+               req->enable = 0;
+       }
+
+       return mbox_process(mbox);
+}
+
+int
+roc_cpt_inline_ipsec_cfg(struct dev *cpt_dev, uint8_t lf_id,
+                        struct roc_nix *roc_nix)
+{
+       bool ena = roc_nix ? true : false;
+       uint16_t nix_pf_func = 0;
+       uint16_t sso_pf_func = 0;
+
+       if (ena) {
+               nix_pf_func = roc_nix_get_pf_func(roc_nix);
+               sso_pf_func = idev_sso_pffunc_get();
+       }
+
+       return cpt_lf_outb_cfg(cpt_dev, sso_pf_func, nix_pf_func, lf_id, ena);
+}
+
+int
+roc_cpt_inline_ipsec_inb_cfg(struct roc_cpt *roc_cpt, uint16_t param1,
+                            uint16_t param2)
+{
+       struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
+       struct cpt_rx_inline_lf_cfg_msg *req;
+       struct mbox *mbox;
+
+       mbox = cpt->dev.mbox;
+
+       req = mbox_alloc_msg_cpt_rx_inline_lf_cfg(mbox);
+       if (req == NULL)
+               return -ENOSPC;
+
+       req->sso_pf_func = idev_sso_pffunc_get();
+       req->param1 = param1;
+       req->param2 = param2;
+
+       return mbox_process(mbox);
+}
+
 int
 roc_cpt_rxc_time_cfg(struct roc_cpt *roc_cpt, struct roc_cpt_rxc_time_cfg *cfg)
 {
@@ -95,7 +370,7 @@ cpt_available_lfs_get(struct dev *dev, uint16_t *nb_lf)
        if (rc)
                return -EIO;
 
-       *nb_lf = rsp->cpt;
+       *nb_lf = PLT_MAX((uint16_t)rsp->cpt, (uint16_t)rsp->cpt1);
        return 0;
 }
 
@@ -109,11 +384,12 @@ cpt_lfs_alloc(struct dev *dev, uint8_t eng_grpmsk, uint8_t blkaddr,
        if (blkaddr != RVU_BLOCK_ADDR_CPT0 && blkaddr != RVU_BLOCK_ADDR_CPT1)
                return -EINVAL;
 
-       PLT_SET_USED(inl_dev_sso);
-
        req = mbox_alloc_msg_cpt_lf_alloc(mbox);
        req->nix_pf_func = 0;
-       req->sso_pf_func = idev_sso_pffunc_get();
+       if (inl_dev_sso && nix_inl_dev_pffunc_get())
+               req->sso_pf_func = nix_inl_dev_pffunc_get();
+       else
+               req->sso_pf_func = idev_sso_pffunc_get();
        req->eng_grpmsk = eng_grpmsk;
        req->blkaddr = blkaddr;
 
@@ -129,7 +405,7 @@ cpt_lfs_free(struct dev *dev)
 }
 
 static int
-cpt_hardware_caps_get(struct dev *dev, union cpt_eng_caps *hw_caps)
+cpt_hardware_caps_get(struct dev *dev, struct roc_cpt *roc_cpt)
 {
        struct cpt_caps_rsp_msg *rsp;
        int ret;
@@ -140,31 +416,103 @@ cpt_hardware_caps_get(struct dev *dev, union cpt_eng_caps *hw_caps)
        if (ret)
                return -EIO;
 
-       mbox_memcpy(hw_caps, rsp->eng_caps,
+       roc_cpt->cpt_revision = rsp->cpt_revision;
+       mbox_memcpy(roc_cpt->hw_caps, rsp->eng_caps,
                    sizeof(union cpt_eng_caps) * CPT_MAX_ENG_TYPES);
 
        return 0;
 }
 
+static uint32_t
+cpt_lf_iq_mem_calc(uint32_t nb_desc)
+{
+       uint32_t len;
+
+       /* Space for instruction group memory */
+       len = CPT_IQ_GRP_SIZE(nb_desc);
+
+       /* Align to 128B */
+       len = PLT_ALIGN(len, ROC_ALIGN);
+
+       /* Space for FC */
+       len += CPT_IQ_FC_LEN;
+
+       /* For instruction queues */
+       len += PLT_ALIGN(CPT_IQ_NB_DESC_SIZE_DIV40(nb_desc) *
+                                CPT_IQ_NB_DESC_MULTIPLIER *
+                                sizeof(struct cpt_inst_s),
+                        ROC_ALIGN);
+
+       return len;
+}
+
+static inline void
+cpt_iq_init(struct roc_cpt_lf *lf)
+{
+       union cpt_lf_q_size lf_q_size = {.u = 0x0};
+       union cpt_lf_q_base lf_q_base = {.u = 0x0};
+       uintptr_t addr;
+
+       lf->io_addr = lf->rbase + CPT_LF_NQX(0);
+
+       /* Disable command queue */
+       roc_cpt_iq_disable(lf);
+
+       /* Set command queue base address */
+       addr = (uintptr_t)lf->iq_vaddr +
+              PLT_ALIGN(CPT_IQ_GRP_SIZE(lf->nb_desc), ROC_ALIGN);
+
+       lf_q_base.u = addr;
+
+       plt_write64(lf_q_base.u, lf->rbase + CPT_LF_Q_BASE);
+
+       /* Set command queue size */
+       lf_q_size.s.size_div40 = CPT_IQ_NB_DESC_SIZE_DIV40(lf->nb_desc);
+       plt_write64(lf_q_size.u, lf->rbase + CPT_LF_Q_SIZE);
+
+       lf->fc_addr = (uint64_t *)addr;
+       lf->fc_hyst_bits = plt_log2_u32(lf->nb_desc) / 2;
+       lf->fc_thresh = lf->nb_desc - (lf->nb_desc % (1 << lf->fc_hyst_bits));
+}
+
 int
 roc_cpt_dev_configure(struct roc_cpt *roc_cpt, int nb_lf)
 {
        struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
-       uint8_t blkaddr = RVU_BLOCK_ADDR_CPT0;
+       uint8_t blkaddr[ROC_CPT_MAX_BLKS];
        struct msix_offset_rsp *rsp;
        uint8_t eng_grpmsk;
+       int blknum = 0;
        int rc, i;
 
+       blkaddr[0] = RVU_BLOCK_ADDR_CPT0;
+       blkaddr[1] = RVU_BLOCK_ADDR_CPT1;
+
+       if ((roc_cpt->cpt_revision == ROC_CPT_REVISION_ID_98XX) &&
+           (cpt->dev.pf_func & 0x1))
+               blknum = (blknum + 1) % ROC_CPT_MAX_BLKS;
+
        /* Request LF resources */
-       rc = cpt_lfs_attach(&cpt->dev, blkaddr, false, nb_lf);
-       if (rc)
+       rc = cpt_lfs_attach(&cpt->dev, blkaddr[blknum], true, nb_lf);
+
+       /* Request LFs from another block if current block has less LFs */
+       if (roc_cpt->cpt_revision == ROC_CPT_REVISION_ID_98XX && rc == ENOSPC) {
+               blknum = (blknum + 1) % ROC_CPT_MAX_BLKS;
+               rc = cpt_lfs_attach(&cpt->dev, blkaddr[blknum], true, nb_lf);
+       }
+       if (rc) {
+               plt_err("Could not attach LFs");
                return rc;
+       }
+
+       for (i = 0; i < nb_lf; i++)
+               cpt->lf_blkaddr[i] = blkaddr[blknum];
 
        eng_grpmsk = (1 << roc_cpt->eng_grp[CPT_ENG_TYPE_AE]) |
                     (1 << roc_cpt->eng_grp[CPT_ENG_TYPE_SE]) |
                     (1 << roc_cpt->eng_grp[CPT_ENG_TYPE_IE]);
 
-       rc = cpt_lfs_alloc(&cpt->dev, eng_grpmsk, blkaddr, false);
+       rc = cpt_lfs_alloc(&cpt->dev, eng_grpmsk, blkaddr[blknum], false);
        if (rc)
                goto lfs_detach;
 
@@ -209,6 +557,67 @@ cpt_get_blkaddr(struct dev *dev)
        return reg & 0x1FFULL ? RVU_BLOCK_ADDR_CPT1 : RVU_BLOCK_ADDR_CPT0;
 }
 
+int
+cpt_lf_init(struct roc_cpt_lf *lf)
+{
+       struct dev *dev = lf->dev;
+       uint64_t blkaddr;
+       void *iq_mem;
+       int rc;
+
+       if (lf->nb_desc == 0 || lf->nb_desc > CPT_LF_MAX_NB_DESC)
+               lf->nb_desc = CPT_LF_DEFAULT_NB_DESC;
+
+       /* Update nb_desc to next power of 2 to aid in pending queue checks */
+       lf->nb_desc = plt_align32pow2(lf->nb_desc);
+
+       /* Allocate memory for instruction queue for CPT LF. */
+       iq_mem = plt_zmalloc(cpt_lf_iq_mem_calc(lf->nb_desc), ROC_ALIGN);
+       if (iq_mem == NULL)
+               return -ENOMEM;
+       plt_atomic_thread_fence(__ATOMIC_ACQ_REL);
+
+       blkaddr = cpt_get_blkaddr(dev);
+       lf->rbase = dev->bar2 + ((blkaddr << 20) | (lf->lf_id << 12));
+       lf->iq_vaddr = iq_mem;
+       lf->lmt_base = dev->lmt_base;
+       lf->pf_func = dev->pf_func;
+
+       /* Initialize instruction queue */
+       cpt_iq_init(lf);
+
+       rc = cpt_lf_register_irqs(lf);
+       if (rc)
+               goto disable_iq;
+
+       return 0;
+
+disable_iq:
+       roc_cpt_iq_disable(lf);
+       plt_free(iq_mem);
+       return rc;
+}
+
+int
+roc_cpt_lf_init(struct roc_cpt *roc_cpt, struct roc_cpt_lf *lf)
+{
+       struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
+       int rc;
+
+       lf->dev = &cpt->dev;
+       lf->roc_cpt = roc_cpt;
+       lf->msixoff = cpt->lf_msix_off[lf->lf_id];
+       lf->pci_dev = cpt->pci_dev;
+
+       rc = cpt_lf_init(lf);
+       if (rc)
+               return rc;
+
+       /* LF init successful */
+       roc_cpt->lf[lf->lf_id] = lf;
+       return rc;
+}
+
 int
 roc_cpt_dev_init(struct roc_cpt *roc_cpt)
 {
@@ -238,7 +647,7 @@ roc_cpt_dev_init(struct roc_cpt *roc_cpt)
        cpt->pci_dev = pci_dev;
        roc_cpt->lmt_base = dev->lmt_base;
 
-       rc = cpt_hardware_caps_get(dev, roc_cpt->hw_caps);
+       rc = cpt_hardware_caps_get(dev, roc_cpt);
        if (rc) {
                plt_err("Could not determine hardware capabilities");
                goto fail;
@@ -251,7 +660,7 @@ roc_cpt_dev_init(struct roc_cpt *roc_cpt)
        }
 
        /* Reserve 1 CPT LF for inline inbound */
-       nb_lf_avail = PLT_MIN(nb_lf_avail, ROC_CPT_MAX_LFS - 1);
+       nb_lf_avail = PLT_MIN(nb_lf_avail, (uint16_t)(ROC_CPT_MAX_LFS - 1));
 
        roc_cpt->nb_lf_avail = nb_lf_avail;
 
@@ -267,6 +676,47 @@ fail:
        return rc;
 }
 
+int
+roc_cpt_lf_ctx_flush(struct roc_cpt_lf *lf, uint64_t cptr)
+{
+       union cpt_lf_ctx_flush reg;
+
+       if (lf == NULL)
+               return -ENOTSUP;
+
+       reg.u = 0;
+       reg.s.pf_func = lf->pf_func;
+       reg.s.inval = 1;
+       reg.s.cptr = cptr;
+
+       plt_write64(reg.u, lf->rbase + CPT_LF_CTX_FLUSH);
+
+       return 0;
+}
+
+void
+cpt_lf_fini(struct roc_cpt_lf *lf)
+{
+       /* Unregister IRQ's */
+       cpt_lf_unregister_irqs(lf);
+
+       /* Disable IQ */
+       roc_cpt_iq_disable(lf);
+
+       /* Free memory */
+       plt_free(lf->iq_vaddr);
+       lf->iq_vaddr = NULL;
+}
+
+void
+roc_cpt_lf_fini(struct roc_cpt_lf *lf)
+{
+       if (lf == NULL)
+               return;
+       lf->roc_cpt->lf[lf->lf_id] = NULL;
+       cpt_lf_fini(lf);
+}
+
 int
 roc_cpt_dev_fini(struct roc_cpt *roc_cpt)
 {
@@ -341,3 +791,102 @@ roc_cpt_eng_grp_add(struct roc_cpt *roc_cpt, enum cpt_eng_type eng_type)
 
        return rsp->eng_grp_num;
 }
+
+void
+roc_cpt_iq_disable(struct roc_cpt_lf *lf)
+{
+       union cpt_lf_ctl lf_ctl = {.u = 0x0};
+       union cpt_lf_q_grp_ptr grp_ptr;
+       union cpt_lf_inprog lf_inprog;
+       int timeout = 20;
+       int cnt;
+
+       /* Disable instructions enqueuing */
+       plt_write64(lf_ctl.u, lf->rbase + CPT_LF_CTL);
+
+       /* Wait for instruction queue to become empty */
+       do {
+               lf_inprog.u = plt_read64(lf->rbase + CPT_LF_INPROG);
+               if (!lf_inprog.s.inflight)
+                       break;
+
+               plt_delay_ms(20);
+               if (timeout-- < 0) {
+                       plt_err("CPT LF %d is still busy", lf->lf_id);
+                       break;
+               }
+
+       } while (1);
+
+       /* Disable executions in the LF's queue.
+        * The queue should be empty at this point
+        */
+       lf_inprog.s.eena = 0x0;
+       plt_write64(lf_inprog.u, lf->rbase + CPT_LF_INPROG);
+
+       /* Wait for instruction queue to become empty */
+       cnt = 0;
+       do {
+               lf_inprog.u = plt_read64(lf->rbase + CPT_LF_INPROG);
+               if (lf_inprog.s.grb_partial)
+                       cnt = 0;
+               else
+                       cnt++;
+               grp_ptr.u = plt_read64(lf->rbase + CPT_LF_Q_GRP_PTR);
+       } while ((cnt < 10) && (grp_ptr.s.nq_ptr != grp_ptr.s.dq_ptr));
+
+       cnt = 0;
+       do {
+               lf_inprog.u = plt_read64(lf->rbase + CPT_LF_INPROG);
+               if ((lf_inprog.s.inflight == 0) && (lf_inprog.s.gwb_cnt < 40) &&
+                   ((lf_inprog.s.grb_cnt == 0) || (lf_inprog.s.grb_cnt == 40)))
+                       cnt++;
+               else
+                       cnt = 0;
+       } while (cnt < 10);
+}
+
+void
+roc_cpt_iq_enable(struct roc_cpt_lf *lf)
+{
+       union cpt_lf_inprog lf_inprog;
+       union cpt_lf_ctl lf_ctl;
+
+       /* Disable command queue */
+       roc_cpt_iq_disable(lf);
+
+       /* Enable instruction queue enqueuing */
+       lf_ctl.u = plt_read64(lf->rbase + CPT_LF_CTL);
+       lf_ctl.s.ena = 1;
+       lf_ctl.s.fc_ena = 1;
+       lf_ctl.s.fc_up_crossing = 0;
+       lf_ctl.s.fc_hyst_bits = lf->fc_hyst_bits;
+       plt_write64(lf_ctl.u, lf->rbase + CPT_LF_CTL);
+
+       /* Enable command queue execution */
+       lf_inprog.u = plt_read64(lf->rbase + CPT_LF_INPROG);
+       lf_inprog.s.eena = 1;
+       plt_write64(lf_inprog.u, lf->rbase + CPT_LF_INPROG);
+
+       cpt_lf_dump(lf);
+}
+
+int
+roc_cpt_lmtline_init(struct roc_cpt *roc_cpt, struct roc_cpt_lmtline *lmtline,
+                    int lf_id)
+{
+       struct roc_cpt_lf *lf;
+
+       lf = roc_cpt->lf[lf_id];
+       if (lf == NULL)
+               return -ENOTSUP;
+
+       lmtline->io_addr = lf->io_addr;
+       if (roc_model_is_cn10k())
+               lmtline->io_addr |= ROC_CN10K_CPT_INST_DW_M1 << 4;
+
+       lmtline->fc_addr = lf->fc_addr;
+       lmtline->lmt_base = lf->lmt_base;
+
+       return 0;
+}