Commit 7fbb3f23 authored by Sunil Goutham's avatar Sunil Goutham Committed by David S. Miller

octeontx2-af: Support for NPC MCAM counters

NPC HW has counters which can be mapped to MCAM
entries to gather entry match statistics. This
patch adds support to allocate, free, clear and retrieve
stats of NPC MCAM counters. New mailbox messages have
been added for this. Similar to MCAM entries both
contiguous and non-contiguous counter allocation is
supported.
Signed-off-by: default avatarSunil Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 651cd265
...@@ -161,6 +161,16 @@ M(NPC_MCAM_DIS_ENTRY, 0x6004, npc_mcam_dis_entry, \ ...@@ -161,6 +161,16 @@ M(NPC_MCAM_DIS_ENTRY, 0x6004, npc_mcam_dis_entry, \
npc_mcam_ena_dis_entry_req, msg_rsp) \ npc_mcam_ena_dis_entry_req, msg_rsp) \
M(NPC_MCAM_SHIFT_ENTRY, 0x6005, npc_mcam_shift_entry, npc_mcam_shift_entry_req,\ M(NPC_MCAM_SHIFT_ENTRY, 0x6005, npc_mcam_shift_entry, npc_mcam_shift_entry_req,\
npc_mcam_shift_entry_rsp) \ npc_mcam_shift_entry_rsp) \
M(NPC_MCAM_ALLOC_COUNTER, 0x6006, npc_mcam_alloc_counter, \
npc_mcam_alloc_counter_req, \
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_CLEAR_COUNTER, 0x6009, npc_mcam_clear_counter, \
npc_mcam_oper_counter_req, msg_rsp) \
M(NPC_MCAM_COUNTER_STATS, 0x600a, npc_mcam_counter_stats, \
npc_mcam_oper_counter_req, \
npc_mcam_oper_counter_rsp) \
/* NIX mbox IDs (range 0x8000 - 0xFFFF) */ \ /* NIX mbox IDs (range 0x8000 - 0xFFFF) */ \
M(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, \ M(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, \
nix_lf_alloc_req, nix_lf_alloc_rsp) \ nix_lf_alloc_req, nix_lf_alloc_rsp) \
...@@ -635,4 +645,30 @@ struct npc_mcam_shift_entry_rsp { ...@@ -635,4 +645,30 @@ struct npc_mcam_shift_entry_rsp {
u16 failed_entry_idx; /* Index in 'curr_entry', not entry itself */ u16 failed_entry_idx; /* Index in 'curr_entry', not entry itself */
}; };
struct npc_mcam_alloc_counter_req {
struct mbox_msghdr hdr;
u8 contig; /* Contiguous counters ? */
#define NPC_MAX_NONCONTIG_COUNTERS 64
u16 count; /* Number of counters requested */
};
struct npc_mcam_alloc_counter_rsp {
struct mbox_msghdr hdr;
u16 cntr; /* Counter allocated or start index if contiguous.
* Invalid incase of non-contiguous.
*/
u16 count; /* Number of counters allocated */
u16 cntr_list[NPC_MAX_NONCONTIG_COUNTERS];
};
struct npc_mcam_oper_counter_req {
struct mbox_msghdr hdr;
u16 cntr; /* Free a counter or clear/fetch it's stats */
};
struct npc_mcam_oper_counter_rsp {
struct mbox_msghdr hdr;
u64 stat; /* valid only while fetching counter's stats */
};
#endif /* MBOX_H */ #endif /* MBOX_H */
...@@ -398,4 +398,14 @@ int rvu_mbox_handler_npc_mcam_dis_entry(struct rvu *rvu, ...@@ -398,4 +398,14 @@ int rvu_mbox_handler_npc_mcam_dis_entry(struct rvu *rvu,
int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu *rvu, int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu *rvu,
struct npc_mcam_shift_entry_req *req, struct npc_mcam_shift_entry_req *req,
struct npc_mcam_shift_entry_rsp *rsp); struct npc_mcam_shift_entry_rsp *rsp);
int rvu_mbox_handler_npc_mcam_alloc_counter(struct rvu *rvu,
struct npc_mcam_alloc_counter_req *req,
struct npc_mcam_alloc_counter_rsp *rsp);
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_counter_stats(struct rvu *rvu,
struct npc_mcam_oper_counter_req *req,
struct npc_mcam_oper_counter_rsp *rsp);
#endif /* RVU_H */ #endif /* RVU_H */
...@@ -933,6 +933,21 @@ static int npc_mcam_verify_entry(struct npc_mcam *mcam, ...@@ -933,6 +933,21 @@ static int npc_mcam_verify_entry(struct npc_mcam *mcam,
return 0; return 0;
} }
static int npc_mcam_verify_counter(struct npc_mcam *mcam,
u16 pcifunc, int cntr)
{
/* Verify if counter is valid and if it is indeed
* allocated to the requesting PFFUNC.
*/
if (cntr >= mcam->counters.max)
return NPC_MCAM_INVALID_REQ;
if (pcifunc != mcam->cntr2pfvf_map[cntr])
return NPC_MCAM_PERM_DENIED;
return 0;
}
/* Sets MCAM entry in bitmap as used. Update /* Sets MCAM entry in bitmap as used. Update
* reverse bitmap too. Should be called with * reverse bitmap too. Should be called with
* 'mcam->lock' held. * 'mcam->lock' held.
...@@ -1485,3 +1500,132 @@ int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu *rvu, ...@@ -1485,3 +1500,132 @@ int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu *rvu,
mutex_unlock(&mcam->lock); mutex_unlock(&mcam->lock);
return rc; return rc;
} }
int rvu_mbox_handler_npc_mcam_alloc_counter(struct rvu *rvu,
struct npc_mcam_alloc_counter_req *req,
struct npc_mcam_alloc_counter_rsp *rsp)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
u16 pcifunc = req->hdr.pcifunc;
u16 max_contig, cntr;
int blkaddr, index;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0)
return NPC_MCAM_INVALID_REQ;
/* If the request is from a PFFUNC with no NIXLF attached, ignore */
if (!is_nixlf_attached(rvu, pcifunc))
return NPC_MCAM_INVALID_REQ;
/* Since list of allocated counter IDs needs to be sent to requester,
* max number of non-contiguous counters per mbox msg is limited.
*/
if (!req->contig && req->count > NPC_MAX_NONCONTIG_COUNTERS)
return NPC_MCAM_INVALID_REQ;
mutex_lock(&mcam->lock);
/* Check if unused counters are available or not */
if (!rvu_rsrc_free_count(&mcam->counters)) {
mutex_unlock(&mcam->lock);
return NPC_MCAM_ALLOC_FAILED;
}
rsp->count = 0;
if (req->contig) {
/* Allocate requested number of contiguous counters, if
* unsuccessful find max contiguous entries available.
*/
index = npc_mcam_find_zero_area(mcam->counters.bmap,
mcam->counters.max, 0,
req->count, &max_contig);
rsp->count = max_contig;
rsp->cntr = index;
for (cntr = index; cntr < (index + max_contig); cntr++) {
__set_bit(cntr, mcam->counters.bmap);
mcam->cntr2pfvf_map[cntr] = pcifunc;
}
} else {
/* Allocate requested number of non-contiguous counters,
* if unsuccessful allocate as many as possible.
*/
for (cntr = 0; cntr < req->count; cntr++) {
index = rvu_alloc_rsrc(&mcam->counters);
if (index < 0)
break;
rsp->cntr_list[cntr] = index;
rsp->count++;
mcam->cntr2pfvf_map[index] = pcifunc;
}
}
mutex_unlock(&mcam->lock);
return 0;
}
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;
mutex_lock(&mcam->lock);
err = npc_mcam_verify_counter(mcam, req->hdr.pcifunc, req->cntr);
if (err) {
mutex_unlock(&mcam->lock);
return err;
}
/* 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);
return 0;
}
int rvu_mbox_handler_npc_mcam_clear_counter(struct rvu *rvu,
struct npc_mcam_oper_counter_req *req, struct msg_rsp *rsp)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
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);
mutex_unlock(&mcam->lock);
if (err)
return err;
rvu_write64(rvu, blkaddr, NPC_AF_MATCH_STATX(req->cntr), 0x00);
return 0;
}
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)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
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);
mutex_unlock(&mcam->lock);
if (err)
return err;
rsp->stat = rvu_read64(rvu, blkaddr, NPC_AF_MATCH_STATX(req->cntr));
rsp->stat &= BIT_ULL(48) - 1;
return 0;
}
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