Commit a0d9528f authored by Naveen Mamindlapalli's avatar Naveen Mamindlapalli Committed by David S. Miller

octeontx2-af: Always configure NIX TX link credits based on max frame size

Currently the NIX TX link credits are initialized based on the max frame
size that can be transmitted on a link but when the MTU is changed, the
NIX TX link credits are reprogrammed by the SW based on the new MTU value.
Since SMQ max packet length is programmed to max frame size by default,
there is a chance that NIX TX may stall while sending a max frame sized
packet on the link with insufficient credits to send the packet all at
once. This patch avoids stall issue by not changing the link credits
dynamically when the MTU is changed.

Fixes: 1c74b891 ("octeontx2-af: Wait for TX link idle for credits change")
Signed-off-by: default avatarNaveen Mamindlapalli <naveenm@marvell.com>
Signed-off-by: default avatarSunil Kovvuri Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarNithin Kumar Dabilpuram <ndabilpuram@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cbc74fc0
......@@ -4143,90 +4143,18 @@ static void nix_find_link_frs(struct rvu *rvu,
req->minlen = minlen;
}
static int
nix_config_link_credits(struct rvu *rvu, int blkaddr, int link,
u16 pcifunc, u64 tx_credits)
{
struct rvu_hwinfo *hw = rvu->hw;
int pf = rvu_get_pf(pcifunc);
u8 cgx_id = 0, lmac_id = 0;
unsigned long poll_tmo;
bool restore_tx_en = 0;
struct nix_hw *nix_hw;
u64 cfg, sw_xoff = 0;
u32 schq = 0;
u32 credits;
int rc;
nix_hw = get_nix_hw(rvu->hw, blkaddr);
if (!nix_hw)
return NIX_AF_ERR_INVALID_NIXBLK;
if (tx_credits == nix_hw->tx_credits[link])
return 0;
/* Enable cgx tx if disabled for credits to be back */
if (is_pf_cgxmapped(rvu, pf)) {
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
restore_tx_en = !rvu_cgx_config_tx(rvu_cgx_pdata(cgx_id, rvu),
lmac_id, true);
}
mutex_lock(&rvu->rsrc_lock);
/* Disable new traffic to link */
if (hw->cap.nix_shaping) {
schq = nix_get_tx_link(rvu, pcifunc);
sw_xoff = rvu_read64(rvu, blkaddr, NIX_AF_TL1X_SW_XOFF(schq));
rvu_write64(rvu, blkaddr,
NIX_AF_TL1X_SW_XOFF(schq), BIT_ULL(0));
}
rc = NIX_AF_ERR_LINK_CREDITS;
poll_tmo = jiffies + usecs_to_jiffies(200000);
/* Wait for credits to return */
do {
if (time_after(jiffies, poll_tmo))
goto exit;
usleep_range(100, 200);
cfg = rvu_read64(rvu, blkaddr,
NIX_AF_TX_LINKX_NORM_CREDIT(link));
credits = (cfg >> 12) & 0xFFFFFULL;
} while (credits != nix_hw->tx_credits[link]);
cfg &= ~(0xFFFFFULL << 12);
cfg |= (tx_credits << 12);
rvu_write64(rvu, blkaddr, NIX_AF_TX_LINKX_NORM_CREDIT(link), cfg);
rc = 0;
nix_hw->tx_credits[link] = tx_credits;
exit:
/* Enable traffic back */
if (hw->cap.nix_shaping && !sw_xoff)
rvu_write64(rvu, blkaddr, NIX_AF_TL1X_SW_XOFF(schq), 0);
/* Restore state of cgx tx */
if (restore_tx_en)
rvu_cgx_config_tx(rvu_cgx_pdata(cgx_id, rvu), lmac_id, false);
mutex_unlock(&rvu->rsrc_lock);
return rc;
}
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;
int blkaddr, link = -1;
struct nix_hw *nix_hw;
struct rvu_pfvf *pfvf;
u8 cgx = 0, lmac = 0;
u16 max_mtu;
u64 cfg;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
if (blkaddr < 0)
......@@ -4247,25 +4175,6 @@ int rvu_mbox_handler_nix_set_hw_frs(struct rvu *rvu, struct nix_frs_cfg *req,
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];
mutex_lock(&rvu->rsrc_lock);
for (schq = 0; schq < txsch->schq.max; schq++) {
if (TXSCH_MAP_FUNC(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);
}
mutex_unlock(&rvu->rsrc_lock);
rx_frscfg:
/* Check if config is for SDP link */
if (req->sdp_link) {
if (!hw->sdp_links)
......@@ -4288,7 +4197,6 @@ int rvu_mbox_handler_nix_set_hw_frs(struct rvu *rvu, struct nix_frs_cfg *req,
if (link < 0)
return NIX_AF_ERR_RX_LINK_INVALID;
linkcfg:
nix_find_link_frs(rvu, req, pcifunc);
......@@ -4298,19 +4206,7 @@ int rvu_mbox_handler_nix_set_hw_frs(struct rvu *rvu, struct nix_frs_cfg *req,
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 = rvu_cgx_get_lmac_fifolen(rvu, cgx, lmac);
if (!lmac_fifo_len) {
dev_err(rvu->dev,
"%s: Failed to get CGX/RPM%d:LMAC%d FIFO size\n",
__func__, cgx, lmac);
return 0;
}
return nix_config_link_credits(rvu, blkaddr, link, pcifunc,
(lmac_fifo_len - req->maxlen) / 16);
return 0;
}
int rvu_mbox_handler_nix_set_rx_cfg(struct rvu *rvu, struct nix_rx_cfg *req,
......
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