diff mbox series

[net-next,4/6] octeontx2-pf: CN20K mbox REQ/ACK implementation for NIC PF

Message ID 20241018203058.3641959-5-saikrishnag@marvell.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series CN20K silicon with mbox support | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 5 this patch: 5
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 11 of 11 maintainers
netdev/build_clang success Errors and warnings before: 4 this patch: 4
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 24 this patch: 24
netdev/checkpatch warning WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc fail Errors and warnings before: 0 this patch: 4
netdev/source_inline success Was 0 now: 0

Commit Message

Sai Krishna Gajula Oct. 18, 2024, 8:30 p.m. UTC
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: Sunil Kovvuri Goutham <sgoutham@marvell.com>
Signed-off-by: Sai Krishna <saikrishnag@marvell.com>
---
 .../marvell/octeontx2/af/cn20k/struct.h       | 15 ++++
 .../ethernet/marvell/octeontx2/nic/Makefile   |  2 +-
 .../ethernet/marvell/octeontx2/nic/cn10k.c    | 18 ++++-
 .../ethernet/marvell/octeontx2/nic/cn10k.h    |  1 +
 .../ethernet/marvell/octeontx2/nic/cn20k.c    | 65 +++++++++++++++
 .../ethernet/marvell/octeontx2/nic/cn20k.h    | 14 ++++
 .../marvell/octeontx2/nic/otx2_common.h       |  5 ++
 .../ethernet/marvell/octeontx2/nic/otx2_pf.c  | 80 +++++++++++++++----
 .../ethernet/marvell/octeontx2/nic/otx2_reg.h |  4 +
 .../ethernet/marvell/octeontx2/nic/otx2_vf.c  |  6 ++
 10 files changed, 188 insertions(+), 22 deletions(-)
 create mode 100644 drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c
 create mode 100644 drivers/net/ethernet/marvell/octeontx2/nic/cn20k.h

Comments

Kalesh Anakkur Purayil Oct. 21, 2024, 3:38 a.m. UTC | #1
On Sat, Oct 19, 2024 at 2:03 AM Sai Krishna <saikrishnag@marvell.com> wrote:
>
> 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: Sunil Kovvuri Goutham <sgoutham@marvell.com>
> Signed-off-by: Sai Krishna <saikrishnag@marvell.com>
> ---
>  .../marvell/octeontx2/af/cn20k/struct.h       | 15 ++++
>  .../ethernet/marvell/octeontx2/nic/Makefile   |  2 +-
>  .../ethernet/marvell/octeontx2/nic/cn10k.c    | 18 ++++-
>  .../ethernet/marvell/octeontx2/nic/cn10k.h    |  1 +
>  .../ethernet/marvell/octeontx2/nic/cn20k.c    | 65 +++++++++++++++
>  .../ethernet/marvell/octeontx2/nic/cn20k.h    | 14 ++++
>  .../marvell/octeontx2/nic/otx2_common.h       |  5 ++
>  .../ethernet/marvell/octeontx2/nic/otx2_pf.c  | 80 +++++++++++++++----
>  .../ethernet/marvell/octeontx2/nic/otx2_reg.h |  4 +
>  .../ethernet/marvell/octeontx2/nic/otx2_vf.c  |  6 ++
>  10 files changed, 188 insertions(+), 22 deletions(-)
>  create mode 100644 drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c
>  create mode 100644 drivers/net/ethernet/marvell/octeontx2/nic/cn20k.h
>
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/struct.h b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/struct.h
> index fccad6e422e8..055ccc8c4689 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/struct.h
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/struct.h
> @@ -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,
> diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
> index 64a97a0a10ed..1e2e838959f4 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
> @@ -7,7 +7,7 @@ obj-$(CONFIG_OCTEONTX2_PF) += rvu_nicpf.o otx2_ptp.o
>  obj-$(CONFIG_OCTEONTX2_VF) += rvu_nicvf.o otx2_ptp.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
>  rvu_nicvf-y := otx2_vf.o
>
> diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
> index c1c99d7054f8..52e0e036d00b 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
> @@ -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);
> diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
> index c1861f7de254..bb030816b523 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
> @@ -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
> index 000000000000..44472a9f9a6e
> --- /dev/null
> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c
> @@ -0,0 +1,65 @@
> +// 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,
> +};
> +
> +int cn20k_init(struct otx2_nic *pfvf)
[Kalesh] This function returns 0 unconditionally and the caller is not
checking the return value. You can change it to return void
> +{
> +       pfvf->hw_ops = &cn20k_hw_ops;
> +
> +       return 0;
> +}
> +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 = (struct otx2_nic *)pf_irq;
> +       struct mbox *mw = &pf->mbox;
> +       struct otx2_mbox_dev *mdev;
> +       struct otx2_mbox *mbox;
> +       struct mbox_hdr *hdr;
> +       int pf_trig_val;
> +
> +       pf_trig_val = otx2_read64(pf, RVU_PF_INT) & 0x3;
> +
> +       /* 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
> index 000000000000..da6210042c62
> --- /dev/null
> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.h
> @@ -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"
> +
> +int cn20k_init(struct otx2_nic *pfvf);
> +#endif /* CN20K_H */
> diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
> index 8e7ed3979f80..d0320192e7a5 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
> @@ -30,6 +30,7 @@
>  #include <rvu.h>
>  #include <rvu_trace.h>
>  #include "qos.h"
> +#include "cn20k.h"
>
>  /* IPv4 flag more fragment bit */
>  #define IPV4_FLAG_MORE                         0x20
> @@ -53,6 +54,9 @@
>  #define NIX_PF_PFC_PRIO_MAX                    8
>  #endif
>
> +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,
> @@ -373,6 +377,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
> diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
> index 5492dea547a1..c0cf228ac714 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
> @@ -958,7 +958,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;
> @@ -1010,10 +1010,18 @@ static irqreturn_t otx2_pfaf_mbox_intr_handler(int irq, void *pf_irq)
>
>  static 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);
>  }
>
> @@ -1025,10 +1033,24 @@ static 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->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->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");
> @@ -1038,8 +1060,14 @@ static 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;
> @@ -1070,7 +1098,7 @@ static 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);
> @@ -1089,12 +1117,20 @@ static 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;
> @@ -2957,8 +2993,13 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>         if (err)
>                 goto err_free_netdev;
>
> -       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);
> @@ -2967,6 +3008,11 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>
>         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)
> diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
> index 858f084b9d47..901f8cf7f27a 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
> @@ -58,6 +58,10 @@
>  #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
>
> diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
> index 99fcc5661674..76b97896ff1c 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
> @@ -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)
> --
> 2.25.1
>
>
Sai Krishna Gajula Oct. 21, 2024, 3:38 p.m. UTC | #2
> -----Original Message-----
> From: Kalesh Anakkur Purayil <kalesh-anakkur.purayil@broadcom.com>
> Sent: Monday, October 21, 2024 9:09 AM
> To: Sai Krishna Gajula <saikrishnag@marvell.com>
> Cc: davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; netdev@vger.kernel.org; linux-kernel@vger.kernel.org;
> Sunil Kovvuri Goutham <sgoutham@marvell.com>; Geethasowjanya Akula
> <gakula@marvell.com>; Linu Cherian <lcherian@marvell.com>; Jerin Jacob
> <jerinj@marvell.com>; Hariprasad Kelam <hkelam@marvell.com>; Subbaraya
> Sundeep Bhatta <sbhatta@marvell.com>
> Subject: Re: [net-next PATCH 4/6] octeontx2-pf: CN20K mbox
> REQ/ACK implementation for NIC PF
> 
> On Sat, Oct 19, 2024 at 2:03 AM Sai Krishna <saikrishnag@marvell.com>
> wrote:
> >
> > 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: Sunil Kovvuri Goutham <sgoutham@marvell.com>
> > Signed-off-by: Sai Krishna <saikrishnag@marvell.com>
> > ---
> >  .../marvell/octeontx2/af/cn20k/struct.h       | 15 ++++
> >  .../ethernet/marvell/octeontx2/nic/Makefile   |  2 +-
> >  .../ethernet/marvell/octeontx2/nic/cn10k.c    | 18 ++++-
> >  .../ethernet/marvell/octeontx2/nic/cn10k.h    |  1 +
> >  .../ethernet/marvell/octeontx2/nic/cn20k.c    | 65 +++++++++++++++
> >  .../ethernet/marvell/octeontx2/nic/cn20k.h    | 14 ++++
> >  .../marvell/octeontx2/nic/otx2_common.h       |  5 ++
> >  .../ethernet/marvell/octeontx2/nic/otx2_pf.c  | 80 +++++++++++++++----
> >  .../ethernet/marvell/octeontx2/nic/otx2_reg.h |  4 +
> >  .../ethernet/marvell/octeontx2/nic/otx2_vf.c  |  6 ++
> >  10 files changed, 188 insertions(+), 22 deletions(-)
> >  create mode 100644 drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c
> >  create mode 100644 drivers/net/ethernet/marvell/octeontx2/nic/cn20k.h
> >
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/struct.h
> b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/struct.h
> > index fccad6e422e8..055ccc8c4689 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/struct.h
> > +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/struct.h
> > @@ -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,
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
> b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
> > index 64a97a0a10ed..1e2e838959f4 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
> > @@ -7,7 +7,7 @@ obj-$(CONFIG_OCTEONTX2_PF) += rvu_nicpf.o
> otx2_ptp.o
> >  obj-$(CONFIG_OCTEONTX2_VF) += rvu_nicvf.o otx2_ptp.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
> >  rvu_nicvf-y := otx2_vf.o
> >
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
> b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
> > index c1c99d7054f8..52e0e036d00b 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
> > @@ -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);
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
> b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
> > index c1861f7de254..bb030816b523 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
> > @@ -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
> > index 000000000000..44472a9f9a6e
> > --- /dev/null
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c
> > @@ -0,0 +1,65 @@
> > +// 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,
> > +};
> > +
> > +int cn20k_init(struct otx2_nic *pfvf)
> [Kalesh] This function returns 0 unconditionally and the caller is not
> checking the return value. You can change it to return void

Ack, will submit V2 patch with the suggested changes.

> > +{
> > +       pfvf->hw_ops = &cn20k_hw_ops;
> > +
> > +       return 0;
> > +}
> > +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 = (struct otx2_nic *)pf_irq;
> > +       struct mbox *mw = &pf->mbox;
> > +       struct otx2_mbox_dev *mdev;
> > +       struct otx2_mbox *mbox;
> > +       struct mbox_hdr *hdr;
> > +       int pf_trig_val;
> > +
> > +       pf_trig_val = otx2_read64(pf, RVU_PF_INT) & 0x3;
> > +
> > +       /* 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
> > index 000000000000..da6210042c62
> > --- /dev/null
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.h
> > @@ -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"
> > +
> > +int cn20k_init(struct otx2_nic *pfvf);
> > +#endif /* CN20K_H */
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
> b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
> > index 8e7ed3979f80..d0320192e7a5 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
> > @@ -30,6 +30,7 @@
> >  #include <rvu.h>
> >  #include <rvu_trace.h>
> >  #include "qos.h"
> > +#include "cn20k.h"
> >
> >  /* IPv4 flag more fragment bit */
> >  #define IPV4_FLAG_MORE                         0x20
> > @@ -53,6 +54,9 @@
> >  #define NIX_PF_PFC_PRIO_MAX                    8
> >  #endif
> >
> > +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,
> > @@ -373,6 +377,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
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
> b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
> > index 5492dea547a1..c0cf228ac714 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
> > @@ -958,7 +958,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;
> > @@ -1010,10 +1010,18 @@ static irqreturn_t
> otx2_pfaf_mbox_intr_handler(int irq, void *pf_irq)
> >
> >  static 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);
> >  }
> >
> > @@ -1025,10 +1033,24 @@ static 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->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->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");
> > @@ -1038,8 +1060,14 @@ static 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;
> > @@ -1070,7 +1098,7 @@ static 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);
> > @@ -1089,12 +1117,20 @@ static 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;
> > @@ -2957,8 +2993,13 @@ static int otx2_probe(struct pci_dev *pdev, const
> struct pci_device_id *id)
> >         if (err)
> >                 goto err_free_netdev;
> >
> > -       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);
> > @@ -2967,6 +3008,11 @@ static int otx2_probe(struct pci_dev *pdev, const
> struct pci_device_id *id)
> >
> >         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)
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
> b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
> > index 858f084b9d47..901f8cf7f27a 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
> > @@ -58,6 +58,10 @@
> >  #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
> >
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
> b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
> > index 99fcc5661674..76b97896ff1c 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
> > @@ -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)
> > --
> > 2.25.1
> >
> >
> 
> 
> --
> Regards,
> Kalesh A P
diff mbox series

Patch

diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/struct.h b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/struct.h
index fccad6e422e8..055ccc8c4689 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/struct.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/struct.h
@@ -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,
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
index 64a97a0a10ed..1e2e838959f4 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
@@ -7,7 +7,7 @@  obj-$(CONFIG_OCTEONTX2_PF) += rvu_nicpf.o otx2_ptp.o
 obj-$(CONFIG_OCTEONTX2_VF) += rvu_nicvf.o otx2_ptp.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
 rvu_nicvf-y := otx2_vf.o
 
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
index c1c99d7054f8..52e0e036d00b 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
@@ -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);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
index c1861f7de254..bb030816b523 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
@@ -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
index 000000000000..44472a9f9a6e
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c
@@ -0,0 +1,65 @@ 
+// 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,
+};
+
+int cn20k_init(struct otx2_nic *pfvf)
+{
+	pfvf->hw_ops = &cn20k_hw_ops;
+
+	return 0;
+}
+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 = (struct otx2_nic *)pf_irq;
+	struct mbox *mw = &pf->mbox;
+	struct otx2_mbox_dev *mdev;
+	struct otx2_mbox *mbox;
+	struct mbox_hdr *hdr;
+	int pf_trig_val;
+
+	pf_trig_val = otx2_read64(pf, RVU_PF_INT) & 0x3;
+
+	/* 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
index 000000000000..da6210042c62
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.h
@@ -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"
+
+int cn20k_init(struct otx2_nic *pfvf);
+#endif /* CN20K_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
index 8e7ed3979f80..d0320192e7a5 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
@@ -30,6 +30,7 @@ 
 #include <rvu.h>
 #include <rvu_trace.h>
 #include "qos.h"
+#include "cn20k.h"
 
 /* IPv4 flag more fragment bit */
 #define IPV4_FLAG_MORE				0x20
@@ -53,6 +54,9 @@ 
 #define NIX_PF_PFC_PRIO_MAX			8
 #endif
 
+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,
@@ -373,6 +377,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
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index 5492dea547a1..c0cf228ac714 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -958,7 +958,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;
@@ -1010,10 +1010,18 @@  static irqreturn_t otx2_pfaf_mbox_intr_handler(int irq, void *pf_irq)
 
 static 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);
 }
 
@@ -1025,10 +1033,24 @@  static 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->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->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");
@@ -1038,8 +1060,14 @@  static 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;
@@ -1070,7 +1098,7 @@  static 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);
@@ -1089,12 +1117,20 @@  static 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;
@@ -2957,8 +2993,13 @@  static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	if (err)
 		goto err_free_netdev;
 
-	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);
@@ -2967,6 +3008,11 @@  static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	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)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
index 858f084b9d47..901f8cf7f27a 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
@@ -58,6 +58,10 @@ 
 #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
 
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
index 99fcc5661674..76b97896ff1c 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
@@ -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)