Commit 40088915 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'octeontx2-af-miscellaneous-changes-for-cpt'

Srujana Challa says:

====================
octeontx2-af: Miscellaneous changes for CPT

This patchset consists of miscellaneous changes for CPT.
First patch enables the CPT HW interrupts, second patch
adds support for CPT LF teardown in non FLR path and
final patch does CPT CTX flush in FLR handler.

v2:
- Fixed a warning reported by kernel test robot.
====================

Link: https://lore.kernel.org/r/20211013055621.1812301-1-schalla@marvell.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents a3d70892 149f3b73
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -191,6 +191,7 @@ M(CPT_INLINE_IPSEC_CFG, 0xA04, cpt_inline_ipsec_cfg, \
M(CPT_STATS,            0xA05, cpt_sts, cpt_sts_req, cpt_sts_rsp)	\
M(CPT_RXC_TIME_CFG,     0xA06, cpt_rxc_time_cfg, cpt_rxc_time_cfg_req,  \
			       msg_rsp)                                 \
M(CPT_CTX_CACHE_SYNC,   0xA07, cpt_ctx_cache_sync, msg_req, msg_rsp)    \
/* SDP mbox IDs (range 0x1000 - 0x11FF) */				\
M(SET_SDP_CHAN_INFO, 0x1000, set_sdp_chan_info, sdp_chan_info_msg, msg_rsp) \
M(GET_SDP_CHAN_INFO, 0x1001, get_sdp_chan_info, msg_req, sdp_get_chan_info_msg) \
@@ -292,10 +293,14 @@ M(NIX_BANDPROF_GET_HWINFO, 0x801f, nix_bandprof_get_hwinfo, msg_req, \
#define MBOX_UP_CGX_MESSAGES						\
M(CGX_LINK_EVENT,	0xC00, cgx_link_event, cgx_link_info_msg, msg_rsp)

#define MBOX_UP_CPT_MESSAGES						\
M(CPT_INST_LMTST,	0xD00, cpt_inst_lmtst, cpt_inst_lmtst_req, msg_rsp)

enum {
#define M(_name, _id, _1, _2, _3) MBOX_MSG_ ## _name = _id,
MBOX_MESSAGES
MBOX_UP_CGX_MESSAGES
MBOX_UP_CPT_MESSAGES
#undef M
};

@@ -1562,6 +1567,13 @@ struct cpt_rxc_time_cfg_req {
	u16 active_limit;
};

/* Mailbox message request format to request for CPT_INST_S lmtst. */
struct cpt_inst_lmtst_req {
	struct mbox_msghdr hdr;
	u64 inst[8];
	u64 rsvd;
};

struct sdp_node_info {
	/* Node to which this PF belons to */
	u8 node_id;
+15 −1
Original line number Diff line number Diff line
@@ -854,6 +854,7 @@ static int rvu_setup_nix_hw_resource(struct rvu *rvu, int blkaddr)
	block->lfcfg_reg = NIX_PRIV_LFX_CFG;
	block->msixcfg_reg = NIX_PRIV_LFX_INT_CFG;
	block->lfreset_reg = NIX_AF_LF_RST;
	block->rvu = rvu;
	sprintf(block->name, "NIX%d", blkid);
	rvu->nix_blkaddr[blkid] = blkaddr;
	return rvu_alloc_bitmap(&block->lf);
@@ -883,6 +884,7 @@ static int rvu_setup_cpt_hw_resource(struct rvu *rvu, int blkaddr)
	block->lfcfg_reg = CPT_PRIV_LFX_CFG;
	block->msixcfg_reg = CPT_PRIV_LFX_INT_CFG;
	block->lfreset_reg = CPT_AF_LF_RST;
	block->rvu = rvu;
	sprintf(block->name, "CPT%d", blkid);
	return rvu_alloc_bitmap(&block->lf);
}
@@ -940,6 +942,7 @@ static int rvu_setup_hw_resources(struct rvu *rvu)
	block->lfcfg_reg = NPA_PRIV_LFX_CFG;
	block->msixcfg_reg = NPA_PRIV_LFX_INT_CFG;
	block->lfreset_reg = NPA_AF_LF_RST;
	block->rvu = rvu;
	sprintf(block->name, "NPA");
	err = rvu_alloc_bitmap(&block->lf);
	if (err) {
@@ -979,6 +982,7 @@ static int rvu_setup_hw_resources(struct rvu *rvu)
	block->lfcfg_reg = SSO_PRIV_LFX_HWGRP_CFG;
	block->msixcfg_reg = SSO_PRIV_LFX_HWGRP_INT_CFG;
	block->lfreset_reg = SSO_AF_LF_HWGRP_RST;
	block->rvu = rvu;
	sprintf(block->name, "SSO GROUP");
	err = rvu_alloc_bitmap(&block->lf);
	if (err) {
@@ -1003,6 +1007,7 @@ static int rvu_setup_hw_resources(struct rvu *rvu)
	block->lfcfg_reg = SSOW_PRIV_LFX_HWS_CFG;
	block->msixcfg_reg = SSOW_PRIV_LFX_HWS_INT_CFG;
	block->lfreset_reg = SSOW_AF_LF_HWS_RST;
	block->rvu = rvu;
	sprintf(block->name, "SSOWS");
	err = rvu_alloc_bitmap(&block->lf);
	if (err) {
@@ -1028,6 +1033,7 @@ static int rvu_setup_hw_resources(struct rvu *rvu)
	block->lfcfg_reg = TIM_PRIV_LFX_CFG;
	block->msixcfg_reg = TIM_PRIV_LFX_INT_CFG;
	block->lfreset_reg = TIM_AF_LF_RST;
	block->rvu = rvu;
	sprintf(block->name, "TIM");
	err = rvu_alloc_bitmap(&block->lf);
	if (err) {
@@ -2526,7 +2532,8 @@ static void rvu_blklf_teardown(struct rvu *rvu, u16 pcifunc, u8 blkaddr)
			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);
			rvu_cpt_lf_teardown(rvu, pcifunc, block->addr, lf,
					    slot);

		err = rvu_lf_reset(rvu, block, lf);
		if (err) {
@@ -2724,6 +2731,8 @@ static void rvu_unregister_interrupts(struct rvu *rvu)
{
	int irq;

	rvu_cpt_unregister_interrupts(rvu);

	/* Disable the Mbox interrupt */
	rvu_write64(rvu, BLKADDR_RVUM, RVU_AF_PFAF_MBOX_INT_ENA_W1C,
		    INTR_MASK(rvu->hw->total_pfs) & ~1ULL);
@@ -2933,6 +2942,11 @@ static int rvu_register_interrupts(struct rvu *rvu)
		goto fail;
	}
	rvu->irq_allocated[offset] = true;

	ret = rvu_cpt_register_interrupts(rvu);
	if (ret)
		goto fail;

	return 0;

fail:
+6 −1
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ struct rvu_block {
	u64  msixcfg_reg;
	u64  lfreset_reg;
	unsigned char name[NAME_SIZE];
	struct rvu *rvu;
};

struct nix_mcast {
@@ -812,7 +813,11 @@ bool is_mcam_entry_enabled(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr,
			   int index);

/* CPT APIs */
int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int lf, int slot);
int rvu_cpt_register_interrupts(struct rvu *rvu);
void rvu_cpt_unregister_interrupts(struct rvu *rvu);
int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf,
			int slot);
int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc);

/* CN10K RVU */
int rvu_set_channels_base(struct rvu *rvu);
+453 −13
Original line number Diff line number Diff line
@@ -37,6 +37,236 @@
	(_rsp)->free_sts_##etype = free_sts;                        \
})

static irqreturn_t rvu_cpt_af_flt_intr_handler(int irq, void *ptr)
{
	struct rvu_block *block = ptr;
	struct rvu *rvu = block->rvu;
	int blkaddr = block->addr;
	u64 reg0, reg1, reg2;

	reg0 = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(0));
	reg1 = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(1));
	if (!is_rvu_otx2(rvu)) {
		reg2 = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(2));
		dev_err_ratelimited(rvu->dev,
				    "Received CPTAF FLT irq : 0x%llx, 0x%llx, 0x%llx",
				     reg0, reg1, reg2);
	} else {
		dev_err_ratelimited(rvu->dev,
				    "Received CPTAF FLT irq : 0x%llx, 0x%llx",
				     reg0, reg1);
	}

	rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT(0), reg0);
	rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT(1), reg1);
	if (!is_rvu_otx2(rvu))
		rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT(2), reg2);

	return IRQ_HANDLED;
}

static irqreturn_t rvu_cpt_af_rvu_intr_handler(int irq, void *ptr)
{
	struct rvu_block *block = ptr;
	struct rvu *rvu = block->rvu;
	int blkaddr = block->addr;
	u64 reg;

	reg = rvu_read64(rvu, blkaddr, CPT_AF_RVU_INT);
	dev_err_ratelimited(rvu->dev, "Received CPTAF RVU irq : 0x%llx", reg);

	rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT, reg);
	return IRQ_HANDLED;
}

static irqreturn_t rvu_cpt_af_ras_intr_handler(int irq, void *ptr)
{
	struct rvu_block *block = ptr;
	struct rvu *rvu = block->rvu;
	int blkaddr = block->addr;
	u64 reg;

	reg = rvu_read64(rvu, blkaddr, CPT_AF_RAS_INT);
	dev_err_ratelimited(rvu->dev, "Received CPTAF RAS irq : 0x%llx", reg);

	rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT, reg);
	return IRQ_HANDLED;
}

static int rvu_cpt_do_register_interrupt(struct rvu_block *block, int irq_offs,
					 irq_handler_t handler,
					 const char *name)
{
	struct rvu *rvu = block->rvu;
	int ret;

	ret = request_irq(pci_irq_vector(rvu->pdev, irq_offs), handler, 0,
			  name, block);
	if (ret) {
		dev_err(rvu->dev, "RVUAF: %s irq registration failed", name);
		return ret;
	}

	WARN_ON(rvu->irq_allocated[irq_offs]);
	rvu->irq_allocated[irq_offs] = true;
	return 0;
}

static void cpt_10k_unregister_interrupts(struct rvu_block *block, int off)
{
	struct rvu *rvu = block->rvu;
	int blkaddr = block->addr;
	int i;

	/* Disable all CPT AF interrupts */
	for (i = 0; i < CPT_10K_AF_INT_VEC_RVU; i++)
		rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1C(i), 0x1);
	rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1C, 0x1);
	rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1C, 0x1);

	for (i = 0; i < CPT_10K_AF_INT_VEC_CNT; i++)
		if (rvu->irq_allocated[off + i]) {
			free_irq(pci_irq_vector(rvu->pdev, off + i), block);
			rvu->irq_allocated[off + i] = false;
		}
}

static void cpt_unregister_interrupts(struct rvu *rvu, int blkaddr)
{
	struct rvu_hwinfo *hw = rvu->hw;
	struct rvu_block *block;
	int i, offs;

	if (!is_block_implemented(rvu->hw, blkaddr))
		return;
	offs = rvu_read64(rvu, blkaddr, CPT_PRIV_AF_INT_CFG) & 0x7FF;
	if (!offs) {
		dev_warn(rvu->dev,
			 "Failed to get CPT_AF_INT vector offsets\n");
		return;
	}
	block = &hw->block[blkaddr];
	if (!is_rvu_otx2(rvu))
		return cpt_10k_unregister_interrupts(block, offs);

	/* Disable all CPT AF interrupts */
	for (i = 0; i < CPT_AF_INT_VEC_RVU; i++)
		rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1C(i), 0x1);
	rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1C, 0x1);
	rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1C, 0x1);

	for (i = 0; i < CPT_AF_INT_VEC_CNT; i++)
		if (rvu->irq_allocated[offs + i]) {
			free_irq(pci_irq_vector(rvu->pdev, offs + i), block);
			rvu->irq_allocated[offs + i] = false;
		}
}

void rvu_cpt_unregister_interrupts(struct rvu *rvu)
{
	cpt_unregister_interrupts(rvu, BLKADDR_CPT0);
	cpt_unregister_interrupts(rvu, BLKADDR_CPT1);
}

static int cpt_10k_register_interrupts(struct rvu_block *block, int off)
{
	struct rvu *rvu = block->rvu;
	int blkaddr = block->addr;
	char irq_name[16];
	int i, ret;

	for (i = CPT_10K_AF_INT_VEC_FLT0; i < CPT_10K_AF_INT_VEC_RVU; i++) {
		snprintf(irq_name, sizeof(irq_name), "CPTAF FLT%d", i);
		ret = rvu_cpt_do_register_interrupt(block, off + i,
						    rvu_cpt_af_flt_intr_handler,
						    irq_name);
		if (ret)
			goto err;
		rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1S(i), 0x1);
	}

	ret = rvu_cpt_do_register_interrupt(block, off + CPT_10K_AF_INT_VEC_RVU,
					    rvu_cpt_af_rvu_intr_handler,
					    "CPTAF RVU");
	if (ret)
		goto err;
	rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1S, 0x1);

	ret = rvu_cpt_do_register_interrupt(block, off + CPT_10K_AF_INT_VEC_RAS,
					    rvu_cpt_af_ras_intr_handler,
					    "CPTAF RAS");
	if (ret)
		goto err;
	rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1S, 0x1);

	return 0;
err:
	rvu_cpt_unregister_interrupts(rvu);
	return ret;
}

static int cpt_register_interrupts(struct rvu *rvu, int blkaddr)
{
	struct rvu_hwinfo *hw = rvu->hw;
	struct rvu_block *block;
	int i, offs, ret = 0;
	char irq_name[16];

	if (!is_block_implemented(rvu->hw, blkaddr))
		return 0;

	block = &hw->block[blkaddr];
	offs = rvu_read64(rvu, blkaddr, CPT_PRIV_AF_INT_CFG) & 0x7FF;
	if (!offs) {
		dev_warn(rvu->dev,
			 "Failed to get CPT_AF_INT vector offsets\n");
		return 0;
	}

	if (!is_rvu_otx2(rvu))
		return cpt_10k_register_interrupts(block, offs);

	for (i = CPT_AF_INT_VEC_FLT0; i < CPT_AF_INT_VEC_RVU; i++) {
		snprintf(irq_name, sizeof(irq_name), "CPTAF FLT%d", i);
		ret = rvu_cpt_do_register_interrupt(block, offs + i,
						    rvu_cpt_af_flt_intr_handler,
						    irq_name);
		if (ret)
			goto err;
		rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1S(i), 0x1);
	}

	ret = rvu_cpt_do_register_interrupt(block, offs + CPT_AF_INT_VEC_RVU,
					    rvu_cpt_af_rvu_intr_handler,
					    "CPTAF RVU");
	if (ret)
		goto err;
	rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1S, 0x1);

	ret = rvu_cpt_do_register_interrupt(block, offs + CPT_AF_INT_VEC_RAS,
					    rvu_cpt_af_ras_intr_handler,
					    "CPTAF RAS");
	if (ret)
		goto err;
	rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1S, 0x1);

	return 0;
err:
	rvu_cpt_unregister_interrupts(rvu);
	return ret;
}

int rvu_cpt_register_interrupts(struct rvu *rvu)
{
	int ret;

	ret = cpt_register_interrupts(rvu, BLKADDR_CPT0);
	if (ret)
		return ret;

	return cpt_register_interrupts(rvu, BLKADDR_CPT1);
}

static int get_cpt_pf_num(struct rvu *rvu)
{
	int i, domain_nr, cpt_pf_num = -1;
@@ -147,9 +377,13 @@ int rvu_mbox_handler_cpt_lf_alloc(struct rvu *rvu,

		rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), val);

		/* Set CPT LF NIX_PF_FUNC and SSO_PF_FUNC */
		val = (u64)req->nix_pf_func << 48 |
		      (u64)req->sso_pf_func << 32;
		/* Set CPT LF NIX_PF_FUNC and SSO_PF_FUNC. EXE_LDWB is set
		 * on reset.
		 */
		val = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf));
		val &= ~(GENMASK_ULL(63, 48) | GENMASK_ULL(47, 32));
		val |= ((u64)req->nix_pf_func << 48 |
			(u64)req->sso_pf_func << 32);
		rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf), val);
	}

@@ -159,7 +393,7 @@ int rvu_mbox_handler_cpt_lf_alloc(struct rvu *rvu,
static int cpt_lf_free(struct rvu *rvu, struct msg_req *req, int blkaddr)
{
	u16 pcifunc = req->hdr.pcifunc;
	int num_lfs, cptlf, slot;
	int num_lfs, cptlf, slot, err;
	struct rvu_block *block;

	block = &rvu->hw->block[blkaddr];
@@ -173,10 +407,15 @@ static int cpt_lf_free(struct rvu *rvu, struct msg_req *req, int blkaddr)
		if (cptlf < 0)
			return CPT_AF_ERR_LF_INVALID;

		/* Reset CPT LF group and priority */
		rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), 0x0);
		/* Reset CPT LF NIX_PF_FUNC and SSO_PF_FUNC */
		rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf), 0x0);
		/* Perform teardown */
		rvu_cpt_lf_teardown(rvu, pcifunc, blkaddr, cptlf, slot);

		/* Reset LF */
		err = rvu_lf_reset(rvu, block, cptlf);
		if (err) {
			dev_err(rvu->dev, "Failed to reset blkaddr %d LF%d\n",
				block->addr, cptlf);
		}
	}

	return 0;
@@ -556,6 +795,58 @@ int rvu_mbox_handler_cpt_rxc_time_cfg(struct rvu *rvu,
	return 0;
}

int rvu_mbox_handler_cpt_ctx_cache_sync(struct rvu *rvu, struct msg_req *req,
					struct msg_rsp *rsp)
{
	return rvu_cpt_ctx_flush(rvu, req->hdr.pcifunc);
}

static void cpt_rxc_teardown(struct rvu *rvu, int blkaddr)
{
	struct cpt_rxc_time_cfg_req req;
	int timeout = 2000;
	u64 reg;

	if (is_rvu_otx2(rvu))
		return;

	/* Set time limit to minimum values, so that rxc entries will be
	 * flushed out quickly.
	 */
	req.step = 1;
	req.zombie_thres = 1;
	req.zombie_limit = 1;
	req.active_thres = 1;
	req.active_limit = 1;

	cpt_rxc_time_cfg(rvu, &req, blkaddr);

	do {
		reg = rvu_read64(rvu, blkaddr, CPT_AF_RXC_ACTIVE_STS);
		udelay(1);
		if (FIELD_GET(RXC_ACTIVE_COUNT, reg))
			timeout--;
		else
			break;
	} while (timeout);

	if (timeout == 0)
		dev_warn(rvu->dev, "Poll for RXC active count hits hard loop counter\n");

	timeout = 2000;
	do {
		reg = rvu_read64(rvu, blkaddr, CPT_AF_RXC_ZOMBIE_STS);
		udelay(1);
		if (FIELD_GET(RXC_ZOMBIE_COUNT, reg))
			timeout--;
		else
			break;
	} while (timeout);

	if (timeout == 0)
		dev_warn(rvu->dev, "Poll for RXC zombie count hits hard loop counter\n");
}

#define INPROG_INFLIGHT(reg)    ((reg) & 0x1FF)
#define INPROG_GRB_PARTIAL(reg) ((reg) & BIT_ULL(31))
#define INPROG_GRB(reg)         (((reg) >> 32) & 0xFF)
@@ -620,14 +911,12 @@ static void cpt_lf_disable_iqueue(struct rvu *rvu, int blkaddr, int slot)
		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 rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, 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;
	if (is_cpt_pf(rvu, pcifunc) || is_cpt_vf(rvu, pcifunc))
		cpt_rxc_teardown(rvu, blkaddr);

	/* Enable BAR2 ALIAS for this pcifunc. */
	reg = BIT_ULL(16) | pcifunc;
@@ -644,3 +933,154 @@ int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int lf, int slot)

	return 0;
}

#define CPT_RES_LEN    16
#define CPT_SE_IE_EGRP 1ULL

static int cpt_inline_inb_lf_cmd_send(struct rvu *rvu, int blkaddr,
				      int nix_blkaddr)
{
	int cpt_pf_num = get_cpt_pf_num(rvu);
	struct cpt_inst_lmtst_req *req;
	dma_addr_t res_daddr;
	int timeout = 3000;
	u8 cpt_idx;
	u64 *inst;
	u16 *res;
	int rc;

	res = kzalloc(CPT_RES_LEN, GFP_KERNEL);
	if (!res)
		return -ENOMEM;

	res_daddr = dma_map_single(rvu->dev, res, CPT_RES_LEN,
				   DMA_BIDIRECTIONAL);
	if (dma_mapping_error(rvu->dev, res_daddr)) {
		dev_err(rvu->dev, "DMA mapping failed for CPT result\n");
		rc = -EFAULT;
		goto res_free;
	}
	*res = 0xFFFF;

	/* Send mbox message to CPT PF */
	req = (struct cpt_inst_lmtst_req *)
	       otx2_mbox_alloc_msg_rsp(&rvu->afpf_wq_info.mbox_up,
				       cpt_pf_num, sizeof(*req),
				       sizeof(struct msg_rsp));
	if (!req) {
		rc = -ENOMEM;
		goto res_daddr_unmap;
	}
	req->hdr.sig = OTX2_MBOX_REQ_SIG;
	req->hdr.id = MBOX_MSG_CPT_INST_LMTST;

	inst = req->inst;
	/* Prepare CPT_INST_S */
	inst[0] = 0;
	inst[1] = res_daddr;
	/* AF PF FUNC */
	inst[2] = 0;
	/* Set QORD */
	inst[3] = 1;
	inst[4] = 0;
	inst[5] = 0;
	inst[6] = 0;
	/* Set EGRP */
	inst[7] = CPT_SE_IE_EGRP << 61;

	/* Subtract 1 from the NIX-CPT credit count to preserve
	 * credit counts.
	 */
	cpt_idx = (blkaddr == BLKADDR_CPT0) ? 0 : 1;
	rvu_write64(rvu, nix_blkaddr, NIX_AF_RX_CPTX_CREDIT(cpt_idx),
		    BIT_ULL(22) - 1);

	otx2_mbox_msg_send(&rvu->afpf_wq_info.mbox_up, cpt_pf_num);
	rc = otx2_mbox_wait_for_rsp(&rvu->afpf_wq_info.mbox_up, cpt_pf_num);
	if (rc)
		dev_warn(rvu->dev, "notification to pf %d failed\n",
			 cpt_pf_num);
	/* Wait for CPT instruction to be completed */
	do {
		mdelay(1);
		if (*res == 0xFFFF)
			timeout--;
		else
			break;
	} while (timeout);

	if (timeout == 0)
		dev_warn(rvu->dev, "Poll for result hits hard loop counter\n");

res_daddr_unmap:
	dma_unmap_single(rvu->dev, res_daddr, CPT_RES_LEN, DMA_BIDIRECTIONAL);
res_free:
	kfree(res);

	return 0;
}

#define CTX_CAM_PF_FUNC   GENMASK_ULL(61, 46)
#define CTX_CAM_CPTR      GENMASK_ULL(45, 0)

int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc)
{
	int nix_blkaddr, blkaddr;
	u16 max_ctx_entries, i;
	int slot = 0, num_lfs;
	u64 reg, cam_data;
	int rc;

	nix_blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
	if (nix_blkaddr < 0)
		return -EINVAL;

	if (is_rvu_otx2(rvu))
		return 0;

	blkaddr = (nix_blkaddr == BLKADDR_NIX1) ? BLKADDR_CPT1 : BLKADDR_CPT0;

	/* Submit CPT_INST_S to track when all packets have been
	 * flushed through for the NIX PF FUNC in inline inbound case.
	 */
	rc = cpt_inline_inb_lf_cmd_send(rvu, blkaddr, nix_blkaddr);
	if (rc)
		return rc;

	/* Wait for rxc entries to be flushed out */
	cpt_rxc_teardown(rvu, blkaddr);

	reg = rvu_read64(rvu, blkaddr, CPT_AF_CONSTANTS0);
	max_ctx_entries = (reg >> 48) & 0xFFF;

	mutex_lock(&rvu->rsrc_lock);

	num_lfs = rvu_get_rsrc_mapcount(rvu_get_pfvf(rvu, pcifunc),
					blkaddr);
	if (num_lfs == 0) {
		dev_warn(rvu->dev, "CPT LF is not configured\n");
		goto unlock;
	}

	/* Enable BAR2 ALIAS for this pcifunc. */
	reg = BIT_ULL(16) | pcifunc;
	rvu_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, reg);

	for (i = 0; i < max_ctx_entries; i++) {
		cam_data = rvu_read64(rvu, blkaddr, CPT_AF_CTX_CAM_DATA(i));

		if ((FIELD_GET(CTX_CAM_PF_FUNC, cam_data) == pcifunc) &&
		    FIELD_GET(CTX_CAM_CPTR, cam_data)) {
			reg = BIT_ULL(46) | FIELD_GET(CTX_CAM_CPTR, cam_data);
			rvu_write64(rvu, blkaddr,
				    CPT_AF_BAR2_ALIASX(slot, CPT_LF_CTX_FLUSH),
				    reg);
		}
	}
	rvu_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, 0);

unlock:
	mutex_unlock(&rvu->rsrc_lock);

	return 0;
}
+11 −0
Original line number Diff line number Diff line
@@ -4512,6 +4512,8 @@ int rvu_mbox_handler_nix_lf_stop_rx(struct rvu *rvu, struct msg_req *req,
	return rvu_cgx_start_stop_io(rvu, pcifunc, false);
}

#define RX_SA_BASE  GENMASK_ULL(52, 7)

void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf)
{
	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
@@ -4519,6 +4521,7 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf)
	int pf = rvu_get_pf(pcifunc);
	struct mac_ops *mac_ops;
	u8 cgx_id, lmac_id;
	u64 sa_base;
	void *cgxd;
	int err;

@@ -4575,6 +4578,14 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf)
	nix_ctx_free(rvu, pfvf);

	nix_free_all_bandprof(rvu, pcifunc);

	sa_base = rvu_read64(rvu, blkaddr, NIX_AF_LFX_RX_IPSEC_SA_BASE(nixlf));
	if (FIELD_GET(RX_SA_BASE, sa_base)) {
		err = rvu_cpt_ctx_flush(rvu, pcifunc);
		if (err)
			dev_err(rvu->dev,
				"CPT ctx flush failed with error: %d\n", err);
	}
}

#define NIX_AF_LFX_TX_CFG_PTP_EN	BIT_ULL(32)
Loading