]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
octeontx2-af: CN20K mbox implementation for AF's VF
authorSai Krishna <saikrishnag@marvell.com>
Wed, 11 Jun 2025 11:01:55 +0000 (16:31 +0530)
committerJakub Kicinski <kuba@kernel.org>
Tue, 17 Jun 2025 00:37:49 +0000 (17:37 -0700)
This patch implements the CN20k MBOX communication between AF and
AF's VFs. This implementation uses separate trigger interrupts
for request, response messages against using trigger message data in CN10K.

Signed-off-by: Sai Krishna <saikrishnag@marvell.com>
Signed-off-by: Sunil Kovvuri Goutham <sgoutham@marvell.com>
Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
Link: https://patch.msgid.link/1749639716-13868-6-git-send-email-sbhatta@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/marvell/octeontx2/af/cn20k/api.h
drivers/net/ethernet/marvell/octeontx2/af/cn20k/mbox_init.c
drivers/net/ethernet/marvell/octeontx2/af/cn20k/reg.h
drivers/net/ethernet/marvell/octeontx2/af/mbox.c
drivers/net/ethernet/marvell/octeontx2/af/rvu.c
drivers/net/ethernet/marvell/octeontx2/af/rvu.h
drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c

index 5e3a1054835dd5e93cec3db775c1ef136ed31b09..4285b5d6a6a29a8775b41c679a819cef13af834b 100644 (file)
@@ -13,6 +13,7 @@
 struct ng_rvu {
        struct mbox_ops         *rvu_mbox_ops;
        struct qmem             *pf_mbox_addr;
+       struct qmem             *vf_mbox_addr;
 };
 
 /* Mbox related APIs */
@@ -21,8 +22,11 @@ int cn20k_rvu_get_mbox_regions(struct rvu *rvu, void **mbox_addr,
                               int num, int type, unsigned long *pf_bmap);
 void cn20k_free_mbox_memory(struct rvu *rvu);
 int cn20k_register_afpf_mbox_intr(struct rvu *rvu);
+int cn20k_register_afvf_mbox_intr(struct rvu *rvu, int pf_vec_start);
 void cn20k_rvu_enable_mbox_intr(struct rvu *rvu);
 void cn20k_rvu_unregister_interrupts(struct rvu *rvu);
 int cn20k_mbox_setup(struct otx2_mbox *mbox, struct pci_dev *pdev,
                     void *reg_base, int direction, int ndevs);
+void cn20k_rvu_enable_afvf_intr(struct rvu *rvu, int vfs);
+void cn20k_rvu_disable_afvf_intr(struct rvu *rvu, int vfs);
 #endif /* CN20K_API_H */
index 5c63a85ada36bb0cfee5b73d286b8e07eba4900a..bd3aab7770ddf5e8ef1855d16b6bc1c1f6e0f4db 100644 (file)
 #include "reg.h"
 #include "api.h"
 
+static irqreturn_t cn20k_afvf_mbox_intr_handler(int irq, void *rvu_irq)
+{
+       struct rvu_irq_data *rvu_irq_data = rvu_irq;
+       struct rvu *rvu = rvu_irq_data->rvu;
+       u64 intr;
+
+       /* Sync with mbox memory region */
+       rmb();
+
+       /* Clear interrupts */
+       intr = rvupf_read64(rvu, rvu_irq_data->intr_status);
+       rvupf_write64(rvu, rvu_irq_data->intr_status, intr);
+
+       if (intr)
+               trace_otx2_msg_interrupt(rvu->pdev, "VF(s) to AF", intr);
+
+       rvu_irq_data->afvf_queue_work_hdlr(&rvu->afvf_wq_info, rvu_irq_data->start,
+                                          rvu_irq_data->mdevs, intr);
+
+       return IRQ_HANDLED;
+}
+
+int cn20k_register_afvf_mbox_intr(struct rvu *rvu, int pf_vec_start)
+{
+       struct rvu_irq_data *irq_data;
+       int intr_vec, offset, vec = 0;
+       int err;
+
+       /* irq data for 4 VFPF intr vectors */
+       irq_data = devm_kcalloc(rvu->dev, 4,
+                               sizeof(struct rvu_irq_data), GFP_KERNEL);
+       if (!irq_data)
+               return -ENOMEM;
+
+       for (intr_vec = RVU_MBOX_PF_INT_VEC_VFPF_MBOX0; intr_vec <=
+                                       RVU_MBOX_PF_INT_VEC_VFPF1_MBOX1;
+                                       intr_vec++, vec++) {
+               switch (intr_vec) {
+               case RVU_MBOX_PF_INT_VEC_VFPF_MBOX0:
+                       irq_data[vec].intr_status =
+                                               RVU_MBOX_PF_VFPF_INTX(0);
+                       irq_data[vec].start = 0;
+                       irq_data[vec].mdevs = 64;
+                       break;
+               case RVU_MBOX_PF_INT_VEC_VFPF_MBOX1:
+                       irq_data[vec].intr_status =
+                                               RVU_MBOX_PF_VFPF_INTX(1);
+                       irq_data[vec].start = 64;
+                       irq_data[vec].mdevs = 64;
+                       break;
+               case RVU_MBOX_PF_INT_VEC_VFPF1_MBOX0:
+                       irq_data[vec].intr_status =
+                                               RVU_MBOX_PF_VFPF1_INTX(0);
+                       irq_data[vec].start = 0;
+                       irq_data[vec].mdevs = 64;
+                       break;
+               case RVU_MBOX_PF_INT_VEC_VFPF1_MBOX1:
+                       irq_data[vec].intr_status = RVU_MBOX_PF_VFPF1_INTX(1);
+                       irq_data[vec].start = 64;
+                       irq_data[vec].mdevs = 64;
+                       break;
+               }
+               irq_data[vec].afvf_queue_work_hdlr =
+                                               rvu_queue_work;
+               offset = pf_vec_start + intr_vec;
+               irq_data[vec].vec_num = offset;
+               irq_data[vec].rvu = rvu;
+
+               sprintf(&rvu->irq_name[offset * NAME_SIZE], "RVUAF VFAF%d Mbox%d",
+                       vec / 2, vec % 2);
+               err = request_irq(pci_irq_vector(rvu->pdev, offset),
+                                 rvu->ng_rvu->rvu_mbox_ops->afvf_intr_handler, 0,
+                                 &rvu->irq_name[offset * NAME_SIZE],
+                                 &irq_data[vec]);
+               if (err) {
+                       dev_err(rvu->dev,
+                               "RVUAF: IRQ registration failed for AFVF mbox irq\n");
+                       return err;
+               }
+               rvu->irq_allocated[offset] = true;
+       }
+
+       return 0;
+}
+
 /* CN20K mbox PFx => AF irq handler */
 static irqreturn_t cn20k_mbox_pf_common_intr_handler(int irq, void *rvu_irq)
 {
@@ -150,6 +235,21 @@ int cn20k_rvu_get_mbox_regions(struct rvu *rvu, void **mbox_addr,
        int region;
        u64 bar;
 
+       if (type == TYPE_AFVF) {
+               for (region = 0; region < num; region++) {
+                       if (!test_bit(region, pf_bmap))
+                               continue;
+
+                       bar = (u64)phys_to_virt((u64)rvu->ng_rvu->vf_mbox_addr->base);
+                       bar += region * MBOX_SIZE;
+                       mbox_addr[region] = (void *)bar;
+
+                       if (!mbox_addr[region])
+                               return -ENOMEM;
+               }
+               return 0;
+       }
+
        for (region = 0; region < num; region++) {
                if (!test_bit(region, pf_bmap))
                        continue;
@@ -180,6 +280,9 @@ static int rvu_alloc_mbox_memory(struct rvu *rvu, int type,
         *
         * AF will access mbox memory using direct physical addresses
         * and PFs will access the same shared memory from BAR2.
+        *
+        * PF <=> VF mbox memory also works in the same fashion.
+        * AFPF, PFVF requires IOVA to be used to maintain the mailbox msgs
         */
 
        err = qmem_alloc(rvu->dev, &mbox_addr, ndevs, mbox_size);
@@ -196,6 +299,10 @@ static int rvu_alloc_mbox_memory(struct rvu *rvu, int type,
                        iova += mbox_size;
                }
                break;
+       case TYPE_AFVF:
+               rvu->ng_rvu->vf_mbox_addr = mbox_addr;
+               rvupf_write64(rvu, RVU_PF_VF_MBOX_ADDR, (u64)mbox_addr->iova);
+               break;
        default:
                return 0;
        }
@@ -205,6 +312,7 @@ static int rvu_alloc_mbox_memory(struct rvu *rvu, int type,
 
 static struct mbox_ops cn20k_mbox_ops = {
        .pf_intr_handler = cn20k_mbox_pf_common_intr_handler,
+       .afvf_intr_handler = cn20k_afvf_mbox_intr_handler,
 };
 
 int cn20k_rvu_mbox_init(struct rvu *rvu, int type, int ndevs)
@@ -216,9 +324,13 @@ int cn20k_rvu_mbox_init(struct rvu *rvu, int type, int ndevs)
 
        rvu->ng_rvu->rvu_mbox_ops = &cn20k_mbox_ops;
 
-       for (dev = 0; dev < ndevs; dev++)
-               rvu_write64(rvu, BLKADDR_RVUM,
-                           RVU_MBOX_AF_PFX_CFG(dev), ilog2(MBOX_SIZE));
+       if (type == TYPE_AFVF) {
+               rvu_write64(rvu, BLKADDR_RVUM, RVU_MBOX_PF_VF_CFG, ilog2(MBOX_SIZE));
+       } else {
+               for (dev = 0; dev < ndevs; dev++)
+                       rvu_write64(rvu, BLKADDR_RVUM,
+                                   RVU_MBOX_AF_PFX_CFG(dev), ilog2(MBOX_SIZE));
+       }
 
        return rvu_alloc_mbox_memory(rvu, type, ndevs, MBOX_SIZE);
 }
@@ -229,6 +341,51 @@ void cn20k_free_mbox_memory(struct rvu *rvu)
                return;
 
        qmem_free(rvu->dev, rvu->ng_rvu->pf_mbox_addr);
+       qmem_free(rvu->dev, rvu->ng_rvu->vf_mbox_addr);
+}
+
+void cn20k_rvu_disable_afvf_intr(struct rvu *rvu, int vfs)
+{
+       rvupf_write64(rvu, RVU_MBOX_PF_VFPF_INT_ENA_W1CX(0), INTR_MASK(vfs));
+       rvupf_write64(rvu, RVU_MBOX_PF_VFPF1_INT_ENA_W1CX(0), INTR_MASK(vfs));
+       rvupf_write64(rvu, RVU_PF_VFFLR_INT_ENA_W1CX(0), INTR_MASK(vfs));
+       rvupf_write64(rvu, RVU_PF_VFME_INT_ENA_W1CX(0), INTR_MASK(vfs));
+
+       if (vfs <= 64)
+               return;
+
+       rvupf_write64(rvu, RVU_MBOX_PF_VFPF_INT_ENA_W1CX(1), INTR_MASK(vfs - 64));
+       rvupf_write64(rvu, RVU_MBOX_PF_VFPF1_INT_ENA_W1CX(1), INTR_MASK(vfs - 64));
+       rvupf_write64(rvu, RVU_PF_VFFLR_INT_ENA_W1CX(1), INTR_MASK(vfs - 64));
+       rvupf_write64(rvu, RVU_PF_VFME_INT_ENA_W1CX(1), INTR_MASK(vfs - 64));
+}
+
+void cn20k_rvu_enable_afvf_intr(struct rvu *rvu, int vfs)
+{
+       /* Clear any pending interrupts and enable AF VF interrupts for
+        * the first 64 VFs.
+        */
+       rvupf_write64(rvu, RVU_MBOX_PF_VFPF_INTX(0), INTR_MASK(vfs));
+       rvupf_write64(rvu, RVU_MBOX_PF_VFPF_INT_ENA_W1SX(0), INTR_MASK(vfs));
+       rvupf_write64(rvu, RVU_MBOX_PF_VFPF1_INTX(0), INTR_MASK(vfs));
+       rvupf_write64(rvu, RVU_MBOX_PF_VFPF1_INT_ENA_W1SX(0), INTR_MASK(vfs));
+
+       /* FLR */
+       rvupf_write64(rvu, RVU_PF_VFFLR_INTX(0), INTR_MASK(vfs));
+       rvupf_write64(rvu, RVU_PF_VFFLR_INT_ENA_W1SX(0), INTR_MASK(vfs));
+
+       /* Same for remaining VFs, if any. */
+       if (vfs <= 64)
+               return;
+
+       rvupf_write64(rvu, RVU_MBOX_PF_VFPF_INTX(1), INTR_MASK(vfs - 64));
+       rvupf_write64(rvu, RVU_MBOX_PF_VFPF_INT_ENA_W1SX(1), INTR_MASK(vfs - 64));
+       rvupf_write64(rvu, RVU_MBOX_PF_VFPF1_INTX(1), INTR_MASK(vfs - 64));
+       rvupf_write64(rvu, RVU_MBOX_PF_VFPF1_INT_ENA_W1SX(1), INTR_MASK(vfs - 64));
+
+       rvupf_write64(rvu, RVU_PF_VFFLR_INTX(1), INTR_MASK(vfs - 64));
+       rvupf_write64(rvu, RVU_PF_VFFLR_INT_ENA_W1SX(1), INTR_MASK(vfs - 64));
+       rvupf_write64(rvu, RVU_PF_VFME_INT_ENA_W1SX(1), INTR_MASK(vfs - 64));
 }
 
 int rvu_alloc_cint_qint_mem(struct rvu *rvu, struct rvu_pfvf *pfvf,
index df2d52567da745b2997e267a0ba9f8a096735f65..affb39803120e863bef43ca3808f5581cb8e608f 100644 (file)
 #define NIX_CINTX_INT_W1S(a)                   (0xd30 | (a) << 12)
 #define NIX_QINTX_CNT(a)                       (0xc00 | (a) << 12)
 
+#define RVU_MBOX_AF_VFAF_INT(a)                        (0x3000 | (a) << 6)
+#define RVU_MBOX_AF_VFAF_INT_W1S(a)            (0x3008 | (a) << 6)
+#define RVU_MBOX_AF_VFAF_INT_ENA_W1S(a)                (0x3010 | (a) << 6)
+#define RVU_MBOX_AF_VFAF_INT_ENA_W1C(a)                (0x3018 | (a) << 6)
+#define RVU_MBOX_AF_VFAF_INT_ENA_W1C(a)                (0x3018 | (a) << 6)
+#define RVU_MBOX_AF_VFAF1_INT(a)               (0x3020 | (a) << 6)
+#define RVU_MBOX_AF_VFAF1_INT_W1S(a)           (0x3028 | (a) << 6)
+#define RVU_MBOX_AF_VFAF1_IN_ENA_W1S(a)                (0x3030 | (a) << 6)
+#define RVU_MBOX_AF_VFAF1_IN_ENA_W1C(a)                (0x3038 | (a) << 6)
+
+#define RVU_MBOX_AF_AFVFX_TRIG(a, b)           (0x10000 | (a) << 4 | (b) << 3)
+#define RVU_MBOX_AF_VFX_ADDR(a)                        (0x20000 | (a) << 4)
+#define RVU_MBOX_AF_VFX_CFG(a)                 (0x28000 | (a) << 4)
+
+#define RVU_MBOX_PF_VFX_PFVF_TRIGX(a)          (0x2000 | (a) << 3)
+
+#define RVU_MBOX_PF_VFPF_INTX(a)               (0x1000 | (a) << 3)
+#define RVU_MBOX_PF_VFPF_INT_W1SX(a)           (0x1020 | (a) << 3)
+#define RVU_MBOX_PF_VFPF_INT_ENA_W1SX(a)       (0x1040 | (a) << 3)
+#define RVU_MBOX_PF_VFPF_INT_ENA_W1CX(a)       (0x1060 | (a) << 3)
+
+#define RVU_MBOX_PF_VFPF1_INTX(a)              (0x1080 | (a) << 3)
+#define RVU_MBOX_PF_VFPF1_INT_W1SX(a)          (0x10a0 | (a) << 3)
+#define RVU_MBOX_PF_VFPF1_INT_ENA_W1SX(a)      (0x10c0 | (a) << 3)
+#define RVU_MBOX_PF_VFPF1_INT_ENA_W1CX(a)      (0x10e0 | (a) << 3)
+
+#define RVU_MBOX_PF_VF_ADDR                    (0xC40)
+#define RVU_MBOX_PF_LMTLINE_ADDR               (0xC48)
+#define RVU_MBOX_PF_VF_CFG                     (0xC60)
+
+#define RVU_MBOX_VF_VFPF_TRIGX(a)              (0x3000 | (a) << 3)
+#define RVU_MBOX_VF_INT                                (0x20)
+#define RVU_MBOX_VF_INT_W1S                    (0x28)
+#define RVU_MBOX_VF_INT_ENA_W1S                        (0x30)
+#define RVU_MBOX_VF_INT_ENA_W1C                        (0x38)
+
+#define RVU_MBOX_VF_VFAF_TRIGX(a)              (0x2000 | (a) << 3)
 #endif /* RVU_MBOX_REG_H */
index 89324a30137fe4bd18a461acf481c513198167b8..75872d257eca8730ccecb28cbb0c24b53a3ac5f8 100644 (file)
@@ -63,24 +63,28 @@ int cn20k_mbox_setup(struct otx2_mbox *mbox, struct pci_dev *pdev,
 {
        switch (direction) {
        case MBOX_DIR_AFPF:
+       case MBOX_DIR_PFVF:
                mbox->tx_start = MBOX_DOWN_TX_START;
                mbox->rx_start = MBOX_DOWN_RX_START;
                mbox->tx_size  = MBOX_DOWN_TX_SIZE;
                mbox->rx_size  = MBOX_DOWN_RX_SIZE;
                break;
        case MBOX_DIR_PFAF:
+       case MBOX_DIR_VFPF:
                mbox->tx_start = MBOX_DOWN_RX_START;
                mbox->rx_start = MBOX_DOWN_TX_START;
                mbox->tx_size  = MBOX_DOWN_RX_SIZE;
                mbox->rx_size  = MBOX_DOWN_TX_SIZE;
                break;
        case MBOX_DIR_AFPF_UP:
+       case MBOX_DIR_PFVF_UP:
                mbox->tx_start = MBOX_UP_TX_START;
                mbox->rx_start = MBOX_UP_RX_START;
                mbox->tx_size  = MBOX_UP_TX_SIZE;
                mbox->rx_size  = MBOX_UP_RX_SIZE;
                break;
        case MBOX_DIR_PFAF_UP:
+       case MBOX_DIR_VFPF_UP:
                mbox->tx_start = MBOX_UP_RX_START;
                mbox->rx_start = MBOX_UP_TX_START;
                mbox->tx_size  = MBOX_UP_RX_SIZE;
@@ -107,6 +111,22 @@ int cn20k_mbox_setup(struct otx2_mbox *mbox, struct pci_dev *pdev,
                mbox->trigger = RVU_MBOX_PF_PFAF_TRIGX(1);
                mbox->tr_shift = 0;
                break;
+       case MBOX_DIR_PFVF:
+               mbox->trigger = RVU_MBOX_PF_VFX_PFVF_TRIGX(1);
+               mbox->tr_shift = 4;
+               break;
+       case MBOX_DIR_PFVF_UP:
+               mbox->trigger = RVU_MBOX_PF_VFX_PFVF_TRIGX(0);
+               mbox->tr_shift = 4;
+               break;
+       case MBOX_DIR_VFPF:
+               mbox->trigger = RVU_MBOX_VF_VFPF_TRIGX(0);
+               mbox->tr_shift = 0;
+               break;
+       case MBOX_DIR_VFPF_UP:
+               mbox->trigger = RVU_MBOX_VF_VFPF_TRIGX(1);
+               mbox->tr_shift = 0;
+               break;
        default:
                return -ENODEV;
        }
index c9e9ef4f25cbe7e25426c81364fab2cdebb26356..bfee71f4cddccbc4cbff5c2030dcb3d8fa3aee51 100644 (file)
@@ -2450,6 +2450,7 @@ error:
 
 static struct mbox_ops rvu_mbox_ops = {
        .pf_intr_handler = rvu_mbox_pf_intr_handler,
+       .afvf_intr_handler = rvu_mbox_intr_handler,
 };
 
 static int rvu_mbox_init(struct rvu *rvu, struct mbox_wq_info *mw,
@@ -2999,6 +3000,10 @@ static int rvu_afvf_msix_vectors_num_ok(struct rvu *rvu)
         * VF interrupts can be handled. Offset equal to zero means
         * that PF vectors are not configured and overlapping AF vectors.
         */
+       if (is_cn20k(rvu->pdev))
+               return (pfvf->msix.max >= RVU_AF_CN20K_INT_VEC_CNT +
+                       RVU_MBOX_PF_INT_VEC_CNT) && offset;
+
        return (pfvf->msix.max >= RVU_AF_INT_VEC_CNT + RVU_PF_INT_VEC_CNT) &&
               offset;
 }
@@ -3107,34 +3112,40 @@ static int rvu_register_interrupts(struct rvu *rvu)
        /* Get PF MSIX vectors offset. */
        pf_vec_start = rvu_read64(rvu, BLKADDR_RVUM,
                                  RVU_PRIV_PFX_INT_CFG(0)) & 0x3ff;
+       if (!is_cn20k(rvu->pdev)) {
+               /* Register MBOX0 interrupt. */
+               offset = pf_vec_start + RVU_PF_INT_VEC_VFPF_MBOX0;
+               sprintf(&rvu->irq_name[offset * NAME_SIZE], "RVUAFVF Mbox0");
+               ret = request_irq(pci_irq_vector(rvu->pdev, offset),
+                                 rvu->ng_rvu->rvu_mbox_ops->afvf_intr_handler, 0,
+                                 &rvu->irq_name[offset * NAME_SIZE],
+                                 rvu);
+               if (ret)
+                       dev_err(rvu->dev,
+                               "RVUAF: IRQ registration failed for Mbox0\n");
 
-       /* Register MBOX0 interrupt. */
-       offset = pf_vec_start + RVU_PF_INT_VEC_VFPF_MBOX0;
-       sprintf(&rvu->irq_name[offset * NAME_SIZE], "RVUAFVF Mbox0");
-       ret = request_irq(pci_irq_vector(rvu->pdev, offset),
-                         rvu_mbox_intr_handler, 0,
-                         &rvu->irq_name[offset * NAME_SIZE],
-                         rvu);
-       if (ret)
-               dev_err(rvu->dev,
-                       "RVUAF: IRQ registration failed for Mbox0\n");
-
-       rvu->irq_allocated[offset] = true;
+               rvu->irq_allocated[offset] = true;
 
-       /* Register MBOX1 interrupt. MBOX1 IRQ number follows MBOX0 so
-        * simply increment current offset by 1.
-        */
-       offset = pf_vec_start + RVU_PF_INT_VEC_VFPF_MBOX1;
-       sprintf(&rvu->irq_name[offset * NAME_SIZE], "RVUAFVF Mbox1");
-       ret = request_irq(pci_irq_vector(rvu->pdev, offset),
-                         rvu_mbox_intr_handler, 0,
-                         &rvu->irq_name[offset * NAME_SIZE],
-                         rvu);
-       if (ret)
-               dev_err(rvu->dev,
-                       "RVUAF: IRQ registration failed for Mbox1\n");
+               /* Register MBOX1 interrupt. MBOX1 IRQ number follows MBOX0 so
+                * simply increment current offset by 1.
+                */
+               offset = pf_vec_start + RVU_PF_INT_VEC_VFPF_MBOX1;
+               sprintf(&rvu->irq_name[offset * NAME_SIZE], "RVUAFVF Mbox1");
+               ret = request_irq(pci_irq_vector(rvu->pdev, offset),
+                                 rvu->ng_rvu->rvu_mbox_ops->afvf_intr_handler, 0,
+                                 &rvu->irq_name[offset * NAME_SIZE],
+                                 rvu);
+               if (ret)
+                       dev_err(rvu->dev,
+                               "RVUAF: IRQ registration failed for Mbox1\n");
 
-       rvu->irq_allocated[offset] = true;
+               rvu->irq_allocated[offset] = true;
+       } else {
+               ret = cn20k_register_afvf_mbox_intr(rvu, pf_vec_start);
+               if (ret)
+                       dev_err(rvu->dev,
+                               "RVUAF: IRQ registration failed for Mbox\n");
+       }
 
        /* Register FLR interrupt handler for AF's VFs */
        offset = pf_vec_start + RVU_PF_INT_VEC_VFFLR0;
@@ -3245,6 +3256,9 @@ static void rvu_disable_afvf_intr(struct rvu *rvu)
 {
        int vfs = rvu->vfs;
 
+       if (is_cn20k(rvu->pdev))
+               return cn20k_rvu_disable_afvf_intr(rvu, vfs);
+
        rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INT_ENA_W1CX(0), INTR_MASK(vfs));
        rvupf_write64(rvu, RVU_PF_VFFLR_INT_ENA_W1CX(0), INTR_MASK(vfs));
        rvupf_write64(rvu, RVU_PF_VFME_INT_ENA_W1CX(0), INTR_MASK(vfs));
@@ -3261,6 +3275,9 @@ static void rvu_enable_afvf_intr(struct rvu *rvu)
 {
        int vfs = rvu->vfs;
 
+       if (is_cn20k(rvu->pdev))
+               return cn20k_rvu_enable_afvf_intr(rvu, vfs);
+
        /* Clear any pending interrupts and enable AF VF interrupts for
         * the first 64 VFs.
         */
index 3332dfd56de5a0fc7710cf983aa21f74ab986dcd..7ee1fdeb5295f371697337e5a7b955e23a5075f4 100644 (file)
@@ -478,6 +478,8 @@ struct rvu_irq_data {
        u64 intr_status;
        void (*rvu_queue_work_hdlr)(struct mbox_wq_info *mw, int first,
                                    int mdevs, u64 intr);
+       void (*afvf_queue_work_hdlr)(struct mbox_wq_info *mw, int first,
+                                    int mdevs, u64 intr);
        struct  rvu *rvu;
        int vec_num;
        int start;
@@ -486,6 +488,7 @@ struct rvu_irq_data {
 
 struct mbox_ops {
        irqreturn_t (*pf_intr_handler)(int irq, void *rvu_irq);
+       irqreturn_t (*afvf_intr_handler)(int irq, void *rvu_irq);
 };
 
 struct channel_fwdata {
index fdc4ce3faf41c394b77f793b23ab7c05778bde17..fa5951645b352b94b0ae3d65bdb84b684b5a09ad 100644 (file)
@@ -12,6 +12,7 @@
 
 static struct dev_hw_ops cn20k_hw_ops = {
        .pfaf_mbox_intr_handler = cn20k_pfaf_mbox_intr_handler,
+       .vfaf_mbox_intr_handler = cn20k_vfaf_mbox_intr_handler,
 };
 
 void cn20k_init(struct otx2_nic *pfvf)
@@ -61,3 +62,49 @@ irqreturn_t cn20k_pfaf_mbox_intr_handler(int irq, void *pf_irq)
 
        return IRQ_HANDLED;
 }
+
+irqreturn_t cn20k_vfaf_mbox_intr_handler(int irq, void *vf_irq)
+{
+       struct otx2_nic *vf = vf_irq;
+       struct otx2_mbox_dev *mdev;
+       struct otx2_mbox *mbox;
+       struct mbox_hdr *hdr;
+       u64 vf_trig_val;
+
+       vf_trig_val = otx2_read64(vf, RVU_VF_INT) & 0x3ULL;
+       /* Clear the IRQ */
+       otx2_write64(vf, RVU_VF_INT, vf_trig_val);
+
+       /* Read latest mbox data */
+       smp_rmb();
+
+       if (vf_trig_val & BIT_ULL(1)) {
+               /* Check for PF => VF response messages */
+               mbox = &vf->mbox.mbox;
+               mdev = &mbox->dev[0];
+               otx2_sync_mbox_bbuf(mbox, 0);
+
+               hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
+               if (hdr->num_msgs)
+                       queue_work(vf->mbox_wq, &vf->mbox.mbox_wrk);
+
+               trace_otx2_msg_interrupt(mbox->pdev, "DOWN reply from PF0 to VF",
+                                        BIT_ULL(1));
+       }
+
+       if (vf_trig_val & BIT_ULL(0)) {
+               /* Check for PF => VF notification messages */
+               mbox = &vf->mbox.mbox_up;
+               mdev = &mbox->dev[0];
+               otx2_sync_mbox_bbuf(mbox, 0);
+
+               hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
+               if (hdr->num_msgs)
+                       queue_work(vf->mbox_wq, &vf->mbox.mbox_up_wrk);
+
+               trace_otx2_msg_interrupt(mbox->pdev, "UP message from PF0 to VF",
+                                        BIT_ULL(0));
+       }
+
+       return IRQ_HANDLED;
+}
index fd8ad963d518fbe555503300682d0a90b31b723d..d8ae28b2c6c8981623b93cf01ffeed4973e775d2 100644 (file)
@@ -65,6 +65,8 @@
 
 irqreturn_t otx2_pfaf_mbox_intr_handler(int irq, void *pf_irq);
 irqreturn_t cn20k_pfaf_mbox_intr_handler(int irq, void *pf_irq);
+irqreturn_t cn20k_vfaf_mbox_intr_handler(int irq, void *vf_irq);
+irqreturn_t otx2_pfvf_mbox_intr_handler(int irq, void *pf_irq);
 
 enum arua_mapped_qtypes {
        AURA_NIX_RQ,
@@ -250,6 +252,7 @@ struct otx2_hw {
        u16                     nix_msixoff; /* Offset of NIX vectors */
        char                    *irq_name;
        cpumask_var_t           *affinity_mask;
+       struct pf_irq_data      *pfvf_irq_devid[4];
 
        /* Stats */
        struct otx2_dev_stats   dev_stats;
@@ -372,6 +375,7 @@ struct dev_hw_ops {
        int     (*refill_pool_ptrs)(void *dev, struct otx2_cq_queue *cq);
        void    (*aura_freeptr)(void *dev, int aura, u64 buf);
        irqreturn_t (*pfaf_mbox_intr_handler)(int irq, void *pf_irq);
+       irqreturn_t (*vfaf_mbox_intr_handler)(int irq, void *pf_irq);
 };
 
 #define CN10K_MCS_SA_PER_SC    4
@@ -439,6 +443,16 @@ struct cn10k_mcs_cfg {
        struct list_head rxsc_list;
 };
 
+struct pf_irq_data {
+       u64 intr_status;
+       void (*pf_queue_work_hdlr)(struct mbox *mb, struct workqueue_struct *mw,
+                                  int first, int mdevs, u64 intr);
+       struct otx2_nic *pf;
+       int vec_num;
+       int start;
+       int mdevs;
+};
+
 struct otx2_nic {
        void __iomem            *reg_base;
        struct net_device       *netdev;
@@ -482,6 +496,7 @@ struct otx2_nic {
        struct mbox             *mbox_pfvf;
        struct workqueue_struct *mbox_wq;
        struct workqueue_struct *mbox_pfvf_wq;
+       struct qmem             *pfvf_mbox_addr;
 
        u8                      total_vfs;
        u16                     pcifunc; /* RVU PF_FUNC */
@@ -1192,4 +1207,6 @@ dma_addr_t otx2_dma_map_skb_frag(struct otx2_nic *pfvf,
                                 struct sk_buff *skb, int seg, int *len);
 void otx2_dma_unmap_skb_frags(struct otx2_nic *pfvf, struct sg_list *sg);
 int otx2_read_free_sqe(struct otx2_nic *pfvf, u16 qidx);
+void otx2_queue_vf_work(struct mbox *mw, struct workqueue_struct *mbox_wq,
+                       int first, int mdevs, u64 intr);
 #endif /* OTX2_COMMON_H */
index 95a65a7c8fc29287388544ad9b1cfdf0c5c3766c..8f67fa42dc94f194d8d97f27a769e1d77d1adcce 100644 (file)
@@ -296,8 +296,8 @@ static int otx2_pf_flr_init(struct otx2_nic *pf, int num_vfs)
        return 0;
 }
 
-static void otx2_queue_vf_work(struct mbox *mw, struct workqueue_struct *mbox_wq,
-                              int first, int mdevs, u64 intr)
+void otx2_queue_vf_work(struct mbox *mw, struct workqueue_struct *mbox_wq,
+                       int first, int mdevs, u64 intr)
 {
        struct otx2_mbox_dev *mdev;
        struct otx2_mbox *mbox;
@@ -547,7 +547,7 @@ end:
        }
 }
 
-static irqreturn_t otx2_pfvf_mbox_intr_handler(int irq, void *pf_irq)
+irqreturn_t otx2_pfvf_mbox_intr_handler(int irq, void *pf_irq)
 {
        struct otx2_nic *pf = (struct otx2_nic *)(pf_irq);
        int vfs = pf->total_vfs;
index 901f8cf7f27a90b5e75d563d42bcca469a575459..1cd576fd09c56ff8efb41584c2738186ca8a2ae3 100644 (file)
 #define RVU_PF_VF_MBOX_ADDR                 (0xC40)
 #define RVU_PF_LMTLINE_ADDR                 (0xC48)
 
+#define RVU_MBOX_PF_VFX_PFVF_TRIGX(a)          (0x2000 | (a) << 3)
+#define RVU_MBOX_PF_VFPF_INTX(a)               (0x1000 | (a) << 3)
+#define RVU_MBOX_PF_VFPF_INT_W1SX(a)           (0x1020 | (a) << 3)
+#define RVU_MBOX_PF_VFPF_INT_ENA_W1SX(a)       (0x1040 | (a) << 3)
+#define RVU_MBOX_PF_VFPF_INT_ENA_W1CX(a)       (0x1060 | (a) << 3)
+
+#define RVU_MBOX_PF_VFPF1_INTX(a)              (0x1080 | (a) << 3)
+#define RVU_MBOX_PF_VFPF1_INT_W1SX(a)          (0x10a0 | (a) << 3)
+#define RVU_MBOX_PF_VFPF1_INT_ENA_W1SX(a)      (0x10c0 | (a) << 3)
+#define RVU_MBOX_PF_VFPF1_INT_ENA_W1CX(a)      (0x10e0 | (a) << 3)
+
 /* RVU VF registers */
 #define        RVU_VF_VFPF_MBOX0                   (0x00000)
 #define        RVU_VF_VFPF_MBOX1                   (0x00008)
@@ -61,6 +72,7 @@
 /* CN20K RVU_MBOX_E: RVU PF/VF MBOX Address Range Enumeration */
 #define RVU_MBOX_AF_PFX_ADDR(a)             (0x5000 | (a) << 4)
 #define RVU_PFX_FUNC_PFAF_MBOX             (0x80000)
+#define RVU_PFX_FUNCX_VFAF_MBOX                    (0x40000)
 
 #define RVU_FUNC_BLKADDR_SHIFT         20
 #define RVU_FUNC_BLKADDR_MASK          0x1FULL
 #define LMT_LF_LMTLINEX(a)             (LMT_LFBASE | 0x000 | (a) << 12)
 #define LMT_LF_LMTCANCEL               (LMT_LFBASE | 0x400)
 
+/* CN20K registers */
+#define RVU_PF_DISC                    (0x0)
+
 #endif /* OTX2_REG_H */
index d2f61438a8476c22635a75a0c688f99ba6e64675..5589fccd370b8a2bc168227600bc209613e0259b 100644 (file)
@@ -240,6 +240,10 @@ static void otx2vf_disable_mbox_intr(struct otx2_nic *vf)
 
        /* Disable VF => PF mailbox IRQ */
        otx2_write64(vf, RVU_VF_INT_ENA_W1C, BIT_ULL(0));
+
+       if (is_cn20k(vf->pdev))
+               otx2_write64(vf, RVU_VF_INT_ENA_W1C, BIT_ULL(0) | BIT_ULL(1));
+
        free_irq(vector, vf);
 }
 
@@ -252,9 +256,18 @@ static int otx2vf_register_mbox_intr(struct otx2_nic *vf, bool probe_pf)
 
        /* Register mailbox interrupt handler */
        irq_name = &hw->irq_name[RVU_VF_INT_VEC_MBOX * NAME_SIZE];
-       snprintf(irq_name, NAME_SIZE, "RVUVFAF Mbox");
-       err = request_irq(pci_irq_vector(vf->pdev, RVU_VF_INT_VEC_MBOX),
-                         otx2vf_vfaf_mbox_intr_handler, 0, irq_name, vf);
+       snprintf(irq_name, NAME_SIZE, "RVUVF%d AFVF Mbox", ((vf->pcifunc &
+                RVU_PFVF_FUNC_MASK) - 1));
+
+       if (!is_cn20k(vf->pdev)) {
+               err = request_irq(pci_irq_vector(vf->pdev, RVU_VF_INT_VEC_MBOX),
+                                 otx2vf_vfaf_mbox_intr_handler, 0, irq_name, vf);
+       } else {
+               err = request_irq(pci_irq_vector(vf->pdev, RVU_VF_INT_VEC_MBOX),
+                                 vf->hw_ops->vfaf_mbox_intr_handler, 0, irq_name,
+                                 vf);
+       }
+
        if (err) {
                dev_err(vf->dev,
                        "RVUPF: IRQ registration failed for VFAF mbox irq\n");
@@ -264,8 +277,15 @@ static int otx2vf_register_mbox_intr(struct otx2_nic *vf, bool probe_pf)
        /* Enable mailbox interrupt for msgs coming from PF.
         * First clear to avoid spurious interrupts, if any.
         */
-       otx2_write64(vf, RVU_VF_INT, BIT_ULL(0));
-       otx2_write64(vf, RVU_VF_INT_ENA_W1S, BIT_ULL(0));
+       if (!is_cn20k(vf->pdev)) {
+               otx2_write64(vf, RVU_VF_INT, BIT_ULL(0));
+               otx2_write64(vf, RVU_VF_INT_ENA_W1S, BIT_ULL(0));
+       } else {
+               otx2_write64(vf, RVU_VF_INT, BIT_ULL(0) | BIT_ULL(1) |
+                            BIT_ULL(2) | BIT_ULL(3));
+               otx2_write64(vf, RVU_VF_INT_ENA_W1S, BIT_ULL(0) |
+                            BIT_ULL(1) | BIT_ULL(2) | BIT_ULL(3));
+       }
 
        if (!probe_pf)
                return 0;
@@ -315,7 +335,13 @@ static int otx2vf_vfaf_mbox_init(struct otx2_nic *vf)
        if (!vf->mbox_wq)
                return -ENOMEM;
 
-       if (test_bit(CN10K_MBOX, &vf->hw.cap_flag)) {
+       /* For cn20k platform, VF mailbox region is in dram aliased from AF
+        * VF MBOX ADDR, MBOX is a separate RVU block.
+        */
+       if (is_cn20k(vf->pdev)) {
+               hwbase = vf->reg_base + RVU_VF_MBOX_REGION + ((u64)BLKADDR_MBOX <<
+                       RVU_FUNC_BLKADDR_SHIFT);
+       } else if (test_bit(CN10K_MBOX, &vf->hw.cap_flag)) {
                /* For cn10k platform, VF mailbox region is in its BAR2
                 * register space
                 */