Commit 561e8752 authored by Sunil Goutham's avatar Sunil Goutham Committed by David S. Miller

octeontx2-af: Enable broadcast packet replication

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: default avatarSunil Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5d9b976d
...@@ -64,6 +64,7 @@ static void rvu_setup_hw_capabilities(struct rvu *rvu) ...@@ -64,6 +64,7 @@ static void rvu_setup_hw_capabilities(struct rvu *rvu)
hw->cap.nix_fixed_txschq_mapping = false; hw->cap.nix_fixed_txschq_mapping = false;
hw->cap.nix_shaping = true; hw->cap.nix_shaping = true;
hw->cap.nix_tx_link_bp = true; hw->cap.nix_tx_link_bp = true;
hw->cap.nix_rx_multicast = true;
if (is_rvu_96xx_B0(rvu)) { if (is_rvu_96xx_B0(rvu)) {
hw->cap.nix_fixed_txschq_mapping = true; hw->cap.nix_fixed_txschq_mapping = true;
...@@ -72,6 +73,8 @@ static void rvu_setup_hw_capabilities(struct rvu *rvu) ...@@ -72,6 +73,8 @@ static void rvu_setup_hw_capabilities(struct rvu *rvu)
hw->cap.nix_txsch_per_sdp_lmac = 76; hw->cap.nix_txsch_per_sdp_lmac = 76;
hw->cap.nix_shaping = false; hw->cap.nix_shaping = false;
hw->cap.nix_tx_link_bp = false; hw->cap.nix_tx_link_bp = false;
if (is_rvu_96xx_A0(rvu))
hw->cap.nix_rx_multicast = false;
} }
} }
......
...@@ -235,6 +235,7 @@ struct hw_cap { ...@@ -235,6 +235,7 @@ struct hw_cap {
bool nix_fixed_txschq_mapping; /* Schq mapping fixed or flexible */ bool nix_fixed_txschq_mapping; /* Schq mapping fixed or flexible */
bool nix_shaping; /* Is shaping and coloring supported */ bool nix_shaping; /* Is shaping and coloring supported */
bool nix_tx_link_bp; /* Can link backpressure TL queues ? */ bool nix_tx_link_bp; /* Can link backpressure TL queues ? */
bool nix_rx_multicast; /* Rx packet replication support */
}; };
struct rvu_hwinfo { struct rvu_hwinfo {
...@@ -441,6 +442,7 @@ void rvu_npc_disable_promisc_entry(struct rvu *rvu, u16 pcifunc, int nixlf); ...@@ -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_enable_promisc_entry(struct rvu *rvu, u16 pcifunc, int nixlf);
void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc, void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
int nixlf, u64 chan); 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); 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_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_disable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
......
...@@ -64,7 +64,6 @@ enum nix_makr_fmt_indexes { ...@@ -64,7 +64,6 @@ enum nix_makr_fmt_indexes {
struct mce { struct mce {
struct hlist_node node; struct hlist_node node;
u16 idx;
u16 pcifunc; u16 pcifunc;
}; };
...@@ -1754,7 +1753,7 @@ static int nix_setup_mce(struct rvu *rvu, int mce, u8 op, ...@@ -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, 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; struct mce *mce, *tail = NULL;
bool delete = false; bool delete = false;
...@@ -1783,7 +1782,6 @@ static int nix_update_mce_list(struct nix_mce_list *mce_list, ...@@ -1783,7 +1782,6 @@ static int nix_update_mce_list(struct nix_mce_list *mce_list,
mce = kzalloc(sizeof(*mce), GFP_KERNEL); mce = kzalloc(sizeof(*mce), GFP_KERNEL);
if (!mce) if (!mce)
return -ENOMEM; return -ENOMEM;
mce->idx = idx;
mce->pcifunc = pcifunc; mce->pcifunc = pcifunc;
if (!tail) if (!tail)
hlist_add_head(&mce->node, &mce_list->head); hlist_add_head(&mce->node, &mce_list->head);
...@@ -1795,12 +1793,12 @@ static int nix_update_mce_list(struct nix_mce_list *mce_list, ...@@ -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) 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 nix_mce_list *mce_list;
struct mce *mce, *next_mce;
struct nix_mcast *mcast; struct nix_mcast *mcast;
struct nix_hw *nix_hw; struct nix_hw *nix_hw;
struct rvu_pfvf *pfvf; struct rvu_pfvf *pfvf;
struct mce *mce;
int blkaddr; int blkaddr;
/* Broadcast pkt replication is not needed for AF's VFs, hence skip */ /* 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) ...@@ -1832,31 +1830,31 @@ static int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add)
mutex_lock(&mcast->mce_lock); 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) if (err)
goto end; goto end;
/* Disable MCAM entry in NPC */ /* Disable MCAM entry in NPC */
if (!mce_list->count) {
if (!mce_list->count) rvu_npc_disable_bcast_entry(rvu, pcifunc);
goto end; goto end;
count = mce_list->count; }
/* Dump the updated list to HW */ /* 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) { hlist_for_each_entry(mce, &mce_list->head, node) {
next_idx = 0; if (idx > last_idx)
count--; break;
if (count) {
next_mce = hlist_entry(mce->node.next, next_idx = idx + 1;
struct mce, node);
next_idx = next_mce->idx;
}
/* EOL should be set in last MCE */ /* EOL should be set in last MCE */
err = nix_setup_mce(rvu, mce->idx, err = nix_setup_mce(rvu, idx, NIX_AQ_INSTOP_WRITE,
NIX_AQ_INSTOP_WRITE, mce->pcifunc, mce->pcifunc, next_idx,
next_idx, count ? false : true); (next_idx > last_idx) ? true : false);
if (err) if (err)
goto end; goto end;
idx++;
} }
end: end:
......
...@@ -477,68 +477,75 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc, ...@@ -477,68 +477,75 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
{ {
struct npc_mcam *mcam = &rvu->hw->mcam; struct npc_mcam *mcam = &rvu->hw->mcam;
struct mcam_entry entry = { {0} }; struct mcam_entry entry = { {0} };
struct rvu_hwinfo *hw = rvu->hw;
struct nix_rx_action action; struct nix_rx_action action;
#ifdef MCAST_MCE
struct rvu_pfvf *pfvf; struct rvu_pfvf *pfvf;
#endif
int blkaddr, index; int blkaddr, index;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0) if (blkaddr < 0)
return; return;
/* Only PF can add a bcast match entry */ /* Skip LBK VFs */
if (pcifunc & RVU_PFVF_FUNC_MASK) 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; 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, index = npc_get_nixlf_mcam_index(mcam, pcifunc,
nixlf, NIXLF_BCAST_ENTRY); nixlf, NIXLF_BCAST_ENTRY);
/* Check for L2B bit and LMAC channel /* Match ingress channel */
* NOTE: Since MKEX default profile(a reduced version intended to entry.kw[0] = chan;
* accommodate more capability but igoring few bits) a stap-gap entry.kw_mask[0] = 0xfffull;
* approach.
* Since we care for L2B which by HRM NPC_PARSE_KEX_S at BIT_POS[25], So /* Match broadcast MAC address.
* moved to BIT_POS[13], ignoring ERRCODE, ERRLEV as we'll loose out * DMAC is extracted at 0th bit of PARSE_KEX::KW1
* 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
*
*/ */
entry.kw[0] = BIT_ULL(13) | chan; entry.kw[1] = 0xffffffffffffull;
entry.kw_mask[0] = BIT_ULL(13) | 0xFFFULL; entry.kw_mask[1] = 0xffffffffffffull;
*(u64 *)&action = 0x00; *(u64 *)&action = 0x00;
#ifdef MCAST_MCE if (!hw->cap.nix_rx_multicast) {
/* Early silicon doesn't support pkt replication, /* Early silicon doesn't support pkt replication,
* so install entry with UCAST action, so that PF * so install entry with UCAST action, so that PF
* receives all broadcast packets. * 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.op = NIX_RX_ACTIONOP_UCAST;
action.pf_func = pcifunc; action.pf_func = pcifunc;
#endif } else {
pfvf = rvu_get_pfvf(rvu, pcifunc);
action.index = pfvf->bcast_mce_idx;
action.op = NIX_RX_ACTIONOP_MCAST;
}
entry.action = *(u64 *)&action; entry.action = *(u64 *)&action;
npc_config_mcam_entry(rvu, mcam, blkaddr, index, npc_config_mcam_entry(rvu, mcam, blkaddr, index,
NIX_INTF_RX, &entry, true); 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, void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
int group, int alg_idx, int mcam_index) int group, int alg_idx, int mcam_index)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment