From 652371c9192a34cc6859afe920260683b377f6f5 Mon Sep 17 00:00:00 2001
From: Gregory Nutt <gnutt@nuttx.org>
Date: Fri, 17 Jul 2015 07:20:16 -0600
Subject: [PATCH] Add CONFIG_NETDEV_LATEINIT that can be used to suppress calls
 to up_netinitialize() from early initialization

---
 ChangeLog                            | 10 ++++++---
 arch/arm/src/common/up_etherstub.c   | 18 ++++++++--------
 arch/arm/src/common/up_initialize.c  |  2 ++
 arch/arm/src/common/up_internal.h    |  8 +++++--
 arch/arm/src/kinetis/Make.defs       |  6 +++++-
 arch/arm/src/lpc17xx/Make.defs       |  6 +++++-
 arch/avr/src/common/up_initialize.c  |  4 +++-
 arch/hc/src/common/up_initialize.c   |  2 ++
 arch/mips/src/common/up_etherstub.c  | 20 +++++++++---------
 arch/mips/src/common/up_initialize.c |  2 ++
 arch/mips/src/pic32mx/Make.defs      |  6 +++++-
 arch/mips/src/pic32mz/Make.defs      |  4 ++++
 arch/sh/src/common/up_initialize.c   |  4 +++-
 arch/x86/src/common/up_initialize.c  |  2 ++
 arch/z16/src/common/up_initialize.c  |  3 +++
 arch/z80/src/common/up_initialize.c  |  5 ++++-
 drivers/net/Kconfig                  | 31 +++++++++++++++++++++++++++-
 17 files changed, 102 insertions(+), 31 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 8206c49ea9..c289b41375 100755
--- a/ChangeLog
+++ b/ChangeLog
@@ -10717,7 +10717,7 @@
 	* libc/netdb:  Add a default value for DNS server IP address.  Make
 	  sure that the IP address has been initialized before permitting DNS
 	  queries (2015-07-13).
-	* libc/netdb:  Add support for a DNS host name resulution cache.  This
+	* libc/netdb:  Add support for a DNS host name resolution cache.  This
 	  can save a lot of DNS name server lookups (but might also have the
 	  negative consequence of using stale IP address mappings (2015-07-13).
 	* graphics/, libnx/, and include/nuttx/nx:  Implement anti-aliasing in
@@ -10725,9 +10725,13 @@
 	* drivers/lcd/ and include/nuttx/lcd: Modify the SSD1306 LCD driver to
 	  support either the SPI or I2C interface.  From Alan Carvalho de Assis
 	  (2015-07-15).
-	* drivers/can.c:  Fix an issue in the CAN driver hwere the rx_sem
+	* arch/src/stm32f7 and arch/include/stm32f7:  Add architecture support
+	  for the STMicro STM32 F7 (2015-07-15).
+	* drivers/can.c:  Fix an issue in the CAN driver where the rx_sem
 	  count can grow beyond bounds (2015-07-15).
 	* configs/stm32f762g-disco/:  Add initialize support for the STMicor
 	  STM32 F7 Discovery board.  This is a work in progress and will be a
 	  while before it is fully functional (2015-07-16).
-
+	* arch/../up_etherstub.c, arch/../up_initialize, and other files: Add
+	  CONFIG_NETDEV_LATEINIT that can be used to suppress calls to
+	  up_netinitialize() from early in initialization (2015-07-17).
diff --git a/arch/arm/src/common/up_etherstub.c b/arch/arm/src/common/up_etherstub.c
index d5868d4349..66b7e41f53 100644
--- a/arch/arm/src/common/up_etherstub.c
+++ b/arch/arm/src/common/up_etherstub.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * arch/arm/src/common/up_etherstub.c
  *
- *   Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ *   Copyright (C) 2011, 2015 Gregory Nutt. All rights reserved.
  *   Author: Gregory Nutt <gnutt@nuttx.org>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -66,18 +66,18 @@
  *
  * Description:
  *   This is a stub version os up_netinitialize.  Normally, up_netinitialize
- *   is defined in board/up_network.c for board-specific ethernet
- *   implementations, or chip/xyx_ethernet.c for chip-specific ethernet
- *   implementations.  The stub version here is used in the cornercase where
- *   the network is enable yet there is no ethernet driver to be initialized.
+ *   is defined in board/xyz_network.c for board-specific Ethernet
+ *   implementations, or chip/xyx_ethernet.c for chip-specific Ethernet
+ *   implementations.  The stub version here is used in the corner case where
+ *   the network is enable yet there is no Ethernet driver to be initialized.
  *   In this case, up_initialize will still try to call up_netinitialize()
- *   when one does not exist.  This cornercase would occur if, for example,
+ *   when one does not exist.  This corner case would occur if, for example,
  *   only a USB network interface is being used or perhaps if a SLIP is
  *   being used).
  *
- *   In the long run, it might be better to have some kind of CONFIG_NO_ETHERNET
- *   to suppress the call to up_netinitialize() in up_initialize().  Then
- *   this stub would not be needed.
+ *   Use of this stub is deprecated.  The preferred mechanism is to use
+ *   CONFIG_NETDEV_LATEINIT=y to suppress the call to up_netinitialize() in
+ *   up_initialize().  Then this stub would not be needed.
  *
  ****************************************************************************/
 
diff --git a/arch/arm/src/common/up_initialize.c b/arch/arm/src/common/up_initialize.c
index 19b948e5c0..cad12d2307 100644
--- a/arch/arm/src/common/up_initialize.c
+++ b/arch/arm/src/common/up_initialize.c
@@ -248,9 +248,11 @@ void up_initialize(void)
   ramlog_sysloginit();
 #endif
 
+#ifndef CONFIG_NETDEV_LATEINIT
   /* Initialize the network */
 
   up_netinitialize();
+#endif
 
   /* Initialize USB -- device and/or host */
 
diff --git a/arch/arm/src/common/up_internal.h b/arch/arm/src/common/up_internal.h
index 9fbfe5bd8f..2f20524b5d 100644
--- a/arch/arm/src/common/up_internal.h
+++ b/arch/arm/src/common/up_internal.h
@@ -478,10 +478,14 @@ void up_wdtinit(void);
 
 /* Networking ***************************************************************/
 
-/* Defined in board/up_network.c for board-specific Ethernet implementations,
+/* Defined in board/xyz_network.c for board-specific Ethernet implementations,
  * or chip/xyx_ethernet.c for chip-specific Ethernet implementations, or
- * common/up_etherstub.c for a cornercase where the network is enabled yet
+ * common/up_etherstub.c for a corner case where the network is enabled yet
  * there is no Ethernet driver to be initialized.
+ *
+ * Use of common/up_etherstub.c is deprecated.  The preferred mechanism is to
+ * use CONFIG_NETDEV_LATEINIT=y to suppress the call to up_netinitialize() in
+ * up_initialize().  Then this stub would not be needed.
  */
 
 #ifdef CONFIG_NET
diff --git a/arch/arm/src/kinetis/Make.defs b/arch/arm/src/kinetis/Make.defs
index b52c116e81..d4bce7b4a7 100644
--- a/arch/arm/src/kinetis/Make.defs
+++ b/arch/arm/src/kinetis/Make.defs
@@ -1,7 +1,7 @@
 ############################################################################
 # arch/arm/src/kinetis/Make.defs
 #
-#   Copyright (C) 2011, 2013-2014 Gregory Nutt. All rights reserved.
+#   Copyright (C) 2011, 2013-2015 Gregory Nutt. All rights reserved.
 #   Author: Gregory Nutt <gnutt@nuttx.org>
 #
 # Redistribution and use in source and binary forms, with or without
@@ -67,6 +67,10 @@ CMN_UASRCS += up_signal_handler.S
 endif
 endif
 
+# Use of common/up_etherstub.c is deprecated.  The preferred mechanism is to
+# use CONFIG_NETDEV_LATEINIT=y to suppress the call to up_netinitialize() in
+# up_initialize().  Then this stub would not be needed.
+
 ifeq ($(CONFIG_NET),y)
 ifneq ($(CONFIG_KINETIS_ENET),y)
 CMN_CSRCS += up_etherstub.c
diff --git a/arch/arm/src/lpc17xx/Make.defs b/arch/arm/src/lpc17xx/Make.defs
index 0b16e7225c..3157b846ba 100644
--- a/arch/arm/src/lpc17xx/Make.defs
+++ b/arch/arm/src/lpc17xx/Make.defs
@@ -1,7 +1,7 @@
 ############################################################################
 # arch/arm/src/lpc17xx/Make.defs
 #
-#   Copyright (C) 2010-2011, 2013-2014 Gregory Nutt. All rights reserved.
+#   Copyright (C) 2010-2011, 2013-2015 Gregory Nutt. All rights reserved.
 #   Author: Gregory Nutt <gnutt@nuttx.org>
 #
 # Redistribution and use in source and binary forms, with or without
@@ -82,6 +82,10 @@ CMN_UASRCS += up_signal_handler.S
 endif
 endif
 
+# Use of common/up_etherstub.c is deprecated.  The preferred mechanism is to
+# use CONFIG_NETDEV_LATEINIT=y to suppress the call to up_netinitialize() in
+# up_initialize().  Then this stub would not be needed.
+
 ifeq ($(CONFIG_NET),y)
 ifneq ($(CONFIG_LPC17_ETHERNET),y)
 CMN_CSRCS += up_etherstub.c
diff --git a/arch/avr/src/common/up_initialize.c b/arch/avr/src/common/up_initialize.c
index be27240420..5fb247847c 100644
--- a/arch/avr/src/common/up_initialize.c
+++ b/arch/avr/src/common/up_initialize.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * arch/avr/src/common/up_initialize.c
  *
- *   Copyright (C) 2010, 2012-2013 Gregory Nutt. All rights reserved.
+ *   Copyright (C) 2010, 2012-2013, 2015 Gregory Nutt. All rights reserved.
  *   Author: Gregory Nutt <gnutt@nuttx.org>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -262,9 +262,11 @@ void up_initialize(void)
   ramlog_sysloginit();
 #endif
 
+#ifndef CONFIG_NETDEV_LATEINIT
   /* Initialize the network */
 
   up_netinitialize();
+#endif
 
   /* Initialize USB */
 
diff --git a/arch/hc/src/common/up_initialize.c b/arch/hc/src/common/up_initialize.c
index 67ab733ea3..f22be91528 100644
--- a/arch/hc/src/common/up_initialize.c
+++ b/arch/hc/src/common/up_initialize.c
@@ -186,9 +186,11 @@ void up_initialize(void)
   ramlog_sysloginit();
 #endif
 
+#ifndef CONFIG_NETDEV_LATEINIT
   /* Initialize the network */
 
   up_netinitialize();
+#endif
 
   /* Initialize USB */
 
diff --git a/arch/mips/src/common/up_etherstub.c b/arch/mips/src/common/up_etherstub.c
index 3ef989bb90..7a42d703e7 100644
--- a/arch/mips/src/common/up_etherstub.c
+++ b/arch/mips/src/common/up_etherstub.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * arch/mips/src/common/up_etherstub.c
  *
- *   Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
+ *   Copyright (C) 2011-2012, 2015 Gregory Nutt. All rights reserved.
  *   Author: Gregory Nutt <gnutt@nuttx.org>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -66,18 +66,18 @@
  *
  * Description:
  *   This is a stub version os up_netinitialize.  Normally, up_netinitialize
- *   is defined in board/up_network.c for board-specific ethernet
- *   implementations, or chip/xyx_ethernet.c for chip-specific ethernet
- *   implementations.  The stub version here is used in the cornercase where
- *   the network is enable yet there is no ethernet driver to be initialized.
+ *   is defined in board/xyz_network.c for board-specific Ethernet
+ *   implementations, or chip/xyx_ethernet.c for chip-specific Ethernet
+ *   implementations.  The stub version here is used in the corner case where
+ *   the network is enable yet there is no Ethernet driver to be initialized.
  *   In this case, up_initialize will still try to call up_netinitialize()
- *   when one does not exist.  This cornercase would occur if, for example,
+ *   when one does not exist.  This corner case would occur if, for example,
  *   only a USB network interface is being used or perhaps if a SLIP is
- *   being used).  In those cases, the initialization path is very different.
+ *   being used).
  *
- *   In the long run, it might be better to have some kind of CONFIG_NO_ETHERNET
- *   to suppress the call to up_netinitialize() in up_initialize().  Then
- *   this stub would not be needed.
+ *   Use of this stub is deprecated.  The preferred mechanism is to use
+ *   CONFIG_NETDEV_LATEINIT=y to suppress the call to up_netinitialize() in
+ *   up_initialize().  Then this stub would not be needed.
  *
  ****************************************************************************/
 
diff --git a/arch/mips/src/common/up_initialize.c b/arch/mips/src/common/up_initialize.c
index 0d40fbad2f..cfe893e795 100644
--- a/arch/mips/src/common/up_initialize.c
+++ b/arch/mips/src/common/up_initialize.c
@@ -188,9 +188,11 @@ void up_initialize(void)
   ramlog_sysloginit();
 #endif
 
+#ifndef CONFIG_NETDEV_LATEINIT
   /* Initialize the network */
 
   up_netinitialize();
+#endif
 
   /* Initialize USB -- device and/or host */
 
diff --git a/arch/mips/src/pic32mx/Make.defs b/arch/mips/src/pic32mx/Make.defs
index 793e9ce065..0202583901 100644
--- a/arch/mips/src/pic32mx/Make.defs
+++ b/arch/mips/src/pic32mx/Make.defs
@@ -1,7 +1,7 @@
 ############################################################################
 # arch/mips/src/pic32mx/Make.defs
 #
-#   Copyright (C) 2011-2012, 2014 Gregory Nutt. All rights reserved.
+#   Copyright (C) 2011-2012, 2014-2015 Gregory Nutt. All rights reserved.
 #   Author: Gregory Nutt <gnutt@nuttx.org>
 #
 # Redistribution and use in source and binary forms, with or without
@@ -51,6 +51,10 @@ CMN_CSRCS += up_usestack.c up_vfork.c
 
 # Configuration dependent common files
 
+# Use of common/up_etherstub.c is deprecated.  The preferred mechanism is to
+# use CONFIG_NETDEV_LATEINIT=y to suppress the call to up_netinitialize() in
+# up_initialize().  Then this stub would not be needed.
+
 ifneq ($(CONFIG_PIC32MX_ETHERNET),y)
 ifeq ($(CONFIG_NET),y)
 CMN_CSRCS += up_etherstub.c
diff --git a/arch/mips/src/pic32mz/Make.defs b/arch/mips/src/pic32mz/Make.defs
index acb7f0323e..b9342179eb 100644
--- a/arch/mips/src/pic32mz/Make.defs
+++ b/arch/mips/src/pic32mz/Make.defs
@@ -51,6 +51,10 @@ CMN_CSRCS += up_usestack.c up_vfork.c
 
 # Configuration dependent common files
 
+# Use of common/up_etherstub.c is deprecated.  The preferred mechanism is to
+# use CONFIG_NETDEV_LATEINIT=y to suppress the call to up_netinitialize() in
+# up_initialize().  Then this stub would not be needed.
+
 ifneq ($(CONFIG_PIC32MZ_ETHERNET),y)
 ifeq ($(CONFIG_NET),y)
 CMN_CSRCS += up_etherstub.c
diff --git a/arch/sh/src/common/up_initialize.c b/arch/sh/src/common/up_initialize.c
index fc99a1f28c..e7f0fbd595 100644
--- a/arch/sh/src/common/up_initialize.c
+++ b/arch/sh/src/common/up_initialize.c
@@ -176,9 +176,11 @@ void up_initialize(void)
   ramlog_sysloginit();
 #endif
 
-  /* Initialize the netwok */
+#ifndef CONFIG_NETDEV_LATEINIT
+  /* Initialize the network */
 
   up_netinitialize();
+#endif
 
   /* Initialize USB */
 
diff --git a/arch/x86/src/common/up_initialize.c b/arch/x86/src/common/up_initialize.c
index 118380887d..9356dd8cd1 100644
--- a/arch/x86/src/common/up_initialize.c
+++ b/arch/x86/src/common/up_initialize.c
@@ -188,9 +188,11 @@ void up_initialize(void)
   ramlog_sysloginit();
 #endif
 
+#ifndef CONFIG_NETDEV_LATEINIT
   /* Initialize the network */
 
   up_netinitialize();
+#endif
 
   /* Initialize USB -- device and/or host */
 
diff --git a/arch/z16/src/common/up_initialize.c b/arch/z16/src/common/up_initialize.c
index 95a5acccbf..e906731d95 100644
--- a/arch/z16/src/common/up_initialize.c
+++ b/arch/z16/src/common/up_initialize.c
@@ -192,8 +192,11 @@ void up_initialize(void)
   ramlog_sysloginit();
 #endif
 
+#ifndef CONFIG_NETDEV_LATEINIT
   /* Initialize the network */
 
   up_netinitialize();
+#endif
+
   board_led_on(LED_IRQSENABLED);
 }
diff --git a/arch/z80/src/common/up_initialize.c b/arch/z80/src/common/up_initialize.c
index ef0840a6f8..a71a256626 100644
--- a/arch/z80/src/common/up_initialize.c
+++ b/arch/z80/src/common/up_initialize.c
@@ -175,8 +175,11 @@ void up_initialize(void)
   ramlog_consoleinit();
 #endif
 
-  /* Initialize the netwok */
+#ifndef CONFIG_NETDEV_LATEINIT
+  /* Initialize the network */
 
   up_netinitialize();
+#endif
+
   board_led_on(LED_IRQSENABLED);
 }
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 5ad4334cfa..91fd96db15 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -6,12 +6,41 @@
 comment "General Ethernet MAC Driver Options"
 
 config NETDEV_MULTINIC
-	bool "Multiple NIC support"
+	bool "Multiple network interface support"
 	default n
 	---help---
 		Select this option if you board and/or MCU are capable of supporting
 		multiple Ethernet MAC drivers.
 
+config NETDEV_LATEINIT
+	bool "Late driver initialization"
+	default n
+	---help---
+		Normally, networking initialization occur in the later phase of the
+		boot process in the function up_initialize() when it calls the
+		driver initialization function, up_netintialize().  This
+		initialization occurs after a sufficient about of the OS has been
+		initialized so that driver registration can be performed, but
+		before the completion of OS initialization and before the first
+		application is started.
+
+		In a few situations, however, you may want to suppress this early
+		network driver initialization.  As examples:
+
+			- If you are using SLIP or PPPD, then there will be no network
+			  driver to be initialized,
+			- Certain multi-network configurations where a simple call to
+			  up_netinitialize() may be insufficient, and
+			- Situations where there are other board-level hardware
+			  dependencies so that the hardware is not in an appropriate
+              state for up_netinitialize() to be called.
+
+		Examples of this latter situation includes such things as network
+		drivers that required some setup via an I2C I/O expander, or network
+		drivers that depend on USB, SPI, I2C, PCI, serial, or other
+		interfaces that may not be ready when up_netiniailize() is normally
+		called.
+
 config NET_DUMPPACKET
 	bool "Enable packet dumping"
 	depends on DEBUG