[U-Boot] [PATCH 1/3] net/eth: set status to active before calling init

Sebastian Andrzej Siewior bigeasy at linutronix.de
Fri Mar 23 21:11:17 CET 2012

If we set the status after successful init call then we get in trouble
if stdout (or setderr) is set to netconsole. If we are going to use one
of those (lets say printf) during ->init() the following happens:
- network is of (state passive)
- we switch on netconsole
- nc_getc() gets called
- in NetLoop() we switch on ethernet via eth_init()
- we end up in tsec_init() (inc case we use the tsec driver). Here we
  call a printf()
- That printf() ends up in nc_puts() because netconsole is our default
- The state is not active yet, so we call eth_init() once again.
- and we are again in tsec_init(). Another printf() is waiting. However,
  due to the recursion check nc_puts() returns early before doing
- we return from each function. Sine nc_puts() thinks that it was in
  charge of enabling the ethernet, it disables it before leaving.
- We return now to the top-most eth_init() function. Since everything
  went fine, it sets the status to active. In reality the network is
  switched off.
- nc_getc() gets called over and over to receive new packets. Sadly the
  nic is disabled and new network packets won't be noticed.

This patch sets the network status early so nc_puts() does not get
confused and disables the network interface in case of a printf() on its

Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>
 net/eth.c |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/net/eth.c b/net/eth.c
index 4280d6d..bca405a 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -380,14 +380,17 @@ int eth_init(bd_t *bis)
 	old_current = eth_current;
 	do {
+		int old_state;
 		debug("Trying %s\n", eth_current->name);
-		if (eth_current->init(eth_current,bis) >= 0) {
-			eth_current->state = ETH_STATE_ACTIVE;
+		old_state = eth_current->state;
+		eth_current->state = ETH_STATE_ACTIVE;
+		if (eth_current->init(eth_current,bis) >= 0)
 			return 0;
-		}
+		eth_current->state = old_state;
 	} while (old_current != eth_current);

More information about the U-Boot mailing list