From: Ratheesh Kannoth <rkannoth@marvell.com>
To: <cjacob@marvell.com>, <davem@davemloft.net>, <hkelam@marvell.com>,
<jbrandeb@kernel.org>, <linux-kernel@vger.kernel.org>,
<netdev@vger.kernel.org>, <sgoutham@marvell.com>
Cc: <andrew+netdev@lunn.ch>, <edumazet@google.com>, <kuba@kernel.org>,
<pabeni@redhat.com>, Naveen Mamindlapalli <naveenm@marvell.com>,
"Ratheesh Kannoth" <rkannoth@marvell.com>
Subject: [PATCH net] octeontx2-af: poll for TX link credits before link mode change
Date: Tue, 18 Aug 2026 09:06:52 +0530 [thread overview]
Message-ID: <20260818033652.2038116-1-rkannoth@marvell.com> (raw)
From: Naveen Mamindlapalli <naveenm@marvell.com>
When a CGX/RPM link mode change is performed while traffic is flowing,
the link is temporarily disabled. NIX TX link credits can drop below
zero during this window and are not restored when the link comes back,
leading to a TX hang.
Set TL1 SW_XOFF before initiating a link mode change and poll until TX
link credits return to their original value. Clear TL1 SW_XOFF when the
link comes back up.
Fixes: 56b6d5398613 ("octeontx2-af: Physical link configuration support")
Signed-off-by: Naveen Mamindlapalli <naveenm@marvell.com>
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
---
.../net/ethernet/marvell/octeontx2/af/rvu.h | 2 +
.../ethernet/marvell/octeontx2/af/rvu_cgx.c | 19 +++++++-
.../ethernet/marvell/octeontx2/af/rvu_nix.c | 48 +++++++++++++++++++
3 files changed, 68 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
index 9d5b7b51bdfa..66e46528e3bd 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
@@ -1048,6 +1048,8 @@ int rvu_nix_mcast_get_mce_index(struct rvu *rvu, u16 pcifunc,
u32 mcast_grp_idx);
int rvu_nix_mcast_update_mcam_entry(struct rvu *rvu, u16 pcifunc,
u32 mcast_grp_idx, u16 mcam_index);
+int rvu_nix_tl1_xoff_wait_for_link_credits(struct rvu *rvu, u16 pcifunc);
+int rvu_nix_tl1_xoff_clear(struct rvu *rvu, u16 pcifunc);
void rvu_nix_flr_free_bpids(struct rvu *rvu, u16 pcifunc);
int rvu_alloc_cint_qint_mem(struct rvu *rvu, struct rvu_pfvf *pfvf,
int blkaddr, int nixlf);
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
index 87d21889dc49..85143684bb6f 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
@@ -234,7 +234,7 @@ static void cgx_notify_pfs(struct cgx_link_event *event, struct rvu *rvu)
struct cgx_link_user_info *linfo;
struct cgx_link_info_msg *msg;
unsigned long pfmap;
- int pfid;
+ int pfid, err;
linfo = &event->link_uinfo;
pfmap = cgxlmac_to_pfmap(rvu, event->cgx_id, event->lmac_id);
@@ -249,6 +249,15 @@ static void cgx_notify_pfs(struct cgx_link_event *event, struct rvu *rvu)
rvu->cgx_cnt_max * rvu->hw->lmac_per_cgx);
clear_bit(pfid, &pfmap);
+ /* clear TL1 sw_xoff */
+ if (linfo->link_up) {
+ err = rvu_nix_tl1_xoff_clear(rvu, pfid << 10);
+ if (err)
+ dev_warn(rvu->dev,
+ "tl1 sw_xoff clear unsuccessful, cgx=%d lmac=%d\n",
+ event->cgx_id, event->lmac_id);
+ }
+
/* check if notification is enabled */
if (!test_bit(pfid, &rvu->pf_notify_bmap)) {
dev_info(rvu->dev, "cgx %d: lmac %d Link status %s\n",
@@ -1221,6 +1230,7 @@ int rvu_mbox_handler_cgx_set_link_mode(struct rvu *rvu,
struct cgx_lmac_fwdata_s *linkmodes;
u8 cgx_idx, lmac;
void *cgxd;
+ int err;
if (!rvu->fwdata)
return LMAC_AF_ERR_FIRMWARE_DATA_NOT_MAPPED;
@@ -1230,11 +1240,18 @@ int rvu_mbox_handler_cgx_set_link_mode(struct rvu *rvu,
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_idx, &lmac);
cgxd = rvu_cgx_pdata(cgx_idx, rvu);
+
if (rvu->hw->lmac_per_cgx == CGX_LMACS_USX)
linkmodes = &rvu->fwdata->cgx_fw_data_usx[cgx_idx][lmac];
else
linkmodes = &rvu->fwdata->cgx_fw_data[cgx_idx][lmac];
+ err = rvu_nix_tl1_xoff_wait_for_link_credits(rvu, req->hdr.pcifunc);
+ if (err)
+ dev_warn(rvu->dev,
+ "tl1 sw_xoff/link_credit_poll unsuccessful, cgx=%d lmac=%d\n",
+ cgx_idx, lmac);
+
rsp->status = cgx_set_link_mode(cgxd, req->args, linkmodes,
cgx_idx, lmac);
return 0;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
index 964bcaae098e..92d8f318783d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
@@ -6704,3 +6704,51 @@ void rvu_block_bcast_xon(struct rvu *rvu, int blkaddr)
cfg = rvu_read64(rvu, blkaddr, NIX_AF_RX_CHANX_CFG(0));
rvu_write64(rvu, blkaddr, NIX_AF_RX_CHANX_CFG(0), cfg);
}
+
+int rvu_nix_tl1_xoff_wait_for_link_credits(struct rvu *rvu, u16 pcifunc)
+{
+ int link, blkaddr, count = 1000;
+ u64 tx_credits, regval;
+ struct nix_hw *nix_hw;
+
+ 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 NIX_AF_ERR_INVALID_NIXBLK;
+
+ /* set TL1 sw_xoff */
+ link = nix_get_tx_link(rvu, pcifunc);
+ rvu_write64(rvu, blkaddr, NIX_AF_TL1X_SW_XOFF(link), 1);
+
+ /* wait for link credits to return */
+ tx_credits = nix_hw->tx_credits[link];
+ while (1) {
+ regval = rvu_read64(rvu, blkaddr, NIX_AF_TX_LINKX_NORM_CREDIT(link));
+ if (((regval >> 12) & 0xFFFFF) == tx_credits)
+ break;
+ count--;
+ if (!count) {
+ dev_err(rvu->dev, "TX link(%d) credit poll timeout\n", link);
+ return -ETIMEDOUT;
+ }
+ cpu_relax();
+ udelay(1);
+ }
+ return 0;
+}
+
+int rvu_nix_tl1_xoff_clear(struct rvu *rvu, u16 pcifunc)
+{
+ int blkaddr;
+
+ blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
+ if (blkaddr < 0)
+ return NIX_AF_ERR_AF_LF_INVALID;
+
+ nix_clear_tx_xoff(rvu, blkaddr, NIX_TXSCH_LVL_TL1,
+ nix_get_tx_link(rvu, pcifunc));
+ return 0;
+}
--
2.43.0
next reply other threads:[~2026-08-18 3:37 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-18 3:36 Ratheesh Kannoth [this message]
2026-08-18 7:38 ` [PATCH net] octeontx2-af: poll for TX link credits before link mode change Jagielski, Jedrzej
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260818033652.2038116-1-rkannoth@marvell.com \
--to=rkannoth@marvell.com \
--cc=andrew+netdev@lunn.ch \
--cc=cjacob@marvell.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=hkelam@marvell.com \
--cc=jbrandeb@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=naveenm@marvell.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=sgoutham@marvell.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox