diff mbox series

[02/12] net: lwip: fix initialization sequence before a command

Message ID 20250314215525.579655-3-jerome.forissier@linaro.org
State New
Headers show
Series lwIP sandbox tests | expand

Commit Message

Jerome Forissier March 14, 2025, 9:55 p.m. UTC
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>
---
 include/net-lwip.h  |  9 ++++++++-
 net/lwip/dhcp.c     |  3 ++-
 net/lwip/dns.c      |  3 ++-
 net/lwip/net-lwip.c | 40 +++++++++++++++++++++++++++++-----------
 net/lwip/ping.c     |  3 ++-
 net/lwip/tftp.c     |  5 ++++-
 net/lwip/wget.c     |  6 +++++-
 7 files changed, 52 insertions(+), 17 deletions(-)
diff mbox series

Patch

diff --git a/include/net-lwip.h b/include/net-lwip.h
index 64e5c720560..0d3bb8a8bd8 100644
--- a/include/net-lwip.h
+++ b/include/net-lwip.h
@@ -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);
diff --git a/net/lwip/dhcp.c b/net/lwip/dhcp.c
index 3b7e4700c6e..92bd7067a7f 100644
--- a/net/lwip/dhcp.c
+++ b/net/lwip/dhcp.c
@@ -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) {
diff --git a/net/lwip/dns.c b/net/lwip/dns.c
index 149bdb784dc..19172ac959a 100644
--- a/net/lwip/dns.c
+++ b/net/lwip/dns.c
@@ -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);
 }
diff --git a/net/lwip/net-lwip.c b/net/lwip/net-lwip.c
index c00a7fe97cd..1e60fa31bfb 100644
--- a/net/lwip/net-lwip.c
+++ b/net/lwip/net-lwip.c
@@ -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;
+	int ret;
 
-	if (!init_done) {
-		eth_init_rings();
-		eth_init();
-		lwip_init();
-		init_done = true;
+	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;
 }
diff --git a/net/lwip/ping.c b/net/lwip/ping.c
index c586a96806d..542ef2cb148 100644
--- a/net/lwip/ping.c
+++ b/net/lwip/ping.c
@@ -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;
diff --git a/net/lwip/tftp.c b/net/lwip/tftp.c
index 123d66b5dba..4f9b2049187 100644
--- a/net/lwip/tftp.c
+++ b/net/lwip/tftp.c
@@ -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;
diff --git a/net/lwip/wget.c b/net/lwip/wget.c
index ec098148835..a3b82908877 100644
--- a/net/lwip/wget.c
+++ b/net/lwip/wget.c
@@ -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;