From: Sunil Goutham <sgout...@marvell.com>

This patch configures all 16 KPUs and iKPU (pkinds) with
the KPU parser profile defined in npc_profile.h. Each KPU
engine has a 128 entry CAM, only CAM entries which are listed
in the profile are enabled and rest are left disabled.

Also
- Memory is allocated for pkind's bitmap and PFFUNC, interface
  channel mapping.
- Added all CSR offsets of NPC HW block.

Signed-off-by: Sunil Goutham <sgout...@marvell.com>
---
 drivers/net/ethernet/marvell/octeontx2/af/Makefile |   2 +-
 drivers/net/ethernet/marvell/octeontx2/af/npc.h    | 100 ++++++++++
 drivers/net/ethernet/marvell/octeontx2/af/rvu.c    |   8 +
 drivers/net/ethernet/marvell/octeontx2/af/rvu.h    |  12 ++
 .../net/ethernet/marvell/octeontx2/af/rvu_npc.c    | 203 +++++++++++++++++++++
 .../net/ethernet/marvell/octeontx2/af/rvu_reg.h    |  61 +++++++
 6 files changed, 385 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c

diff --git a/drivers/net/ethernet/marvell/octeontx2/af/Makefile 
b/drivers/net/ethernet/marvell/octeontx2/af/Makefile
index 264cbd7..06329ac 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/Makefile
+++ b/drivers/net/ethernet/marvell/octeontx2/af/Makefile
@@ -8,4 +8,4 @@ obj-$(CONFIG_OCTEONTX2_AF) += octeontx2_af.o
 
 octeontx2_mbox-y := mbox.o
 octeontx2_af-y := cgx.o rvu.o rvu_cgx.o rvu_npa.o rvu_nix.o \
-                 rvu_reg.o
+                 rvu_reg.o rvu_npc.o
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc.h 
b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
index 3e7ec10..58d8f0b 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/npc.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
@@ -140,4 +140,104 @@ struct npc_kpu_profile {
        struct npc_kpu_profile_action *action;
 };
 
+/* NPC KPU register formats */
+struct npc_kpu_cam {
+#if defined(__BIG_ENDIAN_BITFIELD)
+       u64 rsvd_63_56     : 8;
+       u64 state          : 8;
+       u64 dp2_data       : 16;
+       u64 dp1_data       : 16;
+       u64 dp0_data       : 16;
+#else
+       u64 dp0_data       : 16;
+       u64 dp1_data       : 16;
+       u64 dp2_data       : 16;
+       u64 state          : 8;
+       u64 rsvd_63_56     : 8;
+#endif
+};
+
+struct npc_kpu_action0 {
+#if defined(__BIG_ENDIAN_BITFIELD)
+       u64 rsvd_63_57     : 7;
+       u64 byp_count      : 3;
+       u64 capture_ena    : 1;
+       u64 parse_done     : 1;
+       u64 next_state     : 8;
+       u64 rsvd_43        : 1;
+       u64 capture_lid    : 3;
+       u64 capture_ltype  : 4;
+       u64 capture_flags  : 8;
+       u64 ptr_advance    : 8;
+       u64 var_len_offset : 8;
+       u64 var_len_mask   : 8;
+       u64 var_len_right  : 1;
+       u64 var_len_shift  : 3;
+#else
+       u64 var_len_shift  : 3;
+       u64 var_len_right  : 1;
+       u64 var_len_mask   : 8;
+       u64 var_len_offset : 8;
+       u64 ptr_advance    : 8;
+       u64 capture_flags  : 8;
+       u64 capture_ltype  : 4;
+       u64 capture_lid    : 3;
+       u64 rsvd_43        : 1;
+       u64 next_state     : 8;
+       u64 parse_done     : 1;
+       u64 capture_ena    : 1;
+       u64 byp_count      : 3;
+       u64 rsvd_63_57     : 7;
+#endif
+};
+
+struct npc_kpu_action1 {
+#if defined(__BIG_ENDIAN_BITFIELD)
+       u64 rsvd_63_36     : 28;
+       u64 errlev         : 4;
+       u64 errcode        : 8;
+       u64 dp2_offset     : 8;
+       u64 dp1_offset     : 8;
+       u64 dp0_offset     : 8;
+#else
+       u64 dp0_offset     : 8;
+       u64 dp1_offset     : 8;
+       u64 dp2_offset     : 8;
+       u64 errcode        : 8;
+       u64 errlev         : 4;
+       u64 rsvd_63_36     : 28;
+#endif
+};
+
+struct npc_kpu_pkind_cpi_def {
+#if defined(__BIG_ENDIAN_BITFIELD)
+       u64 ena            : 1;
+       u64 rsvd_62_59     : 4;
+       u64 lid            : 3;
+       u64 ltype_match    : 4;
+       u64 ltype_mask     : 4;
+       u64 flags_match    : 8;
+       u64 flags_mask     : 8;
+       u64 add_offset     : 8;
+       u64 add_mask       : 8;
+       u64 rsvd_15        : 1;
+       u64 add_shift      : 3;
+       u64 rsvd_11_10     : 2;
+       u64 cpi_base       : 10;
+#else
+       u64 cpi_base       : 10;
+       u64 rsvd_11_10     : 2;
+       u64 add_shift      : 3;
+       u64 rsvd_15        : 1;
+       u64 add_mask       : 8;
+       u64 add_offset     : 8;
+       u64 flags_mask     : 8;
+       u64 flags_match    : 8;
+       u64 ltype_mask     : 4;
+       u64 ltype_match    : 4;
+       u64 lid            : 3;
+       u64 rsvd_62_59     : 4;
+       u64 ena            : 1;
+#endif
+};
 #endif /* NPC_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c 
b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
index 9594432..3cb7f76 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
@@ -180,6 +180,9 @@ int rvu_get_blkaddr(struct rvu *rvu, int blktype, u16 
pcifunc)
        bool is_pf;
 
        switch (blktype) {
+       case BLKTYPE_NPC:
+               blkaddr = BLKADDR_NPC;
+               goto exit;
        case BLKTYPE_NPA:
                blkaddr = BLKADDR_NPA;
                goto exit;
@@ -566,6 +569,7 @@ static void rvu_free_hw_resources(struct rvu *rvu)
        u64 cfg;
 
        rvu_npa_freemem(rvu);
+       rvu_npc_freemem(rvu);
        rvu_nix_freemem(rvu);
 
        /* Free block LF bitmaps */
@@ -771,6 +775,10 @@ static int rvu_setup_hw_resources(struct rvu *rvu)
                rvu_scan_block(rvu, block);
        }
 
+       err = rvu_npc_init(rvu);
+       if (err)
+               return err;
+
        err = rvu_npa_init(rvu);
        if (err)
                return err;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h 
b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
index f041d0a..e8e16a7 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
@@ -100,6 +100,11 @@ struct nix_txsch {
        u16  *pfvf_map;
 };
 
+struct npc_pkind {
+       struct rsrc_bmap rsrc;
+       u32     *pfchan_map;
+};
+
 struct nix_hw {
        struct nix_txsch txsch[NIX_TXSCH_LVL_CNT]; /* Tx schedulers */
 };
@@ -113,9 +118,12 @@ struct rvu_hwinfo {
        u8      cgx_links;
        u8      lbk_links;
        u8      sdp_links;
+       u8      npc_kpus;          /* No of parser units */
+
 
        struct rvu_block block[BLK_COUNT]; /* Block info */
        struct nix_hw    *nix0;
+       struct npc_pkind pkind;
 };
 
 struct rvu {
@@ -290,4 +298,8 @@ int rvu_mbox_handler_NIX_TXSCHQ_CFG(struct rvu *rvu,
                                    struct msg_rsp *rsp);
 int rvu_mbox_handler_NIX_STATS_RST(struct rvu *rvu, struct msg_req *req,
                                   struct msg_rsp *rsp);
+
+/* NPC APIs */
+int rvu_npc_init(struct rvu *rvu);
+void rvu_npc_freemem(struct rvu *rvu);
 #endif /* RVU_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c 
b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
new file mode 100644
index 0000000..01baf3e
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
@@ -0,0 +1,203 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Marvell OcteonTx2 RVU Admin Function driver
+ *
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "rvu_struct.h"
+#include "rvu_reg.h"
+#include "rvu.h"
+#include "npc.h"
+#include "npc_profile.h"
+
+static void npc_config_kpuaction(struct rvu *rvu, int blkaddr,
+                                struct npc_kpu_profile_action *kpuaction,
+                                int kpu, int entry, bool pkind)
+{
+       struct npc_kpu_action0 action0 = {0};
+       struct npc_kpu_action1 action1 = {0};
+       u64 reg;
+
+       action1.errlev = kpuaction->errlev;
+       action1.errcode = kpuaction->errcode;
+       action1.dp0_offset = kpuaction->dp0_offset;
+       action1.dp1_offset = kpuaction->dp1_offset;
+       action1.dp2_offset = kpuaction->dp2_offset;
+
+       if (pkind)
+               reg = NPC_AF_PKINDX_ACTION1(entry);
+       else
+               reg = NPC_AF_KPUX_ENTRYX_ACTION1(kpu, entry);
+
+       rvu_write64(rvu, blkaddr, reg, *(u64 *)&action1);
+
+       action0.byp_count = kpuaction->bypass_count;
+       action0.capture_ena = kpuaction->cap_ena;
+       action0.parse_done = kpuaction->parse_done;
+       action0.next_state = kpuaction->next_state;
+       action0.capture_lid = kpuaction->lid;
+       action0.capture_ltype = kpuaction->ltype;
+       action0.capture_flags = kpuaction->flags;
+       action0.ptr_advance = kpuaction->ptr_advance;
+       action0.var_len_offset = kpuaction->offset;
+       action0.var_len_mask = kpuaction->mask;
+       action0.var_len_right = kpuaction->right;
+       action0.var_len_shift = kpuaction->shift;
+
+       if (pkind)
+               reg = NPC_AF_PKINDX_ACTION0(entry);
+       else
+               reg = NPC_AF_KPUX_ENTRYX_ACTION0(kpu, entry);
+
+       rvu_write64(rvu, blkaddr, reg, *(u64 *)&action0);
+}
+
+static void npc_config_kpucam(struct rvu *rvu, int blkaddr,
+                             struct npc_kpu_profile_cam *kpucam,
+                             int kpu, int entry)
+{
+       struct npc_kpu_cam cam0 = {0};
+       struct npc_kpu_cam cam1 = {0};
+
+       cam1.state = kpucam->state & kpucam->state_mask;
+       cam1.dp0_data = kpucam->dp0 & kpucam->dp0_mask;
+       cam1.dp1_data = kpucam->dp1 & kpucam->dp1_mask;
+       cam1.dp2_data = kpucam->dp2 & kpucam->dp2_mask;
+
+       cam0.state = ~kpucam->state & kpucam->state_mask;
+       cam0.dp0_data = ~kpucam->dp0 & kpucam->dp0_mask;
+       cam0.dp1_data = ~kpucam->dp1 & kpucam->dp1_mask;
+       cam0.dp2_data = ~kpucam->dp2 & kpucam->dp2_mask;
+
+       rvu_write64(rvu, blkaddr,
+                   NPC_AF_KPUX_ENTRYX_CAMX(kpu, entry, 0), *(u64 *)&cam0);
+       rvu_write64(rvu, blkaddr,
+                   NPC_AF_KPUX_ENTRYX_CAMX(kpu, entry, 1), *(u64 *)&cam1);
+}
+
+static inline u64 enable_mask(int count)
+{
+       return (((count) < 64) ? ~(BIT_ULL(count) - 1) : (0x00ULL));
+}
+
+static void npc_program_kpu_profile(struct rvu *rvu, int blkaddr, int kpu,
+                                   struct npc_kpu_profile *profile)
+{
+       int entry, num_entries, max_entries;
+
+       if (profile->cam_entries != profile->action_entries) {
+               dev_err(rvu->dev,
+                       "KPU%d: CAM and action entries [%d != %d] not equal\n",
+                       kpu, profile->cam_entries, profile->action_entries);
+       }
+
+       max_entries = rvu_read64(rvu, blkaddr, NPC_AF_CONST1) & 0xFFF;
+
+       /* Program CAM match entries for previous KPU extracted data */
+       num_entries = min_t(int, profile->cam_entries, max_entries);
+       for (entry = 0; entry < num_entries; entry++)
+               npc_config_kpucam(rvu, blkaddr,
+                                 &profile->cam[entry], kpu, entry);
+
+       /* Program this KPU's actions */
+       num_entries = min_t(int, profile->action_entries, max_entries);
+       for (entry = 0; entry < num_entries; entry++)
+               npc_config_kpuaction(rvu, blkaddr, &profile->action[entry],
+                                    kpu, entry, false);
+
+       /* Enable all programmed entries */
+       num_entries = min_t(int, profile->action_entries, profile->cam_entries);
+       rvu_write64(rvu, blkaddr,
+                   NPC_AF_KPUX_ENTRY_DISX(kpu, 0), enable_mask(num_entries));
+       if (num_entries > 64) {
+               rvu_write64(rvu, blkaddr,
+                           NPC_AF_KPUX_ENTRY_DISX(kpu, 1),
+                           enable_mask(num_entries - 64));
+       }
+
+       /* Enable this KPU */
+       rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(kpu), 0x01);
+}
+
+static void npc_parser_profile_init(struct rvu *rvu, int blkaddr)
+{
+       struct rvu_hwinfo *hw = rvu->hw;
+       int num_pkinds, num_kpus, idx;
+       struct npc_pkind *pkind;
+
+       /* Get HW limits */
+       hw->npc_kpus = (rvu_read64(rvu, blkaddr, NPC_AF_CONST) >> 8) & 0x1F;
+
+       /* Disable all KPUs and their entries */
+       for (idx = 0; idx < hw->npc_kpus; idx++) {
+               rvu_write64(rvu, blkaddr,
+                           NPC_AF_KPUX_ENTRY_DISX(idx, 0), ~0ULL);
+               rvu_write64(rvu, blkaddr,
+                           NPC_AF_KPUX_ENTRY_DISX(idx, 1), ~0ULL);
+               rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(idx), 0x00);
+       }
+
+       /* First program IKPU profile i.e PKIND configs.
+        * Check HW max count to avoid configuring junk or
+        * writing to unsupported CSR addresses.
+        */
+       pkind = &hw->pkind;
+       num_pkinds = ARRAY_SIZE(ikpu_action_entries);
+       num_pkinds = min_t(int, pkind->rsrc.max, num_pkinds);
+
+       for (idx = 0; idx < num_pkinds; idx++)
+               npc_config_kpuaction(rvu, blkaddr,
+                                    &ikpu_action_entries[idx], 0, idx, true);
+
+       /* Program KPU CAM and Action profiles */
+       num_kpus = ARRAY_SIZE(npc_kpu_profiles);
+       num_kpus = min_t(int, hw->npc_kpus, num_kpus);
+
+       for (idx = 0; idx < num_kpus; idx++)
+               npc_program_kpu_profile(rvu, blkaddr,
+                                       idx, &npc_kpu_profiles[idx]);
+}
+
+int rvu_npc_init(struct rvu *rvu)
+{
+       struct npc_pkind *pkind = &rvu->hw->pkind;
+       int blkaddr, err;
+
+       blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
+       if (blkaddr < 0) {
+               dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__);
+               return -ENODEV;
+       }
+
+       /* Allocate resource bimap for pkind*/
+       pkind->rsrc.max = (rvu_read64(rvu, blkaddr,
+                                     NPC_AF_CONST1) >> 12) & 0xFF;
+       err = rvu_alloc_bitmap(&pkind->rsrc);
+       if (err)
+               return err;
+
+       /* Allocate mem for pkind to PF and channel mapping info */
+       pkind->pfchan_map = devm_kcalloc(rvu->dev, pkind->rsrc.max,
+                                        sizeof(u32), GFP_KERNEL);
+       if (!pkind->pfchan_map)
+               return -ENOMEM;
+
+       /* Configure KPU profile */
+       npc_parser_profile_init(rvu, blkaddr);
+
+       return 0;
+}
+
+void rvu_npc_freemem(struct rvu *rvu)
+{
+       struct npc_pkind *pkind = &rvu->hw->pkind;
+
+       kfree(pkind->rsrc.bmap);
+}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h 
b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h
index d871a39..09a8d61 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h
@@ -438,4 +438,65 @@
 #define NDC_AF_BLK_RST                  (0x002F0)
 #define NPC_AF_BLK_RST                  (0x00040)
 
+/* NPC */
+#define NPC_AF_CFG                     (0x00000)
+#define NPC_AF_ACTIVE_PC               (0x00010)
+#define NPC_AF_CONST                   (0x00020)
+#define NPC_AF_CONST1                  (0x00030)
+#define NPC_AF_BLK_RST                 (0x00040)
+#define NPC_AF_MCAM_SCRUB_CTL          (0x000a0)
+#define NPC_AF_KCAM_SCRUB_CTL          (0x000b0)
+#define NPC_AF_KPUX_CFG(a)             (0x00500 | (a) << 3)
+#define NPC_AF_PCK_CFG                 (0x00600)
+#define NPC_AF_PCK_DEF_OL2             (0x00610)
+#define NPC_AF_PCK_DEF_OIP4            (0x00620)
+#define NPC_AF_PCK_DEF_OIP6            (0x00630)
+#define NPC_AF_PCK_DEF_IIP4            (0x00640)
+#define NPC_AF_KEX_LDATAX_FLAGS_CFG(a) (0x00800 | (a) << 3)
+#define NPC_AF_INTFX_KEX_CFG(a)                (0x01010 | (a) << 8)
+#define NPC_AF_PKINDX_ACTION0(a)       (0x80000ull | (a) << 6)
+#define NPC_AF_PKINDX_ACTION1(a)       (0x80008ull | (a) << 6)
+#define NPC_AF_PKINDX_CPI_DEFX(a, b)   (0x80020ull | (a) << 6 | (b) << 3)
+#define NPC_AF_KPUX_ENTRYX_CAMX(a, b, c) \
+               (0x100000 | (a) << 14 | (b) << 6 | (c) << 3)
+#define NPC_AF_KPUX_ENTRYX_ACTION0(a, b) \
+               (0x100020 | (a) << 14 | (b) << 6)
+#define NPC_AF_KPUX_ENTRYX_ACTION1(a, b) \
+               (0x100028 | (a) << 14 | (b) << 6)
+#define NPC_AF_KPUX_ENTRY_DISX(a, b)   (0x180000 | (a) << 6 | (b) << 3)
+#define NPC_AF_CPIX_CFG(a)             (0x200000 | (a) << 3)
+#define NPC_AF_INTFX_LIDX_LTX_LDX_CFG(a, b, c, d) \
+               (0x900000 | (a) << 16 | (b) << 12 | (c) << 5 | (d) << 3)
+#define NPC_AF_INTFX_LDATAX_FLAGSX_CFG(a, b, c) \
+               (0x980000 | (a) << 16 | (b) << 12 | (c) << 3)
+#define NPC_AF_MCAMEX_BANKX_CAMX_INTF(a, b, c)       \
+               (0x1000000ull | (a) << 10 | (b) << 6 | (c) << 3)
+#define NPC_AF_MCAMEX_BANKX_CAMX_W0(a, b, c)         \
+               (0x1000010ull | (a) << 10 | (b) << 6 | (c) << 3)
+#define NPC_AF_MCAMEX_BANKX_CAMX_W1(a, b, c)         \
+               (0x1000020ull | (a) << 10 | (b) << 6 | (c) << 3)
+#define NPC_AF_MCAMEX_BANKX_CFG(a, b)   (0x1800000ull | (a) << 8 | (b) << 4)
+#define NPC_AF_MCAMEX_BANKX_STAT_ACT(a, b) \
+               (0x1880000 | (a) << 8 | (b) << 4)
+#define NPC_AF_MATCH_STATX(a)          (0x1880008 | (a) << 8)
+#define NPC_AF_INTFX_MISS_STAT_ACT(a)  (0x1880040 + (a) * 0x8)
+#define NPC_AF_MCAMEX_BANKX_ACTION(a, b) (0x1900000ull | (a) << 8 | (b) << 4)
+#define NPC_AF_MCAMEX_BANKX_TAG_ACT(a, b) \
+               (0x1900008 | (a) << 8 | (b) << 4)
+#define NPC_AF_INTFX_MISS_ACT(a)       (0x1a00000 | (a) << 4)
+#define NPC_AF_INTFX_MISS_TAG_ACT(a)   (0x1b00008 | (a) << 4)
+#define NPC_AF_MCAM_BANKX_HITX(a, b)   (0x1c80000 | (a) << 8 | (b) << 4)
+#define NPC_AF_LKUP_CTL                        (0x2000000)
+#define NPC_AF_LKUP_DATAX(a)           (0x2000200 | (a) << 4)
+#define NPC_AF_LKUP_RESULTX(a)         (0x2000400 | (a) << 4)
+#define NPC_AF_INTFX_STAT(a)           (0x2000800 | (a) << 4)
+#define NPC_AF_DBG_CTL                 (0x3000000)
+#define NPC_AF_DBG_STATUS              (0x3000010)
+#define NPC_AF_KPUX_DBG(a)             (0x3000020 | (a) << 8)
+#define NPC_AF_IKPU_ERR_CTL            (0x3000080)
+#define NPC_AF_KPUX_ERR_CTL(a)         (0x30000a0 | (a) << 8)
+#define NPC_AF_MCAM_DBG                        (0x3001000)
+#define NPC_AF_DBG_DATAX(a)            (0x3001400 | (a) << 4)
+#define NPC_AF_DBG_RESULTX(a)          (0x3001800 | (a) << 4)
+
 #endif /* RVU_REG_H */
-- 
2.7.4

Reply via email to