From 9f7906a58cf194fc43484f5be4b65e368fa59040 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 11 Jun 2026 18:36:10 -0500 Subject: net: lwip: introduce net_lwip_eth_stop() function Add a introduce net_lwip_eth_stop() function and use that to stop the network interface after each command that uses the network. This makes the behavior the same as the legacy net code and avoids potential issues with the network interface being left in an active state after a command finishes. The start/stop is reference-counted since there is at least one command (dhcp) that calls another command (tftp) to avoid starting and stopping the network interface multiple times in a single command. Signed-off-by: David Lechner Reviewed-by: Jerome Forissier --- cmd/lwip/ping.c | 19 +++++++++++-------- cmd/lwip/sntp.c | 10 ++++++++-- include/net-lwip.h | 1 + net/lwip/dhcp.c | 15 +++++++++++---- net/lwip/dns.c | 7 ++++++- net/lwip/net-lwip.c | 16 ++++++++++++++++ net/lwip/nfs.c | 4 ++++ net/lwip/tftp.c | 4 ++++ net/lwip/wget.c | 5 ++++- 9 files changed, 65 insertions(+), 16 deletions(-) diff --git a/cmd/lwip/ping.c b/cmd/lwip/ping.c index fc4cf7bde5f..98fa8e22bce 100644 --- a/cmd/lwip/ping.c +++ b/cmd/lwip/ping.c @@ -163,6 +163,7 @@ static int ping_loop(struct udevice *udev, const ip_addr_t *addr) int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { ip_addr_t addr; + int ret; if (argc < 2) return CMD_RET_USAGE; @@ -171,13 +172,15 @@ int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) return CMD_RET_USAGE; net_try_count = 1; -restart: - if (net_lwip_eth_start() < 0 || ping_loop(eth_get_dev(), &addr) < 0) { - if (net_start_again() == 0) - goto restart; - else - return CMD_RET_FAILURE; - } - return CMD_RET_SUCCESS; + do { + if (net_lwip_eth_start() == 0) { + ret = ping_loop(eth_get_dev(), &addr); + net_lwip_eth_stop(); + if (ret == 0) + return CMD_RET_SUCCESS; + } + } while (net_start_again() == 0); + + return CMD_RET_FAILURE; } diff --git a/cmd/lwip/sntp.c b/cmd/lwip/sntp.c index 608345c873b..5fa400b104a 100644 --- a/cmd/lwip/sntp.c +++ b/cmd/lwip/sntp.c @@ -101,6 +101,7 @@ int do_sntp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) ip_addr_t *srvip; char *server; ip_addr_t ipaddr; + int ret = CMD_RET_FAILURE; switch (argc) { case 1: @@ -127,7 +128,12 @@ int do_sntp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) return CMD_RET_FAILURE; if (sntp_loop(eth_get_dev(), srvip) < 0) - return CMD_RET_FAILURE; + goto out; + + ret = CMD_RET_SUCCESS; + +out: + net_lwip_eth_stop(); - return CMD_RET_SUCCESS; + return ret; } diff --git a/include/net-lwip.h b/include/net-lwip.h index 20cb0992cce..5d0627eb271 100644 --- a/include/net-lwip.h +++ b/include/net-lwip.h @@ -35,6 +35,7 @@ int eth_init_state_only(void); /* Set active state */ int net_lwip_dns_init(void); int net_lwip_eth_start(void); +void net_lwip_eth_stop(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 acdf601d7eb..18dc36ae7ca 100644 --- a/net/lwip/dhcp.c +++ b/net/lwip/dhcp.c @@ -138,18 +138,25 @@ int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) dev = eth_get_dev(); if (!dev) { log_err("No network device\n"); - return CMD_RET_FAILURE; + ret = CMD_RET_FAILURE; + goto out; } ret = dhcp_loop(dev); if (ret) - return ret; + goto out; if (argc > 1) { struct cmd_tbl cmdtp = {}; - return do_tftpb(&cmdtp, 0, argc, argv); + ret = do_tftpb(&cmdtp, 0, argc, argv); + goto out; } - return CMD_RET_SUCCESS; + ret = CMD_RET_SUCCESS; + +out: + net_lwip_eth_stop(); + + return ret; } diff --git a/net/lwip/dns.c b/net/lwip/dns.c index 8b7b3b7f970..b620b0611d6 100644 --- a/net/lwip/dns.c +++ b/net/lwip/dns.c @@ -91,6 +91,7 @@ int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { char *name; char *var = NULL; + int ret; if (argc == 1 || argc > 3) return CMD_RET_USAGE; @@ -103,5 +104,9 @@ int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) if (net_lwip_eth_start() < 0) return CMD_RET_FAILURE; - return dns_loop(eth_get_dev(), name, var); + ret = dns_loop(eth_get_dev(), name, var); + + net_lwip_eth_stop(); + + return ret; } diff --git a/net/lwip/net-lwip.c b/net/lwip/net-lwip.c index 0c83c004cab..cfe5a6a640d 100644 --- a/net/lwip/net-lwip.c +++ b/net/lwip/net-lwip.c @@ -31,6 +31,7 @@ void (*push_packet)(void *, int len) = 0; int net_try_count; static int net_restarted; int net_restart_wrap; +static int net_lwip_eth_started; static uchar net_pkt_buf[(PKTBUFSRX) * PKTSIZE_ALIGN + PKTALIGN] __aligned(PKTALIGN); const u8 net_bcast_ethaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -180,11 +181,15 @@ int net_lwip_eth_start(void) { int ret; + if (net_lwip_eth_started++ > 0) + return 0; + net_init(); eth_halt(); eth_set_current(); ret = eth_init(); if (ret < 0) { + net_lwip_eth_started--; eth_halt(); return ret; } @@ -192,6 +197,17 @@ int net_lwip_eth_start(void) return 0; } +void net_lwip_eth_stop(void) +{ + if (!net_lwip_eth_started) + return; + + if (--net_lwip_eth_started) + return; + + eth_halt(); +} + static struct netif *new_netif(struct udevice *udev, bool with_ip) { unsigned char enetaddr[ARP_HLEN]; diff --git a/net/lwip/nfs.c b/net/lwip/nfs.c index 9e6b801e465..4cc36373fdd 100644 --- a/net/lwip/nfs.c +++ b/net/lwip/nfs.c @@ -187,6 +187,7 @@ static int nfs_loop(struct udevice *udev, ulong addr, char *fname, int do_nfs(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { int ret = CMD_RET_SUCCESS; + bool started = false; char *arg = NULL; char *words[2] = { }; char *fname = NULL; @@ -281,10 +282,13 @@ int do_nfs(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) ret = CMD_RET_FAILURE; goto out; } + started = true; if (nfs_loop(eth_get_dev(), laddr, fname, srvip) < 0) ret = CMD_RET_FAILURE; out: + if (started) + net_lwip_eth_stop(); if (arg != net_boot_file_name) free(arg); return ret; diff --git a/net/lwip/tftp.c b/net/lwip/tftp.c index 7f3b28b8507..571c38172f9 100644 --- a/net/lwip/tftp.c +++ b/net/lwip/tftp.c @@ -261,6 +261,7 @@ static int tftp_loop(struct udevice *udev, ulong addr, char *fname, int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { int ret = CMD_RET_SUCCESS; + bool started = false; char *arg = NULL; char *words[3] = { }; char *fname = NULL; @@ -365,12 +366,15 @@ int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) ret = CMD_RET_FAILURE; goto out; } + started = true; if (tftp_loop(eth_get_dev(), laddr, fname, srvip, port) < 0) ret = CMD_RET_FAILURE; else image_load_addr = laddr; out: + if (started) + net_lwip_eth_stop(); if (arg != net_boot_file_name) free(arg); return ret; diff --git a/net/lwip/wget.c b/net/lwip/wget.c index 3a0b0dca145..247ece18e2b 100644 --- a/net/lwip/wget.c +++ b/net/lwip/wget.c @@ -416,12 +416,15 @@ int wget_do_request(ulong dst_addr, char *uri) udev = eth_get_dev(); netif = net_lwip_new_netif(udev); - if (!netif) + if (!netif) { + net_lwip_eth_stop(); return -ENODEV; + } ret = wget_handle_request(&ctx, is_https, udev, netif); net_lwip_remove_netif(netif); + net_lwip_eth_stop(); return ret; } -- cgit v1.3.1