mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
octeontx2-af: Update bcast list upon NIXLF alloc/free
Upon NIXLF ALLOC/FREE, add or remove corresponding PF_FUNC from the broadcast packet replication list of the CGX LMAC mapped RVU PF. Signed-off-by: Sunil Goutham <sgoutham@marvell.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
52d3d327a2
commit
4b05528ebf
1 changed files with 133 additions and 0 deletions
|
@ -16,6 +16,8 @@
|
|||
#include "rvu.h"
|
||||
#include "cgx.h"
|
||||
|
||||
static int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add);
|
||||
|
||||
enum mc_tbl_sz {
|
||||
MC_TBL_SZ_256,
|
||||
MC_TBL_SZ_512,
|
||||
|
@ -108,6 +110,7 @@ static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf)
|
|||
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
|
||||
u8 cgx_id, lmac_id;
|
||||
int pkind, pf;
|
||||
int err;
|
||||
|
||||
pf = rvu_get_pf(pcifunc);
|
||||
if (!is_pf_cgxmapped(rvu, pf) && type != NIX_INTF_TYPE_LBK)
|
||||
|
@ -130,9 +133,30 @@ static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf)
|
|||
case NIX_INTF_TYPE_LBK:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Add this PF_FUNC to bcast pkt replication list */
|
||||
err = nix_update_bcast_mce_list(rvu, pcifunc, true);
|
||||
if (err) {
|
||||
dev_err(rvu->dev,
|
||||
"Bcast list, failed to enable PF_FUNC 0x%x\n",
|
||||
pcifunc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nix_interface_deinit(struct rvu *rvu, u16 pcifunc, u8 nixlf)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Remove this PF_FUNC from bcast pkt replication list */
|
||||
err = nix_update_bcast_mce_list(rvu, pcifunc, false);
|
||||
if (err) {
|
||||
dev_err(rvu->dev,
|
||||
"Bcast list, failed to disable PF_FUNC 0x%x\n",
|
||||
pcifunc);
|
||||
}
|
||||
}
|
||||
|
||||
static void nix_setup_lso_tso_l3(struct rvu *rvu, int blkaddr,
|
||||
u64 format, bool v4, u64 *fidx)
|
||||
{
|
||||
|
@ -786,6 +810,8 @@ int rvu_mbox_handler_NIX_LF_FREE(struct rvu *rvu, struct msg_req *req,
|
|||
if (nixlf < 0)
|
||||
return NIX_AF_ERR_AF_LF_INVALID;
|
||||
|
||||
nix_interface_deinit(rvu, pcifunc, nixlf);
|
||||
|
||||
/* Reset this NIX LF */
|
||||
err = rvu_lf_reset(rvu, block, nixlf);
|
||||
if (err) {
|
||||
|
@ -1147,6 +1173,113 @@ static int nix_setup_mce(struct rvu *rvu, int mce, u8 op,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int nix_update_mce_list(struct nix_mce_list *mce_list,
|
||||
u16 pcifunc, int idx, bool add)
|
||||
{
|
||||
struct mce *mce, *tail = NULL;
|
||||
bool delete = false;
|
||||
|
||||
/* Scan through the current list */
|
||||
hlist_for_each_entry(mce, &mce_list->head, node) {
|
||||
/* If already exists, then delete */
|
||||
if (mce->pcifunc == pcifunc && !add) {
|
||||
delete = true;
|
||||
break;
|
||||
}
|
||||
tail = mce;
|
||||
}
|
||||
|
||||
if (delete) {
|
||||
hlist_del(&mce->node);
|
||||
kfree(mce);
|
||||
mce_list->count--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!add)
|
||||
return 0;
|
||||
|
||||
/* Add a new one to the list, at the tail */
|
||||
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);
|
||||
else
|
||||
hlist_add_behind(&mce->node, &tail->node);
|
||||
mce_list->count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add)
|
||||
{
|
||||
int err = 0, idx, next_idx, count;
|
||||
struct nix_mce_list *mce_list;
|
||||
struct mce *mce, *next_mce;
|
||||
struct nix_mcast *mcast;
|
||||
struct nix_hw *nix_hw;
|
||||
struct rvu_pfvf *pfvf;
|
||||
int blkaddr;
|
||||
|
||||
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
|
||||
if (blkaddr < 0)
|
||||
return 0;
|
||||
|
||||
nix_hw = get_nix_hw(rvu->hw, blkaddr);
|
||||
if (!nix_hw)
|
||||
return 0;
|
||||
|
||||
mcast = &nix_hw->mcast;
|
||||
|
||||
/* Get this PF/VF func's MCE index */
|
||||
pfvf = rvu_get_pfvf(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK);
|
||||
idx = pfvf->bcast_mce_idx + (pcifunc & RVU_PFVF_FUNC_MASK);
|
||||
|
||||
mce_list = &pfvf->bcast_mce_list;
|
||||
if (idx > (pfvf->bcast_mce_idx + mce_list->max)) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Idx %d > max MCE idx %d, for PF%d bcast list\n",
|
||||
__func__, idx, mce_list->max,
|
||||
pcifunc >> RVU_PFVF_PF_SHIFT);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock(&mcast->mce_lock);
|
||||
|
||||
err = nix_update_mce_list(mce_list, pcifunc, idx, add);
|
||||
if (err)
|
||||
goto end;
|
||||
|
||||
/* Disable MCAM entry in NPC */
|
||||
|
||||
if (!mce_list->count)
|
||||
goto end;
|
||||
count = mce_list->count;
|
||||
|
||||
/* Dump the updated list to HW */
|
||||
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;
|
||||
}
|
||||
/* 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);
|
||||
if (err)
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
spin_unlock(&mcast->mce_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nix_setup_bcast_tables(struct rvu *rvu, struct nix_hw *nix_hw)
|
||||
{
|
||||
struct nix_mcast *mcast = &nix_hw->mcast;
|
||||
|
|
Loading…
Reference in a new issue