Commit c5a73b63 authored by Subbaraya Sundeep's avatar Subbaraya Sundeep Committed by Jakub Kicinski

octeontx2-af: Map NIX block from CGX connection

Firmware configures NIX block mapping for all CGXs
to achieve maximum throughput. This patch reads
the configuration and create mapping between RVU
PF and NIX blocks. And for LBK VFs assign NIX0 for
even numbered VFs and NIX1 for odd numbered VFs.
Signed-off-by: default avatarSubbaraya Sundeep <sbhatta@marvell.com>
Signed-off-by: default avatarSunil Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarRakesh Babu <rsaladi2@marvell.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 221f3dff
......@@ -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 */
......@@ -1252,6 +1252,58 @@ int rvu_mbox_handler_detach_resources(struct rvu *rvu,
return rvu_detach_rsrcs(rvu, detach, detach->hdr.pcifunc);
}
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;
break;
case BLKADDR_NIX0:
default:
pfvf->nix_blkaddr = BLKADDR_NIX0;
break;
}
return pfvf->nix_blkaddr;
}
static int rvu_get_attach_blkaddr(struct rvu *rvu, int blktype, u16 pcifunc)
{
int blkaddr;
switch (blktype) {
case BLKTYPE_NIX:
blkaddr = rvu_get_nix_blkaddr(rvu, pcifunc);
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)
{
......@@ -1265,7 +1317,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);
if (blkaddr < 0)
return;
......@@ -1294,9 +1346,9 @@ 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 && !is_blktype_attached(pfvf, BLKTYPE_NPA)) {
......@@ -1313,7 +1365,10 @@ static int rvu_check_rsrc_availability(struct rvu *rvu,
/* Only one NIX LF can be attached */
if (req->nixlf && !is_blktype_attached(pfvf, BLKTYPE_NIX)) {
block = &hw->block[BLKADDR_NIX0];
blkaddr = rvu_get_attach_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
if (blkaddr < 0)
return blkaddr;
block = &hw->block[blkaddr];
free_lfs = rvu_rsrc_free_count(&block->lf);
if (!free_lfs)
goto fail;
......
......@@ -184,6 +184,8 @@ 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 */
};
struct nix_txsch {
......
......@@ -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++;
}
}
......
......@@ -213,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);
......@@ -247,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,
......@@ -3183,7 +3194,7 @@ static int rvu_nix_block_init(struct rvu *rvu, struct nix_hw *nix_hw)
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 */
......
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