Commit 07ea567d authored by Srujana Challa's avatar Srujana Challa Committed by David S. Miller
Browse files

octeontx2-af: recover CPT engine when it gets fault



When CPT engine has uncorrectable errors, it will get halted and
must be disabled and re-enabled. This patch adds code for the same.

Signed-off-by: default avatarSrujana Challa <schalla@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6c977c5c
Loading
Loading
Loading
Loading
+80 −30
Original line number Diff line number Diff line
@@ -37,34 +37,60 @@
	(_rsp)->free_sts_##etype = free_sts;                        \
})

static irqreturn_t rvu_cpt_af_flt_intr_handler(int irq, void *ptr)
static irqreturn_t cpt_af_flt_intr_handler(int vec, 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);
	u64 reg, val;
	int i, eng;
	u8 grp;

	reg = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(vec));
	dev_err_ratelimited(rvu->dev, "Received CPTAF FLT%d irq : 0x%llx", vec, reg);

	i = -1;
	while ((i = find_next_bit((unsigned long *)&reg, 64, i + 1)) < 64) {
		switch (vec) {
		case 0:
			eng = i;
			break;
		case 1:
			eng = i + 64;
			break;
		case 2:
			eng = i + 128;
			break;
		}
		grp = rvu_read64(rvu, blkaddr, CPT_AF_EXEX_CTL2(eng)) & 0xFF;
		/* Disable and enable the engine which triggers fault */
		rvu_write64(rvu, blkaddr, CPT_AF_EXEX_CTL2(eng), 0x0);
		val = rvu_read64(rvu, blkaddr, CPT_AF_EXEX_CTL(eng));
		rvu_write64(rvu, blkaddr, CPT_AF_EXEX_CTL(eng), val & ~1ULL);

	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);
		rvu_write64(rvu, blkaddr, CPT_AF_EXEX_CTL2(eng), grp);
		rvu_write64(rvu, blkaddr, CPT_AF_EXEX_CTL(eng), val | 1ULL);
	}
	rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT(vec), reg);

	return IRQ_HANDLED;
}

static irqreturn_t rvu_cpt_af_flt0_intr_handler(int irq, void *ptr)
{
	return cpt_af_flt_intr_handler(CPT_AF_INT_VEC_FLT0, ptr);
}

static irqreturn_t rvu_cpt_af_flt1_intr_handler(int irq, void *ptr)
{
	return cpt_af_flt_intr_handler(CPT_AF_INT_VEC_FLT1, ptr);
}

static irqreturn_t rvu_cpt_af_flt2_intr_handler(int irq, void *ptr)
{
	return cpt_af_flt_intr_handler(CPT_10K_AF_INT_VEC_FLT2, ptr);
}

static irqreturn_t rvu_cpt_af_rvu_intr_handler(int irq, void *ptr)
{
	struct rvu_block *block = ptr;
@@ -119,8 +145,10 @@ static void cpt_10k_unregister_interrupts(struct rvu_block *block, int off)
	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_FLTX_INT_ENA_W1C(0), ~0ULL);
	rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1C(1), ~0ULL);
	rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1C(2), 0xFFFF);

	rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1C, 0x1);
	rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1C, 0x1);

@@ -151,7 +179,7 @@ static void cpt_unregister_interrupts(struct rvu *rvu, int blkaddr)

	/* 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_FLTX_INT_ENA_W1C(i), ~0ULL);
	rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1C, 0x1);
	rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1C, 0x1);

@@ -172,16 +200,31 @@ static int cpt_10k_register_interrupts(struct rvu_block *block, int off)
{
	struct rvu *rvu = block->rvu;
	int blkaddr = block->addr;
	irq_handler_t flt_fn;
	int i, ret;

	for (i = CPT_10K_AF_INT_VEC_FLT0; i < CPT_10K_AF_INT_VEC_RVU; i++) {
		sprintf(&rvu->irq_name[(off + i) * NAME_SIZE], "CPTAF FLT%d", i);

		switch (i) {
		case CPT_10K_AF_INT_VEC_FLT0:
			flt_fn = rvu_cpt_af_flt0_intr_handler;
			break;
		case CPT_10K_AF_INT_VEC_FLT1:
			flt_fn = rvu_cpt_af_flt1_intr_handler;
			break;
		case CPT_10K_AF_INT_VEC_FLT2:
			flt_fn = rvu_cpt_af_flt2_intr_handler;
			break;
		}
		ret = rvu_cpt_do_register_interrupt(block, off + i,
						    rvu_cpt_af_flt_intr_handler,
						    &rvu->irq_name[(off + i) * NAME_SIZE]);
						    flt_fn, &rvu->irq_name[(off + i) * NAME_SIZE]);
		if (ret)
			goto err;
		rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1S(i), 0x1);
		if (i == CPT_10K_AF_INT_VEC_FLT2)
			rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1S(i), 0xFFFF);
		else
			rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1S(i), ~0ULL);
	}

	ret = rvu_cpt_do_register_interrupt(block, off + CPT_10K_AF_INT_VEC_RVU,
@@ -208,8 +251,8 @@ static int cpt_register_interrupts(struct rvu *rvu, int blkaddr)
{
	struct rvu_hwinfo *hw = rvu->hw;
	struct rvu_block *block;
	irq_handler_t flt_fn;
	int i, offs, ret = 0;
	char irq_name[16];

	if (!is_block_implemented(rvu->hw, blkaddr))
		return 0;
@@ -226,13 +269,20 @@ static int cpt_register_interrupts(struct rvu *rvu, int blkaddr)
		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);
		sprintf(&rvu->irq_name[(offs + i) * NAME_SIZE], "CPTAF FLT%d", i);
		switch (i) {
		case CPT_AF_INT_VEC_FLT0:
			flt_fn = rvu_cpt_af_flt0_intr_handler;
			break;
		case CPT_AF_INT_VEC_FLT1:
			flt_fn = rvu_cpt_af_flt1_intr_handler;
			break;
		}
		ret = rvu_cpt_do_register_interrupt(block, offs + i,
						    rvu_cpt_af_flt_intr_handler,
						    irq_name);
						    flt_fn, &rvu->irq_name[(offs + i) * NAME_SIZE]);
		if (ret)
			goto err;
		rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1S(i), 0x1);
		rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1S(i), ~0ULL);
	}

	ret = rvu_cpt_do_register_interrupt(block, offs + CPT_AF_INT_VEC_RVU,