octeontx2-af: Support for NPC MCAM counters
authorSunil Goutham <sgoutham@marvell.com>
Mon, 19 Nov 2018 10:47:29 +0000 (16:17 +0530)
committerDavid S. Miller <davem@davemloft.net>
Tue, 20 Nov 2018 01:56:07 +0000 (17:56 -0800)
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: Sunil Goutham <sgoutham@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/octeontx2/af/mbox.h
drivers/net/ethernet/marvell/octeontx2/af/rvu.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c

index f0b1a90317a6378746eee5bba724ffe8c1e7c0c0..0ab74ee77eb312040bbd2c72309c3d43d885121b 100644 (file)
@@ -161,6 +161,16 @@ M(NPC_MCAM_DIS_ENTRY,   0x6004, npc_mcam_dis_entry,                        \
                                 npc_mcam_ena_dis_entry_req, msg_rsp)   \
 M(NPC_MCAM_SHIFT_ENTRY, 0x6005, npc_mcam_shift_entry, npc_mcam_shift_entry_req,\
                                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) */                             \
 M(NIX_LF_ALLOC,                0x8000, nix_lf_alloc,                           \
                                 nix_lf_alloc_req, nix_lf_alloc_rsp)    \
@@ -635,4 +645,30 @@ struct npc_mcam_shift_entry_rsp {
        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 */
index cfe49541b6e247892fdc21e7c10594782d28e29a..898b59c4a9cfbee0d8fd1331add26e42e9554efb 100644 (file)
@@ -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,
                                          struct npc_mcam_shift_entry_req *req,
                                          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 */
index 801c37a9a46d26156a82f967591ddf228b453ffe..1ec508e416532cbac448ebd3a5119c0b6f5f2a5b 100644 (file)
@@ -933,6 +933,21 @@ static int npc_mcam_verify_entry(struct npc_mcam *mcam,
        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
  * reverse bitmap too. Should be called with
  * 'mcam->lock' held.
@@ -1485,3 +1500,132 @@ int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu *rvu,
        mutex_unlock(&mcam->lock);
        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;
+}