Commit 23923ea4 authored by Sunil Goutham's avatar Sunil Goutham Committed by David S. Miller

octeontx2-af: Config NPC KPU engines with parser profile

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: default avatarSunil Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 21e6699e
...@@ -8,4 +8,4 @@ obj-$(CONFIG_OCTEONTX2_AF) += octeontx2_af.o ...@@ -8,4 +8,4 @@ obj-$(CONFIG_OCTEONTX2_AF) += octeontx2_af.o
octeontx2_mbox-y := mbox.o octeontx2_mbox-y := mbox.o
octeontx2_af-y := cgx.o rvu.o rvu_cgx.o rvu_npa.o rvu_nix.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
...@@ -140,4 +140,104 @@ struct npc_kpu_profile { ...@@ -140,4 +140,104 @@ struct npc_kpu_profile {
struct npc_kpu_profile_action *action; 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 */ #endif /* NPC_H */
...@@ -180,6 +180,9 @@ int rvu_get_blkaddr(struct rvu *rvu, int blktype, u16 pcifunc) ...@@ -180,6 +180,9 @@ int rvu_get_blkaddr(struct rvu *rvu, int blktype, u16 pcifunc)
bool is_pf; bool is_pf;
switch (blktype) { switch (blktype) {
case BLKTYPE_NPC:
blkaddr = BLKADDR_NPC;
goto exit;
case BLKTYPE_NPA: case BLKTYPE_NPA:
blkaddr = BLKADDR_NPA; blkaddr = BLKADDR_NPA;
goto exit; goto exit;
...@@ -566,6 +569,7 @@ static void rvu_free_hw_resources(struct rvu *rvu) ...@@ -566,6 +569,7 @@ static void rvu_free_hw_resources(struct rvu *rvu)
u64 cfg; u64 cfg;
rvu_npa_freemem(rvu); rvu_npa_freemem(rvu);
rvu_npc_freemem(rvu);
rvu_nix_freemem(rvu); rvu_nix_freemem(rvu);
/* Free block LF bitmaps */ /* Free block LF bitmaps */
...@@ -771,6 +775,10 @@ static int rvu_setup_hw_resources(struct rvu *rvu) ...@@ -771,6 +775,10 @@ static int rvu_setup_hw_resources(struct rvu *rvu)
rvu_scan_block(rvu, block); rvu_scan_block(rvu, block);
} }
err = rvu_npc_init(rvu);
if (err)
return err;
err = rvu_npa_init(rvu); err = rvu_npa_init(rvu);
if (err) if (err)
return err; return err;
......
...@@ -100,6 +100,11 @@ struct nix_txsch { ...@@ -100,6 +100,11 @@ struct nix_txsch {
u16 *pfvf_map; u16 *pfvf_map;
}; };
struct npc_pkind {
struct rsrc_bmap rsrc;
u32 *pfchan_map;
};
struct nix_hw { struct nix_hw {
struct nix_txsch txsch[NIX_TXSCH_LVL_CNT]; /* Tx schedulers */ struct nix_txsch txsch[NIX_TXSCH_LVL_CNT]; /* Tx schedulers */
}; };
...@@ -113,9 +118,12 @@ struct rvu_hwinfo { ...@@ -113,9 +118,12 @@ struct rvu_hwinfo {
u8 cgx_links; u8 cgx_links;
u8 lbk_links; u8 lbk_links;
u8 sdp_links; u8 sdp_links;
u8 npc_kpus; /* No of parser units */
struct rvu_block block[BLK_COUNT]; /* Block info */ struct rvu_block block[BLK_COUNT]; /* Block info */
struct nix_hw *nix0; struct nix_hw *nix0;
struct npc_pkind pkind;
}; };
struct rvu { struct rvu {
...@@ -290,4 +298,8 @@ int rvu_mbox_handler_NIX_TXSCHQ_CFG(struct rvu *rvu, ...@@ -290,4 +298,8 @@ int rvu_mbox_handler_NIX_TXSCHQ_CFG(struct rvu *rvu,
struct msg_rsp *rsp); struct msg_rsp *rsp);
int rvu_mbox_handler_NIX_STATS_RST(struct rvu *rvu, struct msg_req *req, int rvu_mbox_handler_NIX_STATS_RST(struct rvu *rvu, struct msg_req *req,
struct msg_rsp *rsp); struct msg_rsp *rsp);
/* NPC APIs */
int rvu_npc_init(struct rvu *rvu);
void rvu_npc_freemem(struct rvu *rvu);
#endif /* RVU_H */ #endif /* RVU_H */
// 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);
}
...@@ -438,4 +438,65 @@ ...@@ -438,4 +438,65 @@
#define NDC_AF_BLK_RST (0x002F0) #define NDC_AF_BLK_RST (0x002F0)
#define NPC_AF_BLK_RST (0x00040) #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 */ #endif /* RVU_REG_H */
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