]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
net: lwip: fix initialization sequence before a command
authorJerome Forissier <jerome.forissier@linaro.org>
Tue, 15 Apr 2025 21:17:36 +0000 (23:17 +0200)
committerJerome Forissier <jerome.forissier@linaro.org>
Wed, 23 Apr 2025 08:02:49 +0000 (10:02 +0200)
The things that are done prior to executing a network command with
NET_LWIP are not consistent with what is done with NET. It impacts the
selection of the current device, and more precisely if the active device
is invalid NET would return an error while NET_LWIP would try to pick a
new device. This incorrect behavior was detected thanks to the eth_rotate
sandbox test (dm_test_eth_rotate()).

Fix it by re-using a sequence similar to what NET has in net_loop().
This piece of code is inserted in a function called net_lwip_eth_start()
renamed from net_lwip_eth_set_current().

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
include/net-lwip.h
net/lwip/dhcp.c
net/lwip/dns.c
net/lwip/net-lwip.c
net/lwip/ping.c
net/lwip/tftp.c
net/lwip/wget.c

index 64e5c7205602d37c906d43e861675c6807ff6331..0d3bb8a8bd892c52ad1045b9d5fac5fddc9bc9b9 100644 (file)
@@ -10,7 +10,14 @@ enum proto_t {
        TFTPGET
 };
 
-void net_lwip_set_current(void);
+static inline int eth_is_on_demand_init(void)
+{
+       return 1;
+}
+
+int eth_init_state_only(void); /* Set active state */
+
+int net_lwip_eth_start(void);
 struct netif *net_lwip_new_netif(struct udevice *udev);
 struct netif *net_lwip_new_netif_noip(struct udevice *udev);
 void net_lwip_remove_netif(struct netif *netif);
index 3b7e4700c6e4dfa69505db15343ff15ac695e842..92bd7067a7fb4f2ba53fd4dff47de351f72c94b3 100644 (file)
@@ -115,7 +115,8 @@ int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
        int ret;
        struct udevice *dev;
 
-       net_lwip_set_current();
+       if (net_lwip_eth_start() < 0)
+               return CMD_RET_FAILURE;
 
        dev = eth_get_dev();
        if (!dev) {
index 149bdb784dceb8fc314ad847c08cc10d97cb7a6e..19172ac959acdc34346bdc9844e537e7d1a83f6f 100644 (file)
@@ -121,7 +121,8 @@ int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
        if (argc == 3)
                var = argv[2];
 
-       net_lwip_set_current();
+       if (net_lwip_eth_start() < 0)
+               return CMD_RET_FAILURE;
 
        return dns_loop(eth_get_dev(), name, var);
 }
index 6b7b696dbf0f8b0b4d20c91eaba1606420dc3bfa..6748008736b768e9e5747f977aea4e3f49926a9c 100644 (file)
@@ -134,18 +134,27 @@ static int get_udev_ipv4_info(struct udevice *dev, ip4_addr_t *ip,
        return 0;
 }
 
-/* Initialize the lwIP stack and the ethernet devices and set current device  */
-void net_lwip_set_current(void)
+/*
+ * Initialize the network stack if needed and start the current device if valid
+ */
+int net_lwip_eth_start(void)
 {
-       static bool init_done;
-
-       if (!init_done) {
-               eth_init_rings();
-               eth_init();
-               lwip_init();
-               init_done = true;
+       int ret;
+
+       net_init();
+       if (eth_is_on_demand_init()) {
+               eth_halt();
+               eth_set_current();
+               ret = eth_init();
+               if (ret < 0) {
+                       eth_halt();
+                       return ret;
+               }
+       } else {
+               eth_init_state_only();
        }
-       eth_set_current();
+
+       return 0;
 }
 
 static struct netif *new_netif(struct udevice *udev, bool with_ip)
@@ -224,11 +233,20 @@ void net_lwip_remove_netif(struct netif *netif)
        free(netif);
 }
 
+/*
+ * Initialize the network buffers, an ethernet device, and the lwIP stack
+ * (once).
+ */
 int net_init(void)
 {
-       eth_set_current();
+       static bool init_done;
 
-       net_lwip_new_netif(eth_get_dev());
+       if (!init_done) {
+               eth_init_rings();
+               eth_init();
+               lwip_init();
+               init_done = true;
+       }
 
        return 0;
 }
index c586a96806d719f259c5ac3c9ace96eb93e0fb9c..542ef2cb1487b8123d2ace7a483f4eec360c14e2 100644 (file)
@@ -168,7 +168,8 @@ int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
        if (!ipaddr_aton(argv[1], &addr))
                return CMD_RET_USAGE;
 
-       net_lwip_set_current();
+       if (net_lwip_eth_start() < 0)
+               return CMD_RET_FAILURE;
 
        if (ping_loop(eth_get_dev(), &addr) < 0)
                return CMD_RET_FAILURE;
index 123d66b5dba928ea4006ac7e05b03c57f35ff656..4f9b2049187c5b841bbf82718e5a4008763d04c9 100644 (file)
@@ -280,7 +280,10 @@ int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
                goto out;
        }
 
-       net_lwip_set_current();
+       if (net_lwip_eth_start() < 0) {
+               ret = CMD_RET_FAILURE;
+               goto out;
+       }
 
        if (tftp_loop(eth_get_dev(), laddr, fname, srvip, port) < 0)
                ret = CMD_RET_FAILURE;
index ec0981488352cbd46f3664f9d88c9e0143435f62..a3b82908877f357e29f4e65d7e31a8df7a55ddd7 100644 (file)
@@ -471,7 +471,11 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
 
 int wget_do_request(ulong dst_addr, char *uri)
 {
-       net_lwip_set_current();
+       int ret;
+
+       ret = net_lwip_eth_start();
+       if (ret < 0)
+               return ret;
 
        if (!wget_info)
                wget_info = &default_wget_info;