]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: airoha: Move net_devs registration in a dedicated routine
authorLorenzo Bianconi <lorenzo@kernel.org>
Sun, 14 Dec 2025 09:30:07 +0000 (10:30 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 8 Jan 2026 09:16:45 +0000 (10:16 +0100)
[ Upstream commit 5e7365b5a1ac8f517a7a84442289d7de242deb76 ]

Since airoha_probe() is not executed under rtnl lock, there is small race
where a given device is configured by user-space while the remaining ones
are not completely loaded from the dts yet. This condition will allow a
hw device misconfiguration since there are some conditions (e.g. GDM2 check
in airoha_dev_init()) that require all device are properly loaded from the
device tree. Fix the issue moving net_devices registration at the end of
the airoha_probe routine.

Fixes: 9cd451d414f6e ("net: airoha: Add loopback support for GDM2")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20251214-airoha-fix-dev-registration-v1-1-860e027ad4c6@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/airoha/airoha_eth.c

index 433a646e9831773bf63600e7c3d3b2176c4d133e..0394ba6a90a9b218d54e04b89dab2fd60bd9b867 100644 (file)
@@ -2900,19 +2900,26 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth,
        port->id = id;
        eth->ports[p] = port;
 
-       err = airoha_metadata_dst_alloc(port);
-       if (err)
-               return err;
+       return airoha_metadata_dst_alloc(port);
+}
 
-       err = register_netdev(dev);
-       if (err)
-               goto free_metadata_dst;
+static int airoha_register_gdm_devices(struct airoha_eth *eth)
+{
+       int i;
 
-       return 0;
+       for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
+               struct airoha_gdm_port *port = eth->ports[i];
+               int err;
 
-free_metadata_dst:
-       airoha_metadata_dst_free(port);
-       return err;
+               if (!port)
+                       continue;
+
+               err = register_netdev(port->dev);
+               if (err)
+                       return err;
+       }
+
+       return 0;
 }
 
 static int airoha_probe(struct platform_device *pdev)
@@ -2993,6 +3000,10 @@ static int airoha_probe(struct platform_device *pdev)
                }
        }
 
+       err = airoha_register_gdm_devices(eth);
+       if (err)
+               goto error_napi_stop;
+
        return 0;
 
 error_napi_stop:
@@ -3006,10 +3017,12 @@ error_hw_cleanup:
        for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
                struct airoha_gdm_port *port = eth->ports[i];
 
-               if (port && port->dev->reg_state == NETREG_REGISTERED) {
+               if (!port)
+                       continue;
+
+               if (port->dev->reg_state == NETREG_REGISTERED)
                        unregister_netdev(port->dev);
-                       airoha_metadata_dst_free(port);
-               }
+               airoha_metadata_dst_free(port);
        }
        free_netdev(eth->napi_dev);
        platform_set_drvdata(pdev, NULL);