[RFC 1/2] net: net_up, net_down

Ian Ray ian.ray at ge.com
Mon May 3 13:55:37 CEST 2021


Calls made to eth_halt() by network operations (ping, nfs, tftp, etc.)
break netconsole if it is already running.

* Maintain the network up / down state based on a reference count,
  using new APIs net_up() and net_down().

Note that when network is brought up by netconsole client, then network
will remain up until reboot (because there is no way to stop netconsole
itself).

* Remove net_loop_last_protocol, eth_is_on_demand_init(), and
  eth_set_last_protocol().  This functionality is replaced by
  net_up() / net_down().

* Replace usage of eth_init(), eth_halt() with net_up() and
  net_down() in net.c, ping.c, tftp.c, and netconsole.c.

Signed-off-by: Ian Ray <ian.ray at ge.com>
---
 drivers/net/netconsole.c | 26 +++--------------
 include/net.h            | 23 ++-------------
 net/net.c                | 75 +++++++++++++++++++++++++++++++++---------------
 net/ping.c               |  1 -
 net/tftp.c               |  4 ---
 net/wol.c                |  1 -
 6 files changed, 59 insertions(+), 71 deletions(-)

diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index f1d0630..b6d2e22 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -27,11 +27,6 @@ static short nc_out_port; /* target output port */
 static short nc_in_port; /* source input port */
 static const char *output_packet; /* used by first send udp */
 static int output_packet_len;
-/*
- * Start with a default last protocol.
- * We are only interested in NETCONS or not.
- */
-enum proto_t net_loop_last_protocol = BOOTP;
 
 static void nc_wait_arp_handler(uchar *pkt, unsigned dest,
 				 struct in_addr sip, unsigned src,
@@ -177,7 +172,6 @@ static void nc_send_packet(const char *buf, int len)
 #else
 	struct eth_device *eth;
 #endif
-	int inited = 0;
 	uchar *pkt;
 	uchar *ether;
 	struct in_addr ip;
@@ -200,29 +194,17 @@ static void nc_send_packet(const char *buf, int len)
 		return;
 	}
 
-	if (!eth_is_active(eth)) {
-		if (eth_is_on_demand_init()) {
-			if (eth_init() < 0)
-				return;
-			eth_set_last_protocol(NETCONS);
-		} else {
-			eth_init_state_only();
-		}
-
-		inited = 1;
+	if (net_up(NETCONS) < 0) {
+		return;
 	}
+
 	pkt = (uchar *)net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE;
 	memcpy(pkt, buf, len);
 	ether = nc_ether;
 	ip = nc_ip;
 	net_send_udp_packet(ether, ip, nc_out_port, nc_in_port, len);
 
-	if (inited) {
-		if (eth_is_on_demand_init())
-			eth_halt();
-		else
-			eth_halt_state_only();
-	}
+	net_down();
 }
 
 static int nc_stdio_start(struct stdio_dev *dev)
diff --git a/include/net.h b/include/net.h
index 1bf9867..cc6be60 100644
--- a/include/net.h
+++ b/include/net.h
@@ -599,6 +599,9 @@ int net_loop(enum proto_t);
 /* Load failed.	 Start again. */
 int net_start_again(void);
 
+int net_up(enum proto_t protocol);
+int net_down(void);
+
 /* Get size of the ethernet header when we send */
 int net_eth_hdr_size(void);
 
@@ -706,26 +709,6 @@ int nc_input_packet(uchar *pkt, struct in_addr src_ip, unsigned dest_port,
 	unsigned src_port, unsigned len);
 #endif
 
-static __always_inline int eth_is_on_demand_init(void)
-{
-#if defined(CONFIG_NETCONSOLE) && !defined(CONFIG_SPL_BUILD)
-	extern enum proto_t net_loop_last_protocol;
-
-	return net_loop_last_protocol != NETCONS;
-#else
-	return 1;
-#endif
-}
-
-static inline void eth_set_last_protocol(int protocol)
-{
-#if defined(CONFIG_NETCONSOLE) && !defined(CONFIG_SPL_BUILD)
-	extern enum proto_t net_loop_last_protocol;
-
-	net_loop_last_protocol = protocol;
-#endif
-}
-
 /*
  * Check if autoload is enabled. If so, use either NFS or TFTP to download
  * the boot file.
diff --git a/net/net.c b/net/net.c
index 28d9eeb..45d4f19 100644
--- a/net/net.c
+++ b/net/net.c
@@ -404,6 +404,51 @@ void net_init(void)
  *	Main network processing loop.
  */
 
+static int up_ref;
+static bool up;
+static bool keep_up;
+
+/// Bring net up/active if needed.
+int net_up(enum proto_t protocol)
+{
+	int ret;
+	if (!up) {
+		eth_halt();
+		eth_set_current();
+		ret = eth_init();
+		if (ret < 0) {
+			debug_cond(DEBUG_INT_STATE, "net_up failed\n");
+			eth_halt();
+			return ret;
+		}
+		up = true;
+	} else if (up_ref == 0) {
+		eth_init_state_only();
+	}
+	up_ref++;
+	if (protocol == NETCONS) {
+		keep_up = true;
+	}
+	return 0;
+}
+
+/// Set net inactive if no clients remain.
+int net_down(void)
+{
+	if (up_ref > 0) {
+		up_ref--;
+		if (up_ref == 0) {
+			if (keep_up) {
+				eth_halt_state_only();
+			} else {
+				up = false;
+				eth_halt();
+			}
+		}
+	}
+	return 0;
+}
+
 int net_loop(enum proto_t protocol)
 {
 	int ret = -EINVAL;
@@ -420,16 +465,9 @@ int net_loop(enum proto_t protocol)
 
 	bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
 	net_init();
-	if (eth_is_on_demand_init() || protocol != NETCONS) {
-		eth_halt();
-		eth_set_current();
-		ret = eth_init();
-		if (ret < 0) {
-			eth_halt();
-			return ret;
-		}
-	} else {
-		eth_init_state_only();
+	ret = net_up(protocol);
+	if (ret < 0) {
+		return ret;
 	}
 restart:
 #ifdef CONFIG_USB_KEYBOARD
@@ -448,7 +486,7 @@ restart:
 	switch (net_check_prereq(protocol)) {
 	case 1:
 		/* network not configured */
-		eth_halt();
+		net_down();
 		net_set_state(prev_net_state);
 		return -ENODEV;
 
@@ -589,9 +627,7 @@ restart:
 			net_arp_wait_packet_ip.s_addr = 0;
 
 			net_cleanup_loop();
-			eth_halt();
-			/* Invalidate the last protocol */
-			eth_set_last_protocol(BOOTP);
+			net_down();
 
 			puts("\nAbort\n");
 			/* include a debug print as well incase the debug
@@ -647,12 +683,7 @@ restart:
 				env_set_hex("filesize", net_boot_file_size);
 				env_set_hex("fileaddr", image_load_addr);
 			}
-			if (protocol != NETCONS)
-				eth_halt();
-			else
-				eth_halt_state_only();
-
-			eth_set_last_protocol(protocol);
+			net_down();
 
 			ret = net_boot_file_size;
 			debug_cond(DEBUG_INT_STATE, "--- net_loop Success!\n");
@@ -660,8 +691,7 @@ restart:
 
 		case NETLOOP_FAIL:
 			net_cleanup_loop();
-			/* Invalidate the last protocol */
-			eth_set_last_protocol(BOOTP);
+			net_down();
 			debug_cond(DEBUG_INT_STATE, "--- net_loop Fail!\n");
 			ret = -ENONET;
 			goto done;
@@ -719,7 +749,6 @@ int net_start_again(void)
 	}
 
 	if ((!retry_forever) && (net_try_count > retrycnt)) {
-		eth_halt();
 		net_set_state(NETLOOP_FAIL);
 		/*
 		 * We don't provide a way for the protocol to return an error,
diff --git a/net/ping.c b/net/ping.c
index 0e33660..2c92806 100644
--- a/net/ping.c
+++ b/net/ping.c
@@ -64,7 +64,6 @@ static int ping_send(void)
 
 static void ping_timeout_handler(void)
 {
-	eth_halt();
 	net_set_state(NETLOOP_FAIL);	/* we did not get the reply */
 }
 
diff --git a/net/tftp.c b/net/tftp.c
index 84e970b..dcc387b 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -652,7 +652,6 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
 		net_set_timeout_handler(timeout_ms, tftp_timeout_handler);
 
 		if (store_block(tftp_cur_block - 1, pkt + 2, len)) {
-			eth_halt();
 			net_set_state(NETLOOP_FAIL);
 			break;
 		}
@@ -680,7 +679,6 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
 		case TFTP_ERR_FILE_NOT_FOUND:
 		case TFTP_ERR_ACCESS_DENIED:
 			puts("Not retrying...\n");
-			eth_halt();
 			net_set_state(NETLOOP_FAIL);
 			break;
 		case TFTP_ERR_UNDEFINED:
@@ -829,7 +827,6 @@ void tftp_start(enum proto_t protocol)
 #endif
 	{
 		if (tftp_init_load_addr()) {
-			eth_halt();
 			net_set_state(NETLOOP_FAIL);
 			puts("\nTFTP error: ");
 			puts("trying to overwrite reserved memory...\n");
@@ -885,7 +882,6 @@ void tftp_start_server(void)
 	tftp_filename[0] = 0;
 
 	if (tftp_init_load_addr()) {
-		eth_halt();
 		net_set_state(NETLOOP_FAIL);
 		puts("\nTFTP error: trying to overwrite reserved memory...\n");
 		return;
diff --git a/net/wol.c b/net/wol.c
index 0a62566..cd4e67e 100644
--- a/net/wol.c
+++ b/net/wol.c
@@ -85,7 +85,6 @@ void wol_set_timeout(ulong timeout)
 
 static void wol_timeout_handler(void)
 {
-	eth_halt();
 	net_set_state(NETLOOP_FAIL);
 }
 
-- 
2.10.1



More information about the U-Boot mailing list