[PATCH net-next v6 3/3] net: dsa: let user ports wait for a PHY that probes late

From: Aleksei Sviridkin

Date: Tue Oct 06 2026 - 08:48:07 EST


A user port connects its PHY once, when the switch sets up its ports.
If that PHY needs firmware from the host and its driver is a module not
loaded yet, the port gets no working PHY for the rest of the uptime.

Let a switch driver opt its user ports in to phylink waiting for such a
PHY, and opt in mt7530. Until the PHY attaches, .port_enable sees a NULL
phy, so the opt-in is per driver: qca8k dereferences that argument, and
gswip programs the PHY address from it at open, so a late attach leaves
it wrong until the next open. mt7530 does not use it. Shared ports are
left out.

Found on a Keenetic KN-1012 (MT7981B with an MT7531 switch), where the
EN8811H behind lan4 has its driver on the root filesystem and lan4 was
lost for the uptime.

Assisted-by: LLM
Signed-off-by: Aleksei Sviridkin <f@xxxxxx>
---
Changes in v6: the dsa.h comment says .port_enable must not use its
phy argument, rather than cope with a NULL one.

drivers/net/dsa/mt7530.c | 1 +
include/net/dsa.h | 5 +++++
net/dsa/user.c | 1 +
3 files changed, 7 insertions(+)

diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 7781a63b4e6f..e4c155605e27 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -3548,6 +3548,7 @@ mt7530_probe_common(struct mt7530_priv *priv)
priv->ds->priv = priv;
priv->ds->ops = &mt7530_switch_ops;
priv->ds->phylink_mac_ops = &mt753x_phylink_mac_ops;
+ priv->ds->phy_may_probe_late = true;
mutex_init(&priv->reg_mutex);
spin_lock_init(&priv->stats_lock);
INIT_DELAYED_WORK(&priv->stats_work, mt7530_stats_poll);
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 5d12191b6f6f..04b151cd52ce 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -455,6 +455,11 @@ struct dsa_switch {
*/
u32 dscp_prio_mapping_is_global:1;

+ /* Drivers whose .port_enable does not use its phy argument may set
+ * this to let user ports wait for a PHY that needs host firmware.
+ */
+ u32 phy_may_probe_late:1;
+
/* Listener for switch fabric events */
struct notifier_block nb;

diff --git a/net/dsa/user.c b/net/dsa/user.c
index 041f9060c8ef..41075bb74193 100644
--- a/net/dsa/user.c
+++ b/net/dsa/user.c
@@ -2661,6 +2661,7 @@ static int dsa_user_phy_setup(struct net_device *user_dev)

dp->pl_config.dev = &user_dev->dev;
dp->pl_config.type = PHYLINK_NETDEV;
+ dp->pl_config.phy_may_probe_late = ds->phy_may_probe_late;

/* The get_fixed_state callback takes precedence over polling the
* link GPIO in PHYLINK (see phylink_get_fixed_state). Only set
--
2.53.0