From 123cd0466af1d655570980346974c6cd2b8785f5 Mon Sep 17 00:00:00 2001 From: Julius Bairaktaris Date: Sat, 1 Aug 2026 00:27:46 +0200 Subject: [PATCH] qualcommax: qca_edma: give the DSA conduit a stable MAC address edma_probe() assigns a random address unconditionally, so the conduit changes its MAC on every boot, and with it every DSA user port that has no address of its own and therefore inherits the conduit's. The conduit is a DMA engine behind the switch and has no address of its own, which is why no board describes one for it. Take the address from the switch this conduit serves instead: its ports carry the board's addresses, either from DT or patched in by the bootloader, so this needs nothing added per board. Keep the random address for the case where the switch describes no address either. Assisted-by: Claude:claude-opus-5 Signed-off-by: Julius Bairaktaris Link: https://github.com/openwrt/openwrt/pull/24512 Signed-off-by: Jonas Jelonek --- .../drivers/net/ethernet/qualcomm/qca_edma.c | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_edma.c b/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_edma.c index 9bfa9e867ba..0f032de8efa 100644 --- a/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_edma.c +++ b/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_edma.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -1116,6 +1117,42 @@ static const struct regmap_config edma_regmap_cfg = { .val_bits = 32, }; +/* + * The conduit is a DMA engine behind the switch and has no address of its + * own, so boards describe none: fall back to the switch this conduit serves, + * whose ports carry the board's addresses either from DT or patched in by + * the bootloader. DSA user ports without one of their own inherit whatever + * ends up here. + */ +static int edma_get_mac_address(struct net_device *netdev, + struct device_node *np) +{ + struct device_node *cpu_port; + int ret; + + ret = of_get_ethdev_address(np, netdev); + if (!ret || ret == -EPROBE_DEFER) + return ret; + + for_each_node_with_property(cpu_port, "ethernet") { + struct device_node *conduit __free(device_node) = + of_parse_phandle(cpu_port, "ethernet", 0); + + if (conduit != np) + continue; + + for_each_available_child_of_node_scoped(cpu_port->parent, port) { + ret = of_get_ethdev_address(port, netdev); + if (!ret || ret == -EPROBE_DEFER) { + of_node_put(cpu_port); + return ret; + } + } + } + + return -ENODEV; +} + static int edma_probe(struct platform_device *pdev) { struct clk_bulk_data *clks; @@ -1158,6 +1195,12 @@ static int edma_probe(struct platform_device *pdev) priv->pdev = pdev; priv->soc = device_get_match_data(dev); + ret = edma_get_mac_address(netdev, dev->of_node); + if (ret == -EPROBE_DEFER) + return dev_err_probe(dev, ret, "failed to get MAC address\n"); + if (ret) + eth_hw_addr_random(netdev); + ret = edma_page_pool_create(priv); if (ret) return ret; @@ -1168,7 +1211,6 @@ static int edma_probe(struct platform_device *pdev) SET_NETDEV_DEV(netdev, dev); netdev->dev.of_node = dev->of_node; - eth_hw_addr_random(netdev); netdev->netdev_ops = &edma_netdev_ops; netdev->features = NETIF_F_GRO; netdev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS; -- 2.47.3