octeontx2-af: Enable broadcast packet replication
authorSunil Goutham <sgoutham@marvell.com>
Thu, 14 Nov 2019 05:26:30 +0000 (10:56 +0530)
committerDavid S. Miller <davem@davemloft.net>
Fri, 15 Nov 2019 02:09:16 +0000 (18:09 -0800)
Ingress packet replication support has been added to 96xx B0
silicon. This patch enables using that feature to replicate
ingress broadcast packets to PF and it's VFs.

Also fixed below issues
- VFs can also install NPC MCAM entry to forward broadcast pkts.
  Otherwise, unless PF's interface is UP, VFs will not receive
  bcast packets.
- NPC MCAM entry is disabled when PF and all it's VFs are down.
- Few corner cases in installing multicast entry list.

Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/octeontx2/af/rvu.c
drivers/net/ethernet/marvell/octeontx2/af/rvu.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c

index bf9272f..3985053 100644 (file)
@@ -64,6 +64,7 @@ static void rvu_setup_hw_capabilities(struct rvu *rvu)
        hw->cap.nix_fixed_txschq_mapping = false;
        hw->cap.nix_shaping = true;
        hw->cap.nix_tx_link_bp = true;
+       hw->cap.nix_rx_multicast = true;
 
        if (is_rvu_96xx_B0(rvu)) {
                hw->cap.nix_fixed_txschq_mapping = true;
@@ -72,6 +73,8 @@ static void rvu_setup_hw_capabilities(struct rvu *rvu)
                hw->cap.nix_txsch_per_sdp_lmac = 76;
                hw->cap.nix_shaping = false;
                hw->cap.nix_tx_link_bp = false;
+               if (is_rvu_96xx_A0(rvu))
+                       hw->cap.nix_rx_multicast = false;
        }
 }
 
index 000d02b..7370864 100644 (file)
@@ -235,6 +235,7 @@ struct hw_cap {
        bool    nix_fixed_txschq_mapping; /* Schq mapping fixed or flexible */
        bool    nix_shaping;             /* Is shaping and coloring supported */
        bool    nix_tx_link_bp;          /* Can link backpressure TL queues ? */
+       bool    nix_rx_multicast;        /* Rx packet replication support */
 };
 
 struct rvu_hwinfo {
@@ -441,6 +442,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);
+void rvu_npc_disable_bcast_entry(struct rvu *rvu, u16 pcifunc);
 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);
index 3b32e91..4519d80 100644 (file)
@@ -64,7 +64,6 @@ enum nix_makr_fmt_indexes {
 
 struct mce {
        struct hlist_node       node;
-       u16                     idx;
        u16                     pcifunc;
 };
 
@@ -1754,7 +1753,7 @@ static int nix_setup_mce(struct rvu *rvu, int mce, u8 op,
 }
 
 static int nix_update_mce_list(struct nix_mce_list *mce_list,
-                              u16 pcifunc, int idx, bool add)
+                              u16 pcifunc, bool add)
 {
        struct mce *mce, *tail = NULL;
        bool delete = false;
@@ -1783,7 +1782,6 @@ static int nix_update_mce_list(struct nix_mce_list *mce_list,
        mce = kzalloc(sizeof(*mce), GFP_KERNEL);
        if (!mce)
                return -ENOMEM;
-       mce->idx = idx;
        mce->pcifunc = pcifunc;
        if (!tail)
                hlist_add_head(&mce->node, &mce_list->head);
@@ -1795,12 +1793,12 @@ static int nix_update_mce_list(struct nix_mce_list *mce_list,
 
 static int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add)
 {
-       int err = 0, idx, next_idx, count;
+       int err = 0, idx, next_idx, last_idx;
        struct nix_mce_list *mce_list;
-       struct mce *mce, *next_mce;
        struct nix_mcast *mcast;
        struct nix_hw *nix_hw;
        struct rvu_pfvf *pfvf;
+       struct mce *mce;
        int blkaddr;
 
        /* Broadcast pkt replication is not needed for AF's VFs, hence skip */
@@ -1832,31 +1830,31 @@ static int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add)
 
        mutex_lock(&mcast->mce_lock);
 
-       err = nix_update_mce_list(mce_list, pcifunc, idx, add);
+       err = nix_update_mce_list(mce_list, pcifunc, add);
        if (err)
                goto end;
 
        /* Disable MCAM entry in NPC */
-
-       if (!mce_list->count)
+       if (!mce_list->count) {
+               rvu_npc_disable_bcast_entry(rvu, pcifunc);
                goto end;
-       count = mce_list->count;
+       }
 
        /* Dump the updated list to HW */
+       idx = pfvf->bcast_mce_idx;
+       last_idx = idx + mce_list->count - 1;
        hlist_for_each_entry(mce, &mce_list->head, node) {
-               next_idx = 0;
-               count--;
-               if (count) {
-                       next_mce = hlist_entry(mce->node.next,
-                                              struct mce, node);
-                       next_idx = next_mce->idx;
-               }
+               if (idx > last_idx)
+                       break;
+
+               next_idx = idx + 1;
                /* EOL should be set in last MCE */
-               err = nix_setup_mce(rvu, mce->idx,
-                                   NIX_AQ_INSTOP_WRITE, mce->pcifunc,
-                                   next_idx, count ? false : true);
+               err = nix_setup_mce(rvu, idx, NIX_AQ_INSTOP_WRITE,
+                                   mce->pcifunc, next_idx,
+                                   (next_idx > last_idx) ? true : false);
                if (err)
                        goto end;
+               idx++;
        }
 
 end:
index f0363d0..40e431d 100644 (file)
@@ -477,68 +477,75 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
 {
        struct npc_mcam *mcam = &rvu->hw->mcam;
        struct mcam_entry entry = { {0} };
+       struct rvu_hwinfo *hw = rvu->hw;
        struct nix_rx_action action;
-#ifdef MCAST_MCE
        struct rvu_pfvf *pfvf;
-#endif
        int blkaddr, index;
 
        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
        if (blkaddr < 0)
                return;
 
-       /* Only PF can add a bcast match entry */
-       if (pcifunc & RVU_PFVF_FUNC_MASK)
+       /* Skip LBK VFs */
+       if (is_afvf(pcifunc))
+               return;
+
+       /* If pkt replication is not supported,
+        * then only PF is allowed to add a bcast match entry.
+        */
+       if (!hw->cap.nix_rx_multicast && pcifunc & RVU_PFVF_FUNC_MASK)
                return;
-#ifdef MCAST_MCE
-       pfvf = rvu_get_pfvf(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK);
-#endif
 
+       /* Get 'pcifunc' of PF device */
+       pcifunc = pcifunc & ~RVU_PFVF_FUNC_MASK;
        index = npc_get_nixlf_mcam_index(mcam, pcifunc,
                                         nixlf, NIXLF_BCAST_ENTRY);
 
-       /* Check for L2B bit and LMAC channel
-        * NOTE: Since MKEX default profile(a reduced version intended to
-        * accommodate more capability but igoring few bits) a stap-gap
-        * approach.
-        * Since we care for L2B which by HRM NPC_PARSE_KEX_S at BIT_POS[25], So
-        * moved to BIT_POS[13], ignoring ERRCODE, ERRLEV as we'll loose out
-        * on capability features needed for CoS (/from ODP PoV) e.g: VLAN,
-        * DSCP.
-        *
-        * Reduced layout of MKEX default profile -
-        * Includes following are (i.e.CHAN, L2/3{B/M}, LA, LB, LC, LD):
-        *
-        * BIT_POS[31:28] : LD
-        * BIT_POS[27:24] : LC
-        * BIT_POS[23:20] : LB
-        * BIT_POS[19:16] : LA
-        * BIT_POS[15:12] : L3B, L3M, L2B, L2M
-        * BIT_POS[11:00] : CHAN
-        *
+       /* Match ingress channel */
+       entry.kw[0] = chan;
+       entry.kw_mask[0] = 0xfffull;
+
+       /* Match broadcast MAC address.
+        * DMAC is extracted at 0th bit of PARSE_KEX::KW1
         */
-       entry.kw[0] = BIT_ULL(13) | chan;
-       entry.kw_mask[0] = BIT_ULL(13) | 0xFFFULL;
+       entry.kw[1] = 0xffffffffffffull;
+       entry.kw_mask[1] = 0xffffffffffffull;
 
        *(u64 *)&action = 0x00;
-#ifdef MCAST_MCE
-       /* Early silicon doesn't support pkt replication,
-        * so install entry with UCAST action, so that PF
-        * receives all broadcast packets.
-        */
-       action.op = NIX_RX_ACTIONOP_MCAST;
-       action.pf_func = pcifunc;
-       action.index = pfvf->bcast_mce_idx;
-#else
-       action.op = NIX_RX_ACTIONOP_UCAST;
-       action.pf_func = pcifunc;
-#endif
+       if (!hw->cap.nix_rx_multicast) {
+               /* Early silicon doesn't support pkt replication,
+                * so install entry with UCAST action, so that PF
+                * receives all broadcast packets.
+                */
+               action.op = NIX_RX_ACTIONOP_UCAST;
+               action.pf_func = pcifunc;
+       } else {
+               pfvf = rvu_get_pfvf(rvu, pcifunc);
+               action.index = pfvf->bcast_mce_idx;
+               action.op = NIX_RX_ACTIONOP_MCAST;
+       }
 
        entry.action = *(u64 *)&action;
        npc_config_mcam_entry(rvu, mcam, blkaddr, index,
                              NIX_INTF_RX, &entry, true);
 }
 
+void rvu_npc_disable_bcast_entry(struct rvu *rvu, u16 pcifunc)
+{
+       struct npc_mcam *mcam = &rvu->hw->mcam;
+       int blkaddr, index;
+
+       blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
+       if (blkaddr < 0)
+               return;
+
+       /* Get 'pcifunc' of PF device */
+       pcifunc = pcifunc & ~RVU_PFVF_FUNC_MASK;
+
+       index = npc_get_nixlf_mcam_index(mcam, pcifunc, 0, NIXLF_BCAST_ENTRY);
+       npc_enable_mcam_entry(rvu, mcam, blkaddr, index, false);
+}
+
 void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
                                    int group, int alg_idx, int mcam_index)
 {