OSDN Git Service

octeontx2-af: Handle CPT function level reset
authorSrujana Challa <schalla@marvell.com>
Tue, 2 Feb 2021 15:27:09 +0000 (20:57 +0530)
committerJakub Kicinski <kuba@kernel.org>
Thu, 4 Feb 2021 01:31:34 +0000 (17:31 -0800)
When FLR is initiated for a VF (PCI function level reset),
the parent PF gets a interrupt. PF then sends a message to
admin function (AF), which then cleans up all resources
attached to that VF. This patch adds support to handle
CPT FLR.

Signed-off-by: Narayana Prasad Raju Atherya <pathreya@marvell.com>
Signed-off-by: Suheil Chandran <schandran@marvell.com>
Signed-off-by: Sunil Kovvuri Goutham <sgoutham@marvell.com>
Signed-off-by: Srujana Challa <schalla@marvell.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/marvell/octeontx2/af/rvu.c
drivers/net/ethernet/marvell/octeontx2/af/rvu.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h

index 4ef7fc8..50c2a1d 100644 (file)
@@ -2150,6 +2150,9 @@ static void rvu_blklf_teardown(struct rvu *rvu, u16 pcifunc, u8 blkaddr)
                        rvu_nix_lf_teardown(rvu, pcifunc, block->addr, lf);
                else if (block->addr == BLKADDR_NPA)
                        rvu_npa_lf_teardown(rvu, pcifunc, lf);
+               else if ((block->addr == BLKADDR_CPT0) ||
+                        (block->addr == BLKADDR_CPT1))
+                       rvu_cpt_lf_teardown(rvu, pcifunc, lf, slot);
 
                err = rvu_lf_reset(rvu, block, lf);
                if (err) {
index aabf6d5..ce931d8 100644 (file)
@@ -608,6 +608,8 @@ void npc_enable_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
 void npc_read_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
                         int blkaddr, u16 src, struct mcam_entry *entry,
                         u8 *intf, u8 *ena);
+/* CPT APIs */
+int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int lf, int slot);
 
 #ifdef CONFIG_DEBUG_FS
 void rvu_dbg_init(struct rvu *rvu);
index b6de4b9..0945c3a 100644 (file)
@@ -240,3 +240,92 @@ int rvu_mbox_handler_cpt_rd_wr_register(struct rvu *rvu,
 
        return 0;
 }
+
+#define INPROG_INFLIGHT(reg)    ((reg) & 0x1FF)
+#define INPROG_GRB_PARTIAL(reg) ((reg) & BIT_ULL(31))
+#define INPROG_GRB(reg)         (((reg) >> 32) & 0xFF)
+#define INPROG_GWB(reg)         (((reg) >> 40) & 0xFF)
+
+static void cpt_lf_disable_iqueue(struct rvu *rvu, int blkaddr, int slot)
+{
+       int i = 0, hard_lp_ctr = 100000;
+       u64 inprog, grp_ptr;
+       u16 nq_ptr, dq_ptr;
+
+       /* Disable instructions enqueuing */
+       rvu_write64(rvu, blkaddr, CPT_AF_BAR2_ALIASX(slot, CPT_LF_CTL), 0x0);
+
+       /* Disable executions in the LF's queue */
+       inprog = rvu_read64(rvu, blkaddr,
+                           CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG));
+       inprog &= ~BIT_ULL(16);
+       rvu_write64(rvu, blkaddr,
+                   CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG), inprog);
+
+       /* Wait for CPT queue to become execution-quiescent */
+       do {
+               inprog = rvu_read64(rvu, blkaddr,
+                                   CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG));
+               if (INPROG_GRB_PARTIAL(inprog)) {
+                       i = 0;
+                       hard_lp_ctr--;
+               } else {
+                       i++;
+               }
+
+               grp_ptr = rvu_read64(rvu, blkaddr,
+                                    CPT_AF_BAR2_ALIASX(slot,
+                                                       CPT_LF_Q_GRP_PTR));
+               nq_ptr = (grp_ptr >> 32) & 0x7FFF;
+               dq_ptr = grp_ptr & 0x7FFF;
+
+       } while (hard_lp_ctr && (i < 10) && (nq_ptr != dq_ptr));
+
+       if (hard_lp_ctr == 0)
+               dev_warn(rvu->dev, "CPT FLR hits hard loop counter\n");
+
+       i = 0;
+       hard_lp_ctr = 100000;
+       do {
+               inprog = rvu_read64(rvu, blkaddr,
+                                   CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG));
+
+               if ((INPROG_INFLIGHT(inprog) == 0) &&
+                   (INPROG_GWB(inprog) < 40) &&
+                   ((INPROG_GRB(inprog) == 0) ||
+                    (INPROG_GRB((inprog)) == 40))) {
+                       i++;
+               } else {
+                       i = 0;
+                       hard_lp_ctr--;
+               }
+       } while (hard_lp_ctr && (i < 10));
+
+       if (hard_lp_ctr == 0)
+               dev_warn(rvu->dev, "CPT FLR hits hard loop counter\n");
+}
+
+int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int lf, int slot)
+{
+       int blkaddr;
+       u64 reg;
+
+       blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_CPT, pcifunc);
+       if (blkaddr != BLKADDR_CPT0 && blkaddr != BLKADDR_CPT1)
+               return -EINVAL;
+
+       /* Enable BAR2 ALIAS for this pcifunc. */
+       reg = BIT_ULL(16) | pcifunc;
+       rvu_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, reg);
+
+       cpt_lf_disable_iqueue(rvu, blkaddr, slot);
+
+       /* Set group drop to help clear out hardware */
+       reg = rvu_read64(rvu, blkaddr, CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG));
+       reg |= BIT_ULL(17);
+       rvu_write64(rvu, blkaddr, CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG), reg);
+
+       rvu_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, 0);
+
+       return 0;
+}
index 0fb2aa9..79a6dcf 100644 (file)
 #define CPT_AF_RAS_INT_ENA_W1S          (0x47030)
 #define CPT_AF_RAS_INT_ENA_W1C          (0x47038)
 
+#define AF_BAR2_ALIASX(a, b)            (0x9100000ull | (a) << 12 | (b))
+#define CPT_AF_BAR2_SEL                 0x9000000
+#define CPT_AF_BAR2_ALIASX(a, b)        AF_BAR2_ALIASX(a, b)
+
 #define CPT_AF_LF_CTL2_SHIFT 3
 #define CPT_AF_LF_SSO_PF_FUNC_SHIFT 32
 
+#define CPT_LF_CTL                      0x10
+#define CPT_LF_INPROG                   0x40
+#define CPT_LF_Q_GRP_PTR                0x120
+
 #define NPC_AF_BLK_RST                  (0x00040)
 
 /* NPC */