[U-Boot] [PATCH] net: Improve the speed of netconsole
Joe Hershberger
joe.hershberger at ni.com
Tue Jul 24 22:11:15 CEST 2012
Previously u-boot would initialize the network interface for every
network operation and then shut it down again. This makes sense for
most operations where the network in not known to be needed soon after
the operation is complete. In the case of netconsole, it will use the
network for every interaction with the shell or every printf. This
means that the network is being reinitialized very often. On many
devices, this intialization is very slow.
This patch checks for consecutive netconsole actions and leaves the
ethernet hardware initialized between them. It will still behave the
same old way for all other network operations and any time another
network operation happens between netconsole operations.
Signed-off-by: Joe Hershberger <joe.hershberger at ni.com>
Cc: Stefano Babic <sbabic at denx.de>
---
doc/README.NetConsole | 3 +++
drivers/net/netconsole.c | 26 ++++++++++++++++++++++----
include/net.h | 6 ++++++
net/eth.c | 14 ++++++++++++++
net/net.c | 44 +++++++++++++++++++++++++++++++++++++++-----
5 files changed, 84 insertions(+), 9 deletions(-)
diff --git a/doc/README.NetConsole b/doc/README.NetConsole
index c8bcb90..7a20bf5 100644
--- a/doc/README.NetConsole
+++ b/doc/README.NetConsole
@@ -6,6 +6,9 @@ serial and network input/output devices by adjusting the 'stdin' and
set either of these variables to "nc". Input and output can be
switched independently.
+CONFIG_NETCONSOLE_PERSIST_ETH - Don't reinitialize the Ethernet driver
+ between consecutive calls to netconsole.
+
We use an environment variable 'ncip' to set the IP address and the
port of the destination. The format is <ip_addr>:<port>. If <port> is
omitted, the value of 6666 is used. If the env var doesn't exist, the
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 14243b8..0218302 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -131,8 +131,17 @@ static void nc_send_packet(const char *buf, int len)
}
if (eth->state != ETH_STATE_ACTIVE) {
- if (eth_init(gd->bd) < 0)
- return;
+#ifdef CONFIG_NETCONSOLE_PERSIST_ETH
+ if (net_loop_last_protocol != NETCONS) {
+#endif
+ if (eth_init(gd->bd) < 0)
+ return;
+#ifdef CONFIG_NETCONSOLE_PERSIST_ETH
+ net_loop_last_protocol = NETCONS;
+ } else {
+ eth_init_state_only(gd->bd);
+ }
+#endif
inited = 1;
}
pkt = (uchar *)NetTxPacket + NetEthHdrSize() + IP_UDP_HDR_SIZE;
@@ -141,8 +150,17 @@ static void nc_send_packet(const char *buf, int len)
ip = nc_ip;
NetSendUDPPacket(ether, ip, nc_port, nc_port, len);
- if (inited)
- eth_halt();
+ if (inited) {
+#ifdef CONFIG_NETCONSOLE_PERSIST_ETH
+ if (net_loop_last_protocol != NETCONS) {
+#endif
+ eth_halt();
+#ifdef CONFIG_NETCONSOLE_PERSIST_ETH
+ } else {
+ eth_halt_state_only();
+ }
+#endif
+ }
}
static int nc_start(void)
diff --git a/include/net.h b/include/net.h
index 6d2d6cd..0b75e10 100644
--- a/include/net.h
+++ b/include/net.h
@@ -151,6 +151,12 @@ extern int eth_rx(void); /* Check for received packets */
extern void eth_halt(void); /* stop SCC */
extern char *eth_get_name(void); /* get name of current device */
+#ifdef CONFIG_NETCONSOLE_PERSIST_ETH
+extern int eth_init_state_only(bd_t *bis); /* Set active state */
+extern void eth_halt_state_only(void); /* Set passive state */
+extern enum proto_t net_loop_last_protocol;
+#endif
+
/*
* Set the hardware address for an ethernet interface based on 'eth%daddr'
* environment variable (or just 'ethaddr' if eth_number is 0).
diff --git a/net/eth.c b/net/eth.c
index d526264..54841b9 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -436,6 +436,20 @@ void eth_halt(void)
eth_current->state = ETH_STATE_PASSIVE;
}
+#ifdef CONFIG_NETCONSOLE_PERSIST_ETH
+int eth_init_state_only(bd_t *bis)
+{
+ eth_current->state = ETH_STATE_ACTIVE;
+
+ return 0;
+}
+
+void eth_halt_state_only(void)
+{
+ eth_current->state = ETH_STATE_PASSIVE;
+}
+#endif
+
int eth_send(void *packet, int length)
{
if (!eth_current)
diff --git a/net/net.c b/net/net.c
index 9de7d92..184c182 100644
--- a/net/net.c
+++ b/net/net.c
@@ -180,6 +180,14 @@ IPaddr_t NetNtpServerIP;
int NetTimeOffset;
#endif
+#ifdef CONFIG_NETCONSOLE_PERSIST_ETH
+/*
+ * Start with a default last protocol.
+ * We are only interested in NETCONS or not.
+ */
+enum proto_t net_loop_last_protocol = BOOTP;
+#endif
+
uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
/* Receive packet */
@@ -314,12 +322,20 @@ int NetLoop(enum proto_t protocol)
bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
net_init();
- eth_halt();
- eth_set_current();
- if (eth_init(bd) < 0) {
+#ifdef CONFIG_NETCONSOLE_PERSIST_ETH
+ if (protocol != NETCONS || net_loop_last_protocol != NETCONS) {
+#endif
eth_halt();
- return -1;
+ eth_set_current();
+ if (eth_init(bd) < 0) {
+ eth_halt();
+ return -1;
+ }
+#ifdef CONFIG_NETCONSOLE_PERSIST_ETH
+ } else {
+ eth_init_state_only(bd);
}
+#endif
restart:
memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
@@ -461,6 +477,10 @@ restart:
net_cleanup_loop();
eth_halt();
+#ifdef CONFIG_NETCONSOLE_PERSIST_ETH
+ /* Invalidate the last protocol */
+ net_loop_last_protocol = BOOTP;
+#endif
puts("\nAbort\n");
/* include a debug print as well incase the debug
messages are directed to stderr */
@@ -518,13 +538,27 @@ restart:
sprintf(buf, "%lX", (unsigned long)load_addr);
setenv("fileaddr", buf);
}
- eth_halt();
+#ifdef CONFIG_NETCONSOLE_PERSIST_ETH
+ if (protocol != NETCONS) {
+#endif
+ eth_halt();
+#ifdef CONFIG_NETCONSOLE_PERSIST_ETH
+ } else {
+ eth_halt_state_only();
+ }
+ /* Remember what the last protocol was */
+ net_loop_last_protocol = protocol;
+#endif
ret = NetBootFileXferSize;
debug_cond(DEBUG_INT_STATE, "--- NetLoop Success!\n");
goto done;
case NETLOOP_FAIL:
net_cleanup_loop();
+#ifdef CONFIG_NETCONSOLE_PERSIST_ETH
+ /* Invalidate the last protocol */
+ net_loop_last_protocol = BOOTP;
+#endif
debug_cond(DEBUG_INT_STATE, "--- NetLoop Fail!\n");
goto done;
--
1.6.0.2
More information about the U-Boot
mailing list