Commit c57c58fd authored by Srujana Challa's avatar Srujana Challa Committed by Jakub Kicinski
Browse files

octeontx2-af: Handle CPT function level reset



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: default avatarNarayana Prasad Raju Atherya <pathreya@marvell.com>
Signed-off-by: default avatarSuheil Chandran <schandran@marvell.com>
Signed-off-by: default avatarSunil Kovvuri Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarSrujana Challa <schalla@marvell.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent b0f60fab
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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) {
+2 −0
Original line number Diff line number Diff line
@@ -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);
+89 −0
Original line number Diff line number Diff line
@@ -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;
}
+8 −0
Original line number Diff line number Diff line
@@ -484,9 +484,17 @@
#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 */