octeontx2-af: Support to modify min/max allowed packet lengths
This patch adds support for RVU PF/VFs to modify min/max packet lengths allowed by HW. For VFs on PF0, settings will be automatically applied on LBK link. RX link's min/maxlen is configured to min/max of PF and it's all VFs. On the TX side if requested all SMQs attached to the requesting NIXLF will be updated with new min/max lengths. Also updates transmit credits for Tx links based on new maxlen. Signed-off-by: Sunil Goutham <sgoutham@marvell.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
eac66686c6
commit
9b7dd87ac0
@ -22,6 +22,7 @@
|
||||
|
||||
#define MAX_CGX 3
|
||||
#define MAX_LMAC_PER_CGX 4
|
||||
#define CGX_FIFO_LEN 65536 /* 64K for both Rx & Tx */
|
||||
#define CGX_OFFSET(x) ((x) * MAX_LMAC_PER_CGX)
|
||||
|
||||
/* Registers */
|
||||
|
@ -143,6 +143,11 @@ enum nix_scheduler {
|
||||
NIX_TXSCH_LVL_CNT = 0x5,
|
||||
};
|
||||
|
||||
/* Min/Max packet sizes, excluding FCS */
|
||||
#define NIC_HW_MIN_FRS 40
|
||||
#define NIC_HW_MAX_FRS 9212
|
||||
#define SDP_HW_MAX_FRS 65535
|
||||
|
||||
/* NIX RX action operation*/
|
||||
#define NIX_RX_ACTIONOP_DROP (0x0ull)
|
||||
#define NIX_RX_ACTIONOP_UCAST (0x1ull)
|
||||
|
@ -165,7 +165,8 @@ M(NIX_VTAG_CFG, 0x8008, nix_vtag_cfg, nix_vtag_config, msg_rsp) \
|
||||
M(NIX_RSS_FLOWKEY_CFG, 0x8009, nix_rss_flowkey_cfg, \
|
||||
nix_rss_flowkey_cfg, msg_rsp) \
|
||||
M(NIX_SET_MAC_ADDR, 0x800a, nix_set_mac_addr, nix_set_mac_addr, msg_rsp) \
|
||||
M(NIX_SET_RX_MODE, 0x800b, nix_set_rx_mode, nix_rx_mode, msg_rsp)
|
||||
M(NIX_SET_RX_MODE, 0x800b, nix_set_rx_mode, nix_rx_mode, msg_rsp) \
|
||||
M(NIX_SET_HW_FRS, 0x800c, nix_set_hw_frs, nix_frs_cfg, msg_rsp)
|
||||
|
||||
/* Messages initiated by AF (range 0xC00 - 0xDFF) */
|
||||
#define MBOX_UP_CGX_MESSAGES \
|
||||
@ -527,4 +528,13 @@ struct nix_rx_mode {
|
||||
u16 mode;
|
||||
};
|
||||
|
||||
struct nix_frs_cfg {
|
||||
struct mbox_msghdr hdr;
|
||||
u8 update_smq; /* Update SMQ's min/max lens */
|
||||
u8 update_minlen; /* Set minlen also */
|
||||
u8 sdp_link; /* Set SDP RX link */
|
||||
u16 maxlen;
|
||||
u16 minlen;
|
||||
};
|
||||
|
||||
#endif /* MBOX_H */
|
||||
|
@ -122,6 +122,8 @@ struct rvu_pfvf {
|
||||
u16 tx_chan_base;
|
||||
u8 rx_chan_cnt; /* total number of RX channels */
|
||||
u8 tx_chan_cnt; /* total number of TX channels */
|
||||
u16 maxlen;
|
||||
u16 minlen;
|
||||
|
||||
u8 mac_addr[ETH_ALEN]; /* MAC address of this PF/VF */
|
||||
|
||||
@ -349,6 +351,8 @@ int rvu_mbox_handler_nix_set_mac_addr(struct rvu *rvu,
|
||||
struct msg_rsp *rsp);
|
||||
int rvu_mbox_handler_nix_set_rx_mode(struct rvu *rvu, struct nix_rx_mode *req,
|
||||
struct msg_rsp *rsp);
|
||||
int rvu_mbox_handler_nix_set_hw_frs(struct rvu *rvu, struct nix_frs_cfg *req,
|
||||
struct msg_rsp *rsp);
|
||||
|
||||
/* NPC APIs */
|
||||
int rvu_npc_init(struct rvu *rvu);
|
||||
|
@ -168,14 +168,20 @@ static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf)
|
||||
|
||||
rvu_npc_install_bcast_match_entry(rvu, pcifunc,
|
||||
nixlf, pfvf->rx_chan_base);
|
||||
pfvf->maxlen = NIC_HW_MIN_FRS;
|
||||
pfvf->minlen = NIC_HW_MIN_FRS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nix_interface_deinit(struct rvu *rvu, u16 pcifunc, u8 nixlf)
|
||||
{
|
||||
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
|
||||
int err;
|
||||
|
||||
pfvf->maxlen = 0;
|
||||
pfvf->minlen = 0;
|
||||
|
||||
/* Remove this PF_FUNC from bcast pkt replication list */
|
||||
err = nix_update_bcast_mce_list(rvu, pcifunc, false);
|
||||
if (err) {
|
||||
@ -1778,6 +1784,196 @@ int rvu_mbox_handler_nix_set_rx_mode(struct rvu *rvu, struct nix_rx_mode *req,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nix_find_link_frs(struct rvu *rvu,
|
||||
struct nix_frs_cfg *req, u16 pcifunc)
|
||||
{
|
||||
int pf = rvu_get_pf(pcifunc);
|
||||
struct rvu_pfvf *pfvf;
|
||||
int maxlen, minlen;
|
||||
int numvfs, hwvf;
|
||||
int vf;
|
||||
|
||||
/* Update with requester's min/max lengths */
|
||||
pfvf = rvu_get_pfvf(rvu, pcifunc);
|
||||
pfvf->maxlen = req->maxlen;
|
||||
if (req->update_minlen)
|
||||
pfvf->minlen = req->minlen;
|
||||
|
||||
maxlen = req->maxlen;
|
||||
minlen = req->update_minlen ? req->minlen : 0;
|
||||
|
||||
/* Get this PF's numVFs and starting hwvf */
|
||||
rvu_get_pf_numvfs(rvu, pf, &numvfs, &hwvf);
|
||||
|
||||
/* For each VF, compare requested max/minlen */
|
||||
for (vf = 0; vf < numvfs; vf++) {
|
||||
pfvf = &rvu->hwvf[hwvf + vf];
|
||||
if (pfvf->maxlen > maxlen)
|
||||
maxlen = pfvf->maxlen;
|
||||
if (req->update_minlen &&
|
||||
pfvf->minlen && pfvf->minlen < minlen)
|
||||
minlen = pfvf->minlen;
|
||||
}
|
||||
|
||||
/* Compare requested max/minlen with PF's max/minlen */
|
||||
pfvf = &rvu->pf[pf];
|
||||
if (pfvf->maxlen > maxlen)
|
||||
maxlen = pfvf->maxlen;
|
||||
if (req->update_minlen &&
|
||||
pfvf->minlen && pfvf->minlen < minlen)
|
||||
minlen = pfvf->minlen;
|
||||
|
||||
/* Update the request with max/min PF's and it's VF's max/min */
|
||||
req->maxlen = maxlen;
|
||||
if (req->update_minlen)
|
||||
req->minlen = minlen;
|
||||
}
|
||||
|
||||
int rvu_mbox_handler_nix_set_hw_frs(struct rvu *rvu, struct nix_frs_cfg *req,
|
||||
struct msg_rsp *rsp)
|
||||
{
|
||||
struct rvu_hwinfo *hw = rvu->hw;
|
||||
u16 pcifunc = req->hdr.pcifunc;
|
||||
int pf = rvu_get_pf(pcifunc);
|
||||
int blkaddr, schq, link = -1;
|
||||
struct nix_txsch *txsch;
|
||||
u64 cfg, lmac_fifo_len;
|
||||
struct nix_hw *nix_hw;
|
||||
u8 cgx = 0, lmac = 0;
|
||||
|
||||
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
|
||||
if (blkaddr < 0)
|
||||
return NIX_AF_ERR_AF_LF_INVALID;
|
||||
|
||||
nix_hw = get_nix_hw(rvu->hw, blkaddr);
|
||||
if (!nix_hw)
|
||||
return -EINVAL;
|
||||
|
||||
if (!req->sdp_link && req->maxlen > NIC_HW_MAX_FRS)
|
||||
return NIX_AF_ERR_FRS_INVALID;
|
||||
|
||||
if (req->update_minlen && req->minlen < NIC_HW_MIN_FRS)
|
||||
return NIX_AF_ERR_FRS_INVALID;
|
||||
|
||||
/* Check if requester wants to update SMQ's */
|
||||
if (!req->update_smq)
|
||||
goto rx_frscfg;
|
||||
|
||||
/* Update min/maxlen in each of the SMQ attached to this PF/VF */
|
||||
txsch = &nix_hw->txsch[NIX_TXSCH_LVL_SMQ];
|
||||
spin_lock(&rvu->rsrc_lock);
|
||||
for (schq = 0; schq < txsch->schq.max; schq++) {
|
||||
if (txsch->pfvf_map[schq] != pcifunc)
|
||||
continue;
|
||||
cfg = rvu_read64(rvu, blkaddr, NIX_AF_SMQX_CFG(schq));
|
||||
cfg = (cfg & ~(0xFFFFULL << 8)) | ((u64)req->maxlen << 8);
|
||||
if (req->update_minlen)
|
||||
cfg = (cfg & ~0x7FULL) | ((u64)req->minlen & 0x7F);
|
||||
rvu_write64(rvu, blkaddr, NIX_AF_SMQX_CFG(schq), cfg);
|
||||
}
|
||||
spin_unlock(&rvu->rsrc_lock);
|
||||
|
||||
rx_frscfg:
|
||||
/* Check if config is for SDP link */
|
||||
if (req->sdp_link) {
|
||||
if (!hw->sdp_links)
|
||||
return NIX_AF_ERR_RX_LINK_INVALID;
|
||||
link = hw->cgx_links + hw->lbk_links;
|
||||
goto linkcfg;
|
||||
}
|
||||
|
||||
/* Check if the request is from CGX mapped RVU PF */
|
||||
if (is_pf_cgxmapped(rvu, pf)) {
|
||||
/* Get CGX and LMAC to which this PF is mapped and find link */
|
||||
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx, &lmac);
|
||||
link = (cgx * hw->lmac_per_cgx) + lmac;
|
||||
} else if (pf == 0) {
|
||||
/* For VFs of PF0 ingress is LBK port, so config LBK link */
|
||||
link = hw->cgx_links;
|
||||
}
|
||||
|
||||
if (link < 0)
|
||||
return NIX_AF_ERR_RX_LINK_INVALID;
|
||||
|
||||
nix_find_link_frs(rvu, req, pcifunc);
|
||||
|
||||
linkcfg:
|
||||
cfg = rvu_read64(rvu, blkaddr, NIX_AF_RX_LINKX_CFG(link));
|
||||
cfg = (cfg & ~(0xFFFFULL << 16)) | ((u64)req->maxlen << 16);
|
||||
if (req->update_minlen)
|
||||
cfg = (cfg & ~0xFFFFULL) | req->minlen;
|
||||
rvu_write64(rvu, blkaddr, NIX_AF_RX_LINKX_CFG(link), cfg);
|
||||
|
||||
if (req->sdp_link || pf == 0)
|
||||
return 0;
|
||||
|
||||
/* Update transmit credits for CGX links */
|
||||
lmac_fifo_len =
|
||||
CGX_FIFO_LEN / cgx_get_lmac_cnt(rvu_cgx_pdata(cgx, rvu));
|
||||
cfg = rvu_read64(rvu, blkaddr, NIX_AF_TX_LINKX_NORM_CREDIT(link));
|
||||
cfg &= ~(0xFFFFFULL << 12);
|
||||
cfg |= ((lmac_fifo_len - req->maxlen) / 16) << 12;
|
||||
rvu_write64(rvu, blkaddr, NIX_AF_TX_LINKX_NORM_CREDIT(link), cfg);
|
||||
rvu_write64(rvu, blkaddr, NIX_AF_TX_LINKX_EXPR_CREDIT(link), cfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nix_link_config(struct rvu *rvu, int blkaddr)
|
||||
{
|
||||
struct rvu_hwinfo *hw = rvu->hw;
|
||||
int cgx, lmac_cnt, slink, link;
|
||||
u64 tx_credits;
|
||||
|
||||
/* Set default min/max packet lengths allowed on NIX Rx links.
|
||||
*
|
||||
* With HW reset minlen value of 60byte, HW will treat ARP pkts
|
||||
* as undersize and report them to SW as error pkts, hence
|
||||
* setting it to 40 bytes.
|
||||
*/
|
||||
for (link = 0; link < (hw->cgx_links + hw->lbk_links); link++) {
|
||||
rvu_write64(rvu, blkaddr, NIX_AF_RX_LINKX_CFG(link),
|
||||
NIC_HW_MAX_FRS << 16 | NIC_HW_MIN_FRS);
|
||||
}
|
||||
|
||||
if (hw->sdp_links) {
|
||||
link = hw->cgx_links + hw->lbk_links;
|
||||
rvu_write64(rvu, blkaddr, NIX_AF_RX_LINKX_CFG(link),
|
||||
SDP_HW_MAX_FRS << 16 | NIC_HW_MIN_FRS);
|
||||
}
|
||||
|
||||
/* Set credits for Tx links assuming max packet length allowed.
|
||||
* This will be reconfigured based on MTU set for PF/VF.
|
||||
*/
|
||||
for (cgx = 0; cgx < hw->cgx; cgx++) {
|
||||
lmac_cnt = cgx_get_lmac_cnt(rvu_cgx_pdata(cgx, rvu));
|
||||
tx_credits = ((CGX_FIFO_LEN / lmac_cnt) - NIC_HW_MAX_FRS) / 16;
|
||||
/* Enable credits and set credit pkt count to max allowed */
|
||||
tx_credits = (tx_credits << 12) | (0x1FF << 2) | BIT_ULL(1);
|
||||
slink = cgx * hw->lmac_per_cgx;
|
||||
for (link = slink; link < (slink + lmac_cnt); link++) {
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NIX_AF_TX_LINKX_NORM_CREDIT(link),
|
||||
tx_credits);
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NIX_AF_TX_LINKX_EXPR_CREDIT(link),
|
||||
tx_credits);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set Tx credits for LBK link */
|
||||
slink = hw->cgx_links;
|
||||
for (link = slink; link < (slink + hw->lbk_links); link++) {
|
||||
tx_credits = 1000; /* 10 * max LBK datarate = 10 * 100Gbps */
|
||||
/* Enable credits and set credit pkt count to max allowed */
|
||||
tx_credits = (tx_credits << 12) | (0x1FF << 2) | BIT_ULL(1);
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NIX_AF_TX_LINKX_NORM_CREDIT(link), tx_credits);
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NIX_AF_TX_LINKX_EXPR_CREDIT(link), tx_credits);
|
||||
}
|
||||
}
|
||||
|
||||
static int nix_calibrate_x2p(struct rvu *rvu, int blkaddr)
|
||||
{
|
||||
int idx, err;
|
||||
@ -1922,6 +2118,9 @@ int rvu_nix_init(struct rvu *rvu)
|
||||
(NPC_LID_LC << 8) | (NPC_LT_LC_IP << 4) | 0x0F);
|
||||
|
||||
nix_rx_flowkey_alg_cfg(rvu, blkaddr);
|
||||
|
||||
/* Initialize CGX/LBK/SDP link credits, min/max pkt lengths */
|
||||
nix_link_config(rvu, blkaddr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user