From: Sandeep Haemoon <sandeeph@loljews.com>
To: netdev@vger.kernel.org
Cc: Felix Fietkau <nbd@nbd.name>,
Lorenzo Bianconi <lorenzo@kernel.org>,
stable@vger.kernel.org
Subject: [PATCH net v2] net: ethernet: mtk_eth_soc: allocate dummy netdev before registering netdevs
Date: Sun, 20 Sep 2026 20:38:15 +0300 [thread overview]
Message-ID: <patch-33e50d280ef35a7fd2f2dc09deea463a@loljews.com> (raw)
In-Reply-To: <patch-12c1a57b1d914b28b89455f24de55ee4@loljews.com>
The RX rings and the shared NAPI are carried by an internal "dummy" netdev
(eth->dummy_dev). mtk_probe() creates that dummy device only after the MAC
netdevs have been registered, so for a brief window the netdevs are visible
to the network core while eth->dummy_dev is still NULL.
If anything brings the first netdev up during that window (e.g. netifd
opening the WAN link the instant the interface is registered), mtk_open()
takes the first-open path and runs mtk_start_dma() -> mtk_dma_init() ->
mtk_rx_alloc(), which calls __xdp_rxq_info_reg() with eth->dummy_dev ==
NULL. That triggers
WARNING: CPU: ... Missing net_device from driver
in net/core/xdp.c and returns -ENODEV, so mtk_open() fails and the
interface stays down until it is manually brought up once probe finishes.
Allocate the dummy netdev and add the shared tx/rx NAPI to it before the
register_netdev() loop. Both the dummy-allocation failure and a
register_netdev() failure now unwind through mtk_unreg_dev(), which
unregisters the net_device notifiers and the netdevs registered so far -
stopping a concurrently-opened netdev (ndo_stop) and its NAPI before the
dummy carrier is freed. The never-registered netdevs are skipped thanks to
the NETREG_REGISTERED guard in mtk_unreg_dev() and freed directly.
Fixes: b209bd6d0bff ("net: mediatek: mtk_eth_sock: allocate dummy net_device dynamically")
Signed-off-by: Sandeep Haemoon <sandeeph@loljews.com>
---
Version 2:
- Rebased on top of netdev/net.git, which now carries Lorenzo Bianconi's
"mtk_eth_soc: unregister net_devices in case of probe failure" fix; the
dummy allocation sits before the register_netdev() loop and both its
failure and a register_netdev() failure unwind through mtk_unreg_dev(),
unregistering the net_device notifiers and every netdev registered so
far (never-registered ones are skipped by the NETREG_REGISTERED guard)
before the dummy carrier is freed.
- Error path stops any concurrently-opened netdev (ndo_stop, NAPI
disabled) via that unregister, then frees the dummy carrier; a
dummy-allocation failure likewise cleans the notifier chain that
mtk_add_mac() registered.
- Add Fixes: b209bd6d0bff, the commit that made eth->dummy_dev dynamic
and introduced the NULL window.
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 33 +++++++++++++--------
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 2ea5dfe85..5e7d8b8be 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -5341,6 +5341,22 @@ static int mtk_probe(struct platform_device *pdev)
}
}
+ /* we run 2 devices on the same DMA ring so we need a dummy device
+ * for NAPI to work. Allocate it before registering the netdevs so a
+ * concurrent ndo_open (e.g. netifd bringing the first netdev up the
+ * instant it is registered) never observes eth->dummy_dev == NULL in
+ * mtk_dma_init() -> mtk_rx_alloc() -> __xdp_rxq_info_reg() (net/core/xdp.c
+ * "Missing net_device from driver") and fails the first open.
+ */
+ eth->dummy_dev = alloc_netdev_dummy(0);
+ if (!eth->dummy_dev) {
+ err = -ENOMEM;
+ dev_err(eth->dev, "failed to allocated dummy device\n");
+ goto err_unreg_netdev;
+ }
+ netif_napi_add(eth->dummy_dev, ð->tx_napi, mtk_napi_tx);
+ netif_napi_add(eth->dummy_dev, ð->rx_napi, mtk_napi_rx);
+
for (i = 0; i < MTK_MAX_DEVS; i++) {
if (!eth->netdev[i])
continue;
@@ -5355,18 +5371,6 @@ static int mtk_probe(struct platform_device *pdev)
eth->netdev[i]->base_addr, eth->irq[MTK_FE_IRQ_SHARED]);
}
- /* we run 2 devices on the same DMA ring so we need a dummy device
- * for NAPI to work
- */
- eth->dummy_dev = alloc_netdev_dummy(0);
- if (!eth->dummy_dev) {
- err = -ENOMEM;
- dev_err(eth->dev, "failed to allocated dummy device\n");
- goto err_unreg_netdev;
- }
- netif_napi_add(eth->dummy_dev, ð->tx_napi, mtk_napi_tx);
- netif_napi_add(eth->dummy_dev, ð->rx_napi, mtk_napi_rx);
-
platform_set_drvdata(pdev, eth);
schedule_delayed_work(ð->reset.monitor_work,
MTK_DMA_MONITOR_TIMEOUT);
@@ -5376,6 +5380,11 @@ static int mtk_probe(struct platform_device *pdev)
err_unreg_netdev:
mtk_unreg_dev(eth);
err_deinit_ppe:
+ if (eth->dummy_dev) {
+ netif_napi_del(ð->tx_napi);
+ netif_napi_del(ð->rx_napi);
+ free_netdev(eth->dummy_dev);
+ }
mtk_ppe_deinit(eth);
mtk_mdio_cleanup(eth);
err_free_dev:
--
2.53.0
next prev parent reply other threads:[~2026-09-20 17:38 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-15 18:55 [PATCH] net: ethernet: mtk_eth_soc: allocate dummy netdev before registering netdevs Sandeep Haemoon
2026-09-16 13:32 ` Lorenzo Bianconi
2026-09-19 1:52 ` netdev-bot+sashiko
2026-09-20 17:38 ` Sandeep Haemoon [this message]
2026-09-24 16:31 ` [PATCH net v2] " Jakub Kicinski
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=patch-33e50d280ef35a7fd2f2dc09deea463a@loljews.com \
--to=sandeeph@loljews.com \
--cc=lorenzo@kernel.org \
--cc=nbd@nbd.name \
--cc=netdev@vger.kernel.org \
--cc=stable@vger.kernel.org \
/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