octeontx2-af: recover CPT engine when it gets fault
authorSrujana Challa <schalla@marvell.com>
Wed, 18 Jan 2023 12:03:48 +0000 (17:33 +0530)
committerDavid S. Miller <davem@davemloft.net>
Fri, 20 Jan 2023 09:00:08 +0000 (09:00 +0000)
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: Srujana Challa <schalla@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c

index 38bbae5..1ed16ce 100644 (file)
        (_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_EXEX_CTL2(eng), grp);
+               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_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,