The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH] net: hip04: quiesce tx coalesce timer before teardown
@ 2026-07-03  5:01 Fan Wu
  2026-07-09 12:43 ` Simon Horman
  0 siblings, 1 reply; 3+ messages in thread
From: Fan Wu @ 2026-07-03  5:01 UTC (permalink / raw)
  To: netdev
  Cc: shenjian15, salil.mehta, andrew+netdev, davem, edumazet, kuba,
	pabeni, linux-kernel, stable, Fan Wu

hip04_start_tx_timer() arms priv->tx_coalesce_timer from both the
TX path and the NAPI poll path. The timer callback, tx_done(), derives
priv from the timer and touches priv->napi, priv->reg_inten and
priv->base before scheduling NAPI.

The remove path currently frees the TX/RX rings before unregistering the
netdev. If the interface is still up, unregister_netdev() will run
.ndo_stop only after those rings have already been freed, while a pending
TX coalesce timer or NAPI instance can still reach the ring state. The
timer is also never cancelled before free_netdev() releases the netdev
private area.

Cancel the timer from hip04_mac_stop() after NAPI and the TX queue have
been disabled. In hip04_remove(), unregister the netdev first, drain the
timeout work and timer, and only then free the rings.

hip04_tx_timeout_task() can also restart the device by calling
hip04_mac_stop() followed by hip04_mac_open(). Serialize that restart with
rtnl_lock(), matching the netdev core's .ndo_stop locking, and skip it if
the device is no longer running.

Fixes: a41ea46a9a12 ("net: hisilicon: new hip04 ethernet driver")
Cc: stable@vger.kernel.org
Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
---
diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
index 18376bc..cb9b01c 100644
--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -15,6 +15,7 @@
 #include <linux/of_net.h>
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
+#include <linux/rtnetlink.h>
 
 #define SC_PPE_RESET_DREQ		0x026C
 
@@ -761,6 +762,13 @@ static int hip04_mac_stop(struct net_device *ndev)
 
 	napi_disable(&priv->napi);
 	netif_stop_queue(ndev);
+
+	/* Cancel the TX-coalesce timer after the arming paths (xmit via the
+	 * queue, rx poll via NAPI) are disabled, so a pending tx_done()
+	 * (which dereferences priv) is drained before the device is freed.
+	 */
+	hrtimer_cancel(&priv->tx_coalesce_timer);
+
 	hip04_mac_disable(ndev);
 	hip04_tx_reclaim(ndev, true);
 	hip04_reset_ppe(priv);
@@ -791,8 +799,15 @@ static void hip04_tx_timeout_task(struct work_struct *work)
 	struct hip04_priv *priv;
 
 	priv = container_of(work, struct hip04_priv, tx_timeout_task);
+
+	rtnl_lock();
+	if (!netif_running(priv->ndev))
+		goto out;
+
 	hip04_mac_stop(priv->ndev);
 	hip04_mac_open(priv->ndev);
+out:
+	rtnl_unlock();
 }
 
 static int hip04_get_coalesce(struct net_device *netdev,
@@ -1029,10 +1044,15 @@ static void hip04_remove(struct platform_device *pdev)
 	if (priv->phy)
 		phy_disconnect(priv->phy);
 
-	hip04_free_ring(ndev, d);
 	unregister_netdev(ndev);
-	of_node_put(priv->phy_node);
 	cancel_work_sync(&priv->tx_timeout_task);
+	hrtimer_cancel(&priv->tx_coalesce_timer);
+	/* Free the rings only after the interface is stopped (.ndo_stop via
+	 * unregister_netdev) and the work/timer are drained; the TX/NAPI
+	 * paths touch them while the device is up.
+	 */
+	hip04_free_ring(ndev, d);
+	of_node_put(priv->phy_node);
 	free_netdev(ndev);
 }
 


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-07-11  5:34 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-03  5:01 [PATCH] net: hip04: quiesce tx coalesce timer before teardown Fan Wu
2026-07-09 12:43 ` Simon Horman
2026-07-11  5:34   ` Fan Wu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox