]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
octeontx2-pf: CN20K mbox REQ/ACK implementation for NIC PF
authorSai Krishna <saikrishnag@marvell.com>
Wed, 11 Jun 2025 11:01:54 +0000 (16:31 +0530)
committerJakub Kicinski <kuba@kernel.org>
Tue, 17 Jun 2025 00:37:49 +0000 (17:37 -0700)
This implementation uses separate trigger interrupts for request,
response messages against using trigger message data in CN10K.
This patch adds support for basic mbox implementation for CN20K
from NIC PF side.

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-5-git-send-email-sbhatta@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/marvell/octeontx2/af/cn20k/struct.h
drivers/net/ethernet/marvell/octeontx2/nic/Makefile
drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c [new file with mode: 0644]
drivers/net/ethernet/marvell/octeontx2/nic/cn20k.h [new file with mode: 0644]
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 fccad6e422e85d3bbebefdb0dbde4df7455c047a..76ce3ec6da9cdb5b7d77fd2374a6606b12844be0 100644 (file)
@@ -8,6 +8,21 @@
 #ifndef STRUCT_H
 #define STRUCT_H
 
+/*
+ * CN20k RVU PF MBOX Interrupt Vector Enumeration
+ *
+ * Vectors 0 - 3 are compatible with pre cn20k and hence
+ * existing macros are being reused.
+ */
+enum rvu_mbox_pf_int_vec_e {
+       RVU_MBOX_PF_INT_VEC_VFPF_MBOX0  = 0x4,
+       RVU_MBOX_PF_INT_VEC_VFPF_MBOX1  = 0x5,
+       RVU_MBOX_PF_INT_VEC_VFPF1_MBOX0 = 0x6,
+       RVU_MBOX_PF_INT_VEC_VFPF1_MBOX1 = 0x7,
+       RVU_MBOX_PF_INT_VEC_AFPF_MBOX   = 0x8,
+       RVU_MBOX_PF_INT_VEC_CNT         = 0x9,
+};
+
 /* RVU Admin function Interrupt Vector Enumeration */
 enum rvu_af_cn20k_int_vec_e {
        RVU_AF_CN20K_INT_VEC_POISON             = 0x0,
index 69e0778f9ac10485e79b27bcac39fd6a9e1436b3..883e9f4d601c5c42ef5020f6b5a21b5ddd5f947f 100644 (file)
@@ -8,7 +8,7 @@ obj-$(CONFIG_OCTEONTX2_VF) += rvu_nicvf.o otx2_ptp.o
 obj-$(CONFIG_RVU_ESWITCH) += rvu_rep.o
 
 rvu_nicpf-y := otx2_pf.o otx2_common.o otx2_txrx.o otx2_ethtool.o \
-               otx2_flows.o otx2_tc.o cn10k.o otx2_dmac_flt.o \
+               otx2_flows.o otx2_tc.o cn10k.o cn20k.o otx2_dmac_flt.o \
                otx2_devlink.o qos_sq.o qos.o otx2_xsk.o
 rvu_nicvf-y := otx2_vf.o
 rvu_rep-y := rep.o
index 7f6a435ac680690c8820b84ac06f34a695274a7f..bec7d5b4d7cc0b15536d58467e295d1ea6be121d 100644 (file)
@@ -14,6 +14,7 @@ static struct dev_hw_ops      otx2_hw_ops = {
        .sqe_flush = otx2_sqe_flush,
        .aura_freeptr = otx2_aura_freeptr,
        .refill_pool_ptrs = otx2_refill_pool_ptrs,
+       .pfaf_mbox_intr_handler = otx2_pfaf_mbox_intr_handler,
 };
 
 static struct dev_hw_ops cn10k_hw_ops = {
@@ -21,8 +22,20 @@ static struct dev_hw_ops cn10k_hw_ops = {
        .sqe_flush = cn10k_sqe_flush,
        .aura_freeptr = cn10k_aura_freeptr,
        .refill_pool_ptrs = cn10k_refill_pool_ptrs,
+       .pfaf_mbox_intr_handler = otx2_pfaf_mbox_intr_handler,
 };
 
+void otx2_init_hw_ops(struct otx2_nic *pfvf)
+{
+       if (!test_bit(CN10K_LMTST, &pfvf->hw.cap_flag)) {
+               pfvf->hw_ops = &otx2_hw_ops;
+               return;
+       }
+
+       pfvf->hw_ops = &cn10k_hw_ops;
+}
+EXPORT_SYMBOL(otx2_init_hw_ops);
+
 int cn10k_lmtst_init(struct otx2_nic *pfvf)
 {
 
@@ -30,12 +43,9 @@ int cn10k_lmtst_init(struct otx2_nic *pfvf)
        struct otx2_lmt_info *lmt_info;
        int err, cpu;
 
-       if (!test_bit(CN10K_LMTST, &pfvf->hw.cap_flag)) {
-               pfvf->hw_ops = &otx2_hw_ops;
+       if (!test_bit(CN10K_LMTST, &pfvf->hw.cap_flag))
                return 0;
-       }
 
-       pfvf->hw_ops = &cn10k_hw_ops;
        /* Total LMTLINES = num_online_cpus() * 32 (For Burst flush).*/
        pfvf->tot_lmt_lines = (num_online_cpus() * LMT_BURST_SIZE);
        pfvf->hw.lmt_info = alloc_percpu(struct otx2_lmt_info);
index e3f0bce9908fb1684c93b4617cac2e67cc3cc70f..945ab10bd4edf1433951ebc692e76c26f44c2afd 100644 (file)
@@ -39,4 +39,5 @@ int cn10k_alloc_leaf_profile(struct otx2_nic *pfvf, u16 *leaf);
 int cn10k_set_ipolicer_rate(struct otx2_nic *pfvf, u16 profile,
                            u32 burst, u64 rate, bool pps);
 int cn10k_free_leaf_profile(struct otx2_nic *pfvf, u16 leaf);
+void otx2_init_hw_ops(struct otx2_nic *pfvf);
 #endif /* CN10K_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c
new file mode 100644 (file)
index 0000000..fdc4ce3
--- /dev/null
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Marvell RVU Ethernet driver
+ *
+ * Copyright (C) 2024 Marvell.
+ *
+ */
+
+#include "otx2_common.h"
+#include "otx2_reg.h"
+#include "otx2_struct.h"
+#include "cn10k.h"
+
+static struct dev_hw_ops cn20k_hw_ops = {
+       .pfaf_mbox_intr_handler = cn20k_pfaf_mbox_intr_handler,
+};
+
+void cn20k_init(struct otx2_nic *pfvf)
+{
+       pfvf->hw_ops = &cn20k_hw_ops;
+}
+EXPORT_SYMBOL(cn20k_init);
+/* CN20K mbox AF => PFx irq handler */
+irqreturn_t cn20k_pfaf_mbox_intr_handler(int irq, void *pf_irq)
+{
+       struct otx2_nic *pf = pf_irq;
+       struct mbox *mw = &pf->mbox;
+       struct otx2_mbox_dev *mdev;
+       struct otx2_mbox *mbox;
+       struct mbox_hdr *hdr;
+       u64 pf_trig_val;
+
+       pf_trig_val = otx2_read64(pf, RVU_PF_INT) & 0x3ULL;
+
+       /* Clear the IRQ */
+       otx2_write64(pf, RVU_PF_INT, pf_trig_val);
+
+       if (pf_trig_val & BIT_ULL(0)) {
+               mbox = &mw->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(pf->mbox_wq, &mw->mbox_up_wrk);
+
+               trace_otx2_msg_interrupt(pf->pdev, "UP message from AF to PF",
+                                        BIT_ULL(0));
+       }
+
+       if (pf_trig_val & BIT_ULL(1)) {
+               mbox = &mw->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(pf->mbox_wq, &mw->mbox_wrk);
+               trace_otx2_msg_interrupt(pf->pdev, "DOWN reply from AF to PF",
+                                        BIT_ULL(1));
+       }
+
+       return IRQ_HANDLED;
+}
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.h b/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.h
new file mode 100644 (file)
index 0000000..712bb2b
--- /dev/null
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Marvell RVU Ethernet driver
+ *
+ * Copyright (C) 2024 Marvell.
+ *
+ */
+
+#ifndef CN20K_H
+#define CN20K_H
+
+#include "otx2_common.h"
+
+void cn20k_init(struct otx2_nic *pfvf);
+#endif /* CN20K_H */
index 8ada34a868e98f88c4e5b0466d2bc0b31f3f97b1..fd8ad963d518fbe555503300682d0a90b31b723d 100644 (file)
@@ -33,6 +33,7 @@
 #include "qos.h"
 #include "rep.h"
 #include "cn10k_ipsec.h"
+#include "cn20k.h"
 
 /* IPv4 flag more fragment bit */
 #define IPV4_FLAG_MORE                         0x20
@@ -62,6 +63,9 @@
 /* Number of segments per SG structure */
 #define MAX_SEGS_PER_SG 3
 
+irqreturn_t otx2_pfaf_mbox_intr_handler(int irq, void *pf_irq);
+irqreturn_t cn20k_pfaf_mbox_intr_handler(int irq, void *pf_irq);
+
 enum arua_mapped_qtypes {
        AURA_NIX_RQ,
        AURA_NIX_SQ,
@@ -367,6 +371,7 @@ struct dev_hw_ops {
                             int size, int qidx);
        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);
 };
 
 #define CN10K_MCS_SA_PER_SC    4
index 1dc3e057f52db2644f5ea6ece9acf01760eef8a5..95a65a7c8fc29287388544ad9b1cfdf0c5c3766c 100644 (file)
@@ -1008,7 +1008,7 @@ static void otx2_pfaf_mbox_up_handler(struct work_struct *work)
        otx2_mbox_msg_send(mbox, 0);
 }
 
-static irqreturn_t otx2_pfaf_mbox_intr_handler(int irq, void *pf_irq)
+irqreturn_t otx2_pfaf_mbox_intr_handler(int irq, void *pf_irq)
 {
        struct otx2_nic *pf = (struct otx2_nic *)pf_irq;
        struct mbox *mw = &pf->mbox;
@@ -1066,10 +1066,18 @@ static irqreturn_t otx2_pfaf_mbox_intr_handler(int irq, void *pf_irq)
 
 void otx2_disable_mbox_intr(struct otx2_nic *pf)
 {
-       int vector = pci_irq_vector(pf->pdev, RVU_PF_INT_VEC_AFPF_MBOX);
+       int vector;
 
        /* Disable AF => PF mailbox IRQ */
-       otx2_write64(pf, RVU_PF_INT_ENA_W1C, BIT_ULL(0));
+       if (!is_cn20k(pf->pdev)) {
+               vector = pci_irq_vector(pf->pdev, RVU_PF_INT_VEC_AFPF_MBOX);
+               otx2_write64(pf, RVU_PF_INT_ENA_W1C, BIT_ULL(0));
+       } else {
+               vector = pci_irq_vector(pf->pdev,
+                                       RVU_MBOX_PF_INT_VEC_AFPF_MBOX);
+               otx2_write64(pf, RVU_PF_INT_ENA_W1C,
+                            BIT_ULL(0) | BIT_ULL(1));
+       }
        free_irq(vector, pf);
 }
 EXPORT_SYMBOL(otx2_disable_mbox_intr);
@@ -1082,10 +1090,24 @@ int otx2_register_mbox_intr(struct otx2_nic *pf, bool probe_af)
        int err;
 
        /* Register mailbox interrupt handler */
-       irq_name = &hw->irq_name[RVU_PF_INT_VEC_AFPF_MBOX * NAME_SIZE];
-       snprintf(irq_name, NAME_SIZE, "RVUPFAF Mbox");
-       err = request_irq(pci_irq_vector(pf->pdev, RVU_PF_INT_VEC_AFPF_MBOX),
-                         otx2_pfaf_mbox_intr_handler, 0, irq_name, pf);
+       if (!is_cn20k(pf->pdev)) {
+               irq_name = &hw->irq_name[RVU_PF_INT_VEC_AFPF_MBOX * NAME_SIZE];
+               snprintf(irq_name, NAME_SIZE, "RVUPF%d AFPF Mbox",
+                        rvu_get_pf(pf->pdev, pf->pcifunc));
+               err = request_irq(pci_irq_vector
+                                 (pf->pdev, RVU_PF_INT_VEC_AFPF_MBOX),
+                                 pf->hw_ops->pfaf_mbox_intr_handler,
+                                 0, irq_name, pf);
+       } else {
+               irq_name = &hw->irq_name[RVU_MBOX_PF_INT_VEC_AFPF_MBOX *
+                                               NAME_SIZE];
+               snprintf(irq_name, NAME_SIZE, "RVUPF%d AFPF Mbox",
+                        rvu_get_pf(pf->pdev, pf->pcifunc));
+               err = request_irq(pci_irq_vector
+                                 (pf->pdev, RVU_MBOX_PF_INT_VEC_AFPF_MBOX),
+                                 pf->hw_ops->pfaf_mbox_intr_handler,
+                                 0, irq_name, pf);
+       }
        if (err) {
                dev_err(pf->dev,
                        "RVUPF: IRQ registration failed for PFAF mbox irq\n");
@@ -1095,8 +1117,14 @@ int otx2_register_mbox_intr(struct otx2_nic *pf, bool probe_af)
        /* Enable mailbox interrupt for msgs coming from AF.
         * First clear to avoid spurious interrupts, if any.
         */
-       otx2_write64(pf, RVU_PF_INT, BIT_ULL(0));
-       otx2_write64(pf, RVU_PF_INT_ENA_W1S, BIT_ULL(0));
+       if (!is_cn20k(pf->pdev)) {
+               otx2_write64(pf, RVU_PF_INT, BIT_ULL(0));
+               otx2_write64(pf, RVU_PF_INT_ENA_W1S, BIT_ULL(0));
+       } else {
+               otx2_write64(pf, RVU_PF_INT, BIT_ULL(0) | BIT_ULL(1));
+               otx2_write64(pf, RVU_PF_INT_ENA_W1S, BIT_ULL(0) |
+                            BIT_ULL(1));
+       }
 
        if (!probe_af)
                return 0;
@@ -1127,7 +1155,7 @@ void otx2_pfaf_mbox_destroy(struct otx2_nic *pf)
                pf->mbox_wq = NULL;
        }
 
-       if (mbox->mbox.hwbase)
+       if (mbox->mbox.hwbase && !is_cn20k(pf->pdev))
                iounmap((void __iomem *)mbox->mbox.hwbase);
 
        otx2_mbox_destroy(&mbox->mbox);
@@ -1147,12 +1175,20 @@ int otx2_pfaf_mbox_init(struct otx2_nic *pf)
        if (!pf->mbox_wq)
                return -ENOMEM;
 
-       /* Mailbox is a reserved memory (in RAM) region shared between
-        * admin function (i.e AF) and this PF, shouldn't be mapped as
-        * device memory to allow unaligned accesses.
+       /* For CN20K, AF allocates mbox memory in DRAM and writes PF
+        * regions/offsets in RVU_MBOX_AF_PFX_ADDR, the RVU_PFX_FUNC_PFAF_MBOX
+        * gives the aliased address to access AF/PF mailbox regions.
         */
-       hwbase = ioremap_wc(pci_resource_start(pf->pdev, PCI_MBOX_BAR_NUM),
-                           MBOX_SIZE);
+       if (is_cn20k(pf->pdev))
+               hwbase = pf->reg_base + RVU_PFX_FUNC_PFAF_MBOX +
+                       ((u64)BLKADDR_MBOX << RVU_FUNC_BLKADDR_SHIFT);
+       else
+               /* Mailbox is a reserved memory (in RAM) region shared between
+                * admin function (i.e AF) and this PF, shouldn't be mapped as
+                * device memory to allow unaligned accesses.
+                */
+               hwbase = ioremap_wc(pci_resource_start
+                                   (pf->pdev, PCI_MBOX_BAR_NUM), MBOX_SIZE);
        if (!hwbase) {
                dev_err(pf->dev, "Unable to map PFAF mailbox region\n");
                err = -ENOMEM;
@@ -3000,8 +3036,13 @@ int otx2_init_rsrc(struct pci_dev *pdev, struct otx2_nic *pf)
        if (err)
                return err;
 
-       err = pci_alloc_irq_vectors(hw->pdev, RVU_PF_INT_VEC_CNT,
-                                   RVU_PF_INT_VEC_CNT, PCI_IRQ_MSIX);
+       if (!is_cn20k(pf->pdev))
+               err = pci_alloc_irq_vectors(hw->pdev, RVU_PF_INT_VEC_CNT,
+                                           RVU_PF_INT_VEC_CNT, PCI_IRQ_MSIX);
+       else
+               err = pci_alloc_irq_vectors(hw->pdev, RVU_MBOX_PF_INT_VEC_CNT,
+                                           RVU_MBOX_PF_INT_VEC_CNT,
+                                           PCI_IRQ_MSIX);
        if (err < 0) {
                dev_err(dev, "%s: Failed to alloc %d IRQ vectors\n",
                        __func__, num_vec);
@@ -3010,6 +3051,11 @@ int otx2_init_rsrc(struct pci_dev *pdev, struct otx2_nic *pf)
 
        otx2_setup_dev_hw_settings(pf);
 
+       if (is_cn20k(pf->pdev))
+               cn20k_init(pf);
+       else
+               otx2_init_hw_ops(pf);
+
        /* Init PF <=> AF mailbox stuff */
        err = otx2_pfaf_mbox_init(pf);
        if (err)
index 858f084b9d4740e88bb2d0fa1ce243ed2448783f..901f8cf7f27a90b5e75d563d42bcca469a575459 100644 (file)
 #define        RVU_VF_MSIX_PBAX(a)                 (0xF0000 | (a) << 3)
 #define RVU_VF_MBOX_REGION                  (0xC0000)
 
+/* 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_FUNC_BLKADDR_SHIFT         20
 #define RVU_FUNC_BLKADDR_MASK          0x1FULL
 
index 8a8b598bd389b946a98faca6a47f7d4e672ab3ec..d2f61438a8476c22635a75a0c688f99ba6e64675 100644 (file)
@@ -616,6 +616,12 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        }
 
        otx2_setup_dev_hw_settings(vf);
+
+       if (is_cn20k(vf->pdev))
+               cn20k_init(vf);
+       else
+               otx2_init_hw_ops(vf);
+
        /* Init VF <=> PF mailbox stuff */
        err = otx2vf_vfaf_mbox_init(vf);
        if (err)