From: James Hilliard <james.hilliard1@gmail.com>
To: Russell King <linux@armlinux.org.uk>,
Andrew Lunn <andrew@lunn.ch>,
Heiner Kallweit <hkallweit1@gmail.com>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>,
Joakim Zhang <qiangqing.zhang@nxp.com>,
"Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>,
Maxime Chevallier <maxime.chevallier@bootlin.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
Maxime Coquelin <mcoquelin.stm32@gmail.com>,
Alexandre Torgue <alexandre.torgue@foss.st.com>,
Christian Marangi <ansuelsmth@gmail.com>,
Tiezhu Yang <yangtiezhu@loongson.cn>,
Huacai Chen <chenhuacai@kernel.org>,
Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Jesper Dangaard Brouer <hawk@kernel.org>,
John Fastabend <john.fastabend@gmail.com>,
Stanislav Fomichev <sdf@fomichev.me>,
Serge Semin <fancer.lancer@gmail.com>,
Suraj Jaiswal <quic_jsuraj@quicinc.com>,
Richard Cochran <richardcochran@gmail.com>,
Joao Pinto <Joao.Pinto@synopsys.com>,
Vladimir Oltean <vladimir.oltean@nxp.com>,
Ong Boon Leong <boon.leong.ong@intel.com>,
Voon Weifeng <weifeng.voon@intel.com>,
"Song, Yoong Siang" <yoong.siang.song@intel.com>
Cc: Richard Genoud <richard.genoud@bootlin.com>,
Alastair D'Silva <alastair@d-silva.org>,
Maxime Ripard <mripard@kernel.org>,
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 <zhaojinming@uniontech.com>,
Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>,
Ding Hui <dinghui1111@163.com>,
James Hilliard <james.hilliard1@gmail.com>
Subject: [PATCH net v3 10/10] net: stmmac: retain DMA resources across MTU changes
Date: Thu, 24 Sep 2026 11:44:40 -0600 [thread overview]
Message-ID: <20260924-submit-stmmac-reset-fixes-v1-v3-10-c031e3f3a282@gmail.com> (raw)
In-Reply-To: <20260924-submit-stmmac-reset-fixes-v1-v3-0-c031e3f3a282@gmail.com>
Releasing the current datapath before reopening with a new MTU loses the
working configuration when hardware setup fails. Keep the old rings and
IRQ registrations until replacement hardware setup succeeds, so an
ordinary setup error can restore the old MTU without allocating new rings
or requesting interrupts again.
The preceding changes provide safe allocation unwind, stable DMA/IRQ
objects and a no-reset path for normal-size MTUs. For jumbo transitions,
prepare the replacement first, then quiesce the old queues and drain IRQ
handlers and network readers. Fill holes in the old RX buffer array before
resetting DMA, without altering its descriptors. Rollback can then rebuild
the old rings without allocations.
Only a successful reset permits old descriptors to be rewritten or retired:
clearing a DMA enable bit need not finish an in-flight frame immediately.
Separate buffer allocation from descriptor initialization so preparation
can fail without changing the active rings.
Publish the prospective MTU before MAC setup, since dwmac1000 uses it to
select receive limits. On error, restore the old MTU and configuration
before resetting and rebuilding the old rings. If that reset also fails,
retain the old rings and leave the administratively-up interface detached,
with IRQs released and NAPI stopped, until ordinary down/up recovery.
Distinguish this HALTED state from SUSPENDED, which still owns its IRQs.
Preserve coalescing, PHC registration and packet timestamp filters instead
of running a complete close/open. Reinitialize timestamp hardware after
reset without creating a new PHC. This does not preserve continuous PHC
time across the reset.
Fixes: 3470079687448 ("net: ethernet: stmicro: stmmac: permit MTU change with interface up")
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 +
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 327 +++++++++++++++++-----
2 files changed, 257 insertions(+), 72 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index f07623a1285c..8ebf40789568 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -265,6 +265,8 @@ enum stmmac_datapath_state {
STMMAC_DATAPATH_RUNNING,
/* Resources retained, NAPI and DMA stopped; also after failed resume. */
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 d17c68f55caf..1a552455a633 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1629,24 +1629,10 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv,
stmmac_clear_tx_descriptors(priv, dma_conf, queue);
}
-/**
- * stmmac_init_rx_buffers - init the RX descriptor buffer.
- * @priv: driver private structure
- * @dma_conf: structure to take the dma data
- * @p: descriptor pointer
- * @i: descriptor index
- * @flags: gfp flag
- * @queue: RX queue index
- * Description: this function is called to allocate a receive buffer, perform
- * the DMA mapping and init the descriptor.
- */
-static int stmmac_init_rx_buffers(struct stmmac_priv *priv,
- struct stmmac_dma_conf *dma_conf,
- struct dma_desc *p,
- int i, gfp_t flags, u32 queue)
+static int stmmac_alloc_rx_buffer(struct stmmac_priv *priv,
+ struct stmmac_rx_queue *rx_q,
+ struct stmmac_rx_buffer *buf)
{
- struct stmmac_rx_queue *rx_q = &dma_conf->rx_queue[queue];
- struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i];
gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN);
if (priv->dma_cap.host_dma_width <= 32)
@@ -1663,19 +1649,49 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv,
buf->sec_page = page_pool_alloc_pages(rx_q->page_pool, gfp);
if (!buf->sec_page)
return -ENOMEM;
-
buf->sec_addr = page_pool_get_dma_addr(buf->sec_page);
- stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, true);
- } else {
- buf->sec_page = NULL;
- stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, false);
}
+ return 0;
+}
+
+static void stmmac_init_rx_buffer_desc(struct stmmac_priv *priv,
+ struct stmmac_dma_conf *dma_conf,
+ struct dma_desc *p,
+ struct stmmac_rx_buffer *buf)
+{
+ if (buf->sec_page)
+ buf->sec_addr = page_pool_get_dma_addr(buf->sec_page);
+ stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, !!buf->sec_page);
buf->addr = page_pool_get_dma_addr(buf->page) + buf->page_offset;
stmmac_set_desc_addr(priv, p, buf->addr);
if (dma_conf->dma_buf_sz == BUF_SIZE_16KiB)
stmmac_init_desc3(priv, p);
+}
+
+/**
+ * stmmac_init_rx_buffers - allocate a receive buffer and init its descriptor
+ * @priv: driver private structure
+ * @dma_conf: structure to take the dma data
+ * @p: descriptor pointer
+ * @i: descriptor index
+ * @flags: gfp flag
+ * @queue: RX queue index
+ */
+static int stmmac_init_rx_buffers(struct stmmac_priv *priv,
+ struct stmmac_dma_conf *dma_conf,
+ struct dma_desc *p,
+ int i, gfp_t flags, u32 queue)
+{
+ struct stmmac_rx_queue *rx_q = &dma_conf->rx_queue[queue];
+ struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i];
+ int ret;
+
+ ret = stmmac_alloc_rx_buffer(priv, rx_q, buf);
+ if (ret)
+ return ret;
+ stmmac_init_rx_buffer_desc(priv, dma_conf, p, buf);
return 0;
}
@@ -2132,6 +2148,63 @@ 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, and with all RX buffers prepared. */
+static void stmmac_reinit_dma_desc(struct stmmac_priv *priv)
+{
+ struct stmmac_dma_conf *dma_conf = priv->dma_conf;
+ u32 queue, i;
+
+ stmmac_free_tx_skbufs(priv);
+ stmmac_reset_queues_param(priv);
+ init_dma_tx_desc_rings(priv->dev, dma_conf);
+ stmmac_clear_descriptors(priv, dma_conf);
+
+ for (queue = 0; queue < priv->plat->rx_queues_to_use; queue++) {
+ struct stmmac_rx_queue *rx_q = &dma_conf->rx_queue[queue];
+
+ if (rx_q->state_saved)
+ dev_kfree_skb_any(rx_q->state.skb);
+ rx_q->state.skb = NULL;
+ rx_q->state_saved = 0;
+ rx_q->rx_count_frames = 0;
+ rx_q->buf_alloc_num = dma_conf->dma_rx_size;
+
+ for (i = 0; i < dma_conf->dma_rx_size; i++)
+ stmmac_init_rx_buffer_desc(priv, dma_conf,
+ stmmac_get_rx_desc(priv, rx_q, i),
+ &rx_q->buf_pool[i]);
+
+ if (priv->descriptor_mode == STMMAC_CHAIN_MODE)
+ stmmac_mode_init(priv, stmmac_get_rx_desc(priv, rx_q, 0),
+ rx_q->dma_rx_phy, dma_conf->dma_rx_size,
+ priv->extend_desc);
+ }
+}
+
/**
* __free_dma_rx_desc_resources - free RX dma desc resources (per queue)
* @priv: private structure
@@ -3285,12 +3358,13 @@ static int stmmac_prereset_configure(struct stmmac_priv *priv)
/**
* stmmac_init_dma_engine - DMA init.
* @priv: driver private structure
+ * @reinit: rebuild the retained rings after a successful reset
* Description:
* It inits the DMA invoking the specific MAC/GMAC callback.
* Some DMA parameters can be passed from the platform;
* in case of these are not passed a default is kept for the MAC or GMAC.
*/
-static int stmmac_init_dma_engine(struct stmmac_priv *priv)
+static int stmmac_init_dma_engine(struct stmmac_priv *priv, bool reinit)
{
u8 rx_channels_count = priv->plat->rx_queues_to_use;
u8 tx_channels_count = priv->plat->tx_queues_to_use;
@@ -3310,6 +3384,9 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
return ret;
}
+ if (reinit)
+ stmmac_reinit_dma_desc(priv);
+
/* DMA Configuration */
stmmac_dma_init(priv, priv->ioaddr, priv->plat->dma_cfg);
@@ -3657,6 +3734,7 @@ static bool stmmac_tso_channel_permitted(struct stmmac_priv *priv,
/**
* stmmac_hw_setup - setup mac in a usable state.
* @dev : pointer to the device structure.
+ * @reinit: rebuild retained descriptor rings after the DMA reset
* Description:
* this is the main function to setup the HW in a usable state because the
* dma engine is reset, the core registers are configured (e.g. AXI,
@@ -3666,7 +3744,7 @@ static bool stmmac_tso_channel_permitted(struct stmmac_priv *priv,
* 0 on success and an appropriate (-)ve integer as defined in errno.h
* file on failure.
*/
-static int stmmac_hw_setup(struct net_device *dev)
+static int stmmac_hw_setup(struct net_device *dev, bool reinit)
{
struct stmmac_priv *priv = netdev_priv(dev);
u8 rx_cnt = priv->plat->rx_queues_to_use;
@@ -3688,7 +3766,7 @@ static int stmmac_hw_setup(struct net_device *dev)
phylink_rx_clk_stop_block(priv->phylink);
/* DMA initialization and SW reset */
- ret = stmmac_init_dma_engine(priv);
+ ret = stmmac_init_dma_engine(priv, reinit);
if (ret < 0) {
phylink_rx_clk_stop_unblock(priv->phylink);
netdev_err(priv->dev, "%s: DMA engine initialization failed\n",
@@ -3804,8 +3882,7 @@ static void stmmac_free_irq(struct net_device *dev,
for (j = irq_idx - 1; msi && j >= 0; j--) {
if (msi->tx_irq[j] > 0) {
irq_set_affinity_hint(msi->tx_irq[j], NULL);
- free_irq(msi->tx_irq[j],
- &priv->channel[j]);
+ free_irq(msi->tx_irq[j], &priv->channel[j]);
}
}
irq_idx = priv->plat->rx_queues_to_use;
@@ -3814,8 +3891,7 @@ static void stmmac_free_irq(struct net_device *dev,
for (j = irq_idx - 1; msi && j >= 0; j--) {
if (msi->rx_irq[j] > 0) {
irq_set_affinity_hint(msi->rx_irq[j], NULL);
- free_irq(msi->rx_irq[j],
- &priv->channel[j]);
+ free_irq(msi->rx_irq[j], &priv->channel[j]);
}
}
@@ -4080,14 +4156,40 @@ static int stmmac_request_irq(struct net_device *dev)
return ret;
}
+/* Balance disable_irq()/enable_irq() for every registered IRQ, including
+ * shared lines. Unlike freeing and requesting IRQs, this cannot fail.
+ */
+static void stmmac_set_irq_state(struct stmmac_priv *priv, bool enable)
+{
+ void (*set_state)(unsigned int) = enable ? enable_irq : disable_irq;
+ struct stmmac_msi *msi = priv->msi;
+ int irq = priv->dev->irq;
+ u32 i;
+
+ set_state(irq);
+ if (priv->wol_irq > 0 && priv->wol_irq != irq)
+ set_state(priv->wol_irq);
+ if (priv->sfty_irq > 0 && priv->sfty_irq != irq)
+ set_state(priv->sfty_irq);
+ if (!msi)
+ return;
+ if (msi->sfty_ce_irq > 0 && msi->sfty_ce_irq != irq)
+ set_state(msi->sfty_ce_irq);
+ if (msi->sfty_ue_irq > 0 && msi->sfty_ue_irq != irq)
+ set_state(msi->sfty_ue_irq);
+ for (i = 0; i < priv->plat->rx_queues_to_use; i++)
+ if (msi->rx_irq[i] > 0)
+ set_state(msi->rx_irq[i]);
+ for (i = 0; i < priv->plat->tx_queues_to_use; i++)
+ if (msi->tx_irq[i] > 0)
+ set_state(msi->tx_irq[i]);
+}
+
/**
- * 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)
@@ -4220,7 +4322,7 @@ static int __stmmac_open(struct net_device *dev,
stmmac_reset_queues_param(priv);
- ret = stmmac_hw_setup(dev);
+ ret = stmmac_hw_setup(dev, false);
if (ret < 0) {
netdev_err(priv->dev, "%s: Hw setup failed\n", __func__);
goto init_error;
@@ -4341,8 +4443,9 @@ 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;
@@ -4354,7 +4457,8 @@ static void __stmmac_release(struct net_device *dev)
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);
/* TX error IRQs can restart a queue after the first quiescence. */
stmmac_stop_tx_queues(priv);
@@ -6234,6 +6338,113 @@ 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 chan;
+
+ new_conf = stmmac_setup_dma_desc(priv, mtu);
+ if (IS_ERR(new_conf))
+ return PTR_ERR(new_conf);
+
+ netif_device_detach(dev);
+ phylink_stop(priv->phylink);
+ stmmac_quiesce(priv);
+ timer_delete_sync(&priv->eee_ctrl_timer);
+ if (stmmac_fpe_supported(priv))
+ ethtool_mmsv_stop(&priv->fpe_cfg.mmsv);
+
+ /* An IRQ can recover a TX error and restart a queue. Drain handlers
+ * before the final TX stop, and keep the registrations for rollback.
+ */
+ stmmac_set_irq_state(priv, false);
+ netif_tx_disable(dev);
+ synchronize_net();
+
+ 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);
+ 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);
+ if (restore_ret) {
+ stmmac_stop_all_dma(priv);
+ stmmac_mac_set(priv, priv->ioaddr, false);
+ stmmac_set_irq_state(priv, true);
+ stmmac_free_irq(dev, REQ_IRQ_ERR_ALL, 0);
+ netif_tx_disable(dev);
+ stmmac_stop_all_dma(priv);
+ 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.
+ */
+ free_dma_desc_resources(priv, old_conf);
+ kfree(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);
+ }
+
+ /* Restore timestamping without registering a new PHC or resetting the
+ * user's packet timestamp filters. Timestamping can also be used without
+ * a registered PHC (CONFIG_PTP_1588_CLOCK=n).
+ */
+ if ((priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp) &&
+ priv->plat->clk_ptp_rate) {
+ unsigned long flags;
+
+ write_lock_irqsave(&priv->ptp_lock, flags);
+ stmmac_init_tstamp_counter(priv, priv->systime_flags);
+ if (priv->plat->flags & STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY)
+ stmmac_hwtstamp_correct_latency(priv, priv);
+ write_unlock_irqrestore(&priv->ptp_lock, flags);
+ }
+ stmmac_set_rx_mode(dev);
+ stmmac_vlan_restore(priv);
+
+restart:
+ stmmac_enable_all_queues(priv);
+ stmmac_enable_all_dma_irq(priv);
+ stmmac_set_irq_state(priv, true);
+ 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;
+
+free_new:
+ free_dma_desc_resources(priv, new_conf);
+ kfree(new_conf);
+ return ret;
+}
+
/**
* stmmac_change_mtu - entry point to change MTU size for the device.
* @dev : device pointer.
@@ -6248,9 +6459,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;
@@ -6276,36 +6485,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;
- free_dma_desc_resources(priv, dma_conf);
- kfree(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;
- }
-
- kfree(old_conf);
-
- stmmac_set_rx_mode(dev);
- netif_device_attach(dev);
}
WRITE_ONCE(dev->mtu, mtu);
@@ -7091,7 +7273,8 @@ static int stmmac_bpf(struct net_device *dev, struct netdev_bpf *bpf)
* suspended 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) {
@@ -8470,7 +8653,7 @@ int stmmac_resume(struct device *dev)
stmmac_free_tx_skbufs(priv);
stmmac_clear_descriptors(priv, priv->dma_conf);
- ret = stmmac_hw_setup(ndev);
+ ret = stmmac_hw_setup(ndev, false);
if (ret < 0) {
netdev_err(priv->dev, "%s: Hw setup failed\n", __func__);
goto error_stop_dma;
--
2.53.0
next prev parent reply other threads:[~2026-09-24 17:44 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-24 17:44 [PATCH net v3 00/10] net: stmmac: preserve datapath state across MTU and resume failures James Hilliard
2026-09-24 17:44 ` [PATCH net v3 01/10] net: stmmac: unwind the WoL IRQ after a safety IRQ request failure James Hilliard
2026-09-24 17:44 ` [PATCH net v3 02/10] net: phylink: allow stopping a suspended instance James Hilliard
2026-09-24 17:44 ` [PATCH net v3 03/10] net: stmmac: keep datapath state coherent after reinitialization failure James Hilliard
2026-09-25 19:11 ` netdev-bot+sashiko
2026-09-24 17:44 ` [PATCH net v3 04/10] net: stmmac: leave the datapath running for normal-size MTU changes James Hilliard
2026-09-24 17:44 ` [PATCH net v3 05/10] net: stmmac: unwind partially allocated DMA configurations James Hilliard
2026-09-25 19:11 ` netdev-bot+sashiko
2026-09-24 17:44 ` [PATCH net v3 06/10] net: stmmac: keep DMA configurations at stable addresses James Hilliard
2026-09-25 19:12 ` netdev-bot+sashiko
2026-09-24 17:44 ` [PATCH net v3 07/10] net: stmmac: account for failed live XDP reopening James Hilliard
2026-09-25 19:12 ` netdev-bot+sashiko
2026-09-24 17:44 ` [PATCH net v3 08/10] net: stmmac: use the tracked datapath restart for XSK pool changes James Hilliard
2026-09-25 19:12 ` netdev-bot+sashiko
2026-09-24 17:44 ` [PATCH net v3 09/10] net: stmmac: retain PHY and PM ownership during ethtool reopening James Hilliard
2026-09-25 19:12 ` netdev-bot+sashiko
2026-09-24 17:44 ` James Hilliard [this message]
2026-09-25 19:12 ` [PATCH net v3 10/10] net: stmmac: retain DMA resources across MTU changes netdev-bot+sashiko
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=20260924-submit-stmmac-reset-fixes-v1-v3-10-c031e3f3a282@gmail.com \
--to=james.hilliard1@gmail.com \
--cc=Joao.Pinto@synopsys.com \
--cc=alastair@d-silva.org \
--cc=alexandre.torgue@foss.st.com \
--cc=andrew+netdev@lunn.ch \
--cc=andrew@lunn.ch \
--cc=ansuelsmth@gmail.com \
--cc=ast@kernel.org \
--cc=boon.leong.ong@intel.com \
--cc=bpf@vger.kernel.org \
--cc=chenhuacai@kernel.org \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=dinghui1111@163.com \
--cc=edumazet@google.com \
--cc=fancer.lancer@gmail.com \
--cc=hawk@kernel.org \
--cc=hkallweit1@gmail.com \
--cc=john.fastabend@gmail.com \
--cc=kuba@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-stm32@st-md-mailman.stormreply.com \
--cc=linux@armlinux.org.uk \
--cc=lorenzo.bianconi@oss.qualcomm.com \
--cc=maxime.chevallier@bootlin.com \
--cc=mcoquelin.stm32@gmail.com \
--cc=mripard@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=qiangqing.zhang@nxp.com \
--cc=quic_jsuraj@quicinc.com \
--cc=richard.genoud@bootlin.com \
--cc=richardcochran@gmail.com \
--cc=rmk+kernel@armlinux.org.uk \
--cc=sdf@fomichev.me \
--cc=vladimir.oltean@nxp.com \
--cc=weifeng.voon@intel.com \
--cc=yangtiezhu@loongson.cn \
--cc=yoong.siang.song@intel.com \
--cc=zhaojinming@uniontech.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
all inboxes | Powered by JetHome®