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

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
...@@ -37,34 +37,60 @@ ...@@ -37,34 +37,60 @@
(_rsp)->free_sts_##etype = free_sts; \ (_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_block *block = ptr;
struct rvu *rvu = block->rvu; struct rvu *rvu = block->rvu;
int blkaddr = block->addr; int blkaddr = block->addr;
u64 reg0, reg1, reg2; u64 reg, val;
int i, eng;
reg0 = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(0)); u8 grp;
reg1 = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(1));
if (!is_rvu_otx2(rvu)) { reg = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(vec));
reg2 = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(2)); dev_err_ratelimited(rvu->dev, "Received CPTAF FLT%d irq : 0x%llx", vec, reg);
dev_err_ratelimited(rvu->dev,
"Received CPTAF FLT irq : 0x%llx, 0x%llx, 0x%llx", i = -1;
reg0, reg1, reg2); while ((i = find_next_bit((unsigned long *)&reg, 64, i + 1)) < 64) {
} else { switch (vec) {
dev_err_ratelimited(rvu->dev, case 0:
"Received CPTAF FLT irq : 0x%llx, 0x%llx", eng = i;
reg0, reg1); 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_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);
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; 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) static irqreturn_t rvu_cpt_af_rvu_intr_handler(int irq, void *ptr)
{ {
struct rvu_block *block = ptr; struct rvu_block *block = ptr;
...@@ -119,8 +145,10 @@ static void cpt_10k_unregister_interrupts(struct rvu_block *block, int off) ...@@ -119,8 +145,10 @@ static void cpt_10k_unregister_interrupts(struct rvu_block *block, int off)
int i; int i;
/* Disable all CPT AF interrupts */ /* 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(0), ~0ULL);
rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1C(i), 0x1); 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_RVU_INT_ENA_W1C, 0x1);
rvu_write64(rvu, blkaddr, CPT_AF_RAS_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) ...@@ -151,7 +179,7 @@ static void cpt_unregister_interrupts(struct rvu *rvu, int blkaddr)
/* Disable all CPT AF interrupts */ /* Disable all CPT AF interrupts */
for (i = 0; i < CPT_AF_INT_VEC_RVU; i++) 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_RVU_INT_ENA_W1C, 0x1);
rvu_write64(rvu, blkaddr, CPT_AF_RAS_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) ...@@ -172,16 +200,31 @@ static int cpt_10k_register_interrupts(struct rvu_block *block, int off)
{ {
struct rvu *rvu = block->rvu; struct rvu *rvu = block->rvu;
int blkaddr = block->addr; int blkaddr = block->addr;
irq_handler_t flt_fn;
int i, ret; int i, ret;
for (i = CPT_10K_AF_INT_VEC_FLT0; i < CPT_10K_AF_INT_VEC_RVU; i++) { 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); 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, ret = rvu_cpt_do_register_interrupt(block, off + i,
rvu_cpt_af_flt_intr_handler, flt_fn, &rvu->irq_name[(off + i) * NAME_SIZE]);
&rvu->irq_name[(off + i) * NAME_SIZE]);
if (ret) if (ret)
goto err; 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, 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) ...@@ -208,8 +251,8 @@ static int cpt_register_interrupts(struct rvu *rvu, int blkaddr)
{ {
struct rvu_hwinfo *hw = rvu->hw; struct rvu_hwinfo *hw = rvu->hw;
struct rvu_block *block; struct rvu_block *block;
irq_handler_t flt_fn;
int i, offs, ret = 0; int i, offs, ret = 0;
char irq_name[16];
if (!is_block_implemented(rvu->hw, blkaddr)) if (!is_block_implemented(rvu->hw, blkaddr))
return 0; return 0;
...@@ -226,13 +269,20 @@ static int cpt_register_interrupts(struct rvu *rvu, int blkaddr) ...@@ -226,13 +269,20 @@ static int cpt_register_interrupts(struct rvu *rvu, int blkaddr)
return cpt_10k_register_interrupts(block, offs); return cpt_10k_register_interrupts(block, offs);
for (i = CPT_AF_INT_VEC_FLT0; i < CPT_AF_INT_VEC_RVU; i++) { 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, ret = rvu_cpt_do_register_interrupt(block, offs + i,
rvu_cpt_af_flt_intr_handler, flt_fn, &rvu->irq_name[(offs + i) * NAME_SIZE]);
irq_name);
if (ret) if (ret)
goto err; 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, ret = rvu_cpt_do_register_interrupt(block, offs + CPT_AF_INT_VEC_RVU,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment