diff --git a/drivers/net/ethernet/marvell/octeontx2/af/Makefile b/drivers/net/ethernet/marvell/octeontx2/af/Makefile index 264cbd7bc1eac2164921656242f02182bdd38168..06329acf9c2c9794679f9a183ac062510cf699bc 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 3e7ec10cf4ffb27bf6450ff318bf8ecf4241e694..58d8f0b306467f55d9298ff30ead73a25a671e24 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 3bf007aa472575d856239be05b8838f02e246a8d..dc28fa2b9481c9c364c9625e950c3ac43d4f545e 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 f041d0a26ad5e9ae1c565ce406f2cdd64eda0ce2..e8e16a71fbed36ef1f6fea024282a35de8f2dee3 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 0000000000000000000000000000000000000000..01baf3e0b3e109f309ded822c6228b4effd68ccd --- /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 +#include + +#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 d871a394e72b5822da9e56f72fe0877ab622fd2f..09a8d61f3144b1310f32ce6982eb95fbc9a72f54 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 */