From patchwork Sun Sep 27 21:59:54 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3533 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sto.lore.kernel.org (sto.lore.kernel.org [172.232.135.74]) by mxe881.netcup.net (Postfix) with ESMTPS id 04E991C316A for ; Mon, 28 Sep 2026 00:05:41 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.232.135.74) smtp.mailfrom=linux-sunxi+bounces-26368-noreply=patchwork.local@lists.linux.dev smtp.helo=sto.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.232.135.74 as permitted sender) client-ip=172.232.135.74; envelope-from=linux-sunxi+bounces-26368-noreply=patchwork.local@lists.linux.dev; helo=sto.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sto.lore.kernel.org (Postfix) with ESMTP id 83730606896 for ; Sun, 27 Sep 2026 22:02:58 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 6E63F3CEB83; Sun, 27 Sep 2026 22:00:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="CNLAShxv" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oo2-f41.google.com (mail-oo2-f41.google.com [74.125.231.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C8D613D16E5 for ; Sun, 27 Sep 2026 22:00:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790546446; cv=none; b=RwDE5wJ15iVNwRNTdeaCxcKx6TEmX57ABvhVAZx0oJKXNp1Q8WrjZTWV8pLdwDzbI3CR+mBOey16c7MYCsQArcI+0LEbj+5dbBpbw9FedXMJ5gw/bvZ2dMwQOy5qNHXJMt2E7CfeoXrAFTBZQ5FsSXFSFBOzZH3p6kyR7EH03UY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790546446; c=relaxed/simple; bh=VIduLl42KnAOTfMWR9Pr8MdjqMBHpV/GRP6MkSBNbqQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fSPkId5jS4k2pnvm3pMVPNX7nmvWZPg28Sc3Wep6jPKt6YV3JEPBhgsnoc0FWLFsYGGblHahuSE2Oeu/1F81a3ErDsEQd/26zzUvvkz2O34WaHQE/78+2vhZbsjrhYOaqCW2c8yLY6mti369NEmrpiJXSBC5nQmPvLq1GyX51rI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=CNLAShxv; arc=none smtp.client-ip=74.125.231.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-oo2-f41.google.com with SMTP id 006d021491bc7-6d33d80855eso1788368eaf.1 for ; Sun, 27 Sep 2026 15:00:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790546438; x=1791151238; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=1gLUXzy2Xjx8Cab+i1wrgHaR5HLup8/A3/8/0Q1nuNo=; b=CNLAShxvOwcPGg4xBUm8zl7Nt0HrKkUTACpHyaWdnYfvdwpuvc9Rur4tZ4O7QPGiNq 8M2IDmTW0oengyZz/zOfd9r5AXrwoo1tFNJoPmDO1vzmiBXj9aDmkVhUY/UVuKRNNwmI u/uAQsa+09OgCUKa39g7YKowckw/XcuyJ0KQTLc2UOxV5piCUVL8yEvvktvxzRU90O+z orrmJspGFDb5TkJ0E3wN2LF3JMn92oFhYd0E0aGv0Wxs8Yo9mYzIcthYVzsZRbGfPhYQ NCNV1CzHNvQrurj0tzlvdvEIIG6jL7Cpw1wzgyUUUpHfF+Xz+5SL96GyYLPrwUxzlqMU Nksg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790546438; x=1791151238; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=1gLUXzy2Xjx8Cab+i1wrgHaR5HLup8/A3/8/0Q1nuNo=; b=TrUDvj21g382bfzPXRV0e2nYpViH+1Nq3tZhns/iGow8t1WkBPKxIH9uKOA5/xx2I4 JuW3YTMML8ovZQpGItKg17onj60xYO64s6KnmXUlyeIGKURg1BLngRd5qnCIvSYaYU0y 6EKUSxDvIg2qvGF3IassuFG1rUxq/F2uTjo55Fb1NBa5NsQqOEUz4H9LCE2aMtxUVlgk qTn7PRXhwMTYoNZBau2ZfaQuUdjzbuUvohOQbSRJG18LeegyvZVR1MbW33vBT1UIbyRZ czSnqodHv4hKmFYtJID7prwxMkP8zwm1fcYly3zZ9N9OnP+ykj0Oqpqm6P55Ch1xiMhX sKFQ== X-Forwarded-Encrypted: i=1; AKwUvBw/ie44YNWlp6YWngHXexjBvUOoXSpL7haQNZ2PfXeDXRmszy6PKu4x9uquk5aV+Tw9OUTTG/CDu403iA==@lists.linux.dev X-Gm-Message-State: AFuF++nwvwEwDl1xKDIPpcmHtukLgF8vFTk588NYk9QSUc0W/8EBF306 E2I+KK2WJDLLPw6DOaWaNI78g29vPL3mVNZ3nuFWtNuBHQJJV+i3N/10 X-Gm-Gg: AYBFou3fVVn0243xj2FY3+so96Hu6JmYwrQ2QqN/gPxCCuRXOZZyV7BN5q99xD6XrHw NBc3cAAX9+VhAZoqqZrspDP4s8+kVVVnQQaSwf2g0L4awo/JJ2amq9gnq9pKh/xCDQYfbTmojPm RbmY+TufYFUU1oXC8wnQ/D7CmKX5LGtU1Xto8IB2oV/Lb2pOsNaPovh5bdx31ktc0fXEacFBius Cyo9zu3LxSzGsFFrvH2arwNpHJPqVWNesFDoXAa2CM9NgjBiL36OAUBDtbeUb3BNWy8VAT3Uhoa stSQ/j1j5zfZAJOpCz3wx2hDUTtmYo7QzLU/k21i9DznQSrmYSzkvrdEVNvT7ziRleY9eQY92Qh v41Qjj/txZP2Azm3FlrUW3v7cGuh0Jw1i09G6WyQK6KU7dQsysFv+Gw9MBmRAKHyEy+Td9DyD8X 51DYnTWJSpvKgkSW1eS9N7t7+mh61JLCTliBeW4DlWdo3H7wuQLG8fPPDC/HFDdt6r+KmTidiZA K32n5riNsaA44TX4eK1omSJwIi1tRc09byjNvxrU/E+3XOQq4+yKNcf0DZt8C6GN2PU+/8UbfjX ev+XsOuqtZRNR1Wx1EPAtwWoU4bioeAh1DPSFFXcDZYzmlV89K2P9hR08YupxZnPyN5aVTYTf9I 3/dzfH/IPNn2yvpV9dJ9Aym8hbxaQpCQkLRYCqmfjPQ== X-Received: by 2002:a05:6820:a28b:20b0:6d7:97cf:dba5 with SMTP id 006d021491bc7-6d797cfdd2emr2266574eaf.37.1790546437865; Sun, 27 Sep 2026 15:00:37 -0700 (PDT) Received: from [127.0.1.1] (174-29-1-49.hlrn.qwest.net. [174.29.1.49]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-81b3de6f7e1sm4874147a34.22.2026.09.27.15.00.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 27 Sep 2026 15:00:36 -0700 (PDT) From: James Hilliard Date: Sun, 27 Sep 2026 15:59:54 -0600 Subject: [PATCH net-next v5 19/19] net: stmmac: retain DMA resources across MTU changes Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260927-submit-stmmac-reset-fixes-v1-v5-19-feec6c14dd06@gmail.com> References: <20260927-submit-stmmac-reset-fixes-v1-v5-0-feec6c14dd06@gmail.com> In-Reply-To: <20260927-submit-stmmac-reset-fixes-v1-v5-0-feec6c14dd06@gmail.com> To: Russell King , Andrew Lunn , Heiner Kallweit , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , "Russell King (Oracle)" , Maxime Chevallier , Andrew Lunn , Maxime Coquelin , Alexandre Torgue , Christian Marangi , Tiezhu Yang , Huacai Chen , Alexei Starovoitov , Daniel Borkmann , Jesper Dangaard Brouer , John Fastabend , Stanislav Fomichev , Serge Semin , Suraj Jaiswal , Richard Cochran , Joao Pinto , Vladimir Oltean , Ong Boon Leong , Voon Weifeng , "Song, Yoong Siang" , Linus Walleij , Martin Blumenstingl , Magnus Karlsson , Maciej Fijalkowski , Simon Horman , =?utf-8?b?QmrDtnJuIFTDtnBlbA==?= , Thierry Reding , Jonathan Hunter , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Jose Abreu , Yao Zi , Philipp Zabel Cc: Richard Genoud , Alastair D'Silva , Maxime Ripard , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, bpf@vger.kernel.org, ZhaoJinming , Lorenzo Bianconi , Ding Hui , Linkui Xiao , Linkui Xiao , linux-tegra@vger.kernel.org, linux-sunxi@lists.linux.dev, James Hilliard X-Mailer: b4 0.15.2 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [4.34 / 15.00]; RBL_SENDERSCORE(2.00)[172.232.135.74:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; BAD_REP_POLICIES(0.10)[]; MIME_GOOD(-0.10)[text/plain]; HAS_LIST_UNSUB(-0.01)[]; FREEMAIL_CC(0.00)[bootlin.com,d-silva.org,kernel.org,vger.kernel.org,st-md-mailman.stormreply.com,lists.infradead.org,uniontech.com,oss.qualcomm.com,163.com,kylinos.cn,126.com,lists.linux.dev,gmail.com]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; FROM_HAS_DN(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[sto.lore.kernel.org:rdns,sto.lore.kernel.org:helo]; PRECEDENCE_BULK(0.00)[]; FORGED_SENDER_MAILLIST(0.00)[]; TAGGED_RCPT(0.00)[kernel,netdev]; RCVD_COUNT_FIVE(0.00)[6]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; TAGGED_FROM(0.00)[bounces-26368-noreply=patchwork.local]; FREEMAIL_FROM(0.00)[gmail.com]; RCPT_COUNT_GT_50(0.00)[58]; R_SPF_ALLOW(0.00)[+ip4:172.232.135.74:c]; TO_DN_SOME(0.00)[]; ASN(0.00)[asn:63949, ipnet:172.232.128.0/19, country:SG]; FREEMAIL_TO(0.00)[armlinux.org.uk,lunn.ch,gmail.com,davemloft.net,google.com,kernel.org,redhat.com,bootlin.com,foss.st.com,loongson.cn,iogearbox.net,fomichev.me,quicinc.com,synopsys.com,nxp.com,intel.com,googlemail.com,nvidia.com,sholland.org,ziyao.cc,pengutronix.de]; MIME_TRACE(0.00)[0:+]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_TLS_LAST(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 04E991C316A X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= Prepare the replacement configuration before quiescing the old datapath. Retain its rings and IRQ registrations until setup succeeds so rollback needs no new allocations or IRQ requests. Fill RX buffer holes before reset without altering active descriptors; rebuild the retained rings only after a successful reset. Mask the device DMA interrupt sources, gate shared-IRQ handlers and drain all registered handlers before the final transmitter and timer cancellation. Restore saved interrupt masks only after the selected rings and NAPI are ready. This leaves interrupt-controller lines available to unrelated devices. Program receive limits using the prospective MTU and restore the old MTU before rollback. Reapply PHC and TC state before starting DMA, preserving the PHC registration and packet timestamp filters. Continuous PHC time across the reset is not preserved. If rollback fails, leave the administratively-up interface detached in a distinct HALTED state: rings retained, NAPI disabled and IRQ registrations released. Close or a later down/up can finish cleanup and recovery without freeing IRQs twice. Retain potentially active DMA memory until hardware shutdown is confirmed. Fixes: 3470079687448 ("net: ethernet: stmicro: stmmac: permit MTU change with interface up") Signed-off-by: James Hilliard --- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 216 +++++++++++++++++----- 2 files changed, 173 insertions(+), 45 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 06fe750624b6..a65253d309d0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -279,6 +279,8 @@ enum stmmac_datapath_state { STMMAC_DATAPATH_RUNNING, /* Resources retained, NAPI disabled, DMA stop requested. */ STMMAC_DATAPATH_SUSPENDED, + /* Failed MTU rollback: rings retained, but no IRQs or running NAPI. */ + STMMAC_DATAPATH_HALTED, }; struct stmmac_priv { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 435c76b7db30..7951b3e60d84 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1016,7 +1016,7 @@ static void stmmac_release_ptp(struct stmmac_priv *priv) } /* ptp_mutex excludes configuration and crosstimestamp operations. The - * spinlock also excludes atomic clock reads while changing this gate. + * spinlock also excludes atomic gettime callers while changing this gate. */ static void stmmac_block_ptp(struct stmmac_priv *priv, bool block) { @@ -2251,6 +2251,30 @@ static void stmmac_free_tx_skbufs(struct stmmac_priv *priv) dma_free_tx_skbufs(priv, priv->dma_conf, queue); } +/* NAPI is stopped, but DMA may still be using the old rings. Fill holes in + * the software buffer array without changing any descriptors. If allocation + * fails, the old rings can continue unchanged. Otherwise rollback after a + * reset will not need to allocate buffers. + */ +static int stmmac_prepare_rx_buffers(struct stmmac_priv *priv) +{ + struct stmmac_dma_conf *dma_conf = priv->dma_conf; + u32 queue, i; + int ret; + + for (queue = 0; queue < priv->plat->rx_queues_to_use; queue++) { + struct stmmac_rx_queue *rx_q = &dma_conf->rx_queue[queue]; + + for (i = 0; i < dma_conf->dma_rx_size; i++) { + ret = stmmac_alloc_rx_buffer(priv, rx_q, &rx_q->buf_pool[i]); + if (ret) + return ret; + } + } + + return 0; +} + /* Only after a successful DMA reset. MTU rollback has already filled holes; * resume may need new page-pool buffers or a partially populated XSK ring. */ @@ -4425,14 +4449,38 @@ static void stmmac_synchronize_irq(struct stmmac_priv *priv) synchronize_irq(msi->tx_irq[i]); } +/* Keep the IRQ registrations, but prevent DMA handlers from using the rings. + * The caller drains handlers after quiescing every channel and restores their + * masks only once the active DMA configuration is ready again. + */ +static void stmmac_set_dma_irq_state(struct stmmac_priv *priv, bool enable, + u32 *irq_mask) +{ + u32 channels = max(priv->plat->rx_queues_to_use, + priv->plat->tx_queues_to_use); + u32 chan; + + for (chan = 0; chan < channels; chan++) { + struct stmmac_channel *ch = &priv->channel[chan]; + unsigned long flags; + + spin_lock_irqsave(&ch->lock, flags); + ch->irq_quiesced = !enable; + if (enable) + stmmac_set_dma_irq_mask(priv, priv->ioaddr, chan, + irq_mask[chan]); + else + irq_mask[chan] = stmmac_set_dma_irq_mask(priv, priv->ioaddr, + chan, 0); + spin_unlock_irqrestore(&ch->lock, flags); + } +} + /** - * stmmac_setup_dma_desc - Generate a dma_conf and allocate DMA queue - * @priv: driver private structure - * @mtu: MTU to setup the dma queue and buf with - * Description: Allocate and generate a dma_conf based on the provided MTU. - * Allocate the Tx/Rx DMA queue and init them. - * Return value: - * the dma_conf allocated struct on success and an appropriate ERR_PTR on failure. + * stmmac_setup_dma_desc - allocate and initialize a DMA configuration + * @priv: driver private structure + * @mtu: MTU to size the receive buffers for + * Return: the allocated configuration, or an ERR_PTR on failure */ static struct stmmac_dma_conf * stmmac_setup_dma_desc(struct stmmac_priv *priv, unsigned int mtu) @@ -4666,7 +4714,7 @@ static int __stmmac_open(struct net_device *dev, priv->dma_conf = dma_conf; /* The PHY is suspended when the interface is reopened without - * disconnecting the PHY, e.g. on MTU change. IEEE 802.3 allows PHYs + * disconnecting the PHY, e.g. on an ethtool change. IEEE 802.3 allows PHYs * to stop their receive clock while powered down, but the DMA * software reset in stmmac_hw_setup() requires a running receive * clock, and phylink_start() below resumes the PHY only after the @@ -4823,20 +4871,22 @@ static void stmmac_quiesce(struct stmmac_priv *priv) static void __stmmac_release(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); + enum stmmac_datapath_state state = priv->datapath; - /* A failed MTU reopen has already released the data path. */ + /* There may be no resources left after detached XDP reconfiguration. */ if (priv->datapath == STMMAC_DATAPATH_DOWN) return; phylink_stop(priv->phylink); - /* Suspend retains the resources, but has already stopped activity. */ + /* SUSPENDED and HALTED retain rings with NAPI already disabled. */ if (priv->datapath == STMMAC_DATAPATH_RUNNING) stmmac_quiesce(priv); priv->datapath = STMMAC_DATAPATH_DOWN; /* Free the IRQ lines */ - stmmac_free_irq(dev, REQ_IRQ_ERR_ALL, 0); + if (state != STMMAC_DATAPATH_HALTED) + stmmac_free_irq(dev, REQ_IRQ_ERR_ALL, 0); /* Drain any final IRQ-triggered network activity before DMA shutdown. */ stmmac_stop_tx_queues(priv); @@ -6723,6 +6773,109 @@ static void stmmac_set_rx_mode(struct net_device *dev) stmmac_set_filter(priv, priv->hw, dev); } +static int stmmac_reconfigure_mtu(struct net_device *dev, int mtu) +{ + struct stmmac_priv *priv = netdev_priv(dev); + struct stmmac_dma_conf *old_conf = priv->dma_conf; + struct stmmac_dma_conf *new_conf; + int old_mtu = dev->mtu; + int ret, restore_ret; + u32 irq_mask[STMMAC_CH_MAX]; + u32 chan; + + new_conf = stmmac_setup_dma_desc(priv, mtu); + if (IS_ERR(new_conf)) + return PTR_ERR(new_conf); + + mutex_lock(&priv->ptp_mutex); + stmmac_block_ptp(priv, true); + netif_device_detach(dev); + phylink_stop(priv->phylink); + stmmac_quiesce(priv); + if (stmmac_fpe_supported(priv)) + ethtool_mmsv_stop(&priv->fpe_cfg.mmsv); + + /* Drain handlers before the final TX stop and configuration swap, + * and keep the registrations for rollback. + */ + stmmac_set_dma_irq_state(priv, false, irq_mask); + stmmac_synchronize_irq(priv); + stmmac_stop_tx_queues(priv); + + ret = stmmac_prepare_rx_buffers(priv); + if (ret) + goto restart; + + stmmac_stop_all_dma(priv); + phylink_prepare_resume(priv->phylink); + + /* MAC receive limits must be programmed for the prospective MTU. */ + WRITE_ONCE(dev->mtu, mtu); + priv->dma_conf = new_conf; + stmmac_reset_queues_param(priv); + ret = stmmac_hw_setup(dev, false, true); + if (ret) { + stmmac_stop_all_dma(priv); + stmmac_mac_set(priv, priv->ioaddr, false); + priv->dma_conf = old_conf; + WRITE_ONCE(dev->mtu, old_mtu); + + /* Reuse the retained rings. Reinitialize them only after reset + * has completed, not merely after clearing the DMA enable bits. + */ + restore_ret = stmmac_hw_setup(dev, true, true); + if (restore_ret) { + stmmac_stop_all_dma(priv); + stmmac_mac_set(priv, priv->ioaddr, false); + /* Setup may have restored DMA interrupt enables. */ + stmmac_set_dma_irq_state(priv, false, irq_mask); + stmmac_free_irq(dev, REQ_IRQ_ERR_ALL, 0); + stmmac_stop_tx_queues(priv); + stmmac_stop_all_dma(priv); + memset(irq_mask, 0, sizeof(irq_mask)); + stmmac_set_dma_irq_state(priv, true, irq_mask); + priv->datapath = STMMAC_DATAPATH_HALTED; + netdev_err(dev, "MTU rollback failed: %pe; interface remains detached\n", + ERR_PTR(restore_ret)); + goto free_new; + } + } else { + /* Hardware setup completed its reset before using the new rings. + * The old DMA allocations can now be released safely. + */ + stmmac_put_dma_conf(priv, old_conf); + for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++) + hrtimer_setup(&new_conf->tx_queue[chan].txtimer, + stmmac_tx_timer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + } + + stmmac_set_rx_mode(dev); + stmmac_vlan_restore(priv); + stmmac_start_all_dma(priv); + +restart: + stmmac_block_ptp(priv, false); + mutex_unlock(&priv->ptp_mutex); + stmmac_enable_all_queues(priv); + stmmac_set_dma_irq_state(priv, true, irq_mask); + stmmac_enable_all_dma_irq(priv); + phylink_start(priv->phylink); + netif_device_attach(dev); + for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++) + stmmac_tx_timer_arm(priv, chan); + if (!ret) + return 0; + goto free_conf; + +free_new: + /* Failed rollback leaves the registered PHC inaccessible as well. */ + mutex_unlock(&priv->ptp_mutex); +free_conf: + stmmac_put_dma_conf(priv, new_conf); + return ret; +} + /** * stmmac_change_mtu - entry point to change MTU size for the device. * @dev : device pointer. @@ -6737,9 +6890,7 @@ static void stmmac_set_rx_mode(struct net_device *dev) static int stmmac_change_mtu(struct net_device *dev, int new_mtu) { struct stmmac_priv *priv = netdev_priv(dev); - struct stmmac_dma_conf *old_conf = priv->dma_conf; int txfifosz = priv->plat->tx_fifo_size; - struct stmmac_dma_conf *dma_conf; const int mtu = new_mtu; int ret; @@ -6765,35 +6916,9 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu) */ if (netif_running(dev) && (dev->mtu > ETH_DATA_LEN || mtu > ETH_DATA_LEN)) { - netdev_dbg(priv->dev, "restarting interface to change its MTU\n"); - /* Try to allocate the new DMA conf with the new mtu */ - dma_conf = stmmac_setup_dma_desc(priv, mtu); - if (IS_ERR(dma_conf)) { - netdev_err(priv->dev, "failed allocating new dma conf for new MTU %d\n", - mtu); - return PTR_ERR(dma_conf); - } - - netif_device_detach(dev); - __stmmac_release(dev); - - ret = __stmmac_open(dev, dma_conf); - if (ret) { - priv->dma_conf = old_conf; - stmmac_put_dma_conf(priv, dma_conf); - /* - * Keep the administrative state and PHY/PM ownership until - * ndo_stop(), but prevent use of the released data path. - */ - netif_device_detach(dev); - netdev_err(priv->dev, "failed reopening the interface after MTU change\n"); + ret = stmmac_reconfigure_mtu(dev, mtu); + if (ret) return ret; - } - - stmmac_put_dma_conf(priv, old_conf); - - stmmac_set_rx_mode(dev); - netif_device_attach(dev); } WRITE_ONCE(dev->mtu, mtu); @@ -7632,11 +7757,12 @@ static int stmmac_bpf(struct net_device *dev, struct netdev_bpf *bpf) return -EOPNOTSUPP; /* - * Pool removal must succeed even after a failed resume. Release the - * suspended rings before their pool or XDP buffer layout can change. + * Pool removal must succeed after failed resume or MTU rollback. Release + * retained rings before their pool or XDP buffer layout can change. * Leave the interface detached until it is closed and reopened. */ - if (priv->datapath == STMMAC_DATAPATH_SUSPENDED) + if (priv->datapath == STMMAC_DATAPATH_SUSPENDED || + priv->datapath == STMMAC_DATAPATH_HALTED) __stmmac_release(dev); switch (bpf->command) {