From: Wei Fang Date: Tue, 24 Mar 2026 06:21:19 +0000 (+0800) Subject: net: enetc: reset PIR and CIR if they are not equal when initializing TX ring X-Git-Tag: v7.0-rc7~28^2~45^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0239fd701d33475a39428daa3dc627407cd417a6;p=thirdparty%2Fkernel%2Fstable.git net: enetc: reset PIR and CIR if they are not equal when initializing TX ring Currently the driver does not reset the producer index register (PIR) and consumer index register (CIR) when initializing a TX BD ring. The driver only reads the PIR and CIR and initializes the software indexes. If the TX BD ring is reinitialized when it still contains unsent frames, its PIR and CIR will not be equal after the reinitialization. However, the BDs between CIR and PIR have been freed and become invalid and this can lead to a hardware malfunction, causing the TX BD ring will not work properly. For ENETC v4, it supports software to set the PIR and CIR, so the driver can reset these two registers if they are not equal when reinitializing the TX BD ring. Therefore, add this solution for ENETC v4. Note that this patch does not work for ENETC v1 because it does not support software to set the PIR and CIR. Fixes: 99100d0d9922 ("net: enetc: add preliminary support for i.MX95 ENETC PF") Signed-off-by: Wei Fang Reviewed-by: Claudiu Manoil Reviewed-by: Simon Horman Link: https://patch.msgid.link/20260324062121.2745033-2-wei.fang@nxp.com Signed-off-by: Jakub Kicinski --- diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index a146ceaf2ed6..aa8a87124b10 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -2578,6 +2578,7 @@ EXPORT_SYMBOL_GPL(enetc_free_si_resources); static void enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring) { + struct enetc_si *si = container_of(hw, struct enetc_si, hw); int idx = tx_ring->index; u32 tbmr; @@ -2591,10 +2592,20 @@ static void enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring) enetc_txbdr_wr(hw, idx, ENETC_TBLENR, ENETC_RTBLENR_LEN(tx_ring->bd_count)); - /* clearing PI/CI registers for Tx not supported, adjust sw indexes */ + /* For ENETC v1, clearing PI/CI registers for Tx not supported, + * adjust sw indexes + */ tx_ring->next_to_use = enetc_txbdr_rd(hw, idx, ENETC_TBPIR); tx_ring->next_to_clean = enetc_txbdr_rd(hw, idx, ENETC_TBCIR); + if (tx_ring->next_to_use != tx_ring->next_to_clean && + !is_enetc_rev1(si)) { + tx_ring->next_to_use = 0; + tx_ring->next_to_clean = 0; + enetc_txbdr_wr(hw, idx, ENETC_TBPIR, 0); + enetc_txbdr_wr(hw, idx, ENETC_TBCIR, 0); + } + /* enable Tx ints by setting pkt thr to 1 */ enetc_txbdr_wr(hw, idx, ENETC_TBICR0, ENETC_TBICR0_ICEN | 0x1);