Skip to content

Commit

Permalink
octeontx2-af: Map or unmap NPC MCAM entry and counter
Browse files Browse the repository at this point in the history
Alloc memory to save MCAM 'entry to counter' mapping and since
multiple entries can map to same counter, added counter's reference
count tracking.

Do 'entry to counter' mapping when a entry is being installed
and mbox msg sender requested to configure a counter as well.
Mapping is removed when a entry or counter is being freed or
a explicit mbox msg is received to unmap them.

Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Sunil Goutham authored and David S. Miller committed Nov 20, 2018
1 parent 7fbb3f2 commit a958dd5
Show file tree
Hide file tree
Showing 3 changed files with 192 additions and 4 deletions.
9 changes: 9 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/af/mbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ M(NPC_MCAM_ALLOC_COUNTER, 0x6006, npc_mcam_alloc_counter, \
npc_mcam_alloc_counter_rsp) \
M(NPC_MCAM_FREE_COUNTER, 0x6007, npc_mcam_free_counter, \
npc_mcam_oper_counter_req, msg_rsp) \
M(NPC_MCAM_UNMAP_COUNTER, 0x6008, npc_mcam_unmap_counter, \
npc_mcam_unmap_counter_req, msg_rsp) \
M(NPC_MCAM_CLEAR_COUNTER, 0x6009, npc_mcam_clear_counter, \
npc_mcam_oper_counter_req, msg_rsp) \
M(NPC_MCAM_COUNTER_STATS, 0x600a, npc_mcam_counter_stats, \
Expand Down Expand Up @@ -671,4 +673,11 @@ struct npc_mcam_oper_counter_rsp {
u64 stat; /* valid only while fetching counter's stats */
};

struct npc_mcam_unmap_counter_req {
struct mbox_msghdr hdr;
u16 cntr;
u16 entry; /* Entry and counter to be unmapped */
u8 all; /* Unmap all entries using this counter ? */
};

#endif /* MBOX_H */
4 changes: 4 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/af/rvu.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ struct npc_mcam {
u16 bmap_entries; /* Number of unreserved MCAM entries */
u16 bmap_fcnt; /* MCAM entries free count */
u16 *entry2pfvf_map;
u16 *entry2cntr_map;
u16 *cntr2pfvf_map;
u16 *cntr_refcnt;
u8 keysize; /* MCAM keysize 112/224/448 bits */
u8 banks; /* Number of MCAM banks */
u8 banks_per_entry;/* Number of keywords in key */
Expand Down Expand Up @@ -405,6 +407,8 @@ int rvu_mbox_handler_npc_mcam_free_counter(struct rvu *rvu,
struct npc_mcam_oper_counter_req *req, struct msg_rsp *rsp);
int rvu_mbox_handler_npc_mcam_clear_counter(struct rvu *rvu,
struct npc_mcam_oper_counter_req *req, struct msg_rsp *rsp);
int rvu_mbox_handler_npc_mcam_unmap_counter(struct rvu *rvu,
struct npc_mcam_unmap_counter_req *req, struct msg_rsp *rsp);
int rvu_mbox_handler_npc_mcam_counter_stats(struct rvu *rvu,
struct npc_mcam_oper_counter_req *req,
struct npc_mcam_oper_counter_rsp *rsp);
Expand Down
183 changes: 179 additions & 4 deletions drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

static void npc_mcam_free_all_entries(struct rvu *rvu, struct npc_mcam *mcam,
int blkaddr, u16 pcifunc);
static void npc_mcam_free_all_counters(struct rvu *rvu, struct npc_mcam *mcam,
u16 pcifunc);

void rvu_npc_set_pkind(struct rvu *rvu, int pkind, struct rvu_pfvf *pfvf)
{
Expand Down Expand Up @@ -506,6 +508,9 @@ void rvu_npc_disable_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf)
/* Disable and free all MCAM entries mapped to this 'pcifunc' */
npc_mcam_free_all_entries(rvu, mcam, blkaddr, pcifunc);

/* Free all MCAM counters mapped to this 'pcifunc' */
npc_mcam_free_all_counters(rvu, mcam, pcifunc);

mutex_unlock(&mcam->lock);

/* Disable ucast MCAM match entry of this PF/VF */
Expand Down Expand Up @@ -819,6 +824,19 @@ static int npc_mcam_rsrcs_init(struct rvu *rvu, int blkaddr)
if (!mcam->cntr2pfvf_map)
goto free_mem;

/* Alloc memory for MCAM entry to counter mapping and for tracking
* counter's reference count.
*/
mcam->entry2cntr_map = devm_kcalloc(rvu->dev, mcam->bmap_entries,
sizeof(u16), GFP_KERNEL);
if (!mcam->entry2cntr_map)
goto free_mem;

mcam->cntr_refcnt = devm_kcalloc(rvu->dev, mcam->counters.max,
sizeof(u16), GFP_KERNEL);
if (!mcam->cntr_refcnt)
goto free_mem;

mutex_init(&mcam->lock);

return 0;
Expand Down Expand Up @@ -948,6 +966,36 @@ static int npc_mcam_verify_counter(struct npc_mcam *mcam,
return 0;
}

static void npc_map_mcam_entry_and_cntr(struct rvu *rvu, struct npc_mcam *mcam,
int blkaddr, u16 entry, u16 cntr)
{
u16 index = entry & (mcam->banksize - 1);
u16 bank = npc_get_bank(mcam, entry);

/* Set mapping and increment counter's refcnt */
mcam->entry2cntr_map[entry] = cntr;
mcam->cntr_refcnt[cntr]++;
/* Enable stats */
rvu_write64(rvu, blkaddr,
NPC_AF_MCAMEX_BANKX_STAT_ACT(index, bank),
BIT_ULL(9) | cntr);
}

static void npc_unmap_mcam_entry_and_cntr(struct rvu *rvu,
struct npc_mcam *mcam,
int blkaddr, u16 entry, u16 cntr)
{
u16 index = entry & (mcam->banksize - 1);
u16 bank = npc_get_bank(mcam, entry);

/* Remove mapping and reduce counter's refcnt */
mcam->entry2cntr_map[entry] = NPC_MCAM_INVALID_MAP;
mcam->cntr_refcnt[cntr]--;
/* Disable stats */
rvu_write64(rvu, blkaddr,
NPC_AF_MCAMEX_BANKX_STAT_ACT(index, bank), 0x00);
}

/* Sets MCAM entry in bitmap as used. Update
* reverse bitmap too. Should be called with
* 'mcam->lock' held.
Expand Down Expand Up @@ -983,7 +1031,7 @@ static void npc_mcam_clear_bit(struct npc_mcam *mcam, u16 index)
static void npc_mcam_free_all_entries(struct rvu *rvu, struct npc_mcam *mcam,
int blkaddr, u16 pcifunc)
{
u16 index;
u16 index, cntr;

/* Scan all MCAM entries and free the ones mapped to 'pcifunc' */
for (index = 0; index < mcam->bmap_entries; index++) {
Expand All @@ -993,6 +1041,33 @@ static void npc_mcam_free_all_entries(struct rvu *rvu, struct npc_mcam *mcam,
npc_mcam_clear_bit(mcam, index);
/* Disable the entry */
npc_enable_mcam_entry(rvu, mcam, blkaddr, index, false);

/* Update entry2counter mapping */
cntr = mcam->entry2cntr_map[index];
if (cntr != NPC_MCAM_INVALID_MAP)
npc_unmap_mcam_entry_and_cntr(rvu, mcam,
blkaddr, index,
cntr);
}
}
}

static void npc_mcam_free_all_counters(struct rvu *rvu, struct npc_mcam *mcam,
u16 pcifunc)
{
u16 cntr;

/* Scan all MCAM counters and free the ones mapped to 'pcifunc' */
for (cntr = 0; cntr < mcam->counters.max; cntr++) {
if (mcam->cntr2pfvf_map[cntr] == pcifunc) {
mcam->cntr2pfvf_map[cntr] = NPC_MCAM_INVALID_MAP;
mcam->cntr_refcnt[cntr] = 0;
rvu_free_rsrc(&mcam->counters, cntr);
/* This API is expected to be called after freeing
* MCAM entries, which inturn will remove
* 'entry to counter' mapping.
* No need to do it again.
*/
}
}
}
Expand Down Expand Up @@ -1282,6 +1357,7 @@ static int npc_mcam_alloc_entries(struct npc_mcam *mcam, u16 pcifunc,
(rsp->entry + entry) : rsp->entry_list[entry];
npc_mcam_set_bit(mcam, index);
mcam->entry2pfvf_map[index] = pcifunc;
mcam->entry2cntr_map[index] = NPC_MCAM_INVALID_MAP;
}

/* Update available free count in mbox response */
Expand Down Expand Up @@ -1338,6 +1414,7 @@ int rvu_mbox_handler_npc_mcam_free_entry(struct rvu *rvu,
struct npc_mcam *mcam = &rvu->hw->mcam;
u16 pcifunc = req->hdr.pcifunc;
int blkaddr, rc = 0;
u16 cntr;

blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0)
Expand All @@ -1360,6 +1437,12 @@ int rvu_mbox_handler_npc_mcam_free_entry(struct rvu *rvu,
npc_mcam_clear_bit(mcam, req->entry);
npc_enable_mcam_entry(rvu, mcam, blkaddr, req->entry, false);

/* Update entry2counter mapping */
cntr = mcam->entry2cntr_map[req->entry];
if (cntr != NPC_MCAM_INVALID_MAP)
npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr,
req->entry, cntr);

goto exit;

free_all:
Expand Down Expand Up @@ -1387,6 +1470,12 @@ int rvu_mbox_handler_npc_mcam_write_entry(struct rvu *rvu,
if (rc)
goto exit;

if (req->set_cntr &&
npc_mcam_verify_counter(mcam, pcifunc, req->cntr)) {
rc = NPC_MCAM_INVALID_REQ;
goto exit;
}

if (req->intf != NIX_INTF_RX && req->intf != NIX_INTF_TX) {
rc = NPC_MCAM_INVALID_REQ;
goto exit;
Expand All @@ -1395,6 +1484,10 @@ int rvu_mbox_handler_npc_mcam_write_entry(struct rvu *rvu,
npc_config_mcam_entry(rvu, mcam, blkaddr, req->entry, req->intf,
&req->entry_data, req->enable_entry);

if (req->set_cntr)
npc_map_mcam_entry_and_cntr(rvu, mcam, blkaddr,
req->entry, req->cntr);

rc = 0;
exit:
mutex_unlock(&mcam->lock);
Expand Down Expand Up @@ -1454,8 +1547,8 @@ int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu *rvu,
struct npc_mcam *mcam = &rvu->hw->mcam;
u16 pcifunc = req->hdr.pcifunc;
u16 old_entry, new_entry;
u16 index, cntr;
int blkaddr, rc;
u16 index;

blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0)
Expand All @@ -1480,12 +1573,27 @@ int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu *rvu,
if (rc)
break;

/* new_entry should not have a counter mapped */
if (mcam->entry2cntr_map[new_entry] != NPC_MCAM_INVALID_MAP) {
rc = NPC_MCAM_PERM_DENIED;
break;
}

/* Disable the new_entry */
npc_enable_mcam_entry(rvu, mcam, blkaddr, new_entry, false);

/* Copy rule from old entry to new entry */
npc_copy_mcam_entry(rvu, mcam, blkaddr, old_entry, new_entry);

/* Copy counter mapping, if any */
cntr = mcam->entry2cntr_map[old_entry];
if (cntr != NPC_MCAM_INVALID_MAP) {
npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr,
old_entry, cntr);
npc_map_mcam_entry_and_cntr(rvu, mcam, blkaddr,
new_entry, cntr);
}

/* Enable new_entry and disable old_entry */
npc_enable_mcam_entry(rvu, mcam, blkaddr, new_entry, true);
npc_enable_mcam_entry(rvu, mcam, blkaddr, old_entry, false);
Expand Down Expand Up @@ -1569,7 +1677,12 @@ int rvu_mbox_handler_npc_mcam_free_counter(struct rvu *rvu,
struct npc_mcam_oper_counter_req *req, struct msg_rsp *rsp)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
int err;
u16 index, entry = 0;
int blkaddr, err;

blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0)
return NPC_MCAM_INVALID_REQ;

mutex_lock(&mcam->lock);
err = npc_mcam_verify_counter(mcam, req->hdr.pcifunc, req->cntr);
Expand All @@ -1581,11 +1694,73 @@ int rvu_mbox_handler_npc_mcam_free_counter(struct rvu *rvu,
/* Mark counter as free/unused */
mcam->cntr2pfvf_map[req->cntr] = NPC_MCAM_INVALID_MAP;
rvu_free_rsrc(&mcam->counters, req->cntr);
mutex_unlock(&mcam->lock);

/* Disable all MCAM entry's stats which are using this counter */
while (entry < mcam->bmap_entries) {
if (!mcam->cntr_refcnt[req->cntr])
break;

index = find_next_bit(mcam->bmap, mcam->bmap_entries, entry);
if (index >= mcam->bmap_entries)
break;
if (mcam->entry2cntr_map[index] != req->cntr)
continue;

entry = index + 1;
npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr,
index, req->cntr);
}

mutex_unlock(&mcam->lock);
return 0;
}

int rvu_mbox_handler_npc_mcam_unmap_counter(struct rvu *rvu,
struct npc_mcam_unmap_counter_req *req, struct msg_rsp *rsp)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
u16 index, entry = 0;
int blkaddr, rc;

blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0)
return NPC_MCAM_INVALID_REQ;

mutex_lock(&mcam->lock);
rc = npc_mcam_verify_counter(mcam, req->hdr.pcifunc, req->cntr);
if (rc)
goto exit;

/* Unmap the MCAM entry and counter */
if (!req->all) {
rc = npc_mcam_verify_entry(mcam, req->hdr.pcifunc, req->entry);
if (rc)
goto exit;
npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr,
req->entry, req->cntr);
goto exit;
}

/* Disable all MCAM entry's stats which are using this counter */
while (entry < mcam->bmap_entries) {
if (!mcam->cntr_refcnt[req->cntr])
break;

index = find_next_bit(mcam->bmap, mcam->bmap_entries, entry);
if (index >= mcam->bmap_entries)
break;
if (mcam->entry2cntr_map[index] != req->cntr)
continue;

entry = index + 1;
npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr,
index, req->cntr);
}
exit:
mutex_unlock(&mcam->lock);
return rc;
}

int rvu_mbox_handler_npc_mcam_clear_counter(struct rvu *rvu,
struct npc_mcam_oper_counter_req *req, struct msg_rsp *rsp)
{
Expand Down

0 comments on commit a958dd5

Please sign in to comment.