Commit cfb2cffa authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'support-for-octeontx2-98xx-silcion'

Subbaraya Sundeep says:

====================
Support for OcteonTx2 98xx silicon

OcteonTx2 series of silicons have multiple variants, the
98xx variant has two network interface controllers (NIX blocks)
each of which supports upto 100Gbps. Similarly 98xx supports
two crypto blocks (CPT) to double the crypto performance.
The current RVU drivers support a single NIX and
CPT blocks, this patchset adds support for multiple
blocks of same type to be active at the same time.

Also the number of serdes controllers (CGX) have increased
from three to five on 98xx. Each of the CGX block supports
upto 4 physical interfaces depending on the serdes mode ie
upto 20 physical interfaces. At a time each CGX block can
be mapped to a single NIX. The HW configuration to map CGX
and NIX blocks is done by firmware.

NPC has two new interfaces added NIX1_RX and NIX1_TX
similar to NIX0 interfaces. Also MCAM entries is increased
from 4k to 16k. To support the 16k entries extended set
is added in hardware which are at completely different
register offsets. Fortunately new constant registers
can be read to figure out the extended set is present
or not.

This patch set modifies existing AF and PF drivers
in below order to support 98xx:
- Prepare for supporting multiple blocks of same type.
  Functions which operate with block type to get or set
  resources count are modified to operate with block address
- Manage allocating and freeing LFs from new NIX1 and CPT1 RVU blocks.
- NIX block specific initialization and teardown for NIX1
- Based on the mapping set by Firmware, assign the NIX block
  LFs to a PF/VF.
- Multicast entries context is setup for NIX1 along with NIX0
- NPC changes to support extended set of MCAM entries, counters
  and NIX1 interfaces to NPC.
- All the mailbox changes required for the new blocks in 98xx.
- Since there are more CGX links in 98xx the hardcoded LBK
  link value needed by netdev drivers is not sufficient any
  more. Hence AF consumers need to get the number of all links
  and calculate the LBK link.
- Debugfs changes to display NIX1 contexts similar to NIX0
- Debugfs change to display mapping between CGX, NIX and PF.
====================

Link: https://lore.kernel.org/r/1603948549-781-1-git-send-email-sundeep.lkml@gmail.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 1a025560 e2fb3730
......@@ -145,6 +145,16 @@ int cgx_get_cgxid(void *cgxd)
return cgx->cgx_id;
}
u8 cgx_lmac_get_p2x(int cgx_id, int lmac_id)
{
struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
u64 cfg;
cfg = cgx_read(cgx_dev, lmac_id, CGXX_CMRX_CFG);
return (cfg & CMR_P2X_SEL_MASK) >> CMR_P2X_SEL_SHIFT;
}
/* Ensure the required lock for event queue(where asynchronous events are
* posted) is acquired before calling this API. Else an asynchronous event(with
* latest link status) can reach the destination before this function returns
......@@ -814,8 +824,7 @@ static int cgx_lmac_verify_fwi_version(struct cgx *cgx)
minor_ver = FIELD_GET(RESP_MINOR_VER, resp);
dev_dbg(dev, "Firmware command interface version = %d.%d\n",
major_ver, minor_ver);
if (major_ver != CGX_FIRMWARE_MAJOR_VER ||
minor_ver != CGX_FIRMWARE_MINOR_VER)
if (major_ver != CGX_FIRMWARE_MAJOR_VER)
return -EIO;
else
return 0;
......
......@@ -27,6 +27,10 @@
/* Registers */
#define CGXX_CMRX_CFG 0x00
#define CMR_P2X_SEL_MASK GENMASK_ULL(61, 59)
#define CMR_P2X_SEL_SHIFT 59ULL
#define CMR_P2X_SEL_NIX0 1ULL
#define CMR_P2X_SEL_NIX1 2ULL
#define CMR_EN BIT_ULL(55)
#define DATA_PKT_TX_EN BIT_ULL(53)
#define DATA_PKT_RX_EN BIT_ULL(54)
......@@ -142,5 +146,6 @@ int cgx_lmac_get_pause_frm(void *cgxd, int lmac_id,
int cgx_lmac_set_pause_frm(void *cgxd, int lmac_id,
u8 tx_pause, u8 rx_pause);
void cgx_lmac_ptp_config(void *cgxd, int lmac_id, bool enable);
u8 cgx_lmac_get_p2x(int cgx_id, int lmac_id);
#endif /* CGX_H */
......@@ -174,8 +174,12 @@ enum nix_scheduler {
#define NPC_MCAM_KEY_X2 1
#define NPC_MCAM_KEY_X4 2
#define NIX_INTF_RX 0
#define NIX_INTF_TX 1
#define NIX_INTFX_RX(a) (0x0ull | (a) << 1)
#define NIX_INTFX_TX(a) (0x1ull | (a) << 1)
/* Default interfaces are NIX0_RX and NIX0_TX */
#define NIX_INTF_RX NIX_INTFX_RX(0)
#define NIX_INTF_TX NIX_INTFX_TX(0)
#define NIX_INTF_TYPE_CGX 0
#define NIX_INTF_TYPE_LBK 1
......@@ -206,6 +210,8 @@ enum ndc_idx_e {
NIX0_RX = 0x0,
NIX0_TX = 0x1,
NPA0_U = 0x2,
NIX1_RX = 0x4,
NIX1_TX = 0x5,
};
enum ndc_ctype_e {
......
......@@ -86,7 +86,7 @@ struct mbox_msghdr {
#define OTX2_MBOX_REQ_SIG (0xdead)
#define OTX2_MBOX_RSP_SIG (0xbeef)
u16 sig; /* Signature, for validating corrupted msgs */
#define OTX2_MBOX_VERSION (0x0001)
#define OTX2_MBOX_VERSION (0x0007)
u16 ver; /* Version of msg's structure for this ID */
u16 next_msgoff; /* Offset of next msg within mailbox region */
int rc; /* Msg process'ed response code */
......@@ -271,6 +271,17 @@ struct ready_msg_rsp {
* or to detach partial of a cetain resource type.
* Rest of the fields specify how many of what type to
* be attached.
* To request LFs from two blocks of same type this mailbox
* can be sent twice as below:
* struct rsrc_attach *attach;
* .. Allocate memory for message ..
* attach->cptlfs = 3; <3 LFs from CPT0>
* .. Send message ..
* .. Allocate memory for message ..
* attach->modify = 1;
* attach->cpt_blkaddr = BLKADDR_CPT1;
* attach->cptlfs = 2; <2 LFs from CPT1>
* .. Send message ..
*/
struct rsrc_attach {
struct mbox_msghdr hdr;
......@@ -281,6 +292,7 @@ struct rsrc_attach {
u16 ssow;
u16 timlfs;
u16 cptlfs;
int cpt_blkaddr; /* BLKADDR_CPT0/BLKADDR_CPT1 or 0 for BLKADDR_CPT0 */
};
/* Structure for relinquishing resources.
......@@ -314,6 +326,8 @@ struct msix_offset_rsp {
u16 ssow_msixoff[MAX_RVU_BLKLF_CNT];
u16 timlf_msixoff[MAX_RVU_BLKLF_CNT];
u16 cptlf_msixoff[MAX_RVU_BLKLF_CNT];
u8 cpt1_lfs;
u16 cpt1_lf_msixoff[MAX_RVU_BLKLF_CNT];
};
struct get_hw_cap_rsp {
......@@ -491,6 +505,9 @@ struct nix_lf_alloc_rsp {
u8 lf_tx_stats; /* NIX_AF_CONST1::LF_TX_STATS */
u16 cints; /* NIX_AF_CONST2::CINTS */
u16 qints; /* NIX_AF_CONST2::QINTS */
u8 cgx_links; /* No. of CGX links present in HW */
u8 lbk_links; /* No. of LBK links present in HW */
u8 sdp_links; /* No. of SDP links present in HW */
};
/* NIX AQ enqueue msg */
......
......@@ -13380,7 +13380,7 @@ static const struct npc_lt_def_cfg npc_lt_defaults = {
},
};
static const struct npc_mcam_kex npc_mkex_default = {
static struct npc_mcam_kex npc_mkex_default = {
.mkex_sign = MKEX_SIGN,
.name = "default",
.kpu_version = NPC_KPU_PROFILE_VER,
......
......@@ -66,6 +66,7 @@ static void rvu_setup_hw_capabilities(struct rvu *rvu)
hw->cap.nix_shaping = true;
hw->cap.nix_tx_link_bp = true;
hw->cap.nix_rx_multicast = true;
hw->rvu = rvu;
if (is_rvu_96xx_B0(rvu)) {
hw->cap.nix_fixed_txschq_mapping = true;
......@@ -210,6 +211,9 @@ int rvu_get_lf(struct rvu *rvu, struct rvu_block *block, u16 pcifunc, u16 slot)
* multiple blocks of same type.
*
* @pcifunc has to be zero when no LF is yet attached.
*
* For a pcifunc if LFs are attached from multiple blocks of same type, then
* return blkaddr of first encountered block.
*/
int rvu_get_blkaddr(struct rvu *rvu, int blktype, u16 pcifunc)
{
......@@ -258,20 +262,39 @@ int rvu_get_blkaddr(struct rvu *rvu, int blktype, u16 pcifunc)
devnum = rvu_get_pf(pcifunc);
}
/* Check if the 'pcifunc' has a NIX LF from 'BLKADDR_NIX0' */
/* Check if the 'pcifunc' has a NIX LF from 'BLKADDR_NIX0' or
* 'BLKADDR_NIX1'.
*/
if (blktype == BLKTYPE_NIX) {
reg = is_pf ? RVU_PRIV_PFX_NIX0_CFG : RVU_PRIV_HWVFX_NIX0_CFG;
reg = is_pf ? RVU_PRIV_PFX_NIXX_CFG(0) :
RVU_PRIV_HWVFX_NIXX_CFG(0);
cfg = rvu_read64(rvu, BLKADDR_RVUM, reg | (devnum << 16));
if (cfg)
if (cfg) {
blkaddr = BLKADDR_NIX0;
goto exit;
}
reg = is_pf ? RVU_PRIV_PFX_NIXX_CFG(1) :
RVU_PRIV_HWVFX_NIXX_CFG(1);
cfg = rvu_read64(rvu, BLKADDR_RVUM, reg | (devnum << 16));
if (cfg)
blkaddr = BLKADDR_NIX1;
}
/* Check if the 'pcifunc' has a CPT LF from 'BLKADDR_CPT0' */
if (blktype == BLKTYPE_CPT) {
reg = is_pf ? RVU_PRIV_PFX_CPT0_CFG : RVU_PRIV_HWVFX_CPT0_CFG;
reg = is_pf ? RVU_PRIV_PFX_CPTX_CFG(0) :
RVU_PRIV_HWVFX_CPTX_CFG(0);
cfg = rvu_read64(rvu, BLKADDR_RVUM, reg | (devnum << 16));
if (cfg)
if (cfg) {
blkaddr = BLKADDR_CPT0;
goto exit;
}
reg = is_pf ? RVU_PRIV_PFX_CPTX_CFG(1) :
RVU_PRIV_HWVFX_CPTX_CFG(1);
cfg = rvu_read64(rvu, BLKADDR_RVUM, reg | (devnum << 16));
if (cfg)
blkaddr = BLKADDR_CPT1;
}
exit:
......@@ -306,31 +329,36 @@ static void rvu_update_rsrc_map(struct rvu *rvu, struct rvu_pfvf *pfvf,
block->fn_map[lf] = attach ? pcifunc : 0;
switch (block->type) {
case BLKTYPE_NPA:
switch (block->addr) {
case BLKADDR_NPA:
pfvf->npalf = attach ? true : false;
num_lfs = pfvf->npalf;
break;
case BLKTYPE_NIX:
case BLKADDR_NIX0:
case BLKADDR_NIX1:
pfvf->nixlf = attach ? true : false;
num_lfs = pfvf->nixlf;
break;
case BLKTYPE_SSO:
case BLKADDR_SSO:
attach ? pfvf->sso++ : pfvf->sso--;
num_lfs = pfvf->sso;
break;
case BLKTYPE_SSOW:
case BLKADDR_SSOW:
attach ? pfvf->ssow++ : pfvf->ssow--;
num_lfs = pfvf->ssow;
break;
case BLKTYPE_TIM:
case BLKADDR_TIM:
attach ? pfvf->timlfs++ : pfvf->timlfs--;
num_lfs = pfvf->timlfs;
break;
case BLKTYPE_CPT:
case BLKADDR_CPT0:
attach ? pfvf->cptlfs++ : pfvf->cptlfs--;
num_lfs = pfvf->cptlfs;
break;
case BLKADDR_CPT1:
attach ? pfvf->cpt1_lfs++ : pfvf->cpt1_lfs--;
num_lfs = pfvf->cpt1_lfs;
break;
}
reg = is_pf ? block->pf_lfcnt_reg : block->vf_lfcnt_reg;
......@@ -466,12 +494,16 @@ static void rvu_reset_all_blocks(struct rvu *rvu)
/* Do a HW reset of all RVU blocks */
rvu_block_reset(rvu, BLKADDR_NPA, NPA_AF_BLK_RST);
rvu_block_reset(rvu, BLKADDR_NIX0, NIX_AF_BLK_RST);
rvu_block_reset(rvu, BLKADDR_NIX1, NIX_AF_BLK_RST);
rvu_block_reset(rvu, BLKADDR_NPC, NPC_AF_BLK_RST);
rvu_block_reset(rvu, BLKADDR_SSO, SSO_AF_BLK_RST);
rvu_block_reset(rvu, BLKADDR_TIM, TIM_AF_BLK_RST);
rvu_block_reset(rvu, BLKADDR_CPT0, CPT_AF_BLK_RST);
rvu_block_reset(rvu, BLKADDR_CPT1, CPT_AF_BLK_RST);
rvu_block_reset(rvu, BLKADDR_NDC_NIX0_RX, NDC_AF_BLK_RST);
rvu_block_reset(rvu, BLKADDR_NDC_NIX0_TX, NDC_AF_BLK_RST);
rvu_block_reset(rvu, BLKADDR_NDC_NIX1_RX, NDC_AF_BLK_RST);
rvu_block_reset(rvu, BLKADDR_NDC_NIX1_TX, NDC_AF_BLK_RST);
rvu_block_reset(rvu, BLKADDR_NDC_NPA0, NDC_AF_BLK_RST);
}
......@@ -757,6 +789,62 @@ static void rvu_fwdata_exit(struct rvu *rvu)
iounmap(rvu->fwdata);
}
static int rvu_setup_nix_hw_resource(struct rvu *rvu, int blkaddr)
{
struct rvu_hwinfo *hw = rvu->hw;
struct rvu_block *block;
int blkid;
u64 cfg;
/* Init NIX LF's bitmap */
block = &hw->block[blkaddr];
if (!block->implemented)
return 0;
blkid = (blkaddr == BLKADDR_NIX0) ? 0 : 1;
cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST2);
block->lf.max = cfg & 0xFFF;
block->addr = blkaddr;
block->type = BLKTYPE_NIX;
block->lfshift = 8;
block->lookup_reg = NIX_AF_RVU_LF_CFG_DEBUG;
block->pf_lfcnt_reg = RVU_PRIV_PFX_NIXX_CFG(blkid);
block->vf_lfcnt_reg = RVU_PRIV_HWVFX_NIXX_CFG(blkid);
block->lfcfg_reg = NIX_PRIV_LFX_CFG;
block->msixcfg_reg = NIX_PRIV_LFX_INT_CFG;
block->lfreset_reg = NIX_AF_LF_RST;
sprintf(block->name, "NIX%d", blkid);
rvu->nix_blkaddr[blkid] = blkaddr;
return rvu_alloc_bitmap(&block->lf);
}
static int rvu_setup_cpt_hw_resource(struct rvu *rvu, int blkaddr)
{
struct rvu_hwinfo *hw = rvu->hw;
struct rvu_block *block;
int blkid;
u64 cfg;
/* Init CPT LF's bitmap */
block = &hw->block[blkaddr];
if (!block->implemented)
return 0;
blkid = (blkaddr == BLKADDR_CPT0) ? 0 : 1;
cfg = rvu_read64(rvu, blkaddr, CPT_AF_CONSTANTS0);
block->lf.max = cfg & 0xFF;
block->addr = blkaddr;
block->type = BLKTYPE_CPT;
block->multislot = true;
block->lfshift = 3;
block->lookup_reg = CPT_AF_RVU_LF_CFG_DEBUG;
block->pf_lfcnt_reg = RVU_PRIV_PFX_CPTX_CFG(blkid);
block->vf_lfcnt_reg = RVU_PRIV_HWVFX_CPTX_CFG(blkid);
block->lfcfg_reg = CPT_PRIV_LFX_CFG;
block->msixcfg_reg = CPT_PRIV_LFX_INT_CFG;
block->lfreset_reg = CPT_AF_LF_RST;
sprintf(block->name, "CPT%d", blkid);
return rvu_alloc_bitmap(&block->lf);
}
static int rvu_setup_hw_resources(struct rvu *rvu)
{
struct rvu_hwinfo *hw = rvu->hw;
......@@ -791,27 +879,13 @@ static int rvu_setup_hw_resources(struct rvu *rvu)
return err;
nix:
/* Init NIX LF's bitmap */
block = &hw->block[BLKADDR_NIX0];
if (!block->implemented)
goto sso;
cfg = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_CONST2);
block->lf.max = cfg & 0xFFF;
block->addr = BLKADDR_NIX0;
block->type = BLKTYPE_NIX;
block->lfshift = 8;
block->lookup_reg = NIX_AF_RVU_LF_CFG_DEBUG;
block->pf_lfcnt_reg = RVU_PRIV_PFX_NIX0_CFG;
block->vf_lfcnt_reg = RVU_PRIV_HWVFX_NIX0_CFG;
block->lfcfg_reg = NIX_PRIV_LFX_CFG;
block->msixcfg_reg = NIX_PRIV_LFX_INT_CFG;
block->lfreset_reg = NIX_AF_LF_RST;
sprintf(block->name, "NIX");
err = rvu_alloc_bitmap(&block->lf);
err = rvu_setup_nix_hw_resource(rvu, BLKADDR_NIX0);
if (err)
return err;
err = rvu_setup_nix_hw_resource(rvu, BLKADDR_NIX1);
if (err)
return err;
sso:
/* Init SSO group's bitmap */
block = &hw->block[BLKADDR_SSO];
if (!block->implemented)
......@@ -877,28 +951,13 @@ static int rvu_setup_hw_resources(struct rvu *rvu)
return err;
cpt:
/* Init CPT LF's bitmap */
block = &hw->block[BLKADDR_CPT0];
if (!block->implemented)
goto init;
cfg = rvu_read64(rvu, BLKADDR_CPT0, CPT_AF_CONSTANTS0);
block->lf.max = cfg & 0xFF;
block->addr = BLKADDR_CPT0;
block->type = BLKTYPE_CPT;
block->multislot = true;
block->lfshift = 3;
block->lookup_reg = CPT_AF_RVU_LF_CFG_DEBUG;
block->pf_lfcnt_reg = RVU_PRIV_PFX_CPT0_CFG;
block->vf_lfcnt_reg = RVU_PRIV_HWVFX_CPT0_CFG;
block->lfcfg_reg = CPT_PRIV_LFX_CFG;
block->msixcfg_reg = CPT_PRIV_LFX_INT_CFG;
block->lfreset_reg = CPT_AF_LF_RST;
sprintf(block->name, "CPT");
err = rvu_alloc_bitmap(&block->lf);
err = rvu_setup_cpt_hw_resource(rvu, BLKADDR_CPT0);
if (err)
return err;
err = rvu_setup_cpt_hw_resource(rvu, BLKADDR_CPT1);
if (err)
return err;
init:
/* Allocate memory for PFVF data */
rvu->pf = devm_kcalloc(rvu->dev, hw->total_pfs,
sizeof(struct rvu_pfvf), GFP_KERNEL);
......@@ -1025,7 +1084,30 @@ int rvu_mbox_handler_ready(struct rvu *rvu, struct msg_req *req,
/* Get current count of a RVU block's LF/slots
* provisioned to a given RVU func.
*/
static u16 rvu_get_rsrc_mapcount(struct rvu_pfvf *pfvf, int blktype)
u16 rvu_get_rsrc_mapcount(struct rvu_pfvf *pfvf, int blkaddr)
{
switch (blkaddr) {
case BLKADDR_NPA:
return pfvf->npalf ? 1 : 0;
case BLKADDR_NIX0:
case BLKADDR_NIX1:
return pfvf->nixlf ? 1 : 0;
case BLKADDR_SSO:
return pfvf->sso;
case BLKADDR_SSOW:
return pfvf->ssow;
case BLKADDR_TIM:
return pfvf->timlfs;
case BLKADDR_CPT0:
return pfvf->cptlfs;
case BLKADDR_CPT1:
return pfvf->cpt1_lfs;
}
return 0;
}
/* Return true if LFs of block type are attached to pcifunc */
static bool is_blktype_attached(struct rvu_pfvf *pfvf, int blktype)
{
switch (blktype) {
case BLKTYPE_NPA:
......@@ -1033,15 +1115,16 @@ static u16 rvu_get_rsrc_mapcount(struct rvu_pfvf *pfvf, int blktype)
case BLKTYPE_NIX:
return pfvf->nixlf ? 1 : 0;
case BLKTYPE_SSO:
return pfvf->sso;
return !!pfvf->sso;
case BLKTYPE_SSOW:
return pfvf->ssow;
return !!pfvf->ssow;
case BLKTYPE_TIM:
return pfvf->timlfs;
return !!pfvf->timlfs;
case BLKTYPE_CPT:
return pfvf->cptlfs;
return pfvf->cptlfs || pfvf->cpt1_lfs;
}
return 0;
return false;
}
bool is_pffunc_map_valid(struct rvu *rvu, u16 pcifunc, int blktype)
......@@ -1054,7 +1137,7 @@ bool is_pffunc_map_valid(struct rvu *rvu, u16 pcifunc, int blktype)
pfvf = rvu_get_pfvf(rvu, pcifunc);
/* Check if this PFFUNC has a LF of type blktype attached */
if (!rvu_get_rsrc_mapcount(pfvf, blktype))
if (!is_blktype_attached(pfvf, blktype))
return false;
return true;
......@@ -1095,7 +1178,7 @@ static void rvu_detach_block(struct rvu *rvu, int pcifunc, int blktype)
block = &hw->block[blkaddr];
num_lfs = rvu_get_rsrc_mapcount(pfvf, block->type);
num_lfs = rvu_get_rsrc_mapcount(pfvf, block->addr);
if (!num_lfs)
return;
......@@ -1146,6 +1229,8 @@ static int rvu_detach_rsrcs(struct rvu *rvu, struct rsrc_detach *detach,
continue;
else if ((blkid == BLKADDR_NIX0) && !detach->nixlf)
continue;
else if ((blkid == BLKADDR_NIX1) && !detach->nixlf)
continue;
else if ((blkid == BLKADDR_SSO) && !detach->sso)
continue;
else if ((blkid == BLKADDR_SSOW) && !detach->ssow)
......@@ -1154,6 +1239,8 @@ static int rvu_detach_rsrcs(struct rvu *rvu, struct rsrc_detach *detach,
continue;
else if ((blkid == BLKADDR_CPT0) && !detach->cptlfs)
continue;
else if ((blkid == BLKADDR_CPT1) && !detach->cptlfs)
continue;
}
rvu_detach_block(rvu, pcifunc, block->type);
}
......@@ -1169,8 +1256,73 @@ int rvu_mbox_handler_detach_resources(struct rvu *rvu,
return rvu_detach_rsrcs(rvu, detach, detach->hdr.pcifunc);
}
static void rvu_attach_block(struct rvu *rvu, int pcifunc,
int blktype, int num_lfs)
static int rvu_get_nix_blkaddr(struct rvu *rvu, u16 pcifunc)
{
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
int blkaddr = BLKADDR_NIX0, vf;
struct rvu_pfvf *pf;
/* All CGX mapped PFs are set with assigned NIX block during init */
if (is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) {
pf = rvu_get_pfvf(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK);
blkaddr = pf->nix_blkaddr;
} else if (is_afvf(pcifunc)) {
vf = pcifunc - 1;
/* Assign NIX based on VF number. All even numbered VFs get
* NIX0 and odd numbered gets NIX1
*/
blkaddr = (vf & 1) ? BLKADDR_NIX1 : BLKADDR_NIX0;
/* NIX1 is not present on all silicons */
if (!is_block_implemented(rvu->hw, BLKADDR_NIX1))
blkaddr = BLKADDR_NIX0;
}
switch (blkaddr) {
case BLKADDR_NIX1:
pfvf->nix_blkaddr = BLKADDR_NIX1;
pfvf->nix_rx_intf = NIX_INTFX_RX(1);
pfvf->nix_tx_intf = NIX_INTFX_TX(1);
break;
case BLKADDR_NIX0:
default:
pfvf->nix_blkaddr = BLKADDR_NIX0;
pfvf->nix_rx_intf = NIX_INTFX_RX(0);
pfvf->nix_tx_intf = NIX_INTFX_TX(0);
break;
}
return pfvf->nix_blkaddr;
}
static int rvu_get_attach_blkaddr(struct rvu *rvu, int blktype,
u16 pcifunc, struct rsrc_attach *attach)
{
int blkaddr;
switch (blktype) {
case BLKTYPE_NIX:
blkaddr = rvu_get_nix_blkaddr(rvu, pcifunc);
break;
case BLKTYPE_CPT:
if (attach->hdr.ver < RVU_MULTI_BLK_VER)
return rvu_get_blkaddr(rvu, blktype, 0);
blkaddr = attach->cpt_blkaddr ? attach->cpt_blkaddr :
BLKADDR_CPT0;
if (blkaddr != BLKADDR_CPT0 && blkaddr != BLKADDR_CPT1)
return -ENODEV;
break;
default:
return rvu_get_blkaddr(rvu, blktype, 0);
};
if (is_block_implemented(rvu->hw, blkaddr))
return blkaddr;
return -ENODEV;
}
static void rvu_attach_block(struct rvu *rvu, int pcifunc, int blktype,
int num_lfs, struct rsrc_attach *attach)
{
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
struct rvu_hwinfo *hw = rvu->hw;
......@@ -1182,7 +1334,7 @@ static void rvu_attach_block(struct rvu *rvu, int pcifunc,
if (!num_lfs)
return;
blkaddr = rvu_get_blkaddr(rvu, blktype, 0);
blkaddr = rvu_get_attach_blkaddr(rvu, blktype, pcifunc, attach);
if (blkaddr < 0)
return;
......@@ -1211,12 +1363,12 @@ static int rvu_check_rsrc_availability(struct rvu *rvu,
struct rsrc_attach *req, u16 pcifunc)
{
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
int free_lfs, mappedlfs, blkaddr;
struct rvu_hwinfo *hw = rvu->hw;
struct rvu_block *block;
int free_lfs, mappedlfs;
/* Only one NPA LF can be attached */
if (req->npalf && !rvu_get_rsrc_mapcount(pfvf, BLKTYPE_NPA)) {
if (req->npalf && !is_blktype_attached(pfvf, BLKTYPE_NPA)) {
block = &hw->block[BLKADDR_NPA];
free_lfs = rvu_rsrc_free_count(&block->lf);
if (!free_lfs)
......@@ -1229,8 +1381,12 @@ static int rvu_check_rsrc_availability(struct rvu *rvu,
}
/* Only one NIX LF can be attached */
if (req->nixlf && !rvu_get_rsrc_mapcount(pfvf, BLKTYPE_NIX)) {
block = &hw->block[BLKADDR_NIX0];
if (req->nixlf && !is_blktype_attached(pfvf, BLKTYPE_NIX)) {
blkaddr = rvu_get_attach_blkaddr(rvu, BLKTYPE_NIX,
pcifunc, req);
if (blkaddr < 0)
return blkaddr;
block = &hw->block[blkaddr];
free_lfs = rvu_rsrc_free_count(&block->lf);
if (!free_lfs)
goto fail;
......@@ -1250,7 +1406,7 @@ static int rvu_check_rsrc_availability(struct rvu *rvu,
pcifunc, req->sso, block->lf.max);
return -EINVAL;
}
mappedlfs = rvu_get_rsrc_mapcount(pfvf, block->type);
mappedlfs = rvu_get_rsrc_mapcount(pfvf, block->addr);
free_lfs = rvu_rsrc_free_count(&block->lf);
/* Check if additional resources are available */
if (req->sso > mappedlfs &&
......@@ -1266,7 +1422,7 @@ static int rvu_check_rsrc_availability(struct rvu *rvu,
pcifunc, req->sso, block->lf.max);
return -EINVAL;
}
mappedlfs = rvu_get_rsrc_mapcount(pfvf, block->type);
mappedlfs = rvu_get_rsrc_mapcount(pfvf, block->addr);
free_lfs = rvu_rsrc_free_count(&block->lf);
if (req->ssow > mappedlfs &&
((req->ssow - mappedlfs) > free_lfs))
......@@ -1281,7 +1437,7 @@ static int rvu_check_rsrc_availability(struct rvu *rvu,
pcifunc, req->timlfs, block->lf.max);
return -EINVAL;
}
mappedlfs = rvu_get_rsrc_mapcount(pfvf, block->type);
mappedlfs = rvu_get_rsrc_mapcount(pfvf, block->addr);
free_lfs = rvu_rsrc_free_count(&block->lf);
if (req->timlfs > mappedlfs &&
((req->timlfs - mappedlfs) > free_lfs))
......@@ -1289,14 +1445,18 @@ static int rvu_check_rsrc_availability(struct rvu *rvu,
}
if (req->cptlfs) {
block = &hw->block[BLKADDR_CPT0];
blkaddr = rvu_get_attach_blkaddr(rvu, BLKTYPE_CPT,
pcifunc, req);
if (blkaddr < 0)
return blkaddr;
block = &hw->block[blkaddr];
if (req->cptlfs > block->lf.max) {
dev_err(&rvu->pdev->dev,
"Func 0x%x: Invalid CPTLF req, %d > max %d\n",
pcifunc, req->cptlfs, block->lf.max);
return -EINVAL;
}
mappedlfs = rvu_get_rsrc_mapcount(pfvf, block->type);
mappedlfs = rvu_get_rsrc_mapcount(pfvf, block->addr);
free_lfs = rvu_rsrc_free_count(&block->lf);
if (req->cptlfs > mappedlfs &&
((req->cptlfs - mappedlfs) > free_lfs))
......@@ -1310,6 +1470,22 @@ static int rvu_check_rsrc_availability(struct rvu *rvu,
return -ENOSPC;
}
static bool rvu_attach_from_same_block(struct rvu *rvu, int blktype,
struct rsrc_attach *attach)
{
int blkaddr, num_lfs;
blkaddr = rvu_get_attach_blkaddr(rvu, blktype,
attach->hdr.pcifunc, attach);
if (blkaddr < 0)
return false;
num_lfs = rvu_get_rsrc_mapcount(rvu_get_pfvf(rvu, attach->hdr.pcifunc),
blkaddr);
/* Requester already has LFs from given block ? */
return !!num_lfs;
}
int rvu_mbox_handler_attach_resources(struct rvu *rvu,
struct rsrc_attach *attach,
struct msg_rsp *rsp)
......@@ -1330,10 +1506,10 @@ int rvu_mbox_handler_attach_resources(struct rvu *rvu,
/* Now attach the requested resources */
if (attach->npalf)
rvu_attach_block(rvu, pcifunc, BLKTYPE_NPA, 1);
rvu_attach_block(rvu, pcifunc, BLKTYPE_NPA, 1, attach);
if (attach->nixlf)
rvu_attach_block(rvu, pcifunc, BLKTYPE_NIX, 1);
rvu_attach_block(rvu, pcifunc, BLKTYPE_NIX, 1, attach);
if (attach->sso) {
/* RVU func doesn't know which exact LF or slot is attached
......@@ -1343,25 +1519,30 @@ int rvu_mbox_handler_attach_resources(struct rvu *rvu,
*/
if (attach->modify)
rvu_detach_block(rvu, pcifunc, BLKTYPE_SSO);
rvu_attach_block(rvu, pcifunc, BLKTYPE_SSO, attach->sso);
rvu_attach_block(rvu, pcifunc, BLKTYPE_SSO,
attach->sso, attach);
}
if (attach->ssow) {
if (attach->modify)
rvu_detach_block(rvu, pcifunc, BLKTYPE_SSOW);
rvu_attach_block(rvu, pcifunc, BLKTYPE_SSOW, attach->ssow);
rvu_attach_block(rvu, pcifunc, BLKTYPE_SSOW,
attach->ssow, attach);
}
if (attach->timlfs) {
if (attach->modify)
rvu_detach_block(rvu, pcifunc, BLKTYPE_TIM);
rvu_attach_block(rvu, pcifunc, BLKTYPE_TIM, attach->timlfs);
rvu_attach_block(rvu, pcifunc, BLKTYPE_TIM,
attach->timlfs, attach);
}
if (attach->cptlfs) {
if (attach->modify)
if (attach->modify &&
rvu_attach_from_same_block(rvu, BLKTYPE_CPT, attach))
rvu_detach_block(rvu, pcifunc, BLKTYPE_CPT);
rvu_attach_block(rvu, pcifunc, BLKTYPE_CPT, attach->cptlfs);
rvu_attach_block(rvu, pcifunc, BLKTYPE_CPT,
attach->cptlfs, attach);
}
exit:
......@@ -1439,7 +1620,7 @@ int rvu_mbox_handler_msix_offset(struct rvu *rvu, struct msg_req *req,
struct rvu_hwinfo *hw = rvu->hw;
u16 pcifunc = req->hdr.pcifunc;
struct rvu_pfvf *pfvf;
int lf, slot;
int lf, slot, blkaddr;
pfvf = rvu_get_pfvf(rvu, pcifunc);
if (!pfvf->msix.bmap)
......@@ -1449,8 +1630,14 @@ int rvu_mbox_handler_msix_offset(struct rvu *rvu, struct msg_req *req,
lf = rvu_get_lf(rvu, &hw->block[BLKADDR_NPA], pcifunc, 0);
rsp->npa_msixoff = rvu_get_msix_offset(rvu, pfvf, BLKADDR_NPA, lf);
lf = rvu_get_lf(rvu, &hw->block[BLKADDR_NIX0], pcifunc, 0);
rsp->nix_msixoff = rvu_get_msix_offset(rvu, pfvf, BLKADDR_NIX0, lf);
/* Get BLKADDR from which LFs are attached to pcifunc */
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
if (blkaddr < 0) {
rsp->nix_msixoff = MSIX_VECTOR_INVALID;
} else {
lf = rvu_get_lf(rvu, &hw->block[blkaddr], pcifunc, 0);
rsp->nix_msixoff = rvu_get_msix_offset(rvu, pfvf, blkaddr, lf);
}
rsp->sso = pfvf->sso;
for (slot = 0; slot < rsp->sso; slot++) {
......@@ -1479,6 +1666,14 @@ int rvu_mbox_handler_msix_offset(struct rvu *rvu, struct msg_req *req,
rsp->cptlf_msixoff[slot] =
rvu_get_msix_offset(rvu, pfvf, BLKADDR_CPT0, lf);
}
rsp->cpt1_lfs = pfvf->cpt1_lfs;
for (slot = 0; slot < rsp->cpt1_lfs; slot++) {
lf = rvu_get_lf(rvu, &hw->block[BLKADDR_CPT1], pcifunc, slot);
rsp->cpt1_lf_msixoff[slot] =
rvu_get_msix_offset(rvu, pfvf, BLKADDR_CPT1, lf);
}
return 0;
}
......@@ -1932,7 +2127,7 @@ static void rvu_blklf_teardown(struct rvu *rvu, u16 pcifunc, u8 blkaddr)
block = &rvu->hw->block[blkaddr];
num_lfs = rvu_get_rsrc_mapcount(rvu_get_pfvf(rvu, pcifunc),
block->type);
block->addr);
if (!num_lfs)
return;
for (slot = 0; slot < num_lfs; slot++) {
......@@ -1941,7 +2136,7 @@ static void rvu_blklf_teardown(struct rvu *rvu, u16 pcifunc, u8 blkaddr)
continue;
/* Cleanup LF and reset it */
if (block->addr == BLKADDR_NIX0)
if (block->addr == BLKADDR_NIX0 || block->addr == BLKADDR_NIX1)
rvu_nix_lf_teardown(rvu, pcifunc, block->addr, lf);
else if (block->addr == BLKADDR_NPA)
rvu_npa_lf_teardown(rvu, pcifunc, lf);
......@@ -1963,7 +2158,9 @@ static void __rvu_flr_handler(struct rvu *rvu, u16 pcifunc)
* 3. Cleanup pools (NPA)
*/
rvu_blklf_teardown(rvu, pcifunc, BLKADDR_NIX0);
rvu_blklf_teardown(rvu, pcifunc, BLKADDR_NIX1);
rvu_blklf_teardown(rvu, pcifunc, BLKADDR_CPT0);
rvu_blklf_teardown(rvu, pcifunc, BLKADDR_CPT1);
rvu_blklf_teardown(rvu, pcifunc, BLKADDR_TIM);
rvu_blklf_teardown(rvu, pcifunc, BLKADDR_SSOW);
rvu_blklf_teardown(rvu, pcifunc, BLKADDR_SSO);
......
......@@ -28,6 +28,7 @@
#define PCI_MBOX_BAR_NUM 4
#define NAME_SIZE 32
#define MAX_NIX_BLKS 2
/* PF_FUNC */
#define RVU_PFVF_PF_SHIFT 10
......@@ -137,6 +138,7 @@ struct rvu_pfvf {
u16 ssow;
u16 cptlfs;
u16 timlfs;
u16 cpt1_lfs;
u8 cgx_lmac;
/* Block LF's MSIX vector info */
......@@ -182,6 +184,10 @@ struct rvu_pfvf {
bool cgx_in_use; /* this PF/VF using CGX? */
int cgx_users; /* number of cgx users - used only by PFs */
u8 nix_blkaddr; /* BLKADDR_NIX0/1 assigned to this PF */
u8 nix_rx_intf; /* NIX0_RX/NIX1_RX interface to NPC */
u8 nix_tx_intf; /* NIX0_TX/NIX1_TX interface to NPC */
};
struct nix_txsch {
......@@ -219,6 +225,8 @@ struct nix_lso {
};
struct nix_hw {
int blkaddr;
struct rvu *rvu;
struct nix_txsch txsch[NIX_TXSCH_LVL_CNT]; /* Tx schedulers */
struct nix_mcast mcast;
struct nix_flowkey flowkey;
......@@ -251,10 +259,16 @@ struct rvu_hwinfo {
u8 lbk_links;
u8 sdp_links;
u8 npc_kpus; /* No of parser units */
u8 npc_pkinds; /* No of port kinds */
u8 npc_intfs; /* No of interfaces */
u8 npc_kpu_entries; /* No of KPU entries */
u16 npc_counters; /* No of match stats counters */
bool npc_ext_set; /* Extended register set */
struct hw_cap cap;
struct rvu_block block[BLK_COUNT]; /* Block info */
struct nix_hw *nix0;
struct nix_hw *nix;
struct rvu *rvu;
struct npc_pkind pkind;
struct npc_mcam mcam;
};
......@@ -300,7 +314,7 @@ struct npc_kpu_profile_adapter {
const struct npc_lt_def_cfg *lt_def;
const struct npc_kpu_profile_action *ikpu; /* array[pkinds] */
const struct npc_kpu_profile *kpu; /* array[kpus] */
const struct npc_mcam_kex *mkex;
struct npc_mcam_kex *mkex;
size_t pkinds;
size_t kpus;
};
......@@ -315,6 +329,7 @@ struct rvu {
struct rvu_pfvf *hwvf;
struct mutex rsrc_lock; /* Serialize resource alloc/free */
int vfs; /* Number of VFs attached to RVU */
int nix_blkaddr[MAX_NIX_BLKS];
/* Mbox */
struct mbox_wq_info afpf_wq_info;
......@@ -420,6 +435,7 @@ void rvu_free_rsrc(struct rsrc_bmap *rsrc, int id);
int rvu_rsrc_free_count(struct rsrc_bmap *rsrc);
int rvu_alloc_rsrc_contig(struct rsrc_bmap *rsrc, int nrsrc);
bool rvu_rsrc_check_contig(struct rsrc_bmap *rsrc, int nrsrc);
u16 rvu_get_rsrc_mapcount(struct rvu_pfvf *pfvf, int blkaddr);
int rvu_get_pf(u16 pcifunc);
struct rvu_pfvf *rvu_get_pfvf(struct rvu *rvu, int pcifunc);
void rvu_get_pf_numvfs(struct rvu *rvu, int pf, int *numvfs, int *hwvf);
......@@ -485,6 +501,8 @@ int rvu_get_nixlf_count(struct rvu *rvu);
void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int npalf);
int nix_get_nixlf(struct rvu *rvu, u16 pcifunc, int *nixlf, int *nix_blkaddr);
int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add);
struct nix_hw *get_nix_hw(struct rvu_hwinfo *hw, int blkaddr);
int rvu_get_next_nix_blkaddr(struct rvu *rvu, int blkaddr);
/* NPC APIs */
int rvu_npc_init(struct rvu *rvu);
......@@ -513,6 +531,10 @@ void rvu_npc_get_mcam_entry_alloc_info(struct rvu *rvu, u16 pcifunc,
void rvu_npc_get_mcam_counter_alloc_info(struct rvu *rvu, u16 pcifunc,
int blkaddr, int *alloc_cnt,
int *enable_cnt);
bool is_npc_intf_tx(u8 intf);
bool is_npc_intf_rx(u8 intf);
bool is_npc_interface_valid(struct rvu *rvu, u8 intf);
int rvu_npc_get_tx_nibble_cfg(struct rvu *rvu, u64 nibble_ena);
#ifdef CONFIG_DEBUG_FS
void rvu_dbg_init(struct rvu *rvu);
......
......@@ -74,6 +74,20 @@ void *rvu_cgx_pdata(u8 cgx_id, struct rvu *rvu)
return rvu->cgx_idmap[cgx_id];
}
/* Based on P2X connectivity find mapped NIX block for a PF */
static void rvu_map_cgx_nix_block(struct rvu *rvu, int pf,
int cgx_id, int lmac_id)
{
struct rvu_pfvf *pfvf = &rvu->pf[pf];
u8 p2x;
p2x = cgx_lmac_get_p2x(cgx_id, lmac_id);
/* Firmware sets P2X_SELECT as either NIX0 or NIX1 */
pfvf->nix_blkaddr = BLKADDR_NIX0;
if (p2x == CMR_P2X_SEL_NIX1)
pfvf->nix_blkaddr = BLKADDR_NIX1;
}
static int rvu_map_cgx_lmac_pf(struct rvu *rvu)
{
struct npc_pkind *pkind = &rvu->hw->pkind;
......@@ -117,6 +131,7 @@ static int rvu_map_cgx_lmac_pf(struct rvu *rvu)
rvu->cgxlmac2pf_map[CGX_OFFSET(cgx) + lmac] = 1 << pf;
free_pkind = rvu_alloc_rsrc(&pkind->rsrc);
pkind->pfchan_map[free_pkind] = ((pf) & 0x3F) << 16;
rvu_map_cgx_nix_block(rvu, pf, cgx, lmac);
rvu->cgx_mapped_pfs++;
}
}
......
......@@ -224,18 +224,53 @@ static ssize_t rvu_dbg_rsrc_attach_status(struct file *filp,
RVU_DEBUG_FOPS(rsrc_status, rsrc_attach_status, NULL);
static bool rvu_dbg_is_valid_lf(struct rvu *rvu, int blktype, int lf,
static int rvu_dbg_rvu_pf_cgx_map_display(struct seq_file *filp, void *unused)
{
struct rvu *rvu = filp->private;
struct pci_dev *pdev = NULL;
char cgx[10], lmac[10];
struct rvu_pfvf *pfvf;
int pf, domain, blkid;
u8 cgx_id, lmac_id;
u16 pcifunc;
domain = 2;
seq_puts(filp, "PCI dev\t\tRVU PF Func\tNIX block\tCGX\tLMAC\n");
for (pf = 0; pf < rvu->hw->total_pfs; pf++) {
if (!is_pf_cgxmapped(rvu, pf))
continue;
pdev = pci_get_domain_bus_and_slot(domain, pf + 1, 0);
if (!pdev)
continue;
cgx[0] = 0;
lmac[0] = 0;
pcifunc = pf << 10;
pfvf = rvu_get_pfvf(rvu, pcifunc);
if (pfvf->nix_blkaddr == BLKADDR_NIX0)
blkid = 0;
else
blkid = 1;
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id,
&lmac_id);
sprintf(cgx, "CGX%d", cgx_id);
sprintf(lmac, "LMAC%d", lmac_id);
seq_printf(filp, "%s\t0x%x\t\tNIX%d\t\t%s\t%s\n",
dev_name(&pdev->dev), pcifunc, blkid, cgx, lmac);
}
return 0;
}
RVU_DEBUG_SEQ_FOPS(rvu_pf_cgx_map, rvu_pf_cgx_map_display, NULL);
static bool rvu_dbg_is_valid_lf(struct rvu *rvu, int blkaddr, int lf,
u16 *pcifunc)
{
struct rvu_block *block;
struct rvu_hwinfo *hw;
int blkaddr;
blkaddr = rvu_get_blkaddr(rvu, blktype, 0);
if (blkaddr < 0) {
dev_warn(rvu->dev, "Invalid blktype\n");
return false;
}
hw = rvu->hw;
block = &hw->block[blkaddr];
......@@ -291,10 +326,12 @@ static int rvu_dbg_qsize_display(struct seq_file *filp, void *unsused,
{
void (*print_qsize)(struct seq_file *filp,
struct rvu_pfvf *pfvf) = NULL;
struct dentry *current_dir;
struct rvu_pfvf *pfvf;
struct rvu *rvu;
int qsize_id;
u16 pcifunc;
int blkaddr;
rvu = filp->private;
switch (blktype) {
......@@ -312,7 +349,15 @@ static int rvu_dbg_qsize_display(struct seq_file *filp, void *unsused,
return -EINVAL;
}
if (!rvu_dbg_is_valid_lf(rvu, blktype, qsize_id, &pcifunc))
if (blktype == BLKTYPE_NPA) {
blkaddr = BLKADDR_NPA;
} else {
current_dir = filp->file->f_path.dentry->d_parent;
blkaddr = (!strcmp(current_dir->d_name.name, "nix1") ?
BLKADDR_NIX1 : BLKADDR_NIX0);
}
if (!rvu_dbg_is_valid_lf(rvu, blkaddr, qsize_id, &pcifunc))
return -EINVAL;
pfvf = rvu_get_pfvf(rvu, pcifunc);
......@@ -329,6 +374,8 @@ static ssize_t rvu_dbg_qsize_write(struct file *filp,
struct seq_file *seqfile = filp->private_data;
char *cmd_buf, *cmd_buf_tmp, *subtoken;
struct rvu *rvu = seqfile->private;
struct dentry *current_dir;
int blkaddr;
u16 pcifunc;
int ret, lf;
......@@ -355,7 +402,15 @@ static ssize_t rvu_dbg_qsize_write(struct file *filp,
goto qsize_write_done;
}
if (!rvu_dbg_is_valid_lf(rvu, blktype, lf, &pcifunc)) {
if (blktype == BLKTYPE_NPA) {
blkaddr = BLKADDR_NPA;
} else {
current_dir = filp->f_path.dentry->d_parent;
blkaddr = (!strcmp(current_dir->d_name.name, "nix1") ?
BLKADDR_NIX1 : BLKADDR_NIX0);
}
if (!rvu_dbg_is_valid_lf(rvu, blkaddr, lf, &pcifunc)) {
ret = -EINVAL;
goto qsize_write_done;
}
......@@ -498,7 +553,7 @@ static int rvu_dbg_npa_ctx_display(struct seq_file *m, void *unused, int ctype)
return -EINVAL;
}
if (!rvu_dbg_is_valid_lf(rvu, BLKTYPE_NPA, npalf, &pcifunc))
if (!rvu_dbg_is_valid_lf(rvu, BLKADDR_NPA, npalf, &pcifunc))
return -EINVAL;
pfvf = rvu_get_pfvf(rvu, pcifunc);
......@@ -556,7 +611,7 @@ static int write_npa_ctx(struct rvu *rvu, bool all,
int max_id = 0;
u16 pcifunc;
if (!rvu_dbg_is_valid_lf(rvu, BLKTYPE_NPA, npalf, &pcifunc))
if (!rvu_dbg_is_valid_lf(rvu, BLKADDR_NPA, npalf, &pcifunc))
return -EINVAL;
pfvf = rvu_get_pfvf(rvu, pcifunc);
......@@ -704,9 +759,17 @@ static void ndc_cache_stats(struct seq_file *s, int blk_addr,
int ctype, int transaction)
{
u64 req, out_req, lat, cant_alloc;
struct rvu *rvu = s->private;
struct nix_hw *nix_hw;
struct rvu *rvu;
int port;
if (blk_addr == BLKADDR_NDC_NPA0) {
rvu = s->private;
} else {
nix_hw = s->private;
rvu = nix_hw->rvu;
}
for (port = 0; port < NDC_MAX_PORT; port++) {
req = rvu_read64(rvu, blk_addr, NDC_AF_PORTX_RTX_RWX_REQ_PC
(port, ctype, transaction));
......@@ -749,9 +812,17 @@ RVU_DEBUG_SEQ_FOPS(npa_ndc_cache, npa_ndc_cache_display, NULL);
static int ndc_blk_hits_miss_stats(struct seq_file *s, int idx, int blk_addr)
{
struct rvu *rvu = s->private;
struct nix_hw *nix_hw;
struct rvu *rvu;
int bank, max_bank;
if (blk_addr == BLKADDR_NDC_NPA0) {
rvu = s->private;
} else {
nix_hw = s->private;
rvu = nix_hw->rvu;
}
max_bank = NDC_MAX_BANK(rvu, blk_addr);
for (bank = 0; bank < max_bank; bank++) {
seq_printf(s, "BANK:%d\n", bank);
......@@ -767,16 +838,30 @@ static int ndc_blk_hits_miss_stats(struct seq_file *s, int idx, int blk_addr)
static int rvu_dbg_nix_ndc_rx_cache_display(struct seq_file *filp, void *unused)
{
return ndc_blk_cache_stats(filp, NIX0_RX,
BLKADDR_NDC_NIX0_RX);
struct nix_hw *nix_hw = filp->private;
int blkaddr = 0;
int ndc_idx = 0;
blkaddr = (nix_hw->blkaddr == BLKADDR_NIX1 ?
BLKADDR_NDC_NIX1_RX : BLKADDR_NDC_NIX0_RX);
ndc_idx = (nix_hw->blkaddr == BLKADDR_NIX1 ? NIX1_RX : NIX0_RX);
return ndc_blk_cache_stats(filp, ndc_idx, blkaddr);
}
RVU_DEBUG_SEQ_FOPS(nix_ndc_rx_cache, nix_ndc_rx_cache_display, NULL);
static int rvu_dbg_nix_ndc_tx_cache_display(struct seq_file *filp, void *unused)
{
return ndc_blk_cache_stats(filp, NIX0_TX,
BLKADDR_NDC_NIX0_TX);
struct nix_hw *nix_hw = filp->private;
int blkaddr = 0;
int ndc_idx = 0;
blkaddr = (nix_hw->blkaddr == BLKADDR_NIX1 ?
BLKADDR_NDC_NIX1_TX : BLKADDR_NDC_NIX0_TX);
ndc_idx = (nix_hw->blkaddr == BLKADDR_NIX1 ? NIX1_TX : NIX0_TX);
return ndc_blk_cache_stats(filp, ndc_idx, blkaddr);
}
RVU_DEBUG_SEQ_FOPS(nix_ndc_tx_cache, nix_ndc_tx_cache_display, NULL);
......@@ -792,8 +877,14 @@ RVU_DEBUG_SEQ_FOPS(npa_ndc_hits_miss, npa_ndc_hits_miss_display, NULL);
static int rvu_dbg_nix_ndc_rx_hits_miss_display(struct seq_file *filp,
void *unused)
{
return ndc_blk_hits_miss_stats(filp,
NPA0_U, BLKADDR_NDC_NIX0_RX);
struct nix_hw *nix_hw = filp->private;
int ndc_idx = NPA0_U;
int blkaddr = 0;
blkaddr = (nix_hw->blkaddr == BLKADDR_NIX1 ?
BLKADDR_NDC_NIX1_RX : BLKADDR_NDC_NIX0_RX);
return ndc_blk_hits_miss_stats(filp, ndc_idx, blkaddr);
}
RVU_DEBUG_SEQ_FOPS(nix_ndc_rx_hits_miss, nix_ndc_rx_hits_miss_display, NULL);
......@@ -801,8 +892,14 @@ RVU_DEBUG_SEQ_FOPS(nix_ndc_rx_hits_miss, nix_ndc_rx_hits_miss_display, NULL);
static int rvu_dbg_nix_ndc_tx_hits_miss_display(struct seq_file *filp,
void *unused)
{
return ndc_blk_hits_miss_stats(filp,
NPA0_U, BLKADDR_NDC_NIX0_TX);
struct nix_hw *nix_hw = filp->private;
int ndc_idx = NPA0_U;
int blkaddr = 0;
blkaddr = (nix_hw->blkaddr == BLKADDR_NIX1 ?
BLKADDR_NDC_NIX1_TX : BLKADDR_NDC_NIX0_TX);
return ndc_blk_hits_miss_stats(filp, ndc_idx, blkaddr);
}
RVU_DEBUG_SEQ_FOPS(nix_ndc_tx_hits_miss, nix_ndc_tx_hits_miss_display, NULL);
......@@ -969,7 +1066,8 @@ static int rvu_dbg_nix_queue_ctx_display(struct seq_file *filp,
{
void (*print_nix_ctx)(struct seq_file *filp,
struct nix_aq_enq_rsp *rsp) = NULL;
struct rvu *rvu = filp->private;
struct nix_hw *nix_hw = filp->private;
struct rvu *rvu = nix_hw->rvu;
struct nix_aq_enq_req aq_req;
struct nix_aq_enq_rsp rsp;
char *ctype_string = NULL;
......@@ -1001,7 +1099,7 @@ static int rvu_dbg_nix_queue_ctx_display(struct seq_file *filp,
return -EINVAL;
}
if (!rvu_dbg_is_valid_lf(rvu, BLKTYPE_NIX, nixlf, &pcifunc))
if (!rvu_dbg_is_valid_lf(rvu, nix_hw->blkaddr, nixlf, &pcifunc))
return -EINVAL;
pfvf = rvu_get_pfvf(rvu, pcifunc);
......@@ -1053,13 +1151,15 @@ static int rvu_dbg_nix_queue_ctx_display(struct seq_file *filp,
}
static int write_nix_queue_ctx(struct rvu *rvu, bool all, int nixlf,
int id, int ctype, char *ctype_string)
int id, int ctype, char *ctype_string,
struct seq_file *m)
{
struct nix_hw *nix_hw = m->private;
struct rvu_pfvf *pfvf;
int max_id = 0;
u16 pcifunc;
if (!rvu_dbg_is_valid_lf(rvu, BLKTYPE_NIX, nixlf, &pcifunc))
if (!rvu_dbg_is_valid_lf(rvu, nix_hw->blkaddr, nixlf, &pcifunc))
return -EINVAL;
pfvf = rvu_get_pfvf(rvu, pcifunc);
......@@ -1119,7 +1219,8 @@ static ssize_t rvu_dbg_nix_queue_ctx_write(struct file *filp,
int ctype)
{
struct seq_file *m = filp->private_data;
struct rvu *rvu = m->private;
struct nix_hw *nix_hw = m->private;
struct rvu *rvu = nix_hw->rvu;
char *cmd_buf, *ctype_string;
int nixlf, id = 0, ret;
bool all = false;
......@@ -1155,7 +1256,7 @@ static ssize_t rvu_dbg_nix_queue_ctx_write(struct file *filp,
goto done;
} else {
ret = write_nix_queue_ctx(rvu, all, nixlf, id, ctype,
ctype_string);
ctype_string, m);
}
done:
kfree(cmd_buf);
......@@ -1259,49 +1360,67 @@ static int rvu_dbg_nix_qsize_display(struct seq_file *filp, void *unused)
RVU_DEBUG_SEQ_FOPS(nix_qsize, nix_qsize_display, nix_qsize_write);
static void rvu_dbg_nix_init(struct rvu *rvu)
static void rvu_dbg_nix_init(struct rvu *rvu, int blkaddr)
{
const struct device *dev = &rvu->pdev->dev;
struct nix_hw *nix_hw;
struct dentry *pfile;
rvu->rvu_dbg.nix = debugfs_create_dir("nix", rvu->rvu_dbg.root);
if (!rvu->rvu_dbg.nix) {
dev_err(rvu->dev, "create debugfs dir failed for nix\n");
if (!is_block_implemented(rvu->hw, blkaddr))
return;
if (blkaddr == BLKADDR_NIX0) {
rvu->rvu_dbg.nix = debugfs_create_dir("nix", rvu->rvu_dbg.root);
if (!rvu->rvu_dbg.nix) {
dev_err(rvu->dev, "create debugfs dir failed for nix\n");
return;
}
nix_hw = &rvu->hw->nix[0];
} else {
rvu->rvu_dbg.nix = debugfs_create_dir("nix1",
rvu->rvu_dbg.root);
if (!rvu->rvu_dbg.nix) {
dev_err(rvu->dev,
"create debugfs dir failed for nix1\n");
return;
}
nix_hw = &rvu->hw->nix[1];
}
pfile = debugfs_create_file("sq_ctx", 0600, rvu->rvu_dbg.nix, rvu,
pfile = debugfs_create_file("sq_ctx", 0600, rvu->rvu_dbg.nix, nix_hw,
&rvu_dbg_nix_sq_ctx_fops);
if (!pfile)
goto create_failed;
pfile = debugfs_create_file("rq_ctx", 0600, rvu->rvu_dbg.nix, rvu,
pfile = debugfs_create_file("rq_ctx", 0600, rvu->rvu_dbg.nix, nix_hw,
&rvu_dbg_nix_rq_ctx_fops);
if (!pfile)
goto create_failed;
pfile = debugfs_create_file("cq_ctx", 0600, rvu->rvu_dbg.nix, rvu,
pfile = debugfs_create_file("cq_ctx", 0600, rvu->rvu_dbg.nix, nix_hw,
&rvu_dbg_nix_cq_ctx_fops);
if (!pfile)
goto create_failed;
pfile = debugfs_create_file("ndc_tx_cache", 0600, rvu->rvu_dbg.nix, rvu,
&rvu_dbg_nix_ndc_tx_cache_fops);
pfile = debugfs_create_file("ndc_tx_cache", 0600, rvu->rvu_dbg.nix,
nix_hw, &rvu_dbg_nix_ndc_tx_cache_fops);
if (!pfile)
goto create_failed;
pfile = debugfs_create_file("ndc_rx_cache", 0600, rvu->rvu_dbg.nix, rvu,
&rvu_dbg_nix_ndc_rx_cache_fops);
pfile = debugfs_create_file("ndc_rx_cache", 0600, rvu->rvu_dbg.nix,
nix_hw, &rvu_dbg_nix_ndc_rx_cache_fops);
if (!pfile)
goto create_failed;
pfile = debugfs_create_file("ndc_tx_hits_miss", 0600, rvu->rvu_dbg.nix,
rvu, &rvu_dbg_nix_ndc_tx_hits_miss_fops);
nix_hw,
&rvu_dbg_nix_ndc_tx_hits_miss_fops);
if (!pfile)
goto create_failed;
pfile = debugfs_create_file("ndc_rx_hits_miss", 0600, rvu->rvu_dbg.nix,
rvu, &rvu_dbg_nix_ndc_rx_hits_miss_fops);
nix_hw,
&rvu_dbg_nix_ndc_rx_hits_miss_fops);
if (!pfile)
goto create_failed;
......@@ -1312,7 +1431,8 @@ static void rvu_dbg_nix_init(struct rvu *rvu)
return;
create_failed:
dev_err(dev, "Failed to create debugfs dir/file for NIX\n");
dev_err(dev,
"Failed to create debugfs dir/file for NIX blk\n");
debugfs_remove_recursive(rvu->rvu_dbg.nix);
}
......@@ -1565,7 +1685,7 @@ static int rvu_dbg_npc_mcam_info_display(struct seq_file *filp, void *unsued)
struct rvu *rvu = filp->private;
int pf, vf, numvfs, blkaddr;
struct npc_mcam *mcam;
u16 pcifunc;
u16 pcifunc, counters;
u64 cfg;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
......@@ -1573,6 +1693,7 @@ static int rvu_dbg_npc_mcam_info_display(struct seq_file *filp, void *unsued)
return -ENODEV;
mcam = &rvu->hw->mcam;
counters = rvu->hw->npc_counters;
seq_puts(filp, "\nNPC MCAM info:\n");
/* MCAM keywidth on receive and transmit sides */
......@@ -1595,10 +1716,9 @@ static int rvu_dbg_npc_mcam_info_display(struct seq_file *filp, void *unsued)
seq_printf(filp, "\t\t Available \t: %d\n", mcam->bmap_fcnt);
/* MCAM counters */
cfg = rvu_read64(rvu, blkaddr, NPC_AF_CONST);
cfg = (cfg >> 48) & 0xFFFF;
seq_printf(filp, "\n\t\t MCAM counters \t: %lld\n", cfg);
seq_printf(filp, "\t\t Reserved \t: %lld\n", cfg - mcam->counters.max);
seq_printf(filp, "\n\t\t MCAM counters \t: %d\n", counters);
seq_printf(filp, "\t\t Reserved \t: %d\n",
counters - mcam->counters.max);
seq_printf(filp, "\t\t Available \t: %d\n",
rvu_rsrc_free_count(&mcam->counters));
......@@ -1691,8 +1811,15 @@ void rvu_dbg_init(struct rvu *rvu)
if (!pfile)
goto create_failed;
pfile = debugfs_create_file("rvu_pf_cgx_map", 0444, rvu->rvu_dbg.root,
rvu, &rvu_dbg_rvu_pf_cgx_map_fops);
if (!pfile)
goto create_failed;
rvu_dbg_npa_init(rvu);
rvu_dbg_nix_init(rvu);
rvu_dbg_nix_init(rvu, BLKADDR_NIX0);
rvu_dbg_nix_init(rvu, BLKADDR_NIX1);
rvu_dbg_cgx_init(rvu);
rvu_dbg_npc_init(rvu);
......
......@@ -68,6 +68,23 @@ struct mce {
u16 pcifunc;
};
int rvu_get_next_nix_blkaddr(struct rvu *rvu, int blkaddr)
{
int i = 0;
/*If blkaddr is 0, return the first nix block address*/
if (blkaddr == 0)
return rvu->nix_blkaddr[blkaddr];
while (i + 1 < MAX_NIX_BLKS) {
if (rvu->nix_blkaddr[i] == blkaddr)
return rvu->nix_blkaddr[i + 1];
i++;
}
return 0;
}
bool is_nixlf_attached(struct rvu *rvu, u16 pcifunc)
{
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
......@@ -81,14 +98,16 @@ bool is_nixlf_attached(struct rvu *rvu, u16 pcifunc)
int rvu_get_nixlf_count(struct rvu *rvu)
{
int blkaddr = 0, max = 0;
struct rvu_block *block;
int blkaddr;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);
if (blkaddr < 0)
return 0;
block = &rvu->hw->block[blkaddr];
return block->lf.max;
blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr);
while (blkaddr) {
block = &rvu->hw->block[blkaddr];
max += block->lf.max;
blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr);
}
return max;
}
int nix_get_nixlf(struct rvu *rvu, u16 pcifunc, int *nixlf, int *nix_blkaddr)
......@@ -130,11 +149,18 @@ static u16 nix_alloc_mce_list(struct nix_mcast *mcast, int count)
return idx;
}
static inline struct nix_hw *get_nix_hw(struct rvu_hwinfo *hw, int blkaddr)
struct nix_hw *get_nix_hw(struct rvu_hwinfo *hw, int blkaddr)
{
if (blkaddr == BLKADDR_NIX0 && hw->nix0)
return hw->nix0;
int nix_blkaddr = 0, i = 0;
struct rvu *rvu = hw->rvu;
nix_blkaddr = rvu_get_next_nix_blkaddr(rvu, nix_blkaddr);
while (nix_blkaddr) {
if (blkaddr == nix_blkaddr && hw->nix)
return &hw->nix[i];
nix_blkaddr = rvu_get_next_nix_blkaddr(rvu, nix_blkaddr);
i++;
}
return NULL;
}
......@@ -187,8 +213,8 @@ static bool is_valid_txschq(struct rvu *rvu, int blkaddr,
static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf)
{
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
int pkind, pf, vf, lbkid;
u8 cgx_id, lmac_id;
int pkind, pf, vf;
int err;
pf = rvu_get_pf(pcifunc);
......@@ -221,13 +247,24 @@ static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf)
case NIX_INTF_TYPE_LBK:
vf = (pcifunc & RVU_PFVF_FUNC_MASK) - 1;
/* If NIX1 block is present on the silicon then NIXes are
* assigned alternatively for lbk interfaces. NIX0 should
* send packets on lbk link 1 channels and NIX1 should send
* on lbk link 0 channels for the communication between
* NIX0 and NIX1.
*/
lbkid = 0;
if (rvu->hw->lbk_links > 1)
lbkid = vf & 0x1 ? 0 : 1;
/* Note that AF's VFs work in pairs and talk over consecutive
* loopback channels.Therefore if odd number of AF VFs are
* enabled then the last VF remains with no pair.
*/
pfvf->rx_chan_base = NIX_CHAN_LBK_CHX(0, vf);
pfvf->tx_chan_base = vf & 0x1 ? NIX_CHAN_LBK_CHX(0, vf - 1) :
NIX_CHAN_LBK_CHX(0, vf + 1);
pfvf->rx_chan_base = NIX_CHAN_LBK_CHX(lbkid, vf);
pfvf->tx_chan_base = vf & 0x1 ?
NIX_CHAN_LBK_CHX(lbkid, vf - 1) :
NIX_CHAN_LBK_CHX(lbkid, vf + 1);
pfvf->rx_chan_cnt = 1;
pfvf->tx_chan_cnt = 1;
rvu_npc_install_promisc_entry(rvu, pcifunc, nixlf,
......@@ -612,8 +649,9 @@ static int nix_aq_enqueue_wait(struct rvu *rvu, struct rvu_block *block,
return 0;
}
static int rvu_nix_aq_enq_inst(struct rvu *rvu, struct nix_aq_enq_req *req,
struct nix_aq_enq_rsp *rsp)
static int rvu_nix_blk_aq_enq_inst(struct rvu *rvu, struct nix_hw *nix_hw,
struct nix_aq_enq_req *req,
struct nix_aq_enq_rsp *rsp)
{
struct rvu_hwinfo *hw = rvu->hw;
u16 pcifunc = req->hdr.pcifunc;
......@@ -626,10 +664,7 @@ static int rvu_nix_aq_enq_inst(struct rvu *rvu, struct nix_aq_enq_req *req,
bool ena;
u64 cfg;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
if (blkaddr < 0)
return NIX_AF_ERR_AF_LF_INVALID;
blkaddr = nix_hw->blkaddr;
block = &hw->block[blkaddr];
aq = block->aq;
if (!aq) {
......@@ -669,8 +704,9 @@ static int rvu_nix_aq_enq_inst(struct rvu *rvu, struct nix_aq_enq_req *req,
break;
case NIX_AQ_CTYPE_MCE:
cfg = rvu_read64(rvu, blkaddr, NIX_AF_RX_MCAST_CFG);
/* Check if index exceeds MCE list length */
if (!hw->nix0->mcast.mce_ctx ||
if (!nix_hw->mcast.mce_ctx ||
(req->qidx >= (256UL << (cfg & 0xF))))
rc = NIX_AF_ERR_AQ_ENQUEUE;
......@@ -832,6 +868,23 @@ static int rvu_nix_aq_enq_inst(struct rvu *rvu, struct nix_aq_enq_req *req,
return 0;
}
static int rvu_nix_aq_enq_inst(struct rvu *rvu, struct nix_aq_enq_req *req,
struct nix_aq_enq_rsp *rsp)
{
struct nix_hw *nix_hw;
int blkaddr;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, req->hdr.pcifunc);
if (blkaddr < 0)
return NIX_AF_ERR_AF_LF_INVALID;
nix_hw = get_nix_hw(rvu->hw, blkaddr);
if (!nix_hw)
return -EINVAL;
return rvu_nix_blk_aq_enq_inst(rvu, nix_hw, req, rsp);
}
static const char *nix_get_ctx_name(int ctype)
{
switch (ctype) {
......@@ -1164,6 +1217,10 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST2);
rsp->qints = ((cfg >> 12) & 0xFFF);
rsp->cints = ((cfg >> 24) & 0xFFF);
rsp->cgx_links = hw->cgx_links;
rsp->lbk_links = hw->lbk_links;
rsp->sdp_links = hw->sdp_links;
return rc;
}
......@@ -1950,8 +2007,8 @@ int rvu_mbox_handler_nix_vtag_cfg(struct rvu *rvu,
return 0;
}
static int nix_setup_mce(struct rvu *rvu, int mce, u8 op,
u16 pcifunc, int next, bool eol)
static int nix_blk_setup_mce(struct rvu *rvu, struct nix_hw *nix_hw,
int mce, u8 op, u16 pcifunc, int next, bool eol)
{
struct nix_aq_enq_req aq_req;
int err;
......@@ -1971,7 +2028,7 @@ static int nix_setup_mce(struct rvu *rvu, int mce, u8 op,
/* All fields valid */
*(u64 *)(&aq_req.mce_mask) = ~0ULL;
err = rvu_nix_aq_enq_inst(rvu, &aq_req, NULL);
err = rvu_nix_blk_aq_enq_inst(rvu, nix_hw, &aq_req, NULL);
if (err) {
dev_err(rvu->dev, "Failed to setup Bcast MCE for PF%d:VF%d\n",
rvu_get_pf(pcifunc), pcifunc & RVU_PFVF_FUNC_MASK);
......@@ -2077,9 +2134,9 @@ int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add)
next_idx = idx + 1;
/* EOL should be set in last MCE */
err = nix_setup_mce(rvu, idx, NIX_AQ_INSTOP_WRITE,
mce->pcifunc, next_idx,
(next_idx > last_idx) ? true : false);
err = nix_blk_setup_mce(rvu, nix_hw, idx, NIX_AQ_INSTOP_WRITE,
mce->pcifunc, next_idx,
(next_idx > last_idx) ? true : false);
if (err)
goto end;
idx++;
......@@ -2108,6 +2165,11 @@ static int nix_setup_bcast_tables(struct rvu *rvu, struct nix_hw *nix_hw)
numvfs = (cfg >> 12) & 0xFF;
pfvf = &rvu->pf[pf];
/* This NIX0/1 block mapped to PF ? */
if (pfvf->nix_blkaddr != nix_hw->blkaddr)
continue;
/* Save the start MCE */
pfvf->bcast_mce_idx = nix_alloc_mce_list(mcast, numvfs + 1);
......@@ -2122,9 +2184,10 @@ static int nix_setup_bcast_tables(struct rvu *rvu, struct nix_hw *nix_hw)
* Will be updated when a NIXLF is attached/detached to
* these PF/VFs.
*/
err = nix_setup_mce(rvu, pfvf->bcast_mce_idx + idx,
NIX_AQ_INSTOP_INIT,
pcifunc, 0, true);
err = nix_blk_setup_mce(rvu, nix_hw,
pfvf->bcast_mce_idx + idx,
NIX_AQ_INSTOP_INIT,
pcifunc, 0, true);
if (err)
return err;
}
......@@ -3109,17 +3172,15 @@ static int nix_aq_init(struct rvu *rvu, struct rvu_block *block)
return 0;
}
int rvu_nix_init(struct rvu *rvu)
static int rvu_nix_block_init(struct rvu *rvu, struct nix_hw *nix_hw)
{
const struct npc_lt_def_cfg *ltdefs;
struct rvu_hwinfo *hw = rvu->hw;
int blkaddr = nix_hw->blkaddr;
struct rvu_block *block;
int blkaddr, err;
int err;
u64 cfg;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);
if (blkaddr < 0)
return 0;
block = &hw->block[blkaddr];
if (is_rvu_96xx_B0(rvu)) {
......@@ -3153,7 +3214,7 @@ int rvu_nix_init(struct rvu *rvu)
hw->cgx = (cfg >> 12) & 0xF;
hw->lmac_per_cgx = (cfg >> 8) & 0xF;
hw->cgx_links = hw->cgx * hw->lmac_per_cgx;
hw->lbk_links = 1;
hw->lbk_links = (cfg >> 24) & 0xF;
hw->sdp_links = 1;
/* Initialize admin queue */
......@@ -3164,26 +3225,21 @@ int rvu_nix_init(struct rvu *rvu)
/* Restore CINT timer delay to HW reset values */
rvu_write64(rvu, blkaddr, NIX_AF_CINT_DELAY, 0x0ULL);
if (blkaddr == BLKADDR_NIX0) {
hw->nix0 = devm_kzalloc(rvu->dev,
sizeof(struct nix_hw), GFP_KERNEL);
if (!hw->nix0)
return -ENOMEM;
err = nix_setup_txschq(rvu, hw->nix0, blkaddr);
if (is_block_implemented(hw, blkaddr)) {
err = nix_setup_txschq(rvu, nix_hw, blkaddr);
if (err)
return err;
err = nix_af_mark_format_setup(rvu, hw->nix0, blkaddr);
err = nix_af_mark_format_setup(rvu, nix_hw, blkaddr);
if (err)
return err;
err = nix_setup_mcast(rvu, hw->nix0, blkaddr);
err = nix_setup_mcast(rvu, nix_hw, blkaddr);
if (err)
return err;
/* Configure segmentation offload formats */
nix_setup_lso(rvu, hw->nix0, blkaddr);
nix_setup_lso(rvu, nix_hw, blkaddr);
/* Config Outer/Inner L2, IP, TCP, UDP and SCTP NPC layer info.
* This helps HW protocol checker to identify headers
......@@ -3236,23 +3292,44 @@ int rvu_nix_init(struct rvu *rvu)
return 0;
}
void rvu_nix_freemem(struct rvu *rvu)
int rvu_nix_init(struct rvu *rvu)
{
struct rvu_hwinfo *hw = rvu->hw;
struct rvu_block *block;
struct nix_hw *nix_hw;
int blkaddr = 0, err;
int i = 0;
hw->nix = devm_kcalloc(rvu->dev, MAX_NIX_BLKS, sizeof(struct nix_hw),
GFP_KERNEL);
if (!hw->nix)
return -ENOMEM;
blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr);
while (blkaddr) {
nix_hw = &hw->nix[i];
nix_hw->rvu = rvu;
nix_hw->blkaddr = blkaddr;
err = rvu_nix_block_init(rvu, nix_hw);
if (err)
return err;
blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr);
i++;
}
return 0;
}
static void rvu_nix_block_freemem(struct rvu *rvu, int blkaddr,
struct rvu_block *block)
{
struct nix_txsch *txsch;
struct nix_mcast *mcast;
struct nix_hw *nix_hw;
int blkaddr, lvl;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);
if (blkaddr < 0)
return;
int lvl;
block = &hw->block[blkaddr];
rvu_aq_free(rvu, block->aq);
if (blkaddr == BLKADDR_NIX0) {
if (is_block_implemented(rvu->hw, blkaddr)) {
nix_hw = get_nix_hw(rvu->hw, blkaddr);
if (!nix_hw)
return;
......@@ -3269,6 +3346,20 @@ void rvu_nix_freemem(struct rvu *rvu)
}
}
void rvu_nix_freemem(struct rvu *rvu)
{
struct rvu_hwinfo *hw = rvu->hw;
struct rvu_block *block;
int blkaddr = 0;
blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr);
while (blkaddr) {
block = &hw->block[blkaddr];
rvu_nix_block_freemem(rvu, blkaddr, block);
blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr);
}
}
int rvu_mbox_handler_nix_lf_start_rx(struct rvu *rvu, struct msg_req *req,
struct msg_rsp *rsp)
{
......
......@@ -36,6 +36,33 @@ static void npc_mcam_free_all_entries(struct rvu *rvu, struct npc_mcam *mcam,
static void npc_mcam_free_all_counters(struct rvu *rvu, struct npc_mcam *mcam,
u16 pcifunc);
bool is_npc_intf_tx(u8 intf)
{
return !!(intf & 0x1);
}
bool is_npc_intf_rx(u8 intf)
{
return !(intf & 0x1);
}
bool is_npc_interface_valid(struct rvu *rvu, u8 intf)
{
struct rvu_hwinfo *hw = rvu->hw;
return intf < hw->npc_intfs;
}
int rvu_npc_get_tx_nibble_cfg(struct rvu *rvu, u64 nibble_ena)
{
/* Due to a HW issue in these silicon versions, parse nibble enable
* configuration has to be identical for both Rx and Tx interfaces.
*/
if (is_rvu_96xx_B0(rvu))
return nibble_ena;
return 0;
}
void rvu_npc_set_pkind(struct rvu *rvu, int pkind, struct rvu_pfvf *pfvf)
{
int blkaddr;
......@@ -94,6 +121,31 @@ int npc_config_ts_kpuaction(struct rvu *rvu, int pf, u16 pcifunc, bool enable)
return 0;
}
static int npc_get_ucast_mcam_index(struct npc_mcam *mcam, u16 pcifunc,
int nixlf)
{
struct rvu_hwinfo *hw = container_of(mcam, struct rvu_hwinfo, mcam);
struct rvu *rvu = hw->rvu;
int blkaddr = 0, max = 0;
struct rvu_block *block;
struct rvu_pfvf *pfvf;
pfvf = rvu_get_pfvf(rvu, pcifunc);
/* Given a PF/VF and NIX LF number calculate the unicast mcam
* entry index based on the NIX block assigned to the PF/VF.
*/
blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr);
while (blkaddr) {
if (pfvf->nix_blkaddr == blkaddr)
break;
block = &rvu->hw->block[blkaddr];
max += block->lf.max;
blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr);
}
return mcam->nixlf_offset + (max + nixlf) * RSVD_MCAM_ENTRIES_PER_NIXLF;
}
static int npc_get_nixlf_mcam_index(struct npc_mcam *mcam,
u16 pcifunc, int nixlf, int type)
{
......@@ -114,7 +166,7 @@ static int npc_get_nixlf_mcam_index(struct npc_mcam *mcam,
return index + 1;
}
return (mcam->nixlf_offset + (nixlf * RSVD_MCAM_ENTRIES_PER_NIXLF));
return npc_get_ucast_mcam_index(mcam, pcifunc, nixlf);
}
static int npc_get_bank(struct npc_mcam *mcam, int index)
......@@ -413,7 +465,7 @@ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
entry.action = *(u64 *)&action;
npc_config_mcam_entry(rvu, mcam, blkaddr, index,
NIX_INTF_RX, &entry, true);
pfvf->nix_rx_intf, &entry, true);
/* add VLAN matching, setup action and save entry back for later */
entry.kw[0] |= (NPC_LT_LB_STAG_QINQ | NPC_LT_LB_CTAG) << 20;
......@@ -430,6 +482,7 @@ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
int nixlf, u64 chan, bool allmulti)
{
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
struct npc_mcam *mcam = &rvu->hw->mcam;
int blkaddr, ucast_idx, index, kwi;
struct mcam_entry entry = { {0} };
......@@ -473,7 +526,7 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
entry.action = *(u64 *)&action;
npc_config_mcam_entry(rvu, mcam, blkaddr, index,
NIX_INTF_RX, &entry, true);
pfvf->nix_rx_intf, &entry, true);
}
static void npc_enadis_promisc_entry(struct rvu *rvu, u16 pcifunc,
......@@ -531,6 +584,7 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
/* Get 'pcifunc' of PF device */
pcifunc = pcifunc & ~RVU_PFVF_FUNC_MASK;
pfvf = rvu_get_pfvf(rvu, pcifunc);
index = npc_get_nixlf_mcam_index(mcam, pcifunc,
nixlf, NIXLF_BCAST_ENTRY);
......@@ -553,14 +607,13 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
action.op = NIX_RX_ACTIONOP_UCAST;
action.pf_func = pcifunc;
} else {
pfvf = rvu_get_pfvf(rvu, pcifunc);
action.index = pfvf->bcast_mce_idx;
action.op = NIX_RX_ACTIONOP_MCAST;
}
entry.action = *(u64 *)&action;
npc_config_mcam_entry(rvu, mcam, blkaddr, index,
NIX_INTF_RX, &entry, true);
pfvf->nix_rx_intf, &entry, true);
}
void rvu_npc_enable_bcast_entry(struct rvu *rvu, u16 pcifunc, bool enable)
......@@ -732,44 +785,78 @@ void rvu_npc_disable_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf)
rvu_write64(rvu, blkaddr, \
NPC_AF_INTFX_LDATAX_FLAGSX_CFG(intf, ld, flags), cfg)
static void npc_program_mkex_profile(struct rvu *rvu, int blkaddr,
const struct npc_mcam_kex *mkex)
static void npc_program_mkex_rx(struct rvu *rvu, int blkaddr,
struct npc_mcam_kex *mkex, u8 intf)
{
int lid, lt, ld, fl;
rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(NIX_INTF_RX),
mkex->keyx_cfg[NIX_INTF_RX]);
rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(NIX_INTF_TX),
mkex->keyx_cfg[NIX_INTF_TX]);
if (is_npc_intf_tx(intf))
return;
for (ld = 0; ld < NPC_MAX_LD; ld++)
rvu_write64(rvu, blkaddr, NPC_AF_KEX_LDATAX_FLAGS_CFG(ld),
mkex->kex_ld_flags[ld]);
rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf),
mkex->keyx_cfg[NIX_INTF_RX]);
/* Program LDATA */
for (lid = 0; lid < NPC_MAX_LID; lid++) {
for (lt = 0; lt < NPC_MAX_LT; lt++) {
for (ld = 0; ld < NPC_MAX_LD; ld++) {
SET_KEX_LD(NIX_INTF_RX, lid, lt, ld,
for (ld = 0; ld < NPC_MAX_LD; ld++)
SET_KEX_LD(intf, lid, lt, ld,
mkex->intf_lid_lt_ld[NIX_INTF_RX]
[lid][lt][ld]);
SET_KEX_LD(NIX_INTF_TX, lid, lt, ld,
mkex->intf_lid_lt_ld[NIX_INTF_TX]
[lid][lt][ld]);
}
}
}
/* Program LFLAGS */
for (ld = 0; ld < NPC_MAX_LD; ld++) {
for (fl = 0; fl < NPC_MAX_LFL; fl++) {
SET_KEX_LDFLAGS(NIX_INTF_RX, ld, fl,
for (fl = 0; fl < NPC_MAX_LFL; fl++)
SET_KEX_LDFLAGS(intf, ld, fl,
mkex->intf_ld_flags[NIX_INTF_RX]
[ld][fl]);
}
}
static void npc_program_mkex_tx(struct rvu *rvu, int blkaddr,
struct npc_mcam_kex *mkex, u8 intf)
{
int lid, lt, ld, fl;
SET_KEX_LDFLAGS(NIX_INTF_TX, ld, fl,
if (is_npc_intf_rx(intf))
return;
rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf),
mkex->keyx_cfg[NIX_INTF_TX]);
/* Program LDATA */
for (lid = 0; lid < NPC_MAX_LID; lid++) {
for (lt = 0; lt < NPC_MAX_LT; lt++) {
for (ld = 0; ld < NPC_MAX_LD; ld++)
SET_KEX_LD(intf, lid, lt, ld,
mkex->intf_lid_lt_ld[NIX_INTF_TX]
[lid][lt][ld]);
}
}
/* Program LFLAGS */
for (ld = 0; ld < NPC_MAX_LD; ld++) {
for (fl = 0; fl < NPC_MAX_LFL; fl++)
SET_KEX_LDFLAGS(intf, ld, fl,
mkex->intf_ld_flags[NIX_INTF_TX]
[ld][fl]);
}
}
}
static void npc_program_mkex_profile(struct rvu *rvu, int blkaddr,
struct npc_mcam_kex *mkex)
{
struct rvu_hwinfo *hw = rvu->hw;
u8 intf;
int ld;
for (ld = 0; ld < NPC_MAX_LD; ld++)
rvu_write64(rvu, blkaddr, NPC_AF_KEX_LDATAX_FLAGS_CFG(ld),
mkex->kex_ld_flags[ld]);
for (intf = 0; intf < hw->npc_intfs; intf++) {
npc_program_mkex_rx(rvu, blkaddr, mkex, intf);
npc_program_mkex_tx(rvu, blkaddr, mkex, intf);
}
}
......@@ -909,7 +996,7 @@ static void npc_program_kpu_profile(struct rvu *rvu, int blkaddr, int kpu,
kpu, profile->cam_entries, profile->action_entries);
}
max_entries = rvu_read64(rvu, blkaddr, NPC_AF_CONST1) & 0xFFF;
max_entries = rvu->hw->npc_kpu_entries;
/* Program CAM match entries for previous KPU extracted data */
num_entries = min_t(int, profile->cam_entries, max_entries);
......@@ -964,9 +1051,6 @@ static void npc_parser_profile_init(struct rvu *rvu, int blkaddr)
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,
......@@ -1005,12 +1089,6 @@ static int npc_mcam_rsrcs_init(struct rvu *rvu, int blkaddr)
int rsvd, err;
u64 cfg;
/* Get HW limits */
cfg = rvu_read64(rvu, blkaddr, NPC_AF_CONST);
mcam->banks = (cfg >> 44) & 0xF;
mcam->banksize = (cfg >> 28) & 0xFFFF;
mcam->counters.max = (cfg >> 48) & 0xFFFF;
/* Actual number of MCAM entries vary by entry size */
cfg = (rvu_read64(rvu, blkaddr,
NPC_AF_INTFX_KEX_CFG(0)) >> 32) & 0x07;
......@@ -1077,12 +1155,6 @@ static int npc_mcam_rsrcs_init(struct rvu *rvu, int blkaddr)
mcam->hprio_count = mcam->lprio_count;
mcam->hprio_end = mcam->hprio_count;
/* Reserve last counter for MCAM RX miss action which is set to
* drop pkt. This way we will know how many pkts didn't match
* any MCAM entry.
*/
mcam->counters.max--;
mcam->rx_miss_act_cntr = mcam->counters.max;
/* Allocate bitmap for managing MCAM counters and memory
* for saving counter to RVU PFFUNC allocation mapping.
......@@ -1118,12 +1190,110 @@ static int npc_mcam_rsrcs_init(struct rvu *rvu, int blkaddr)
return -ENOMEM;
}
static void rvu_npc_hw_init(struct rvu *rvu, int blkaddr)
{
struct npc_pkind *pkind = &rvu->hw->pkind;
struct npc_mcam *mcam = &rvu->hw->mcam;
struct rvu_hwinfo *hw = rvu->hw;
u64 npc_const, npc_const1;
u64 npc_const2 = 0;
npc_const = rvu_read64(rvu, blkaddr, NPC_AF_CONST);
npc_const1 = rvu_read64(rvu, blkaddr, NPC_AF_CONST1);
if (npc_const1 & BIT_ULL(63))
npc_const2 = rvu_read64(rvu, blkaddr, NPC_AF_CONST2);
pkind->rsrc.max = (npc_const1 >> 12) & 0xFFULL;
hw->npc_kpu_entries = npc_const1 & 0xFFFULL;
hw->npc_kpus = (npc_const >> 8) & 0x1FULL;
hw->npc_intfs = npc_const & 0xFULL;
hw->npc_counters = (npc_const >> 48) & 0xFFFFULL;
mcam->banks = (npc_const >> 44) & 0xFULL;
mcam->banksize = (npc_const >> 28) & 0xFFFFULL;
/* Extended set */
if (npc_const2) {
hw->npc_ext_set = true;
hw->npc_counters = (npc_const2 >> 16) & 0xFFFFULL;
mcam->banksize = npc_const2 & 0xFFFFULL;
}
mcam->counters.max = hw->npc_counters;
}
static void rvu_npc_setup_interfaces(struct rvu *rvu, int blkaddr)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
struct rvu_hwinfo *hw = rvu->hw;
u64 nibble_ena, rx_kex, tx_kex;
u8 intf;
/* Reserve last counter for MCAM RX miss action which is set to
* drop packet. This way we will know how many pkts didn't match
* any MCAM entry.
*/
mcam->counters.max--;
mcam->rx_miss_act_cntr = mcam->counters.max;
rx_kex = npc_mkex_default.keyx_cfg[NIX_INTF_RX];
tx_kex = npc_mkex_default.keyx_cfg[NIX_INTF_TX];
nibble_ena = FIELD_GET(NPC_PARSE_NIBBLE, rx_kex);
nibble_ena = rvu_npc_get_tx_nibble_cfg(rvu, nibble_ena);
if (nibble_ena) {
tx_kex &= ~NPC_PARSE_NIBBLE;
tx_kex |= FIELD_PREP(NPC_PARSE_NIBBLE, nibble_ena);
npc_mkex_default.keyx_cfg[NIX_INTF_TX] = tx_kex;
}
/* Configure RX interfaces */
for (intf = 0; intf < hw->npc_intfs; intf++) {
if (is_npc_intf_tx(intf))
continue;
/* Set RX MCAM search key size. LA..LE (ltype only) + Channel */
rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf),
rx_kex);
/* If MCAM lookup doesn't result in a match, drop the received
* packet. And map this action to a counter to count dropped
* packets.
*/
rvu_write64(rvu, blkaddr,
NPC_AF_INTFX_MISS_ACT(intf), NIX_RX_ACTIONOP_DROP);
/* NPC_AF_INTFX_MISS_STAT_ACT[14:12] - counter[11:9]
* NPC_AF_INTFX_MISS_STAT_ACT[8:0] - counter[8:0]
*/
rvu_write64(rvu, blkaddr,
NPC_AF_INTFX_MISS_STAT_ACT(intf),
((mcam->rx_miss_act_cntr >> 9) << 12) |
BIT_ULL(9) | mcam->rx_miss_act_cntr);
}
/* Configure TX interfaces */
for (intf = 0; intf < hw->npc_intfs; intf++) {
if (is_npc_intf_rx(intf))
continue;
/* Extract Ltypes LID_LA to LID_LE */
rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf),
tx_kex);
/* Set TX miss action to UCAST_DEFAULT i.e
* transmit the packet on NIX LF SQ's default channel.
*/
rvu_write64(rvu, blkaddr,
NPC_AF_INTFX_MISS_ACT(intf),
NIX_TX_ACTIONOP_UCAST_DEFAULT);
}
}
int rvu_npc_init(struct rvu *rvu)
{
struct npc_kpu_profile_adapter *kpu = &rvu->kpu;
struct npc_pkind *pkind = &rvu->hw->pkind;
struct npc_mcam *mcam = &rvu->hw->mcam;
u64 cfg, nibble_ena, rx_kex, tx_kex;
int blkaddr, entry, bank, err;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
......@@ -1132,17 +1302,15 @@ int rvu_npc_init(struct rvu *rvu)
return -ENODEV;
}
rvu_npc_hw_init(rvu, blkaddr);
/* First disable all MCAM entries, to stop traffic towards NIXLFs */
cfg = rvu_read64(rvu, blkaddr, NPC_AF_CONST);
for (bank = 0; bank < ((cfg >> 44) & 0xF); bank++) {
for (entry = 0; entry < ((cfg >> 28) & 0xFFFF); entry++)
for (bank = 0; bank < mcam->banks; bank++) {
for (entry = 0; entry < mcam->banksize; entry++)
rvu_write64(rvu, blkaddr,
NPC_AF_MCAMEX_BANKX_CFG(entry, bank), 0);
}
/* 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;
......@@ -1180,21 +1348,7 @@ int rvu_npc_init(struct rvu *rvu)
BIT_ULL(32) | BIT_ULL(24) | BIT_ULL(6) |
BIT_ULL(2) | BIT_ULL(1));
/* Set RX and TX side MCAM search key size.
* LA..LD (ltype only) + Channel
*/
rx_kex = npc_mkex_default.keyx_cfg[NIX_INTF_RX];
tx_kex = npc_mkex_default.keyx_cfg[NIX_INTF_TX];
nibble_ena = FIELD_GET(NPC_PARSE_NIBBLE, rx_kex);
rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(NIX_INTF_RX), rx_kex);
/* Due to an errata (35786) in A0 pass silicon, parse nibble enable
* configuration has to be identical for both Rx and Tx interfaces.
*/
if (is_rvu_96xx_B0(rvu)) {
tx_kex &= ~NPC_PARSE_NIBBLE;
tx_kex |= FIELD_PREP(NPC_PARSE_NIBBLE, nibble_ena);
}
rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(NIX_INTF_TX), tx_kex);
rvu_npc_setup_interfaces(rvu, blkaddr);
err = npc_mcam_rsrcs_init(rvu, blkaddr);
if (err)
......@@ -1203,20 +1357,6 @@ int rvu_npc_init(struct rvu *rvu)
/* Configure MKEX profile */
npc_load_mkex_profile(rvu, blkaddr, rvu->mkex_pfl_name);
/* Set TX miss action to UCAST_DEFAULT i.e
* transmit the packet on NIX LF SQ's default channel.
*/
rvu_write64(rvu, blkaddr, NPC_AF_INTFX_MISS_ACT(NIX_INTF_TX),
NIX_TX_ACTIONOP_UCAST_DEFAULT);
/* If MCAM lookup doesn't result in a match, drop the received packet.
* And map this action to a counter to count dropped pkts.
*/
rvu_write64(rvu, blkaddr, NPC_AF_INTFX_MISS_ACT(NIX_INTF_RX),
NIX_RX_ACTIONOP_DROP);
rvu_write64(rvu, blkaddr, NPC_AF_INTFX_MISS_STAT_ACT(NIX_INTF_RX),
BIT_ULL(9) | mcam->rx_miss_act_cntr);
return 0;
}
......@@ -1307,10 +1447,13 @@ static void npc_map_mcam_entry_and_cntr(struct rvu *rvu, struct npc_mcam *mcam,
/* Set mapping and increment counter's refcnt */
mcam->entry2cntr_map[entry] = cntr;
mcam->cntr_refcnt[cntr]++;
/* Enable stats */
/* Enable stats
* NPC_AF_MCAMEX_BANKX_STAT_ACT[14:12] - counter[11:9]
* NPC_AF_MCAMEX_BANKX_STAT_ACT[8:0] - counter[8:0]
*/
rvu_write64(rvu, blkaddr,
NPC_AF_MCAMEX_BANKX_STAT_ACT(index, bank),
BIT_ULL(9) | cntr);
((cntr >> 9) << 12) | BIT_ULL(9) | cntr);
}
static void npc_unmap_mcam_entry_and_cntr(struct rvu *rvu,
......@@ -1789,9 +1932,11 @@ int rvu_mbox_handler_npc_mcam_write_entry(struct rvu *rvu,
struct npc_mcam_write_entry_req *req,
struct msg_rsp *rsp)
{
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc);
struct npc_mcam *mcam = &rvu->hw->mcam;
u16 pcifunc = req->hdr.pcifunc;
int blkaddr, rc;
u8 nix_intf;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0)
......@@ -1808,12 +1953,17 @@ int rvu_mbox_handler_npc_mcam_write_entry(struct rvu *rvu,
goto exit;
}
if (req->intf != NIX_INTF_RX && req->intf != NIX_INTF_TX) {
if (!is_npc_interface_valid(rvu, req->intf)) {
rc = NPC_MCAM_INVALID_REQ;
goto exit;
}
npc_config_mcam_entry(rvu, mcam, blkaddr, req->entry, req->intf,
if (is_npc_intf_tx(req->intf))
nix_intf = pfvf->nix_tx_intf;
else
nix_intf = pfvf->nix_rx_intf;
npc_config_mcam_entry(rvu, mcam, blkaddr, req->entry, nix_intf,
&req->entry_data, req->enable_entry);
if (req->set_cntr)
......@@ -2141,6 +2291,7 @@ int rvu_mbox_handler_npc_mcam_alloc_and_write_entry(struct rvu *rvu,
struct npc_mcam_alloc_and_write_entry_req *req,
struct npc_mcam_alloc_and_write_entry_rsp *rsp)
{
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc);
struct npc_mcam_alloc_counter_req cntr_req;
struct npc_mcam_alloc_counter_rsp cntr_rsp;
struct npc_mcam_alloc_entry_req entry_req;
......@@ -2149,12 +2300,13 @@ int rvu_mbox_handler_npc_mcam_alloc_and_write_entry(struct rvu *rvu,
u16 entry = NPC_MCAM_ENTRY_INVALID;
u16 cntr = NPC_MCAM_ENTRY_INVALID;
int blkaddr, rc;
u8 nix_intf;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0)
return NPC_MCAM_INVALID_REQ;
if (req->intf != NIX_INTF_RX && req->intf != NIX_INTF_TX)
if (!is_npc_interface_valid(rvu, req->intf))
return NPC_MCAM_INVALID_REQ;
/* Try to allocate a MCAM entry */
......@@ -2196,7 +2348,13 @@ int rvu_mbox_handler_npc_mcam_alloc_and_write_entry(struct rvu *rvu,
write_entry:
mutex_lock(&mcam->lock);
npc_config_mcam_entry(rvu, mcam, blkaddr, entry, req->intf,
if (is_npc_intf_tx(req->intf))
nix_intf = pfvf->nix_tx_intf;
else
nix_intf = pfvf->nix_rx_intf;
npc_config_mcam_entry(rvu, mcam, blkaddr, entry, nix_intf,
&req->entry_data, req->enable_entry);
if (req->alloc_cntr)
......@@ -2274,7 +2432,7 @@ int rvu_npc_update_rxvlan(struct rvu *rvu, u16 pcifunc, int nixlf)
pfvf->entry.action = npc_get_mcam_action(rvu, mcam, blkaddr, index);
enable = is_mcam_entry_enabled(rvu, mcam, blkaddr, index);
npc_config_mcam_entry(rvu, mcam, blkaddr, pfvf->rxvlan_index,
NIX_INTF_RX, &pfvf->entry, enable);
pfvf->nix_rx_intf, &pfvf->entry, enable);
return 0;
}
......@@ -35,7 +35,7 @@ static struct hw_reg_map txsch_reg_map[NIX_TXSCH_LVL_CNT] = {
{0x1200, 0x12E0} } },
{NIX_TXSCH_LVL_TL3, 3, 0xFFFF, {{0x1000, 0x10E0}, {0x1600, 0x1608},
{0x1610, 0x1618} } },
{NIX_TXSCH_LVL_TL2, 2, 0xFFFF, {{0x0E00, 0x0EE0}, {0x1700, 0x1768} } },
{NIX_TXSCH_LVL_TL2, 2, 0xFFFF, {{0x0E00, 0x0EE0}, {0x1700, 0x17B0} } },
{NIX_TXSCH_LVL_TL1, 1, 0xFFFF, {{0x0C00, 0x0D98} } },
};
......
......@@ -54,20 +54,20 @@
#define RVU_PRIV_PFX_MSIX_CFG(a) (0x8000110 | (a) << 16)
#define RVU_PRIV_PFX_ID_CFG(a) (0x8000120 | (a) << 16)
#define RVU_PRIV_PFX_INT_CFG(a) (0x8000200 | (a) << 16)
#define RVU_PRIV_PFX_NIX0_CFG (0x8000300)
#define RVU_PRIV_PFX_NIXX_CFG(a) (0x8000300 | (a) << 3)
#define RVU_PRIV_PFX_NPA_CFG (0x8000310)
#define RVU_PRIV_PFX_SSO_CFG (0x8000320)
#define RVU_PRIV_PFX_SSOW_CFG (0x8000330)
#define RVU_PRIV_PFX_TIM_CFG (0x8000340)
#define RVU_PRIV_PFX_CPT0_CFG (0x8000350)
#define RVU_PRIV_PFX_CPTX_CFG(a) (0x8000350 | (a) << 3)
#define RVU_PRIV_BLOCK_TYPEX_REV(a) (0x8000400 | (a) << 3)
#define RVU_PRIV_HWVFX_INT_CFG(a) (0x8001280 | (a) << 16)
#define RVU_PRIV_HWVFX_NIX0_CFG (0x8001300)
#define RVU_PRIV_HWVFX_NIXX_CFG(a) (0x8001300 | (a) << 3)
#define RVU_PRIV_HWVFX_NPA_CFG (0x8001310)
#define RVU_PRIV_HWVFX_SSO_CFG (0x8001320)
#define RVU_PRIV_HWVFX_SSOW_CFG (0x8001330)
#define RVU_PRIV_HWVFX_TIM_CFG (0x8001340)
#define RVU_PRIV_HWVFX_CPT0_CFG (0x8001350)
#define RVU_PRIV_HWVFX_CPTX_CFG(a) (0x8001350 | (a) << 3)
/* RVU PF registers */
#define RVU_PF_VFX_PFVF_MBOX0 (0x00000)
......@@ -446,6 +446,8 @@
#define NPC_AF_BLK_RST (0x00040)
#define NPC_AF_MCAM_SCRUB_CTL (0x000a0)
#define NPC_AF_KCAM_SCRUB_CTL (0x000b0)
#define NPC_AF_CONST2 (0x00100)
#define NPC_AF_CONST3 (0x00110)
#define NPC_AF_KPUX_CFG(a) (0x00500 | (a) << 3)
#define NPC_AF_PCK_CFG (0x00600)
#define NPC_AF_PCK_DEF_OL2 (0x00610)
......@@ -469,20 +471,7 @@
(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)
......@@ -499,6 +488,70 @@
#define NPC_AF_DBG_DATAX(a) (0x3001400 | (a) << 4)
#define NPC_AF_DBG_RESULTX(a) (0x3001800 | (a) << 4)
#define NPC_AF_MCAMEX_BANKX_CAMX_INTF(a, b, c) ({ \
u64 offset; \
\
offset = (0x1000000ull | (a) << 10 | (b) << 6 | (c) << 3); \
if (rvu->hw->npc_ext_set) \
offset = (0x8000000ull | (a) << 8 | (b) << 22 | (c) << 3); \
offset; })
#define NPC_AF_MCAMEX_BANKX_CAMX_W0(a, b, c) ({ \
u64 offset; \
\
offset = (0x1000010ull | (a) << 10 | (b) << 6 | (c) << 3); \
if (rvu->hw->npc_ext_set) \
offset = (0x8000010ull | (a) << 8 | (b) << 22 | (c) << 3); \
offset; })
#define NPC_AF_MCAMEX_BANKX_CAMX_W1(a, b, c) ({ \
u64 offset; \
\
offset = (0x1000020ull | (a) << 10 | (b) << 6 | (c) << 3); \
if (rvu->hw->npc_ext_set) \
offset = (0x8000020ull | (a) << 8 | (b) << 22 | (c) << 3); \
offset; })
#define NPC_AF_MCAMEX_BANKX_CFG(a, b) ({ \
u64 offset; \
\
offset = (0x1800000ull | (a) << 8 | (b) << 4); \
if (rvu->hw->npc_ext_set) \
offset = (0x8000038ull | (a) << 8 | (b) << 22); \
offset; })
#define NPC_AF_MCAMEX_BANKX_ACTION(a, b) ({ \
u64 offset; \
\
offset = (0x1900000ull | (a) << 8 | (b) << 4); \
if (rvu->hw->npc_ext_set) \
offset = (0x8000040ull | (a) << 8 | (b) << 22); \
offset; }) \
#define NPC_AF_MCAMEX_BANKX_TAG_ACT(a, b) ({ \
u64 offset; \
\
offset = (0x1900008ull | (a) << 8 | (b) << 4); \
if (rvu->hw->npc_ext_set) \
offset = (0x8000048ull | (a) << 8 | (b) << 22); \
offset; }) \
#define NPC_AF_MCAMEX_BANKX_STAT_ACT(a, b) ({ \
u64 offset; \
\
offset = (0x1880000ull | (a) << 8 | (b) << 4); \
if (rvu->hw->npc_ext_set) \
offset = (0x8000050ull | (a) << 8 | (b) << 22); \
offset; }) \
#define NPC_AF_MATCH_STATX(a) ({ \
u64 offset; \
\
offset = (0x1880008ull | (a) << 8); \
if (rvu->hw->npc_ext_set) \
offset = (0x8000078ull | (a) << 8); \
offset; }) \
/* NDC */
#define NDC_AF_CONST (0x00000)
#define NDC_AF_CLK_EN (0x00020)
......
......@@ -14,6 +14,8 @@
/* RVU Block revision IDs */
#define RVU_BLK_RVUM_REVID 0x01
#define RVU_MULTI_BLK_VER 0x7ULL
/* RVU Block Address Enumeration */
enum rvu_block_addr_e {
BLKADDR_RVUM = 0x0ULL,
......@@ -31,7 +33,9 @@ enum rvu_block_addr_e {
BLKADDR_NDC_NIX0_RX = 0xcULL,
BLKADDR_NDC_NIX0_TX = 0xdULL,
BLKADDR_NDC_NPA0 = 0xeULL,
BLK_COUNT = 0xfULL,
BLKADDR_NDC_NIX1_RX = 0x10ULL,
BLKADDR_NDC_NIX1_TX = 0x11ULL,
BLK_COUNT = 0x12ULL,
};
/* RVU Block Type Enumeration */
......
......@@ -531,8 +531,10 @@ static int otx2_get_link(struct otx2_nic *pfvf)
link = 4 * ((map >> 8) & 0xF) + ((map >> 4) & 0xF);
}
/* LBK channel */
if (pfvf->hw.tx_chan_base < SDP_CHAN_BASE)
link = 12;
if (pfvf->hw.tx_chan_base < SDP_CHAN_BASE) {
map = pfvf->hw.tx_chan_base & 0x7FF;
link = pfvf->hw.cgx_links | ((map >> 8) & 0xF);
}
return link;
}
......@@ -1503,6 +1505,8 @@ void mbox_handler_nix_lf_alloc(struct otx2_nic *pfvf,
pfvf->hw.tx_chan_base = rsp->tx_chan_base;
pfvf->hw.lso_tsov4_idx = rsp->lso_tsov4_idx;
pfvf->hw.lso_tsov6_idx = rsp->lso_tsov6_idx;
pfvf->hw.cgx_links = rsp->cgx_links;
pfvf->hw.lbk_links = rsp->lbk_links;
}
EXPORT_SYMBOL(mbox_handler_nix_lf_alloc);
......
......@@ -197,6 +197,8 @@ struct otx2_hw {
struct otx2_drv_stats drv_stats;
u64 cgx_rx_stats[CGX_RX_STATS_COUNT];
u64 cgx_tx_stats[CGX_TX_STATS_COUNT];
u8 cgx_links; /* No. of CGX links present in HW */
u8 lbk_links; /* No. of LBK links present in HW */
};
struct otx2_vf_config {
......
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