Skip to content

Commit

Permalink
octeontx2-af: Config NPC KPU engines with parser profile
Browse files Browse the repository at this point in the history
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 <sgoutham@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Sunil Goutham authored and David S. Miller committed Oct 23, 2018
1 parent 21e6699 commit 23923ea
Show file tree
Hide file tree
Showing 6 changed files with 385 additions and 1 deletion.
2 changes: 1 addition & 1 deletion drivers/net/ethernet/marvell/octeontx2/af/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
100 changes: 100 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/af/npc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
8 changes: 8 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/af/rvu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down
12 changes: 12 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/af/rvu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
};
Expand All @@ -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 {
Expand Down Expand Up @@ -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 */
203 changes: 203 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
Original file line number Diff line number Diff line change
@@ -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);
}
Loading

0 comments on commit 23923ea

Please sign in to comment.