diff mbox series

[11/20] octeontx2-af: Add support for stripping STAG/CTAG

Message ID 1541702161-30673-12-git-send-email-sunil.kovvuri@gmail.com
State Changes Requested, archived
Delegated to: David Miller
Headers show
Series octeontx2-af: NPC MCAM support and FLR handling | expand

Commit Message

Sunil Kovvuri Nov. 8, 2018, 6:35 p.m. UTC
From: Tomasz Duszynski <tduszynski@marvell.com>

This works by shadowing existing UCAST MCAM entry
with a new one additionally matching either NPC_LT_LB_CTAG
or NPC_LT_LB_STAG. For this to fully work one needs to
send properly configured NIX_VTAG_CFG message afterwards i.e with
strip and capture enabled and type set to 0.

On receiving tagged packet NIX will remove outer VLAN and capture
TCI in NIX_RX_PARSE_S.

Also simplified RX Vtag configuration flow
With this setting STRIP/CAPTURE VTAG actions separately would be
possible. Following combinations are possible: STRIP,
STRIP and CAPTURE, CAPTURE or nothing (0 disables respective actions).

Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
---
 drivers/net/ethernet/marvell/octeontx2/af/mbox.h   |  6 +-
 drivers/net/ethernet/marvell/octeontx2/af/npc.h    | 30 ++++++++
 drivers/net/ethernet/marvell/octeontx2/af/rvu.h    |  8 +++
 .../net/ethernet/marvell/octeontx2/af/rvu_nix.c    | 83 +++++++++++++++++-----
 .../net/ethernet/marvell/octeontx2/af/rvu_npc.c    | 46 +++++++++++-
 5 files changed, 152 insertions(+), 21 deletions(-)

Comments

Arnd Bergmann Nov. 8, 2018, 8:47 p.m. UTC | #1
On Thu, Nov 8, 2018 at 7:37 PM <sunil.kovvuri@gmail.com> wrote:

> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc.h b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
> index f98b011..3f7e5e6 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/npc.h
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
> @@ -259,4 +259,34 @@ struct nix_rx_action {
>  #endif
>  };
>
> +struct nix_rx_vtag_action {
> +#if defined(__BIG_ENDIAN_BITFIELD)
> +       u64     rsvd_63_48      :16;
> +       u64     vtag1_valid     :1;
> +       u64     vtag1_type      :3;
> +       u64     rsvd_43         :1;
> +       u64     vtag1_lid       :3;
> +       u64     vtag1_relptr    :8;
> +       u64     rsvd_31_16      :16;
> +       u64     vtag0_valid     :1;
> +       u64     vtag0_type      :3;
> +       u64     rsvd_11         :1;
> +       u64     vtag0_lid       :3;
> +       u64     vtag0_relptr    :8;
> +#else
> +       u64     vtag0_relptr    :8;
> +       u64     vtag0_lid       :3;
> +       u64     rsvd_11         :1;
> +       u64     vtag0_type      :3;
> +       u64     vtag0_valid     :1;
> +       u64     rsvd_31_16      :16;
> +       u64     vtag1_relptr    :8;
> +       u64     vtag1_lid       :3;
> +       u64     rsvd_43         :1;
> +       u64     vtag1_type      :3;
> +       u64     vtag1_valid     :1;
> +       u64     rsvd_63_48      :16;
> +#endif
> +};

Here is another instance of bitfields in an interface structure. As
before, please try to avoid doing that and use bit shifts and masks
instead.

       Arnd
Sunil Kovvuri Nov. 9, 2018, 4:29 a.m. UTC | #2
On Fri, Nov 9, 2018 at 2:17 AM Arnd Bergmann <arnd@arndb.de> wrote:
>
> On Thu, Nov 8, 2018 at 7:37 PM <sunil.kovvuri@gmail.com> wrote:
>
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc.h b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
> > index f98b011..3f7e5e6 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/af/npc.h
> > +++ b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
> > @@ -259,4 +259,34 @@ struct nix_rx_action {
> >  #endif
> >  };
> >
> > +struct nix_rx_vtag_action {
> > +#if defined(__BIG_ENDIAN_BITFIELD)
> > +       u64     rsvd_63_48      :16;
> > +       u64     vtag1_valid     :1;
> > +       u64     vtag1_type      :3;
> > +       u64     rsvd_43         :1;
> > +       u64     vtag1_lid       :3;
> > +       u64     vtag1_relptr    :8;
> > +       u64     rsvd_31_16      :16;
> > +       u64     vtag0_valid     :1;
> > +       u64     vtag0_type      :3;
> > +       u64     rsvd_11         :1;
> > +       u64     vtag0_lid       :3;
> > +       u64     vtag0_relptr    :8;
> > +#else
> > +       u64     vtag0_relptr    :8;
> > +       u64     vtag0_lid       :3;
> > +       u64     rsvd_11         :1;
> > +       u64     vtag0_type      :3;
> > +       u64     vtag0_valid     :1;
> > +       u64     rsvd_31_16      :16;
> > +       u64     vtag1_relptr    :8;
> > +       u64     vtag1_lid       :3;
> > +       u64     rsvd_43         :1;
> > +       u64     vtag1_type      :3;
> > +       u64     vtag1_valid     :1;
> > +       u64     rsvd_63_48      :16;
> > +#endif
> > +};
>
> Here is another instance of bitfields in an interface structure. As
> before, please try to avoid doing that and use bit shifts and masks
> instead.
>
>        Arnd

No, this struct is not part of communication interface.
This is used to fill up a register in a bit more readable fashion
instead of plain bit shifts.

===
struct nix_rx_vtag_action vtag_action;

        *(u64 *)&vtag_action = 0;
        vtag_action.vtag0_valid = 1;
        /* must match type set in NIX_VTAG_CFG */
        vtag_action.vtag0_type = 0;
        vtag_action.vtag0_lid = NPC_LID_LA;
        vtag_action.vtag0_relptr = 12;
        entry.vtag_action = *(u64 *)&vtag_action;

        /* Set TAG 'action' */
        rvu_write64(rvu, blkaddr, NPC_AF_MCAMEX_BANKX_TAG_ACT(index, actbank),
                    entry->vtag_action);
===

Thanks,
Sunil.
Arnd Bergmann Nov. 9, 2018, 11:12 a.m. UTC | #3
On Fri, Nov 9, 2018 at 5:29 AM Sunil Kovvuri <sunil.kovvuri@gmail.com> wrote:
> On Fri, Nov 9, 2018 at 2:17 AM Arnd Bergmann <arnd@arndb.de> wrote:
> > On Thu, Nov 8, 2018 at 7:37 PM <sunil.kovvuri@gmail.com> wrote:

> >
> > Here is another instance of bitfields in an interface structure. As
> > before, please try to avoid doing that and use bit shifts and masks
> > instead.
> >
> >        Arnd
>
> No, this struct is not part of communication interface.
> This is used to fill up a register in a bit more readable fashion
> instead of plain bit shifts.

But this is still an interface, isn't it? Writing to the register
implies that there is some hardware that interprets the
bits, so they have to be in the right place.

> ===
> struct nix_rx_vtag_action vtag_action;
>
>         *(u64 *)&vtag_action = 0;
>         vtag_action.vtag0_valid = 1;
>         /* must match type set in NIX_VTAG_CFG */
>         vtag_action.vtag0_type = 0;
>         vtag_action.vtag0_lid = NPC_LID_LA;
>         vtag_action.vtag0_relptr = 12;
>         entry.vtag_action = *(u64 *)&vtag_action;
>
>         /* Set TAG 'action' */
>         rvu_write64(rvu, blkaddr, NPC_AF_MCAMEX_BANKX_TAG_ACT(index, actbank),
>                     entry->vtag_action);

I assume this rvu_write64() does a cpu_to_le64() swap on big-endian,
so the contents again are in the wrong place. I don't see any non-reserved
fields that span an 8-bit boundary, so you can probably rearrange the bits
to make it work, but generally speaking it's better to not rely on how the
compiler lays out bit fields.

        Arnd
Sunil Kovvuri Nov. 9, 2018, 5:06 p.m. UTC | #4
On Fri, Nov 9, 2018 at 4:42 PM Arnd Bergmann <arnd@arndb.de> wrote:
>
> On Fri, Nov 9, 2018 at 5:29 AM Sunil Kovvuri <sunil.kovvuri@gmail.com> wrote:
> > On Fri, Nov 9, 2018 at 2:17 AM Arnd Bergmann <arnd@arndb.de> wrote:
> > > On Thu, Nov 8, 2018 at 7:37 PM <sunil.kovvuri@gmail.com> wrote:
>
> > >
> > > Here is another instance of bitfields in an interface structure. As
> > > before, please try to avoid doing that and use bit shifts and masks
> > > instead.
> > >
> > >        Arnd
> >
> > No, this struct is not part of communication interface.
> > This is used to fill up a register in a bit more readable fashion
> > instead of plain bit shifts.
>
> But this is still an interface, isn't it? Writing to the register
> implies that there is some hardware that interprets the
> bits, so they have to be in the right place.
>
> > ===
> > struct nix_rx_vtag_action vtag_action;
> >
> >         *(u64 *)&vtag_action = 0;
> >         vtag_action.vtag0_valid = 1;
> >         /* must match type set in NIX_VTAG_CFG */
> >         vtag_action.vtag0_type = 0;
> >         vtag_action.vtag0_lid = NPC_LID_LA;
> >         vtag_action.vtag0_relptr = 12;
> >         entry.vtag_action = *(u64 *)&vtag_action;
> >
> >         /* Set TAG 'action' */
> >         rvu_write64(rvu, blkaddr, NPC_AF_MCAMEX_BANKX_TAG_ACT(index, actbank),
> >                     entry->vtag_action);
>
> I assume this rvu_write64() does a cpu_to_le64() swap on big-endian,
> so the contents again are in the wrong place. I don't see any non-reserved
> fields that span an 8-bit boundary, so you can probably rearrange the bits
> to make it work, but generally speaking it's better to not rely on how the
> compiler lays out bit fields.
>
>         Arnd

Agreed.
Will fix and submit a new series.

Thanks,
Sunil.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
index 737dbc9..f2bf77d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
@@ -181,7 +181,8 @@  M(NIX_SET_MAC_ADDR,	0x800a, nix_set_mac_addr, msg_rsp)		\
 M(NIX_SET_RX_MODE,	0x800b, nix_rx_mode, msg_rsp)			\
 M(NIX_SET_HW_FRS,	0x800c, nix_frs_cfg, msg_rsp)			\
 M(NIX_LF_START_RX,	0x800d, msg_req, msg_rsp)			\
-M(NIX_LF_STOP_RX,	0x800e, msg_req, msg_rsp)
+M(NIX_LF_STOP_RX,	0x800e, msg_req, msg_rsp)			\
+M(NIX_RXVLAN_ALLOC,	0x8012, msg_req, msg_rsp)
 
 /* Messages initiated by AF (range 0xC00 - 0xDFF) */
 #define MBOX_UP_CGX_MESSAGES						\
@@ -499,6 +500,7 @@  struct nix_txschq_config {
 
 struct nix_vtag_config {
 	struct mbox_msghdr hdr;
+	/* '0' for 4 octet VTAG, '1' for 8 octet VTAG */
 	u8 vtag_size;
 	/* cfg_type is '0' for tx vlan cfg
 	 * cfg_type is '1' for rx vlan cfg
@@ -519,7 +521,7 @@  struct nix_vtag_config {
 
 		/* valid when cfg_type is '1' */
 		struct {
-			/* rx vtag type index */
+			/* rx vtag type index, valid values are in 0..7 range */
 			u8 vtag_type;
 			/* rx vtag strip */
 			u8 strip_vtag :1;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc.h b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
index f98b011..3f7e5e6 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/npc.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
@@ -259,4 +259,34 @@  struct nix_rx_action {
 #endif
 };
 
+struct nix_rx_vtag_action {
+#if defined(__BIG_ENDIAN_BITFIELD)
+	u64     rsvd_63_48      :16;
+	u64     vtag1_valid     :1;
+	u64     vtag1_type      :3;
+	u64     rsvd_43         :1;
+	u64     vtag1_lid       :3;
+	u64     vtag1_relptr    :8;
+	u64     rsvd_31_16      :16;
+	u64     vtag0_valid     :1;
+	u64     vtag0_type      :3;
+	u64     rsvd_11         :1;
+	u64     vtag0_lid       :3;
+	u64     vtag0_relptr    :8;
+#else
+	u64     vtag0_relptr    :8;
+	u64     vtag0_lid       :3;
+	u64     rsvd_11         :1;
+	u64     vtag0_type      :3;
+	u64     vtag0_valid     :1;
+	u64     rsvd_31_16      :16;
+	u64     vtag1_relptr    :8;
+	u64     vtag1_lid       :3;
+	u64     rsvd_43         :1;
+	u64     vtag1_type      :3;
+	u64     vtag1_valid     :1;
+	u64     rsvd_63_48      :16;
+#endif
+};
+
 #endif /* NPC_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
index 12fbdba..e213bf4 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
@@ -142,6 +142,11 @@  struct rvu_pfvf {
 	/* Broadcast pkt replication info */
 	u16			bcast_mce_idx;
 	struct nix_mce_list	bcast_mce_list;
+
+	/* VLAN offload */
+	struct mcam_entry entry;
+	int rxvlan_index;
+	bool rxvlan;
 };
 
 struct nix_txsch {
@@ -356,6 +361,8 @@  int rvu_mbox_handler_NIX_STATS_RST(struct rvu *rvu, struct msg_req *req,
 int rvu_mbox_handler_NIX_VTAG_CFG(struct rvu *rvu,
 				  struct nix_vtag_config *req,
 				  struct msg_rsp *rsp);
+int rvu_mbox_handler_NIX_RXVLAN_ALLOC(struct rvu *rvu, struct msg_req *req,
+				      struct msg_rsp *rsp);
 int rvu_mbox_handler_NIX_RSS_FLOWKEY_CFG(struct rvu *rvu,
 					 struct nix_rss_flowkey_cfg *req,
 					 struct msg_rsp *rsp);
@@ -384,6 +391,7 @@  void rvu_npc_disable_promisc_entry(struct rvu *rvu, u16 pcifunc, int nixlf);
 void rvu_npc_enable_promisc_entry(struct rvu *rvu, u16 pcifunc, int nixlf);
 void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
 				       int nixlf, u64 chan);
+int rvu_npc_update_rxvlan(struct rvu *rvu, u16 pcifunc, int nixlf);
 void rvu_npc_disable_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
 void rvu_npc_disable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
 void rvu_npc_enable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
index 5853af4..70a2997 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
@@ -192,6 +192,7 @@  static void nix_interface_deinit(struct rvu *rvu, u16 pcifunc, u8 nixlf)
 
 	pfvf->maxlen = 0;
 	pfvf->minlen = 0;
+	pfvf->rxvlan = false;
 
 	/* Remove this PF_FUNC from bcast pkt replication list */
 	err = nix_update_bcast_mce_list(rvu, pcifunc, false);
@@ -1209,28 +1210,15 @@  int rvu_mbox_handler_NIX_TXSCHQ_CFG(struct rvu *rvu,
 static int nix_rx_vtag_cfg(struct rvu *rvu, int nixlf, int blkaddr,
 			   struct nix_vtag_config *req)
 {
-	u64 regval = 0;
+	u64 regval = req->vtag_size;
 
-#define NIX_VTAGTYPE_MAX 0x8ull
-#define NIX_VTAGSIZE_MASK 0x7ull
-#define NIX_VTAGSTRIP_CAP_MASK 0x30ull
-
-	if (req->rx.vtag_type >= NIX_VTAGTYPE_MAX ||
-	    req->vtag_size > VTAGSIZE_T8)
+	if (req->rx.vtag_type > 7 || req->vtag_size > VTAGSIZE_T8)
 		return -EINVAL;
 
-	regval = rvu_read64(rvu, blkaddr,
-			    NIX_AF_LFX_RX_VTAG_TYPEX(nixlf, req->rx.vtag_type));
-
-	if (req->rx.strip_vtag && req->rx.capture_vtag)
-		regval |= BIT_ULL(4) | BIT_ULL(5);
-	else if (req->rx.strip_vtag)
+	if (req->rx.capture_vtag)
+		regval |= BIT_ULL(5);
+	if (req->rx.strip_vtag)
 		regval |= BIT_ULL(4);
-	else
-		regval &= ~(BIT_ULL(4) | BIT_ULL(5));
-
-	regval &= ~NIX_VTAGSIZE_MASK;
-	regval |= req->vtag_size & NIX_VTAGSIZE_MASK;
 
 	rvu_write64(rvu, blkaddr,
 		    NIX_AF_LFX_RX_VTAG_TYPEX(nixlf, req->rx.vtag_type), regval);
@@ -1770,6 +1758,9 @@  int rvu_mbox_handler_NIX_SET_MAC_ADDR(struct rvu *rvu,
 
 	rvu_npc_install_ucast_entry(rvu, pcifunc, nixlf,
 				    pfvf->rx_chan_base, req->mac_addr);
+
+	rvu_npc_update_rxvlan(rvu, pcifunc, nixlf);
+
 	return 0;
 }
 
@@ -1803,6 +1794,9 @@  int rvu_mbox_handler_NIX_SET_RX_MODE(struct rvu *rvu, struct nix_rx_mode *req,
 	else
 		rvu_npc_install_promisc_entry(rvu, pcifunc, nixlf,
 					      pfvf->rx_chan_base, allmulti);
+
+	rvu_npc_update_rxvlan(rvu, pcifunc, nixlf);
+
 	return 0;
 }
 
@@ -1941,6 +1935,59 @@  int rvu_mbox_handler_NIX_SET_HW_FRS(struct rvu *rvu, struct nix_frs_cfg *req,
 	return 0;
 }
 
+int rvu_mbox_handler_NIX_RXVLAN_ALLOC(struct rvu *rvu, struct msg_req *req,
+				      struct msg_rsp *rsp)
+{
+	struct npc_mcam_alloc_entry_req alloc_req = { };
+	struct npc_mcam_alloc_entry_rsp alloc_rsp = { };
+	struct npc_mcam_free_entry_req free_req = { };
+	u16 pcifunc = req->hdr.pcifunc;
+	int blkaddr, nixlf, err;
+	struct rvu_pfvf *pfvf;
+
+	pfvf = rvu_get_pfvf(rvu, pcifunc);
+	if (pfvf->rxvlan)
+		return 0;
+
+	/* alloc new mcam entry */
+	alloc_req.hdr.pcifunc = pcifunc;
+	alloc_req.count = 1;
+
+	err = rvu_mbox_handler_NPC_MCAM_ALLOC_ENTRY(rvu, &alloc_req,
+						    &alloc_rsp);
+	if (err)
+		return err;
+
+	/* update entry to enable rxvlan offload */
+	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
+	if (blkaddr < 0) {
+		err = NIX_AF_ERR_AF_LF_INVALID;
+		goto free_entry;
+	}
+
+	nixlf = rvu_get_lf(rvu, &rvu->hw->block[blkaddr], pcifunc, 0);
+	if (nixlf < 0) {
+		err = NIX_AF_ERR_AF_LF_INVALID;
+		goto free_entry;
+	}
+
+	pfvf->rxvlan_index = alloc_rsp.entry_list[0];
+	/* all it means is that rxvlan_index is valid */
+	pfvf->rxvlan = true;
+
+	err = rvu_npc_update_rxvlan(rvu, pcifunc, nixlf);
+	if (err)
+		goto free_entry;
+
+	return 0;
+free_entry:
+	free_req.hdr.pcifunc = pcifunc;
+	free_req.entry = alloc_rsp.entry_list[0];
+	rvu_mbox_handler_NPC_MCAM_FREE_ENTRY(rvu, &free_req, rsp);
+	pfvf->rxvlan = false;
+	return err;
+}
+
 static void nix_link_config(struct rvu *rvu, int blkaddr)
 {
 	struct rvu_hwinfo *hw = rvu->hw;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
index 100ce29..5dbb5cd 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
@@ -306,7 +306,9 @@  static u64 npc_get_mcam_action(struct rvu *rvu, struct npc_mcam *mcam,
 void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
 				 int nixlf, u64 chan, u8 *mac_addr)
 {
+	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
 	struct npc_mcam *mcam = &rvu->hw->mcam;
+	struct nix_rx_vtag_action vtag_action;
 	struct mcam_entry entry = { {0} };
 	struct nix_rx_action action;
 	int blkaddr, index, kwi;
@@ -345,6 +347,20 @@  void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
 	entry.action = *(u64 *)&action;
 	npc_config_mcam_entry(rvu, mcam, blkaddr, index,
 			      NIX_INTF_RX, &entry, true);
+
+	/* add VLAN matching, setup action and save entry back for later */
+	entry.kw[0] |= (NPC_LT_LB_STAG | NPC_LT_LB_CTAG) << 20;
+	entry.kw_mask[0] |= (NPC_LT_LB_STAG & NPC_LT_LB_CTAG) << 20;
+
+	*(u64 *)&vtag_action = 0;
+	vtag_action.vtag0_valid = 1;
+	/* must match type set in NIX_VTAG_CFG */
+	vtag_action.vtag0_type = 0;
+	vtag_action.vtag0_lid = NPC_LID_LA;
+	vtag_action.vtag0_relptr = 12;
+	entry.vtag_action = *(u64 *)&vtag_action;
+
+	memcpy(&pfvf->entry, &entry, sizeof(entry));
 }
 
 void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
@@ -352,7 +368,7 @@  void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
 {
 	struct npc_mcam *mcam = &rvu->hw->mcam;
 	struct mcam_entry entry = { {0} };
-	struct nix_rx_action action;
+	struct nix_rx_action action = { };
 	int blkaddr, index, kwi;
 
 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
@@ -521,6 +537,8 @@  void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
 
 	rvu_write64(rvu, blkaddr,
 		    NPC_AF_MCAMEX_BANKX_ACTION(index, bank), *(u64 *)&action);
+
+	rvu_npc_update_rxvlan(rvu, pcifunc, nixlf);
 }
 
 static void npc_enadis_default_entries(struct rvu *rvu, u16 pcifunc,
@@ -560,6 +578,8 @@  static void npc_enadis_default_entries(struct rvu *rvu, u16 pcifunc,
 		rvu_npc_enable_promisc_entry(rvu, pcifunc, nixlf);
 	else
 		rvu_npc_disable_promisc_entry(rvu, pcifunc, nixlf);
+
+	rvu_npc_update_rxvlan(rvu, pcifunc, nixlf);
 }
 
 void rvu_npc_disable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf)
@@ -2018,3 +2038,27 @@  int rvu_mbox_handler_NPC_GET_KEX_CFG(struct rvu *rvu, struct msg_req *req,
 	}
 	return 0;
 }
+
+int rvu_npc_update_rxvlan(struct rvu *rvu, u16 pcifunc, int nixlf)
+{
+	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
+	struct npc_mcam *mcam = &rvu->hw->mcam;
+	int blkaddr, index;
+	bool enable;
+
+	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
+	if (blkaddr < 0)
+		return NIX_AF_ERR_AF_LF_INVALID;
+
+	if (!pfvf->rxvlan)
+		return 0;
+
+	index = npc_get_nixlf_mcam_index(mcam, pcifunc, nixlf,
+					 NIXLF_UCAST_ENTRY);
+	pfvf->entry.action = npc_get_mcam_action(rvu, mcam, blkaddr, index);
+	enable = is_mcam_entry_enabled(rvu, mcam, blkaddr, index);
+	npc_config_mcam_entry(rvu, mcam, blkaddr, pfvf->rxvlan_index,
+			      NIX_INTF_RX, &pfvf->entry, enable);
+
+	return 0;
+}