octeontx2-af: Enable CPT HW interrupts
authorSrujana Challa <schalla@marvell.com>
Wed, 13 Oct 2021 05:56:19 +0000 (11:26 +0530)
committerJakub Kicinski <kuba@kernel.org>
Fri, 15 Oct 2021 03:01:06 +0000 (20:01 -0700)
This patch enables and registers interrupt handler for CPT HW
interrupts.

Signed-off-by: Srujana Challa <schalla@marvell.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/marvell/octeontx2/af/rvu.c
drivers/net/ethernet/marvell/octeontx2/af/rvu.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_struct.h

index 0a1e9f6..7698a67 100644 (file)
@@ -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 @@ nix:
        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 @@ ssow:
        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 @@ tim:
        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) {
@@ -2724,6 +2730,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 +2941,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:
index 58b1666..cdbd284 100644 (file)
@@ -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,6 +813,8 @@ bool is_mcam_entry_enabled(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr,
                           int index);
 
 /* CPT APIs */
+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 lf, int slot);
 
 /* CN10K RVU */
index 267d092..2591314 100644 (file)
        (_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;
index 77ac966..edc9367 100644 (file)
@@ -62,6 +62,24 @@ enum rvu_af_int_vec_e {
        RVU_AF_INT_VEC_CNT    = 0x5,
 };
 
+/* CPT Admin function Interrupt Vector Enumeration */
+enum cpt_af_int_vec_e {
+       CPT_AF_INT_VEC_FLT0     = 0x0,
+       CPT_AF_INT_VEC_FLT1     = 0x1,
+       CPT_AF_INT_VEC_RVU      = 0x2,
+       CPT_AF_INT_VEC_RAS      = 0x3,
+       CPT_AF_INT_VEC_CNT      = 0x4,
+};
+
+enum cpt_10k_af_int_vec_e {
+       CPT_10K_AF_INT_VEC_FLT0 = 0x0,
+       CPT_10K_AF_INT_VEC_FLT1 = 0x1,
+       CPT_10K_AF_INT_VEC_FLT2 = 0x2,
+       CPT_10K_AF_INT_VEC_RVU  = 0x3,
+       CPT_10K_AF_INT_VEC_RAS  = 0x4,
+       CPT_10K_AF_INT_VEC_CNT  = 0x5,
+};
+
 /* NPA Admin function Interrupt Vector Enumeration */
 enum npa_af_int_vec_e {
        NPA_AF_INT_VEC_RVU      = 0x0,