RE: [EXTERNAL] Re: [net-next,v3 4/8] cn10k-ipsec: Initialize crypto hardware for outb inline ipsec

From: Bharat Bhushan
Date: Mon Jun 03 2024 - 04:47:07 EST




> -----Original Message-----
> From: Kalesh Anakkur Purayil <kalesh-anakkur.purayil@xxxxxxxxxxxx>
> Sent: Wednesday, May 29, 2024 11:16 AM
> To: Bharat Bhushan <bbhushan2@xxxxxxxxxxx>
> Cc: netdev@xxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx; Sunil Kovvuri
> Goutham <sgoutham@xxxxxxxxxxx>; Geethasowjanya Akula
> <gakula@xxxxxxxxxxx>; Subbaraya Sundeep Bhatta <sbhatta@xxxxxxxxxxx>;
> Hariprasad Kelam <hkelam@xxxxxxxxxxx>; davem@xxxxxxxxxxxxx;
> edumazet@xxxxxxxxxx; kuba@xxxxxxxxxx; pabeni@xxxxxxxxxx; Jerin Jacob
> <jerinj@xxxxxxxxxxx>; Linu Cherian <lcherian@xxxxxxxxxxx>;
> richardcochran@xxxxxxxxx
> Subject: [EXTERNAL] Re: [net-next,v3 4/8] cn10k-ipsec: Initialize crypto
> hardware for outb inline ipsec
>
> ----------------------------------------------------------------------
> On Tue, May 28, 2024 at 7:27 PM Bharat Bhushan
> <bbhushan2@xxxxxxxxxxx> wrote:
> >
> > One crypto hardware logical function (cpt-lf) per netdev is
> > required for inline ipsec outbound functionality. Allocate,
> > attach and initialize one crypto hardware function when
> > enabling inline ipsec crypto offload. Crypto hardware
> > function will be detached and freed on disabling inline
> > ipsec.
> >
> > Signed-off-by: Bharat Bhushan <bbhushan2@xxxxxxxxxxx>
> > ---
> > v1->v2:
> > - Fix compilation error to build driver a module
> > - Fix couple of compilation warnings
> >
> > .../ethernet/marvell/octeontx2/nic/Makefile | 1 +
> > .../marvell/octeontx2/nic/cn10k_ipsec.c | 393 ++++++++++++++++++
> > .../marvell/octeontx2/nic/cn10k_ipsec.h | 104 +++++
> > .../marvell/octeontx2/nic/otx2_common.h | 18 +
> > .../ethernet/marvell/octeontx2/nic/otx2_pf.c | 14 +-
> > .../ethernet/marvell/octeontx2/nic/otx2_vf.c | 10 +-
> > 6 files changed, 538 insertions(+), 2 deletions(-)
> > create mode 100644
> drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c
> > create mode 100644
> drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h
> >
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
> b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
> > index 5664f768cb0c..9695f967d416 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
> > @@ -14,5 +14,6 @@ rvu_nicvf-y := otx2_vf.o otx2_devlink.o
> > rvu_nicpf-$(CONFIG_DCB) += otx2_dcbnl.o
> > rvu_nicvf-$(CONFIG_DCB) += otx2_dcbnl.o
> > rvu_nicpf-$(CONFIG_MACSEC) += cn10k_macsec.o
> > +rvu_nicpf-$(CONFIG_XFRM_OFFLOAD) += cn10k_ipsec.o
> >
> > ccflags-y += -I$(srctree)/drivers/net/ethernet/marvell/octeontx2/af
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c
> b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c
> > new file mode 100644
> > index 000000000000..b221b67815ee
> > --- /dev/null
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c
> > @@ -0,0 +1,393 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/* Marvell IPSEC offload driver
> > + *
> > + * Copyright (C) 2024 Marvell.
> > + */
> > +
> > +#include <net/xfrm.h>
> > +#include <linux/netdevice.h>
> > +#include <linux/bitfield.h>
> > +
> > +#include "otx2_common.h"
> > +#include "cn10k_ipsec.h"
> > +
> > +static bool is_dev_support_inline_ipsec(struct pci_dev *pdev)
> > +{
> > + return is_dev_cn10ka_b0(pdev) || is_dev_cn10kb(pdev);
> > +}
> > +
> > +static int cn10k_outb_cptlf_attach(struct otx2_nic *pf)
> > +{
> > + struct rsrc_attach *attach;
> > + int err;
> > +
> > + mutex_lock(&pf->mbox.lock);
> > + /* Get memory to put this msg */
> > + attach = otx2_mbox_alloc_msg_attach_resources(&pf->mbox);
> > + if (!attach) {
> > + mutex_unlock(&pf->mbox.lock);
> > + return -ENOMEM;
> > + }
> [Kalesh] To make it consistent with other functions, you can add a
> label unlock and re-write it as:
> if (!attach) {
> err = -ENOMEM;
> goto unlock;

Yes, will take care

> }
> > +
> > + attach->cptlfs = true;
> > + attach->modify = true;
> > +
> > + /* Send attach request to AF */
> > + err = otx2_sync_mbox_msg(&pf->mbox);
> > + if (err) {
> > + mutex_unlock(&pf->mbox.lock);
> > + return err;
> > + }
> > +
> > + mutex_unlock(&pf->mbox.lock);
> > + return 0;
> > +}
> > +
> > +static int cn10k_outb_cptlf_detach(struct otx2_nic *pf)
> > +{
> > + struct rsrc_detach *detach;
> > +
> > + mutex_lock(&pf->mbox.lock);
> > + detach = otx2_mbox_alloc_msg_detach_resources(&pf->mbox);
> > + if (!detach) {
> > + mutex_unlock(&pf->mbox.lock);
> > + return -ENOMEM;
> > + }
> [Kalesh] Same comment as above
> > +
> > + detach->partial = true;
> > + detach->cptlfs = true;
> > +
> > + /* Send detach request to AF */
> > + otx2_sync_mbox_msg(&pf->mbox);
> > + mutex_unlock(&pf->mbox.lock);
> > + return 0;
> > +}
> > +
> > +static int cn10k_outb_cptlf_alloc(struct otx2_nic *pf)
> > +{
> > + struct cpt_lf_alloc_req_msg *req;
> > + int ret = 0;
> [Kalesh] No need to initialize ret here. You are little inconsistent
> in naming the variable, ret vs err :)

Okay, will use ret;

> > +
> > + mutex_lock(&pf->mbox.lock);
> > + req = otx2_mbox_alloc_msg_cpt_lf_alloc(&pf->mbox);
> > + if (!req) {
> > + ret = -ENOMEM;
> > + goto error;
> > + }
> > +
> > + /* PF function */
> > + req->nix_pf_func = pf->pcifunc;
> > + /* Enable SE-IE Engine Group */
> > + req->eng_grpmsk = 1 << CN10K_DEF_CPT_IPSEC_EGRP;
> > +
> > + ret = otx2_sync_mbox_msg(&pf->mbox);
> > +
> > +error:
> [Kalesh]: I would be better name the label as unlock.

Yes, will take care

> > + mutex_unlock(&pf->mbox.lock);
> > + return ret;
> > +}
> > +
> > +static void cn10k_outb_cptlf_free(struct otx2_nic *pf)
> > +{
> > + mutex_lock(&pf->mbox.lock);
> > + otx2_mbox_alloc_msg_cpt_lf_free(&pf->mbox);
> > + otx2_sync_mbox_msg(&pf->mbox);
> > + mutex_unlock(&pf->mbox.lock);
> > +}
> > +
> > +static int cn10k_outb_cptlf_config(struct otx2_nic *pf)
> > +{
> > + struct cpt_inline_ipsec_cfg_msg *req;
> > + int ret = 0;
> [Kalesh] No need to initialize the variable here.
> > +
> > + mutex_lock(&pf->mbox.lock);
> > + req = otx2_mbox_alloc_msg_cpt_inline_ipsec_cfg(&pf->mbox);
> > + if (!req) {
> > + ret = -ENOMEM;
> > + goto error;
> > + }
> > +
> > + req->dir = CPT_INLINE_OUTBOUND;
> > + req->enable = 1;
> > + req->nix_pf_func = pf->pcifunc;
> > + ret = otx2_sync_mbox_msg(&pf->mbox);
> > +error:
> > + mutex_unlock(&pf->mbox.lock);
> > + return ret;
> > +}
> > +
> > +static void cn10k_outb_cptlf_iq_enable(struct otx2_nic *pf)
> > +{
> > + u64 reg_val;
> > +
> > + /* Set Execution Enable of instruction queue */
> > + reg_val = otx2_read64(pf, CN10K_CPT_LF_INPROG);
> > + reg_val |= BIT_ULL(16);
> > + otx2_write64(pf, CN10K_CPT_LF_INPROG, reg_val);
> > +
> > + /* Set iqueue's enqueuing */
> > + reg_val = otx2_read64(pf, CN10K_CPT_LF_CTL);
> > + reg_val |= BIT_ULL(0);
> > + otx2_write64(pf, CN10K_CPT_LF_CTL, reg_val);
> > +}
> > +
> > +static void cn10k_outb_cptlf_iq_disable(struct otx2_nic *pf)
> > +{
> > + u32 inflight, grb_cnt, gwb_cnt;
> > + u32 nq_ptr, dq_ptr;
> > + int timeout = 20;
> > + u64 reg_val;
> > + int cnt;
> > +
> > + /* Disable instructions enqueuing */
> > + otx2_write64(pf, CN10K_CPT_LF_CTL, 0ull);
> > +
> > + /* Wait for instruction queue to become empty.
> > + * CPT_LF_INPROG.INFLIGHT count is zero
> > + */
> > + do {
> > + reg_val = otx2_read64(pf, CN10K_CPT_LF_INPROG);
> > + inflight = FIELD_GET(CPT_LF_INPROG_INFLIGHT, reg_val);
> > + if (!inflight)
> > + break;
> > +
> > + usleep_range(10000, 20000);
> > + if (timeout-- < 0) {
> > + netdev_err(pf->netdev, "Timeout to cleanup CPT IQ\n");
> > + break;
> > + }
> > + } while (1);
> > +
> > + /* Disable executions in the LF's queue,
> > + * the queue should be empty at this point
> > + */
> > + reg_val &= ~BIT_ULL(16);
> > + otx2_write64(pf, CN10K_CPT_LF_INPROG, reg_val);
> > +
> > + /* Wait for instruction queue to become empty */
> > + cnt = 0;
> > + do {
> > + reg_val = otx2_read64(pf, CN10K_CPT_LF_INPROG);
> > + if (reg_val & BIT_ULL(31))
> > + cnt = 0;
> > + else
> > + cnt++;
> > + reg_val = otx2_read64(pf, CN10K_CPT_LF_Q_GRP_PTR);
> > + nq_ptr = FIELD_GET(CPT_LF_Q_GRP_PTR_DQ_PTR, reg_val);
> > + dq_ptr = FIELD_GET(CPT_LF_Q_GRP_PTR_DQ_PTR, reg_val);
> > + } while ((cnt < 10) && (nq_ptr != dq_ptr));
> > +
> > + cnt = 0;
> > + do {
> > + reg_val = otx2_read64(pf, CN10K_CPT_LF_INPROG);
> > + inflight = FIELD_GET(CPT_LF_INPROG_INFLIGHT, reg_val);
> > + grb_cnt = FIELD_GET(CPT_LF_INPROG_GRB_CNT, reg_val);
> > + gwb_cnt = FIELD_GET(CPT_LF_INPROG_GWB_CNT, reg_val);
> > + if (inflight == 0 && gwb_cnt < 40 &&
> > + (grb_cnt == 0 || grb_cnt == 40))
> > + cnt++;
> > + else
> > + cnt = 0;
> > + } while (cnt < 10);
> > +}
> > +
> > +/* Allocate memory for CPT outbound Instruction queue.
> > + * Instruction queue memory format is:
> > + * -----------------------------
> > + * | Instruction Group memory |
> > + * | (CPT_LF_Q_SIZE[SIZE_DIV40] |
> > + * | x 16 Bytes) |
> > + * | |
> > + * ----------------------------- <-- CPT_LF_Q_BASE[ADDR]
> > + * | Flow Control (128 Bytes) |
> > + * | |
> > + * -----------------------------
> > + * | Instruction Memory |
> > + * | (CPT_LF_Q_SIZE[SIZE_DIV40] |
> > + * | × 40 × 64 bytes) |
> > + * | |
> > + * -----------------------------
> > + */
> > +static int cn10k_outb_cptlf_iq_alloc(struct otx2_nic *pf)
> > +{
> > + struct cn10k_cpt_inst_queue *iq = &pf->ipsec.iq;
> > +
> > + iq->size = CN10K_CPT_INST_QLEN_BYTES + CN10K_CPT_Q_FC_LEN +
> > + CN10K_CPT_INST_GRP_QLEN_BYTES + OTX2_ALIGN;
> > +
> > + iq->real_vaddr = dma_alloc_coherent(pf->dev, iq->size,
> > + &iq->real_dma_addr, GFP_KERNEL);
> > + if (!iq->real_vaddr)
> > + return -ENOMEM;
> > +
> > + /* iq->vaddr/dma_addr points to Flow Control location */
> > + iq->vaddr = iq->real_vaddr + CN10K_CPT_INST_GRP_QLEN_BYTES;
> > + iq->dma_addr = iq->real_dma_addr +
> CN10K_CPT_INST_GRP_QLEN_BYTES;
> > +
> > + /* Align pointers */
> > + iq->vaddr = PTR_ALIGN(iq->vaddr, OTX2_ALIGN);
> > + iq->dma_addr = PTR_ALIGN(iq->dma_addr, OTX2_ALIGN);
> > + return 0;
> > +}
> > +
> > +static void cn10k_outb_cptlf_iq_free(struct otx2_nic *pf)
> > +{
> > + struct cn10k_cpt_inst_queue *iq = &pf->ipsec.iq;
> > +
> > + if (!iq->real_vaddr)
> > + dma_free_coherent(pf->dev, iq->size, iq->real_vaddr,
> > + iq->real_dma_addr);
> > +
> > + iq->real_vaddr = NULL;
> > + iq->vaddr = NULL;
> > +}
> > +
> > +static int cn10k_outb_cptlf_iq_init(struct otx2_nic *pf)
> > +{
> > + u64 reg_val;
> > + int ret;
> > +
> > + /* Allocate Memory for CPT IQ */
> > + ret = cn10k_outb_cptlf_iq_alloc(pf);
> > + if (ret)
> > + return ret;
> > +
> > + /* Disable IQ */
> > + cn10k_outb_cptlf_iq_disable(pf);
> > +
> > + /* Set IQ base address */
> > + otx2_write64(pf, CN10K_CPT_LF_Q_BASE, pf->ipsec.iq.dma_addr);
> > +
> > + /* Set IQ size */
> > + reg_val = FIELD_PREP(CPT_LF_Q_SIZE_DIV40, CN10K_CPT_SIZE_DIV40
> +
> > + CN10K_CPT_EXTRA_SIZE_DIV40);
> > + otx2_write64(pf, CN10K_CPT_LF_Q_SIZE, reg_val);
> > +
> > + return 0;
> > +}
> > +
> > +static int cn10k_outb_cptlf_init(struct otx2_nic *pf)
> > +{
> > + int ret = 0;
> [Kalesh] There is no need to initialize this variable.
> > +
> > + /* Initialize CPTLF Instruction Queue (IQ) */
> > + ret = cn10k_outb_cptlf_iq_init(pf);
> > + if (ret)
> > + return ret;
> > +
> > + /* Configure CPTLF for outbound inline ipsec */
> > + ret = cn10k_outb_cptlf_config(pf);
> > + if (ret)
> > + goto iq_clean;
> > +
> > + /* Enable CPTLF IQ */
> > + cn10k_outb_cptlf_iq_enable(pf);
> > + return 0;
> > +iq_clean:
> > + cn10k_outb_cptlf_iq_free(pf);
> > + return ret;
> > +}
> > +
> > +static int cn10k_outb_cpt_init(struct net_device *netdev)
> > +{
> > + struct otx2_nic *pf = netdev_priv(netdev);
> > + int ret;
> > +
> > + mutex_lock(&pf->ipsec.lock);
> > +
> > + /* Attach a CPT LF for outbound inline ipsec */
> > + ret = cn10k_outb_cptlf_attach(pf);
> > + if (ret)
> > + goto unlock;
> > +
> > + /* Allocate a CPT LF for outbound inline ipsec */
> > + ret = cn10k_outb_cptlf_alloc(pf);
> > + if (ret)
> > + goto detach;
> > +
> > + /* Initialize the CPTLF for outbound inline ipsec */
> > + ret = cn10k_outb_cptlf_init(pf);
> > + if (ret)
> > + goto lf_free;
> > +
> > + pf->ipsec.io_addr = (__force u64)otx2_get_regaddr(pf,
> > + CN10K_CPT_LF_NQX(0));
> > +
> > + /* Set inline ipsec enabled for this device */
> > + pf->flags |= OTX2_FLAG_INLINE_IPSEC_ENABLED;
> > +
> > + goto unlock;
> > +
> > +lf_free:
> > + cn10k_outb_cptlf_free(pf);
> > +detach:
> > + cn10k_outb_cptlf_detach(pf);
> > +unlock:
> > + mutex_unlock(&pf->ipsec.lock);
> > + return ret;
> > +}
> > +
> > +static int cn10k_outb_cpt_clean(struct otx2_nic *pf)
> > +{
> > + int err;
> > +
> > + mutex_lock(&pf->ipsec.lock);
> > +
> > + /* Set inline ipsec disabled for this device */
> > + pf->flags &= ~OTX2_FLAG_INLINE_IPSEC_ENABLED;
> > +
> > + /* Disable CPTLF Instruction Queue (IQ) */
> > + cn10k_outb_cptlf_iq_disable(pf);
> > +
> > + /* Set IQ base address and size to 0 */
> > + otx2_write64(pf, CN10K_CPT_LF_Q_BASE, 0);
> > + otx2_write64(pf, CN10K_CPT_LF_Q_SIZE, 0);
> > +
> > + /* Free CPTLF IQ */
> > + cn10k_outb_cptlf_iq_free(pf);
> > +
> > + /* Free and detach CPT LF */
> > + cn10k_outb_cptlf_free(pf);
> > + err = cn10k_outb_cptlf_detach(pf);
> > + if (err)
> > + netdev_err(pf->netdev, "Failed to detach CPT LF\n");
> > +
> > + mutex_unlock(&pf->ipsec.lock);
> > + return err;
> > +}
> > +
> > +int cn10k_ipsec_ethtool_init(struct net_device *netdev, bool enable)
> > +{
> > + struct otx2_nic *pf = netdev_priv(netdev);
> > +
> > + /* Inline ipsec supported on cn10k */
> > + if (!is_dev_support_inline_ipsec(pf->pdev))
> > + return -ENODEV;
> [Kalesh] NODEV vs NOTSUPP ?

No SUPPOP is better.

> > +
> > + if (!enable)
> > + return cn10k_outb_cpt_clean(pf);
> > +
> > + /* Initialize CPT for outbound inline ipsec */
> > + return cn10k_outb_cpt_init(netdev);
> > +}
> > +
> > +int cn10k_ipsec_init(struct net_device *netdev)
> > +{
> > + struct otx2_nic *pf = netdev_priv(netdev);
> > +
> > + if (!is_dev_support_inline_ipsec(pf->pdev))
> > + return 0;
> [Kalesh] This function returns 0 always, maybe you can change it to return

Yes this patch returns zero only but follow up patches add code to return non-zero as well.
So as to have minimum difference I kept it like that.

Thanks
-Bharat

> void.
> > +
> > + mutex_init(&pf->ipsec.lock);
> > + return 0;
> > +}
> > +EXPORT_SYMBOL(cn10k_ipsec_init);
> > +
> > +void cn10k_ipsec_clean(struct otx2_nic *pf)
> > +{
> > + if (!is_dev_support_inline_ipsec(pf->pdev))
> > + return;
> > +
> > + cn10k_outb_cpt_clean(pf);
> > +}
> > +EXPORT_SYMBOL(cn10k_ipsec_clean);
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h
> b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h
> > new file mode 100644
> > index 000000000000..b322e19d5e23
> > --- /dev/null
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h
> > @@ -0,0 +1,104 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/* Marvell IPSEC offload driver
> > + *
> > + * Copyright (C) 2024 Marvell.
> > + */
> > +
> > +#ifndef CN10K_IPSEC_H
> > +#define CN10K_IPSEC_H
> > +
> > +#include <linux/types.h>
> > +
> > +/* CPT instruction size in bytes */
> > +#define CN10K_CPT_INST_SIZE 64
> > +
> > +/* CPT instruction (CPT_INST_S) queue length */
> > +#define CN10K_CPT_INST_QLEN 8200
> > +
> > +/* CPT instruction queue size passed to HW is in units of
> > + * 40*CPT_INST_S messages.
> > + */
> > +#define CN10K_CPT_SIZE_DIV40 (CN10K_CPT_INST_QLEN / 40)
> > +
> > +/* CPT needs 320 free entries */
> > +#define CN10K_CPT_INST_QLEN_EXTRA_BYTES (320 *
> CN10K_CPT_INST_SIZE)
> > +#define CN10K_CPT_EXTRA_SIZE_DIV40 (320 / 40)
> > +
> > +/* CPT instruction queue length in bytes */
> > +#define CN10K_CPT_INST_QLEN_BYTES \
> > + ((CN10K_CPT_SIZE_DIV40 * 40 * CN10K_CPT_INST_SIZE) + \
> > + CN10K_CPT_INST_QLEN_EXTRA_BYTES)
> > +
> > +/* CPT instruction group queue length in bytes */
> > +#define CN10K_CPT_INST_GRP_QLEN_BYTES \
> > + ((CN10K_CPT_SIZE_DIV40 + CN10K_CPT_EXTRA_SIZE_DIV40) * 16)
> > +
> > +/* CPT FC length in bytes */
> > +#define CN10K_CPT_Q_FC_LEN 128
> > +
> > +/* Default CPT engine group for inline ipsec */
> > +#define CN10K_DEF_CPT_IPSEC_EGRP 1
> > +
> > +/* CN10K CPT LF registers */
> > +#define CPT_LFBASE (BLKTYPE_CPT <<
> RVU_FUNC_BLKADDR_SHIFT)
> > +#define CN10K_CPT_LF_CTL (CPT_LFBASE | 0x10)
> > +#define CN10K_CPT_LF_INPROG (CPT_LFBASE | 0x40)
> > +#define CN10K_CPT_LF_Q_BASE (CPT_LFBASE | 0xf0)
> > +#define CN10K_CPT_LF_Q_SIZE (CPT_LFBASE | 0x100)
> > +#define CN10K_CPT_LF_Q_INST_PTR (CPT_LFBASE | 0x110)
> > +#define CN10K_CPT_LF_Q_GRP_PTR (CPT_LFBASE | 0x120)
> > +#define CN10K_CPT_LF_NQX(a) (CPT_LFBASE | 0x400 | (a) << 3)
> > +#define CN10K_CPT_LF_CTX_FLUSH (CPT_LFBASE | 0x510)
> > +
> > +struct cn10k_cpt_inst_queue {
> > + u8 *vaddr;
> > + u8 *real_vaddr;
> > + dma_addr_t dma_addr;
> > + dma_addr_t real_dma_addr;
> > + u32 size;
> > +};
> > +
> > +struct cn10k_ipsec {
> > + /* Outbound CPT */
> > + u64 io_addr;
> > + /* Lock to protect SA management */
> > + struct mutex lock;
> > + struct cn10k_cpt_inst_queue iq;
> > +};
> > +
> > +/* CPT LF_INPROG Register */
> > +#define CPT_LF_INPROG_INFLIGHT GENMASK_ULL(8, 0)
> > +#define CPT_LF_INPROG_GRB_CNT GENMASK_ULL(39, 32)
> > +#define CPT_LF_INPROG_GWB_CNT GENMASK_ULL(47, 40)
> > +
> > +/* CPT LF_Q_GRP_PTR Register */
> > +#define CPT_LF_Q_GRP_PTR_DQ_PTR GENMASK_ULL(14, 0)
> > +#define CPT_LF_Q_GRP_PTR_NQ_PTR GENMASK_ULL(46, 32)
> > +
> > +/* CPT LF_Q_SIZE Register */
> > +#define CPT_LF_Q_BASE_ADDR GENMASK_ULL(52, 7)
> > +
> > +/* CPT LF_Q_SIZE Register */
> > +#define CPT_LF_Q_SIZE_DIV40 GENMASK_ULL(14, 0)
> > +
> > +#ifdef CONFIG_XFRM_OFFLOAD
> > +int cn10k_ipsec_init(struct net_device *netdev);
> > +void cn10k_ipsec_clean(struct otx2_nic *pf);
> > +int cn10k_ipsec_ethtool_init(struct net_device *netdev, bool enable);
> > +#else
> > +static inline __maybe_unused int cn10k_ipsec_init(struct net_device
> *netdev)
> > +{
> > + return 0;
> > +}
> > +
> > +static inline __maybe_unused void cn10k_ipsec_clean(struct otx2_nic *pf)
> > +{
> > +}
> > +
> > +static inline __maybe_unused
> > +int cn10k_ipsec_ethtool_init(struct net_device *netdev, bool enable)
> > +{
> > + return 0;
> > +}
> > +#endif
> > +#endif // CN10K_IPSEC_H
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
> b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
> > index 42a759a33c11..859bbc78e653 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
> > @@ -29,6 +29,7 @@
> > #include "otx2_devlink.h"
> > #include <rvu_trace.h>
> > #include "qos.h"
> > +#include "cn10k_ipsec.h"
> >
> > /* IPv4 flag more fragment bit */
> > #define IPV4_FLAG_MORE 0x20
> > @@ -39,6 +40,7 @@
> > #define PCI_DEVID_OCTEONTX2_RVU_AFVF 0xA0F8
> >
> > #define PCI_SUBSYS_DEVID_96XX_RVU_PFVF 0xB200
> > +#define PCI_SUBSYS_DEVID_CN10K_A_RVU_PFVF 0xB900
> > #define PCI_SUBSYS_DEVID_CN10K_B_RVU_PFVF 0xBD00
> >
> > /* PCI BAR nos */
> > @@ -467,6 +469,7 @@ struct otx2_nic {
> > #define OTX2_FLAG_PTP_ONESTEP_SYNC BIT_ULL(15)
> > #define OTX2_FLAG_ADPTV_INT_COAL_ENABLED BIT_ULL(16)
> > #define OTX2_FLAG_TC_MARK_ENABLED BIT_ULL(17)
> > +#define OTX2_FLAG_INLINE_IPSEC_ENABLED BIT_ULL(18)
> > u64 flags;
> > u64 *cq_op_addr;
> >
> > @@ -534,6 +537,9 @@ struct otx2_nic {
> > #if IS_ENABLED(CONFIG_MACSEC)
> > struct cn10k_mcs_cfg *macsec_cfg;
> > #endif
> > +
> > + /* Inline ipsec */
> > + struct cn10k_ipsec ipsec;
> > };
> >
> > static inline bool is_otx2_lbkvf(struct pci_dev *pdev)
> > @@ -578,6 +584,15 @@ static inline bool is_dev_cn10kb(struct pci_dev
> *pdev)
> > return pdev->subsystem_device ==
> PCI_SUBSYS_DEVID_CN10K_B_RVU_PFVF;
> > }
> >
> > +static inline bool is_dev_cn10ka_b0(struct pci_dev *pdev)
> > +{
> > + if (pdev->subsystem_device ==
> PCI_SUBSYS_DEVID_CN10K_A_RVU_PFVF &&
> > + (pdev->revision & 0xFF) == 0x54)
> > + return true;
> > +
> > + return false;
> > +}
> > +
> > static inline void otx2_setup_dev_hw_settings(struct otx2_nic *pfvf)
> > {
> > struct otx2_hw *hw = &pfvf->hw;
> > @@ -627,6 +642,9 @@ static inline void __iomem *otx2_get_regaddr(struct
> otx2_nic *nic, u64 offset)
> > case BLKTYPE_NPA:
> > blkaddr = BLKADDR_NPA;
> > break;
> > + case BLKTYPE_CPT:
> > + blkaddr = BLKADDR_CPT0;
> > + break;
> > default:
> > blkaddr = BLKADDR_RVUM;
> > break;
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
> b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
> > index cbd5050f58e8..a7e17d870420 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
> > @@ -26,6 +26,7 @@
> > #include "cn10k.h"
> > #include "qos.h"
> > #include <rvu_trace.h>
> > +#include "cn10k_ipsec.h"
> >
> > #define DRV_NAME "rvu_nicpf"
> > #define DRV_STRING "Marvell RVU NIC Physical Function Driver"
> > @@ -2201,6 +2202,10 @@ static int otx2_set_features(struct net_device
> *netdev,
> > return otx2_enable_rxvlan(pf,
> > features & NETIF_F_HW_VLAN_CTAG_RX);
> >
> > + if (changed & NETIF_F_HW_ESP)
> > + return cn10k_ipsec_ethtool_init(netdev,
> > + features & NETIF_F_HW_ESP);
> > +
> > return otx2_handle_ntuple_tc_features(netdev, features);
> > }
> >
> > @@ -3065,10 +3070,14 @@ static int otx2_probe(struct pci_dev *pdev,
> const struct pci_device_id *id)
> > /* reset CGX/RPM MAC stats */
> > otx2_reset_mac_stats(pf);
> >
> > + err = cn10k_ipsec_init(netdev);
> > + if (err)
> > + goto err_mcs_free;
> > +
> > err = register_netdev(netdev);
> > if (err) {
> > dev_err(dev, "Failed to register netdevice\n");
> > - goto err_mcs_free;
> > + goto err_ipsec_clean;
> > }
> >
> > err = otx2_wq_init(pf);
> > @@ -3109,6 +3118,8 @@ static int otx2_probe(struct pci_dev *pdev, const
> struct pci_device_id *id)
> > otx2_mcam_flow_del(pf);
> > err_unreg_netdev:
> > unregister_netdev(netdev);
> > +err_ipsec_clean:
> > + cn10k_ipsec_clean(pf);
> > err_mcs_free:
> > cn10k_mcs_free(pf);
> > err_del_mcam_entries:
> > @@ -3286,6 +3297,7 @@ static void otx2_remove(struct pci_dev *pdev)
> >
> > otx2_unregister_dl(pf);
> > unregister_netdev(netdev);
> > + cn10k_ipsec_clean(pf);
> > cn10k_mcs_free(pf);
> > otx2_sriov_disable(pf->pdev);
> > otx2_sriov_vfcfg_cleanup(pf);
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
> b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
> > index 99fcc5661674..6fc70c3cafb6 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
> > @@ -14,6 +14,7 @@
> > #include "otx2_reg.h"
> > #include "otx2_ptp.h"
> > #include "cn10k.h"
> > +#include "cn10k_ipsec.h"
> >
> > #define DRV_NAME "rvu_nicvf"
> > #define DRV_STRING "Marvell RVU NIC Virtual Function Driver"
> > @@ -682,10 +683,14 @@ static int otx2vf_probe(struct pci_dev *pdev,
> const struct pci_device_id *id)
> > snprintf(netdev->name, sizeof(netdev->name), "lbk%d", n);
> > }
> >
> > + err = cn10k_ipsec_init(netdev);
> > + if (err)
> > + goto err_ptp_destroy;
> > +
> > err = register_netdev(netdev);
> > if (err) {
> > dev_err(dev, "Failed to register netdevice\n");
> > - goto err_ptp_destroy;
> > + goto err_ipsec_clean;
> > }
> >
> > err = otx2_wq_init(vf);
> > @@ -719,6 +724,8 @@ static int otx2vf_probe(struct pci_dev *pdev, const
> struct pci_device_id *id)
> > otx2_shutdown_tc(vf);
> > err_unreg_netdev:
> > unregister_netdev(netdev);
> > +err_ipsec_clean:
> > + cn10k_ipsec_clean(vf);
> > err_ptp_destroy:
> > otx2_ptp_destroy(vf);
> > err_detach_rsrc:
> > @@ -771,6 +778,7 @@ static void otx2vf_remove(struct pci_dev *pdev)
> > unregister_netdev(netdev);
> > if (vf->otx2_wq)
> > destroy_workqueue(vf->otx2_wq);
> > + cn10k_ipsec_clean(vf);
> > otx2_ptp_destroy(vf);
> > otx2_mcam_flow_del(vf);
> > otx2_shutdown_tc(vf);
> > --
> > 2.34.1
> >
> >
>
>
> --
> Regards,
> Kalesh A P