]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
qualcommax: qca_edma: give the DSA conduit a stable MAC address 24512/head
authorJulius Bairaktaris <julius@bairaktaris.de>
Fri, 31 Jul 2026 22:27:46 +0000 (00:27 +0200)
committerJonas Jelonek <jelonek.jonas@gmail.com>
Sun, 2 Aug 2026 09:17:46 +0000 (11:17 +0200)
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 <julius@bairaktaris.de>
Link: https://github.com/openwrt/openwrt/pull/24512
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_edma.c

index 9bfa9e867ba0d900c6c3a1926aeff66f8e609d7a..0f032de8efaf0cc8680cfd6de25efe772009691f 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_net.h>
 #include <linux/of_platform.h>
 #include <linux/property.h>
 #include <linux/regmap.h>
@@ -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;