All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [RFC PATCH 0/7] Add Driver Model support to network stack
@ 2015-01-27 23:27 Joe Hershberger
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 1/7] net: Provide a function to get the current MAC address Joe Hershberger
                   ` (8 more replies)
  0 siblings, 9 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-01-27 23:27 UTC (permalink / raw)
  To: u-boot

For now this simply addresses the MAC part of the network hardware.
The next part to implement is the PHY children.  I wanted to get early
feedback on what I have so far to make sure I'm going in the direction
that Simon envisioned.


Joe Hershberger (7):
  net: Provide a function to get the current MAC address
  net: Rename helper function to be more clear
  net: Remove unneeded "extern" in net.h
  net: Refactor in preparation for driver model
  net: Add basic driver model support to Ethernet stack
  net: Add network support to sandbox
  net: Add ARP and PING response to sandbox driver

 arch/mips/cpu/mips32/au1x00/au1x00_eth.c |   2 +-
 arch/powerpc/cpu/mpc8260/ether_fcc.c     |   2 +-
 arch/powerpc/cpu/mpc85xx/ether_fcc.c     |   2 +-
 arch/powerpc/cpu/mpc8xx/scc.c            |   2 +-
 arch/sandbox/dts/sandbox.dts             |   4 +
 common/board_r.c                         |   4 +-
 common/cmd_bdinfo.c                      |   2 +
 drivers/net/Makefile                     |   2 +
 drivers/net/sandbox.c                    | 166 +++++++++++++
 include/configs/sandbox.h                |  14 +-
 include/dm/uclass-id.h                   |   1 +
 include/net.h                            | 158 +++++++-----
 net/eth.c                                | 408 +++++++++++++++++++++++++++----
 net/net.c                                |   2 +-
 14 files changed, 649 insertions(+), 120 deletions(-)
 create mode 100644 drivers/net/sandbox.c

-- 
1.7.11.5

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 1/7] net: Provide a function to get the current MAC address
  2015-01-27 23:27 [U-Boot] [RFC PATCH 0/7] Add Driver Model support to network stack Joe Hershberger
@ 2015-01-27 23:27 ` Joe Hershberger
  2015-01-28  2:33   ` Simon Glass
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 2/7] net: Rename helper function to be more clear Joe Hershberger
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-01-27 23:27 UTC (permalink / raw)
  To: u-boot

The current implementation exposes the eth_device struct to code that
needs to access the MAC address.  Add a wrapper function for this to
abstract away the pointer for this operation.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
---

 arch/mips/cpu/mips32/au1x00/au1x00_eth.c | 2 +-
 arch/powerpc/cpu/mpc8260/ether_fcc.c     | 2 +-
 arch/powerpc/cpu/mpc85xx/ether_fcc.c     | 2 +-
 arch/powerpc/cpu/mpc8xx/scc.c            | 2 +-
 include/net.h                            | 8 ++++++++
 net/net.c                                | 2 +-
 6 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_eth.c b/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
index 4770f56..535d713 100644
--- a/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
+++ b/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
@@ -238,7 +238,7 @@ static int au1x00_init(struct eth_device* dev, bd_t * bd){
 	}
 
 	/* Put mac addr in little endian */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
 	*mac_addr_high	=	(ea[5] <<  8) | (ea[4]	    ) ;
 	*mac_addr_low	=	(ea[3] << 24) | (ea[2] << 16) |
 		(ea[1] <<  8) | (ea[0]	    ) ;
diff --git a/arch/powerpc/cpu/mpc8260/ether_fcc.c b/arch/powerpc/cpu/mpc8260/ether_fcc.c
index f9f15b5..f777ba1 100644
--- a/arch/powerpc/cpu/mpc8260/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc8260/ether_fcc.c
@@ -299,7 +299,7 @@ static int fec_init(struct eth_device* dev, bd_t *bis)
      * it unique by setting a few bits in the upper byte of the
      * non-static part of the address.
      */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
     pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
     pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
     pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/arch/powerpc/cpu/mpc85xx/ether_fcc.c b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
index 166dc9e..58d4bfb 100644
--- a/arch/powerpc/cpu/mpc85xx/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
@@ -338,7 +338,7 @@ static int fec_init(struct eth_device* dev, bd_t *bis)
      * it unique by setting a few bits in the upper byte of the
      * non-static part of the address.
      */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
     pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
     pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
     pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/arch/powerpc/cpu/mpc8xx/scc.c b/arch/powerpc/cpu/mpc8xx/scc.c
index 251966b..66e4014 100644
--- a/arch/powerpc/cpu/mpc8xx/scc.c
+++ b/arch/powerpc/cpu/mpc8xx/scc.c
@@ -339,7 +339,7 @@ static int scc_init (struct eth_device *dev, bd_t * bis)
 	pram_ptr->sen_gaddr3 = 0x0;	/* Group Address Filter 3 (unused) */
 	pram_ptr->sen_gaddr4 = 0x0;	/* Group Address Filter 4 (unused) */
 
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
 	pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4];
 	pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2];
 	pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/include/net.h b/include/net.h
index 73ea88b..a9579ee 100644
--- a/include/net.h
+++ b/include/net.h
@@ -111,6 +111,14 @@ struct eth_device *eth_get_dev(void)
 {
 	return eth_current;
 }
+
+static inline unsigned char *eth_get_ethaddr(void)
+{
+	if (eth_current)
+		return eth_current->enetaddr;
+	return NULL;
+}
+
 extern struct eth_device *eth_get_dev_by_name(const char *devname);
 extern struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
 extern int eth_get_dev_index(void);		/* get the device index */
diff --git a/net/net.c b/net/net.c
index 2bea07b..ddd630c 100644
--- a/net/net.c
+++ b/net/net.c
@@ -275,7 +275,7 @@ static void NetInitLoop(void)
 		env_changed_id = env_id;
 	}
 	if (eth_get_dev())
-		memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
+		memcpy(NetOurEther, eth_get_ethaddr(), 6);
 
 	return;
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 2/7] net: Rename helper function to be more clear
  2015-01-27 23:27 [U-Boot] [RFC PATCH 0/7] Add Driver Model support to network stack Joe Hershberger
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 1/7] net: Provide a function to get the current MAC address Joe Hershberger
@ 2015-01-27 23:27 ` Joe Hershberger
  2015-01-28  2:34   ` Simon Glass
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 3/7] net: Remove unneeded "extern" in net.h Joe Hershberger
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-01-27 23:27 UTC (permalink / raw)
  To: u-boot

Make it clear that the helper is checking the addr, not setting it.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
---

 net/eth.c | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/net/eth.c b/net/eth.c
index eac4f7b..65e8c77 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -153,11 +153,6 @@ static void eth_current_changed(void)
 		setenv("ethact", NULL);
 }
 
-static int eth_address_set(unsigned char *addr)
-{
-	return memcmp(addr, "\0\0\0\0\0\0", 6);
-}
-
 int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		   int eth_number)
 {
@@ -166,9 +161,9 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 
 	eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
 
-	if (eth_address_set(env_enetaddr)) {
-		if (eth_address_set(dev->enetaddr) &&
-				memcmp(dev->enetaddr, env_enetaddr, 6)) {
+	if (!is_zero_ether_addr(env_enetaddr)) {
+		if (!is_zero_ether_addr(dev->enetaddr) &&
+		    memcmp(dev->enetaddr, env_enetaddr, 6)) {
 			printf("\nWarning: %s MAC addresses don't match:\n",
 				dev->name);
 			printf("Address in SROM is         %pM\n",
@@ -183,7 +178,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 					     dev->enetaddr);
 		printf("\nWarning: %s using MAC address from net device\n",
 			dev->name);
-	} else if (!(eth_address_set(dev->enetaddr))) {
+	} else if (is_zero_ether_addr(dev->enetaddr)) {
 		printf("\nError: %s address not set.\n",
 		       dev->name);
 		return -EINVAL;
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 3/7] net: Remove unneeded "extern" in net.h
  2015-01-27 23:27 [U-Boot] [RFC PATCH 0/7] Add Driver Model support to network stack Joe Hershberger
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 1/7] net: Provide a function to get the current MAC address Joe Hershberger
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 2/7] net: Rename helper function to be more clear Joe Hershberger
@ 2015-01-27 23:27 ` Joe Hershberger
  2015-01-28  2:34   ` Simon Glass
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 4/7] net: Refactor in preparation for driver model Joe Hershberger
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-01-27 23:27 UTC (permalink / raw)
  To: u-boot

Many of the functions in net.h were preceded extern needlessly. Removing
them to limit the number of checkpatch.pl complaints.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
---

 include/net.h | 96 +++++++++++++++++++++++++++++------------------------------
 1 file changed, 48 insertions(+), 48 deletions(-)

diff --git a/include/net.h b/include/net.h
index a9579ee..ff8b7af 100644
--- a/include/net.h
+++ b/include/net.h
@@ -97,11 +97,11 @@ struct eth_device {
 	void *priv;
 };
 
-extern int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
-extern int eth_register(struct eth_device* dev);/* Register network device */
-extern int eth_unregister(struct eth_device *dev);/* Remove network device */
-extern void eth_try_another(int first_restart);	/* Change the device */
-extern void eth_set_current(void);		/* set nterface to ethcur var */
+int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
+int eth_register(struct eth_device *dev);/* Register network device */
+int eth_unregister(struct eth_device *dev);/* Remove network device */
+void eth_try_another(int first_restart);	/* Change the device */
+void eth_set_current(void);		/* set nterface to ethcur var */
 
 /* get the current device MAC */
 extern struct eth_device *eth_current;
@@ -119,12 +119,12 @@ static inline unsigned char *eth_get_ethaddr(void)
 	return NULL;
 }
 
-extern struct eth_device *eth_get_dev_by_name(const char *devname);
-extern struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
-extern int eth_get_dev_index(void);		/* get the device index */
-extern void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
-extern int eth_getenv_enetaddr(char *name, uchar *enetaddr);
-extern int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
+struct eth_device *eth_get_dev_by_name(const char *devname);
+struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
+int eth_get_dev_index(void);		/* get the device index */
+void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
+int eth_getenv_enetaddr(char *name, uchar *enetaddr);
+int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 
 /*
  * Get the hardware address for an ethernet interface .
@@ -135,20 +135,20 @@ extern int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
  * Returns:
  *	Return true if the address is valid.
  */
-extern int eth_getenv_enetaddr_by_index(const char *base_name, int index,
-					uchar *enetaddr);
+int eth_getenv_enetaddr_by_index(const char *base_name, int index,
+				 uchar *enetaddr);
 
-extern int usb_eth_initialize(bd_t *bi);
-extern int eth_init(bd_t *bis);			/* Initialize the device */
-extern int eth_send(void *packet, int length);	   /* Send a packet */
+int usb_eth_initialize(bd_t *bi);
+int eth_init(bd_t *bis);			/* Initialize the device */
+int eth_send(void *packet, int length);	   /* Send a packet */
 
 #ifdef CONFIG_API
-extern int eth_receive(void *packet, int length); /* Receive a packet*/
-extern void (*push_packet)(void *packet, int length);
+int eth_receive(void *packet, int length); /* Receive a packet*/
+void (*push_packet)(void *packet, int length);
 #endif
-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 */
+int eth_rx(void);			/* Check for received packets */
+void eth_halt(void);			/* stop SCC */
+char *eth_get_name(void);		/* get name of current device */
 
 /* Set active state */
 static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
@@ -469,25 +469,25 @@ extern IPaddr_t Mcast_addr;
 #endif
 
 /* Initialize the network adapter */
-extern void net_init(void);
-extern int NetLoop(enum proto_t);
+void net_init(void);
+int NetLoop(enum proto_t);
 
 /* Shutdown adapters and cleanup */
-extern void	NetStop(void);
+void	NetStop(void);
 
 /* Load failed.	 Start again. */
-extern void	NetStartAgain(void);
+void	NetStartAgain(void);
 
 /* Get size of the ethernet header when we send */
-extern int	NetEthHdrSize(void);
+int	NetEthHdrSize(void);
 
 /* Set ethernet header; returns the size of the header */
-extern int NetSetEther(uchar *, uchar *, uint);
-extern int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot);
+int NetSetEther(uchar *, uchar *, uint);
+int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot);
 
 /* Set IP header */
-extern void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source);
-extern void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport,
+void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source);
+void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport,
 				int sport, int len);
 
 /**
@@ -521,16 +521,16 @@ unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new_sum);
 int ip_checksum_ok(const void *addr, unsigned nbytes);
 
 /* Checksum */
-extern int	NetCksumOk(uchar *, int);	/* Return true if cksum OK */
-extern uint	NetCksum(uchar *, int);		/* Calculate the checksum */
+int	NetCksumOk(uchar *, int);	/* Return true if cksum OK */
+uint	NetCksum(uchar *, int);		/* Calculate the checksum */
 
 /* Callbacks */
-extern rxhand_f *net_get_udp_handler(void);	/* Get UDP RX packet handler */
-extern void net_set_udp_handler(rxhand_f *);	/* Set UDP RX packet handler */
-extern rxhand_f *net_get_arp_handler(void);	/* Get ARP RX packet handler */
-extern void net_set_arp_handler(rxhand_f *);	/* Set ARP RX packet handler */
-extern void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
-extern void	NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
+rxhand_f *net_get_udp_handler(void);	/* Get UDP RX packet handler */
+void net_set_udp_handler(rxhand_f *);	/* Set UDP RX packet handler */
+rxhand_f *net_get_arp_handler(void);	/* Get ARP RX packet handler */
+void net_set_arp_handler(rxhand_f *);	/* Set ARP RX packet handler */
+void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
+void	NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
 
 /* Network loop state */
 enum net_loop_state {
@@ -563,11 +563,11 @@ static inline void NetSendPacket(uchar *pkt, int len)
  * @param sport Source UDP port
  * @param payload_len Length of data after the UDP header
  */
-extern int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport,
+int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport,
 			int sport, int payload_len);
 
 /* Processes a received packet */
-extern void NetReceive(uchar *, int);
+void NetReceive(uchar *, int);
 
 #ifdef CONFIG_NETCONSOLE
 void NcStart(void);
@@ -715,28 +715,28 @@ static inline void eth_random_addr(uchar *addr)
 }
 
 /* Convert an IP address to a string */
-extern void ip_to_string(IPaddr_t x, char *s);
+void ip_to_string(IPaddr_t x, char *s);
 
 /* Convert a string to ip address */
-extern IPaddr_t string_to_ip(const char *s);
+IPaddr_t string_to_ip(const char *s);
 
 /* Convert a VLAN id to a string */
-extern void VLAN_to_string(ushort x, char *s);
+void VLAN_to_string(ushort x, char *s);
 
 /* Convert a string to a vlan id */
-extern ushort string_to_VLAN(const char *s);
+ushort string_to_VLAN(const char *s);
 
 /* read a VLAN id from an environment variable */
-extern ushort getenv_VLAN(char *);
+ushort getenv_VLAN(char *);
 
 /* copy a filename (allow for "..." notation, limit length) */
-extern void copy_filename(char *dst, const char *src, int size);
+void copy_filename(char *dst, const char *src, int size);
 
 /* get a random source port */
-extern unsigned int random_port(void);
+unsigned int random_port(void);
 
 /* Update U-Boot over TFTP */
-extern int update_tftp(ulong addr);
+int update_tftp(ulong addr);
 
 /**********************************************************************/
 
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 4/7] net: Refactor in preparation for driver model
  2015-01-27 23:27 [U-Boot] [RFC PATCH 0/7] Add Driver Model support to network stack Joe Hershberger
                   ` (2 preceding siblings ...)
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 3/7] net: Remove unneeded "extern" in net.h Joe Hershberger
@ 2015-01-27 23:27 ` Joe Hershberger
  2015-01-28  2:34   ` Simon Glass
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 5/7] net: Add basic driver model support to Ethernet stack Joe Hershberger
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-01-27 23:27 UTC (permalink / raw)
  To: u-boot

Move some things around and organize things so that the driver model
implementation will fit in more easily.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
---

 include/net.h | 63 +++++++++++++++++++++++++------------------------
 net/eth.c     | 75 +++++++++++++++++++++++++++++++----------------------------
 2 files changed, 73 insertions(+), 65 deletions(-)

diff --git a/include/net.h b/include/net.h
index ff8b7af..7eef9cc 100644
--- a/include/net.h
+++ b/include/net.h
@@ -100,10 +100,7 @@ struct eth_device {
 int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
 int eth_register(struct eth_device *dev);/* Register network device */
 int eth_unregister(struct eth_device *dev);/* Remove network device */
-void eth_try_another(int first_restart);	/* Change the device */
-void eth_set_current(void);		/* set nterface to ethcur var */
 
-/* get the current device MAC */
 extern struct eth_device *eth_current;
 
 static inline __attribute__((always_inline))
@@ -112,6 +109,7 @@ struct eth_device *eth_get_dev(void)
 	return eth_current;
 }
 
+/* get the current device MAC */
 static inline unsigned char *eth_get_ethaddr(void)
 {
 	if (eth_current)
@@ -119,6 +117,37 @@ static inline unsigned char *eth_get_ethaddr(void)
 	return NULL;
 }
 
+/* Set active state */
+static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
+{
+	eth_get_dev()->state = ETH_STATE_ACTIVE;
+
+	return 0;
+}
+/* Set passive state */
+static inline __attribute__((always_inline)) void eth_halt_state_only(void)
+{
+	eth_get_dev()->state = ETH_STATE_PASSIVE;
+}
+
+/*
+ * Set the hardware address for an ethernet interface based on 'eth%daddr'
+ * environment variable (or just 'ethaddr' if eth_number is 0).
+ * Args:
+ *	base_name - base name for device (normally "eth")
+ *	eth_number - value of %d (0 for first device of this type)
+ * Returns:
+ *	0 is success, non-zero is error status from driver.
+ */
+int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
+		     int eth_number);
+
+int usb_eth_initialize(bd_t *bi);
+#endif
+
+void eth_try_another(int first_restart);	/* Change the device */
+void eth_set_current(void);		/* set nterface to ethcur var */
+
 struct eth_device *eth_get_dev_by_name(const char *devname);
 struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
 int eth_get_dev_index(void);		/* get the device index */
@@ -138,7 +167,6 @@ int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 int eth_getenv_enetaddr_by_index(const char *base_name, int index,
 				 uchar *enetaddr);
 
-int usb_eth_initialize(bd_t *bi);
 int eth_init(bd_t *bis);			/* Initialize the device */
 int eth_send(void *packet, int length);	   /* Send a packet */
 
@@ -148,32 +176,7 @@ void (*push_packet)(void *packet, int length);
 #endif
 int eth_rx(void);			/* Check for received packets */
 void eth_halt(void);			/* stop SCC */
-char *eth_get_name(void);		/* get name of current device */
-
-/* Set active state */
-static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
-{
-	eth_get_dev()->state = ETH_STATE_ACTIVE;
-
-	return 0;
-}
-/* Set passive state */
-static inline __attribute__((always_inline)) void eth_halt_state_only(void)
-{
-	eth_get_dev()->state = ETH_STATE_PASSIVE;
-}
-
-/*
- * Set the hardware address for an ethernet interface based on 'eth%daddr'
- * environment variable (or just 'ethaddr' if eth_number is 0).
- * Args:
- *	base_name - base name for device (normally "eth")
- *	eth_number - value of %d (0 for first device of this type)
- * Returns:
- *	0 is success, non-zero is error status from driver.
- */
-int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
-		     int eth_number);
+const char *eth_get_name(void);		/* get name of current device */
 
 #ifdef CONFIG_MCAST_TFTP
 int eth_mcast_join(IPaddr_t mcast_addr, u8 join);
diff --git a/net/eth.c b/net/eth.c
index 65e8c77..c02548c 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -55,6 +55,14 @@ static inline int eth_setenv_enetaddr_by_index(const char *base_name, int index,
 	return eth_setenv_enetaddr(enetvar, enetaddr);
 }
 
+static void eth_env_init(void)
+{
+	const char *s;
+
+	s = getenv("bootfile");
+	if (s != NULL)
+		copy_filename(BootFile, s, sizeof(BootFile));
+}
 
 static int eth_mac_skip(int index)
 {
@@ -87,6 +95,11 @@ static unsigned int eth_rcv_current, eth_rcv_last;
 static struct eth_device *eth_devices;
 struct eth_device *eth_current;
 
+static void eth_set_current_to_next(void)
+{
+	eth_current = eth_current->next;
+}
+
 struct eth_device *eth_get_dev_by_name(const char *devname)
 {
 	struct eth_device *dev, *target_dev;
@@ -137,22 +150,6 @@ int eth_get_dev_index(void)
 	return eth_current->index;
 }
 
-static void eth_current_changed(void)
-{
-	char *act = getenv("ethact");
-	/* update current ethernet name */
-	if (eth_current) {
-		if (act == NULL || strcmp(act, eth_current->name) != 0)
-			setenv("ethact", eth_current->name);
-	}
-	/*
-	 * remove the variable completely if there is no active
-	 * interface
-	 */
-	else if (act != NULL)
-		setenv("ethact", NULL);
-}
-
 int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		   int eth_number)
 {
@@ -251,14 +248,6 @@ int eth_unregister(struct eth_device *dev)
 	return 0;
 }
 
-static void eth_env_init(bd_t *bis)
-{
-	const char *s;
-
-	if ((s = getenv("bootfile")) != NULL)
-		copy_filename(BootFile, s, sizeof(BootFile));
-}
-
 int eth_initialize(bd_t *bis)
 {
 	int num_devices = 0;
@@ -479,6 +468,22 @@ int eth_receive(void *packet, int length)
 }
 #endif /* CONFIG_API */
 
+static void eth_current_changed(void)
+{
+	char *act = getenv("ethact");
+	/* update current ethernet name */
+	if (eth_get_dev()) {
+		if (act == NULL || strcmp(act, eth_get_name()) != 0)
+			setenv("ethact", eth_get_name());
+	}
+	/*
+	 * remove the variable completely if there is no active
+	 * interface
+	 */
+	else if (act != NULL)
+		setenv("ethact", NULL);
+}
+
 void eth_try_another(int first_restart)
 {
 	static struct eth_device *first_failed;
@@ -492,17 +497,17 @@ void eth_try_another(int first_restart)
 	if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
 		return;
 
-	if (!eth_current)
+	if (!eth_get_dev())
 		return;
 
 	if (first_restart)
-		first_failed = eth_current;
+		first_failed = eth_get_dev();
 
-	eth_current = eth_current->next;
+	eth_set_current_to_next();
 
 	eth_current_changed();
 
-	if (first_failed == eth_current)
+	if (first_failed == eth_get_dev())
 		NetRestartWrap = 1;
 }
 
@@ -513,7 +518,7 @@ void eth_set_current(void)
 	struct eth_device *old_current;
 	int	env_id;
 
-	if (!eth_current)	/* XXX no current */
+	if (!eth_get_dev())	/* XXX no current */
 		return;
 
 	env_id = get_env_id();
@@ -522,18 +527,18 @@ void eth_set_current(void)
 		env_changed_id = env_id;
 	}
 	if (act != NULL) {
-		old_current = eth_current;
+		old_current = eth_get_dev();
 		do {
-			if (strcmp(eth_current->name, act) == 0)
+			if (strcmp(eth_get_name(), act) == 0)
 				return;
-			eth_current = eth_current->next;
-		} while (old_current != eth_current);
+			eth_set_current_to_next();
+		} while (old_current != eth_get_dev());
 	}
 
 	eth_current_changed();
 }
 
-char *eth_get_name(void)
+const char *eth_get_name(void)
 {
-	return eth_current ? eth_current->name : "unknown";
+	return eth_get_dev() ? eth_get_dev()->name : "unknown";
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 5/7] net: Add basic driver model support to Ethernet stack
  2015-01-27 23:27 [U-Boot] [RFC PATCH 0/7] Add Driver Model support to network stack Joe Hershberger
                   ` (3 preceding siblings ...)
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 4/7] net: Refactor in preparation for driver model Joe Hershberger
@ 2015-01-27 23:27 ` Joe Hershberger
  2015-01-28  2:34   ` Simon Glass
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 6/7] net: Add network support to sandbox Joe Hershberger
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-01-27 23:27 UTC (permalink / raw)
  To: u-boot

First just add support for MAC drivers.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
---

 common/board_r.c       |   4 +-
 common/cmd_bdinfo.c    |   2 +
 include/dm/uclass-id.h |   1 +
 include/net.h          |  23 ++++
 net/eth.c              | 320 ++++++++++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 346 insertions(+), 4 deletions(-)

diff --git a/common/board_r.c b/common/board_r.c
index a301cc2..9a41cae 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -572,7 +572,7 @@ static int initr_bbmii(void)
 }
 #endif
 
-#ifdef CONFIG_CMD_NET
+#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
 static int initr_net(void)
 {
 	puts("Net:   ");
@@ -841,7 +841,7 @@ init_fnc_t init_sequence_r[] = {
 #ifdef CONFIG_BITBANGMII
 	initr_bbmii,
 #endif
-#ifdef CONFIG_CMD_NET
+#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
 	INIT_FUNC_WATCHDOG_RESET
 	initr_net,
 #endif
diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
index e6d8a7a..8688cf9 100644
--- a/common/cmd_bdinfo.c
+++ b/common/cmd_bdinfo.c
@@ -34,6 +34,7 @@ static void print_eth(int idx)
 	printf("%-12s= %s\n", name, val);
 }
 
+#ifndef CONFIG_DM_ETH
 __maybe_unused
 static void print_eths(void)
 {
@@ -52,6 +53,7 @@ static void print_eths(void)
 	printf("current eth = %s\n", eth_get_name());
 	printf("ip_addr     = %s\n", getenv("ipaddr"));
 }
+#endif
 
 __maybe_unused
 static void print_lnum(const char *name, unsigned long long value)
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index f17c3c2..b04cbc9 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -33,6 +33,7 @@ enum uclass_id {
 	UCLASS_I2C,		/* I2C bus */
 	UCLASS_I2C_GENERIC,	/* Generic I2C device */
 	UCLASS_I2C_EEPROM,	/* I2C EEPROM device */
+	UCLASS_ETH,		/* Network device */
 
 	UCLASS_COUNT,
 	UCLASS_INVALID = -1,
diff --git a/include/net.h b/include/net.h
index 7eef9cc..25636e2 100644
--- a/include/net.h
+++ b/include/net.h
@@ -78,6 +78,29 @@ enum eth_state_t {
 	ETH_STATE_ACTIVE
 };
 
+#ifdef CONFIG_DM_ETH
+struct eth_pdata {
+	phys_addr_t iobase;
+};
+
+struct eth_ops {
+	int (*init)(struct udevice *dev, bd_t *bis);
+	int (*send)(struct udevice *dev, void *packet, int length);
+	int (*recv)(struct udevice *dev);
+	void (*halt)(struct udevice *dev);
+#ifdef CONFIG_MCAST_TFTP
+	int (*mcast)(struct udevice *dev, const u8 *enetaddr, u8 set);
+#endif
+	int (*write_hwaddr)(struct udevice *dev);
+};
+
+struct udevice *eth_get_dev(void); /* get the current device */
+unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
+int eth_init_state_only(bd_t *bis); /* Set active state */
+void eth_halt_state_only(void); /* Set passive state */
+#endif
+
+#ifndef CONFIG_DM_ETH
 struct eth_device {
 	char name[16];
 	unsigned char enetaddr[6];
diff --git a/net/eth.c b/net/eth.c
index c02548c..d245b65 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -72,6 +72,321 @@ static int eth_mac_skip(int index)
 	return ((skip_state = getenv(enetvar)) != NULL);
 }
 
+static void eth_current_changed(void);
+
+#ifdef CONFIG_DM_ETH
+#include <dm.h>
+
+struct eth_device_priv {
+	unsigned char enetaddr[6];
+	int state;
+	int index;
+	void *priv;
+};
+
+struct eth_uclass_priv {
+	struct udevice *current;
+	int max_index;
+};
+
+static void eth_set_current_to_next(void)
+{
+	struct uclass *uc;
+	struct eth_uclass_priv *priv;
+
+	uclass_get(UCLASS_ETH, &uc);
+	priv = uc->priv;
+	uclass_next_device(&(priv->current));
+	if (!priv->current)
+		uclass_first_device(UCLASS_ETH, &(priv->current));
+}
+
+struct udevice *eth_get_dev(void)
+{
+	struct uclass *uc;
+	uclass_get(UCLASS_ETH, &uc);
+
+	struct eth_uclass_priv *priv = uc->priv;
+	return priv->current;
+}
+
+static void eth_set_dev(struct udevice *dev)
+{
+	struct uclass *uc;
+	uclass_get(UCLASS_ETH, &uc);
+
+	struct eth_uclass_priv *priv = uc->priv;
+	priv->current = dev;
+}
+
+unsigned char *eth_get_ethaddr(void)
+{
+	struct eth_device_priv *priv;
+	if (eth_get_dev()) {
+		priv = eth_get_dev()->uclass_priv;
+		if (priv)
+			return priv->enetaddr;
+	}
+	return NULL;
+}
+
+/* Set active state */
+int eth_init_state_only(bd_t *bis)
+{
+	struct eth_device_priv *priv;
+	if (eth_get_dev()) {
+		priv = eth_get_dev()->uclass_priv;
+		if (priv)
+			priv->state = ETH_STATE_ACTIVE;
+	}
+
+	return 0;
+}
+/* Set passive state */
+void eth_halt_state_only(void)
+{
+	struct eth_device_priv *priv;
+	if (eth_get_dev()) {
+		priv = eth_get_dev()->uclass_priv;
+		if (priv)
+			priv->state = ETH_STATE_PASSIVE;
+	}
+}
+
+int eth_get_dev_index(void)
+{
+	struct eth_device_priv *priv;
+	if (eth_get_dev()) {
+		priv = eth_get_dev()->uclass_priv;
+		if (priv)
+			return priv->index;
+	}
+	return -1;
+}
+
+int eth_init(bd_t *bis)
+{
+	struct udevice *current, *old_current, *dev;
+	struct uclass *uc;
+
+	current = eth_get_dev();
+	if (!current) {
+		puts("No ethernet found.\n");
+		return -1;
+	}
+
+	/* Sync environment with network devices */
+	uclass_get(UCLASS_ETH, &uc);
+	uclass_foreach_dev(dev, uc) {
+		uchar env_enetaddr[6];
+
+		if (eth_getenv_enetaddr_by_index("eth", dev->seq,
+						 env_enetaddr)) {
+			struct eth_device_priv *priv = dev->uclass_priv;
+			if (priv)
+				memcpy(priv->enetaddr, env_enetaddr, 6);
+		}
+	};
+
+	old_current = current;
+	do {
+		debug("Trying %s\n", current->name);
+
+		if (current->driver) {
+			const struct eth_ops *ops = current->driver->ops;
+			if (ops->init(current, bis) >= 0) {
+				struct eth_device_priv *priv =
+					current->uclass_priv;
+				if (priv)
+					priv->state = ETH_STATE_ACTIVE;
+
+				return 0;
+			}
+		}
+		debug("FAIL\n");
+
+		eth_try_another(0);
+		current = eth_get_dev();
+	} while (old_current != current);
+
+	return -1;
+}
+
+void eth_halt(void)
+{
+	struct udevice *current;
+
+	current = eth_get_dev();
+	if (!current)
+		return;
+	if (!current->driver)
+		return;
+
+	const struct eth_ops *ops = current->driver->ops;
+	ops->halt(current);
+
+	struct eth_device_priv *priv = current->uclass_priv;
+	if (priv)
+		priv->state = ETH_STATE_PASSIVE;
+}
+
+int eth_send(void *packet, int length)
+{
+	struct udevice *current;
+
+	current = eth_get_dev();
+	if (!current)
+		return -1;
+	if (!current->driver)
+		return -1;
+
+	const struct eth_ops *ops = current->driver->ops;
+	return ops->send(current, packet, length);
+}
+
+int eth_rx(void)
+{
+	struct udevice *current;
+
+	current = eth_get_dev();
+	if (!current)
+		return -1;
+	if (!current->driver)
+		return -1;
+
+	const struct eth_ops *ops = current->driver->ops;
+	return ops->recv(current);
+}
+
+static int eth_write_hwaddr(struct udevice *dev, const char *base_name,
+		   int eth_number)
+{
+	unsigned char env_enetaddr[6];
+	int ret = 0;
+
+	eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
+
+	struct eth_device_priv *priv = dev->uclass_priv;
+	if (!is_zero_ether_addr(env_enetaddr)) {
+		if (!is_zero_ether_addr(priv->enetaddr) &&
+		    memcmp(priv->enetaddr, env_enetaddr, 6)) {
+			printf("\nWarning: %s MAC addresses don't match:\n",
+			       dev->name);
+			printf("Address in SROM is         %pM\n",
+			       priv->enetaddr);
+			printf("Address in environment is  %pM\n",
+			       env_enetaddr);
+		}
+
+		memcpy(priv->enetaddr, env_enetaddr, 6);
+	} else if (is_valid_ether_addr(priv->enetaddr)) {
+		eth_setenv_enetaddr_by_index(base_name, eth_number,
+					     priv->enetaddr);
+		printf("\nWarning: %s using MAC address from net device\n",
+		       dev->name);
+	} else if (is_zero_ether_addr(priv->enetaddr)) {
+		printf("\nError: %s address not set.\n",
+		       dev->name);
+		return -EINVAL;
+	}
+
+	const struct eth_ops *ops = dev->driver->ops;
+	if (ops->write_hwaddr && !eth_mac_skip(eth_number)) {
+		if (!is_valid_ether_addr(priv->enetaddr)) {
+			printf("\nError: %s address %pM illegal value\n",
+			       dev->name, priv->enetaddr);
+			return -EINVAL;
+		}
+
+		ret = ops->write_hwaddr(dev);
+		if (ret)
+			printf("\nWarning: %s failed to set MAC address\n",
+			       dev->name);
+	}
+
+	return ret;
+}
+
+static int eth_uclass_init(struct uclass *class)
+{
+	bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
+
+	struct eth_uclass_priv *priv = class->priv;
+	priv->max_index = 0;
+
+	eth_env_init();
+
+	return 0;
+}
+
+static int eth_post_bind(struct udevice *dev)
+{
+	struct udevice *first;
+
+	uclass_first_device(UCLASS_ETH, &first);
+	if (first == dev) {
+		eth_current_changed();
+		eth_set_dev(dev);
+	}
+
+	struct eth_device_priv *priv = dev->uclass_priv;
+	struct eth_uclass_priv *uclass_priv = dev->uclass->priv;
+	if (priv) {
+		priv->state = ETH_STATE_INIT;
+		priv->index = uclass_priv->max_index++;
+	}
+
+	return 0;
+}
+
+static int eth_pre_unbind(struct udevice *dev)
+{
+	struct udevice *first;
+	struct udevice *current;
+
+	current = eth_get_dev();
+	uclass_first_device(UCLASS_ETH, &first);
+	if (current == dev) {
+		if (dev == first)
+			uclass_next_device(&current);
+		else
+			current = first;
+		eth_current_changed();
+		eth_set_dev(current);
+	}
+
+	return 0;
+}
+
+static int eth_post_probe(struct udevice *dev)
+{
+	char *ethprime = getenv("ethprime");
+	if (ethprime && strcmp(dev->name, ethprime) == 0)
+		eth_set_dev(dev);
+
+	if (strchr(dev->name, ' '))
+		printf("\nWarning: eth device name \"%s\" has a space!\n",
+		       dev->name);
+
+	struct eth_device_priv *priv = dev->uclass_priv;
+	if (priv)
+		return eth_write_hwaddr(dev, "eth", priv->index);
+	return 1;
+}
+
+UCLASS_DRIVER(eth) = {
+	.name		= "eth",
+	.id		= UCLASS_ETH,
+	.post_bind	= eth_post_bind,
+	.pre_unbind	= eth_pre_unbind,
+	.post_probe	= eth_post_probe,
+	.init		= eth_uclass_init,
+	.priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
+	.per_device_auto_alloc_size = sizeof(struct eth_device_priv),
+};
+#endif
+
+#ifndef CONFIG_DM_ETH
 /*
  * CPU and board-specific Ethernet initializations.  Aliased function
  * signals caller to move on
@@ -423,6 +738,7 @@ int eth_rx(void)
 
 	return eth_current->recv(eth_current);
 }
+#endif /* ifndef CONFIG_DM_ETH */
 
 #ifdef CONFIG_API
 static void eth_save_packet(void *packet, int length)
@@ -486,7 +802,7 @@ static void eth_current_changed(void)
 
 void eth_try_another(int first_restart)
 {
-	static struct eth_device *first_failed;
+	static void *first_failed;
 	char *ethrotate;
 
 	/*
@@ -515,7 +831,7 @@ void eth_set_current(void)
 {
 	static char *act;
 	static int  env_changed_id;
-	struct eth_device *old_current;
+	void *old_current;
 	int	env_id;
 
 	if (!eth_get_dev())	/* XXX no current */
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 6/7] net: Add network support to sandbox
  2015-01-27 23:27 [U-Boot] [RFC PATCH 0/7] Add Driver Model support to network stack Joe Hershberger
                   ` (4 preceding siblings ...)
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 5/7] net: Add basic driver model support to Ethernet stack Joe Hershberger
@ 2015-01-27 23:27 ` Joe Hershberger
  2015-01-28  2:34   ` Simon Glass
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 7/7] net: Add ARP and PING response to sandbox driver Joe Hershberger
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-01-27 23:27 UTC (permalink / raw)
  To: u-boot

Add basic network support to sandbox which includes a network driver.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
---

 arch/sandbox/dts/sandbox.dts |  4 ++
 drivers/net/Makefile         |  2 +
 drivers/net/sandbox.c        | 91 ++++++++++++++++++++++++++++++++++++++++++++
 include/configs/sandbox.h    | 14 ++++---
 4 files changed, 106 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/sandbox.c

diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 11748ae..a1d3199 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -174,4 +174,8 @@
 		};
 	};
 
+	eth at 10002000 {
+		compatible = "sandbox,eth";
+		reg = <0x10002000 0x1000>;
+	};
 };
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 46c4ac6..2659a8a 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -50,6 +50,8 @@ obj-$(CONFIG_NS8382X) += ns8382x.o
 obj-$(CONFIG_PCNET) += pcnet.o
 obj-$(CONFIG_RTL8139) += rtl8139.o
 obj-$(CONFIG_RTL8169) += rtl8169.o
+obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
+obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o
 obj-$(CONFIG_SH_ETHER) += sh_eth.o
 obj-$(CONFIG_SMC91111) += smc91111.o
 obj-$(CONFIG_SMC911X) += smc911x.o
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
new file mode 100644
index 0000000..e1ee69b
--- /dev/null
+++ b/drivers/net/sandbox.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct eth_sandbox_priv {
+	void *device;
+	int sd;
+};
+
+int sb_eth_init(struct udevice *dev, bd_t *bis)
+{
+	printf("eth_sandbox: Init\n");
+
+	return 0;
+}
+
+int sb_eth_send(struct udevice *dev, void *packet, int length)
+{
+	printf("eth_sandbox: Send packet %d\n", length);
+
+	return 0;
+#endif
+}
+
+int sb_eth_recv(struct udevice *dev)
+{
+	return 0;
+}
+
+void sb_eth_halt(struct udevice *dev)
+{
+	printf("eth_sandbox: Halt\n");
+}
+
+int sb_eth_write_hwaddr(struct udevice *dev)
+{
+	printf("eth_sandbox: Write HW ADDR\n");
+	return 0;
+}
+
+static const struct eth_ops eth_sandbox_ops = {
+	.init			= sb_eth_init,
+	.send			= sb_eth_send,
+	.recv			= sb_eth_recv,
+	.halt			= sb_eth_halt,
+	.write_hwaddr		= sb_eth_write_hwaddr,
+};
+
+static int eth_sandbox_remove(struct udevice *dev)
+{
+	return 0;
+}
+
+#ifdef CONFIG_OF_CONTROL
+static int sandbox_eth_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev->platdata;
+
+	pdata->iobase = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
+	return 0;
+}
+
+static const struct udevice_id sandbox_eth_ids[] = {
+	{ .compatible = "sandbox,eth" },
+	{ }
+};
+#endif
+
+U_BOOT_DRIVER(eth_sandbox) = {
+	.name	= "eth_sandbox",
+	.id	= UCLASS_ETH,
+	.of_match = of_match_ptr(sandbox_eth_ids),
+	.ofdata_to_platdata = of_match_ptr(sandbox_eth_ofdata_to_platdata),
+	.remove	= eth_sandbox_remove,
+	.ops	= &eth_sandbox_ops,
+	.priv_auto_alloc_size = sizeof(struct eth_sandbox_priv),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 657f751..67bfc52 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -143,9 +143,9 @@
 /* include default commands */
 #include <config_cmd_default.h>
 
-/* We don't have networking support yet */
-#undef CONFIG_CMD_NET
-#undef CONFIG_CMD_NFS
+#define CONFIG_DM_ETH
+#define CONFIG_ETH_SANDBOX
+#define CONFIG_CMD_PING
 
 #define CONFIG_CMD_HASH
 #define CONFIG_HASH_VERIFY
@@ -188,12 +188,16 @@
 
 #define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial,cros-ec-keyb\0" \
 					"stdout=serial,lcd\0" \
-					"stderr=serial,lcd\0"
+					"stderr=serial,lcd\0" \
+					"ethaddr=00:00:11:22:33:44\0" \
+					"ipaddr=1.2.3.4\0"
 #else
 
 #define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial\0" \
 					"stdout=serial,lcd\0" \
-					"stderr=serial,lcd\0"
+					"stderr=serial,lcd\0" \
+					"ethaddr=00:00:11:22:33:44\0" \
+					"ipaddr=1.2.3.4\0"
 #endif
 
 #define CONFIG_GZIP_COMPRESSED
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 7/7] net: Add ARP and PING response to sandbox driver
  2015-01-27 23:27 [U-Boot] [RFC PATCH 0/7] Add Driver Model support to network stack Joe Hershberger
                   ` (5 preceding siblings ...)
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 6/7] net: Add network support to sandbox Joe Hershberger
@ 2015-01-27 23:27 ` Joe Hershberger
  2015-01-28  2:34   ` Simon Glass
  2015-01-28  2:33 ` [U-Boot] [RFC PATCH 0/7] Add Driver Model support to network stack Simon Glass
  2015-02-03  0:38 ` [U-Boot] [RFC PATCH v2 0/8] " Joe Hershberger
  8 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-01-27 23:27 UTC (permalink / raw)
  To: u-boot

The sandbox driver will now generate response traffic to exercise the
ping command even when no network exists.  This allows the basic data
pathways of the DM to be tested.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
---

 drivers/net/sandbox.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)

diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
index e1ee69b..49413f2 100644
--- a/drivers/net/sandbox.c
+++ b/drivers/net/sandbox.c
@@ -20,6 +20,11 @@ struct eth_sandbox_priv {
 	int sd;
 };
 
+static uchar fake_host_hwaddr[ARP_HLEN] = {0x00, 0x00, 0x66, 0x44, 0x22, 0x00};
+static IPaddr_t fake_host_ipaddr;
+static uchar recv_packet_buffer[PKTSIZE];
+static int recv_packet_length;
+
 int sb_eth_init(struct udevice *dev, bd_t *bis)
 {
 	printf("eth_sandbox: Init\n");
@@ -31,12 +36,82 @@ int sb_eth_send(struct udevice *dev, void *packet, int length)
 {
 	printf("eth_sandbox: Send packet %d\n", length);
 
+	struct ethernet_hdr *eth = packet;
+	if (ntohs(eth->et_protlen) == PROT_ARP) {
+		struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
+		if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
+			/* store this as the assumed IP of the fake host */
+			fake_host_ipaddr = NetReadIP(&arp->ar_tpa);
+			/* Formulate a fake response */
+			struct ethernet_hdr *eth_recv =
+				(void *)recv_packet_buffer;
+			memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
+			memcpy(eth_recv->et_src, fake_host_hwaddr, ARP_HLEN);
+			eth_recv->et_protlen = htons(PROT_ARP);
+
+			struct arp_hdr *arp_recv = (void *)recv_packet_buffer +
+				ETHER_HDR_SIZE;
+			arp_recv->ar_hrd = htons(ARP_ETHER);
+			arp_recv->ar_pro = htons(PROT_IP);
+			arp_recv->ar_hln = ARP_HLEN;
+			arp_recv->ar_pln = ARP_PLEN;
+			arp_recv->ar_op = htons(ARPOP_REPLY);
+			memcpy(&arp_recv->ar_sha, fake_host_hwaddr, ARP_HLEN);
+			NetWriteIP(&arp_recv->ar_spa, fake_host_ipaddr);
+			memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN);
+			NetCopyIP(&arp_recv->ar_tpa, &arp->ar_spa);
+
+			recv_packet_length = ETHER_HDR_SIZE + ARP_HDR_SIZE;
+		}
+	} else if (ntohs(eth->et_protlen) == PROT_IP) {
+		struct ip_udp_hdr *ip = packet + ETHER_HDR_SIZE;
+		if (ip->ip_p == IPPROTO_ICMP) {
+			struct icmp_hdr *icmp = (struct icmp_hdr *)&ip->udp_src;
+			if (icmp->type == ICMP_ECHO_REQUEST) {
+				/* reply to the ping */
+				memcpy(recv_packet_buffer, packet, length);
+				struct ethernet_hdr *eth_recv =
+					(void *)recv_packet_buffer;
+				struct ip_udp_hdr *ipr =
+					(void *)recv_packet_buffer +
+					ETHER_HDR_SIZE;
+				struct icmp_hdr *icmpr =
+					(struct icmp_hdr *)&ipr->udp_src;
+				memcpy(eth_recv->et_dest, eth->et_src,
+				       ARP_HLEN);
+				memcpy(eth_recv->et_src, fake_host_hwaddr,
+				       ARP_HLEN);
+				ipr->ip_sum = 0;
+				ipr->ip_off = 0;
+				NetCopyIP((void *)&ipr->ip_dst, &ip->ip_src);
+				NetWriteIP((void *)&ipr->ip_src,
+					   fake_host_ipaddr);
+				ipr->ip_sum = ~NetCksum((uchar *)ipr,
+					IP_HDR_SIZE >> 1);
+
+				icmpr->type = ICMP_ECHO_REPLY;
+				icmpr->checksum = 0;
+				icmpr->checksum = ~NetCksum((uchar *)icmpr,
+					(length - ETHER_HDR_SIZE -
+						IP_HDR_SIZE) >> 1);
+
+				recv_packet_length = length;
+			}
+		}
+	}
+
 	return 0;
 #endif
 }
 
 int sb_eth_recv(struct udevice *dev)
 {
+	if (recv_packet_length) {
+		int lcl_recv_packet_length = recv_packet_length;
+		printf("eth_sandbox: received packet %d\n", recv_packet_length);
+		recv_packet_length = 0;
+		NetReceive((void *)recv_packet_buffer, lcl_recv_packet_length);
+	}
 	return 0;
 }
 
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 0/7] Add Driver Model support to network stack
  2015-01-27 23:27 [U-Boot] [RFC PATCH 0/7] Add Driver Model support to network stack Joe Hershberger
                   ` (6 preceding siblings ...)
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 7/7] net: Add ARP and PING response to sandbox driver Joe Hershberger
@ 2015-01-28  2:33 ` Simon Glass
  2015-02-03  0:38 ` [U-Boot] [RFC PATCH v2 0/8] " Joe Hershberger
  8 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-01-28  2:33 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 27 January 2015 at 16:27, Joe Hershberger <joe.hershberger@ni.com> wrote:
> For now this simply addresses the MAC part of the network hardware.
> The next part to implement is the PHY children.  I wanted to get early
> feedback on what I have so far to make sure I'm going in the direction
> that Simon envisioned.
>

It's great to see this! My comments are against each patch.

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 1/7] net: Provide a function to get the current MAC address
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 1/7] net: Provide a function to get the current MAC address Joe Hershberger
@ 2015-01-28  2:33   ` Simon Glass
  2015-01-28  9:45     ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-01-28  2:33 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 27 January 2015 at 16:27, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The current implementation exposes the eth_device struct to code that
> needs to access the MAC address.  Add a wrapper function for this to
> abstract away the pointer for this operation.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> ---
>
>  arch/mips/cpu/mips32/au1x00/au1x00_eth.c | 2 +-
>  arch/powerpc/cpu/mpc8260/ether_fcc.c     | 2 +-
>  arch/powerpc/cpu/mpc85xx/ether_fcc.c     | 2 +-
>  arch/powerpc/cpu/mpc8xx/scc.c            | 2 +-
>  include/net.h                            | 8 ++++++++
>  net/net.c                                | 2 +-
>  6 files changed, 13 insertions(+), 5 deletions(-)
>
> diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_eth.c b/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
> index 4770f56..535d713 100644
> --- a/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
> +++ b/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
> @@ -238,7 +238,7 @@ static int au1x00_init(struct eth_device* dev, bd_t * bd){
>         }
>
>         /* Put mac addr in little endian */
> -#define ea eth_get_dev()->enetaddr
> +#define ea eth_get_ethaddr()
>         *mac_addr_high  =       (ea[5] <<  8) | (ea[4]      ) ;
>         *mac_addr_low   =       (ea[3] << 24) | (ea[2] << 16) |

I know this is existing code, but (perhaps separately) it might be
nice to remove the #define and assign it it to a local variable, i.e.:

unsigned char *ea = eth_get_ethaddr();

>                 (ea[1] <<  8) | (ea[0]      ) ;
> diff --git a/arch/powerpc/cpu/mpc8260/ether_fcc.c b/arch/powerpc/cpu/mpc8260/ether_fcc.c
> index f9f15b5..f777ba1 100644
> --- a/arch/powerpc/cpu/mpc8260/ether_fcc.c
> +++ b/arch/powerpc/cpu/mpc8260/ether_fcc.c
> @@ -299,7 +299,7 @@ static int fec_init(struct eth_device* dev, bd_t *bis)
>       * it unique by setting a few bits in the upper byte of the
>       * non-static part of the address.
>       */
> -#define ea eth_get_dev()->enetaddr
> +#define ea eth_get_ethaddr()
>      pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
>      pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
>      pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
> diff --git a/arch/powerpc/cpu/mpc85xx/ether_fcc.c b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
> index 166dc9e..58d4bfb 100644
> --- a/arch/powerpc/cpu/mpc85xx/ether_fcc.c
> +++ b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
> @@ -338,7 +338,7 @@ static int fec_init(struct eth_device* dev, bd_t *bis)
>       * it unique by setting a few bits in the upper byte of the
>       * non-static part of the address.
>       */
> -#define ea eth_get_dev()->enetaddr
> +#define ea eth_get_ethaddr()
>      pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
>      pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
>      pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
> diff --git a/arch/powerpc/cpu/mpc8xx/scc.c b/arch/powerpc/cpu/mpc8xx/scc.c
> index 251966b..66e4014 100644
> --- a/arch/powerpc/cpu/mpc8xx/scc.c
> +++ b/arch/powerpc/cpu/mpc8xx/scc.c
> @@ -339,7 +339,7 @@ static int scc_init (struct eth_device *dev, bd_t * bis)
>         pram_ptr->sen_gaddr3 = 0x0;     /* Group Address Filter 3 (unused) */
>         pram_ptr->sen_gaddr4 = 0x0;     /* Group Address Filter 4 (unused) */
>
> -#define ea eth_get_dev()->enetaddr
> +#define ea eth_get_ethaddr()
>         pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4];
>         pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2];
>         pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0];
> diff --git a/include/net.h b/include/net.h
> index 73ea88b..a9579ee 100644
> --- a/include/net.h
> +++ b/include/net.h
> @@ -111,6 +111,14 @@ struct eth_device *eth_get_dev(void)
>  {
>         return eth_current;
>  }
> +
> +static inline unsigned char *eth_get_ethaddr(void)
> +{
> +       if (eth_current)
> +               return eth_current->enetaddr;
> +       return NULL;
> +}
> +
>  extern struct eth_device *eth_get_dev_by_name(const char *devname);
>  extern struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
>  extern int eth_get_dev_index(void);            /* get the device index */
> diff --git a/net/net.c b/net/net.c
> index 2bea07b..ddd630c 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -275,7 +275,7 @@ static void NetInitLoop(void)
>                 env_changed_id = env_id;
>         }
>         if (eth_get_dev())
> -               memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
> +               memcpy(NetOurEther, eth_get_ethaddr(), 6);
>
>         return;
>  }
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 2/7] net: Rename helper function to be more clear
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 2/7] net: Rename helper function to be more clear Joe Hershberger
@ 2015-01-28  2:34   ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-01-28  2:34 UTC (permalink / raw)
  To: u-boot

On 27 January 2015 at 16:27, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Make it clear that the helper is checking the addr, not setting it.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> ---
>
>  net/eth.c | 13 ++++---------
>  1 file changed, 4 insertions(+), 9 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

>
> diff --git a/net/eth.c b/net/eth.c
> index eac4f7b..65e8c77 100644
> --- a/net/eth.c
> +++ b/net/eth.c
> @@ -153,11 +153,6 @@ static void eth_current_changed(void)
>                 setenv("ethact", NULL);
>  }
>
> -static int eth_address_set(unsigned char *addr)
> -{
> -       return memcmp(addr, "\0\0\0\0\0\0", 6);
> -}
> -
>  int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
>                    int eth_number)
>  {
> @@ -166,9 +161,9 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
>
>         eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
>
> -       if (eth_address_set(env_enetaddr)) {
> -               if (eth_address_set(dev->enetaddr) &&
> -                               memcmp(dev->enetaddr, env_enetaddr, 6)) {
> +       if (!is_zero_ether_addr(env_enetaddr)) {
> +               if (!is_zero_ether_addr(dev->enetaddr) &&
> +                   memcmp(dev->enetaddr, env_enetaddr, 6)) {
>                         printf("\nWarning: %s MAC addresses don't match:\n",
>                                 dev->name);
>                         printf("Address in SROM is         %pM\n",
> @@ -183,7 +178,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
>                                              dev->enetaddr);
>                 printf("\nWarning: %s using MAC address from net device\n",
>                         dev->name);
> -       } else if (!(eth_address_set(dev->enetaddr))) {
> +       } else if (is_zero_ether_addr(dev->enetaddr)) {
>                 printf("\nError: %s address not set.\n",
>                        dev->name);
>                 return -EINVAL;
> --
> 1.7.11.5
>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 3/7] net: Remove unneeded "extern" in net.h
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 3/7] net: Remove unneeded "extern" in net.h Joe Hershberger
@ 2015-01-28  2:34   ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-01-28  2:34 UTC (permalink / raw)
  To: u-boot

On 27 January 2015 at 16:27, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Many of the functions in net.h were preceded extern needlessly. Removing
> them to limit the number of checkpatch.pl complaints.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> ---
>
>  include/net.h | 96 +++++++++++++++++++++++++++++------------------------------
>  1 file changed, 48 insertions(+), 48 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 4/7] net: Refactor in preparation for driver model
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 4/7] net: Refactor in preparation for driver model Joe Hershberger
@ 2015-01-28  2:34   ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-01-28  2:34 UTC (permalink / raw)
  To: u-boot

On 27 January 2015 at 16:27, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Move some things around and organize things so that the driver model
> implementation will fit in more easily.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> ---
>
>  include/net.h | 63 +++++++++++++++++++++++++------------------------
>  net/eth.c     | 75 +++++++++++++++++++++++++++++++----------------------------
>  2 files changed, 73 insertions(+), 65 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 5/7] net: Add basic driver model support to Ethernet stack
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 5/7] net: Add basic driver model support to Ethernet stack Joe Hershberger
@ 2015-01-28  2:34   ` Simon Glass
  2015-01-28 10:22     ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-01-28  2:34 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 27 January 2015 at 16:27, Joe Hershberger <joe.hershberger@ni.com> wrote:
> First just add support for MAC drivers.
>

I don't fully understand this partly because my knowledge of the
network stack is limited. So I'll make a few comments and we can go
from there.

> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> ---
>
>  common/board_r.c       |   4 +-
>  common/cmd_bdinfo.c    |   2 +
>  include/dm/uclass-id.h |   1 +
>  include/net.h          |  23 ++++
>  net/eth.c              | 320 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  5 files changed, 346 insertions(+), 4 deletions(-)
>
> diff --git a/common/board_r.c b/common/board_r.c
> index a301cc2..9a41cae 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -572,7 +572,7 @@ static int initr_bbmii(void)
>  }
>  #endif
>
> -#ifdef CONFIG_CMD_NET
> +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
>  static int initr_net(void)
>  {
>         puts("Net:   ");
> @@ -841,7 +841,7 @@ init_fnc_t init_sequence_r[] = {
>  #ifdef CONFIG_BITBANGMII
>         initr_bbmii,
>  #endif
> -#ifdef CONFIG_CMD_NET
> +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
>         INIT_FUNC_WATCHDOG_RESET
>         initr_net,
>  #endif
> diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
> index e6d8a7a..8688cf9 100644
> --- a/common/cmd_bdinfo.c
> +++ b/common/cmd_bdinfo.c
> @@ -34,6 +34,7 @@ static void print_eth(int idx)
>         printf("%-12s= %s\n", name, val);
>  }
>
> +#ifndef CONFIG_DM_ETH
>  __maybe_unused
>  static void print_eths(void)
>  {
> @@ -52,6 +53,7 @@ static void print_eths(void)
>         printf("current eth = %s\n", eth_get_name());
>         printf("ip_addr     = %s\n", getenv("ipaddr"));
>  }
> +#endif
>
>  __maybe_unused
>  static void print_lnum(const char *name, unsigned long long value)
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index f17c3c2..b04cbc9 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -33,6 +33,7 @@ enum uclass_id {
>         UCLASS_I2C,             /* I2C bus */
>         UCLASS_I2C_GENERIC,     /* Generic I2C device */
>         UCLASS_I2C_EEPROM,      /* I2C EEPROM device */
> +       UCLASS_ETH,             /* Network device */

Ethernet device?

>
>         UCLASS_COUNT,
>         UCLASS_INVALID = -1,
> diff --git a/include/net.h b/include/net.h
> index 7eef9cc..25636e2 100644
> --- a/include/net.h
> +++ b/include/net.h
> @@ -78,6 +78,29 @@ enum eth_state_t {
>         ETH_STATE_ACTIVE
>  };
>
> +#ifdef CONFIG_DM_ETH
> +struct eth_pdata {
> +       phys_addr_t iobase;
> +};
> +
> +struct eth_ops {
> +       int (*init)(struct udevice *dev, bd_t *bis);
> +       int (*send)(struct udevice *dev, void *packet, int length);
> +       int (*recv)(struct udevice *dev);
> +       void (*halt)(struct udevice *dev);
> +#ifdef CONFIG_MCAST_TFTP
> +       int (*mcast)(struct udevice *dev, const u8 *enetaddr, u8 set);
> +#endif
> +       int (*write_hwaddr)(struct udevice *dev);
> +};
> +
> +struct udevice *eth_get_dev(void); /* get the current device */
> +unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
> +int eth_init_state_only(bd_t *bis); /* Set active state */
> +void eth_halt_state_only(void); /* Set passive state */
> +#endif
> +
> +#ifndef CONFIG_DM_ETH
>  struct eth_device {
>         char name[16];
>         unsigned char enetaddr[6];
> diff --git a/net/eth.c b/net/eth.c
> index c02548c..d245b65 100644
> --- a/net/eth.c
> +++ b/net/eth.c
> @@ -72,6 +72,321 @@ static int eth_mac_skip(int index)
>         return ((skip_state = getenv(enetvar)) != NULL);
>  }
>
> +static void eth_current_changed(void);
> +
> +#ifdef CONFIG_DM_ETH
> +#include <dm.h>
> +
> +struct eth_device_priv {
> +       unsigned char enetaddr[6];
> +       int state;
> +       int index;
> +       void *priv;

Suggestion: you could have per-child platform data as well as
per-child private data. See u-boot-dm/master for this. It is used for
I2C and SPI to hold the address of the child on the bus.

You could use it to hold the MAC address. I think this *might* be
better because the MAC address can then be set and retained even when
the device is probed/removed.

> +};
> +
> +struct eth_uclass_priv {
> +       struct udevice *current;
> +       int max_index;
> +};
> +
> +static void eth_set_current_to_next(void)
> +{
> +       struct uclass *uc;
> +       struct eth_uclass_priv *priv;
> +
> +       uclass_get(UCLASS_ETH, &uc);
> +       priv = uc->priv;
> +       uclass_next_device(&(priv->current));

Note that this will probe the device. I think you are storing the
current ethernet device in the uclass, but you could just as well have
a static variable in this file if that is easier.

(Also remove internal brackets)

If priv->current is NULL, this will die.

Also to avoid confusion I think you should use uc_priv for the uclass
priv local variable, to distinguish it from priv.

> +       if (!priv->current)
> +               uclass_first_device(UCLASS_ETH, &(priv->current));

If I understand this correctly, I think you want:

if (priv->current)
    uclass_next_device(&priv->current)
else
   uclass_first_device(uc, &priv->current)

> +}
> +
> +struct udevice *eth_get_dev(void)
> +{
> +       struct uclass *uc;
> +       uclass_get(UCLASS_ETH, &uc);
> +
> +       struct eth_uclass_priv *priv = uc->priv;

This is OK so long as the device has been probed. I think it always is
because you use uclass_next_device() to get the device.

> +       return priv->current;
> +}
> +
> +static void eth_set_dev(struct udevice *dev)
> +{
> +       struct uclass *uc;
> +       uclass_get(UCLASS_ETH, &uc);
> +
> +       struct eth_uclass_priv *priv = uc->priv;
> +       priv->current = dev;
> +}
> +
> +unsigned char *eth_get_ethaddr(void)
> +{
> +       struct eth_device_priv *priv;
> +       if (eth_get_dev()) {
> +               priv = eth_get_dev()->uclass_priv;
> +               if (priv)

This check should be unnecessary. Same in other cases below.

> +                       return priv->enetaddr;
> +       }
> +       return NULL;
> +}
> +
> +/* Set active state */
> +int eth_init_state_only(bd_t *bis)
> +{
> +       struct eth_device_priv *priv;
> +       if (eth_get_dev()) {
> +               priv = eth_get_dev()->uclass_priv;
> +               if (priv)
> +                       priv->state = ETH_STATE_ACTIVE;
> +       }
> +
> +       return 0;
> +}
> +/* Set passive state */
> +void eth_halt_state_only(void)
> +{
> +       struct eth_device_priv *priv;
> +       if (eth_get_dev()) {
> +               priv = eth_get_dev()->uclass_priv;
> +               if (priv)
> +                       priv->state = ETH_STATE_PASSIVE;
> +       }
> +}
> +
> +int eth_get_dev_index(void)
> +{
> +       struct eth_device_priv *priv;
> +       if (eth_get_dev()) {
> +               priv = eth_get_dev()->uclass_priv;
> +               if (priv)
> +                       return priv->index;
> +       }
> +       return -1;
> +}
> +
> +int eth_init(bd_t *bis)
> +{
> +       struct udevice *current, *old_current, *dev;
> +       struct uclass *uc;
> +
> +       current = eth_get_dev();
> +       if (!current) {
> +               puts("No ethernet found.\n");
> +               return -1;
> +       }
> +
> +       /* Sync environment with network devices */
> +       uclass_get(UCLASS_ETH, &uc);
> +       uclass_foreach_dev(dev, uc) {
> +               uchar env_enetaddr[6];
> +
> +               if (eth_getenv_enetaddr_by_index("eth", dev->seq,
> +                                                env_enetaddr)) {
> +                       struct eth_device_priv *priv = dev->uclass_priv;
> +                       if (priv)
> +                               memcpy(priv->enetaddr, env_enetaddr, 6);
> +               }
> +       };
> +
> +       old_current = current;
> +       do {
> +               debug("Trying %s\n", current->name);
> +
> +               if (current->driver) {
> +                       const struct eth_ops *ops = current->driver->ops;
> +                       if (ops->init(current, bis) >= 0) {
> +                               struct eth_device_priv *priv =
> +                                       current->uclass_priv;
> +                               if (priv)
> +                                       priv->state = ETH_STATE_ACTIVE;
> +
> +                               return 0;
> +                       }
> +               }
> +               debug("FAIL\n");
> +
> +               eth_try_another(0);
> +               current = eth_get_dev();
> +       } while (old_current != current);
> +
> +       return -1;

-ENODEV?

> +}
> +
> +void eth_halt(void)
> +{
> +       struct udevice *current;
> +
> +       current = eth_get_dev();
> +       if (!current)
> +               return;
> +       if (!current->driver)
> +               return;
> +
> +       const struct eth_ops *ops = current->driver->ops;
> +       ops->halt(current);
> +
> +       struct eth_device_priv *priv = current->uclass_priv;
> +       if (priv)
> +               priv->state = ETH_STATE_PASSIVE;
> +}
> +
> +int eth_send(void *packet, int length)
> +{
> +       struct udevice *current;
> +
> +       current = eth_get_dev();
> +       if (!current)
> +               return -1;
> +       if (!current->driver)
> +               return -1;
> +
> +       const struct eth_ops *ops = current->driver->ops;
> +       return ops->send(current, packet, length);
> +}
> +

As a general comment, there is an implicit assumption that only one
device can be active at a time. I suppose that is a U-Boot limitation,
but we don't need to keep it for driver model, or at least we could
permit multiple devices to be probed at a time.

But still I wonder if you should have functions that are passed a
udevice, like eth_rx(struct udevice *dev).

> +int eth_rx(void)
> +{
> +       struct udevice *current;
> +
> +       current = eth_get_dev();
> +       if (!current)
> +               return -1;
> +       if (!current->driver)
> +               return -1;
> +
> +       const struct eth_ops *ops = current->driver->ops;
> +       return ops->recv(current);
> +}
> +
> +static int eth_write_hwaddr(struct udevice *dev, const char *base_name,
> +                  int eth_number)
> +{
> +       unsigned char env_enetaddr[6];
> +       int ret = 0;
> +
> +       eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
> +
> +       struct eth_device_priv *priv = dev->uclass_priv;
> +       if (!is_zero_ether_addr(env_enetaddr)) {
> +               if (!is_zero_ether_addr(priv->enetaddr) &&
> +                   memcmp(priv->enetaddr, env_enetaddr, 6)) {
> +                       printf("\nWarning: %s MAC addresses don't match:\n",
> +                              dev->name);
> +                       printf("Address in SROM is         %pM\n",
> +                              priv->enetaddr);
> +                       printf("Address in environment is  %pM\n",
> +                              env_enetaddr);
> +               }
> +
> +               memcpy(priv->enetaddr, env_enetaddr, 6);
> +       } else if (is_valid_ether_addr(priv->enetaddr)) {
> +               eth_setenv_enetaddr_by_index(base_name, eth_number,
> +                                            priv->enetaddr);
> +               printf("\nWarning: %s using MAC address from net device\n",
> +                      dev->name);
> +       } else if (is_zero_ether_addr(priv->enetaddr)) {
> +               printf("\nError: %s address not set.\n",
> +                      dev->name);
> +               return -EINVAL;
> +       }
> +
> +       const struct eth_ops *ops = dev->driver->ops;
> +       if (ops->write_hwaddr && !eth_mac_skip(eth_number)) {
> +               if (!is_valid_ether_addr(priv->enetaddr)) {
> +                       printf("\nError: %s address %pM illegal value\n",
> +                              dev->name, priv->enetaddr);
> +                       return -EINVAL;
> +               }
> +
> +               ret = ops->write_hwaddr(dev);
> +               if (ret)
> +                       printf("\nWarning: %s failed to set MAC address\n",
> +                              dev->name);
> +       }
> +
> +       return ret;
> +}
> +
> +static int eth_uclass_init(struct uclass *class)
> +{
> +       bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
> +
> +       struct eth_uclass_priv *priv = class->priv;
> +       priv->max_index = 0;

What is max_index used for?

> +
> +       eth_env_init();
> +
> +       return 0;
> +}
> +
> +static int eth_post_bind(struct udevice *dev)
> +{
> +       struct udevice *first;
> +
> +       uclass_first_device(UCLASS_ETH, &first);
> +       if (first == dev) {
> +               eth_current_changed();
> +               eth_set_dev(dev);
> +       }
> +
> +       struct eth_device_priv *priv = dev->uclass_priv;
> +       struct eth_uclass_priv *uclass_priv = dev->uclass->priv;
> +       if (priv) {
> +               priv->state = ETH_STATE_INIT;
> +               priv->index = uclass_priv->max_index++;

OK I see it is the number of devices. Does this ever decrease?

Anyway, struct udevice has a seq member which can give every device a
unique sequence number in the uclass automatically (and if you define
DM_UC_FLAG_SEQ_ALIAS then the device tree aliases can provide this
numbering)

Otherwise I'm not sure what this function is trying to do.

> +       }
> +
> +       return 0;
> +}
> +
> +static int eth_pre_unbind(struct udevice *dev)
> +{
> +       struct udevice *first;
> +       struct udevice *current;
> +
> +       current = eth_get_dev();
> +       uclass_first_device(UCLASS_ETH, &first);
> +       if (current == dev) {
> +               if (dev == first)
> +                       uclass_next_device(&current);
> +               else
> +                       current = first;
> +               eth_current_changed();
> +               eth_set_dev(current);
> +       }

I'm not sure what this function is trying to do.

> +
> +       return 0;
> +}
> +
> +static int eth_post_probe(struct udevice *dev)
> +{
> +       char *ethprime = getenv("ethprime");
> +       if (ethprime && strcmp(dev->name, ethprime) == 0)
> +               eth_set_dev(dev);

What does this do?

> +
> +       if (strchr(dev->name, ' '))
> +               printf("\nWarning: eth device name \"%s\" has a space!\n",
> +                      dev->name);

BTW if this is an error you could refuse to bind it - e.g. in the
eth_post_bind, return -EINVAL

> +
> +       struct eth_device_priv *priv = dev->uclass_priv;
> +       if (priv)
> +               return eth_write_hwaddr(dev, "eth", priv->index);
> +       return 1;
> +}
> +
> +UCLASS_DRIVER(eth) = {
> +       .name           = "eth",
> +       .id             = UCLASS_ETH,
> +       .post_bind      = eth_post_bind,
> +       .pre_unbind     = eth_pre_unbind,
> +       .post_probe     = eth_post_probe,
> +       .init           = eth_uclass_init,
> +       .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
> +       .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
> +};
> +#endif
> +
> +#ifndef CONFIG_DM_ETH
>  /*
>   * CPU and board-specific Ethernet initializations.  Aliased function
>   * signals caller to move on
> @@ -423,6 +738,7 @@ int eth_rx(void)
>
>         return eth_current->recv(eth_current);
>  }
> +#endif /* ifndef CONFIG_DM_ETH */
>
>  #ifdef CONFIG_API
>  static void eth_save_packet(void *packet, int length)
> @@ -486,7 +802,7 @@ static void eth_current_changed(void)
>
>  void eth_try_another(int first_restart)
>  {
> -       static struct eth_device *first_failed;
> +       static void *first_failed;
>         char *ethrotate;
>
>         /*
> @@ -515,7 +831,7 @@ void eth_set_current(void)
>  {
>         static char *act;
>         static int  env_changed_id;
> -       struct eth_device *old_current;
> +       void *old_current;
>         int     env_id;
>
>         if (!eth_get_dev())     /* XXX no current */
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 6/7] net: Add network support to sandbox
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 6/7] net: Add network support to sandbox Joe Hershberger
@ 2015-01-28  2:34   ` Simon Glass
  2015-01-28 10:24     ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-01-28  2:34 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 27 January 2015 at 16:27, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Add basic network support to sandbox which includes a network driver.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> ---
>
>  arch/sandbox/dts/sandbox.dts |  4 ++
>  drivers/net/Makefile         |  2 +
>  drivers/net/sandbox.c        | 91 ++++++++++++++++++++++++++++++++++++++++++++
>  include/configs/sandbox.h    | 14 ++++---
>  4 files changed, 106 insertions(+), 5 deletions(-)
>  create mode 100644 drivers/net/sandbox.c
>
> diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
> index 11748ae..a1d3199 100644
> --- a/arch/sandbox/dts/sandbox.dts
> +++ b/arch/sandbox/dts/sandbox.dts
> @@ -174,4 +174,8 @@
>                 };
>         };
>
> +       eth at 10002000 {
> +               compatible = "sandbox,eth";
> +               reg = <0x10002000 0x1000>;
> +       };
>  };
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 46c4ac6..2659a8a 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -50,6 +50,8 @@ obj-$(CONFIG_NS8382X) += ns8382x.o
>  obj-$(CONFIG_PCNET) += pcnet.o
>  obj-$(CONFIG_RTL8139) += rtl8139.o
>  obj-$(CONFIG_RTL8169) += rtl8169.o
> +obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
> +obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o
>  obj-$(CONFIG_SH_ETHER) += sh_eth.o
>  obj-$(CONFIG_SMC91111) += smc91111.o
>  obj-$(CONFIG_SMC911X) += smc911x.o
> diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
> new file mode 100644
> index 0000000..e1ee69b
> --- /dev/null
> +++ b/drivers/net/sandbox.c
> @@ -0,0 +1,91 @@
> +/*
> + * Copyright (c) 2015 National Instruments
> + *
> + * (C) Copyright 2015
> + * Joe Hershberger <joe.hershberger@ni.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <fdtdec.h>
> +#include <malloc.h>
> +#include <net.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct eth_sandbox_priv {
> +       void *device;
> +       int sd;

I'm not sure what these are for.

> +};
> +
> +int sb_eth_init(struct udevice *dev, bd_t *bis)
> +{
> +       printf("eth_sandbox: Init\n");

debug()?

> +
> +       return 0;
> +}
> +
> +int sb_eth_send(struct udevice *dev, void *packet, int length)
> +{
> +       printf("eth_sandbox: Send packet %d\n", length);
> +
> +       return 0;
> +#endif
> +}
> +
> +int sb_eth_recv(struct udevice *dev)
> +{
> +       return 0;
> +}
> +
> +void sb_eth_halt(struct udevice *dev)
> +{
> +       printf("eth_sandbox: Halt\n");
> +}
> +
> +int sb_eth_write_hwaddr(struct udevice *dev)
> +{
> +       printf("eth_sandbox: Write HW ADDR\n");
> +       return 0;
> +}
> +
> +static const struct eth_ops eth_sandbox_ops = {
> +       .init                   = sb_eth_init,
> +       .send                   = sb_eth_send,
> +       .recv                   = sb_eth_recv,
> +       .halt                   = sb_eth_halt,
> +       .write_hwaddr           = sb_eth_write_hwaddr,
> +};
> +
> +static int eth_sandbox_remove(struct udevice *dev)
> +{
> +       return 0;
> +}
> +
> +#ifdef CONFIG_OF_CONTROL
> +static int sandbox_eth_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct eth_pdata *pdata = dev->platdata;
> +
> +       pdata->iobase = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
> +       return 0;
> +}
> +
> +static const struct udevice_id sandbox_eth_ids[] = {
> +       { .compatible = "sandbox,eth" },
> +       { }
> +};
> +#endif
> +
> +U_BOOT_DRIVER(eth_sandbox) = {
> +       .name   = "eth_sandbox",
> +       .id     = UCLASS_ETH,
> +       .of_match = of_match_ptr(sandbox_eth_ids),
> +       .ofdata_to_platdata = of_match_ptr(sandbox_eth_ofdata_to_platdata),
> +       .remove = eth_sandbox_remove,
> +       .ops    = &eth_sandbox_ops,
> +       .priv_auto_alloc_size = sizeof(struct eth_sandbox_priv),
> +       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
> +};
> diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
> index 657f751..67bfc52 100644
> --- a/include/configs/sandbox.h
> +++ b/include/configs/sandbox.h
> @@ -143,9 +143,9 @@
>  /* include default commands */
>  #include <config_cmd_default.h>
>
> -/* We don't have networking support yet */
> -#undef CONFIG_CMD_NET
> -#undef CONFIG_CMD_NFS
> +#define CONFIG_DM_ETH
> +#define CONFIG_ETH_SANDBOX
> +#define CONFIG_CMD_PING
>
>  #define CONFIG_CMD_HASH
>  #define CONFIG_HASH_VERIFY
> @@ -188,12 +188,16 @@
>
>  #define CONFIG_EXTRA_ENV_SETTINGS      "stdin=serial,cros-ec-keyb\0" \
>                                         "stdout=serial,lcd\0" \
> -                                       "stderr=serial,lcd\0"
> +                                       "stderr=serial,lcd\0" \
> +                                       "ethaddr=00:00:11:22:33:44\0" \
> +                                       "ipaddr=1.2.3.4\0"
>  #else
>
>  #define CONFIG_EXTRA_ENV_SETTINGS      "stdin=serial\0" \
>                                         "stdout=serial,lcd\0" \
> -                                       "stderr=serial,lcd\0"
> +                                       "stderr=serial,lcd\0" \
> +                                       "ethaddr=00:00:11:22:33:44\0" \
> +                                       "ipaddr=1.2.3.4\0"
>  #endif
>
>  #define CONFIG_GZIP_COMPRESSED
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 7/7] net: Add ARP and PING response to sandbox driver
  2015-01-27 23:27 ` [U-Boot] [RFC PATCH 7/7] net: Add ARP and PING response to sandbox driver Joe Hershberger
@ 2015-01-28  2:34   ` Simon Glass
       [not found]     ` <CANr=Z=YcT=OvcA8ggaMCrOfyS5ShjFzgK6AW9gpfsNsZqcgfPA@mail.gmail.com>
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-01-28  2:34 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 27 January 2015 at 16:27, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The sandbox driver will now generate response traffic to exercise the
> ping command even when no network exists.  This allows the basic data
> pathways of the DM to be tested.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> ---

Looks like this can support ping. Very nice.

>
>  drivers/net/sandbox.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 75 insertions(+)
>
> diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
> index e1ee69b..49413f2 100644
> --- a/drivers/net/sandbox.c
> +++ b/drivers/net/sandbox.c
> @@ -20,6 +20,11 @@ struct eth_sandbox_priv {
>         int sd;
>  };
>
> +static uchar fake_host_hwaddr[ARP_HLEN] = {0x00, 0x00, 0x66, 0x44, 0x22, 0x00};
> +static IPaddr_t fake_host_ipaddr;
> +static uchar recv_packet_buffer[PKTSIZE];
> +static int recv_packet_length;

This could go in the driver's priv area (then we could support
multiple sandbox devices).

> +
>  int sb_eth_init(struct udevice *dev, bd_t *bis)
>  {
>         printf("eth_sandbox: Init\n");
> @@ -31,12 +36,82 @@ int sb_eth_send(struct udevice *dev, void *packet, int length)
>  {
>         printf("eth_sandbox: Send packet %d\n", length);
>
> +       struct ethernet_hdr *eth = packet;
> +       if (ntohs(eth->et_protlen) == PROT_ARP) {
> +               struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
> +               if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
> +                       /* store this as the assumed IP of the fake host */
> +                       fake_host_ipaddr = NetReadIP(&arp->ar_tpa);
> +                       /* Formulate a fake response */
> +                       struct ethernet_hdr *eth_recv =
> +                               (void *)recv_packet_buffer;
> +                       memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
> +                       memcpy(eth_recv->et_src, fake_host_hwaddr, ARP_HLEN);
> +                       eth_recv->et_protlen = htons(PROT_ARP);
> +
> +                       struct arp_hdr *arp_recv = (void *)recv_packet_buffer +
> +                               ETHER_HDR_SIZE;
> +                       arp_recv->ar_hrd = htons(ARP_ETHER);
> +                       arp_recv->ar_pro = htons(PROT_IP);
> +                       arp_recv->ar_hln = ARP_HLEN;
> +                       arp_recv->ar_pln = ARP_PLEN;
> +                       arp_recv->ar_op = htons(ARPOP_REPLY);
> +                       memcpy(&arp_recv->ar_sha, fake_host_hwaddr, ARP_HLEN);
> +                       NetWriteIP(&arp_recv->ar_spa, fake_host_ipaddr);
> +                       memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN);
> +                       NetCopyIP(&arp_recv->ar_tpa, &arp->ar_spa);
> +
> +                       recv_packet_length = ETHER_HDR_SIZE + ARP_HDR_SIZE;
> +               }
> +       } else if (ntohs(eth->et_protlen) == PROT_IP) {
> +               struct ip_udp_hdr *ip = packet + ETHER_HDR_SIZE;
> +               if (ip->ip_p == IPPROTO_ICMP) {
> +                       struct icmp_hdr *icmp = (struct icmp_hdr *)&ip->udp_src;
> +                       if (icmp->type == ICMP_ECHO_REQUEST) {
> +                               /* reply to the ping */
> +                               memcpy(recv_packet_buffer, packet, length);
> +                               struct ethernet_hdr *eth_recv =
> +                                       (void *)recv_packet_buffer;
> +                               struct ip_udp_hdr *ipr =
> +                                       (void *)recv_packet_buffer +
> +                                       ETHER_HDR_SIZE;
> +                               struct icmp_hdr *icmpr =
> +                                       (struct icmp_hdr *)&ipr->udp_src;
> +                               memcpy(eth_recv->et_dest, eth->et_src,
> +                                      ARP_HLEN);
> +                               memcpy(eth_recv->et_src, fake_host_hwaddr,
> +                                      ARP_HLEN);
> +                               ipr->ip_sum = 0;
> +                               ipr->ip_off = 0;
> +                               NetCopyIP((void *)&ipr->ip_dst, &ip->ip_src);
> +                               NetWriteIP((void *)&ipr->ip_src,
> +                                          fake_host_ipaddr);
> +                               ipr->ip_sum = ~NetCksum((uchar *)ipr,
> +                                       IP_HDR_SIZE >> 1);
> +
> +                               icmpr->type = ICMP_ECHO_REPLY;
> +                               icmpr->checksum = 0;
> +                               icmpr->checksum = ~NetCksum((uchar *)icmpr,
> +                                       (length - ETHER_HDR_SIZE -
> +                                               IP_HDR_SIZE) >> 1);
> +
> +                               recv_packet_length = length;
> +                       }
> +               }
> +       }
> +
>         return 0;
>  #endif
>  }
>
>  int sb_eth_recv(struct udevice *dev)
>  {
> +       if (recv_packet_length) {
> +               int lcl_recv_packet_length = recv_packet_length;
> +               printf("eth_sandbox: received packet %d\n", recv_packet_length);
> +               recv_packet_length = 0;
> +               NetReceive((void *)recv_packet_buffer, lcl_recv_packet_length);
> +       }
>         return 0;
>  }
>

Looks good.

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 1/7] net: Provide a function to get the current MAC address
  2015-01-28  2:33   ` Simon Glass
@ 2015-01-28  9:45     ` Joe Hershberger
  2015-01-29  1:46       ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-01-28  9:45 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 27, 2015 at 8:33 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 27 January 2015 at 16:27, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > The current implementation exposes the eth_device struct to code that
> > needs to access the MAC address.  Add a wrapper function for this to
> > abstract away the pointer for this operation.
> >
> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> > ---
> >
> >  arch/mips/cpu/mips32/au1x00/au1x00_eth.c | 2 +-
> >  arch/powerpc/cpu/mpc8260/ether_fcc.c     | 2 +-
> >  arch/powerpc/cpu/mpc85xx/ether_fcc.c     | 2 +-
> >  arch/powerpc/cpu/mpc8xx/scc.c            | 2 +-
> >  include/net.h                            | 8 ++++++++
> >  net/net.c                                | 2 +-
> >  6 files changed, 13 insertions(+), 5 deletions(-)
> >
> > diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
b/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
> > index 4770f56..535d713 100644
> > --- a/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
> > +++ b/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
> > @@ -238,7 +238,7 @@ static int au1x00_init(struct eth_device* dev, bd_t
* bd){
> >         }
> >
> >         /* Put mac addr in little endian */
> > -#define ea eth_get_dev()->enetaddr
> > +#define ea eth_get_ethaddr()
> >         *mac_addr_high  =       (ea[5] <<  8) | (ea[4]      ) ;
> >         *mac_addr_low   =       (ea[3] << 24) | (ea[2] << 16) |
>
> I know this is existing code, but (perhaps separately) it might be
> nice to remove the #define and assign it it to a local variable, i.e.:
>
> unsigned char *ea = eth_get_ethaddr();

I'm sure that if this code is not deleted before it is reworked that this
sort of improvement will be made.  For this series I just wanted to change
as little as possible.  I agree that the #define is ugly.

> >                 (ea[1] <<  8) | (ea[0]      ) ;
> > diff --git a/arch/powerpc/cpu/mpc8260/ether_fcc.c
b/arch/powerpc/cpu/mpc8260/ether_fcc.c
> > index f9f15b5..f777ba1 100644
> > --- a/arch/powerpc/cpu/mpc8260/ether_fcc.c
> > +++ b/arch/powerpc/cpu/mpc8260/ether_fcc.c
> > @@ -299,7 +299,7 @@ static int fec_init(struct eth_device* dev, bd_t
*bis)
> >       * it unique by setting a few bits in the upper byte of the
> >       * non-static part of the address.
> >       */
> > -#define ea eth_get_dev()->enetaddr
> > +#define ea eth_get_ethaddr()
> >      pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
> >      pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
> >      pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
> > diff --git a/arch/powerpc/cpu/mpc85xx/ether_fcc.c
b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
> > index 166dc9e..58d4bfb 100644
> > --- a/arch/powerpc/cpu/mpc85xx/ether_fcc.c
> > +++ b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
> > @@ -338,7 +338,7 @@ static int fec_init(struct eth_device* dev, bd_t
*bis)
> >       * it unique by setting a few bits in the upper byte of the
> >       * non-static part of the address.
> >       */
> > -#define ea eth_get_dev()->enetaddr
> > +#define ea eth_get_ethaddr()
> >      pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
> >      pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
> >      pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
> > diff --git a/arch/powerpc/cpu/mpc8xx/scc.c
b/arch/powerpc/cpu/mpc8xx/scc.c
> > index 251966b..66e4014 100644
> > --- a/arch/powerpc/cpu/mpc8xx/scc.c
> > +++ b/arch/powerpc/cpu/mpc8xx/scc.c
> > @@ -339,7 +339,7 @@ static int scc_init (struct eth_device *dev, bd_t *
bis)
> >         pram_ptr->sen_gaddr3 = 0x0;     /* Group Address Filter 3
(unused) */
> >         pram_ptr->sen_gaddr4 = 0x0;     /* Group Address Filter 4
(unused) */
> >
> > -#define ea eth_get_dev()->enetaddr
> > +#define ea eth_get_ethaddr()
> >         pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4];
> >         pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2];
> >         pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0];
> > diff --git a/include/net.h b/include/net.h
> > index 73ea88b..a9579ee 100644
> > --- a/include/net.h
> > +++ b/include/net.h
> > @@ -111,6 +111,14 @@ struct eth_device *eth_get_dev(void)
> >  {
> >         return eth_current;
> >  }
> > +
> > +static inline unsigned char *eth_get_ethaddr(void)
> > +{
> > +       if (eth_current)
> > +               return eth_current->enetaddr;
> > +       return NULL;
> > +}
> > +
> >  extern struct eth_device *eth_get_dev_by_name(const char *devname);
> >  extern struct eth_device *eth_get_dev_by_index(int index); /* get dev
@ index */
> >  extern int eth_get_dev_index(void);            /* get the device index
*/
> > diff --git a/net/net.c b/net/net.c
> > index 2bea07b..ddd630c 100644
> > --- a/net/net.c
> > +++ b/net/net.c
> > @@ -275,7 +275,7 @@ static void NetInitLoop(void)
> >                 env_changed_id = env_id;
> >         }
> >         if (eth_get_dev())
> > -               memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
> > +               memcpy(NetOurEther, eth_get_ethaddr(), 6);
> >
> >         return;
> >  }
> > --
> > 1.7.11.5
> >
>
> Regards,
> Simon
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 5/7] net: Add basic driver model support to Ethernet stack
  2015-01-28  2:34   ` Simon Glass
@ 2015-01-28 10:22     ` Joe Hershberger
  2015-01-29  1:56       ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-01-28 10:22 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 27, 2015 at 8:34 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 27 January 2015 at 16:27, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > First just add support for MAC drivers.
> >
>
> I don't fully understand this partly because my knowledge of the
> network stack is limited. So I'll make a few comments and we can go
> from there.

Sounds good.

> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> > ---
> >
> >  common/board_r.c       |   4 +-
> >  common/cmd_bdinfo.c    |   2 +
> >  include/dm/uclass-id.h |   1 +
> >  include/net.h          |  23 ++++
> >  net/eth.c              | 320
++++++++++++++++++++++++++++++++++++++++++++++++-
> >  5 files changed, 346 insertions(+), 4 deletions(-)
> >
> > diff --git a/common/board_r.c b/common/board_r.c
> > index a301cc2..9a41cae 100644
> > --- a/common/board_r.c
> > +++ b/common/board_r.c
> > @@ -572,7 +572,7 @@ static int initr_bbmii(void)
> >  }
> >  #endif
> >
> > -#ifdef CONFIG_CMD_NET
> > +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
> >  static int initr_net(void)
> >  {
> >         puts("Net:   ");
> > @@ -841,7 +841,7 @@ init_fnc_t init_sequence_r[] = {
> >  #ifdef CONFIG_BITBANGMII
> >         initr_bbmii,
> >  #endif
> > -#ifdef CONFIG_CMD_NET
> > +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
> >         INIT_FUNC_WATCHDOG_RESET
> >         initr_net,
> >  #endif
> > diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
> > index e6d8a7a..8688cf9 100644
> > --- a/common/cmd_bdinfo.c
> > +++ b/common/cmd_bdinfo.c
> > @@ -34,6 +34,7 @@ static void print_eth(int idx)
> >         printf("%-12s= %s\n", name, val);
> >  }
> >
> > +#ifndef CONFIG_DM_ETH
> >  __maybe_unused
> >  static void print_eths(void)
> >  {
> > @@ -52,6 +53,7 @@ static void print_eths(void)
> >         printf("current eth = %s\n", eth_get_name());
> >         printf("ip_addr     = %s\n", getenv("ipaddr"));
> >  }
> > +#endif
> >
> >  __maybe_unused
> >  static void print_lnum(const char *name, unsigned long long value)
> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> > index f17c3c2..b04cbc9 100644
> > --- a/include/dm/uclass-id.h
> > +++ b/include/dm/uclass-id.h
> > @@ -33,6 +33,7 @@ enum uclass_id {
> >         UCLASS_I2C,             /* I2C bus */
> >         UCLASS_I2C_GENERIC,     /* Generic I2C device */
> >         UCLASS_I2C_EEPROM,      /* I2C EEPROM device */
> > +       UCLASS_ETH,             /* Network device */
>
> Ethernet device?

Sure.

> >
> >         UCLASS_COUNT,
> >         UCLASS_INVALID = -1,
> > diff --git a/include/net.h b/include/net.h
> > index 7eef9cc..25636e2 100644
> > --- a/include/net.h
> > +++ b/include/net.h
> > @@ -78,6 +78,29 @@ enum eth_state_t {
> >         ETH_STATE_ACTIVE
> >  };
> >
> > +#ifdef CONFIG_DM_ETH
> > +struct eth_pdata {
> > +       phys_addr_t iobase;
> > +};
> > +
> > +struct eth_ops {
> > +       int (*init)(struct udevice *dev, bd_t *bis);
> > +       int (*send)(struct udevice *dev, void *packet, int length);
> > +       int (*recv)(struct udevice *dev);
> > +       void (*halt)(struct udevice *dev);
> > +#ifdef CONFIG_MCAST_TFTP
> > +       int (*mcast)(struct udevice *dev, const u8 *enetaddr, u8 set);
> > +#endif
> > +       int (*write_hwaddr)(struct udevice *dev);
> > +};
> > +
> > +struct udevice *eth_get_dev(void); /* get the current device */
> > +unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
> > +int eth_init_state_only(bd_t *bis); /* Set active state */
> > +void eth_halt_state_only(void); /* Set passive state */
> > +#endif
> > +
> > +#ifndef CONFIG_DM_ETH
> >  struct eth_device {
> >         char name[16];
> >         unsigned char enetaddr[6];
> > diff --git a/net/eth.c b/net/eth.c
> > index c02548c..d245b65 100644
> > --- a/net/eth.c
> > +++ b/net/eth.c
> > @@ -72,6 +72,321 @@ static int eth_mac_skip(int index)
> >         return ((skip_state = getenv(enetvar)) != NULL);
> >  }
> >
> > +static void eth_current_changed(void);
> > +
> > +#ifdef CONFIG_DM_ETH
> > +#include <dm.h>
> > +
> > +struct eth_device_priv {
> > +       unsigned char enetaddr[6];
> > +       int state;
> > +       int index;
> > +       void *priv;
>
> Suggestion: you could have per-child platform data as well as
> per-child private data. See u-boot-dm/master for this. It is used for
> I2C and SPI to hold the address of the child on the bus.
>
> You could use it to hold the MAC address. I think this *might* be
> better because the MAC address can then be set and retained even when
> the device is probed/removed.

So in net.h you'll see that I have a platdata structure as well... the
reason I didn't put the MAC address in there is that the data is not
sourced from the device tree or the platform data in general.  It either
comes from the env (default) or it is read from the network MAC's eeprom.
I'll need a little more convincing that the MAC should move.

> > +};
> > +
> > +struct eth_uclass_priv {
> > +       struct udevice *current;
> > +       int max_index;
> > +};
> > +
> > +static void eth_set_current_to_next(void)
> > +{
> > +       struct uclass *uc;
> > +       struct eth_uclass_priv *priv;
> > +
> > +       uclass_get(UCLASS_ETH, &uc);
> > +       priv = uc->priv;
> > +       uclass_next_device(&(priv->current));
>
> Note that this will probe the device. I think you are storing the
> current ethernet device in the uclass, but you could just as well have
> a static variable in this file if that is easier.

I started out using a static variable for the current device, but other
code in u-boot uses the current device (via the eth_get_dev() function) and
I want it to not require and extern to a non-static variable.

> (Also remove internal brackets)

Yes... forgot to clean this up.

> If priv->current is NULL, this will die.

This function should not get called if priv->current is NULL.

> Also to avoid confusion I think you should use uc_priv for the uclass
> priv local variable, to distinguish it from priv.

OK.

> > +       if (!priv->current)
> > +               uclass_first_device(UCLASS_ETH, &(priv->current));
>
> If I understand this correctly, I think you want:
>
> if (priv->current)
>     uclass_next_device(&priv->current)
> else
>    uclass_first_device(uc, &priv->current)

No... I'm not switching on priv->current being NULL... I get the next, and
then if THAT is NULL, I start at the beginning.  priv->current must never
be NULL (outside of this transition).

This is emulating the behavior that used to exist where the linked list
instead of terminating linked back to the head.  This way we always cycle
through all adapters and never stop.

> > +}
> > +
> > +struct udevice *eth_get_dev(void)
> > +{
> > +       struct uclass *uc;
> > +       uclass_get(UCLASS_ETH, &uc);
> > +
> > +       struct eth_uclass_priv *priv = uc->priv;
>
> This is OK so long as the device has been probed. I think it always is
> because you use uclass_next_device() to get the device.

Why would the device being probed have any relationship with the priv in
the uclass itself?  I would expect the uclass priv to be there regardless.
This is not the per-device uc_priv.

> > +       return priv->current;
> > +}
> > +
> > +static void eth_set_dev(struct udevice *dev)
> > +{
> > +       struct uclass *uc;
> > +       uclass_get(UCLASS_ETH, &uc);
> > +
> > +       struct eth_uclass_priv *priv = uc->priv;
> > +       priv->current = dev;
> > +}
> > +
> > +unsigned char *eth_get_ethaddr(void)
> > +{
> > +       struct eth_device_priv *priv;
> > +       if (eth_get_dev()) {
> > +               priv = eth_get_dev()->uclass_priv;
> > +               if (priv)
>
> This check should be unnecessary. Same in other cases below.

So this is guaranteed?  In all cases?  I ran into some pre-allocated
buffers that don't get created if post_probe returns an error, for instance.

> > +                       return priv->enetaddr;
> > +       }
> > +       return NULL;
> > +}
> > +
> > +/* Set active state */
> > +int eth_init_state_only(bd_t *bis)
> > +{
> > +       struct eth_device_priv *priv;
> > +       if (eth_get_dev()) {
> > +               priv = eth_get_dev()->uclass_priv;
> > +               if (priv)
> > +                       priv->state = ETH_STATE_ACTIVE;
> > +       }
> > +
> > +       return 0;
> > +}
> > +/* Set passive state */
> > +void eth_halt_state_only(void)
> > +{
> > +       struct eth_device_priv *priv;
> > +       if (eth_get_dev()) {
> > +               priv = eth_get_dev()->uclass_priv;
> > +               if (priv)
> > +                       priv->state = ETH_STATE_PASSIVE;
> > +       }
> > +}
> > +
> > +int eth_get_dev_index(void)
> > +{
> > +       struct eth_device_priv *priv;
> > +       if (eth_get_dev()) {
> > +               priv = eth_get_dev()->uclass_priv;
> > +               if (priv)
> > +                       return priv->index;
> > +       }
> > +       return -1;
> > +}
> > +
> > +int eth_init(bd_t *bis)
> > +{
> > +       struct udevice *current, *old_current, *dev;
> > +       struct uclass *uc;
> > +
> > +       current = eth_get_dev();
> > +       if (!current) {
> > +               puts("No ethernet found.\n");
> > +               return -1;
> > +       }
> > +
> > +       /* Sync environment with network devices */
> > +       uclass_get(UCLASS_ETH, &uc);
> > +       uclass_foreach_dev(dev, uc) {
> > +               uchar env_enetaddr[6];
> > +
> > +               if (eth_getenv_enetaddr_by_index("eth", dev->seq,
> > +                                                env_enetaddr)) {
> > +                       struct eth_device_priv *priv = dev->uclass_priv;
> > +                       if (priv)
> > +                               memcpy(priv->enetaddr, env_enetaddr, 6);
> > +               }
> > +       };
> > +
> > +       old_current = current;
> > +       do {
> > +               debug("Trying %s\n", current->name);
> > +
> > +               if (current->driver) {
> > +                       const struct eth_ops *ops =
current->driver->ops;
> > +                       if (ops->init(current, bis) >= 0) {
> > +                               struct eth_device_priv *priv =
> > +                                       current->uclass_priv;
> > +                               if (priv)
> > +                                       priv->state = ETH_STATE_ACTIVE;
> > +
> > +                               return 0;
> > +                       }
> > +               }
> > +               debug("FAIL\n");
> > +
> > +               eth_try_another(0);
> > +               current = eth_get_dev();
> > +       } while (old_current != current);
> > +
> > +       return -1;
>
> -ENODEV?

OK.

> > +}
> > +
> > +void eth_halt(void)
> > +{
> > +       struct udevice *current;
> > +
> > +       current = eth_get_dev();
> > +       if (!current)
> > +               return;
> > +       if (!current->driver)
> > +               return;
> > +
> > +       const struct eth_ops *ops = current->driver->ops;
> > +       ops->halt(current);
> > +
> > +       struct eth_device_priv *priv = current->uclass_priv;
> > +       if (priv)
> > +               priv->state = ETH_STATE_PASSIVE;
> > +}
> > +
> > +int eth_send(void *packet, int length)
> > +{
> > +       struct udevice *current;
> > +
> > +       current = eth_get_dev();
> > +       if (!current)
> > +               return -1;
> > +       if (!current->driver)
> > +               return -1;
> > +
> > +       const struct eth_ops *ops = current->driver->ops;
> > +       return ops->send(current, packet, length);
> > +}
> > +
>
> As a general comment, there is an implicit assumption that only one
> device can be active at a time. I suppose that is a U-Boot limitation,
> but we don't need to keep it for driver model, or at least we could
> permit multiple devices to be probed at a time.

I agree that longer term we should look for ways to remove that limitation,
but for now everything that uses the network assumes that the "ethact" env
var selects the device.  There would be a lot of commands to break
compatibility with to allow them to specify the device.  I say we hold off
on that for now.

> But still I wonder if you should have functions that are passed a
> udevice, like eth_rx(struct udevice *dev).

Even if those functions did, the commands would need to change too.  Future
enhancement, I think.

> > +int eth_rx(void)
> > +{
> > +       struct udevice *current;
> > +
> > +       current = eth_get_dev();
> > +       if (!current)
> > +               return -1;
> > +       if (!current->driver)
> > +               return -1;
> > +
> > +       const struct eth_ops *ops = current->driver->ops;
> > +       return ops->recv(current);
> > +}
> > +
> > +static int eth_write_hwaddr(struct udevice *dev, const char *base_name,
> > +                  int eth_number)
> > +{
> > +       unsigned char env_enetaddr[6];
> > +       int ret = 0;
> > +
> > +       eth_getenv_enetaddr_by_index(base_name, eth_number,
env_enetaddr);
> > +
> > +       struct eth_device_priv *priv = dev->uclass_priv;
> > +       if (!is_zero_ether_addr(env_enetaddr)) {
> > +               if (!is_zero_ether_addr(priv->enetaddr) &&
> > +                   memcmp(priv->enetaddr, env_enetaddr, 6)) {
> > +                       printf("\nWarning: %s MAC addresses don't
match:\n",
> > +                              dev->name);
> > +                       printf("Address in SROM is         %pM\n",
> > +                              priv->enetaddr);
> > +                       printf("Address in environment is  %pM\n",
> > +                              env_enetaddr);
> > +               }
> > +
> > +               memcpy(priv->enetaddr, env_enetaddr, 6);
> > +       } else if (is_valid_ether_addr(priv->enetaddr)) {
> > +               eth_setenv_enetaddr_by_index(base_name, eth_number,
> > +                                            priv->enetaddr);
> > +               printf("\nWarning: %s using MAC address from net
device\n",
> > +                      dev->name);
> > +       } else if (is_zero_ether_addr(priv->enetaddr)) {
> > +               printf("\nError: %s address not set.\n",
> > +                      dev->name);
> > +               return -EINVAL;
> > +       }
> > +
> > +       const struct eth_ops *ops = dev->driver->ops;
> > +       if (ops->write_hwaddr && !eth_mac_skip(eth_number)) {
> > +               if (!is_valid_ether_addr(priv->enetaddr)) {
> > +                       printf("\nError: %s address %pM illegal
value\n",
> > +                              dev->name, priv->enetaddr);
> > +                       return -EINVAL;
> > +               }
> > +
> > +               ret = ops->write_hwaddr(dev);
> > +               if (ret)
> > +                       printf("\nWarning: %s failed to set MAC
address\n",
> > +                              dev->name);
> > +       }
> > +
> > +       return ret;
> > +}
> > +
> > +static int eth_uclass_init(struct uclass *class)
> > +{
> > +       bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
> > +
> > +       struct eth_uclass_priv *priv = class->priv;
> > +       priv->max_index = 0;
>
> What is max_index used for?

For knowing the number of devices that have been bound and allocating the
next unused index for the next device.

> > +
> > +       eth_env_init();
> > +
> > +       return 0;
> > +}
> > +
> > +static int eth_post_bind(struct udevice *dev)
> > +{
> > +       struct udevice *first;
> > +
> > +       uclass_first_device(UCLASS_ETH, &first);
> > +       if (first == dev) {
> > +               eth_current_changed();
> > +               eth_set_dev(dev);
> > +       }
> > +
> > +       struct eth_device_priv *priv = dev->uclass_priv;
> > +       struct eth_uclass_priv *uclass_priv = dev->uclass->priv;
> > +       if (priv) {
> > +               priv->state = ETH_STATE_INIT;
> > +               priv->index = uclass_priv->max_index++;
>
> OK I see it is the number of devices. Does this ever decrease?

Never decreases.

> Anyway, struct udevice has a seq member which can give every device a
> unique sequence number in the uclass automatically (and if you define
> DM_UC_FLAG_SEQ_ALIAS then the device tree aliases can provide this
> numbering)

I actually used the seq number originally and that worked fine with
platdata.  When I moved to the device tree, that's where it fell apart.  In
the device tree, it is expected that the eth name will include an
eth at baseaddr format.  The DM code then takes that value that is the
baseaddr and sets it as the requested seq.  That means I get eth268443648
instead of eth0.  No good.  So now I keep track of my own seq (index) to
make sure I get consistent device names.

> Otherwise I'm not sure what this function is trying to do.

I needs to initialize the priv->current variable so that everything that
tries to use the network finds a current eth device.
It also initializes the state variable, which is also important.

> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static int eth_pre_unbind(struct udevice *dev)
> > +{
> > +       struct udevice *first;
> > +       struct udevice *current;
> > +
> > +       current = eth_get_dev();
> > +       uclass_first_device(UCLASS_ETH, &first);
> > +       if (current == dev) {
> > +               if (dev == first)
> > +                       uclass_next_device(&current);
> > +               else
> > +                       current = first;
> > +               eth_current_changed();
> > +               eth_set_dev(current);
> > +       }
>
> I'm not sure what this function is trying to do.

Again, this is just ensuring the "current" variable is always valid.

> > +
> > +       return 0;
> > +}
> > +
> > +static int eth_post_probe(struct udevice *dev)
> > +{
> > +       char *ethprime = getenv("ethprime");
> > +       if (ethprime && strcmp(dev->name, ethprime) == 0)
> > +               eth_set_dev(dev);
>
> What does this do?

This allows the initial "current" device to be specified by they "ethprime"
env var.  This is preserving existing behaviors as controlled by these env
vars.

> > +
> > +       if (strchr(dev->name, ' '))
> > +               printf("\nWarning: eth device name \"%s\" has a
space!\n",
> > +                      dev->name);
>
> BTW if this is an error you could refuse to bind it - e.g. in the
> eth_post_bind, return -EINVAL

Good idea.

> > +
> > +       struct eth_device_priv *priv = dev->uclass_priv;
> > +       if (priv)
> > +               return eth_write_hwaddr(dev, "eth", priv->index);
> > +       return 1;
> > +}
> > +
> > +UCLASS_DRIVER(eth) = {
> > +       .name           = "eth",
> > +       .id             = UCLASS_ETH,
> > +       .post_bind      = eth_post_bind,
> > +       .pre_unbind     = eth_pre_unbind,
> > +       .post_probe     = eth_post_probe,
> > +       .init           = eth_uclass_init,
> > +       .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
> > +       .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
> > +};
> > +#endif
> > +
> > +#ifndef CONFIG_DM_ETH
> >  /*
> >   * CPU and board-specific Ethernet initializations.  Aliased function
> >   * signals caller to move on
> > @@ -423,6 +738,7 @@ int eth_rx(void)
> >
> >         return eth_current->recv(eth_current);
> >  }
> > +#endif /* ifndef CONFIG_DM_ETH */
> >
> >  #ifdef CONFIG_API
> >  static void eth_save_packet(void *packet, int length)
> > @@ -486,7 +802,7 @@ static void eth_current_changed(void)
> >
> >  void eth_try_another(int first_restart)
> >  {
> > -       static struct eth_device *first_failed;
> > +       static void *first_failed;
> >         char *ethrotate;
> >
> >         /*
> > @@ -515,7 +831,7 @@ void eth_set_current(void)
> >  {
> >         static char *act;
> >         static int  env_changed_id;
> > -       struct eth_device *old_current;
> > +       void *old_current;
> >         int     env_id;
> >
> >         if (!eth_get_dev())     /* XXX no current */
> > --
> > 1.7.11.5
> >
>
> Regards,
> Simon
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 6/7] net: Add network support to sandbox
  2015-01-28  2:34   ` Simon Glass
@ 2015-01-28 10:24     ` Joe Hershberger
  0 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-01-28 10:24 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 27, 2015 at 8:34 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 27 January 2015 at 16:27, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > Add basic network support to sandbox which includes a network driver.
> >
> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> > ---
> >
> >  arch/sandbox/dts/sandbox.dts |  4 ++
> >  drivers/net/Makefile         |  2 +
> >  drivers/net/sandbox.c        | 91
++++++++++++++++++++++++++++++++++++++++++++
> >  include/configs/sandbox.h    | 14 ++++---
> >  4 files changed, 106 insertions(+), 5 deletions(-)
> >  create mode 100644 drivers/net/sandbox.c
> >
> > diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
> > index 11748ae..a1d3199 100644
> > --- a/arch/sandbox/dts/sandbox.dts
> > +++ b/arch/sandbox/dts/sandbox.dts
> > @@ -174,4 +174,8 @@
> >                 };
> >         };
> >
> > +       eth at 10002000 {
> > +               compatible = "sandbox,eth";
> > +               reg = <0x10002000 0x1000>;
> > +       };
> >  };
> > diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> > index 46c4ac6..2659a8a 100644
> > --- a/drivers/net/Makefile
> > +++ b/drivers/net/Makefile
> > @@ -50,6 +50,8 @@ obj-$(CONFIG_NS8382X) += ns8382x.o
> >  obj-$(CONFIG_PCNET) += pcnet.o
> >  obj-$(CONFIG_RTL8139) += rtl8139.o
> >  obj-$(CONFIG_RTL8169) += rtl8169.o
> > +obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
> > +obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o
> >  obj-$(CONFIG_SH_ETHER) += sh_eth.o
> >  obj-$(CONFIG_SMC91111) += smc91111.o
> >  obj-$(CONFIG_SMC911X) += smc911x.o
> > diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
> > new file mode 100644
> > index 0000000..e1ee69b
> > --- /dev/null
> > +++ b/drivers/net/sandbox.c
> > @@ -0,0 +1,91 @@
> > +/*
> > + * Copyright (c) 2015 National Instruments
> > + *
> > + * (C) Copyright 2015
> > + * Joe Hershberger <joe.hershberger@ni.com>
> > + *
> > + * SPDX-License-Identifier:    GPL-2.0+
> > + */
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <fdtdec.h>
> > +#include <malloc.h>
> > +#include <net.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +struct eth_sandbox_priv {
> > +       void *device;
> > +       int sd;
>
> I'm not sure what these are for.

This is accidentally left over from an experiment.  I'd like to pursue it,
but I'm having trouble with the build env.  I'll probably post what I have
so for and maybe you have some ideas for how to make it compile without
making it into a .lib

> > +};
> > +
> > +int sb_eth_init(struct udevice *dev, bd_t *bis)
> > +{
> > +       printf("eth_sandbox: Init\n");
>
> debug()?

OK

> > +
> > +       return 0;
> > +}
> > +
> > +int sb_eth_send(struct udevice *dev, void *packet, int length)
> > +{
> > +       printf("eth_sandbox: Send packet %d\n", length);
> > +
> > +       return 0;
> > +#endif
> > +}
> > +
> > +int sb_eth_recv(struct udevice *dev)
> > +{
> > +       return 0;
> > +}
> > +
> > +void sb_eth_halt(struct udevice *dev)
> > +{
> > +       printf("eth_sandbox: Halt\n");
> > +}
> > +
> > +int sb_eth_write_hwaddr(struct udevice *dev)
> > +{
> > +       printf("eth_sandbox: Write HW ADDR\n");
> > +       return 0;
> > +}
> > +
> > +static const struct eth_ops eth_sandbox_ops = {
> > +       .init                   = sb_eth_init,
> > +       .send                   = sb_eth_send,
> > +       .recv                   = sb_eth_recv,
> > +       .halt                   = sb_eth_halt,
> > +       .write_hwaddr           = sb_eth_write_hwaddr,
> > +};
> > +
> > +static int eth_sandbox_remove(struct udevice *dev)
> > +{
> > +       return 0;
> > +}
> > +
> > +#ifdef CONFIG_OF_CONTROL
> > +static int sandbox_eth_ofdata_to_platdata(struct udevice *dev)
> > +{
> > +       struct eth_pdata *pdata = dev->platdata;
> > +
> > +       pdata->iobase = fdtdec_get_addr(gd->fdt_blob, dev->of_offset,
"reg");
> > +       return 0;
> > +}
> > +
> > +static const struct udevice_id sandbox_eth_ids[] = {
> > +       { .compatible = "sandbox,eth" },
> > +       { }
> > +};
> > +#endif
> > +
> > +U_BOOT_DRIVER(eth_sandbox) = {
> > +       .name   = "eth_sandbox",
> > +       .id     = UCLASS_ETH,
> > +       .of_match = of_match_ptr(sandbox_eth_ids),
> > +       .ofdata_to_platdata =
of_match_ptr(sandbox_eth_ofdata_to_platdata),
> > +       .remove = eth_sandbox_remove,
> > +       .ops    = &eth_sandbox_ops,
> > +       .priv_auto_alloc_size = sizeof(struct eth_sandbox_priv),
> > +       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
> > +};
> > diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
> > index 657f751..67bfc52 100644
> > --- a/include/configs/sandbox.h
> > +++ b/include/configs/sandbox.h
> > @@ -143,9 +143,9 @@
> >  /* include default commands */
> >  #include <config_cmd_default.h>
> >
> > -/* We don't have networking support yet */
> > -#undef CONFIG_CMD_NET
> > -#undef CONFIG_CMD_NFS
> > +#define CONFIG_DM_ETH
> > +#define CONFIG_ETH_SANDBOX
> > +#define CONFIG_CMD_PING
> >
> >  #define CONFIG_CMD_HASH
> >  #define CONFIG_HASH_VERIFY
> > @@ -188,12 +188,16 @@
> >
> >  #define CONFIG_EXTRA_ENV_SETTINGS      "stdin=serial,cros-ec-keyb\0" \
> >                                         "stdout=serial,lcd\0" \
> > -                                       "stderr=serial,lcd\0"
> > +                                       "stderr=serial,lcd\0" \
> > +                                       "ethaddr=00:00:11:22:33:44\0" \
> > +                                       "ipaddr=1.2.3.4\0"
> >  #else
> >
> >  #define CONFIG_EXTRA_ENV_SETTINGS      "stdin=serial\0" \
> >                                         "stdout=serial,lcd\0" \
> > -                                       "stderr=serial,lcd\0"
> > +                                       "stderr=serial,lcd\0" \
> > +                                       "ethaddr=00:00:11:22:33:44\0" \
> > +                                       "ipaddr=1.2.3.4\0"
> >  #endif
> >
> >  #define CONFIG_GZIP_COMPRESSED
> > --
> > 1.7.11.5
> >
>
> Regards,
> Simon
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 1/7] net: Provide a function to get the current MAC address
  2015-01-28  9:45     ` Joe Hershberger
@ 2015-01-29  1:46       ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-01-29  1:46 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 28 January 2015 at 02:45, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> On Tue, Jan 27, 2015 at 8:33 PM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 27 January 2015 at 16:27, Joe Hershberger <joe.hershberger@ni.com>
>> wrote:
>> > The current implementation exposes the eth_device struct to code that
>> > needs to access the MAC address.  Add a wrapper function for this to
>> > abstract away the pointer for this operation.
>> >
>> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>> > ---
>> >
>> >  arch/mips/cpu/mips32/au1x00/au1x00_eth.c | 2 +-
>> >  arch/powerpc/cpu/mpc8260/ether_fcc.c     | 2 +-
>> >  arch/powerpc/cpu/mpc85xx/ether_fcc.c     | 2 +-
>> >  arch/powerpc/cpu/mpc8xx/scc.c            | 2 +-
>> >  include/net.h                            | 8 ++++++++
>> >  net/net.c                                | 2 +-
>> >  6 files changed, 13 insertions(+), 5 deletions(-)
>> >
>> > diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
>> > b/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
>> > index 4770f56..535d713 100644
>> > --- a/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
>> > +++ b/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
>> > @@ -238,7 +238,7 @@ static int au1x00_init(struct eth_device* dev, bd_t
>> > * bd){
>> >         }
>> >
>> >         /* Put mac addr in little endian */
>> > -#define ea eth_get_dev()->enetaddr
>> > +#define ea eth_get_ethaddr()
>> >         *mac_addr_high  =       (ea[5] <<  8) | (ea[4]      ) ;
>> >         *mac_addr_low   =       (ea[3] << 24) | (ea[2] << 16) |
>>
>> I know this is existing code, but (perhaps separately) it might be
>> nice to remove the #define and assign it it to a local variable, i.e.:
>>
>> unsigned char *ea = eth_get_ethaddr();
>
> I'm sure that if this code is not deleted before it is reworked that this
> sort of improvement will be made.  For this series I just wanted to change
> as little as possible.  I agree that the #define is ugly.

OK sounds good.

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 5/7] net: Add basic driver model support to Ethernet stack
  2015-01-28 10:22     ` Joe Hershberger
@ 2015-01-29  1:56       ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-01-29  1:56 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 28 January 2015 at 03:22, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> On Tue, Jan 27, 2015 at 8:34 PM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 27 January 2015 at 16:27, Joe Hershberger <joe.hershberger@ni.com>
>> wrote:
>> > First just add support for MAC drivers.
>> >
>>
>> I don't fully understand this partly because my knowledge of the
>> network stack is limited. So I'll make a few comments and we can go
>> from there.
>
> Sounds good.
>
>> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>> > ---
>> >
>> >  common/board_r.c       |   4 +-
>> >  common/cmd_bdinfo.c    |   2 +
>> >  include/dm/uclass-id.h |   1 +
>> >  include/net.h          |  23 ++++
>> >  net/eth.c              | 320
>> > ++++++++++++++++++++++++++++++++++++++++++++++++-
>> >  5 files changed, 346 insertions(+), 4 deletions(-)
>> >
>> > diff --git a/common/board_r.c b/common/board_r.c
>> > index a301cc2..9a41cae 100644
>> > --- a/common/board_r.c
>> > +++ b/common/board_r.c
>> > @@ -572,7 +572,7 @@ static int initr_bbmii(void)
>> >  }
>> >  #endif
>> >
>> > -#ifdef CONFIG_CMD_NET
>> > +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
>> >  static int initr_net(void)
>> >  {
>> >         puts("Net:   ");
>> > @@ -841,7 +841,7 @@ init_fnc_t init_sequence_r[] = {
>> >  #ifdef CONFIG_BITBANGMII
>> >         initr_bbmii,
>> >  #endif
>> > -#ifdef CONFIG_CMD_NET
>> > +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
>> >         INIT_FUNC_WATCHDOG_RESET
>> >         initr_net,
>> >  #endif
>> > diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
>> > index e6d8a7a..8688cf9 100644
>> > --- a/common/cmd_bdinfo.c
>> > +++ b/common/cmd_bdinfo.c
>> > @@ -34,6 +34,7 @@ static void print_eth(int idx)
>> >         printf("%-12s= %s\n", name, val);
>> >  }
>> >
>> > +#ifndef CONFIG_DM_ETH
>> >  __maybe_unused
>> >  static void print_eths(void)
>> >  {
>> > @@ -52,6 +53,7 @@ static void print_eths(void)
>> >         printf("current eth = %s\n", eth_get_name());
>> >         printf("ip_addr     = %s\n", getenv("ipaddr"));
>> >  }
>> > +#endif
>> >
>> >  __maybe_unused
>> >  static void print_lnum(const char *name, unsigned long long value)
>> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
>> > index f17c3c2..b04cbc9 100644
>> > --- a/include/dm/uclass-id.h
>> > +++ b/include/dm/uclass-id.h
>> > @@ -33,6 +33,7 @@ enum uclass_id {
>> >         UCLASS_I2C,             /* I2C bus */
>> >         UCLASS_I2C_GENERIC,     /* Generic I2C device */
>> >         UCLASS_I2C_EEPROM,      /* I2C EEPROM device */
>> > +       UCLASS_ETH,             /* Network device */
>>
>> Ethernet device?
>
> Sure.
>
>> >
>> >         UCLASS_COUNT,
>> >         UCLASS_INVALID = -1,
>> > diff --git a/include/net.h b/include/net.h
>> > index 7eef9cc..25636e2 100644
>> > --- a/include/net.h
>> > +++ b/include/net.h
>> > @@ -78,6 +78,29 @@ enum eth_state_t {
>> >         ETH_STATE_ACTIVE
>> >  };
>> >
>> > +#ifdef CONFIG_DM_ETH
>> > +struct eth_pdata {
>> > +       phys_addr_t iobase;
>> > +};
>> > +
>> > +struct eth_ops {
>> > +       int (*init)(struct udevice *dev, bd_t *bis);
>> > +       int (*send)(struct udevice *dev, void *packet, int length);
>> > +       int (*recv)(struct udevice *dev);
>> > +       void (*halt)(struct udevice *dev);
>> > +#ifdef CONFIG_MCAST_TFTP
>> > +       int (*mcast)(struct udevice *dev, const u8 *enetaddr, u8 set);
>> > +#endif
>> > +       int (*write_hwaddr)(struct udevice *dev);
>> > +};
>> > +
>> > +struct udevice *eth_get_dev(void); /* get the current device */
>> > +unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
>> > +int eth_init_state_only(bd_t *bis); /* Set active state */
>> > +void eth_halt_state_only(void); /* Set passive state */
>> > +#endif
>> > +
>> > +#ifndef CONFIG_DM_ETH
>> >  struct eth_device {
>> >         char name[16];
>> >         unsigned char enetaddr[6];
>> > diff --git a/net/eth.c b/net/eth.c
>> > index c02548c..d245b65 100644
>> > --- a/net/eth.c
>> > +++ b/net/eth.c
>> > @@ -72,6 +72,321 @@ static int eth_mac_skip(int index)
>> >         return ((skip_state = getenv(enetvar)) != NULL);
>> >  }
>> >
>> > +static void eth_current_changed(void);
>> > +
>> > +#ifdef CONFIG_DM_ETH
>> > +#include <dm.h>
>> > +
>> > +struct eth_device_priv {
>> > +       unsigned char enetaddr[6];
>> > +       int state;
>> > +       int index;
>> > +       void *priv;
>>
>> Suggestion: you could have per-child platform data as well as
>> per-child private data. See u-boot-dm/master for this. It is used for
>> I2C and SPI to hold the address of the child on the bus.
>>
>> You could use it to hold the MAC address. I think this *might* be
>> better because the MAC address can then be set and retained even when
>> the device is probed/removed.
>
> So in net.h you'll see that I have a platdata structure as well... the
> reason I didn't put the MAC address in there is that the data is not sourced
> from the device tree or the platform data in general.  It either comes from
> the env (default) or it is read from the network MAC's eeprom.  I'll need a
> little more convincing that the MAC should move.

OK. If it only exists when the device is active (probed) then that is fine.

>
>> > +};
>> > +
>> > +struct eth_uclass_priv {
>> > +       struct udevice *current;
>> > +       int max_index;
>> > +};
>> > +
>> > +static void eth_set_current_to_next(void)
>> > +{
>> > +       struct uclass *uc;
>> > +       struct eth_uclass_priv *priv;
>> > +
>> > +       uclass_get(UCLASS_ETH, &uc);
>> > +       priv = uc->priv;
>> > +       uclass_next_device(&(priv->current));
>>
>> Note that this will probe the device. I think you are storing the
>> current ethernet device in the uclass, but you could just as well have
>> a static variable in this file if that is easier.
>
> I started out using a static variable for the current device, but other code
> in u-boot uses the current device (via the eth_get_dev() function) and I
> want it to not require and extern to a non-static variable.

OK.

>
>> (Also remove internal brackets)
>
> Yes... forgot to clean this up.
>
>> If priv->current is NULL, this will die.
>
> This function should not get called if priv->current is NULL.
>
>> Also to avoid confusion I think you should use uc_priv for the uclass
>> priv local variable, to distinguish it from priv.
>
> OK.
>
>> > +       if (!priv->current)
>> > +               uclass_first_device(UCLASS_ETH, &(priv->current));
>>
>> If I understand this correctly, I think you want:
>>
>> if (priv->current)
>>     uclass_next_device(&priv->current)
>> else
>>    uclass_first_device(uc, &priv->current)
>
> No... I'm not switching on priv->current being NULL... I get the next, and
> then if THAT is NULL, I start at the beginning.  priv->current must never be
> NULL (outside of this transition).
>
> This is emulating the behavior that used to exist where the linked list
> instead of terminating linked back to the head.  This way we always cycle
> through all adapters and never stop.

OK I see.

>
>> > +}
>> > +
>> > +struct udevice *eth_get_dev(void)
>> > +{
>> > +       struct uclass *uc;
>> > +       uclass_get(UCLASS_ETH, &uc);
>> > +
>> > +       struct eth_uclass_priv *priv = uc->priv;
>>
>> This is OK so long as the device has been probed. I think it always is
>> because you use uclass_next_device() to get the device.
>
> Why would the device being probed have any relationship with the priv in the
> uclass itself?  I would expect the uclass priv to be there regardless. This
> is not the per-device uc_priv.

Yes you are right, I was confused by the 'priv' name.

>
>> > +       return priv->current;
>> > +}
>> > +
>> > +static void eth_set_dev(struct udevice *dev)
>> > +{
>> > +       struct uclass *uc;
>> > +       uclass_get(UCLASS_ETH, &uc);
>> > +
>> > +       struct eth_uclass_priv *priv = uc->priv;
>> > +       priv->current = dev;
>> > +}
>> > +
>> > +unsigned char *eth_get_ethaddr(void)
>> > +{
>> > +       struct eth_device_priv *priv;
>> > +       if (eth_get_dev()) {
>> > +               priv = eth_get_dev()->uclass_priv;
>> > +               if (priv)
>>
>> This check should be unnecessary. Same in other cases below.
>
> So this is guaranteed?  In all cases?  I ran into some pre-allocated buffers
> that don't get created if post_probe returns an error, for instance.

If the device is probed then it has uclass_priv. If post_probe()
returns an error then the device will be removed (i.e. the probe will
fail).

>
>
>> > +                       return priv->enetaddr;
>> > +       }
>> > +       return NULL;
>> > +}
>> > +
>> > +/* Set active state */
>> > +int eth_init_state_only(bd_t *bis)
>> > +{
>> > +       struct eth_device_priv *priv;
>> > +       if (eth_get_dev()) {
>> > +               priv = eth_get_dev()->uclass_priv;
>> > +               if (priv)
>> > +                       priv->state = ETH_STATE_ACTIVE;
>> > +       }
>> > +
>> > +       return 0;
>> > +}
>> > +/* Set passive state */
>> > +void eth_halt_state_only(void)
>> > +{
>> > +       struct eth_device_priv *priv;
>> > +       if (eth_get_dev()) {
>> > +               priv = eth_get_dev()->uclass_priv;
>> > +               if (priv)
>> > +                       priv->state = ETH_STATE_PASSIVE;
>> > +       }
>> > +}
>> > +
>> > +int eth_get_dev_index(void)
>> > +{
>> > +       struct eth_device_priv *priv;
>> > +       if (eth_get_dev()) {
>> > +               priv = eth_get_dev()->uclass_priv;
>> > +               if (priv)
>> > +                       return priv->index;
>> > +       }
>> > +       return -1;
>> > +}
>> > +
>> > +int eth_init(bd_t *bis)
>> > +{
>> > +       struct udevice *current, *old_current, *dev;
>> > +       struct uclass *uc;
>> > +
>> > +       current = eth_get_dev();
>> > +       if (!current) {
>> > +               puts("No ethernet found.\n");
>> > +               return -1;
>> > +       }
>> > +
>> > +       /* Sync environment with network devices */
>> > +       uclass_get(UCLASS_ETH, &uc);
>> > +       uclass_foreach_dev(dev, uc) {
>> > +               uchar env_enetaddr[6];
>> > +
>> > +               if (eth_getenv_enetaddr_by_index("eth", dev->seq,
>> > +                                                env_enetaddr)) {
>> > +                       struct eth_device_priv *priv = dev->uclass_priv;
>> > +                       if (priv)
>> > +                               memcpy(priv->enetaddr, env_enetaddr, 6);
>> > +               }
>> > +       };
>> > +
>> > +       old_current = current;
>> > +       do {
>> > +               debug("Trying %s\n", current->name);
>> > +
>> > +               if (current->driver) {
>> > +                       const struct eth_ops *ops =
>> > current->driver->ops;
>> > +                       if (ops->init(current, bis) >= 0) {
>> > +                               struct eth_device_priv *priv =
>> > +                                       current->uclass_priv;
>> > +                               if (priv)
>> > +                                       priv->state = ETH_STATE_ACTIVE;
>> > +
>> > +                               return 0;
>> > +                       }
>> > +               }
>> > +               debug("FAIL\n");
>> > +
>> > +               eth_try_another(0);
>> > +               current = eth_get_dev();
>> > +       } while (old_current != current);
>> > +
>> > +       return -1;
>>
>> -ENODEV?
>
> OK.
>
>
>> > +}
>> > +
>> > +void eth_halt(void)
>> > +{
>> > +       struct udevice *current;
>> > +
>> > +       current = eth_get_dev();
>> > +       if (!current)
>> > +               return;
>> > +       if (!current->driver)
>> > +               return;
>> > +
>> > +       const struct eth_ops *ops = current->driver->ops;
>> > +       ops->halt(current);
>> > +
>> > +       struct eth_device_priv *priv = current->uclass_priv;
>> > +       if (priv)
>> > +               priv->state = ETH_STATE_PASSIVE;
>> > +}
>> > +
>> > +int eth_send(void *packet, int length)
>> > +{
>> > +       struct udevice *current;
>> > +
>> > +       current = eth_get_dev();
>> > +       if (!current)
>> > +               return -1;
>> > +       if (!current->driver)
>> > +               return -1;
>> > +
>> > +       const struct eth_ops *ops = current->driver->ops;
>> > +       return ops->send(current, packet, length);
>> > +}
>> > +
>>
>> As a general comment, there is an implicit assumption that only one
>> device can be active at a time. I suppose that is a U-Boot limitation,
>> but we don't need to keep it for driver model, or at least we could
>> permit multiple devices to be probed at a time.
>
> I agree that longer term we should look for ways to remove that limitation,
> but for now everything that uses the network assumes that the "ethact" env
> var selects the device.  There would be a lot of commands to break
> compatibility with to allow them to specify the device.  I say we hold off
> on that for now.

OK

One thing to be careful of is probing devices before you use them. By
using uclass_first_device() you will probe the device. If you want to
pick a particular device and probe it, you will need to find the
device through another means - e.g. a helper function in the uclass to
find the device without probing it.

>
>> But still I wonder if you should have functions that are passed a
>> udevice, like eth_rx(struct udevice *dev).
>
> Even if those functions did, the commands would need to change too.  Future
> enhancement, I think.

OK

>
>
>> > +int eth_rx(void)
>> > +{
>> > +       struct udevice *current;
>> > +
>> > +       current = eth_get_dev();
>> > +       if (!current)
>> > +               return -1;
>> > +       if (!current->driver)
>> > +               return -1;
>> > +
>> > +       const struct eth_ops *ops = current->driver->ops;
>> > +       return ops->recv(current);
>> > +}
>> > +
>> > +static int eth_write_hwaddr(struct udevice *dev, const char *base_name,
>> > +                  int eth_number)
>> > +{
>> > +       unsigned char env_enetaddr[6];
>> > +       int ret = 0;
>> > +
>> > +       eth_getenv_enetaddr_by_index(base_name, eth_number,
>> > env_enetaddr);
>> > +
>> > +       struct eth_device_priv *priv = dev->uclass_priv;
>> > +       if (!is_zero_ether_addr(env_enetaddr)) {
>> > +               if (!is_zero_ether_addr(priv->enetaddr) &&
>> > +                   memcmp(priv->enetaddr, env_enetaddr, 6)) {
>> > +                       printf("\nWarning: %s MAC addresses don't
>> > match:\n",
>> > +                              dev->name);
>> > +                       printf("Address in SROM is         %pM\n",
>> > +                              priv->enetaddr);
>> > +                       printf("Address in environment is  %pM\n",
>> > +                              env_enetaddr);
>> > +               }
>> > +
>> > +               memcpy(priv->enetaddr, env_enetaddr, 6);
>> > +       } else if (is_valid_ether_addr(priv->enetaddr)) {
>> > +               eth_setenv_enetaddr_by_index(base_name, eth_number,
>> > +                                            priv->enetaddr);
>> > +               printf("\nWarning: %s using MAC address from net
>> > device\n",
>> > +                      dev->name);
>> > +       } else if (is_zero_ether_addr(priv->enetaddr)) {
>> > +               printf("\nError: %s address not set.\n",
>> > +                      dev->name);
>> > +               return -EINVAL;
>> > +       }
>> > +
>> > +       const struct eth_ops *ops = dev->driver->ops;
>> > +       if (ops->write_hwaddr && !eth_mac_skip(eth_number)) {
>> > +               if (!is_valid_ether_addr(priv->enetaddr)) {
>> > +                       printf("\nError: %s address %pM illegal
>> > value\n",
>> > +                              dev->name, priv->enetaddr);
>> > +                       return -EINVAL;
>> > +               }
>> > +
>> > +               ret = ops->write_hwaddr(dev);
>> > +               if (ret)
>> > +                       printf("\nWarning: %s failed to set MAC
>> > address\n",
>> > +                              dev->name);
>> > +       }
>> > +
>> > +       return ret;
>> > +}
>> > +
>> > +static int eth_uclass_init(struct uclass *class)
>> > +{
>> > +       bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
>> > +
>> > +       struct eth_uclass_priv *priv = class->priv;
>> > +       priv->max_index = 0;
>>
>> What is max_index used for?
>
> For knowing the number of devices that have been bound and allocating the
> next unused index for the next device.

Is this different from the number of devices in the uclass?

>
>> > +
>> > +       eth_env_init();
>> > +
>> > +       return 0;
>> > +}
>> > +
>> > +static int eth_post_bind(struct udevice *dev)
>> > +{
>> > +       struct udevice *first;
>> > +
>> > +       uclass_first_device(UCLASS_ETH, &first);
>> > +       if (first == dev) {
>> > +               eth_current_changed();
>> > +               eth_set_dev(dev);
>> > +       }
>> > +
>> > +       struct eth_device_priv *priv = dev->uclass_priv;
>> > +       struct eth_uclass_priv *uclass_priv = dev->uclass->priv;
>> > +       if (priv) {
>> > +               priv->state = ETH_STATE_INIT;
>> > +               priv->index = uclass_priv->max_index++;
>>
>> OK I see it is the number of devices. Does this ever decrease?
>
> Never decreases.
>
>> Anyway, struct udevice has a seq member which can give every device a
>> unique sequence number in the uclass automatically (and if you define
>> DM_UC_FLAG_SEQ_ALIAS then the device tree aliases can provide this
>> numbering)
>
> I actually used the seq number originally and that worked fine with
> platdata.  When I moved to the device tree, that's where it fell apart.  In
> the device tree, it is expected that the eth name will include an
> eth at baseaddr format.  The DM code then takes that value that is the baseaddr
> and sets it as the requested seq.  That means I get eth268443648 instead of
> eth0.  No good.  So now I keep track of my own seq (index) to make sure I
> get consistent device names.

That should be fixed now - see u-boot-dm/master. Also the alias
approach is useful since it lets you number the devices within the
uclass as you wish.

>
>> Otherwise I'm not sure what this function is trying to do.
>
> I needs to initialize the priv->current variable so that everything that
> tries to use the network finds a current eth device.
> It also initializes the state variable, which is also important.

OK, also you can't really probe a device in the post_bind() handler.
Probing should only happen when the device is used.

>
>> > +       }
>> > +
>> > +       return 0;
>> > +}
>> > +
>> > +static int eth_pre_unbind(struct udevice *dev)
>> > +{
>> > +       struct udevice *first;
>> > +       struct udevice *current;
>> > +
>> > +       current = eth_get_dev();
>> > +       uclass_first_device(UCLASS_ETH, &first);
>> > +       if (current == dev) {
>> > +               if (dev == first)
>> > +                       uclass_next_device(&current);
>> > +               else
>> > +                       current = first;
>> > +               eth_current_changed();
>> > +               eth_set_dev(current);
>> > +       }
>>
>> I'm not sure what this function is trying to do.
>
> Again, this is just ensuring the "current" variable is always valid.

OK. Shouldn't this happen when the device is removed rather than when
it is unbound (well I suppose if it happens when removed it doesn't
need to happen when unbound).

>
>> > +
>> > +       return 0;
>> > +}
>> > +
>> > +static int eth_post_probe(struct udevice *dev)
>> > +{
>> > +       char *ethprime = getenv("ethprime");
>> > +       if (ethprime && strcmp(dev->name, ethprime) == 0)
>> > +               eth_set_dev(dev);
>>
>> What does this do?
>
> This allows the initial "current" device to be specified by they "ethprime"
> env var.  This is preserving existing behaviors as controlled by these env
> vars.

OK

>
>> > +
>> > +       if (strchr(dev->name, ' '))
>> > +               printf("\nWarning: eth device name \"%s\" has a
>> > space!\n",
>> > +                      dev->name);
>>
>> BTW if this is an error you could refuse to bind it - e.g. in the
>> eth_post_bind, return -EINVAL
>
> Good idea.
>
>
>> > +
>> > +       struct eth_device_priv *priv = dev->uclass_priv;
>> > +       if (priv)
>> > +               return eth_write_hwaddr(dev, "eth", priv->index);
>> > +       return 1;
>> > +}
>> > +
>> > +UCLASS_DRIVER(eth) = {
>> > +       .name           = "eth",
>> > +       .id             = UCLASS_ETH,
>> > +       .post_bind      = eth_post_bind,
>> > +       .pre_unbind     = eth_pre_unbind,
>> > +       .post_probe     = eth_post_probe,
>> > +       .init           = eth_uclass_init,
>> > +       .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
>> > +       .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
>> > +};
>> > +#endif
>> > +
>> > +#ifndef CONFIG_DM_ETH
>> >  /*
>> >   * CPU and board-specific Ethernet initializations.  Aliased function
>> >   * signals caller to move on
>> > @@ -423,6 +738,7 @@ int eth_rx(void)
>> >
>> >         return eth_current->recv(eth_current);
>> >  }
>> > +#endif /* ifndef CONFIG_DM_ETH */
>> >
>> >  #ifdef CONFIG_API
>> >  static void eth_save_packet(void *packet, int length)
>> > @@ -486,7 +802,7 @@ static void eth_current_changed(void)
>> >
>> >  void eth_try_another(int first_restart)
>> >  {
>> > -       static struct eth_device *first_failed;
>> > +       static void *first_failed;
>> >         char *ethrotate;
>> >
>> >         /*
>> > @@ -515,7 +831,7 @@ void eth_set_current(void)
>> >  {
>> >         static char *act;
>> >         static int  env_changed_id;
>> > -       struct eth_device *old_current;
>> > +       void *old_current;
>> >         int     env_id;
>> >
>> >         if (!eth_get_dev())     /* XXX no current */


Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH 7/7] net: Add ARP and PING response to sandbox driver
       [not found]     ` <CANr=Z=YcT=OvcA8ggaMCrOfyS5ShjFzgK6AW9gpfsNsZqcgfPA@mail.gmail.com>
@ 2015-01-29  1:58       ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-01-29  1:58 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 28 January 2015 at 03:36, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> On Tue, Jan 27, 2015 at 8:34 PM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 27 January 2015 at 16:27, Joe Hershberger <joe.hershberger@ni.com>
>> wrote:
>> > The sandbox driver will now generate response traffic to exercise the
>> > ping command even when no network exists.  This allows the basic data
>> > pathways of the DM to be tested.
>> >
>> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>> > ---
>>
>> Looks like this can support ping. Very nice.
>
> I looked at other ways to test the network stack in sandbox, create tests in
> the test/ dir, etc., but this seemed like the best and most straightforward
> way to exercise it without tons of extra code, so I went for this approach.

Well we still need tests in the test/ directory - every uclass should
have tests. In this case the tests could start up a few devices and
try ping. Also the environment variable logic needs tests.

>
>> >
>> >  drivers/net/sandbox.c | 75
>> > +++++++++++++++++++++++++++++++++++++++++++++++++++
>> >  1 file changed, 75 insertions(+)
>> >
>> > diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
>> > index e1ee69b..49413f2 100644
>> > --- a/drivers/net/sandbox.c
>> > +++ b/drivers/net/sandbox.c
>> > @@ -20,6 +20,11 @@ struct eth_sandbox_priv {
>> >         int sd;
>> >  };
>> >
>> > +static uchar fake_host_hwaddr[ARP_HLEN] = {0x00, 0x00, 0x66, 0x44,
>> > 0x22, 0x00};
>> > +static IPaddr_t fake_host_ipaddr;
>> > +static uchar recv_packet_buffer[PKTSIZE];
>> > +static int recv_packet_length;
>>
>> This could go in the driver's priv area (then we could support
>> multiple sandbox devices).
>
> Good idea.
>
>
>> > +
>> >  int sb_eth_init(struct udevice *dev, bd_t *bis)
>> >  {
>> >         printf("eth_sandbox: Init\n");
>> > @@ -31,12 +36,82 @@ int sb_eth_send(struct udevice *dev, void *packet,
>> > int length)
>> >  {
>> >         printf("eth_sandbox: Send packet %d\n", length);
>> >
>> > +       struct ethernet_hdr *eth = packet;
>> > +       if (ntohs(eth->et_protlen) == PROT_ARP) {
>> > +               struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
>> > +               if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
>> > +                       /* store this as the assumed IP of the fake host
>> > */
>> > +                       fake_host_ipaddr = NetReadIP(&arp->ar_tpa);
>> > +                       /* Formulate a fake response */
>> > +                       struct ethernet_hdr *eth_recv =
>> > +                               (void *)recv_packet_buffer;
>> > +                       memcpy(eth_recv->et_dest, eth->et_src,
>> > ARP_HLEN);
>> > +                       memcpy(eth_recv->et_src, fake_host_hwaddr,
>> > ARP_HLEN);
>> > +                       eth_recv->et_protlen = htons(PROT_ARP);
>> > +
>> > +                       struct arp_hdr *arp_recv = (void
>> > *)recv_packet_buffer +
>> > +                               ETHER_HDR_SIZE;
>> > +                       arp_recv->ar_hrd = htons(ARP_ETHER);
>> > +                       arp_recv->ar_pro = htons(PROT_IP);
>> > +                       arp_recv->ar_hln = ARP_HLEN;
>> > +                       arp_recv->ar_pln = ARP_PLEN;
>> > +                       arp_recv->ar_op = htons(ARPOP_REPLY);
>> > +                       memcpy(&arp_recv->ar_sha, fake_host_hwaddr,
>> > ARP_HLEN);
>> > +                       NetWriteIP(&arp_recv->ar_spa, fake_host_ipaddr);
>> > +                       memcpy(&arp_recv->ar_tha, &arp->ar_sha,
>> > ARP_HLEN);
>> > +                       NetCopyIP(&arp_recv->ar_tpa, &arp->ar_spa);
>> > +
>> > +                       recv_packet_length = ETHER_HDR_SIZE +
>> > ARP_HDR_SIZE;
>> > +               }
>> > +       } else if (ntohs(eth->et_protlen) == PROT_IP) {
>> > +               struct ip_udp_hdr *ip = packet + ETHER_HDR_SIZE;
>> > +               if (ip->ip_p == IPPROTO_ICMP) {
>> > +                       struct icmp_hdr *icmp = (struct icmp_hdr
>> > *)&ip->udp_src;
>> > +                       if (icmp->type == ICMP_ECHO_REQUEST) {
>> > +                               /* reply to the ping */
>> > +                               memcpy(recv_packet_buffer, packet,
>> > length);
>> > +                               struct ethernet_hdr *eth_recv =
>> > +                                       (void *)recv_packet_buffer;
>> > +                               struct ip_udp_hdr *ipr =
>> > +                                       (void *)recv_packet_buffer +
>> > +                                       ETHER_HDR_SIZE;
>> > +                               struct icmp_hdr *icmpr =
>> > +                                       (struct icmp_hdr
>> > *)&ipr->udp_src;
>> > +                               memcpy(eth_recv->et_dest, eth->et_src,
>> > +                                      ARP_HLEN);
>> > +                               memcpy(eth_recv->et_src,
>> > fake_host_hwaddr,
>> > +                                      ARP_HLEN);
>> > +                               ipr->ip_sum = 0;
>> > +                               ipr->ip_off = 0;
>> > +                               NetCopyIP((void *)&ipr->ip_dst,
>> > &ip->ip_src);
>> > +                               NetWriteIP((void *)&ipr->ip_src,
>> > +                                          fake_host_ipaddr);
>> > +                               ipr->ip_sum = ~NetCksum((uchar *)ipr,
>> > +                                       IP_HDR_SIZE >> 1);
>> > +
>> > +                               icmpr->type = ICMP_ECHO_REPLY;
>> > +                               icmpr->checksum = 0;
>> > +                               icmpr->checksum = ~NetCksum((uchar
>> > *)icmpr,
>> > +                                       (length - ETHER_HDR_SIZE -
>> > +                                               IP_HDR_SIZE) >> 1);
>> > +
>> > +                               recv_packet_length = length;
>> > +                       }
>> > +               }
>> > +       }
>> > +
>> >         return 0;
>> >  #endif
>> >  }
>> >
>> >  int sb_eth_recv(struct udevice *dev)
>> >  {
>> > +       if (recv_packet_length) {
>> > +               int lcl_recv_packet_length = recv_packet_length;
>> > +               printf("eth_sandbox: received packet %d\n",
>> > recv_packet_length);
>> > +               recv_packet_length = 0;
>> > +               NetReceive((void *)recv_packet_buffer,
>> > lcl_recv_packet_length);
>> > +       }
>> >         return 0;
>> >  }
>> >
>>
>> Looks good.
>
> Thanks.

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 0/8] Add Driver Model support to network stack
  2015-01-27 23:27 [U-Boot] [RFC PATCH 0/7] Add Driver Model support to network stack Joe Hershberger
                   ` (7 preceding siblings ...)
  2015-01-28  2:33 ` [U-Boot] [RFC PATCH 0/7] Add Driver Model support to network stack Simon Glass
@ 2015-02-03  0:38 ` Joe Hershberger
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 1/8] net: Provide a function to get the current MAC address Joe Hershberger
                     ` (8 more replies)
  8 siblings, 9 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-02-03  0:38 UTC (permalink / raw)
  To: u-boot

For now this simply addresses the MAC part of the network hardware.
The next part to implement is the PHY children.  I wanted to get early
feedback on what I have so far to make sure I'm going in the direction
that Simon envisioned.

Added an additional patch that I've been playing with to allow actual
networking from within sandbox, but I haven't come across a good way
to make it build in the u-boot build system. Any good ideas are welcome.

Changes in v2:
-Updated comments
-Removed extra parentheses
-Changed eth_uclass_priv local var names to be uc_priv
-Update error codes
-Cause an invalid name to fail binding
-Rebase on top of dm/master
-Stop maintaining our own index and use DM seq now that it works for our needs
-Move the hwaddr to platdata so that its memory is allocated at bind when we need it
-Prevent device from being probed before used by a command (i.e. before eth_init()).
-Change printfs to debug in sandbox driver
-Remove unused priv struct for sandbox driver
-Change printfs to debug in sandbox driver
-Move static data to priv
-Move fake hwaddr to the device tree
-Added the raw packet proof-of-concept patch.

Joe Hershberger (8):
  net: Provide a function to get the current MAC address
  net: Rename helper function to be more clear
  net: Remove unneeded "extern" in net.h
  net: Refactor in preparation for driver model
  net: Add basic driver model support to Ethernet stack
  net: Add network support to sandbox
  net: Add ARP and PING response to sandbox driver
  net: Add actual networking support to sandbox's driver

 arch/mips/cpu/mips32/au1x00/au1x00_eth.c |   2 +-
 arch/powerpc/cpu/mpc8260/ether_fcc.c     |   2 +-
 arch/powerpc/cpu/mpc85xx/ether_fcc.c     |   2 +-
 arch/powerpc/cpu/mpc8xx/scc.c            |   2 +-
 arch/sandbox/dts/sandbox.dts             |   5 +
 common/board_r.c                         |   4 +-
 common/cmd_bdinfo.c                      |   2 +
 drivers/net/Makefile                     |   2 +
 drivers/net/sandbox-raw.c                |  60 +++++
 drivers/net/sandbox.c                    | 204 ++++++++++++++++
 include/configs/sandbox.h                |  14 +-
 include/dm/uclass-id.h                   |   1 +
 include/net.h                            | 159 +++++++-----
 net/eth.c                                | 407 +++++++++++++++++++++++++++----
 net/net.c                                |   2 +-
 15 files changed, 748 insertions(+), 120 deletions(-)
 create mode 100644 drivers/net/sandbox-raw.c
 create mode 100644 drivers/net/sandbox.c

-- 
1.7.11.5

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 1/8] net: Provide a function to get the current MAC address
  2015-02-03  0:38 ` [U-Boot] [RFC PATCH v2 0/8] " Joe Hershberger
@ 2015-02-03  0:38   ` Joe Hershberger
  2015-02-07  1:25     ` Simon Glass
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 2/8] net: Rename helper function to be more clear Joe Hershberger
                     ` (7 subsequent siblings)
  8 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-03  0:38 UTC (permalink / raw)
  To: u-boot

The current implementation exposes the eth_device struct to code that
needs to access the MAC address.  Add a wrapper function for this to
abstract away the pointer for this operation.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
---

Changes in v2: None

 arch/mips/cpu/mips32/au1x00/au1x00_eth.c | 2 +-
 arch/powerpc/cpu/mpc8260/ether_fcc.c     | 2 +-
 arch/powerpc/cpu/mpc85xx/ether_fcc.c     | 2 +-
 arch/powerpc/cpu/mpc8xx/scc.c            | 2 +-
 include/net.h                            | 8 ++++++++
 net/net.c                                | 2 +-
 6 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_eth.c b/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
index 4770f56..535d713 100644
--- a/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
+++ b/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
@@ -238,7 +238,7 @@ static int au1x00_init(struct eth_device* dev, bd_t * bd){
 	}
 
 	/* Put mac addr in little endian */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
 	*mac_addr_high	=	(ea[5] <<  8) | (ea[4]	    ) ;
 	*mac_addr_low	=	(ea[3] << 24) | (ea[2] << 16) |
 		(ea[1] <<  8) | (ea[0]	    ) ;
diff --git a/arch/powerpc/cpu/mpc8260/ether_fcc.c b/arch/powerpc/cpu/mpc8260/ether_fcc.c
index f9f15b5..f777ba1 100644
--- a/arch/powerpc/cpu/mpc8260/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc8260/ether_fcc.c
@@ -299,7 +299,7 @@ static int fec_init(struct eth_device* dev, bd_t *bis)
      * it unique by setting a few bits in the upper byte of the
      * non-static part of the address.
      */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
     pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
     pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
     pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/arch/powerpc/cpu/mpc85xx/ether_fcc.c b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
index 166dc9e..58d4bfb 100644
--- a/arch/powerpc/cpu/mpc85xx/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
@@ -338,7 +338,7 @@ static int fec_init(struct eth_device* dev, bd_t *bis)
      * it unique by setting a few bits in the upper byte of the
      * non-static part of the address.
      */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
     pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
     pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
     pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/arch/powerpc/cpu/mpc8xx/scc.c b/arch/powerpc/cpu/mpc8xx/scc.c
index 251966b..66e4014 100644
--- a/arch/powerpc/cpu/mpc8xx/scc.c
+++ b/arch/powerpc/cpu/mpc8xx/scc.c
@@ -339,7 +339,7 @@ static int scc_init (struct eth_device *dev, bd_t * bis)
 	pram_ptr->sen_gaddr3 = 0x0;	/* Group Address Filter 3 (unused) */
 	pram_ptr->sen_gaddr4 = 0x0;	/* Group Address Filter 4 (unused) */
 
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
 	pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4];
 	pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2];
 	pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/include/net.h b/include/net.h
index 73ea88b..a9579ee 100644
--- a/include/net.h
+++ b/include/net.h
@@ -111,6 +111,14 @@ struct eth_device *eth_get_dev(void)
 {
 	return eth_current;
 }
+
+static inline unsigned char *eth_get_ethaddr(void)
+{
+	if (eth_current)
+		return eth_current->enetaddr;
+	return NULL;
+}
+
 extern struct eth_device *eth_get_dev_by_name(const char *devname);
 extern struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
 extern int eth_get_dev_index(void);		/* get the device index */
diff --git a/net/net.c b/net/net.c
index 2bea07b..ddd630c 100644
--- a/net/net.c
+++ b/net/net.c
@@ -275,7 +275,7 @@ static void NetInitLoop(void)
 		env_changed_id = env_id;
 	}
 	if (eth_get_dev())
-		memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
+		memcpy(NetOurEther, eth_get_ethaddr(), 6);
 
 	return;
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 2/8] net: Rename helper function to be more clear
  2015-02-03  0:38 ` [U-Boot] [RFC PATCH v2 0/8] " Joe Hershberger
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 1/8] net: Provide a function to get the current MAC address Joe Hershberger
@ 2015-02-03  0:38   ` Joe Hershberger
  2015-02-07  1:25     ` Simon Glass
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 3/8] net: Remove unneeded "extern" in net.h Joe Hershberger
                     ` (6 subsequent siblings)
  8 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-03  0:38 UTC (permalink / raw)
  To: u-boot

Make it clear that the helper is checking the addr, not setting it.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
---

Changes in v2: None

 net/eth.c | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/net/eth.c b/net/eth.c
index eac4f7b..65e8c77 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -153,11 +153,6 @@ static void eth_current_changed(void)
 		setenv("ethact", NULL);
 }
 
-static int eth_address_set(unsigned char *addr)
-{
-	return memcmp(addr, "\0\0\0\0\0\0", 6);
-}
-
 int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		   int eth_number)
 {
@@ -166,9 +161,9 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 
 	eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
 
-	if (eth_address_set(env_enetaddr)) {
-		if (eth_address_set(dev->enetaddr) &&
-				memcmp(dev->enetaddr, env_enetaddr, 6)) {
+	if (!is_zero_ether_addr(env_enetaddr)) {
+		if (!is_zero_ether_addr(dev->enetaddr) &&
+		    memcmp(dev->enetaddr, env_enetaddr, 6)) {
 			printf("\nWarning: %s MAC addresses don't match:\n",
 				dev->name);
 			printf("Address in SROM is         %pM\n",
@@ -183,7 +178,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 					     dev->enetaddr);
 		printf("\nWarning: %s using MAC address from net device\n",
 			dev->name);
-	} else if (!(eth_address_set(dev->enetaddr))) {
+	} else if (is_zero_ether_addr(dev->enetaddr)) {
 		printf("\nError: %s address not set.\n",
 		       dev->name);
 		return -EINVAL;
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 3/8] net: Remove unneeded "extern" in net.h
  2015-02-03  0:38 ` [U-Boot] [RFC PATCH v2 0/8] " Joe Hershberger
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 1/8] net: Provide a function to get the current MAC address Joe Hershberger
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 2/8] net: Rename helper function to be more clear Joe Hershberger
@ 2015-02-03  0:38   ` Joe Hershberger
  2015-02-07  1:25     ` Simon Glass
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 4/8] net: Refactor in preparation for driver model Joe Hershberger
                     ` (5 subsequent siblings)
  8 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-03  0:38 UTC (permalink / raw)
  To: u-boot

Many of the functions in net.h were preceded extern needlessly. Removing
them to limit the number of checkpatch.pl complaints.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
---

Changes in v2: None

 include/net.h | 96 +++++++++++++++++++++++++++++------------------------------
 1 file changed, 48 insertions(+), 48 deletions(-)

diff --git a/include/net.h b/include/net.h
index a9579ee..ff8b7af 100644
--- a/include/net.h
+++ b/include/net.h
@@ -97,11 +97,11 @@ struct eth_device {
 	void *priv;
 };
 
-extern int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
-extern int eth_register(struct eth_device* dev);/* Register network device */
-extern int eth_unregister(struct eth_device *dev);/* Remove network device */
-extern void eth_try_another(int first_restart);	/* Change the device */
-extern void eth_set_current(void);		/* set nterface to ethcur var */
+int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
+int eth_register(struct eth_device *dev);/* Register network device */
+int eth_unregister(struct eth_device *dev);/* Remove network device */
+void eth_try_another(int first_restart);	/* Change the device */
+void eth_set_current(void);		/* set nterface to ethcur var */
 
 /* get the current device MAC */
 extern struct eth_device *eth_current;
@@ -119,12 +119,12 @@ static inline unsigned char *eth_get_ethaddr(void)
 	return NULL;
 }
 
-extern struct eth_device *eth_get_dev_by_name(const char *devname);
-extern struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
-extern int eth_get_dev_index(void);		/* get the device index */
-extern void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
-extern int eth_getenv_enetaddr(char *name, uchar *enetaddr);
-extern int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
+struct eth_device *eth_get_dev_by_name(const char *devname);
+struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
+int eth_get_dev_index(void);		/* get the device index */
+void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
+int eth_getenv_enetaddr(char *name, uchar *enetaddr);
+int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 
 /*
  * Get the hardware address for an ethernet interface .
@@ -135,20 +135,20 @@ extern int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
  * Returns:
  *	Return true if the address is valid.
  */
-extern int eth_getenv_enetaddr_by_index(const char *base_name, int index,
-					uchar *enetaddr);
+int eth_getenv_enetaddr_by_index(const char *base_name, int index,
+				 uchar *enetaddr);
 
-extern int usb_eth_initialize(bd_t *bi);
-extern int eth_init(bd_t *bis);			/* Initialize the device */
-extern int eth_send(void *packet, int length);	   /* Send a packet */
+int usb_eth_initialize(bd_t *bi);
+int eth_init(bd_t *bis);			/* Initialize the device */
+int eth_send(void *packet, int length);	   /* Send a packet */
 
 #ifdef CONFIG_API
-extern int eth_receive(void *packet, int length); /* Receive a packet*/
-extern void (*push_packet)(void *packet, int length);
+int eth_receive(void *packet, int length); /* Receive a packet*/
+void (*push_packet)(void *packet, int length);
 #endif
-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 */
+int eth_rx(void);			/* Check for received packets */
+void eth_halt(void);			/* stop SCC */
+char *eth_get_name(void);		/* get name of current device */
 
 /* Set active state */
 static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
@@ -469,25 +469,25 @@ extern IPaddr_t Mcast_addr;
 #endif
 
 /* Initialize the network adapter */
-extern void net_init(void);
-extern int NetLoop(enum proto_t);
+void net_init(void);
+int NetLoop(enum proto_t);
 
 /* Shutdown adapters and cleanup */
-extern void	NetStop(void);
+void	NetStop(void);
 
 /* Load failed.	 Start again. */
-extern void	NetStartAgain(void);
+void	NetStartAgain(void);
 
 /* Get size of the ethernet header when we send */
-extern int	NetEthHdrSize(void);
+int	NetEthHdrSize(void);
 
 /* Set ethernet header; returns the size of the header */
-extern int NetSetEther(uchar *, uchar *, uint);
-extern int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot);
+int NetSetEther(uchar *, uchar *, uint);
+int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot);
 
 /* Set IP header */
-extern void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source);
-extern void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport,
+void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source);
+void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport,
 				int sport, int len);
 
 /**
@@ -521,16 +521,16 @@ unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new_sum);
 int ip_checksum_ok(const void *addr, unsigned nbytes);
 
 /* Checksum */
-extern int	NetCksumOk(uchar *, int);	/* Return true if cksum OK */
-extern uint	NetCksum(uchar *, int);		/* Calculate the checksum */
+int	NetCksumOk(uchar *, int);	/* Return true if cksum OK */
+uint	NetCksum(uchar *, int);		/* Calculate the checksum */
 
 /* Callbacks */
-extern rxhand_f *net_get_udp_handler(void);	/* Get UDP RX packet handler */
-extern void net_set_udp_handler(rxhand_f *);	/* Set UDP RX packet handler */
-extern rxhand_f *net_get_arp_handler(void);	/* Get ARP RX packet handler */
-extern void net_set_arp_handler(rxhand_f *);	/* Set ARP RX packet handler */
-extern void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
-extern void	NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
+rxhand_f *net_get_udp_handler(void);	/* Get UDP RX packet handler */
+void net_set_udp_handler(rxhand_f *);	/* Set UDP RX packet handler */
+rxhand_f *net_get_arp_handler(void);	/* Get ARP RX packet handler */
+void net_set_arp_handler(rxhand_f *);	/* Set ARP RX packet handler */
+void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
+void	NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
 
 /* Network loop state */
 enum net_loop_state {
@@ -563,11 +563,11 @@ static inline void NetSendPacket(uchar *pkt, int len)
  * @param sport Source UDP port
  * @param payload_len Length of data after the UDP header
  */
-extern int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport,
+int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport,
 			int sport, int payload_len);
 
 /* Processes a received packet */
-extern void NetReceive(uchar *, int);
+void NetReceive(uchar *, int);
 
 #ifdef CONFIG_NETCONSOLE
 void NcStart(void);
@@ -715,28 +715,28 @@ static inline void eth_random_addr(uchar *addr)
 }
 
 /* Convert an IP address to a string */
-extern void ip_to_string(IPaddr_t x, char *s);
+void ip_to_string(IPaddr_t x, char *s);
 
 /* Convert a string to ip address */
-extern IPaddr_t string_to_ip(const char *s);
+IPaddr_t string_to_ip(const char *s);
 
 /* Convert a VLAN id to a string */
-extern void VLAN_to_string(ushort x, char *s);
+void VLAN_to_string(ushort x, char *s);
 
 /* Convert a string to a vlan id */
-extern ushort string_to_VLAN(const char *s);
+ushort string_to_VLAN(const char *s);
 
 /* read a VLAN id from an environment variable */
-extern ushort getenv_VLAN(char *);
+ushort getenv_VLAN(char *);
 
 /* copy a filename (allow for "..." notation, limit length) */
-extern void copy_filename(char *dst, const char *src, int size);
+void copy_filename(char *dst, const char *src, int size);
 
 /* get a random source port */
-extern unsigned int random_port(void);
+unsigned int random_port(void);
 
 /* Update U-Boot over TFTP */
-extern int update_tftp(ulong addr);
+int update_tftp(ulong addr);
 
 /**********************************************************************/
 
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 4/8] net: Refactor in preparation for driver model
  2015-02-03  0:38 ` [U-Boot] [RFC PATCH v2 0/8] " Joe Hershberger
                     ` (2 preceding siblings ...)
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 3/8] net: Remove unneeded "extern" in net.h Joe Hershberger
@ 2015-02-03  0:38   ` Joe Hershberger
  2015-02-07  1:25     ` Simon Glass
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 5/8] net: Add basic driver model support to Ethernet stack Joe Hershberger
                     ` (4 subsequent siblings)
  8 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-03  0:38 UTC (permalink / raw)
  To: u-boot

Move some things around and organize things so that the driver model
implementation will fit in more easily.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
---

Changes in v2: None

 include/net.h | 63 +++++++++++++++++++++++++------------------------
 net/eth.c     | 75 +++++++++++++++++++++++++++++++----------------------------
 2 files changed, 73 insertions(+), 65 deletions(-)

diff --git a/include/net.h b/include/net.h
index ff8b7af..7eef9cc 100644
--- a/include/net.h
+++ b/include/net.h
@@ -100,10 +100,7 @@ struct eth_device {
 int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
 int eth_register(struct eth_device *dev);/* Register network device */
 int eth_unregister(struct eth_device *dev);/* Remove network device */
-void eth_try_another(int first_restart);	/* Change the device */
-void eth_set_current(void);		/* set nterface to ethcur var */
 
-/* get the current device MAC */
 extern struct eth_device *eth_current;
 
 static inline __attribute__((always_inline))
@@ -112,6 +109,7 @@ struct eth_device *eth_get_dev(void)
 	return eth_current;
 }
 
+/* get the current device MAC */
 static inline unsigned char *eth_get_ethaddr(void)
 {
 	if (eth_current)
@@ -119,6 +117,37 @@ static inline unsigned char *eth_get_ethaddr(void)
 	return NULL;
 }
 
+/* Set active state */
+static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
+{
+	eth_get_dev()->state = ETH_STATE_ACTIVE;
+
+	return 0;
+}
+/* Set passive state */
+static inline __attribute__((always_inline)) void eth_halt_state_only(void)
+{
+	eth_get_dev()->state = ETH_STATE_PASSIVE;
+}
+
+/*
+ * Set the hardware address for an ethernet interface based on 'eth%daddr'
+ * environment variable (or just 'ethaddr' if eth_number is 0).
+ * Args:
+ *	base_name - base name for device (normally "eth")
+ *	eth_number - value of %d (0 for first device of this type)
+ * Returns:
+ *	0 is success, non-zero is error status from driver.
+ */
+int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
+		     int eth_number);
+
+int usb_eth_initialize(bd_t *bi);
+#endif
+
+void eth_try_another(int first_restart);	/* Change the device */
+void eth_set_current(void);		/* set nterface to ethcur var */
+
 struct eth_device *eth_get_dev_by_name(const char *devname);
 struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
 int eth_get_dev_index(void);		/* get the device index */
@@ -138,7 +167,6 @@ int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 int eth_getenv_enetaddr_by_index(const char *base_name, int index,
 				 uchar *enetaddr);
 
-int usb_eth_initialize(bd_t *bi);
 int eth_init(bd_t *bis);			/* Initialize the device */
 int eth_send(void *packet, int length);	   /* Send a packet */
 
@@ -148,32 +176,7 @@ void (*push_packet)(void *packet, int length);
 #endif
 int eth_rx(void);			/* Check for received packets */
 void eth_halt(void);			/* stop SCC */
-char *eth_get_name(void);		/* get name of current device */
-
-/* Set active state */
-static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
-{
-	eth_get_dev()->state = ETH_STATE_ACTIVE;
-
-	return 0;
-}
-/* Set passive state */
-static inline __attribute__((always_inline)) void eth_halt_state_only(void)
-{
-	eth_get_dev()->state = ETH_STATE_PASSIVE;
-}
-
-/*
- * Set the hardware address for an ethernet interface based on 'eth%daddr'
- * environment variable (or just 'ethaddr' if eth_number is 0).
- * Args:
- *	base_name - base name for device (normally "eth")
- *	eth_number - value of %d (0 for first device of this type)
- * Returns:
- *	0 is success, non-zero is error status from driver.
- */
-int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
-		     int eth_number);
+const char *eth_get_name(void);		/* get name of current device */
 
 #ifdef CONFIG_MCAST_TFTP
 int eth_mcast_join(IPaddr_t mcast_addr, u8 join);
diff --git a/net/eth.c b/net/eth.c
index 65e8c77..c02548c 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -55,6 +55,14 @@ static inline int eth_setenv_enetaddr_by_index(const char *base_name, int index,
 	return eth_setenv_enetaddr(enetvar, enetaddr);
 }
 
+static void eth_env_init(void)
+{
+	const char *s;
+
+	s = getenv("bootfile");
+	if (s != NULL)
+		copy_filename(BootFile, s, sizeof(BootFile));
+}
 
 static int eth_mac_skip(int index)
 {
@@ -87,6 +95,11 @@ static unsigned int eth_rcv_current, eth_rcv_last;
 static struct eth_device *eth_devices;
 struct eth_device *eth_current;
 
+static void eth_set_current_to_next(void)
+{
+	eth_current = eth_current->next;
+}
+
 struct eth_device *eth_get_dev_by_name(const char *devname)
 {
 	struct eth_device *dev, *target_dev;
@@ -137,22 +150,6 @@ int eth_get_dev_index(void)
 	return eth_current->index;
 }
 
-static void eth_current_changed(void)
-{
-	char *act = getenv("ethact");
-	/* update current ethernet name */
-	if (eth_current) {
-		if (act == NULL || strcmp(act, eth_current->name) != 0)
-			setenv("ethact", eth_current->name);
-	}
-	/*
-	 * remove the variable completely if there is no active
-	 * interface
-	 */
-	else if (act != NULL)
-		setenv("ethact", NULL);
-}
-
 int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		   int eth_number)
 {
@@ -251,14 +248,6 @@ int eth_unregister(struct eth_device *dev)
 	return 0;
 }
 
-static void eth_env_init(bd_t *bis)
-{
-	const char *s;
-
-	if ((s = getenv("bootfile")) != NULL)
-		copy_filename(BootFile, s, sizeof(BootFile));
-}
-
 int eth_initialize(bd_t *bis)
 {
 	int num_devices = 0;
@@ -479,6 +468,22 @@ int eth_receive(void *packet, int length)
 }
 #endif /* CONFIG_API */
 
+static void eth_current_changed(void)
+{
+	char *act = getenv("ethact");
+	/* update current ethernet name */
+	if (eth_get_dev()) {
+		if (act == NULL || strcmp(act, eth_get_name()) != 0)
+			setenv("ethact", eth_get_name());
+	}
+	/*
+	 * remove the variable completely if there is no active
+	 * interface
+	 */
+	else if (act != NULL)
+		setenv("ethact", NULL);
+}
+
 void eth_try_another(int first_restart)
 {
 	static struct eth_device *first_failed;
@@ -492,17 +497,17 @@ void eth_try_another(int first_restart)
 	if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
 		return;
 
-	if (!eth_current)
+	if (!eth_get_dev())
 		return;
 
 	if (first_restart)
-		first_failed = eth_current;
+		first_failed = eth_get_dev();
 
-	eth_current = eth_current->next;
+	eth_set_current_to_next();
 
 	eth_current_changed();
 
-	if (first_failed == eth_current)
+	if (first_failed == eth_get_dev())
 		NetRestartWrap = 1;
 }
 
@@ -513,7 +518,7 @@ void eth_set_current(void)
 	struct eth_device *old_current;
 	int	env_id;
 
-	if (!eth_current)	/* XXX no current */
+	if (!eth_get_dev())	/* XXX no current */
 		return;
 
 	env_id = get_env_id();
@@ -522,18 +527,18 @@ void eth_set_current(void)
 		env_changed_id = env_id;
 	}
 	if (act != NULL) {
-		old_current = eth_current;
+		old_current = eth_get_dev();
 		do {
-			if (strcmp(eth_current->name, act) == 0)
+			if (strcmp(eth_get_name(), act) == 0)
 				return;
-			eth_current = eth_current->next;
-		} while (old_current != eth_current);
+			eth_set_current_to_next();
+		} while (old_current != eth_get_dev());
 	}
 
 	eth_current_changed();
 }
 
-char *eth_get_name(void)
+const char *eth_get_name(void)
 {
-	return eth_current ? eth_current->name : "unknown";
+	return eth_get_dev() ? eth_get_dev()->name : "unknown";
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 5/8] net: Add basic driver model support to Ethernet stack
  2015-02-03  0:38 ` [U-Boot] [RFC PATCH v2 0/8] " Joe Hershberger
                     ` (3 preceding siblings ...)
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 4/8] net: Refactor in preparation for driver model Joe Hershberger
@ 2015-02-03  0:38   ` Joe Hershberger
  2015-02-07  1:25     ` Simon Glass
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 6/8] net: Add network support to sandbox Joe Hershberger
                     ` (3 subsequent siblings)
  8 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-03  0:38 UTC (permalink / raw)
  To: u-boot

First just add support for MAC drivers.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v2:
-Updated comments
-Removed extra parentheses
-Changed eth_uclass_priv local var names to be uc_priv
-Update error codes
-Cause an invalid name to fail binding
-Rebase on top of dm/master
-Stop maintaining our own index and use DM seq now that it works for our needs
-Move the hwaddr to platdata so that its memory is allocated at bind when we need it
-Prevent device from being probed before used by a command (i.e. before eth_init()).

 common/board_r.c       |   4 +-
 common/cmd_bdinfo.c    |   2 +
 include/dm/uclass-id.h |   1 +
 include/net.h          |  24 ++++
 net/eth.c              | 319 ++++++++++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 346 insertions(+), 4 deletions(-)

diff --git a/common/board_r.c b/common/board_r.c
index 68a9448..75147b7 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -556,7 +556,7 @@ static int initr_bbmii(void)
 }
 #endif
 
-#ifdef CONFIG_CMD_NET
+#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
 static int initr_net(void)
 {
 	puts("Net:   ");
@@ -825,7 +825,7 @@ init_fnc_t init_sequence_r[] = {
 #ifdef CONFIG_BITBANGMII
 	initr_bbmii,
 #endif
-#ifdef CONFIG_CMD_NET
+#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
 	INIT_FUNC_WATCHDOG_RESET
 	initr_net,
 #endif
diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
index e6d8a7a..8688cf9 100644
--- a/common/cmd_bdinfo.c
+++ b/common/cmd_bdinfo.c
@@ -34,6 +34,7 @@ static void print_eth(int idx)
 	printf("%-12s= %s\n", name, val);
 }
 
+#ifndef CONFIG_DM_ETH
 __maybe_unused
 static void print_eths(void)
 {
@@ -52,6 +53,7 @@ static void print_eths(void)
 	printf("current eth = %s\n", eth_get_name());
 	printf("ip_addr     = %s\n", getenv("ipaddr"));
 }
+#endif
 
 __maybe_unused
 static void print_lnum(const char *name, unsigned long long value)
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 91bb90d..ad96682 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -34,6 +34,7 @@ enum uclass_id {
 	UCLASS_I2C_GENERIC,	/* Generic I2C device */
 	UCLASS_I2C_EEPROM,	/* I2C EEPROM device */
 	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
+	UCLASS_ETH,		/* Ethernet device */
 
 	UCLASS_COUNT,
 	UCLASS_INVALID = -1,
diff --git a/include/net.h b/include/net.h
index 7eef9cc..4d21d91 100644
--- a/include/net.h
+++ b/include/net.h
@@ -78,6 +78,30 @@ enum eth_state_t {
 	ETH_STATE_ACTIVE
 };
 
+#ifdef CONFIG_DM_ETH
+struct eth_pdata {
+	phys_addr_t iobase;
+	unsigned char enetaddr[6];
+};
+
+struct eth_ops {
+	int (*init)(struct udevice *dev, bd_t *bis);
+	int (*send)(struct udevice *dev, void *packet, int length);
+	int (*recv)(struct udevice *dev);
+	void (*halt)(struct udevice *dev);
+#ifdef CONFIG_MCAST_TFTP
+	int (*mcast)(struct udevice *dev, const u8 *enetaddr, u8 set);
+#endif
+	int (*write_hwaddr)(struct udevice *dev);
+};
+
+struct udevice *eth_get_dev(void); /* get the current device */
+unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
+int eth_init_state_only(bd_t *bis); /* Set active state */
+void eth_halt_state_only(void); /* Set passive state */
+#endif
+
+#ifndef CONFIG_DM_ETH
 struct eth_device {
 	char name[16];
 	unsigned char enetaddr[6];
diff --git a/net/eth.c b/net/eth.c
index c02548c..1b5a169 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -72,6 +72,320 @@ static int eth_mac_skip(int index)
 	return ((skip_state = getenv(enetvar)) != NULL);
 }
 
+static void eth_current_changed(void);
+
+#ifdef CONFIG_DM_ETH
+#include <dm.h>
+#include <dm/device-internal.h>
+
+struct eth_device_priv {
+	int state;
+	void *priv;
+};
+
+struct eth_uclass_priv {
+	struct udevice *current;
+};
+
+static void eth_set_current_to_next(void)
+{
+	struct uclass *uc;
+	struct eth_uclass_priv *uc_priv;
+
+	uclass_get(UCLASS_ETH, &uc);
+	uc_priv = uc->priv;
+	uclass_next_device(&uc_priv->current);
+	if (!uc_priv->current)
+		uclass_first_device(UCLASS_ETH, &uc_priv->current);
+}
+
+struct udevice *eth_get_dev(void)
+{
+	struct uclass *uc;
+	uclass_get(UCLASS_ETH, &uc);
+
+	struct eth_uclass_priv *uc_priv = uc->priv;
+	return uc_priv->current;
+}
+
+static void eth_set_dev(struct udevice *dev)
+{
+	struct uclass *uc;
+	uclass_get(UCLASS_ETH, &uc);
+
+	struct eth_uclass_priv *uc_priv = uc->priv;
+	uc_priv->current = dev;
+}
+
+unsigned char *eth_get_ethaddr(void)
+{
+	struct eth_pdata *pdata;
+	if (eth_get_dev()) {
+		pdata = eth_get_dev()->platdata;
+		if (pdata)
+			return pdata->enetaddr;
+	}
+	return NULL;
+}
+
+/* Set active state */
+int eth_init_state_only(bd_t *bis)
+{
+	struct eth_device_priv *priv;
+	if (eth_get_dev()) {
+		priv = eth_get_dev()->uclass_priv;
+		if (priv)
+			priv->state = ETH_STATE_ACTIVE;
+	}
+
+	return 0;
+}
+/* Set passive state */
+void eth_halt_state_only(void)
+{
+	struct eth_device_priv *priv;
+	if (eth_get_dev()) {
+		priv = eth_get_dev()->uclass_priv;
+		if (priv)
+			priv->state = ETH_STATE_PASSIVE;
+	}
+}
+
+int eth_get_dev_index(void)
+{
+	if (eth_get_dev())
+		return eth_get_dev()->seq;
+	return -1;
+}
+
+int eth_init(bd_t *bis)
+{
+	struct udevice *current, *old_current, *dev;
+	struct uclass *uc;
+
+	current = eth_get_dev();
+	if (!current) {
+		puts("No ethernet found.\n");
+		return -1;
+	}
+	device_probe(current);
+
+	/* Sync environment with network devices */
+	uclass_get(UCLASS_ETH, &uc);
+	uclass_foreach_dev(dev, uc) {
+		uchar env_enetaddr[6];
+
+		if (eth_getenv_enetaddr_by_index("eth", dev->seq,
+						 env_enetaddr)) {
+			struct eth_pdata *pdata = dev->platdata;
+			if (pdata)
+				memcpy(pdata->enetaddr, env_enetaddr, 6);
+		}
+	};
+
+	old_current = current;
+	do {
+		debug("Trying %s\n", current->name);
+
+		if (current->driver) {
+			const struct eth_ops *ops = current->driver->ops;
+			if (ops->init(current, bis) >= 0) {
+				struct eth_device_priv *priv =
+					current->uclass_priv;
+				if (priv)
+					priv->state = ETH_STATE_ACTIVE;
+
+				return 0;
+			}
+		}
+		debug("FAIL\n");
+
+		eth_try_another(0);
+		current = eth_get_dev();
+	} while (old_current != current);
+
+	return -ENODEV;
+}
+
+void eth_halt(void)
+{
+	struct udevice *current;
+
+	current = eth_get_dev();
+	if (!current)
+		return;
+	if (!current->driver)
+		return;
+
+	const struct eth_ops *ops = current->driver->ops;
+	ops->halt(current);
+
+	struct eth_device_priv *priv = current->uclass_priv;
+	if (priv)
+		priv->state = ETH_STATE_PASSIVE;
+}
+
+int eth_send(void *packet, int length)
+{
+	struct udevice *current;
+
+	current = eth_get_dev();
+	if (!current)
+		return -1;
+	if (!current->driver)
+		return -1;
+
+	const struct eth_ops *ops = current->driver->ops;
+	return ops->send(current, packet, length);
+}
+
+int eth_rx(void)
+{
+	struct udevice *current;
+
+	current = eth_get_dev();
+	if (!current)
+		return -1;
+	if (!current->driver)
+		return -1;
+
+	const struct eth_ops *ops = current->driver->ops;
+	return ops->recv(current);
+}
+
+static int eth_write_hwaddr(struct udevice *dev, const char *base_name,
+		   int eth_number)
+{
+	unsigned char env_enetaddr[6];
+	int ret = 0;
+
+	eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
+
+	struct eth_pdata *pdata = dev->platdata;
+	if (!is_zero_ether_addr(env_enetaddr)) {
+		if (!is_zero_ether_addr(pdata->enetaddr) &&
+		    memcmp(pdata->enetaddr, env_enetaddr, 6)) {
+			printf("\nWarning: %s MAC addresses don't match:\n",
+			       dev->name);
+			printf("Address in SROM is         %pM\n",
+			       pdata->enetaddr);
+			printf("Address in environment is  %pM\n",
+			       env_enetaddr);
+		}
+
+		memcpy(pdata->enetaddr, env_enetaddr, 6);
+	} else if (is_valid_ether_addr(pdata->enetaddr)) {
+		eth_setenv_enetaddr_by_index(base_name, eth_number,
+					     pdata->enetaddr);
+		printf("\nWarning: %s using MAC address from net device\n",
+		       dev->name);
+	} else if (is_zero_ether_addr(pdata->enetaddr)) {
+		printf("\nError: %s address not set.\n",
+		       dev->name);
+		return -EINVAL;
+	}
+
+	const struct eth_ops *ops = dev->driver->ops;
+	if (ops->write_hwaddr && !eth_mac_skip(eth_number)) {
+		if (!is_valid_ether_addr(pdata->enetaddr)) {
+			printf("\nError: %s address %pM illegal value\n",
+			       dev->name, pdata->enetaddr);
+			return -EINVAL;
+		}
+
+		ret = ops->write_hwaddr(dev);
+		if (ret)
+			printf("\nWarning: %s failed to set MAC address\n",
+			       dev->name);
+	}
+
+	return ret;
+}
+
+static int eth_uclass_init(struct uclass *class)
+{
+	bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
+
+	eth_env_init();
+
+	return 0;
+}
+
+static int eth_post_bind(struct udevice *dev)
+{
+	if (strchr(dev->name, ' ')) {
+		printf("\nError: eth device name \"%s\" has a space!\n",
+		       dev->name);
+		return -EINVAL;
+	}
+
+	if (!eth_get_dev()) {
+		eth_set_dev(dev);
+		eth_current_changed();
+	}
+
+	char *ethprime = getenv("ethprime");
+	if (ethprime && strcmp(dev->name, ethprime) == 0) {
+		eth_set_dev(dev);
+		eth_current_changed();
+	}
+
+	/*
+	 * Devices need to write the hwaddr even if not probed so that Linux
+	 * will have access to the hwaddr that u-boot stored for the device.
+	 */
+	eth_write_hwaddr(dev, "eth", uclass_resolve_seq(dev));
+
+	return 0;
+}
+
+static int eth_pre_unbind(struct udevice *dev)
+{
+	struct udevice *first = NULL;
+	struct udevice *current;
+	struct uclass *uc;
+
+	uclass_get(UCLASS_ETH, &uc);
+	uclass_foreach_dev(current, uc) {
+		if (!first)
+			first = current;
+		if (current == dev) {
+			if (dev == first) {
+				current = list_entry(current->uclass_node.next,
+					   struct udevice, uclass_node);
+			} else {
+				current = first;
+			}
+			eth_set_dev(current);
+			eth_current_changed();
+		}
+	}
+
+	return 0;
+}
+
+static int eth_post_probe(struct udevice *dev)
+{
+	struct eth_device_priv *priv = dev->uclass_priv;
+	if (priv)
+		priv->state = ETH_STATE_INIT;
+
+	return 0;
+}
+
+UCLASS_DRIVER(eth) = {
+	.name		= "eth",
+	.id		= UCLASS_ETH,
+	.post_bind	= eth_post_bind,
+	.pre_unbind	= eth_pre_unbind,
+	.post_probe	= eth_post_probe,
+	.init		= eth_uclass_init,
+	.priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
+	.per_device_auto_alloc_size = sizeof(struct eth_device_priv),
+};
+#endif
+
+#ifndef CONFIG_DM_ETH
 /*
  * CPU and board-specific Ethernet initializations.  Aliased function
  * signals caller to move on
@@ -423,6 +737,7 @@ int eth_rx(void)
 
 	return eth_current->recv(eth_current);
 }
+#endif /* ifndef CONFIG_DM_ETH */
 
 #ifdef CONFIG_API
 static void eth_save_packet(void *packet, int length)
@@ -486,7 +801,7 @@ static void eth_current_changed(void)
 
 void eth_try_another(int first_restart)
 {
-	static struct eth_device *first_failed;
+	static void *first_failed;
 	char *ethrotate;
 
 	/*
@@ -515,7 +830,7 @@ void eth_set_current(void)
 {
 	static char *act;
 	static int  env_changed_id;
-	struct eth_device *old_current;
+	void *old_current;
 	int	env_id;
 
 	if (!eth_get_dev())	/* XXX no current */
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 6/8] net: Add network support to sandbox
  2015-02-03  0:38 ` [U-Boot] [RFC PATCH v2 0/8] " Joe Hershberger
                     ` (4 preceding siblings ...)
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 5/8] net: Add basic driver model support to Ethernet stack Joe Hershberger
@ 2015-02-03  0:38   ` Joe Hershberger
  2015-02-07  1:25     ` Simon Glass
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 7/8] net: Add ARP and PING response to sandbox driver Joe Hershberger
                     ` (2 subsequent siblings)
  8 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-03  0:38 UTC (permalink / raw)
  To: u-boot

Add basic network support to sandbox which includes a network driver.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v2:
-Change printfs to debug in sandbox driver
-Remove unused priv struct for sandbox driver

 arch/sandbox/dts/sandbox.dts |  4 +++
 drivers/net/Makefile         |  2 ++
 drivers/net/sandbox.c        | 86 ++++++++++++++++++++++++++++++++++++++++++++
 include/configs/sandbox.h    | 14 +++++---
 4 files changed, 101 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/sandbox.c

diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 4c63e4f..502eb3d 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -183,4 +183,8 @@
 		};
 	};
 
+	eth at 10002000 {
+		compatible = "sandbox,eth";
+		reg = <0x10002000 0x1000>;
+	};
 };
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 46c4ac6..2659a8a 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -50,6 +50,8 @@ obj-$(CONFIG_NS8382X) += ns8382x.o
 obj-$(CONFIG_PCNET) += pcnet.o
 obj-$(CONFIG_RTL8139) += rtl8139.o
 obj-$(CONFIG_RTL8169) += rtl8169.o
+obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
+obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o
 obj-$(CONFIG_SH_ETHER) += sh_eth.o
 obj-$(CONFIG_SMC91111) += smc91111.o
 obj-$(CONFIG_SMC911X) += smc911x.o
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
new file mode 100644
index 0000000..3b7c3ac
--- /dev/null
+++ b/drivers/net/sandbox.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int sb_eth_init(struct udevice *dev, bd_t *bis)
+{
+	debug("eth_sandbox: Init\n");
+
+	return 0;
+}
+
+int sb_eth_send(struct udevice *dev, void *packet, int length)
+{
+	debug("eth_sandbox: Send packet %d\n", length);
+
+	return 0;
+#endif
+}
+
+int sb_eth_recv(struct udevice *dev)
+{
+	return 0;
+}
+
+void sb_eth_halt(struct udevice *dev)
+{
+	debug("eth_sandbox: Halt\n");
+}
+
+int sb_eth_write_hwaddr(struct udevice *dev)
+{
+	debug("eth_sandbox: Write HW ADDR\n");
+	return 0;
+}
+
+static const struct eth_ops eth_sandbox_ops = {
+	.init			= sb_eth_init,
+	.send			= sb_eth_send,
+	.recv			= sb_eth_recv,
+	.halt			= sb_eth_halt,
+	.write_hwaddr		= sb_eth_write_hwaddr,
+};
+
+static int eth_sandbox_remove(struct udevice *dev)
+{
+	return 0;
+}
+
+#ifdef CONFIG_OF_CONTROL
+static int sandbox_eth_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev->platdata;
+
+	pdata->iobase = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
+	return 0;
+}
+
+static const struct udevice_id sandbox_eth_ids[] = {
+	{ .compatible = "sandbox,eth" },
+	{ }
+};
+#endif
+
+U_BOOT_DRIVER(eth_sandbox) = {
+	.name	= "eth_sandbox",
+	.id	= UCLASS_ETH,
+	.of_match = of_match_ptr(sandbox_eth_ids),
+	.ofdata_to_platdata = of_match_ptr(sandbox_eth_ofdata_to_platdata),
+	.remove	= eth_sandbox_remove,
+	.ops	= &eth_sandbox_ops,
+	.priv_auto_alloc_size = sizeof(struct eth_sandbox_priv),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index e9d3f32..484caa8 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -139,9 +139,9 @@
 /* include default commands */
 #include <config_cmd_default.h>
 
-/* We don't have networking support yet */
-#undef CONFIG_CMD_NET
-#undef CONFIG_CMD_NFS
+#define CONFIG_DM_ETH
+#define CONFIG_ETH_SANDBOX
+#define CONFIG_CMD_PING
 
 #define CONFIG_CMD_HASH
 #define CONFIG_HASH_VERIFY
@@ -184,12 +184,16 @@
 
 #define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial,cros-ec-keyb\0" \
 					"stdout=serial,lcd\0" \
-					"stderr=serial,lcd\0"
+					"stderr=serial,lcd\0" \
+					"ethaddr=00:00:11:22:33:44\0" \
+					"ipaddr=1.2.3.4\0"
 #else
 
 #define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial\0" \
 					"stdout=serial,lcd\0" \
-					"stderr=serial,lcd\0"
+					"stderr=serial,lcd\0" \
+					"ethaddr=00:00:11:22:33:44\0" \
+					"ipaddr=1.2.3.4\0"
 #endif
 
 #define CONFIG_GZIP_COMPRESSED
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 7/8] net: Add ARP and PING response to sandbox driver
  2015-02-03  0:38 ` [U-Boot] [RFC PATCH v2 0/8] " Joe Hershberger
                     ` (5 preceding siblings ...)
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 6/8] net: Add network support to sandbox Joe Hershberger
@ 2015-02-03  0:38   ` Joe Hershberger
  2015-02-07  1:25     ` Simon Glass
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 8/8] net: Add actual networking support to sandbox's driver Joe Hershberger
  2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
  8 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-03  0:38 UTC (permalink / raw)
  To: u-boot

The sandbox driver will now generate response traffic to exercise the
ping command even when no network exists.  This allows the basic data
pathways of the DM to be tested.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
---

Changes in v2:
-Change printfs to debug in sandbox driver
-Move static data to priv
-Move fake hwaddr to the device tree

 arch/sandbox/dts/sandbox.dts |  1 +
 drivers/net/sandbox.c        | 95 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 96 insertions(+)

diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 502eb3d..ba635e8 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -186,5 +186,6 @@
 	eth at 10002000 {
 		compatible = "sandbox,eth";
 		reg = <0x10002000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
 	};
 };
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
index 3b7c3ac..79a2fd5 100644
--- a/drivers/net/sandbox.c
+++ b/drivers/net/sandbox.c
@@ -15,16 +15,102 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+struct eth_sandbox_priv {
+	uchar fake_host_hwaddr[ARP_HLEN];
+	IPaddr_t fake_host_ipaddr;
+	uchar recv_packet_buffer[PKTSIZE];
+	int recv_packet_length;
+};
+
 int sb_eth_init(struct udevice *dev, bd_t *bis)
 {
 	debug("eth_sandbox: Init\n");
 
+	struct eth_sandbox_priv *priv = dev->priv;
+	u32 int_array[ARP_HLEN];
+	int i;
+
+	fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "fake-host-hwaddr",
+			     int_array, ARP_HLEN);
+	for (i = 0; i < ARP_HLEN; i++)
+		priv->fake_host_hwaddr[i] = (uchar)int_array[i];
+
 	return 0;
 }
 
 int sb_eth_send(struct udevice *dev, void *packet, int length)
 {
 	debug("eth_sandbox: Send packet %d\n", length);
+	struct eth_sandbox_priv *priv = dev->priv;
+
+	struct ethernet_hdr *eth = packet;
+	if (ntohs(eth->et_protlen) == PROT_ARP) {
+		struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
+		if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
+			/* store this as the assumed IP of the fake host */
+			priv->fake_host_ipaddr = NetReadIP(&arp->ar_tpa);
+			/* Formulate a fake response */
+			struct ethernet_hdr *eth_recv =
+				(void *)priv->recv_packet_buffer;
+			memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
+			memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
+			       ARP_HLEN);
+			eth_recv->et_protlen = htons(PROT_ARP);
+
+			struct arp_hdr *arp_recv =
+				(void *)priv->recv_packet_buffer +
+				ETHER_HDR_SIZE;
+			arp_recv->ar_hrd = htons(ARP_ETHER);
+			arp_recv->ar_pro = htons(PROT_IP);
+			arp_recv->ar_hln = ARP_HLEN;
+			arp_recv->ar_pln = ARP_PLEN;
+			arp_recv->ar_op = htons(ARPOP_REPLY);
+			memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr,
+			       ARP_HLEN);
+			NetWriteIP(&arp_recv->ar_spa, priv->fake_host_ipaddr);
+			memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN);
+			NetCopyIP(&arp_recv->ar_tpa, &arp->ar_spa);
+
+			priv->recv_packet_length = ETHER_HDR_SIZE +
+				ARP_HDR_SIZE;
+		}
+	} else if (ntohs(eth->et_protlen) == PROT_IP) {
+		struct ip_udp_hdr *ip = packet + ETHER_HDR_SIZE;
+		if (ip->ip_p == IPPROTO_ICMP) {
+			struct icmp_hdr *icmp = (struct icmp_hdr *)&ip->udp_src;
+			if (icmp->type == ICMP_ECHO_REQUEST) {
+				/* reply to the ping */
+				memcpy(priv->recv_packet_buffer, packet,
+				       length);
+				struct ethernet_hdr *eth_recv =
+					(void *)priv->recv_packet_buffer;
+				struct ip_udp_hdr *ipr =
+					(void *)priv->recv_packet_buffer +
+					ETHER_HDR_SIZE;
+				struct icmp_hdr *icmpr =
+					(struct icmp_hdr *)&ipr->udp_src;
+				memcpy(eth_recv->et_dest, eth->et_src,
+				       ARP_HLEN);
+				memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
+				       ARP_HLEN);
+				ipr->ip_sum = 0;
+				ipr->ip_off = 0;
+				NetCopyIP((void *)&ipr->ip_dst, &ip->ip_src);
+				NetWriteIP((void *)&ipr->ip_src,
+					   priv->fake_host_ipaddr);
+				ipr->ip_sum = ~NetCksum((uchar *)ipr,
+					IP_HDR_SIZE >> 1);
+
+				icmpr->type = ICMP_ECHO_REPLY;
+				icmpr->checksum = 0;
+				icmpr->checksum = ~NetCksum((uchar *)icmpr,
+					(length - ETHER_HDR_SIZE -
+						IP_HDR_SIZE) >> 1);
+
+				priv->recv_packet_length = length;
+			}
+		}
+	}
 
 	return 0;
 #endif
@@ -32,6 +118,15 @@ int sb_eth_send(struct udevice *dev, void *packet, int length)
 
 int sb_eth_recv(struct udevice *dev)
 {
+	struct eth_sandbox_priv *priv = dev->priv;
+	if (priv->recv_packet_length) {
+		int lcl_recv_packet_length = priv->recv_packet_length;
+		debug("eth_sandbox: received packet %d\n",
+		      priv->recv_packet_length);
+		priv->recv_packet_length = 0;
+		NetReceive((void *)priv->recv_packet_buffer,
+			   lcl_recv_packet_length);
+	}
 	return 0;
 }
 
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 8/8] net: Add actual networking support to sandbox's driver
  2015-02-03  0:38 ` [U-Boot] [RFC PATCH v2 0/8] " Joe Hershberger
                     ` (6 preceding siblings ...)
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 7/8] net: Add ARP and PING response to sandbox driver Joe Hershberger
@ 2015-02-03  0:38   ` Joe Hershberger
  2015-02-07  1:25     ` Simon Glass
  2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
  8 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-03  0:38 UTC (permalink / raw)
  To: u-boot

This doesn't build right now

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v2:
-Added the raw packet proof-of-concept patch.

 drivers/net/sandbox-raw.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/sandbox.c     | 23 ++++++++++++++++++
 2 files changed, 83 insertions(+)
 create mode 100644 drivers/net/sandbox-raw.c

diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
new file mode 100644
index 0000000..735783c
--- /dev/null
+++ b/drivers/net/sandbox-raw.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+int sandbox_raw_init(int *sd, void **devp)
+{
+	uint8_t eth0mac[6];
+	int tempsd = 0;
+	struct ifreq ifr;
+	const char *ifname = "eth0";
+
+	strcpy(ifr.ifr_name, ifname);
+	ifr.ifr_addr.sa_family = AF_INET;
+	memset(eth0mac, 0, 6);
+	tempsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+	if (tempsd < 0)
+		return 1;
+	if (ioctl(tempsd, SIOCGIFHWADDR, &ifr) < 0) {
+		close(tempsd);
+		return 1;
+	}
+	memcpy(eth0mac, ifr.ifr_hwaddr.sa_data, 6 * sizeof(uint8_t));
+	close(tempsd);
+
+	*devp = malloc(sizeof(struct sockaddr_ll));
+	struct sockaddr_ll *device = *devp;
+	memset(device, 0, sizeof(struct sockaddr_ll));
+	device->sll_ifindex = if_nametoindex(ifname);
+	device->sll_family = AF_PACKET;
+	memcpy(device->sll_addr, eth0mac, 6);
+	device->sll_halen = htons(6);
+
+	*sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+
+	return 0;
+}
+
+int sandbox_raw_send(void *packet, int length, int sd, void *device)
+{
+	if (sendto(sd, packet, length, 0,
+		   (struct sockaddr *)device, sizeof(struct sockaddr)) <= 0)
+		return 1;
+	return 0;
+}
+
+int sandbox_raw_halt(int sd)
+{
+	close(sd);
+}
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
index 79a2fd5..c5113b4 100644
--- a/drivers/net/sandbox.c
+++ b/drivers/net/sandbox.c
@@ -20,8 +20,18 @@ struct eth_sandbox_priv {
 	IPaddr_t fake_host_ipaddr;
 	uchar recv_packet_buffer[PKTSIZE];
 	int recv_packet_length;
+#ifdef CONFIG_ETH_SANDBOX_RAW
+	void *device;
+	int sd;
+#endif
 };
 
+#ifdef CONFIG_ETH_SANDBOX_RAW
+int sandbox_raw_init(int *sd, void **devp);
+int sandbox_raw_send(void *packet, int length, int sd, void *device);
+int sandbox_raw_halt(int sd);
+#endif
+
 int sb_eth_init(struct udevice *dev, bd_t *bis)
 {
 	debug("eth_sandbox: Init\n");
@@ -35,6 +45,11 @@ int sb_eth_init(struct udevice *dev, bd_t *bis)
 	for (i = 0; i < ARP_HLEN; i++)
 		priv->fake_host_hwaddr[i] = (uchar)int_array[i];
 
+#ifdef CONFIG_ETH_SANDBOX_RAW
+	int ret = sandbox_raw_init(&(priv->sd), &(priv->device));
+	if (ret)
+		return ret;
+#endif
 	return 0;
 }
 
@@ -43,6 +58,9 @@ int sb_eth_send(struct udevice *dev, void *packet, int length)
 	debug("eth_sandbox: Send packet %d\n", length);
 	struct eth_sandbox_priv *priv = dev->priv;
 
+#ifdef CONFIG_ETH_SANDBOX_RAW
+	return sandbox_raw_send(packet, length, priv->sd, priv->device);
+#else
 	struct ethernet_hdr *eth = packet;
 	if (ntohs(eth->et_protlen) == PROT_ARP) {
 		struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
@@ -133,6 +151,11 @@ int sb_eth_recv(struct udevice *dev)
 void sb_eth_halt(struct udevice *dev)
 {
 	debug("eth_sandbox: Halt\n");
+
+#ifdef CONFIG_ETH_SANDBOX_RAW
+	struct eth_sandbox_priv *priv = dev->priv;
+	sandbox_raw_halt(priv->sd);
+#endif
 }
 
 int sb_eth_write_hwaddr(struct udevice *dev)
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 1/8] net: Provide a function to get the current MAC address
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 1/8] net: Provide a function to get the current MAC address Joe Hershberger
@ 2015-02-07  1:25     ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-07  1:25 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 2 February 2015 at 17:38, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The current implementation exposes the eth_device struct to code that
> needs to access the MAC address.  Add a wrapper function for this to
> abstract away the pointer for this operation.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> ---
>
> Changes in v2: None
>
>  arch/mips/cpu/mips32/au1x00/au1x00_eth.c | 2 +-
>  arch/powerpc/cpu/mpc8260/ether_fcc.c     | 2 +-
>  arch/powerpc/cpu/mpc85xx/ether_fcc.c     | 2 +-
>  arch/powerpc/cpu/mpc8xx/scc.c            | 2 +-
>  include/net.h                            | 8 ++++++++
>  net/net.c                                | 2 +-
>  6 files changed, 13 insertions(+), 5 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

I think the first file might have been dropped.

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 2/8] net: Rename helper function to be more clear
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 2/8] net: Rename helper function to be more clear Joe Hershberger
@ 2015-02-07  1:25     ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-07  1:25 UTC (permalink / raw)
  To: u-boot

On 2 February 2015 at 17:38, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Make it clear that the helper is checking the addr, not setting it.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

Reviewed-by: Simon Glass <sjg@chromium.org>

> ---
>
> Changes in v2: None
>
>  net/eth.c | 13 ++++---------
>  1 file changed, 4 insertions(+), 9 deletions(-)
>
> diff --git a/net/eth.c b/net/eth.c
> index eac4f7b..65e8c77 100644
> --- a/net/eth.c
> +++ b/net/eth.c
> @@ -153,11 +153,6 @@ static void eth_current_changed(void)
>                 setenv("ethact", NULL);
>  }
>
> -static int eth_address_set(unsigned char *addr)
> -{
> -       return memcmp(addr, "\0\0\0\0\0\0", 6);
> -}
> -
>  int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
>                    int eth_number)
>  {
> @@ -166,9 +161,9 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
>
>         eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
>
> -       if (eth_address_set(env_enetaddr)) {
> -               if (eth_address_set(dev->enetaddr) &&
> -                               memcmp(dev->enetaddr, env_enetaddr, 6)) {
> +       if (!is_zero_ether_addr(env_enetaddr)) {
> +               if (!is_zero_ether_addr(dev->enetaddr) &&
> +                   memcmp(dev->enetaddr, env_enetaddr, 6)) {
>                         printf("\nWarning: %s MAC addresses don't match:\n",
>                                 dev->name);
>                         printf("Address in SROM is         %pM\n",
> @@ -183,7 +178,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
>                                              dev->enetaddr);
>                 printf("\nWarning: %s using MAC address from net device\n",
>                         dev->name);
> -       } else if (!(eth_address_set(dev->enetaddr))) {
> +       } else if (is_zero_ether_addr(dev->enetaddr)) {
>                 printf("\nError: %s address not set.\n",
>                        dev->name);
>                 return -EINVAL;
> --
> 1.7.11.5
>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 3/8] net: Remove unneeded "extern" in net.h
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 3/8] net: Remove unneeded "extern" in net.h Joe Hershberger
@ 2015-02-07  1:25     ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-07  1:25 UTC (permalink / raw)
  To: u-boot

On 2 February 2015 at 17:38, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Many of the functions in net.h were preceded extern needlessly. Removing
> them to limit the number of checkpatch.pl complaints.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

I think you dropped my tag on these?

Reviewed-by: Simon Glass <sjg@chromium.org>


> ---
>
> Changes in v2: None
>
>  include/net.h | 96 +++++++++++++++++++++++++++++------------------------------
>  1 file changed, 48 insertions(+), 48 deletions(-)
>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 4/8] net: Refactor in preparation for driver model
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 4/8] net: Refactor in preparation for driver model Joe Hershberger
@ 2015-02-07  1:25     ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-07  1:25 UTC (permalink / raw)
  To: u-boot

On 2 February 2015 at 17:38, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Move some things around and organize things so that the driver model
> implementation will fit in more easily.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> ---
>
> Changes in v2: None
>
>  include/net.h | 63 +++++++++++++++++++++++++------------------------
>  net/eth.c     | 75 +++++++++++++++++++++++++++++++----------------------------
>  2 files changed, 73 insertions(+), 65 deletions(-)

No changes so:

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 5/8] net: Add basic driver model support to Ethernet stack
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 5/8] net: Add basic driver model support to Ethernet stack Joe Hershberger
@ 2015-02-07  1:25     ` Simon Glass
  2015-02-11  6:25       ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-02-07  1:25 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 2 February 2015 at 17:38, Joe Hershberger <joe.hershberger@ni.com> wrote:
> First just add support for MAC drivers.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v2:
> -Updated comments
> -Removed extra parentheses
> -Changed eth_uclass_priv local var names to be uc_priv
> -Update error codes
> -Cause an invalid name to fail binding
> -Rebase on top of dm/master
> -Stop maintaining our own index and use DM seq now that it works for our needs
> -Move the hwaddr to platdata so that its memory is allocated at bind when we need it
> -Prevent device from being probed before used by a command (i.e. before eth_init()).
>
>  common/board_r.c       |   4 +-
>  common/cmd_bdinfo.c    |   2 +
>  include/dm/uclass-id.h |   1 +
>  include/net.h          |  24 ++++
>  net/eth.c              | 319 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  5 files changed, 346 insertions(+), 4 deletions(-)
>
> diff --git a/common/board_r.c b/common/board_r.c
> index 68a9448..75147b7 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -556,7 +556,7 @@ static int initr_bbmii(void)
>  }
>  #endif
>
> -#ifdef CONFIG_CMD_NET
> +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
>  static int initr_net(void)
>  {
>         puts("Net:   ");
> @@ -825,7 +825,7 @@ init_fnc_t init_sequence_r[] = {
>  #ifdef CONFIG_BITBANGMII
>         initr_bbmii,
>  #endif
> -#ifdef CONFIG_CMD_NET
> +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
>         INIT_FUNC_WATCHDOG_RESET
>         initr_net,
>  #endif
> diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
> index e6d8a7a..8688cf9 100644
> --- a/common/cmd_bdinfo.c
> +++ b/common/cmd_bdinfo.c
> @@ -34,6 +34,7 @@ static void print_eth(int idx)
>         printf("%-12s= %s\n", name, val);
>  }
>
> +#ifndef CONFIG_DM_ETH
>  __maybe_unused
>  static void print_eths(void)
>  {
> @@ -52,6 +53,7 @@ static void print_eths(void)
>         printf("current eth = %s\n", eth_get_name());
>         printf("ip_addr     = %s\n", getenv("ipaddr"));
>  }
> +#endif
>
>  __maybe_unused
>  static void print_lnum(const char *name, unsigned long long value)
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index 91bb90d..ad96682 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -34,6 +34,7 @@ enum uclass_id {
>         UCLASS_I2C_GENERIC,     /* Generic I2C device */
>         UCLASS_I2C_EEPROM,      /* I2C EEPROM device */
>         UCLASS_MOD_EXP,         /* RSA Mod Exp device */
> +       UCLASS_ETH,             /* Ethernet device */
>
>         UCLASS_COUNT,
>         UCLASS_INVALID = -1,
> diff --git a/include/net.h b/include/net.h
> index 7eef9cc..4d21d91 100644
> --- a/include/net.h
> +++ b/include/net.h
> @@ -78,6 +78,30 @@ enum eth_state_t {
>         ETH_STATE_ACTIVE
>  };
>
> +#ifdef CONFIG_DM_ETH

You may not need this?

> +struct eth_pdata {
> +       phys_addr_t iobase;
> +       unsigned char enetaddr[6];
> +};
> +
> +struct eth_ops {
> +       int (*init)(struct udevice *dev, bd_t *bis);
> +       int (*send)(struct udevice *dev, void *packet, int length);
> +       int (*recv)(struct udevice *dev);
> +       void (*halt)(struct udevice *dev);
> +#ifdef CONFIG_MCAST_TFTP
> +       int (*mcast)(struct udevice *dev, const u8 *enetaddr, u8 set);
> +#endif
> +       int (*write_hwaddr)(struct udevice *dev);
> +};
> +
> +struct udevice *eth_get_dev(void); /* get the current device */
> +unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
> +int eth_init_state_only(bd_t *bis); /* Set active state */
> +void eth_halt_state_only(void); /* Set passive state */
> +#endif
> +
> +#ifndef CONFIG_DM_ETH
>  struct eth_device {
>         char name[16];
>         unsigned char enetaddr[6];
> diff --git a/net/eth.c b/net/eth.c
> index c02548c..1b5a169 100644
> --- a/net/eth.c
> +++ b/net/eth.c
> @@ -72,6 +72,320 @@ static int eth_mac_skip(int index)
>         return ((skip_state = getenv(enetvar)) != NULL);
>  }
>
> +static void eth_current_changed(void);
> +
> +#ifdef CONFIG_DM_ETH
> +#include <dm.h>
> +#include <dm/device-internal.h>

These should go at the top of the file - should be OK to always
include them (i.e. no #ifdef)

> +
> +struct eth_device_priv {
> +       int state;
> +       void *priv;
> +};
> +
> +struct eth_uclass_priv {
> +       struct udevice *current;
> +};
> +
> +static void eth_set_current_to_next(void)
> +{
> +       struct uclass *uc;
> +       struct eth_uclass_priv *uc_priv;
> +
> +       uclass_get(UCLASS_ETH, &uc);

This can actually return an error, although I agree there is little
point in handling it. So I suppose this is OK.

> +       uc_priv = uc->priv;
> +       uclass_next_device(&uc_priv->current);
> +       if (!uc_priv->current)
> +               uclass_first_device(UCLASS_ETH, &uc_priv->current);
> +}
> +
> +struct udevice *eth_get_dev(void)
> +{
> +       struct uclass *uc;

blank line here

> +       uclass_get(UCLASS_ETH, &uc);
> +
> +       struct eth_uclass_priv *uc_priv = uc->priv;
> +       return uc_priv->current;
> +}
> +
> +static void eth_set_dev(struct udevice *dev)
> +{
> +       struct uclass *uc;

blank line here

> +       uclass_get(UCLASS_ETH, &uc);
> +
> +       struct eth_uclass_priv *uc_priv = uc->priv;
> +       uc_priv->current = dev;
> +}
> +
> +unsigned char *eth_get_ethaddr(void)
> +{
> +       struct eth_pdata *pdata;

blank line here

> +       if (eth_get_dev()) {
> +               pdata = eth_get_dev()->platdata;
> +               if (pdata)
> +                       return pdata->enetaddr;
> +       }
> +       return NULL;
> +}
> +
> +/* Set active state */
> +int eth_init_state_only(bd_t *bis)
> +{
> +       struct eth_device_priv *priv;

blank line here

> +       if (eth_get_dev()) {
> +               priv = eth_get_dev()->uclass_priv;
> +               if (priv)
> +                       priv->state = ETH_STATE_ACTIVE;
> +       }
> +
> +       return 0;
> +}
> +/* Set passive state */
> +void eth_halt_state_only(void)
> +{
> +       struct eth_device_priv *priv;

blank line here

> +       if (eth_get_dev()) {
> +               priv = eth_get_dev()->uclass_priv;
> +               if (priv)
> +                       priv->state = ETH_STATE_PASSIVE;
> +       }
> +}
> +
> +int eth_get_dev_index(void)
> +{
> +       if (eth_get_dev())
> +               return eth_get_dev()->seq;
> +       return -1;
> +}
> +
> +int eth_init(bd_t *bis)
> +{
> +       struct udevice *current, *old_current, *dev;
> +       struct uclass *uc;
> +
> +       current = eth_get_dev();
> +       if (!current) {
> +               puts("No ethernet found.\n");
> +               return -1;
> +       }
> +       device_probe(current);

Check error

> +
> +       /* Sync environment with network devices */
> +       uclass_get(UCLASS_ETH, &uc);
> +       uclass_foreach_dev(dev, uc) {
> +               uchar env_enetaddr[6];
> +
> +               if (eth_getenv_enetaddr_by_index("eth", dev->seq,
> +                                                env_enetaddr)) {
> +                       struct eth_pdata *pdata = dev->platdata;

blank line

Do all devices have the same platdata by design? What if a particular
device wants its own?

> +                       if (pdata)

What do you need this check?

> +                               memcpy(pdata->enetaddr, env_enetaddr, 6);
> +               }
> +       };
> +
> +       old_current = current;
> +       do {
> +               debug("Trying %s\n", current->name);
> +
> +               if (current->driver) {
> +                       const struct eth_ops *ops = current->driver->ops;

blank line

> +                       if (ops->init(current, bis) >= 0) {
> +                               struct eth_device_priv *priv =
> +                                       current->uclass_priv;
> +                               if (priv)
> +                                       priv->state = ETH_STATE_ACTIVE;
> +
> +                               return 0;
> +                       }
> +               }
> +               debug("FAIL\n");
> +
> +               eth_try_another(0);
> +               current = eth_get_dev();
> +       } while (old_current != current);
> +
> +       return -ENODEV;
> +}
> +
> +void eth_halt(void)
> +{
> +       struct udevice *current;
> +
> +       current = eth_get_dev();
> +       if (!current)
> +               return;
> +       if (!current->driver)
> +               return;
> +
> +       const struct eth_ops *ops = current->driver->ops;
> +       ops->halt(current);
> +
> +       struct eth_device_priv *priv = current->uclass_priv;
> +       if (priv)
> +               priv->state = ETH_STATE_PASSIVE;
> +}
> +
> +int eth_send(void *packet, int length)
> +{
> +       struct udevice *current;
> +
> +       current = eth_get_dev();
> +       if (!current)
> +               return -1;
> +       if (!current->driver)
> +               return -1;

Seems like eth_get_dev() should return an error code if current or
current->driver is NULL.

> +
> +       const struct eth_ops *ops = current->driver->ops;
> +       return ops->send(current, packet, length);
> +}
> +
> +int eth_rx(void)
> +{
> +       struct udevice *current;
> +
> +       current = eth_get_dev();
> +       if (!current)
> +               return -1;
> +       if (!current->driver)
> +               return -1;
> +
> +       const struct eth_ops *ops = current->driver->ops;
> +       return ops->recv(current);
> +}
> +
> +static int eth_write_hwaddr(struct udevice *dev, const char *base_name,
> +                  int eth_number)
> +{
> +       unsigned char env_enetaddr[6];
> +       int ret = 0;
> +
> +       eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
> +
> +       struct eth_pdata *pdata = dev->platdata;
> +       if (!is_zero_ether_addr(env_enetaddr)) {
> +               if (!is_zero_ether_addr(pdata->enetaddr) &&
> +                   memcmp(pdata->enetaddr, env_enetaddr, 6)) {
> +                       printf("\nWarning: %s MAC addresses don't match:\n",
> +                              dev->name);
> +                       printf("Address in SROM is         %pM\n",
> +                              pdata->enetaddr);
> +                       printf("Address in environment is  %pM\n",
> +                              env_enetaddr);
> +               }
> +
> +               memcpy(pdata->enetaddr, env_enetaddr, 6);
> +       } else if (is_valid_ether_addr(pdata->enetaddr)) {
> +               eth_setenv_enetaddr_by_index(base_name, eth_number,
> +                                            pdata->enetaddr);
> +               printf("\nWarning: %s using MAC address from net device\n",
> +                      dev->name);
> +       } else if (is_zero_ether_addr(pdata->enetaddr)) {
> +               printf("\nError: %s address not set.\n",
> +                      dev->name);
> +               return -EINVAL;
> +       }
> +
> +       const struct eth_ops *ops = dev->driver->ops;
> +       if (ops->write_hwaddr && !eth_mac_skip(eth_number)) {
> +               if (!is_valid_ether_addr(pdata->enetaddr)) {
> +                       printf("\nError: %s address %pM illegal value\n",
> +                              dev->name, pdata->enetaddr);
> +                       return -EINVAL;
> +               }
> +
> +               ret = ops->write_hwaddr(dev);
> +               if (ret)
> +                       printf("\nWarning: %s failed to set MAC address\n",
> +                              dev->name);
> +       }

The above code seems mostly duplicated but I suppose it is hard to
make it common?

> +
> +       return ret;
> +}
> +
> +static int eth_uclass_init(struct uclass *class)
> +{
> +       bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
> +
> +       eth_env_init();
> +
> +       return 0;
> +}
> +
> +static int eth_post_bind(struct udevice *dev)
> +{
> +       if (strchr(dev->name, ' ')) {
> +               printf("\nError: eth device name \"%s\" has a space!\n",
> +                      dev->name);
> +               return -EINVAL;
> +       }
> +
> +       if (!eth_get_dev()) {
> +               eth_set_dev(dev);
> +               eth_current_changed();
> +       }

I still don't really get what you are doing here. Perhaps you could
add some comments? There should be no probed devices at this stage
since you are binding only.

> +
> +       char *ethprime = getenv("ethprime");
> +       if (ethprime && strcmp(dev->name, ethprime) == 0) {
> +               eth_set_dev(dev);
> +               eth_current_changed();
> +       }
> +
> +       /*
> +        * Devices need to write the hwaddr even if not probed so that Linux
> +        * will have access to the hwaddr that u-boot stored for the device.
> +        */
> +       eth_write_hwaddr(dev, "eth", uclass_resolve_seq(dev));
> +
> +       return 0;
> +}
> +
> +static int eth_pre_unbind(struct udevice *dev)
> +{
> +       struct udevice *first = NULL;
> +       struct udevice *current;
> +       struct uclass *uc;
> +
> +       uclass_get(UCLASS_ETH, &uc);
> +       uclass_foreach_dev(current, uc) {
> +               if (!first)
> +                       first = current;
> +               if (current == dev) {
> +                       if (dev == first) {
> +                               current = list_entry(current->uclass_node.next,
> +                                          struct udevice, uclass_node);
> +                       } else {
> +                               current = first;
> +                       }
> +                       eth_set_dev(current);
> +                       eth_current_changed();
> +               }
> +       }

If this is turning down a device it really should happen in a remove()
method. Maybe in post_remove()?

> +
> +       return 0;
> +}
> +
> +static int eth_post_probe(struct udevice *dev)
> +{
> +       struct eth_device_priv *priv = dev->uclass_priv;
> +       if (priv)
> +               priv->state = ETH_STATE_INIT;
> +
> +       return 0;
> +}
> +
> +UCLASS_DRIVER(eth) = {
> +       .name           = "eth",
> +       .id             = UCLASS_ETH,
> +       .post_bind      = eth_post_bind,
> +       .pre_unbind     = eth_pre_unbind,
> +       .post_probe     = eth_post_probe,
> +       .init           = eth_uclass_init,
> +       .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
> +       .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
> +};
> +#endif
> +
> +#ifndef CONFIG_DM_ETH
>  /*
>   * CPU and board-specific Ethernet initializations.  Aliased function
>   * signals caller to move on
> @@ -423,6 +737,7 @@ int eth_rx(void)
>
>         return eth_current->recv(eth_current);
>  }
> +#endif /* ifndef CONFIG_DM_ETH */
>
>  #ifdef CONFIG_API
>  static void eth_save_packet(void *packet, int length)
> @@ -486,7 +801,7 @@ static void eth_current_changed(void)
>
>  void eth_try_another(int first_restart)
>  {
> -       static struct eth_device *first_failed;
> +       static void *first_failed;
>         char *ethrotate;
>
>         /*
> @@ -515,7 +830,7 @@ void eth_set_current(void)
>  {
>         static char *act;
>         static int  env_changed_id;
> -       struct eth_device *old_current;
> +       void *old_current;
>         int     env_id;
>
>         if (!eth_get_dev())     /* XXX no current */
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 6/8] net: Add network support to sandbox
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 6/8] net: Add network support to sandbox Joe Hershberger
@ 2015-02-07  1:25     ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-07  1:25 UTC (permalink / raw)
  To: u-boot

On 2 February 2015 at 17:38, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Add basic network support to sandbox which includes a network driver.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v2:
> -Change printfs to debug in sandbox driver
> -Remove unused priv struct for sandbox driver
>
>  arch/sandbox/dts/sandbox.dts |  4 +++
>  drivers/net/Makefile         |  2 ++
>  drivers/net/sandbox.c        | 86 ++++++++++++++++++++++++++++++++++++++++++++
>  include/configs/sandbox.h    | 14 +++++---
>  4 files changed, 101 insertions(+), 5 deletions(-)
>  create mode 100644 drivers/net/sandbox.c

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 7/8] net: Add ARP and PING response to sandbox driver
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 7/8] net: Add ARP and PING response to sandbox driver Joe Hershberger
@ 2015-02-07  1:25     ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-07  1:25 UTC (permalink / raw)
  To: u-boot

On 2 February 2015 at 17:38, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The sandbox driver will now generate response traffic to exercise the
> ping command even when no network exists.  This allows the basic data
> pathways of the DM to be tested.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> ---
>
> Changes in v2:
> -Change printfs to debug in sandbox driver
> -Move static data to priv
> -Move fake hwaddr to the device tree
>
>  arch/sandbox/dts/sandbox.dts |  1 +
>  drivers/net/sandbox.c        | 95 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 96 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 8/8] net: Add actual networking support to sandbox's driver
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 8/8] net: Add actual networking support to sandbox's driver Joe Hershberger
@ 2015-02-07  1:25     ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-07  1:25 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 2 February 2015 at 17:38, Joe Hershberger <joe.hershberger@ni.com> wrote:
> This doesn't build right now
>

Is this intended to connect sandbox to the real network? Very interesting if so.

> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v2:
> -Added the raw packet proof-of-concept patch.
>
>  drivers/net/sandbox-raw.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/sandbox.c     | 23 ++++++++++++++++++
>  2 files changed, 83 insertions(+)
>  create mode 100644 drivers/net/sandbox-raw.c

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack
  2015-02-03  0:38 ` [U-Boot] [RFC PATCH v2 0/8] " Joe Hershberger
                     ` (7 preceding siblings ...)
  2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 8/8] net: Add actual networking support to sandbox's driver Joe Hershberger
@ 2015-02-11  1:30   ` Joe Hershberger
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 01/14] dm: core: Allow seq numbers to be resolved before probe Joe Hershberger
                       ` (14 more replies)
  8 siblings, 15 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-02-11  1:30 UTC (permalink / raw)
  To: u-boot

For now this simply addresses the MAC part of the network hardware.
The next part to implement is the PHY children.  I wanted to get early
feedback on what I have so far to make sure I'm going in the direction
that Simon envisioned.

I've now added unit tests to verify functionality.

Added an additional patch that I've been playing with to allow actual
networking from within sandbox, but I haven't come across a good way
to make it build in the u-boot build system. Any good ideas are welcome.

Changes in v3:
-Add seq patch to dm core
-Reorder dm test makefile
-Move the get_dev_by_* protos to also be !DM_ETH like the impl
-Correct the pre_unbind logic
-Correct failure chaining from bind to probe to init
--Fail init if not activated
--Fail probe if ethaddr not set
-Update ethaddr from env unconditionally on init
-Use set current to select the current device regardless of the previous selection
-Allow current eth dev to be NULL
-Fixed blank line formatting for variable declaration
-Added 2 more ethaddr to sandbox
-Print which device in the debug write hwaddr
-Prevent a crash if memory is not allocated
-Added dm eth testing
-Added support for aliases
-Added support for ethprime
-Added testing for netretry
-Made the os raw packet support for sandbox eth build and work.

Changes in v2:
-Updated comments
-Removed extra parentheses
-Changed eth_uclass_priv local var names to be uc_priv
-Update error codes
-Cause an invalid name to fail binding
-Rebase on top of dm/master
-Stop maintaining our own index and use DM seq now that it works for our needs
-Move the hwaddr to platdata so that its memory is allocated at bind when we need it
-Prevent device from being probed before used by a command (i.e. before eth_init()).
-Change printfs to debug in sandbox driver
-Remove unused priv struct for sandbox driver
-Change printfs to debug in sandbox driver
-Move static data to priv
-Move fake hwaddr to the device tree
-Added the raw packet proof-of-concept patch.

Joe Hershberger (14):
  dm: core: Allow seq numbers to be resolved before probe
  test: dm: Reorder the objects to build
  net: Provide a function to get the current MAC address
  net: Rename helper function to be more clear
  net: Remove unneeded "extern" in net.h
  net: Refactor in preparation for driver model
  dm: eth: Add basic driver model support to Ethernet stack
  dm: eth: Add network support to sandbox
  dm: eth: Add ARP and PING response to sandbox driver
  test: dm: eth: Add tests for the eth dm implementation
  dm: eth: Add support for aliases
  dm: eth: Add support for ethprime env var
  dm: eth: Add testing for netretry env var
  dm: eth: Add a bridge to a real network for sandbox

 arch/mips/cpu/mips32/au1x00/au1x00_eth.c  |   2 +-
 arch/powerpc/cpu/mpc8260/ether_fcc.c      |   2 +-
 arch/powerpc/cpu/mpc85xx/ether_fcc.c      |   2 +-
 arch/powerpc/cpu/mpc8xx/scc.c             |   2 +-
 arch/sandbox/dts/sandbox.dts              |  11 +
 arch/sandbox/include/asm/sandbox-raw-os.h |  16 +
 common/board_r.c                          |   4 +-
 common/cmd_bdinfo.c                       |   2 +
 drivers/core/uclass.c                     |   4 +-
 drivers/net/Makefile                      |  12 +
 drivers/net/sandbox-raw-os.c              | 105 +++++++
 drivers/net/sandbox-raw.c                 | 128 ++++++++
 drivers/net/sandbox.c                     | 187 ++++++++++++
 include/configs/sandbox.h                 |  19 +-
 include/dm/uclass-id.h                    |   1 +
 include/fdtdec.h                          |   1 +
 include/net.h                             | 164 +++++++----
 lib/fdtdec.c                              |   1 +
 net/eth.c                                 | 474 ++++++++++++++++++++++++++----
 net/net.c                                 |   2 +-
 test/dm/Makefile                          |   5 +-
 test/dm/eth.c                             | 110 +++++++
 test/dm/test.dts                          |  20 ++
 23 files changed, 1146 insertions(+), 128 deletions(-)
 create mode 100644 arch/sandbox/include/asm/sandbox-raw-os.h
 create mode 100644 drivers/net/sandbox-raw-os.c
 create mode 100644 drivers/net/sandbox-raw.c
 create mode 100644 drivers/net/sandbox.c
 create mode 100644 test/dm/eth.c

-- 
1.7.11.5

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 01/14] dm: core: Allow seq numbers to be resolved before probe
  2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
@ 2015-02-11  1:30     ` Joe Hershberger
  2015-02-11  4:39       ` Simon Glass
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 02/14] test: dm: Reorder the objects to build Joe Hershberger
                       ` (13 subsequent siblings)
  14 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-11  1:30 UTC (permalink / raw)
  To: u-boot

Before this patch, if the sequence numbers were resolved before probe,
this code would insist on defining new non-conflicting-with-itself seq
numbers. Now any "non -1" seq number is accepted as already resolved.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v3:
-Add seq patch to dm core

Changes in v2: None

 drivers/core/uclass.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 289a5d2..2d8b6f8 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -366,7 +366,9 @@ int uclass_resolve_seq(struct udevice *dev)
 	int seq;
 	int ret;
 
-	assert(dev->seq == -1);
+	if (dev->seq != -1)
+		return dev->seq;
+
 	ret = uclass_find_device_by_seq(dev->uclass->uc_drv->id, dev->req_seq,
 					false, &dup);
 	if (!ret) {
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 02/14] test: dm: Reorder the objects to build
  2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 01/14] dm: core: Allow seq numbers to be resolved before probe Joe Hershberger
@ 2015-02-11  1:30     ` Joe Hershberger
  2015-02-11  4:39       ` Simon Glass
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 03/14] net: Provide a function to get the current MAC address Joe Hershberger
                       ` (12 subsequent siblings)
  14 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-11  1:30 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v3:
-Reorder dm test makefile

Changes in v2: None

 test/dm/Makefile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/dm/Makefile b/test/dm/Makefile
index 612aa95..1d9148f 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -18,7 +18,7 @@ obj-$(CONFIG_DM_TEST) += core.o
 obj-$(CONFIG_DM_TEST) += ut.o
 ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_DM_GPIO) += gpio.o
-obj-$(CONFIG_DM_SPI) += spi.o
-obj-$(CONFIG_DM_SPI_FLASH) += sf.o
 obj-$(CONFIG_DM_I2C) += i2c.o
+obj-$(CONFIG_DM_SPI_FLASH) += sf.o
+obj-$(CONFIG_DM_SPI) += spi.o
 endif
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 03/14] net: Provide a function to get the current MAC address
  2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 01/14] dm: core: Allow seq numbers to be resolved before probe Joe Hershberger
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 02/14] test: dm: Reorder the objects to build Joe Hershberger
@ 2015-02-11  1:30     ` Joe Hershberger
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 04/14] net: Rename helper function to be more clear Joe Hershberger
                       ` (11 subsequent siblings)
  14 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-02-11  1:30 UTC (permalink / raw)
  To: u-boot

The current implementation exposes the eth_device struct to code that
needs to access the MAC address.  Add a wrapper function for this to
abstract away the pointer for this operation.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/mips/cpu/mips32/au1x00/au1x00_eth.c | 2 +-
 arch/powerpc/cpu/mpc8260/ether_fcc.c     | 2 +-
 arch/powerpc/cpu/mpc85xx/ether_fcc.c     | 2 +-
 arch/powerpc/cpu/mpc8xx/scc.c            | 2 +-
 include/net.h                            | 8 ++++++++
 net/net.c                                | 2 +-
 6 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_eth.c b/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
index 4770f56..535d713 100644
--- a/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
+++ b/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
@@ -238,7 +238,7 @@ static int au1x00_init(struct eth_device* dev, bd_t * bd){
 	}
 
 	/* Put mac addr in little endian */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
 	*mac_addr_high	=	(ea[5] <<  8) | (ea[4]	    ) ;
 	*mac_addr_low	=	(ea[3] << 24) | (ea[2] << 16) |
 		(ea[1] <<  8) | (ea[0]	    ) ;
diff --git a/arch/powerpc/cpu/mpc8260/ether_fcc.c b/arch/powerpc/cpu/mpc8260/ether_fcc.c
index f9f15b5..f777ba1 100644
--- a/arch/powerpc/cpu/mpc8260/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc8260/ether_fcc.c
@@ -299,7 +299,7 @@ static int fec_init(struct eth_device* dev, bd_t *bis)
      * it unique by setting a few bits in the upper byte of the
      * non-static part of the address.
      */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
     pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
     pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
     pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/arch/powerpc/cpu/mpc85xx/ether_fcc.c b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
index 166dc9e..58d4bfb 100644
--- a/arch/powerpc/cpu/mpc85xx/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
@@ -338,7 +338,7 @@ static int fec_init(struct eth_device* dev, bd_t *bis)
      * it unique by setting a few bits in the upper byte of the
      * non-static part of the address.
      */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
     pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
     pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
     pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/arch/powerpc/cpu/mpc8xx/scc.c b/arch/powerpc/cpu/mpc8xx/scc.c
index 251966b..66e4014 100644
--- a/arch/powerpc/cpu/mpc8xx/scc.c
+++ b/arch/powerpc/cpu/mpc8xx/scc.c
@@ -339,7 +339,7 @@ static int scc_init (struct eth_device *dev, bd_t * bis)
 	pram_ptr->sen_gaddr3 = 0x0;	/* Group Address Filter 3 (unused) */
 	pram_ptr->sen_gaddr4 = 0x0;	/* Group Address Filter 4 (unused) */
 
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
 	pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4];
 	pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2];
 	pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/include/net.h b/include/net.h
index 73ea88b..a9579ee 100644
--- a/include/net.h
+++ b/include/net.h
@@ -111,6 +111,14 @@ struct eth_device *eth_get_dev(void)
 {
 	return eth_current;
 }
+
+static inline unsigned char *eth_get_ethaddr(void)
+{
+	if (eth_current)
+		return eth_current->enetaddr;
+	return NULL;
+}
+
 extern struct eth_device *eth_get_dev_by_name(const char *devname);
 extern struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
 extern int eth_get_dev_index(void);		/* get the device index */
diff --git a/net/net.c b/net/net.c
index 2bea07b..ddd630c 100644
--- a/net/net.c
+++ b/net/net.c
@@ -275,7 +275,7 @@ static void NetInitLoop(void)
 		env_changed_id = env_id;
 	}
 	if (eth_get_dev())
-		memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
+		memcpy(NetOurEther, eth_get_ethaddr(), 6);
 
 	return;
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 04/14] net: Rename helper function to be more clear
  2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
                       ` (2 preceding siblings ...)
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 03/14] net: Provide a function to get the current MAC address Joe Hershberger
@ 2015-02-11  1:30     ` Joe Hershberger
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 05/14] net: Remove unneeded "extern" in net.h Joe Hershberger
                       ` (10 subsequent siblings)
  14 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-02-11  1:30 UTC (permalink / raw)
  To: u-boot

Make it clear that the helper is checking the addr, not setting it.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 net/eth.c | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/net/eth.c b/net/eth.c
index eac4f7b..65e8c77 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -153,11 +153,6 @@ static void eth_current_changed(void)
 		setenv("ethact", NULL);
 }
 
-static int eth_address_set(unsigned char *addr)
-{
-	return memcmp(addr, "\0\0\0\0\0\0", 6);
-}
-
 int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		   int eth_number)
 {
@@ -166,9 +161,9 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 
 	eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
 
-	if (eth_address_set(env_enetaddr)) {
-		if (eth_address_set(dev->enetaddr) &&
-				memcmp(dev->enetaddr, env_enetaddr, 6)) {
+	if (!is_zero_ether_addr(env_enetaddr)) {
+		if (!is_zero_ether_addr(dev->enetaddr) &&
+		    memcmp(dev->enetaddr, env_enetaddr, 6)) {
 			printf("\nWarning: %s MAC addresses don't match:\n",
 				dev->name);
 			printf("Address in SROM is         %pM\n",
@@ -183,7 +178,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 					     dev->enetaddr);
 		printf("\nWarning: %s using MAC address from net device\n",
 			dev->name);
-	} else if (!(eth_address_set(dev->enetaddr))) {
+	} else if (is_zero_ether_addr(dev->enetaddr)) {
 		printf("\nError: %s address not set.\n",
 		       dev->name);
 		return -EINVAL;
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 05/14] net: Remove unneeded "extern" in net.h
  2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
                       ` (3 preceding siblings ...)
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 04/14] net: Rename helper function to be more clear Joe Hershberger
@ 2015-02-11  1:30     ` Joe Hershberger
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 06/14] net: Refactor in preparation for driver model Joe Hershberger
                       ` (9 subsequent siblings)
  14 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-02-11  1:30 UTC (permalink / raw)
  To: u-boot

Many of the functions in net.h were preceded extern needlessly. Removing
them to limit the number of checkpatch.pl complaints.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 include/net.h | 96 +++++++++++++++++++++++++++++------------------------------
 1 file changed, 48 insertions(+), 48 deletions(-)

diff --git a/include/net.h b/include/net.h
index a9579ee..ff8b7af 100644
--- a/include/net.h
+++ b/include/net.h
@@ -97,11 +97,11 @@ struct eth_device {
 	void *priv;
 };
 
-extern int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
-extern int eth_register(struct eth_device* dev);/* Register network device */
-extern int eth_unregister(struct eth_device *dev);/* Remove network device */
-extern void eth_try_another(int first_restart);	/* Change the device */
-extern void eth_set_current(void);		/* set nterface to ethcur var */
+int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
+int eth_register(struct eth_device *dev);/* Register network device */
+int eth_unregister(struct eth_device *dev);/* Remove network device */
+void eth_try_another(int first_restart);	/* Change the device */
+void eth_set_current(void);		/* set nterface to ethcur var */
 
 /* get the current device MAC */
 extern struct eth_device *eth_current;
@@ -119,12 +119,12 @@ static inline unsigned char *eth_get_ethaddr(void)
 	return NULL;
 }
 
-extern struct eth_device *eth_get_dev_by_name(const char *devname);
-extern struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
-extern int eth_get_dev_index(void);		/* get the device index */
-extern void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
-extern int eth_getenv_enetaddr(char *name, uchar *enetaddr);
-extern int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
+struct eth_device *eth_get_dev_by_name(const char *devname);
+struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
+int eth_get_dev_index(void);		/* get the device index */
+void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
+int eth_getenv_enetaddr(char *name, uchar *enetaddr);
+int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 
 /*
  * Get the hardware address for an ethernet interface .
@@ -135,20 +135,20 @@ extern int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
  * Returns:
  *	Return true if the address is valid.
  */
-extern int eth_getenv_enetaddr_by_index(const char *base_name, int index,
-					uchar *enetaddr);
+int eth_getenv_enetaddr_by_index(const char *base_name, int index,
+				 uchar *enetaddr);
 
-extern int usb_eth_initialize(bd_t *bi);
-extern int eth_init(bd_t *bis);			/* Initialize the device */
-extern int eth_send(void *packet, int length);	   /* Send a packet */
+int usb_eth_initialize(bd_t *bi);
+int eth_init(bd_t *bis);			/* Initialize the device */
+int eth_send(void *packet, int length);	   /* Send a packet */
 
 #ifdef CONFIG_API
-extern int eth_receive(void *packet, int length); /* Receive a packet*/
-extern void (*push_packet)(void *packet, int length);
+int eth_receive(void *packet, int length); /* Receive a packet*/
+void (*push_packet)(void *packet, int length);
 #endif
-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 */
+int eth_rx(void);			/* Check for received packets */
+void eth_halt(void);			/* stop SCC */
+char *eth_get_name(void);		/* get name of current device */
 
 /* Set active state */
 static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
@@ -469,25 +469,25 @@ extern IPaddr_t Mcast_addr;
 #endif
 
 /* Initialize the network adapter */
-extern void net_init(void);
-extern int NetLoop(enum proto_t);
+void net_init(void);
+int NetLoop(enum proto_t);
 
 /* Shutdown adapters and cleanup */
-extern void	NetStop(void);
+void	NetStop(void);
 
 /* Load failed.	 Start again. */
-extern void	NetStartAgain(void);
+void	NetStartAgain(void);
 
 /* Get size of the ethernet header when we send */
-extern int	NetEthHdrSize(void);
+int	NetEthHdrSize(void);
 
 /* Set ethernet header; returns the size of the header */
-extern int NetSetEther(uchar *, uchar *, uint);
-extern int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot);
+int NetSetEther(uchar *, uchar *, uint);
+int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot);
 
 /* Set IP header */
-extern void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source);
-extern void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport,
+void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source);
+void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport,
 				int sport, int len);
 
 /**
@@ -521,16 +521,16 @@ unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new_sum);
 int ip_checksum_ok(const void *addr, unsigned nbytes);
 
 /* Checksum */
-extern int	NetCksumOk(uchar *, int);	/* Return true if cksum OK */
-extern uint	NetCksum(uchar *, int);		/* Calculate the checksum */
+int	NetCksumOk(uchar *, int);	/* Return true if cksum OK */
+uint	NetCksum(uchar *, int);		/* Calculate the checksum */
 
 /* Callbacks */
-extern rxhand_f *net_get_udp_handler(void);	/* Get UDP RX packet handler */
-extern void net_set_udp_handler(rxhand_f *);	/* Set UDP RX packet handler */
-extern rxhand_f *net_get_arp_handler(void);	/* Get ARP RX packet handler */
-extern void net_set_arp_handler(rxhand_f *);	/* Set ARP RX packet handler */
-extern void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
-extern void	NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
+rxhand_f *net_get_udp_handler(void);	/* Get UDP RX packet handler */
+void net_set_udp_handler(rxhand_f *);	/* Set UDP RX packet handler */
+rxhand_f *net_get_arp_handler(void);	/* Get ARP RX packet handler */
+void net_set_arp_handler(rxhand_f *);	/* Set ARP RX packet handler */
+void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
+void	NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
 
 /* Network loop state */
 enum net_loop_state {
@@ -563,11 +563,11 @@ static inline void NetSendPacket(uchar *pkt, int len)
  * @param sport Source UDP port
  * @param payload_len Length of data after the UDP header
  */
-extern int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport,
+int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport,
 			int sport, int payload_len);
 
 /* Processes a received packet */
-extern void NetReceive(uchar *, int);
+void NetReceive(uchar *, int);
 
 #ifdef CONFIG_NETCONSOLE
 void NcStart(void);
@@ -715,28 +715,28 @@ static inline void eth_random_addr(uchar *addr)
 }
 
 /* Convert an IP address to a string */
-extern void ip_to_string(IPaddr_t x, char *s);
+void ip_to_string(IPaddr_t x, char *s);
 
 /* Convert a string to ip address */
-extern IPaddr_t string_to_ip(const char *s);
+IPaddr_t string_to_ip(const char *s);
 
 /* Convert a VLAN id to a string */
-extern void VLAN_to_string(ushort x, char *s);
+void VLAN_to_string(ushort x, char *s);
 
 /* Convert a string to a vlan id */
-extern ushort string_to_VLAN(const char *s);
+ushort string_to_VLAN(const char *s);
 
 /* read a VLAN id from an environment variable */
-extern ushort getenv_VLAN(char *);
+ushort getenv_VLAN(char *);
 
 /* copy a filename (allow for "..." notation, limit length) */
-extern void copy_filename(char *dst, const char *src, int size);
+void copy_filename(char *dst, const char *src, int size);
 
 /* get a random source port */
-extern unsigned int random_port(void);
+unsigned int random_port(void);
 
 /* Update U-Boot over TFTP */
-extern int update_tftp(ulong addr);
+int update_tftp(ulong addr);
 
 /**********************************************************************/
 
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 06/14] net: Refactor in preparation for driver model
  2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
                       ` (4 preceding siblings ...)
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 05/14] net: Remove unneeded "extern" in net.h Joe Hershberger
@ 2015-02-11  1:30     ` Joe Hershberger
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 07/14] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
                       ` (8 subsequent siblings)
  14 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-02-11  1:30 UTC (permalink / raw)
  To: u-boot

Move some things around and organize things so that the driver model
implementation will fit in more easily.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v3:
-Move the get_dev_by_* protos to also be !DM_ETH like the impl

Changes in v2: None

 include/net.h | 66 +++++++++++++++++++++++++++-------------------------
 net/eth.c     | 75 +++++++++++++++++++++++++++++++----------------------------
 2 files changed, 74 insertions(+), 67 deletions(-)

diff --git a/include/net.h b/include/net.h
index ff8b7af..4d7575e 100644
--- a/include/net.h
+++ b/include/net.h
@@ -100,10 +100,7 @@ struct eth_device {
 int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
 int eth_register(struct eth_device *dev);/* Register network device */
 int eth_unregister(struct eth_device *dev);/* Remove network device */
-void eth_try_another(int first_restart);	/* Change the device */
-void eth_set_current(void);		/* set nterface to ethcur var */
 
-/* get the current device MAC */
 extern struct eth_device *eth_current;
 
 static inline __attribute__((always_inline))
@@ -111,7 +108,10 @@ struct eth_device *eth_get_dev(void)
 {
 	return eth_current;
 }
+struct eth_device *eth_get_dev_by_name(const char *devname);
+struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
 
+/* get the current device MAC */
 static inline unsigned char *eth_get_ethaddr(void)
 {
 	if (eth_current)
@@ -119,8 +119,36 @@ static inline unsigned char *eth_get_ethaddr(void)
 	return NULL;
 }
 
-struct eth_device *eth_get_dev_by_name(const char *devname);
-struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
+/* Set active state */
+static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
+{
+	eth_get_dev()->state = ETH_STATE_ACTIVE;
+
+	return 0;
+}
+/* Set passive state */
+static inline __attribute__((always_inline)) void eth_halt_state_only(void)
+{
+	eth_get_dev()->state = ETH_STATE_PASSIVE;
+}
+
+/*
+ * Set the hardware address for an ethernet interface based on 'eth%daddr'
+ * environment variable (or just 'ethaddr' if eth_number is 0).
+ * Args:
+ *	base_name - base name for device (normally "eth")
+ *	eth_number - value of %d (0 for first device of this type)
+ * Returns:
+ *	0 is success, non-zero is error status from driver.
+ */
+int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
+		     int eth_number);
+
+int usb_eth_initialize(bd_t *bi);
+
+void eth_try_another(int first_restart);	/* Change the device */
+void eth_set_current(void);		/* set nterface to ethcur var */
+
 int eth_get_dev_index(void);		/* get the device index */
 void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
 int eth_getenv_enetaddr(char *name, uchar *enetaddr);
@@ -138,7 +166,6 @@ int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 int eth_getenv_enetaddr_by_index(const char *base_name, int index,
 				 uchar *enetaddr);
 
-int usb_eth_initialize(bd_t *bi);
 int eth_init(bd_t *bis);			/* Initialize the device */
 int eth_send(void *packet, int length);	   /* Send a packet */
 
@@ -148,32 +175,7 @@ void (*push_packet)(void *packet, int length);
 #endif
 int eth_rx(void);			/* Check for received packets */
 void eth_halt(void);			/* stop SCC */
-char *eth_get_name(void);		/* get name of current device */
-
-/* Set active state */
-static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
-{
-	eth_get_dev()->state = ETH_STATE_ACTIVE;
-
-	return 0;
-}
-/* Set passive state */
-static inline __attribute__((always_inline)) void eth_halt_state_only(void)
-{
-	eth_get_dev()->state = ETH_STATE_PASSIVE;
-}
-
-/*
- * Set the hardware address for an ethernet interface based on 'eth%daddr'
- * environment variable (or just 'ethaddr' if eth_number is 0).
- * Args:
- *	base_name - base name for device (normally "eth")
- *	eth_number - value of %d (0 for first device of this type)
- * Returns:
- *	0 is success, non-zero is error status from driver.
- */
-int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
-		     int eth_number);
+const char *eth_get_name(void);		/* get name of current device */
 
 #ifdef CONFIG_MCAST_TFTP
 int eth_mcast_join(IPaddr_t mcast_addr, u8 join);
diff --git a/net/eth.c b/net/eth.c
index 65e8c77..c02548c 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -55,6 +55,14 @@ static inline int eth_setenv_enetaddr_by_index(const char *base_name, int index,
 	return eth_setenv_enetaddr(enetvar, enetaddr);
 }
 
+static void eth_env_init(void)
+{
+	const char *s;
+
+	s = getenv("bootfile");
+	if (s != NULL)
+		copy_filename(BootFile, s, sizeof(BootFile));
+}
 
 static int eth_mac_skip(int index)
 {
@@ -87,6 +95,11 @@ static unsigned int eth_rcv_current, eth_rcv_last;
 static struct eth_device *eth_devices;
 struct eth_device *eth_current;
 
+static void eth_set_current_to_next(void)
+{
+	eth_current = eth_current->next;
+}
+
 struct eth_device *eth_get_dev_by_name(const char *devname)
 {
 	struct eth_device *dev, *target_dev;
@@ -137,22 +150,6 @@ int eth_get_dev_index(void)
 	return eth_current->index;
 }
 
-static void eth_current_changed(void)
-{
-	char *act = getenv("ethact");
-	/* update current ethernet name */
-	if (eth_current) {
-		if (act == NULL || strcmp(act, eth_current->name) != 0)
-			setenv("ethact", eth_current->name);
-	}
-	/*
-	 * remove the variable completely if there is no active
-	 * interface
-	 */
-	else if (act != NULL)
-		setenv("ethact", NULL);
-}
-
 int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		   int eth_number)
 {
@@ -251,14 +248,6 @@ int eth_unregister(struct eth_device *dev)
 	return 0;
 }
 
-static void eth_env_init(bd_t *bis)
-{
-	const char *s;
-
-	if ((s = getenv("bootfile")) != NULL)
-		copy_filename(BootFile, s, sizeof(BootFile));
-}
-
 int eth_initialize(bd_t *bis)
 {
 	int num_devices = 0;
@@ -479,6 +468,22 @@ int eth_receive(void *packet, int length)
 }
 #endif /* CONFIG_API */
 
+static void eth_current_changed(void)
+{
+	char *act = getenv("ethact");
+	/* update current ethernet name */
+	if (eth_get_dev()) {
+		if (act == NULL || strcmp(act, eth_get_name()) != 0)
+			setenv("ethact", eth_get_name());
+	}
+	/*
+	 * remove the variable completely if there is no active
+	 * interface
+	 */
+	else if (act != NULL)
+		setenv("ethact", NULL);
+}
+
 void eth_try_another(int first_restart)
 {
 	static struct eth_device *first_failed;
@@ -492,17 +497,17 @@ void eth_try_another(int first_restart)
 	if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
 		return;
 
-	if (!eth_current)
+	if (!eth_get_dev())
 		return;
 
 	if (first_restart)
-		first_failed = eth_current;
+		first_failed = eth_get_dev();
 
-	eth_current = eth_current->next;
+	eth_set_current_to_next();
 
 	eth_current_changed();
 
-	if (first_failed == eth_current)
+	if (first_failed == eth_get_dev())
 		NetRestartWrap = 1;
 }
 
@@ -513,7 +518,7 @@ void eth_set_current(void)
 	struct eth_device *old_current;
 	int	env_id;
 
-	if (!eth_current)	/* XXX no current */
+	if (!eth_get_dev())	/* XXX no current */
 		return;
 
 	env_id = get_env_id();
@@ -522,18 +527,18 @@ void eth_set_current(void)
 		env_changed_id = env_id;
 	}
 	if (act != NULL) {
-		old_current = eth_current;
+		old_current = eth_get_dev();
 		do {
-			if (strcmp(eth_current->name, act) == 0)
+			if (strcmp(eth_get_name(), act) == 0)
 				return;
-			eth_current = eth_current->next;
-		} while (old_current != eth_current);
+			eth_set_current_to_next();
+		} while (old_current != eth_get_dev());
 	}
 
 	eth_current_changed();
 }
 
-char *eth_get_name(void)
+const char *eth_get_name(void)
 {
-	return eth_current ? eth_current->name : "unknown";
+	return eth_get_dev() ? eth_get_dev()->name : "unknown";
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 07/14] dm: eth: Add basic driver model support to Ethernet stack
  2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
                       ` (5 preceding siblings ...)
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 06/14] net: Refactor in preparation for driver model Joe Hershberger
@ 2015-02-11  1:30     ` Joe Hershberger
  2015-02-15 15:49       ` Simon Glass
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 08/14] dm: eth: Add network support to sandbox Joe Hershberger
                       ` (7 subsequent siblings)
  14 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-11  1:30 UTC (permalink / raw)
  To: u-boot

First just add support for MAC drivers.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v3:
-Correct the pre_unbind logic
-Correct failure chaining from bind to probe to init
--Fail init if not activated
--Fail probe if ethaddr not set
-Update ethaddr from env unconditionally on init
-Use set current to select the current device regardless of the previous selection
-Allow current eth dev to be NULL
-Fixed blank line formatting for variable declaration

Changes in v2:
-Updated comments
-Removed extra parentheses
-Changed eth_uclass_priv local var names to be uc_priv
-Update error codes
-Cause an invalid name to fail binding
-Rebase on top of dm/master
-Stop maintaining our own index and use DM seq now that it works for our needs
-Move the hwaddr to platdata so that its memory is allocated at bind when we need it
-Prevent device from being probed before used by a command (i.e. before eth_init()).

 common/board_r.c       |   4 +-
 common/cmd_bdinfo.c    |   2 +
 include/dm/uclass-id.h |   1 +
 include/net.h          |  25 ++++
 net/eth.c              | 336 ++++++++++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 361 insertions(+), 7 deletions(-)

diff --git a/common/board_r.c b/common/board_r.c
index 68a9448..75147b7 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -556,7 +556,7 @@ static int initr_bbmii(void)
 }
 #endif
 
-#ifdef CONFIG_CMD_NET
+#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
 static int initr_net(void)
 {
 	puts("Net:   ");
@@ -825,7 +825,7 @@ init_fnc_t init_sequence_r[] = {
 #ifdef CONFIG_BITBANGMII
 	initr_bbmii,
 #endif
-#ifdef CONFIG_CMD_NET
+#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
 	INIT_FUNC_WATCHDOG_RESET
 	initr_net,
 #endif
diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
index e6d8a7a..8688cf9 100644
--- a/common/cmd_bdinfo.c
+++ b/common/cmd_bdinfo.c
@@ -34,6 +34,7 @@ static void print_eth(int idx)
 	printf("%-12s= %s\n", name, val);
 }
 
+#ifndef CONFIG_DM_ETH
 __maybe_unused
 static void print_eths(void)
 {
@@ -52,6 +53,7 @@ static void print_eths(void)
 	printf("current eth = %s\n", eth_get_name());
 	printf("ip_addr     = %s\n", getenv("ipaddr"));
 }
+#endif
 
 __maybe_unused
 static void print_lnum(const char *name, unsigned long long value)
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 91bb90d..ad96682 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -34,6 +34,7 @@ enum uclass_id {
 	UCLASS_I2C_GENERIC,	/* Generic I2C device */
 	UCLASS_I2C_EEPROM,	/* I2C EEPROM device */
 	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
+	UCLASS_ETH,		/* Ethernet device */
 
 	UCLASS_COUNT,
 	UCLASS_INVALID = -1,
diff --git a/include/net.h b/include/net.h
index 4d7575e..11471bd 100644
--- a/include/net.h
+++ b/include/net.h
@@ -78,6 +78,30 @@ enum eth_state_t {
 	ETH_STATE_ACTIVE
 };
 
+#ifdef CONFIG_DM_ETH
+struct eth_pdata {
+	phys_addr_t iobase;
+	unsigned char enetaddr[6];
+};
+
+struct eth_ops {
+	int (*init)(struct udevice *dev, bd_t *bis);
+	int (*send)(struct udevice *dev, void *packet, int length);
+	int (*recv)(struct udevice *dev);
+	void (*halt)(struct udevice *dev);
+#ifdef CONFIG_MCAST_TFTP
+	int (*mcast)(struct udevice *dev, const u8 *enetaddr, u8 set);
+#endif
+	int (*write_hwaddr)(struct udevice *dev);
+};
+
+struct udevice *eth_get_dev(void); /* get the current device */
+unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
+int eth_init_state_only(bd_t *bis); /* Set active state */
+void eth_halt_state_only(void); /* Set passive state */
+#endif
+
+#ifndef CONFIG_DM_ETH
 struct eth_device {
 	char name[16];
 	unsigned char enetaddr[6];
@@ -145,6 +169,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		     int eth_number);
 
 int usb_eth_initialize(bd_t *bi);
+#endif
 
 void eth_try_another(int first_restart);	/* Change the device */
 void eth_set_current(void);		/* set nterface to ethcur var */
diff --git a/net/eth.c b/net/eth.c
index c02548c..e84b948 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -1,12 +1,15 @@
 /*
  * (C) Copyright 2001-2010
  * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ * Joe Hershberger, National Instruments
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #include <common.h>
 #include <command.h>
+#include <dm.h>
+#include <dm/device-internal.h>
 #include <net.h>
 #include <miiphy.h>
 #include <phy.h>
@@ -72,6 +75,331 @@ static int eth_mac_skip(int index)
 	return ((skip_state = getenv(enetvar)) != NULL);
 }
 
+static void eth_current_changed(void);
+
+#ifdef CONFIG_DM_ETH
+struct eth_device_priv {
+	int state;
+	void *priv;
+};
+
+struct eth_uclass_priv {
+	struct udevice *current;
+};
+
+static void eth_set_current_to_next(void)
+{
+	struct uclass *uc;
+	struct eth_uclass_priv *uc_priv;
+
+	uclass_get(UCLASS_ETH, &uc);
+	uc_priv = uc->priv;
+	if (uc_priv->current)
+		uclass_next_device(&uc_priv->current);
+	if (!uc_priv->current)
+		uclass_first_device(UCLASS_ETH, &uc_priv->current);
+}
+
+struct udevice *eth_get_dev(void)
+{
+	struct uclass *uc;
+	struct eth_uclass_priv *uc_priv;
+
+	uclass_get(UCLASS_ETH, &uc);
+	uc_priv = uc->priv;
+
+	return uc_priv->current;
+}
+
+static void eth_set_dev(struct udevice *dev)
+{
+	struct uclass *uc;
+	struct eth_uclass_priv *uc_priv;
+
+	uclass_get(UCLASS_ETH, &uc);
+	uc_priv = uc->priv;
+	uc_priv->current = dev;
+}
+
+unsigned char *eth_get_ethaddr(void)
+{
+	struct eth_pdata *pdata;
+
+	if (eth_get_dev()) {
+		pdata = eth_get_dev()->platdata;
+		if (pdata)
+			return pdata->enetaddr;
+	}
+	return NULL;
+}
+
+/* Set active state */
+int eth_init_state_only(bd_t *bis)
+{
+	struct eth_device_priv *priv;
+
+	if (eth_get_dev()) {
+		priv = eth_get_dev()->uclass_priv;
+		if (priv)
+			priv->state = ETH_STATE_ACTIVE;
+	}
+	return 0;
+}
+/* Set passive state */
+void eth_halt_state_only(void)
+{
+	struct eth_device_priv *priv;
+
+	if (eth_get_dev()) {
+		priv = eth_get_dev()->uclass_priv;
+		if (priv)
+			priv->state = ETH_STATE_PASSIVE;
+	}
+}
+
+int eth_get_dev_index(void)
+{
+	if (eth_get_dev())
+		return eth_get_dev()->seq;
+	return -1;
+}
+
+int eth_init(bd_t *bis)
+{
+	struct udevice *current, *old_current, *dev;
+	int retval;
+	struct uclass *uc;
+
+	current = eth_get_dev();
+	if (!current) {
+		puts("No ethernet found.\n");
+		return -1;
+	}
+	retval = device_probe(current);
+	if (retval)
+		return retval;
+
+	/* Sync environment with network devices */
+	uclass_get(UCLASS_ETH, &uc);
+	uclass_foreach_dev(dev, uc) {
+		uchar env_enetaddr[6];
+		struct eth_pdata *pdata = dev->platdata;
+
+		if (eth_getenv_enetaddr_by_index("eth", dev->seq, env_enetaddr))
+			memcpy(pdata->enetaddr, env_enetaddr, 6);
+		else
+			memset(pdata->enetaddr, 0, 6);
+	}
+
+	old_current = current;
+	do {
+		debug("Trying %s\n", current->name);
+
+		if (current->driver && (current->flags & DM_FLAG_ACTIVATED)) {
+			const struct eth_ops *ops = current->driver->ops;
+
+			if (ops->init(current, bis) >= 0) {
+				struct eth_device_priv *priv =
+					current->uclass_priv;
+				if (priv)
+					priv->state = ETH_STATE_ACTIVE;
+
+				return 0;
+			}
+		}
+		debug("FAIL\n");
+
+		eth_try_another(0);
+		current = eth_get_dev();
+	} while (old_current != current);
+
+	return -ENODEV;
+}
+
+void eth_halt(void)
+{
+	struct udevice *current;
+	const struct eth_ops *ops;
+	struct eth_device_priv *priv;
+
+	current = eth_get_dev();
+	if (!current)
+		return;
+	if (!current->driver)
+		return;
+
+	ops = current->driver->ops;
+	ops->halt(current);
+
+	priv = current->uclass_priv;
+	if (priv)
+		priv->state = ETH_STATE_PASSIVE;
+}
+
+int eth_send(void *packet, int length)
+{
+	struct udevice *current;
+	const struct eth_ops *ops;
+
+	current = eth_get_dev();
+	if (!current)
+		return -1;
+	if (!current->driver)
+		return -1;
+	ops = current->driver->ops;
+
+	return ops->send(current, packet, length);
+}
+
+int eth_rx(void)
+{
+	struct udevice *current;
+	const struct eth_ops *ops;
+
+	current = eth_get_dev();
+	if (!current)
+		return -1;
+	if (!current->driver)
+		return -1;
+	ops = current->driver->ops;
+
+	return ops->recv(current);
+}
+
+static int eth_write_hwaddr(struct udevice *dev, const char *base_name,
+		   int eth_number)
+{
+	unsigned char env_enetaddr[6];
+	int ret = 0;
+	struct eth_pdata *pdata;
+	const struct eth_ops *ops;
+
+	eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
+
+	pdata = dev->platdata;
+	if (!is_zero_ether_addr(env_enetaddr)) {
+		if (!is_zero_ether_addr(pdata->enetaddr) &&
+		    memcmp(pdata->enetaddr, env_enetaddr, 6)) {
+			printf("\nWarning: %s MAC addresses don't match:\n",
+			       dev->name);
+			printf("Address in SROM is         %pM\n",
+			       pdata->enetaddr);
+			printf("Address in environment is  %pM\n",
+			       env_enetaddr);
+		}
+
+		memcpy(pdata->enetaddr, env_enetaddr, 6);
+	} else if (is_valid_ether_addr(pdata->enetaddr)) {
+		eth_setenv_enetaddr_by_index(base_name, eth_number,
+					     pdata->enetaddr);
+		printf("\nWarning: %s using MAC address from net device\n",
+		       dev->name);
+	} else if (is_zero_ether_addr(pdata->enetaddr)) {
+		printf("\nError: %s address not set.\n",
+		       dev->name);
+		return -EINVAL;
+	}
+
+	ops = dev->driver->ops;
+	if (dev->driver && ops && ops->write_hwaddr &&
+	    !eth_mac_skip(eth_number)) {
+		if (!is_valid_ether_addr(pdata->enetaddr)) {
+			printf("\nError: %s address %pM illegal value\n",
+			       dev->name, pdata->enetaddr);
+			return -EINVAL;
+		}
+
+		ret = ops->write_hwaddr(dev);
+		if (ret)
+			printf("\nWarning: %s failed to set MAC address\n",
+			       dev->name);
+	}
+
+	return ret;
+}
+
+static int eth_uclass_init(struct uclass *class)
+{
+	bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
+
+	eth_env_init();
+
+	return 0;
+}
+
+static int eth_post_bind(struct udevice *dev)
+{
+	if (strchr(dev->name, ' ')) {
+		printf("\nError: eth device name \"%s\" has a space!\n",
+		       dev->name);
+		return -EINVAL;
+	}
+
+	/*
+	 * Devices need to write the hwaddr even if not probed so that Linux
+	 * will have access to the hwaddr that u-boot stored for the device.
+	 */
+	dev->seq = uclass_resolve_seq(dev);
+	eth_write_hwaddr(dev, "eth", dev->seq);
+
+	return 0;
+}
+
+static int eth_pre_unbind(struct udevice *dev)
+{
+	struct udevice *first = NULL;
+	struct udevice *active;
+	struct udevice *it;
+	struct uclass *uc;
+
+	uclass_get(UCLASS_ETH, &uc);
+	uclass_foreach_dev(it, uc) {
+		if (!first)
+			first = it;
+		if (it == dev) {
+			if (dev == first) {
+				active = list_entry(it->uclass_node.next,
+					   struct udevice, uclass_node);
+				if (&active->uclass_node == &uc->dev_head)
+					active = NULL;
+			} else {
+				active = first;
+			}
+			eth_set_dev(active);
+			eth_current_changed();
+		}
+	}
+
+	return 0;
+}
+
+static int eth_post_probe(struct udevice *dev)
+{
+	struct eth_device_priv *priv = dev->uclass_priv;
+	struct eth_pdata *pdata = dev->platdata;
+
+	if (priv)
+		priv->state = ETH_STATE_INIT;
+
+	if (is_zero_ether_addr(pdata->enetaddr))
+		return -EINVAL;
+
+	return 0;
+}
+
+UCLASS_DRIVER(eth) = {
+	.name		= "eth",
+	.id		= UCLASS_ETH,
+	.post_bind	= eth_post_bind,
+	.pre_unbind	= eth_pre_unbind,
+	.post_probe	= eth_post_probe,
+	.init		= eth_uclass_init,
+	.priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
+	.per_device_auto_alloc_size = sizeof(struct eth_device_priv),
+};
+#endif
+
+#ifndef CONFIG_DM_ETH
 /*
  * CPU and board-specific Ethernet initializations.  Aliased function
  * signals caller to move on
@@ -423,6 +751,7 @@ int eth_rx(void)
 
 	return eth_current->recv(eth_current);
 }
+#endif /* ifndef CONFIG_DM_ETH */
 
 #ifdef CONFIG_API
 static void eth_save_packet(void *packet, int length)
@@ -486,7 +815,7 @@ static void eth_current_changed(void)
 
 void eth_try_another(int first_restart)
 {
-	static struct eth_device *first_failed;
+	static void *first_failed;
 	char *ethrotate;
 
 	/*
@@ -515,12 +844,9 @@ void eth_set_current(void)
 {
 	static char *act;
 	static int  env_changed_id;
-	struct eth_device *old_current;
+	void *old_current;
 	int	env_id;
 
-	if (!eth_get_dev())	/* XXX no current */
-		return;
-
 	env_id = get_env_id();
 	if ((act == NULL) || (env_changed_id != env_id)) {
 		act = getenv("ethact");
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 08/14] dm: eth: Add network support to sandbox
  2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
                       ` (6 preceding siblings ...)
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 07/14] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
@ 2015-02-11  1:30     ` Joe Hershberger
  2015-02-15 15:49       ` Simon Glass
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 09/14] dm: eth: Add ARP and PING response to sandbox driver Joe Hershberger
                       ` (6 subsequent siblings)
  14 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-11  1:30 UTC (permalink / raw)
  To: u-boot

Add basic network support to sandbox which includes a network driver.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v3:
-Added 2 more ethaddr to sandbox
-Print which device in the debug write hwaddr

Changes in v2:
-Change printfs to debug in sandbox driver
-Remove unused priv struct for sandbox driver

 arch/sandbox/dts/sandbox.dts |  4 +++
 drivers/net/Makefile         |  1 +
 drivers/net/sandbox.c        | 86 ++++++++++++++++++++++++++++++++++++++++++++
 include/configs/sandbox.h    | 18 +++++++---
 4 files changed, 104 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/sandbox.c

diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 4c63e4f..502eb3d 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -183,4 +183,8 @@
 		};
 	};
 
+	eth at 10002000 {
+		compatible = "sandbox,eth";
+		reg = <0x10002000 0x1000>;
+	};
 };
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 46c4ac6..15dc431 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_NS8382X) += ns8382x.o
 obj-$(CONFIG_PCNET) += pcnet.o
 obj-$(CONFIG_RTL8139) += rtl8139.o
 obj-$(CONFIG_RTL8169) += rtl8169.o
+obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
 obj-$(CONFIG_SH_ETHER) += sh_eth.o
 obj-$(CONFIG_SMC91111) += smc91111.o
 obj-$(CONFIG_SMC911X) += smc911x.o
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
new file mode 100644
index 0000000..2a2ad41
--- /dev/null
+++ b/drivers/net/sandbox.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int sb_eth_init(struct udevice *dev, bd_t *bis)
+{
+	debug("eth_sandbox: Init\n");
+
+	return 0;
+}
+
+static int sb_eth_send(struct udevice *dev, void *packet, int length)
+{
+	debug("eth_sandbox: Send packet %d\n", length);
+
+	return 0;
+}
+
+static int sb_eth_recv(struct udevice *dev)
+{
+	return 0;
+}
+
+static void sb_eth_halt(struct udevice *dev)
+{
+	debug("eth_sandbox: Halt\n");
+}
+
+static int sb_eth_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev->platdata;
+	debug("eth_sandbox %s: Write HW ADDR - %pM\n", dev->name,
+	      pdata->enetaddr);
+	return 0;
+}
+
+static const struct eth_ops sb_eth_ops = {
+	.init			= sb_eth_init,
+	.send			= sb_eth_send,
+	.recv			= sb_eth_recv,
+	.halt			= sb_eth_halt,
+	.write_hwaddr		= sb_eth_write_hwaddr,
+};
+
+static int sb_eth_remove(struct udevice *dev)
+{
+	return 0;
+}
+
+#ifdef CONFIG_OF_CONTROL
+static int sb_eth_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev->platdata;
+
+	pdata->iobase = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
+	return 0;
+}
+
+static const struct udevice_id sb_eth_ids[] = {
+	{ .compatible = "sandbox,eth" },
+	{ }
+};
+#endif
+
+U_BOOT_DRIVER(eth_sandbox) = {
+	.name	= "eth_sandbox",
+	.id	= UCLASS_ETH,
+	.of_match = of_match_ptr(sb_eth_ids),
+	.ofdata_to_platdata = of_match_ptr(sb_eth_ofdata_to_platdata),
+	.remove	= sb_eth_remove,
+	.ops	= &sb_eth_ops,
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index e9d3f32..fdba1c8 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -139,9 +139,9 @@
 /* include default commands */
 #include <config_cmd_default.h>
 
-/* We don't have networking support yet */
-#undef CONFIG_CMD_NET
-#undef CONFIG_CMD_NFS
+#define CONFIG_DM_ETH
+#define CONFIG_ETH_SANDBOX
+#define CONFIG_CMD_PING
 
 #define CONFIG_CMD_HASH
 #define CONFIG_HASH_VERIFY
@@ -184,12 +184,20 @@
 
 #define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial,cros-ec-keyb\0" \
 					"stdout=serial,lcd\0" \
-					"stderr=serial,lcd\0"
+					"stderr=serial,lcd\0" \
+					"ethaddr=00:00:11:22:33:44\0" \
+					"eth1addr=00:00:11:22:33:45\0" \
+					"eth2addr=00:00:11:22:33:46\0" \
+					"ipaddr=1.2.3.4\0"
 #else
 
 #define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial\0" \
 					"stdout=serial,lcd\0" \
-					"stderr=serial,lcd\0"
+					"stderr=serial,lcd\0" \
+					"ethaddr=00:00:11:22:33:44\0" \
+					"eth1addr=00:00:11:22:33:45\0" \
+					"eth2addr=00:00:11:22:33:46\0" \
+					"ipaddr=1.2.3.4\0"
 #endif
 
 #define CONFIG_GZIP_COMPRESSED
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 09/14] dm: eth: Add ARP and PING response to sandbox driver
  2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
                       ` (7 preceding siblings ...)
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 08/14] dm: eth: Add network support to sandbox Joe Hershberger
@ 2015-02-11  1:30     ` Joe Hershberger
  2015-02-15 15:49       ` Simon Glass
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 10/14] test: dm: eth: Add tests for the eth dm implementation Joe Hershberger
                       ` (5 subsequent siblings)
  14 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-11  1:30 UTC (permalink / raw)
  To: u-boot

The sandbox driver will now generate response traffic to exercise the
ping command even when no network exists.  This allows the basic data
pathways of the DM to be tested.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
-Prevent a crash if memory is not allocated

Changes in v2:
-Change printfs to debug in sandbox driver
-Move static data to priv
-Move fake hwaddr to the device tree

 arch/sandbox/dts/sandbox.dts |   1 +
 drivers/net/sandbox.c        | 101 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 102 insertions(+)

diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 502eb3d..ba635e8 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -186,5 +186,6 @@
 	eth at 10002000 {
 		compatible = "sandbox,eth";
 		reg = <0x10002000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
 	};
 };
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
index 2a2ad41..f9fa1a1 100644
--- a/drivers/net/sandbox.c
+++ b/drivers/net/sandbox.c
@@ -15,22 +15,121 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+struct eth_sandbox_priv {
+	uchar fake_host_hwaddr[ARP_HLEN];
+	IPaddr_t fake_host_ipaddr;
+	uchar recv_packet_buffer[PKTSIZE];
+	int recv_packet_length;
+};
+
 static int sb_eth_init(struct udevice *dev, bd_t *bis)
 {
 	debug("eth_sandbox: Init\n");
 
+	struct eth_sandbox_priv *priv = dev->priv;
+	u32 int_array[ARP_HLEN];
+	int i;
+
+	if (!priv)
+		return -EINVAL;
+
+	fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "fake-host-hwaddr",
+			     int_array, ARP_HLEN);
+	for (i = 0; i < ARP_HLEN; i++)
+		priv->fake_host_hwaddr[i] = (uchar)int_array[i];
+
 	return 0;
 }
 
 static int sb_eth_send(struct udevice *dev, void *packet, int length)
 {
 	debug("eth_sandbox: Send packet %d\n", length);
+	struct eth_sandbox_priv *priv = dev->priv;
+	struct ethernet_hdr *eth = packet;
+
+	if (ntohs(eth->et_protlen) == PROT_ARP) {
+		struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
+		if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
+			/* store this as the assumed IP of the fake host */
+			priv->fake_host_ipaddr = NetReadIP(&arp->ar_tpa);
+			/* Formulate a fake response */
+			struct ethernet_hdr *eth_recv =
+				(void *)priv->recv_packet_buffer;
+			memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
+			memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
+			       ARP_HLEN);
+			eth_recv->et_protlen = htons(PROT_ARP);
+
+			struct arp_hdr *arp_recv =
+				(void *)priv->recv_packet_buffer +
+				ETHER_HDR_SIZE;
+			arp_recv->ar_hrd = htons(ARP_ETHER);
+			arp_recv->ar_pro = htons(PROT_IP);
+			arp_recv->ar_hln = ARP_HLEN;
+			arp_recv->ar_pln = ARP_PLEN;
+			arp_recv->ar_op = htons(ARPOP_REPLY);
+			memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr,
+			       ARP_HLEN);
+			NetWriteIP(&arp_recv->ar_spa, priv->fake_host_ipaddr);
+			memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN);
+			NetCopyIP(&arp_recv->ar_tpa, &arp->ar_spa);
+
+			priv->recv_packet_length = ETHER_HDR_SIZE +
+				ARP_HDR_SIZE;
+		}
+	} else if (ntohs(eth->et_protlen) == PROT_IP) {
+		struct ip_udp_hdr *ip = packet + ETHER_HDR_SIZE;
+		if (ip->ip_p == IPPROTO_ICMP) {
+			struct icmp_hdr *icmp = (struct icmp_hdr *)&ip->udp_src;
+			if (icmp->type == ICMP_ECHO_REQUEST) {
+				/* reply to the ping */
+				memcpy(priv->recv_packet_buffer, packet,
+				       length);
+				struct ethernet_hdr *eth_recv =
+					(void *)priv->recv_packet_buffer;
+				struct ip_udp_hdr *ipr =
+					(void *)priv->recv_packet_buffer +
+					ETHER_HDR_SIZE;
+				struct icmp_hdr *icmpr =
+					(struct icmp_hdr *)&ipr->udp_src;
+				memcpy(eth_recv->et_dest, eth->et_src,
+				       ARP_HLEN);
+				memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
+				       ARP_HLEN);
+				ipr->ip_sum = 0;
+				ipr->ip_off = 0;
+				NetCopyIP((void *)&ipr->ip_dst, &ip->ip_src);
+				NetWriteIP((void *)&ipr->ip_src,
+					   priv->fake_host_ipaddr);
+				ipr->ip_sum = ~NetCksum((uchar *)ipr,
+					IP_HDR_SIZE >> 1);
+
+				icmpr->type = ICMP_ECHO_REPLY;
+				icmpr->checksum = 0;
+				icmpr->checksum = ~NetCksum((uchar *)icmpr,
+					(length - ETHER_HDR_SIZE -
+						IP_HDR_SIZE) >> 1);
+
+				priv->recv_packet_length = length;
+			}
+		}
+	}
 
 	return 0;
 }
 
 static int sb_eth_recv(struct udevice *dev)
 {
+	struct eth_sandbox_priv *priv = dev->priv;
+
+	if (priv && priv->recv_packet_length) {
+		int lcl_recv_packet_length = priv->recv_packet_length;
+		debug("eth_sandbox: received packet %d\n",
+		      priv->recv_packet_length);
+		priv->recv_packet_length = 0;
+		NetReceive((void *)priv->recv_packet_buffer,
+			   lcl_recv_packet_length);
+	}
 	return 0;
 }
 
@@ -42,6 +141,7 @@ static void sb_eth_halt(struct udevice *dev)
 static int sb_eth_write_hwaddr(struct udevice *dev)
 {
 	struct eth_pdata *pdata = dev->platdata;
+
 	debug("eth_sandbox %s: Write HW ADDR - %pM\n", dev->name,
 	      pdata->enetaddr);
 	return 0;
@@ -82,5 +182,6 @@ U_BOOT_DRIVER(eth_sandbox) = {
 	.ofdata_to_platdata = of_match_ptr(sb_eth_ofdata_to_platdata),
 	.remove	= sb_eth_remove,
 	.ops	= &sb_eth_ops,
+	.priv_auto_alloc_size = sizeof(struct eth_sandbox_priv),
 	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
 };
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 10/14] test: dm: eth: Add tests for the eth dm implementation
  2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
                       ` (8 preceding siblings ...)
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 09/14] dm: eth: Add ARP and PING response to sandbox driver Joe Hershberger
@ 2015-02-11  1:30     ` Joe Hershberger
  2015-02-15 15:50       ` Simon Glass
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 11/14] dm: eth: Add support for aliases Joe Hershberger
                       ` (4 subsequent siblings)
  14 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-11  1:30 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v3:
-Added dm eth testing

Changes in v2: None

 test/dm/Makefile |  1 +
 test/dm/eth.c    | 39 +++++++++++++++++++++++++++++++++++++++
 test/dm/test.dts | 18 ++++++++++++++++++
 3 files changed, 58 insertions(+)
 create mode 100644 test/dm/eth.c

diff --git a/test/dm/Makefile b/test/dm/Makefile
index 1d9148f..b2eb989 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_DM_TEST) += ut.o
 obj-$(CONFIG_DM_TEST) += core.o
 obj-$(CONFIG_DM_TEST) += ut.o
 ifneq ($(CONFIG_SANDBOX),)
+obj-$(CONFIG_DM_ETH) += eth.o
 obj-$(CONFIG_DM_GPIO) += gpio.o
 obj-$(CONFIG_DM_I2C) += i2c.o
 obj-$(CONFIG_DM_SPI_FLASH) += sf.o
diff --git a/test/dm/eth.c b/test/dm/eth.c
new file mode 100644
index 0000000..2b29fa2
--- /dev/null
+++ b/test/dm/eth.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <dm/ut.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int dm_test_eth(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+
+	setenv("ethact", "eth at 10002000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	setenv("ethact", "eth at 10003000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10003000", getenv("ethact"));
+
+	setenv("ethact", "eth at 10004000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	return 0;
+}
+
+DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
diff --git a/test/dm/test.dts b/test/dm/test.dts
index 84024a4..2f68cdf 100644
--- a/test/dm/test.dts
+++ b/test/dm/test.dts
@@ -149,4 +149,22 @@
 		};
 	};
 
+	eth at 10002000 {
+		compatible = "sandbox,eth";
+		reg = <0x10002000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
+	};
+
+	eth at 10003000 {
+		compatible = "sandbox,eth";
+		reg = <0x10003000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
+	};
+
+	eth at 10004000 {
+		compatible = "sandbox,eth";
+		reg = <0x10004000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x22>;
+	};
+
 };
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 11/14] dm: eth: Add support for aliases
  2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
                       ` (9 preceding siblings ...)
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 10/14] test: dm: eth: Add tests for the eth dm implementation Joe Hershberger
@ 2015-02-11  1:30     ` Joe Hershberger
  2015-02-15 15:50       ` Simon Glass
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 12/14] dm: eth: Add support for ethprime env var Joe Hershberger
                       ` (3 subsequent siblings)
  14 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-11  1:30 UTC (permalink / raw)
  To: u-boot

Allow network devices to be referred to as "eth0" instead of
"eth at 12345678" when specified in ethact.

Add tests to verify this behavior.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v3:
-Added support for aliases

Changes in v2: None

 include/configs/sandbox.h |  4 ++--
 include/fdtdec.h          |  1 +
 include/net.h             |  5 +++++
 lib/fdtdec.c              |  1 +
 net/eth.c                 | 53 +++++++++++++++++++++++++++++++++++++++--------
 test/dm/eth.c             | 25 ++++++++++++++++++++++
 test/dm/test.dts          | 10 +++++----
 7 files changed, 84 insertions(+), 15 deletions(-)

diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index fdba1c8..9df5f74 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -187,7 +187,7 @@
 					"stderr=serial,lcd\0" \
 					"ethaddr=00:00:11:22:33:44\0" \
 					"eth1addr=00:00:11:22:33:45\0" \
-					"eth2addr=00:00:11:22:33:46\0" \
+					"eth5addr=00:00:11:22:33:46\0" \
 					"ipaddr=1.2.3.4\0"
 #else
 
@@ -196,7 +196,7 @@
 					"stderr=serial,lcd\0" \
 					"ethaddr=00:00:11:22:33:44\0" \
 					"eth1addr=00:00:11:22:33:45\0" \
-					"eth2addr=00:00:11:22:33:46\0" \
+					"eth5addr=00:00:11:22:33:46\0" \
 					"ipaddr=1.2.3.4\0"
 #endif
 
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 231eed7..e945baa 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -167,6 +167,7 @@ enum fdt_compat_id {
 	COMPAT_INTEL_GMA,		/* Intel Graphics Media Accelerator */
 	COMPAT_AMS_AS3722,		/* AMS AS3722 PMIC */
 	COMPAT_INTEL_ICH_SPI,		/* Intel ICH7/9 SPI controller */
+	COMPAT_ETHERNET,		/* Ethernet devices */
 
 	COMPAT_COUNT,
 };
diff --git a/include/net.h b/include/net.h
index 11471bd..4e98850 100644
--- a/include/net.h
+++ b/include/net.h
@@ -38,6 +38,8 @@
 
 #define PKTALIGN	ARCH_DMA_MINALIGN
 
+#define ETH_MAX_DEVS	32
+
 /* IPv4 addresses are always 32 bits in size */
 typedef __be32		IPaddr_t;
 
@@ -79,6 +81,8 @@ enum eth_state_t {
 };
 
 #ifdef CONFIG_DM_ETH
+#define ETH_ALIAS_ROOT "eth"
+
 struct eth_pdata {
 	phys_addr_t iobase;
 	unsigned char enetaddr[6];
@@ -96,6 +100,7 @@ struct eth_ops {
 };
 
 struct udevice *eth_get_dev(void); /* get the current device */
+struct udevice *eth_get_dev_by_name(const char *devname);
 unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
 int eth_init_state_only(bd_t *bis); /* Set active state */
 void eth_halt_state_only(void); /* Set passive state */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 5bf8f29..33b0a53 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -75,6 +75,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(INTEL_GMA, "intel,gma"),
 	COMPAT(AMS_AS3722, "ams,as3722"),
 	COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
+	COMPAT(ETHERNET, "eth"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
diff --git a/net/eth.c b/net/eth.c
index e84b948..762effe 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -10,11 +10,14 @@
 #include <command.h>
 #include <dm.h>
 #include <dm/device-internal.h>
+#include <fdtdec.h>
 #include <net.h>
 #include <miiphy.h>
 #include <phy.h>
 #include <asm/errno.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 void eth_parse_enetaddr(const char *addr, uchar *enetaddr)
 {
 	char *end;
@@ -121,6 +124,39 @@ static void eth_set_dev(struct udevice *dev)
 	uc_priv->current = dev;
 }
 
+/*
+ * Find the udevice that either has the name passed in as devname or has an
+ * alias named devname.
+ */
+struct udevice *eth_get_dev_by_name(const char *devname)
+{
+	int node_list[ETH_MAX_DEVS];
+	int count;
+	int seq;
+	char *endp = NULL;
+	const char *true_name = devname;
+	struct udevice *it;
+	struct uclass *uc;
+
+	count = fdtdec_find_aliases_for_id(gd->fdt_blob, ETH_ALIAS_ROOT,
+					   COMPAT_ETHERNET, node_list,
+					   ETH_MAX_DEVS);
+
+	seq = simple_strtoul(devname + strlen(ETH_ALIAS_ROOT), &endp, 10);
+
+	if (endp > devname + strlen(ETH_ALIAS_ROOT) && count > seq &&
+	    node_list[seq])
+		true_name = fdt_get_name(gd->fdt_blob, node_list[seq], NULL);
+
+	uclass_get(UCLASS_ETH, &uc);
+	uclass_foreach_dev(it, uc) {
+		if (strcmp(it->name, true_name) == 0 || it->seq == seq)
+			return it;
+	}
+
+	return NULL;
+}
+
 unsigned char *eth_get_ethaddr(void)
 {
 	struct eth_pdata *pdata;
@@ -396,6 +432,7 @@ UCLASS_DRIVER(eth) = {
 	.init		= eth_uclass_init,
 	.priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
 	.per_device_auto_alloc_size = sizeof(struct eth_device_priv),
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 };
 #endif
 
@@ -428,6 +465,11 @@ static void eth_set_current_to_next(void)
 	eth_current = eth_current->next;
 }
 
+static void eth_set_dev(struct eth_device *dev)
+{
+	eth_current = dev;
+}
+
 struct eth_device *eth_get_dev_by_name(const char *devname)
 {
 	struct eth_device *dev, *target_dev;
@@ -844,7 +886,6 @@ void eth_set_current(void)
 {
 	static char *act;
 	static int  env_changed_id;
-	void *old_current;
 	int	env_id;
 
 	env_id = get_env_id();
@@ -852,14 +893,8 @@ void eth_set_current(void)
 		act = getenv("ethact");
 		env_changed_id = env_id;
 	}
-	if (act != NULL) {
-		old_current = eth_get_dev();
-		do {
-			if (strcmp(eth_get_name(), act) == 0)
-				return;
-			eth_set_current_to_next();
-		} while (old_current != eth_get_dev());
-	}
+	if (act != NULL)
+		eth_set_dev(eth_get_dev_by_name(act));
 
 	eth_current_changed();
 }
diff --git a/test/dm/eth.c b/test/dm/eth.c
index 2b29fa2..c0a8ab5 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -37,3 +37,28 @@ static int dm_test_eth(struct dm_test_state *dms)
 }
 
 DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
+
+static int dm_test_eth_alias(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+	setenv("ethact", "eth0");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	setenv("ethact", "eth1");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	/* Expected to fail since eth2 is not defined in the device tree */
+	setenv("ethact", "eth2");
+	ut_asserteq(-1, NetLoop(PING));
+	ut_asserteq_ptr(NULL, getenv("ethact"));
+
+	setenv("ethact", "eth5");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10003000", getenv("ethact"));
+
+	return 0;
+}
+
+DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
diff --git a/test/dm/test.dts b/test/dm/test.dts
index 2f68cdf..c5008c3 100644
--- a/test/dm/test.dts
+++ b/test/dm/test.dts
@@ -17,6 +17,8 @@
 		testfdt3 = "/b-test";
 		testfdt5 = "/some-bus/c-test at 5";
 		testfdt8 = "/a-test";
+		eth0 = "/eth at 10002000";
+		eth5 = &eth_5;
 	};
 
 	uart0: serial {
@@ -150,19 +152,19 @@
 	};
 
 	eth at 10002000 {
-		compatible = "sandbox,eth";
+		compatible = "sandbox,eth", "eth";
 		reg = <0x10002000 0x1000>;
 		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
 	};
 
-	eth at 10003000 {
-		compatible = "sandbox,eth";
+	eth_5: eth at 10003000 {
+		compatible = "sandbox,eth", "eth";
 		reg = <0x10003000 0x1000>;
 		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
 	};
 
 	eth at 10004000 {
-		compatible = "sandbox,eth";
+		compatible = "sandbox,eth", "eth";
 		reg = <0x10004000 0x1000>;
 		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x22>;
 	};
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 12/14] dm: eth: Add support for ethprime env var
  2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
                       ` (10 preceding siblings ...)
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 11/14] dm: eth: Add support for aliases Joe Hershberger
@ 2015-02-11  1:30     ` Joe Hershberger
  2015-02-15 15:50       ` Simon Glass
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 13/14] dm: eth: Add testing for netretry " Joe Hershberger
                       ` (2 subsequent siblings)
  14 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-11  1:30 UTC (permalink / raw)
  To: u-boot

The ethprime env var is used to indicate the starting device if none is
specified in ethact. Also support aliases specified in the ethprime var.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v3:
-Added support for ethprime

Changes in v2: None

 net/eth.c     | 13 ++++++++++++-
 test/dm/eth.c | 21 +++++++++++++++++++++
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/net/eth.c b/net/eth.c
index 762effe..1770662 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -893,8 +893,19 @@ void eth_set_current(void)
 		act = getenv("ethact");
 		env_changed_id = env_id;
 	}
-	if (act != NULL)
+
+	if (act == NULL) {
+		char *ethprime = getenv("ethprime");
+
+		if (ethprime && eth_get_dev_by_name(ethprime)) {
+			eth_set_dev(eth_get_dev_by_name(ethprime));
+		} else {
+			eth_set_dev(NULL);
+			eth_set_current_to_next();
+		}
+	} else {
 		eth_set_dev(eth_get_dev_by_name(act));
+	}
 
 	eth_current_changed();
 }
diff --git a/test/dm/eth.c b/test/dm/eth.c
index c0a8ab5..b39a94a 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -62,3 +62,24 @@ static int dm_test_eth_alias(struct dm_test_state *dms)
 }
 
 DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
+
+static int dm_test_eth_prime(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+
+	/* Expected to be "eth at 10003000" because of ethprime variable */
+	setenv("ethact", NULL);
+	setenv("ethprime", "eth5");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10003000", getenv("ethact"));
+
+	/* Expected to be "eth at 10002000" because it is first */
+	setenv("ethact", NULL);
+	setenv("ethprime", NULL);
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	return 0;
+}
+
+DM_TEST(dm_test_eth_prime, DM_TESTF_SCAN_FDT);
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 13/14] dm: eth: Add testing for netretry env var
  2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
                       ` (11 preceding siblings ...)
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 12/14] dm: eth: Add support for ethprime env var Joe Hershberger
@ 2015-02-11  1:30     ` Joe Hershberger
  2015-02-15 15:50       ` Simon Glass
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 14/14] dm: eth: Add a bridge to a real network for sandbox Joe Hershberger
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
  14 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-11  1:30 UTC (permalink / raw)
  To: u-boot

Make sure that the retry behavior occurs as expected.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v3:
-Added testing for netretry

Changes in v2: None

 test/dm/eth.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/test/dm/eth.c b/test/dm/eth.c
index b39a94a..831a994 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -83,3 +83,28 @@ static int dm_test_eth_prime(struct dm_test_state *dms)
 }
 
 DM_TEST(dm_test_eth_prime, DM_TESTF_SCAN_FDT);
+
+static int dm_test_eth_retry(struct dm_test_state *dms)
+{
+	char ethaddr[18];
+
+	NetPingIP = string_to_ip("1.1.2.2");
+	strcpy(ethaddr, getenv("eth1addr"));
+	setenv("ethact", "eth at 10004000");
+	setenv("eth1addr", NULL);
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	setenv("ethact", "eth at 10004000");
+	setenv("netretry", "no");
+	ut_asserteq(-1, NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	/* Restore the env */
+	setenv("eth1addr", ethaddr);
+	setenv("netretry", NULL);
+
+	return 0;
+}
+
+DM_TEST(dm_test_eth_retry, DM_TESTF_SCAN_FDT);
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 14/14] dm: eth: Add a bridge to a real network for sandbox
  2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
                       ` (12 preceding siblings ...)
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 13/14] dm: eth: Add testing for netretry " Joe Hershberger
@ 2015-02-11  1:30     ` Joe Hershberger
  2015-02-15 15:50       ` Simon Glass
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
  14 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-11  1:30 UTC (permalink / raw)
  To: u-boot

Implement a bridge between u-boot's network stack and Linux's raw packet
API allowing the sandbox to send and receive packets using the host
machine's network interface.

This raw Ethernet API requires elevated privileges.  You can either run
as root, or you can add the capability needed like so:

sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v3:
-Made the os raw packet support for sandbox eth build and work.

Changes in v2:
-Added the raw packet proof-of-concept patch.

 arch/sandbox/dts/sandbox.dts              |   6 ++
 arch/sandbox/include/asm/sandbox-raw-os.h |  16 ++++
 drivers/net/Makefile                      |  11 +++
 drivers/net/sandbox-raw-os.c              | 105 ++++++++++++++++++++++++
 drivers/net/sandbox-raw.c                 | 128 ++++++++++++++++++++++++++++++
 include/configs/sandbox.h                 |   1 +
 6 files changed, 267 insertions(+)
 create mode 100644 arch/sandbox/include/asm/sandbox-raw-os.h
 create mode 100644 drivers/net/sandbox-raw-os.c
 create mode 100644 drivers/net/sandbox-raw.c

diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index ba635e8..13bd6c2 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -188,4 +188,10 @@
 		reg = <0x10002000 0x1000>;
 		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
 	};
+
+	eth at 80000000 {
+		compatible = "sandbox,eth,raw";
+		reg = <0x80000000 0x1000>;
+		host-raw-interface = "eth0";
+	};
 };
diff --git a/arch/sandbox/include/asm/sandbox-raw-os.h b/arch/sandbox/include/asm/sandbox-raw-os.h
new file mode 100644
index 0000000..4e5d418
--- /dev/null
+++ b/arch/sandbox/include/asm/sandbox-raw-os.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#pragma once
+
+int sandbox_raw_init(int *sd, void **devp, const char *ifname,
+		     unsigned char *ethmac);
+int sandbox_raw_send(void *packet, int length, int sd, void *device);
+int sandbox_raw_recv(void *packet, int *length, int sd, void *device);
+void sandbox_raw_halt(int *sd, void **devp);
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 15dc431..39975b3 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -51,6 +51,8 @@ obj-$(CONFIG_PCNET) += pcnet.o
 obj-$(CONFIG_RTL8139) += rtl8139.o
 obj-$(CONFIG_RTL8169) += rtl8169.o
 obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
+obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o
+obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw-os.o
 obj-$(CONFIG_SH_ETHER) += sh_eth.o
 obj-$(CONFIG_SMC91111) += smc91111.o
 obj-$(CONFIG_SMC911X) += smc911x.o
@@ -68,3 +70,12 @@ obj-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o xilinx_ll_temac_mdio.o \
 obj-$(CONFIG_ZYNQ_GEM) += zynq_gem.o
 obj-$(CONFIG_FSL_MC_ENET) += fsl_mc/
 obj-$(CONFIG_VSC9953) += vsc9953.o
+
+# sandbox-raw-os.c is built in the system env, so needs standard includes
+# CFLAGS_REMOVE_sandbox-raw-os.o cannot be used to drop header include path
+quiet_cmd_cc_sandbox-raw-os.o = CC $(quiet_modtag)  $@
+cmd_cc_sandbox-raw-os.o = $(CC) $(filter-out -nostdinc, \
+	$(patsubst -I%,-idirafter%,$(c_flags))) -c -o $@ $<
+
+$(obj)/sandbox-raw-os.o: $(src)/sandbox-raw-os.c FORCE
+	$(call if_changed_dep,cc_sandbox-raw-os.o)
diff --git a/drivers/net/sandbox-raw-os.c b/drivers/net/sandbox-raw-os.c
new file mode 100644
index 0000000..43fae60
--- /dev/null
+++ b/drivers/net/sandbox-raw-os.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <errno.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+
+int sandbox_raw_init(int *sd, void **devp, const char *ifname,
+		     unsigned char *ethmac)
+{
+	int tempsd = 0;
+	struct ifreq ifr;
+
+	strcpy(ifr.ifr_name, ifname);
+	ifr.ifr_addr.sa_family = AF_INET;
+	memset(ethmac, 0, 6);
+	tempsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+	if (tempsd < 0) {
+		printf("Failed to open socket: %d %s\n", errno,
+		       strerror(errno));
+		return 1;
+	}
+	if (ioctl(tempsd, SIOCGIFHWADDR, &ifr) < 0) {
+		printf("Failed to call ioctl: %s\n", strerror(errno));
+		close(tempsd);
+		return 1;
+	}
+	/*
+	 * This only works if the MAC address is overridden with the actual MAC
+	 * address of the interface being used.
+	 */
+	memcpy(ethmac, ifr.ifr_hwaddr.sa_data, 6 * sizeof(uint8_t));
+	close(tempsd);
+
+	*devp = malloc(sizeof(struct sockaddr_ll));
+	struct sockaddr_ll *device = *devp;
+	memset(device, 0, sizeof(struct sockaddr_ll));
+	device->sll_ifindex = if_nametoindex(ifname);
+	device->sll_family = AF_PACKET;
+	memcpy(device->sll_addr, ethmac, 6);
+	device->sll_halen = htons(6);
+
+	*sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+	setsockopt(*sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
+		   strlen(ifname) + 1);
+
+	return 0;
+}
+
+int sandbox_raw_send(void *packet, int length, int sd, void *device)
+{
+	int retval;
+
+	if (!sd || !device)
+		return -EINVAL;
+	retval = sendto(sd, packet, length, 0,
+		   (struct sockaddr *)device, sizeof(struct sockaddr_ll));
+	if (retval < 0)
+		printf("Failed to send packet: %d %s\n", errno,
+		       strerror(errno));
+	return retval;
+}
+
+int sandbox_raw_recv(void *packet, int *length, int sd, void *device)
+{
+	int retval;
+	int saddr_size;
+
+	if (!sd || !device)
+		return -EINVAL;
+	saddr_size = sizeof(struct sockaddr);
+	retval = recvfrom(sd, packet, 1536, 0, (struct sockaddr *)device,
+			  (socklen_t *)&saddr_size);
+	*length = 0;
+	if (retval > 0) {
+		*length = retval;
+		return 0;
+	}
+
+	return retval;
+}
+
+void sandbox_raw_halt(int *sd, void **devp)
+{
+	free((struct sockaddr_ll *)*devp);
+	*devp = NULL;
+	close(*sd);
+	*sd = -1;
+}
diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
new file mode 100644
index 0000000..90e462a
--- /dev/null
+++ b/drivers/net/sandbox-raw.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/sandbox-raw-os.h>
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct eth_sandbox_raw_priv {
+	int sd;
+	void *device;
+};
+
+static int sb_eth_raw_init(struct udevice *dev, bd_t *bis)
+{
+	debug("eth_sandbox_raw: Init\n");
+
+	struct eth_sandbox_raw_priv *priv = dev->priv;
+	if (!priv)
+		return -EINVAL;
+
+	struct eth_pdata *pdata = dev->platdata;
+	int retval;
+	const char *interface = fdt_getprop(gd->fdt_blob, dev->of_offset,
+					    "host-raw-interface", NULL);
+
+	retval = sandbox_raw_init(&priv->sd, &priv->device, interface,
+				  pdata->enetaddr);
+
+	return retval;
+}
+
+static int sb_eth_raw_send(struct udevice *dev, void *packet, int length)
+{
+	debug("eth_sandbox_raw: Send packet %d\n", length);
+
+	struct eth_sandbox_raw_priv *priv = dev->priv;
+
+	return sandbox_raw_send(packet, length, priv->sd, priv->device);
+}
+
+static int sb_eth_raw_recv(struct udevice *dev)
+{
+	struct eth_sandbox_raw_priv *priv = dev->priv;
+
+	int retval;
+	uchar buffer[PKTSIZE];
+	int length;
+
+	if (!priv)
+		return 0;
+	retval = sandbox_raw_recv(buffer, &length, priv->sd, priv->device);
+	if (!retval && length) {
+		debug("eth_sandbox_raw: received packet %d\n",
+		      length);
+		NetReceive(buffer, length);
+	}
+	return 0;
+}
+
+static void sb_eth_raw_halt(struct udevice *dev)
+{
+	debug("eth_sandbox_raw: Halt\n");
+
+	struct eth_sandbox_raw_priv *priv = dev->priv;
+
+	if (!priv)
+		return;
+	sandbox_raw_halt(&priv->sd, &priv->device);
+}
+
+static int sb_eth_raw_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev->platdata;
+
+	debug("eth_sandbox_raw %s: Write HW ADDR - %pM\n", dev->name,
+	      pdata->enetaddr);
+	return 0;
+}
+
+static const struct eth_ops sb_eth_raw_ops = {
+	.init			= sb_eth_raw_init,
+	.send			= sb_eth_raw_send,
+	.recv			= sb_eth_raw_recv,
+	.halt			= sb_eth_raw_halt,
+	.write_hwaddr		= sb_eth_raw_write_hwaddr,
+};
+
+static int sb_eth_raw_remove(struct udevice *dev)
+{
+	return 0;
+}
+
+#ifdef CONFIG_OF_CONTROL
+static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev->platdata;
+
+	pdata->iobase = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
+	return 0;
+}
+
+static const struct udevice_id sb_eth_raw_ids[] = {
+	{ .compatible = "sandbox,eth,raw" },
+	{ }
+};
+#endif
+
+U_BOOT_DRIVER(eth_sandbox_raw) = {
+	.name	= "eth_sandbox_raw",
+	.id	= UCLASS_ETH,
+	.of_match = of_match_ptr(sb_eth_raw_ids),
+	.ofdata_to_platdata = of_match_ptr(sb_eth_raw_ofdata_to_platdata),
+	.remove	= sb_eth_raw_remove,
+	.ops	= &sb_eth_raw_ops,
+	.priv_auto_alloc_size = sizeof(struct eth_sandbox_raw_priv),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 9df5f74..7afa3d2 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -141,6 +141,7 @@
 
 #define CONFIG_DM_ETH
 #define CONFIG_ETH_SANDBOX
+#define CONFIG_ETH_SANDBOX_RAW
 #define CONFIG_CMD_PING
 
 #define CONFIG_CMD_HASH
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 02/14] test: dm: Reorder the objects to build
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 02/14] test: dm: Reorder the objects to build Joe Hershberger
@ 2015-02-11  4:39       ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-11  4:39 UTC (permalink / raw)
  To: u-boot

On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v3:
> -Reorder dm test makefile
>
> Changes in v2: None
>
>  test/dm/Makefile | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

Acked-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 01/14] dm: core: Allow seq numbers to be resolved before probe
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 01/14] dm: core: Allow seq numbers to be resolved before probe Joe Hershberger
@ 2015-02-11  4:39       ` Simon Glass
  2015-02-11  6:08         ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-02-11  4:39 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Before this patch, if the sequence numbers were resolved before probe,
> this code would insist on defining new non-conflicting-with-itself seq
> numbers. Now any "non -1" seq number is accepted as already resolved.

Can you explain what problem this solves? At present, when probing a
device, ->seq must be -1 (sort-of by definition since it doesn't exist
as an active device in the uclass).

>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v3:
> -Add seq patch to dm core
>
> Changes in v2: None
>
>  drivers/core/uclass.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
> index 289a5d2..2d8b6f8 100644
> --- a/drivers/core/uclass.c
> +++ b/drivers/core/uclass.c
> @@ -366,7 +366,9 @@ int uclass_resolve_seq(struct udevice *dev)
>         int seq;
>         int ret;
>
> -       assert(dev->seq == -1);
> +       if (dev->seq != -1)
> +               return dev->seq;
> +
>         ret = uclass_find_device_by_seq(dev->uclass->uc_drv->id, dev->req_seq,
>                                         false, &dup);
>         if (!ret) {
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 01/14] dm: core: Allow seq numbers to be resolved before probe
  2015-02-11  4:39       ` Simon Glass
@ 2015-02-11  6:08         ` Joe Hershberger
  2015-02-13  5:14           ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-11  6:08 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Tue, Feb 10, 2015 at 10:39 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > Before this patch, if the sequence numbers were resolved before probe,
> > this code would insist on defining new non-conflicting-with-itself seq
> > numbers. Now any "non -1" seq number is accepted as already resolved.
>
> Can you explain what problem this solves? At present, when probing a
> device, ->seq must be -1 (sort-of by definition since it doesn't exist
> as an active device in the uclass).

Please look at eth_post_bind() in patch 07/14.  The Ethernet devices need
to write their hardware addresses to the registers in bind (since it needs
to happen regardless of the device being used so that Linux will see the
MAC address).  As such, the sequence number is needed to look up the
ethaddr. In order to avoid probing all the devices to get the seq number
resolved, I resolve it in post_bind to avoid the rest of the overhead (thus
no longer probing in post_bind, which was one of the issues previously).
Then when probe comes along, the seq is already resolved.  That's why this
patch is needed.

Thanks,
-Joe

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 5/8] net: Add basic driver model support to Ethernet stack
  2015-02-07  1:25     ` Simon Glass
@ 2015-02-11  6:25       ` Joe Hershberger
  2015-02-13  5:20         ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-11  6:25 UTC (permalink / raw)
  To: u-boot

On Fri, Feb 6, 2015 at 7:25 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 2 February 2015 at 17:38, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > First just add support for MAC drivers.
> >
> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> >
> > ---
> >
> > Changes in v2:
> > -Updated comments
> > -Removed extra parentheses
> > -Changed eth_uclass_priv local var names to be uc_priv
> > -Update error codes
> > -Cause an invalid name to fail binding
> > -Rebase on top of dm/master
> > -Stop maintaining our own index and use DM seq now that it works for
our needs
> > -Move the hwaddr to platdata so that its memory is allocated at bind
when we need it
> > -Prevent device from being probed before used by a command (i.e. before
eth_init()).
> >
> >  common/board_r.c       |   4 +-
> >  common/cmd_bdinfo.c    |   2 +
> >  include/dm/uclass-id.h |   1 +
> >  include/net.h          |  24 ++++
> >  net/eth.c              | 319
++++++++++++++++++++++++++++++++++++++++++++++++-
> >  5 files changed, 346 insertions(+), 4 deletions(-)
> >
> > diff --git a/common/board_r.c b/common/board_r.c
> > index 68a9448..75147b7 100644
> > --- a/common/board_r.c
> > +++ b/common/board_r.c
> > @@ -556,7 +556,7 @@ static int initr_bbmii(void)
> >  }
> >  #endif
> >
> > -#ifdef CONFIG_CMD_NET
> > +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
> >  static int initr_net(void)
> >  {
> >         puts("Net:   ");
> > @@ -825,7 +825,7 @@ init_fnc_t init_sequence_r[] = {
> >  #ifdef CONFIG_BITBANGMII
> >         initr_bbmii,
> >  #endif
> > -#ifdef CONFIG_CMD_NET
> > +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
> >         INIT_FUNC_WATCHDOG_RESET
> >         initr_net,
> >  #endif
> > diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
> > index e6d8a7a..8688cf9 100644
> > --- a/common/cmd_bdinfo.c
> > +++ b/common/cmd_bdinfo.c
> > @@ -34,6 +34,7 @@ static void print_eth(int idx)
> >         printf("%-12s= %s\n", name, val);
> >  }
> >
> > +#ifndef CONFIG_DM_ETH
> >  __maybe_unused
> >  static void print_eths(void)
> >  {
> > @@ -52,6 +53,7 @@ static void print_eths(void)
> >         printf("current eth = %s\n", eth_get_name());
> >         printf("ip_addr     = %s\n", getenv("ipaddr"));
> >  }
> > +#endif
> >
> >  __maybe_unused
> >  static void print_lnum(const char *name, unsigned long long value)
> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> > index 91bb90d..ad96682 100644
> > --- a/include/dm/uclass-id.h
> > +++ b/include/dm/uclass-id.h
> > @@ -34,6 +34,7 @@ enum uclass_id {
> >         UCLASS_I2C_GENERIC,     /* Generic I2C device */
> >         UCLASS_I2C_EEPROM,      /* I2C EEPROM device */
> >         UCLASS_MOD_EXP,         /* RSA Mod Exp device */
> > +       UCLASS_ETH,             /* Ethernet device */
> >
> >         UCLASS_COUNT,
> >         UCLASS_INVALID = -1,
> > diff --git a/include/net.h b/include/net.h
> > index 7eef9cc..4d21d91 100644
> > --- a/include/net.h
> > +++ b/include/net.h
> > @@ -78,6 +78,30 @@ enum eth_state_t {
> >         ETH_STATE_ACTIVE
> >  };
> >
> > +#ifdef CONFIG_DM_ETH
>
> You may not need this?

I need it for the function prototypes that have a different device pointer
parameter.

> > +struct eth_pdata {
> > +       phys_addr_t iobase;
> > +       unsigned char enetaddr[6];
> > +};
> > +
> > +struct eth_ops {
> > +       int (*init)(struct udevice *dev, bd_t *bis);
> > +       int (*send)(struct udevice *dev, void *packet, int length);
> > +       int (*recv)(struct udevice *dev);
> > +       void (*halt)(struct udevice *dev);
> > +#ifdef CONFIG_MCAST_TFTP
> > +       int (*mcast)(struct udevice *dev, const u8 *enetaddr, u8 set);
> > +#endif
> > +       int (*write_hwaddr)(struct udevice *dev);
> > +};
> > +
> > +struct udevice *eth_get_dev(void); /* get the current device */
> > +unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
> > +int eth_init_state_only(bd_t *bis); /* Set active state */
> > +void eth_halt_state_only(void); /* Set passive state */
> > +#endif
> > +
> > +#ifndef CONFIG_DM_ETH
> >  struct eth_device {
> >         char name[16];
> >         unsigned char enetaddr[6];
> > diff --git a/net/eth.c b/net/eth.c
> > index c02548c..1b5a169 100644
> > --- a/net/eth.c
> > +++ b/net/eth.c
> > @@ -72,6 +72,320 @@ static int eth_mac_skip(int index)
> >         return ((skip_state = getenv(enetvar)) != NULL);
> >  }
> >
> > +static void eth_current_changed(void);
> > +
> > +#ifdef CONFIG_DM_ETH
> > +#include <dm.h>
> > +#include <dm/device-internal.h>
>
> These should go at the top of the file - should be OK to always
> include them (i.e. no #ifdef)

OK... Moved them.

> > +
> > +struct eth_device_priv {
> > +       int state;
> > +       void *priv;
> > +};
> > +
> > +struct eth_uclass_priv {
> > +       struct udevice *current;
> > +};
> > +
> > +static void eth_set_current_to_next(void)
> > +{
> > +       struct uclass *uc;
> > +       struct eth_uclass_priv *uc_priv;
> > +
> > +       uclass_get(UCLASS_ETH, &uc);
>
> This can actually return an error, although I agree there is little
> point in handling it. So I suppose this is OK.

I think this should be a given.

> > +       uc_priv = uc->priv;
> > +       uclass_next_device(&uc_priv->current);
> > +       if (!uc_priv->current)
> > +               uclass_first_device(UCLASS_ETH, &uc_priv->current);
> > +}
> > +
> > +struct udevice *eth_get_dev(void)
> > +{
> > +       struct uclass *uc;
>
> blank line here

OK on all of these.

> > +       uclass_get(UCLASS_ETH, &uc);
> > +
> > +       struct eth_uclass_priv *uc_priv = uc->priv;
> > +       return uc_priv->current;
> > +}
> > +
> > +static void eth_set_dev(struct udevice *dev)
> > +{
> > +       struct uclass *uc;
>
> blank line here
>
> > +       uclass_get(UCLASS_ETH, &uc);
> > +
> > +       struct eth_uclass_priv *uc_priv = uc->priv;
> > +       uc_priv->current = dev;
> > +}
> > +
> > +unsigned char *eth_get_ethaddr(void)
> > +{
> > +       struct eth_pdata *pdata;
>
> blank line here
>
> > +       if (eth_get_dev()) {
> > +               pdata = eth_get_dev()->platdata;
> > +               if (pdata)
> > +                       return pdata->enetaddr;
> > +       }
> > +       return NULL;
> > +}
> > +
> > +/* Set active state */
> > +int eth_init_state_only(bd_t *bis)
> > +{
> > +       struct eth_device_priv *priv;
>
> blank line here
>
> > +       if (eth_get_dev()) {
> > +               priv = eth_get_dev()->uclass_priv;
> > +               if (priv)
> > +                       priv->state = ETH_STATE_ACTIVE;
> > +       }
> > +
> > +       return 0;
> > +}
> > +/* Set passive state */
> > +void eth_halt_state_only(void)
> > +{
> > +       struct eth_device_priv *priv;
>
> blank line here
>
> > +       if (eth_get_dev()) {
> > +               priv = eth_get_dev()->uclass_priv;
> > +               if (priv)
> > +                       priv->state = ETH_STATE_PASSIVE;
> > +       }
> > +}
> > +
> > +int eth_get_dev_index(void)
> > +{
> > +       if (eth_get_dev())
> > +               return eth_get_dev()->seq;
> > +       return -1;
> > +}
> > +
> > +int eth_init(bd_t *bis)
> > +{
> > +       struct udevice *current, *old_current, *dev;
> > +       struct uclass *uc;
> > +
> > +       current = eth_get_dev();
> > +       if (!current) {
> > +               puts("No ethernet found.\n");
> > +               return -1;
> > +       }
> > +       device_probe(current);
>
> Check error

OK.

> > +
> > +       /* Sync environment with network devices */
> > +       uclass_get(UCLASS_ETH, &uc);
> > +       uclass_foreach_dev(dev, uc) {
> > +               uchar env_enetaddr[6];
> > +
> > +               if (eth_getenv_enetaddr_by_index("eth", dev->seq,
> > +                                                env_enetaddr)) {
> > +                       struct eth_pdata *pdata = dev->platdata;
>
> blank line
>
> Do all devices have the same platdata by design? What if a particular
> device wants its own?

That's a good question.  I imagine some devices may have something unique,
but I would expect they would read that data into the priv data that they
define.  How do other subsystems handle platform data for unique devices?

> > +                       if (pdata)
>
> What do you need this check?

No.  This was left over from when enetaddr was in priv.

> > +                               memcpy(pdata->enetaddr, env_enetaddr,
6);
> > +               }
> > +       };
> > +
> > +       old_current = current;
> > +       do {
> > +               debug("Trying %s\n", current->name);
> > +
> > +               if (current->driver) {
> > +                       const struct eth_ops *ops =
current->driver->ops;
>
> blank line
>
> > +                       if (ops->init(current, bis) >= 0) {
> > +                               struct eth_device_priv *priv =
> > +                                       current->uclass_priv;
> > +                               if (priv)
> > +                                       priv->state = ETH_STATE_ACTIVE;
> > +
> > +                               return 0;
> > +                       }
> > +               }
> > +               debug("FAIL\n");
> > +
> > +               eth_try_another(0);
> > +               current = eth_get_dev();
> > +       } while (old_current != current);
> > +
> > +       return -ENODEV;
> > +}
> > +
> > +void eth_halt(void)
> > +{
> > +       struct udevice *current;
> > +
> > +       current = eth_get_dev();
> > +       if (!current)
> > +               return;
> > +       if (!current->driver)
> > +               return;
> > +
> > +       const struct eth_ops *ops = current->driver->ops;
> > +       ops->halt(current);
> > +
> > +       struct eth_device_priv *priv = current->uclass_priv;
> > +       if (priv)
> > +               priv->state = ETH_STATE_PASSIVE;
> > +}
> > +
> > +int eth_send(void *packet, int length)
> > +{
> > +       struct udevice *current;
> > +
> > +       current = eth_get_dev();
> > +       if (!current)
> > +               return -1;
> > +       if (!current->driver)
> > +               return -1;
>
> Seems like eth_get_dev() should return an error code if current or
> current->driver is NULL.

It's returning a pointer, so I prefer it to be NULL or a valid pointer.

Perhaps you meant to say that eth_send() should return an error code?

> > +
> > +       const struct eth_ops *ops = current->driver->ops;
> > +       return ops->send(current, packet, length);
> > +}
> > +
> > +int eth_rx(void)
> > +{
> > +       struct udevice *current;
> > +
> > +       current = eth_get_dev();
> > +       if (!current)
> > +               return -1;
> > +       if (!current->driver)
> > +               return -1;
> > +
> > +       const struct eth_ops *ops = current->driver->ops;
> > +       return ops->recv(current);
> > +}
> > +
> > +static int eth_write_hwaddr(struct udevice *dev, const char *base_name,
> > +                  int eth_number)
> > +{
> > +       unsigned char env_enetaddr[6];
> > +       int ret = 0;
> > +
> > +       eth_getenv_enetaddr_by_index(base_name, eth_number,
env_enetaddr);
> > +
> > +       struct eth_pdata *pdata = dev->platdata;
> > +       if (!is_zero_ether_addr(env_enetaddr)) {
> > +               if (!is_zero_ether_addr(pdata->enetaddr) &&
> > +                   memcmp(pdata->enetaddr, env_enetaddr, 6)) {
> > +                       printf("\nWarning: %s MAC addresses don't
match:\n",
> > +                              dev->name);
> > +                       printf("Address in SROM is         %pM\n",
> > +                              pdata->enetaddr);
> > +                       printf("Address in environment is  %pM\n",
> > +                              env_enetaddr);
> > +               }
> > +
> > +               memcpy(pdata->enetaddr, env_enetaddr, 6);
> > +       } else if (is_valid_ether_addr(pdata->enetaddr)) {
> > +               eth_setenv_enetaddr_by_index(base_name, eth_number,
> > +                                            pdata->enetaddr);
> > +               printf("\nWarning: %s using MAC address from net
device\n",
> > +                      dev->name);
> > +       } else if (is_zero_ether_addr(pdata->enetaddr)) {
> > +               printf("\nError: %s address not set.\n",
> > +                      dev->name);
> > +               return -EINVAL;
> > +       }
> > +
> > +       const struct eth_ops *ops = dev->driver->ops;
> > +       if (ops->write_hwaddr && !eth_mac_skip(eth_number)) {
> > +               if (!is_valid_ether_addr(pdata->enetaddr)) {
> > +                       printf("\nError: %s address %pM illegal
value\n",
> > +                              dev->name, pdata->enetaddr);
> > +                       return -EINVAL;
> > +               }
> > +
> > +               ret = ops->write_hwaddr(dev);
> > +               if (ret)
> > +                       printf("\nWarning: %s failed to set MAC
address\n",
> > +                              dev->name);
> > +       }
>
> The above code seems mostly duplicated but I suppose it is hard to
> make it common?

It is, but I look forward to the day when we delete the other copy.  It
would be difficult to combine, for sure.

> > +
> > +       return ret;
> > +}
> > +
> > +static int eth_uclass_init(struct uclass *class)
> > +{
> > +       bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
> > +
> > +       eth_env_init();
> > +
> > +       return 0;
> > +}
> > +
> > +static int eth_post_bind(struct udevice *dev)
> > +{
> > +       if (strchr(dev->name, ' ')) {
> > +               printf("\nError: eth device name \"%s\" has a space!\n",
> > +                      dev->name);
> > +               return -EINVAL;
> > +       }
> > +
> > +       if (!eth_get_dev()) {
> > +               eth_set_dev(dev);
> > +               eth_current_changed();
> > +       }
>
> I still don't really get what you are doing here. Perhaps you could
> add some comments? There should be no probed devices at this stage
> since you are binding only.

This has changed a fair amount in v3.  Please comment there if it's more
clear now.

> > +
> > +       char *ethprime = getenv("ethprime");
> > +       if (ethprime && strcmp(dev->name, ethprime) == 0) {
> > +               eth_set_dev(dev);
> > +               eth_current_changed();
> > +       }
> > +
> > +       /*
> > +        * Devices need to write the hwaddr even if not probed so that
Linux
> > +        * will have access to the hwaddr that u-boot stored for the
device.
> > +        */
> > +       eth_write_hwaddr(dev, "eth", uclass_resolve_seq(dev));
> > +
> > +       return 0;
> > +}
> > +
> > +static int eth_pre_unbind(struct udevice *dev)
> > +{
> > +       struct udevice *first = NULL;
> > +       struct udevice *current;
> > +       struct uclass *uc;
> > +
> > +       uclass_get(UCLASS_ETH, &uc);
> > +       uclass_foreach_dev(current, uc) {
> > +               if (!first)
> > +                       first = current;
> > +               if (current == dev) {
> > +                       if (dev == first) {
> > +                               current =
list_entry(current->uclass_node.next,
> > +                                          struct udevice, uclass_node);
> > +                       } else {
> > +                               current = first;
> > +                       }
> > +                       eth_set_dev(current);
> > +                       eth_current_changed();
> > +               }
> > +       }
>
> If this is turning down a device it really should happen in a remove()
> method. Maybe in post_remove()?

This has changed a fair amount in v3.  Please comment there if it's more
clear now.

> > +
> > +       return 0;
> > +}
> > +
> > +static int eth_post_probe(struct udevice *dev)
> > +{
> > +       struct eth_device_priv *priv = dev->uclass_priv;
> > +       if (priv)
> > +               priv->state = ETH_STATE_INIT;
> > +
> > +       return 0;
> > +}
> > +
> > +UCLASS_DRIVER(eth) = {
> > +       .name           = "eth",
> > +       .id             = UCLASS_ETH,
> > +       .post_bind      = eth_post_bind,
> > +       .pre_unbind     = eth_pre_unbind,
> > +       .post_probe     = eth_post_probe,
> > +       .init           = eth_uclass_init,
> > +       .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
> > +       .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
> > +};
> > +#endif
> > +
> > +#ifndef CONFIG_DM_ETH
> >  /*
> >   * CPU and board-specific Ethernet initializations.  Aliased function
> >   * signals caller to move on
> > @@ -423,6 +737,7 @@ int eth_rx(void)
> >
> >         return eth_current->recv(eth_current);
> >  }
> > +#endif /* ifndef CONFIG_DM_ETH */
> >
> >  #ifdef CONFIG_API
> >  static void eth_save_packet(void *packet, int length)
> > @@ -486,7 +801,7 @@ static void eth_current_changed(void)
> >
> >  void eth_try_another(int first_restart)
> >  {
> > -       static struct eth_device *first_failed;
> > +       static void *first_failed;
> >         char *ethrotate;
> >
> >         /*
> > @@ -515,7 +830,7 @@ void eth_set_current(void)
> >  {
> >         static char *act;
> >         static int  env_changed_id;
> > -       struct eth_device *old_current;
> > +       void *old_current;
> >         int     env_id;
> >
> >         if (!eth_get_dev())     /* XXX no current */
> > --
> > 1.7.11.5
> >
>
> Regards,
> Simon
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 01/14] dm: core: Allow seq numbers to be resolved before probe
  2015-02-11  6:08         ` Joe Hershberger
@ 2015-02-13  5:14           ` Simon Glass
  2015-02-14  2:33             ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-02-13  5:14 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 10 February 2015 at 23:08, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> Hi Simon,
>
> On Tue, Feb 10, 2015 at 10:39 PM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com>
>> wrote:
>> > Before this patch, if the sequence numbers were resolved before probe,
>> > this code would insist on defining new non-conflicting-with-itself seq
>> > numbers. Now any "non -1" seq number is accepted as already resolved.
>>
>> Can you explain what problem this solves? At present, when probing a
>> device, ->seq must be -1 (sort-of by definition since it doesn't exist
>> as an active device in the uclass).
>
> Please look at eth_post_bind() in patch 07/14.  The Ethernet devices need to
> write their hardware addresses to the registers in bind (since it needs to
> happen regardless of the device being used so that Linux will see the MAC
> address).  As such, the sequence number is needed to look up the ethaddr. In
> order to avoid probing all the devices to get the seq number resolved, I
> resolve it in post_bind to avoid the rest of the overhead (thus no longer
> probing in post_bind, which was one of the issues previously).  Then when
> probe comes along, the seq is already resolved.  That's why this patch is
> needed.

OK I see.

This is a bit messy. If the MAC address assignment is part of the bind
step then it shouldn't need the seq number.

I can think of some poor ways to do this but a nice way is not obvious!

One option would be probe all the Ethernet devices on startup. If
probe() only set up the hardware (including MAC address) then that
might work. It would be fairly fast since it wouldn't involve starting
up the link, etc. I suspect you are worried about a lot of Ethernet
devices sitting around probed by unused. I'm not sure if that matters
though.

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 5/8] net: Add basic driver model support to Ethernet stack
  2015-02-11  6:25       ` Joe Hershberger
@ 2015-02-13  5:20         ` Simon Glass
  2015-02-14  2:43           ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-02-13  5:20 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 10 February 2015 at 23:25, Joe Hershberger <joe.hershberger@gmail.com> wrote:
>
>
> On Fri, Feb 6, 2015 at 7:25 PM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 2 February 2015 at 17:38, Joe Hershberger <joe.hershberger@ni.com>
>> wrote:
>> > First just add support for MAC drivers.
>> >
>> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>> >
>> > ---
>> >
>> > Changes in v2:
>> > -Updated comments
>> > -Removed extra parentheses
>> > -Changed eth_uclass_priv local var names to be uc_priv
>> > -Update error codes
>> > -Cause an invalid name to fail binding
>> > -Rebase on top of dm/master
>> > -Stop maintaining our own index and use DM seq now that it works for our
>> > needs
>> > -Move the hwaddr to platdata so that its memory is allocated at bind
>> > when we need it
>> > -Prevent device from being probed before used by a command (i.e. before
>> > eth_init()).
>> >
>> >  common/board_r.c       |   4 +-
>> >  common/cmd_bdinfo.c    |   2 +
>> >  include/dm/uclass-id.h |   1 +
>> >  include/net.h          |  24 ++++
>> >  net/eth.c              | 319
>> > ++++++++++++++++++++++++++++++++++++++++++++++++-
>> >  5 files changed, 346 insertions(+), 4 deletions(-)
>> >

[snip]

>> > diff --git a/net/eth.c b/net/eth.c
>> > index c02548c..1b5a169 100644
>> > --- a/net/eth.c
>> > +++ b/net/eth.c
>> > @@ -72,6 +72,320 @@ static int eth_mac_skip(int index)
>> >         return ((skip_state = getenv(enetvar)) != NULL);
>> >  }
>> >
>> > +static void eth_current_changed(void);
>> > +
>> > +#ifdef CONFIG_DM_ETH
>> > +#include <dm.h>
>> > +#include <dm/device-internal.h>
>>
>> These should go at the top of the file - should be OK to always
>> include them (i.e. no #ifdef)
>
> OK... Moved them.
>
>> > +
>> > +struct eth_device_priv {
>> > +       int state;
>> > +       void *priv;
>> > +};
>> > +
>> > +struct eth_uclass_priv {
>> > +       struct udevice *current;
>> > +};
>> > +
>> > +static void eth_set_current_to_next(void)
>> > +{
>> > +       struct uclass *uc;
>> > +       struct eth_uclass_priv *uc_priv;
>> > +
>> > +       uclass_get(UCLASS_ETH, &uc);
>>
>> This can actually return an error, although I agree there is little
>> point in handling it. So I suppose this is OK.
>
> I think this should be a given.
>
>> > +       uc_priv = uc->priv;
>> > +       uclass_next_device(&uc_priv->current);
>> > +       if (!uc_priv->current)
>> > +               uclass_first_device(UCLASS_ETH, &uc_priv->current);
>> > +}
>> > +
>> > +struct udevice *eth_get_dev(void)
>> > +{
>> > +       struct uclass *uc;
>>
>> blank line here
>
> OK on all of these.
>
>
>> > +       uclass_get(UCLASS_ETH, &uc);
>> > +
>> > +       struct eth_uclass_priv *uc_priv = uc->priv;
>> > +       return uc_priv->current;
>> > +}
>> > +
>> > +static void eth_set_dev(struct udevice *dev)
>> > +{
>> > +       struct uclass *uc;
>>
>> blank line here
>>
>> > +       uclass_get(UCLASS_ETH, &uc);
>> > +
>> > +       struct eth_uclass_priv *uc_priv = uc->priv;
>> > +       uc_priv->current = dev;
>> > +}
>> > +
>> > +unsigned char *eth_get_ethaddr(void)
>> > +{
>> > +       struct eth_pdata *pdata;
>>
>> blank line here
>>
>> > +       if (eth_get_dev()) {
>> > +               pdata = eth_get_dev()->platdata;
>> > +               if (pdata)
>> > +                       return pdata->enetaddr;
>> > +       }
>> > +       return NULL;
>> > +}
>> > +
>> > +/* Set active state */
>> > +int eth_init_state_only(bd_t *bis)
>> > +{
>> > +       struct eth_device_priv *priv;
>>
>> blank line here
>>
>> > +       if (eth_get_dev()) {
>> > +               priv = eth_get_dev()->uclass_priv;
>> > +               if (priv)
>> > +                       priv->state = ETH_STATE_ACTIVE;
>> > +       }
>> > +
>> > +       return 0;
>> > +}
>> > +/* Set passive state */
>> > +void eth_halt_state_only(void)
>> > +{
>> > +       struct eth_device_priv *priv;
>>
>> blank line here
>>
>> > +       if (eth_get_dev()) {
>> > +               priv = eth_get_dev()->uclass_priv;
>> > +               if (priv)
>> > +                       priv->state = ETH_STATE_PASSIVE;
>> > +       }
>> > +}
>> > +
>> > +int eth_get_dev_index(void)
>> > +{
>> > +       if (eth_get_dev())
>> > +               return eth_get_dev()->seq;
>> > +       return -1;
>> > +}
>> > +
>> > +int eth_init(bd_t *bis)
>> > +{
>> > +       struct udevice *current, *old_current, *dev;
>> > +       struct uclass *uc;
>> > +
>> > +       current = eth_get_dev();
>> > +       if (!current) {
>> > +               puts("No ethernet found.\n");
>> > +               return -1;
>> > +       }
>> > +       device_probe(current);
>>
>> Check error
>
> OK.
>
>> > +
>> > +       /* Sync environment with network devices */
>> > +       uclass_get(UCLASS_ETH, &uc);
>> > +       uclass_foreach_dev(dev, uc) {
>> > +               uchar env_enetaddr[6];
>> > +
>> > +               if (eth_getenv_enetaddr_by_index("eth", dev->seq,
>> > +                                                env_enetaddr)) {
>> > +                       struct eth_pdata *pdata = dev->platdata;
>>
>> blank line
>>
>> Do all devices have the same platdata by design? What if a particular
>> device wants its own?
>
> That's a good question.  I imagine some devices may have something unique,
> but I would expect they would read that data into the priv data that they
> define.  How do other subsystems handle platform data for unique devices?

There isn't great support for it. Typically the device has its own
platform data. For buses there is per-child platform data, which the
uclass can define, but we don't have uclass-defined platform data for
normal devices (which are not children).

>
>> > +                       if (pdata)
>>
>> What do you need this check?
>
> No.  This was left over from when enetaddr was in priv.
>
>
>> > +                               memcpy(pdata->enetaddr, env_enetaddr,
>> > 6);
>> > +               }
>> > +       };
>> > +
>> > +       old_current = current;
>> > +       do {
>> > +               debug("Trying %s\n", current->name);
>> > +
>> > +               if (current->driver) {
>> > +                       const struct eth_ops *ops =
>> > current->driver->ops;
>>
>> blank line
>>
>> > +                       if (ops->init(current, bis) >= 0) {
>> > +                               struct eth_device_priv *priv =
>> > +                                       current->uclass_priv;
>> > +                               if (priv)
>> > +                                       priv->state = ETH_STATE_ACTIVE;
>> > +
>> > +                               return 0;
>> > +                       }
>> > +               }
>> > +               debug("FAIL\n");
>> > +
>> > +               eth_try_another(0);
>> > +               current = eth_get_dev();
>> > +       } while (old_current != current);
>> > +
>> > +       return -ENODEV;
>> > +}
>> > +
>> > +void eth_halt(void)
>> > +{
>> > +       struct udevice *current;
>> > +
>> > +       current = eth_get_dev();
>> > +       if (!current)
>> > +               return;
>> > +       if (!current->driver)
>> > +               return;
>> > +
>> > +       const struct eth_ops *ops = current->driver->ops;
>> > +       ops->halt(current);
>> > +
>> > +       struct eth_device_priv *priv = current->uclass_priv;
>> > +       if (priv)
>> > +               priv->state = ETH_STATE_PASSIVE;
>> > +}
>> > +
>> > +int eth_send(void *packet, int length)
>> > +{
>> > +       struct udevice *current;
>> > +
>> > +       current = eth_get_dev();
>> > +       if (!current)
>> > +               return -1;
>> > +       if (!current->driver)
>> > +               return -1;
>>
>> Seems like eth_get_dev() should return an error code if current or
>> current->driver is NULL.
>
> It's returning a pointer, so I prefer it to be NULL or a valid pointer.
>
> Perhaps you meant to say that eth_send() should return an error code?

Well yes that too. But -1 is not a valid error anymore. You need to
use -EPERM or something. And whatever went wrong with eth_get_dev()
should really be returned. So you could do:

   ret = eth_get_dev(&current);
   if (ret)
      return ret;

or if you prefer:

   current = eth_get_dev();
   if (IS_ERR(current))
      return PTR_ERR(current);

>
>
>> > +
>> > +       const struct eth_ops *ops = current->driver->ops;
>> > +       return ops->send(current, packet, length);
>> > +}
>> > +
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 01/14] dm: core: Allow seq numbers to be resolved before probe
  2015-02-13  5:14           ` Simon Glass
@ 2015-02-14  2:33             ` Joe Hershberger
  2015-02-15 15:59               ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-14  2:33 UTC (permalink / raw)
  To: u-boot

On Thu, Feb 12, 2015 at 11:14 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 10 February 2015 at 23:08, Joe Hershberger <joe.hershberger@gmail.com>
wrote:
> > Hi Simon,
> >
> > On Tue, Feb 10, 2015 at 10:39 PM, Simon Glass <sjg@chromium.org> wrote:
> >>
> >> Hi Joe,
> >>
> >> On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com>
> >> wrote:
> >> > Before this patch, if the sequence numbers were resolved before
probe,
> >> > this code would insist on defining new non-conflicting-with-itself
seq
> >> > numbers. Now any "non -1" seq number is accepted as already resolved.
> >>
> >> Can you explain what problem this solves? At present, when probing a
> >> device, ->seq must be -1 (sort-of by definition since it doesn't exist
> >> as an active device in the uclass).
> >
> > Please look at eth_post_bind() in patch 07/14.  The Ethernet devices
need to
> > write their hardware addresses to the registers in bind (since it needs
to
> > happen regardless of the device being used so that Linux will see the
MAC
> > address).  As such, the sequence number is needed to look up the
ethaddr. In
> > order to avoid probing all the devices to get the seq number resolved, I
> > resolve it in post_bind to avoid the rest of the overhead (thus no
longer
> > probing in post_bind, which was one of the issues previously).  Then
when
> > probe comes along, the seq is already resolved.  That's why this patch
is
> > needed.
>
> OK I see.
>
> This is a bit messy. If the MAC address assignment is part of the bind
> step then it shouldn't need the seq number.

Not sure why you say that.  The reason I need the seq number is because I
need to look up the proper env variable for the MAC address.  E.g. ethaddr,
eth2addr, etc.  The seq number select which one to read from the env.

> I can think of some poor ways to do this but a nice way is not obvious!

Not sure what you're referring to here.  What is "this" in this context?

> One option would be probe all the Ethernet devices on startup. If
> probe() only set up the hardware (including MAC address) then that
> might work. It would be fairly fast since it wouldn't involve starting
> up the link, etc. I suspect you are worried about a lot of Ethernet
> devices sitting around probed by unused. I'm not sure if that matters
> though.

I had it probing the devices originally (by calling first and next) and you
commented that it shouldn't happen until the devices are used.  However, I
don't think we can guarantee that all drivers that come later will have
simple probe (since that's not part of the contract).  I think I agree with
your original statement that we should not probe.  It seems more suitable
to write the hwaddr in bind as a known and limited side effect.

The seq number resolution seems fairly well contained as I implemented it
in bind.  I simply call the core function and write the result to the
device member.  Then of course this patch to remove the assert.

Thanks,
-Joe

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v2 5/8] net: Add basic driver model support to Ethernet stack
  2015-02-13  5:20         ` Simon Glass
@ 2015-02-14  2:43           ` Joe Hershberger
  0 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-02-14  2:43 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Thu, Feb 12, 2015 at 11:20 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 10 February 2015 at 23:25, Joe Hershberger <joe.hershberger@gmail.com>
wrote:
> >
> >
> > On Fri, Feb 6, 2015 at 7:25 PM, Simon Glass <sjg@chromium.org> wrote:
> >>
> >> Hi Joe,
> >>
> >> On 2 February 2015 at 17:38, Joe Hershberger <joe.hershberger@ni.com>
> >> wrote:
> >> > First just add support for MAC drivers.
> >> >
> >> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> >> >
> >> > ---
> >> >
> >> > Changes in v2:
> >> > -Updated comments
> >> > -Removed extra parentheses
> >> > -Changed eth_uclass_priv local var names to be uc_priv
> >> > -Update error codes
> >> > -Cause an invalid name to fail binding
> >> > -Rebase on top of dm/master
> >> > -Stop maintaining our own index and use DM seq now that it works for
our
> >> > needs
> >> > -Move the hwaddr to platdata so that its memory is allocated at bind
> >> > when we need it
> >> > -Prevent device from being probed before used by a command (i.e.
before
> >> > eth_init()).
> >> >
> >> >  common/board_r.c       |   4 +-
> >> >  common/cmd_bdinfo.c    |   2 +
> >> >  include/dm/uclass-id.h |   1 +
> >> >  include/net.h          |  24 ++++
> >> >  net/eth.c              | 319
> >> > ++++++++++++++++++++++++++++++++++++++++++++++++-
> >> >  5 files changed, 346 insertions(+), 4 deletions(-)
> >> >
>
> [snip]
>
> >> > diff --git a/net/eth.c b/net/eth.c
> >> > index c02548c..1b5a169 100644
> >> > --- a/net/eth.c
> >> > +++ b/net/eth.c
> >> > @@ -72,6 +72,320 @@ static int eth_mac_skip(int index)
> >> >         return ((skip_state = getenv(enetvar)) != NULL);
> >> >  }
> >> >
> >> > +static void eth_current_changed(void);
> >> > +
> >> > +#ifdef CONFIG_DM_ETH
> >> > +#include <dm.h>
> >> > +#include <dm/device-internal.h>
> >>
> >> These should go at the top of the file - should be OK to always
> >> include them (i.e. no #ifdef)
> >
> > OK... Moved them.
> >
> >> > +
> >> > +struct eth_device_priv {
> >> > +       int state;
> >> > +       void *priv;
> >> > +};
> >> > +
> >> > +struct eth_uclass_priv {
> >> > +       struct udevice *current;
> >> > +};
> >> > +
> >> > +static void eth_set_current_to_next(void)
> >> > +{
> >> > +       struct uclass *uc;
> >> > +       struct eth_uclass_priv *uc_priv;
> >> > +
> >> > +       uclass_get(UCLASS_ETH, &uc);
> >>
> >> This can actually return an error, although I agree there is little
> >> point in handling it. So I suppose this is OK.
> >
> > I think this should be a given.
> >
> >> > +       uc_priv = uc->priv;
> >> > +       uclass_next_device(&uc_priv->current);
> >> > +       if (!uc_priv->current)
> >> > +               uclass_first_device(UCLASS_ETH, &uc_priv->current);
> >> > +}
> >> > +
> >> > +struct udevice *eth_get_dev(void)
> >> > +{
> >> > +       struct uclass *uc;
> >>
> >> blank line here
> >
> > OK on all of these.
> >
> >
> >> > +       uclass_get(UCLASS_ETH, &uc);
> >> > +
> >> > +       struct eth_uclass_priv *uc_priv = uc->priv;
> >> > +       return uc_priv->current;
> >> > +}
> >> > +
> >> > +static void eth_set_dev(struct udevice *dev)
> >> > +{
> >> > +       struct uclass *uc;
> >>
> >> blank line here
> >>
> >> > +       uclass_get(UCLASS_ETH, &uc);
> >> > +
> >> > +       struct eth_uclass_priv *uc_priv = uc->priv;
> >> > +       uc_priv->current = dev;
> >> > +}
> >> > +
> >> > +unsigned char *eth_get_ethaddr(void)
> >> > +{
> >> > +       struct eth_pdata *pdata;
> >>
> >> blank line here
> >>
> >> > +       if (eth_get_dev()) {
> >> > +               pdata = eth_get_dev()->platdata;
> >> > +               if (pdata)
> >> > +                       return pdata->enetaddr;
> >> > +       }
> >> > +       return NULL;
> >> > +}
> >> > +
> >> > +/* Set active state */
> >> > +int eth_init_state_only(bd_t *bis)
> >> > +{
> >> > +       struct eth_device_priv *priv;
> >>
> >> blank line here
> >>
> >> > +       if (eth_get_dev()) {
> >> > +               priv = eth_get_dev()->uclass_priv;
> >> > +               if (priv)
> >> > +                       priv->state = ETH_STATE_ACTIVE;
> >> > +       }
> >> > +
> >> > +       return 0;
> >> > +}
> >> > +/* Set passive state */
> >> > +void eth_halt_state_only(void)
> >> > +{
> >> > +       struct eth_device_priv *priv;
> >>
> >> blank line here
> >>
> >> > +       if (eth_get_dev()) {
> >> > +               priv = eth_get_dev()->uclass_priv;
> >> > +               if (priv)
> >> > +                       priv->state = ETH_STATE_PASSIVE;
> >> > +       }
> >> > +}
> >> > +
> >> > +int eth_get_dev_index(void)
> >> > +{
> >> > +       if (eth_get_dev())
> >> > +               return eth_get_dev()->seq;
> >> > +       return -1;
> >> > +}
> >> > +
> >> > +int eth_init(bd_t *bis)
> >> > +{
> >> > +       struct udevice *current, *old_current, *dev;
> >> > +       struct uclass *uc;
> >> > +
> >> > +       current = eth_get_dev();
> >> > +       if (!current) {
> >> > +               puts("No ethernet found.\n");
> >> > +               return -1;
> >> > +       }
> >> > +       device_probe(current);
> >>
> >> Check error
> >
> > OK.
> >
> >> > +
> >> > +       /* Sync environment with network devices */
> >> > +       uclass_get(UCLASS_ETH, &uc);
> >> > +       uclass_foreach_dev(dev, uc) {
> >> > +               uchar env_enetaddr[6];
> >> > +
> >> > +               if (eth_getenv_enetaddr_by_index("eth", dev->seq,
> >> > +                                                env_enetaddr)) {
> >> > +                       struct eth_pdata *pdata = dev->platdata;
> >>
> >> blank line
> >>
> >> Do all devices have the same platdata by design? What if a particular
> >> device wants its own?
> >
> > That's a good question.  I imagine some devices may have something
unique,
> > but I would expect they would read that data into the priv data that
they
> > define.  How do other subsystems handle platform data for unique
devices?
>
> There isn't great support for it. Typically the device has its own
> platform data. For buses there is per-child platform data, which the
> uclass can define, but we don't have uclass-defined platform data for
> normal devices (which are not children).

So I guess that means we should leave it until needed and then extend core
to support such things on non-bus-children?

> >
> >> > +                       if (pdata)
> >>
> >> What do you need this check?
> >
> > No.  This was left over from when enetaddr was in priv.
> >
> >
> >> > +                               memcpy(pdata->enetaddr, env_enetaddr,
> >> > 6);
> >> > +               }
> >> > +       };
> >> > +
> >> > +       old_current = current;
> >> > +       do {
> >> > +               debug("Trying %s\n", current->name);
> >> > +
> >> > +               if (current->driver) {
> >> > +                       const struct eth_ops *ops =
> >> > current->driver->ops;
> >>
> >> blank line
> >>
> >> > +                       if (ops->init(current, bis) >= 0) {
> >> > +                               struct eth_device_priv *priv =
> >> > +                                       current->uclass_priv;
> >> > +                               if (priv)
> >> > +                                       priv->state =
ETH_STATE_ACTIVE;
> >> > +
> >> > +                               return 0;
> >> > +                       }
> >> > +               }
> >> > +               debug("FAIL\n");
> >> > +
> >> > +               eth_try_another(0);
> >> > +               current = eth_get_dev();
> >> > +       } while (old_current != current);
> >> > +
> >> > +       return -ENODEV;
> >> > +}
> >> > +
> >> > +void eth_halt(void)
> >> > +{
> >> > +       struct udevice *current;
> >> > +
> >> > +       current = eth_get_dev();
> >> > +       if (!current)
> >> > +               return;
> >> > +       if (!current->driver)
> >> > +               return;
> >> > +
> >> > +       const struct eth_ops *ops = current->driver->ops;
> >> > +       ops->halt(current);
> >> > +
> >> > +       struct eth_device_priv *priv = current->uclass_priv;
> >> > +       if (priv)
> >> > +               priv->state = ETH_STATE_PASSIVE;
> >> > +}
> >> > +
> >> > +int eth_send(void *packet, int length)
> >> > +{
> >> > +       struct udevice *current;
> >> > +
> >> > +       current = eth_get_dev();
> >> > +       if (!current)
> >> > +               return -1;
> >> > +       if (!current->driver)
> >> > +               return -1;
> >>
> >> Seems like eth_get_dev() should return an error code if current or
> >> current->driver is NULL.
> >
> > It's returning a pointer, so I prefer it to be NULL or a valid pointer.
> >
> > Perhaps you meant to say that eth_send() should return an error code?
>
> Well yes that too. But -1 is not a valid error anymore. You need to
> use -EPERM or something. And whatever went wrong with eth_get_dev()
> should really be returned. So you could do:
>
>    ret = eth_get_dev(&current);
>    if (ret)
>       return ret;

I don't see this as equivalent.

> or if you prefer:
>
>    current = eth_get_dev();
>    if (IS_ERR(current))
>       return PTR_ERR(current);

This makes more sense, but given that eth_get_dev() is not doing anything
other than returning a static global variable, it seems that "NULL" is a
valid return.  That's just the value of that variable.  Nothing "went
wrong". It seems like it's jumping through hoops to convert NULL into some
error code, return that code as a pointer, then convert it back, when the
test for NULL is far more straightforward in the caller and easier to read.

I completely agree about not returning -1 from eth_send() and already have
that change in for the next version.

Thanks,
-Joe

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 07/14] dm: eth: Add basic driver model support to Ethernet stack
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 07/14] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
@ 2015-02-15 15:49       ` Simon Glass
  2015-02-17  4:37         ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-02-15 15:49 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com> wrote:
> First just add support for MAC drivers.

It has taken me a while to get through all this unfortunately.

This seems OK to me but needs a clean-up with more comments, etc. If
you like these could go in a separate patch, so if you want to do that
please add my Reviewed-by: Simon Glass <sjg@chromium.org> to this one.
I would prefer that we sort out the bind/probe problem before this is
merged but I understand you now have quite a bit of work built on top,
and the problems can be separated.

So if you like we could do one more version, merge it, and continue
with refinements after that.

>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v3:
> -Correct the pre_unbind logic
> -Correct failure chaining from bind to probe to init
> --Fail init if not activated
> --Fail probe if ethaddr not set
> -Update ethaddr from env unconditionally on init
> -Use set current to select the current device regardless of the previous selection
> -Allow current eth dev to be NULL
> -Fixed blank line formatting for variable declaration
>
> Changes in v2:
> -Updated comments
> -Removed extra parentheses
> -Changed eth_uclass_priv local var names to be uc_priv
> -Update error codes
> -Cause an invalid name to fail binding
> -Rebase on top of dm/master
> -Stop maintaining our own index and use DM seq now that it works for our needs
> -Move the hwaddr to platdata so that its memory is allocated at bind when we need it
> -Prevent device from being probed before used by a command (i.e. before eth_init()).
>
>  common/board_r.c       |   4 +-
>  common/cmd_bdinfo.c    |   2 +
>  include/dm/uclass-id.h |   1 +
>  include/net.h          |  25 ++++
>  net/eth.c              | 336 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  5 files changed, 361 insertions(+), 7 deletions(-)
>
> diff --git a/common/board_r.c b/common/board_r.c
> index 68a9448..75147b7 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -556,7 +556,7 @@ static int initr_bbmii(void)
>  }
>  #endif
>
> -#ifdef CONFIG_CMD_NET
> +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
>  static int initr_net(void)
>  {
>         puts("Net:   ");
> @@ -825,7 +825,7 @@ init_fnc_t init_sequence_r[] = {
>  #ifdef CONFIG_BITBANGMII
>         initr_bbmii,
>  #endif
> -#ifdef CONFIG_CMD_NET
> +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
>         INIT_FUNC_WATCHDOG_RESET
>         initr_net,
>  #endif
> diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
> index e6d8a7a..8688cf9 100644
> --- a/common/cmd_bdinfo.c
> +++ b/common/cmd_bdinfo.c
> @@ -34,6 +34,7 @@ static void print_eth(int idx)
>         printf("%-12s= %s\n", name, val);
>  }
>
> +#ifndef CONFIG_DM_ETH
>  __maybe_unused
>  static void print_eths(void)
>  {
> @@ -52,6 +53,7 @@ static void print_eths(void)
>         printf("current eth = %s\n", eth_get_name());
>         printf("ip_addr     = %s\n", getenv("ipaddr"));
>  }
> +#endif
>
>  __maybe_unused
>  static void print_lnum(const char *name, unsigned long long value)
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index 91bb90d..ad96682 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -34,6 +34,7 @@ enum uclass_id {
>         UCLASS_I2C_GENERIC,     /* Generic I2C device */
>         UCLASS_I2C_EEPROM,      /* I2C EEPROM device */
>         UCLASS_MOD_EXP,         /* RSA Mod Exp device */
> +       UCLASS_ETH,             /* Ethernet device */
>
>         UCLASS_COUNT,
>         UCLASS_INVALID = -1,
> diff --git a/include/net.h b/include/net.h
> index 4d7575e..11471bd 100644
> --- a/include/net.h
> +++ b/include/net.h
> @@ -78,6 +78,30 @@ enum eth_state_t {
>         ETH_STATE_ACTIVE
>  };
>
> +#ifdef CONFIG_DM_ETH
> +struct eth_pdata {
> +       phys_addr_t iobase;
> +       unsigned char enetaddr[6];
> +};
> +
> +struct eth_ops {
> +       int (*init)(struct udevice *dev, bd_t *bis);

Why do we pass in bd_t? Isn't that available through gd->bd?

> +       int (*send)(struct udevice *dev, void *packet, int length);
> +       int (*recv)(struct udevice *dev);
> +       void (*halt)(struct udevice *dev);
> +#ifdef CONFIG_MCAST_TFTP
> +       int (*mcast)(struct udevice *dev, const u8 *enetaddr, u8 set);

s/u8/bool/ or maybe int? On ARM at least it is inefficient to keep
having to mask the parameters.

> +#endif
> +       int (*write_hwaddr)(struct udevice *dev);
> +};

Can you please add interface comments on all of these plus the four
below? I'm trying to make driver model an opportunity to improve the
code as we go. Things like what the function does, what packet
contains.

> +
> +struct udevice *eth_get_dev(void); /* get the current device */
> +unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
> +int eth_init_state_only(bd_t *bis); /* Set active state */
> +void eth_halt_state_only(void); /* Set passive state */

Can you expand these a bit? The first one can return NULL in some
situations. The second returns a pointer to 6 bytes I think (perhaps
we should define a struct for this in a future patch?)  What are
active and passive state? Why does one function get passed bd_t and
not the other (better if neither did).

> +#endif
> +
> +#ifndef CONFIG_DM_ETH
>  struct eth_device {
>         char name[16];
>         unsigned char enetaddr[6];
> @@ -145,6 +169,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
>                      int eth_number);
>
>  int usb_eth_initialize(bd_t *bi);
> +#endif
>
>  void eth_try_another(int first_restart);       /* Change the device */
>  void eth_set_current(void);            /* set nterface to ethcur var */
> diff --git a/net/eth.c b/net/eth.c
> index c02548c..e84b948 100644
> --- a/net/eth.c
> +++ b/net/eth.c
> @@ -1,12 +1,15 @@
>  /*
>   * (C) Copyright 2001-2010
>   * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
> + * Joe Hershberger, National Instruments
>   *
>   * SPDX-License-Identifier:    GPL-2.0+
>   */
>
>  #include <common.h>
>  #include <command.h>
> +#include <dm.h>
> +#include <dm/device-internal.h>
>  #include <net.h>
>  #include <miiphy.h>
>  #include <phy.h>
> @@ -72,6 +75,331 @@ static int eth_mac_skip(int index)
>         return ((skip_state = getenv(enetvar)) != NULL);
>  }
>
> +static void eth_current_changed(void);
> +
> +#ifdef CONFIG_DM_ETH

/**
 * struct eth_device_priv - private structure for each Ethernet device
 *
 * @state:    ...
 * @priv: ...
 /

> +struct eth_device_priv {
> +       int state;
> +       void *priv;
> +};
> +

Structure attached to the uclass itself.

> +struct eth_uclass_priv {
> +       struct udevice *current;
> +};
> +
> +static void eth_set_current_to_next(void)
> +{
> +       struct uclass *uc;
> +       struct eth_uclass_priv *uc_priv;
> +
> +       uclass_get(UCLASS_ETH, &uc);
> +       uc_priv = uc->priv;
> +       if (uc_priv->current)
> +               uclass_next_device(&uc_priv->current);
> +       if (!uc_priv->current)
> +               uclass_first_device(UCLASS_ETH, &uc_priv->current);
> +}
> +

I think you should have something like this to avoid this duplication:

static struct eth_uclass_priv *get_uclass_priv(void)
{
      struct uclass *uc;

      uclass_get(UCLASS_ETH, &uc);
      assert(uc);
      return uc->priv;
}

At some point we should add a uclass_get_priv() function in uclass.h.

> +struct udevice *eth_get_dev(void)
> +{
> +       struct uclass *uc;
> +       struct eth_uclass_priv *uc_priv;
> +
> +       uclass_get(UCLASS_ETH, &uc);
> +       uc_priv = uc->priv;
> +
> +       return uc_priv->current;
> +}
> +
> +static void eth_set_dev(struct udevice *dev)
> +{
> +       struct uclass *uc;
> +       struct eth_uclass_priv *uc_priv;
> +
> +       uclass_get(UCLASS_ETH, &uc);
> +       uc_priv = uc->priv;
> +       uc_priv->current = dev;
> +}
> +
> +unsigned char *eth_get_ethaddr(void)
> +{
> +       struct eth_pdata *pdata;
> +
> +       if (eth_get_dev()) {
> +               pdata = eth_get_dev()->platdata;
> +               if (pdata)
> +                       return pdata->enetaddr;
> +       }
> +       return NULL;
> +}
> +
> +/* Set active state */
> +int eth_init_state_only(bd_t *bis)

This doesn't seem to use bis, so I suspect it is for backwards compatibility.

> +{
> +       struct eth_device_priv *priv;
> +
> +       if (eth_get_dev()) {
> +               priv = eth_get_dev()->uclass_priv;
> +               if (priv)
> +                       priv->state = ETH_STATE_ACTIVE;

It looks like state uses an enum, so that should be described in the
comment I mentioned earlier.

> +       }
> +       return 0;
> +}
> +/* Set passive state */
> +void eth_halt_state_only(void)
> +{
> +       struct eth_device_priv *priv;
> +
> +       if (eth_get_dev()) {
> +               priv = eth_get_dev()->uclass_priv;
> +               if (priv)
> +                       priv->state = ETH_STATE_PASSIVE;
> +       }
> +}
> +
> +int eth_get_dev_index(void)
> +{
> +       if (eth_get_dev())
> +               return eth_get_dev()->seq;
> +       return -1;
> +}
> +
> +int eth_init(bd_t *bis)
> +{
> +       struct udevice *current, *old_current, *dev;
> +       int retval;
> +       struct uclass *uc;
> +
> +       current = eth_get_dev();
> +       if (!current) {
> +               puts("No ethernet found.\n");

printf() as I believe we are trying to avoid puts().

> +               return -1;
> +       }
> +       retval = device_probe(current);
> +       if (retval)
> +               return retval;
> +
> +       /* Sync environment with network devices */
> +       uclass_get(UCLASS_ETH, &uc);
> +       uclass_foreach_dev(dev, uc) {
> +               uchar env_enetaddr[6];
> +               struct eth_pdata *pdata = dev->platdata;
> +

ret = device_probe(dev);
if (ret) ...

here since you can't use dev->seq otherwise.

> +               if (eth_getenv_enetaddr_by_index("eth", dev->seq, env_enetaddr))
> +                       memcpy(pdata->enetaddr, env_enetaddr, 6);
> +               else
> +                       memset(pdata->enetaddr, 0, 6);
> +       }
> +
> +       old_current = current;
> +       do {
> +               debug("Trying %s\n", current->name);
> +
> +               if (current->driver && (current->flags & DM_FLAG_ACTIVATED)) {

There is no need to check current->driver (here and elsewhere)

device_active(current)

> +                       const struct eth_ops *ops = current->driver->ops;
> +
> +                       if (ops->init(current, bis) >= 0) {
> +                               struct eth_device_priv *priv =
> +                                       current->uclass_priv;
> +                               if (priv)

Remove this check too

> +                                       priv->state = ETH_STATE_ACTIVE;
> +
> +                               return 0;
> +                       }
> +               }
> +               debug("FAIL\n");
> +
> +               eth_try_another(0);
> +               current = eth_get_dev();
> +       } while (old_current != current);
> +
> +       return -ENODEV;
> +}
> +
> +void eth_halt(void)
> +{
> +       struct udevice *current;
> +       const struct eth_ops *ops;
> +       struct eth_device_priv *priv;
> +
> +       current = eth_get_dev();
> +       if (!current)
> +               return;
> +       if (!current->driver)
> +               return;

Remove these checks

> +
> +       ops = current->driver->ops;

Define this in your header file:

#define eth_get_ops(dev)        ((struct eth_ops *)(dev)->driver->ops)

then one day we can add checks on dev, etc.

> +       ops->halt(current);

If you like you can drop the local variable and use:

eth_get_ops(dev)->halt(current)

> +
> +       priv = current->uclass_priv;
> +       if (priv)
> +               priv->state = ETH_STATE_PASSIVE;
> +}
> +
> +int eth_send(void *packet, int length)
> +{
> +       struct udevice *current;
> +       const struct eth_ops *ops;
> +
> +       current = eth_get_dev();
> +       if (!current)
> +               return -1;
> +       if (!current->driver)
> +               return -1;
> +       ops = current->driver->ops;
> +
> +       return ops->send(current, packet, length);
> +}
> +
> +int eth_rx(void)
> +{
> +       struct udevice *current;
> +       const struct eth_ops *ops;
> +
> +       current = eth_get_dev();
> +       if (!current)
> +               return -1;
> +       if (!current->driver)
> +               return -1;
> +       ops = current->driver->ops;
> +
> +       return ops->recv(current);
> +}
> +
> +static int eth_write_hwaddr(struct udevice *dev, const char *base_name,
> +                  int eth_number)
> +{
> +       unsigned char env_enetaddr[6];
> +       int ret = 0;
> +       struct eth_pdata *pdata;
> +       const struct eth_ops *ops;
> +
> +       eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
> +
> +       pdata = dev->platdata;
> +       if (!is_zero_ether_addr(env_enetaddr)) {
> +               if (!is_zero_ether_addr(pdata->enetaddr) &&
> +                   memcmp(pdata->enetaddr, env_enetaddr, 6)) {
> +                       printf("\nWarning: %s MAC addresses don't match:\n",
> +                              dev->name);
> +                       printf("Address in SROM is         %pM\n",
> +                              pdata->enetaddr);
> +                       printf("Address in environment is  %pM\n",
> +                              env_enetaddr);
> +               }
> +
> +               memcpy(pdata->enetaddr, env_enetaddr, 6);
> +       } else if (is_valid_ether_addr(pdata->enetaddr)) {
> +               eth_setenv_enetaddr_by_index(base_name, eth_number,
> +                                            pdata->enetaddr);
> +               printf("\nWarning: %s using MAC address from net device\n",
> +                      dev->name);
> +       } else if (is_zero_ether_addr(pdata->enetaddr)) {
> +               printf("\nError: %s address not set.\n",
> +                      dev->name);
> +               return -EINVAL;
> +       }
> +
> +       ops = dev->driver->ops;
> +       if (dev->driver && ops && ops->write_hwaddr &&
> +           !eth_mac_skip(eth_number)) {
> +               if (!is_valid_ether_addr(pdata->enetaddr)) {
> +                       printf("\nError: %s address %pM illegal value\n",
> +                              dev->name, pdata->enetaddr);
> +                       return -EINVAL;
> +               }
> +
> +               ret = ops->write_hwaddr(dev);
> +               if (ret)
> +                       printf("\nWarning: %s failed to set MAC address\n",
> +                              dev->name);
> +       }
> +
> +       return ret;
> +}
> +
> +static int eth_uclass_init(struct uclass *class)
> +{
> +       bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
> +
> +       eth_env_init();
> +
> +       return 0;
> +}
> +
> +static int eth_post_bind(struct udevice *dev)
> +{
> +       if (strchr(dev->name, ' ')) {
> +               printf("\nError: eth device name \"%s\" has a space!\n",
> +                      dev->name);
> +               return -EINVAL;
> +       }
> +
> +       /*
> +        * Devices need to write the hwaddr even if not probed so that Linux
> +        * will have access to the hwaddr that u-boot stored for the device.
> +        */
> +       dev->seq = uclass_resolve_seq(dev);
> +       eth_write_hwaddr(dev, "eth", dev->seq);

I still don't like this sorry. I don't see why you can't do this in
eth_init() above?

If you really want to do this, please add #ifndef CONFIG_DM_NET around
the check you have taken out and we can sort it out later.

> +
> +       return 0;
> +}
> +
> +static int eth_pre_unbind(struct udevice *dev)

It still feels like this is using binding as the presence/absence of a
device rather than probing. When a device is removed with the remove()
method, it is no longer available for use, so things like
eth_try_another() should ignore them. By the time we come to unbind a
device, it should already be removed.

One way to think of this is that the probe()/remove() corresponds to
the same idea as in Linux, and bind()/unbind() is a new thing meaning
that we are aware of the device but it may not currently be available.

> +{
> +       struct udevice *first = NULL;
> +       struct udevice *active;
> +       struct udevice *it;
> +       struct uclass *uc;
> +
> +       uclass_get(UCLASS_ETH, &uc);
> +       uclass_foreach_dev(it, uc) {
> +               if (!first)
> +                       first = it;
> +               if (it == dev) {
> +                       if (dev == first) {
> +                               active = list_entry(it->uclass_node.next,
> +                                          struct udevice, uclass_node);
> +                               if (&active->uclass_node == &uc->dev_head)
> +                                       active = NULL;
> +                       } else {
> +                               active = first;
> +                       }
> +                       eth_set_dev(active);
> +                       eth_current_changed();
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +static int eth_post_probe(struct udevice *dev)
> +{
> +       struct eth_device_priv *priv = dev->uclass_priv;
> +       struct eth_pdata *pdata = dev->platdata;
> +
> +       if (priv)

no need for this check

> +               priv->state = ETH_STATE_INIT;
> +
> +       if (is_zero_ether_addr(pdata->enetaddr))
> +               return -EINVAL;
> +
> +       return 0;
> +}
> +
> +UCLASS_DRIVER(eth) = {
> +       .name           = "eth",
> +       .id             = UCLASS_ETH,
> +       .post_bind      = eth_post_bind,
> +       .pre_unbind     = eth_pre_unbind,
> +       .post_probe     = eth_post_probe,
> +       .init           = eth_uclass_init,
> +       .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
> +       .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
> +};
> +#endif
> +
> +#ifndef CONFIG_DM_ETH
>  /*
>   * CPU and board-specific Ethernet initializations.  Aliased function
>   * signals caller to move on
> @@ -423,6 +751,7 @@ int eth_rx(void)
>
>         return eth_current->recv(eth_current);
>  }
> +#endif /* ifndef CONFIG_DM_ETH */
>
>  #ifdef CONFIG_API
>  static void eth_save_packet(void *packet, int length)
> @@ -486,7 +815,7 @@ static void eth_current_changed(void)
>
>  void eth_try_another(int first_restart)
>  {
> -       static struct eth_device *first_failed;
> +       static void *first_failed;
>         char *ethrotate;
>
>         /*
> @@ -515,12 +844,9 @@ void eth_set_current(void)
>  {
>         static char *act;
>         static int  env_changed_id;
> -       struct eth_device *old_current;
> +       void *old_current;
>         int     env_id;
>
> -       if (!eth_get_dev())     /* XXX no current */
> -               return;
> -
>         env_id = get_env_id();
>         if ((act == NULL) || (env_changed_id != env_id)) {
>                 act = getenv("ethact");
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 08/14] dm: eth: Add network support to sandbox
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 08/14] dm: eth: Add network support to sandbox Joe Hershberger
@ 2015-02-15 15:49       ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-15 15:49 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Add basic network support to sandbox which includes a network driver.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v3:
> -Added 2 more ethaddr to sandbox
> -Print which device in the debug write hwaddr
>
> Changes in v2:
> -Change printfs to debug in sandbox driver
> -Remove unused priv struct for sandbox driver
>
>  arch/sandbox/dts/sandbox.dts |  4 +++
>  drivers/net/Makefile         |  1 +
>  drivers/net/sandbox.c        | 86 ++++++++++++++++++++++++++++++++++++++++++++
>  include/configs/sandbox.h    | 18 +++++++---
>  4 files changed, 104 insertions(+), 5 deletions(-)
>  create mode 100644 drivers/net/sandbox.c
>
> diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
> index 4c63e4f..502eb3d 100644
> --- a/arch/sandbox/dts/sandbox.dts
> +++ b/arch/sandbox/dts/sandbox.dts
> @@ -183,4 +183,8 @@
>                 };
>         };
>
> +       eth at 10002000 {
> +               compatible = "sandbox,eth";
> +               reg = <0x10002000 0x1000>;
> +       };
>  };
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 46c4ac6..15dc431 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -50,6 +50,7 @@ obj-$(CONFIG_NS8382X) += ns8382x.o
>  obj-$(CONFIG_PCNET) += pcnet.o
>  obj-$(CONFIG_RTL8139) += rtl8139.o
>  obj-$(CONFIG_RTL8169) += rtl8169.o
> +obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
>  obj-$(CONFIG_SH_ETHER) += sh_eth.o
>  obj-$(CONFIG_SMC91111) += smc91111.o
>  obj-$(CONFIG_SMC911X) += smc911x.o
> diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
> new file mode 100644
> index 0000000..2a2ad41
> --- /dev/null
> +++ b/drivers/net/sandbox.c
> @@ -0,0 +1,86 @@
> +/*
> + * Copyright (c) 2015 National Instruments
> + *
> + * (C) Copyright 2015
> + * Joe Hershberger <joe.hershberger@ni.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <fdtdec.h>
> +#include <malloc.h>
> +#include <net.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static int sb_eth_init(struct udevice *dev, bd_t *bis)
> +{
> +       debug("eth_sandbox: Init\n");
> +
> +       return 0;
> +}
> +
> +static int sb_eth_send(struct udevice *dev, void *packet, int length)
> +{
> +       debug("eth_sandbox: Send packet %d\n", length);
> +
> +       return 0;
> +}
> +
> +static int sb_eth_recv(struct udevice *dev)
> +{
> +       return 0;
> +}
> +
> +static void sb_eth_halt(struct udevice *dev)
> +{
> +       debug("eth_sandbox: Halt\n");
> +}
> +
> +static int sb_eth_write_hwaddr(struct udevice *dev)
> +{
> +       struct eth_pdata *pdata = dev->platdata;
> +       debug("eth_sandbox %s: Write HW ADDR - %pM\n", dev->name,
> +             pdata->enetaddr);
> +       return 0;
> +}
> +
> +static const struct eth_ops sb_eth_ops = {
> +       .init                   = sb_eth_init,
> +       .send                   = sb_eth_send,
> +       .recv                   = sb_eth_recv,
> +       .halt                   = sb_eth_halt,
> +       .write_hwaddr           = sb_eth_write_hwaddr,
> +};
> +
> +static int sb_eth_remove(struct udevice *dev)
> +{
> +       return 0;
> +}
> +
> +#ifdef CONFIG_OF_CONTROL
> +static int sb_eth_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct eth_pdata *pdata = dev->platdata;
> +
> +       pdata->iobase = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
> +       return 0;
> +}
> +
> +static const struct udevice_id sb_eth_ids[] = {
> +       { .compatible = "sandbox,eth" },
> +       { }
> +};
> +#endif
> +
> +U_BOOT_DRIVER(eth_sandbox) = {
> +       .name   = "eth_sandbox",
> +       .id     = UCLASS_ETH,
> +       .of_match = of_match_ptr(sb_eth_ids),
> +       .ofdata_to_platdata = of_match_ptr(sb_eth_ofdata_to_platdata),
> +       .remove = sb_eth_remove,
> +       .ops    = &sb_eth_ops,
> +       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
> +};
> diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
> index e9d3f32..fdba1c8 100644
> --- a/include/configs/sandbox.h
> +++ b/include/configs/sandbox.h
> @@ -139,9 +139,9 @@
>  /* include default commands */
>  #include <config_cmd_default.h>
>
> -/* We don't have networking support yet */
> -#undef CONFIG_CMD_NET
> -#undef CONFIG_CMD_NFS
> +#define CONFIG_DM_ETH
> +#define CONFIG_ETH_SANDBOX
> +#define CONFIG_CMD_PING
>
>  #define CONFIG_CMD_HASH
>  #define CONFIG_HASH_VERIFY
> @@ -184,12 +184,20 @@
>
>  #define CONFIG_EXTRA_ENV_SETTINGS      "stdin=serial,cros-ec-keyb\0" \
>                                         "stdout=serial,lcd\0" \
> -                                       "stderr=serial,lcd\0"
> +                                       "stderr=serial,lcd\0" \
> +                                       "ethaddr=00:00:11:22:33:44\0" \
> +                                       "eth1addr=00:00:11:22:33:45\0" \
> +                                       "eth2addr=00:00:11:22:33:46\0" \
> +                                       "ipaddr=1.2.3.4\0"
>  #else
>
>  #define CONFIG_EXTRA_ENV_SETTINGS      "stdin=serial\0" \
>                                         "stdout=serial,lcd\0" \
> -                                       "stderr=serial,lcd\0"
> +                                       "stderr=serial,lcd\0" \
> +                                       "ethaddr=00:00:11:22:33:44\0" \
> +                                       "eth1addr=00:00:11:22:33:45\0" \
> +                                       "eth2addr=00:00:11:22:33:46\0" \
> +                                       "ipaddr=1.2.3.4\0"
>  #endif

This needs tidying up, something like:

#define SANDBOX_DEVICE_SETTINGS "stdin...stderr"
#define SANDBOX_NET_SETTINGS "your ones"

#define CONFIG_EXTRA_ENV_SETTINGS SANDBOX_DEVICE_SETTINGS SANDBOX_NET_SETTINGS

>
>  #define CONFIG_GZIP_COMPRESSED
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 09/14] dm: eth: Add ARP and PING response to sandbox driver
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 09/14] dm: eth: Add ARP and PING response to sandbox driver Joe Hershberger
@ 2015-02-15 15:49       ` Simon Glass
  2015-02-17  4:46         ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-02-15 15:49 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The sandbox driver will now generate response traffic to exercise the
> ping command even when no network exists.  This allows the basic data
> pathways of the DM to be tested.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> -Prevent a crash if memory is not allocated
>
> Changes in v2:
> -Change printfs to debug in sandbox driver
> -Move static data to priv
> -Move fake hwaddr to the device tree
>
>  arch/sandbox/dts/sandbox.dts |   1 +
>  drivers/net/sandbox.c        | 101 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 102 insertions(+)
>
> diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
> index 502eb3d..ba635e8 100644
> --- a/arch/sandbox/dts/sandbox.dts
> +++ b/arch/sandbox/dts/sandbox.dts
> @@ -186,5 +186,6 @@
>         eth at 10002000 {
>                 compatible = "sandbox,eth";
>                 reg = <0x10002000 0x1000>;
> +               fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
>         };
>  };
> diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
> index 2a2ad41..f9fa1a1 100644
> --- a/drivers/net/sandbox.c
> +++ b/drivers/net/sandbox.c
> @@ -15,22 +15,121 @@
>
>  DECLARE_GLOBAL_DATA_PTR;
>
> +struct eth_sandbox_priv {
> +       uchar fake_host_hwaddr[ARP_HLEN];
> +       IPaddr_t fake_host_ipaddr;
> +       uchar recv_packet_buffer[PKTSIZE];
> +       int recv_packet_length;
> +};
> +
>  static int sb_eth_init(struct udevice *dev, bd_t *bis)
>  {
>         debug("eth_sandbox: Init\n");
>
> +       struct eth_sandbox_priv *priv = dev->priv;
> +       u32 int_array[ARP_HLEN];
> +       int i;
> +
> +       if (!priv)
> +               return -EINVAL;

How can this happen?

> +
> +       fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "fake-host-hwaddr",
> +                            int_array, ARP_HLEN);
> +       for (i = 0; i < ARP_HLEN; i++)
> +               priv->fake_host_hwaddr[i] = (uchar)int_array[i];
> +
>         return 0;
>  }
>
>  static int sb_eth_send(struct udevice *dev, void *packet, int length)
>  {
>         debug("eth_sandbox: Send packet %d\n", length);
> +       struct eth_sandbox_priv *priv = dev->priv;
> +       struct ethernet_hdr *eth = packet;
> +
> +       if (ntohs(eth->et_protlen) == PROT_ARP) {
> +               struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
> +               if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
> +                       /* store this as the assumed IP of the fake host */
> +                       priv->fake_host_ipaddr = NetReadIP(&arp->ar_tpa);
> +                       /* Formulate a fake response */
> +                       struct ethernet_hdr *eth_recv =
> +                               (void *)priv->recv_packet_buffer;
> +                       memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
> +                       memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
> +                              ARP_HLEN);
> +                       eth_recv->et_protlen = htons(PROT_ARP);
> +
> +                       struct arp_hdr *arp_recv =
> +                               (void *)priv->recv_packet_buffer +
> +                               ETHER_HDR_SIZE;
> +                       arp_recv->ar_hrd = htons(ARP_ETHER);
> +                       arp_recv->ar_pro = htons(PROT_IP);
> +                       arp_recv->ar_hln = ARP_HLEN;
> +                       arp_recv->ar_pln = ARP_PLEN;
> +                       arp_recv->ar_op = htons(ARPOP_REPLY);
> +                       memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr,
> +                              ARP_HLEN);
> +                       NetWriteIP(&arp_recv->ar_spa, priv->fake_host_ipaddr);
> +                       memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN);
> +                       NetCopyIP(&arp_recv->ar_tpa, &arp->ar_spa);
> +
> +                       priv->recv_packet_length = ETHER_HDR_SIZE +
> +                               ARP_HDR_SIZE;
> +               }
> +       } else if (ntohs(eth->et_protlen) == PROT_IP) {
> +               struct ip_udp_hdr *ip = packet + ETHER_HDR_SIZE;
> +               if (ip->ip_p == IPPROTO_ICMP) {
> +                       struct icmp_hdr *icmp = (struct icmp_hdr *)&ip->udp_src;
> +                       if (icmp->type == ICMP_ECHO_REQUEST) {
> +                               /* reply to the ping */
> +                               memcpy(priv->recv_packet_buffer, packet,
> +                                      length);
> +                               struct ethernet_hdr *eth_recv =
> +                                       (void *)priv->recv_packet_buffer;
> +                               struct ip_udp_hdr *ipr =
> +                                       (void *)priv->recv_packet_buffer +
> +                                       ETHER_HDR_SIZE;
> +                               struct icmp_hdr *icmpr =
> +                                       (struct icmp_hdr *)&ipr->udp_src;
> +                               memcpy(eth_recv->et_dest, eth->et_src,
> +                                      ARP_HLEN);
> +                               memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
> +                                      ARP_HLEN);
> +                               ipr->ip_sum = 0;
> +                               ipr->ip_off = 0;
> +                               NetCopyIP((void *)&ipr->ip_dst, &ip->ip_src);
> +                               NetWriteIP((void *)&ipr->ip_src,
> +                                          priv->fake_host_ipaddr);
> +                               ipr->ip_sum = ~NetCksum((uchar *)ipr,
> +                                       IP_HDR_SIZE >> 1);
> +
> +                               icmpr->type = ICMP_ECHO_REPLY;
> +                               icmpr->checksum = 0;
> +                               icmpr->checksum = ~NetCksum((uchar *)icmpr,
> +                                       (length - ETHER_HDR_SIZE -
> +                                               IP_HDR_SIZE) >> 1);
> +
> +                               priv->recv_packet_length = length;
> +                       }
> +               }
> +       }
>
>         return 0;
>  }
>
>  static int sb_eth_recv(struct udevice *dev)
>  {
> +       struct eth_sandbox_priv *priv = dev->priv;
> +
> +       if (priv && priv->recv_packet_length) {
> +               int lcl_recv_packet_length = priv->recv_packet_length;
> +               debug("eth_sandbox: received packet %d\n",
> +                     priv->recv_packet_length);
> +               priv->recv_packet_length = 0;
> +               NetReceive((void *)priv->recv_packet_buffer,
> +                          lcl_recv_packet_length);
> +       }
>         return 0;
>  }
>
> @@ -42,6 +141,7 @@ static void sb_eth_halt(struct udevice *dev)
>  static int sb_eth_write_hwaddr(struct udevice *dev)
>  {
>         struct eth_pdata *pdata = dev->platdata;
> +
>         debug("eth_sandbox %s: Write HW ADDR - %pM\n", dev->name,
>               pdata->enetaddr);
>         return 0;
> @@ -82,5 +182,6 @@ U_BOOT_DRIVER(eth_sandbox) = {
>         .ofdata_to_platdata = of_match_ptr(sb_eth_ofdata_to_platdata),
>         .remove = sb_eth_remove,
>         .ops    = &sb_eth_ops,
> +       .priv_auto_alloc_size = sizeof(struct eth_sandbox_priv),
>         .platdata_auto_alloc_size = sizeof(struct eth_pdata),
>  };
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 10/14] test: dm: eth: Add tests for the eth dm implementation
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 10/14] test: dm: eth: Add tests for the eth dm implementation Joe Hershberger
@ 2015-02-15 15:50       ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-15 15:50 UTC (permalink / raw)
  To: u-boot

On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---

This needs a commit message describing what is added. With that:

Reviewed-by: Simon Glass <sjg@chromium.org>

>
> Changes in v3:
> -Added dm eth testing
>
> Changes in v2: None
>
>  test/dm/Makefile |  1 +
>  test/dm/eth.c    | 39 +++++++++++++++++++++++++++++++++++++++
>  test/dm/test.dts | 18 ++++++++++++++++++
>  3 files changed, 58 insertions(+)
>  create mode 100644 test/dm/eth.c
>
> diff --git a/test/dm/Makefile b/test/dm/Makefile
> index 1d9148f..b2eb989 100644
> --- a/test/dm/Makefile
> +++ b/test/dm/Makefile
> @@ -17,6 +17,7 @@ obj-$(CONFIG_DM_TEST) += ut.o
>  obj-$(CONFIG_DM_TEST) += core.o
>  obj-$(CONFIG_DM_TEST) += ut.o
>  ifneq ($(CONFIG_SANDBOX),)
> +obj-$(CONFIG_DM_ETH) += eth.o
>  obj-$(CONFIG_DM_GPIO) += gpio.o
>  obj-$(CONFIG_DM_I2C) += i2c.o
>  obj-$(CONFIG_DM_SPI_FLASH) += sf.o
> diff --git a/test/dm/eth.c b/test/dm/eth.c
> new file mode 100644
> index 0000000..2b29fa2
> --- /dev/null
> +++ b/test/dm/eth.c
> @@ -0,0 +1,39 @@
> +/*
> + * Copyright (c) 2015 National Instruments
> + *
> + * (C) Copyright 2015
> + * Joe Hershberger <joe.hershberger@ni.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/test.h>
> +#include <dm/ut.h>
> +#include <fdtdec.h>
> +#include <malloc.h>
> +#include <net.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static int dm_test_eth(struct dm_test_state *dms)
> +{
> +       NetPingIP = string_to_ip("1.1.2.2");
> +
> +       setenv("ethact", "eth at 10002000");
> +       ut_assertok(NetLoop(PING));
> +       ut_asserteq_str("eth at 10002000", getenv("ethact"));
> +
> +       setenv("ethact", "eth at 10003000");
> +       ut_assertok(NetLoop(PING));
> +       ut_asserteq_str("eth at 10003000", getenv("ethact"));
> +
> +       setenv("ethact", "eth at 10004000");
> +       ut_assertok(NetLoop(PING));
> +       ut_asserteq_str("eth at 10004000", getenv("ethact"));
> +
> +       return 0;
> +}
> +
> +DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
> diff --git a/test/dm/test.dts b/test/dm/test.dts
> index 84024a4..2f68cdf 100644
> --- a/test/dm/test.dts
> +++ b/test/dm/test.dts
> @@ -149,4 +149,22 @@
>                 };
>         };
>
> +       eth at 10002000 {
> +               compatible = "sandbox,eth";
> +               reg = <0x10002000 0x1000>;
> +               fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
> +       };
> +
> +       eth at 10003000 {
> +               compatible = "sandbox,eth";
> +               reg = <0x10003000 0x1000>;
> +               fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
> +       };
> +
> +       eth at 10004000 {
> +               compatible = "sandbox,eth";
> +               reg = <0x10004000 0x1000>;
> +               fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x22>;
> +       };
> +
>  };
> --
> 1.7.11.5
>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 11/14] dm: eth: Add support for aliases
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 11/14] dm: eth: Add support for aliases Joe Hershberger
@ 2015-02-15 15:50       ` Simon Glass
  2015-02-17  5:04         ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-02-15 15:50 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Allow network devices to be referred to as "eth0" instead of
> "eth at 12345678" when specified in ethact.
>
> Add tests to verify this behavior.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v3:
> -Added support for aliases
>
> Changes in v2: None
>
>  include/configs/sandbox.h |  4 ++--
>  include/fdtdec.h          |  1 +
>  include/net.h             |  5 +++++
>  lib/fdtdec.c              |  1 +
>  net/eth.c                 | 53 +++++++++++++++++++++++++++++++++++++++--------
>  test/dm/eth.c             | 25 ++++++++++++++++++++++
>  test/dm/test.dts          | 10 +++++----
>  7 files changed, 84 insertions(+), 15 deletions(-)
>
> diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
> index fdba1c8..9df5f74 100644
> --- a/include/configs/sandbox.h
> +++ b/include/configs/sandbox.h
> @@ -187,7 +187,7 @@
>                                         "stderr=serial,lcd\0" \
>                                         "ethaddr=00:00:11:22:33:44\0" \
>                                         "eth1addr=00:00:11:22:33:45\0" \
> -                                       "eth2addr=00:00:11:22:33:46\0" \
> +                                       "eth5addr=00:00:11:22:33:46\0" \
>                                         "ipaddr=1.2.3.4\0"
>  #else
>
> @@ -196,7 +196,7 @@
>                                         "stderr=serial,lcd\0" \
>                                         "ethaddr=00:00:11:22:33:44\0" \
>                                         "eth1addr=00:00:11:22:33:45\0" \
> -                                       "eth2addr=00:00:11:22:33:46\0" \
> +                                       "eth5addr=00:00:11:22:33:46\0" \
>                                         "ipaddr=1.2.3.4\0"
>  #endif
>
> diff --git a/include/fdtdec.h b/include/fdtdec.h
> index 231eed7..e945baa 100644
> --- a/include/fdtdec.h
> +++ b/include/fdtdec.h
> @@ -167,6 +167,7 @@ enum fdt_compat_id {
>         COMPAT_INTEL_GMA,               /* Intel Graphics Media Accelerator */
>         COMPAT_AMS_AS3722,              /* AMS AS3722 PMIC */
>         COMPAT_INTEL_ICH_SPI,           /* Intel ICH7/9 SPI controller */
> +       COMPAT_ETHERNET,                /* Ethernet devices */

SANDBOX_ETHERNET

>
>         COMPAT_COUNT,
>  };
> diff --git a/include/net.h b/include/net.h
> index 11471bd..4e98850 100644
> --- a/include/net.h
> +++ b/include/net.h
> @@ -38,6 +38,8 @@
>
>  #define PKTALIGN       ARCH_DMA_MINALIGN
>
> +#define ETH_MAX_DEVS   32
> +
>  /* IPv4 addresses are always 32 bits in size */
>  typedef __be32         IPaddr_t;
>
> @@ -79,6 +81,8 @@ enum eth_state_t {
>  };
>
>  #ifdef CONFIG_DM_ETH
> +#define ETH_ALIAS_ROOT "eth"
> +
>  struct eth_pdata {
>         phys_addr_t iobase;
>         unsigned char enetaddr[6];
> @@ -96,6 +100,7 @@ struct eth_ops {
>  };
>
>  struct udevice *eth_get_dev(void); /* get the current device */
> +struct udevice *eth_get_dev_by_name(const char *devname);
>  unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
>  int eth_init_state_only(bd_t *bis); /* Set active state */
>  void eth_halt_state_only(void); /* Set passive state */
> diff --git a/lib/fdtdec.c b/lib/fdtdec.c
> index 5bf8f29..33b0a53 100644
> --- a/lib/fdtdec.c
> +++ b/lib/fdtdec.c
> @@ -75,6 +75,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
>         COMPAT(INTEL_GMA, "intel,gma"),
>         COMPAT(AMS_AS3722, "ams,as3722"),
>         COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
> +       COMPAT(ETHERNET, "eth"),

sandbox,eth

>  };
>
>  const char *fdtdec_get_compatible(enum fdt_compat_id id)
> diff --git a/net/eth.c b/net/eth.c
> index e84b948..762effe 100644
> --- a/net/eth.c
> +++ b/net/eth.c
> @@ -10,11 +10,14 @@
>  #include <command.h>
>  #include <dm.h>
>  #include <dm/device-internal.h>
> +#include <fdtdec.h>
>  #include <net.h>
>  #include <miiphy.h>
>  #include <phy.h>
>  #include <asm/errno.h>
>
> +DECLARE_GLOBAL_DATA_PTR;
> +
>  void eth_parse_enetaddr(const char *addr, uchar *enetaddr)
>  {
>         char *end;
> @@ -121,6 +124,39 @@ static void eth_set_dev(struct udevice *dev)
>         uc_priv->current = dev;
>  }
>
> +/*
> + * Find the udevice that either has the name passed in as devname or has an
> + * alias named devname.
> + */
> +struct udevice *eth_get_dev_by_name(const char *devname)
> +{
> +       int node_list[ETH_MAX_DEVS];
> +       int count;
> +       int seq;
> +       char *endp = NULL;
> +       const char *true_name = devname;
> +       struct udevice *it;
> +       struct uclass *uc;
> +
> +       count = fdtdec_find_aliases_for_id(gd->fdt_blob, ETH_ALIAS_ROOT,
> +                                          COMPAT_ETHERNET, node_list,
> +                                          ETH_MAX_DEVS);
> +
> +       seq = simple_strtoul(devname + strlen(ETH_ALIAS_ROOT), &endp, 10);
> +
> +       if (endp > devname + strlen(ETH_ALIAS_ROOT) && count > seq &&
> +           node_list[seq])
> +               true_name = fdt_get_name(gd->fdt_blob, node_list[seq], NULL);
> +
> +       uclass_get(UCLASS_ETH, &uc);
> +       uclass_foreach_dev(it, uc) {
> +               if (strcmp(it->name, true_name) == 0 || it->seq == seq)
> +                       return it;
> +       }

Is it possible for eth_get_dev_by_name() to just look up the name provided?

You already have this:

uclass_foreach_dev(it, uc) {
if (strcmp(it->name, true_name) == 0 || it->seq == seq)
return it;
}

It feels like you just need to through through the devices in the
uclass and strcmp(dev->name, find_name).

I guess I am suffering because I don't understand what you are trying
to do, so am not sure if there is an easier way with driver model. We
really should not go looking in the device tree in
eth_get_dev_by_name()...driver is responsible for parsing that.

> +
> +       return NULL;
> +}
> +
>  unsigned char *eth_get_ethaddr(void)
>  {
>         struct eth_pdata *pdata;
> @@ -396,6 +432,7 @@ UCLASS_DRIVER(eth) = {
>         .init           = eth_uclass_init,
>         .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
>         .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
> +       .flags          = DM_UC_FLAG_SEQ_ALIAS,
>  };
>  #endif
>
> @@ -428,6 +465,11 @@ static void eth_set_current_to_next(void)
>         eth_current = eth_current->next;
>  }
>
> +static void eth_set_dev(struct eth_device *dev)
> +{
> +       eth_current = dev;
> +}
> +
>  struct eth_device *eth_get_dev_by_name(const char *devname)
>  {
>         struct eth_device *dev, *target_dev;
> @@ -844,7 +886,6 @@ void eth_set_current(void)
>  {
>         static char *act;
>         static int  env_changed_id;
> -       void *old_current;
>         int     env_id;
>
>         env_id = get_env_id();
> @@ -852,14 +893,8 @@ void eth_set_current(void)
>                 act = getenv("ethact");
>                 env_changed_id = env_id;
>         }
> -       if (act != NULL) {
> -               old_current = eth_get_dev();
> -               do {
> -                       if (strcmp(eth_get_name(), act) == 0)
> -                               return;
> -                       eth_set_current_to_next();
> -               } while (old_current != eth_get_dev());
> -       }
> +       if (act != NULL)
> +               eth_set_dev(eth_get_dev_by_name(act));
>
>         eth_current_changed();
>  }
> diff --git a/test/dm/eth.c b/test/dm/eth.c
> index 2b29fa2..c0a8ab5 100644
> --- a/test/dm/eth.c
> +++ b/test/dm/eth.c
> @@ -37,3 +37,28 @@ static int dm_test_eth(struct dm_test_state *dms)
>  }
>
>  DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
> +
> +static int dm_test_eth_alias(struct dm_test_state *dms)
> +{
> +       NetPingIP = string_to_ip("1.1.2.2");
> +       setenv("ethact", "eth0");
> +       ut_assertok(NetLoop(PING));
> +       ut_asserteq_str("eth at 10002000", getenv("ethact"));
> +
> +       setenv("ethact", "eth1");
> +       ut_assertok(NetLoop(PING));
> +       ut_asserteq_str("eth at 10004000", getenv("ethact"));
> +
> +       /* Expected to fail since eth2 is not defined in the device tree */
> +       setenv("ethact", "eth2");
> +       ut_asserteq(-1, NetLoop(PING));
> +       ut_asserteq_ptr(NULL, getenv("ethact"));
> +
> +       setenv("ethact", "eth5");
> +       ut_assertok(NetLoop(PING));
> +       ut_asserteq_str("eth at 10003000", getenv("ethact"));
> +
> +       return 0;
> +}
> +
> +DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
> diff --git a/test/dm/test.dts b/test/dm/test.dts
> index 2f68cdf..c5008c3 100644
> --- a/test/dm/test.dts
> +++ b/test/dm/test.dts
> @@ -17,6 +17,8 @@
>                 testfdt3 = "/b-test";
>                 testfdt5 = "/some-bus/c-test at 5";
>                 testfdt8 = "/a-test";
> +               eth0 = "/eth at 10002000";
> +               eth5 = &eth_5;
>         };
>
>         uart0: serial {
> @@ -150,19 +152,19 @@
>         };
>
>         eth at 10002000 {
> -               compatible = "sandbox,eth";
> +               compatible = "sandbox,eth", "eth";
>                 reg = <0x10002000 0x1000>;
>                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
>         };
>
> -       eth at 10003000 {
> -               compatible = "sandbox,eth";
> +       eth_5: eth at 10003000 {
> +               compatible = "sandbox,eth", "eth";
>                 reg = <0x10003000 0x1000>;
>                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
>         };
>
>         eth at 10004000 {
> -               compatible = "sandbox,eth";
> +               compatible = "sandbox,eth", "eth";
>                 reg = <0x10004000 0x1000>;
>                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x22>;
>         };
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 12/14] dm: eth: Add support for ethprime env var
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 12/14] dm: eth: Add support for ethprime env var Joe Hershberger
@ 2015-02-15 15:50       ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-15 15:50 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The ethprime env var is used to indicate the starting device if none is
> specified in ethact. Also support aliases specified in the ethprime var.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

Reviewed-by: Simon Glass <sjg@chromium.org>

Two nits below.

>
> ---
>
> Changes in v3:
> -Added support for ethprime
>
> Changes in v2: None
>
>  net/eth.c     | 13 ++++++++++++-
>  test/dm/eth.c | 21 +++++++++++++++++++++
>  2 files changed, 33 insertions(+), 1 deletion(-)
>
> diff --git a/net/eth.c b/net/eth.c
> index 762effe..1770662 100644
> --- a/net/eth.c
> +++ b/net/eth.c
> @@ -893,8 +893,19 @@ void eth_set_current(void)
>                 act = getenv("ethact");
>                 env_changed_id = env_id;
>         }
> -       if (act != NULL)
> +
> +       if (act == NULL) {
> +               char *ethprime = getenv("ethprime");
> +
> +               if (ethprime && eth_get_dev_by_name(ethprime)) {
> +                       eth_set_dev(eth_get_dev_by_name(ethprime));

Can you store the result of eth_get_dev_by_name() and reuse it? It
seems like an expensive function.

> +               } else {
> +                       eth_set_dev(NULL);
> +                       eth_set_current_to_next();
> +               }
> +       } else {
>                 eth_set_dev(eth_get_dev_by_name(act));
> +       }
>
>         eth_current_changed();
>  }
> diff --git a/test/dm/eth.c b/test/dm/eth.c
> index c0a8ab5..b39a94a 100644
> --- a/test/dm/eth.c
> +++ b/test/dm/eth.c
> @@ -62,3 +62,24 @@ static int dm_test_eth_alias(struct dm_test_state *dms)
>  }
>
>  DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
> +
> +static int dm_test_eth_prime(struct dm_test_state *dms)
> +{
> +       NetPingIP = string_to_ip("1.1.2.2");
> +
> +       /* Expected to be "eth at 10003000" because of ethprime variable */
> +       setenv("ethact", NULL);
> +       setenv("ethprime", "eth5");
> +       ut_assertok(NetLoop(PING));
> +       ut_asserteq_str("eth at 10003000", getenv("ethact"));
> +
> +       /* Expected to be "eth at 10002000" because it is first */
> +       setenv("ethact", NULL);
> +       setenv("ethprime", NULL);
> +       ut_assertok(NetLoop(PING));
> +       ut_asserteq_str("eth at 10002000", getenv("ethact"));
> +
> +       return 0;
> +}
> +

Can you remove this blank line so it is consistent with other test files?

> +DM_TEST(dm_test_eth_prime, DM_TESTF_SCAN_FDT);
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 13/14] dm: eth: Add testing for netretry env var
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 13/14] dm: eth: Add testing for netretry " Joe Hershberger
@ 2015-02-15 15:50       ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-15 15:50 UTC (permalink / raw)
  To: u-boot

On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Make sure that the retry behavior occurs as expected.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

Reviewed-by: Simon Glass <sjg@chromium.org>

Nit below.

>
> ---
>
> Changes in v3:
> -Added testing for netretry
>
> Changes in v2: None
>
>  test/dm/eth.c | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
>
> diff --git a/test/dm/eth.c b/test/dm/eth.c
> index b39a94a..831a994 100644
> --- a/test/dm/eth.c
> +++ b/test/dm/eth.c
> @@ -83,3 +83,28 @@ static int dm_test_eth_prime(struct dm_test_state *dms)
>  }
>
>  DM_TEST(dm_test_eth_prime, DM_TESTF_SCAN_FDT);
> +
> +static int dm_test_eth_retry(struct dm_test_state *dms)
> +{
> +       char ethaddr[18];
> +
> +       NetPingIP = string_to_ip("1.1.2.2");
> +       strcpy(ethaddr, getenv("eth1addr"));
> +       setenv("ethact", "eth at 10004000");
> +       setenv("eth1addr", NULL);
> +       ut_assertok(NetLoop(PING));
> +       ut_asserteq_str("eth at 10002000", getenv("ethact"));
> +
> +       setenv("ethact", "eth at 10004000");
> +       setenv("netretry", "no");
> +       ut_asserteq(-1, NetLoop(PING));
> +       ut_asserteq_str("eth at 10004000", getenv("ethact"));
> +
> +       /* Restore the env */
> +       setenv("eth1addr", ethaddr);
> +       setenv("netretry", NULL);
> +
> +       return 0;
> +}
> +

Remove blank line again

> +DM_TEST(dm_test_eth_retry, DM_TESTF_SCAN_FDT);
> --
> 1.7.11.5
>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 14/14] dm: eth: Add a bridge to a real network for sandbox
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 14/14] dm: eth: Add a bridge to a real network for sandbox Joe Hershberger
@ 2015-02-15 15:50       ` Simon Glass
  2015-02-17  5:16         ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-02-15 15:50 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Implement a bridge between u-boot's network stack and Linux's raw packet
> API allowing the sandbox to send and receive packets using the host
> machine's network interface.
>
> This raw Ethernet API requires elevated privileges.  You can either run
> as root, or you can add the capability needed like so:
>
> sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot

Can you add a note about thsi in README.sandbox? This seems like a
major new feature. It was talked about a few years ago when sandbox
was first created.

>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v3:
> -Made the os raw packet support for sandbox eth build and work.
>
> Changes in v2:
> -Added the raw packet proof-of-concept patch.
>
>  arch/sandbox/dts/sandbox.dts              |   6 ++
>  arch/sandbox/include/asm/sandbox-raw-os.h |  16 ++++
>  drivers/net/Makefile                      |  11 +++
>  drivers/net/sandbox-raw-os.c              | 105 ++++++++++++++++++++++++
>  drivers/net/sandbox-raw.c                 | 128 ++++++++++++++++++++++++++++++
>  include/configs/sandbox.h                 |   1 +
>  6 files changed, 267 insertions(+)
>  create mode 100644 arch/sandbox/include/asm/sandbox-raw-os.h
>  create mode 100644 drivers/net/sandbox-raw-os.c
>  create mode 100644 drivers/net/sandbox-raw.c
>
> diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
> index ba635e8..13bd6c2 100644
> --- a/arch/sandbox/dts/sandbox.dts
> +++ b/arch/sandbox/dts/sandbox.dts
> @@ -188,4 +188,10 @@
>                 reg = <0x10002000 0x1000>;
>                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
>         };
> +
> +       eth at 80000000 {
> +               compatible = "sandbox,eth,raw";

We normally have "vendor,device", so maybe "sandbox,raw-eth"

> +               reg = <0x80000000 0x1000>;
> +               host-raw-interface = "eth0";
> +       };
>  };
> diff --git a/arch/sandbox/include/asm/sandbox-raw-os.h b/arch/sandbox/include/asm/sandbox-raw-os.h
> new file mode 100644
> index 0000000..4e5d418
> --- /dev/null
> +++ b/arch/sandbox/include/asm/sandbox-raw-os.h
> @@ -0,0 +1,16 @@
> +/*
> + * Copyright (c) 2015 National Instruments
> + *
> + * (C) Copyright 2015
> + * Joe Hershberger <joe.hershberger@ni.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#pragma once

We use #ifdef for this in U-Boot at present. I'm not sure why -
perhaps compatibility?

> +
> +int sandbox_raw_init(int *sd, void **devp, const char *ifname,
> +                    unsigned char *ethmac);
> +int sandbox_raw_send(void *packet, int length, int sd, void *device);
> +int sandbox_raw_recv(void *packet, int *length, int sd, void *device);
> +void sandbox_raw_halt(int *sd, void **devp);

Function comments, also what is 'device'?

> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 15dc431..39975b3 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -51,6 +51,8 @@ obj-$(CONFIG_PCNET) += pcnet.o
>  obj-$(CONFIG_RTL8139) += rtl8139.o
>  obj-$(CONFIG_RTL8169) += rtl8169.o
>  obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
> +obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o
> +obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw-os.o
>  obj-$(CONFIG_SH_ETHER) += sh_eth.o
>  obj-$(CONFIG_SMC91111) += smc91111.o
>  obj-$(CONFIG_SMC911X) += smc911x.o
> @@ -68,3 +70,12 @@ obj-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o xilinx_ll_temac_mdio.o \
>  obj-$(CONFIG_ZYNQ_GEM) += zynq_gem.o
>  obj-$(CONFIG_FSL_MC_ENET) += fsl_mc/
>  obj-$(CONFIG_VSC9953) += vsc9953.o
> +
> +# sandbox-raw-os.c is built in the system env, so needs standard includes
> +# CFLAGS_REMOVE_sandbox-raw-os.o cannot be used to drop header include path
> +quiet_cmd_cc_sandbox-raw-os.o = CC $(quiet_modtag)  $@
> +cmd_cc_sandbox-raw-os.o = $(CC) $(filter-out -nostdinc, \
> +       $(patsubst -I%,-idirafter%,$(c_flags))) -c -o $@ $<
> +
> +$(obj)/sandbox-raw-os.o: $(src)/sandbox-raw-os.c FORCE
> +       $(call if_changed_dep,cc_sandbox-raw-os.o)

Can we please move this to the same directory as os.c, so that all the
OS-specific stuff is in one place.

> diff --git a/drivers/net/sandbox-raw-os.c b/drivers/net/sandbox-raw-os.c
> new file mode 100644
> index 0000000..43fae60
> --- /dev/null
> +++ b/drivers/net/sandbox-raw-os.c
> @@ -0,0 +1,105 @@
> +/*
> + * Copyright (c) 2015 National Instruments
> + *
> + * (C) Copyright 2015
> + * Joe Hershberger <joe.hershberger@ni.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <errno.h>
> +#include <net/if.h>
> +#include <netinet/in.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/types.h>
> +#include <sys/ioctl.h>
> +#include <sys/socket.h>
> +#include <unistd.h>
> +
> +#include <linux/if_ether.h>
> +#include <linux/if_packet.h>
> +
> +int sandbox_raw_init(int *sd, void **devp, const char *ifname,
> +                    unsigned char *ethmac)
> +{
> +       int tempsd = 0;
> +       struct ifreq ifr;
> +
> +       strcpy(ifr.ifr_name, ifname);
> +       ifr.ifr_addr.sa_family = AF_INET;
> +       memset(ethmac, 0, 6);
> +       tempsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
> +       if (tempsd < 0) {
> +               printf("Failed to open socket: %d %s\n", errno,
> +                      strerror(errno));
> +               return 1;

How about:

   return -errno

here? That is what U-Boot tends to use now.

> +       }
> +       if (ioctl(tempsd, SIOCGIFHWADDR, &ifr) < 0) {
> +               printf("Failed to call ioctl: %s\n", strerror(errno));
> +               close(tempsd);
> +               return 1;
> +       }
> +       /*
> +        * This only works if the MAC address is overridden with the actual MAC
> +        * address of the interface being used.
> +        */
> +       memcpy(ethmac, ifr.ifr_hwaddr.sa_data, 6 * sizeof(uint8_t));
> +       close(tempsd);
> +
> +       *devp = malloc(sizeof(struct sockaddr_ll));
> +       struct sockaddr_ll *device = *devp;
> +       memset(device, 0, sizeof(struct sockaddr_ll));
> +       device->sll_ifindex = if_nametoindex(ifname);
> +       device->sll_family = AF_PACKET;
> +       memcpy(device->sll_addr, ethmac, 6);
> +       device->sll_halen = htons(6);
> +
> +       *sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
> +       setsockopt(*sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
> +                  strlen(ifname) + 1);
> +
> +       return 0;
> +}
> +
> +int sandbox_raw_send(void *packet, int length, int sd, void *device)
> +{
> +       int retval;
> +
> +       if (!sd || !device)
> +               return -EINVAL;
> +       retval = sendto(sd, packet, length, 0,
> +                  (struct sockaddr *)device, sizeof(struct sockaddr_ll));
> +       if (retval < 0)
> +               printf("Failed to send packet: %d %s\n", errno,
> +                      strerror(errno));
> +       return retval;
> +}
> +
> +int sandbox_raw_recv(void *packet, int *length, int sd, void *device)
> +{
> +       int retval;
> +       int saddr_size;
> +
> +       if (!sd || !device)
> +               return -EINVAL;
> +       saddr_size = sizeof(struct sockaddr);
> +       retval = recvfrom(sd, packet, 1536, 0, (struct sockaddr *)device,
> +                         (socklen_t *)&saddr_size);
> +       *length = 0;
> +       if (retval > 0) {
> +               *length = retval;
> +               return 0;
> +       }
> +
> +       return retval;
> +}
> +
> +void sandbox_raw_halt(int *sd, void **devp)
> +{
> +       free((struct sockaddr_ll *)*devp);
> +       *devp = NULL;
> +       close(*sd);
> +       *sd = -1;
> +}
> diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
> new file mode 100644
> index 0000000..90e462a
> --- /dev/null
> +++ b/drivers/net/sandbox-raw.c
> @@ -0,0 +1,128 @@
> +/*
> + * Copyright (c) 2015 National Instruments
> + *
> + * (C) Copyright 2015
> + * Joe Hershberger <joe.hershberger@ni.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <asm/sandbox-raw-os.h>
> +#include <common.h>
> +#include <dm.h>
> +#include <fdtdec.h>
> +#include <malloc.h>
> +#include <net.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct eth_sandbox_raw_priv {
> +       int sd;
> +       void *device;

comments

> +};
> +
> +static int sb_eth_raw_init(struct udevice *dev, bd_t *bis)
> +{
> +       debug("eth_sandbox_raw: Init\n");

Put after declarations (perhaps removing code from decls if you like)
in each case.

> +
> +       struct eth_sandbox_raw_priv *priv = dev->priv;

add blank line

> +       if (!priv)
> +               return -EINVAL;

As elsewhere I don't understand why this is needed

> +
> +       struct eth_pdata *pdata = dev->platdata;
> +       int retval;
> +       const char *interface = fdt_getprop(gd->fdt_blob, dev->of_offset,
> +                                           "host-raw-interface", NULL);
> +
> +       retval = sandbox_raw_init(&priv->sd, &priv->device, interface,
> +                                 pdata->enetaddr);
> +
> +       return retval;
> +}
> +
> +static int sb_eth_raw_send(struct udevice *dev, void *packet, int length)
> +{
> +       debug("eth_sandbox_raw: Send packet %d\n", length);
> +
> +       struct eth_sandbox_raw_priv *priv = dev->priv;

dev_get_priv(dev) in each case

> +
> +       return sandbox_raw_send(packet, length, priv->sd, priv->device);
> +}
> +
> +static int sb_eth_raw_recv(struct udevice *dev)
> +{
> +       struct eth_sandbox_raw_priv *priv = dev->priv;
> +

remove blank line

> +       int retval;
> +       uchar buffer[PKTSIZE];
> +       int length;
> +
> +       if (!priv)
> +               return 0;
> +       retval = sandbox_raw_recv(buffer, &length, priv->sd, priv->device);
> +       if (!retval && length) {
> +               debug("eth_sandbox_raw: received packet %d\n",
> +                     length);
> +               NetReceive(buffer, length);
> +       }
> +       return 0;
> +}
> +
> +static void sb_eth_raw_halt(struct udevice *dev)
> +{
> +       debug("eth_sandbox_raw: Halt\n");
> +
> +       struct eth_sandbox_raw_priv *priv = dev->priv;
> +
> +       if (!priv)
> +               return;
> +       sandbox_raw_halt(&priv->sd, &priv->device);
> +}
> +
> +static int sb_eth_raw_write_hwaddr(struct udevice *dev)
> +{
> +       struct eth_pdata *pdata = dev->platdata;
> +
> +       debug("eth_sandbox_raw %s: Write HW ADDR - %pM\n", dev->name,
> +             pdata->enetaddr);
> +       return 0;
> +}
> +
> +static const struct eth_ops sb_eth_raw_ops = {
> +       .init                   = sb_eth_raw_init,
> +       .send                   = sb_eth_raw_send,
> +       .recv                   = sb_eth_raw_recv,
> +       .halt                   = sb_eth_raw_halt,
> +       .write_hwaddr           = sb_eth_raw_write_hwaddr,
> +};
> +
> +static int sb_eth_raw_remove(struct udevice *dev)
> +{
> +       return 0;
> +}
> +
> +#ifdef CONFIG_OF_CONTROL

This is always defined for sandbox.

> +static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct eth_pdata *pdata = dev->platdata;
> +
> +       pdata->iobase = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");

dev_get_addr() is now available in dm/master if you prefer to use that.

> +       return 0;
> +}
> +
> +static const struct udevice_id sb_eth_raw_ids[] = {
> +       { .compatible = "sandbox,eth,raw" },
> +       { }
> +};
> +#endif
> +
> +U_BOOT_DRIVER(eth_sandbox_raw) = {
> +       .name   = "eth_sandbox_raw",
> +       .id     = UCLASS_ETH,
> +       .of_match = of_match_ptr(sb_eth_raw_ids),
> +       .ofdata_to_platdata = of_match_ptr(sb_eth_raw_ofdata_to_platdata),
> +       .remove = sb_eth_raw_remove,
> +       .ops    = &sb_eth_raw_ops,
> +       .priv_auto_alloc_size = sizeof(struct eth_sandbox_raw_priv),
> +       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
> +};
> diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
> index 9df5f74..7afa3d2 100644
> --- a/include/configs/sandbox.h
> +++ b/include/configs/sandbox.h
> @@ -141,6 +141,7 @@
>
>  #define CONFIG_DM_ETH
>  #define CONFIG_ETH_SANDBOX
> +#define CONFIG_ETH_SANDBOX_RAW

These should go in Kconfig. Could be a follow-on patch if that is easier.

>  #define CONFIG_CMD_PING
>
>  #define CONFIG_CMD_HASH
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 01/14] dm: core: Allow seq numbers to be resolved before probe
  2015-02-14  2:33             ` Joe Hershberger
@ 2015-02-15 15:59               ` Simon Glass
  2015-02-17  4:17                 ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-02-15 15:59 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 13 February 2015 at 19:33, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> On Thu, Feb 12, 2015 at 11:14 PM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 10 February 2015 at 23:08, Joe Hershberger <joe.hershberger@gmail.com>
>> wrote:
>> > Hi Simon,
>> >
>> > On Tue, Feb 10, 2015 at 10:39 PM, Simon Glass <sjg@chromium.org> wrote:
>> >>
>> >> Hi Joe,
>> >>
>> >> On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com>
>> >> wrote:
>> >> > Before this patch, if the sequence numbers were resolved before
>> >> > probe,
>> >> > this code would insist on defining new non-conflicting-with-itself
>> >> > seq
>> >> > numbers. Now any "non -1" seq number is accepted as already resolved.
>> >>
>> >> Can you explain what problem this solves? At present, when probing a
>> >> device, ->seq must be -1 (sort-of by definition since it doesn't exist
>> >> as an active device in the uclass).
>> >
>> > Please look at eth_post_bind() in patch 07/14.  The Ethernet devices
>> > need to
>> > write their hardware addresses to the registers in bind (since it needs
>> > to
>> > happen regardless of the device being used so that Linux will see the
>> > MAC
>> > address).  As such, the sequence number is needed to look up the
>> > ethaddr. In
>> > order to avoid probing all the devices to get the seq number resolved, I
>> > resolve it in post_bind to avoid the rest of the overhead (thus no
>> > longer
>> > probing in post_bind, which was one of the issues previously).  Then
>> > when
>> > probe comes along, the seq is already resolved.  That's why this patch
>> > is
>> > needed.
>>
>> OK I see.
>>
>> This is a bit messy. If the MAC address assignment is part of the bind
>> step then it shouldn't need the seq number.
>
> Not sure why you say that.  The reason I need the seq number is because I
> need to look up the proper env variable for the MAC address.  E.g. ethaddr,
> eth2addr, etc.  The seq number select which one to read from the env.

We should be able to do this after a probe. A device which is bound
but not probed does not have a sequence number, as things currently
stand.

>
>> I can think of some poor ways to do this but a nice way is not obvious!
>
> Not sure what you're referring to here.  What is "this" in this context?

Figuring out the sequence number.

>
>> One option would be probe all the Ethernet devices on startup. If
>> probe() only set up the hardware (including MAC address) then that
>> might work. It would be fairly fast since it wouldn't involve starting
>> up the link, etc. I suspect you are worried about a lot of Ethernet
>> devices sitting around probed by unused. I'm not sure if that matters
>> though.
>
> I had it probing the devices originally (by calling first and next) and you
> commented that it shouldn't happen until the devices are used.  However, I

That was because your code was probing things in the bind mehod.

> don't think we can guarantee that all drivers that come later will have
> simple probe (since that's not part of the contract).  I think I agree with
> your original statement that we should not probe.  It seems more suitable to
> write the hwaddr in bind as a known and limited side effect.

I don't like the idea of an ethernet device supporting writing its
hardware address before it is probed. Until it is probed we don't
really know it is there, nor where it is exactly (bus, memory
address). So I think writing the hardware address makes more sense
after probe. But probe should not happen as part of bind. It seems to
me it could happen in your eth_init().

>
> The seq number resolution seems fairly well contained as I implemented it in
> bind.  I simply call the core function and write the result to the device
> member.  Then of course this patch to remove the assert.

Yes it is well contained, but I still don't think it is right. If you
want to put '#ifndef CONFIG_DM_NET' around the assert in
uclass_resolve_seq() while we work it out, that is OK with me.

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 01/14] dm: core: Allow seq numbers to be resolved before probe
  2015-02-15 15:59               ` Simon Glass
@ 2015-02-17  4:17                 ` Joe Hershberger
  2015-02-18  5:02                   ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-17  4:17 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Sun, Feb 15, 2015 at 9:59 AM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 13 February 2015 at 19:33, Joe Hershberger <joe.hershberger@gmail.com>
wrote:
> > On Thu, Feb 12, 2015 at 11:14 PM, Simon Glass <sjg@chromium.org> wrote:
> >>
> >> Hi Joe,
> >>
> >> On 10 February 2015 at 23:08, Joe Hershberger <
joe.hershberger@gmail.com>
> >> wrote:
> >> > Hi Simon,
> >> >
> >> > On Tue, Feb 10, 2015 at 10:39 PM, Simon Glass <sjg@chromium.org>
wrote:
> >> >>
> >> >> Hi Joe,
> >> >>
> >> >> On 10 February 2015 at 18:30, Joe Hershberger <
joe.hershberger@ni.com>
> >> >> wrote:
> >> >> > Before this patch, if the sequence numbers were resolved before
> >> >> > probe,
> >> >> > this code would insist on defining new non-conflicting-with-itself
> >> >> > seq
> >> >> > numbers. Now any "non -1" seq number is accepted as already
resolved.
> >> >>
> >> >> Can you explain what problem this solves? At present, when probing a
> >> >> device, ->seq must be -1 (sort-of by definition since it doesn't
exist
> >> >> as an active device in the uclass).
> >> >
> >> > Please look at eth_post_bind() in patch 07/14.  The Ethernet devices
> >> > need to
> >> > write their hardware addresses to the registers in bind (since it
needs
> >> > to
> >> > happen regardless of the device being used so that Linux will see the
> >> > MAC
> >> > address).  As such, the sequence number is needed to look up the
> >> > ethaddr. In
> >> > order to avoid probing all the devices to get the seq number
resolved, I
> >> > resolve it in post_bind to avoid the rest of the overhead (thus no
> >> > longer
> >> > probing in post_bind, which was one of the issues previously).  Then
> >> > when
> >> > probe comes along, the seq is already resolved.  That's why this
patch
> >> > is
> >> > needed.
> >>
> >> OK I see.
> >>
> >> This is a bit messy. If the MAC address assignment is part of the bind
> >> step then it shouldn't need the seq number.
> >
> > Not sure why you say that.  The reason I need the seq number is because
I
> > need to look up the proper env variable for the MAC address.  E.g.
ethaddr,
> > eth2addr, etc.  The seq number select which one to read from the env.
>
> We should be able to do this after a probe. A device which is bound
> but not probed does not have a sequence number, as things currently
> stand.
>
> >
> >> I can think of some poor ways to do this but a nice way is not obvious!
> >
> > Not sure what you're referring to here.  What is "this" in this context?
>
> Figuring out the sequence number.
>
> >
> >> One option would be probe all the Ethernet devices on startup. If
> >> probe() only set up the hardware (including MAC address) then that
> >> might work. It would be fairly fast since it wouldn't involve starting
> >> up the link, etc. I suspect you are worried about a lot of Ethernet
> >> devices sitting around probed by unused. I'm not sure if that matters
> >> though.
> >
> > I had it probing the devices originally (by calling first and next) and
you
> > commented that it shouldn't happen until the devices are used.
However, I
>
> That was because your code was probing things in the bind mehod.
>
> > don't think we can guarantee that all drivers that come later will have
> > simple probe (since that's not part of the contract).  I think I agree
with
> > your original statement that we should not probe.  It seems more
suitable to
> > write the hwaddr in bind as a known and limited side effect.
>
> I don't like the idea of an ethernet device supporting writing its
> hardware address before it is probed. Until it is probed we don't
> really know it is there, nor where it is exactly (bus, memory
> address). So I think writing the hardware address makes more sense
> after probe. But probe should not happen as part of bind. It seems to
> me it could happen in your eth_init().

OK.  I can see why you prefer not to have the hardware accessed in bind.
In order to probe the devices (but not from bind) I'll have to add back
eth_initialize() and have it probe all of the devices.  the "eth_init()"
that you see here is what gets called when the network is enabled, so it
certainly shouldn't go in eth_init().  I could potentially rename it to
eth_start() or something.  That would be clearer, but would break from the
former naming for anyone familiar.

> > The seq number resolution seems fairly well contained as I implemented
it in
> > bind.  I simply call the core function and write the result to the
device
> > member.  Then of course this patch to remove the assert.
>
> Yes it is well contained, but I still don't think it is right. If you
> want to put '#ifndef CONFIG_DM_NET' around the assert in
> uclass_resolve_seq() while we work it out, that is OK with me.

I will work on making it correct instead of adding that.

-Joe

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 07/14] dm: eth: Add basic driver model support to Ethernet stack
  2015-02-15 15:49       ` Simon Glass
@ 2015-02-17  4:37         ` Joe Hershberger
  2015-02-18  5:02           ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-17  4:37 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Sun, Feb 15, 2015 at 9:49 AM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > First just add support for MAC drivers.
>
> It has taken me a while to get through all this unfortunately.
>
> This seems OK to me but needs a clean-up with more comments, etc. If
> you like these could go in a separate patch, so if you want to do that
> please add my Reviewed-by: Simon Glass <sjg@chromium.org> to this one.
> I would prefer that we sort out the bind/probe problem before this is
> merged but I understand you now have quite a bit of work built on top,
> and the problems can be separated.
>
> So if you like we could do one more version, merge it, and continue
> with refinements after that.

I'm a bit leery to merge this until I've actually got more of the
real-world implementation for a board done.  I guess it could always be
corrected in the future, but at the same time, I think it should be fairly
complete.  Do you prefer that it go in as smaller parts?  There's still no
actual board supported and the MDIO / PHY support is not done yet.

> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> >
> > ---
> >
> > Changes in v3:
> > -Correct the pre_unbind logic
> > -Correct failure chaining from bind to probe to init
> > --Fail init if not activated
> > --Fail probe if ethaddr not set
> > -Update ethaddr from env unconditionally on init
> > -Use set current to select the current device regardless of the
previous selection
> > -Allow current eth dev to be NULL
> > -Fixed blank line formatting for variable declaration
> >
> > Changes in v2:
> > -Updated comments
> > -Removed extra parentheses
> > -Changed eth_uclass_priv local var names to be uc_priv
> > -Update error codes
> > -Cause an invalid name to fail binding
> > -Rebase on top of dm/master
> > -Stop maintaining our own index and use DM seq now that it works for
our needs
> > -Move the hwaddr to platdata so that its memory is allocated at bind
when we need it
> > -Prevent device from being probed before used by a command (i.e. before
eth_init()).
> >
> >  common/board_r.c       |   4 +-
> >  common/cmd_bdinfo.c    |   2 +
> >  include/dm/uclass-id.h |   1 +
> >  include/net.h          |  25 ++++
> >  net/eth.c              | 336
++++++++++++++++++++++++++++++++++++++++++++++++-
> >  5 files changed, 361 insertions(+), 7 deletions(-)
> >
> > diff --git a/common/board_r.c b/common/board_r.c
> > index 68a9448..75147b7 100644
> > --- a/common/board_r.c
> > +++ b/common/board_r.c
> > @@ -556,7 +556,7 @@ static int initr_bbmii(void)
> >  }
> >  #endif
> >
> > -#ifdef CONFIG_CMD_NET
> > +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
> >  static int initr_net(void)
> >  {
> >         puts("Net:   ");
> > @@ -825,7 +825,7 @@ init_fnc_t init_sequence_r[] = {
> >  #ifdef CONFIG_BITBANGMII
> >         initr_bbmii,
> >  #endif
> > -#ifdef CONFIG_CMD_NET
> > +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
> >         INIT_FUNC_WATCHDOG_RESET
> >         initr_net,
> >  #endif
> > diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
> > index e6d8a7a..8688cf9 100644
> > --- a/common/cmd_bdinfo.c
> > +++ b/common/cmd_bdinfo.c
> > @@ -34,6 +34,7 @@ static void print_eth(int idx)
> >         printf("%-12s= %s\n", name, val);
> >  }
> >
> > +#ifndef CONFIG_DM_ETH
> >  __maybe_unused
> >  static void print_eths(void)
> >  {
> > @@ -52,6 +53,7 @@ static void print_eths(void)
> >         printf("current eth = %s\n", eth_get_name());
> >         printf("ip_addr     = %s\n", getenv("ipaddr"));
> >  }
> > +#endif
> >
> >  __maybe_unused
> >  static void print_lnum(const char *name, unsigned long long value)
> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> > index 91bb90d..ad96682 100644
> > --- a/include/dm/uclass-id.h
> > +++ b/include/dm/uclass-id.h
> > @@ -34,6 +34,7 @@ enum uclass_id {
> >         UCLASS_I2C_GENERIC,     /* Generic I2C device */
> >         UCLASS_I2C_EEPROM,      /* I2C EEPROM device */
> >         UCLASS_MOD_EXP,         /* RSA Mod Exp device */
> > +       UCLASS_ETH,             /* Ethernet device */
> >
> >         UCLASS_COUNT,
> >         UCLASS_INVALID = -1,
> > diff --git a/include/net.h b/include/net.h
> > index 4d7575e..11471bd 100644
> > --- a/include/net.h
> > +++ b/include/net.h
> > @@ -78,6 +78,30 @@ enum eth_state_t {
> >         ETH_STATE_ACTIVE
> >  };
> >
> > +#ifdef CONFIG_DM_ETH
> > +struct eth_pdata {
> > +       phys_addr_t iobase;
> > +       unsigned char enetaddr[6];
> > +};
> > +
> > +struct eth_ops {
> > +       int (*init)(struct udevice *dev, bd_t *bis);
>
> Why do we pass in bd_t? Isn't that available through gd->bd?

Legacy.  I can kill it if you like.

> > +       int (*send)(struct udevice *dev, void *packet, int length);
> > +       int (*recv)(struct udevice *dev);
> > +       void (*halt)(struct udevice *dev);
> > +#ifdef CONFIG_MCAST_TFTP
> > +       int (*mcast)(struct udevice *dev, const u8 *enetaddr, u8 set);
>
> s/u8/bool/ or maybe int? On ARM at least it is inefficient to keep
> having to mask the parameters.

Again, legacy.  I just copied the former function prototypes and changed
the first parameter to udevice*.

> > +#endif
> > +       int (*write_hwaddr)(struct udevice *dev);
> > +};
>
> Can you please add interface comments on all of these plus the four
> below? I'm trying to make driver model an opportunity to improve the
> code as we go. Things like what the function does, what packet
> contains.

OK.

> > +
> > +struct udevice *eth_get_dev(void); /* get the current device */
> > +unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
> > +int eth_init_state_only(bd_t *bis); /* Set active state */
> > +void eth_halt_state_only(void); /* Set passive state */
>
> Can you expand these a bit? The first one can return NULL in some
> situations. The second returns a pointer to 6 bytes I think (perhaps
> we should define a struct for this in a future patch?)  What are
> active and passive state? Why does one function get passed bd_t and
> not the other (better if neither did).

Legacy.  Same function prototypes as original.  As for active and passive
state, that basically is what the Ethernet stack uses to keep track of if
the network driver is enabled.  These state-only functions were added to
improve NetConsole performance on certain hardware without overhauling the
network stack state transitions.

> > +#endif
> > +
> > +#ifndef CONFIG_DM_ETH
> >  struct eth_device {
> >         char name[16];
> >         unsigned char enetaddr[6];
> > @@ -145,6 +169,7 @@ int eth_write_hwaddr(struct eth_device *dev, const
char *base_name,
> >                      int eth_number);
> >
> >  int usb_eth_initialize(bd_t *bi);
> > +#endif
> >
> >  void eth_try_another(int first_restart);       /* Change the device */
> >  void eth_set_current(void);            /* set nterface to ethcur var */
> > diff --git a/net/eth.c b/net/eth.c
> > index c02548c..e84b948 100644
> > --- a/net/eth.c
> > +++ b/net/eth.c
> > @@ -1,12 +1,15 @@
> >  /*
> >   * (C) Copyright 2001-2010
> >   * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
> > + * Joe Hershberger, National Instruments
> >   *
> >   * SPDX-License-Identifier:    GPL-2.0+
> >   */
> >
> >  #include <common.h>
> >  #include <command.h>
> > +#include <dm.h>
> > +#include <dm/device-internal.h>
> >  #include <net.h>
> >  #include <miiphy.h>
> >  #include <phy.h>
> > @@ -72,6 +75,331 @@ static int eth_mac_skip(int index)
> >         return ((skip_state = getenv(enetvar)) != NULL);
> >  }
> >
> > +static void eth_current_changed(void);
> > +
> > +#ifdef CONFIG_DM_ETH
>
> /**
>  * struct eth_device_priv - private structure for each Ethernet device
>  *
>  * @state:    ...
>  * @priv: ...
>  /
>
> > +struct eth_device_priv {
> > +       int state;
> > +       void *priv;
> > +};
> > +
>
> Structure attached to the uclass itself.
>
> > +struct eth_uclass_priv {
> > +       struct udevice *current;
> > +};
> > +
> > +static void eth_set_current_to_next(void)
> > +{
> > +       struct uclass *uc;
> > +       struct eth_uclass_priv *uc_priv;
> > +
> > +       uclass_get(UCLASS_ETH, &uc);
> > +       uc_priv = uc->priv;
> > +       if (uc_priv->current)
> > +               uclass_next_device(&uc_priv->current);
> > +       if (!uc_priv->current)
> > +               uclass_first_device(UCLASS_ETH, &uc_priv->current);
> > +}
> > +
>
> I think you should have something like this to avoid this duplication:
>
> static struct eth_uclass_priv *get_uclass_priv(void)
> {
>       struct uclass *uc;
>
>       uclass_get(UCLASS_ETH, &uc);
>       assert(uc);
>       return uc->priv;
> }

OK.

> At some point we should add a uclass_get_priv() function in uclass.h.
>
> > +struct udevice *eth_get_dev(void)
> > +{
> > +       struct uclass *uc;
> > +       struct eth_uclass_priv *uc_priv;
> > +
> > +       uclass_get(UCLASS_ETH, &uc);
> > +       uc_priv = uc->priv;
> > +
> > +       return uc_priv->current;
> > +}
> > +
> > +static void eth_set_dev(struct udevice *dev)
> > +{
> > +       struct uclass *uc;
> > +       struct eth_uclass_priv *uc_priv;
> > +
> > +       uclass_get(UCLASS_ETH, &uc);
> > +       uc_priv = uc->priv;
> > +       uc_priv->current = dev;
> > +}
> > +
> > +unsigned char *eth_get_ethaddr(void)
> > +{
> > +       struct eth_pdata *pdata;
> > +
> > +       if (eth_get_dev()) {
> > +               pdata = eth_get_dev()->platdata;
> > +               if (pdata)
> > +                       return pdata->enetaddr;
> > +       }
> > +       return NULL;
> > +}
> > +
> > +/* Set active state */
> > +int eth_init_state_only(bd_t *bis)
>
> This doesn't seem to use bis, so I suspect it is for backwards
compatibility.

Correct.

> > +{
> > +       struct eth_device_priv *priv;
> > +
> > +       if (eth_get_dev()) {
> > +               priv = eth_get_dev()->uclass_priv;
> > +               if (priv)
> > +                       priv->state = ETH_STATE_ACTIVE;
>
> It looks like state uses an enum, so that should be described in the
> comment I mentioned earlier.

OK

> > +       }
> > +       return 0;
> > +}
> > +/* Set passive state */
> > +void eth_halt_state_only(void)
> > +{
> > +       struct eth_device_priv *priv;
> > +
> > +       if (eth_get_dev()) {
> > +               priv = eth_get_dev()->uclass_priv;
> > +               if (priv)
> > +                       priv->state = ETH_STATE_PASSIVE;
> > +       }
> > +}
> > +
> > +int eth_get_dev_index(void)
> > +{
> > +       if (eth_get_dev())
> > +               return eth_get_dev()->seq;
> > +       return -1;
> > +}
> > +
> > +int eth_init(bd_t *bis)
> > +{
> > +       struct udevice *current, *old_current, *dev;
> > +       int retval;
> > +       struct uclass *uc;
> > +
> > +       current = eth_get_dev();
> > +       if (!current) {
> > +               puts("No ethernet found.\n");
>
> printf() as I believe we are trying to avoid puts().

Sorry... once again a copy of the previous code with eth_device switched to
udevice.

> > +               return -1;
> > +       }
> > +       retval = device_probe(current);
> > +       if (retval)
> > +               return retval;
> > +
> > +       /* Sync environment with network devices */
> > +       uclass_get(UCLASS_ETH, &uc);
> > +       uclass_foreach_dev(dev, uc) {
> > +               uchar env_enetaddr[6];
> > +               struct eth_pdata *pdata = dev->platdata;
> > +
>
> ret = device_probe(dev);
> if (ret) ...
>
> here since you can't use dev->seq otherwise.

It should already be probed before this function can be called.

> > +               if (eth_getenv_enetaddr_by_index("eth", dev->seq,
env_enetaddr))
> > +                       memcpy(pdata->enetaddr, env_enetaddr, 6);
> > +               else
> > +                       memset(pdata->enetaddr, 0, 6);
> > +       }
> > +
> > +       old_current = current;
> > +       do {
> > +               debug("Trying %s\n", current->name);
> > +
> > +               if (current->driver && (current->flags &
DM_FLAG_ACTIVATED)) {
>
> There is no need to check current->driver (here and elsewhere)

OK

> device_active(current)
>
> > +                       const struct eth_ops *ops =
current->driver->ops;
> > +
> > +                       if (ops->init(current, bis) >= 0) {
> > +                               struct eth_device_priv *priv =
> > +                                       current->uclass_priv;
> > +                               if (priv)
>
> Remove this check too

OK

> > +                                       priv->state = ETH_STATE_ACTIVE;
> > +
> > +                               return 0;
> > +                       }
> > +               }
> > +               debug("FAIL\n");
> > +
> > +               eth_try_another(0);
> > +               current = eth_get_dev();
> > +       } while (old_current != current);
> > +
> > +       return -ENODEV;
> > +}
> > +
> > +void eth_halt(void)
> > +{
> > +       struct udevice *current;
> > +       const struct eth_ops *ops;
> > +       struct eth_device_priv *priv;
> > +
> > +       current = eth_get_dev();
> > +       if (!current)
> > +               return;
> > +       if (!current->driver)
> > +               return;
>
> Remove these checks
>
> > +
> > +       ops = current->driver->ops;
>
> Define this in your header file:
>
> #define eth_get_ops(dev)        ((struct eth_ops *)(dev)->driver->ops)
>
> then one day we can add checks on dev, etc.
>
> > +       ops->halt(current);
>
> If you like you can drop the local variable and use:
>
> eth_get_ops(dev)->halt(current)
>
> > +
> > +       priv = current->uclass_priv;
> > +       if (priv)
> > +               priv->state = ETH_STATE_PASSIVE;
> > +}
> > +
> > +int eth_send(void *packet, int length)
> > +{
> > +       struct udevice *current;
> > +       const struct eth_ops *ops;
> > +
> > +       current = eth_get_dev();
> > +       if (!current)
> > +               return -1;
> > +       if (!current->driver)
> > +               return -1;
> > +       ops = current->driver->ops;
> > +
> > +       return ops->send(current, packet, length);
> > +}
> > +
> > +int eth_rx(void)
> > +{
> > +       struct udevice *current;
> > +       const struct eth_ops *ops;
> > +
> > +       current = eth_get_dev();
> > +       if (!current)
> > +               return -1;
> > +       if (!current->driver)
> > +               return -1;
> > +       ops = current->driver->ops;
> > +
> > +       return ops->recv(current);
> > +}
> > +
> > +static int eth_write_hwaddr(struct udevice *dev, const char *base_name,
> > +                  int eth_number)
> > +{
> > +       unsigned char env_enetaddr[6];
> > +       int ret = 0;
> > +       struct eth_pdata *pdata;
> > +       const struct eth_ops *ops;
> > +
> > +       eth_getenv_enetaddr_by_index(base_name, eth_number,
env_enetaddr);
> > +
> > +       pdata = dev->platdata;
> > +       if (!is_zero_ether_addr(env_enetaddr)) {
> > +               if (!is_zero_ether_addr(pdata->enetaddr) &&
> > +                   memcmp(pdata->enetaddr, env_enetaddr, 6)) {
> > +                       printf("\nWarning: %s MAC addresses don't
match:\n",
> > +                              dev->name);
> > +                       printf("Address in SROM is         %pM\n",
> > +                              pdata->enetaddr);
> > +                       printf("Address in environment is  %pM\n",
> > +                              env_enetaddr);
> > +               }
> > +
> > +               memcpy(pdata->enetaddr, env_enetaddr, 6);
> > +       } else if (is_valid_ether_addr(pdata->enetaddr)) {
> > +               eth_setenv_enetaddr_by_index(base_name, eth_number,
> > +                                            pdata->enetaddr);
> > +               printf("\nWarning: %s using MAC address from net
device\n",
> > +                      dev->name);
> > +       } else if (is_zero_ether_addr(pdata->enetaddr)) {
> > +               printf("\nError: %s address not set.\n",
> > +                      dev->name);
> > +               return -EINVAL;
> > +       }
> > +
> > +       ops = dev->driver->ops;
> > +       if (dev->driver && ops && ops->write_hwaddr &&
> > +           !eth_mac_skip(eth_number)) {
> > +               if (!is_valid_ether_addr(pdata->enetaddr)) {
> > +                       printf("\nError: %s address %pM illegal
value\n",
> > +                              dev->name, pdata->enetaddr);
> > +                       return -EINVAL;
> > +               }
> > +
> > +               ret = ops->write_hwaddr(dev);
> > +               if (ret)
> > +                       printf("\nWarning: %s failed to set MAC
address\n",
> > +                              dev->name);
> > +       }
> > +
> > +       return ret;
> > +}
> > +
> > +static int eth_uclass_init(struct uclass *class)
> > +{
> > +       bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
> > +
> > +       eth_env_init();
> > +
> > +       return 0;
> > +}
> > +
> > +static int eth_post_bind(struct udevice *dev)
> > +{
> > +       if (strchr(dev->name, ' ')) {
> > +               printf("\nError: eth device name \"%s\" has a space!\n",
> > +                      dev->name);
> > +               return -EINVAL;
> > +       }
> > +
> > +       /*
> > +        * Devices need to write the hwaddr even if not probed so that
Linux
> > +        * will have access to the hwaddr that u-boot stored for the
device.
> > +        */
> > +       dev->seq = uclass_resolve_seq(dev);
> > +       eth_write_hwaddr(dev, "eth", dev->seq);
>
> I still don't like this sorry. I don't see why you can't do this in
> eth_init() above?

I'll have to make a new function for this (explained in the other patch
comments).

> If you really want to do this, please add #ifndef CONFIG_DM_NET around
> the check you have taken out and we can sort it out later.
>
> > +
> > +       return 0;
> > +}
> > +
> > +static int eth_pre_unbind(struct udevice *dev)
>
> It still feels like this is using binding as the presence/absence of a
> device rather than probing. When a device is removed with the remove()
> method, it is no longer available for use, so things like
> eth_try_another() should ignore them. By the time we come to unbind a
> device, it should already be removed.
>
> One way to think of this is that the probe()/remove() corresponds to
> the same idea as in Linux, and bind()/unbind() is a new thing meaning
> that we are aware of the device but it may not currently be available.

OK... That makes sense.  I'll move it over.

> > +{
> > +       struct udevice *first = NULL;
> > +       struct udevice *active;
> > +       struct udevice *it;
> > +       struct uclass *uc;
> > +
> > +       uclass_get(UCLASS_ETH, &uc);
> > +       uclass_foreach_dev(it, uc) {
> > +               if (!first)
> > +                       first = it;
> > +               if (it == dev) {
> > +                       if (dev == first) {
> > +                               active =
list_entry(it->uclass_node.next,
> > +                                          struct udevice, uclass_node);
> > +                               if (&active->uclass_node ==
&uc->dev_head)
> > +                                       active = NULL;
> > +                       } else {
> > +                               active = first;
> > +                       }
> > +                       eth_set_dev(active);
> > +                       eth_current_changed();
> > +               }
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static int eth_post_probe(struct udevice *dev)
> > +{
> > +       struct eth_device_priv *priv = dev->uclass_priv;
> > +       struct eth_pdata *pdata = dev->platdata;
> > +
> > +       if (priv)
>
> no need for this check

OK

> > +               priv->state = ETH_STATE_INIT;
> > +
> > +       if (is_zero_ether_addr(pdata->enetaddr))
> > +               return -EINVAL;
> > +
> > +       return 0;
> > +}
> > +
> > +UCLASS_DRIVER(eth) = {
> > +       .name           = "eth",
> > +       .id             = UCLASS_ETH,
> > +       .post_bind      = eth_post_bind,
> > +       .pre_unbind     = eth_pre_unbind,
> > +       .post_probe     = eth_post_probe,
> > +       .init           = eth_uclass_init,
> > +       .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
> > +       .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
> > +};
> > +#endif
> > +
> > +#ifndef CONFIG_DM_ETH
> >  /*
> >   * CPU and board-specific Ethernet initializations.  Aliased function
> >   * signals caller to move on
> > @@ -423,6 +751,7 @@ int eth_rx(void)
> >
> >         return eth_current->recv(eth_current);
> >  }
> > +#endif /* ifndef CONFIG_DM_ETH */
> >
> >  #ifdef CONFIG_API
> >  static void eth_save_packet(void *packet, int length)
> > @@ -486,7 +815,7 @@ static void eth_current_changed(void)
> >
> >  void eth_try_another(int first_restart)
> >  {
> > -       static struct eth_device *first_failed;
> > +       static void *first_failed;
> >         char *ethrotate;
> >
> >         /*
> > @@ -515,12 +844,9 @@ void eth_set_current(void)
> >  {
> >         static char *act;
> >         static int  env_changed_id;
> > -       struct eth_device *old_current;
> > +       void *old_current;
> >         int     env_id;
> >
> > -       if (!eth_get_dev())     /* XXX no current */
> > -               return;
> > -
> >         env_id = get_env_id();
> >         if ((act == NULL) || (env_changed_id != env_id)) {
> >                 act = getenv("ethact");
> > --
> > 1.7.11.5
> >

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 09/14] dm: eth: Add ARP and PING response to sandbox driver
  2015-02-15 15:49       ` Simon Glass
@ 2015-02-17  4:46         ` Joe Hershberger
  2015-02-18  5:02           ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-17  4:46 UTC (permalink / raw)
  To: u-boot

On Sun, Feb 15, 2015 at 9:49 AM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > The sandbox driver will now generate response traffic to exercise the
> > ping command even when no network exists.  This allows the basic data
> > pathways of the DM to be tested.
> >
> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> > Reviewed-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3:
> > -Prevent a crash if memory is not allocated
> >
> > Changes in v2:
> > -Change printfs to debug in sandbox driver
> > -Move static data to priv
> > -Move fake hwaddr to the device tree
> >
> >  arch/sandbox/dts/sandbox.dts |   1 +
> >  drivers/net/sandbox.c        | 101
+++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 102 insertions(+)
> >
> > diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
> > index 502eb3d..ba635e8 100644
> > --- a/arch/sandbox/dts/sandbox.dts
> > +++ b/arch/sandbox/dts/sandbox.dts
> > @@ -186,5 +186,6 @@
> >         eth at 10002000 {
> >                 compatible = "sandbox,eth";
> >                 reg = <0x10002000 0x1000>;
> > +               fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
> >         };
> >  };
> > diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
> > index 2a2ad41..f9fa1a1 100644
> > --- a/drivers/net/sandbox.c
> > +++ b/drivers/net/sandbox.c
> > @@ -15,22 +15,121 @@
> >
> >  DECLARE_GLOBAL_DATA_PTR;
> >
> > +struct eth_sandbox_priv {
> > +       uchar fake_host_hwaddr[ARP_HLEN];
> > +       IPaddr_t fake_host_ipaddr;
> > +       uchar recv_packet_buffer[PKTSIZE];
> > +       int recv_packet_length;
> > +};
> > +
> >  static int sb_eth_init(struct udevice *dev, bd_t *bis)
> >  {
> >         debug("eth_sandbox: Init\n");
> >
> > +       struct eth_sandbox_priv *priv = dev->priv;
> > +       u32 int_array[ARP_HLEN];
> > +       int i;
> > +
> > +       if (!priv)
> > +               return -EINVAL;
>
> How can this happen?

If I recall this was happening when the probe failed due to being unable to
find a MAC address.  This meant that the device was not active when the
init was called on it.  I believe I later remedied it by checking that
the DM_FLAG_ACTIVATED was set, so this check is probably not needed any
longer.

Is there a way in DM to iterate through only those devices that have been
successfully probed or is it my responsibility to check activated before
using any ops?

> > +
> > +       fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
"fake-host-hwaddr",
> > +                            int_array, ARP_HLEN);
> > +       for (i = 0; i < ARP_HLEN; i++)
> > +               priv->fake_host_hwaddr[i] = (uchar)int_array[i];
> > +
> >         return 0;
> >  }
> >
> >  static int sb_eth_send(struct udevice *dev, void *packet, int length)
> >  {
> >         debug("eth_sandbox: Send packet %d\n", length);
> > +       struct eth_sandbox_priv *priv = dev->priv;
> > +       struct ethernet_hdr *eth = packet;
> > +
> > +       if (ntohs(eth->et_protlen) == PROT_ARP) {
> > +               struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
> > +               if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
> > +                       /* store this as the assumed IP of the fake
host */
> > +                       priv->fake_host_ipaddr =
NetReadIP(&arp->ar_tpa);
> > +                       /* Formulate a fake response */
> > +                       struct ethernet_hdr *eth_recv =
> > +                               (void *)priv->recv_packet_buffer;
> > +                       memcpy(eth_recv->et_dest, eth->et_src,
ARP_HLEN);
> > +                       memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
> > +                              ARP_HLEN);
> > +                       eth_recv->et_protlen = htons(PROT_ARP);
> > +
> > +                       struct arp_hdr *arp_recv =
> > +                               (void *)priv->recv_packet_buffer +
> > +                               ETHER_HDR_SIZE;
> > +                       arp_recv->ar_hrd = htons(ARP_ETHER);
> > +                       arp_recv->ar_pro = htons(PROT_IP);
> > +                       arp_recv->ar_hln = ARP_HLEN;
> > +                       arp_recv->ar_pln = ARP_PLEN;
> > +                       arp_recv->ar_op = htons(ARPOP_REPLY);
> > +                       memcpy(&arp_recv->ar_sha,
priv->fake_host_hwaddr,
> > +                              ARP_HLEN);
> > +                       NetWriteIP(&arp_recv->ar_spa,
priv->fake_host_ipaddr);
> > +                       memcpy(&arp_recv->ar_tha, &arp->ar_sha,
ARP_HLEN);
> > +                       NetCopyIP(&arp_recv->ar_tpa, &arp->ar_spa);
> > +
> > +                       priv->recv_packet_length = ETHER_HDR_SIZE +
> > +                               ARP_HDR_SIZE;
> > +               }
> > +       } else if (ntohs(eth->et_protlen) == PROT_IP) {
> > +               struct ip_udp_hdr *ip = packet + ETHER_HDR_SIZE;
> > +               if (ip->ip_p == IPPROTO_ICMP) {
> > +                       struct icmp_hdr *icmp = (struct icmp_hdr
*)&ip->udp_src;
> > +                       if (icmp->type == ICMP_ECHO_REQUEST) {
> > +                               /* reply to the ping */
> > +                               memcpy(priv->recv_packet_buffer, packet,
> > +                                      length);
> > +                               struct ethernet_hdr *eth_recv =
> > +                                       (void
*)priv->recv_packet_buffer;
> > +                               struct ip_udp_hdr *ipr =
> > +                                       (void
*)priv->recv_packet_buffer +
> > +                                       ETHER_HDR_SIZE;
> > +                               struct icmp_hdr *icmpr =
> > +                                       (struct icmp_hdr
*)&ipr->udp_src;
> > +                               memcpy(eth_recv->et_dest, eth->et_src,
> > +                                      ARP_HLEN);
> > +                               memcpy(eth_recv->et_src,
priv->fake_host_hwaddr,
> > +                                      ARP_HLEN);
> > +                               ipr->ip_sum = 0;
> > +                               ipr->ip_off = 0;
> > +                               NetCopyIP((void *)&ipr->ip_dst,
&ip->ip_src);
> > +                               NetWriteIP((void *)&ipr->ip_src,
> > +                                          priv->fake_host_ipaddr);
> > +                               ipr->ip_sum = ~NetCksum((uchar *)ipr,
> > +                                       IP_HDR_SIZE >> 1);
> > +
> > +                               icmpr->type = ICMP_ECHO_REPLY;
> > +                               icmpr->checksum = 0;
> > +                               icmpr->checksum = ~NetCksum((uchar
*)icmpr,
> > +                                       (length - ETHER_HDR_SIZE -
> > +                                               IP_HDR_SIZE) >> 1);
> > +
> > +                               priv->recv_packet_length = length;
> > +                       }
> > +               }
> > +       }
> >
> >         return 0;
> >  }
> >
> >  static int sb_eth_recv(struct udevice *dev)
> >  {
> > +       struct eth_sandbox_priv *priv = dev->priv;
> > +
> > +       if (priv && priv->recv_packet_length) {
> > +               int lcl_recv_packet_length = priv->recv_packet_length;
> > +               debug("eth_sandbox: received packet %d\n",
> > +                     priv->recv_packet_length);
> > +               priv->recv_packet_length = 0;
> > +               NetReceive((void *)priv->recv_packet_buffer,
> > +                          lcl_recv_packet_length);
> > +       }
> >         return 0;
> >  }
> >
> > @@ -42,6 +141,7 @@ static void sb_eth_halt(struct udevice *dev)
> >  static int sb_eth_write_hwaddr(struct udevice *dev)
> >  {
> >         struct eth_pdata *pdata = dev->platdata;
> > +
> >         debug("eth_sandbox %s: Write HW ADDR - %pM\n", dev->name,
> >               pdata->enetaddr);
> >         return 0;
> > @@ -82,5 +182,6 @@ U_BOOT_DRIVER(eth_sandbox) = {
> >         .ofdata_to_platdata = of_match_ptr(sb_eth_ofdata_to_platdata),
> >         .remove = sb_eth_remove,
> >         .ops    = &sb_eth_ops,
> > +       .priv_auto_alloc_size = sizeof(struct eth_sandbox_priv),
> >         .platdata_auto_alloc_size = sizeof(struct eth_pdata),
> >  };
> > --
> > 1.7.11.5
> >
>
> Regards,
> Simon
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 11/14] dm: eth: Add support for aliases
  2015-02-15 15:50       ` Simon Glass
@ 2015-02-17  5:04         ` Joe Hershberger
  2015-02-18  5:02           ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-17  5:04 UTC (permalink / raw)
  To: u-boot

On Sun, Feb 15, 2015 at 9:50 AM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > Allow network devices to be referred to as "eth0" instead of
> > "eth at 12345678" when specified in ethact.
> >
> > Add tests to verify this behavior.
> >
> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> >
> > ---
> >
> > Changes in v3:
> > -Added support for aliases
> >
> > Changes in v2: None
> >
> >  include/configs/sandbox.h |  4 ++--
> >  include/fdtdec.h          |  1 +
> >  include/net.h             |  5 +++++
> >  lib/fdtdec.c              |  1 +
> >  net/eth.c                 | 53
+++++++++++++++++++++++++++++++++++++++--------
> >  test/dm/eth.c             | 25 ++++++++++++++++++++++
> >  test/dm/test.dts          | 10 +++++----
> >  7 files changed, 84 insertions(+), 15 deletions(-)
> >
> > diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
> > index fdba1c8..9df5f74 100644
> > --- a/include/configs/sandbox.h
> > +++ b/include/configs/sandbox.h
> > @@ -187,7 +187,7 @@
> >                                         "stderr=serial,lcd\0" \
> >                                         "ethaddr=00:00:11:22:33:44\0" \
> >                                         "eth1addr=00:00:11:22:33:45\0" \
> > -                                       "eth2addr=00:00:11:22:33:46\0" \
> > +                                       "eth5addr=00:00:11:22:33:46\0" \
> >                                         "ipaddr=1.2.3.4\0"
> >  #else
> >
> > @@ -196,7 +196,7 @@
> >                                         "stderr=serial,lcd\0" \
> >                                         "ethaddr=00:00:11:22:33:44\0" \
> >                                         "eth1addr=00:00:11:22:33:45\0" \
> > -                                       "eth2addr=00:00:11:22:33:46\0" \
> > +                                       "eth5addr=00:00:11:22:33:46\0" \
> >                                         "ipaddr=1.2.3.4\0"
> >  #endif
> >
> > diff --git a/include/fdtdec.h b/include/fdtdec.h
> > index 231eed7..e945baa 100644
> > --- a/include/fdtdec.h
> > +++ b/include/fdtdec.h
> > @@ -167,6 +167,7 @@ enum fdt_compat_id {
> >         COMPAT_INTEL_GMA,               /* Intel Graphics Media
Accelerator */
> >         COMPAT_AMS_AS3722,              /* AMS AS3722 PMIC */
> >         COMPAT_INTEL_ICH_SPI,           /* Intel ICH7/9 SPI controller
*/
> > +       COMPAT_ETHERNET,                /* Ethernet devices */
>
> SANDBOX_ETHERNET

This is not limited to sandbox.  This is needed for all Ethernet MACs.  Is
there some other way that I should be identifying with all devices in the
device tree of a certain class?

> >
> >         COMPAT_COUNT,
> >  };
> > diff --git a/include/net.h b/include/net.h
> > index 11471bd..4e98850 100644
> > --- a/include/net.h
> > +++ b/include/net.h
> > @@ -38,6 +38,8 @@
> >
> >  #define PKTALIGN       ARCH_DMA_MINALIGN
> >
> > +#define ETH_MAX_DEVS   32
> > +
> >  /* IPv4 addresses are always 32 bits in size */
> >  typedef __be32         IPaddr_t;
> >
> > @@ -79,6 +81,8 @@ enum eth_state_t {
> >  };
> >
> >  #ifdef CONFIG_DM_ETH
> > +#define ETH_ALIAS_ROOT "eth"
> > +
> >  struct eth_pdata {
> >         phys_addr_t iobase;
> >         unsigned char enetaddr[6];
> > @@ -96,6 +100,7 @@ struct eth_ops {
> >  };
> >
> >  struct udevice *eth_get_dev(void); /* get the current device */
> > +struct udevice *eth_get_dev_by_name(const char *devname);
> >  unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
> >  int eth_init_state_only(bd_t *bis); /* Set active state */
> >  void eth_halt_state_only(void); /* Set passive state */
> > diff --git a/lib/fdtdec.c b/lib/fdtdec.c
> > index 5bf8f29..33b0a53 100644
> > --- a/lib/fdtdec.c
> > +++ b/lib/fdtdec.c
> > @@ -75,6 +75,7 @@ static const char * const compat_names[COMPAT_COUNT]
= {
> >         COMPAT(INTEL_GMA, "intel,gma"),
> >         COMPAT(AMS_AS3722, "ams,as3722"),
> >         COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
> > +       COMPAT(ETHERNET, "eth"),
>
> sandbox,eth

Again, this is used to identify all Ethernet controllers.
Perhaps fdtdec_find_aliases_for_id() should not be limiting the alias
search to those that have a certain "compatible" string?

> >  };
> >
> >  const char *fdtdec_get_compatible(enum fdt_compat_id id)
> > diff --git a/net/eth.c b/net/eth.c
> > index e84b948..762effe 100644
> > --- a/net/eth.c
> > +++ b/net/eth.c
> > @@ -10,11 +10,14 @@
> >  #include <command.h>
> >  #include <dm.h>
> >  #include <dm/device-internal.h>
> > +#include <fdtdec.h>
> >  #include <net.h>
> >  #include <miiphy.h>
> >  #include <phy.h>
> >  #include <asm/errno.h>
> >
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> >  void eth_parse_enetaddr(const char *addr, uchar *enetaddr)
> >  {
> >         char *end;
> > @@ -121,6 +124,39 @@ static void eth_set_dev(struct udevice *dev)
> >         uc_priv->current = dev;
> >  }
> >
> > +/*
> > + * Find the udevice that either has the name passed in as devname or
has an
> > + * alias named devname.
> > + */
> > +struct udevice *eth_get_dev_by_name(const char *devname)
> > +{
> > +       int node_list[ETH_MAX_DEVS];
> > +       int count;
> > +       int seq;
> > +       char *endp = NULL;
> > +       const char *true_name = devname;
> > +       struct udevice *it;
> > +       struct uclass *uc;
> > +
> > +       count = fdtdec_find_aliases_for_id(gd->fdt_blob, ETH_ALIAS_ROOT,
> > +                                          COMPAT_ETHERNET, node_list,
> > +                                          ETH_MAX_DEVS);
> > +
> > +       seq = simple_strtoul(devname + strlen(ETH_ALIAS_ROOT), &endp,
10);
> > +
> > +       if (endp > devname + strlen(ETH_ALIAS_ROOT) && count > seq &&
> > +           node_list[seq])
> > +               true_name = fdt_get_name(gd->fdt_blob, node_list[seq],
NULL);
> > +
> > +       uclass_get(UCLASS_ETH, &uc);
> > +       uclass_foreach_dev(it, uc) {
> > +               if (strcmp(it->name, true_name) == 0 || it->seq == seq)
> > +                       return it;
> > +       }
>
> Is it possible for eth_get_dev_by_name() to just look up the name
provided?
>
> You already have this:
>
> uclass_foreach_dev(it, uc) {
> if (strcmp(it->name, true_name) == 0 || it->seq == seq)
> return it;
> }
>
> It feels like you just need to through through the devices in the
> uclass and strcmp(dev->name, find_name).

That works fine for looking up the exact name, but that's not the point of
this patch.  Such code was already there and you can see it below.

> I guess I am suffering because I don't understand what you are trying
> to do, so am not sure if there is an easier way with driver model. We
> really should not go looking in the device tree in
> eth_get_dev_by_name()...driver is responsible for parsing that.

Perhaps this is a limitation of fdtdec_find_aliases_for_id().  I need to be
able to look up the device based on its alias.  It doesn't seem to me that
I'm digging around in the device tree at random places that should be done
by the driver.  I'm simply wanting to ask the device tree what the alias
that the user passed in is pointing at.  Potentially is it not an alias,
but a full name.  Either way, I want to return the udevice.

> > +
> > +       return NULL;
> > +}
> > +
> >  unsigned char *eth_get_ethaddr(void)
> >  {
> >         struct eth_pdata *pdata;
> > @@ -396,6 +432,7 @@ UCLASS_DRIVER(eth) = {
> >         .init           = eth_uclass_init,
> >         .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
> >         .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
> > +       .flags          = DM_UC_FLAG_SEQ_ALIAS,
> >  };
> >  #endif
> >
> > @@ -428,6 +465,11 @@ static void eth_set_current_to_next(void)
> >         eth_current = eth_current->next;
> >  }
> >
> > +static void eth_set_dev(struct eth_device *dev)
> > +{
> > +       eth_current = dev;
> > +}
> > +
> >  struct eth_device *eth_get_dev_by_name(const char *devname)
> >  {
> >         struct eth_device *dev, *target_dev;
> > @@ -844,7 +886,6 @@ void eth_set_current(void)
> >  {
> >         static char *act;
> >         static int  env_changed_id;
> > -       void *old_current;
> >         int     env_id;
> >
> >         env_id = get_env_id();
> > @@ -852,14 +893,8 @@ void eth_set_current(void)
> >                 act = getenv("ethact");
> >                 env_changed_id = env_id;
> >         }
> > -       if (act != NULL) {
> > -               old_current = eth_get_dev();
> > -               do {
> > -                       if (strcmp(eth_get_name(), act) == 0)
> > -                               return;
> > -                       eth_set_current_to_next();
> > -               } while (old_current != eth_get_dev());
> > -       }

This is the simple compare that is being replaced.

> > +       if (act != NULL)
> > +               eth_set_dev(eth_get_dev_by_name(act));
> >
> >         eth_current_changed();
> >  }
> > diff --git a/test/dm/eth.c b/test/dm/eth.c
> > index 2b29fa2..c0a8ab5 100644
> > --- a/test/dm/eth.c
> > +++ b/test/dm/eth.c
> > @@ -37,3 +37,28 @@ static int dm_test_eth(struct dm_test_state *dms)
> >  }
> >
> >  DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
> > +
> > +static int dm_test_eth_alias(struct dm_test_state *dms)
> > +{
> > +       NetPingIP = string_to_ip("1.1.2.2");
> > +       setenv("ethact", "eth0");
> > +       ut_assertok(NetLoop(PING));
> > +       ut_asserteq_str("eth at 10002000", getenv("ethact"));
> > +
> > +       setenv("ethact", "eth1");
> > +       ut_assertok(NetLoop(PING));
> > +       ut_asserteq_str("eth at 10004000", getenv("ethact"));
> > +
> > +       /* Expected to fail since eth2 is not defined in the device
tree */
> > +       setenv("ethact", "eth2");
> > +       ut_asserteq(-1, NetLoop(PING));
> > +       ut_asserteq_ptr(NULL, getenv("ethact"));
> > +
> > +       setenv("ethact", "eth5");
> > +       ut_assertok(NetLoop(PING));
> > +       ut_asserteq_str("eth at 10003000", getenv("ethact"));
> > +
> > +       return 0;
> > +}
> > +
> > +DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
> > diff --git a/test/dm/test.dts b/test/dm/test.dts
> > index 2f68cdf..c5008c3 100644
> > --- a/test/dm/test.dts
> > +++ b/test/dm/test.dts
> > @@ -17,6 +17,8 @@
> >                 testfdt3 = "/b-test";
> >                 testfdt5 = "/some-bus/c-test at 5";
> >                 testfdt8 = "/a-test";
> > +               eth0 = "/eth at 10002000";
> > +               eth5 = &eth_5;
> >         };
> >
> >         uart0: serial {
> > @@ -150,19 +152,19 @@
> >         };
> >
> >         eth at 10002000 {
> > -               compatible = "sandbox,eth";
> > +               compatible = "sandbox,eth", "eth";
> >                 reg = <0x10002000 0x1000>;
> >                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
> >         };
> >
> > -       eth at 10003000 {
> > -               compatible = "sandbox,eth";
> > +       eth_5: eth at 10003000 {
> > +               compatible = "sandbox,eth", "eth";
> >                 reg = <0x10003000 0x1000>;
> >                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
> >         };
> >
> >         eth at 10004000 {
> > -               compatible = "sandbox,eth";
> > +               compatible = "sandbox,eth", "eth";
> >                 reg = <0x10004000 0x1000>;
> >                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x22>;
> >         };
> > --
> > 1.7.11.5
> >
>
> Regards,
> Simon
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 14/14] dm: eth: Add a bridge to a real network for sandbox
  2015-02-15 15:50       ` Simon Glass
@ 2015-02-17  5:16         ` Joe Hershberger
  2015-02-18  5:02           ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-17  5:16 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Sun, Feb 15, 2015 at 9:50 AM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > Implement a bridge between u-boot's network stack and Linux's raw packet
> > API allowing the sandbox to send and receive packets using the host
> > machine's network interface.
> >
> > This raw Ethernet API requires elevated privileges.  You can either run
> > as root, or you can add the capability needed like so:
> >
> > sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot
>
> Can you add a note about thsi in README.sandbox? This seems like a
> major new feature. It was talked about a few years ago when sandbox
> was first created.

OK.  Can you maybe point me to that conversation so I can understand what
was anticipated potentially covering more of what was expected.

> >
> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> >
> > ---
> >
> > Changes in v3:
> > -Made the os raw packet support for sandbox eth build and work.
> >
> > Changes in v2:
> > -Added the raw packet proof-of-concept patch.
> >
> >  arch/sandbox/dts/sandbox.dts              |   6 ++
> >  arch/sandbox/include/asm/sandbox-raw-os.h |  16 ++++
> >  drivers/net/Makefile                      |  11 +++
> >  drivers/net/sandbox-raw-os.c              | 105
++++++++++++++++++++++++
> >  drivers/net/sandbox-raw.c                 | 128
++++++++++++++++++++++++++++++
> >  include/configs/sandbox.h                 |   1 +
> >  6 files changed, 267 insertions(+)
> >  create mode 100644 arch/sandbox/include/asm/sandbox-raw-os.h
> >  create mode 100644 drivers/net/sandbox-raw-os.c
> >  create mode 100644 drivers/net/sandbox-raw.c
> >
> > diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
> > index ba635e8..13bd6c2 100644
> > --- a/arch/sandbox/dts/sandbox.dts
> > +++ b/arch/sandbox/dts/sandbox.dts
> > @@ -188,4 +188,10 @@
> >                 reg = <0x10002000 0x1000>;
> >                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
> >         };
> > +
> > +       eth at 80000000 {
> > +               compatible = "sandbox,eth,raw";
>
> We normally have "vendor,device", so maybe "sandbox,raw-eth"

OK

> > +               reg = <0x80000000 0x1000>;
> > +               host-raw-interface = "eth0";
> > +       };
> >  };
> > diff --git a/arch/sandbox/include/asm/sandbox-raw-os.h
b/arch/sandbox/include/asm/sandbox-raw-os.h
> > new file mode 100644
> > index 0000000..4e5d418
> > --- /dev/null
> > +++ b/arch/sandbox/include/asm/sandbox-raw-os.h
> > @@ -0,0 +1,16 @@
> > +/*
> > + * Copyright (c) 2015 National Instruments
> > + *
> > + * (C) Copyright 2015
> > + * Joe Hershberger <joe.hershberger@ni.com>
> > + *
> > + * SPDX-License-Identifier:    GPL-2.0+
> > + */
> > +
> > +#pragma once
>
> We use #ifdef for this in U-Boot at present. I'm not sure why -
> perhaps compatibility?

OK

> > +
> > +int sandbox_raw_init(int *sd, void **devp, const char *ifname,
> > +                    unsigned char *ethmac);
> > +int sandbox_raw_send(void *packet, int length, int sd, void *device);
> > +int sandbox_raw_recv(void *packet, int *length, int sd, void *device);
> > +void sandbox_raw_halt(int *sd, void **devp);
>
> Function comments, also what is 'device'?

Comments about what?  These are just the functions that implement the
Ethernet driver ops.  Is it not sufficient to document the driver ops
themselves (as you requested in the other patch)?

> > diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> > index 15dc431..39975b3 100644
> > --- a/drivers/net/Makefile
> > +++ b/drivers/net/Makefile
> > @@ -51,6 +51,8 @@ obj-$(CONFIG_PCNET) += pcnet.o
> >  obj-$(CONFIG_RTL8139) += rtl8139.o
> >  obj-$(CONFIG_RTL8169) += rtl8169.o
> >  obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
> > +obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o
> > +obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw-os.o
> >  obj-$(CONFIG_SH_ETHER) += sh_eth.o
> >  obj-$(CONFIG_SMC91111) += smc91111.o
> >  obj-$(CONFIG_SMC911X) += smc911x.o
> > @@ -68,3 +70,12 @@ obj-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o
xilinx_ll_temac_mdio.o \
> >  obj-$(CONFIG_ZYNQ_GEM) += zynq_gem.o
> >  obj-$(CONFIG_FSL_MC_ENET) += fsl_mc/
> >  obj-$(CONFIG_VSC9953) += vsc9953.o
> > +
> > +# sandbox-raw-os.c is built in the system env, so needs standard
includes
> > +# CFLAGS_REMOVE_sandbox-raw-os.o cannot be used to drop header include
path
> > +quiet_cmd_cc_sandbox-raw-os.o = CC $(quiet_modtag)  $@
> > +cmd_cc_sandbox-raw-os.o = $(CC) $(filter-out -nostdinc, \
> > +       $(patsubst -I%,-idirafter%,$(c_flags))) -c -o $@ lt;
> > +
> > +$(obj)/sandbox-raw-os.o: $(src)/sandbox-raw-os.c FORCE
> > +       $(call if_changed_dep,cc_sandbox-raw-os.o)
>
> Can we please move this to the same directory as os.c, so that all the
> OS-specific stuff is in one place.

OK

> > diff --git a/drivers/net/sandbox-raw-os.c b/drivers/net/sandbox-raw-os.c
> > new file mode 100644
> > index 0000000..43fae60
> > --- /dev/null
> > +++ b/drivers/net/sandbox-raw-os.c
> > @@ -0,0 +1,105 @@
> > +/*
> > + * Copyright (c) 2015 National Instruments
> > + *
> > + * (C) Copyright 2015
> > + * Joe Hershberger <joe.hershberger@ni.com>
> > + *
> > + * SPDX-License-Identifier:    GPL-2.0+
> > + */
> > +
> > +#include <errno.h>
> > +#include <net/if.h>
> > +#include <netinet/in.h>
> > +#include <stdio.h>
> > +#include <stdlib.h>
> > +#include <string.h>
> > +#include <sys/types.h>
> > +#include <sys/ioctl.h>
> > +#include <sys/socket.h>
> > +#include <unistd.h>
> > +
> > +#include <linux/if_ether.h>
> > +#include <linux/if_packet.h>
> > +
> > +int sandbox_raw_init(int *sd, void **devp, const char *ifname,
> > +                    unsigned char *ethmac)
> > +{
> > +       int tempsd = 0;
> > +       struct ifreq ifr;
> > +
> > +       strcpy(ifr.ifr_name, ifname);
> > +       ifr.ifr_addr.sa_family = AF_INET;
> > +       memset(ethmac, 0, 6);
> > +       tempsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
> > +       if (tempsd < 0) {
> > +               printf("Failed to open socket: %d %s\n", errno,
> > +                      strerror(errno));
> > +               return 1;
>
> How about:
>
>    return -errno
>
> here? That is what U-Boot tends to use now.

OK

> > +       }
> > +       if (ioctl(tempsd, SIOCGIFHWADDR, &ifr) < 0) {
> > +               printf("Failed to call ioctl: %s\n", strerror(errno));
> > +               close(tempsd);
> > +               return 1;
> > +       }
> > +       /*
> > +        * This only works if the MAC address is overridden with the
actual MAC
> > +        * address of the interface being used.
> > +        */
> > +       memcpy(ethmac, ifr.ifr_hwaddr.sa_data, 6 * sizeof(uint8_t));
> > +       close(tempsd);
> > +
> > +       *devp = malloc(sizeof(struct sockaddr_ll));
> > +       struct sockaddr_ll *device = *devp;
> > +       memset(device, 0, sizeof(struct sockaddr_ll));
> > +       device->sll_ifindex = if_nametoindex(ifname);
> > +       device->sll_family = AF_PACKET;
> > +       memcpy(device->sll_addr, ethmac, 6);
> > +       device->sll_halen = htons(6);
> > +
> > +       *sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
> > +       setsockopt(*sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
> > +                  strlen(ifname) + 1);
> > +
> > +       return 0;
> > +}
> > +
> > +int sandbox_raw_send(void *packet, int length, int sd, void *device)
> > +{
> > +       int retval;
> > +
> > +       if (!sd || !device)
> > +               return -EINVAL;
> > +       retval = sendto(sd, packet, length, 0,
> > +                  (struct sockaddr *)device, sizeof(struct
sockaddr_ll));
> > +       if (retval < 0)
> > +               printf("Failed to send packet: %d %s\n", errno,
> > +                      strerror(errno));
> > +       return retval;
> > +}
> > +
> > +int sandbox_raw_recv(void *packet, int *length, int sd, void *device)
> > +{
> > +       int retval;
> > +       int saddr_size;
> > +
> > +       if (!sd || !device)
> > +               return -EINVAL;
> > +       saddr_size = sizeof(struct sockaddr);
> > +       retval = recvfrom(sd, packet, 1536, 0, (struct sockaddr
*)device,
> > +                         (socklen_t *)&saddr_size);
> > +       *length = 0;
> > +       if (retval > 0) {
> > +               *length = retval;
> > +               return 0;
> > +       }
> > +
> > +       return retval;
> > +}
> > +
> > +void sandbox_raw_halt(int *sd, void **devp)
> > +{
> > +       free((struct sockaddr_ll *)*devp);
> > +       *devp = NULL;
> > +       close(*sd);
> > +       *sd = -1;
> > +}
> > diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
> > new file mode 100644
> > index 0000000..90e462a
> > --- /dev/null
> > +++ b/drivers/net/sandbox-raw.c
> > @@ -0,0 +1,128 @@
> > +/*
> > + * Copyright (c) 2015 National Instruments
> > + *
> > + * (C) Copyright 2015
> > + * Joe Hershberger <joe.hershberger@ni.com>
> > + *
> > + * SPDX-License-Identifier:    GPL-2.0+
> > + */
> > +
> > +#include <asm/sandbox-raw-os.h>
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <fdtdec.h>
> > +#include <malloc.h>
> > +#include <net.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +struct eth_sandbox_raw_priv {
> > +       int sd;
> > +       void *device;
>
> comments
>
> > +};
> > +
> > +static int sb_eth_raw_init(struct udevice *dev, bd_t *bis)
> > +{
> > +       debug("eth_sandbox_raw: Init\n");
>
> Put after declarations (perhaps removing code from decls if you like)
> in each case.
>
> > +
> > +       struct eth_sandbox_raw_priv *priv = dev->priv;
>
> add blank line
>
> > +       if (!priv)
> > +               return -EINVAL;
>
> As elsewhere I don't understand why this is needed
>
> > +
> > +       struct eth_pdata *pdata = dev->platdata;
> > +       int retval;
> > +       const char *interface = fdt_getprop(gd->fdt_blob,
dev->of_offset,
> > +                                           "host-raw-interface", NULL);
> > +
> > +       retval = sandbox_raw_init(&priv->sd, &priv->device, interface,
> > +                                 pdata->enetaddr);
> > +
> > +       return retval;
> > +}
> > +
> > +static int sb_eth_raw_send(struct udevice *dev, void *packet, int
length)
> > +{
> > +       debug("eth_sandbox_raw: Send packet %d\n", length);
> > +
> > +       struct eth_sandbox_raw_priv *priv = dev->priv;
>
> dev_get_priv(dev) in each case
>
> > +
> > +       return sandbox_raw_send(packet, length, priv->sd, priv->device);
> > +}
> > +
> > +static int sb_eth_raw_recv(struct udevice *dev)
> > +{
> > +       struct eth_sandbox_raw_priv *priv = dev->priv;
> > +
>
> remove blank line
>
> > +       int retval;
> > +       uchar buffer[PKTSIZE];
> > +       int length;
> > +
> > +       if (!priv)
> > +               return 0;
> > +       retval = sandbox_raw_recv(buffer, &length, priv->sd,
priv->device);
> > +       if (!retval && length) {
> > +               debug("eth_sandbox_raw: received packet %d\n",
> > +                     length);
> > +               NetReceive(buffer, length);
> > +       }
> > +       return 0;
> > +}
> > +
> > +static void sb_eth_raw_halt(struct udevice *dev)
> > +{
> > +       debug("eth_sandbox_raw: Halt\n");
> > +
> > +       struct eth_sandbox_raw_priv *priv = dev->priv;
> > +
> > +       if (!priv)
> > +               return;
> > +       sandbox_raw_halt(&priv->sd, &priv->device);
> > +}
> > +
> > +static int sb_eth_raw_write_hwaddr(struct udevice *dev)
> > +{
> > +       struct eth_pdata *pdata = dev->platdata;
> > +
> > +       debug("eth_sandbox_raw %s: Write HW ADDR - %pM\n", dev->name,
> > +             pdata->enetaddr);
> > +       return 0;
> > +}
> > +
> > +static const struct eth_ops sb_eth_raw_ops = {
> > +       .init                   = sb_eth_raw_init,
> > +       .send                   = sb_eth_raw_send,
> > +       .recv                   = sb_eth_raw_recv,
> > +       .halt                   = sb_eth_raw_halt,
> > +       .write_hwaddr           = sb_eth_raw_write_hwaddr,
> > +};
> > +
> > +static int sb_eth_raw_remove(struct udevice *dev)
> > +{
> > +       return 0;
> > +}
> > +
> > +#ifdef CONFIG_OF_CONTROL
>
> This is always defined for sandbox.

I figured it was a good pattern to use in general, but if you want me to
prune it out of sandbox-only code I can.

> > +static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev)
> > +{
> > +       struct eth_pdata *pdata = dev->platdata;
> > +
> > +       pdata->iobase = fdtdec_get_addr(gd->fdt_blob, dev->of_offset,
"reg");
>
> dev_get_addr() is now available in dm/master if you prefer to use that.

OK

> > +       return 0;
> > +}
> > +
> > +static const struct udevice_id sb_eth_raw_ids[] = {
> > +       { .compatible = "sandbox,eth,raw" },
> > +       { }
> > +};
> > +#endif
> > +
> > +U_BOOT_DRIVER(eth_sandbox_raw) = {
> > +       .name   = "eth_sandbox_raw",
> > +       .id     = UCLASS_ETH,
> > +       .of_match = of_match_ptr(sb_eth_raw_ids),
> > +       .ofdata_to_platdata =
of_match_ptr(sb_eth_raw_ofdata_to_platdata),
> > +       .remove = sb_eth_raw_remove,
> > +       .ops    = &sb_eth_raw_ops,
> > +       .priv_auto_alloc_size = sizeof(struct eth_sandbox_raw_priv),
> > +       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
> > +};
> > diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
> > index 9df5f74..7afa3d2 100644
> > --- a/include/configs/sandbox.h
> > +++ b/include/configs/sandbox.h
> > @@ -141,6 +141,7 @@
> >
> >  #define CONFIG_DM_ETH
> >  #define CONFIG_ETH_SANDBOX
> > +#define CONFIG_ETH_SANDBOX_RAW
>
> These should go in Kconfig. Could be a follow-on patch if that is easier.

OK

> >  #define CONFIG_CMD_PING
> >
> >  #define CONFIG_CMD_HASH
> > --
> > 1.7.11.5
> >
>
> Regards,
> Simon
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 01/14] dm: core: Allow seq numbers to be resolved before probe
  2015-02-17  4:17                 ` Joe Hershberger
@ 2015-02-18  5:02                   ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-18  5:02 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 16 February 2015 at 21:17, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> Hi Simon,
>
>
> On Sun, Feb 15, 2015 at 9:59 AM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 13 February 2015 at 19:33, Joe Hershberger <joe.hershberger@gmail.com>
>> wrote:
>> > On Thu, Feb 12, 2015 at 11:14 PM, Simon Glass <sjg@chromium.org> wrote:
>> >>
>> >> Hi Joe,
>> >>
>> >> On 10 February 2015 at 23:08, Joe Hershberger
>> >> <joe.hershberger@gmail.com>
>> >> wrote:
>> >> > Hi Simon,
>> >> >
>> >> > On Tue, Feb 10, 2015 at 10:39 PM, Simon Glass <sjg@chromium.org>
>> >> > wrote:
>> >> >>
>> >> >> Hi Joe,
>> >> >>
>> >> >> On 10 February 2015 at 18:30, Joe Hershberger
>> >> >> <joe.hershberger@ni.com>
>> >> >> wrote:
>> >> >> > Before this patch, if the sequence numbers were resolved before
>> >> >> > probe,
>> >> >> > this code would insist on defining new non-conflicting-with-itself
>> >> >> > seq
>> >> >> > numbers. Now any "non -1" seq number is accepted as already
>> >> >> > resolved.
>> >> >>
>> >> >> Can you explain what problem this solves? At present, when probing a
>> >> >> device, ->seq must be -1 (sort-of by definition since it doesn't
>> >> >> exist
>> >> >> as an active device in the uclass).
>> >> >
>> >> > Please look at eth_post_bind() in patch 07/14.  The Ethernet devices
>> >> > need to
>> >> > write their hardware addresses to the registers in bind (since it
>> >> > needs
>> >> > to
>> >> > happen regardless of the device being used so that Linux will see the
>> >> > MAC
>> >> > address).  As such, the sequence number is needed to look up the
>> >> > ethaddr. In
>> >> > order to avoid probing all the devices to get the seq number
>> >> > resolved, I
>> >> > resolve it in post_bind to avoid the rest of the overhead (thus no
>> >> > longer
>> >> > probing in post_bind, which was one of the issues previously).  Then
>> >> > when
>> >> > probe comes along, the seq is already resolved.  That's why this
>> >> > patch
>> >> > is
>> >> > needed.
>> >>
>> >> OK I see.
>> >>
>> >> This is a bit messy. If the MAC address assignment is part of the bind
>> >> step then it shouldn't need the seq number.
>> >
>> > Not sure why you say that.  The reason I need the seq number is because
>> > I
>> > need to look up the proper env variable for the MAC address.  E.g.
>> > ethaddr,
>> > eth2addr, etc.  The seq number select which one to read from the env.
>>
>> We should be able to do this after a probe. A device which is bound
>> but not probed does not have a sequence number, as things currently
>> stand.
>>
>> >
>> >> I can think of some poor ways to do this but a nice way is not obvious!
>> >
>> > Not sure what you're referring to here.  What is "this" in this context?
>>
>> Figuring out the sequence number.
>>
>> >
>> >> One option would be probe all the Ethernet devices on startup. If
>> >> probe() only set up the hardware (including MAC address) then that
>> >> might work. It would be fairly fast since it wouldn't involve starting
>> >> up the link, etc. I suspect you are worried about a lot of Ethernet
>> >> devices sitting around probed by unused. I'm not sure if that matters
>> >> though.
>> >
>> > I had it probing the devices originally (by calling first and next) and
>> > you
>> > commented that it shouldn't happen until the devices are used.  However,
>> > I
>>
>> That was because your code was probing things in the bind mehod.
>>
>> > don't think we can guarantee that all drivers that come later will have
>> > simple probe (since that's not part of the contract).  I think I agree
>> > with
>> > your original statement that we should not probe.  It seems more
>> > suitable to
>> > write the hwaddr in bind as a known and limited side effect.
>>
>> I don't like the idea of an ethernet device supporting writing its
>> hardware address before it is probed. Until it is probed we don't
>> really know it is there, nor where it is exactly (bus, memory
>> address). So I think writing the hardware address makes more sense
>> after probe. But probe should not happen as part of bind. It seems to
>> me it could happen in your eth_init().
>
> OK.  I can see why you prefer not to have the hardware accessed in bind.  In
> order to probe the devices (but not from bind) I'll have to add back
> eth_initialize() and have it probe all of the devices.  the "eth_init()"
> that you see here is what gets called when the network is enabled, so it
> certainly shouldn't go in eth_init().  I could potentially rename it to
> eth_start() or something.  That would be clearer, but would break from the
> former naming for anyone familiar.

I see. Maybe eth_probe_all_devices()?

>
>> > The seq number resolution seems fairly well contained as I implemented
>> > it in
>> > bind.  I simply call the core function and write the result to the
>> > device
>> > member.  Then of course this patch to remove the assert.
>>
>> Yes it is well contained, but I still don't think it is right. If you
>> want to put '#ifndef CONFIG_DM_NET' around the assert in
>> uclass_resolve_seq() while we work it out, that is OK with me.
>
> I will work on making it correct instead of adding that.

OK.

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 07/14] dm: eth: Add basic driver model support to Ethernet stack
  2015-02-17  4:37         ` Joe Hershberger
@ 2015-02-18  5:02           ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-18  5:02 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 16 February 2015 at 21:37, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> Hi Simon,
>
> On Sun, Feb 15, 2015 at 9:49 AM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com>
>> wrote:
>> > First just add support for MAC drivers.
>>
>> It has taken me a while to get through all this unfortunately.
>>
>> This seems OK to me but needs a clean-up with more comments, etc. If
>> you like these could go in a separate patch, so if you want to do that
>> please add my Reviewed-by: Simon Glass <sjg@chromium.org> to this one.
>> I would prefer that we sort out the bind/probe problem before this is
>> merged but I understand you now have quite a bit of work built on top,
>> and the problems can be separated.
>>
>> So if you like we could do one more version, merge it, and continue
>> with refinements after that.
>
> I'm a bit leery to merge this until I've actually got more of the real-world
> implementation for a board done.  I guess it could always be corrected in
> the future, but at the same time, I think it should be fairly complete.  Do
> you prefer that it go in as smaller parts?  There's still no actual board
> supported and the MDIO / PHY support is not done yet.

It's up to you, but I know what it is like when you have a lot of
patches backed up. A real board certainly helps though.

>
>> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>> >
>> > ---
>> >
>> > Changes in v3:
>> > -Correct the pre_unbind logic
>> > -Correct failure chaining from bind to probe to init
>> > --Fail init if not activated
>> > --Fail probe if ethaddr not set
>> > -Update ethaddr from env unconditionally on init
>> > -Use set current to select the current device regardless of the previous
>> > selection
>> > -Allow current eth dev to be NULL
>> > -Fixed blank line formatting for variable declaration
>> >
>> > Changes in v2:
>> > -Updated comments
>> > -Removed extra parentheses
>> > -Changed eth_uclass_priv local var names to be uc_priv
>> > -Update error codes
>> > -Cause an invalid name to fail binding
>> > -Rebase on top of dm/master
>> > -Stop maintaining our own index and use DM seq now that it works for our
>> > needs
>> > -Move the hwaddr to platdata so that its memory is allocated at bind
>> > when we need it
>> > -Prevent device from being probed before used by a command (i.e. before
>> > eth_init()).
>> >
>> >  common/board_r.c       |   4 +-
>> >  common/cmd_bdinfo.c    |   2 +
>> >  include/dm/uclass-id.h |   1 +
>> >  include/net.h          |  25 ++++
>> >  net/eth.c              | 336
>> > ++++++++++++++++++++++++++++++++++++++++++++++++-
>> >  5 files changed, 361 insertions(+), 7 deletions(-)
>> >
>> > diff --git a/common/board_r.c b/common/board_r.c
>> > index 68a9448..75147b7 100644
>> > --- a/common/board_r.c
>> > +++ b/common/board_r.c
>> > @@ -556,7 +556,7 @@ static int initr_bbmii(void)
>> >  }
>> >  #endif
>> >
>> > -#ifdef CONFIG_CMD_NET
>> > +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
>> >  static int initr_net(void)
>> >  {
>> >         puts("Net:   ");
>> > @@ -825,7 +825,7 @@ init_fnc_t init_sequence_r[] = {
>> >  #ifdef CONFIG_BITBANGMII
>> >         initr_bbmii,
>> >  #endif
>> > -#ifdef CONFIG_CMD_NET
>> > +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
>> >         INIT_FUNC_WATCHDOG_RESET
>> >         initr_net,
>> >  #endif
>> > diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
>> > index e6d8a7a..8688cf9 100644
>> > --- a/common/cmd_bdinfo.c
>> > +++ b/common/cmd_bdinfo.c
>> > @@ -34,6 +34,7 @@ static void print_eth(int idx)
>> >         printf("%-12s= %s\n", name, val);
>> >  }
>> >
>> > +#ifndef CONFIG_DM_ETH
>> >  __maybe_unused
>> >  static void print_eths(void)
>> >  {
>> > @@ -52,6 +53,7 @@ static void print_eths(void)
>> >         printf("current eth = %s\n", eth_get_name());
>> >         printf("ip_addr     = %s\n", getenv("ipaddr"));
>> >  }
>> > +#endif
>> >
>> >  __maybe_unused
>> >  static void print_lnum(const char *name, unsigned long long value)
>> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
>> > index 91bb90d..ad96682 100644
>> > --- a/include/dm/uclass-id.h
>> > +++ b/include/dm/uclass-id.h
>> > @@ -34,6 +34,7 @@ enum uclass_id {
>> >         UCLASS_I2C_GENERIC,     /* Generic I2C device */
>> >         UCLASS_I2C_EEPROM,      /* I2C EEPROM device */
>> >         UCLASS_MOD_EXP,         /* RSA Mod Exp device */
>> > +       UCLASS_ETH,             /* Ethernet device */
>> >
>> >         UCLASS_COUNT,
>> >         UCLASS_INVALID = -1,
>> > diff --git a/include/net.h b/include/net.h
>> > index 4d7575e..11471bd 100644
>> > --- a/include/net.h
>> > +++ b/include/net.h
>> > @@ -78,6 +78,30 @@ enum eth_state_t {
>> >         ETH_STATE_ACTIVE
>> >  };
>> >
>> > +#ifdef CONFIG_DM_ETH
>> > +struct eth_pdata {
>> > +       phys_addr_t iobase;
>> > +       unsigned char enetaddr[6];
>> > +};
>> > +
>> > +struct eth_ops {
>> > +       int (*init)(struct udevice *dev, bd_t *bis);
>>
>> Why do we pass in bd_t? Isn't that available through gd->bd?
>
> Legacy.  I can kill it if you like.

OK, that's fine, it can die later.

>
>> > +       int (*send)(struct udevice *dev, void *packet, int length);
>> > +       int (*recv)(struct udevice *dev);
>> > +       void (*halt)(struct udevice *dev);
>> > +#ifdef CONFIG_MCAST_TFTP
>> > +       int (*mcast)(struct udevice *dev, const u8 *enetaddr, u8 set);
>>
>> s/u8/bool/ or maybe int? On ARM at least it is inefficient to keep
>> having to mask the parameters.
>
> Again, legacy.  I just copied the former function prototypes and changed the
> first parameter to udevice*.
>
>> > +#endif
>> > +       int (*write_hwaddr)(struct udevice *dev);
>> > +};
>>
>> Can you please add interface comments on all of these plus the four
>> below? I'm trying to make driver model an opportunity to improve the
>> code as we go. Things like what the function does, what packet
>> contains.
>
> OK.
>
>> > +
>> > +struct udevice *eth_get_dev(void); /* get the current device */
>> > +unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
>> > +int eth_init_state_only(bd_t *bis); /* Set active state */
>> > +void eth_halt_state_only(void); /* Set passive state */
>>
>> Can you expand these a bit? The first one can return NULL in some
>> situations. The second returns a pointer to 6 bytes I think (perhaps
>> we should define a struct for this in a future patch?)  What are
>> active and passive state? Why does one function get passed bd_t and
>> not the other (better if neither did).
>
> Legacy.  Same function prototypes as original.  As for active and passive
> state, that basically is what the Ethernet stack uses to keep track of if
> the network driver is enabled.  These state-only functions were added to
> improve NetConsole performance on certain hardware without overhauling the
> network stack state transitions.

OK

>
>> > +#endif
>> > +
>> > +#ifndef CONFIG_DM_ETH
>> >  struct eth_device {
>> >         char name[16];
>> >         unsigned char enetaddr[6];
>> > @@ -145,6 +169,7 @@ int eth_write_hwaddr(struct eth_device *dev, const
>> > char *base_name,
>> >                      int eth_number);
>> >
>> >  int usb_eth_initialize(bd_t *bi);
>> > +#endif
>> >
>> >  void eth_try_another(int first_restart);       /* Change the device */
>> >  void eth_set_current(void);            /* set nterface to ethcur var */
>> > diff --git a/net/eth.c b/net/eth.c
>> > index c02548c..e84b948 100644
>> > --- a/net/eth.c
>> > +++ b/net/eth.c
>> > @@ -1,12 +1,15 @@
>> >  /*
>> >   * (C) Copyright 2001-2010
>> >   * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
>> > + * Joe Hershberger, National Instruments
>> >   *
>> >   * SPDX-License-Identifier:    GPL-2.0+
>> >   */
>> >
>> >  #include <common.h>
>> >  #include <command.h>
>> > +#include <dm.h>
>> > +#include <dm/device-internal.h>
>> >  #include <net.h>
>> >  #include <miiphy.h>
>> >  #include <phy.h>
>> > @@ -72,6 +75,331 @@ static int eth_mac_skip(int index)
>> >         return ((skip_state = getenv(enetvar)) != NULL);
>> >  }
>> >
>> > +static void eth_current_changed(void);
>> > +
>> > +#ifdef CONFIG_DM_ETH
>>
>> /**
>>  * struct eth_device_priv - private structure for each Ethernet device
>>  *
>>  * @state:    ...
>>  * @priv: ...
>>  /
>>
>> > +struct eth_device_priv {
>> > +       int state;
>> > +       void *priv;
>> > +};
>> > +
>>
>> Structure attached to the uclass itself.
>>
>> > +struct eth_uclass_priv {
>> > +       struct udevice *current;
>> > +};
>> > +
>> > +static void eth_set_current_to_next(void)
>> > +{
>> > +       struct uclass *uc;
>> > +       struct eth_uclass_priv *uc_priv;
>> > +
>> > +       uclass_get(UCLASS_ETH, &uc);
>> > +       uc_priv = uc->priv;
>> > +       if (uc_priv->current)
>> > +               uclass_next_device(&uc_priv->current);
>> > +       if (!uc_priv->current)
>> > +               uclass_first_device(UCLASS_ETH, &uc_priv->current);
>> > +}
>> > +
>>
>> I think you should have something like this to avoid this duplication:
>>
>> static struct eth_uclass_priv *get_uclass_priv(void)
>> {
>>       struct uclass *uc;
>>
>>       uclass_get(UCLASS_ETH, &uc);
>>       assert(uc);
>>       return uc->priv;
>> }
>
> OK.
>
>> At some point we should add a uclass_get_priv() function in uclass.h.
>>
>> > +struct udevice *eth_get_dev(void)
>> > +{
>> > +       struct uclass *uc;
>> > +       struct eth_uclass_priv *uc_priv;
>> > +
>> > +       uclass_get(UCLASS_ETH, &uc);
>> > +       uc_priv = uc->priv;
>> > +
>> > +       return uc_priv->current;
>> > +}
>> > +
>> > +static void eth_set_dev(struct udevice *dev)
>> > +{
>> > +       struct uclass *uc;
>> > +       struct eth_uclass_priv *uc_priv;
>> > +
>> > +       uclass_get(UCLASS_ETH, &uc);
>> > +       uc_priv = uc->priv;
>> > +       uc_priv->current = dev;
>> > +}
>> > +
>> > +unsigned char *eth_get_ethaddr(void)
>> > +{
>> > +       struct eth_pdata *pdata;
>> > +
>> > +       if (eth_get_dev()) {
>> > +               pdata = eth_get_dev()->platdata;
>> > +               if (pdata)
>> > +                       return pdata->enetaddr;
>> > +       }
>> > +       return NULL;
>> > +}
>> > +
>> > +/* Set active state */
>> > +int eth_init_state_only(bd_t *bis)
>>
>> This doesn't seem to use bis, so I suspect it is for backwards
>> compatibility.
>
> Correct.
>
>> > +{
>> > +       struct eth_device_priv *priv;
>> > +
>> > +       if (eth_get_dev()) {
>> > +               priv = eth_get_dev()->uclass_priv;
>> > +               if (priv)
>> > +                       priv->state = ETH_STATE_ACTIVE;
>>
>> It looks like state uses an enum, so that should be described in the
>> comment I mentioned earlier.
>
> OK
>
>> > +       }
>> > +       return 0;
>> > +}
>> > +/* Set passive state */
>> > +void eth_halt_state_only(void)
>> > +{
>> > +       struct eth_device_priv *priv;
>> > +
>> > +       if (eth_get_dev()) {
>> > +               priv = eth_get_dev()->uclass_priv;
>> > +               if (priv)
>> > +                       priv->state = ETH_STATE_PASSIVE;
>> > +       }
>> > +}
>> > +
>> > +int eth_get_dev_index(void)
>> > +{
>> > +       if (eth_get_dev())
>> > +               return eth_get_dev()->seq;
>> > +       return -1;
>> > +}
>> > +
>> > +int eth_init(bd_t *bis)
>> > +{
>> > +       struct udevice *current, *old_current, *dev;
>> > +       int retval;
>> > +       struct uclass *uc;
>> > +
>> > +       current = eth_get_dev();
>> > +       if (!current) {
>> > +               puts("No ethernet found.\n");
>>
>> printf() as I believe we are trying to avoid puts().
>
> Sorry... once again a copy of the previous code with eth_device switched to
> udevice.

OK, so it could be an oppty to tidy it up, but it's fine to leave it.

>
>> > +               return -1;
>> > +       }
>> > +       retval = device_probe(current);
>> > +       if (retval)
>> > +               return retval;
>> > +
>> > +       /* Sync environment with network devices */
>> > +       uclass_get(UCLASS_ETH, &uc);
>> > +       uclass_foreach_dev(dev, uc) {
>> > +               uchar env_enetaddr[6];
>> > +               struct eth_pdata *pdata = dev->platdata;
>> > +
>>
>> ret = device_probe(dev);
>> if (ret) ...
>>
>> here since you can't use dev->seq otherwise.
>
> It should already be probed before this function can be called.

OK, can you add a comment about that here?

>
>> > +               if (eth_getenv_enetaddr_by_index("eth", dev->seq,
>> > env_enetaddr))
>> > +                       memcpy(pdata->enetaddr, env_enetaddr, 6);
>> > +               else
>> > +                       memset(pdata->enetaddr, 0, 6);
>> > +       }
>> > +
>> > +       old_current = current;
>> > +       do {
>> > +               debug("Trying %s\n", current->name);
>> > +
>> > +               if (current->driver && (current->flags &
>> > DM_FLAG_ACTIVATED)) {
>>
>> There is no need to check current->driver (here and elsewhere)
>
> OK
>
>> device_active(current)
>>
>> > +                       const struct eth_ops *ops =
>> > current->driver->ops;
>> > +
>> > +                       if (ops->init(current, bis) >= 0) {
>> > +                               struct eth_device_priv *priv =
>> > +                                       current->uclass_priv;
>> > +                               if (priv)
>>
>> Remove this check too
>
> OK
>
>
>> > +                                       priv->state = ETH_STATE_ACTIVE;
>> > +
>> > +                               return 0;
>> > +                       }
>> > +               }
>> > +               debug("FAIL\n");
>> > +
>> > +               eth_try_another(0);
>> > +               current = eth_get_dev();
>> > +       } while (old_current != current);
>> > +
>> > +       return -ENODEV;
>> > +}
>> > +
>> > +void eth_halt(void)
>> > +{
>> > +       struct udevice *current;
>> > +       const struct eth_ops *ops;
>> > +       struct eth_device_priv *priv;
>> > +
>> > +       current = eth_get_dev();
>> > +       if (!current)
>> > +               return;
>> > +       if (!current->driver)
>> > +               return;
>>
>> Remove these checks
>>
>> > +
>> > +       ops = current->driver->ops;
>>
>> Define this in your header file:
>>
>> #define eth_get_ops(dev)        ((struct eth_ops *)(dev)->driver->ops)
>>
>> then one day we can add checks on dev, etc.
>>
>> > +       ops->halt(current);
>>
>> If you like you can drop the local variable and use:
>>
>> eth_get_ops(dev)->halt(current)
>>
>> > +
>> > +       priv = current->uclass_priv;
>> > +       if (priv)
>> > +               priv->state = ETH_STATE_PASSIVE;
>> > +}
>> > +
>> > +int eth_send(void *packet, int length)
>> > +{
>> > +       struct udevice *current;
>> > +       const struct eth_ops *ops;
>> > +
>> > +       current = eth_get_dev();
>> > +       if (!current)
>> > +               return -1;
>> > +       if (!current->driver)
>> > +               return -1;
>> > +       ops = current->driver->ops;
>> > +
>> > +       return ops->send(current, packet, length);
>> > +}
>> > +
>> > +int eth_rx(void)
>> > +{
>> > +       struct udevice *current;
>> > +       const struct eth_ops *ops;
>> > +
>> > +       current = eth_get_dev();
>> > +       if (!current)
>> > +               return -1;
>> > +       if (!current->driver)
>> > +               return -1;
>> > +       ops = current->driver->ops;
>> > +
>> > +       return ops->recv(current);
>> > +}
>> > +
>> > +static int eth_write_hwaddr(struct udevice *dev, const char *base_name,
>> > +                  int eth_number)
>> > +{
>> > +       unsigned char env_enetaddr[6];
>> > +       int ret = 0;
>> > +       struct eth_pdata *pdata;
>> > +       const struct eth_ops *ops;
>> > +
>> > +       eth_getenv_enetaddr_by_index(base_name, eth_number,
>> > env_enetaddr);
>> > +
>> > +       pdata = dev->platdata;
>> > +       if (!is_zero_ether_addr(env_enetaddr)) {
>> > +               if (!is_zero_ether_addr(pdata->enetaddr) &&
>> > +                   memcmp(pdata->enetaddr, env_enetaddr, 6)) {
>> > +                       printf("\nWarning: %s MAC addresses don't
>> > match:\n",
>> > +                              dev->name);
>> > +                       printf("Address in SROM is         %pM\n",
>> > +                              pdata->enetaddr);
>> > +                       printf("Address in environment is  %pM\n",
>> > +                              env_enetaddr);
>> > +               }
>> > +
>> > +               memcpy(pdata->enetaddr, env_enetaddr, 6);
>> > +       } else if (is_valid_ether_addr(pdata->enetaddr)) {
>> > +               eth_setenv_enetaddr_by_index(base_name, eth_number,
>> > +                                            pdata->enetaddr);
>> > +               printf("\nWarning: %s using MAC address from net
>> > device\n",
>> > +                      dev->name);
>> > +       } else if (is_zero_ether_addr(pdata->enetaddr)) {
>> > +               printf("\nError: %s address not set.\n",
>> > +                      dev->name);
>> > +               return -EINVAL;
>> > +       }
>> > +
>> > +       ops = dev->driver->ops;
>> > +       if (dev->driver && ops && ops->write_hwaddr &&
>> > +           !eth_mac_skip(eth_number)) {
>> > +               if (!is_valid_ether_addr(pdata->enetaddr)) {
>> > +                       printf("\nError: %s address %pM illegal
>> > value\n",
>> > +                              dev->name, pdata->enetaddr);
>> > +                       return -EINVAL;
>> > +               }
>> > +
>> > +               ret = ops->write_hwaddr(dev);
>> > +               if (ret)
>> > +                       printf("\nWarning: %s failed to set MAC
>> > address\n",
>> > +                              dev->name);
>> > +       }
>> > +
>> > +       return ret;
>> > +}
>> > +
>> > +static int eth_uclass_init(struct uclass *class)
>> > +{
>> > +       bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
>> > +
>> > +       eth_env_init();
>> > +
>> > +       return 0;
>> > +}
>> > +
>> > +static int eth_post_bind(struct udevice *dev)
>> > +{
>> > +       if (strchr(dev->name, ' ')) {
>> > +               printf("\nError: eth device name \"%s\" has a space!\n",
>> > +                      dev->name);
>> > +               return -EINVAL;
>> > +       }
>> > +
>> > +       /*
>> > +        * Devices need to write the hwaddr even if not probed so that
>> > Linux
>> > +        * will have access to the hwaddr that u-boot stored for the
>> > device.
>> > +        */
>> > +       dev->seq = uclass_resolve_seq(dev);
>> > +       eth_write_hwaddr(dev, "eth", dev->seq);
>>
>> I still don't like this sorry. I don't see why you can't do this in
>> eth_init() above?
>
> I'll have to make a new function for this (explained in the other patch
> comments).
>
>> If you really want to do this, please add #ifndef CONFIG_DM_NET around
>> the check you have taken out and we can sort it out later.
>>
>> > +
>> > +       return 0;
>> > +}
>> > +
>> > +static int eth_pre_unbind(struct udevice *dev)
>>
>> It still feels like this is using binding as the presence/absence of a
>> device rather than probing. When a device is removed with the remove()
>> method, it is no longer available for use, so things like
>> eth_try_another() should ignore them. By the time we come to unbind a
>> device, it should already be removed.
>>
>> One way to think of this is that the probe()/remove() corresponds to
>> the same idea as in Linux, and bind()/unbind() is a new thing meaning
>> that we are aware of the device but it may not currently be available.
>
> OK... That makes sense.  I'll move it over.
>
>
>> > +{
>> > +       struct udevice *first = NULL;
>> > +       struct udevice *active;
>> > +       struct udevice *it;
>> > +       struct uclass *uc;
>> > +
>> > +       uclass_get(UCLASS_ETH, &uc);
>> > +       uclass_foreach_dev(it, uc) {
>> > +               if (!first)
>> > +                       first = it;
>> > +               if (it == dev) {
>> > +                       if (dev == first) {
>> > +                               active =
>> > list_entry(it->uclass_node.next,
>> > +                                          struct udevice, uclass_node);
>> > +                               if (&active->uclass_node ==
>> > &uc->dev_head)
>> > +                                       active = NULL;
>> > +                       } else {
>> > +                               active = first;
>> > +                       }
>> > +                       eth_set_dev(active);
>> > +                       eth_current_changed();
>> > +               }
>> > +       }
>> > +
>> > +       return 0;
>> > +}
>> > +
>> > +static int eth_post_probe(struct udevice *dev)
>> > +{
>> > +       struct eth_device_priv *priv = dev->uclass_priv;
>> > +       struct eth_pdata *pdata = dev->platdata;
>> > +
>> > +       if (priv)
>>
>> no need for this check
>
> OK
>
>> > +               priv->state = ETH_STATE_INIT;
>> > +
>> > +       if (is_zero_ether_addr(pdata->enetaddr))
>> > +               return -EINVAL;
>> > +
>> > +       return 0;
>> > +}
>> > +
>> > +UCLASS_DRIVER(eth) = {
>> > +       .name           = "eth",
>> > +       .id             = UCLASS_ETH,
>> > +       .post_bind      = eth_post_bind,
>> > +       .pre_unbind     = eth_pre_unbind,
>> > +       .post_probe     = eth_post_probe,
>> > +       .init           = eth_uclass_init,
>> > +       .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
>> > +       .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
>> > +};
>> > +#endif
>> > +
>> > +#ifndef CONFIG_DM_ETH
>> >  /*
>> >   * CPU and board-specific Ethernet initializations.  Aliased function
>> >   * signals caller to move on
>> > @@ -423,6 +751,7 @@ int eth_rx(void)
>> >
>> >         return eth_current->recv(eth_current);
>> >  }
>> > +#endif /* ifndef CONFIG_DM_ETH */
>> >
>> >  #ifdef CONFIG_API
>> >  static void eth_save_packet(void *packet, int length)
>> > @@ -486,7 +815,7 @@ static void eth_current_changed(void)
>> >
>> >  void eth_try_another(int first_restart)
>> >  {
>> > -       static struct eth_device *first_failed;
>> > +       static void *first_failed;
>> >         char *ethrotate;
>> >
>> >         /*
>> > @@ -515,12 +844,9 @@ void eth_set_current(void)
>> >  {
>> >         static char *act;
>> >         static int  env_changed_id;
>> > -       struct eth_device *old_current;
>> > +       void *old_current;
>> >         int     env_id;
>> >
>> > -       if (!eth_get_dev())     /* XXX no current */
>> > -               return;
>> > -
>> >         env_id = get_env_id();
>> >         if ((act == NULL) || (env_changed_id != env_id)) {
>> >                 act = getenv("ethact");
>> > --
>> > 1.7.11.5
>> >
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 09/14] dm: eth: Add ARP and PING response to sandbox driver
  2015-02-17  4:46         ` Joe Hershberger
@ 2015-02-18  5:02           ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-18  5:02 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 16 February 2015 at 21:46, Joe Hershberger <joe.hershberger@gmail.com> wrote:
>
>
> On Sun, Feb 15, 2015 at 9:49 AM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com>
>> wrote:
>> > The sandbox driver will now generate response traffic to exercise the
>> > ping command even when no network exists.  This allows the basic data
>> > pathways of the DM to be tested.
>> >
>> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>> > Reviewed-by: Simon Glass <sjg@chromium.org>
>> > ---
>> >
>> > Changes in v3:
>> > -Prevent a crash if memory is not allocated
>> >
>> > Changes in v2:
>> > -Change printfs to debug in sandbox driver
>> > -Move static data to priv
>> > -Move fake hwaddr to the device tree
>> >
>> >  arch/sandbox/dts/sandbox.dts |   1 +
>> >  drivers/net/sandbox.c        | 101
>> > +++++++++++++++++++++++++++++++++++++++++++
>> >  2 files changed, 102 insertions(+)
>> >
>> > diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
>> > index 502eb3d..ba635e8 100644
>> > --- a/arch/sandbox/dts/sandbox.dts
>> > +++ b/arch/sandbox/dts/sandbox.dts
>> > @@ -186,5 +186,6 @@
>> >         eth at 10002000 {
>> >                 compatible = "sandbox,eth";
>> >                 reg = <0x10002000 0x1000>;
>> > +               fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
>> >         };
>> >  };
>> > diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
>> > index 2a2ad41..f9fa1a1 100644
>> > --- a/drivers/net/sandbox.c
>> > +++ b/drivers/net/sandbox.c
>> > @@ -15,22 +15,121 @@
>> >
>> >  DECLARE_GLOBAL_DATA_PTR;
>> >
>> > +struct eth_sandbox_priv {
>> > +       uchar fake_host_hwaddr[ARP_HLEN];
>> > +       IPaddr_t fake_host_ipaddr;
>> > +       uchar recv_packet_buffer[PKTSIZE];
>> > +       int recv_packet_length;
>> > +};
>> > +
>> >  static int sb_eth_init(struct udevice *dev, bd_t *bis)
>> >  {
>> >         debug("eth_sandbox: Init\n");
>> >
>> > +       struct eth_sandbox_priv *priv = dev->priv;
>> > +       u32 int_array[ARP_HLEN];
>> > +       int i;
>> > +
>> > +       if (!priv)
>> > +               return -EINVAL;
>>
>> How can this happen?
>
> If I recall this was happening when the probe failed due to being unable to
> find a MAC address.  This meant that the device was not active when the init
> was called on it.  I believe I later remedied it by checking that the
> DM_FLAG_ACTIVATED was set, so this check is probably not needed any longer.
>
> Is there a way in DM to iterate through only those devices that have been
> successfully probed or is it my responsibility to check activated before
> using any ops?

I normally check it in the uclass. The functions which return a device
-e.g. uclass_get_device...() normally probe the device before it is
returned. The idea is that it should be hard to obtain a 'struct
udevice' in non-core code (i.e. outside drivers/core) without it being
probed first.

But if you want to iterate across all devices and skip those that are
not probed you will need to do it yourself, or add helper functions.

[snip]

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 11/14] dm: eth: Add support for aliases
  2015-02-17  5:04         ` Joe Hershberger
@ 2015-02-18  5:02           ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-18  5:02 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 16 February 2015 at 22:04, Joe Hershberger <joe.hershberger@gmail.com> wrote:
>
>
> On Sun, Feb 15, 2015 at 9:50 AM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com>
>> wrote:
>> > Allow network devices to be referred to as "eth0" instead of
>> > "eth at 12345678" when specified in ethact.
>> >
>> > Add tests to verify this behavior.
>> >
>> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>> >
>> > ---
>> >
>> > Changes in v3:
>> > -Added support for aliases
>> >
>> > Changes in v2: None
>> >
>> >  include/configs/sandbox.h |  4 ++--
>> >  include/fdtdec.h          |  1 +
>> >  include/net.h             |  5 +++++
>> >  lib/fdtdec.c              |  1 +
>> >  net/eth.c                 | 53
>> > +++++++++++++++++++++++++++++++++++++++--------
>> >  test/dm/eth.c             | 25 ++++++++++++++++++++++
>> >  test/dm/test.dts          | 10 +++++----
>> >  7 files changed, 84 insertions(+), 15 deletions(-)
>> >
>> > diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
>> > index fdba1c8..9df5f74 100644
>> > --- a/include/configs/sandbox.h
>> > +++ b/include/configs/sandbox.h
>> > @@ -187,7 +187,7 @@
>> >                                         "stderr=serial,lcd\0" \
>> >                                         "ethaddr=00:00:11:22:33:44\0" \
>> >                                         "eth1addr=00:00:11:22:33:45\0" \
>> > -                                       "eth2addr=00:00:11:22:33:46\0" \
>> > +                                       "eth5addr=00:00:11:22:33:46\0" \
>> >                                         "ipaddr=1.2.3.4\0"
>> >  #else
>> >
>> > @@ -196,7 +196,7 @@
>> >                                         "stderr=serial,lcd\0" \
>> >                                         "ethaddr=00:00:11:22:33:44\0" \
>> >                                         "eth1addr=00:00:11:22:33:45\0" \
>> > -                                       "eth2addr=00:00:11:22:33:46\0" \
>> > +                                       "eth5addr=00:00:11:22:33:46\0" \
>> >                                         "ipaddr=1.2.3.4\0"
>> >  #endif
>> >
>> > diff --git a/include/fdtdec.h b/include/fdtdec.h
>> > index 231eed7..e945baa 100644
>> > --- a/include/fdtdec.h
>> > +++ b/include/fdtdec.h
>> > @@ -167,6 +167,7 @@ enum fdt_compat_id {
>> >         COMPAT_INTEL_GMA,               /* Intel Graphics Media
>> > Accelerator */
>> >         COMPAT_AMS_AS3722,              /* AMS AS3722 PMIC */
>> >         COMPAT_INTEL_ICH_SPI,           /* Intel ICH7/9 SPI controller
>> > */
>> > +       COMPAT_ETHERNET,                /* Ethernet devices */
>>
>> SANDBOX_ETHERNET
>
> This is not limited to sandbox.  This is needed for all Ethernet MACs.  Is
> there some other way that I should be identifying with all devices in the
> device tree of a certain class?

Not that I know of. But each Ethernet driver would need its own
compatible string, since otherwise driver model won't use the right
driver.

>
>> >
>> >         COMPAT_COUNT,
>> >  };
>> > diff --git a/include/net.h b/include/net.h
>> > index 11471bd..4e98850 100644
>> > --- a/include/net.h
>> > +++ b/include/net.h
>> > @@ -38,6 +38,8 @@
>> >
>> >  #define PKTALIGN       ARCH_DMA_MINALIGN
>> >
>> > +#define ETH_MAX_DEVS   32
>> > +
>> >  /* IPv4 addresses are always 32 bits in size */
>> >  typedef __be32         IPaddr_t;
>> >
>> > @@ -79,6 +81,8 @@ enum eth_state_t {
>> >  };
>> >
>> >  #ifdef CONFIG_DM_ETH
>> > +#define ETH_ALIAS_ROOT "eth"
>> > +
>> >  struct eth_pdata {
>> >         phys_addr_t iobase;
>> >         unsigned char enetaddr[6];
>> > @@ -96,6 +100,7 @@ struct eth_ops {
>> >  };
>> >
>> >  struct udevice *eth_get_dev(void); /* get the current device */
>> > +struct udevice *eth_get_dev_by_name(const char *devname);
>> >  unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
>> >  int eth_init_state_only(bd_t *bis); /* Set active state */
>> >  void eth_halt_state_only(void); /* Set passive state */
>> > diff --git a/lib/fdtdec.c b/lib/fdtdec.c
>> > index 5bf8f29..33b0a53 100644
>> > --- a/lib/fdtdec.c
>> > +++ b/lib/fdtdec.c
>> > @@ -75,6 +75,7 @@ static const char * const compat_names[COMPAT_COUNT] =
>> > {
>> >         COMPAT(INTEL_GMA, "intel,gma"),
>> >         COMPAT(AMS_AS3722, "ams,as3722"),
>> >         COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
>> > +       COMPAT(ETHERNET, "eth"),
>>
>> sandbox,eth
>
> Again, this is used to identify all Ethernet controllers. Perhaps
> fdtdec_find_aliases_for_id() should not be limiting the alias search to
> those that have a certain "compatible" string?

I think you want 'sandbox,ethernet' here, or similar, but you probably
don't want to use that fdtdec function ultimately. Driver model should
do it all for you.

>
>
>> >  };
>> >
>> >  const char *fdtdec_get_compatible(enum fdt_compat_id id)
>> > diff --git a/net/eth.c b/net/eth.c
>> > index e84b948..762effe 100644
>> > --- a/net/eth.c
>> > +++ b/net/eth.c
>> > @@ -10,11 +10,14 @@
>> >  #include <command.h>
>> >  #include <dm.h>
>> >  #include <dm/device-internal.h>
>> > +#include <fdtdec.h>
>> >  #include <net.h>
>> >  #include <miiphy.h>
>> >  #include <phy.h>
>> >  #include <asm/errno.h>
>> >
>> > +DECLARE_GLOBAL_DATA_PTR;
>> > +
>> >  void eth_parse_enetaddr(const char *addr, uchar *enetaddr)
>> >  {
>> >         char *end;
>> > @@ -121,6 +124,39 @@ static void eth_set_dev(struct udevice *dev)
>> >         uc_priv->current = dev;
>> >  }
>> >
>> > +/*
>> > + * Find the udevice that either has the name passed in as devname or
>> > has an
>> > + * alias named devname.
>> > + */
>> > +struct udevice *eth_get_dev_by_name(const char *devname)
>> > +{
>> > +       int node_list[ETH_MAX_DEVS];
>> > +       int count;
>> > +       int seq;
>> > +       char *endp = NULL;
>> > +       const char *true_name = devname;
>> > +       struct udevice *it;
>> > +       struct uclass *uc;
>> > +
>> > +       count = fdtdec_find_aliases_for_id(gd->fdt_blob, ETH_ALIAS_ROOT,
>> > +                                          COMPAT_ETHERNET, node_list,
>> > +                                          ETH_MAX_DEVS);
>> > +
>> > +       seq = simple_strtoul(devname + strlen(ETH_ALIAS_ROOT), &endp,
>> > 10);
>> > +
>> > +       if (endp > devname + strlen(ETH_ALIAS_ROOT) && count > seq &&
>> > +           node_list[seq])
>> > +               true_name = fdt_get_name(gd->fdt_blob, node_list[seq],
>> > NULL);
>> > +
>> > +       uclass_get(UCLASS_ETH, &uc);
>> > +       uclass_foreach_dev(it, uc) {
>> > +               if (strcmp(it->name, true_name) == 0 || it->seq == seq)
>> > +                       return it;
>> > +       }
>>
>> Is it possible for eth_get_dev_by_name() to just look up the name
>> provided?
>>
>> You already have this:
>>
>> uclass_foreach_dev(it, uc) {
>> if (strcmp(it->name, true_name) == 0 || it->seq == seq)
>> return it;
>> }
>>
>> It feels like you just need to through through the devices in the
>> uclass and strcmp(dev->name, find_name).
>
> That works fine for looking up the exact name, but that's not the point of
> this patch.  Such code was already there and you can see it below.

OK

>
>> I guess I am suffering because I don't understand what you are trying
>> to do, so am not sure if there is an easier way with driver model. We
>> really should not go looking in the device tree in
>> eth_get_dev_by_name()...driver is responsible for parsing that.
>
> Perhaps this is a limitation of fdtdec_find_aliases_for_id().  I need to be
> able to look up the device based on its alias.  It doesn't seem to me that
> I'm digging around in the device tree at random places that should be done
> by the driver.  I'm simply wanting to ask the device tree what the alias
> that the user passed in is pointing at.  Potentially is it not an alias, but
> a full name.  Either way, I want to return the udevice.

If you want to know the device's number, use dev->req_seq. This will
hold the alias number. If it is -1 then the device is not mentioned in
/aliases in the device tree.

But please see if you can use the existing driver model features to
find devices, their numbers, etc.

>
>
>> > +
>> > +       return NULL;
>> > +}
>> > +
>> >  unsigned char *eth_get_ethaddr(void)
>> >  {
>> >         struct eth_pdata *pdata;
>> > @@ -396,6 +432,7 @@ UCLASS_DRIVER(eth) = {
>> >         .init           = eth_uclass_init,
>> >         .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
>> >         .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
>> > +       .flags          = DM_UC_FLAG_SEQ_ALIAS,
>> >  };
>> >  #endif
>> >
>> > @@ -428,6 +465,11 @@ static void eth_set_current_to_next(void)
>> >         eth_current = eth_current->next;
>> >  }
>> >
>> > +static void eth_set_dev(struct eth_device *dev)
>> > +{
>> > +       eth_current = dev;
>> > +}
>> > +
>> >  struct eth_device *eth_get_dev_by_name(const char *devname)
>> >  {
>> >         struct eth_device *dev, *target_dev;
>> > @@ -844,7 +886,6 @@ void eth_set_current(void)
>> >  {
>> >         static char *act;
>> >         static int  env_changed_id;
>> > -       void *old_current;
>> >         int     env_id;
>> >
>> >         env_id = get_env_id();
>> > @@ -852,14 +893,8 @@ void eth_set_current(void)
>> >                 act = getenv("ethact");
>> >                 env_changed_id = env_id;
>> >         }
>> > -       if (act != NULL) {
>> > -               old_current = eth_get_dev();
>> > -               do {
>> > -                       if (strcmp(eth_get_name(), act) == 0)
>> > -                               return;
>> > -                       eth_set_current_to_next();
>> > -               } while (old_current != eth_get_dev());
>> > -       }
>
> This is the simple compare that is being replaced.
>
>> > +       if (act != NULL)
>> > +               eth_set_dev(eth_get_dev_by_name(act));
>> >
>> >         eth_current_changed();
>> >  }
>> > diff --git a/test/dm/eth.c b/test/dm/eth.c
>> > index 2b29fa2..c0a8ab5 100644
>> > --- a/test/dm/eth.c
>> > +++ b/test/dm/eth.c
>> > @@ -37,3 +37,28 @@ static int dm_test_eth(struct dm_test_state *dms)
>> >  }
>> >
>> >  DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
>> > +
>> > +static int dm_test_eth_alias(struct dm_test_state *dms)
>> > +{
>> > +       NetPingIP = string_to_ip("1.1.2.2");
>> > +       setenv("ethact", "eth0");
>> > +       ut_assertok(NetLoop(PING));
>> > +       ut_asserteq_str("eth at 10002000", getenv("ethact"));
>> > +
>> > +       setenv("ethact", "eth1");
>> > +       ut_assertok(NetLoop(PING));
>> > +       ut_asserteq_str("eth at 10004000", getenv("ethact"));
>> > +
>> > +       /* Expected to fail since eth2 is not defined in the device tree
>> > */
>> > +       setenv("ethact", "eth2");
>> > +       ut_asserteq(-1, NetLoop(PING));
>> > +       ut_asserteq_ptr(NULL, getenv("ethact"));
>> > +
>> > +       setenv("ethact", "eth5");
>> > +       ut_assertok(NetLoop(PING));
>> > +       ut_asserteq_str("eth at 10003000", getenv("ethact"));
>> > +
>> > +       return 0;
>> > +}
>> > +
>> > +DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
>> > diff --git a/test/dm/test.dts b/test/dm/test.dts
>> > index 2f68cdf..c5008c3 100644
>> > --- a/test/dm/test.dts
>> > +++ b/test/dm/test.dts
>> > @@ -17,6 +17,8 @@
>> >                 testfdt3 = "/b-test";
>> >                 testfdt5 = "/some-bus/c-test at 5";
>> >                 testfdt8 = "/a-test";
>> > +               eth0 = "/eth at 10002000";
>> > +               eth5 = &eth_5;
>> >         };
>> >
>> >         uart0: serial {
>> > @@ -150,19 +152,19 @@
>> >         };
>> >
>> >         eth at 10002000 {
>> > -               compatible = "sandbox,eth";
>> > +               compatible = "sandbox,eth", "eth";
>> >                 reg = <0x10002000 0x1000>;
>> >                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
>> >         };
>> >
>> > -       eth at 10003000 {
>> > -               compatible = "sandbox,eth";
>> > +       eth_5: eth at 10003000 {
>> > +               compatible = "sandbox,eth", "eth";
>> >                 reg = <0x10003000 0x1000>;
>> >                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
>> >         };
>> >
>> >         eth at 10004000 {
>> > -               compatible = "sandbox,eth";
>> > +               compatible = "sandbox,eth", "eth";
>> >                 reg = <0x10004000 0x1000>;
>> >                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x22>;
>> >         };
>> > --
>> > 1.7.11.5

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 14/14] dm: eth: Add a bridge to a real network for sandbox
  2015-02-17  5:16         ` Joe Hershberger
@ 2015-02-18  5:02           ` Simon Glass
  2015-02-19 23:44             ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-02-18  5:02 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 16 February 2015 at 22:16, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> Hi Simon,
>
> On Sun, Feb 15, 2015 at 9:50 AM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com>
>> wrote:
>> > Implement a bridge between u-boot's network stack and Linux's raw packet
>> > API allowing the sandbox to send and receive packets using the host
>> > machine's network interface.
>> >
>> > This raw Ethernet API requires elevated privileges.  You can either run
>> > as root, or you can add the capability needed like so:
>> >
>> > sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot
>>
>> Can you add a note about thsi in README.sandbox? This seems like a
>> major new feature. It was talked about a few years ago when sandbox
>> was first created.
>
> OK.  Can you maybe point me to that conversation so I can understand what
> was anticipated potentially covering more of what was expected.

All I could find was this:

http://permalink.gmane.org/gmane.comp.boot-loaders.u-boot/108687

>
>> >
>> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>> >
>> > ---
>> >
>> > Changes in v3:
>> > -Made the os raw packet support for sandbox eth build and work.
>> >
>> > Changes in v2:
>> > -Added the raw packet proof-of-concept patch.
>> >
>> >  arch/sandbox/dts/sandbox.dts              |   6 ++
>> >  arch/sandbox/include/asm/sandbox-raw-os.h |  16 ++++
>> >  drivers/net/Makefile                      |  11 +++
>> >  drivers/net/sandbox-raw-os.c              | 105
>> > ++++++++++++++++++++++++
>> >  drivers/net/sandbox-raw.c                 | 128
>> > ++++++++++++++++++++++++++++++
>> >  include/configs/sandbox.h                 |   1 +
>> >  6 files changed, 267 insertions(+)
>> >  create mode 100644 arch/sandbox/include/asm/sandbox-raw-os.h
>> >  create mode 100644 drivers/net/sandbox-raw-os.c
>> >  create mode 100644 drivers/net/sandbox-raw.c
>> >
>> > diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
>> > index ba635e8..13bd6c2 100644
>> > --- a/arch/sandbox/dts/sandbox.dts
>> > +++ b/arch/sandbox/dts/sandbox.dts
>> > @@ -188,4 +188,10 @@
>> >                 reg = <0x10002000 0x1000>;
>> >                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
>> >         };
>> > +
>> > +       eth at 80000000 {
>> > +               compatible = "sandbox,eth,raw";
>>
>> We normally have "vendor,device", so maybe "sandbox,raw-eth"
>
> OK
>
>> > +               reg = <0x80000000 0x1000>;
>> > +               host-raw-interface = "eth0";
>> > +       };
>> >  };
>> > diff --git a/arch/sandbox/include/asm/sandbox-raw-os.h
>> > b/arch/sandbox/include/asm/sandbox-raw-os.h
>> > new file mode 100644
>> > index 0000000..4e5d418
>> > --- /dev/null
>> > +++ b/arch/sandbox/include/asm/sandbox-raw-os.h
>> > @@ -0,0 +1,16 @@
>> > +/*
>> > + * Copyright (c) 2015 National Instruments
>> > + *
>> > + * (C) Copyright 2015
>> > + * Joe Hershberger <joe.hershberger@ni.com>
>> > + *
>> > + * SPDX-License-Identifier:    GPL-2.0+
>> > + */
>> > +
>> > +#pragma once
>>
>> We use #ifdef for this in U-Boot at present. I'm not sure why -
>> perhaps compatibility?
>
> OK
>
>> > +
>> > +int sandbox_raw_init(int *sd, void **devp, const char *ifname,
>> > +                    unsigned char *ethmac);
>> > +int sandbox_raw_send(void *packet, int length, int sd, void *device);
>> > +int sandbox_raw_recv(void *packet, int *length, int sd, void *device);
>> > +void sandbox_raw_halt(int *sd, void **devp);
>>
>> Function comments, also what is 'device'?
>
> Comments about what?  These are just the functions that implement the
> Ethernet driver ops.  Is it not sufficient to document the driver ops
> themselves (as you requested in the other patch)?

Well they seem to have different parameters:

- what is 'device'?
- what is'sd''?

I think these warrant comments.

>
>> > diff --git a/drivers/net/Makefile b/drivers/net/Makefile
>> > index 15dc431..39975b3 100644
>> > --- a/drivers/net/Makefile
>> > +++ b/drivers/net/Makefile
>> > @@ -51,6 +51,8 @@ obj-$(CONFIG_PCNET) += pcnet.o
>> >  obj-$(CONFIG_RTL8139) += rtl8139.o
>> >  obj-$(CONFIG_RTL8169) += rtl8169.o
>> >  obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
>> > +obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o
>> > +obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw-os.o
>> >  obj-$(CONFIG_SH_ETHER) += sh_eth.o
>> >  obj-$(CONFIG_SMC91111) += smc91111.o
>> >  obj-$(CONFIG_SMC911X) += smc911x.o
>> > @@ -68,3 +70,12 @@ obj-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o
>> > xilinx_ll_temac_mdio.o \
>> >  obj-$(CONFIG_ZYNQ_GEM) += zynq_gem.o
>> >  obj-$(CONFIG_FSL_MC_ENET) += fsl_mc/
>> >  obj-$(CONFIG_VSC9953) += vsc9953.o
>> > +
>> > +# sandbox-raw-os.c is built in the system env, so needs standard
>> > includes
>> > +# CFLAGS_REMOVE_sandbox-raw-os.o cannot be used to drop header include
>> > path
>> > +quiet_cmd_cc_sandbox-raw-os.o = CC $(quiet_modtag)  $@
>> > +cmd_cc_sandbox-raw-os.o = $(CC) $(filter-out -nostdinc, \
>> > +       $(patsubst -I%,-idirafter%,$(c_flags))) -c -o $@ lt;
>> > +
>> > +$(obj)/sandbox-raw-os.o: $(src)/sandbox-raw-os.c FORCE
>> > +       $(call if_changed_dep,cc_sandbox-raw-os.o)
>>
>> Can we please move this to the same directory as os.c, so that all the
>> OS-specific stuff is in one place.
>
> OK
>
>
>> > diff --git a/drivers/net/sandbox-raw-os.c b/drivers/net/sandbox-raw-os.c
>> > new file mode 100644
>> > index 0000000..43fae60
>> > --- /dev/null
>> > +++ b/drivers/net/sandbox-raw-os.c
>> > @@ -0,0 +1,105 @@
>> > +/*
>> > + * Copyright (c) 2015 National Instruments
>> > + *
>> > + * (C) Copyright 2015
>> > + * Joe Hershberger <joe.hershberger@ni.com>
>> > + *
>> > + * SPDX-License-Identifier:    GPL-2.0+
>> > + */
>> > +
>> > +#include <errno.h>
>> > +#include <net/if.h>
>> > +#include <netinet/in.h>
>> > +#include <stdio.h>
>> > +#include <stdlib.h>
>> > +#include <string.h>
>> > +#include <sys/types.h>
>> > +#include <sys/ioctl.h>
>> > +#include <sys/socket.h>
>> > +#include <unistd.h>
>> > +
>> > +#include <linux/if_ether.h>
>> > +#include <linux/if_packet.h>
>> > +
>> > +int sandbox_raw_init(int *sd, void **devp, const char *ifname,
>> > +                    unsigned char *ethmac)
>> > +{
>> > +       int tempsd = 0;
>> > +       struct ifreq ifr;
>> > +
>> > +       strcpy(ifr.ifr_name, ifname);
>> > +       ifr.ifr_addr.sa_family = AF_INET;
>> > +       memset(ethmac, 0, 6);
>> > +       tempsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
>> > +       if (tempsd < 0) {
>> > +               printf("Failed to open socket: %d %s\n", errno,
>> > +                      strerror(errno));
>> > +               return 1;
>>
>> How about:
>>
>>    return -errno
>>
>> here? That is what U-Boot tends to use now.
>
> OK
>
>
>> > +       }
>> > +       if (ioctl(tempsd, SIOCGIFHWADDR, &ifr) < 0) {
>> > +               printf("Failed to call ioctl: %s\n", strerror(errno));
>> > +               close(tempsd);
>> > +               return 1;
>> > +       }
>> > +       /*
>> > +        * This only works if the MAC address is overridden with the
>> > actual MAC
>> > +        * address of the interface being used.
>> > +        */
>> > +       memcpy(ethmac, ifr.ifr_hwaddr.sa_data, 6 * sizeof(uint8_t));
>> > +       close(tempsd);
>> > +
>> > +       *devp = malloc(sizeof(struct sockaddr_ll));
>> > +       struct sockaddr_ll *device = *devp;
>> > +       memset(device, 0, sizeof(struct sockaddr_ll));
>> > +       device->sll_ifindex = if_nametoindex(ifname);
>> > +       device->sll_family = AF_PACKET;
>> > +       memcpy(device->sll_addr, ethmac, 6);
>> > +       device->sll_halen = htons(6);
>> > +
>> > +       *sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
>> > +       setsockopt(*sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
>> > +                  strlen(ifname) + 1);
>> > +
>> > +       return 0;
>> > +}
>> > +
>> > +int sandbox_raw_send(void *packet, int length, int sd, void *device)
>> > +{
>> > +       int retval;
>> > +
>> > +       if (!sd || !device)
>> > +               return -EINVAL;
>> > +       retval = sendto(sd, packet, length, 0,
>> > +                  (struct sockaddr *)device, sizeof(struct
>> > sockaddr_ll));
>> > +       if (retval < 0)
>> > +               printf("Failed to send packet: %d %s\n", errno,
>> > +                      strerror(errno));
>> > +       return retval;
>> > +}
>> > +
>> > +int sandbox_raw_recv(void *packet, int *length, int sd, void *device)
>> > +{
>> > +       int retval;
>> > +       int saddr_size;
>> > +
>> > +       if (!sd || !device)
>> > +               return -EINVAL;
>> > +       saddr_size = sizeof(struct sockaddr);
>> > +       retval = recvfrom(sd, packet, 1536, 0, (struct sockaddr
>> > *)device,
>> > +                         (socklen_t *)&saddr_size);
>> > +       *length = 0;
>> > +       if (retval > 0) {
>> > +               *length = retval;
>> > +               return 0;
>> > +       }
>> > +
>> > +       return retval;
>> > +}
>> > +
>> > +void sandbox_raw_halt(int *sd, void **devp)
>> > +{
>> > +       free((struct sockaddr_ll *)*devp);
>> > +       *devp = NULL;
>> > +       close(*sd);
>> > +       *sd = -1;
>> > +}
>> > diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
>> > new file mode 100644
>> > index 0000000..90e462a
>> > --- /dev/null
>> > +++ b/drivers/net/sandbox-raw.c
>> > @@ -0,0 +1,128 @@
>> > +/*
>> > + * Copyright (c) 2015 National Instruments
>> > + *
>> > + * (C) Copyright 2015
>> > + * Joe Hershberger <joe.hershberger@ni.com>
>> > + *
>> > + * SPDX-License-Identifier:    GPL-2.0+
>> > + */
>> > +
>> > +#include <asm/sandbox-raw-os.h>
>> > +#include <common.h>
>> > +#include <dm.h>
>> > +#include <fdtdec.h>
>> > +#include <malloc.h>
>> > +#include <net.h>
>> > +
>> > +DECLARE_GLOBAL_DATA_PTR;
>> > +
>> > +struct eth_sandbox_raw_priv {
>> > +       int sd;
>> > +       void *device;
>>
>> comments
>>
>> > +};
>> > +
>> > +static int sb_eth_raw_init(struct udevice *dev, bd_t *bis)
>> > +{
>> > +       debug("eth_sandbox_raw: Init\n");
>>
>> Put after declarations (perhaps removing code from decls if you like)
>> in each case.
>>
>> > +
>> > +       struct eth_sandbox_raw_priv *priv = dev->priv;
>>
>> add blank line
>>
>> > +       if (!priv)
>> > +               return -EINVAL;
>>
>> As elsewhere I don't understand why this is needed
>>
>> > +
>> > +       struct eth_pdata *pdata = dev->platdata;
>> > +       int retval;
>> > +       const char *interface = fdt_getprop(gd->fdt_blob,
>> > dev->of_offset,
>> > +                                           "host-raw-interface", NULL);
>> > +
>> > +       retval = sandbox_raw_init(&priv->sd, &priv->device, interface,
>> > +                                 pdata->enetaddr);
>> > +
>> > +       return retval;
>> > +}
>> > +
>> > +static int sb_eth_raw_send(struct udevice *dev, void *packet, int
>> > length)
>> > +{
>> > +       debug("eth_sandbox_raw: Send packet %d\n", length);
>> > +
>> > +       struct eth_sandbox_raw_priv *priv = dev->priv;
>>
>> dev_get_priv(dev) in each case
>>
>> > +
>> > +       return sandbox_raw_send(packet, length, priv->sd, priv->device);
>> > +}
>> > +
>> > +static int sb_eth_raw_recv(struct udevice *dev)
>> > +{
>> > +       struct eth_sandbox_raw_priv *priv = dev->priv;
>> > +
>>
>> remove blank line
>>
>> > +       int retval;
>> > +       uchar buffer[PKTSIZE];
>> > +       int length;
>> > +
>> > +       if (!priv)
>> > +               return 0;
>> > +       retval = sandbox_raw_recv(buffer, &length, priv->sd,
>> > priv->device);
>> > +       if (!retval && length) {
>> > +               debug("eth_sandbox_raw: received packet %d\n",
>> > +                     length);
>> > +               NetReceive(buffer, length);
>> > +       }
>> > +       return 0;
>> > +}
>> > +
>> > +static void sb_eth_raw_halt(struct udevice *dev)
>> > +{
>> > +       debug("eth_sandbox_raw: Halt\n");
>> > +
>> > +       struct eth_sandbox_raw_priv *priv = dev->priv;
>> > +
>> > +       if (!priv)
>> > +               return;
>> > +       sandbox_raw_halt(&priv->sd, &priv->device);
>> > +}
>> > +
>> > +static int sb_eth_raw_write_hwaddr(struct udevice *dev)
>> > +{
>> > +       struct eth_pdata *pdata = dev->platdata;
>> > +
>> > +       debug("eth_sandbox_raw %s: Write HW ADDR - %pM\n", dev->name,
>> > +             pdata->enetaddr);
>> > +       return 0;
>> > +}
>> > +
>> > +static const struct eth_ops sb_eth_raw_ops = {
>> > +       .init                   = sb_eth_raw_init,
>> > +       .send                   = sb_eth_raw_send,
>> > +       .recv                   = sb_eth_raw_recv,
>> > +       .halt                   = sb_eth_raw_halt,
>> > +       .write_hwaddr           = sb_eth_raw_write_hwaddr,
>> > +};
>> > +
>> > +static int sb_eth_raw_remove(struct udevice *dev)
>> > +{
>> > +       return 0;
>> > +}
>> > +
>> > +#ifdef CONFIG_OF_CONTROL
>>
>> This is always defined for sandbox.
>
> I figured it was a good pattern to use in general, but if you want me to
> prune it out of sandbox-only code I can.

I think so, it is pointless really and just clutters the code. I can't
imagine sandbox being built without device tree (famous last words!)

>
>> > +static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev)
>> > +{
>> > +       struct eth_pdata *pdata = dev->platdata;
>> > +
>> > +       pdata->iobase = fdtdec_get_addr(gd->fdt_blob, dev->of_offset,
>> > "reg");
>>
>> dev_get_addr() is now available in dm/master if you prefer to use that.
>
> OK
>
>
>> > +       return 0;
>> > +}
>> > +
>> > +static const struct udevice_id sb_eth_raw_ids[] = {
>> > +       { .compatible = "sandbox,eth,raw" },
>> > +       { }
>> > +};
>> > +#endif
>> > +
>> > +U_BOOT_DRIVER(eth_sandbox_raw) = {
>> > +       .name   = "eth_sandbox_raw",
>> > +       .id     = UCLASS_ETH,
>> > +       .of_match = of_match_ptr(sb_eth_raw_ids),
>> > +       .ofdata_to_platdata =
>> > of_match_ptr(sb_eth_raw_ofdata_to_platdata),
>> > +       .remove = sb_eth_raw_remove,
>> > +       .ops    = &sb_eth_raw_ops,
>> > +       .priv_auto_alloc_size = sizeof(struct eth_sandbox_raw_priv),
>> > +       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
>> > +};
>> > diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
>> > index 9df5f74..7afa3d2 100644
>> > --- a/include/configs/sandbox.h
>> > +++ b/include/configs/sandbox.h
>> > @@ -141,6 +141,7 @@
>> >
>> >  #define CONFIG_DM_ETH
>> >  #define CONFIG_ETH_SANDBOX
>> > +#define CONFIG_ETH_SANDBOX_RAW
>>
>> These should go in Kconfig. Could be a follow-on patch if that is easier.
>
> OK
>
>> >  #define CONFIG_CMD_PING
>> >
>> >  #define CONFIG_CMD_HASH
>> > --
>> > 1.7.11.5
>> >

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 14/14] dm: eth: Add a bridge to a real network for sandbox
  2015-02-18  5:02           ` Simon Glass
@ 2015-02-19 23:44             ` Joe Hershberger
  2015-02-20 19:33               ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-19 23:44 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Tue, Feb 17, 2015 at 11:02 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 16 February 2015 at 22:16, Joe Hershberger <joe.hershberger@gmail.com>
wrote:
> > Hi Simon,
> >
> > On Sun, Feb 15, 2015 at 9:50 AM, Simon Glass <sjg@chromium.org> wrote:
> >>
> >> Hi Joe,
> >>
> >> On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com>
> >> wrote:
> >> > Implement a bridge between u-boot's network stack and Linux's raw
packet
> >> > API allowing the sandbox to send and receive packets using the host
> >> > machine's network interface.
> >> >
> >> > This raw Ethernet API requires elevated privileges.  You can either
run
> >> > as root, or you can add the capability needed like so:
> >> >
> >> > sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot
> >>
> >> Can you add a note about thsi in README.sandbox? This seems like a
> >> major new feature. It was talked about a few years ago when sandbox
> >> was first created.
> >
> > OK.  Can you maybe point me to that conversation so I can understand
what
> > was anticipated potentially covering more of what was expected.
>
> All I could find was this:
>
> http://permalink.gmane.org/gmane.comp.boot-loaders.u-boot/108687

I dug around and found this too:

http://comments.gmane.org/gmane.comp.boot-loaders.u-boot/118685

It seems it was more complicated to setup, but may have other benefits
(such as being more likely to be able to change MAC address settings
eventually).

[snip]

Cheers,
-Joe

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v3 14/14] dm: eth: Add a bridge to a real network for sandbox
  2015-02-19 23:44             ` Joe Hershberger
@ 2015-02-20 19:33               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-20 19:33 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 19 February 2015 at 16:44, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> Hi Simon,
>
> On Tue, Feb 17, 2015 at 11:02 PM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 16 February 2015 at 22:16, Joe Hershberger <joe.hershberger@gmail.com>
>> wrote:
>> > Hi Simon,
>> >
>> > On Sun, Feb 15, 2015 at 9:50 AM, Simon Glass <sjg@chromium.org> wrote:
>> >>
>> >> Hi Joe,
>> >>
>> >> On 10 February 2015 at 18:30, Joe Hershberger <joe.hershberger@ni.com>
>> >> wrote:
>> >> > Implement a bridge between u-boot's network stack and Linux's raw
>> >> > packet
>> >> > API allowing the sandbox to send and receive packets using the host
>> >> > machine's network interface.
>> >> >
>> >> > This raw Ethernet API requires elevated privileges.  You can either
>> >> > run
>> >> > as root, or you can add the capability needed like so:
>> >> >
>> >> > sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot
>> >>
>> >> Can you add a note about thsi in README.sandbox? This seems like a
>> >> major new feature. It was talked about a few years ago when sandbox
>> >> was first created.
>> >
>> > OK.  Can you maybe point me to that conversation so I can understand
>> > what
>> > was anticipated potentially covering more of what was expected.
>>
>> All I could find was this:
>>
>> http://permalink.gmane.org/gmane.comp.boot-loaders.u-boot/108687
>
> I dug around and found this too:
>
> http://comments.gmane.org/gmane.comp.boot-loaders.u-boot/118685
>
> It seems it was more complicated to setup, but may have other benefits (such
> as being more likely to be able to change MAC address settings eventually).

Ah yes that is it.

I think your method is simpler and useful, and therefore generally
better as a starting point. The TAP idea if we have it should be a
separate feature. I really like that to, but it requires setup as you
say.

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack
  2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
                       ` (13 preceding siblings ...)
  2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 14/14] dm: eth: Add a bridge to a real network for sandbox Joe Hershberger
@ 2015-02-25  0:02     ` Joe Hershberger
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 01/23] test: dm: Reorder the objects to build Joe Hershberger
                         ` (24 more replies)
  14 siblings, 25 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

Add support for the Ethernet MAC controllers.  Phy support will come later.

I am still leaving this as an RFC because I plan to add real board support
before committing to mainline. When it is acceptable / accepted, I will push it
as a dev branch on the net repo until a real device is supported. If any
required changes are discovered in the process of supporting a real device I
will send those as a patch against the dev branch, but then squash before
sending the non-RFC version. I plan to rebase when the merge window opens
anyway.

If desired, let me know which of the non-DM related prerequisite patches are
wanted for this release.

I've added unit tests to verify functionality.

There is an additional driver for sandbox that bridges to the RAW
Ethernet API in Linux which lets you test with real traffic. It now
supports localhost as well (the 'lo' interface).

Changes in v4:
-New to v4
-Fix compile regression in !DM_ETH case
-New to v4
-New to v4
-New to v4
-New to v4
-New to v4
-Redo the seq / probe implementation
--Don't prevent eth_initialize on driver model
--Use eth_initialize to probe all devices and write_hwaddr
--Look up MAC address in post-probe
--Include ethprime handling in eth_initialize
--If current == NULL, always check if there is a device available in eth_get_dev
--Move env init call from uclass init to eth_initialize
--Print the alias in eth_initialize
-Stop handling selecting a new "current" in pre-unbind as it will now work itself out by clearing the pointer
-Change -1 returns to error constants
-Remove bd_t *bis from dm eth_ops init function
-Add documentation to the structures
-Add a helper function for eth_uclass_priv
-Change puts to printf
-Add eth_get_ops helper
-Rename init() to start() in ops
-Rename halt() to stop() in ops
-Remove checks for driver==NULL
-Remove priv pointer in per-device priv struct (drivers already get their own directly from DM)
-Cleaned up sandbox EXTRA_ENV define
-Moved config to Kconfig
-Removed checks on priv != NULL and added protection in uclass instead
-Use only the seq from DM to find aliases
-Load from ethprime on eth_initialize()
-Added testing for ethrotate
-Add ability to disable ping reply in sandbox eth driver
-Updated expected behavior based on changes to the NetLoop
-Added comments to README.sandbox
-Use accessors for platdata and priv
-Add comments to priv struct definition
-Move os file to arch
-Cleanup var definition order
-Moved config to Kconfig
-Clean up the interface to sandbox's eth-raw-os by passing priv to raw-os
-Fixed the MAC address limitation (now all traffic uses MAC address from env)
-New to v4
-Added support for the 'lo' network interface

Changes in v3:
-Reorder dm test makefile
-Move the get_dev_by_* protos to also be !DM_ETH like the impl
-Correct the pre_unbind logic
-Correct failure chaining from bind to probe to init
--Fail init if not activated
--Fail probe if ethaddr not set
-Update ethaddr from env unconditionally on init
-Use set current to select the current device regardless of the previous selection
-Allow current eth dev to be NULL
-Fixed blank line formatting for variable declaration
-Added 2 more ethaddr to sandbox
-Print which device in the debug write hwaddr
-Prevent a crash if memory is not allocated
-Added dm eth testing
-Added support for aliases
-Added support for ethprime
-Added testing for netretry
-Made the os raw packet support for sandbox eth build and work.

Changes in v2:
-Updated comments
-Removed extra parentheses
-Changed eth_uclass_priv local var names to be uc_priv
-Update error codes
-Cause an invalid name to fail binding
-Rebase on top of dm/master
-Stop maintaining our own index and use DM seq now that it works for our needs
-Move the hwaddr to platdata so that its memory is allocated at bind when we need it
-Prevent device from being probed before used by a command (i.e. before eth_init()).
-Change printfs to debug in sandbox driver
-Remove unused priv struct for sandbox driver
-Change printfs to debug in sandbox driver
-Move static data to priv
-Move fake hwaddr to the device tree
-Added the raw packet proof-of-concept patch.

Joe Hershberger (23):
  test: dm: Reorder the objects to build
  common: Make sure arch-specific map_sysmem() is defined
  net: Provide a function to get the current MAC address
  net: Rename helper function to be more clear
  net: Remove unneeded "extern" in net.h
  net: Refactor in preparation for driver model
  net: Change return codes from net/eth.c to use errorno constants
  net: Use int instead of u8 for boolean flag
  net: Remove the bd* parameter from net stack functions
  net: Make netretry actually do something
  net: Access mapped physmem in net functions
  dm: eth: Add basic driver model support to Ethernet stack
  sandbox: eth: Add network support to sandbox
  sandbox: eth: Add ARP and PING response to sandbox driver
  test: dm: eth: Add tests for the eth dm implementation
  dm: eth: Add support for aliases
  dm: eth: Add support for ethprime env var
  test: dm: eth: Add testing for ethrotate env var
  sandbox: eth: Add ability to disable ping reply in sandbox eth driver
  test: dm: net: Add a test of the netretry behavior
  sandbox: eth: Add a bridge to a real network for sandbox
  sandbox: Enable DHCP and IP defrag
  sandbox: eth: Add support for using the 'lo' interface

 arch/mips/mach-au1x00/au1x00_eth.c    |   2 +-
 arch/powerpc/cpu/mpc8260/ether_fcc.c  |   2 +-
 arch/powerpc/cpu/mpc85xx/ether_fcc.c  |   2 +-
 arch/powerpc/cpu/mpc8xx/scc.c         |   2 +-
 arch/sandbox/Kconfig                  |  12 +
 arch/sandbox/cpu/Makefile             |  10 +
 arch/sandbox/cpu/eth-raw-os.c         | 198 +++++++++++++
 arch/sandbox/dts/sandbox.dts          |  21 ++
 arch/sandbox/include/asm/eth-raw-os.h |  40 +++
 board/sandbox/README.sandbox          |  17 +-
 common/board_r.c                      |   2 +-
 common/cmd_bdinfo.c                   |   2 +
 drivers/net/Kconfig                   |  28 ++
 drivers/net/Makefile                  |   2 +
 drivers/net/netconsole.c              |   4 +-
 drivers/net/sandbox-raw.c             | 163 +++++++++++
 drivers/net/sandbox.c                 | 200 +++++++++++++
 include/common.h                      |   4 +-
 include/configs/sandbox.h             |  25 +-
 include/dm/uclass-id.h                |   1 +
 include/net.h                         | 187 ++++++++----
 net/eth.c                             | 521 +++++++++++++++++++++++++++++-----
 net/net.c                             |  17 +-
 net/nfs.c                             |   2 +-
 net/tftp.c                            |   2 +-
 test/dm/Makefile                      |   5 +-
 test/dm/eth.c                         | 129 +++++++++
 test/dm/test.dts                      |  20 ++
 28 files changed, 1466 insertions(+), 154 deletions(-)
 create mode 100644 arch/sandbox/cpu/eth-raw-os.c
 create mode 100644 arch/sandbox/include/asm/eth-raw-os.h
 create mode 100644 drivers/net/sandbox-raw.c
 create mode 100644 drivers/net/sandbox.c
 create mode 100644 test/dm/eth.c

-- 
1.7.11.5

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 01/23] test: dm: Reorder the objects to build
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 02/23] common: Make sure arch-specific map_sysmem() is defined Joe Hershberger
                         ` (23 subsequent siblings)
  24 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Acked-by: Simon Glass <sjg@chromium.org>

---

Changes in v4: None
Changes in v3:
-Reorder dm test makefile

Changes in v2: None

 test/dm/Makefile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/dm/Makefile b/test/dm/Makefile
index 612aa95..1d9148f 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -18,7 +18,7 @@ obj-$(CONFIG_DM_TEST) += core.o
 obj-$(CONFIG_DM_TEST) += ut.o
 ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_DM_GPIO) += gpio.o
-obj-$(CONFIG_DM_SPI) += spi.o
-obj-$(CONFIG_DM_SPI_FLASH) += sf.o
 obj-$(CONFIG_DM_I2C) += i2c.o
+obj-$(CONFIG_DM_SPI_FLASH) += sf.o
+obj-$(CONFIG_DM_SPI) += spi.o
 endif
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 02/23] common: Make sure arch-specific map_sysmem() is defined
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 01/23] test: dm: Reorder the objects to build Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-03-01 18:07         ` Simon Glass
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 03/23] net: Provide a function to get the current MAC address Joe Hershberger
                         ` (22 subsequent siblings)
  24 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

In the case where the arch defines a custom map_sysmem(), make sure that
including just common.h is sufficient to have these functions as they
are when the arch does not override it.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 include/common.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/include/common.h b/include/common.h
index 77c55c6..6510efc 100644
--- a/include/common.h
+++ b/include/common.h
@@ -846,7 +846,9 @@ int cpu_release(int nr, int argc, char * const argv[]);
 #endif
 
 /* Define a null map_sysmem() if the architecture doesn't use it */
-# ifndef CONFIG_ARCH_MAP_SYSMEM
+# ifdef CONFIG_ARCH_MAP_SYSMEM
+#include <asm/io.h>
+# else
 static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
 {
 	return (void *)(uintptr_t)paddr;
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 03/23] net: Provide a function to get the current MAC address
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 01/23] test: dm: Reorder the objects to build Joe Hershberger
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 02/23] common: Make sure arch-specific map_sysmem() is defined Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 04/23] net: Rename helper function to be more clear Joe Hershberger
                         ` (21 subsequent siblings)
  24 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

The current implementation exposes the eth_device struct to code that
needs to access the MAC address.  Add a wrapper function for this to
abstract away the pointer for this operation.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 arch/mips/mach-au1x00/au1x00_eth.c   | 2 +-
 arch/powerpc/cpu/mpc8260/ether_fcc.c | 2 +-
 arch/powerpc/cpu/mpc85xx/ether_fcc.c | 2 +-
 arch/powerpc/cpu/mpc8xx/scc.c        | 2 +-
 include/net.h                        | 8 ++++++++
 net/net.c                            | 2 +-
 6 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/arch/mips/mach-au1x00/au1x00_eth.c b/arch/mips/mach-au1x00/au1x00_eth.c
index 39c5b6b..a47f088 100644
--- a/arch/mips/mach-au1x00/au1x00_eth.c
+++ b/arch/mips/mach-au1x00/au1x00_eth.c
@@ -238,7 +238,7 @@ static int au1x00_init(struct eth_device* dev, bd_t * bd){
 	}
 
 	/* Put mac addr in little endian */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
 	*mac_addr_high	=	(ea[5] <<  8) | (ea[4]	    ) ;
 	*mac_addr_low	=	(ea[3] << 24) | (ea[2] << 16) |
 		(ea[1] <<  8) | (ea[0]	    ) ;
diff --git a/arch/powerpc/cpu/mpc8260/ether_fcc.c b/arch/powerpc/cpu/mpc8260/ether_fcc.c
index f9f15b5..f777ba1 100644
--- a/arch/powerpc/cpu/mpc8260/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc8260/ether_fcc.c
@@ -299,7 +299,7 @@ static int fec_init(struct eth_device* dev, bd_t *bis)
      * it unique by setting a few bits in the upper byte of the
      * non-static part of the address.
      */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
     pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
     pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
     pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/arch/powerpc/cpu/mpc85xx/ether_fcc.c b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
index 166dc9e..58d4bfb 100644
--- a/arch/powerpc/cpu/mpc85xx/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
@@ -338,7 +338,7 @@ static int fec_init(struct eth_device* dev, bd_t *bis)
      * it unique by setting a few bits in the upper byte of the
      * non-static part of the address.
      */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
     pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
     pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
     pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/arch/powerpc/cpu/mpc8xx/scc.c b/arch/powerpc/cpu/mpc8xx/scc.c
index 251966b..66e4014 100644
--- a/arch/powerpc/cpu/mpc8xx/scc.c
+++ b/arch/powerpc/cpu/mpc8xx/scc.c
@@ -339,7 +339,7 @@ static int scc_init (struct eth_device *dev, bd_t * bis)
 	pram_ptr->sen_gaddr3 = 0x0;	/* Group Address Filter 3 (unused) */
 	pram_ptr->sen_gaddr4 = 0x0;	/* Group Address Filter 4 (unused) */
 
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
 	pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4];
 	pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2];
 	pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/include/net.h b/include/net.h
index 43e3d28..6c76976 100644
--- a/include/net.h
+++ b/include/net.h
@@ -111,6 +111,14 @@ struct eth_device *eth_get_dev(void)
 {
 	return eth_current;
 }
+
+static inline unsigned char *eth_get_ethaddr(void)
+{
+	if (eth_current)
+		return eth_current->enetaddr;
+	return NULL;
+}
+
 extern struct eth_device *eth_get_dev_by_name(const char *devname);
 extern struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
 extern int eth_get_dev_index(void);		/* get the device index */
diff --git a/net/net.c b/net/net.c
index b60ce62..4b3c90e 100644
--- a/net/net.c
+++ b/net/net.c
@@ -275,7 +275,7 @@ static void NetInitLoop(void)
 		env_changed_id = env_id;
 	}
 	if (eth_get_dev())
-		memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
+		memcpy(NetOurEther, eth_get_ethaddr(), 6);
 
 	return;
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 04/23] net: Rename helper function to be more clear
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (2 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 03/23] net: Provide a function to get the current MAC address Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 05/23] net: Remove unneeded "extern" in net.h Joe Hershberger
                         ` (20 subsequent siblings)
  24 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

Make it clear that the helper is checking the addr, not setting it.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 net/eth.c | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/net/eth.c b/net/eth.c
index eac4f7b..65e8c77 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -153,11 +153,6 @@ static void eth_current_changed(void)
 		setenv("ethact", NULL);
 }
 
-static int eth_address_set(unsigned char *addr)
-{
-	return memcmp(addr, "\0\0\0\0\0\0", 6);
-}
-
 int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		   int eth_number)
 {
@@ -166,9 +161,9 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 
 	eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
 
-	if (eth_address_set(env_enetaddr)) {
-		if (eth_address_set(dev->enetaddr) &&
-				memcmp(dev->enetaddr, env_enetaddr, 6)) {
+	if (!is_zero_ether_addr(env_enetaddr)) {
+		if (!is_zero_ether_addr(dev->enetaddr) &&
+		    memcmp(dev->enetaddr, env_enetaddr, 6)) {
 			printf("\nWarning: %s MAC addresses don't match:\n",
 				dev->name);
 			printf("Address in SROM is         %pM\n",
@@ -183,7 +178,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 					     dev->enetaddr);
 		printf("\nWarning: %s using MAC address from net device\n",
 			dev->name);
-	} else if (!(eth_address_set(dev->enetaddr))) {
+	} else if (is_zero_ether_addr(dev->enetaddr)) {
 		printf("\nError: %s address not set.\n",
 		       dev->name);
 		return -EINVAL;
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 05/23] net: Remove unneeded "extern" in net.h
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (3 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 04/23] net: Rename helper function to be more clear Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 06/23] net: Refactor in preparation for driver model Joe Hershberger
                         ` (19 subsequent siblings)
  24 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

Many of the functions in net.h were preceded extern needlessly. Removing
them to limit the number of checkpatch.pl complaints.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/net.h | 92 +++++++++++++++++++++++++++++------------------------------
 1 file changed, 46 insertions(+), 46 deletions(-)

diff --git a/include/net.h b/include/net.h
index 6c76976..b82a29d 100644
--- a/include/net.h
+++ b/include/net.h
@@ -97,11 +97,11 @@ struct eth_device {
 	void *priv;
 };
 
-extern int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
-extern int eth_register(struct eth_device* dev);/* Register network device */
-extern int eth_unregister(struct eth_device *dev);/* Remove network device */
-extern void eth_try_another(int first_restart);	/* Change the device */
-extern void eth_set_current(void);		/* set nterface to ethcur var */
+int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
+int eth_register(struct eth_device *dev);/* Register network device */
+int eth_unregister(struct eth_device *dev);/* Remove network device */
+void eth_try_another(int first_restart);	/* Change the device */
+void eth_set_current(void);		/* set nterface to ethcur var */
 
 /* get the current device MAC */
 extern struct eth_device *eth_current;
@@ -119,12 +119,12 @@ static inline unsigned char *eth_get_ethaddr(void)
 	return NULL;
 }
 
-extern struct eth_device *eth_get_dev_by_name(const char *devname);
-extern struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
-extern int eth_get_dev_index(void);		/* get the device index */
-extern void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
-extern int eth_getenv_enetaddr(char *name, uchar *enetaddr);
-extern int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
+struct eth_device *eth_get_dev_by_name(const char *devname);
+struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
+int eth_get_dev_index(void);		/* get the device index */
+void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
+int eth_getenv_enetaddr(char *name, uchar *enetaddr);
+int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 
 /*
  * Get the hardware address for an ethernet interface .
@@ -135,20 +135,20 @@ extern int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
  * Returns:
  *	Return true if the address is valid.
  */
-extern int eth_getenv_enetaddr_by_index(const char *base_name, int index,
-					uchar *enetaddr);
+int eth_getenv_enetaddr_by_index(const char *base_name, int index,
+				 uchar *enetaddr);
 
-extern int usb_eth_initialize(bd_t *bi);
-extern int eth_init(bd_t *bis);			/* Initialize the device */
-extern int eth_send(void *packet, int length);	   /* Send a packet */
+int usb_eth_initialize(bd_t *bi);
+int eth_init(bd_t *bis);			/* Initialize the device */
+int eth_send(void *packet, int length);	   /* Send a packet */
 
 #ifdef CONFIG_API
-extern int eth_receive(void *packet, int length); /* Receive a packet*/
-extern void (*push_packet)(void *packet, int length);
+int eth_receive(void *packet, int length); /* Receive a packet*/
+void (*push_packet)(void *packet, int length);
 #endif
-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 */
+int eth_rx(void);			/* Check for received packets */
+void eth_halt(void);			/* stop SCC */
+char *eth_get_name(void);		/* get name of current device */
 
 /* Set active state */
 static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
@@ -469,25 +469,25 @@ extern IPaddr_t Mcast_addr;
 #endif
 
 /* Initialize the network adapter */
-extern void net_init(void);
-extern int NetLoop(enum proto_t);
+void net_init(void);
+int NetLoop(enum proto_t);
 
 /* Shutdown adapters and cleanup */
-extern void	NetStop(void);
+void	NetStop(void);
 
 /* Load failed.	 Start again. */
-extern void	NetStartAgain(void);
+void	NetStartAgain(void);
 
 /* Get size of the ethernet header when we send */
-extern int	NetEthHdrSize(void);
+int	NetEthHdrSize(void);
 
 /* Set ethernet header; returns the size of the header */
-extern int NetSetEther(uchar *, uchar *, uint);
-extern int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot);
+int NetSetEther(uchar *, uchar *, uint);
+int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot);
 
 /* Set IP header */
-extern void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source);
-extern void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport,
+void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source);
+void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport,
 				int sport, int len);
 
 /**
@@ -521,12 +521,12 @@ unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new_sum);
 int ip_checksum_ok(const void *addr, unsigned nbytes);
 
 /* Callbacks */
-extern rxhand_f *net_get_udp_handler(void);	/* Get UDP RX packet handler */
-extern void net_set_udp_handler(rxhand_f *);	/* Set UDP RX packet handler */
-extern rxhand_f *net_get_arp_handler(void);	/* Get ARP RX packet handler */
-extern void net_set_arp_handler(rxhand_f *);	/* Set ARP RX packet handler */
-extern void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
-extern void	NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
+rxhand_f *net_get_udp_handler(void);	/* Get UDP RX packet handler */
+void net_set_udp_handler(rxhand_f *);	/* Set UDP RX packet handler */
+rxhand_f *net_get_arp_handler(void);	/* Get ARP RX packet handler */
+void net_set_arp_handler(rxhand_f *);	/* Set ARP RX packet handler */
+void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
+void	NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
 
 /* Network loop state */
 enum net_loop_state {
@@ -559,11 +559,11 @@ static inline void NetSendPacket(uchar *pkt, int len)
  * @param sport Source UDP port
  * @param payload_len Length of data after the UDP header
  */
-extern int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport,
+int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport,
 			int sport, int payload_len);
 
 /* Processes a received packet */
-extern void NetReceive(uchar *, int);
+void NetReceive(uchar *, int);
 
 #ifdef CONFIG_NETCONSOLE
 void NcStart(void);
@@ -711,28 +711,28 @@ static inline void eth_random_addr(uchar *addr)
 }
 
 /* Convert an IP address to a string */
-extern void ip_to_string(IPaddr_t x, char *s);
+void ip_to_string(IPaddr_t x, char *s);
 
 /* Convert a string to ip address */
-extern IPaddr_t string_to_ip(const char *s);
+IPaddr_t string_to_ip(const char *s);
 
 /* Convert a VLAN id to a string */
-extern void VLAN_to_string(ushort x, char *s);
+void VLAN_to_string(ushort x, char *s);
 
 /* Convert a string to a vlan id */
-extern ushort string_to_VLAN(const char *s);
+ushort string_to_VLAN(const char *s);
 
 /* read a VLAN id from an environment variable */
-extern ushort getenv_VLAN(char *);
+ushort getenv_VLAN(char *);
 
 /* copy a filename (allow for "..." notation, limit length) */
-extern void copy_filename(char *dst, const char *src, int size);
+void copy_filename(char *dst, const char *src, int size);
 
 /* get a random source port */
-extern unsigned int random_port(void);
+unsigned int random_port(void);
 
 /* Update U-Boot over TFTP */
-extern int update_tftp(ulong addr);
+int update_tftp(ulong addr);
 
 /**********************************************************************/
 
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 06/23] net: Refactor in preparation for driver model
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (4 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 05/23] net: Remove unneeded "extern" in net.h Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-03-01 18:08         ` Simon Glass
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 07/23] net: Change return codes from net/eth.c to use errorno constants Joe Hershberger
                         ` (18 subsequent siblings)
  24 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

Move some things around and organize things so that the driver model
implementation will fit in more easily.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v4:
-Fix compile regression in !DM_ETH case

Changes in v3:
-Move the get_dev_by_* protos to also be !DM_ETH like the impl

Changes in v2: None

 include/net.h | 68 +++++++++++++++++++++++++++-------------------------
 net/eth.c     | 77 +++++++++++++++++++++++++++++++----------------------------
 2 files changed, 76 insertions(+), 69 deletions(-)

diff --git a/include/net.h b/include/net.h
index b82a29d..4cef00c 100644
--- a/include/net.h
+++ b/include/net.h
@@ -97,13 +97,9 @@ struct eth_device {
 	void *priv;
 };
 
-int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
 int eth_register(struct eth_device *dev);/* Register network device */
 int eth_unregister(struct eth_device *dev);/* Remove network device */
-void eth_try_another(int first_restart);	/* Change the device */
-void eth_set_current(void);		/* set nterface to ethcur var */
 
-/* get the current device MAC */
 extern struct eth_device *eth_current;
 
 static inline __attribute__((always_inline))
@@ -111,7 +107,10 @@ struct eth_device *eth_get_dev(void)
 {
 	return eth_current;
 }
+struct eth_device *eth_get_dev_by_name(const char *devname);
+struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
 
+/* get the current device MAC */
 static inline unsigned char *eth_get_ethaddr(void)
 {
 	if (eth_current)
@@ -119,8 +118,37 @@ static inline unsigned char *eth_get_ethaddr(void)
 	return NULL;
 }
 
-struct eth_device *eth_get_dev_by_name(const char *devname);
-struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
+/* Set active state */
+static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
+{
+	eth_get_dev()->state = ETH_STATE_ACTIVE;
+
+	return 0;
+}
+/* Set passive state */
+static inline __attribute__((always_inline)) void eth_halt_state_only(void)
+{
+	eth_get_dev()->state = ETH_STATE_PASSIVE;
+}
+
+/*
+ * Set the hardware address for an ethernet interface based on 'eth%daddr'
+ * environment variable (or just 'ethaddr' if eth_number is 0).
+ * Args:
+ *	base_name - base name for device (normally "eth")
+ *	eth_number - value of %d (0 for first device of this type)
+ * Returns:
+ *	0 is success, non-zero is error status from driver.
+ */
+int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
+		     int eth_number);
+
+int usb_eth_initialize(bd_t *bi);
+
+int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
+void eth_try_another(int first_restart);	/* Change the device */
+void eth_set_current(void);		/* set nterface to ethcur var */
+
 int eth_get_dev_index(void);		/* get the device index */
 void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
 int eth_getenv_enetaddr(char *name, uchar *enetaddr);
@@ -138,7 +166,6 @@ int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 int eth_getenv_enetaddr_by_index(const char *base_name, int index,
 				 uchar *enetaddr);
 
-int usb_eth_initialize(bd_t *bi);
 int eth_init(bd_t *bis);			/* Initialize the device */
 int eth_send(void *packet, int length);	   /* Send a packet */
 
@@ -148,32 +175,7 @@ void (*push_packet)(void *packet, int length);
 #endif
 int eth_rx(void);			/* Check for received packets */
 void eth_halt(void);			/* stop SCC */
-char *eth_get_name(void);		/* get name of current device */
-
-/* Set active state */
-static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
-{
-	eth_get_dev()->state = ETH_STATE_ACTIVE;
-
-	return 0;
-}
-/* Set passive state */
-static inline __attribute__((always_inline)) void eth_halt_state_only(void)
-{
-	eth_get_dev()->state = ETH_STATE_PASSIVE;
-}
-
-/*
- * Set the hardware address for an ethernet interface based on 'eth%daddr'
- * environment variable (or just 'ethaddr' if eth_number is 0).
- * Args:
- *	base_name - base name for device (normally "eth")
- *	eth_number - value of %d (0 for first device of this type)
- * Returns:
- *	0 is success, non-zero is error status from driver.
- */
-int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
-		     int eth_number);
+const char *eth_get_name(void);		/* get name of current device */
 
 #ifdef CONFIG_MCAST_TFTP
 int eth_mcast_join(IPaddr_t mcast_addr, u8 join);
diff --git a/net/eth.c b/net/eth.c
index 65e8c77..3df3c11 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -55,6 +55,14 @@ static inline int eth_setenv_enetaddr_by_index(const char *base_name, int index,
 	return eth_setenv_enetaddr(enetvar, enetaddr);
 }
 
+static void eth_env_init(void)
+{
+	const char *s;
+
+	s = getenv("bootfile");
+	if (s != NULL)
+		copy_filename(BootFile, s, sizeof(BootFile));
+}
 
 static int eth_mac_skip(int index)
 {
@@ -87,6 +95,11 @@ static unsigned int eth_rcv_current, eth_rcv_last;
 static struct eth_device *eth_devices;
 struct eth_device *eth_current;
 
+static void eth_set_current_to_next(void)
+{
+	eth_current = eth_current->next;
+}
+
 struct eth_device *eth_get_dev_by_name(const char *devname)
 {
 	struct eth_device *dev, *target_dev;
@@ -137,22 +150,6 @@ int eth_get_dev_index(void)
 	return eth_current->index;
 }
 
-static void eth_current_changed(void)
-{
-	char *act = getenv("ethact");
-	/* update current ethernet name */
-	if (eth_current) {
-		if (act == NULL || strcmp(act, eth_current->name) != 0)
-			setenv("ethact", eth_current->name);
-	}
-	/*
-	 * remove the variable completely if there is no active
-	 * interface
-	 */
-	else if (act != NULL)
-		setenv("ethact", NULL);
-}
-
 int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		   int eth_number)
 {
@@ -251,14 +248,6 @@ int eth_unregister(struct eth_device *dev)
 	return 0;
 }
 
-static void eth_env_init(bd_t *bis)
-{
-	const char *s;
-
-	if ((s = getenv("bootfile")) != NULL)
-		copy_filename(BootFile, s, sizeof(BootFile));
-}
-
 int eth_initialize(bd_t *bis)
 {
 	int num_devices = 0;
@@ -274,7 +263,7 @@ int eth_initialize(bd_t *bis)
 	phy_init();
 #endif
 
-	eth_env_init(bis);
+	eth_env_init();
 
 	/*
 	 * If board-specific initialization exists, call it.
@@ -479,6 +468,22 @@ int eth_receive(void *packet, int length)
 }
 #endif /* CONFIG_API */
 
+static void eth_current_changed(void)
+{
+	char *act = getenv("ethact");
+	/* update current ethernet name */
+	if (eth_get_dev()) {
+		if (act == NULL || strcmp(act, eth_get_name()) != 0)
+			setenv("ethact", eth_get_name());
+	}
+	/*
+	 * remove the variable completely if there is no active
+	 * interface
+	 */
+	else if (act != NULL)
+		setenv("ethact", NULL);
+}
+
 void eth_try_another(int first_restart)
 {
 	static struct eth_device *first_failed;
@@ -492,17 +497,17 @@ void eth_try_another(int first_restart)
 	if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
 		return;
 
-	if (!eth_current)
+	if (!eth_get_dev())
 		return;
 
 	if (first_restart)
-		first_failed = eth_current;
+		first_failed = eth_get_dev();
 
-	eth_current = eth_current->next;
+	eth_set_current_to_next();
 
 	eth_current_changed();
 
-	if (first_failed == eth_current)
+	if (first_failed == eth_get_dev())
 		NetRestartWrap = 1;
 }
 
@@ -513,7 +518,7 @@ void eth_set_current(void)
 	struct eth_device *old_current;
 	int	env_id;
 
-	if (!eth_current)	/* XXX no current */
+	if (!eth_get_dev())	/* XXX no current */
 		return;
 
 	env_id = get_env_id();
@@ -522,18 +527,18 @@ void eth_set_current(void)
 		env_changed_id = env_id;
 	}
 	if (act != NULL) {
-		old_current = eth_current;
+		old_current = eth_get_dev();
 		do {
-			if (strcmp(eth_current->name, act) == 0)
+			if (strcmp(eth_get_name(), act) == 0)
 				return;
-			eth_current = eth_current->next;
-		} while (old_current != eth_current);
+			eth_set_current_to_next();
+		} while (old_current != eth_get_dev());
 	}
 
 	eth_current_changed();
 }
 
-char *eth_get_name(void)
+const char *eth_get_name(void)
 {
-	return eth_current ? eth_current->name : "unknown";
+	return eth_get_dev() ? eth_get_dev()->name : "unknown";
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 07/23] net: Change return codes from net/eth.c to use errorno constants
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (5 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 06/23] net: Refactor in preparation for driver model Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-02-26  0:53         ` Simon Glass
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 08/23] net: Use int instead of u8 for boolean flag Joe Hershberger
                         ` (17 subsequent siblings)
  24 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

Many functions returned -1 previously. Change them to return appropriate error
codes.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reported-by: Simon Glass <sjg@chromium.org>

---

Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 net/eth.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/net/eth.c b/net/eth.c
index 3df3c11..214375b 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -225,7 +225,7 @@ int eth_unregister(struct eth_device *dev)
 
 	/* No device */
 	if (!eth_devices)
-		return -1;
+		return -ENODEV;
 
 	for (cur = eth_devices; cur->next != eth_devices && cur->next != dev;
 	     cur = cur->next)
@@ -233,7 +233,7 @@ int eth_unregister(struct eth_device *dev)
 
 	/* Device not found */
 	if (cur->next != dev)
-		return -1;
+		return -ENODEV;
 
 	cur->next = dev->next;
 
@@ -366,7 +366,7 @@ int eth_init(bd_t *bis)
 
 	if (!eth_current) {
 		puts("No ethernet found.\n");
-		return -1;
+		return -ENODEV;
 	}
 
 	/* Sync environment with network devices */
@@ -395,7 +395,7 @@ int eth_init(bd_t *bis)
 		eth_try_another(0);
 	} while (old_current != eth_current);
 
-	return -1;
+	return -ETIMEDOUT;
 }
 
 void eth_halt(void)
@@ -411,7 +411,7 @@ void eth_halt(void)
 int eth_send(void *packet, int length)
 {
 	if (!eth_current)
-		return -1;
+		return -ENODEV;
 
 	return eth_current->send(eth_current, packet, length);
 }
@@ -419,7 +419,7 @@ int eth_send(void *packet, int length)
 int eth_rx(void)
 {
 	if (!eth_current)
-		return -1;
+		return -ENODEV;
 
 	return eth_current->recv(eth_current);
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 08/23] net: Use int instead of u8 for boolean flag
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (6 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 07/23] net: Change return codes from net/eth.c to use errorno constants Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-02-26  0:53         ` Simon Glass
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 09/23] net: Remove the bd* parameter from net stack functions Joe Hershberger
                         ` (16 subsequent siblings)
  24 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

On some archs masking the parameter is inefficient, so don't use u8.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reported-by: Simon Glass <sjg@chromium.org>

---

Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 include/net.h | 2 +-
 net/eth.c     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/net.h b/include/net.h
index 4cef00c..ad20145 100644
--- a/include/net.h
+++ b/include/net.h
@@ -178,7 +178,7 @@ void eth_halt(void);			/* stop SCC */
 const char *eth_get_name(void);		/* get name of current device */
 
 #ifdef CONFIG_MCAST_TFTP
-int eth_mcast_join(IPaddr_t mcast_addr, u8 join);
+int eth_mcast_join(IPaddr_t mcast_addr, int join);
 u32 ether_crc(size_t len, unsigned char const *p);
 #endif
 
diff --git a/net/eth.c b/net/eth.c
index 214375b..484b995 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -319,7 +319,7 @@ int eth_initialize(bd_t *bis)
  * mcast_addr: multicast ipaddr from which multicast Mac is made
  * join: 1=join, 0=leave.
  */
-int eth_mcast_join(IPaddr_t mcast_ip, u8 join)
+int eth_mcast_join(IPaddr_t mcast_ip, int join)
 {
 	u8 mcast_mac[6];
 	if (!eth_current || !eth_current->mcast)
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 09/23] net: Remove the bd* parameter from net stack functions
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (7 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 08/23] net: Use int instead of u8 for boolean flag Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-03-01 18:07         ` Simon Glass
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 10/23] net: Make netretry actually do something Joe Hershberger
                         ` (15 subsequent siblings)
  24 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

This value is not used by the network stack and is available in the
global data, so stop passing it around.  For the one legacy function
that still expects it (init op on old Ethernet drivers) pass in the
global pointer version directly to avoid changing that interface.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reported-by: Simon Glass <sjg@chromium.org>

---

Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 common/board_r.c         |  2 +-
 drivers/net/netconsole.c |  4 ++--
 include/net.h            |  6 +++---
 net/eth.c                | 12 +++++++-----
 net/net.c                |  7 +++----
 5 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/common/board_r.c b/common/board_r.c
index 4fcd4f6..b62f72f 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -584,7 +584,7 @@ static int initr_bbmii(void)
 static int initr_net(void)
 {
 	puts("Net:   ");
-	eth_initialize(gd->bd);
+	eth_initialize();
 #if defined(CONFIG_RESET_PHY_R)
 	debug("Reset Ethernet PHY\n");
 	reset_phy();
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 677c89f..87cea7a 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -193,11 +193,11 @@ static void nc_send_packet(const char *buf, int len)
 
 	if (eth->state != ETH_STATE_ACTIVE) {
 		if (eth_is_on_demand_init()) {
-			if (eth_init(gd->bd) < 0)
+			if (eth_init() < 0)
 				return;
 			eth_set_last_protocol(NETCONS);
 		} else
-			eth_init_state_only(gd->bd);
+			eth_init_state_only();
 
 		inited = 1;
 	}
diff --git a/include/net.h b/include/net.h
index ad20145..10d38f8 100644
--- a/include/net.h
+++ b/include/net.h
@@ -119,7 +119,7 @@ static inline unsigned char *eth_get_ethaddr(void)
 }
 
 /* Set active state */
-static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
+static inline __attribute__((always_inline)) int eth_init_state_only(void)
 {
 	eth_get_dev()->state = ETH_STATE_ACTIVE;
 
@@ -145,7 +145,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 
 int usb_eth_initialize(bd_t *bi);
 
-int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
+int eth_initialize(void);		/* Initialize network subsystem */
 void eth_try_another(int first_restart);	/* Change the device */
 void eth_set_current(void);		/* set nterface to ethcur var */
 
@@ -166,7 +166,7 @@ int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 int eth_getenv_enetaddr_by_index(const char *base_name, int index,
 				 uchar *enetaddr);
 
-int eth_init(bd_t *bis);			/* Initialize the device */
+int eth_init(void);			/* Initialize the device */
 int eth_send(void *packet, int length);	   /* Send a packet */
 
 #ifdef CONFIG_API
diff --git a/net/eth.c b/net/eth.c
index 484b995..7bbaac4 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -12,6 +12,8 @@
 #include <phy.h>
 #include <asm/errno.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 void eth_parse_enetaddr(const char *addr, uchar *enetaddr)
 {
 	char *end;
@@ -248,7 +250,7 @@ int eth_unregister(struct eth_device *dev)
 	return 0;
 }
 
-int eth_initialize(bd_t *bis)
+int eth_initialize(void)
 {
 	int num_devices = 0;
 	eth_devices = NULL;
@@ -270,10 +272,10 @@ int eth_initialize(bd_t *bis)
 	 * If not, call a CPU-specific one
 	 */
 	if (board_eth_init != __def_eth_init) {
-		if (board_eth_init(bis) < 0)
+		if (board_eth_init(gd->bd) < 0)
 			printf("Board Net Initialization Failed\n");
 	} else if (cpu_eth_init != __def_eth_init) {
-		if (cpu_eth_init(bis) < 0)
+		if (cpu_eth_init(gd->bd) < 0)
 			printf("CPU Net Initialization Failed\n");
 	} else
 		printf("Net Initialization Skipped\n");
@@ -360,7 +362,7 @@ u32 ether_crc(size_t len, unsigned char const *p)
 #endif
 
 
-int eth_init(bd_t *bis)
+int eth_init(void)
 {
 	struct eth_device *old_current, *dev;
 
@@ -385,7 +387,7 @@ int eth_init(bd_t *bis)
 	do {
 		debug("Trying %s\n", eth_current->name);
 
-		if (eth_current->init(eth_current, bis) >= 0) {
+		if (eth_current->init(eth_current, gd->bd) >= 0) {
 			eth_current->state = ETH_STATE_ACTIVE;
 
 			return 0;
diff --git a/net/net.c b/net/net.c
index 4b3c90e..e5ab07c 100644
--- a/net/net.c
+++ b/net/net.c
@@ -324,7 +324,6 @@ void net_init(void)
 
 int NetLoop(enum proto_t protocol)
 {
-	bd_t *bd = gd->bd;
 	int ret = -1;
 
 	NetRestarted = 0;
@@ -337,12 +336,12 @@ int NetLoop(enum proto_t protocol)
 	if (eth_is_on_demand_init() || protocol != NETCONS) {
 		eth_halt();
 		eth_set_current();
-		if (eth_init(bd) < 0) {
+		if (eth_init() < 0) {
 			eth_halt();
 			return -1;
 		}
 	} else
-		eth_init_state_only(bd);
+		eth_init_state_only();
 
 restart:
 #ifdef CONFIG_USB_KEYBOARD
@@ -618,7 +617,7 @@ void NetStartAgain(void)
 #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
 	eth_try_another(!NetRestarted);
 #endif
-	eth_init(gd->bd);
+	eth_init();
 	if (NetRestartWrap) {
 		NetRestartWrap = 0;
 		if (NetDevExists) {
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 10/23] net: Make netretry actually do something
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (8 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 09/23] net: Remove the bd* parameter from net stack functions Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-03-01 18:07         ` Simon Glass
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 11/23] net: Access mapped physmem in net functions Joe Hershberger
                         ` (14 subsequent siblings)
  24 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

netretry previously would only retry in one specific case (your MAC
address is not set) and no other. This is basically useless. In the DM
implementation for eth it turns this into a completely useless case
since an un-configured MAC address results in not even entering the
NetLoop. The behavior is now changed to retry any failed command
(rotating through the eth adapters if ethrotate != no).

It also defaulted to retry forever. It is now changed to default to not
retry

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 net/net.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/net/net.c b/net/net.c
index e5ab07c..37b4aab 100644
--- a/net/net.c
+++ b/net/net.c
@@ -527,6 +527,8 @@ restart:
 			(*x)();
 		}
 
+		if (net_state == NETLOOP_FAIL)
+			NetStartAgain();
 
 		switch (net_state) {
 
@@ -602,8 +604,10 @@ void NetStartAgain(void)
 			retrycnt = 1;
 		else
 			retrycnt = simple_strtoul(nretry, NULL, 0);
-	} else
-		retry_forever = 1;
+	} else {
+		retrycnt = 0;
+		retry_forever = 0;
+	}
 
 	if ((!retry_forever) && (NetTryCount >= retrycnt)) {
 		eth_halt();
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 11/23] net: Access mapped physmem in net functions
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (9 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 10/23] net: Make netretry actually do something Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-03-01 18:07         ` Simon Glass
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 12/23] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
                         ` (13 subsequent siblings)
  24 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

Previously the net functions would access memory assuming physmem did
not need to be mapped.  In sandbox, that's not the case.

Now we map the physmem specified by the user in loadaddr to the buffer
that represents that space.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 net/nfs.c  | 2 +-
 net/tftp.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/nfs.c b/net/nfs.c
index 381b75f..c816acd 100644
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -93,7 +93,7 @@ store_block(uchar *src, unsigned offset, unsigned len)
 	} else
 #endif /* CONFIG_SYS_DIRECT_FLASH_NFS */
 	{
-		(void)memcpy((void *)(load_addr + offset), src, len);
+		memcpy((void *)(map_sysmem(load_addr, 0) + offset), src, len);
 	}
 
 	if (NetBootFileXferSize < (offset+len))
diff --git a/net/tftp.c b/net/tftp.c
index 0a2c533..9290182 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -184,7 +184,7 @@ store_block(int block, uchar *src, unsigned len)
 	} else
 #endif /* CONFIG_SYS_DIRECT_FLASH_TFTP */
 	{
-		(void)memcpy((void *)(load_addr + offset), src, len);
+		memcpy((void *)(map_sysmem(load_addr, 0) + offset), src, len);
 	}
 #ifdef CONFIG_MCAST_TFTP
 	if (Multicast)
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 12/23] dm: eth: Add basic driver model support to Ethernet stack
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (10 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 11/23] net: Access mapped physmem in net functions Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-03-01 18:07         ` Simon Glass
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 13/23] sandbox: eth: Add network support to sandbox Joe Hershberger
                         ` (12 subsequent siblings)
  24 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

First just add support for MAC drivers.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v4:
-Redo the seq / probe implementation
--Don't prevent eth_initialize on driver model
--Use eth_initialize to probe all devices and write_hwaddr
--Look up MAC address in post-probe
--Include ethprime handling in eth_initialize
--If current == NULL, always check if there is a device available in eth_get_dev
--Move env init call from uclass init to eth_initialize
--Print the alias in eth_initialize
-Stop handling selecting a new "current" in pre-unbind as it will now work itself out by clearing the pointer
-Change -1 returns to error constants
-Remove bd_t *bis from dm eth_ops init function
-Add documentation to the structures
-Add a helper function for eth_uclass_priv
-Change puts to printf
-Add eth_get_ops helper
-Rename init() to start() in ops
-Rename halt() to stop() in ops
-Remove checks for driver==NULL
-Remove priv pointer in per-device priv struct (drivers already get their own directly from DM)

Changes in v3:
-Correct the pre_unbind logic
-Correct failure chaining from bind to probe to init
--Fail init if not activated
--Fail probe if ethaddr not set
-Update ethaddr from env unconditionally on init
-Use set current to select the current device regardless of the previous selection
-Allow current eth dev to be NULL
-Fixed blank line formatting for variable declaration

Changes in v2:
-Updated comments
-Removed extra parentheses
-Changed eth_uclass_priv local var names to be uc_priv
-Update error codes
-Cause an invalid name to fail binding
-Rebase on top of dm/master
-Stop maintaining our own index and use DM seq now that it works for our needs
-Move the hwaddr to platdata so that its memory is allocated at bind when we need it
-Prevent device from being probed before used by a command (i.e. before eth_init()).

 common/cmd_bdinfo.c    |   2 +
 drivers/net/Kconfig    |   5 +
 include/dm/uclass-id.h |   1 +
 include/net.h          |  52 ++++++++
 net/eth.c              | 345 ++++++++++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 399 insertions(+), 6 deletions(-)

diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
index aa81da2..b4cce25 100644
--- a/common/cmd_bdinfo.c
+++ b/common/cmd_bdinfo.c
@@ -34,6 +34,7 @@ static void print_eth(int idx)
 	printf("%-12s= %s\n", name, val);
 }
 
+#ifndef CONFIG_DM_ETH
 __maybe_unused
 static void print_eths(void)
 {
@@ -52,6 +53,7 @@ static void print_eths(void)
 	printf("current eth = %s\n", eth_get_name());
 	printf("ip_addr     = %s\n", getenv("ipaddr"));
 }
+#endif
 
 __maybe_unused
 static void print_lnum(const char *name, unsigned long long value)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index e69de29..bdd0f05 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -0,0 +1,5 @@
+config DM_ETH
+	bool "Enable Driver Model for Ethernet drivers"
+	depends on DM
+	help
+	  Enable driver model for Ethernet.
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 91bb90d..ad96682 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -34,6 +34,7 @@ enum uclass_id {
 	UCLASS_I2C_GENERIC,	/* Generic I2C device */
 	UCLASS_I2C_EEPROM,	/* I2C EEPROM device */
 	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
+	UCLASS_ETH,		/* Ethernet device */
 
 	UCLASS_COUNT,
 	UCLASS_INVALID = -1,
diff --git a/include/net.h b/include/net.h
index 10d38f8..508c572 100644
--- a/include/net.h
+++ b/include/net.h
@@ -78,6 +78,57 @@ enum eth_state_t {
 	ETH_STATE_ACTIVE
 };
 
+#ifdef CONFIG_DM_ETH
+/**
+ * struct eth_pdata - Platform data for Ethernet MAC controllers
+ *
+ * @iobase: The base address of the hardware registers
+ * @enetaddr: The Ethernet MAC address that is loaded from EEPROM or env
+ */
+struct eth_pdata {
+	phys_addr_t iobase;
+	unsigned char enetaddr[6];
+};
+
+/**
+ * struct eth_ops - functions of Ethernet MAC controllers
+ *
+ * start: Prepare the hardware to send and receive packets
+ * send: Send the bytes passed in "packet" as a packet on the wire
+ * recv: Check if the hardware received a packet. Call the network stack if so
+ * stop: Stop the hardware from looking for packets - may be called even if
+ *	 state == PASSIVE
+ * mcast: Join or leave a multicast group (for TFTP) - optional
+ * write_hwaddr: Write a MAC address to the hardware (used to pass it to Linux
+ *		 on some platforms like ARM). This function expects the
+ *		 eth_pdata::enetaddr field to be populated - optional
+ * read_rom_hwaddr: Some devices have a backup of the MAC address stored in a
+ *		    ROM on the board. This is how the driver should expose it
+ *		    to the network stack. This function should fill in the
+ *		    eth_pdata::enetaddr field - optional
+ */
+struct eth_ops {
+	int (*start)(struct udevice *dev);
+	int (*send)(struct udevice *dev, void *packet, int length);
+	int (*recv)(struct udevice *dev);
+	void (*stop)(struct udevice *dev);
+#ifdef CONFIG_MCAST_TFTP
+	int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
+#endif
+	int (*write_hwaddr)(struct udevice *dev);
+	int (*read_rom_hwaddr)(struct udevice *dev);
+};
+
+#define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
+
+struct udevice *eth_get_dev(void); /* get the current device */
+unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
+/* Used only when NetConsole is enabled */
+int eth_init_state_only(void); /* Set active state */
+void eth_halt_state_only(void); /* Set passive state */
+#endif
+
+#ifndef CONFIG_DM_ETH
 struct eth_device {
 	char name[16];
 	unsigned char enetaddr[6];
@@ -144,6 +195,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		     int eth_number);
 
 int usb_eth_initialize(bd_t *bi);
+#endif
 
 int eth_initialize(void);		/* Initialize network subsystem */
 void eth_try_another(int first_restart);	/* Change the device */
diff --git a/net/eth.c b/net/eth.c
index 7bbaac4..9c2dfb9 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -1,12 +1,15 @@
 /*
- * (C) Copyright 2001-2010
+ * (C) Copyright 2001-2015
  * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ * Joe Hershberger, National Instruments
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #include <common.h>
 #include <command.h>
+#include <dm.h>
+#include <dm/device-internal.h>
 #include <net.h>
 #include <miiphy.h>
 #include <phy.h>
@@ -74,6 +77,338 @@ static int eth_mac_skip(int index)
 	return ((skip_state = getenv(enetvar)) != NULL);
 }
 
+static void eth_current_changed(void);
+
+#ifdef CONFIG_DM_ETH
+/**
+ * struct eth_device_priv - private structure for each Ethernet device
+ *
+ * @state: The state of the Ethernet MAC driver (defined by enum eth_state_t)
+ */
+struct eth_device_priv {
+	enum eth_state_t state;
+};
+
+/**
+ * struct eth_uclass_priv - The structure attached to the uclass itself
+ *
+ * @current: The Ethernet device that the network functions are using
+ */
+struct eth_uclass_priv {
+	struct udevice *current;
+};
+
+static struct eth_uclass_priv *eth_get_uclass_priv(void)
+{
+	struct uclass *uc;
+
+	uclass_get(UCLASS_ETH, &uc);
+	assert(uc);
+	return uc->priv;
+}
+
+static void eth_set_current_to_next(void)
+{
+	struct eth_uclass_priv *uc_priv;
+
+	uc_priv = eth_get_uclass_priv();
+	if (uc_priv->current)
+		uclass_next_device(&uc_priv->current);
+	if (!uc_priv->current)
+		uclass_first_device(UCLASS_ETH, &uc_priv->current);
+}
+
+struct udevice *eth_get_dev(void)
+{
+	if (!eth_get_uclass_priv()->current)
+		uclass_first_device(UCLASS_ETH,
+				    &eth_get_uclass_priv()->current);
+	return eth_get_uclass_priv()->current;
+}
+
+static void eth_set_dev(struct udevice *dev)
+{
+	device_probe(dev);
+	eth_get_uclass_priv()->current = dev;
+}
+
+unsigned char *eth_get_ethaddr(void)
+{
+	struct eth_pdata *pdata;
+
+	if (eth_get_dev()) {
+		pdata = eth_get_dev()->platdata;
+		return pdata->enetaddr;
+	}
+
+	return NULL;
+}
+
+/* Set active state without calling start on the driver */
+int eth_init_state_only(void)
+{
+	struct udevice *current;
+	struct eth_device_priv *priv;
+
+	current = eth_get_dev();
+	if (!current || !device_active(current))
+		return -EINVAL;
+
+	priv = current->uclass_priv;
+	priv->state = ETH_STATE_ACTIVE;
+
+	return 0;
+}
+
+/* Set passive state without calling stop on the driver */
+void eth_halt_state_only(void)
+{
+	struct udevice *current;
+	struct eth_device_priv *priv;
+
+	current = eth_get_dev();
+	if (!current || !device_active(current))
+		return;
+
+	priv = current->uclass_priv;
+	priv->state = ETH_STATE_PASSIVE;
+}
+
+int eth_get_dev_index(void)
+{
+	if (eth_get_dev())
+		return eth_get_dev()->seq;
+	return -1;
+}
+
+int eth_init(void)
+{
+	struct udevice *current;
+	struct udevice *old_current;
+
+	current = eth_get_dev();
+	if (!current) {
+		printf("No ethernet found.\n");
+		return -ENODEV;
+	}
+
+	old_current = current;
+	do {
+		debug("Trying %s\n", current->name);
+
+		if (device_active(current)) {
+			uchar env_enetaddr[6];
+			struct eth_pdata *pdata = current->platdata;
+
+			/* Sync environment with network device */
+			if (eth_getenv_enetaddr_by_index("eth", current->seq,
+							 env_enetaddr))
+				memcpy(pdata->enetaddr, env_enetaddr, 6);
+			else
+				memset(pdata->enetaddr, 0, 6);
+
+			if (eth_get_ops(current)->start(current) >= 0) {
+				struct eth_device_priv *priv =
+					current->uclass_priv;
+
+				priv->state = ETH_STATE_ACTIVE;
+				return 0;
+			}
+		}
+		debug("FAIL\n");
+
+		/* This will ensure the new "current" attempted to probe */
+		eth_try_another(0);
+		current = eth_get_dev();
+	} while (old_current != current);
+
+	return -ENODEV;
+}
+
+void eth_halt(void)
+{
+	struct udevice *current;
+	struct eth_device_priv *priv;
+
+	current = eth_get_dev();
+	if (!current || !device_active(current))
+		return;
+
+	eth_get_ops(current)->stop(current);
+	priv = current->uclass_priv;
+	priv->state = ETH_STATE_PASSIVE;
+}
+
+int eth_send(void *packet, int length)
+{
+	struct udevice *current;
+
+	current = eth_get_dev();
+	if (!current)
+		return -ENODEV;
+
+	if (!device_active(current))
+		return -EINVAL;
+
+	return eth_get_ops(current)->send(current, packet, length);
+}
+
+int eth_rx(void)
+{
+	struct udevice *current;
+
+	current = eth_get_dev();
+	if (!current)
+		return -ENODEV;
+
+	if (!device_active(current))
+		return -EINVAL;
+
+	return eth_get_ops(current)->recv(current);
+}
+
+static int eth_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev->platdata;
+	int ret = 0;
+
+	if (!dev || !device_active(dev))
+		return -EINVAL;
+
+	/* seq is valid since the device is active */
+	if (eth_get_ops(dev)->write_hwaddr && !eth_mac_skip(dev->seq)) {
+		if (!is_valid_ether_addr(pdata->enetaddr)) {
+			printf("\nError: %s address %pM illegal value\n",
+			       dev->name, pdata->enetaddr);
+			return -EINVAL;
+		}
+
+		ret = eth_get_ops(dev)->write_hwaddr(dev);
+		if (ret)
+			printf("\nWarning: %s failed to set MAC address\n",
+			       dev->name);
+	}
+
+	return ret;
+}
+
+int eth_initialize(void)
+{
+	int num_devices = 0;
+	struct udevice *dev;
+
+	bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
+	eth_env_init();
+
+	/*
+	 * Devices need to write the hwaddr even if not started so that Linux
+	 * will have access to the hwaddr that u-boot stored for the device.
+	 * This is accomplished by attempting to probe each device and calling
+	 * their write_hwaddr() operation.
+	 */
+	uclass_first_device(UCLASS_ETH, &dev);
+	if (!dev) {
+		printf("No ethernet found.\n");
+		bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
+	} else {
+		bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
+		do {
+			if (num_devices)
+				printf(", ");
+
+			printf("eth%d: %s", dev->seq, dev->name);
+
+			eth_write_hwaddr(dev);
+
+			uclass_next_device(&dev);
+			num_devices++;
+		} while (dev);
+
+		putc('\n');
+	}
+
+	return num_devices;
+}
+
+static int eth_post_bind(struct udevice *dev)
+{
+	if (strchr(dev->name, ' ')) {
+		printf("\nError: eth device name \"%s\" has a space!\n",
+		       dev->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int eth_pre_unbind(struct udevice *dev)
+{
+	/* Don't hang onto a pointer that is going away */
+	if (dev == eth_get_uclass_priv()->current)
+		eth_set_dev(NULL);
+
+	return 0;
+}
+
+static int eth_post_probe(struct udevice *dev)
+{
+	struct eth_device_priv *priv = dev->uclass_priv;
+	struct eth_pdata *pdata = dev->platdata;
+	unsigned char env_enetaddr[6];
+
+	priv->state = ETH_STATE_INIT;
+
+	/* Check if the device has a MAC address in ROM */
+	if (eth_get_ops(dev)->read_rom_hwaddr)
+		eth_get_ops(dev)->read_rom_hwaddr(dev);
+
+	eth_getenv_enetaddr_by_index("eth", dev->seq, env_enetaddr);
+	if (!is_zero_ether_addr(env_enetaddr)) {
+		if (!is_zero_ether_addr(pdata->enetaddr) &&
+		    memcmp(pdata->enetaddr, env_enetaddr, 6)) {
+			printf("\nWarning: %s MAC addresses don't match:\n",
+			       dev->name);
+			printf("Address in SROM is         %pM\n",
+			       pdata->enetaddr);
+			printf("Address in environment is  %pM\n",
+			       env_enetaddr);
+		}
+
+		/* Override the ROM MAC address */
+		memcpy(pdata->enetaddr, env_enetaddr, 6);
+	} else if (is_valid_ether_addr(pdata->enetaddr)) {
+		eth_setenv_enetaddr_by_index("eth", dev->seq, pdata->enetaddr);
+		printf("\nWarning: %s using MAC address from ROM\n",
+		       dev->name);
+	} else if (is_zero_ether_addr(pdata->enetaddr)) {
+		printf("\nError: %s address not set.\n",
+		       dev->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int eth_pre_remove(struct udevice *dev)
+{
+	eth_get_ops(dev)->stop(dev);
+
+	return 0;
+}
+
+UCLASS_DRIVER(eth) = {
+	.name		= "eth",
+	.id		= UCLASS_ETH,
+	.post_bind	= eth_post_bind,
+	.pre_unbind	= eth_pre_unbind,
+	.post_probe	= eth_post_probe,
+	.pre_remove	= eth_pre_remove,
+	.priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
+	.per_device_auto_alloc_size = sizeof(struct eth_device_priv),
+};
+#endif
+
+#ifndef CONFIG_DM_ETH
 /*
  * CPU and board-specific Ethernet initializations.  Aliased function
  * signals caller to move on
@@ -425,6 +760,7 @@ int eth_rx(void)
 
 	return eth_current->recv(eth_current);
 }
+#endif /* ifndef CONFIG_DM_ETH */
 
 #ifdef CONFIG_API
 static void eth_save_packet(void *packet, int length)
@@ -488,7 +824,7 @@ static void eth_current_changed(void)
 
 void eth_try_another(int first_restart)
 {
-	static struct eth_device *first_failed;
+	static void *first_failed;
 	char *ethrotate;
 
 	/*
@@ -517,12 +853,9 @@ void eth_set_current(void)
 {
 	static char *act;
 	static int  env_changed_id;
-	struct eth_device *old_current;
+	void *old_current;
 	int	env_id;
 
-	if (!eth_get_dev())	/* XXX no current */
-		return;
-
 	env_id = get_env_id();
 	if ((act == NULL) || (env_changed_id != env_id)) {
 		act = getenv("ethact");
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 13/23] sandbox: eth: Add network support to sandbox
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (11 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 12/23] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-03-01 18:07         ` Simon Glass
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 14/23] sandbox: eth: Add ARP and PING response to sandbox driver Joe Hershberger
                         ` (11 subsequent siblings)
  24 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

Add basic network support to sandbox which includes a network driver.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v4:
-Cleaned up sandbox EXTRA_ENV define
-Moved config to Kconfig

Changes in v3:
-Added 2 more ethaddr to sandbox
-Print which device in the debug write hwaddr

Changes in v2:
-Change printfs to debug in sandbox driver
-Remove unused priv struct for sandbox driver

 arch/sandbox/Kconfig         |  9 +++++
 arch/sandbox/dts/sandbox.dts |  4 +++
 board/sandbox/README.sandbox |  4 +--
 drivers/net/Kconfig          | 18 ++++++++++
 drivers/net/Makefile         |  1 +
 drivers/net/sandbox.c        | 84 ++++++++++++++++++++++++++++++++++++++++++++
 include/configs/sandbox.h    | 16 +++++----
 7 files changed, 128 insertions(+), 8 deletions(-)
 create mode 100644 drivers/net/sandbox.c

diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index 2098b9c..186b58d 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -34,4 +34,13 @@ config DM_I2C
 config DM_TEST
 	default y
 
+config NET
+	default y
+
+config NETDEVICES
+	default y
+
+config DM_ETH
+	default y
+
 endmenu
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 9ce31bf..36b3bd8 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -181,4 +181,8 @@
 		};
 	};
 
+	eth at 10002000 {
+		compatible = "sandbox,eth";
+		reg = <0x10002000 0x1000>;
+	};
 };
diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
index 3c0df17..c1f5f7e 100644
--- a/board/sandbox/README.sandbox
+++ b/board/sandbox/README.sandbox
@@ -173,16 +173,16 @@ U-Boot sandbox supports these emulations:
 - Chrome OS EC
 - GPIO
 - Host filesystem (access files on the host from within U-Boot)
+- I2C
 - Keyboard (Chrome OS)
 - LCD
+- Network
 - Serial (for console only)
 - Sound (incomplete - see sandbox_sdl_sound_init() for details)
 - SPI
 - SPI flash
 - TPM (Trusted Platform Module)
 
-Notable omissions are networking and I2C.
-
 A wide range of commands is implemented. Filesystems which use a block
 device are supported.
 
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index bdd0f05..b08746a 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -3,3 +3,21 @@ config DM_ETH
 	depends on DM
 	help
 	  Enable driver model for Ethernet.
+
+menuconfig NETDEVICES
+	bool "Network device support"
+	depends on NET
+	help
+	  You must select Y to enable any network device support
+	  Generally if you have any networking support this is a given
+
+	  If unsure, say Y
+
+if NETDEVICES
+
+config ETH_SANDBOX
+	depends on DM_ETH && SANDBOX
+	default y
+	bool "Sandbox: Mocked Ethernet driver"
+
+endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 46c4ac6..15dc431 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_NS8382X) += ns8382x.o
 obj-$(CONFIG_PCNET) += pcnet.o
 obj-$(CONFIG_RTL8139) += rtl8139.o
 obj-$(CONFIG_RTL8169) += rtl8169.o
+obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
 obj-$(CONFIG_SH_ETHER) += sh_eth.o
 obj-$(CONFIG_SMC91111) += smc91111.o
 obj-$(CONFIG_SMC911X) += smc911x.o
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
new file mode 100644
index 0000000..834e02a
--- /dev/null
+++ b/drivers/net/sandbox.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int sb_eth_start(struct udevice *dev)
+{
+	debug("eth_sandbox: Start\n");
+
+	return 0;
+}
+
+static int sb_eth_send(struct udevice *dev, void *packet, int length)
+{
+	debug("eth_sandbox: Send packet %d\n", length);
+
+	return 0;
+}
+
+static int sb_eth_recv(struct udevice *dev)
+{
+	return 0;
+}
+
+static void sb_eth_stop(struct udevice *dev)
+{
+	debug("eth_sandbox: Stop\n");
+}
+
+static int sb_eth_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	debug("eth_sandbox %s: Write HW ADDR - %pM\n", dev->name,
+	      pdata->enetaddr);
+	return 0;
+}
+
+static const struct eth_ops sb_eth_ops = {
+	.start			= sb_eth_start,
+	.send			= sb_eth_send,
+	.recv			= sb_eth_recv,
+	.stop			= sb_eth_stop,
+	.write_hwaddr		= sb_eth_write_hwaddr,
+};
+
+static int sb_eth_remove(struct udevice *dev)
+{
+	return 0;
+}
+
+static int sb_eth_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	pdata->iobase = dev_get_addr(dev);
+	return 0;
+}
+
+static const struct udevice_id sb_eth_ids[] = {
+	{ .compatible = "sandbox,eth" },
+	{ }
+};
+
+U_BOOT_DRIVER(eth_sandbox) = {
+	.name	= "eth_sandbox",
+	.id	= UCLASS_ETH,
+	.of_match = sb_eth_ids,
+	.ofdata_to_platdata = sb_eth_ofdata_to_platdata,
+	.remove	= sb_eth_remove,
+	.ops	= &sb_eth_ops,
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index febbfb6..664b984 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -126,9 +126,6 @@
 /* include default commands */
 #include <config_cmd_default.h>
 
-/* We don't have networking support yet */
-#undef CONFIG_CMD_NET
-#undef CONFIG_CMD_NFS
 
 #define CONFIG_CMD_HASH
 #define CONFIG_HASH_VERIFY
@@ -165,16 +162,23 @@
 
 #define CONFIG_KEYBOARD
 
-#define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial,cros-ec-keyb\0" \
+#define SANDBOX_SERIAL_SETTINGS		"stdin=serial,cros-ec-keyb\0" \
 					"stdout=serial,lcd\0" \
 					"stderr=serial,lcd\0"
 #else
-
-#define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial\0" \
+#define SANDBOX_SERIAL_SETTINGS		"stdin=serial\0" \
 					"stdout=serial,lcd\0" \
 					"stderr=serial,lcd\0"
 #endif
 
+#define SANDBOX_ETH_SETTINGS		"ethaddr=00:00:11:22:33:44\0" \
+					"eth1addr=00:00:11:22:33:45\0" \
+					"eth2addr=00:00:11:22:33:46\0" \
+					"ipaddr=1.2.3.4\0"
+
+#define CONFIG_EXTRA_ENV_SETTINGS	SANDBOX_SERIAL_SETTINGS \
+					SANDBOX_ETH_SETTINGS
+
 #define CONFIG_GZIP_COMPRESSED
 #define CONFIG_BZIP2
 #define CONFIG_LZO
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 14/23] sandbox: eth: Add ARP and PING response to sandbox driver
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (12 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 13/23] sandbox: eth: Add network support to sandbox Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 15/23] test: dm: eth: Add tests for the eth dm implementation Joe Hershberger
                         ` (10 subsequent siblings)
  24 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

The sandbox driver will now generate response traffic to exercise the
ping command even when no network exists.  This allows the basic data
pathways of the DM to be tested.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v4:
-Removed checks on priv != NULL and added protection in uclass instead

Changes in v3:
-Prevent a crash if memory is not allocated

Changes in v2:
-Change printfs to debug in sandbox driver
-Move static data to priv
-Move fake hwaddr to the device tree

 arch/sandbox/dts/sandbox.dts |   1 +
 drivers/net/sandbox.c        | 111 +++++++++++++++++++++++++++++++++++++++++++
 include/configs/sandbox.h    |   1 +
 3 files changed, 113 insertions(+)

diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 36b3bd8..235dcc0 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -184,5 +184,6 @@
 	eth at 10002000 {
 		compatible = "sandbox,eth";
 		reg = <0x10002000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
 	};
 };
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
index 834e02a..81362e6 100644
--- a/drivers/net/sandbox.c
+++ b/drivers/net/sandbox.c
@@ -14,22 +14,132 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/**
+ * struct eth_sandbox_priv - memory for sandbox mock driver
+ *
+ * fake_host_hwaddr: MAC address of mocked machine
+ * fake_host_ipaddr: IP address of mocked machine
+ * recv_packet_buffer: buffer of the packet returned as received
+ * recv_packet_length: length of the packet returned as received
+ */
+struct eth_sandbox_priv {
+	uchar fake_host_hwaddr[ARP_HLEN];
+	IPaddr_t fake_host_ipaddr;
+	uchar recv_packet_buffer[PKTSIZE];
+	int recv_packet_length;
+};
+
 static int sb_eth_start(struct udevice *dev)
 {
+	struct eth_sandbox_priv *priv = dev_get_priv(dev);
+	u32 int_array[ARP_HLEN];
+	int i;
+
 	debug("eth_sandbox: Start\n");
 
+	fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "fake-host-hwaddr",
+			     int_array, ARP_HLEN);
+	for (i = 0; i < ARP_HLEN; i++)
+		priv->fake_host_hwaddr[i] = (uchar)int_array[i];
+
 	return 0;
 }
 
 static int sb_eth_send(struct udevice *dev, void *packet, int length)
 {
+	struct eth_sandbox_priv *priv = dev_get_priv(dev);
+	struct ethernet_hdr *eth = packet;
+
 	debug("eth_sandbox: Send packet %d\n", length);
 
+	if (ntohs(eth->et_protlen) == PROT_ARP) {
+		struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
+
+		if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
+			struct ethernet_hdr *eth_recv;
+			struct arp_hdr *arp_recv;
+
+			/* store this as the assumed IP of the fake host */
+			priv->fake_host_ipaddr = NetReadIP(&arp->ar_tpa);
+			/* Formulate a fake response */
+			eth_recv = (void *)priv->recv_packet_buffer;
+			memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
+			memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
+			       ARP_HLEN);
+			eth_recv->et_protlen = htons(PROT_ARP);
+
+			arp_recv = (void *)priv->recv_packet_buffer +
+				ETHER_HDR_SIZE;
+			arp_recv->ar_hrd = htons(ARP_ETHER);
+			arp_recv->ar_pro = htons(PROT_IP);
+			arp_recv->ar_hln = ARP_HLEN;
+			arp_recv->ar_pln = ARP_PLEN;
+			arp_recv->ar_op = htons(ARPOP_REPLY);
+			memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr,
+			       ARP_HLEN);
+			NetWriteIP(&arp_recv->ar_spa, priv->fake_host_ipaddr);
+			memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN);
+			NetCopyIP(&arp_recv->ar_tpa, &arp->ar_spa);
+
+			priv->recv_packet_length = ETHER_HDR_SIZE +
+				ARP_HDR_SIZE;
+		}
+	} else if (ntohs(eth->et_protlen) == PROT_IP) {
+		struct ip_udp_hdr *ip = packet + ETHER_HDR_SIZE;
+
+		if (ip->ip_p == IPPROTO_ICMP) {
+			struct icmp_hdr *icmp = (struct icmp_hdr *)&ip->udp_src;
+
+			if (icmp->type == ICMP_ECHO_REQUEST) {
+				struct ethernet_hdr *eth_recv;
+				struct ip_udp_hdr *ipr;
+				struct icmp_hdr *icmpr;
+
+				/* reply to the ping */
+				memcpy(priv->recv_packet_buffer, packet,
+				       length);
+				eth_recv = (void *)priv->recv_packet_buffer;
+				ipr = (void *)priv->recv_packet_buffer +
+					ETHER_HDR_SIZE;
+				icmpr = (struct icmp_hdr *)&ipr->udp_src;
+				memcpy(eth_recv->et_dest, eth->et_src,
+				       ARP_HLEN);
+				memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
+				       ARP_HLEN);
+				ipr->ip_sum = 0;
+				ipr->ip_off = 0;
+				NetCopyIP((void *)&ipr->ip_dst, &ip->ip_src);
+				NetWriteIP((void *)&ipr->ip_src,
+					   priv->fake_host_ipaddr);
+				ipr->ip_sum = compute_ip_checksum(ipr,
+					IP_HDR_SIZE);
+
+				icmpr->type = ICMP_ECHO_REPLY;
+				icmpr->checksum = 0;
+				icmpr->checksum = compute_ip_checksum(icmpr,
+					ICMP_HDR_SIZE);
+
+				priv->recv_packet_length = length;
+			}
+		}
+	}
+
 	return 0;
 }
 
 static int sb_eth_recv(struct udevice *dev)
 {
+	struct eth_sandbox_priv *priv = dev_get_priv(dev);
+
+	if (priv->recv_packet_length) {
+		int lcl_recv_packet_length = priv->recv_packet_length;
+
+		debug("eth_sandbox: received packet %d\n",
+		      priv->recv_packet_length);
+		priv->recv_packet_length = 0;
+		NetReceive((void *)priv->recv_packet_buffer,
+			   lcl_recv_packet_length);
+	}
 	return 0;
 }
 
@@ -80,5 +190,6 @@ U_BOOT_DRIVER(eth_sandbox) = {
 	.ofdata_to_platdata = sb_eth_ofdata_to_platdata,
 	.remove	= sb_eth_remove,
 	.ops	= &sb_eth_ops,
+	.priv_auto_alloc_size = sizeof(struct eth_sandbox_priv),
 	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
 };
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 664b984..9189f6a 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -126,6 +126,7 @@
 /* include default commands */
 #include <config_cmd_default.h>
 
+#define CONFIG_CMD_PING
 
 #define CONFIG_CMD_HASH
 #define CONFIG_HASH_VERIFY
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 15/23] test: dm: eth: Add tests for the eth dm implementation
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (13 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 14/23] sandbox: eth: Add ARP and PING response to sandbox driver Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 16/23] dm: eth: Add support for aliases Joe Hershberger
                         ` (9 subsequent siblings)
  24 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

Add a test for the eth uclass using the sandbox eth driver. Verify basic
functionality of the network stack / eth uclass by exercising the ping
function.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v4: None
Changes in v3:
-Added dm eth testing

Changes in v2: None

 test/dm/Makefile |  1 +
 test/dm/eth.c    | 38 ++++++++++++++++++++++++++++++++++++++
 test/dm/test.dts | 18 ++++++++++++++++++
 3 files changed, 57 insertions(+)
 create mode 100644 test/dm/eth.c

diff --git a/test/dm/Makefile b/test/dm/Makefile
index 1d9148f..b2eb989 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_DM_TEST) += ut.o
 obj-$(CONFIG_DM_TEST) += core.o
 obj-$(CONFIG_DM_TEST) += ut.o
 ifneq ($(CONFIG_SANDBOX),)
+obj-$(CONFIG_DM_ETH) += eth.o
 obj-$(CONFIG_DM_GPIO) += gpio.o
 obj-$(CONFIG_DM_I2C) += i2c.o
 obj-$(CONFIG_DM_SPI_FLASH) += sf.o
diff --git a/test/dm/eth.c b/test/dm/eth.c
new file mode 100644
index 0000000..04ccf49
--- /dev/null
+++ b/test/dm/eth.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <dm/ut.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int dm_test_eth(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+
+	setenv("ethact", "eth at 10002000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	setenv("ethact", "eth at 10003000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10003000", getenv("ethact"));
+
+	setenv("ethact", "eth at 10004000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	return 0;
+}
+DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
diff --git a/test/dm/test.dts b/test/dm/test.dts
index 84024a4..2f68cdf 100644
--- a/test/dm/test.dts
+++ b/test/dm/test.dts
@@ -149,4 +149,22 @@
 		};
 	};
 
+	eth at 10002000 {
+		compatible = "sandbox,eth";
+		reg = <0x10002000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
+	};
+
+	eth at 10003000 {
+		compatible = "sandbox,eth";
+		reg = <0x10003000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
+	};
+
+	eth at 10004000 {
+		compatible = "sandbox,eth";
+		reg = <0x10004000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x22>;
+	};
+
 };
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 16/23] dm: eth: Add support for aliases
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (14 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 15/23] test: dm: eth: Add tests for the eth dm implementation Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-03-01 18:07         ` Simon Glass
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 17/23] dm: eth: Add support for ethprime env var Joe Hershberger
                         ` (8 subsequent siblings)
  24 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

Allow network devices to be referred to as "eth0" instead of
"eth at 12345678" when specified in ethact.

Add tests to verify this behavior.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v4:
-Use only the seq from DM to find aliases

Changes in v3:
-Added support for aliases

Changes in v2: None

 include/configs/sandbox.h |  2 +-
 include/net.h             |  1 +
 net/eth.c                 | 47 ++++++++++++++++++++++++++++++++++++++---------
 test/dm/eth.c             | 24 ++++++++++++++++++++++++
 test/dm/test.dts          |  4 +++-
 5 files changed, 67 insertions(+), 11 deletions(-)

diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 9189f6a..caf9f5a 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -174,7 +174,7 @@
 
 #define SANDBOX_ETH_SETTINGS		"ethaddr=00:00:11:22:33:44\0" \
 					"eth1addr=00:00:11:22:33:45\0" \
-					"eth2addr=00:00:11:22:33:46\0" \
+					"eth5addr=00:00:11:22:33:46\0" \
 					"ipaddr=1.2.3.4\0"
 
 #define CONFIG_EXTRA_ENV_SETTINGS	SANDBOX_SERIAL_SETTINGS \
diff --git a/include/net.h b/include/net.h
index 508c572..e9cb4a3 100644
--- a/include/net.h
+++ b/include/net.h
@@ -122,6 +122,7 @@ struct eth_ops {
 #define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
 
 struct udevice *eth_get_dev(void); /* get the current device */
+struct udevice *eth_get_dev_by_name(const char *devname);
 unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
 /* Used only when NetConsole is enabled */
 int eth_init_state_only(void); /* Set active state */
diff --git a/net/eth.c b/net/eth.c
index 9c2dfb9..8b853e8 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -132,6 +132,36 @@ static void eth_set_dev(struct udevice *dev)
 	eth_get_uclass_priv()->current = dev;
 }
 
+/*
+ * Find the udevice that either has the name passed in as devname or has an
+ * alias named devname.
+ */
+struct udevice *eth_get_dev_by_name(const char *devname)
+{
+	int seq;
+	char *endp = NULL;
+	const char *startp;
+	struct udevice *it;
+	struct uclass *uc;
+
+	startp = devname + strlen("eth");
+	seq = simple_strtoul(startp, &endp, 10);
+
+	uclass_get(UCLASS_ETH, &uc);
+	uclass_foreach_dev(it, uc) {
+		/* We need the seq to be valid, so make sure it's probed */
+		device_probe(it);
+		/*
+		 * Check for the name or the sequence number to match
+		 */
+		if (strcmp(it->name, devname) == 0 ||
+		    (endp > startp && it->seq == seq))
+			return it;
+	}
+
+	return NULL;
+}
+
 unsigned char *eth_get_ethaddr(void)
 {
 	struct eth_pdata *pdata;
@@ -405,6 +435,7 @@ UCLASS_DRIVER(eth) = {
 	.pre_remove	= eth_pre_remove,
 	.priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
 	.per_device_auto_alloc_size = sizeof(struct eth_device_priv),
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 };
 #endif
 
@@ -437,6 +468,11 @@ static void eth_set_current_to_next(void)
 	eth_current = eth_current->next;
 }
 
+static void eth_set_dev(struct eth_device *dev)
+{
+	eth_current = dev;
+}
+
 struct eth_device *eth_get_dev_by_name(const char *devname)
 {
 	struct eth_device *dev, *target_dev;
@@ -853,7 +889,6 @@ void eth_set_current(void)
 {
 	static char *act;
 	static int  env_changed_id;
-	void *old_current;
 	int	env_id;
 
 	env_id = get_env_id();
@@ -861,14 +896,8 @@ void eth_set_current(void)
 		act = getenv("ethact");
 		env_changed_id = env_id;
 	}
-	if (act != NULL) {
-		old_current = eth_get_dev();
-		do {
-			if (strcmp(eth_get_name(), act) == 0)
-				return;
-			eth_set_current_to_next();
-		} while (old_current != eth_get_dev());
-	}
+	if (act != NULL)
+		eth_set_dev(eth_get_dev_by_name(act));
 
 	eth_current_changed();
 }
diff --git a/test/dm/eth.c b/test/dm/eth.c
index 04ccf49..5688b71 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -36,3 +36,27 @@ static int dm_test_eth(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
+
+static int dm_test_eth_alias(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+	setenv("ethact", "eth0");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	setenv("ethact", "eth1");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	/* Expected to fail since eth2 is not defined in the device tree */
+	setenv("ethact", "eth2");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	setenv("ethact", "eth5");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10003000", getenv("ethact"));
+
+	return 0;
+}
+DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
diff --git a/test/dm/test.dts b/test/dm/test.dts
index 2f68cdf..bc2409d 100644
--- a/test/dm/test.dts
+++ b/test/dm/test.dts
@@ -17,6 +17,8 @@
 		testfdt3 = "/b-test";
 		testfdt5 = "/some-bus/c-test at 5";
 		testfdt8 = "/a-test";
+		eth0 = "/eth at 10002000";
+		eth5 = &eth_5;
 	};
 
 	uart0: serial {
@@ -155,7 +157,7 @@
 		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
 	};
 
-	eth at 10003000 {
+	eth_5: eth at 10003000 {
 		compatible = "sandbox,eth";
 		reg = <0x10003000 0x1000>;
 		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 17/23] dm: eth: Add support for ethprime env var
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (15 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 16/23] dm: eth: Add support for aliases Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-03-01 18:07         ` Simon Glass
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 18/23] test: dm: eth: Add testing for ethrotate " Joe Hershberger
                         ` (7 subsequent siblings)
  24 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

The ethprime env var is used to indicate the starting device if none is
specified in ethact. Also support aliases specified in the ethprime var.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v4:
-Load from ethprime on eth_initialize()

Changes in v3:
-Added support for ethprime

Changes in v2: None

 net/eth.c     | 29 ++++++++++++++++++++++++++++-
 test/dm/eth.c | 20 ++++++++++++++++++++
 2 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/net/eth.c b/net/eth.c
index 8b853e8..3b3cd84 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -341,6 +341,18 @@ int eth_initialize(void)
 		printf("No ethernet found.\n");
 		bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
 	} else {
+		char *ethprime = getenv("ethprime");
+		struct udevice *prime_dev = NULL;
+
+		if (ethprime)
+			prime_dev = eth_get_dev_by_name(ethprime);
+		if (prime_dev) {
+			eth_set_dev(prime_dev);
+			eth_current_changed();
+		} else {
+			eth_set_dev(NULL);
+		}
+
 		bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
 		do {
 			if (num_devices)
@@ -348,6 +360,9 @@ int eth_initialize(void)
 
 			printf("eth%d: %s", dev->seq, dev->name);
 
+			if (ethprime && dev == prime_dev)
+				printf(" [PRIME]");
+
 			eth_write_hwaddr(dev);
 
 			uclass_next_device(&dev);
@@ -896,8 +911,20 @@ void eth_set_current(void)
 		act = getenv("ethact");
 		env_changed_id = env_id;
 	}
-	if (act != NULL)
+
+	if (act == NULL) {
+		char *ethprime = getenv("ethprime");
+		struct udevice *dev = NULL;
+
+		if (ethprime)
+			dev = eth_get_dev_by_name(ethprime);
+		if (dev)
+			eth_set_dev(dev);
+		else
+			eth_set_dev(NULL);
+	} else {
 		eth_set_dev(eth_get_dev_by_name(act));
+	}
 
 	eth_current_changed();
 }
diff --git a/test/dm/eth.c b/test/dm/eth.c
index 5688b71..96e3c46 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -60,3 +60,23 @@ static int dm_test_eth_alias(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
+
+static int dm_test_eth_prime(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+
+	/* Expected to be "eth at 10003000" because of ethprime variable */
+	setenv("ethact", NULL);
+	setenv("ethprime", "eth5");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10003000", getenv("ethact"));
+
+	/* Expected to be "eth at 10002000" because it is first */
+	setenv("ethact", NULL);
+	setenv("ethprime", NULL);
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	return 0;
+}
+DM_TEST(dm_test_eth_prime, DM_TESTF_SCAN_FDT);
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 18/23] test: dm: eth: Add testing for ethrotate env var
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (16 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 17/23] dm: eth: Add support for ethprime env var Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-03-01 18:07         ` Simon Glass
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 19/23] sandbox: eth: Add ability to disable ping reply in sandbox eth driver Joe Hershberger
                         ` (6 subsequent siblings)
  24 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

Make sure that the ethrotate behavior occurs as expected.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v4:
-Added testing for ethrotate

Changes in v3: None
Changes in v2: None

 test/dm/eth.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/test/dm/eth.c b/test/dm/eth.c
index 96e3c46..a3cbd3f 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -80,3 +80,27 @@ static int dm_test_eth_prime(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_eth_prime, DM_TESTF_SCAN_FDT);
+
+static int dm_test_eth_rotate(struct dm_test_state *dms)
+{
+	char ethaddr[18];
+
+	NetPingIP = string_to_ip("1.1.2.2");
+	strcpy(ethaddr, getenv("eth1addr"));
+	setenv("ethact", "eth at 10004000");
+	setenv("eth1addr", NULL);
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	setenv("ethact", "eth at 10004000");
+	setenv("ethrotate", "no");
+	ut_asserteq(-1, NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	/* Restore the env */
+	setenv("eth1addr", ethaddr);
+	setenv("ethrotate", NULL);
+
+	return 0;
+}
+DM_TEST(dm_test_eth_rotate, DM_TESTF_SCAN_FDT);
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 19/23] sandbox: eth: Add ability to disable ping reply in sandbox eth driver
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (17 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 18/23] test: dm: eth: Add testing for ethrotate " Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-03-01 18:07         ` Simon Glass
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 20/23] test: dm: net: Add a test of the netretry behavior Joe Hershberger
                         ` (5 subsequent siblings)
  24 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

This is needed to test the netretry functionality (make the command fail
on a sandbox eth device).

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v4:
-Add ability to disable ping reply in sandbox eth driver

Changes in v3: None
Changes in v2: None

 drivers/net/sandbox.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
index 81362e6..28fe09a 100644
--- a/drivers/net/sandbox.c
+++ b/drivers/net/sandbox.c
@@ -49,9 +49,14 @@ static int sb_eth_send(struct udevice *dev, void *packet, int length)
 {
 	struct eth_sandbox_priv *priv = dev_get_priv(dev);
 	struct ethernet_hdr *eth = packet;
+	char varname[32];
 
 	debug("eth_sandbox: Send packet %d\n", length);
 
+	sprintf(varname, "eth_sandbox_disable_%d", dev->seq);
+	if (getenv_yesno(varname) > 0)
+		return 0;
+
 	if (ntohs(eth->et_protlen) == PROT_ARP) {
 		struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
 
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 20/23] test: dm: net: Add a test of the netretry behavior
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (18 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 19/23] sandbox: eth: Add ability to disable ping reply in sandbox eth driver Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-03-01 18:07         ` Simon Glass
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 21/23] sandbox: eth: Add a bridge to a real network for sandbox Joe Hershberger
                         ` (4 subsequent siblings)
  24 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

The effect of the "netretry" env var was recently changed. This test
checks that behavior.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v4:
-Updated expected behavior based on changes to the NetLoop

Changes in v3:
-Added testing for netretry

Changes in v2: None

 test/dm/eth.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/test/dm/eth.c b/test/dm/eth.c
index a3cbd3f..4581c8e 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -104,3 +104,26 @@ static int dm_test_eth_rotate(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_eth_rotate, DM_TESTF_SCAN_FDT);
+
+static int dm_test_net_retry(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+
+	setenv("eth_sandbox_disable_1", "yes");
+	setenv("ethact", "eth at 10004000");
+	setenv("netretry", "yes");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	setenv("ethact", "eth at 10004000");
+	setenv("netretry", "no");
+	ut_asserteq(-1, NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	/* Restore the env */
+	setenv("netretry", NULL);
+	setenv("eth_sandbox_disable_1", NULL);
+
+	return 0;
+}
+DM_TEST(dm_test_net_retry, DM_TESTF_SCAN_FDT);
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 21/23] sandbox: eth: Add a bridge to a real network for sandbox
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (19 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 20/23] test: dm: net: Add a test of the netretry behavior Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-03-01 18:07         ` Simon Glass
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 22/23] sandbox: Enable DHCP and IP defrag Joe Hershberger
                         ` (3 subsequent siblings)
  24 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

Implement a bridge between u-boot's network stack and Linux's raw packet
API allowing the sandbox to send and receive packets using the host
machine's network interface.

This raw Ethernet API requires elevated privileges.  You can either run
as root, or you can add the capability needed like so:

sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v4:
-Added comments to README.sandbox
-Use accessors for platdata and priv
-Add comments to priv struct definition
-Move os file to arch
-Cleanup var definition order
-Moved config to Kconfig
-Clean up the interface to sandbox's eth-raw-os by passing priv to raw-os
-Fixed the MAC address limitation (now all traffic uses MAC address from env)

Changes in v3:
-Made the os raw packet support for sandbox eth build and work.

Changes in v2:
-Added the raw packet proof-of-concept patch.

 arch/sandbox/Kconfig                  |   3 +
 arch/sandbox/cpu/Makefile             |  10 ++++
 arch/sandbox/cpu/eth-raw-os.c         | 102 +++++++++++++++++++++++++++++++++
 arch/sandbox/dts/sandbox.dts          |   6 ++
 arch/sandbox/include/asm/eth-raw-os.h |  32 +++++++++++
 board/sandbox/README.sandbox          |  13 +++++
 drivers/net/Kconfig                   |   5 ++
 drivers/net/Makefile                  |   1 +
 drivers/net/sandbox-raw.c             | 105 ++++++++++++++++++++++++++++++++++
 9 files changed, 277 insertions(+)
 create mode 100644 arch/sandbox/cpu/eth-raw-os.c
 create mode 100644 arch/sandbox/include/asm/eth-raw-os.h
 create mode 100644 drivers/net/sandbox-raw.c

diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index 186b58d..f84b3fc 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -43,4 +43,7 @@ config NETDEVICES
 config DM_ETH
 	default y
 
+config ETH_SANDBOX_RAW
+	default y
+
 endmenu
diff --git a/arch/sandbox/cpu/Makefile b/arch/sandbox/cpu/Makefile
index 7d4410c..1b42fee 100644
--- a/arch/sandbox/cpu/Makefile
+++ b/arch/sandbox/cpu/Makefile
@@ -8,6 +8,7 @@
 #
 
 obj-y	:= cpu.o os.o start.o state.o
+obj-$(CONFIG_ETH_SANDBOX_RAW)	+= eth-raw-os.o
 obj-$(CONFIG_SANDBOX_SDL)	+= sdl.o
 
 # os.c is build in the system environment, so needs standard includes
@@ -20,3 +21,12 @@ $(obj)/os.o: $(src)/os.c FORCE
 	$(call if_changed_dep,cc_os.o)
 $(obj)/sdl.o: $(src)/sdl.c FORCE
 	$(call if_changed_dep,cc_os.o)
+
+# eth-raw-os.c is built in the system env, so needs standard includes
+# CFLAGS_REMOVE_eth-raw-os.o cannot be used to drop header include path
+quiet_cmd_cc_eth-raw-os.o = CC $(quiet_modtag)  $@
+cmd_cc_eth-raw-os.o = $(CC) $(filter-out -nostdinc, \
+	$(patsubst -I%,-idirafter%,$(c_flags))) -c -o $@ $<
+
+$(obj)/eth-raw-os.o: $(src)/eth-raw-os.c FORCE
+	$(call if_changed_dep,cc_eth-raw-os.o)
diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c
new file mode 100644
index 0000000..9218f94
--- /dev/null
+++ b/arch/sandbox/cpu/eth-raw-os.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <asm/eth-raw-os.h>
+#include <errno.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+
+int sandbox_eth_raw_os_init(const char *ifname, unsigned char *ethmac,
+			    struct eth_sandbox_raw_priv *priv)
+{
+	struct sockaddr_ll *device;
+	struct packet_mreq mr;
+
+	/* Prepare device struct */
+	priv->device = malloc(sizeof(struct sockaddr_ll));
+	device = priv->device;
+	memset(device, 0, sizeof(struct sockaddr_ll));
+	device->sll_ifindex = if_nametoindex(ifname);
+	device->sll_family = AF_PACKET;
+	memcpy(device->sll_addr, ethmac, 6);
+	device->sll_halen = htons(6);
+
+	/* Open socket */
+	priv->sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+	if (priv->sd < 0) {
+		printf("Failed to open socket: %d %s\n", errno,
+		       strerror(errno));
+		return -errno;
+	}
+	/* Bind to the specified interface */
+	setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
+		   strlen(ifname) + 1);
+
+	/* Enable promiscuous mode to receive responses meant for us */
+	mr.mr_ifindex = device->sll_ifindex;
+	mr.mr_type = PACKET_MR_PROMISC;
+	setsockopt(priv->sd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
+		   &mr, sizeof(mr));
+	return 0;
+}
+
+int sandbox_eth_raw_os_send(void *packet, int length,
+			    const struct eth_sandbox_raw_priv *priv)
+{
+	int retval;
+
+	if (!priv->sd || !priv->device)
+		return -EINVAL;
+
+	retval = sendto(priv->sd, packet, length, 0,
+			(struct sockaddr *)priv->device,
+			sizeof(struct sockaddr_ll));
+	if (retval < 0)
+		printf("Failed to send packet: %d %s\n", errno,
+		       strerror(errno));
+	return retval;
+}
+
+int sandbox_eth_raw_os_recv(void *packet, int *length,
+			    const struct eth_sandbox_raw_priv *priv)
+{
+	int retval;
+	int saddr_size;
+
+	if (!priv->sd || !priv->device)
+		return -EINVAL;
+	saddr_size = sizeof(struct sockaddr);
+	retval = recvfrom(priv->sd, packet, 1536, 0,
+			  (struct sockaddr *)priv->device,
+			  (socklen_t *)&saddr_size);
+	*length = 0;
+	if (retval > 0) {
+		*length = retval;
+		return 0;
+	}
+	return retval;
+}
+
+void sandbox_eth_raw_os_halt(struct eth_sandbox_raw_priv *priv)
+{
+	free((struct sockaddr_ll *)priv->device);
+	priv->device = NULL;
+	close(priv->sd);
+	priv->sd = -1;
+}
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 235dcc0..b6762f4 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -186,4 +186,10 @@
 		reg = <0x10002000 0x1000>;
 		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
 	};
+
+	eth at 80000000 {
+		compatible = "sandbox,eth-raw";
+		reg = <0x80000000 0x1000>;
+		host-raw-interface = "eth0";
+	};
 };
diff --git a/arch/sandbox/include/asm/eth-raw-os.h b/arch/sandbox/include/asm/eth-raw-os.h
new file mode 100644
index 0000000..d92b72c
--- /dev/null
+++ b/arch/sandbox/include/asm/eth-raw-os.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __ETH_RAW_OS_H
+#define __ETH_RAW_OS_H
+
+/**
+ * struct eth_sandbox_raw_priv - raw socket session
+ *
+ * sd: socket descriptor - the open socket during a session
+ * device: struct sockaddr_ll - the host interface packets move to/from
+ */
+struct eth_sandbox_raw_priv {
+	int sd;
+	void *device;
+};
+
+int sandbox_eth_raw_os_init(const char *ifname, unsigned char *ethmac,
+			    struct eth_sandbox_raw_priv *priv);
+int sandbox_eth_raw_os_send(void *packet, int length,
+			    const struct eth_sandbox_raw_priv *priv);
+int sandbox_eth_raw_os_recv(void *packet, int *length,
+			    const struct eth_sandbox_raw_priv *priv);
+void sandbox_eth_raw_os_halt(struct eth_sandbox_raw_priv *priv);
+
+#endif /* __ETH_RAW_OS_H */
diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
index c1f5f7e..c4c3139 100644
--- a/board/sandbox/README.sandbox
+++ b/board/sandbox/README.sandbox
@@ -190,6 +190,19 @@ Also sandbox uses generic board (CONFIG_SYS_GENERIC_BOARD) and supports
 driver model (CONFIG_DM) and associated commands.
 
 
+Linux RAW Networking Bridge
+---------------------------
+
+The sandbox_eth_raw driver bridges traffic between the bottom of the network
+stack and the RAW sockets API in Linux. This allows much of the u-boot network
+functionality to be tested in sandbox against real network traffic.
+
+The RAW sockets Ethernet API requires elevated privileges in Linux. You can
+either run as root, or you can add the capability needed like so:
+
+sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot
+
+
 SPI Emulation
 -------------
 
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index b08746a..dcbfa8a 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -20,4 +20,9 @@ config ETH_SANDBOX
 	default y
 	bool "Sandbox: Mocked Ethernet driver"
 
+config ETH_SANDBOX_RAW
+	depends on DM_ETH && SANDBOX
+	default y
+	bool "Sandbox: Bridge to Linux Raw Sockets"
+
 endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 15dc431..2659a8a 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_PCNET) += pcnet.o
 obj-$(CONFIG_RTL8139) += rtl8139.o
 obj-$(CONFIG_RTL8169) += rtl8169.o
 obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
+obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o
 obj-$(CONFIG_SH_ETHER) += sh_eth.o
 obj-$(CONFIG_SMC91111) += smc91111.o
 obj-$(CONFIG_SMC911X) += smc911x.o
diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
new file mode 100644
index 0000000..01b33a9
--- /dev/null
+++ b/drivers/net/sandbox-raw.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <asm/eth-raw-os.h>
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+
+static int sb_eth_raw_start(struct udevice *dev)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	int retval;
+	const char *interface;
+
+	debug("eth_sandbox_raw: Start\n");
+
+	interface = fdt_getprop(gd->fdt_blob, dev->of_offset,
+					    "host-raw-interface", NULL);
+
+	retval = sandbox_eth_raw_os_init(interface, pdata->enetaddr, priv);
+
+	return retval;
+}
+
+static int sb_eth_raw_send(struct udevice *dev, void *packet, int length)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+
+	debug("eth_sandbox_raw: Send packet %d\n", length);
+
+	return sandbox_eth_raw_os_send(packet, length, priv);
+}
+
+static int sb_eth_raw_recv(struct udevice *dev)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+	int retval;
+	uchar buffer[PKTSIZE];
+	int length;
+
+	retval = sandbox_eth_raw_os_recv(buffer, &length, priv);
+
+	if (!retval && length) {
+		debug("eth_sandbox_raw: received packet %d\n",
+		      length);
+		NetReceive(buffer, length);
+	}
+	return 0;
+}
+
+static void sb_eth_raw_stop(struct udevice *dev)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+
+	debug("eth_sandbox_raw: Stop\n");
+
+	sandbox_eth_raw_os_halt(priv);
+}
+
+static const struct eth_ops sb_eth_raw_ops = {
+	.start			= sb_eth_raw_start,
+	.send			= sb_eth_raw_send,
+	.recv			= sb_eth_raw_recv,
+	.stop			= sb_eth_raw_stop,
+};
+
+static int sb_eth_raw_remove(struct udevice *dev)
+{
+	return 0;
+}
+
+static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	pdata->iobase = dev_get_addr(dev);
+	return 0;
+}
+
+static const struct udevice_id sb_eth_raw_ids[] = {
+	{ .compatible = "sandbox,eth-raw" },
+	{ }
+};
+
+U_BOOT_DRIVER(eth_sandbox_raw) = {
+	.name	= "eth_sandbox_raw",
+	.id	= UCLASS_ETH,
+	.of_match = sb_eth_raw_ids,
+	.ofdata_to_platdata = sb_eth_raw_ofdata_to_platdata,
+	.remove	= sb_eth_raw_remove,
+	.ops	= &sb_eth_raw_ops,
+	.priv_auto_alloc_size = sizeof(struct eth_sandbox_raw_priv),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 22/23] sandbox: Enable DHCP and IP defrag
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (20 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 21/23] sandbox: eth: Add a bridge to a real network for sandbox Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-03-01 18:07         ` Simon Glass
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 23/23] sandbox: eth: Add support for using the 'lo' interface Joe Hershberger
                         ` (2 subsequent siblings)
  24 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

This is now testable via the eth-raw interface

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 include/configs/sandbox.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index caf9f5a..034050e 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -127,6 +127,14 @@
 #include <config_cmd_default.h>
 
 #define CONFIG_CMD_PING
+#define CONFIG_CMD_DHCP
+#define CONFIG_BOOTP_DNS
+#define CONFIG_BOOTP_DNS2
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_SEND_HOSTNAME
+#define CONFIG_BOOTP_SERVERIP
+#define CONFIG_BOOTP_SUBNETMASK
+#define CONFIG_IP_DEFRAG
 
 #define CONFIG_CMD_HASH
 #define CONFIG_HASH_VERIFY
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 23/23] sandbox: eth: Add support for using the 'lo' interface
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (21 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 22/23] sandbox: Enable DHCP and IP defrag Joe Hershberger
@ 2015-02-25  0:02       ` Joe Hershberger
  2015-03-01 18:07         ` Simon Glass
  2015-03-01 16:13       ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Simon Glass
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
  24 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-02-25  0:02 UTC (permalink / raw)
  To: u-boot

The 'lo' interface on Linux doesn't support thinks like ARP or
link-layer access like we use to talk to a normal network interface.
A higher-level network API must be used to access localhost.

As written, this interface is limited to not supporting ICMP since the
API doesn't allow the socket to be opened for all IP traffic and be able
to receive at the same time. UDP is far more useful to test with, so it
was selected over ICMP. Ping won't work, but things like TFTP should
work.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v4:
-Added support for the 'lo' network interface

Changes in v3: None
Changes in v2: None

 arch/sandbox/cpu/eth-raw-os.c         | 152 +++++++++++++++++++++++++++-------
 arch/sandbox/dts/sandbox.dts          |  10 +++
 arch/sandbox/include/asm/eth-raw-os.h |  10 ++-
 drivers/net/sandbox-raw.c             |  62 +++++++++++++-
 4 files changed, 203 insertions(+), 31 deletions(-)

diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c
index 9218f94..acb150a 100644
--- a/arch/sandbox/cpu/eth-raw-os.c
+++ b/arch/sandbox/cpu/eth-raw-os.c
@@ -11,6 +11,8 @@
 #include <errno.h>
 #include <net/if.h>
 #include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -19,51 +21,139 @@
 #include <sys/socket.h>
 #include <unistd.h>
 
+#include <arpa/inet.h>
 #include <linux/if_ether.h>
 #include <linux/if_packet.h>
 
 int sandbox_eth_raw_os_init(const char *ifname, unsigned char *ethmac,
 			    struct eth_sandbox_raw_priv *priv)
 {
-	struct sockaddr_ll *device;
-	struct packet_mreq mr;
-
-	/* Prepare device struct */
-	priv->device = malloc(sizeof(struct sockaddr_ll));
-	device = priv->device;
-	memset(device, 0, sizeof(struct sockaddr_ll));
-	device->sll_ifindex = if_nametoindex(ifname);
-	device->sll_family = AF_PACKET;
-	memcpy(device->sll_addr, ethmac, 6);
-	device->sll_halen = htons(6);
-
-	/* Open socket */
-	priv->sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
-	if (priv->sd < 0) {
-		printf("Failed to open socket: %d %s\n", errno,
-		       strerror(errno));
-		return -errno;
+	if (priv->local) {
+		struct sockaddr_in *device;
+		int ret;
+		struct timeval tv;
+		int one = 1;
+
+		/* Prepare device struct */
+		priv->device = malloc(sizeof(struct sockaddr_in));
+		device = priv->device;
+		memset(device, 0, sizeof(struct sockaddr_in));
+		device->sin_family = AF_INET;
+		ret = inet_pton(AF_INET, "127.0.0.1",
+			  (struct in_addr *)&device->sin_addr.s_addr);
+		if (ret < 0) {
+			printf("Failed to convert address: %d %s\n", errno,
+			       strerror(errno));
+			return -errno;
+		}
+
+		/**
+		 * Open socket
+		 *  Since we specify UDP here, any incoming ICMP packets will
+		 *  not be received, so things like ping will not work on this
+		 *  localhost interface.
+		 */
+		priv->sd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
+		if (priv->sd < 0) {
+			printf("Failed to open socket: %d %s\n", errno,
+			       strerror(errno));
+			return -errno;
+		}
+
+		/* Allow the receive to timeout after a millisecond */
+		tv.tv_sec = 0;
+		tv.tv_usec = 1000;
+		ret = setsockopt(priv->sd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,
+			   sizeof(struct timeval));
+		if (ret < 0) {
+			printf("Failed to set opt: %d %s\n", errno,
+			       strerror(errno));
+			return -errno;
+		}
+
+		/* Include the UDP/IP headers on send and receive */
+		ret = setsockopt(priv->sd, IPPROTO_IP, IP_HDRINCL, &one,
+				 sizeof(one));
+		if (ret < 0) {
+			printf("Failed to set opt: %d %s\n", errno,
+			       strerror(errno));
+			return -errno;
+		}
+		priv->local_bind_sd = -1;
+		priv->local_bind_udp_port = 0;
+	} else {
+		struct sockaddr_ll *device;
+		struct packet_mreq mr;
+
+		/* Prepare device struct */
+		priv->device = malloc(sizeof(struct sockaddr_ll));
+		device = priv->device;
+		memset(device, 0, sizeof(struct sockaddr_ll));
+		device->sll_ifindex = if_nametoindex(ifname);
+		device->sll_family = AF_PACKET;
+		memcpy(device->sll_addr, ethmac, 6);
+		device->sll_halen = htons(6);
+
+		/* Open socket */
+		priv->sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+		if (priv->sd < 0) {
+			printf("Failed to open socket: %d %s\n", errno,
+			       strerror(errno));
+			return -errno;
+		}
+		/* Bind to the specified interface */
+		setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
+			   strlen(ifname) + 1);
+
+		/* Enable promiscuous mode to receive responses meant for us */
+		mr.mr_ifindex = device->sll_ifindex;
+		mr.mr_type = PACKET_MR_PROMISC;
+		setsockopt(priv->sd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
+			   &mr, sizeof(mr));
 	}
-	/* Bind to the specified interface */
-	setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
-		   strlen(ifname) + 1);
-
-	/* Enable promiscuous mode to receive responses meant for us */
-	mr.mr_ifindex = device->sll_ifindex;
-	mr.mr_type = PACKET_MR_PROMISC;
-	setsockopt(priv->sd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
-		   &mr, sizeof(mr));
+
 	return 0;
 }
 
 int sandbox_eth_raw_os_send(void *packet, int length,
-			    const struct eth_sandbox_raw_priv *priv)
+			    struct eth_sandbox_raw_priv *priv)
 {
 	int retval;
+	struct udphdr *udph = packet + sizeof(struct iphdr);
 
 	if (!priv->sd || !priv->device)
 		return -EINVAL;
 
+	if (priv->local && (priv->local_bind_sd == -1 ||
+			    priv->local_bind_udp_port != udph->source)) {
+		struct iphdr *iph = packet;
+		struct sockaddr_in addr;
+
+		if (priv->local_bind_sd != -1)
+			close(priv->local_bind_sd);
+
+		/* A normal UDP socket is required to bind */
+		priv->local_bind_sd = socket(AF_INET, SOCK_DGRAM, 0);
+		if (priv->local_bind_sd < 0) {
+			printf("Failed to open bind sd: %d %s\n", errno,
+			       strerror(errno));
+			return -errno;
+		}
+		priv->local_bind_udp_port = udph->source;
+
+		/**
+		 * Bind the UDP port that we intend to use as our source port
+		 * so that the kernel will not send ICMP port unreachable
+		 */
+		addr.sin_family = AF_INET;
+		addr.sin_port = udph->source;
+		addr.sin_addr.s_addr = iph->saddr;
+		retval = bind(priv->local_bind_sd, &addr, sizeof(addr));
+		if (retval < 0)
+			printf("Failed to bind: %d %s\n", errno,
+			       strerror(errno));
+	}
+
 	retval = sendto(priv->sd, packet, length, 0,
 			(struct sockaddr *)priv->device,
 			sizeof(struct sockaddr_ll));
@@ -99,4 +189,10 @@ void sandbox_eth_raw_os_halt(struct eth_sandbox_raw_priv *priv)
 	priv->device = NULL;
 	close(priv->sd);
 	priv->sd = -1;
+	if (priv->local) {
+		if (priv->local_bind_sd != -1)
+			close(priv->local_bind_sd);
+		priv->local_bind_sd = -1;
+		priv->local_bind_udp_port = 0;
+	}
 }
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index b6762f4..9851bda 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -4,6 +4,10 @@
 	#address-cells = <1>;
 	#size-cells = <0>;
 
+	aliases {
+		eth5 = "/eth at 90000000";
+	};
+
 	chosen {
 		stdout-path = "/serial";
 	};
@@ -192,4 +196,10 @@
 		reg = <0x80000000 0x1000>;
 		host-raw-interface = "eth0";
 	};
+
+	eth at 90000000 {
+		compatible = "sandbox,eth-raw";
+		reg = <0x90000000 0x1000>;
+		host-raw-interface = "lo";
+	};
 };
diff --git a/arch/sandbox/include/asm/eth-raw-os.h b/arch/sandbox/include/asm/eth-raw-os.h
index d92b72c..44e7050 100644
--- a/arch/sandbox/include/asm/eth-raw-os.h
+++ b/arch/sandbox/include/asm/eth-raw-os.h
@@ -15,16 +15,24 @@
  *
  * sd: socket descriptor - the open socket during a session
  * device: struct sockaddr_ll - the host interface packets move to/from
+ * local: 1 or 0 to select a local interface or not
+ * local_bindsd: socket descriptor to prevent the kernel from sending
+ *		 a message to the server claiming the port is
+ *		 unreachable
+ * local_bind_udp_port: The UDP port number that we bound to
  */
 struct eth_sandbox_raw_priv {
 	int sd;
 	void *device;
+	int local;
+	int local_bind_sd;
+	unsigned short local_bind_udp_port;
 };
 
 int sandbox_eth_raw_os_init(const char *ifname, unsigned char *ethmac,
 			    struct eth_sandbox_raw_priv *priv);
 int sandbox_eth_raw_os_send(void *packet, int length,
-			    const struct eth_sandbox_raw_priv *priv);
+			    struct eth_sandbox_raw_priv *priv);
 int sandbox_eth_raw_os_recv(void *packet, int *length,
 			    const struct eth_sandbox_raw_priv *priv);
 void sandbox_eth_raw_os_halt(struct eth_sandbox_raw_priv *priv);
diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
index 01b33a9..4b0f836 100644
--- a/drivers/net/sandbox-raw.c
+++ b/drivers/net/sandbox-raw.c
@@ -15,6 +15,8 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static int reply_arp;
+static IPaddr_t arp_ip;
 
 static int sb_eth_raw_start(struct udevice *dev)
 {
@@ -28,6 +30,12 @@ static int sb_eth_raw_start(struct udevice *dev)
 	interface = fdt_getprop(gd->fdt_blob, dev->of_offset,
 					    "host-raw-interface", NULL);
 
+	if (strcmp(interface, "lo") == 0) {
+		priv->local = 1;
+		setenv("ipaddr", "127.0.0.1");
+		setenv("serverip", "127.0.0.1");
+	}
+
 	retval = sandbox_eth_raw_os_init(interface, pdata->enetaddr, priv);
 
 	return retval;
@@ -39,19 +47,69 @@ static int sb_eth_raw_send(struct udevice *dev, void *packet, int length)
 
 	debug("eth_sandbox_raw: Send packet %d\n", length);
 
+	if (priv->local) {
+		struct ethernet_hdr *eth = packet;
+
+		if (ntohs(eth->et_protlen) == PROT_ARP) {
+			struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
+
+			/**
+			 * localhost works on a higher level API in Linux than
+			 * ARP packets, so fake it
+			 */
+			arp_ip = NetReadIP(&arp->ar_tpa);
+			reply_arp = 1;
+			return 0;
+		}
+		packet += ETHER_HDR_SIZE;
+		length -= ETHER_HDR_SIZE;
+	}
 	return sandbox_eth_raw_os_send(packet, length, priv);
 }
 
 static int sb_eth_raw_recv(struct udevice *dev)
 {
+	struct eth_pdata *pdata = dev_get_platdata(dev);
 	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
-	int retval;
+	int retval = 0;
 	uchar buffer[PKTSIZE];
 	int length;
 
-	retval = sandbox_eth_raw_os_recv(buffer, &length, priv);
+	if (reply_arp) {
+		struct arp_hdr *arp = (void *)buffer + ETHER_HDR_SIZE;
+
+		/* Formulate a fake ARP */
+		arp->ar_hrd = htons(ARP_ETHER);
+		arp->ar_pro = htons(PROT_IP);
+		arp->ar_hln = ARP_HLEN;
+		arp->ar_pln = ARP_PLEN;
+		arp->ar_op = htons(ARPOP_REPLY);
+		/* Any non-zero MAC address will work */
+		memset(&arp->ar_sha, 0x01, ARP_HLEN);
+		/* Use whatever IP we were looking for (always 127.0.0.1?) */
+		NetWriteIP(&arp->ar_spa, arp_ip);
+		memcpy(&arp->ar_tha, pdata->enetaddr, ARP_HLEN);
+		NetWriteIP(&arp->ar_tpa, NetOurIP);
+		length = ARP_HDR_SIZE;
+	} else {
+		/* If local, the Ethernet header won't be included; skip it */
+		uchar *pktptr = priv->local ? buffer + ETHER_HDR_SIZE : buffer;
+
+		retval = sandbox_eth_raw_os_recv(pktptr, &length, priv);
+	}
 
 	if (!retval && length) {
+		if (priv->local) {
+			struct ethernet_hdr *eth = (void *)buffer;
+
+			/* Fill in enough of the missing Ethernet header */
+			memcpy(eth->et_dest, pdata->enetaddr, ARP_HLEN);
+			memset(eth->et_src, 0x01, ARP_HLEN);
+			eth->et_protlen = htons(reply_arp ? PROT_ARP : PROT_IP);
+			reply_arp = 0;
+			length += ETHER_HDR_SIZE;
+		}
+
 		debug("eth_sandbox_raw: received packet %d\n",
 		      length);
 		NetReceive(buffer, length);
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 08/23] net: Use int instead of u8 for boolean flag
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 08/23] net: Use int instead of u8 for boolean flag Joe Hershberger
@ 2015-02-26  0:53         ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-26  0:53 UTC (permalink / raw)
  To: u-boot

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> On some archs masking the parameter is inefficient, so don't use u8.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reported-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v4:
> -New to v4
>
> Changes in v3: None
> Changes in v2: None
>
>  include/net.h | 2 +-
>  net/eth.c     | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 07/23] net: Change return codes from net/eth.c to use errorno constants
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 07/23] net: Change return codes from net/eth.c to use errorno constants Joe Hershberger
@ 2015-02-26  0:53         ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-02-26  0:53 UTC (permalink / raw)
  To: u-boot

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Many functions returned -1 previously. Change them to return appropriate error
> codes.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reported-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v4:
> -New to v4
>
> Changes in v3: None
> Changes in v2: None
>
>  net/eth.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (22 preceding siblings ...)
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 23/23] sandbox: eth: Add support for using the 'lo' interface Joe Hershberger
@ 2015-03-01 16:13       ` Simon Glass
  2015-03-01 22:12         ` Joe Hershberger
  2015-03-03 22:29         ` Joe Hershberger
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
  24 siblings, 2 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-01 16:13 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Add support for the Ethernet MAC controllers.  Phy support will come later.
>
> I am still leaving this as an RFC because I plan to add real board support
> before committing to mainline. When it is acceptable / accepted, I will push it
> as a dev branch on the net repo until a real device is supported. If any
> required changes are discovered in the process of supporting a real device I
> will send those as a patch against the dev branch, but then squash before
> sending the non-RFC version. I plan to rebase when the merge window opens
> anyway.
>
> If desired, let me know which of the non-DM related prerequisite patches are
> wanted for this release.
>
> I've added unit tests to verify functionality.
>
> There is an additional driver for sandbox that bridges to the RAW
> Ethernet API in Linux which lets you test with real traffic. It now
> supports localhost as well (the 'lo' interface).

I've got some comments queued up the the series so will send those
soon (never got to it this week so am catching up!). I wanted to try
it out on a board to see how things look. The short answer is that it
works really nicely on sunxi. I'll send some patches that I needed,
hopefully that doesn't duplicate any work you have done.

In terms of getting this into mainline, I'd be happy to use
u-boot-dm/next if that suits you and Tom. There are series for PCI and
USB to sort out, and if the last merge window is any indication it's a
real struggle to get multiple large series applied within the merge
window when there are dependencies between them.

Some general comments that I will put here for want of a better place:

- it would be good to have the DM code in drivers/net/eth-uclass.c at some point
- struct eth_pdata is used by the uclass and is common to all drivers,
but I wonder if we will find that drivers want to add their own
private platdata? I added phy_interface but that is generic. Let's
see.
- I think the recv() method should change before long. The
NetReceive() call should be made from the uclass since it is common to
all drivers. Then the recv() method can return a packet if it finds
one, but not submit it for processing

One interesting point for me is that you have taken a slightly more
ambitious approach with the conversion by not reusing eth_device. That
seems to have have worked out well and makes me think I could revisit
SPI flash perhaps and do the same.

>
> Changes in v4:
> -New to v4
> -Fix compile regression in !DM_ETH case
> -New to v4
> -New to v4
> -New to v4
> -New to v4
> -New to v4

If you put this in a patch, patman will remove duplicates in the cover letter.

Series-process-log: uniq

You can also sort with:

Series-process-log: sort, uniq

> -Redo the seq / probe implementation
> --Don't prevent eth_initialize on driver model
> --Use eth_initialize to probe all devices and write_hwaddr
> --Look up MAC address in post-probe
> --Include ethprime handling in eth_initialize
> --If current == NULL, always check if there is a device available in eth_get_dev
> --Move env init call from uclass init to eth_initialize
> --Print the alias in eth_initialize
> -Stop handling selecting a new "current" in pre-unbind as it will now work itself out by clearing the pointer
> -Change -1 returns to error constants
> -Remove bd_t *bis from dm eth_ops init function
> -Add documentation to the structures
> -Add a helper function for eth_uclass_priv
> -Change puts to printf
> -Add eth_get_ops helper
> -Rename init() to start() in ops
> -Rename halt() to stop() in ops
> -Remove checks for driver==NULL
> -Remove priv pointer in per-device priv struct (drivers already get their own directly from DM)
> -Cleaned up sandbox EXTRA_ENV define
> -Moved config to Kconfig
> -Removed checks on priv != NULL and added protection in uclass instead
> -Use only the seq from DM to find aliases
> -Load from ethprime on eth_initialize()
> -Added testing for ethrotate
> -Add ability to disable ping reply in sandbox eth driver
> -Updated expected behavior based on changes to the NetLoop
> -Added comments to README.sandbox
> -Use accessors for platdata and priv
> -Add comments to priv struct definition
> -Move os file to arch
> -Cleanup var definition order
> -Moved config to Kconfig
> -Clean up the interface to sandbox's eth-raw-os by passing priv to raw-os
> -Fixed the MAC address limitation (now all traffic uses MAC address from env)
> -New to v4
> -Added support for the 'lo' network interface
>
> Changes in v3:
> -Reorder dm test makefile
> -Move the get_dev_by_* protos to also be !DM_ETH like the impl
> -Correct the pre_unbind logic
> -Correct failure chaining from bind to probe to init
> --Fail init if not activated
> --Fail probe if ethaddr not set
> -Update ethaddr from env unconditionally on init
> -Use set current to select the current device regardless of the previous selection
> -Allow current eth dev to be NULL
> -Fixed blank line formatting for variable declaration
> -Added 2 more ethaddr to sandbox
> -Print which device in the debug write hwaddr
> -Prevent a crash if memory is not allocated
> -Added dm eth testing
> -Added support for aliases
> -Added support for ethprime
> -Added testing for netretry
> -Made the os raw packet support for sandbox eth build and work.
>
> Changes in v2:
> -Updated comments
> -Removed extra parentheses
> -Changed eth_uclass_priv local var names to be uc_priv
> -Update error codes
> -Cause an invalid name to fail binding
> -Rebase on top of dm/master
> -Stop maintaining our own index and use DM seq now that it works for our needs
> -Move the hwaddr to platdata so that its memory is allocated at bind when we need it
> -Prevent device from being probed before used by a command (i.e. before eth_init()).
> -Change printfs to debug in sandbox driver
> -Remove unused priv struct for sandbox driver
> -Change printfs to debug in sandbox driver
> -Move static data to priv
> -Move fake hwaddr to the device tree
> -Added the raw packet proof-of-concept patch.
>
> Joe Hershberger (23):
>   test: dm: Reorder the objects to build
>   common: Make sure arch-specific map_sysmem() is defined
>   net: Provide a function to get the current MAC address
>   net: Rename helper function to be more clear
>   net: Remove unneeded "extern" in net.h
>   net: Refactor in preparation for driver model
>   net: Change return codes from net/eth.c to use errorno constants
>   net: Use int instead of u8 for boolean flag
>   net: Remove the bd* parameter from net stack functions
>   net: Make netretry actually do something
>   net: Access mapped physmem in net functions
>   dm: eth: Add basic driver model support to Ethernet stack
>   sandbox: eth: Add network support to sandbox
>   sandbox: eth: Add ARP and PING response to sandbox driver
>   test: dm: eth: Add tests for the eth dm implementation
>   dm: eth: Add support for aliases
>   dm: eth: Add support for ethprime env var
>   test: dm: eth: Add testing for ethrotate env var
>   sandbox: eth: Add ability to disable ping reply in sandbox eth driver
>   test: dm: net: Add a test of the netretry behavior
>   sandbox: eth: Add a bridge to a real network for sandbox
>   sandbox: Enable DHCP and IP defrag
>   sandbox: eth: Add support for using the 'lo' interface
>
>  arch/mips/mach-au1x00/au1x00_eth.c    |   2 +-
>  arch/powerpc/cpu/mpc8260/ether_fcc.c  |   2 +-
>  arch/powerpc/cpu/mpc85xx/ether_fcc.c  |   2 +-
>  arch/powerpc/cpu/mpc8xx/scc.c         |   2 +-
>  arch/sandbox/Kconfig                  |  12 +
>  arch/sandbox/cpu/Makefile             |  10 +
>  arch/sandbox/cpu/eth-raw-os.c         | 198 +++++++++++++
>  arch/sandbox/dts/sandbox.dts          |  21 ++
>  arch/sandbox/include/asm/eth-raw-os.h |  40 +++
>  board/sandbox/README.sandbox          |  17 +-
>  common/board_r.c                      |   2 +-
>  common/cmd_bdinfo.c                   |   2 +
>  drivers/net/Kconfig                   |  28 ++
>  drivers/net/Makefile                  |   2 +
>  drivers/net/netconsole.c              |   4 +-
>  drivers/net/sandbox-raw.c             | 163 +++++++++++
>  drivers/net/sandbox.c                 | 200 +++++++++++++
>  include/common.h                      |   4 +-
>  include/configs/sandbox.h             |  25 +-
>  include/dm/uclass-id.h                |   1 +
>  include/net.h                         | 187 ++++++++----
>  net/eth.c                             | 521 +++++++++++++++++++++++++++++-----
>  net/net.c                             |  17 +-
>  net/nfs.c                             |   2 +-
>  net/tftp.c                            |   2 +-
>  test/dm/Makefile                      |   5 +-
>  test/dm/eth.c                         | 129 +++++++++
>  test/dm/test.dts                      |  20 ++
>  28 files changed, 1466 insertions(+), 154 deletions(-)
>  create mode 100644 arch/sandbox/cpu/eth-raw-os.c
>  create mode 100644 arch/sandbox/include/asm/eth-raw-os.h
>  create mode 100644 drivers/net/sandbox-raw.c
>  create mode 100644 drivers/net/sandbox.c
>  create mode 100644 test/dm/eth.c
>
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 02/23] common: Make sure arch-specific map_sysmem() is defined
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 02/23] common: Make sure arch-specific map_sysmem() is defined Joe Hershberger
@ 2015-03-01 18:07         ` Simon Glass
  2015-03-01 21:16           ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-03-01 18:07 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> In the case where the arch defines a custom map_sysmem(), make sure that
> including just common.h is sufficient to have these functions as they
> are when the arch does not override it.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v4:
> -New to v4
>
> Changes in v3: None
> Changes in v2: None
>
>  include/common.h | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/include/common.h b/include/common.h
> index 77c55c6..6510efc 100644
> --- a/include/common.h
> +++ b/include/common.h
> @@ -846,7 +846,9 @@ int cpu_release(int nr, int argc, char * const argv[]);
>  #endif
>
>  /* Define a null map_sysmem() if the architecture doesn't use it */
> -# ifndef CONFIG_ARCH_MAP_SYSMEM
> +# ifdef CONFIG_ARCH_MAP_SYSMEM
> +#include <asm/io.h>
> +# else
>  static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
>  {
>         return (void *)(uintptr_t)paddr;

Do we need this patch? Is it just for sandbox? It would be nice to
remove things from common.h rather than adding them!

Anyway if you want to go ahead I'm OK with it.

Reviewed-by: Simon Glass <sjg@chromium.org>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 09/23] net: Remove the bd* parameter from net stack functions
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 09/23] net: Remove the bd* parameter from net stack functions Joe Hershberger
@ 2015-03-01 18:07         ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-01 18:07 UTC (permalink / raw)
  To: u-boot

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> This value is not used by the network stack and is available in the
> global data, so stop passing it around.  For the one legacy function
> that still expects it (init op on old Ethernet drivers) pass in the
> global pointer version directly to avoid changing that interface.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reported-by: Simon Glass <sjg@chromium.org>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 10/23] net: Make netretry actually do something
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 10/23] net: Make netretry actually do something Joe Hershberger
@ 2015-03-01 18:07         ` Simon Glass
  2015-03-01 21:53           ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-03-01 18:07 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> netretry previously would only retry in one specific case (your MAC
> address is not set) and no other. This is basically useless. In the DM
> implementation for eth it turns this into a completely useless case
> since an un-configured MAC address results in not even entering the
> NetLoop. The behavior is now changed to retry any failed command
> (rotating through the eth adapters if ethrotate != no).
>
> It also defaulted to retry forever. It is now changed to default to not
> retry

That last bit seems like a big change. Does it mean that if I forget
to plug in the Ethernet it might not recover?

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 11/23] net: Access mapped physmem in net functions
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 11/23] net: Access mapped physmem in net functions Joe Hershberger
@ 2015-03-01 18:07         ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-01 18:07 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Previously the net functions would access memory assuming physmem did
> not need to be mapped.  In sandbox, that's not the case.
>
> Now we map the physmem specified by the user in loadaddr to the buffer
> that represents that space.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v4:
> -New to v4
>
> Changes in v3: None
> Changes in v2: None
>
>  net/nfs.c  | 2 +-
>  net/tftp.c | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/net/nfs.c b/net/nfs.c
> index 381b75f..c816acd 100644
> --- a/net/nfs.c
> +++ b/net/nfs.c
> @@ -93,7 +93,7 @@ store_block(uchar *src, unsigned offset, unsigned len)
>         } else
>  #endif /* CONFIG_SYS_DIRECT_FLASH_NFS */
>         {
> -               (void)memcpy((void *)(load_addr + offset), src, len);
> +               memcpy((void *)(map_sysmem(load_addr, 0) + offset), src, len);

I think this would be better as:

               memcpy(map_sysmem(load_addr + offset, src_len), src, len);

and for consistency we should call unmap_sysmem() too.

   void *ptr = map_sysmem(load_addr + offset, src_len);

   memcpy(ptr, src, len);
   unmap_sysmem(ptr);

>         }
>
>         if (NetBootFileXferSize < (offset+len))
> diff --git a/net/tftp.c b/net/tftp.c
> index 0a2c533..9290182 100644
> --- a/net/tftp.c
> +++ b/net/tftp.c
> @@ -184,7 +184,7 @@ store_block(int block, uchar *src, unsigned len)
>         } else
>  #endif /* CONFIG_SYS_DIRECT_FLASH_TFTP */
>         {
> -               (void)memcpy((void *)(load_addr + offset), src, len);
> +               memcpy((void *)(map_sysmem(load_addr, 0) + offset), src, len);

Similar here.

>         }
>  #ifdef CONFIG_MCAST_TFTP
>         if (Multicast)
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 12/23] dm: eth: Add basic driver model support to Ethernet stack
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 12/23] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
@ 2015-03-01 18:07         ` Simon Glass
  2015-03-01 21:45           ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-03-01 18:07 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> First just add support for MAC drivers.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

Reviewed-by: Simon Glass <sjg@chromium.org>

This looks right to me. I still have some comments on error handling,
but I'm OK with you addressing these in a follow-on patch if you like.

>
> ---
>
> Changes in v4:
> -Redo the seq / probe implementation
> --Don't prevent eth_initialize on driver model
> --Use eth_initialize to probe all devices and write_hwaddr
> --Look up MAC address in post-probe
> --Include ethprime handling in eth_initialize
> --If current == NULL, always check if there is a device available in eth_get_dev
> --Move env init call from uclass init to eth_initialize
> --Print the alias in eth_initialize
> -Stop handling selecting a new "current" in pre-unbind as it will now work itself out by clearing the pointer
> -Change -1 returns to error constants
> -Remove bd_t *bis from dm eth_ops init function
> -Add documentation to the structures
> -Add a helper function for eth_uclass_priv
> -Change puts to printf
> -Add eth_get_ops helper
> -Rename init() to start() in ops
> -Rename halt() to stop() in ops
> -Remove checks for driver==NULL
> -Remove priv pointer in per-device priv struct (drivers already get their own directly from DM)
>
> Changes in v3:
> -Correct the pre_unbind logic
> -Correct failure chaining from bind to probe to init
> --Fail init if not activated
> --Fail probe if ethaddr not set
> -Update ethaddr from env unconditionally on init
> -Use set current to select the current device regardless of the previous selection
> -Allow current eth dev to be NULL
> -Fixed blank line formatting for variable declaration
>
> Changes in v2:
> -Updated comments
> -Removed extra parentheses
> -Changed eth_uclass_priv local var names to be uc_priv
> -Update error codes
> -Cause an invalid name to fail binding
> -Rebase on top of dm/master
> -Stop maintaining our own index and use DM seq now that it works for our needs
> -Move the hwaddr to platdata so that its memory is allocated at bind when we need it
> -Prevent device from being probed before used by a command (i.e. before eth_init()).
>
>  common/cmd_bdinfo.c    |   2 +
>  drivers/net/Kconfig    |   5 +
>  include/dm/uclass-id.h |   1 +
>  include/net.h          |  52 ++++++++
>  net/eth.c              | 345 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  5 files changed, 399 insertions(+), 6 deletions(-)
>
> diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
> index aa81da2..b4cce25 100644
> --- a/common/cmd_bdinfo.c
> +++ b/common/cmd_bdinfo.c
> @@ -34,6 +34,7 @@ static void print_eth(int idx)
>         printf("%-12s= %s\n", name, val);
>  }
>
> +#ifndef CONFIG_DM_ETH
>  __maybe_unused
>  static void print_eths(void)
>  {
> @@ -52,6 +53,7 @@ static void print_eths(void)
>         printf("current eth = %s\n", eth_get_name());
>         printf("ip_addr     = %s\n", getenv("ipaddr"));
>  }
> +#endif
>
>  __maybe_unused
>  static void print_lnum(const char *name, unsigned long long value)
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index e69de29..bdd0f05 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -0,0 +1,5 @@
> +config DM_ETH
> +       bool "Enable Driver Model for Ethernet drivers"
> +       depends on DM
> +       help
> +         Enable driver model for Ethernet.

Here you could mention that the eth_...() interface is then
implemented by the Ethernet uclass. Perhaps a few other notes too? See
for example drivers/spi/Kconfig or drivers/gpio/Kconfig.

> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index 91bb90d..ad96682 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -34,6 +34,7 @@ enum uclass_id {
>         UCLASS_I2C_GENERIC,     /* Generic I2C device */
>         UCLASS_I2C_EEPROM,      /* I2C EEPROM device */
>         UCLASS_MOD_EXP,         /* RSA Mod Exp device */
> +       UCLASS_ETH,             /* Ethernet device */
>
>         UCLASS_COUNT,
>         UCLASS_INVALID = -1,
> diff --git a/include/net.h b/include/net.h
> index 10d38f8..508c572 100644
> --- a/include/net.h
> +++ b/include/net.h
> @@ -78,6 +78,57 @@ enum eth_state_t {
>         ETH_STATE_ACTIVE
>  };
>
> +#ifdef CONFIG_DM_ETH
> +/**
> + * struct eth_pdata - Platform data for Ethernet MAC controllers
> + *
> + * @iobase: The base address of the hardware registers
> + * @enetaddr: The Ethernet MAC address that is loaded from EEPROM or env
> + */
> +struct eth_pdata {
> +       phys_addr_t iobase;
> +       unsigned char enetaddr[6];
> +};
> +
> +/**
> + * struct eth_ops - functions of Ethernet MAC controllers
> + *
> + * start: Prepare the hardware to send and receive packets
> + * send: Send the bytes passed in "packet" as a packet on the wire
> + * recv: Check if the hardware received a packet. Call the network stack if so
> + * stop: Stop the hardware from looking for packets - may be called even if
> + *      state == PASSIVE
> + * mcast: Join or leave a multicast group (for TFTP) - optional
> + * write_hwaddr: Write a MAC address to the hardware (used to pass it to Linux
> + *              on some platforms like ARM). This function expects the
> + *              eth_pdata::enetaddr field to be populated - optional
> + * read_rom_hwaddr: Some devices have a backup of the MAC address stored in a
> + *                 ROM on the board. This is how the driver should expose it
> + *                 to the network stack. This function should fill in the
> + *                 eth_pdata::enetaddr field - optional
> + */
> +struct eth_ops {
> +       int (*start)(struct udevice *dev);
> +       int (*send)(struct udevice *dev, void *packet, int length);
> +       int (*recv)(struct udevice *dev);
> +       void (*stop)(struct udevice *dev);
> +#ifdef CONFIG_MCAST_TFTP
> +       int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
> +#endif
> +       int (*write_hwaddr)(struct udevice *dev);
> +       int (*read_rom_hwaddr)(struct udevice *dev);
> +};
> +
> +#define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
> +
> +struct udevice *eth_get_dev(void); /* get the current device */
> +unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
> +/* Used only when NetConsole is enabled */
> +int eth_init_state_only(void); /* Set active state */
> +void eth_halt_state_only(void); /* Set passive state */
> +#endif
> +
> +#ifndef CONFIG_DM_ETH
>  struct eth_device {
>         char name[16];
>         unsigned char enetaddr[6];
> @@ -144,6 +195,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
>                      int eth_number);
>
>  int usb_eth_initialize(bd_t *bi);
> +#endif
>
>  int eth_initialize(void);              /* Initialize network subsystem */
>  void eth_try_another(int first_restart);       /* Change the device */
> diff --git a/net/eth.c b/net/eth.c
> index 7bbaac4..9c2dfb9 100644
> --- a/net/eth.c
> +++ b/net/eth.c
> @@ -1,12 +1,15 @@
>  /*
> - * (C) Copyright 2001-2010
> + * (C) Copyright 2001-2015
>   * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
> + * Joe Hershberger, National Instruments
>   *
>   * SPDX-License-Identifier:    GPL-2.0+
>   */
>
>  #include <common.h>
>  #include <command.h>
> +#include <dm.h>
> +#include <dm/device-internal.h>

The dm/ headers should go after the asm/ header below.

>  #include <net.h>
>  #include <miiphy.h>
>  #include <phy.h>
> @@ -74,6 +77,338 @@ static int eth_mac_skip(int index)
>         return ((skip_state = getenv(enetvar)) != NULL);
>  }
>
> +static void eth_current_changed(void);
> +
> +#ifdef CONFIG_DM_ETH
> +/**
> + * struct eth_device_priv - private structure for each Ethernet device
> + *
> + * @state: The state of the Ethernet MAC driver (defined by enum eth_state_t)
> + */
> +struct eth_device_priv {
> +       enum eth_state_t state;
> +};
> +
> +/**
> + * struct eth_uclass_priv - The structure attached to the uclass itself
> + *
> + * @current: The Ethernet device that the network functions are using
> + */
> +struct eth_uclass_priv {
> +       struct udevice *current;
> +};
> +
> +static struct eth_uclass_priv *eth_get_uclass_priv(void)
> +{
> +       struct uclass *uc;
> +
> +       uclass_get(UCLASS_ETH, &uc);
> +       assert(uc);
> +       return uc->priv;
> +}
> +
> +static void eth_set_current_to_next(void)
> +{
> +       struct eth_uclass_priv *uc_priv;
> +
> +       uc_priv = eth_get_uclass_priv();
> +       if (uc_priv->current)
> +               uclass_next_device(&uc_priv->current);
> +       if (!uc_priv->current)
> +               uclass_first_device(UCLASS_ETH, &uc_priv->current);
> +}
> +
> +struct udevice *eth_get_dev(void)

This function needs a comment. It isn't clear what is it supposed to
return. Does it only return probed devices (in which case the check in
eth_halt() etc. for device_active() is redundant? Or can it return
devices which cannot be probed?

I suggest that it only returns probed devices, as it simplifies the code.

> +{
> +       if (!eth_get_uclass_priv()->current)
> +               uclass_first_device(UCLASS_ETH,
> +                                   &eth_get_uclass_priv()->current);

This can return an error. You will then eat it and return the device
anyway, even though uclass_first_device() will not change ->current.

> +       return eth_get_uclass_priv()->current;

Also I think it would be better to have a local variable here for
uc_priv, as in the above functino.

> +}
> +
> +static void eth_set_dev(struct udevice *dev)
> +{
> +       device_probe(dev);

This needs an error check, since if it fails you cannot use the
device. Also in eth_pre_unbind() you call this function with NULL.

So I think this function should return an error.

> +       eth_get_uclass_priv()->current = dev;
> +}
> +
> +unsigned char *eth_get_ethaddr(void)
> +{
> +       struct eth_pdata *pdata;
> +
> +       if (eth_get_dev()) {
> +               pdata = eth_get_dev()->platdata;
> +               return pdata->enetaddr;
> +       }
> +
> +       return NULL;
> +}
> +
> +/* Set active state without calling start on the driver */
> +int eth_init_state_only(void)
> +{
> +       struct udevice *current;
> +       struct eth_device_priv *priv;
> +
> +       current = eth_get_dev();
> +       if (!current || !device_active(current))
> +               return -EINVAL;
> +
> +       priv = current->uclass_priv;
> +       priv->state = ETH_STATE_ACTIVE;
> +
> +       return 0;
> +}
> +
> +/* Set passive state without calling stop on the driver */
> +void eth_halt_state_only(void)
> +{
> +       struct udevice *current;
> +       struct eth_device_priv *priv;
> +
> +       current = eth_get_dev();
> +       if (!current || !device_active(current))
> +               return;
> +
> +       priv = current->uclass_priv;
> +       priv->state = ETH_STATE_PASSIVE;
> +}
> +
> +int eth_get_dev_index(void)
> +{
> +       if (eth_get_dev())
> +               return eth_get_dev()->seq;
> +       return -1;
> +}
> +
> +int eth_init(void)
> +{
> +       struct udevice *current;
> +       struct udevice *old_current;
> +
> +       current = eth_get_dev();
> +       if (!current) {
> +               printf("No ethernet found.\n");
> +               return -ENODEV;
> +       }
> +
> +       old_current = current;
> +       do {
> +               debug("Trying %s\n", current->name);
> +
> +               if (device_active(current)) {
> +                       uchar env_enetaddr[6];
> +                       struct eth_pdata *pdata = current->platdata;
> +
> +                       /* Sync environment with network device */
> +                       if (eth_getenv_enetaddr_by_index("eth", current->seq,
> +                                                        env_enetaddr))
> +                               memcpy(pdata->enetaddr, env_enetaddr, 6);
> +                       else
> +                               memset(pdata->enetaddr, 0, 6);
> +
> +                       if (eth_get_ops(current)->start(current) >= 0) {
> +                               struct eth_device_priv *priv =
> +                                       current->uclass_priv;
> +
> +                               priv->state = ETH_STATE_ACTIVE;
> +                               return 0;
> +                       }
> +               }
> +               debug("FAIL\n");
> +
> +               /* This will ensure the new "current" attempted to probe */
> +               eth_try_another(0);
> +               current = eth_get_dev();
> +       } while (old_current != current);
> +
> +       return -ENODEV;
> +}
> +
> +void eth_halt(void)
> +{
> +       struct udevice *current;
> +       struct eth_device_priv *priv;
> +
> +       current = eth_get_dev();
> +       if (!current || !device_active(current))
> +               return;

As above, probably this device_active() check is redundant?

> +
> +       eth_get_ops(current)->stop(current);

How about adding error checking in these functions? Then eventually we
can plumb it through. Driver authors are not going to motivated to
deal with errors if they know that their caller ignores them.

ret = eth_get_ops...
if (ret) {
   /* We cannot return the error at present */
  debug("%s: stop() returned error %d\n", __func__, ret);
}

> +       priv = current->uclass_priv;
> +       priv->state = ETH_STATE_PASSIVE;
> +}
> +
> +int eth_send(void *packet, int length)
> +{
> +       struct udevice *current;
> +
> +       current = eth_get_dev();
> +       if (!current)
> +               return -ENODEV;
> +
> +       if (!device_active(current))
> +               return -EINVAL;
> +
> +       return eth_get_ops(current)->send(current, packet, length);
> +}
> +
> +int eth_rx(void)
> +{
> +       struct udevice *current;
> +
> +       current = eth_get_dev();
> +       if (!current)
> +               return -ENODEV;
> +
> +       if (!device_active(current))
> +               return -EINVAL;
> +
> +       return eth_get_ops(current)->recv(current);
> +}
> +
> +static int eth_write_hwaddr(struct udevice *dev)
> +{
> +       struct eth_pdata *pdata = dev->platdata;
> +       int ret = 0;
> +
> +       if (!dev || !device_active(dev))
> +               return -EINVAL;
> +
> +       /* seq is valid since the device is active */
> +       if (eth_get_ops(dev)->write_hwaddr && !eth_mac_skip(dev->seq)) {
> +               if (!is_valid_ether_addr(pdata->enetaddr)) {
> +                       printf("\nError: %s address %pM illegal value\n",
> +                              dev->name, pdata->enetaddr);
> +                       return -EINVAL;
> +               }
> +
> +               ret = eth_get_ops(dev)->write_hwaddr(dev);
> +               if (ret)
> +                       printf("\nWarning: %s failed to set MAC address\n",
> +                              dev->name);
> +       }
> +
> +       return ret;
> +}
> +
> +int eth_initialize(void)
> +{
> +       int num_devices = 0;
> +       struct udevice *dev;
> +
> +       bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
> +       eth_env_init();
> +
> +       /*
> +        * Devices need to write the hwaddr even if not started so that Linux
> +        * will have access to the hwaddr that u-boot stored for the device.
> +        * This is accomplished by attempting to probe each device and calling
> +        * their write_hwaddr() operation.
> +        */
> +       uclass_first_device(UCLASS_ETH, &dev);
> +       if (!dev) {
> +               printf("No ethernet found.\n");
> +               bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
> +       } else {
> +               bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
> +               do {
> +                       if (num_devices)
> +                               printf(", ");
> +
> +                       printf("eth%d: %s", dev->seq, dev->name);
> +
> +                       eth_write_hwaddr(dev);
> +
> +                       uclass_next_device(&dev);
> +                       num_devices++;
> +               } while (dev);
> +
> +               putc('\n');
> +       }
> +
> +       return num_devices;
> +}
> +
> +static int eth_post_bind(struct udevice *dev)
> +{
> +       if (strchr(dev->name, ' ')) {
> +               printf("\nError: eth device name \"%s\" has a space!\n",
> +                      dev->name);
> +               return -EINVAL;
> +       }
> +
> +       return 0;
> +}
> +
> +static int eth_pre_unbind(struct udevice *dev)
> +{
> +       /* Don't hang onto a pointer that is going away */
> +       if (dev == eth_get_uclass_priv()->current)
> +               eth_set_dev(NULL);
> +
> +       return 0;
> +}
> +
> +static int eth_post_probe(struct udevice *dev)
> +{
> +       struct eth_device_priv *priv = dev->uclass_priv;
> +       struct eth_pdata *pdata = dev->platdata;
> +       unsigned char env_enetaddr[6];
> +
> +       priv->state = ETH_STATE_INIT;
> +
> +       /* Check if the device has a MAC address in ROM */
> +       if (eth_get_ops(dev)->read_rom_hwaddr)
> +               eth_get_ops(dev)->read_rom_hwaddr(dev);
> +
> +       eth_getenv_enetaddr_by_index("eth", dev->seq, env_enetaddr);
> +       if (!is_zero_ether_addr(env_enetaddr)) {
> +               if (!is_zero_ether_addr(pdata->enetaddr) &&
> +                   memcmp(pdata->enetaddr, env_enetaddr, 6)) {
> +                       printf("\nWarning: %s MAC addresses don't match:\n",
> +                              dev->name);
> +                       printf("Address in SROM is         %pM\n",
> +                              pdata->enetaddr);
> +                       printf("Address in environment is  %pM\n",
> +                              env_enetaddr);
> +               }
> +
> +               /* Override the ROM MAC address */
> +               memcpy(pdata->enetaddr, env_enetaddr, 6);
> +       } else if (is_valid_ether_addr(pdata->enetaddr)) {
> +               eth_setenv_enetaddr_by_index("eth", dev->seq, pdata->enetaddr);
> +               printf("\nWarning: %s using MAC address from ROM\n",
> +                      dev->name);
> +       } else if (is_zero_ether_addr(pdata->enetaddr)) {
> +               printf("\nError: %s address not set.\n",
> +                      dev->name);
> +               return -EINVAL;
> +       }
> +
> +       return 0;
> +}
> +
> +static int eth_pre_remove(struct udevice *dev)
> +{
> +       eth_get_ops(dev)->stop(dev);
> +
> +       return 0;
> +}
> +
> +UCLASS_DRIVER(eth) = {
> +       .name           = "eth",
> +       .id             = UCLASS_ETH,
> +       .post_bind      = eth_post_bind,
> +       .pre_unbind     = eth_pre_unbind,
> +       .post_probe     = eth_post_probe,
> +       .pre_remove     = eth_pre_remove,
> +       .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
> +       .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
> +};
> +#endif

Could we put the uclass in its own eth-uclass.c file at some point?

> +
> +#ifndef CONFIG_DM_ETH
>  /*
>   * CPU and board-specific Ethernet initializations.  Aliased function
>   * signals caller to move on
> @@ -425,6 +760,7 @@ int eth_rx(void)
>
>         return eth_current->recv(eth_current);
>  }
> +#endif /* ifndef CONFIG_DM_ETH */
>
>  #ifdef CONFIG_API
>  static void eth_save_packet(void *packet, int length)
> @@ -488,7 +824,7 @@ static void eth_current_changed(void)
>
>  void eth_try_another(int first_restart)
>  {
> -       static struct eth_device *first_failed;
> +       static void *first_failed;
>         char *ethrotate;
>
>         /*
> @@ -517,12 +853,9 @@ void eth_set_current(void)
>  {
>         static char *act;
>         static int  env_changed_id;
> -       struct eth_device *old_current;
> +       void *old_current;
>         int     env_id;
>
> -       if (!eth_get_dev())     /* XXX no current */
> -               return;
> -
>         env_id = get_env_id();
>         if ((act == NULL) || (env_changed_id != env_id)) {
>                 act = getenv("ethact");
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 16/23] dm: eth: Add support for aliases
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 16/23] dm: eth: Add support for aliases Joe Hershberger
@ 2015-03-01 18:07         ` Simon Glass
  2015-03-01 22:04           ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-03-01 18:07 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Allow network devices to be referred to as "eth0" instead of
> "eth at 12345678" when specified in ethact.
>
> Add tests to verify this behavior.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>

Reviewed-by: Simon Glass <sjg@chromium.org>

Again a few comments on error handling for follow-up.

> ---
>
> Changes in v4:
> -Use only the seq from DM to find aliases
>
> Changes in v3:
> -Added support for aliases
>
> Changes in v2: None
>
>  include/configs/sandbox.h |  2 +-
>  include/net.h             |  1 +
>  net/eth.c                 | 47 ++++++++++++++++++++++++++++++++++++++---------
>  test/dm/eth.c             | 24 ++++++++++++++++++++++++
>  test/dm/test.dts          |  4 +++-
>  5 files changed, 67 insertions(+), 11 deletions(-)
>
> diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
> index 9189f6a..caf9f5a 100644
> --- a/include/configs/sandbox.h
> +++ b/include/configs/sandbox.h
> @@ -174,7 +174,7 @@
>
>  #define SANDBOX_ETH_SETTINGS           "ethaddr=00:00:11:22:33:44\0" \
>                                         "eth1addr=00:00:11:22:33:45\0" \
> -                                       "eth2addr=00:00:11:22:33:46\0" \
> +                                       "eth5addr=00:00:11:22:33:46\0" \
>                                         "ipaddr=1.2.3.4\0"
>
>  #define CONFIG_EXTRA_ENV_SETTINGS      SANDBOX_SERIAL_SETTINGS \
> diff --git a/include/net.h b/include/net.h
> index 508c572..e9cb4a3 100644
> --- a/include/net.h
> +++ b/include/net.h
> @@ -122,6 +122,7 @@ struct eth_ops {
>  #define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
>
>  struct udevice *eth_get_dev(void); /* get the current device */
> +struct udevice *eth_get_dev_by_name(const char *devname);

This needs a comment to describe what devname is exactly. I thought it
was a device name. Also it seems to requite a minimum length of 3
characters?

>  unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
>  /* Used only when NetConsole is enabled */
>  int eth_init_state_only(void); /* Set active state */
> diff --git a/net/eth.c b/net/eth.c
> index 9c2dfb9..8b853e8 100644
> --- a/net/eth.c
> +++ b/net/eth.c
> @@ -132,6 +132,36 @@ static void eth_set_dev(struct udevice *dev)
>         eth_get_uclass_priv()->current = dev;
>  }
>
> +/*
> + * Find the udevice that either has the name passed in as devname or has an
> + * alias named devname.
> + */
> +struct udevice *eth_get_dev_by_name(const char *devname)
> +{
> +       int seq;
> +       char *endp = NULL;
> +       const char *startp;
> +       struct udevice *it;
> +       struct uclass *uc;
> +
> +       startp = devname + strlen("eth");
> +       seq = simple_strtoul(startp, &endp, 10);
> +
> +       uclass_get(UCLASS_ETH, &uc);
> +       uclass_foreach_dev(it, uc) {
> +               /* We need the seq to be valid, so make sure it's probed */
> +               device_probe(it);

Error check. I think this function is should return an error.

> +               /*
> +                * Check for the name or the sequence number to match
> +                */
> +               if (strcmp(it->name, devname) == 0 ||
> +                   (endp > startp && it->seq == seq))
> +                       return it;
> +       }
> +
> +       return NULL;
> +}
> +
>  unsigned char *eth_get_ethaddr(void)
>  {
>         struct eth_pdata *pdata;
> @@ -405,6 +435,7 @@ UCLASS_DRIVER(eth) = {
>         .pre_remove     = eth_pre_remove,
>         .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
>         .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
> +       .flags          = DM_UC_FLAG_SEQ_ALIAS,
>  };
>  #endif
>
> @@ -437,6 +468,11 @@ static void eth_set_current_to_next(void)
>         eth_current = eth_current->next;
>  }
>
> +static void eth_set_dev(struct eth_device *dev)
> +{
> +       eth_current = dev;
> +}
> +
>  struct eth_device *eth_get_dev_by_name(const char *devname)
>  {
>         struct eth_device *dev, *target_dev;
> @@ -853,7 +889,6 @@ void eth_set_current(void)
>  {
>         static char *act;
>         static int  env_changed_id;
> -       void *old_current;
>         int     env_id;
>
>         env_id = get_env_id();
> @@ -861,14 +896,8 @@ void eth_set_current(void)
>                 act = getenv("ethact");
>                 env_changed_id = env_id;
>         }
> -       if (act != NULL) {
> -               old_current = eth_get_dev();
> -               do {
> -                       if (strcmp(eth_get_name(), act) == 0)
> -                               return;
> -                       eth_set_current_to_next();
> -               } while (old_current != eth_get_dev());
> -       }
> +       if (act != NULL)
> +               eth_set_dev(eth_get_dev_by_name(act));

Again I think the error handling here is dodgy. You may have a device
which fails to probe but it will not be reported here.

>
>         eth_current_changed();
>  }
> diff --git a/test/dm/eth.c b/test/dm/eth.c
> index 04ccf49..5688b71 100644
> --- a/test/dm/eth.c
> +++ b/test/dm/eth.c
> @@ -36,3 +36,27 @@ static int dm_test_eth(struct dm_test_state *dms)
>         return 0;
>  }
>  DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
> +
> +static int dm_test_eth_alias(struct dm_test_state *dms)
> +{
> +       NetPingIP = string_to_ip("1.1.2.2");
> +       setenv("ethact", "eth0");
> +       ut_assertok(NetLoop(PING));
> +       ut_asserteq_str("eth at 10002000", getenv("ethact"));
> +
> +       setenv("ethact", "eth1");
> +       ut_assertok(NetLoop(PING));
> +       ut_asserteq_str("eth at 10004000", getenv("ethact"));
> +
> +       /* Expected to fail since eth2 is not defined in the device tree */
> +       setenv("ethact", "eth2");
> +       ut_assertok(NetLoop(PING));
> +       ut_asserteq_str("eth at 10002000", getenv("ethact"));
> +
> +       setenv("ethact", "eth5");
> +       ut_assertok(NetLoop(PING));
> +       ut_asserteq_str("eth at 10003000", getenv("ethact"));

Looks good to me.

> +
> +       return 0;
> +}
> +DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
> diff --git a/test/dm/test.dts b/test/dm/test.dts
> index 2f68cdf..bc2409d 100644
> --- a/test/dm/test.dts
> +++ b/test/dm/test.dts
> @@ -17,6 +17,8 @@
>                 testfdt3 = "/b-test";
>                 testfdt5 = "/some-bus/c-test at 5";
>                 testfdt8 = "/a-test";
> +               eth0 = "/eth at 10002000";
> +               eth5 = &eth_5;
>         };
>
>         uart0: serial {
> @@ -155,7 +157,7 @@
>                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
>         };
>
> -       eth at 10003000 {
> +       eth_5: eth at 10003000 {
>                 compatible = "sandbox,eth";
>                 reg = <0x10003000 0x1000>;
>                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 18/23] test: dm: eth: Add testing for ethrotate env var
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 18/23] test: dm: eth: Add testing for ethrotate " Joe Hershberger
@ 2015-03-01 18:07         ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-01 18:07 UTC (permalink / raw)
  To: u-boot

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Make sure that the ethrotate behavior occurs as expected.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 19/23] sandbox: eth: Add ability to disable ping reply in sandbox eth driver
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 19/23] sandbox: eth: Add ability to disable ping reply in sandbox eth driver Joe Hershberger
@ 2015-03-01 18:07         ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-01 18:07 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> This is needed to test the netretry functionality (make the command fail
> on a sandbox eth device).
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>

Rather than using environment variables to communicate, you should use
a function call into this code. See arch/sandbox/include/asm/test.h.

Or you can create a state function and update the state (see state.h)
if you want it to affect more than one driver.

> ---
>
> Changes in v4:
> -Add ability to disable ping reply in sandbox eth driver
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/net/sandbox.c | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
> index 81362e6..28fe09a 100644
> --- a/drivers/net/sandbox.c
> +++ b/drivers/net/sandbox.c
> @@ -49,9 +49,14 @@ static int sb_eth_send(struct udevice *dev, void *packet, int length)
>  {
>         struct eth_sandbox_priv *priv = dev_get_priv(dev);
>         struct ethernet_hdr *eth = packet;
> +       char varname[32];
>
>         debug("eth_sandbox: Send packet %d\n", length);
>
> +       sprintf(varname, "eth_sandbox_disable_%d", dev->seq);
> +       if (getenv_yesno(varname) > 0)
> +               return 0;
> +
>         if (ntohs(eth->et_protlen) == PROT_ARP) {
>                 struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
>
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 22/23] sandbox: Enable DHCP and IP defrag
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 22/23] sandbox: Enable DHCP and IP defrag Joe Hershberger
@ 2015-03-01 18:07         ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-01 18:07 UTC (permalink / raw)
  To: u-boot

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> This is now testable via the eth-raw interface
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v4:
> -New to v4
>
> Changes in v3: None
> Changes in v2: None
>
>  include/configs/sandbox.h | 8 ++++++++
>  1 file changed, 8 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

>
> diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
> index caf9f5a..034050e 100644
> --- a/include/configs/sandbox.h
> +++ b/include/configs/sandbox.h
> @@ -127,6 +127,14 @@
>  #include <config_cmd_default.h>
>
>  #define CONFIG_CMD_PING
> +#define CONFIG_CMD_DHCP
> +#define CONFIG_BOOTP_DNS
> +#define CONFIG_BOOTP_DNS2
> +#define CONFIG_BOOTP_GATEWAY
> +#define CONFIG_BOOTP_SEND_HOSTNAME
> +#define CONFIG_BOOTP_SERVERIP
> +#define CONFIG_BOOTP_SUBNETMASK
> +#define CONFIG_IP_DEFRAG
>
>  #define CONFIG_CMD_HASH
>  #define CONFIG_HASH_VERIFY
> --
> 1.7.11.5
>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 23/23] sandbox: eth: Add support for using the 'lo' interface
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 23/23] sandbox: eth: Add support for using the 'lo' interface Joe Hershberger
@ 2015-03-01 18:07         ` Simon Glass
  2015-03-02  7:18           ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-03-01 18:07 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The 'lo' interface on Linux doesn't support thinks like ARP or
> link-layer access like we use to talk to a normal network interface.
> A higher-level network API must be used to access localhost.
>
> As written, this interface is limited to not supporting ICMP since the
> API doesn't allow the socket to be opened for all IP traffic and be able
> to receive at the same time. UDP is far more useful to test with, so it
> was selected over ICMP. Ping won't work, but things like TFTP should
> work.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v4:
> -Added support for the 'lo' network interface
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/sandbox/cpu/eth-raw-os.c         | 152 +++++++++++++++++++++++++++-------
>  arch/sandbox/dts/sandbox.dts          |  10 +++
>  arch/sandbox/include/asm/eth-raw-os.h |  10 ++-
>  drivers/net/sandbox-raw.c             |  62 +++++++++++++-
>  4 files changed, 203 insertions(+), 31 deletions(-)
>
> diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c
> index 9218f94..acb150a 100644
> --- a/arch/sandbox/cpu/eth-raw-os.c
> +++ b/arch/sandbox/cpu/eth-raw-os.c
> @@ -11,6 +11,8 @@
>  #include <errno.h>
>  #include <net/if.h>
>  #include <netinet/in.h>
> +#include <netinet/ip.h>
> +#include <netinet/udp.h>
>  #include <stdio.h>
>  #include <stdlib.h>
>  #include <string.h>
> @@ -19,51 +21,139 @@
>  #include <sys/socket.h>
>  #include <unistd.h>
>
> +#include <arpa/inet.h>
>  #include <linux/if_ether.h>
>  #include <linux/if_packet.h>
>
>  int sandbox_eth_raw_os_init(const char *ifname, unsigned char *ethmac,
>                             struct eth_sandbox_raw_priv *priv)
>  {
> -       struct sockaddr_ll *device;
> -       struct packet_mreq mr;
> -
> -       /* Prepare device struct */
> -       priv->device = malloc(sizeof(struct sockaddr_ll));
> -       device = priv->device;
> -       memset(device, 0, sizeof(struct sockaddr_ll));
> -       device->sll_ifindex = if_nametoindex(ifname);
> -       device->sll_family = AF_PACKET;
> -       memcpy(device->sll_addr, ethmac, 6);
> -       device->sll_halen = htons(6);
> -
> -       /* Open socket */
> -       priv->sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
> -       if (priv->sd < 0) {
> -               printf("Failed to open socket: %d %s\n", errno,
> -                      strerror(errno));
> -               return -errno;
> +       if (priv->local) {

Can you put these two blocks of code (if and else) in separate
functions and call them from here? This function is too long.

> +               struct sockaddr_in *device;
> +               int ret;
> +               struct timeval tv;
> +               int one = 1;
> +
> +               /* Prepare device struct */
> +               priv->device = malloc(sizeof(struct sockaddr_in));

return -ENOMEM if NULL.

> +               device = priv->device;
> +               memset(device, 0, sizeof(struct sockaddr_in));
> +               device->sin_family = AF_INET;
> +               ret = inet_pton(AF_INET, "127.0.0.1",

Is this INADDR_LOOPBACK? Maybe you can just assign it here?

> +                         (struct in_addr *)&device->sin_addr.s_addr);
> +               if (ret < 0) {
> +                       printf("Failed to convert address: %d %s\n", errno,
> +                              strerror(errno));
> +                       return -errno;
> +               }
> +
> +               /**
> +                * Open socket
> +                *  Since we specify UDP here, any incoming ICMP packets will
> +                *  not be received, so things like ping will not work on this
> +                *  localhost interface.
> +                */
> +               priv->sd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
> +               if (priv->sd < 0) {
> +                       printf("Failed to open socket: %d %s\n", errno,
> +                              strerror(errno));
> +                       return -errno;
> +               }
> +
> +               /* Allow the receive to timeout after a millisecond */
> +               tv.tv_sec = 0;
> +               tv.tv_usec = 1000;
> +               ret = setsockopt(priv->sd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,
> +                          sizeof(struct timeval));
> +               if (ret < 0) {
> +                       printf("Failed to set opt: %d %s\n", errno,
> +                              strerror(errno));
> +                       return -errno;
> +               }
> +
> +               /* Include the UDP/IP headers on send and receive */
> +               ret = setsockopt(priv->sd, IPPROTO_IP, IP_HDRINCL, &one,
> +                                sizeof(one));
> +               if (ret < 0) {
> +                       printf("Failed to set opt: %d %s\n", errno,
> +                              strerror(errno));
> +                       return -errno;
> +               }
> +               priv->local_bind_sd = -1;
> +               priv->local_bind_udp_port = 0;
> +       } else {
> +               struct sockaddr_ll *device;
> +               struct packet_mreq mr;
> +
> +               /* Prepare device struct */
> +               priv->device = malloc(sizeof(struct sockaddr_ll));
> +               device = priv->device;
> +               memset(device, 0, sizeof(struct sockaddr_ll));
> +               device->sll_ifindex = if_nametoindex(ifname);
> +               device->sll_family = AF_PACKET;
> +               memcpy(device->sll_addr, ethmac, 6);
> +               device->sll_halen = htons(6);
> +
> +               /* Open socket */
> +               priv->sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
> +               if (priv->sd < 0) {
> +                       printf("Failed to open socket: %d %s\n", errno,
> +                              strerror(errno));
> +                       return -errno;
> +               }
> +               /* Bind to the specified interface */
> +               setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
> +                          strlen(ifname) + 1);
> +
> +               /* Enable promiscuous mode to receive responses meant for us */
> +               mr.mr_ifindex = device->sll_ifindex;
> +               mr.mr_type = PACKET_MR_PROMISC;
> +               setsockopt(priv->sd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
> +                          &mr, sizeof(mr));
>         }
> -       /* Bind to the specified interface */
> -       setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
> -                  strlen(ifname) + 1);
> -
> -       /* Enable promiscuous mode to receive responses meant for us */
> -       mr.mr_ifindex = device->sll_ifindex;
> -       mr.mr_type = PACKET_MR_PROMISC;
> -       setsockopt(priv->sd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
> -                  &mr, sizeof(mr));
> +
>         return 0;
>  }
>
>  int sandbox_eth_raw_os_send(void *packet, int length,
> -                           const struct eth_sandbox_raw_priv *priv)
> +                           struct eth_sandbox_raw_priv *priv)
>  {
>         int retval;
> +       struct udphdr *udph = packet + sizeof(struct iphdr);
>
>         if (!priv->sd || !priv->device)
>                 return -EINVAL;
>
> +       if (priv->local && (priv->local_bind_sd == -1 ||
> +                           priv->local_bind_udp_port != udph->source)) {

What does this block of code do? Comment?

> +               struct iphdr *iph = packet;
> +               struct sockaddr_in addr;
> +
> +               if (priv->local_bind_sd != -1)
> +                       close(priv->local_bind_sd);
> +
> +               /* A normal UDP socket is required to bind */
> +               priv->local_bind_sd = socket(AF_INET, SOCK_DGRAM, 0);
> +               if (priv->local_bind_sd < 0) {
> +                       printf("Failed to open bind sd: %d %s\n", errno,
> +                              strerror(errno));
> +                       return -errno;
> +               }
> +               priv->local_bind_udp_port = udph->source;
> +
> +               /**
> +                * Bind the UDP port that we intend to use as our source port
> +                * so that the kernel will not send ICMP port unreachable

Do you mean return the 'ICMP port unreachable' error?

> +                */
> +               addr.sin_family = AF_INET;
> +               addr.sin_port = udph->source;
> +               addr.sin_addr.s_addr = iph->saddr;
> +               retval = bind(priv->local_bind_sd, &addr, sizeof(addr));
> +               if (retval < 0)
> +                       printf("Failed to bind: %d %s\n", errno,
> +                              strerror(errno));
> +       }
> +
>         retval = sendto(priv->sd, packet, length, 0,
>                         (struct sockaddr *)priv->device,
>                         sizeof(struct sockaddr_ll));
> @@ -99,4 +189,10 @@ void sandbox_eth_raw_os_halt(struct eth_sandbox_raw_priv *priv)
>         priv->device = NULL;
>         close(priv->sd);
>         priv->sd = -1;
> +       if (priv->local) {
> +               if (priv->local_bind_sd != -1)
> +                       close(priv->local_bind_sd);
> +               priv->local_bind_sd = -1;
> +               priv->local_bind_udp_port = 0;
> +       }
>  }
> diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
> index b6762f4..9851bda 100644
> --- a/arch/sandbox/dts/sandbox.dts
> +++ b/arch/sandbox/dts/sandbox.dts
> @@ -4,6 +4,10 @@
>         #address-cells = <1>;
>         #size-cells = <0>;
>
> +       aliases {
> +               eth5 = "/eth at 90000000";
> +       };
> +
>         chosen {
>                 stdout-path = "/serial";
>         };
> @@ -192,4 +196,10 @@
>                 reg = <0x80000000 0x1000>;
>                 host-raw-interface = "eth0";
>         };
> +
> +       eth at 90000000 {
> +               compatible = "sandbox,eth-raw";
> +               reg = <0x90000000 0x1000>;
> +               host-raw-interface = "lo";
> +       };
>  };
> diff --git a/arch/sandbox/include/asm/eth-raw-os.h b/arch/sandbox/include/asm/eth-raw-os.h
> index d92b72c..44e7050 100644
> --- a/arch/sandbox/include/asm/eth-raw-os.h
> +++ b/arch/sandbox/include/asm/eth-raw-os.h
> @@ -15,16 +15,24 @@
>   *
>   * sd: socket descriptor - the open socket during a session
>   * device: struct sockaddr_ll - the host interface packets move to/from
> + * local: 1 or 0 to select a local interface or not

Should expand this a bit. The local interface is the loopback
device....why do you want one over the other?

> + * local_bindsd: socket descriptor to prevent the kernel from sending
> + *              a message to the server claiming the port is
> + *              unreachable
> + * local_bind_udp_port: The UDP port number that we bound to
>   */
>  struct eth_sandbox_raw_priv {
>         int sd;
>         void *device;
> +       int local;
> +       int local_bind_sd;
> +       unsigned short local_bind_udp_port;
>  };
>
>  int sandbox_eth_raw_os_init(const char *ifname, unsigned char *ethmac,
>                             struct eth_sandbox_raw_priv *priv);
>  int sandbox_eth_raw_os_send(void *packet, int length,
> -                           const struct eth_sandbox_raw_priv *priv);
> +                           struct eth_sandbox_raw_priv *priv);
>  int sandbox_eth_raw_os_recv(void *packet, int *length,
>                             const struct eth_sandbox_raw_priv *priv);
>  void sandbox_eth_raw_os_halt(struct eth_sandbox_raw_priv *priv);
> diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
> index 01b33a9..4b0f836 100644
> --- a/drivers/net/sandbox-raw.c
> +++ b/drivers/net/sandbox-raw.c
> @@ -15,6 +15,8 @@
>
>  DECLARE_GLOBAL_DATA_PTR;
>
> +static int reply_arp;
> +static IPaddr_t arp_ip;
>
>  static int sb_eth_raw_start(struct udevice *dev)
>  {
> @@ -28,6 +30,12 @@ static int sb_eth_raw_start(struct udevice *dev)
>         interface = fdt_getprop(gd->fdt_blob, dev->of_offset,
>                                             "host-raw-interface", NULL);
>
> +       if (strcmp(interface, "lo") == 0) {
> +               priv->local = 1;
> +               setenv("ipaddr", "127.0.0.1");
> +               setenv("serverip", "127.0.0.1");
> +       }
> +
>         retval = sandbox_eth_raw_os_init(interface, pdata->enetaddr, priv);
>
>         return retval;
> @@ -39,19 +47,69 @@ static int sb_eth_raw_send(struct udevice *dev, void *packet, int length)
>
>         debug("eth_sandbox_raw: Send packet %d\n", length);
>
> +       if (priv->local) {
> +               struct ethernet_hdr *eth = packet;
> +
> +               if (ntohs(eth->et_protlen) == PROT_ARP) {
> +                       struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
> +
> +                       /**
> +                        * localhost works on a higher level API in Linux than

nit: higher-level

> +                        * ARP packets, so fake it

fake what?

> +                        */
> +                       arp_ip = NetReadIP(&arp->ar_tpa);
> +                       reply_arp = 1;
> +                       return 0;
> +               }
> +               packet += ETHER_HDR_SIZE;
> +               length -= ETHER_HDR_SIZE;
> +       }
>         return sandbox_eth_raw_os_send(packet, length, priv);
>  }
>
>  static int sb_eth_raw_recv(struct udevice *dev)
>  {
> +       struct eth_pdata *pdata = dev_get_platdata(dev);
>         struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
> -       int retval;
> +       int retval = 0;
>         uchar buffer[PKTSIZE];
>         int length;
>
> -       retval = sandbox_eth_raw_os_recv(buffer, &length, priv);
> +       if (reply_arp) {
> +               struct arp_hdr *arp = (void *)buffer + ETHER_HDR_SIZE;
> +
> +               /* Formulate a fake ARP */
> +               arp->ar_hrd = htons(ARP_ETHER);
> +               arp->ar_pro = htons(PROT_IP);
> +               arp->ar_hln = ARP_HLEN;
> +               arp->ar_pln = ARP_PLEN;
> +               arp->ar_op = htons(ARPOP_REPLY);
> +               /* Any non-zero MAC address will work */
> +               memset(&arp->ar_sha, 0x01, ARP_HLEN);
> +               /* Use whatever IP we were looking for (always 127.0.0.1?) */
> +               NetWriteIP(&arp->ar_spa, arp_ip);
> +               memcpy(&arp->ar_tha, pdata->enetaddr, ARP_HLEN);
> +               NetWriteIP(&arp->ar_tpa, NetOurIP);
> +               length = ARP_HDR_SIZE;
> +       } else {
> +               /* If local, the Ethernet header won't be included; skip it */
> +               uchar *pktptr = priv->local ? buffer + ETHER_HDR_SIZE : buffer;
> +
> +               retval = sandbox_eth_raw_os_recv(pktptr, &length, priv);
> +       }
>
>         if (!retval && length) {
> +               if (priv->local) {
> +                       struct ethernet_hdr *eth = (void *)buffer;
> +
> +                       /* Fill in enough of the missing Ethernet header */
> +                       memcpy(eth->et_dest, pdata->enetaddr, ARP_HLEN);
> +                       memset(eth->et_src, 0x01, ARP_HLEN);
> +                       eth->et_protlen = htons(reply_arp ? PROT_ARP : PROT_IP);
> +                       reply_arp = 0;
> +                       length += ETHER_HDR_SIZE;
> +               }
> +
>                 debug("eth_sandbox_raw: received packet %d\n",
>                       length);
>                 NetReceive(buffer, length);
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 20/23] test: dm: net: Add a test of the netretry behavior
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 20/23] test: dm: net: Add a test of the netretry behavior Joe Hershberger
@ 2015-03-01 18:07         ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-01 18:07 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The effect of the "netretry" env var was recently changed. This test
> checks that behavior.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v4:
> -Updated expected behavior based on changes to the NetLoop
>
> Changes in v3:
> -Added testing for netretry
>
> Changes in v2: None
>
>  test/dm/eth.c | 23 +++++++++++++++++++++++
>  1 file changed, 23 insertions(+)
>
> diff --git a/test/dm/eth.c b/test/dm/eth.c
> index a3cbd3f..4581c8e 100644
> --- a/test/dm/eth.c
> +++ b/test/dm/eth.c
> @@ -104,3 +104,26 @@ static int dm_test_eth_rotate(struct dm_test_state *dms)
>         return 0;
>  }
>  DM_TEST(dm_test_eth_rotate, DM_TESTF_SCAN_FDT);
> +
> +static int dm_test_net_retry(struct dm_test_state *dms)
> +{
> +       NetPingIP = string_to_ip("1.1.2.2");
> +
> +       setenv("eth_sandbox_disable_1", "yes");

As mentioned in the other patch, something like:

sandbox_eth_set_disable(1, true);

> +       setenv("ethact", "eth at 10004000");
> +       setenv("netretry", "yes");
> +       ut_assertok(NetLoop(PING));
> +       ut_asserteq_str("eth at 10002000", getenv("ethact"));
> +

A comment against each test case as to why it works or doesn't would help.

> +       setenv("ethact", "eth at 10004000");
> +       setenv("netretry", "no");
> +       ut_asserteq(-1, NetLoop(PING));

One day it would be nice if this could return an error code from errno.h.

> +       ut_asserteq_str("eth at 10004000", getenv("ethact"));
> +
> +       /* Restore the env */
> +       setenv("netretry", NULL);
> +       setenv("eth_sandbox_disable_1", NULL);

sandbox_eth_set_disable(1, false);

> +
> +       return 0;
> +}
> +DM_TEST(dm_test_net_retry, DM_TESTF_SCAN_FDT);
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 13/23] sandbox: eth: Add network support to sandbox
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 13/23] sandbox: eth: Add network support to sandbox Joe Hershberger
@ 2015-03-01 18:07         ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-01 18:07 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Add basic network support to sandbox which includes a network driver.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v4:
> -Cleaned up sandbox EXTRA_ENV define
> -Moved config to Kconfig
>
> Changes in v3:
> -Added 2 more ethaddr to sandbox
> -Print which device in the debug write hwaddr
>
> Changes in v2:
> -Change printfs to debug in sandbox driver
> -Remove unused priv struct for sandbox driver
>
>  arch/sandbox/Kconfig         |  9 +++++
>  arch/sandbox/dts/sandbox.dts |  4 +++
>  board/sandbox/README.sandbox |  4 +--
>  drivers/net/Kconfig          | 18 ++++++++++
>  drivers/net/Makefile         |  1 +
>  drivers/net/sandbox.c        | 84 ++++++++++++++++++++++++++++++++++++++++++++
>  include/configs/sandbox.h    | 16 +++++----
>  7 files changed, 128 insertions(+), 8 deletions(-)
>  create mode 100644 drivers/net/sandbox.c
>
> diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
> index 2098b9c..186b58d 100644
> --- a/arch/sandbox/Kconfig
> +++ b/arch/sandbox/Kconfig
> @@ -34,4 +34,13 @@ config DM_I2C
>  config DM_TEST
>         default y
>
> +config NET
> +       default y
> +
> +config NETDEVICES
> +       default y
> +
> +config DM_ETH
> +       default y
> +
>  endmenu
> diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
> index 9ce31bf..36b3bd8 100644
> --- a/arch/sandbox/dts/sandbox.dts
> +++ b/arch/sandbox/dts/sandbox.dts
> @@ -181,4 +181,8 @@
>                 };
>         };
>
> +       eth at 10002000 {
> +               compatible = "sandbox,eth";
> +               reg = <0x10002000 0x1000>;
> +       };
>  };
> diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
> index 3c0df17..c1f5f7e 100644
> --- a/board/sandbox/README.sandbox
> +++ b/board/sandbox/README.sandbox
> @@ -173,16 +173,16 @@ U-Boot sandbox supports these emulations:
>  - Chrome OS EC
>  - GPIO
>  - Host filesystem (access files on the host from within U-Boot)
> +- I2C
>  - Keyboard (Chrome OS)
>  - LCD
> +- Network
>  - Serial (for console only)
>  - Sound (incomplete - see sandbox_sdl_sound_init() for details)
>  - SPI
>  - SPI flash
>  - TPM (Trusted Platform Module)
>
> -Notable omissions are networking and I2C.
> -
>  A wide range of commands is implemented. Filesystems which use a block
>  device are supported.
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index bdd0f05..b08746a 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -3,3 +3,21 @@ config DM_ETH
>         depends on DM
>         help
>           Enable driver model for Ethernet.
> +
> +menuconfig NETDEVICES
> +       bool "Network device support"
> +       depends on NET
> +       help
> +         You must select Y to enable any network device support
> +         Generally if you have any networking support this is a given
> +
> +         If unsure, say Y
> +
> +if NETDEVICES
> +
> +config ETH_SANDBOX
> +       depends on DM_ETH && SANDBOX
> +       default y
> +       bool "Sandbox: Mocked Ethernet driver"

This needs some help.

> +
> +endif # NETDEVICES
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 46c4ac6..15dc431 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -50,6 +50,7 @@ obj-$(CONFIG_NS8382X) += ns8382x.o
>  obj-$(CONFIG_PCNET) += pcnet.o
>  obj-$(CONFIG_RTL8139) += rtl8139.o
>  obj-$(CONFIG_RTL8169) += rtl8169.o
> +obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
>  obj-$(CONFIG_SH_ETHER) += sh_eth.o
>  obj-$(CONFIG_SMC91111) += smc91111.o
>  obj-$(CONFIG_SMC911X) += smc911x.o
> diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
> new file mode 100644
> index 0000000..834e02a
> --- /dev/null
> +++ b/drivers/net/sandbox.c
> @@ -0,0 +1,84 @@
> +/*
> + * Copyright (c) 2015 National Instruments
> + *
> + * (C) Copyright 2015
> + * Joe Hershberger <joe.hershberger@ni.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <malloc.h>
> +#include <net.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static int sb_eth_start(struct udevice *dev)
> +{
> +       debug("eth_sandbox: Start\n");
> +
> +       return 0;
> +}
> +
> +static int sb_eth_send(struct udevice *dev, void *packet, int length)
> +{
> +       debug("eth_sandbox: Send packet %d\n", length);
> +
> +       return 0;
> +}
> +
> +static int sb_eth_recv(struct udevice *dev)
> +{
> +       return 0;
> +}
> +
> +static void sb_eth_stop(struct udevice *dev)
> +{
> +       debug("eth_sandbox: Stop\n");
> +}
> +
> +static int sb_eth_write_hwaddr(struct udevice *dev)
> +{
> +       struct eth_pdata *pdata = dev_get_platdata(dev);
> +
> +       debug("eth_sandbox %s: Write HW ADDR - %pM\n", dev->name,
> +             pdata->enetaddr);
> +       return 0;
> +}
> +
> +static const struct eth_ops sb_eth_ops = {
> +       .start                  = sb_eth_start,
> +       .send                   = sb_eth_send,
> +       .recv                   = sb_eth_recv,
> +       .stop                   = sb_eth_stop,
> +       .write_hwaddr           = sb_eth_write_hwaddr,
> +};
> +
> +static int sb_eth_remove(struct udevice *dev)
> +{
> +       return 0;
> +}
> +
> +static int sb_eth_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct eth_pdata *pdata = dev_get_platdata(dev);
> +
> +       pdata->iobase = dev_get_addr(dev);
> +       return 0;
> +}
> +
> +static const struct udevice_id sb_eth_ids[] = {
> +       { .compatible = "sandbox,eth" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(eth_sandbox) = {
> +       .name   = "eth_sandbox",
> +       .id     = UCLASS_ETH,
> +       .of_match = sb_eth_ids,
> +       .ofdata_to_platdata = sb_eth_ofdata_to_platdata,
> +       .remove = sb_eth_remove,
> +       .ops    = &sb_eth_ops,
> +       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
> +};
> diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
> index febbfb6..664b984 100644
> --- a/include/configs/sandbox.h
> +++ b/include/configs/sandbox.h
> @@ -126,9 +126,6 @@
>  /* include default commands */
>  #include <config_cmd_default.h>
>
> -/* We don't have networking support yet */
> -#undef CONFIG_CMD_NET
> -#undef CONFIG_CMD_NFS
>
>  #define CONFIG_CMD_HASH
>  #define CONFIG_HASH_VERIFY
> @@ -165,16 +162,23 @@
>
>  #define CONFIG_KEYBOARD
>
> -#define CONFIG_EXTRA_ENV_SETTINGS      "stdin=serial,cros-ec-keyb\0" \
> +#define SANDBOX_SERIAL_SETTINGS                "stdin=serial,cros-ec-keyb\0" \
>                                         "stdout=serial,lcd\0" \
>                                         "stderr=serial,lcd\0"
>  #else
> -
> -#define CONFIG_EXTRA_ENV_SETTINGS      "stdin=serial\0" \
> +#define SANDBOX_SERIAL_SETTINGS                "stdin=serial\0" \
>                                         "stdout=serial,lcd\0" \
>                                         "stderr=serial,lcd\0"
>  #endif
>
> +#define SANDBOX_ETH_SETTINGS           "ethaddr=00:00:11:22:33:44\0" \
> +                                       "eth1addr=00:00:11:22:33:45\0" \
> +                                       "eth2addr=00:00:11:22:33:46\0" \
> +                                       "ipaddr=1.2.3.4\0"
> +
> +#define CONFIG_EXTRA_ENV_SETTINGS      SANDBOX_SERIAL_SETTINGS \
> +                                       SANDBOX_ETH_SETTINGS
> +
>  #define CONFIG_GZIP_COMPRESSED
>  #define CONFIG_BZIP2
>  #define CONFIG_LZO
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 21/23] sandbox: eth: Add a bridge to a real network for sandbox
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 21/23] sandbox: eth: Add a bridge to a real network for sandbox Joe Hershberger
@ 2015-03-01 18:07         ` Simon Glass
  2015-03-02  7:17           ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-03-01 18:07 UTC (permalink / raw)
  To: u-boot

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Implement a bridge between u-boot's network stack and Linux's raw packet
> API allowing the sandbox to send and receive packets using the host
> machine's network interface.
>
> This raw Ethernet API requires elevated privileges.  You can either run
> as root, or you can add the capability needed like so:
>
> sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

Reviewed-by: Simon Glass <sjg@chromium.org>

A few nits below.

>
> ---
>
> Changes in v4:
> -Added comments to README.sandbox
> -Use accessors for platdata and priv
> -Add comments to priv struct definition
> -Move os file to arch
> -Cleanup var definition order
> -Moved config to Kconfig
> -Clean up the interface to sandbox's eth-raw-os by passing priv to raw-os
> -Fixed the MAC address limitation (now all traffic uses MAC address from env)
>
> Changes in v3:
> -Made the os raw packet support for sandbox eth build and work.
>
> Changes in v2:
> -Added the raw packet proof-of-concept patch.
>
>  arch/sandbox/Kconfig                  |   3 +
>  arch/sandbox/cpu/Makefile             |  10 ++++
>  arch/sandbox/cpu/eth-raw-os.c         | 102 +++++++++++++++++++++++++++++++++
>  arch/sandbox/dts/sandbox.dts          |   6 ++
>  arch/sandbox/include/asm/eth-raw-os.h |  32 +++++++++++
>  board/sandbox/README.sandbox          |  13 +++++
>  drivers/net/Kconfig                   |   5 ++
>  drivers/net/Makefile                  |   1 +
>  drivers/net/sandbox-raw.c             | 105 ++++++++++++++++++++++++++++++++++
>  9 files changed, 277 insertions(+)
>  create mode 100644 arch/sandbox/cpu/eth-raw-os.c
>  create mode 100644 arch/sandbox/include/asm/eth-raw-os.h
>  create mode 100644 drivers/net/sandbox-raw.c
>
> diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
> index 186b58d..f84b3fc 100644
> --- a/arch/sandbox/Kconfig
> +++ b/arch/sandbox/Kconfig
> @@ -43,4 +43,7 @@ config NETDEVICES
>  config DM_ETH
>         default y
>
> +config ETH_SANDBOX_RAW
> +       default y
> +
>  endmenu
> diff --git a/arch/sandbox/cpu/Makefile b/arch/sandbox/cpu/Makefile
> index 7d4410c..1b42fee 100644
> --- a/arch/sandbox/cpu/Makefile
> +++ b/arch/sandbox/cpu/Makefile
> @@ -8,6 +8,7 @@
>  #
>
>  obj-y  := cpu.o os.o start.o state.o
> +obj-$(CONFIG_ETH_SANDBOX_RAW)  += eth-raw-os.o
>  obj-$(CONFIG_SANDBOX_SDL)      += sdl.o
>
>  # os.c is build in the system environment, so needs standard includes
> @@ -20,3 +21,12 @@ $(obj)/os.o: $(src)/os.c FORCE
>         $(call if_changed_dep,cc_os.o)
>  $(obj)/sdl.o: $(src)/sdl.c FORCE
>         $(call if_changed_dep,cc_os.o)
> +
> +# eth-raw-os.c is built in the system env, so needs standard includes
> +# CFLAGS_REMOVE_eth-raw-os.o cannot be used to drop header include path
> +quiet_cmd_cc_eth-raw-os.o = CC $(quiet_modtag)  $@
> +cmd_cc_eth-raw-os.o = $(CC) $(filter-out -nostdinc, \
> +       $(patsubst -I%,-idirafter%,$(c_flags))) -c -o $@ $<
> +
> +$(obj)/eth-raw-os.o: $(src)/eth-raw-os.c FORCE
> +       $(call if_changed_dep,cc_eth-raw-os.o)
> diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c
> new file mode 100644
> index 0000000..9218f94
> --- /dev/null
> +++ b/arch/sandbox/cpu/eth-raw-os.c
> @@ -0,0 +1,102 @@
> +/*
> + * Copyright (c) 2015 National Instruments
> + *
> + * (C) Copyright 2015
> + * Joe Hershberger <joe.hershberger@ni.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0
> + */
> +
> +#include <asm/eth-raw-os.h>
> +#include <errno.h>
> +#include <net/if.h>
> +#include <netinet/in.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/types.h>
> +#include <sys/ioctl.h>
> +#include <sys/socket.h>
> +#include <unistd.h>
> +
> +#include <linux/if_ether.h>
> +#include <linux/if_packet.h>
> +
> +int sandbox_eth_raw_os_init(const char *ifname, unsigned char *ethmac,
> +                           struct eth_sandbox_raw_priv *priv)
> +{
> +       struct sockaddr_ll *device;
> +       struct packet_mreq mr;
> +
> +       /* Prepare device struct */
> +       priv->device = malloc(sizeof(struct sockaddr_ll));

This calls U-Boot's malloc() and it can return NULL, so you should
return -ENOMEM in that case.

> +       device = priv->device;
> +       memset(device, 0, sizeof(struct sockaddr_ll));
> +       device->sll_ifindex = if_nametoindex(ifname);
> +       device->sll_family = AF_PACKET;
> +       memcpy(device->sll_addr, ethmac, 6);
> +       device->sll_halen = htons(6);
> +
> +       /* Open socket */
> +       priv->sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
> +       if (priv->sd < 0) {
> +               printf("Failed to open socket: %d %s\n", errno,
> +                      strerror(errno));
> +               return -errno;
> +       }
> +       /* Bind to the specified interface */
> +       setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
> +                  strlen(ifname) + 1);
> +
> +       /* Enable promiscuous mode to receive responses meant for us */
> +       mr.mr_ifindex = device->sll_ifindex;
> +       mr.mr_type = PACKET_MR_PROMISC;
> +       setsockopt(priv->sd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
> +                  &mr, sizeof(mr));
> +       return 0;
> +}
> +
> +int sandbox_eth_raw_os_send(void *packet, int length,
> +                           const struct eth_sandbox_raw_priv *priv)
> +{
> +       int retval;
> +
> +       if (!priv->sd || !priv->device)
> +               return -EINVAL;
> +
> +       retval = sendto(priv->sd, packet, length, 0,
> +                       (struct sockaddr *)priv->device,
> +                       sizeof(struct sockaddr_ll));
> +       if (retval < 0)
> +               printf("Failed to send packet: %d %s\n", errno,
> +                      strerror(errno));

return -errno here?

> +       return retval;
> +}
> +
> +int sandbox_eth_raw_os_recv(void *packet, int *length,
> +                           const struct eth_sandbox_raw_priv *priv)
> +{
> +       int retval;
> +       int saddr_size;
> +
> +       if (!priv->sd || !priv->device)
> +               return -EINVAL;
> +       saddr_size = sizeof(struct sockaddr);
> +       retval = recvfrom(priv->sd, packet, 1536, 0,
> +                         (struct sockaddr *)priv->device,
> +                         (socklen_t *)&saddr_size);
> +       *length = 0;
> +       if (retval > 0) {
> +               *length = retval;
> +               return 0;
> +       }
> +       return retval;

return -errno here? At present you are returning -1 I think, which is -EPERM.

> +}
> +
> +void sandbox_eth_raw_os_halt(struct eth_sandbox_raw_priv *priv)
> +{
> +       free((struct sockaddr_ll *)priv->device);

Don't need that cast?

> +       priv->device = NULL;
> +       close(priv->sd);
> +       priv->sd = -1;
> +}
> diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
> index 235dcc0..b6762f4 100644
> --- a/arch/sandbox/dts/sandbox.dts
> +++ b/arch/sandbox/dts/sandbox.dts
> @@ -186,4 +186,10 @@
>                 reg = <0x10002000 0x1000>;
>                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
>         };
> +
> +       eth at 80000000 {
> +               compatible = "sandbox,eth-raw";
> +               reg = <0x80000000 0x1000>;
> +               host-raw-interface = "eth0";
> +       };
>  };
> diff --git a/arch/sandbox/include/asm/eth-raw-os.h b/arch/sandbox/include/asm/eth-raw-os.h
> new file mode 100644
> index 0000000..d92b72c
> --- /dev/null
> +++ b/arch/sandbox/include/asm/eth-raw-os.h
> @@ -0,0 +1,32 @@
> +/*
> + * Copyright (c) 2015 National Instruments
> + *
> + * (C) Copyright 2015
> + * Joe Hershberger <joe.hershberger@ni.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0
> + */
> +
> +#ifndef __ETH_RAW_OS_H
> +#define __ETH_RAW_OS_H
> +
> +/**
> + * struct eth_sandbox_raw_priv - raw socket session
> + *
> + * sd: socket descriptor - the open socket during a session
> + * device: struct sockaddr_ll - the host interface packets move to/from
> + */
> +struct eth_sandbox_raw_priv {
> +       int sd;
> +       void *device;
> +};
> +
> +int sandbox_eth_raw_os_init(const char *ifname, unsigned char *ethmac,
> +                           struct eth_sandbox_raw_priv *priv);
> +int sandbox_eth_raw_os_send(void *packet, int length,
> +                           const struct eth_sandbox_raw_priv *priv);
> +int sandbox_eth_raw_os_recv(void *packet, int *length,
> +                           const struct eth_sandbox_raw_priv *priv);
> +void sandbox_eth_raw_os_halt(struct eth_sandbox_raw_priv *priv);
> +
> +#endif /* __ETH_RAW_OS_H */
> diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
> index c1f5f7e..c4c3139 100644
> --- a/board/sandbox/README.sandbox
> +++ b/board/sandbox/README.sandbox
> @@ -190,6 +190,19 @@ Also sandbox uses generic board (CONFIG_SYS_GENERIC_BOARD) and supports
>  driver model (CONFIG_DM) and associated commands.
>
>
> +Linux RAW Networking Bridge
> +---------------------------
> +
> +The sandbox_eth_raw driver bridges traffic between the bottom of the network
> +stack and the RAW sockets API in Linux. This allows much of the u-boot network
> +functionality to be tested in sandbox against real network traffic.
> +
> +The RAW sockets Ethernet API requires elevated privileges in Linux. You can
> +either run as root, or you can add the capability needed like so:
> +
> +sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot

This is so cool.

Can you give some examples here? For me, ping seems to work, but I
can't use bootp. Is that what the raw mode is for? How do I enable it?
I tried setting ethact but am not sure what I am doing.

Useful examples would be:

- ping
- bootp
- tftpboot

and how to use raw/normal device.

> +
> +
>  SPI Emulation
>  -------------
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index b08746a..dcbfa8a 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -20,4 +20,9 @@ config ETH_SANDBOX
>         default y
>         bool "Sandbox: Mocked Ethernet driver"
>
> +config ETH_SANDBOX_RAW
> +       depends on DM_ETH && SANDBOX
> +       default y
> +       bool "Sandbox: Bridge to Linux Raw Sockets"

This needs some help.

> +
>  endif # NETDEVICES
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 15dc431..2659a8a 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -51,6 +51,7 @@ obj-$(CONFIG_PCNET) += pcnet.o
>  obj-$(CONFIG_RTL8139) += rtl8139.o
>  obj-$(CONFIG_RTL8169) += rtl8169.o
>  obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
> +obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o
>  obj-$(CONFIG_SH_ETHER) += sh_eth.o
>  obj-$(CONFIG_SMC91111) += smc91111.o
>  obj-$(CONFIG_SMC911X) += smc911x.o
> diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
> new file mode 100644
> index 0000000..01b33a9
> --- /dev/null
> +++ b/drivers/net/sandbox-raw.c
> @@ -0,0 +1,105 @@
> +/*
> + * Copyright (c) 2015 National Instruments
> + *
> + * (C) Copyright 2015
> + * Joe Hershberger <joe.hershberger@ni.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0
> + */
> +
> +#include <asm/eth-raw-os.h>
> +#include <common.h>
> +#include <dm.h>
> +#include <malloc.h>
> +#include <net.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +
> +static int sb_eth_raw_start(struct udevice *dev)
> +{
> +       struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
> +       struct eth_pdata *pdata = dev_get_platdata(dev);
> +       int retval;
> +       const char *interface;
> +
> +       debug("eth_sandbox_raw: Start\n");
> +
> +       interface = fdt_getprop(gd->fdt_blob, dev->of_offset,
> +                                           "host-raw-interface", NULL);

This can return NULL, so you should return -EINVAL in that case.

> +
> +       retval = sandbox_eth_raw_os_init(interface, pdata->enetaddr, priv);
> +
> +       return retval;
> +}
> +
> +static int sb_eth_raw_send(struct udevice *dev, void *packet, int length)
> +{
> +       struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
> +
> +       debug("eth_sandbox_raw: Send packet %d\n", length);
> +
> +       return sandbox_eth_raw_os_send(packet, length, priv);
> +}
> +
> +static int sb_eth_raw_recv(struct udevice *dev)
> +{
> +       struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
> +       int retval;
> +       uchar buffer[PKTSIZE];
> +       int length;
> +
> +       retval = sandbox_eth_raw_os_recv(buffer, &length, priv);
> +
> +       if (!retval && length) {
> +               debug("eth_sandbox_raw: received packet %d\n",
> +                     length);
> +               NetReceive(buffer, length);
> +       }
> +       return 0;
> +}
> +
> +static void sb_eth_raw_stop(struct udevice *dev)
> +{
> +       struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
> +
> +       debug("eth_sandbox_raw: Stop\n");
> +
> +       sandbox_eth_raw_os_halt(priv);
> +}
> +
> +static const struct eth_ops sb_eth_raw_ops = {
> +       .start                  = sb_eth_raw_start,
> +       .send                   = sb_eth_raw_send,
> +       .recv                   = sb_eth_raw_recv,
> +       .stop                   = sb_eth_raw_stop,
> +};
> +
> +static int sb_eth_raw_remove(struct udevice *dev)
> +{
> +       return 0;
> +}

You can drop this function.

> +
> +static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct eth_pdata *pdata = dev_get_platdata(dev);
> +
> +       pdata->iobase = dev_get_addr(dev);
> +       return 0;
> +}
> +
> +static const struct udevice_id sb_eth_raw_ids[] = {
> +       { .compatible = "sandbox,eth-raw" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(eth_sandbox_raw) = {
> +       .name   = "eth_sandbox_raw",
> +       .id     = UCLASS_ETH,
> +       .of_match = sb_eth_raw_ids,
> +       .ofdata_to_platdata = sb_eth_raw_ofdata_to_platdata,
> +       .remove = sb_eth_raw_remove,
> +       .ops    = &sb_eth_raw_ops,
> +       .priv_auto_alloc_size = sizeof(struct eth_sandbox_raw_priv),
> +       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
> +};
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 17/23] dm: eth: Add support for ethprime env var
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 17/23] dm: eth: Add support for ethprime env var Joe Hershberger
@ 2015-03-01 18:07         ` Simon Glass
  2015-03-01 22:06           ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-03-01 18:07 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The ethprime env var is used to indicate the starting device if none is
> specified in ethact. Also support aliases specified in the ethprime var.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v4:
> -Load from ethprime on eth_initialize()
>
> Changes in v3:
> -Added support for ethprime
>
> Changes in v2: None
>
>  net/eth.c     | 29 ++++++++++++++++++++++++++++-
>  test/dm/eth.c | 20 ++++++++++++++++++++
>  2 files changed, 48 insertions(+), 1 deletion(-)
>
> diff --git a/net/eth.c b/net/eth.c
> index 8b853e8..3b3cd84 100644
> --- a/net/eth.c
> +++ b/net/eth.c
> @@ -341,6 +341,18 @@ int eth_initialize(void)
>                 printf("No ethernet found.\n");
>                 bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
>         } else {
> +               char *ethprime = getenv("ethprime");
> +               struct udevice *prime_dev = NULL;
> +
> +               if (ethprime)
> +                       prime_dev = eth_get_dev_by_name(ethprime);
> +               if (prime_dev) {
> +                       eth_set_dev(prime_dev);
> +                       eth_current_changed();
> +               } else {
> +                       eth_set_dev(NULL);
> +               }
> +
>                 bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
>                 do {
>                         if (num_devices)
> @@ -348,6 +360,9 @@ int eth_initialize(void)
>
>                         printf("eth%d: %s", dev->seq, dev->name);
>
> +                       if (ethprime && dev == prime_dev)
> +                               printf(" [PRIME]");
> +
>                         eth_write_hwaddr(dev);
>
>                         uclass_next_device(&dev);
> @@ -896,8 +911,20 @@ void eth_set_current(void)
>                 act = getenv("ethact");
>                 env_changed_id = env_id;
>         }
> -       if (act != NULL)
> +
> +       if (act == NULL) {
> +               char *ethprime = getenv("ethprime");
> +               struct udevice *dev = NULL;
> +
> +               if (ethprime)
> +                       dev = eth_get_dev_by_name(ethprime);

This function can return either a net_device or a udevice. So if
DM_ETH is not enabled, you will get a warning here.

> +               if (dev)
> +                       eth_set_dev(dev);
> +               else
> +                       eth_set_dev(NULL);
> +       } else {
>                 eth_set_dev(eth_get_dev_by_name(act));
> +       }
>
>         eth_current_changed();
>  }
> diff --git a/test/dm/eth.c b/test/dm/eth.c
> index 5688b71..96e3c46 100644
> --- a/test/dm/eth.c
> +++ b/test/dm/eth.c
> @@ -60,3 +60,23 @@ static int dm_test_eth_alias(struct dm_test_state *dms)
>         return 0;
>  }
>  DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
> +
> +static int dm_test_eth_prime(struct dm_test_state *dms)
> +{
> +       NetPingIP = string_to_ip("1.1.2.2");
> +
> +       /* Expected to be "eth at 10003000" because of ethprime variable */
> +       setenv("ethact", NULL);
> +       setenv("ethprime", "eth5");
> +       ut_assertok(NetLoop(PING));
> +       ut_asserteq_str("eth at 10003000", getenv("ethact"));
> +
> +       /* Expected to be "eth at 10002000" because it is first */
> +       setenv("ethact", NULL);
> +       setenv("ethprime", NULL);
> +       ut_assertok(NetLoop(PING));
> +       ut_asserteq_str("eth at 10002000", getenv("ethact"));
> +
> +       return 0;
> +}
> +DM_TEST(dm_test_eth_prime, DM_TESTF_SCAN_FDT);
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 06/23] net: Refactor in preparation for driver model
  2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 06/23] net: Refactor in preparation for driver model Joe Hershberger
@ 2015-03-01 18:08         ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-01 18:08 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Move some things around and organize things so that the driver model
> implementation will fit in more easily.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v4:
> -Fix compile regression in !DM_ETH case
>
> Changes in v3:
> -Move the get_dev_by_* protos to also be !DM_ETH like the impl
>
> Changes in v2: None
>
>  include/net.h | 68 +++++++++++++++++++++++++++-------------------------
>  net/eth.c     | 77 +++++++++++++++++++++++++++++++----------------------------
>  2 files changed, 76 insertions(+), 69 deletions(-)
>

I think I mention this in a later response. But for this patch I see
the errors below:

08: net: Refactor in preparation for driver model
       arm:  +   snow seaboard
       x86:  +   coreboot-x86
+../net/eth.c: In function ?eth_register?:
+../net/eth.c:208:3: error: implicit declaration of function
?eth_current_changed? [-Werror=implicit-function-declaration]
+   eth_current_changed();
+   ^
+../net/eth.c: At top level:
+../net/eth.c:471:13: error: conflicting types for
?eth_current_changed? [-Werror]
+ static void eth_current_changed(void)
+             ^
+../net/eth.c:471:13: error: static declaration of
?eth_current_changed? follows non-static declaration
+../net/eth.c:208:3: note: previous implicit declaration of
?eth_current_changed? was here
+cc1: all warnings being treated as errors
+make[2]: *** [net/eth.o] Error 1
+make[1]: *** [net] Error 2
+make: *** [sub-make] Error 2

[snip]

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 02/23] common: Make sure arch-specific map_sysmem() is defined
  2015-03-01 18:07         ` Simon Glass
@ 2015-03-01 21:16           ` Joe Hershberger
  2015-03-02  2:24             ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-01 21:16 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Sun, Mar 1, 2015 at 12:07 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > In the case where the arch defines a custom map_sysmem(), make sure that
> > including just common.h is sufficient to have these functions as they
> > are when the arch does not override it.
> >
> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> >
> > ---
> >
> > Changes in v4:
> > -New to v4
> >
> > Changes in v3: None
> > Changes in v2: None
> >
> >  include/common.h | 4 +++-
> >  1 file changed, 3 insertions(+), 1 deletion(-)
> >
> > diff --git a/include/common.h b/include/common.h
> > index 77c55c6..6510efc 100644
> > --- a/include/common.h
> > +++ b/include/common.h
> > @@ -846,7 +846,9 @@ int cpu_release(int nr, int argc, char * const
argv[]);
> >  #endif
> >
> >  /* Define a null map_sysmem() if the architecture doesn't use it */
> > -# ifndef CONFIG_ARCH_MAP_SYSMEM
> > +# ifdef CONFIG_ARCH_MAP_SYSMEM
> > +#include <asm/io.h>
> > +# else
> >  static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
> >  {
> >         return (void *)(uintptr_t)paddr;
>
> Do we need this patch? Is it just for sandbox? It would be nice to
> remove things from common.h rather than adding them!

If you have a recommendation for where these static inline functions should
move, then I'm happy to move it all to a new place. My assertion is that
whatever it is that you include to get these static inlines should also be
what you include when CONFIG_ARCH_MAP_SYSMEM is defined. You should not
need to include the arch-specific header separately each place that one of
these mapping functions is used.

> Anyway if you want to go ahead I'm OK with it.
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 12/23] dm: eth: Add basic driver model support to Ethernet stack
  2015-03-01 18:07         ` Simon Glass
@ 2015-03-01 21:45           ` Joe Hershberger
  2015-03-02  2:26             ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-01 21:45 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Sun, Mar 1, 2015 at 12:07 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > First just add support for MAC drivers.
> >
> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> This looks right to me. I still have some comments on error handling,
> but I'm OK with you addressing these in a follow-on patch if you like.

Thanks for going back and forth on this to make it right.

> > ---
> >
> > Changes in v4:
> > -Redo the seq / probe implementation
> > --Don't prevent eth_initialize on driver model
> > --Use eth_initialize to probe all devices and write_hwaddr
> > --Look up MAC address in post-probe
> > --Include ethprime handling in eth_initialize
> > --If current == NULL, always check if there is a device available in
eth_get_dev
> > --Move env init call from uclass init to eth_initialize
> > --Print the alias in eth_initialize
> > -Stop handling selecting a new "current" in pre-unbind as it will now
work itself out by clearing the pointer
> > -Change -1 returns to error constants
> > -Remove bd_t *bis from dm eth_ops init function
> > -Add documentation to the structures
> > -Add a helper function for eth_uclass_priv
> > -Change puts to printf
> > -Add eth_get_ops helper
> > -Rename init() to start() in ops
> > -Rename halt() to stop() in ops
> > -Remove checks for driver==NULL
> > -Remove priv pointer in per-device priv struct (drivers already get
their own directly from DM)
> >
> > Changes in v3:
> > -Correct the pre_unbind logic
> > -Correct failure chaining from bind to probe to init
> > --Fail init if not activated
> > --Fail probe if ethaddr not set
> > -Update ethaddr from env unconditionally on init
> > -Use set current to select the current device regardless of the
previous selection
> > -Allow current eth dev to be NULL
> > -Fixed blank line formatting for variable declaration
> >
> > Changes in v2:
> > -Updated comments
> > -Removed extra parentheses
> > -Changed eth_uclass_priv local var names to be uc_priv
> > -Update error codes
> > -Cause an invalid name to fail binding
> > -Rebase on top of dm/master
> > -Stop maintaining our own index and use DM seq now that it works for
our needs
> > -Move the hwaddr to platdata so that its memory is allocated at bind
when we need it
> > -Prevent device from being probed before used by a command (i.e. before
eth_init()).
> >
> >  common/cmd_bdinfo.c    |   2 +
> >  drivers/net/Kconfig    |   5 +
> >  include/dm/uclass-id.h |   1 +
> >  include/net.h          |  52 ++++++++
> >  net/eth.c              | 345
++++++++++++++++++++++++++++++++++++++++++++++++-
> >  5 files changed, 399 insertions(+), 6 deletions(-)
> >
> > diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
> > index aa81da2..b4cce25 100644
> > --- a/common/cmd_bdinfo.c
> > +++ b/common/cmd_bdinfo.c
> > @@ -34,6 +34,7 @@ static void print_eth(int idx)
> >         printf("%-12s= %s\n", name, val);
> >  }
> >
> > +#ifndef CONFIG_DM_ETH
> >  __maybe_unused
> >  static void print_eths(void)
> >  {
> > @@ -52,6 +53,7 @@ static void print_eths(void)
> >         printf("current eth = %s\n", eth_get_name());
> >         printf("ip_addr     = %s\n", getenv("ipaddr"));
> >  }
> > +#endif
> >
> >  __maybe_unused
> >  static void print_lnum(const char *name, unsigned long long value)
> > diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> > index e69de29..bdd0f05 100644
> > --- a/drivers/net/Kconfig
> > +++ b/drivers/net/Kconfig
> > @@ -0,0 +1,5 @@
> > +config DM_ETH
> > +       bool "Enable Driver Model for Ethernet drivers"
> > +       depends on DM
> > +       help
> > +         Enable driver model for Ethernet.
>
> Here you could mention that the eth_...() interface is then
> implemented by the Ethernet uclass. Perhaps a few other notes too? See
> for example drivers/spi/Kconfig or drivers/gpio/Kconfig.

OK

> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> > index 91bb90d..ad96682 100644
> > --- a/include/dm/uclass-id.h
> > +++ b/include/dm/uclass-id.h
> > @@ -34,6 +34,7 @@ enum uclass_id {
> >         UCLASS_I2C_GENERIC,     /* Generic I2C device */
> >         UCLASS_I2C_EEPROM,      /* I2C EEPROM device */
> >         UCLASS_MOD_EXP,         /* RSA Mod Exp device */
> > +       UCLASS_ETH,             /* Ethernet device */
> >
> >         UCLASS_COUNT,
> >         UCLASS_INVALID = -1,
> > diff --git a/include/net.h b/include/net.h
> > index 10d38f8..508c572 100644
> > --- a/include/net.h
> > +++ b/include/net.h
> > @@ -78,6 +78,57 @@ enum eth_state_t {
> >         ETH_STATE_ACTIVE
> >  };
> >
> > +#ifdef CONFIG_DM_ETH
> > +/**
> > + * struct eth_pdata - Platform data for Ethernet MAC controllers
> > + *
> > + * @iobase: The base address of the hardware registers
> > + * @enetaddr: The Ethernet MAC address that is loaded from EEPROM or
env
> > + */
> > +struct eth_pdata {
> > +       phys_addr_t iobase;
> > +       unsigned char enetaddr[6];
> > +};
> > +
> > +/**
> > + * struct eth_ops - functions of Ethernet MAC controllers
> > + *
> > + * start: Prepare the hardware to send and receive packets
> > + * send: Send the bytes passed in "packet" as a packet on the wire
> > + * recv: Check if the hardware received a packet. Call the network
stack if so
> > + * stop: Stop the hardware from looking for packets - may be called
even if
> > + *      state == PASSIVE
> > + * mcast: Join or leave a multicast group (for TFTP) - optional
> > + * write_hwaddr: Write a MAC address to the hardware (used to pass it
to Linux
> > + *              on some platforms like ARM). This function expects the
> > + *              eth_pdata::enetaddr field to be populated - optional
> > + * read_rom_hwaddr: Some devices have a backup of the MAC address
stored in a
> > + *                 ROM on the board. This is how the driver should
expose it
> > + *                 to the network stack. This function should fill in
the
> > + *                 eth_pdata::enetaddr field - optional

I consider this one of the primary purposes that board-specific init exists
for Ethernet. I think this will help to eliminate them. I'm interested in
your thoughts about how to generically expose this to a board / SoC /
driver. For now I was thinking that it would be up to the driver to fan out
if needed, meaning that if the driver doesn't know the MAC, it has a
board-hook function call, but if it does, like USB or PCI adapters, it
won't have board hooks. [sorry for the run-on sentence] I feel it's
non-ideal, but can work for now.

> > + */
> > +struct eth_ops {
> > +       int (*start)(struct udevice *dev);
> > +       int (*send)(struct udevice *dev, void *packet, int length);
> > +       int (*recv)(struct udevice *dev);
> > +       void (*stop)(struct udevice *dev);
> > +#ifdef CONFIG_MCAST_TFTP
> > +       int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
> > +#endif
> > +       int (*write_hwaddr)(struct udevice *dev);
> > +       int (*read_rom_hwaddr)(struct udevice *dev);
> > +};
> > +
> > +#define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
> > +
> > +struct udevice *eth_get_dev(void); /* get the current device */
> > +unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
> > +/* Used only when NetConsole is enabled */
> > +int eth_init_state_only(void); /* Set active state */
> > +void eth_halt_state_only(void); /* Set passive state */
> > +#endif
> > +
> > +#ifndef CONFIG_DM_ETH
> >  struct eth_device {
> >         char name[16];
> >         unsigned char enetaddr[6];
> > @@ -144,6 +195,7 @@ int eth_write_hwaddr(struct eth_device *dev, const
char *base_name,
> >                      int eth_number);
> >
> >  int usb_eth_initialize(bd_t *bi);
> > +#endif
> >
> >  int eth_initialize(void);              /* Initialize network subsystem
*/
> >  void eth_try_another(int first_restart);       /* Change the device */
> > diff --git a/net/eth.c b/net/eth.c
> > index 7bbaac4..9c2dfb9 100644
> > --- a/net/eth.c
> > +++ b/net/eth.c
> > @@ -1,12 +1,15 @@
> >  /*
> > - * (C) Copyright 2001-2010
> > + * (C) Copyright 2001-2015
> >   * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
> > + * Joe Hershberger, National Instruments
> >   *
> >   * SPDX-License-Identifier:    GPL-2.0+
> >   */
> >
> >  #include <common.h>
> >  #include <command.h>
> > +#include <dm.h>
> > +#include <dm/device-internal.h>
>
> The dm/ headers should go after the asm/ header below.

What in the asm headers affects the dm headers? Or is it an aesthetics
request?

> >  #include <net.h>
> >  #include <miiphy.h>
> >  #include <phy.h>
> > @@ -74,6 +77,338 @@ static int eth_mac_skip(int index)
> >         return ((skip_state = getenv(enetvar)) != NULL);
> >  }
> >
> > +static void eth_current_changed(void);
> > +
> > +#ifdef CONFIG_DM_ETH
> > +/**
> > + * struct eth_device_priv - private structure for each Ethernet device
> > + *
> > + * @state: The state of the Ethernet MAC driver (defined by enum
eth_state_t)
> > + */
> > +struct eth_device_priv {
> > +       enum eth_state_t state;
> > +};
> > +
> > +/**
> > + * struct eth_uclass_priv - The structure attached to the uclass itself
> > + *
> > + * @current: The Ethernet device that the network functions are using
> > + */
> > +struct eth_uclass_priv {
> > +       struct udevice *current;
> > +};
> > +
> > +static struct eth_uclass_priv *eth_get_uclass_priv(void)
> > +{
> > +       struct uclass *uc;
> > +
> > +       uclass_get(UCLASS_ETH, &uc);
> > +       assert(uc);
> > +       return uc->priv;
> > +}
> > +
> > +static void eth_set_current_to_next(void)
> > +{
> > +       struct eth_uclass_priv *uc_priv;
> > +
> > +       uc_priv = eth_get_uclass_priv();
> > +       if (uc_priv->current)
> > +               uclass_next_device(&uc_priv->current);
> > +       if (!uc_priv->current)
> > +               uclass_first_device(UCLASS_ETH, &uc_priv->current);
> > +}
> > +
> > +struct udevice *eth_get_dev(void)
>
> This function needs a comment. It isn't clear what is it supposed to
> return. Does it only return probed devices (in which case the check in
> eth_halt() etc. for device_active() is redundant? Or can it return
> devices which cannot be probed?

In the current implementation it will return any device (probe-able or
not), as it is the caller that has the logic to decide how to move on or
not.

> I suggest that it only returns probed devices, as it simplifies the code.

I can evaluate that, but it is not currently expected anywhere.

> > +{
> > +       if (!eth_get_uclass_priv()->current)
> > +               uclass_first_device(UCLASS_ETH,
> > +                                   &eth_get_uclass_priv()->current);
>
> This can return an error. You will then eat it and return the device
> anyway, even though uclass_first_device() will not change ->current.

This can return the error from the probe(), but is the probe fails it also
return a NULL pointer, which is what I'm using to determine success. I
can't return the device in the error case because uclass_first_device()
doesn't give it to me.

> > +       return eth_get_uclass_priv()->current;
>
> Also I think it would be better to have a local variable here for
> uc_priv, as in the above functino.

OK

> > +}
> > +
> > +static void eth_set_dev(struct udevice *dev)
> > +{
> > +       device_probe(dev);
>
> This needs an error check, since if it fails you cannot use the
> device. Also in eth_pre_unbind() you call this function with NULL.

The device_probe() function already has that check, so I didn't bother
adding it again here.

> So I think this function should return an error.

I'm not sure what other error it would return. If it's just the NULL
pointer, the caller knows what it passed in. NULL pointer is valid here.
Essentially asking to unset this device as current (as in pre_unbind
handler).

> > +       eth_get_uclass_priv()->current = dev;
> > +}
> > +
> > +unsigned char *eth_get_ethaddr(void)
> > +{
> > +       struct eth_pdata *pdata;
> > +
> > +       if (eth_get_dev()) {
> > +               pdata = eth_get_dev()->platdata;
> > +               return pdata->enetaddr;
> > +       }
> > +
> > +       return NULL;
> > +}
> > +
> > +/* Set active state without calling start on the driver */
> > +int eth_init_state_only(void)
> > +{
> > +       struct udevice *current;
> > +       struct eth_device_priv *priv;
> > +
> > +       current = eth_get_dev();
> > +       if (!current || !device_active(current))
> > +               return -EINVAL;
> > +
> > +       priv = current->uclass_priv;
> > +       priv->state = ETH_STATE_ACTIVE;
> > +
> > +       return 0;
> > +}
> > +
> > +/* Set passive state without calling stop on the driver */
> > +void eth_halt_state_only(void)
> > +{
> > +       struct udevice *current;
> > +       struct eth_device_priv *priv;
> > +
> > +       current = eth_get_dev();
> > +       if (!current || !device_active(current))
> > +               return;
> > +
> > +       priv = current->uclass_priv;
> > +       priv->state = ETH_STATE_PASSIVE;
> > +}
> > +
> > +int eth_get_dev_index(void)
> > +{
> > +       if (eth_get_dev())
> > +               return eth_get_dev()->seq;
> > +       return -1;
> > +}
> > +
> > +int eth_init(void)
> > +{
> > +       struct udevice *current;
> > +       struct udevice *old_current;
> > +
> > +       current = eth_get_dev();
> > +       if (!current) {
> > +               printf("No ethernet found.\n");
> > +               return -ENODEV;
> > +       }
> > +
> > +       old_current = current;
> > +       do {
> > +               debug("Trying %s\n", current->name);
> > +
> > +               if (device_active(current)) {
> > +                       uchar env_enetaddr[6];
> > +                       struct eth_pdata *pdata = current->platdata;
> > +
> > +                       /* Sync environment with network device */
> > +                       if (eth_getenv_enetaddr_by_index("eth",
current->seq,
> > +                                                        env_enetaddr))
> > +                               memcpy(pdata->enetaddr, env_enetaddr,
6);
> > +                       else
> > +                               memset(pdata->enetaddr, 0, 6);
> > +
> > +                       if (eth_get_ops(current)->start(current) >= 0) {
> > +                               struct eth_device_priv *priv =
> > +                                       current->uclass_priv;
> > +
> > +                               priv->state = ETH_STATE_ACTIVE;
> > +                               return 0;
> > +                       }
> > +               }
> > +               debug("FAIL\n");
> > +
> > +               /* This will ensure the new "current" attempted to
probe */
> > +               eth_try_another(0);
> > +               current = eth_get_dev();
> > +       } while (old_current != current);
> > +
> > +       return -ENODEV;
> > +}
> > +
> > +void eth_halt(void)
> > +{
> > +       struct udevice *current;
> > +       struct eth_device_priv *priv;
> > +
> > +       current = eth_get_dev();
> > +       if (!current || !device_active(current))
> > +               return;
>
> As above, probably this device_active() check is redundant?

There is a case where it is not redundant. If the eth_set_dev() is called
with a device that fails to probe, then it will be called the current
device, but not be active. This is needed to be able to skip over a device
that won't probe to get to one that will.

> > +
> > +       eth_get_ops(current)->stop(current);
>
> How about adding error checking in these functions? Then eventually we
> can plumb it through. Driver authors are not going to motivated to
> deal with errors if they know that their caller ignores them.
>
> ret = eth_get_ops...
> if (ret) {
>    /* We cannot return the error at present */
>   debug("%s: stop() returned error %d\n", __func__, ret);
> }

OK

> > +       priv = current->uclass_priv;
> > +       priv->state = ETH_STATE_PASSIVE;
> > +}
> > +
> > +int eth_send(void *packet, int length)
> > +{
> > +       struct udevice *current;
> > +
> > +       current = eth_get_dev();
> > +       if (!current)
> > +               return -ENODEV;
> > +
> > +       if (!device_active(current))
> > +               return -EINVAL;
> > +
> > +       return eth_get_ops(current)->send(current, packet, length);
> > +}
> > +
> > +int eth_rx(void)
> > +{
> > +       struct udevice *current;
> > +
> > +       current = eth_get_dev();
> > +       if (!current)
> > +               return -ENODEV;
> > +
> > +       if (!device_active(current))
> > +               return -EINVAL;
> > +
> > +       return eth_get_ops(current)->recv(current);
> > +}
> > +
> > +static int eth_write_hwaddr(struct udevice *dev)
> > +{
> > +       struct eth_pdata *pdata = dev->platdata;
> > +       int ret = 0;
> > +
> > +       if (!dev || !device_active(dev))
> > +               return -EINVAL;
> > +
> > +       /* seq is valid since the device is active */
> > +       if (eth_get_ops(dev)->write_hwaddr && !eth_mac_skip(dev->seq)) {
> > +               if (!is_valid_ether_addr(pdata->enetaddr)) {
> > +                       printf("\nError: %s address %pM illegal
value\n",
> > +                              dev->name, pdata->enetaddr);
> > +                       return -EINVAL;
> > +               }
> > +
> > +               ret = eth_get_ops(dev)->write_hwaddr(dev);
> > +               if (ret)
> > +                       printf("\nWarning: %s failed to set MAC
address\n",
> > +                              dev->name);
> > +       }
> > +
> > +       return ret;
> > +}
> > +
> > +int eth_initialize(void)
> > +{
> > +       int num_devices = 0;
> > +       struct udevice *dev;
> > +
> > +       bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
> > +       eth_env_init();
> > +
> > +       /*
> > +        * Devices need to write the hwaddr even if not started so that
Linux
> > +        * will have access to the hwaddr that u-boot stored for the
device.
> > +        * This is accomplished by attempting to probe each device and
calling
> > +        * their write_hwaddr() operation.
> > +        */
> > +       uclass_first_device(UCLASS_ETH, &dev);
> > +       if (!dev) {
> > +               printf("No ethernet found.\n");
> > +               bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
> > +       } else {
> > +               bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
> > +               do {
> > +                       if (num_devices)
> > +                               printf(", ");
> > +
> > +                       printf("eth%d: %s", dev->seq, dev->name);
> > +
> > +                       eth_write_hwaddr(dev);
> > +
> > +                       uclass_next_device(&dev);
> > +                       num_devices++;
> > +               } while (dev);
> > +
> > +               putc('\n');
> > +       }
> > +
> > +       return num_devices;
> > +}
> > +
> > +static int eth_post_bind(struct udevice *dev)
> > +{
> > +       if (strchr(dev->name, ' ')) {
> > +               printf("\nError: eth device name \"%s\" has a space!\n",
> > +                      dev->name);
> > +               return -EINVAL;
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static int eth_pre_unbind(struct udevice *dev)
> > +{
> > +       /* Don't hang onto a pointer that is going away */
> > +       if (dev == eth_get_uclass_priv()->current)
> > +               eth_set_dev(NULL);
> > +
> > +       return 0;
> > +}
> > +
> > +static int eth_post_probe(struct udevice *dev)
> > +{
> > +       struct eth_device_priv *priv = dev->uclass_priv;
> > +       struct eth_pdata *pdata = dev->platdata;
> > +       unsigned char env_enetaddr[6];
> > +
> > +       priv->state = ETH_STATE_INIT;
> > +
> > +       /* Check if the device has a MAC address in ROM */
> > +       if (eth_get_ops(dev)->read_rom_hwaddr)
> > +               eth_get_ops(dev)->read_rom_hwaddr(dev);
> > +
> > +       eth_getenv_enetaddr_by_index("eth", dev->seq, env_enetaddr);
> > +       if (!is_zero_ether_addr(env_enetaddr)) {
> > +               if (!is_zero_ether_addr(pdata->enetaddr) &&
> > +                   memcmp(pdata->enetaddr, env_enetaddr, 6)) {
> > +                       printf("\nWarning: %s MAC addresses don't
match:\n",
> > +                              dev->name);
> > +                       printf("Address in SROM is         %pM\n",
> > +                              pdata->enetaddr);
> > +                       printf("Address in environment is  %pM\n",
> > +                              env_enetaddr);
> > +               }
> > +
> > +               /* Override the ROM MAC address */
> > +               memcpy(pdata->enetaddr, env_enetaddr, 6);
> > +       } else if (is_valid_ether_addr(pdata->enetaddr)) {
> > +               eth_setenv_enetaddr_by_index("eth", dev->seq,
pdata->enetaddr);
> > +               printf("\nWarning: %s using MAC address from ROM\n",
> > +                      dev->name);
> > +       } else if (is_zero_ether_addr(pdata->enetaddr)) {
> > +               printf("\nError: %s address not set.\n",
> > +                      dev->name);
> > +               return -EINVAL;
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static int eth_pre_remove(struct udevice *dev)
> > +{
> > +       eth_get_ops(dev)->stop(dev);
> > +
> > +       return 0;
> > +}
> > +
> > +UCLASS_DRIVER(eth) = {
> > +       .name           = "eth",
> > +       .id             = UCLASS_ETH,
> > +       .post_bind      = eth_post_bind,
> > +       .pre_unbind     = eth_pre_unbind,
> > +       .post_probe     = eth_post_probe,
> > +       .pre_remove     = eth_pre_remove,
> > +       .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
> > +       .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
> > +};
> > +#endif
>
> Could we put the uclass in its own eth-uclass.c file at some point?

At some point, yes.

> > +
> > +#ifndef CONFIG_DM_ETH
> >  /*
> >   * CPU and board-specific Ethernet initializations.  Aliased function
> >   * signals caller to move on
> > @@ -425,6 +760,7 @@ int eth_rx(void)
> >
> >         return eth_current->recv(eth_current);
> >  }
> > +#endif /* ifndef CONFIG_DM_ETH */
> >
> >  #ifdef CONFIG_API
> >  static void eth_save_packet(void *packet, int length)
> > @@ -488,7 +824,7 @@ static void eth_current_changed(void)
> >
> >  void eth_try_another(int first_restart)
> >  {
> > -       static struct eth_device *first_failed;
> > +       static void *first_failed;
> >         char *ethrotate;
> >
> >         /*
> > @@ -517,12 +853,9 @@ void eth_set_current(void)
> >  {
> >         static char *act;
> >         static int  env_changed_id;
> > -       struct eth_device *old_current;
> > +       void *old_current;
> >         int     env_id;
> >
> > -       if (!eth_get_dev())     /* XXX no current */
> > -               return;
> > -
> >         env_id = get_env_id();
> >         if ((act == NULL) || (env_changed_id != env_id)) {
> >                 act = getenv("ethact");
> > --
> > 1.7.11.5
> >
>
> Regards,
> Simon
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 10/23] net: Make netretry actually do something
  2015-03-01 18:07         ` Simon Glass
@ 2015-03-01 21:53           ` Joe Hershberger
  2015-03-02  2:24             ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-01 21:53 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Sun, Mar 1, 2015 at 12:07 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > netretry previously would only retry in one specific case (your MAC
> > address is not set) and no other. This is basically useless. In the DM
> > implementation for eth it turns this into a completely useless case
> > since an un-configured MAC address results in not even entering the
> > NetLoop. The behavior is now changed to retry any failed command
> > (rotating through the eth adapters if ethrotate != no).
> >
> > It also defaulted to retry forever. It is now changed to default to not
> > retry
>
> That last bit seems like a big change. Does it mean that if I forget
> to plug in the Ethernet it might not recover?

It seems like it at face value, but this actually is far closer to
maintaining existing behavior.

As described in the first paragraph, only a missing MAC address would be
retried. all other forms of failure (unplugged Ethernet, for instance)
would just error out. This provides a way to retry if that is a behavior
you want. Most times if you ping an address, for instance, you would expect
your script to get a failure code, not for the ping to be attempted on a
different interface (which would become the new default behavior without
this env var default also changing).

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 16/23] dm: eth: Add support for aliases
  2015-03-01 18:07         ` Simon Glass
@ 2015-03-01 22:04           ` Joe Hershberger
  2015-03-02  2:23             ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-01 22:04 UTC (permalink / raw)
  To: u-boot

On Sun, Mar 1, 2015 at 12:07 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > Allow network devices to be referred to as "eth0" instead of
> > "eth at 12345678" when specified in ethact.
> >
> > Add tests to verify this behavior.
> >
> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> >
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> Again a few comments on error handling for follow-up.
>
> > ---
> >
> > Changes in v4:
> > -Use only the seq from DM to find aliases
> >
> > Changes in v3:
> > -Added support for aliases
> >
> > Changes in v2: None
> >
> >  include/configs/sandbox.h |  2 +-
> >  include/net.h             |  1 +
> >  net/eth.c                 | 47
++++++++++++++++++++++++++++++++++++++---------
> >  test/dm/eth.c             | 24 ++++++++++++++++++++++++
> >  test/dm/test.dts          |  4 +++-
> >  5 files changed, 67 insertions(+), 11 deletions(-)
> >
> > diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
> > index 9189f6a..caf9f5a 100644
> > --- a/include/configs/sandbox.h
> > +++ b/include/configs/sandbox.h
> > @@ -174,7 +174,7 @@
> >
> >  #define SANDBOX_ETH_SETTINGS           "ethaddr=00:00:11:22:33:44\0" \
> >                                         "eth1addr=00:00:11:22:33:45\0" \
> > -                                       "eth2addr=00:00:11:22:33:46\0" \
> > +                                       "eth5addr=00:00:11:22:33:46\0" \
> >                                         "ipaddr=1.2.3.4\0"
> >
> >  #define CONFIG_EXTRA_ENV_SETTINGS      SANDBOX_SERIAL_SETTINGS \
> > diff --git a/include/net.h b/include/net.h
> > index 508c572..e9cb4a3 100644
> > --- a/include/net.h
> > +++ b/include/net.h
> > @@ -122,6 +122,7 @@ struct eth_ops {
> >  #define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
> >
> >  struct udevice *eth_get_dev(void); /* get the current device */
> > +struct udevice *eth_get_dev_by_name(const char *devname);
>
> This needs a comment to describe what devname is exactly. I thought it
> was a device name.

OK

> Also it seems to requite a minimum length of 3
> characters?

Good point. This is a bug. I should be checking the size first. It is not
an intended requirement.

> >  unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
> >  /* Used only when NetConsole is enabled */
> >  int eth_init_state_only(void); /* Set active state */
> > diff --git a/net/eth.c b/net/eth.c
> > index 9c2dfb9..8b853e8 100644
> > --- a/net/eth.c
> > +++ b/net/eth.c
> > @@ -132,6 +132,36 @@ static void eth_set_dev(struct udevice *dev)
> >         eth_get_uclass_priv()->current = dev;
> >  }
> >
> > +/*
> > + * Find the udevice that either has the name passed in as devname or
has an
> > + * alias named devname.
> > + */
> > +struct udevice *eth_get_dev_by_name(const char *devname)
> > +{
> > +       int seq;
> > +       char *endp = NULL;
> > +       const char *startp;
> > +       struct udevice *it;
> > +       struct uclass *uc;
> > +
> > +       startp = devname + strlen("eth");
> > +       seq = simple_strtoul(startp, &endp, 10);
> > +
> > +       uclass_get(UCLASS_ETH, &uc);
> > +       uclass_foreach_dev(it, uc) {
> > +               /* We need the seq to be valid, so make sure it's
probed */
> > +               device_probe(it);
>
> Error check. I think this function is should return an error.

This is simply searching. If a device annot be probed, why error out a
search for presumably a different device? I can look into adding a unit
test to validate this behavior.

> > +               /*
> > +                * Check for the name or the sequence number to match
> > +                */
> > +               if (strcmp(it->name, devname) == 0 ||
> > +                   (endp > startp && it->seq == seq))
> > +                       return it;
> > +       }
> > +
> > +       return NULL;
> > +}
> > +
> >  unsigned char *eth_get_ethaddr(void)
> >  {
> >         struct eth_pdata *pdata;
> > @@ -405,6 +435,7 @@ UCLASS_DRIVER(eth) = {
> >         .pre_remove     = eth_pre_remove,
> >         .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
> >         .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
> > +       .flags          = DM_UC_FLAG_SEQ_ALIAS,
> >  };
> >  #endif
> >
> > @@ -437,6 +468,11 @@ static void eth_set_current_to_next(void)
> >         eth_current = eth_current->next;
> >  }
> >
> > +static void eth_set_dev(struct eth_device *dev)
> > +{
> > +       eth_current = dev;
> > +}
> > +
> >  struct eth_device *eth_get_dev_by_name(const char *devname)
> >  {
> >         struct eth_device *dev, *target_dev;
> > @@ -853,7 +889,6 @@ void eth_set_current(void)
> >  {
> >         static char *act;
> >         static int  env_changed_id;
> > -       void *old_current;
> >         int     env_id;
> >
> >         env_id = get_env_id();
> > @@ -861,14 +896,8 @@ void eth_set_current(void)
> >                 act = getenv("ethact");
> >                 env_changed_id = env_id;
> >         }
> > -       if (act != NULL) {
> > -               old_current = eth_get_dev();
> > -               do {
> > -                       if (strcmp(eth_get_name(), act) == 0)
> > -                               return;
> > -                       eth_set_current_to_next();
> > -               } while (old_current != eth_get_dev());
> > -       }
> > +       if (act != NULL)
> > +               eth_set_dev(eth_get_dev_by_name(act));
>
> Again I think the error handling here is dodgy. You may have a device
> which fails to probe but it will not be reported here.

I'll think about how to make errors be reported when you explicitly ask for
a device, but not when you are just scanning through them.

> >
> >         eth_current_changed();
> >  }
> > diff --git a/test/dm/eth.c b/test/dm/eth.c
> > index 04ccf49..5688b71 100644
> > --- a/test/dm/eth.c
> > +++ b/test/dm/eth.c
> > @@ -36,3 +36,27 @@ static int dm_test_eth(struct dm_test_state *dms)
> >         return 0;
> >  }
> >  DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
> > +
> > +static int dm_test_eth_alias(struct dm_test_state *dms)
> > +{
> > +       NetPingIP = string_to_ip("1.1.2.2");
> > +       setenv("ethact", "eth0");
> > +       ut_assertok(NetLoop(PING));
> > +       ut_asserteq_str("eth at 10002000", getenv("ethact"));
> > +
> > +       setenv("ethact", "eth1");
> > +       ut_assertok(NetLoop(PING));
> > +       ut_asserteq_str("eth at 10004000", getenv("ethact"));
> > +
> > +       /* Expected to fail since eth2 is not defined in the device
tree */
> > +       setenv("ethact", "eth2");
> > +       ut_assertok(NetLoop(PING));
> > +       ut_asserteq_str("eth at 10002000", getenv("ethact"));
> > +
> > +       setenv("ethact", "eth5");
> > +       ut_assertok(NetLoop(PING));
> > +       ut_asserteq_str("eth at 10003000", getenv("ethact"));
>
> Looks good to me.
>
> > +
> > +       return 0;
> > +}
> > +DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
> > diff --git a/test/dm/test.dts b/test/dm/test.dts
> > index 2f68cdf..bc2409d 100644
> > --- a/test/dm/test.dts
> > +++ b/test/dm/test.dts
> > @@ -17,6 +17,8 @@
> >                 testfdt3 = "/b-test";
> >                 testfdt5 = "/some-bus/c-test at 5";
> >                 testfdt8 = "/a-test";
> > +               eth0 = "/eth at 10002000";
> > +               eth5 = &eth_5;
> >         };
> >
> >         uart0: serial {
> > @@ -155,7 +157,7 @@
> >                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
> >         };
> >
> > -       eth at 10003000 {
> > +       eth_5: eth at 10003000 {
> >                 compatible = "sandbox,eth";
> >                 reg = <0x10003000 0x1000>;
> >                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
> > --
> > 1.7.11.5
> >
>
> Regards,
> Simon
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 17/23] dm: eth: Add support for ethprime env var
  2015-03-01 18:07         ` Simon Glass
@ 2015-03-01 22:06           ` Joe Hershberger
  0 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-01 22:06 UTC (permalink / raw)
  To: u-boot

On Sun, Mar 1, 2015 at 12:07 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > The ethprime env var is used to indicate the starting device if none is
> > specified in ethact. Also support aliases specified in the ethprime var.
> >
> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> > Reviewed-by: Simon Glass <sjg@chromium.org>
> >
> > ---
> >
> > Changes in v4:
> > -Load from ethprime on eth_initialize()
> >
> > Changes in v3:
> > -Added support for ethprime
> >
> > Changes in v2: None
> >
> >  net/eth.c     | 29 ++++++++++++++++++++++++++++-
> >  test/dm/eth.c | 20 ++++++++++++++++++++
> >  2 files changed, 48 insertions(+), 1 deletion(-)
> >
> > diff --git a/net/eth.c b/net/eth.c
> > index 8b853e8..3b3cd84 100644
> > --- a/net/eth.c
> > +++ b/net/eth.c
> > @@ -341,6 +341,18 @@ int eth_initialize(void)
> >                 printf("No ethernet found.\n");
> >                 bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
> >         } else {
> > +               char *ethprime = getenv("ethprime");
> > +               struct udevice *prime_dev = NULL;
> > +
> > +               if (ethprime)
> > +                       prime_dev = eth_get_dev_by_name(ethprime);
> > +               if (prime_dev) {
> > +                       eth_set_dev(prime_dev);
> > +                       eth_current_changed();
> > +               } else {
> > +                       eth_set_dev(NULL);
> > +               }
> > +
> >                 bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
> >                 do {
> >                         if (num_devices)
> > @@ -348,6 +360,9 @@ int eth_initialize(void)
> >
> >                         printf("eth%d: %s", dev->seq, dev->name);
> >
> > +                       if (ethprime && dev == prime_dev)
> > +                               printf(" [PRIME]");
> > +
> >                         eth_write_hwaddr(dev);
> >
> >                         uclass_next_device(&dev);
> > @@ -896,8 +911,20 @@ void eth_set_current(void)
> >                 act = getenv("ethact");
> >                 env_changed_id = env_id;
> >         }
> > -       if (act != NULL)
> > +
> > +       if (act == NULL) {
> > +               char *ethprime = getenv("ethprime");
> > +               struct udevice *dev = NULL;
> > +
> > +               if (ethprime)
> > +                       dev = eth_get_dev_by_name(ethprime);
>
> This function can return either a net_device or a udevice. So if
> DM_ETH is not enabled, you will get a warning here.

Yes, my apologies.I didn't notice this regression until right after I
posted the series. It is fixed in my branch.

> > +               if (dev)
> > +                       eth_set_dev(dev);
> > +               else
> > +                       eth_set_dev(NULL);
> > +       } else {
> >                 eth_set_dev(eth_get_dev_by_name(act));
> > +       }
> >
> >         eth_current_changed();
> >  }
> > diff --git a/test/dm/eth.c b/test/dm/eth.c
> > index 5688b71..96e3c46 100644
> > --- a/test/dm/eth.c
> > +++ b/test/dm/eth.c
> > @@ -60,3 +60,23 @@ static int dm_test_eth_alias(struct dm_test_state
*dms)
> >         return 0;
> >  }
> >  DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
> > +
> > +static int dm_test_eth_prime(struct dm_test_state *dms)
> > +{
> > +       NetPingIP = string_to_ip("1.1.2.2");
> > +
> > +       /* Expected to be "eth at 10003000" because of ethprime variable */
> > +       setenv("ethact", NULL);
> > +       setenv("ethprime", "eth5");
> > +       ut_assertok(NetLoop(PING));
> > +       ut_asserteq_str("eth at 10003000", getenv("ethact"));
> > +
> > +       /* Expected to be "eth at 10002000" because it is first */
> > +       setenv("ethact", NULL);
> > +       setenv("ethprime", NULL);
> > +       ut_assertok(NetLoop(PING));
> > +       ut_asserteq_str("eth at 10002000", getenv("ethact"));
> > +
> > +       return 0;
> > +}
> > +DM_TEST(dm_test_eth_prime, DM_TESTF_SCAN_FDT);
> > --
> > 1.7.11.5
> >
>
> Regards,
> Simon
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack
  2015-03-01 16:13       ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Simon Glass
@ 2015-03-01 22:12         ` Joe Hershberger
  2015-03-02  2:23           ` Simon Glass
  2015-03-03 22:29         ` Joe Hershberger
  1 sibling, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-01 22:12 UTC (permalink / raw)
  To: u-boot

On Sun, Mar 1, 2015 at 10:13 AM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > Add support for the Ethernet MAC controllers.  Phy support will come
later.
> >
> > I am still leaving this as an RFC because I plan to add real board
support
> > before committing to mainline. When it is acceptable / accepted, I will
push it
> > as a dev branch on the net repo until a real device is supported. If any
> > required changes are discovered in the process of supporting a real
device I
> > will send those as a patch against the dev branch, but then squash
before
> > sending the non-RFC version. I plan to rebase when the merge window
opens
> > anyway.
> >
> > If desired, let me know which of the non-DM related prerequisite
patches are
> > wanted for this release.
> >
> > I've added unit tests to verify functionality.
> >
> > There is an additional driver for sandbox that bridges to the RAW
> > Ethernet API in Linux which lets you test with real traffic. It now
> > supports localhost as well (the 'lo' interface).
>
> I've got some comments queued up the the series so will send those
> soon (never got to it this week so am catching up!). I wanted to try
> it out on a board to see how things look. The short answer is that it
> works really nicely on sunxi. I'll send some patches that I needed,
> hopefully that doesn't duplicate any work you have done.

It's great that works on your board without much effort. Looking at those
patches I wouldn't say it duplicates much effort. It's more like your
changes are a stop-gap to my efforts, which makes me less inclined to wait
for all of the additional phy and mdio driver-model changes to be complete
before integrating the dm-eth support to mainline.

> In terms of getting this into mainline, I'd be happy to use
> u-boot-dm/next if that suits you and Tom. There are series for PCI and
> USB to sort out, and if the last merge window is any indication it's a
> real struggle to get multiple large series applied within the merge
> window when there are dependencies between them.

That makes sense to me. Since it is a next branch, we are still agreeing
that the branch will be rebased on top of the release, correct?

> Some general comments that I will put here for want of a better place:
>
> - it would be good to have the DM code in drivers/net/eth-uclass.c at
some point

I completely agree.  I moved it there probably 3 different times locally in
slightly different ways and backed it out each time.  I think it should be
a follow-on clean-up patch. It makes this initial patch series messier than
I wanted (hence I backed it out). That is the long-term goal.

> - struct eth_pdata is used by the uclass and is common to all drivers,
> but I wonder if we will find that drivers want to add their own
> private platdata? I added phy_interface but that is generic. Let's
> see.

Yeah, I think that's something that can be revisited pretty easily if the
need becomes clear.

> - I think the recv() method should change before long. The
> NetReceive() call should be made from the uclass since it is common to
> all drivers. Then the recv() method can return a packet if it finds
> one, but not submit it for processing

I agree. I never liked how it was laid out and now is a great opportunity
to change it since every driver has to be touched anyway.

> One interesting point for me is that you have taken a slightly more
> ambitious approach with the conversion by not reusing eth_device. That
> seems to have have worked out well and makes me think I could revisit
> SPI flash perhaps and do the same.

I agree that it's nicer to get rid of the extra wrapping structure.
Naturally the refactor could happen any time, but it seemed simple enough
to just do now.

> >
> > Changes in v4:
> > -New to v4
> > -Fix compile regression in !DM_ETH case
> > -New to v4
> > -New to v4
> > -New to v4
> > -New to v4
> > -New to v4
>
> If you put this in a patch, patman will remove duplicates in the cover
letter.
>
> Series-process-log: uniq
>
> You can also sort with:
>
> Series-process-log: sort, uniq

Thanks for the tip. Any reason these are not enabled by default?

> > -Redo the seq / probe implementation
> > --Don't prevent eth_initialize on driver model
> > --Use eth_initialize to probe all devices and write_hwaddr
> > --Look up MAC address in post-probe
> > --Include ethprime handling in eth_initialize
> > --If current == NULL, always check if there is a device available in
eth_get_dev
> > --Move env init call from uclass init to eth_initialize
> > --Print the alias in eth_initialize
> > -Stop handling selecting a new "current" in pre-unbind as it will now
work itself out by clearing the pointer
> > -Change -1 returns to error constants
> > -Remove bd_t *bis from dm eth_ops init function
> > -Add documentation to the structures
> > -Add a helper function for eth_uclass_priv
> > -Change puts to printf
> > -Add eth_get_ops helper
> > -Rename init() to start() in ops
> > -Rename halt() to stop() in ops
> > -Remove checks for driver==NULL
> > -Remove priv pointer in per-device priv struct (drivers already get
their own directly from DM)
> > -Cleaned up sandbox EXTRA_ENV define
> > -Moved config to Kconfig
> > -Removed checks on priv != NULL and added protection in uclass instead
> > -Use only the seq from DM to find aliases
> > -Load from ethprime on eth_initialize()
> > -Added testing for ethrotate
> > -Add ability to disable ping reply in sandbox eth driver
> > -Updated expected behavior based on changes to the NetLoop
> > -Added comments to README.sandbox
> > -Use accessors for platdata and priv
> > -Add comments to priv struct definition
> > -Move os file to arch
> > -Cleanup var definition order
> > -Moved config to Kconfig
> > -Clean up the interface to sandbox's eth-raw-os by passing priv to
raw-os
> > -Fixed the MAC address limitation (now all traffic uses MAC address
from env)
> > -New to v4
> > -Added support for the 'lo' network interface
> >
> > Changes in v3:
> > -Reorder dm test makefile
> > -Move the get_dev_by_* protos to also be !DM_ETH like the impl
> > -Correct the pre_unbind logic
> > -Correct failure chaining from bind to probe to init
> > --Fail init if not activated
> > --Fail probe if ethaddr not set
> > -Update ethaddr from env unconditionally on init
> > -Use set current to select the current device regardless of the
previous selection
> > -Allow current eth dev to be NULL
> > -Fixed blank line formatting for variable declaration
> > -Added 2 more ethaddr to sandbox
> > -Print which device in the debug write hwaddr
> > -Prevent a crash if memory is not allocated
> > -Added dm eth testing
> > -Added support for aliases
> > -Added support for ethprime
> > -Added testing for netretry
> > -Made the os raw packet support for sandbox eth build and work.
> >
> > Changes in v2:
> > -Updated comments
> > -Removed extra parentheses
> > -Changed eth_uclass_priv local var names to be uc_priv
> > -Update error codes
> > -Cause an invalid name to fail binding
> > -Rebase on top of dm/master
> > -Stop maintaining our own index and use DM seq now that it works for
our needs
> > -Move the hwaddr to platdata so that its memory is allocated at bind
when we need it
> > -Prevent device from being probed before used by a command (i.e. before
eth_init()).
> > -Change printfs to debug in sandbox driver
> > -Remove unused priv struct for sandbox driver
> > -Change printfs to debug in sandbox driver
> > -Move static data to priv
> > -Move fake hwaddr to the device tree
> > -Added the raw packet proof-of-concept patch.
> >
> > Joe Hershberger (23):
> >   test: dm: Reorder the objects to build
> >   common: Make sure arch-specific map_sysmem() is defined
> >   net: Provide a function to get the current MAC address
> >   net: Rename helper function to be more clear
> >   net: Remove unneeded "extern" in net.h
> >   net: Refactor in preparation for driver model
> >   net: Change return codes from net/eth.c to use errorno constants
> >   net: Use int instead of u8 for boolean flag
> >   net: Remove the bd* parameter from net stack functions
> >   net: Make netretry actually do something
> >   net: Access mapped physmem in net functions
> >   dm: eth: Add basic driver model support to Ethernet stack
> >   sandbox: eth: Add network support to sandbox
> >   sandbox: eth: Add ARP and PING response to sandbox driver
> >   test: dm: eth: Add tests for the eth dm implementation
> >   dm: eth: Add support for aliases
> >   dm: eth: Add support for ethprime env var
> >   test: dm: eth: Add testing for ethrotate env var
> >   sandbox: eth: Add ability to disable ping reply in sandbox eth driver
> >   test: dm: net: Add a test of the netretry behavior
> >   sandbox: eth: Add a bridge to a real network for sandbox
> >   sandbox: Enable DHCP and IP defrag
> >   sandbox: eth: Add support for using the 'lo' interface
> >
> >  arch/mips/mach-au1x00/au1x00_eth.c    |   2 +-
> >  arch/powerpc/cpu/mpc8260/ether_fcc.c  |   2 +-
> >  arch/powerpc/cpu/mpc85xx/ether_fcc.c  |   2 +-
> >  arch/powerpc/cpu/mpc8xx/scc.c         |   2 +-
> >  arch/sandbox/Kconfig                  |  12 +
> >  arch/sandbox/cpu/Makefile             |  10 +
> >  arch/sandbox/cpu/eth-raw-os.c         | 198 +++++++++++++
> >  arch/sandbox/dts/sandbox.dts          |  21 ++
> >  arch/sandbox/include/asm/eth-raw-os.h |  40 +++
> >  board/sandbox/README.sandbox          |  17 +-
> >  common/board_r.c                      |   2 +-
> >  common/cmd_bdinfo.c                   |   2 +
> >  drivers/net/Kconfig                   |  28 ++
> >  drivers/net/Makefile                  |   2 +
> >  drivers/net/netconsole.c              |   4 +-
> >  drivers/net/sandbox-raw.c             | 163 +++++++++++
> >  drivers/net/sandbox.c                 | 200 +++++++++++++
> >  include/common.h                      |   4 +-
> >  include/configs/sandbox.h             |  25 +-
> >  include/dm/uclass-id.h                |   1 +
> >  include/net.h                         | 187 ++++++++----
> >  net/eth.c                             | 521
+++++++++++++++++++++++++++++-----
> >  net/net.c                             |  17 +-
> >  net/nfs.c                             |   2 +-
> >  net/tftp.c                            |   2 +-
> >  test/dm/Makefile                      |   5 +-
> >  test/dm/eth.c                         | 129 +++++++++
> >  test/dm/test.dts                      |  20 ++
> >  28 files changed, 1466 insertions(+), 154 deletions(-)
> >  create mode 100644 arch/sandbox/cpu/eth-raw-os.c
> >  create mode 100644 arch/sandbox/include/asm/eth-raw-os.h
> >  create mode 100644 drivers/net/sandbox-raw.c
> >  create mode 100644 drivers/net/sandbox.c
> >  create mode 100644 test/dm/eth.c
> >
> > --
> > 1.7.11.5
> >
>
> Regards,
> Simon
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack
  2015-03-01 22:12         ` Joe Hershberger
@ 2015-03-02  2:23           ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-02  2:23 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 1 March 2015 at 15:12, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> On Sun, Mar 1, 2015 at 10:13 AM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com>
>> wrote:
>> > Add support for the Ethernet MAC controllers.  Phy support will come
>> > later.
>> >
>> > I am still leaving this as an RFC because I plan to add real board
>> > support
>> > before committing to mainline. When it is acceptable / accepted, I will
>> > push it
>> > as a dev branch on the net repo until a real device is supported. If any
>> > required changes are discovered in the process of supporting a real
>> > device I
>> > will send those as a patch against the dev branch, but then squash
>> > before
>> > sending the non-RFC version. I plan to rebase when the merge window
>> > opens
>> > anyway.
>> >
>> > If desired, let me know which of the non-DM related prerequisite patches
>> > are
>> > wanted for this release.
>> >
>> > I've added unit tests to verify functionality.
>> >
>> > There is an additional driver for sandbox that bridges to the RAW
>> > Ethernet API in Linux which lets you test with real traffic. It now
>> > supports localhost as well (the 'lo' interface).
>>
>> I've got some comments queued up the the series so will send those
>> soon (never got to it this week so am catching up!). I wanted to try
>> it out on a board to see how things look. The short answer is that it
>> works really nicely on sunxi. I'll send some patches that I needed,
>> hopefully that doesn't duplicate any work you have done.
>
> It's great that works on your board without much effort. Looking at those
> patches I wouldn't say it duplicates much effort. It's more like your
> changes are a stop-gap to my efforts, which makes me less inclined to wait
> for all of the additional phy and mdio driver-model changes to be complete
> before integrating the dm-eth support to mainline.
>
>> In terms of getting this into mainline, I'd be happy to use
>> u-boot-dm/next if that suits you and Tom. There are series for PCI and
>> USB to sort out, and if the last merge window is any indication it's a
>> real struggle to get multiple large series applied within the merge
>> window when there are dependencies between them.
>
> That makes sense to me. Since it is a next branch, we are still agreeing
> that the branch will be rebased on top of the release, correct?

Yes, once it is in u-boot-dm/next I'll keep it rebased. But since we
are at RC2 I don't expect much effort there.

I want to do this because I originally planned to get PCI into the
current release, but found there were just too many patches to respin
and apply during the merge window, and I didn't get to it. This will
make it easier.

>
>> Some general comments that I will put here for want of a better place:
>>
>> - it would be good to have the DM code in drivers/net/eth-uclass.c at some
>> point
>
> I completely agree.  I moved it there probably 3 different times locally in
> slightly different ways and backed it out each time.  I think it should be a
> follow-on clean-up patch. It makes this initial patch series messier than I
> wanted (hence I backed it out). That is the long-term goal.
>
>> - struct eth_pdata is used by the uclass and is common to all drivers,
>> but I wonder if we will find that drivers want to add their own
>> private platdata? I added phy_interface but that is generic. Let's
>> see.
>
> Yeah, I think that's something that can be revisited pretty easily if the
> need becomes clear.
>
>> - I think the recv() method should change before long. The
>> NetReceive() call should be made from the uclass since it is common to
>> all drivers. Then the recv() method can return a packet if it finds
>> one, but not submit it for processing
>
> I agree. I never liked how it was laid out and now is a great opportunity to
> change it since every driver has to be touched anyway.
>
>> One interesting point for me is that you have taken a slightly more
>> ambitious approach with the conversion by not reusing eth_device. That
>> seems to have have worked out well and makes me think I could revisit
>> SPI flash perhaps and do the same.
>
> I agree that it's nicer to get rid of the extra wrapping structure.
> Naturally the refactor could happen any time, but it seemed simple enough to
> just do now.

All sounds good.

>
>> >
>> > Changes in v4:
>> > -New to v4
>> > -Fix compile regression in !DM_ETH case
>> > -New to v4
>> > -New to v4
>> > -New to v4
>> > -New to v4
>> > -New to v4
>>
>> If you put this in a patch, patman will remove duplicates in the cover
>> letter.
>>
>> Series-process-log: uniq
>>
>> You can also sort with:
>>
>> Series-process-log: sort, uniq
>
> Thanks for the tip. Any reason these are not enabled by default?

From memory I think some people didn't want their change logs to be
reordered (perhaps because they use more than one line per entry,
which I never do).

I suppose we could change it and see if anyone sqeals!

[snip]

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 16/23] dm: eth: Add support for aliases
  2015-03-01 22:04           ` Joe Hershberger
@ 2015-03-02  2:23             ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-02  2:23 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 1 March 2015 at 15:04, Joe Hershberger <joe.hershberger@gmail.com> wrote:
>
>
> On Sun, Mar 1, 2015 at 12:07 PM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com>
>> wrote:
>> > Allow network devices to be referred to as "eth0" instead of
>> > "eth at 12345678" when specified in ethact.
>> >
>> > Add tests to verify this behavior.
>> >
>> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>> >
>>
>> Reviewed-by: Simon Glass <sjg@chromium.org>
>>
>> Again a few comments on error handling for follow-up.
>>
>> > ---
>> >
>> > Changes in v4:
>> > -Use only the seq from DM to find aliases
>> >
>> > Changes in v3:
>> > -Added support for aliases
>> >
>> > Changes in v2: None
>> >
>> >  include/configs/sandbox.h |  2 +-
>> >  include/net.h             |  1 +
>> >  net/eth.c                 | 47
>> > ++++++++++++++++++++++++++++++++++++++---------
>> >  test/dm/eth.c             | 24 ++++++++++++++++++++++++
>> >  test/dm/test.dts          |  4 +++-
>> >  5 files changed, 67 insertions(+), 11 deletions(-)
>> >
>> > diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
>> > index 9189f6a..caf9f5a 100644
>> > --- a/include/configs/sandbox.h
>> > +++ b/include/configs/sandbox.h
>> > @@ -174,7 +174,7 @@
>> >
>> >  #define SANDBOX_ETH_SETTINGS           "ethaddr=00:00:11:22:33:44\0" \
>> >                                         "eth1addr=00:00:11:22:33:45\0" \
>> > -                                       "eth2addr=00:00:11:22:33:46\0" \
>> > +                                       "eth5addr=00:00:11:22:33:46\0" \
>> >                                         "ipaddr=1.2.3.4\0"
>> >
>> >  #define CONFIG_EXTRA_ENV_SETTINGS      SANDBOX_SERIAL_SETTINGS \
>> > diff --git a/include/net.h b/include/net.h
>> > index 508c572..e9cb4a3 100644
>> > --- a/include/net.h
>> > +++ b/include/net.h
>> > @@ -122,6 +122,7 @@ struct eth_ops {
>> >  #define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
>> >
>> >  struct udevice *eth_get_dev(void); /* get the current device */
>> > +struct udevice *eth_get_dev_by_name(const char *devname);
>>
>> This needs a comment to describe what devname is exactly. I thought it
>> was a device name.
>
> OK
>
>> Also it seems to requite a minimum length of 3
>> characters?
>
> Good point. This is a bug. I should be checking the size first. It is not an
> intended requirement.
>
>> >  unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
>> >  /* Used only when NetConsole is enabled */
>> >  int eth_init_state_only(void); /* Set active state */
>> > diff --git a/net/eth.c b/net/eth.c
>> > index 9c2dfb9..8b853e8 100644
>> > --- a/net/eth.c
>> > +++ b/net/eth.c
>> > @@ -132,6 +132,36 @@ static void eth_set_dev(struct udevice *dev)
>> >         eth_get_uclass_priv()->current = dev;
>> >  }
>> >
>> > +/*
>> > + * Find the udevice that either has the name passed in as devname or
>> > has an
>> > + * alias named devname.
>> > + */
>> > +struct udevice *eth_get_dev_by_name(const char *devname)
>> > +{
>> > +       int seq;
>> > +       char *endp = NULL;
>> > +       const char *startp;
>> > +       struct udevice *it;
>> > +       struct uclass *uc;
>> > +
>> > +       startp = devname + strlen("eth");
>> > +       seq = simple_strtoul(startp, &endp, 10);
>> > +
>> > +       uclass_get(UCLASS_ETH, &uc);
>> > +       uclass_foreach_dev(it, uc) {
>> > +               /* We need the seq to be valid, so make sure it's probed
>> > */
>> > +               device_probe(it);
>>
>> Error check. I think this function is should return an error.
>
> This is simply searching. If a device annot be probed, why error out a
> search for presumably a different device? I can look into adding a unit test
> to validate this behavior.

Well normal error behaviour is to report the error to the upper layers
which may or may not stop.

But a failure to probe a device which should be there seems bad.

Anyway if you are wanting to not check these errors you should at
least add big comments in those places as to why. I'd hate for people
not to understand the rationale and just assume that errors don't
matter (because they don't understand the special cases here).

>
>> > +               /*
>> > +                * Check for the name or the sequence number to match
>> > +                */
>> > +               if (strcmp(it->name, devname) == 0 ||
>> > +                   (endp > startp && it->seq == seq))
>> > +                       return it;
>> > +       }
>> > +
>> > +       return NULL;
>> > +}
>> > +
>> >  unsigned char *eth_get_ethaddr(void)
>> >  {
>> >         struct eth_pdata *pdata;
>> > @@ -405,6 +435,7 @@ UCLASS_DRIVER(eth) = {
>> >         .pre_remove     = eth_pre_remove,
>> >         .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
>> >         .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
>> > +       .flags          = DM_UC_FLAG_SEQ_ALIAS,
>> >  };
>> >  #endif
>> >
>> > @@ -437,6 +468,11 @@ static void eth_set_current_to_next(void)
>> >         eth_current = eth_current->next;
>> >  }
>> >
>> > +static void eth_set_dev(struct eth_device *dev)
>> > +{
>> > +       eth_current = dev;
>> > +}
>> > +
>> >  struct eth_device *eth_get_dev_by_name(const char *devname)
>> >  {
>> >         struct eth_device *dev, *target_dev;
>> > @@ -853,7 +889,6 @@ void eth_set_current(void)
>> >  {
>> >         static char *act;
>> >         static int  env_changed_id;
>> > -       void *old_current;
>> >         int     env_id;
>> >
>> >         env_id = get_env_id();
>> > @@ -861,14 +896,8 @@ void eth_set_current(void)
>> >                 act = getenv("ethact");
>> >                 env_changed_id = env_id;
>> >         }
>> > -       if (act != NULL) {
>> > -               old_current = eth_get_dev();
>> > -               do {
>> > -                       if (strcmp(eth_get_name(), act) == 0)
>> > -                               return;
>> > -                       eth_set_current_to_next();
>> > -               } while (old_current != eth_get_dev());
>> > -       }
>> > +       if (act != NULL)
>> > +               eth_set_dev(eth_get_dev_by_name(act));
>>
>> Again I think the error handling here is dodgy. You may have a device
>> which fails to probe but it will not be reported here.
>
> I'll think about how to make errors be reported when you explicitly ask for
> a device, but not when you are just scanning through them.

It's an interesting question, and fair enough - this is a design
decision. But please comment it.

[snip]

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 02/23] common: Make sure arch-specific map_sysmem() is defined
  2015-03-01 21:16           ` Joe Hershberger
@ 2015-03-02  2:24             ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-02  2:24 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 1 March 2015 at 14:16, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> Hi Simon,
>
>
> On Sun, Mar 1, 2015 at 12:07 PM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com>
>> wrote:
>> > In the case where the arch defines a custom map_sysmem(), make sure that
>> > including just common.h is sufficient to have these functions as they
>> > are when the arch does not override it.
>> >
>> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>> >
>> > ---
>> >
>> > Changes in v4:
>> > -New to v4
>> >
>> > Changes in v3: None
>> > Changes in v2: None
>> >
>> >  include/common.h | 4 +++-
>> >  1 file changed, 3 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/include/common.h b/include/common.h
>> > index 77c55c6..6510efc 100644
>> > --- a/include/common.h
>> > +++ b/include/common.h
>> > @@ -846,7 +846,9 @@ int cpu_release(int nr, int argc, char * const
>> > argv[]);
>> >  #endif
>> >
>> >  /* Define a null map_sysmem() if the architecture doesn't use it */
>> > -# ifndef CONFIG_ARCH_MAP_SYSMEM
>> > +# ifdef CONFIG_ARCH_MAP_SYSMEM
>> > +#include <asm/io.h>
>> > +# else
>> >  static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
>> >  {
>> >         return (void *)(uintptr_t)paddr;
>>
>> Do we need this patch? Is it just for sandbox? It would be nice to
>> remove things from common.h rather than adding them!
>
> If you have a recommendation for where these static inline functions should
> move, then I'm happy to move it all to a new place. My assertion is that
> whatever it is that you include to get these static inlines should also be
> what you include when CONFIG_ARCH_MAP_SYSMEM is defined. You should not need
> to include the arch-specific header separately each place that one of these
> mapping functions is used.

Fair enough. I suppose there are two options - requiring all files to
include asm/io.h, and putting them in common.h (or some other file).

Overall I think I'd prefer that they go in a separate file (perhaps
mapmem.h) and include that file everywhere. What do you think?

>
>> Anyway if you want to go ahead I'm OK with it.
>>
>> Reviewed-by: Simon Glass <sjg@chromium.org>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 10/23] net: Make netretry actually do something
  2015-03-01 21:53           ` Joe Hershberger
@ 2015-03-02  2:24             ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-02  2:24 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 1 March 2015 at 14:53, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> Hi Simon,
>
>
> On Sun, Mar 1, 2015 at 12:07 PM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com>
>> wrote:
>> > netretry previously would only retry in one specific case (your MAC
>> > address is not set) and no other. This is basically useless. In the DM
>> > implementation for eth it turns this into a completely useless case
>> > since an un-configured MAC address results in not even entering the
>> > NetLoop. The behavior is now changed to retry any failed command
>> > (rotating through the eth adapters if ethrotate != no).
>> >
>> > It also defaulted to retry forever. It is now changed to default to not
>> > retry
>>
>> That last bit seems like a big change. Does it mean that if I forget
>> to plug in the Ethernet it might not recover?
>
> It seems like it at face value, but this actually is far closer to
> maintaining existing behavior.
>
> As described in the first paragraph, only a missing MAC address would be
> retried. all other forms of failure (unplugged Ethernet, for instance) would
> just error out. This provides a way to retry if that is a behavior you want.
> Most times if you ping an address, for instance, you would expect your
> script to get a failure code, not for the ping to be attempted on a
> different interface (which would become the new default behavior without
> this env var default also changing).

Thanks for explaining this.

Reviewed-by: Simon Glass <sjg@chromium.org>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 12/23] dm: eth: Add basic driver model support to Ethernet stack
  2015-03-01 21:45           ` Joe Hershberger
@ 2015-03-02  2:26             ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-02  2:26 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 1 March 2015 at 14:45, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> Hi Simon,
>
> On Sun, Mar 1, 2015 at 12:07 PM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com>
>> wrote:
>> > First just add support for MAC drivers.
>> >
>> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>>
>> Reviewed-by: Simon Glass <sjg@chromium.org>
>>
>> This looks right to me. I still have some comments on error handling,
>> but I'm OK with you addressing these in a follow-on patch if you like.
>
> Thanks for going back and forth on this to make it right.

I'm pleased to see it coming together.

>
>> > ---
>> >
>> > Changes in v4:
>> > -Redo the seq / probe implementation
>> > --Don't prevent eth_initialize on driver model
>> > --Use eth_initialize to probe all devices and write_hwaddr
>> > --Look up MAC address in post-probe
>> > --Include ethprime handling in eth_initialize
>> > --If current == NULL, always check if there is a device available in
>> > eth_get_dev
>> > --Move env init call from uclass init to eth_initialize
>> > --Print the alias in eth_initialize
>> > -Stop handling selecting a new "current" in pre-unbind as it will now
>> > work itself out by clearing the pointer
>> > -Change -1 returns to error constants
>> > -Remove bd_t *bis from dm eth_ops init function
>> > -Add documentation to the structures
>> > -Add a helper function for eth_uclass_priv
>> > -Change puts to printf
>> > -Add eth_get_ops helper
>> > -Rename init() to start() in ops
>> > -Rename halt() to stop() in ops
>> > -Remove checks for driver==NULL
>> > -Remove priv pointer in per-device priv struct (drivers already get
>> > their own directly from DM)
>> >
>> > Changes in v3:
>> > -Correct the pre_unbind logic
>> > -Correct failure chaining from bind to probe to init
>> > --Fail init if not activated
>> > --Fail probe if ethaddr not set
>> > -Update ethaddr from env unconditionally on init
>> > -Use set current to select the current device regardless of the previous
>> > selection
>> > -Allow current eth dev to be NULL
>> > -Fixed blank line formatting for variable declaration
>> >
>> > Changes in v2:
>> > -Updated comments
>> > -Removed extra parentheses
>> > -Changed eth_uclass_priv local var names to be uc_priv
>> > -Update error codes
>> > -Cause an invalid name to fail binding
>> > -Rebase on top of dm/master
>> > -Stop maintaining our own index and use DM seq now that it works for our
>> > needs
>> > -Move the hwaddr to platdata so that its memory is allocated at bind
>> > when we need it
>> > -Prevent device from being probed before used by a command (i.e. before
>> > eth_init()).
>> >
>> >  common/cmd_bdinfo.c    |   2 +
>> >  drivers/net/Kconfig    |   5 +
>> >  include/dm/uclass-id.h |   1 +
>> >  include/net.h          |  52 ++++++++
>> >  net/eth.c              | 345
>> > ++++++++++++++++++++++++++++++++++++++++++++++++-
>> >  5 files changed, 399 insertions(+), 6 deletions(-)
>> >
>> > diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
>> > index aa81da2..b4cce25 100644
>> > --- a/common/cmd_bdinfo.c
>> > +++ b/common/cmd_bdinfo.c
>> > @@ -34,6 +34,7 @@ static void print_eth(int idx)
>> >         printf("%-12s= %s\n", name, val);
>> >  }
>> >
>> > +#ifndef CONFIG_DM_ETH
>> >  __maybe_unused
>> >  static void print_eths(void)
>> >  {
>> > @@ -52,6 +53,7 @@ static void print_eths(void)
>> >         printf("current eth = %s\n", eth_get_name());
>> >         printf("ip_addr     = %s\n", getenv("ipaddr"));
>> >  }
>> > +#endif
>> >
>> >  __maybe_unused
>> >  static void print_lnum(const char *name, unsigned long long value)
>> > diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
>> > index e69de29..bdd0f05 100644
>> > --- a/drivers/net/Kconfig
>> > +++ b/drivers/net/Kconfig
>> > @@ -0,0 +1,5 @@
>> > +config DM_ETH
>> > +       bool "Enable Driver Model for Ethernet drivers"
>> > +       depends on DM
>> > +       help
>> > +         Enable driver model for Ethernet.
>>
>> Here you could mention that the eth_...() interface is then
>> implemented by the Ethernet uclass. Perhaps a few other notes too? See
>> for example drivers/spi/Kconfig or drivers/gpio/Kconfig.
>
> OK
>
>> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
>> > index 91bb90d..ad96682 100644
>> > --- a/include/dm/uclass-id.h
>> > +++ b/include/dm/uclass-id.h
>> > @@ -34,6 +34,7 @@ enum uclass_id {
>> >         UCLASS_I2C_GENERIC,     /* Generic I2C device */
>> >         UCLASS_I2C_EEPROM,      /* I2C EEPROM device */
>> >         UCLASS_MOD_EXP,         /* RSA Mod Exp device */
>> > +       UCLASS_ETH,             /* Ethernet device */
>> >
>> >         UCLASS_COUNT,
>> >         UCLASS_INVALID = -1,
>> > diff --git a/include/net.h b/include/net.h
>> > index 10d38f8..508c572 100644
>> > --- a/include/net.h
>> > +++ b/include/net.h
>> > @@ -78,6 +78,57 @@ enum eth_state_t {
>> >         ETH_STATE_ACTIVE
>> >  };
>> >
>> > +#ifdef CONFIG_DM_ETH
>> > +/**
>> > + * struct eth_pdata - Platform data for Ethernet MAC controllers
>> > + *
>> > + * @iobase: The base address of the hardware registers
>> > + * @enetaddr: The Ethernet MAC address that is loaded from EEPROM or
>> > env
>> > + */
>> > +struct eth_pdata {
>> > +       phys_addr_t iobase;
>> > +       unsigned char enetaddr[6];
>> > +};
>> > +
>> > +/**
>> > + * struct eth_ops - functions of Ethernet MAC controllers
>> > + *
>> > + * start: Prepare the hardware to send and receive packets
>> > + * send: Send the bytes passed in "packet" as a packet on the wire
>> > + * recv: Check if the hardware received a packet. Call the network
>> > stack if so
>> > + * stop: Stop the hardware from looking for packets - may be called
>> > even if
>> > + *      state == PASSIVE
>> > + * mcast: Join or leave a multicast group (for TFTP) - optional
>> > + * write_hwaddr: Write a MAC address to the hardware (used to pass it
>> > to Linux
>> > + *              on some platforms like ARM). This function expects the
>> > + *              eth_pdata::enetaddr field to be populated - optional
>> > + * read_rom_hwaddr: Some devices have a backup of the MAC address
>> > stored in a
>> > + *                 ROM on the board. This is how the driver should
>> > expose it
>> > + *                 to the network stack. This function should fill in
>> > the
>> > + *                 eth_pdata::enetaddr field - optional
>
> I consider this one of the primary purposes that board-specific init exists
> for Ethernet. I think this will help to eliminate them. I'm interested in
> your thoughts about how to generically expose this to a board / SoC /
> driver. For now I was thinking that it would be up to the driver to fan out
> if needed, meaning that if the driver doesn't know the MAC, it has a
> board-hook function call, but if it does, like USB or PCI adapters, it won't
> have board hooks. [sorry for the run-on sentence] I feel it's non-ideal, but
> can work for now.

As a general principle I think we should avoid all board hooks. The
information (if needed) should be in the device tree / platform data
provided by the board, or perhaps set up by the board through some
sort of call. Of course the MAC address is in some ways a special
case. I don't have a good answer for this, but perhaps it will become
apparent once we have more Ethernet driver support?

>
>> > + */
>> > +struct eth_ops {
>> > +       int (*start)(struct udevice *dev);
>> > +       int (*send)(struct udevice *dev, void *packet, int length);
>> > +       int (*recv)(struct udevice *dev);
>> > +       void (*stop)(struct udevice *dev);
>> > +#ifdef CONFIG_MCAST_TFTP
>> > +       int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
>> > +#endif
>> > +       int (*write_hwaddr)(struct udevice *dev);
>> > +       int (*read_rom_hwaddr)(struct udevice *dev);
>> > +};
>> > +
>> > +#define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
>> > +
>> > +struct udevice *eth_get_dev(void); /* get the current device */
>> > +unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
>> > +/* Used only when NetConsole is enabled */
>> > +int eth_init_state_only(void); /* Set active state */
>> > +void eth_halt_state_only(void); /* Set passive state */
>> > +#endif
>> > +
>> > +#ifndef CONFIG_DM_ETH
>> >  struct eth_device {
>> >         char name[16];
>> >         unsigned char enetaddr[6];
>> > @@ -144,6 +195,7 @@ int eth_write_hwaddr(struct eth_device *dev, const
>> > char *base_name,
>> >                      int eth_number);
>> >
>> >  int usb_eth_initialize(bd_t *bi);
>> > +#endif
>> >
>> >  int eth_initialize(void);              /* Initialize network subsystem
>> > */
>> >  void eth_try_another(int first_restart);       /* Change the device */
>> > diff --git a/net/eth.c b/net/eth.c
>> > index 7bbaac4..9c2dfb9 100644
>> > --- a/net/eth.c
>> > +++ b/net/eth.c
>> > @@ -1,12 +1,15 @@
>> >  /*
>> > - * (C) Copyright 2001-2010
>> > + * (C) Copyright 2001-2015
>> >   * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
>> > + * Joe Hershberger, National Instruments
>> >   *
>> >   * SPDX-License-Identifier:    GPL-2.0+
>> >   */
>> >
>> >  #include <common.h>
>> >  #include <command.h>
>> > +#include <dm.h>
>> > +#include <dm/device-internal.h>
>>
>> The dm/ headers should go after the asm/ header below.
>
> What in the asm headers affects the dm headers? Or is it an aesthetics
> request?
>
>
>> >  #include <net.h>
>> >  #include <miiphy.h>
>> >  #include <phy.h>
>> > @@ -74,6 +77,338 @@ static int eth_mac_skip(int index)
>> >         return ((skip_state = getenv(enetvar)) != NULL);
>> >  }
>> >
>> > +static void eth_current_changed(void);
>> > +
>> > +#ifdef CONFIG_DM_ETH
>> > +/**
>> > + * struct eth_device_priv - private structure for each Ethernet device
>> > + *
>> > + * @state: The state of the Ethernet MAC driver (defined by enum
>> > eth_state_t)
>> > + */
>> > +struct eth_device_priv {
>> > +       enum eth_state_t state;
>> > +};
>> > +
>> > +/**
>> > + * struct eth_uclass_priv - The structure attached to the uclass itself
>> > + *
>> > + * @current: The Ethernet device that the network functions are using
>> > + */
>> > +struct eth_uclass_priv {
>> > +       struct udevice *current;
>> > +};
>> > +
>> > +static struct eth_uclass_priv *eth_get_uclass_priv(void)
>> > +{
>> > +       struct uclass *uc;
>> > +
>> > +       uclass_get(UCLASS_ETH, &uc);
>> > +       assert(uc);
>> > +       return uc->priv;
>> > +}
>> > +
>> > +static void eth_set_current_to_next(void)
>> > +{
>> > +       struct eth_uclass_priv *uc_priv;
>> > +
>> > +       uc_priv = eth_get_uclass_priv();
>> > +       if (uc_priv->current)
>> > +               uclass_next_device(&uc_priv->current);
>> > +       if (!uc_priv->current)
>> > +               uclass_first_device(UCLASS_ETH, &uc_priv->current);
>> > +}
>> > +
>> > +struct udevice *eth_get_dev(void)
>>
>> This function needs a comment. It isn't clear what is it supposed to
>> return. Does it only return probed devices (in which case the check in
>> eth_halt() etc. for device_active() is redundant? Or can it return
>> devices which cannot be probed?
>
> In the current implementation it will return any device (probe-able or not),
> as it is the caller that has the logic to decide how to move on or not.
>
>> I suggest that it only returns probed devices, as it simplifies the code.
>
> I can evaluate that, but it is not currently expected anywhere.

Well I'll leave this to you.

>
>> > +{
>> > +       if (!eth_get_uclass_priv()->current)
>> > +               uclass_first_device(UCLASS_ETH,
>> > +                                   &eth_get_uclass_priv()->current);
>>
>> This can return an error. You will then eat it and return the device
>> anyway, even though uclass_first_device() will not change ->current.
>
> This can return the error from the probe(), but is the probe fails it also
> return a NULL pointer, which is what I'm using to determine success. I can't
> return the device in the error case because uclass_first_device() doesn't
> give it to me.

Overall (and maybe this is best figured out later) I think the
functions that swallow errors should have special names and be
commented that way. The innocuous name eth_get_dev() hides quite a few
features. Perhaps eth_scan_for_suitable_device() ?

>
>> > +       return eth_get_uclass_priv()->current;
>>
>> Also I think it would be better to have a local variable here for
>> uc_priv, as in the above functino.
>
> OK
>
>> > +}
>> > +
>> > +static void eth_set_dev(struct udevice *dev)
>> > +{
>> > +       device_probe(dev);
>>
>> This needs an error check, since if it fails you cannot use the
>> device. Also in eth_pre_unbind() you call this function with NULL.
>
> The device_probe() function already has that check, so I didn't bother
> adding it again here.
>
>> So I think this function should return an error.
>
> I'm not sure what other error it would return. If it's just the NULL
> pointer, the caller knows what it passed in. NULL pointer is valid here.
> Essentially asking to unset this device as current (as in pre_unbind
> handler).

You are relying on device_probe() returning an error when dev is NULL?
OK, I suppose. Could use a comment.

[snip]

Regards
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 21/23] sandbox: eth: Add a bridge to a real network for sandbox
  2015-03-01 18:07         ` Simon Glass
@ 2015-03-02  7:17           ` Joe Hershberger
  2015-03-02 15:48             ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-02  7:17 UTC (permalink / raw)
  To: u-boot

On Sun, Mar 1, 2015 at 12:07 PM, Simon Glass <sjg@chromium.org> wrote:
>
> On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > Implement a bridge between u-boot's network stack and Linux's raw packet
> > API allowing the sandbox to send and receive packets using the host
> > machine's network interface.
> >
> > This raw Ethernet API requires elevated privileges.  You can either run
> > as root, or you can add the capability needed like so:
> >
> > sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot
> >
> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> A few nits below.
>
> >
> > ---
> >
> > Changes in v4:
> > -Added comments to README.sandbox
> > -Use accessors for platdata and priv
> > -Add comments to priv struct definition
> > -Move os file to arch
> > -Cleanup var definition order
> > -Moved config to Kconfig
> > -Clean up the interface to sandbox's eth-raw-os by passing priv to
raw-os
> > -Fixed the MAC address limitation (now all traffic uses MAC address
from env)
> >
> > Changes in v3:
> > -Made the os raw packet support for sandbox eth build and work.
> >
> > Changes in v2:
> > -Added the raw packet proof-of-concept patch.
> >
> >  arch/sandbox/Kconfig                  |   3 +
> >  arch/sandbox/cpu/Makefile             |  10 ++++
> >  arch/sandbox/cpu/eth-raw-os.c         | 102
+++++++++++++++++++++++++++++++++
> >  arch/sandbox/dts/sandbox.dts          |   6 ++
> >  arch/sandbox/include/asm/eth-raw-os.h |  32 +++++++++++
> >  board/sandbox/README.sandbox          |  13 +++++
> >  drivers/net/Kconfig                   |   5 ++
> >  drivers/net/Makefile                  |   1 +
> >  drivers/net/sandbox-raw.c             | 105
++++++++++++++++++++++++++++++++++
> >  9 files changed, 277 insertions(+)
> >  create mode 100644 arch/sandbox/cpu/eth-raw-os.c
> >  create mode 100644 arch/sandbox/include/asm/eth-raw-os.h
> >  create mode 100644 drivers/net/sandbox-raw.c
> >
> > diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
> > index 186b58d..f84b3fc 100644
> > --- a/arch/sandbox/Kconfig
> > +++ b/arch/sandbox/Kconfig
> > @@ -43,4 +43,7 @@ config NETDEVICES
> >  config DM_ETH
> >         default y
> >
> > +config ETH_SANDBOX_RAW
> > +       default y
> > +
> >  endmenu
> > diff --git a/arch/sandbox/cpu/Makefile b/arch/sandbox/cpu/Makefile
> > index 7d4410c..1b42fee 100644
> > --- a/arch/sandbox/cpu/Makefile
> > +++ b/arch/sandbox/cpu/Makefile
> > @@ -8,6 +8,7 @@
> >  #
> >
> >  obj-y  := cpu.o os.o start.o state.o
> > +obj-$(CONFIG_ETH_SANDBOX_RAW)  += eth-raw-os.o
> >  obj-$(CONFIG_SANDBOX_SDL)      += sdl.o
> >
> >  # os.c is build in the system environment, so needs standard includes
> > @@ -20,3 +21,12 @@ $(obj)/os.o: $(src)/os.c FORCE
> >         $(call if_changed_dep,cc_os.o)
> >  $(obj)/sdl.o: $(src)/sdl.c FORCE
> >         $(call if_changed_dep,cc_os.o)
> > +
> > +# eth-raw-os.c is built in the system env, so needs standard includes
> > +# CFLAGS_REMOVE_eth-raw-os.o cannot be used to drop header include path
> > +quiet_cmd_cc_eth-raw-os.o = CC $(quiet_modtag)  $@
> > +cmd_cc_eth-raw-os.o = $(CC) $(filter-out -nostdinc, \
> > +       $(patsubst -I%,-idirafter%,$(c_flags))) -c -o $@ lt;
> > +
> > +$(obj)/eth-raw-os.o: $(src)/eth-raw-os.c FORCE
> > +       $(call if_changed_dep,cc_eth-raw-os.o)
> > diff --git a/arch/sandbox/cpu/eth-raw-os.c
b/arch/sandbox/cpu/eth-raw-os.c
> > new file mode 100644
> > index 0000000..9218f94
> > --- /dev/null
> > +++ b/arch/sandbox/cpu/eth-raw-os.c
> > @@ -0,0 +1,102 @@
> > +/*
> > + * Copyright (c) 2015 National Instruments
> > + *
> > + * (C) Copyright 2015
> > + * Joe Hershberger <joe.hershberger@ni.com>
> > + *
> > + * SPDX-License-Identifier:    GPL-2.0
> > + */
> > +
> > +#include <asm/eth-raw-os.h>
> > +#include <errno.h>
> > +#include <net/if.h>
> > +#include <netinet/in.h>
> > +#include <stdio.h>
> > +#include <stdlib.h>
> > +#include <string.h>
> > +#include <sys/types.h>
> > +#include <sys/ioctl.h>
> > +#include <sys/socket.h>
> > +#include <unistd.h>
> > +
> > +#include <linux/if_ether.h>
> > +#include <linux/if_packet.h>
> > +
> > +int sandbox_eth_raw_os_init(const char *ifname, unsigned char *ethmac,
> > +                           struct eth_sandbox_raw_priv *priv)
> > +{
> > +       struct sockaddr_ll *device;
> > +       struct packet_mreq mr;
> > +
> > +       /* Prepare device struct */
> > +       priv->device = malloc(sizeof(struct sockaddr_ll));
>
> This calls U-Boot's malloc() and it can return NULL, so you should
> return -ENOMEM in that case.

OK

> > +       device = priv->device;
> > +       memset(device, 0, sizeof(struct sockaddr_ll));
> > +       device->sll_ifindex = if_nametoindex(ifname);
> > +       device->sll_family = AF_PACKET;
> > +       memcpy(device->sll_addr, ethmac, 6);
> > +       device->sll_halen = htons(6);
> > +
> > +       /* Open socket */
> > +       priv->sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
> > +       if (priv->sd < 0) {
> > +               printf("Failed to open socket: %d %s\n", errno,
> > +                      strerror(errno));
> > +               return -errno;
> > +       }
> > +       /* Bind to the specified interface */
> > +       setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
> > +                  strlen(ifname) + 1);
> > +
> > +       /* Enable promiscuous mode to receive responses meant for us */
> > +       mr.mr_ifindex = device->sll_ifindex;
> > +       mr.mr_type = PACKET_MR_PROMISC;
> > +       setsockopt(priv->sd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
> > +                  &mr, sizeof(mr));
> > +       return 0;
> > +}
> > +
> > +int sandbox_eth_raw_os_send(void *packet, int length,
> > +                           const struct eth_sandbox_raw_priv *priv)
> > +{
> > +       int retval;
> > +
> > +       if (!priv->sd || !priv->device)
> > +               return -EINVAL;
> > +
> > +       retval = sendto(priv->sd, packet, length, 0,
> > +                       (struct sockaddr *)priv->device,
> > +                       sizeof(struct sockaddr_ll));
> > +       if (retval < 0)
> > +               printf("Failed to send packet: %d %s\n", errno,
> > +                      strerror(errno));
>
> return -errno here?

OK

> > +       return retval;
> > +}
> > +
> > +int sandbox_eth_raw_os_recv(void *packet, int *length,
> > +                           const struct eth_sandbox_raw_priv *priv)
> > +{
> > +       int retval;
> > +       int saddr_size;
> > +
> > +       if (!priv->sd || !priv->device)
> > +               return -EINVAL;
> > +       saddr_size = sizeof(struct sockaddr);
> > +       retval = recvfrom(priv->sd, packet, 1536, 0,
> > +                         (struct sockaddr *)priv->device,
> > +                         (socklen_t *)&saddr_size);
> > +       *length = 0;
> > +       if (retval > 0) {
> > +               *length = retval;
> > +               return 0;
> > +       }
> > +       return retval;
>
> return -errno here? At present you are returning -1 I think, which is
-EPERM.

OK

> > +}
> > +
> > +void sandbox_eth_raw_os_halt(struct eth_sandbox_raw_priv *priv)
> > +{
> > +       free((struct sockaddr_ll *)priv->device);
>
> Don't need that cast?

Hmm... good point.

> > +       priv->device = NULL;
> > +       close(priv->sd);
> > +       priv->sd = -1;
> > +}
> > diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
> > index 235dcc0..b6762f4 100644
> > --- a/arch/sandbox/dts/sandbox.dts
> > +++ b/arch/sandbox/dts/sandbox.dts
> > @@ -186,4 +186,10 @@
> >                 reg = <0x10002000 0x1000>;
> >                 fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
> >         };
> > +
> > +       eth at 80000000 {
> > +               compatible = "sandbox,eth-raw";
> > +               reg = <0x80000000 0x1000>;
> > +               host-raw-interface = "eth0";
> > +       };
> >  };
> > diff --git a/arch/sandbox/include/asm/eth-raw-os.h
b/arch/sandbox/include/asm/eth-raw-os.h
> > new file mode 100644
> > index 0000000..d92b72c
> > --- /dev/null
> > +++ b/arch/sandbox/include/asm/eth-raw-os.h
> > @@ -0,0 +1,32 @@
> > +/*
> > + * Copyright (c) 2015 National Instruments
> > + *
> > + * (C) Copyright 2015
> > + * Joe Hershberger <joe.hershberger@ni.com>
> > + *
> > + * SPDX-License-Identifier:    GPL-2.0
> > + */
> > +
> > +#ifndef __ETH_RAW_OS_H
> > +#define __ETH_RAW_OS_H
> > +
> > +/**
> > + * struct eth_sandbox_raw_priv - raw socket session
> > + *
> > + * sd: socket descriptor - the open socket during a session
> > + * device: struct sockaddr_ll - the host interface packets move to/from
> > + */
> > +struct eth_sandbox_raw_priv {
> > +       int sd;
> > +       void *device;
> > +};
> > +
> > +int sandbox_eth_raw_os_init(const char *ifname, unsigned char *ethmac,
> > +                           struct eth_sandbox_raw_priv *priv);
> > +int sandbox_eth_raw_os_send(void *packet, int length,
> > +                           const struct eth_sandbox_raw_priv *priv);
> > +int sandbox_eth_raw_os_recv(void *packet, int *length,
> > +                           const struct eth_sandbox_raw_priv *priv);
> > +void sandbox_eth_raw_os_halt(struct eth_sandbox_raw_priv *priv);
> > +
> > +#endif /* __ETH_RAW_OS_H */
> > diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
> > index c1f5f7e..c4c3139 100644
> > --- a/board/sandbox/README.sandbox
> > +++ b/board/sandbox/README.sandbox
> > @@ -190,6 +190,19 @@ Also sandbox uses generic board
(CONFIG_SYS_GENERIC_BOARD) and supports
> >  driver model (CONFIG_DM) and associated commands.
> >
> >
> > +Linux RAW Networking Bridge
> > +---------------------------
> > +
> > +The sandbox_eth_raw driver bridges traffic between the bottom of the
network
> > +stack and the RAW sockets API in Linux. This allows much of the u-boot
network
> > +functionality to be tested in sandbox against real network traffic.
> > +
> > +The RAW sockets Ethernet API requires elevated privileges in Linux.
You can
> > +either run as root, or you can add the capability needed like so:
> > +
> > +sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot
>
> This is so cool.

:D

> Can you give some examples here? For me, ping seems to work, but I
> can't use bootp. Is that what the raw mode is for? How do I enable it?
> I tried setting ethact but am not sure what I am doing.

Sorry it's not clear. I'll update it, but if you want to play with it in
the mean time, I'll explain here. But first, what were the symptoms where
you say you couldn't use bootp?

This patch only supports the RAW AF_PACKET API.  This is needed to get
access to the lowest level of the network stack in Linux. This means that
all of the Ethernet frame is included. This allows the u-boot network stack
to be fully used. In other words, nothing about the Linux network stack is
involved in forming the packets that end up on the wire. To receive the
responses to packets sent from u-boot the network interface has to be set
to promiscuous mode so that the network card won't filter out packets not
destined for its configured (on Linux) MAC address.

The device tree as added by this patch should be everything you need to use
eth0 on the host machine.

To contrast, the patch that adds support for the 'lo' interface cannot use
the RAW AF_PACKET API because the lo interface doesn't support
Ethernet-level traffic. It is a higher-level interface that is expected
only to be used at the AF_INET level of the API. As such, the most raw we
can get on that interface is the RAW AF_INET API on UDP. This allows us to
set the IP_HDRINCL option to include everything except the Ethernet header
in the packets we send and receive.

There is no decision to make. The local code path will only work on the
'lo' interface and the not-local code path will only work on non-'lo'
interface. This check is explicit in sb_eth_raw_start().

> Useful examples would be:
>
> - ping
> - bootp
> - tftpboot

I have tested all 3 of these with just the device tree included in this
patch. All that you need to do is set the eth1addr to something. Set ethact
to "eth1".

You can then use dhcp (typically need to set autoload to no first) or set a
static IP. Then you can ping or tftp.

If you set ethact to eth5 (the localhost interface in the device tree in
the 'lo' support patch) then don't expect ping to work, but you should be
able to tftpboot from the local TFTP server.

> and how to use raw/normal device.

I hope this is clear above.

> > +
> > +
> >  SPI Emulation
> >  -------------
> >
> > diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> > index b08746a..dcbfa8a 100644
> > --- a/drivers/net/Kconfig
> > +++ b/drivers/net/Kconfig
> > @@ -20,4 +20,9 @@ config ETH_SANDBOX
> >         default y
> >         bool "Sandbox: Mocked Ethernet driver"
> >
> > +config ETH_SANDBOX_RAW
> > +       depends on DM_ETH && SANDBOX
> > +       default y
> > +       bool "Sandbox: Bridge to Linux Raw Sockets"
>
> This needs some help.
>
> > +
> >  endif # NETDEVICES
> > diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> > index 15dc431..2659a8a 100644
> > --- a/drivers/net/Makefile
> > +++ b/drivers/net/Makefile
> > @@ -51,6 +51,7 @@ obj-$(CONFIG_PCNET) += pcnet.o
> >  obj-$(CONFIG_RTL8139) += rtl8139.o
> >  obj-$(CONFIG_RTL8169) += rtl8169.o
> >  obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
> > +obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o
> >  obj-$(CONFIG_SH_ETHER) += sh_eth.o
> >  obj-$(CONFIG_SMC91111) += smc91111.o
> >  obj-$(CONFIG_SMC911X) += smc911x.o
> > diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
> > new file mode 100644
> > index 0000000..01b33a9
> > --- /dev/null
> > +++ b/drivers/net/sandbox-raw.c
> > @@ -0,0 +1,105 @@
> > +/*
> > + * Copyright (c) 2015 National Instruments
> > + *
> > + * (C) Copyright 2015
> > + * Joe Hershberger <joe.hershberger@ni.com>
> > + *
> > + * SPDX-License-Identifier:    GPL-2.0
> > + */
> > +
> > +#include <asm/eth-raw-os.h>
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <malloc.h>
> > +#include <net.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +
> > +static int sb_eth_raw_start(struct udevice *dev)
> > +{
> > +       struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
> > +       struct eth_pdata *pdata = dev_get_platdata(dev);
> > +       int retval;
> > +       const char *interface;
> > +
> > +       debug("eth_sandbox_raw: Start\n");
> > +
> > +       interface = fdt_getprop(gd->fdt_blob, dev->of_offset,
> > +                                           "host-raw-interface", NULL);
>
> This can return NULL, so you should return -EINVAL in that case.

OK

> > +
> > +       retval = sandbox_eth_raw_os_init(interface, pdata->enetaddr,
priv);
> > +
> > +       return retval;
> > +}
> > +
> > +static int sb_eth_raw_send(struct udevice *dev, void *packet, int
length)
> > +{
> > +       struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
> > +
> > +       debug("eth_sandbox_raw: Send packet %d\n", length);
> > +
> > +       return sandbox_eth_raw_os_send(packet, length, priv);
> > +}
> > +
> > +static int sb_eth_raw_recv(struct udevice *dev)
> > +{
> > +       struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
> > +       int retval;
> > +       uchar buffer[PKTSIZE];
> > +       int length;
> > +
> > +       retval = sandbox_eth_raw_os_recv(buffer, &length, priv);
> > +
> > +       if (!retval && length) {
> > +               debug("eth_sandbox_raw: received packet %d\n",
> > +                     length);
> > +               NetReceive(buffer, length);
> > +       }
> > +       return 0;
> > +}
> > +
> > +static void sb_eth_raw_stop(struct udevice *dev)
> > +{
> > +       struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
> > +
> > +       debug("eth_sandbox_raw: Stop\n");
> > +
> > +       sandbox_eth_raw_os_halt(priv);
> > +}
> > +
> > +static const struct eth_ops sb_eth_raw_ops = {
> > +       .start                  = sb_eth_raw_start,
> > +       .send                   = sb_eth_raw_send,
> > +       .recv                   = sb_eth_raw_recv,
> > +       .stop                   = sb_eth_raw_stop,
> > +};
> > +
> > +static int sb_eth_raw_remove(struct udevice *dev)
> > +{
> > +       return 0;
> > +}
>
> You can drop this function.

Good point.

> > +
> > +static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev)
> > +{
> > +       struct eth_pdata *pdata = dev_get_platdata(dev);
> > +
> > +       pdata->iobase = dev_get_addr(dev);
> > +       return 0;
> > +}
> > +
> > +static const struct udevice_id sb_eth_raw_ids[] = {
> > +       { .compatible = "sandbox,eth-raw" },
> > +       { }
> > +};
> > +
> > +U_BOOT_DRIVER(eth_sandbox_raw) = {
> > +       .name   = "eth_sandbox_raw",
> > +       .id     = UCLASS_ETH,
> > +       .of_match = sb_eth_raw_ids,
> > +       .ofdata_to_platdata = sb_eth_raw_ofdata_to_platdata,
> > +       .remove = sb_eth_raw_remove,
> > +       .ops    = &sb_eth_raw_ops,
> > +       .priv_auto_alloc_size = sizeof(struct eth_sandbox_raw_priv),
> > +       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
> > +};
> > --
> > 1.7.11.5
> >
>
> Regards,
> Simon
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 23/23] sandbox: eth: Add support for using the 'lo' interface
  2015-03-01 18:07         ` Simon Glass
@ 2015-03-02  7:18           ` Joe Hershberger
  2015-03-02 22:16             ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-02  7:18 UTC (permalink / raw)
  To: u-boot

On Sun, Mar 1, 2015 at 12:07 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > The 'lo' interface on Linux doesn't support thinks like ARP or
> > link-layer access like we use to talk to a normal network interface.
> > A higher-level network API must be used to access localhost.
> >
> > As written, this interface is limited to not supporting ICMP since the
> > API doesn't allow the socket to be opened for all IP traffic and be able
> > to receive at the same time. UDP is far more useful to test with, so it
> > was selected over ICMP. Ping won't work, but things like TFTP should
> > work.
> >
> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> >
> > ---
> >
> > Changes in v4:
> > -Added support for the 'lo' network interface
> >
> > Changes in v3: None
> > Changes in v2: None
> >
> >  arch/sandbox/cpu/eth-raw-os.c         | 152
+++++++++++++++++++++++++++-------
> >  arch/sandbox/dts/sandbox.dts          |  10 +++
> >  arch/sandbox/include/asm/eth-raw-os.h |  10 ++-
> >  drivers/net/sandbox-raw.c             |  62 +++++++++++++-
> >  4 files changed, 203 insertions(+), 31 deletions(-)
> >
> > diff --git a/arch/sandbox/cpu/eth-raw-os.c
b/arch/sandbox/cpu/eth-raw-os.c
> > index 9218f94..acb150a 100644
> > --- a/arch/sandbox/cpu/eth-raw-os.c
> > +++ b/arch/sandbox/cpu/eth-raw-os.c
> > @@ -11,6 +11,8 @@
> >  #include <errno.h>
> >  #include <net/if.h>
> >  #include <netinet/in.h>
> > +#include <netinet/ip.h>
> > +#include <netinet/udp.h>
> >  #include <stdio.h>
> >  #include <stdlib.h>
> >  #include <string.h>
> > @@ -19,51 +21,139 @@
> >  #include <sys/socket.h>
> >  #include <unistd.h>
> >
> > +#include <arpa/inet.h>
> >  #include <linux/if_ether.h>
> >  #include <linux/if_packet.h>
> >
> >  int sandbox_eth_raw_os_init(const char *ifname, unsigned char *ethmac,
> >                             struct eth_sandbox_raw_priv *priv)
> >  {
> > -       struct sockaddr_ll *device;
> > -       struct packet_mreq mr;
> > -
> > -       /* Prepare device struct */
> > -       priv->device = malloc(sizeof(struct sockaddr_ll));
> > -       device = priv->device;
> > -       memset(device, 0, sizeof(struct sockaddr_ll));
> > -       device->sll_ifindex = if_nametoindex(ifname);
> > -       device->sll_family = AF_PACKET;
> > -       memcpy(device->sll_addr, ethmac, 6);
> > -       device->sll_halen = htons(6);
> > -
> > -       /* Open socket */
> > -       priv->sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
> > -       if (priv->sd < 0) {
> > -               printf("Failed to open socket: %d %s\n", errno,
> > -                      strerror(errno));
> > -               return -errno;
> > +       if (priv->local) {
>
> Can you put these two blocks of code (if and else) in separate
> functions and call them from here? This function is too long.

OK

> > +               struct sockaddr_in *device;
> > +               int ret;
> > +               struct timeval tv;
> > +               int one = 1;
> > +
> > +               /* Prepare device struct */
> > +               priv->device = malloc(sizeof(struct sockaddr_in));
>
> return -ENOMEM if NULL.
>
> > +               device = priv->device;
> > +               memset(device, 0, sizeof(struct sockaddr_in));
> > +               device->sin_family = AF_INET;
> > +               ret = inet_pton(AF_INET, "127.0.0.1",
>
> Is this INADDR_LOOPBACK? Maybe you can just assign it here?
>
> > +                         (struct in_addr *)&device->sin_addr.s_addr);
> > +               if (ret < 0) {
> > +                       printf("Failed to convert address: %d %s\n",
errno,
> > +                              strerror(errno));
> > +                       return -errno;
> > +               }
> > +
> > +               /**
> > +                * Open socket
> > +                *  Since we specify UDP here, any incoming ICMP
packets will
> > +                *  not be received, so things like ping will not work
on this
> > +                *  localhost interface.
> > +                */
> > +               priv->sd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
> > +               if (priv->sd < 0) {
> > +                       printf("Failed to open socket: %d %s\n", errno,
> > +                              strerror(errno));
> > +                       return -errno;
> > +               }
> > +
> > +               /* Allow the receive to timeout after a millisecond */
> > +               tv.tv_sec = 0;
> > +               tv.tv_usec = 1000;
> > +               ret = setsockopt(priv->sd, SOL_SOCKET, SO_RCVTIMEO,
(char *)&tv,
> > +                          sizeof(struct timeval));
> > +               if (ret < 0) {
> > +                       printf("Failed to set opt: %d %s\n", errno,
> > +                              strerror(errno));
> > +                       return -errno;
> > +               }
> > +
> > +               /* Include the UDP/IP headers on send and receive */
> > +               ret = setsockopt(priv->sd, IPPROTO_IP, IP_HDRINCL, &one,
> > +                                sizeof(one));
> > +               if (ret < 0) {
> > +                       printf("Failed to set opt: %d %s\n", errno,
> > +                              strerror(errno));
> > +                       return -errno;
> > +               }
> > +               priv->local_bind_sd = -1;
> > +               priv->local_bind_udp_port = 0;
> > +       } else {
> > +               struct sockaddr_ll *device;
> > +               struct packet_mreq mr;
> > +
> > +               /* Prepare device struct */
> > +               priv->device = malloc(sizeof(struct sockaddr_ll));
> > +               device = priv->device;
> > +               memset(device, 0, sizeof(struct sockaddr_ll));
> > +               device->sll_ifindex = if_nametoindex(ifname);
> > +               device->sll_family = AF_PACKET;
> > +               memcpy(device->sll_addr, ethmac, 6);
> > +               device->sll_halen = htons(6);
> > +
> > +               /* Open socket */
> > +               priv->sd = socket(PF_PACKET, SOCK_RAW,
htons(ETH_P_ALL));
> > +               if (priv->sd < 0) {
> > +                       printf("Failed to open socket: %d %s\n", errno,
> > +                              strerror(errno));
> > +                       return -errno;
> > +               }
> > +               /* Bind to the specified interface */
> > +               setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE,
ifname,
> > +                          strlen(ifname) + 1);
> > +
> > +               /* Enable promiscuous mode to receive responses meant
for us */
> > +               mr.mr_ifindex = device->sll_ifindex;
> > +               mr.mr_type = PACKET_MR_PROMISC;
> > +               setsockopt(priv->sd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
> > +                          &mr, sizeof(mr));
> >         }
> > -       /* Bind to the specified interface */
> > -       setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
> > -                  strlen(ifname) + 1);
> > -
> > -       /* Enable promiscuous mode to receive responses meant for us */
> > -       mr.mr_ifindex = device->sll_ifindex;
> > -       mr.mr_type = PACKET_MR_PROMISC;
> > -       setsockopt(priv->sd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
> > -                  &mr, sizeof(mr));
> > +
> >         return 0;
> >  }
> >
> >  int sandbox_eth_raw_os_send(void *packet, int length,
> > -                           const struct eth_sandbox_raw_priv *priv)
> > +                           struct eth_sandbox_raw_priv *priv)
> >  {
> >         int retval;
> > +       struct udphdr *udph = packet + sizeof(struct iphdr);
> >
> >         if (!priv->sd || !priv->device)
> >                 return -EINVAL;
> >
> > +       if (priv->local && (priv->local_bind_sd == -1 ||
> > +                           priv->local_bind_udp_port != udph->source))
{
>
> What does this block of code do? Comment?

OK, I'll add a comment. This block of code came about when testing tftp on
the localhost interface. When using the RAW AF_INET API, the network stack
is still in play responding to incoming traffic based on open "ports".
Since it is raw (at the IP layer, no Ethernet) the network stack tells the
TFTP server that the port it responded to is closed. This causes the TFTP
transfer to be aborted. This block of code inspects the outgoing packet as
formulated by the u-boot network stack to determine the source port (that
the TFTP server will send packets back to) and opens a typical UDP socket
on that port, thus preventing the network stack from sending that ICMP
message claiming that the port has no bound socket.

> > +               struct iphdr *iph = packet;
> > +               struct sockaddr_in addr;
> > +
> > +               if (priv->local_bind_sd != -1)
> > +                       close(priv->local_bind_sd);
> > +
> > +               /* A normal UDP socket is required to bind */
> > +               priv->local_bind_sd = socket(AF_INET, SOCK_DGRAM, 0);
> > +               if (priv->local_bind_sd < 0) {
> > +                       printf("Failed to open bind sd: %d %s\n", errno,
> > +                              strerror(errno));
> > +                       return -errno;
> > +               }
> > +               priv->local_bind_udp_port = udph->source;
> > +
> > +               /**
> > +                * Bind the UDP port that we intend to use as our
source port
> > +                * so that the kernel will not send ICMP port
unreachable
>
> Do you mean return the 'ICMP port unreachable' error?

I guess it is an error. I just thought of it as guidance to the sender.

> > +                */
> > +               addr.sin_family = AF_INET;
> > +               addr.sin_port = udph->source;
> > +               addr.sin_addr.s_addr = iph->saddr;
> > +               retval = bind(priv->local_bind_sd, &addr, sizeof(addr));
> > +               if (retval < 0)
> > +                       printf("Failed to bind: %d %s\n", errno,
> > +                              strerror(errno));
> > +       }
> > +
> >         retval = sendto(priv->sd, packet, length, 0,
> >                         (struct sockaddr *)priv->device,
> >                         sizeof(struct sockaddr_ll));
> > @@ -99,4 +189,10 @@ void sandbox_eth_raw_os_halt(struct
eth_sandbox_raw_priv *priv)
> >         priv->device = NULL;
> >         close(priv->sd);
> >         priv->sd = -1;
> > +       if (priv->local) {
> > +               if (priv->local_bind_sd != -1)
> > +                       close(priv->local_bind_sd);
> > +               priv->local_bind_sd = -1;
> > +               priv->local_bind_udp_port = 0;
> > +       }
> >  }
> > diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
> > index b6762f4..9851bda 100644
> > --- a/arch/sandbox/dts/sandbox.dts
> > +++ b/arch/sandbox/dts/sandbox.dts
> > @@ -4,6 +4,10 @@
> >         #address-cells = <1>;
> >         #size-cells = <0>;
> >
> > +       aliases {
> > +               eth5 = "/eth at 90000000";
> > +       };
> > +
> >         chosen {
> >                 stdout-path = "/serial";
> >         };
> > @@ -192,4 +196,10 @@
> >                 reg = <0x80000000 0x1000>;
> >                 host-raw-interface = "eth0";
> >         };
> > +
> > +       eth at 90000000 {
> > +               compatible = "sandbox,eth-raw";
> > +               reg = <0x90000000 0x1000>;
> > +               host-raw-interface = "lo";
> > +       };
> >  };
> > diff --git a/arch/sandbox/include/asm/eth-raw-os.h
b/arch/sandbox/include/asm/eth-raw-os.h
> > index d92b72c..44e7050 100644
> > --- a/arch/sandbox/include/asm/eth-raw-os.h
> > +++ b/arch/sandbox/include/asm/eth-raw-os.h
> > @@ -15,16 +15,24 @@
> >   *
> >   * sd: socket descriptor - the open socket during a session
> >   * device: struct sockaddr_ll - the host interface packets move to/from
> > + * local: 1 or 0 to select a local interface or not
>
> Should expand this a bit. The local interface is the loopback
> device....why do you want one over the other?

Not sure what you're getting at here. You want local if you want to talk to
a local server (TFTP is what I tested with). You want non-local if you want
to talk over a real Ethernet interface to a different machine than the one
running sandbox.

> > + * local_bindsd: socket descriptor to prevent the kernel from sending
> > + *              a message to the server claiming the port is
> > + *              unreachable
> > + * local_bind_udp_port: The UDP port number that we bound to
> >   */
> >  struct eth_sandbox_raw_priv {
> >         int sd;
> >         void *device;
> > +       int local;
> > +       int local_bind_sd;
> > +       unsigned short local_bind_udp_port;
> >  };
> >
> >  int sandbox_eth_raw_os_init(const char *ifname, unsigned char *ethmac,
> >                             struct eth_sandbox_raw_priv *priv);
> >  int sandbox_eth_raw_os_send(void *packet, int length,
> > -                           const struct eth_sandbox_raw_priv *priv);
> > +                           struct eth_sandbox_raw_priv *priv);
> >  int sandbox_eth_raw_os_recv(void *packet, int *length,
> >                             const struct eth_sandbox_raw_priv *priv);
> >  void sandbox_eth_raw_os_halt(struct eth_sandbox_raw_priv *priv);
> > diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
> > index 01b33a9..4b0f836 100644
> > --- a/drivers/net/sandbox-raw.c
> > +++ b/drivers/net/sandbox-raw.c
> > @@ -15,6 +15,8 @@
> >
> >  DECLARE_GLOBAL_DATA_PTR;
> >
> > +static int reply_arp;
> > +static IPaddr_t arp_ip;
> >
> >  static int sb_eth_raw_start(struct udevice *dev)
> >  {
> > @@ -28,6 +30,12 @@ static int sb_eth_raw_start(struct udevice *dev)
> >         interface = fdt_getprop(gd->fdt_blob, dev->of_offset,
> >                                             "host-raw-interface", NULL);
> >
> > +       if (strcmp(interface, "lo") == 0) {
> > +               priv->local = 1;
> > +               setenv("ipaddr", "127.0.0.1");
> > +               setenv("serverip", "127.0.0.1");
> > +       }
> > +
> >         retval = sandbox_eth_raw_os_init(interface, pdata->enetaddr,
priv);
> >
> >         return retval;
> > @@ -39,19 +47,69 @@ static int sb_eth_raw_send(struct udevice *dev,
void *packet, int length)
> >
> >         debug("eth_sandbox_raw: Send packet %d\n", length);
> >
> > +       if (priv->local) {
> > +               struct ethernet_hdr *eth = packet;
> > +
> > +               if (ntohs(eth->et_protlen) == PROT_ARP) {
> > +                       struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
> > +
> > +                       /**
> > +                        * localhost works on a higher level API in
Linux than
>
> nit: higher-level
>
> > +                        * ARP packets, so fake it
>
> fake what?

Fake an ARP response. The u-boot network stack is sending an ARP request
(to find the MAC address to address the actual packet to) and requires an
ARP response to continue. Since this is the localhost interface, there is
no Etherent level traffic at all, so there is no way to send an ARP request
or to get a response. For this reason we fake the response to make the
u-boot network stack happy.

> > +                        */
> > +                       arp_ip = NetReadIP(&arp->ar_tpa);
> > +                       reply_arp = 1;
> > +                       return 0;
> > +               }
> > +               packet += ETHER_HDR_SIZE;
> > +               length -= ETHER_HDR_SIZE;
> > +       }
> >         return sandbox_eth_raw_os_send(packet, length, priv);
> >  }
> >
> >  static int sb_eth_raw_recv(struct udevice *dev)
> >  {
> > +       struct eth_pdata *pdata = dev_get_platdata(dev);
> >         struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
> > -       int retval;
> > +       int retval = 0;
> >         uchar buffer[PKTSIZE];
> >         int length;
> >
> > -       retval = sandbox_eth_raw_os_recv(buffer, &length, priv);
> > +       if (reply_arp) {
> > +               struct arp_hdr *arp = (void *)buffer + ETHER_HDR_SIZE;
> > +
> > +               /* Formulate a fake ARP */
> > +               arp->ar_hrd = htons(ARP_ETHER);
> > +               arp->ar_pro = htons(PROT_IP);
> > +               arp->ar_hln = ARP_HLEN;
> > +               arp->ar_pln = ARP_PLEN;
> > +               arp->ar_op = htons(ARPOP_REPLY);
> > +               /* Any non-zero MAC address will work */
> > +               memset(&arp->ar_sha, 0x01, ARP_HLEN);
> > +               /* Use whatever IP we were looking for (always
127.0.0.1?) */
> > +               NetWriteIP(&arp->ar_spa, arp_ip);
> > +               memcpy(&arp->ar_tha, pdata->enetaddr, ARP_HLEN);
> > +               NetWriteIP(&arp->ar_tpa, NetOurIP);
> > +               length = ARP_HDR_SIZE;
> > +       } else {
> > +               /* If local, the Ethernet header won't be included;
skip it */
> > +               uchar *pktptr = priv->local ? buffer + ETHER_HDR_SIZE :
buffer;
> > +
> > +               retval = sandbox_eth_raw_os_recv(pktptr, &length, priv);
> > +       }
> >
> >         if (!retval && length) {
> > +               if (priv->local) {
> > +                       struct ethernet_hdr *eth = (void *)buffer;
> > +
> > +                       /* Fill in enough of the missing Ethernet
header */
> > +                       memcpy(eth->et_dest, pdata->enetaddr, ARP_HLEN);
> > +                       memset(eth->et_src, 0x01, ARP_HLEN);
> > +                       eth->et_protlen = htons(reply_arp ? PROT_ARP :
PROT_IP);
> > +                       reply_arp = 0;
> > +                       length += ETHER_HDR_SIZE;
> > +               }
> > +
> >                 debug("eth_sandbox_raw: received packet %d\n",
> >                       length);
> >                 NetReceive(buffer, length);
> > --
> > 1.7.11.5
> >
>
> Regards,
> Simon
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 21/23] sandbox: eth: Add a bridge to a real network for sandbox
  2015-03-02  7:17           ` Joe Hershberger
@ 2015-03-02 15:48             ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-02 15:48 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 2 March 2015 at 00:17, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> On Sun, Mar 1, 2015 at 12:07 PM, Simon Glass <sjg@chromium.org> wrote:
>>
>> On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com>
>> wrote:
>> > Implement a bridge between u-boot's network stack and Linux's raw packet
>> > API allowing the sandbox to send and receive packets using the host
>> > machine's network interface.
>> >
>> > This raw Ethernet API requires elevated privileges.  You can either run
>> > as root, or you can add the capability needed like so:
>> >
>> > sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot
>> >
>> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>>
>> Reviewed-by: Simon Glass <sjg@chromium.org>
>>
>> A few nits below.

[snip]

>> >
>> > +Linux RAW Networking Bridge
>> > +---------------------------
>> > +
>> > +The sandbox_eth_raw driver bridges traffic between the bottom of the
>> > network
>> > +stack and the RAW sockets API in Linux. This allows much of the u-boot
>> > network
>> > +functionality to be tested in sandbox against real network traffic.
>> > +
>> > +The RAW sockets Ethernet API requires elevated privileges in Linux. You
>> > can
>> > +either run as root, or you can add the capability needed like so:
>> > +
>> > +sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot
>>
>> This is so cool.
>
> :D
>
>> Can you give some examples here? For me, ping seems to work, but I
>> can't use bootp. Is that what the raw mode is for? How do I enable it?
>> I tried setting ethact but am not sure what I am doing.
>
> Sorry it's not clear. I'll update it, but if you want to play with it in the
> mean time, I'll explain here. But first, what were the symptoms where you
> say you couldn't use bootp?
>
> This patch only supports the RAW AF_PACKET API.  This is needed to get
> access to the lowest level of the network stack in Linux. This means that
> all of the Ethernet frame is included. This allows the u-boot network stack
> to be fully used. In other words, nothing about the Linux network stack is
> involved in forming the packets that end up on the wire. To receive the
> responses to packets sent from u-boot the network interface has to be set to
> promiscuous mode so that the network card won't filter out packets not
> destined for its configured (on Linux) MAC address.
>
> The device tree as added by this patch should be everything you need to use
> eth0 on the host machine.
>
> To contrast, the patch that adds support for the 'lo' interface cannot use
> the RAW AF_PACKET API because the lo interface doesn't support
> Ethernet-level traffic. It is a higher-level interface that is expected only
> to be used at the AF_INET level of the API. As such, the most raw we can get
> on that interface is the RAW AF_INET API on UDP. This allows us to set the
> IP_HDRINCL option to include everything except the Ethernet header in the
> packets we send and receive.
>
> There is no decision to make. The local code path will only work on the 'lo'
> interface and the not-local code path will only work on non-'lo' interface.
> This check is explicit in sb_eth_raw_start().
>
>> Useful examples would be:
>>
>> - ping
>> - bootp
>> - tftpboot
>
> I have tested all 3 of these with just the device tree included in this
> patch. All that you need to do is set the eth1addr to something. Set ethact
> to "eth1".
>
> You can then use dhcp (typically need to set autoload to no first) or set a
> static IP. Then you can ping or tftp.
>
> If you set ethact to eth5 (the localhost interface in the device tree in the
> 'lo' support patch) then don't expect ping to work, but you should be able
> to tftpboot from the local TFTP server.
>
>> and how to use raw/normal device.
>
> I hope this is clear above.
>

OK the ethact might have been what I was missing. Anyway I'll wait
until you update the README and try again.

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 23/23] sandbox: eth: Add support for using the 'lo' interface
  2015-03-02  7:18           ` Joe Hershberger
@ 2015-03-02 22:16             ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-02 22:16 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 2 March 2015 at 00:18, Joe Hershberger <joe.hershberger@gmail.com> wrote:
>
>
> On Sun, Mar 1, 2015 at 12:07 PM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 24 February 2015 at 17:02, Joe Hershberger <joe.hershberger@ni.com>
>> wrote:
>> > The 'lo' interface on Linux doesn't support thinks like ARP or
>> > link-layer access like we use to talk to a normal network interface.
>> > A higher-level network API must be used to access localhost.
>> >
>> > As written, this interface is limited to not supporting ICMP since the
>> > API doesn't allow the socket to be opened for all IP traffic and be able
>> > to receive at the same time. UDP is far more useful to test with, so it
>> > was selected over ICMP. Ping won't work, but things like TFTP should
>> > work.
>> >
>> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>> >
>> > ---
>> >
>> > Changes in v4:
>> > -Added support for the 'lo' network interface
>> >
>> > Changes in v3: None
>> > Changes in v2: None
>> >
>> >  arch/sandbox/cpu/eth-raw-os.c         | 152
>> > +++++++++++++++++++++++++++-------
>> >  arch/sandbox/dts/sandbox.dts          |  10 +++
>> >  arch/sandbox/include/asm/eth-raw-os.h |  10 ++-
>> >  drivers/net/sandbox-raw.c             |  62 +++++++++++++-
>> >  4 files changed, 203 insertions(+), 31 deletions(-)
>> >
>> > diff --git a/arch/sandbox/cpu/eth-raw-os.c
>> > b/arch/sandbox/cpu/eth-raw-os.c
>> > index 9218f94..acb150a 100644
>> > --- a/arch/sandbox/cpu/eth-raw-os.c
>> > +++ b/arch/sandbox/cpu/eth-raw-os.c
>> > @@ -11,6 +11,8 @@
>> >  #include <errno.h>
>> >  #include <net/if.h>
>> >  #include <netinet/in.h>
>> > +#include <netinet/ip.h>
>> > +#include <netinet/udp.h>
>> >  #include <stdio.h>
>> >  #include <stdlib.h>
>> >  #include <string.h>
>> > @@ -19,51 +21,139 @@
>> >  #include <sys/socket.h>
>> >  #include <unistd.h>
>> >
>> > +#include <arpa/inet.h>
>> >  #include <linux/if_ether.h>
>> >  #include <linux/if_packet.h>
>> >
>> >  int sandbox_eth_raw_os_init(const char *ifname, unsigned char *ethmac,
>> >                             struct eth_sandbox_raw_priv *priv)
>> >  {
>> > -       struct sockaddr_ll *device;
>> > -       struct packet_mreq mr;
>> > -
>> > -       /* Prepare device struct */
>> > -       priv->device = malloc(sizeof(struct sockaddr_ll));
>> > -       device = priv->device;
>> > -       memset(device, 0, sizeof(struct sockaddr_ll));
>> > -       device->sll_ifindex = if_nametoindex(ifname);
>> > -       device->sll_family = AF_PACKET;
>> > -       memcpy(device->sll_addr, ethmac, 6);
>> > -       device->sll_halen = htons(6);
>> > -
>> > -       /* Open socket */
>> > -       priv->sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
>> > -       if (priv->sd < 0) {
>> > -               printf("Failed to open socket: %d %s\n", errno,
>> > -                      strerror(errno));
>> > -               return -errno;
>> > +       if (priv->local) {
>>
>> Can you put these two blocks of code (if and else) in separate
>> functions and call them from here? This function is too long.
>
> OK
>
>> > +               struct sockaddr_in *device;
>> > +               int ret;
>> > +               struct timeval tv;
>> > +               int one = 1;
>> > +
>> > +               /* Prepare device struct */
>> > +               priv->device = malloc(sizeof(struct sockaddr_in));
>>
>> return -ENOMEM if NULL.
>>
>> > +               device = priv->device;
>> > +               memset(device, 0, sizeof(struct sockaddr_in));
>> > +               device->sin_family = AF_INET;
>> > +               ret = inet_pton(AF_INET, "127.0.0.1",
>>
>> Is this INADDR_LOOPBACK? Maybe you can just assign it here?
>>
>> > +                         (struct in_addr *)&device->sin_addr.s_addr);
>> > +               if (ret < 0) {
>> > +                       printf("Failed to convert address: %d %s\n",
>> > errno,
>> > +                              strerror(errno));
>> > +                       return -errno;
>> > +               }
>> > +
>> > +               /**
>> > +                * Open socket
>> > +                *  Since we specify UDP here, any incoming ICMP packets
>> > will
>> > +                *  not be received, so things like ping will not work
>> > on this
>> > +                *  localhost interface.
>> > +                */
>> > +               priv->sd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
>> > +               if (priv->sd < 0) {
>> > +                       printf("Failed to open socket: %d %s\n", errno,
>> > +                              strerror(errno));
>> > +                       return -errno;
>> > +               }
>> > +
>> > +               /* Allow the receive to timeout after a millisecond */
>> > +               tv.tv_sec = 0;
>> > +               tv.tv_usec = 1000;
>> > +               ret = setsockopt(priv->sd, SOL_SOCKET, SO_RCVTIMEO,
>> > (char *)&tv,
>> > +                          sizeof(struct timeval));
>> > +               if (ret < 0) {
>> > +                       printf("Failed to set opt: %d %s\n", errno,
>> > +                              strerror(errno));
>> > +                       return -errno;
>> > +               }
>> > +
>> > +               /* Include the UDP/IP headers on send and receive */
>> > +               ret = setsockopt(priv->sd, IPPROTO_IP, IP_HDRINCL, &one,
>> > +                                sizeof(one));
>> > +               if (ret < 0) {
>> > +                       printf("Failed to set opt: %d %s\n", errno,
>> > +                              strerror(errno));
>> > +                       return -errno;
>> > +               }
>> > +               priv->local_bind_sd = -1;
>> > +               priv->local_bind_udp_port = 0;
>> > +       } else {
>> > +               struct sockaddr_ll *device;
>> > +               struct packet_mreq mr;
>> > +
>> > +               /* Prepare device struct */
>> > +               priv->device = malloc(sizeof(struct sockaddr_ll));
>> > +               device = priv->device;
>> > +               memset(device, 0, sizeof(struct sockaddr_ll));
>> > +               device->sll_ifindex = if_nametoindex(ifname);
>> > +               device->sll_family = AF_PACKET;
>> > +               memcpy(device->sll_addr, ethmac, 6);
>> > +               device->sll_halen = htons(6);
>> > +
>> > +               /* Open socket */
>> > +               priv->sd = socket(PF_PACKET, SOCK_RAW,
>> > htons(ETH_P_ALL));
>> > +               if (priv->sd < 0) {
>> > +                       printf("Failed to open socket: %d %s\n", errno,
>> > +                              strerror(errno));
>> > +                       return -errno;
>> > +               }
>> > +               /* Bind to the specified interface */
>> > +               setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE,
>> > ifname,
>> > +                          strlen(ifname) + 1);
>> > +
>> > +               /* Enable promiscuous mode to receive responses meant
>> > for us */
>> > +               mr.mr_ifindex = device->sll_ifindex;
>> > +               mr.mr_type = PACKET_MR_PROMISC;
>> > +               setsockopt(priv->sd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
>> > +                          &mr, sizeof(mr));
>> >         }
>> > -       /* Bind to the specified interface */
>> > -       setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
>> > -                  strlen(ifname) + 1);
>> > -
>> > -       /* Enable promiscuous mode to receive responses meant for us */
>> > -       mr.mr_ifindex = device->sll_ifindex;
>> > -       mr.mr_type = PACKET_MR_PROMISC;
>> > -       setsockopt(priv->sd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
>> > -                  &mr, sizeof(mr));
>> > +
>> >         return 0;
>> >  }
>> >
>> >  int sandbox_eth_raw_os_send(void *packet, int length,
>> > -                           const struct eth_sandbox_raw_priv *priv)
>> > +                           struct eth_sandbox_raw_priv *priv)
>> >  {
>> >         int retval;
>> > +       struct udphdr *udph = packet + sizeof(struct iphdr);
>> >
>> >         if (!priv->sd || !priv->device)
>> >                 return -EINVAL;
>> >
>> > +       if (priv->local && (priv->local_bind_sd == -1 ||
>> > +                           priv->local_bind_udp_port != udph->source))
>> > {
>>
>> What does this block of code do? Comment?
>
> OK, I'll add a comment. This block of code came about when testing tftp on
> the localhost interface. When using the RAW AF_INET API, the network stack
> is still in play responding to incoming traffic based on open "ports". Since
> it is raw (at the IP layer, no Ethernet) the network stack tells the TFTP
> server that the port it responded to is closed. This causes the TFTP
> transfer to be aborted. This block of code inspects the outgoing packet as
> formulated by the u-boot network stack to determine the source port (that
> the TFTP server will send packets back to) and opens a typical UDP socket on
> that port, thus preventing the network stack from sending that ICMP message
> claiming that the port has no bound socket.

Sounds like a good comment :-)

>
>> > +               struct iphdr *iph = packet;
>> > +               struct sockaddr_in addr;
>> > +
>> > +               if (priv->local_bind_sd != -1)
>> > +                       close(priv->local_bind_sd);
>> > +
>> > +               /* A normal UDP socket is required to bind */
>> > +               priv->local_bind_sd = socket(AF_INET, SOCK_DGRAM, 0);
>> > +               if (priv->local_bind_sd < 0) {
>> > +                       printf("Failed to open bind sd: %d %s\n", errno,
>> > +                              strerror(errno));
>> > +                       return -errno;
>> > +               }
>> > +               priv->local_bind_udp_port = udph->source;
>> > +
>> > +               /**
>> > +                * Bind the UDP port that we intend to use as our source
>> > port
>> > +                * so that the kernel will not send ICMP port
>> > unreachable
>>
>> Do you mean return the 'ICMP port unreachable' error?
>
> I guess it is an error. I just thought of it as guidance to the sender.
>
>> > +                */
>> > +               addr.sin_family = AF_INET;
>> > +               addr.sin_port = udph->source;
>> > +               addr.sin_addr.s_addr = iph->saddr;
>> > +               retval = bind(priv->local_bind_sd, &addr, sizeof(addr));
>> > +               if (retval < 0)
>> > +                       printf("Failed to bind: %d %s\n", errno,
>> > +                              strerror(errno));
>> > +       }
>> > +
>> >         retval = sendto(priv->sd, packet, length, 0,
>> >                         (struct sockaddr *)priv->device,
>> >                         sizeof(struct sockaddr_ll));
>> > @@ -99,4 +189,10 @@ void sandbox_eth_raw_os_halt(struct
>> > eth_sandbox_raw_priv *priv)
>> >         priv->device = NULL;
>> >         close(priv->sd);
>> >         priv->sd = -1;
>> > +       if (priv->local) {
>> > +               if (priv->local_bind_sd != -1)
>> > +                       close(priv->local_bind_sd);
>> > +               priv->local_bind_sd = -1;
>> > +               priv->local_bind_udp_port = 0;
>> > +       }
>> >  }
>> > diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
>> > index b6762f4..9851bda 100644
>> > --- a/arch/sandbox/dts/sandbox.dts
>> > +++ b/arch/sandbox/dts/sandbox.dts
>> > @@ -4,6 +4,10 @@
>> >         #address-cells = <1>;
>> >         #size-cells = <0>;
>> >
>> > +       aliases {
>> > +               eth5 = "/eth at 90000000";
>> > +       };
>> > +
>> >         chosen {
>> >                 stdout-path = "/serial";
>> >         };
>> > @@ -192,4 +196,10 @@
>> >                 reg = <0x80000000 0x1000>;
>> >                 host-raw-interface = "eth0";
>> >         };
>> > +
>> > +       eth at 90000000 {
>> > +               compatible = "sandbox,eth-raw";
>> > +               reg = <0x90000000 0x1000>;
>> > +               host-raw-interface = "lo";
>> > +       };
>> >  };
>> > diff --git a/arch/sandbox/include/asm/eth-raw-os.h
>> > b/arch/sandbox/include/asm/eth-raw-os.h
>> > index d92b72c..44e7050 100644
>> > --- a/arch/sandbox/include/asm/eth-raw-os.h
>> > +++ b/arch/sandbox/include/asm/eth-raw-os.h
>> > @@ -15,16 +15,24 @@
>> >   *
>> >   * sd: socket descriptor - the open socket during a session
>> >   * device: struct sockaddr_ll - the host interface packets move to/from
>> > + * local: 1 or 0 to select a local interface or not
>>
>> Should expand this a bit. The local interface is the loopback
>> device....why do you want one over the other?
>
> Not sure what you're getting at here. You want local if you want to talk to
> a local server (TFTP is what I tested with). You want non-local if you want
> to talk over a real Ethernet interface to a different machine than the one
> running sandbox.

That's what I was wondering. Just a few notes in the comment about how
to choose the parameter value.

>
>> > + * local_bindsd: socket descriptor to prevent the kernel from sending
>> > + *              a message to the server claiming the port is
>> > + *              unreachable
>> > + * local_bind_udp_port: The UDP port number that we bound to
>> >   */
>> >  struct eth_sandbox_raw_priv {
>> >         int sd;
>> >         void *device;
>> > +       int local;
>> > +       int local_bind_sd;
>> > +       unsigned short local_bind_udp_port;
>> >  };
>> >
>> >  int sandbox_eth_raw_os_init(const char *ifname, unsigned char *ethmac,
>> >                             struct eth_sandbox_raw_priv *priv);
>> >  int sandbox_eth_raw_os_send(void *packet, int length,
>> > -                           const struct eth_sandbox_raw_priv *priv);
>> > +                           struct eth_sandbox_raw_priv *priv);
>> >  int sandbox_eth_raw_os_recv(void *packet, int *length,
>> >                             const struct eth_sandbox_raw_priv *priv);
>> >  void sandbox_eth_raw_os_halt(struct eth_sandbox_raw_priv *priv);
>> > diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
>> > index 01b33a9..4b0f836 100644
>> > --- a/drivers/net/sandbox-raw.c
>> > +++ b/drivers/net/sandbox-raw.c
>> > @@ -15,6 +15,8 @@
>> >
>> >  DECLARE_GLOBAL_DATA_PTR;
>> >
>> > +static int reply_arp;
>> > +static IPaddr_t arp_ip;
>> >
>> >  static int sb_eth_raw_start(struct udevice *dev)
>> >  {
>> > @@ -28,6 +30,12 @@ static int sb_eth_raw_start(struct udevice *dev)
>> >         interface = fdt_getprop(gd->fdt_blob, dev->of_offset,
>> >                                             "host-raw-interface", NULL);
>> >
>> > +       if (strcmp(interface, "lo") == 0) {
>> > +               priv->local = 1;
>> > +               setenv("ipaddr", "127.0.0.1");
>> > +               setenv("serverip", "127.0.0.1");
>> > +       }
>> > +
>> >         retval = sandbox_eth_raw_os_init(interface, pdata->enetaddr,
>> > priv);
>> >
>> >         return retval;
>> > @@ -39,19 +47,69 @@ static int sb_eth_raw_send(struct udevice *dev, void
>> > *packet, int length)
>> >
>> >         debug("eth_sandbox_raw: Send packet %d\n", length);
>> >
>> > +       if (priv->local) {
>> > +               struct ethernet_hdr *eth = packet;
>> > +
>> > +               if (ntohs(eth->et_protlen) == PROT_ARP) {
>> > +                       struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
>> > +
>> > +                       /**
>> > +                        * localhost works on a higher level API in
>> > Linux than
>>
>> nit: higher-level
>>
>> > +                        * ARP packets, so fake it
>>
>> fake what?
>
> Fake an ARP response. The u-boot network stack is sending an ARP request (to
> find the MAC address to address the actual packet to) and requires an ARP
> response to continue. Since this is the localhost interface, there is no
> Etherent level traffic at all, so there is no way to send an ARP request or
> to get a response. For this reason we fake the response to make the u-boot
> network stack happy.

OK, please add this to the comment too.

>
>
>> > +                        */
>> > +                       arp_ip = NetReadIP(&arp->ar_tpa);
>> > +                       reply_arp = 1;
>> > +                       return 0;
>> > +               }
>> > +               packet += ETHER_HDR_SIZE;
>> > +               length -= ETHER_HDR_SIZE;
>> > +       }
>> >         return sandbox_eth_raw_os_send(packet, length, priv);
>> >  }
>> >
>> >  static int sb_eth_raw_recv(struct udevice *dev)
>> >  {
>> > +       struct eth_pdata *pdata = dev_get_platdata(dev);
>> >         struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
>> > -       int retval;
>> > +       int retval = 0;
>> >         uchar buffer[PKTSIZE];
>> >         int length;
>> >
>> > -       retval = sandbox_eth_raw_os_recv(buffer, &length, priv);
>> > +       if (reply_arp) {
>> > +               struct arp_hdr *arp = (void *)buffer + ETHER_HDR_SIZE;
>> > +
>> > +               /* Formulate a fake ARP */
>> > +               arp->ar_hrd = htons(ARP_ETHER);
>> > +               arp->ar_pro = htons(PROT_IP);
>> > +               arp->ar_hln = ARP_HLEN;
>> > +               arp->ar_pln = ARP_PLEN;
>> > +               arp->ar_op = htons(ARPOP_REPLY);
>> > +               /* Any non-zero MAC address will work */
>> > +               memset(&arp->ar_sha, 0x01, ARP_HLEN);
>> > +               /* Use whatever IP we were looking for (always
>> > 127.0.0.1?) */
>> > +               NetWriteIP(&arp->ar_spa, arp_ip);
>> > +               memcpy(&arp->ar_tha, pdata->enetaddr, ARP_HLEN);
>> > +               NetWriteIP(&arp->ar_tpa, NetOurIP);
>> > +               length = ARP_HDR_SIZE;
>> > +       } else {
>> > +               /* If local, the Ethernet header won't be included; skip
>> > it */
>> > +               uchar *pktptr = priv->local ? buffer + ETHER_HDR_SIZE :
>> > buffer;
>> > +
>> > +               retval = sandbox_eth_raw_os_recv(pktptr, &length, priv);
>> > +       }
>> >
>> >         if (!retval && length) {
>> > +               if (priv->local) {
>> > +                       struct ethernet_hdr *eth = (void *)buffer;
>> > +
>> > +                       /* Fill in enough of the missing Ethernet header
>> > */
>> > +                       memcpy(eth->et_dest, pdata->enetaddr, ARP_HLEN);
>> > +                       memset(eth->et_src, 0x01, ARP_HLEN);
>> > +                       eth->et_protlen = htons(reply_arp ? PROT_ARP :
>> > PROT_IP);
>> > +                       reply_arp = 0;
>> > +                       length += ETHER_HDR_SIZE;
>> > +               }
>> > +
>> >                 debug("eth_sandbox_raw: received packet %d\n",
>> >                       length);
>> >                 NetReceive(buffer, length);
>> > --
>> > 1.7.11.5

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack
  2015-03-01 16:13       ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Simon Glass
  2015-03-01 22:12         ` Joe Hershberger
@ 2015-03-03 22:29         ` Joe Hershberger
  2015-03-03 23:14           ` Simon Glass
  1 sibling, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-03 22:29 UTC (permalink / raw)
  To: u-boot

On Sun, Mar 1, 2015 at 10:13 AM, Simon Glass <sjg@chromium.org> wrote:

[snip]

> - I think the recv() method should change before long. The
> NetReceive() call should be made from the uclass since it is common to
> all drivers. Then the recv() method can return a packet if it finds
> one, but not submit it for processing

I looked into doing this and I think it may be more of a step backward.
Currently devices can directly hand their DMA buffers to the network stack.
With this change, most drivers would be forced to memcpy each packet into
the supplied buffer.

I do plan to rename the function, though.

-Joe

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack
  2015-03-03 22:29         ` Joe Hershberger
@ 2015-03-03 23:14           ` Simon Glass
  2015-03-03 23:32             ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-03-03 23:14 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 3 March 2015 at 15:29, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> On Sun, Mar 1, 2015 at 10:13 AM, Simon Glass <sjg@chromium.org> wrote:
>
> [snip]
>
>> - I think the recv() method should change before long. The
>> NetReceive() call should be made from the uclass since it is common to
>> all drivers. Then the recv() method can return a packet if it finds
>> one, but not submit it for processing
>
> I looked into doing this and I think it may be more of a step backward.
> Currently devices can directly hand their DMA buffers to the network stack.
> With this change, most drivers would be forced to memcpy each packet into
> the supplied buffer.

I don't see why. The uclass can request the address and length of the buffer.

int (*recv)(char **buffp, int **lenp);

>
> I do plan to rename the function, though.

OK.

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack
  2015-03-03 23:14           ` Simon Glass
@ 2015-03-03 23:32             ` Joe Hershberger
  2015-03-03 23:40               ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-03 23:32 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Tue, Mar 3, 2015 at 5:14 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 3 March 2015 at 15:29, Joe Hershberger <joe.hershberger@gmail.com>
wrote:
> > On Sun, Mar 1, 2015 at 10:13 AM, Simon Glass <sjg@chromium.org> wrote:
> >
> > [snip]
> >
> >> - I think the recv() method should change before long. The
> >> NetReceive() call should be made from the uclass since it is common to
> >> all drivers. Then the recv() method can return a packet if it finds
> >> one, but not submit it for processing
> >
> > I looked into doing this and I think it may be more of a step backward.
> > Currently devices can directly hand their DMA buffers to the network
stack.
> > With this change, most drivers would be forced to memcpy each packet
into
> > the supplied buffer.
>
> I don't see why. The uclass can request the address and length of the
buffer.
>
> int (*recv)(char **buffp, int **lenp);

That works... I think I'll return the length though. I don't see much value
in having a pointer to the length.

int (*recv)(uchar **packetp);

-Joe

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack
  2015-03-03 23:32             ` Joe Hershberger
@ 2015-03-03 23:40               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-03 23:40 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 3 March 2015 at 16:32, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> Hi Simon,
>
>
> On Tue, Mar 3, 2015 at 5:14 PM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 3 March 2015 at 15:29, Joe Hershberger <joe.hershberger@gmail.com>
>> wrote:
>> > On Sun, Mar 1, 2015 at 10:13 AM, Simon Glass <sjg@chromium.org> wrote:
>> >
>> > [snip]
>> >
>> >> - I think the recv() method should change before long. The
>> >> NetReceive() call should be made from the uclass since it is common to
>> >> all drivers. Then the recv() method can return a packet if it finds
>> >> one, but not submit it for processing
>> >
>> > I looked into doing this and I think it may be more of a step backward.
>> > Currently devices can directly hand their DMA buffers to the network
>> > stack.
>> > With this change, most drivers would be forced to memcpy each packet
>> > into
>> > the supplied buffer.
>>
>> I don't see why. The uclass can request the address and length of the
>> buffer.
>>
>> int (*recv)(char **buffp, int **lenp);
>
> That works... I think I'll return the length though. I don't see much value
> in having a pointer to the length.
>
> int (*recv)(uchar **packetp);

LGTM.

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 0/27] Add Driver Model support to network stack
  2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
                         ` (23 preceding siblings ...)
  2015-03-01 16:13       ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Simon Glass
@ 2015-03-04  2:40       ` Joe Hershberger
  2015-03-04  2:40         ` [U-Boot] [PATCH v5 01/27] test: dm: Reorder the objects to build Joe Hershberger
                           ` (27 more replies)
  24 siblings, 28 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:40 UTC (permalink / raw)
  To: u-boot

Add support for the Ethernet MAC controllers.  Phy support will come later.

Switching from RFC to a patch series to be applied to dm/master as a staging
area for this series to make it happen more quickly when the window opens.

If desired, let me know which of the non-DM related prerequisite patches are
wanted for this release.

I've added unit tests to verify functionality.

There is an additional driver for sandbox that bridges to the RAW
Ethernet API in Linux which lets you test with real traffic. It now
supports localhost as well (the 'lo' interface).

Changes in v5:
-Add a note to doc/README.drivers.eth about its obsolescence
-Add details about lo support to the README
-Added a comment about devname
-Added a test for skipping un-probe-able devices
-Added comments about test cases
-Added fallback for setting promiscuous mode
-Added help to Kconfig
-Added help to the sandbox eth mock driver Kconfig entry
-Added more details and examples in the README
-Check for NULL when reading fdt for host interface
-Check for malloc failure
-Expanded the Kconfig help
-Fix compile error on !DM_ETH
-Fixed warning from missing declaration
-Include new mapmem.h header
-Moved dm/ header
-Moved to a separate header mapmem.h
-New to v5
-Only check for alias if the name is long enough
-Remove cast of pointer passed to free
-Remove socket timeout
-Remove the empty sb_eth_raw_remove function
-Return -errno in from send and recv
-Return errno from recv
-Separate init to 2 helper static functions
-Set the socket to non-blocking
-Simplify sandbox eth driver by switching from int array to byte array
-Switch priv from packet buffer to a pointer to net_rx_packets[0]
-Switched to function to control state of mock driver
-Unmap memory for consistency
-Use INADDR_LOOPBACK
-Use a function call to change mock driver behavior
-Use local var for priv in eth_get_dev()
-Use more verbose comments
-Use net_rx_packets instead of a stack buffer

Changes in v4:
--Don't prevent eth_initialize on driver model
--If current == NULL, always check if there is a device available in eth_get_dev
--Include ethprime handling in eth_initialize
--Look up MAC address in post-probe
--Move env init call from uclass init to eth_initialize
--Print the alias in eth_initialize
--Use eth_initialize to probe all devices and write_hwaddr
-Add a helper function for eth_uclass_priv
-Add ability to disable ping reply in sandbox eth driver
-Add comments to priv struct definition
-Add documentation to the structures
-Add eth_get_ops helper
-Added comments to README.sandbox
-Added support for the 'lo' network interface
-Added testing for ethrotate
-Change -1 returns to error constants
-Change puts to printf
-Clean up the interface to sandbox's eth-raw-os by passing priv to raw-os
-Cleaned up sandbox EXTRA_ENV define
-Cleanup var definition order
-Fix compile regression in !DM_ETH case
-Fixed the MAC address limitation (now all traffic uses MAC address from env)
-Load from ethprime on eth_initialize()
-Move os file to arch
-Moved config to Kconfig
-New to v4
-Redo the seq / probe implementation
-Remove bd_t *bis from dm eth_ops init function
-Remove checks for driver==NULL
-Remove priv pointer in per-device priv struct (drivers already get their own directly from DM)
-Removed checks on priv != NULL and added protection in uclass instead
-Rename halt() to stop() in ops
-Rename init() to start() in ops
-Stop handling selecting a new "current" in pre-unbind as it will now work itself out by clearing the pointer
-Updated expected behavior based on changes to the NetLoop
-Use accessors for platdata and priv
-Use only the seq from DM to find aliases

Changes in v3:
--Fail init if not activated
--Fail probe if ethaddr not set
-Added 2 more ethaddr to sandbox
-Added dm eth testing
-Added support for aliases
-Added support for ethprime
-Added testing for netretry
-Allow current eth dev to be NULL
-Correct failure chaining from bind to probe to init
-Correct the pre_unbind logic
-Fixed blank line formatting for variable declaration
-Made the os raw packet support for sandbox eth build and work.
-Move the get_dev_by_* protos to also be !DM_ETH like the impl
-Prevent a crash if memory is not allocated
-Print which device in the debug write hwaddr
-Reorder dm test makefile
-Update ethaddr from env unconditionally on init
-Use set current to select the current device regardless of the previous selection

Changes in v2:
-Added the raw packet proof-of-concept patch.
-Cause an invalid name to fail binding
-Change printfs to debug in sandbox driver
-Changed eth_uclass_priv local var names to be uc_priv
-Move fake hwaddr to the device tree
-Move static data to priv
-Move the hwaddr to platdata so that its memory is allocated at bind when we need it
-Prevent device from being probed before used by a command (i.e. before eth_init()).
-Rebase on top of dm/master
-Remove unused priv struct for sandbox driver
-Removed extra parentheses
-Stop maintaining our own index and use DM seq now that it works for our needs
-Update error codes
-Updated comments

Joe Hershberger (27):
  test: dm: Reorder the objects to build
  common: Make sure arch-specific map_sysmem() is defined
  net: Provide a function to get the current MAC address
  net: Rename helper function to be more clear
  net: Remove unneeded "extern" in net.h
  net: Refactor in preparation for driver model
  net: Change return codes from net/eth.c to use errorno constants
  net: Use int instead of u8 for boolean flag
  net: Remove the bd* parameter from net stack functions
  net: Make netretry actually do something
  net: Access mapped physmem in net functions
  cmd: net: Clean up return codes
  dm: eth: Add basic driver model support to Ethernet stack
  net: Clean up network stack names used in DM drivers
  dm: eth: Pass the packet pointer as a parameter to recv
  sandbox: eth: Add network support to sandbox
  sandbox: eth: Add ARP and PING response to sandbox driver
  test: dm: eth: Add tests for the eth dm implementation
  dm: eth: Add support for aliases
  dm: eth: Add support for ethprime env var
  test: dm: eth: Add testing for ethrotate env var
  sandbox: eth: Add ability to disable ping reply in sandbox eth driver
  test: dm: net: Add a test of the netretry behavior
  sandbox: eth: Add a bridge to a real network for sandbox
  sandbox: Enable DHCP and IP defrag
  sandbox: eth: Add support for using the 'lo' interface
  net: Improve error handling

 arch/arm/lib/bootm.c                  |   1 +
 arch/mips/mach-au1x00/au1x00_eth.c    |   2 +-
 arch/powerpc/cpu/mpc8260/ether_fcc.c  |   2 +-
 arch/powerpc/cpu/mpc85xx/ether_fcc.c  |   2 +-
 arch/powerpc/cpu/mpc8xx/scc.c         |   2 +-
 arch/sandbox/Kconfig                  |  12 +
 arch/sandbox/cpu/Makefile             |  10 +
 arch/sandbox/cpu/eth-raw-os.c         | 249 +++++++++++++++
 arch/sandbox/dts/sandbox.dts          |  21 ++
 arch/sandbox/include/asm/eth-raw-os.h |  40 +++
 arch/sandbox/include/asm/eth.h        |  15 +
 board/sandbox/README.sandbox          |  78 ++++-
 common/board_f.c                      |   1 +
 common/board_r.c                      |   3 +-
 common/bootm.c                        |   1 +
 common/cmd_bdinfo.c                   |   2 +
 common/cmd_bootm.c                    |   1 +
 common/cmd_demo.c                     |   1 +
 common/cmd_fat.c                      |   1 +
 common/cmd_fdt.c                      |   1 +
 common/cmd_lzmadec.c                  |   1 +
 common/cmd_md5sum.c                   |   1 +
 common/cmd_mem.c                      |   1 +
 common/cmd_net.c                      |  45 ++-
 common/cmd_nvedit.c                   |   1 +
 common/cmd_pxe.c                      |   1 +
 common/cmd_sf.c                       |   1 +
 common/cmd_source.c                   |   1 +
 common/cmd_trace.c                    |   1 +
 common/cmd_ximg.c                     |   1 +
 common/hash.c                         |   1 +
 common/image-fdt.c                    |   1 +
 common/image-fit.c                    |   1 +
 common/image.c                        |   1 +
 common/iotrace.c                      |   1 +
 common/lcd.c                          |   1 +
 common/malloc_simple.c                |   1 +
 doc/README.drivers.eth                |   6 +
 drivers/demo/demo-simple.c            |   1 +
 drivers/i2c/i2c-uniphier-f.c          |   1 +
 drivers/i2c/i2c-uniphier.c            |   1 +
 drivers/mtd/spi/sf_probe.c            |   1 +
 drivers/net/Kconfig                   |  42 +++
 drivers/net/Makefile                  |   2 +
 drivers/net/netconsole.c              |   4 +-
 drivers/net/sandbox-raw.c             | 165 ++++++++++
 drivers/net/sandbox.c                 | 201 ++++++++++++
 drivers/serial/ns16550.c              |   1 +
 drivers/serial/serial_uniphier.c      |   1 +
 fs/fs.c                               |   1 +
 include/common.h                      |  17 -
 include/configs/sandbox.h             |  25 +-
 include/dm/uclass-id.h                |   1 +
 include/mapmem.h                      |  32 ++
 include/net.h                         | 199 ++++++++----
 lib/trace.c                           |   1 +
 net/eth.c                             | 578 ++++++++++++++++++++++++++++++----
 net/net.c                             |  67 ++--
 net/nfs.c                             |   6 +-
 net/tftp.c                            |   6 +-
 test/compression.c                    |   1 +
 test/dm/Makefile                      |   5 +-
 test/dm/cmd_dm.c                      |   1 +
 test/dm/eth.c                         | 156 +++++++++
 test/dm/test.dts                      |  20 ++
 65 files changed, 1838 insertions(+), 210 deletions(-)
 create mode 100644 arch/sandbox/cpu/eth-raw-os.c
 create mode 100644 arch/sandbox/include/asm/eth-raw-os.h
 create mode 100644 arch/sandbox/include/asm/eth.h
 create mode 100644 drivers/net/sandbox-raw.c
 create mode 100644 drivers/net/sandbox.c
 create mode 100644 include/mapmem.h
 create mode 100644 test/dm/eth.c

-- 
1.7.11.5

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 01/27] test: dm: Reorder the objects to build
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
@ 2015-03-04  2:40         ` Joe Hershberger
  2015-03-04  2:40         ` [U-Boot] [PATCH v5 02/27] common: Make sure arch-specific map_sysmem() is defined Joe Hershberger
                           ` (26 subsequent siblings)
  27 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:40 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Acked-by: Simon Glass <sjg@chromium.org>

---

Changes in v5: None
Changes in v4: None
Changes in v3:
-Reorder dm test makefile

Changes in v2: None

 test/dm/Makefile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/dm/Makefile b/test/dm/Makefile
index 612aa95..1d9148f 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -18,7 +18,7 @@ obj-$(CONFIG_DM_TEST) += core.o
 obj-$(CONFIG_DM_TEST) += ut.o
 ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_DM_GPIO) += gpio.o
-obj-$(CONFIG_DM_SPI) += spi.o
-obj-$(CONFIG_DM_SPI_FLASH) += sf.o
 obj-$(CONFIG_DM_I2C) += i2c.o
+obj-$(CONFIG_DM_SPI_FLASH) += sf.o
+obj-$(CONFIG_DM_SPI) += spi.o
 endif
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 02/27] common: Make sure arch-specific map_sysmem() is defined
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
  2015-03-04  2:40         ` [U-Boot] [PATCH v5 01/27] test: dm: Reorder the objects to build Joe Hershberger
@ 2015-03-04  2:40         ` Joe Hershberger
  2015-03-04 19:18           ` Simon Glass
  2015-03-04  2:40         ` [U-Boot] [PATCH v5 03/27] net: Provide a function to get the current MAC address Joe Hershberger
                           ` (25 subsequent siblings)
  27 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:40 UTC (permalink / raw)
  To: u-boot

In the case where the arch defines a custom map_sysmem(), make sure that
including just common.h is sufficient to have these functions as they
are when the arch does not override it.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v5:
-Moved to a separate header mapmem.h

Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 arch/arm/lib/bootm.c             |  1 +
 common/board_f.c                 |  1 +
 common/board_r.c                 |  1 +
 common/bootm.c                   |  1 +
 common/cmd_bootm.c               |  1 +
 common/cmd_demo.c                |  1 +
 common/cmd_fat.c                 |  1 +
 common/cmd_fdt.c                 |  1 +
 common/cmd_lzmadec.c             |  1 +
 common/cmd_md5sum.c              |  1 +
 common/cmd_mem.c                 |  1 +
 common/cmd_nvedit.c              |  1 +
 common/cmd_pxe.c                 |  1 +
 common/cmd_sf.c                  |  1 +
 common/cmd_source.c              |  1 +
 common/cmd_trace.c               |  1 +
 common/cmd_ximg.c                |  1 +
 common/hash.c                    |  1 +
 common/image-fdt.c               |  1 +
 common/image-fit.c               |  1 +
 common/image.c                   |  1 +
 common/iotrace.c                 |  1 +
 common/lcd.c                     |  1 +
 common/malloc_simple.c           |  1 +
 drivers/demo/demo-simple.c       |  1 +
 drivers/i2c/i2c-uniphier-f.c     |  1 +
 drivers/i2c/i2c-uniphier.c       |  1 +
 drivers/mtd/spi/sf_probe.c       |  1 +
 drivers/serial/ns16550.c         |  1 +
 drivers/serial/serial_uniphier.c |  1 +
 fs/fs.c                          |  1 +
 include/common.h                 | 17 -----------------
 include/mapmem.h                 | 32 ++++++++++++++++++++++++++++++++
 lib/trace.c                      |  1 +
 test/compression.c               |  1 +
 test/dm/cmd_dm.c                 |  1 +
 36 files changed, 66 insertions(+), 17 deletions(-)
 create mode 100644 include/mapmem.h

diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 0c1298a..42b052c 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -18,6 +18,7 @@
 #include <u-boot/zlib.h>
 #include <asm/byteorder.h>
 #include <libfdt.h>
+#include <mapmem.h>
 #include <fdt_support.h>
 #include <asm/bootm.h>
 #include <asm/secure.h>
diff --git a/common/board_f.c b/common/board_f.c
index 4d8b8a6..1b7e7d9 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -23,6 +23,7 @@
 #include <i2c.h>
 #include <initcall.h>
 #include <logbuff.h>
+#include <mapmem.h>
 
 /* TODO: Can we move these into arch/ headers? */
 #ifdef CONFIG_8xx
diff --git a/common/board_r.c b/common/board_r.c
index 4fcd4f6..af0f274 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -33,6 +33,7 @@
 #endif
 #include <logbuff.h>
 #include <malloc.h>
+#include <mapmem.h>
 #ifdef CONFIG_BITBANGMII
 #include <miiphy.h>
 #endif
diff --git a/common/bootm.c b/common/bootm.c
index 34f60bb..6842029 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -13,6 +13,7 @@
 #include <fdt_support.h>
 #include <lmb.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <asm/io.h>
 #include <linux/lzo.h>
 #include <lzma/LzmaTypes.h>
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index 48199bf..b3d3968 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -16,6 +16,7 @@
 #include <image.h>
 #include <lmb.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <nand.h>
 #include <asm/byteorder.h>
 #include <linux/compiler.h>
diff --git a/common/cmd_demo.c b/common/cmd_demo.c
index 8a10bdf..209dc4a 100644
--- a/common/cmd_demo.c
+++ b/common/cmd_demo.c
@@ -9,6 +9,7 @@
 
 #include <common.h>
 #include <dm-demo.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 struct udevice *demo_dev;
diff --git a/common/cmd_fat.c b/common/cmd_fat.c
index c00fb28..aae993d 100644
--- a/common/cmd_fat.c
+++ b/common/cmd_fat.c
@@ -14,6 +14,7 @@
 #include <net.h>
 #include <ata.h>
 #include <asm/io.h>
+#include <mapmem.h>
 #include <part.h>
 #include <fat.h>
 #include <fs.h>
diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c
index 48b3e70..682b655 100644
--- a/common/cmd_fdt.c
+++ b/common/cmd_fdt.c
@@ -15,6 +15,7 @@
 #include <asm/global_data.h>
 #include <libfdt.h>
 #include <fdt_support.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 #define MAX_LEVEL	32		/* how deeply nested we will go */
diff --git a/common/cmd_lzmadec.c b/common/cmd_lzmadec.c
index 7b0b3fd..1ad9ed6 100644
--- a/common/cmd_lzmadec.c
+++ b/common/cmd_lzmadec.c
@@ -12,6 +12,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 #include <lzma/LzmaTools.h>
diff --git a/common/cmd_md5sum.c b/common/cmd_md5sum.c
index d22ace5..23bb81e 100644
--- a/common/cmd_md5sum.c
+++ b/common/cmd_md5sum.c
@@ -10,6 +10,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <mapmem.h>
 #include <u-boot/md5.h>
 #include <asm/io.h>
 
diff --git a/common/cmd_mem.c b/common/cmd_mem.c
index bcb3ee3..66a41da 100644
--- a/common/cmd_mem.c
+++ b/common/cmd_mem.c
@@ -20,6 +20,7 @@
 #endif
 #include <hash.h>
 #include <inttypes.h>
+#include <mapmem.h>
 #include <watchdog.h>
 #include <asm/io.h>
 #include <linux/compiler.h>
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 855808c..be792ae 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -31,6 +31,7 @@
 #include <search.h>
 #include <errno.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <watchdog.h>
 #include <linux/stddef.h>
 #include <asm/byteorder.h>
diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c
index 7e32c95..96f963d 100644
--- a/common/cmd_pxe.c
+++ b/common/cmd_pxe.c
@@ -8,6 +8,7 @@
 #include <common.h>
 #include <command.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <errno.h>
diff --git a/common/cmd_sf.c b/common/cmd_sf.c
index 5c788e9..01c37de 100644
--- a/common/cmd_sf.c
+++ b/common/cmd_sf.c
@@ -10,6 +10,7 @@
 #include <div64.h>
 #include <dm.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <spi.h>
 #include <spi_flash.h>
 
diff --git a/common/cmd_source.c b/common/cmd_source.c
index 6881bc9..d2a881d 100644
--- a/common/cmd_source.c
+++ b/common/cmd_source.c
@@ -19,6 +19,7 @@
 #include <command.h>
 #include <image.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #if defined(CONFIG_8xx)
diff --git a/common/cmd_trace.c b/common/cmd_trace.c
index 8c630e6..1e62a1a 100644
--- a/common/cmd_trace.c
+++ b/common/cmd_trace.c
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <mapmem.h>
 #include <trace.h>
 #include <asm/io.h>
 
diff --git a/common/cmd_ximg.c b/common/cmd_ximg.c
index 64b9186..8b8645c 100644
--- a/common/cmd_ximg.c
+++ b/common/cmd_ximg.c
@@ -15,6 +15,7 @@
 #include <common.h>
 #include <command.h>
 #include <image.h>
+#include <mapmem.h>
 #include <watchdog.h>
 #if defined(CONFIG_BZIP2)
 #include <bzlib.h>
diff --git a/common/hash.c b/common/hash.c
index d154d02..b4e3e80 100644
--- a/common/hash.c
+++ b/common/hash.c
@@ -14,6 +14,7 @@
 #include <common.h>
 #include <command.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <hw_sha.h>
 #include <asm/io.h>
 #include <asm/errno.h>
diff --git a/common/image-fdt.c b/common/image-fdt.c
index d9e4728..7e2da7b 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -14,6 +14,7 @@
 #include <errno.h>
 #include <image.h>
 #include <libfdt.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 #ifndef CONFIG_SYS_FDT_PAD
diff --git a/common/image-fit.c b/common/image-fit.c
index 778d2a1..4eb4d42 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -16,6 +16,7 @@
 #else
 #include <common.h>
 #include <errno.h>
+#include <mapmem.h>
 #include <asm/io.h>
 DECLARE_GLOBAL_DATA_PTR;
 #endif /* !USE_HOSTCC*/
diff --git a/common/image.c b/common/image.c
index a911aa9..f3277c9 100644
--- a/common/image.c
+++ b/common/image.c
@@ -27,6 +27,7 @@
 
 #include <environment.h>
 #include <image.h>
+#include <mapmem.h>
 
 #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
 #include <libfdt.h>
diff --git a/common/iotrace.c b/common/iotrace.c
index ced426e..2725563 100644
--- a/common/iotrace.c
+++ b/common/iotrace.c
@@ -7,6 +7,7 @@
 #define IOTRACE_IMPL
 
 #include <common.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 DECLARE_GLOBAL_DATA_PTR;
diff --git a/common/lcd.c b/common/lcd.c
index f33942c..6982759 100644
--- a/common/lcd.c
+++ b/common/lcd.c
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <stdio_dev.h>
 #include <lcd.h>
+#include <mapmem.h>
 #include <watchdog.h>
 #include <asm/unaligned.h>
 #include <splash.h>
diff --git a/common/malloc_simple.c b/common/malloc_simple.c
index 64ae036..d445199 100644
--- a/common/malloc_simple.c
+++ b/common/malloc_simple.c
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 DECLARE_GLOBAL_DATA_PTR;
diff --git a/drivers/demo/demo-simple.c b/drivers/demo/demo-simple.c
index 2bcb7df..f069748 100644
--- a/drivers/demo/demo-simple.c
+++ b/drivers/demo/demo-simple.c
@@ -10,6 +10,7 @@
 #include <common.h>
 #include <dm.h>
 #include <dm-demo.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 static int simple_hello(struct udevice *dev, int ch)
diff --git a/drivers/i2c/i2c-uniphier-f.c b/drivers/i2c/i2c-uniphier-f.c
index 6707edd..ffa6ce5 100644
--- a/drivers/i2c/i2c-uniphier-f.c
+++ b/drivers/i2c/i2c-uniphier-f.c
@@ -13,6 +13,7 @@
 #include <dm/root.h>
 #include <i2c.h>
 #include <fdtdec.h>
+#include <mapmem.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
diff --git a/drivers/i2c/i2c-uniphier.c b/drivers/i2c/i2c-uniphier.c
index 64a9ed8..760457f 100644
--- a/drivers/i2c/i2c-uniphier.c
+++ b/drivers/i2c/i2c-uniphier.c
@@ -13,6 +13,7 @@
 #include <dm/root.h>
 #include <i2c.h>
 #include <fdtdec.h>
+#include <mapmem.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 4103723..ffc4caa 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -13,6 +13,7 @@
 #include <errno.h>
 #include <fdtdec.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <spi.h>
 #include <spi_flash.h>
 #include <asm/io.h>
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index eb00f1c..61b36b6 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -8,6 +8,7 @@
 #include <dm.h>
 #include <errno.h>
 #include <fdtdec.h>
+#include <mapmem.h>
 #include <ns16550.h>
 #include <serial.h>
 #include <watchdog.h>
diff --git a/drivers/serial/serial_uniphier.c b/drivers/serial/serial_uniphier.c
index e8a1608..d36d20d 100644
--- a/drivers/serial/serial_uniphier.c
+++ b/drivers/serial/serial_uniphier.c
@@ -10,6 +10,7 @@
 #include <asm/errno.h>
 #include <dm/device.h>
 #include <dm/platform_data/serial-uniphier.h>
+#include <mapmem.h>
 #include <serial.h>
 #include <fdtdec.h>
 
diff --git a/fs/fs.c b/fs/fs.c
index 483273f..ac0897d 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -17,6 +17,7 @@
 #include <config.h>
 #include <errno.h>
 #include <common.h>
+#include <mapmem.h>
 #include <part.h>
 #include <ext4fs.h>
 #include <fat.h>
diff --git a/include/common.h b/include/common.h
index 77c55c6..3ccc6f3 100644
--- a/include/common.h
+++ b/include/common.h
@@ -845,23 +845,6 @@ int cpu_disable(int nr);
 int cpu_release(int nr, int argc, char * const argv[]);
 #endif
 
-/* Define a null map_sysmem() if the architecture doesn't use it */
-# ifndef CONFIG_ARCH_MAP_SYSMEM
-static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
-{
-	return (void *)(uintptr_t)paddr;
-}
-
-static inline void unmap_sysmem(const void *vaddr)
-{
-}
-
-static inline phys_addr_t map_to_sysmem(const void *ptr)
-{
-	return (phys_addr_t)(uintptr_t)ptr;
-}
-# endif
-
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_PPC
diff --git a/include/mapmem.h b/include/mapmem.h
new file mode 100644
index 0000000..42ef3e8
--- /dev/null
+++ b/include/mapmem.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef __MAPMEM_H
+#define __MAPMEM_H
+
+/* Define a null map_sysmem() if the architecture doesn't use it */
+# ifdef CONFIG_ARCH_MAP_SYSMEM
+#include <asm/io.h>
+# else
+static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
+{
+	return (void *)(uintptr_t)paddr;
+}
+
+static inline void unmap_sysmem(const void *vaddr)
+{
+}
+
+static inline phys_addr_t map_to_sysmem(const void *ptr)
+{
+	return (phys_addr_t)(uintptr_t)ptr;
+}
+# endif
+
+#endif /* __MAPMEM_H */
diff --git a/lib/trace.c b/lib/trace.c
index 711e5b5..ad5e07b 100644
--- a/lib/trace.c
+++ b/lib/trace.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <mapmem.h>
 #include <trace.h>
 #include <asm/io.h>
 #include <asm/sections.h>
diff --git a/test/compression.c b/test/compression.c
index ea2e4ad..7ef3a8c 100644
--- a/test/compression.c
+++ b/test/compression.c
@@ -10,6 +10,7 @@
 #include <bootm.h>
 #include <command.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 #include <u-boot/zlib.h>
diff --git a/test/dm/cmd_dm.c b/test/dm/cmd_dm.c
index 79a674e..195815e 100644
--- a/test/dm/cmd_dm.c
+++ b/test/dm/cmd_dm.c
@@ -10,6 +10,7 @@
 #include <common.h>
 #include <dm.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <errno.h>
 #include <asm/io.h>
 #include <dm/root.h>
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 03/27] net: Provide a function to get the current MAC address
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
  2015-03-04  2:40         ` [U-Boot] [PATCH v5 01/27] test: dm: Reorder the objects to build Joe Hershberger
  2015-03-04  2:40         ` [U-Boot] [PATCH v5 02/27] common: Make sure arch-specific map_sysmem() is defined Joe Hershberger
@ 2015-03-04  2:40         ` Joe Hershberger
  2015-03-04  2:40         ` [U-Boot] [PATCH v5 04/27] net: Rename helper function to be more clear Joe Hershberger
                           ` (24 subsequent siblings)
  27 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:40 UTC (permalink / raw)
  To: u-boot

The current implementation exposes the eth_device struct to code that
needs to access the MAC address.  Add a wrapper function for this to
abstract away the pointer for this operation.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 arch/mips/mach-au1x00/au1x00_eth.c   | 2 +-
 arch/powerpc/cpu/mpc8260/ether_fcc.c | 2 +-
 arch/powerpc/cpu/mpc85xx/ether_fcc.c | 2 +-
 arch/powerpc/cpu/mpc8xx/scc.c        | 2 +-
 include/net.h                        | 8 ++++++++
 net/net.c                            | 2 +-
 6 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/arch/mips/mach-au1x00/au1x00_eth.c b/arch/mips/mach-au1x00/au1x00_eth.c
index 39c5b6b..a47f088 100644
--- a/arch/mips/mach-au1x00/au1x00_eth.c
+++ b/arch/mips/mach-au1x00/au1x00_eth.c
@@ -238,7 +238,7 @@ static int au1x00_init(struct eth_device* dev, bd_t * bd){
 	}
 
 	/* Put mac addr in little endian */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
 	*mac_addr_high	=	(ea[5] <<  8) | (ea[4]	    ) ;
 	*mac_addr_low	=	(ea[3] << 24) | (ea[2] << 16) |
 		(ea[1] <<  8) | (ea[0]	    ) ;
diff --git a/arch/powerpc/cpu/mpc8260/ether_fcc.c b/arch/powerpc/cpu/mpc8260/ether_fcc.c
index f9f15b5..f777ba1 100644
--- a/arch/powerpc/cpu/mpc8260/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc8260/ether_fcc.c
@@ -299,7 +299,7 @@ static int fec_init(struct eth_device* dev, bd_t *bis)
      * it unique by setting a few bits in the upper byte of the
      * non-static part of the address.
      */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
     pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
     pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
     pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/arch/powerpc/cpu/mpc85xx/ether_fcc.c b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
index 166dc9e..58d4bfb 100644
--- a/arch/powerpc/cpu/mpc85xx/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
@@ -338,7 +338,7 @@ static int fec_init(struct eth_device* dev, bd_t *bis)
      * it unique by setting a few bits in the upper byte of the
      * non-static part of the address.
      */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
     pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
     pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
     pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/arch/powerpc/cpu/mpc8xx/scc.c b/arch/powerpc/cpu/mpc8xx/scc.c
index 251966b..66e4014 100644
--- a/arch/powerpc/cpu/mpc8xx/scc.c
+++ b/arch/powerpc/cpu/mpc8xx/scc.c
@@ -339,7 +339,7 @@ static int scc_init (struct eth_device *dev, bd_t * bis)
 	pram_ptr->sen_gaddr3 = 0x0;	/* Group Address Filter 3 (unused) */
 	pram_ptr->sen_gaddr4 = 0x0;	/* Group Address Filter 4 (unused) */
 
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
 	pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4];
 	pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2];
 	pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/include/net.h b/include/net.h
index 43e3d28..6c76976 100644
--- a/include/net.h
+++ b/include/net.h
@@ -111,6 +111,14 @@ struct eth_device *eth_get_dev(void)
 {
 	return eth_current;
 }
+
+static inline unsigned char *eth_get_ethaddr(void)
+{
+	if (eth_current)
+		return eth_current->enetaddr;
+	return NULL;
+}
+
 extern struct eth_device *eth_get_dev_by_name(const char *devname);
 extern struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
 extern int eth_get_dev_index(void);		/* get the device index */
diff --git a/net/net.c b/net/net.c
index b60ce62..4b3c90e 100644
--- a/net/net.c
+++ b/net/net.c
@@ -275,7 +275,7 @@ static void NetInitLoop(void)
 		env_changed_id = env_id;
 	}
 	if (eth_get_dev())
-		memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
+		memcpy(NetOurEther, eth_get_ethaddr(), 6);
 
 	return;
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 04/27] net: Rename helper function to be more clear
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (2 preceding siblings ...)
  2015-03-04  2:40         ` [U-Boot] [PATCH v5 03/27] net: Provide a function to get the current MAC address Joe Hershberger
@ 2015-03-04  2:40         ` Joe Hershberger
  2015-03-04  2:40         ` [U-Boot] [PATCH v5 05/27] net: Remove unneeded "extern" in net.h Joe Hershberger
                           ` (23 subsequent siblings)
  27 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:40 UTC (permalink / raw)
  To: u-boot

Make it clear that the helper is checking the addr, not setting it.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 net/eth.c | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/net/eth.c b/net/eth.c
index eac4f7b..65e8c77 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -153,11 +153,6 @@ static void eth_current_changed(void)
 		setenv("ethact", NULL);
 }
 
-static int eth_address_set(unsigned char *addr)
-{
-	return memcmp(addr, "\0\0\0\0\0\0", 6);
-}
-
 int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		   int eth_number)
 {
@@ -166,9 +161,9 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 
 	eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
 
-	if (eth_address_set(env_enetaddr)) {
-		if (eth_address_set(dev->enetaddr) &&
-				memcmp(dev->enetaddr, env_enetaddr, 6)) {
+	if (!is_zero_ether_addr(env_enetaddr)) {
+		if (!is_zero_ether_addr(dev->enetaddr) &&
+		    memcmp(dev->enetaddr, env_enetaddr, 6)) {
 			printf("\nWarning: %s MAC addresses don't match:\n",
 				dev->name);
 			printf("Address in SROM is         %pM\n",
@@ -183,7 +178,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 					     dev->enetaddr);
 		printf("\nWarning: %s using MAC address from net device\n",
 			dev->name);
-	} else if (!(eth_address_set(dev->enetaddr))) {
+	} else if (is_zero_ether_addr(dev->enetaddr)) {
 		printf("\nError: %s address not set.\n",
 		       dev->name);
 		return -EINVAL;
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 05/27] net: Remove unneeded "extern" in net.h
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (3 preceding siblings ...)
  2015-03-04  2:40         ` [U-Boot] [PATCH v5 04/27] net: Rename helper function to be more clear Joe Hershberger
@ 2015-03-04  2:40         ` Joe Hershberger
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 06/27] net: Refactor in preparation for driver model Joe Hershberger
                           ` (22 subsequent siblings)
  27 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:40 UTC (permalink / raw)
  To: u-boot

Many of the functions in net.h were preceded extern needlessly. Removing
them to limit the number of checkpatch.pl complaints.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/net.h | 92 +++++++++++++++++++++++++++++------------------------------
 1 file changed, 46 insertions(+), 46 deletions(-)

diff --git a/include/net.h b/include/net.h
index 6c76976..b82a29d 100644
--- a/include/net.h
+++ b/include/net.h
@@ -97,11 +97,11 @@ struct eth_device {
 	void *priv;
 };
 
-extern int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
-extern int eth_register(struct eth_device* dev);/* Register network device */
-extern int eth_unregister(struct eth_device *dev);/* Remove network device */
-extern void eth_try_another(int first_restart);	/* Change the device */
-extern void eth_set_current(void);		/* set nterface to ethcur var */
+int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
+int eth_register(struct eth_device *dev);/* Register network device */
+int eth_unregister(struct eth_device *dev);/* Remove network device */
+void eth_try_another(int first_restart);	/* Change the device */
+void eth_set_current(void);		/* set nterface to ethcur var */
 
 /* get the current device MAC */
 extern struct eth_device *eth_current;
@@ -119,12 +119,12 @@ static inline unsigned char *eth_get_ethaddr(void)
 	return NULL;
 }
 
-extern struct eth_device *eth_get_dev_by_name(const char *devname);
-extern struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
-extern int eth_get_dev_index(void);		/* get the device index */
-extern void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
-extern int eth_getenv_enetaddr(char *name, uchar *enetaddr);
-extern int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
+struct eth_device *eth_get_dev_by_name(const char *devname);
+struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
+int eth_get_dev_index(void);		/* get the device index */
+void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
+int eth_getenv_enetaddr(char *name, uchar *enetaddr);
+int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 
 /*
  * Get the hardware address for an ethernet interface .
@@ -135,20 +135,20 @@ extern int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
  * Returns:
  *	Return true if the address is valid.
  */
-extern int eth_getenv_enetaddr_by_index(const char *base_name, int index,
-					uchar *enetaddr);
+int eth_getenv_enetaddr_by_index(const char *base_name, int index,
+				 uchar *enetaddr);
 
-extern int usb_eth_initialize(bd_t *bi);
-extern int eth_init(bd_t *bis);			/* Initialize the device */
-extern int eth_send(void *packet, int length);	   /* Send a packet */
+int usb_eth_initialize(bd_t *bi);
+int eth_init(bd_t *bis);			/* Initialize the device */
+int eth_send(void *packet, int length);	   /* Send a packet */
 
 #ifdef CONFIG_API
-extern int eth_receive(void *packet, int length); /* Receive a packet*/
-extern void (*push_packet)(void *packet, int length);
+int eth_receive(void *packet, int length); /* Receive a packet*/
+void (*push_packet)(void *packet, int length);
 #endif
-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 */
+int eth_rx(void);			/* Check for received packets */
+void eth_halt(void);			/* stop SCC */
+char *eth_get_name(void);		/* get name of current device */
 
 /* Set active state */
 static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
@@ -469,25 +469,25 @@ extern IPaddr_t Mcast_addr;
 #endif
 
 /* Initialize the network adapter */
-extern void net_init(void);
-extern int NetLoop(enum proto_t);
+void net_init(void);
+int NetLoop(enum proto_t);
 
 /* Shutdown adapters and cleanup */
-extern void	NetStop(void);
+void	NetStop(void);
 
 /* Load failed.	 Start again. */
-extern void	NetStartAgain(void);
+void	NetStartAgain(void);
 
 /* Get size of the ethernet header when we send */
-extern int	NetEthHdrSize(void);
+int	NetEthHdrSize(void);
 
 /* Set ethernet header; returns the size of the header */
-extern int NetSetEther(uchar *, uchar *, uint);
-extern int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot);
+int NetSetEther(uchar *, uchar *, uint);
+int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot);
 
 /* Set IP header */
-extern void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source);
-extern void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport,
+void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source);
+void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport,
 				int sport, int len);
 
 /**
@@ -521,12 +521,12 @@ unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new_sum);
 int ip_checksum_ok(const void *addr, unsigned nbytes);
 
 /* Callbacks */
-extern rxhand_f *net_get_udp_handler(void);	/* Get UDP RX packet handler */
-extern void net_set_udp_handler(rxhand_f *);	/* Set UDP RX packet handler */
-extern rxhand_f *net_get_arp_handler(void);	/* Get ARP RX packet handler */
-extern void net_set_arp_handler(rxhand_f *);	/* Set ARP RX packet handler */
-extern void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
-extern void	NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
+rxhand_f *net_get_udp_handler(void);	/* Get UDP RX packet handler */
+void net_set_udp_handler(rxhand_f *);	/* Set UDP RX packet handler */
+rxhand_f *net_get_arp_handler(void);	/* Get ARP RX packet handler */
+void net_set_arp_handler(rxhand_f *);	/* Set ARP RX packet handler */
+void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
+void	NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
 
 /* Network loop state */
 enum net_loop_state {
@@ -559,11 +559,11 @@ static inline void NetSendPacket(uchar *pkt, int len)
  * @param sport Source UDP port
  * @param payload_len Length of data after the UDP header
  */
-extern int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport,
+int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport,
 			int sport, int payload_len);
 
 /* Processes a received packet */
-extern void NetReceive(uchar *, int);
+void NetReceive(uchar *, int);
 
 #ifdef CONFIG_NETCONSOLE
 void NcStart(void);
@@ -711,28 +711,28 @@ static inline void eth_random_addr(uchar *addr)
 }
 
 /* Convert an IP address to a string */
-extern void ip_to_string(IPaddr_t x, char *s);
+void ip_to_string(IPaddr_t x, char *s);
 
 /* Convert a string to ip address */
-extern IPaddr_t string_to_ip(const char *s);
+IPaddr_t string_to_ip(const char *s);
 
 /* Convert a VLAN id to a string */
-extern void VLAN_to_string(ushort x, char *s);
+void VLAN_to_string(ushort x, char *s);
 
 /* Convert a string to a vlan id */
-extern ushort string_to_VLAN(const char *s);
+ushort string_to_VLAN(const char *s);
 
 /* read a VLAN id from an environment variable */
-extern ushort getenv_VLAN(char *);
+ushort getenv_VLAN(char *);
 
 /* copy a filename (allow for "..." notation, limit length) */
-extern void copy_filename(char *dst, const char *src, int size);
+void copy_filename(char *dst, const char *src, int size);
 
 /* get a random source port */
-extern unsigned int random_port(void);
+unsigned int random_port(void);
 
 /* Update U-Boot over TFTP */
-extern int update_tftp(ulong addr);
+int update_tftp(ulong addr);
 
 /**********************************************************************/
 
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 06/27] net: Refactor in preparation for driver model
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (4 preceding siblings ...)
  2015-03-04  2:40         ` [U-Boot] [PATCH v5 05/27] net: Remove unneeded "extern" in net.h Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 07/27] net: Change return codes from net/eth.c to use errorno constants Joe Hershberger
                           ` (21 subsequent siblings)
  27 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

Move some things around and organize things so that the driver model
implementation will fit in more easily.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v5:
-Fixed warning from missing declaration

Changes in v4:
-Fix compile regression in !DM_ETH case

Changes in v3:
-Move the get_dev_by_* protos to also be !DM_ETH like the impl

Changes in v2: None

 include/net.h | 68 +++++++++++++++++++++++++-------------------------
 net/eth.c     | 79 ++++++++++++++++++++++++++++++++---------------------------
 2 files changed, 78 insertions(+), 69 deletions(-)

diff --git a/include/net.h b/include/net.h
index b82a29d..4cef00c 100644
--- a/include/net.h
+++ b/include/net.h
@@ -97,13 +97,9 @@ struct eth_device {
 	void *priv;
 };
 
-int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
 int eth_register(struct eth_device *dev);/* Register network device */
 int eth_unregister(struct eth_device *dev);/* Remove network device */
-void eth_try_another(int first_restart);	/* Change the device */
-void eth_set_current(void);		/* set nterface to ethcur var */
 
-/* get the current device MAC */
 extern struct eth_device *eth_current;
 
 static inline __attribute__((always_inline))
@@ -111,7 +107,10 @@ struct eth_device *eth_get_dev(void)
 {
 	return eth_current;
 }
+struct eth_device *eth_get_dev_by_name(const char *devname);
+struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
 
+/* get the current device MAC */
 static inline unsigned char *eth_get_ethaddr(void)
 {
 	if (eth_current)
@@ -119,8 +118,37 @@ static inline unsigned char *eth_get_ethaddr(void)
 	return NULL;
 }
 
-struct eth_device *eth_get_dev_by_name(const char *devname);
-struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
+/* Set active state */
+static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
+{
+	eth_get_dev()->state = ETH_STATE_ACTIVE;
+
+	return 0;
+}
+/* Set passive state */
+static inline __attribute__((always_inline)) void eth_halt_state_only(void)
+{
+	eth_get_dev()->state = ETH_STATE_PASSIVE;
+}
+
+/*
+ * Set the hardware address for an ethernet interface based on 'eth%daddr'
+ * environment variable (or just 'ethaddr' if eth_number is 0).
+ * Args:
+ *	base_name - base name for device (normally "eth")
+ *	eth_number - value of %d (0 for first device of this type)
+ * Returns:
+ *	0 is success, non-zero is error status from driver.
+ */
+int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
+		     int eth_number);
+
+int usb_eth_initialize(bd_t *bi);
+
+int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
+void eth_try_another(int first_restart);	/* Change the device */
+void eth_set_current(void);		/* set nterface to ethcur var */
+
 int eth_get_dev_index(void);		/* get the device index */
 void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
 int eth_getenv_enetaddr(char *name, uchar *enetaddr);
@@ -138,7 +166,6 @@ int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 int eth_getenv_enetaddr_by_index(const char *base_name, int index,
 				 uchar *enetaddr);
 
-int usb_eth_initialize(bd_t *bi);
 int eth_init(bd_t *bis);			/* Initialize the device */
 int eth_send(void *packet, int length);	   /* Send a packet */
 
@@ -148,32 +175,7 @@ void (*push_packet)(void *packet, int length);
 #endif
 int eth_rx(void);			/* Check for received packets */
 void eth_halt(void);			/* stop SCC */
-char *eth_get_name(void);		/* get name of current device */
-
-/* Set active state */
-static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
-{
-	eth_get_dev()->state = ETH_STATE_ACTIVE;
-
-	return 0;
-}
-/* Set passive state */
-static inline __attribute__((always_inline)) void eth_halt_state_only(void)
-{
-	eth_get_dev()->state = ETH_STATE_PASSIVE;
-}
-
-/*
- * Set the hardware address for an ethernet interface based on 'eth%daddr'
- * environment variable (or just 'ethaddr' if eth_number is 0).
- * Args:
- *	base_name - base name for device (normally "eth")
- *	eth_number - value of %d (0 for first device of this type)
- * Returns:
- *	0 is success, non-zero is error status from driver.
- */
-int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
-		     int eth_number);
+const char *eth_get_name(void);		/* get name of current device */
 
 #ifdef CONFIG_MCAST_TFTP
 int eth_mcast_join(IPaddr_t mcast_addr, u8 join);
diff --git a/net/eth.c b/net/eth.c
index 65e8c77..84919e0 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -55,6 +55,14 @@ static inline int eth_setenv_enetaddr_by_index(const char *base_name, int index,
 	return eth_setenv_enetaddr(enetvar, enetaddr);
 }
 
+static void eth_env_init(void)
+{
+	const char *s;
+
+	s = getenv("bootfile");
+	if (s != NULL)
+		copy_filename(BootFile, s, sizeof(BootFile));
+}
 
 static int eth_mac_skip(int index)
 {
@@ -64,6 +72,8 @@ static int eth_mac_skip(int index)
 	return ((skip_state = getenv(enetvar)) != NULL);
 }
 
+static void eth_current_changed(void);
+
 /*
  * CPU and board-specific Ethernet initializations.  Aliased function
  * signals caller to move on
@@ -87,6 +97,11 @@ static unsigned int eth_rcv_current, eth_rcv_last;
 static struct eth_device *eth_devices;
 struct eth_device *eth_current;
 
+static void eth_set_current_to_next(void)
+{
+	eth_current = eth_current->next;
+}
+
 struct eth_device *eth_get_dev_by_name(const char *devname)
 {
 	struct eth_device *dev, *target_dev;
@@ -137,22 +152,6 @@ int eth_get_dev_index(void)
 	return eth_current->index;
 }
 
-static void eth_current_changed(void)
-{
-	char *act = getenv("ethact");
-	/* update current ethernet name */
-	if (eth_current) {
-		if (act == NULL || strcmp(act, eth_current->name) != 0)
-			setenv("ethact", eth_current->name);
-	}
-	/*
-	 * remove the variable completely if there is no active
-	 * interface
-	 */
-	else if (act != NULL)
-		setenv("ethact", NULL);
-}
-
 int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		   int eth_number)
 {
@@ -251,14 +250,6 @@ int eth_unregister(struct eth_device *dev)
 	return 0;
 }
 
-static void eth_env_init(bd_t *bis)
-{
-	const char *s;
-
-	if ((s = getenv("bootfile")) != NULL)
-		copy_filename(BootFile, s, sizeof(BootFile));
-}
-
 int eth_initialize(bd_t *bis)
 {
 	int num_devices = 0;
@@ -274,7 +265,7 @@ int eth_initialize(bd_t *bis)
 	phy_init();
 #endif
 
-	eth_env_init(bis);
+	eth_env_init();
 
 	/*
 	 * If board-specific initialization exists, call it.
@@ -479,6 +470,22 @@ int eth_receive(void *packet, int length)
 }
 #endif /* CONFIG_API */
 
+static void eth_current_changed(void)
+{
+	char *act = getenv("ethact");
+	/* update current ethernet name */
+	if (eth_get_dev()) {
+		if (act == NULL || strcmp(act, eth_get_name()) != 0)
+			setenv("ethact", eth_get_name());
+	}
+	/*
+	 * remove the variable completely if there is no active
+	 * interface
+	 */
+	else if (act != NULL)
+		setenv("ethact", NULL);
+}
+
 void eth_try_another(int first_restart)
 {
 	static struct eth_device *first_failed;
@@ -492,17 +499,17 @@ void eth_try_another(int first_restart)
 	if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
 		return;
 
-	if (!eth_current)
+	if (!eth_get_dev())
 		return;
 
 	if (first_restart)
-		first_failed = eth_current;
+		first_failed = eth_get_dev();
 
-	eth_current = eth_current->next;
+	eth_set_current_to_next();
 
 	eth_current_changed();
 
-	if (first_failed == eth_current)
+	if (first_failed == eth_get_dev())
 		NetRestartWrap = 1;
 }
 
@@ -513,7 +520,7 @@ void eth_set_current(void)
 	struct eth_device *old_current;
 	int	env_id;
 
-	if (!eth_current)	/* XXX no current */
+	if (!eth_get_dev())	/* XXX no current */
 		return;
 
 	env_id = get_env_id();
@@ -522,18 +529,18 @@ void eth_set_current(void)
 		env_changed_id = env_id;
 	}
 	if (act != NULL) {
-		old_current = eth_current;
+		old_current = eth_get_dev();
 		do {
-			if (strcmp(eth_current->name, act) == 0)
+			if (strcmp(eth_get_name(), act) == 0)
 				return;
-			eth_current = eth_current->next;
-		} while (old_current != eth_current);
+			eth_set_current_to_next();
+		} while (old_current != eth_get_dev());
 	}
 
 	eth_current_changed();
 }
 
-char *eth_get_name(void)
+const char *eth_get_name(void)
 {
-	return eth_current ? eth_current->name : "unknown";
+	return eth_get_dev() ? eth_get_dev()->name : "unknown";
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 07/27] net: Change return codes from net/eth.c to use errorno constants
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (5 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 06/27] net: Refactor in preparation for driver model Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 08/27] net: Use int instead of u8 for boolean flag Joe Hershberger
                           ` (20 subsequent siblings)
  27 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

Many functions returned -1 previously. Change them to return appropriate error
codes.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reported-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v5: None
Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 net/eth.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/net/eth.c b/net/eth.c
index 84919e0..9ad15cd 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -227,7 +227,7 @@ int eth_unregister(struct eth_device *dev)
 
 	/* No device */
 	if (!eth_devices)
-		return -1;
+		return -ENODEV;
 
 	for (cur = eth_devices; cur->next != eth_devices && cur->next != dev;
 	     cur = cur->next)
@@ -235,7 +235,7 @@ int eth_unregister(struct eth_device *dev)
 
 	/* Device not found */
 	if (cur->next != dev)
-		return -1;
+		return -ENODEV;
 
 	cur->next = dev->next;
 
@@ -368,7 +368,7 @@ int eth_init(bd_t *bis)
 
 	if (!eth_current) {
 		puts("No ethernet found.\n");
-		return -1;
+		return -ENODEV;
 	}
 
 	/* Sync environment with network devices */
@@ -397,7 +397,7 @@ int eth_init(bd_t *bis)
 		eth_try_another(0);
 	} while (old_current != eth_current);
 
-	return -1;
+	return -ETIMEDOUT;
 }
 
 void eth_halt(void)
@@ -413,7 +413,7 @@ void eth_halt(void)
 int eth_send(void *packet, int length)
 {
 	if (!eth_current)
-		return -1;
+		return -ENODEV;
 
 	return eth_current->send(eth_current, packet, length);
 }
@@ -421,7 +421,7 @@ int eth_send(void *packet, int length)
 int eth_rx(void)
 {
 	if (!eth_current)
-		return -1;
+		return -ENODEV;
 
 	return eth_current->recv(eth_current);
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 08/27] net: Use int instead of u8 for boolean flag
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (6 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 07/27] net: Change return codes from net/eth.c to use errorno constants Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 09/27] net: Remove the bd* parameter from net stack functions Joe Hershberger
                           ` (19 subsequent siblings)
  27 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

On some archs masking the parameter is inefficient, so don't use u8.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reported-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v5: None
Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 include/net.h | 2 +-
 net/eth.c     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/net.h b/include/net.h
index 4cef00c..ad20145 100644
--- a/include/net.h
+++ b/include/net.h
@@ -178,7 +178,7 @@ void eth_halt(void);			/* stop SCC */
 const char *eth_get_name(void);		/* get name of current device */
 
 #ifdef CONFIG_MCAST_TFTP
-int eth_mcast_join(IPaddr_t mcast_addr, u8 join);
+int eth_mcast_join(IPaddr_t mcast_addr, int join);
 u32 ether_crc(size_t len, unsigned char const *p);
 #endif
 
diff --git a/net/eth.c b/net/eth.c
index 9ad15cd..b86994e 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -321,7 +321,7 @@ int eth_initialize(bd_t *bis)
  * mcast_addr: multicast ipaddr from which multicast Mac is made
  * join: 1=join, 0=leave.
  */
-int eth_mcast_join(IPaddr_t mcast_ip, u8 join)
+int eth_mcast_join(IPaddr_t mcast_ip, int join)
 {
 	u8 mcast_mac[6];
 	if (!eth_current || !eth_current->mcast)
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 09/27] net: Remove the bd* parameter from net stack functions
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (7 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 08/27] net: Use int instead of u8 for boolean flag Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 10/27] net: Make netretry actually do something Joe Hershberger
                           ` (18 subsequent siblings)
  27 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

This value is not used by the network stack and is available in the
global data, so stop passing it around.  For the one legacy function
that still expects it (init op on old Ethernet drivers) pass in the
global pointer version directly to avoid changing that interface.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reported-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v5: None
Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 common/board_r.c         |  2 +-
 drivers/net/netconsole.c |  4 ++--
 include/net.h            |  6 +++---
 net/eth.c                | 12 +++++++-----
 net/net.c                |  7 +++----
 5 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/common/board_r.c b/common/board_r.c
index af0f274..b882d9b 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -585,7 +585,7 @@ static int initr_bbmii(void)
 static int initr_net(void)
 {
 	puts("Net:   ");
-	eth_initialize(gd->bd);
+	eth_initialize();
 #if defined(CONFIG_RESET_PHY_R)
 	debug("Reset Ethernet PHY\n");
 	reset_phy();
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 677c89f..87cea7a 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -193,11 +193,11 @@ static void nc_send_packet(const char *buf, int len)
 
 	if (eth->state != ETH_STATE_ACTIVE) {
 		if (eth_is_on_demand_init()) {
-			if (eth_init(gd->bd) < 0)
+			if (eth_init() < 0)
 				return;
 			eth_set_last_protocol(NETCONS);
 		} else
-			eth_init_state_only(gd->bd);
+			eth_init_state_only();
 
 		inited = 1;
 	}
diff --git a/include/net.h b/include/net.h
index ad20145..10d38f8 100644
--- a/include/net.h
+++ b/include/net.h
@@ -119,7 +119,7 @@ static inline unsigned char *eth_get_ethaddr(void)
 }
 
 /* Set active state */
-static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
+static inline __attribute__((always_inline)) int eth_init_state_only(void)
 {
 	eth_get_dev()->state = ETH_STATE_ACTIVE;
 
@@ -145,7 +145,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 
 int usb_eth_initialize(bd_t *bi);
 
-int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
+int eth_initialize(void);		/* Initialize network subsystem */
 void eth_try_another(int first_restart);	/* Change the device */
 void eth_set_current(void);		/* set nterface to ethcur var */
 
@@ -166,7 +166,7 @@ int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 int eth_getenv_enetaddr_by_index(const char *base_name, int index,
 				 uchar *enetaddr);
 
-int eth_init(bd_t *bis);			/* Initialize the device */
+int eth_init(void);			/* Initialize the device */
 int eth_send(void *packet, int length);	   /* Send a packet */
 
 #ifdef CONFIG_API
diff --git a/net/eth.c b/net/eth.c
index b86994e..66ecb79 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -12,6 +12,8 @@
 #include <phy.h>
 #include <asm/errno.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 void eth_parse_enetaddr(const char *addr, uchar *enetaddr)
 {
 	char *end;
@@ -250,7 +252,7 @@ int eth_unregister(struct eth_device *dev)
 	return 0;
 }
 
-int eth_initialize(bd_t *bis)
+int eth_initialize(void)
 {
 	int num_devices = 0;
 	eth_devices = NULL;
@@ -272,10 +274,10 @@ int eth_initialize(bd_t *bis)
 	 * If not, call a CPU-specific one
 	 */
 	if (board_eth_init != __def_eth_init) {
-		if (board_eth_init(bis) < 0)
+		if (board_eth_init(gd->bd) < 0)
 			printf("Board Net Initialization Failed\n");
 	} else if (cpu_eth_init != __def_eth_init) {
-		if (cpu_eth_init(bis) < 0)
+		if (cpu_eth_init(gd->bd) < 0)
 			printf("CPU Net Initialization Failed\n");
 	} else
 		printf("Net Initialization Skipped\n");
@@ -362,7 +364,7 @@ u32 ether_crc(size_t len, unsigned char const *p)
 #endif
 
 
-int eth_init(bd_t *bis)
+int eth_init(void)
 {
 	struct eth_device *old_current, *dev;
 
@@ -387,7 +389,7 @@ int eth_init(bd_t *bis)
 	do {
 		debug("Trying %s\n", eth_current->name);
 
-		if (eth_current->init(eth_current, bis) >= 0) {
+		if (eth_current->init(eth_current, gd->bd) >= 0) {
 			eth_current->state = ETH_STATE_ACTIVE;
 
 			return 0;
diff --git a/net/net.c b/net/net.c
index 4b3c90e..e5ab07c 100644
--- a/net/net.c
+++ b/net/net.c
@@ -324,7 +324,6 @@ void net_init(void)
 
 int NetLoop(enum proto_t protocol)
 {
-	bd_t *bd = gd->bd;
 	int ret = -1;
 
 	NetRestarted = 0;
@@ -337,12 +336,12 @@ int NetLoop(enum proto_t protocol)
 	if (eth_is_on_demand_init() || protocol != NETCONS) {
 		eth_halt();
 		eth_set_current();
-		if (eth_init(bd) < 0) {
+		if (eth_init() < 0) {
 			eth_halt();
 			return -1;
 		}
 	} else
-		eth_init_state_only(bd);
+		eth_init_state_only();
 
 restart:
 #ifdef CONFIG_USB_KEYBOARD
@@ -618,7 +617,7 @@ void NetStartAgain(void)
 #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
 	eth_try_another(!NetRestarted);
 #endif
-	eth_init(gd->bd);
+	eth_init();
 	if (NetRestartWrap) {
 		NetRestartWrap = 0;
 		if (NetDevExists) {
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 10/27] net: Make netretry actually do something
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (8 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 09/27] net: Remove the bd* parameter from net stack functions Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 11/27] net: Access mapped physmem in net functions Joe Hershberger
                           ` (17 subsequent siblings)
  27 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

netretry previously would only retry in one specific case (your MAC
address is not set) and no other. This is basically useless. In the DM
implementation for eth it turns this into a completely useless case
since an un-configured MAC address results in not even entering the
NetLoop. The behavior is now changed to retry any failed command
(rotating through the eth adapters if ethrotate != no).

It also defaulted to retry forever. It is now changed to default to not
retry

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v5: None
Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 net/net.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/net/net.c b/net/net.c
index e5ab07c..37b4aab 100644
--- a/net/net.c
+++ b/net/net.c
@@ -527,6 +527,8 @@ restart:
 			(*x)();
 		}
 
+		if (net_state == NETLOOP_FAIL)
+			NetStartAgain();
 
 		switch (net_state) {
 
@@ -602,8 +604,10 @@ void NetStartAgain(void)
 			retrycnt = 1;
 		else
 			retrycnt = simple_strtoul(nretry, NULL, 0);
-	} else
-		retry_forever = 1;
+	} else {
+		retrycnt = 0;
+		retry_forever = 0;
+	}
 
 	if ((!retry_forever) && (NetTryCount >= retrycnt)) {
 		eth_halt();
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 11/27] net: Access mapped physmem in net functions
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (9 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 10/27] net: Make netretry actually do something Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04 18:34           ` Simon Glass
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 12/27] cmd: net: Clean up return codes Joe Hershberger
                           ` (16 subsequent siblings)
  27 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

Previously the net functions would access memory assuming physmem did
not need to be mapped.  In sandbox, that's not the case.

Now we map the physmem specified by the user in loadaddr to the buffer
that represents that space.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v5:
-Include new mapmem.h header
-Unmap memory for consistency

Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 net/nfs.c  | 6 +++++-
 net/tftp.c | 6 +++++-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/net/nfs.c b/net/nfs.c
index 381b75f..8e05ae5 100644
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -26,6 +26,7 @@
 #include <command.h>
 #include <net.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include "nfs.h"
 #include "bootp.h"
 
@@ -93,7 +94,10 @@ store_block(uchar *src, unsigned offset, unsigned len)
 	} else
 #endif /* CONFIG_SYS_DIRECT_FLASH_NFS */
 	{
-		(void)memcpy((void *)(load_addr + offset), src, len);
+		void *ptr = map_sysmem(load_addr + offset, len);
+
+		memcpy(ptr, src, len);
+		unmap_sysmem(ptr);
 	}
 
 	if (NetBootFileXferSize < (offset+len))
diff --git a/net/tftp.c b/net/tftp.c
index 0a2c533..51c67be 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <mapmem.h>
 #include <net.h>
 #include "tftp.h"
 #include "bootp.h"
@@ -184,7 +185,10 @@ store_block(int block, uchar *src, unsigned len)
 	} else
 #endif /* CONFIG_SYS_DIRECT_FLASH_TFTP */
 	{
-		(void)memcpy((void *)(load_addr + offset), src, len);
+		void *ptr = map_sysmem(load_addr + offset, len);
+
+		memcpy(ptr, src, len);
+		unmap_sysmem(ptr);
 	}
 #ifdef CONFIG_MCAST_TFTP
 	if (Multicast)
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 12/27] cmd: net: Clean up return codes
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (10 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 11/27] net: Access mapped physmem in net functions Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04 18:35           ` Simon Glass
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 13/27] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
                           ` (15 subsequent siblings)
  27 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

The return codes in common/cmd_net.c had a number of inconsistencies.
Update them to all use the enum from command.h

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v5:
-New to v5

Changes in v4: None
Changes in v3: None
Changes in v2: None

 common/cmd_net.c | 45 +++++++++++++++++++++------------------------
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/common/cmd_net.c b/common/cmd_net.c
index 09489d4..3f52edc 100644
--- a/common/cmd_net.c
+++ b/common/cmd_net.c
@@ -44,10 +44,7 @@ U_BOOT_CMD(
 #ifdef CONFIG_CMD_TFTPPUT
 int do_tftpput(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	int ret;
-
-	ret = netboot_common(TFTPPUT, cmdtp, argc, argv);
-	return ret;
+	return netboot_common(TFTPPUT, cmdtp, argc, argv);
 }
 
 U_BOOT_CMD(
@@ -217,7 +214,7 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 		if (strict_strtoul(argv[1], 16, &save_addr) < 0 ||
 			strict_strtoul(argv[2], 16, &save_size) < 0) {
 			printf("Invalid address/size\n");
-			return cmd_usage(cmdtp);
+			return CMD_RET_USAGE;
 		}
 		copy_filename(BootFile, argv[3], sizeof(BootFile));
 		break;
@@ -230,7 +227,7 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 
 	if ((size = NetLoop(proto)) < 0) {
 		bootstage_error(BOOTSTAGE_ID_NET_NETLOOP_OK);
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 	bootstage_mark(BOOTSTAGE_ID_NET_NETLOOP_OK);
 
@@ -240,7 +237,7 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 	/* done if no file was loaded (no errors though) */
 	if (size == 0) {
 		bootstage_error(BOOTSTAGE_ID_NET_LOADED);
-		return 0;
+		return CMD_RET_SUCCESS;
 	}
 
 	/* flush cache */
@@ -250,10 +247,10 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 
 	rcode = bootm_maybe_autostart(cmdtp, argv[0]);
 
-	if (rcode < 0)
-		bootstage_error(BOOTSTAGE_ID_NET_DONE_ERR);
-	else
+	if (rcode == CMD_RET_SUCCESS)
 		bootstage_mark(BOOTSTAGE_ID_NET_DONE);
+	else
+		bootstage_error(BOOTSTAGE_ID_NET_DONE_ERR);
 	return rcode;
 }
 
@@ -261,7 +258,7 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 static int do_ping(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	if (argc < 2)
-		return -1;
+		return CMD_RET_USAGE;
 
 	NetPingIP = string_to_ip(argv[1]);
 	if (NetPingIP == 0)
@@ -269,12 +266,12 @@ static int do_ping(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 	if (NetLoop(PING) < 0) {
 		printf("ping failed; host %s is not alive\n", argv[1]);
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 
 	printf("host %s is alive\n", argv[1]);
 
-	return 0;
+	return CMD_RET_SUCCESS;
 }
 
 U_BOOT_CMD(
@@ -313,12 +310,12 @@ int do_cdp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	r = NetLoop(CDP);
 	if (r < 0) {
 		printf("cdp failed; perhaps not a CISCO switch?\n");
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 
 	cdp_update_env();
 
-	return 0;
+	return CMD_RET_SUCCESS;
 }
 
 U_BOOT_CMD(
@@ -337,13 +334,13 @@ int do_sntp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		NetNtpServerIP = getenv_IPaddr("ntpserverip");
 		if (NetNtpServerIP == 0) {
 			printf("ntpserverip not set\n");
-			return (1);
+			return CMD_RET_FAILURE;
 		}
 	} else {
 		NetNtpServerIP = string_to_ip(argv[1]);
 		if (NetNtpServerIP == 0) {
 			printf("Bad NTP server IP address\n");
-			return (1);
+			return CMD_RET_FAILURE;
 		}
 	}
 
@@ -356,10 +353,10 @@ int do_sntp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	if (NetLoop(SNTP) < 0) {
 		printf("SNTP failed: host %pI4 not responding\n",
 			&NetNtpServerIP);
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 
-	return 0;
+	return CMD_RET_SUCCESS;
 }
 
 U_BOOT_CMD(
@@ -389,7 +386,7 @@ int do_dns(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	 */
 	if (strlen(argv[1]) >= 255) {
 		printf("dns error: hostname too long\n");
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 
 	NetDNSResolve = argv[1];
@@ -401,10 +398,10 @@ int do_dns(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 	if (NetLoop(DNS) < 0) {
 		printf("dns lookup of %s failed, check setup\n", argv[1]);
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 
-	return 0;
+	return CMD_RET_SUCCESS;
 }
 
 U_BOOT_CMD(
@@ -422,7 +419,7 @@ static int do_link_local(cmd_tbl_t *cmdtp, int flag, int argc,
 	char tmp[22];
 
 	if (NetLoop(LINKLOCAL) < 0)
-		return 1;
+		return CMD_RET_FAILURE;
 
 	NetOurGatewayIP = 0;
 	ip_to_string(NetOurGatewayIP, tmp);
@@ -435,7 +432,7 @@ static int do_link_local(cmd_tbl_t *cmdtp, int flag, int argc,
 	setenv("ipaddr", tmp);
 	setenv("llipaddr", tmp); /* store this for next time */
 
-	return 0;
+	return CMD_RET_SUCCESS;
 }
 
 U_BOOT_CMD(
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 13/27] dm: eth: Add basic driver model support to Ethernet stack
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (11 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 12/27] cmd: net: Clean up return codes Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04 18:35           ` Simon Glass
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 14/27] net: Clean up network stack names used in DM drivers Joe Hershberger
                           ` (14 subsequent siblings)
  27 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

First just add support for MAC drivers.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v5:
-Add a note to doc/README.drivers.eth about its obsolescence
-Expanded the Kconfig help
-Moved dm/ header
-Use local var for priv in eth_get_dev()

Changes in v4:
--Don't prevent eth_initialize on driver model
--If current == NULL, always check if there is a device available in eth_get_dev
--Include ethprime handling in eth_initialize
--Look up MAC address in post-probe
--Move env init call from uclass init to eth_initialize
--Print the alias in eth_initialize
--Use eth_initialize to probe all devices and write_hwaddr
-Add a helper function for eth_uclass_priv
-Add documentation to the structures
-Add eth_get_ops helper
-Change -1 returns to error constants
-Change puts to printf
-Redo the seq / probe implementation
-Remove bd_t *bis from dm eth_ops init function
-Remove checks for driver==NULL
-Remove priv pointer in per-device priv struct (drivers already get their own directly from DM)
-Rename halt() to stop() in ops
-Rename init() to start() in ops
-Stop handling selecting a new "current" in pre-unbind as it will now work itself out by clearing the pointer

Changes in v3:
--Fail init if not activated
--Fail probe if ethaddr not set
-Allow current eth dev to be NULL
-Correct failure chaining from bind to probe to init
-Correct the pre_unbind logic
-Fixed blank line formatting for variable declaration
-Update ethaddr from env unconditionally on init
-Use set current to select the current device regardless of the previous selection

Changes in v2:
-Cause an invalid name to fail binding
-Changed eth_uclass_priv local var names to be uc_priv
-Move the hwaddr to platdata so that its memory is allocated at bind when we need it
-Prevent device from being probed before used by a command (i.e. before eth_init()).
-Rebase on top of dm/master
-Removed extra parentheses
-Stop maintaining our own index and use DM seq now that it works for our needs
-Update error codes
-Updated comments

 common/cmd_bdinfo.c    |   2 +
 doc/README.drivers.eth |   6 +
 drivers/net/Kconfig    |   9 ++
 include/dm/uclass-id.h |   1 +
 include/net.h          |  52 ++++++++
 net/eth.c              | 346 ++++++++++++++++++++++++++++++++++++++++++++++++-
 6 files changed, 410 insertions(+), 6 deletions(-)

diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
index aa81da2..b4cce25 100644
--- a/common/cmd_bdinfo.c
+++ b/common/cmd_bdinfo.c
@@ -34,6 +34,7 @@ static void print_eth(int idx)
 	printf("%-12s= %s\n", name, val);
 }
 
+#ifndef CONFIG_DM_ETH
 __maybe_unused
 static void print_eths(void)
 {
@@ -52,6 +53,7 @@ static void print_eths(void)
 	printf("current eth = %s\n", eth_get_name());
 	printf("ip_addr     = %s\n", getenv("ipaddr"));
 }
+#endif
 
 __maybe_unused
 static void print_lnum(const char *name, unsigned long long value)
diff --git a/doc/README.drivers.eth b/doc/README.drivers.eth
index eb83038..98728bc 100644
--- a/doc/README.drivers.eth
+++ b/doc/README.drivers.eth
@@ -1,3 +1,9 @@
+!!! WARNING !!!
+
+This guide describes to the old way of doing things. No new Ethernet drivers
+should be implemented this way. All new drivers should be written against the
+U-Boot core driver model. See doc/driver-model/README.txt
+
 -----------------------
  Ethernet Driver Guide
 -----------------------
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index e69de29..94cf099 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -0,0 +1,9 @@
+config DM_ETH
+	bool "Enable Driver Model for Ethernet drivers"
+	depends on DM
+	help
+	  Enable driver model for Ethernet.
+
+	  The eth_*() interface will be implemented by the UC_ETH class
+	  This is currently implemented in net/eth.c
+	  Look in include/net.h for details.
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 91bb90d..ad96682 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -34,6 +34,7 @@ enum uclass_id {
 	UCLASS_I2C_GENERIC,	/* Generic I2C device */
 	UCLASS_I2C_EEPROM,	/* I2C EEPROM device */
 	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
+	UCLASS_ETH,		/* Ethernet device */
 
 	UCLASS_COUNT,
 	UCLASS_INVALID = -1,
diff --git a/include/net.h b/include/net.h
index 10d38f8..508c572 100644
--- a/include/net.h
+++ b/include/net.h
@@ -78,6 +78,57 @@ enum eth_state_t {
 	ETH_STATE_ACTIVE
 };
 
+#ifdef CONFIG_DM_ETH
+/**
+ * struct eth_pdata - Platform data for Ethernet MAC controllers
+ *
+ * @iobase: The base address of the hardware registers
+ * @enetaddr: The Ethernet MAC address that is loaded from EEPROM or env
+ */
+struct eth_pdata {
+	phys_addr_t iobase;
+	unsigned char enetaddr[6];
+};
+
+/**
+ * struct eth_ops - functions of Ethernet MAC controllers
+ *
+ * start: Prepare the hardware to send and receive packets
+ * send: Send the bytes passed in "packet" as a packet on the wire
+ * recv: Check if the hardware received a packet. Call the network stack if so
+ * stop: Stop the hardware from looking for packets - may be called even if
+ *	 state == PASSIVE
+ * mcast: Join or leave a multicast group (for TFTP) - optional
+ * write_hwaddr: Write a MAC address to the hardware (used to pass it to Linux
+ *		 on some platforms like ARM). This function expects the
+ *		 eth_pdata::enetaddr field to be populated - optional
+ * read_rom_hwaddr: Some devices have a backup of the MAC address stored in a
+ *		    ROM on the board. This is how the driver should expose it
+ *		    to the network stack. This function should fill in the
+ *		    eth_pdata::enetaddr field - optional
+ */
+struct eth_ops {
+	int (*start)(struct udevice *dev);
+	int (*send)(struct udevice *dev, void *packet, int length);
+	int (*recv)(struct udevice *dev);
+	void (*stop)(struct udevice *dev);
+#ifdef CONFIG_MCAST_TFTP
+	int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
+#endif
+	int (*write_hwaddr)(struct udevice *dev);
+	int (*read_rom_hwaddr)(struct udevice *dev);
+};
+
+#define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
+
+struct udevice *eth_get_dev(void); /* get the current device */
+unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
+/* Used only when NetConsole is enabled */
+int eth_init_state_only(void); /* Set active state */
+void eth_halt_state_only(void); /* Set passive state */
+#endif
+
+#ifndef CONFIG_DM_ETH
 struct eth_device {
 	char name[16];
 	unsigned char enetaddr[6];
@@ -144,6 +195,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		     int eth_number);
 
 int usb_eth_initialize(bd_t *bi);
+#endif
 
 int eth_initialize(void);		/* Initialize network subsystem */
 void eth_try_another(int first_restart);	/* Change the device */
diff --git a/net/eth.c b/net/eth.c
index 66ecb79..1abf027 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -1,16 +1,19 @@
 /*
- * (C) Copyright 2001-2010
+ * (C) Copyright 2001-2015
  * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ * Joe Hershberger, National Instruments
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #include <common.h>
 #include <command.h>
+#include <dm.h>
 #include <net.h>
 #include <miiphy.h>
 #include <phy.h>
 #include <asm/errno.h>
+#include <dm/device-internal.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -76,6 +79,339 @@ static int eth_mac_skip(int index)
 
 static void eth_current_changed(void);
 
+#ifdef CONFIG_DM_ETH
+/**
+ * struct eth_device_priv - private structure for each Ethernet device
+ *
+ * @state: The state of the Ethernet MAC driver (defined by enum eth_state_t)
+ */
+struct eth_device_priv {
+	enum eth_state_t state;
+};
+
+/**
+ * struct eth_uclass_priv - The structure attached to the uclass itself
+ *
+ * @current: The Ethernet device that the network functions are using
+ */
+struct eth_uclass_priv {
+	struct udevice *current;
+};
+
+static struct eth_uclass_priv *eth_get_uclass_priv(void)
+{
+	struct uclass *uc;
+
+	uclass_get(UCLASS_ETH, &uc);
+	assert(uc);
+	return uc->priv;
+}
+
+static void eth_set_current_to_next(void)
+{
+	struct eth_uclass_priv *uc_priv;
+
+	uc_priv = eth_get_uclass_priv();
+	if (uc_priv->current)
+		uclass_next_device(&uc_priv->current);
+	if (!uc_priv->current)
+		uclass_first_device(UCLASS_ETH, &uc_priv->current);
+}
+
+struct udevice *eth_get_dev(void)
+{
+	struct eth_uclass_priv *uc_priv;
+
+	uc_priv = eth_get_uclass_priv();
+	if (!uc_priv->current)
+		uclass_first_device(UCLASS_ETH,
+				    &uc_priv->current);
+	return uc_priv->current;
+}
+
+static void eth_set_dev(struct udevice *dev)
+{
+	device_probe(dev);
+	eth_get_uclass_priv()->current = dev;
+}
+
+unsigned char *eth_get_ethaddr(void)
+{
+	struct eth_pdata *pdata;
+
+	if (eth_get_dev()) {
+		pdata = eth_get_dev()->platdata;
+		return pdata->enetaddr;
+	}
+
+	return NULL;
+}
+
+/* Set active state without calling start on the driver */
+int eth_init_state_only(void)
+{
+	struct udevice *current;
+	struct eth_device_priv *priv;
+
+	current = eth_get_dev();
+	if (!current || !device_active(current))
+		return -EINVAL;
+
+	priv = current->uclass_priv;
+	priv->state = ETH_STATE_ACTIVE;
+
+	return 0;
+}
+
+/* Set passive state without calling stop on the driver */
+void eth_halt_state_only(void)
+{
+	struct udevice *current;
+	struct eth_device_priv *priv;
+
+	current = eth_get_dev();
+	if (!current || !device_active(current))
+		return;
+
+	priv = current->uclass_priv;
+	priv->state = ETH_STATE_PASSIVE;
+}
+
+int eth_get_dev_index(void)
+{
+	if (eth_get_dev())
+		return eth_get_dev()->seq;
+	return -1;
+}
+
+int eth_init(void)
+{
+	struct udevice *current;
+	struct udevice *old_current;
+
+	current = eth_get_dev();
+	if (!current) {
+		printf("No ethernet found.\n");
+		return -ENODEV;
+	}
+
+	old_current = current;
+	do {
+		debug("Trying %s\n", current->name);
+
+		if (device_active(current)) {
+			uchar env_enetaddr[6];
+			struct eth_pdata *pdata = current->platdata;
+
+			/* Sync environment with network device */
+			if (eth_getenv_enetaddr_by_index("eth", current->seq,
+							 env_enetaddr))
+				memcpy(pdata->enetaddr, env_enetaddr, 6);
+			else
+				memset(pdata->enetaddr, 0, 6);
+
+			if (eth_get_ops(current)->start(current) >= 0) {
+				struct eth_device_priv *priv =
+					current->uclass_priv;
+
+				priv->state = ETH_STATE_ACTIVE;
+				return 0;
+			}
+		}
+		debug("FAIL\n");
+
+		/* This will ensure the new "current" attempted to probe */
+		eth_try_another(0);
+		current = eth_get_dev();
+	} while (old_current != current);
+
+	return -ENODEV;
+}
+
+void eth_halt(void)
+{
+	struct udevice *current;
+	struct eth_device_priv *priv;
+
+	current = eth_get_dev();
+	if (!current || !device_active(current))
+		return;
+
+	eth_get_ops(current)->stop(current);
+	priv = current->uclass_priv;
+	priv->state = ETH_STATE_PASSIVE;
+}
+
+int eth_send(void *packet, int length)
+{
+	struct udevice *current;
+
+	current = eth_get_dev();
+	if (!current)
+		return -ENODEV;
+
+	if (!device_active(current))
+		return -EINVAL;
+
+	return eth_get_ops(current)->send(current, packet, length);
+}
+
+int eth_rx(void)
+{
+	struct udevice *current;
+
+	current = eth_get_dev();
+	if (!current)
+		return -ENODEV;
+
+	if (!device_active(current))
+		return -EINVAL;
+
+	return eth_get_ops(current)->recv(current);
+}
+
+static int eth_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev->platdata;
+	int ret = 0;
+
+	if (!dev || !device_active(dev))
+		return -EINVAL;
+
+	/* seq is valid since the device is active */
+	if (eth_get_ops(dev)->write_hwaddr && !eth_mac_skip(dev->seq)) {
+		if (!is_valid_ether_addr(pdata->enetaddr)) {
+			printf("\nError: %s address %pM illegal value\n",
+			       dev->name, pdata->enetaddr);
+			return -EINVAL;
+		}
+
+		ret = eth_get_ops(dev)->write_hwaddr(dev);
+		if (ret)
+			printf("\nWarning: %s failed to set MAC address\n",
+			       dev->name);
+	}
+
+	return ret;
+}
+
+int eth_initialize(void)
+{
+	int num_devices = 0;
+	struct udevice *dev;
+
+	bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
+	eth_env_init();
+
+	/*
+	 * Devices need to write the hwaddr even if not started so that Linux
+	 * will have access to the hwaddr that u-boot stored for the device.
+	 * This is accomplished by attempting to probe each device and calling
+	 * their write_hwaddr() operation.
+	 */
+	uclass_first_device(UCLASS_ETH, &dev);
+	if (!dev) {
+		printf("No ethernet found.\n");
+		bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
+	} else {
+		bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
+		do {
+			if (num_devices)
+				printf(", ");
+
+			printf("eth%d: %s", dev->seq, dev->name);
+
+			eth_write_hwaddr(dev);
+
+			uclass_next_device(&dev);
+			num_devices++;
+		} while (dev);
+
+		putc('\n');
+	}
+
+	return num_devices;
+}
+
+static int eth_post_bind(struct udevice *dev)
+{
+	if (strchr(dev->name, ' ')) {
+		printf("\nError: eth device name \"%s\" has a space!\n",
+		       dev->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int eth_pre_unbind(struct udevice *dev)
+{
+	/* Don't hang onto a pointer that is going away */
+	if (dev == eth_get_uclass_priv()->current)
+		eth_set_dev(NULL);
+
+	return 0;
+}
+
+static int eth_post_probe(struct udevice *dev)
+{
+	struct eth_device_priv *priv = dev->uclass_priv;
+	struct eth_pdata *pdata = dev->platdata;
+	unsigned char env_enetaddr[6];
+
+	priv->state = ETH_STATE_INIT;
+
+	/* Check if the device has a MAC address in ROM */
+	if (eth_get_ops(dev)->read_rom_hwaddr)
+		eth_get_ops(dev)->read_rom_hwaddr(dev);
+
+	eth_getenv_enetaddr_by_index("eth", dev->seq, env_enetaddr);
+	if (!is_zero_ether_addr(env_enetaddr)) {
+		if (!is_zero_ether_addr(pdata->enetaddr) &&
+		    memcmp(pdata->enetaddr, env_enetaddr, 6)) {
+			printf("\nWarning: %s MAC addresses don't match:\n",
+			       dev->name);
+			printf("Address in SROM is         %pM\n",
+			       pdata->enetaddr);
+			printf("Address in environment is  %pM\n",
+			       env_enetaddr);
+		}
+
+		/* Override the ROM MAC address */
+		memcpy(pdata->enetaddr, env_enetaddr, 6);
+	} else if (is_valid_ether_addr(pdata->enetaddr)) {
+		eth_setenv_enetaddr_by_index("eth", dev->seq, pdata->enetaddr);
+		printf("\nWarning: %s using MAC address from ROM\n",
+		       dev->name);
+	} else if (is_zero_ether_addr(pdata->enetaddr)) {
+		printf("\nError: %s address not set.\n",
+		       dev->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int eth_pre_remove(struct udevice *dev)
+{
+	eth_get_ops(dev)->stop(dev);
+
+	return 0;
+}
+
+UCLASS_DRIVER(eth) = {
+	.name		= "eth",
+	.id		= UCLASS_ETH,
+	.post_bind	= eth_post_bind,
+	.pre_unbind	= eth_pre_unbind,
+	.post_probe	= eth_post_probe,
+	.pre_remove	= eth_pre_remove,
+	.priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
+	.per_device_auto_alloc_size = sizeof(struct eth_device_priv),
+};
+#endif
+
+#ifndef CONFIG_DM_ETH
 /*
  * CPU and board-specific Ethernet initializations.  Aliased function
  * signals caller to move on
@@ -427,6 +763,7 @@ int eth_rx(void)
 
 	return eth_current->recv(eth_current);
 }
+#endif /* ifndef CONFIG_DM_ETH */
 
 #ifdef CONFIG_API
 static void eth_save_packet(void *packet, int length)
@@ -490,7 +827,7 @@ static void eth_current_changed(void)
 
 void eth_try_another(int first_restart)
 {
-	static struct eth_device *first_failed;
+	static void *first_failed;
 	char *ethrotate;
 
 	/*
@@ -519,12 +856,9 @@ void eth_set_current(void)
 {
 	static char *act;
 	static int  env_changed_id;
-	struct eth_device *old_current;
+	void *old_current;
 	int	env_id;
 
-	if (!eth_get_dev())	/* XXX no current */
-		return;
-
 	env_id = get_env_id();
 	if ((act == NULL) || (env_changed_id != env_id)) {
 		act = getenv("ethact");
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 14/27] net: Clean up network stack names used in DM drivers
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (12 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 13/27] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04 18:35           ` Simon Glass
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 15/27] dm: eth: Pass the packet pointer as a parameter to recv Joe Hershberger
                           ` (13 subsequent siblings)
  27 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

Take the opportunity to enforce better names on newly written or
retrofitted Ethernet drivers.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v5:
-New to v5

Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/net.h |  9 ++++++++-
 net/net.c     | 30 +++++++++++++++++++-----------
 2 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/include/net.h b/include/net.h
index 508c572..4e44832 100644
--- a/include/net.h
+++ b/include/net.h
@@ -466,7 +466,11 @@ extern uchar		NetServerEther[6];	/* Boot server enet address */
 extern IPaddr_t		NetOurIP;	/* Our    IP addr (0 = unknown) */
 extern IPaddr_t		NetServerIP;	/* Server IP addr (0 = unknown) */
 extern uchar		*NetTxPacket;		/* THE transmit packet */
+#ifdef CONFIG_DM_ETH
+extern uchar		*net_rx_packets[PKTBUFSRX]; /* Receive packets */
+#else
 extern uchar		*NetRxPackets[PKTBUFSRX]; /* Receive packets */
+#endif
 extern uchar		*NetRxPacket;		/* Current receive packet */
 extern int		NetRxPacketLen;		/* Current rx packet length */
 extern unsigned		NetIPID;		/* IP ID (counting) */
@@ -616,8 +620,11 @@ static inline void NetSendPacket(uchar *pkt, int len)
 int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport,
 			int sport, int payload_len);
 
+#ifndef CONFIG_DM_ETH
+#define NetReceive(in_packet, len) net_process_received_packet(in_packet, len)
+#endif
 /* Processes a received packet */
-void NetReceive(uchar *, int);
+void net_process_received_packet(uchar *in_packet, int len);
 
 #ifdef CONFIG_NETCONSOLE
 void NcStart(void);
diff --git a/net/net.c b/net/net.c
index 37b4aab..afec443 100644
--- a/net/net.c
+++ b/net/net.c
@@ -183,10 +183,13 @@ int		NetTimeOffset;
 #endif
 
 static uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
-
+#ifdef CONFIG_DM_ETH
+/* Receive packets */
+uchar *net_rx_packets[PKTBUFSRX];
+#else
 /* Receive packet */
 uchar *NetRxPackets[PKTBUFSRX];
-
+#endif
 /* Current UDP RX packet handler */
 static rxhand_f *udp_packet_handler;
 /* Current ARP RX packet handler */
@@ -304,9 +307,15 @@ void net_init(void)
 
 		NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
 		NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
+#ifdef CONFIG_DM_ETH
+		for (i = 0; i < PKTBUFSRX; i++) {
+			net_rx_packets[i] = NetTxPacket + (i + 1) *
+				PKTSIZE_ALIGN;
+		}
+#else
 		for (i = 0; i < PKTBUFSRX; i++)
 			NetRxPackets[i] = NetTxPacket + (i + 1) * PKTSIZE_ALIGN;
-
+#endif
 		ArpInit();
 		net_clear_handlers();
 
@@ -952,8 +961,7 @@ static void receive_icmp(struct ip_udp_hdr *ip, int len,
 	}
 }
 
-void
-NetReceive(uchar *inpkt, int len)
+void net_process_received_packet(uchar *in_packet, int len)
 {
 	struct ethernet_hdr *et;
 	struct ip_udp_hdr *ip;
@@ -967,9 +975,9 @@ NetReceive(uchar *inpkt, int len)
 
 	debug_cond(DEBUG_NET_PKT, "packet received\n");
 
-	NetRxPacket = inpkt;
+	NetRxPacket = in_packet;
 	NetRxPacketLen = len;
-	et = (struct ethernet_hdr *)inpkt;
+	et = (struct ethernet_hdr *)in_packet;
 
 	/* too small packet? */
 	if (len < ETHER_HDR_SIZE)
@@ -977,7 +985,7 @@ NetReceive(uchar *inpkt, int len)
 
 #ifdef CONFIG_API
 	if (push_packet) {
-		(*push_packet)(inpkt, len);
+		(*push_packet)(in_packet, len);
 		return;
 	}
 #endif
@@ -1004,11 +1012,11 @@ NetReceive(uchar *inpkt, int len)
 		 */
 		eth_proto = ntohs(et802->et_prot);
 
-		ip = (struct ip_udp_hdr *)(inpkt + E802_HDR_SIZE);
+		ip = (struct ip_udp_hdr *)(in_packet + E802_HDR_SIZE);
 		len -= E802_HDR_SIZE;
 
 	} else if (eth_proto != PROT_VLAN) {	/* normal packet */
-		ip = (struct ip_udp_hdr *)(inpkt + ETHER_HDR_SIZE);
+		ip = (struct ip_udp_hdr *)(in_packet + ETHER_HDR_SIZE);
 		len -= ETHER_HDR_SIZE;
 
 	} else {			/* VLAN packet */
@@ -1033,7 +1041,7 @@ NetReceive(uchar *inpkt, int len)
 		vlanid = cti & VLAN_IDMASK;
 		eth_proto = ntohs(vet->vet_type);
 
-		ip = (struct ip_udp_hdr *)(inpkt + VLAN_ETHER_HDR_SIZE);
+		ip = (struct ip_udp_hdr *)(in_packet + VLAN_ETHER_HDR_SIZE);
 		len -= VLAN_ETHER_HDR_SIZE;
 	}
 
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 15/27] dm: eth: Pass the packet pointer as a parameter to recv
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (13 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 14/27] net: Clean up network stack names used in DM drivers Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04 18:35           ` Simon Glass
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 16/27] sandbox: eth: Add network support to sandbox Joe Hershberger
                           ` (12 subsequent siblings)
  27 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

Stop forcing drivers to call net_process_received_packet() - formerly
called NetReceive(). Now the uclass will handle calling the driver for
each packet until the driver errors or has nothing to return. The uclass
will then pass the good packets off to the network stack by calling
net_process_received_packet().

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v5:
-New to v5

Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/net.h |  2 +-
 net/eth.c     | 13 ++++++++++++-
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/include/net.h b/include/net.h
index 4e44832..37d1f36 100644
--- a/include/net.h
+++ b/include/net.h
@@ -110,7 +110,7 @@ struct eth_pdata {
 struct eth_ops {
 	int (*start)(struct udevice *dev);
 	int (*send)(struct udevice *dev, void *packet, int length);
-	int (*recv)(struct udevice *dev);
+	int (*recv)(struct udevice *dev, uchar **packetp);
 	void (*stop)(struct udevice *dev);
 #ifdef CONFIG_MCAST_TFTP
 	int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
diff --git a/net/eth.c b/net/eth.c
index 1abf027..b66d253 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -259,6 +259,9 @@ int eth_send(void *packet, int length)
 int eth_rx(void)
 {
 	struct udevice *current;
+	uchar *packet;
+	int ret;
+	int i;
 
 	current = eth_get_dev();
 	if (!current)
@@ -267,7 +270,15 @@ int eth_rx(void)
 	if (!device_active(current))
 		return -EINVAL;
 
-	return eth_get_ops(current)->recv(current);
+	/* Process up to 32 packets at one time */
+	for (i = 0; i < 32; i++) {
+		ret = eth_get_ops(current)->recv(current, &packet);
+		if (ret > 0)
+			net_process_received_packet(packet, ret);
+		else
+			break;
+	}
+	return ret;
 }
 
 static int eth_write_hwaddr(struct udevice *dev)
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 16/27] sandbox: eth: Add network support to sandbox
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (14 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 15/27] dm: eth: Pass the packet pointer as a parameter to recv Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04 18:35           ` Simon Glass
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 17/27] sandbox: eth: Add ARP and PING response to sandbox driver Joe Hershberger
                           ` (11 subsequent siblings)
  27 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

Add basic network support to sandbox which includes a network driver.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v5:
-Added help to the sandbox eth mock driver Kconfig entry

Changes in v4:
-Cleaned up sandbox EXTRA_ENV define
-Moved config to Kconfig

Changes in v3:
-Added 2 more ethaddr to sandbox
-Print which device in the debug write hwaddr

Changes in v2:
-Change printfs to debug in sandbox driver
-Remove unused priv struct for sandbox driver

 arch/sandbox/Kconfig         |  9 +++++
 arch/sandbox/dts/sandbox.dts |  4 +++
 board/sandbox/README.sandbox |  4 +--
 drivers/net/Kconfig          | 23 ++++++++++++
 drivers/net/Makefile         |  1 +
 drivers/net/sandbox.c        | 84 ++++++++++++++++++++++++++++++++++++++++++++
 include/configs/sandbox.h    | 16 +++++----
 7 files changed, 133 insertions(+), 8 deletions(-)
 create mode 100644 drivers/net/sandbox.c

diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index 2098b9c..186b58d 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -34,4 +34,13 @@ config DM_I2C
 config DM_TEST
 	default y
 
+config NET
+	default y
+
+config NETDEVICES
+	default y
+
+config DM_ETH
+	default y
+
 endmenu
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 9ce31bf..36b3bd8 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -181,4 +181,8 @@
 		};
 	};
 
+	eth at 10002000 {
+		compatible = "sandbox,eth";
+		reg = <0x10002000 0x1000>;
+	};
 };
diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
index 3c0df17..c1f5f7e 100644
--- a/board/sandbox/README.sandbox
+++ b/board/sandbox/README.sandbox
@@ -173,16 +173,16 @@ U-Boot sandbox supports these emulations:
 - Chrome OS EC
 - GPIO
 - Host filesystem (access files on the host from within U-Boot)
+- I2C
 - Keyboard (Chrome OS)
 - LCD
+- Network
 - Serial (for console only)
 - Sound (incomplete - see sandbox_sdl_sound_init() for details)
 - SPI
 - SPI flash
 - TPM (Trusted Platform Module)
 
-Notable omissions are networking and I2C.
-
 A wide range of commands is implemented. Filesystems which use a block
 device are supported.
 
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 94cf099..e46e57b 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -7,3 +7,26 @@ config DM_ETH
 	  The eth_*() interface will be implemented by the UC_ETH class
 	  This is currently implemented in net/eth.c
 	  Look in include/net.h for details.
+
+menuconfig NETDEVICES
+	bool "Network device support"
+	depends on NET
+	help
+	  You must select Y to enable any network device support
+	  Generally if you have any networking support this is a given
+
+	  If unsure, say Y
+
+if NETDEVICES
+
+config ETH_SANDBOX
+	depends on DM_ETH && SANDBOX
+	default y
+	bool "Sandbox: Mocked Ethernet driver"
+	help
+	  This driver simply responds with fake ARP replies and ping
+	  replies that are used to verify network stack functionality
+
+	  This driver is particularly useful in the test/dm/eth.c tests
+
+endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 46c4ac6..15dc431 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_NS8382X) += ns8382x.o
 obj-$(CONFIG_PCNET) += pcnet.o
 obj-$(CONFIG_RTL8139) += rtl8139.o
 obj-$(CONFIG_RTL8169) += rtl8169.o
+obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
 obj-$(CONFIG_SH_ETHER) += sh_eth.o
 obj-$(CONFIG_SMC91111) += smc91111.o
 obj-$(CONFIG_SMC911X) += smc911x.o
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
new file mode 100644
index 0000000..522990d
--- /dev/null
+++ b/drivers/net/sandbox.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int sb_eth_start(struct udevice *dev)
+{
+	debug("eth_sandbox: Start\n");
+
+	return 0;
+}
+
+static int sb_eth_send(struct udevice *dev, void *packet, int length)
+{
+	debug("eth_sandbox: Send packet %d\n", length);
+
+	return 0;
+}
+
+static int sb_eth_recv(struct udevice *dev, uchar **packetp)
+{
+	return 0;
+}
+
+static void sb_eth_stop(struct udevice *dev)
+{
+	debug("eth_sandbox: Stop\n");
+}
+
+static int sb_eth_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	debug("eth_sandbox %s: Write HW ADDR - %pM\n", dev->name,
+	      pdata->enetaddr);
+	return 0;
+}
+
+static const struct eth_ops sb_eth_ops = {
+	.start			= sb_eth_start,
+	.send			= sb_eth_send,
+	.recv			= sb_eth_recv,
+	.stop			= sb_eth_stop,
+	.write_hwaddr		= sb_eth_write_hwaddr,
+};
+
+static int sb_eth_remove(struct udevice *dev)
+{
+	return 0;
+}
+
+static int sb_eth_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	pdata->iobase = dev_get_addr(dev);
+	return 0;
+}
+
+static const struct udevice_id sb_eth_ids[] = {
+	{ .compatible = "sandbox,eth" },
+	{ }
+};
+
+U_BOOT_DRIVER(eth_sandbox) = {
+	.name	= "eth_sandbox",
+	.id	= UCLASS_ETH,
+	.of_match = sb_eth_ids,
+	.ofdata_to_platdata = sb_eth_ofdata_to_platdata,
+	.remove	= sb_eth_remove,
+	.ops	= &sb_eth_ops,
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index febbfb6..664b984 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -126,9 +126,6 @@
 /* include default commands */
 #include <config_cmd_default.h>
 
-/* We don't have networking support yet */
-#undef CONFIG_CMD_NET
-#undef CONFIG_CMD_NFS
 
 #define CONFIG_CMD_HASH
 #define CONFIG_HASH_VERIFY
@@ -165,16 +162,23 @@
 
 #define CONFIG_KEYBOARD
 
-#define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial,cros-ec-keyb\0" \
+#define SANDBOX_SERIAL_SETTINGS		"stdin=serial,cros-ec-keyb\0" \
 					"stdout=serial,lcd\0" \
 					"stderr=serial,lcd\0"
 #else
-
-#define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial\0" \
+#define SANDBOX_SERIAL_SETTINGS		"stdin=serial\0" \
 					"stdout=serial,lcd\0" \
 					"stderr=serial,lcd\0"
 #endif
 
+#define SANDBOX_ETH_SETTINGS		"ethaddr=00:00:11:22:33:44\0" \
+					"eth1addr=00:00:11:22:33:45\0" \
+					"eth2addr=00:00:11:22:33:46\0" \
+					"ipaddr=1.2.3.4\0"
+
+#define CONFIG_EXTRA_ENV_SETTINGS	SANDBOX_SERIAL_SETTINGS \
+					SANDBOX_ETH_SETTINGS
+
 #define CONFIG_GZIP_COMPRESSED
 #define CONFIG_BZIP2
 #define CONFIG_LZO
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 17/27] sandbox: eth: Add ARP and PING response to sandbox driver
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (15 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 16/27] sandbox: eth: Add network support to sandbox Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 18/27] test: dm: eth: Add tests for the eth dm implementation Joe Hershberger
                           ` (10 subsequent siblings)
  27 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

The sandbox driver will now generate response traffic to exercise the
ping command even when no network exists.  This allows the basic data
pathways of the DM to be tested.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v5:
-Simplify sandbox eth driver by switching from int array to byte array
-Switch priv from packet buffer to a pointer to net_rx_packets[0]

Changes in v4:
-Removed checks on priv != NULL and added protection in uclass instead

Changes in v3:
-Prevent a crash if memory is not allocated

Changes in v2:
-Change printfs to debug in sandbox driver
-Move fake hwaddr to the device tree
-Move static data to priv

 arch/sandbox/dts/sandbox.dts |   1 +
 drivers/net/sandbox.c        | 107 +++++++++++++++++++++++++++++++++++++++++++
 include/configs/sandbox.h    |   1 +
 3 files changed, 109 insertions(+)

diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 36b3bd8..c2a3304 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -184,5 +184,6 @@
 	eth at 10002000 {
 		compatible = "sandbox,eth";
 		reg = <0x10002000 0x1000>;
+		fake-host-hwaddr = [00 00 66 44 22 00];
 	};
 };
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
index 522990d..cb69a95 100644
--- a/drivers/net/sandbox.c
+++ b/drivers/net/sandbox.c
@@ -14,22 +14,128 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/**
+ * struct eth_sandbox_priv - memory for sandbox mock driver
+ *
+ * fake_host_hwaddr: MAC address of mocked machine
+ * fake_host_ipaddr: IP address of mocked machine
+ * recv_packet_buffer: buffer of the packet returned as received
+ * recv_packet_length: length of the packet returned as received
+ */
+struct eth_sandbox_priv {
+	uchar fake_host_hwaddr[ARP_HLEN];
+	IPaddr_t fake_host_ipaddr;
+	uchar *recv_packet_buffer;
+	int recv_packet_length;
+};
+
 static int sb_eth_start(struct udevice *dev)
 {
+	struct eth_sandbox_priv *priv = dev_get_priv(dev);
+
 	debug("eth_sandbox: Start\n");
 
+	fdtdec_get_byte_array(gd->fdt_blob, dev->of_offset, "fake-host-hwaddr",
+			      priv->fake_host_hwaddr, ARP_HLEN);
+	priv->recv_packet_buffer = net_rx_packets[0];
 	return 0;
 }
 
 static int sb_eth_send(struct udevice *dev, void *packet, int length)
 {
+	struct eth_sandbox_priv *priv = dev_get_priv(dev);
+	struct ethernet_hdr *eth = packet;
+
 	debug("eth_sandbox: Send packet %d\n", length);
 
+	if (ntohs(eth->et_protlen) == PROT_ARP) {
+		struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
+
+		if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
+			struct ethernet_hdr *eth_recv;
+			struct arp_hdr *arp_recv;
+
+			/* store this as the assumed IP of the fake host */
+			priv->fake_host_ipaddr = NetReadIP(&arp->ar_tpa);
+			/* Formulate a fake response */
+			eth_recv = (void *)priv->recv_packet_buffer;
+			memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
+			memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
+			       ARP_HLEN);
+			eth_recv->et_protlen = htons(PROT_ARP);
+
+			arp_recv = (void *)priv->recv_packet_buffer +
+				ETHER_HDR_SIZE;
+			arp_recv->ar_hrd = htons(ARP_ETHER);
+			arp_recv->ar_pro = htons(PROT_IP);
+			arp_recv->ar_hln = ARP_HLEN;
+			arp_recv->ar_pln = ARP_PLEN;
+			arp_recv->ar_op = htons(ARPOP_REPLY);
+			memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr,
+			       ARP_HLEN);
+			NetWriteIP(&arp_recv->ar_spa, priv->fake_host_ipaddr);
+			memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN);
+			NetCopyIP(&arp_recv->ar_tpa, &arp->ar_spa);
+
+			priv->recv_packet_length = ETHER_HDR_SIZE +
+				ARP_HDR_SIZE;
+		}
+	} else if (ntohs(eth->et_protlen) == PROT_IP) {
+		struct ip_udp_hdr *ip = packet + ETHER_HDR_SIZE;
+
+		if (ip->ip_p == IPPROTO_ICMP) {
+			struct icmp_hdr *icmp = (struct icmp_hdr *)&ip->udp_src;
+
+			if (icmp->type == ICMP_ECHO_REQUEST) {
+				struct ethernet_hdr *eth_recv;
+				struct ip_udp_hdr *ipr;
+				struct icmp_hdr *icmpr;
+
+				/* reply to the ping */
+				memcpy(priv->recv_packet_buffer, packet,
+				       length);
+				eth_recv = (void *)priv->recv_packet_buffer;
+				ipr = (void *)priv->recv_packet_buffer +
+					ETHER_HDR_SIZE;
+				icmpr = (struct icmp_hdr *)&ipr->udp_src;
+				memcpy(eth_recv->et_dest, eth->et_src,
+				       ARP_HLEN);
+				memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
+				       ARP_HLEN);
+				ipr->ip_sum = 0;
+				ipr->ip_off = 0;
+				NetCopyIP((void *)&ipr->ip_dst, &ip->ip_src);
+				NetWriteIP((void *)&ipr->ip_src,
+					   priv->fake_host_ipaddr);
+				ipr->ip_sum = compute_ip_checksum(ipr,
+					IP_HDR_SIZE);
+
+				icmpr->type = ICMP_ECHO_REPLY;
+				icmpr->checksum = 0;
+				icmpr->checksum = compute_ip_checksum(icmpr,
+					ICMP_HDR_SIZE);
+
+				priv->recv_packet_length = length;
+			}
+		}
+	}
+
 	return 0;
 }
 
 static int sb_eth_recv(struct udevice *dev, uchar **packetp)
 {
+	struct eth_sandbox_priv *priv = dev_get_priv(dev);
+
+	if (priv->recv_packet_length) {
+		int lcl_recv_packet_length = priv->recv_packet_length;
+
+		debug("eth_sandbox: received packet %d\n",
+		      priv->recv_packet_length);
+		priv->recv_packet_length = 0;
+		*packetp = priv->recv_packet_buffer;
+		return lcl_recv_packet_length;
+	}
 	return 0;
 }
 
@@ -80,5 +186,6 @@ U_BOOT_DRIVER(eth_sandbox) = {
 	.ofdata_to_platdata = sb_eth_ofdata_to_platdata,
 	.remove	= sb_eth_remove,
 	.ops	= &sb_eth_ops,
+	.priv_auto_alloc_size = sizeof(struct eth_sandbox_priv),
 	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
 };
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 664b984..9189f6a 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -126,6 +126,7 @@
 /* include default commands */
 #include <config_cmd_default.h>
 
+#define CONFIG_CMD_PING
 
 #define CONFIG_CMD_HASH
 #define CONFIG_HASH_VERIFY
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 18/27] test: dm: eth: Add tests for the eth dm implementation
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (16 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 17/27] sandbox: eth: Add ARP and PING response to sandbox driver Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 19/27] dm: eth: Add support for aliases Joe Hershberger
                           ` (9 subsequent siblings)
  27 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

Add a test for the eth uclass using the sandbox eth driver. Verify basic
functionality of the network stack / eth uclass by exercising the ping
function.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v5: None
Changes in v4: None
Changes in v3:
-Added dm eth testing

Changes in v2: None

 test/dm/Makefile |  1 +
 test/dm/eth.c    | 38 ++++++++++++++++++++++++++++++++++++++
 test/dm/test.dts | 18 ++++++++++++++++++
 3 files changed, 57 insertions(+)
 create mode 100644 test/dm/eth.c

diff --git a/test/dm/Makefile b/test/dm/Makefile
index 1d9148f..b2eb989 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_DM_TEST) += ut.o
 obj-$(CONFIG_DM_TEST) += core.o
 obj-$(CONFIG_DM_TEST) += ut.o
 ifneq ($(CONFIG_SANDBOX),)
+obj-$(CONFIG_DM_ETH) += eth.o
 obj-$(CONFIG_DM_GPIO) += gpio.o
 obj-$(CONFIG_DM_I2C) += i2c.o
 obj-$(CONFIG_DM_SPI_FLASH) += sf.o
diff --git a/test/dm/eth.c b/test/dm/eth.c
new file mode 100644
index 0000000..04ccf49
--- /dev/null
+++ b/test/dm/eth.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <dm/ut.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int dm_test_eth(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+
+	setenv("ethact", "eth at 10002000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	setenv("ethact", "eth at 10003000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10003000", getenv("ethact"));
+
+	setenv("ethact", "eth at 10004000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	return 0;
+}
+DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
diff --git a/test/dm/test.dts b/test/dm/test.dts
index 84024a4..2f68cdf 100644
--- a/test/dm/test.dts
+++ b/test/dm/test.dts
@@ -149,4 +149,22 @@
 		};
 	};
 
+	eth at 10002000 {
+		compatible = "sandbox,eth";
+		reg = <0x10002000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
+	};
+
+	eth at 10003000 {
+		compatible = "sandbox,eth";
+		reg = <0x10003000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
+	};
+
+	eth at 10004000 {
+		compatible = "sandbox,eth";
+		reg = <0x10004000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x22>;
+	};
+
 };
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 19/27] dm: eth: Add support for aliases
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (17 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 18/27] test: dm: eth: Add tests for the eth dm implementation Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04 18:35           ` Simon Glass
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 20/27] dm: eth: Add support for ethprime env var Joe Hershberger
                           ` (8 subsequent siblings)
  27 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

Allow network devices to be referred to as "eth0" instead of
"eth at 12345678" when specified in ethact.

Add tests to verify this behavior.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v5:
-Added a comment about devname
-Only check for alias if the name is long enough

Changes in v4:
-Use only the seq from DM to find aliases

Changes in v3:
-Added support for aliases

Changes in v2: None

 include/configs/sandbox.h |  2 +-
 include/net.h             |  5 +++++
 net/eth.c                 | 50 ++++++++++++++++++++++++++++++++++++++---------
 test/dm/eth.c             | 24 +++++++++++++++++++++++
 test/dm/test.dts          |  4 +++-
 5 files changed, 74 insertions(+), 11 deletions(-)

diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 9189f6a..caf9f5a 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -174,7 +174,7 @@
 
 #define SANDBOX_ETH_SETTINGS		"ethaddr=00:00:11:22:33:44\0" \
 					"eth1addr=00:00:11:22:33:45\0" \
-					"eth2addr=00:00:11:22:33:46\0" \
+					"eth5addr=00:00:11:22:33:46\0" \
 					"ipaddr=1.2.3.4\0"
 
 #define CONFIG_EXTRA_ENV_SETTINGS	SANDBOX_SERIAL_SETTINGS \
diff --git a/include/net.h b/include/net.h
index 37d1f36..5846dfb 100644
--- a/include/net.h
+++ b/include/net.h
@@ -122,6 +122,11 @@ struct eth_ops {
 #define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
 
 struct udevice *eth_get_dev(void); /* get the current device */
+/*
+ * The devname can be either an exact name given by the driver or device tree
+ * or it can be an alias of the form "eth%d"
+ */
+struct udevice *eth_get_dev_by_name(const char *devname);
 unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
 /* Used only when NetConsole is enabled */
 int eth_init_state_only(void); /* Set active state */
diff --git a/net/eth.c b/net/eth.c
index b66d253..14a072b 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -135,6 +135,39 @@ static void eth_set_dev(struct udevice *dev)
 	eth_get_uclass_priv()->current = dev;
 }
 
+/*
+ * Find the udevice that either has the name passed in as devname or has an
+ * alias named devname.
+ */
+struct udevice *eth_get_dev_by_name(const char *devname)
+{
+	int seq = -1;
+	char *endp = NULL;
+	const char *startp = NULL;
+	struct udevice *it;
+	struct uclass *uc;
+
+	/* Must be longer than 3 to be an alias */
+	if (strlen(devname) > strlen("eth")) {
+		startp = devname + strlen("eth");
+		seq = simple_strtoul(startp, &endp, 10);
+	}
+
+	uclass_get(UCLASS_ETH, &uc);
+	uclass_foreach_dev(it, uc) {
+		/* We need the seq to be valid, so make sure it's probed */
+		device_probe(it);
+		/*
+		 * Check for the name or the sequence number to match
+		 */
+		if (strcmp(it->name, devname) == 0 ||
+		    (endp > startp && it->seq == seq))
+			return it;
+	}
+
+	return NULL;
+}
+
 unsigned char *eth_get_ethaddr(void)
 {
 	struct eth_pdata *pdata;
@@ -419,6 +452,7 @@ UCLASS_DRIVER(eth) = {
 	.pre_remove	= eth_pre_remove,
 	.priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
 	.per_device_auto_alloc_size = sizeof(struct eth_device_priv),
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 };
 #endif
 
@@ -451,6 +485,11 @@ static void eth_set_current_to_next(void)
 	eth_current = eth_current->next;
 }
 
+static void eth_set_dev(struct eth_device *dev)
+{
+	eth_current = dev;
+}
+
 struct eth_device *eth_get_dev_by_name(const char *devname)
 {
 	struct eth_device *dev, *target_dev;
@@ -867,7 +906,6 @@ void eth_set_current(void)
 {
 	static char *act;
 	static int  env_changed_id;
-	void *old_current;
 	int	env_id;
 
 	env_id = get_env_id();
@@ -875,14 +913,8 @@ void eth_set_current(void)
 		act = getenv("ethact");
 		env_changed_id = env_id;
 	}
-	if (act != NULL) {
-		old_current = eth_get_dev();
-		do {
-			if (strcmp(eth_get_name(), act) == 0)
-				return;
-			eth_set_current_to_next();
-		} while (old_current != eth_get_dev());
-	}
+	if (act != NULL)
+		eth_set_dev(eth_get_dev_by_name(act));
 
 	eth_current_changed();
 }
diff --git a/test/dm/eth.c b/test/dm/eth.c
index 04ccf49..5688b71 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -36,3 +36,27 @@ static int dm_test_eth(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
+
+static int dm_test_eth_alias(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+	setenv("ethact", "eth0");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	setenv("ethact", "eth1");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	/* Expected to fail since eth2 is not defined in the device tree */
+	setenv("ethact", "eth2");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	setenv("ethact", "eth5");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10003000", getenv("ethact"));
+
+	return 0;
+}
+DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
diff --git a/test/dm/test.dts b/test/dm/test.dts
index 2f68cdf..bc2409d 100644
--- a/test/dm/test.dts
+++ b/test/dm/test.dts
@@ -17,6 +17,8 @@
 		testfdt3 = "/b-test";
 		testfdt5 = "/some-bus/c-test at 5";
 		testfdt8 = "/a-test";
+		eth0 = "/eth at 10002000";
+		eth5 = &eth_5;
 	};
 
 	uart0: serial {
@@ -155,7 +157,7 @@
 		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
 	};
 
-	eth at 10003000 {
+	eth_5: eth at 10003000 {
 		compatible = "sandbox,eth";
 		reg = <0x10003000 0x1000>;
 		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 20/27] dm: eth: Add support for ethprime env var
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (18 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 19/27] dm: eth: Add support for aliases Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 21/27] test: dm: eth: Add testing for ethrotate " Joe Hershberger
                           ` (7 subsequent siblings)
  27 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

The ethprime env var is used to indicate the starting device if none is
specified in ethact. Also support aliases specified in the ethprime var.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v5:
-Fix compile error on !DM_ETH

Changes in v4:
-Load from ethprime on eth_initialize()

Changes in v3:
-Added support for ethprime

Changes in v2: None

 net/eth.c     | 29 ++++++++++++++++++++++++++++-
 test/dm/eth.c | 20 ++++++++++++++++++++
 2 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/net/eth.c b/net/eth.c
index 14a072b..9966cf0 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -358,6 +358,18 @@ int eth_initialize(void)
 		printf("No ethernet found.\n");
 		bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
 	} else {
+		char *ethprime = getenv("ethprime");
+		struct udevice *prime_dev = NULL;
+
+		if (ethprime)
+			prime_dev = eth_get_dev_by_name(ethprime);
+		if (prime_dev) {
+			eth_set_dev(prime_dev);
+			eth_current_changed();
+		} else {
+			eth_set_dev(NULL);
+		}
+
 		bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
 		do {
 			if (num_devices)
@@ -365,6 +377,9 @@ int eth_initialize(void)
 
 			printf("eth%d: %s", dev->seq, dev->name);
 
+			if (ethprime && dev == prime_dev)
+				printf(" [PRIME]");
+
 			eth_write_hwaddr(dev);
 
 			uclass_next_device(&dev);
@@ -913,8 +928,20 @@ void eth_set_current(void)
 		act = getenv("ethact");
 		env_changed_id = env_id;
 	}
-	if (act != NULL)
+
+	if (act == NULL) {
+		char *ethprime = getenv("ethprime");
+		void *dev = NULL;
+
+		if (ethprime)
+			dev = eth_get_dev_by_name(ethprime);
+		if (dev)
+			eth_set_dev(dev);
+		else
+			eth_set_dev(NULL);
+	} else {
 		eth_set_dev(eth_get_dev_by_name(act));
+	}
 
 	eth_current_changed();
 }
diff --git a/test/dm/eth.c b/test/dm/eth.c
index 5688b71..96e3c46 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -60,3 +60,23 @@ static int dm_test_eth_alias(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
+
+static int dm_test_eth_prime(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+
+	/* Expected to be "eth at 10003000" because of ethprime variable */
+	setenv("ethact", NULL);
+	setenv("ethprime", "eth5");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10003000", getenv("ethact"));
+
+	/* Expected to be "eth at 10002000" because it is first */
+	setenv("ethact", NULL);
+	setenv("ethprime", NULL);
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	return 0;
+}
+DM_TEST(dm_test_eth_prime, DM_TESTF_SCAN_FDT);
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 21/27] test: dm: eth: Add testing for ethrotate env var
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (19 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 20/27] dm: eth: Add support for ethprime env var Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04 18:35           ` Simon Glass
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 22/27] sandbox: eth: Add ability to disable ping reply in sandbox eth driver Joe Hershberger
                           ` (6 subsequent siblings)
  27 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

Make sure that the ethrotate behavior occurs as expected.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v5:
-Added a test for skipping un-probe-able devices

Changes in v4:
-Added testing for ethrotate

Changes in v3: None
Changes in v2: None

 test/dm/eth.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/test/dm/eth.c b/test/dm/eth.c
index 96e3c46..9b55013 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -80,3 +80,45 @@ static int dm_test_eth_prime(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_eth_prime, DM_TESTF_SCAN_FDT);
+
+static int dm_test_eth_rotate(struct dm_test_state *dms)
+{
+	char ethaddr[18];
+
+	/* Invalidate eth1's MAC address */
+	NetPingIP = string_to_ip("1.1.2.2");
+	strcpy(ethaddr, getenv("eth1addr"));
+	setenv("eth1addr", NULL);
+
+	/* Make sure that the default is to rotate to the next interface */
+	setenv("ethact", "eth at 10004000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	/* If ethrotate is no, then we should fail on a bad MAC */
+	setenv("ethact", "eth at 10004000");
+	setenv("ethrotate", "no");
+	ut_asserteq(-1, NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	/* Restore the env */
+	setenv("eth1addr", ethaddr);
+	setenv("ethrotate", NULL);
+
+	/* Invalidate eth0's MAC address */
+	strcpy(ethaddr, getenv("ethaddr"));
+	setenv(".flags", "ethaddr");
+	setenv("ethaddr", NULL);
+
+	/* Make sure we can skip invalid devices */
+	setenv("ethact", "eth at 10004000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	/* Restore the env */
+	setenv("ethaddr", ethaddr);
+	setenv(".flags", NULL);
+
+	return 0;
+}
+DM_TEST(dm_test_eth_rotate, DM_TESTF_SCAN_FDT);
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 22/27] sandbox: eth: Add ability to disable ping reply in sandbox eth driver
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (20 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 21/27] test: dm: eth: Add testing for ethrotate " Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04 18:35           ` Simon Glass
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 23/27] test: dm: net: Add a test of the netretry behavior Joe Hershberger
                           ` (5 subsequent siblings)
  27 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

This is needed to test the netretry functionality (make the command fail
on a sandbox eth device).

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v5:
-Use a function call to change mock driver behavior

Changes in v4:
-Add ability to disable ping reply in sandbox eth driver

Changes in v3: None
Changes in v2: None

 arch/sandbox/include/asm/eth.h | 15 +++++++++++++++
 drivers/net/sandbox.c          | 10 ++++++++++
 2 files changed, 25 insertions(+)
 create mode 100644 arch/sandbox/include/asm/eth.h

diff --git a/arch/sandbox/include/asm/eth.h b/arch/sandbox/include/asm/eth.h
new file mode 100644
index 0000000..4b79ede
--- /dev/null
+++ b/arch/sandbox/include/asm/eth.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __ETH_H
+#define __ETH_H
+
+void sandbox_eth_disable_response(int index, bool disable);
+
+#endif /* __ETH_H */
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
index cb69a95..0dfd144 100644
--- a/drivers/net/sandbox.c
+++ b/drivers/net/sandbox.c
@@ -29,6 +29,13 @@ struct eth_sandbox_priv {
 	int recv_packet_length;
 };
 
+static bool disabled[8] = {false};
+
+void sandbox_eth_disable_response(int index, bool disable)
+{
+	disabled[index] = disable;
+}
+
 static int sb_eth_start(struct udevice *dev)
 {
 	struct eth_sandbox_priv *priv = dev_get_priv(dev);
@@ -48,6 +55,9 @@ static int sb_eth_send(struct udevice *dev, void *packet, int length)
 
 	debug("eth_sandbox: Send packet %d\n", length);
 
+	if (disabled[dev->seq])
+		return 0;
+
 	if (ntohs(eth->et_protlen) == PROT_ARP) {
 		struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
 
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 23/27] test: dm: net: Add a test of the netretry behavior
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (21 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 22/27] sandbox: eth: Add ability to disable ping reply in sandbox eth driver Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04 18:35           ` Simon Glass
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 24/27] sandbox: eth: Add a bridge to a real network for sandbox Joe Hershberger
                           ` (4 subsequent siblings)
  27 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

The effect of the "netretry" env var was recently changed. This test
checks that behavior.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v5:
-Added comments about test cases
-Switched to function to control state of mock driver

Changes in v4:
-Updated expected behavior based on changes to the NetLoop

Changes in v3:
-Added testing for netretry

Changes in v2: None

 test/dm/eth.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/test/dm/eth.c b/test/dm/eth.c
index 9b55013..a0e9359 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -14,6 +14,7 @@
 #include <fdtdec.h>
 #include <malloc.h>
 #include <net.h>
+#include <asm/eth.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -122,3 +123,34 @@ static int dm_test_eth_rotate(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_eth_rotate, DM_TESTF_SCAN_FDT);
+
+static int dm_test_net_retry(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+
+	/*
+	 * eth1 is disabled and netretry is yes, so the ping should succeed and
+	 * the active device should be eth0
+	 */
+	sandbox_eth_disable_response(1, true);
+	setenv("ethact", "eth at 10004000");
+	setenv("netretry", "yes");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	/*
+	 * eth1 is disabled and netretry is no, so the ping should fail and the
+	 * active device should be eth1
+	 */
+	setenv("ethact", "eth at 10004000");
+	setenv("netretry", "no");
+	ut_asserteq(-1, NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	/* Restore the env */
+	setenv("netretry", NULL);
+	sandbox_eth_disable_response(1, false);
+
+	return 0;
+}
+DM_TEST(dm_test_net_retry, DM_TESTF_SCAN_FDT);
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 24/27] sandbox: eth: Add a bridge to a real network for sandbox
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (22 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 23/27] test: dm: net: Add a test of the netretry behavior Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04 18:35           ` Simon Glass
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 25/27] sandbox: Enable DHCP and IP defrag Joe Hershberger
                           ` (3 subsequent siblings)
  27 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

Implement a bridge between u-boot's network stack and Linux's raw packet
API allowing the sandbox to send and receive packets using the host
machine's network interface.

This raw Ethernet API requires elevated privileges.  You can either run
as root, or you can add the capability needed like so:

sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v5:
-Added fallback for setting promiscuous mode
-Added help to Kconfig
-Added more details and examples in the README
-Check for NULL when reading fdt for host interface
-Check for malloc failure
-Remove cast of pointer passed to free
-Remove the empty sb_eth_raw_remove function
-Return -errno in from send and recv
-Return errno from recv
-Set the socket to non-blocking
-Use net_rx_packets instead of a stack buffer

Changes in v4:
-Add comments to priv struct definition
-Added comments to README.sandbox
-Clean up the interface to sandbox's eth-raw-os by passing priv to raw-os
-Cleanup var definition order
-Fixed the MAC address limitation (now all traffic uses MAC address from env)
-Move os file to arch
-Moved config to Kconfig
-Use accessors for platdata and priv

Changes in v3:
-Made the os raw packet support for sandbox eth build and work.

Changes in v2:
-Added the raw packet proof-of-concept patch.

 arch/sandbox/Kconfig                  |   3 +
 arch/sandbox/cpu/Makefile             |  10 +++
 arch/sandbox/cpu/eth-raw-os.c         | 140 ++++++++++++++++++++++++++++++++++
 arch/sandbox/dts/sandbox.dts          |   6 ++
 arch/sandbox/include/asm/eth-raw-os.h |  32 ++++++++
 board/sandbox/README.sandbox          |  52 +++++++++++++
 drivers/net/Kconfig                   |  10 +++
 drivers/net/Makefile                  |   1 +
 drivers/net/sandbox-raw.c             |  98 ++++++++++++++++++++++++
 9 files changed, 352 insertions(+)
 create mode 100644 arch/sandbox/cpu/eth-raw-os.c
 create mode 100644 arch/sandbox/include/asm/eth-raw-os.h
 create mode 100644 drivers/net/sandbox-raw.c

diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index 186b58d..f84b3fc 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -43,4 +43,7 @@ config NETDEVICES
 config DM_ETH
 	default y
 
+config ETH_SANDBOX_RAW
+	default y
+
 endmenu
diff --git a/arch/sandbox/cpu/Makefile b/arch/sandbox/cpu/Makefile
index 7d4410c..1b42fee 100644
--- a/arch/sandbox/cpu/Makefile
+++ b/arch/sandbox/cpu/Makefile
@@ -8,6 +8,7 @@
 #
 
 obj-y	:= cpu.o os.o start.o state.o
+obj-$(CONFIG_ETH_SANDBOX_RAW)	+= eth-raw-os.o
 obj-$(CONFIG_SANDBOX_SDL)	+= sdl.o
 
 # os.c is build in the system environment, so needs standard includes
@@ -20,3 +21,12 @@ $(obj)/os.o: $(src)/os.c FORCE
 	$(call if_changed_dep,cc_os.o)
 $(obj)/sdl.o: $(src)/sdl.c FORCE
 	$(call if_changed_dep,cc_os.o)
+
+# eth-raw-os.c is built in the system env, so needs standard includes
+# CFLAGS_REMOVE_eth-raw-os.o cannot be used to drop header include path
+quiet_cmd_cc_eth-raw-os.o = CC $(quiet_modtag)  $@
+cmd_cc_eth-raw-os.o = $(CC) $(filter-out -nostdinc, \
+	$(patsubst -I%,-idirafter%,$(c_flags))) -c -o $@ $<
+
+$(obj)/eth-raw-os.o: $(src)/eth-raw-os.c FORCE
+	$(call if_changed_dep,cc_eth-raw-os.o)
diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c
new file mode 100644
index 0000000..601205a
--- /dev/null
+++ b/arch/sandbox/cpu/eth-raw-os.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <asm/eth-raw-os.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+
+int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
+			    struct eth_sandbox_raw_priv *priv)
+{
+	struct sockaddr_ll *device;
+	struct packet_mreq mr;
+	int ret;
+	int flags;
+
+	/* Prepare device struct */
+	priv->device = malloc(sizeof(struct sockaddr_ll));
+	if (priv->device == NULL)
+		return -ENOMEM;
+	device = priv->device;
+	memset(device, 0, sizeof(struct sockaddr_ll));
+	device->sll_ifindex = if_nametoindex(ifname);
+	device->sll_family = AF_PACKET;
+	memcpy(device->sll_addr, ethmac, 6);
+	device->sll_halen = htons(6);
+
+	/* Open socket */
+	priv->sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+	if (priv->sd < 0) {
+		printf("Failed to open socket: %d %s\n", errno,
+		       strerror(errno));
+		return -errno;
+	}
+	/* Bind to the specified interface */
+	ret = setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
+		   strlen(ifname) + 1);
+	if (ret < 0) {
+		printf("Failed to bind to '%s': %d %s\n", ifname, errno,
+		       strerror(errno));
+		return -errno;
+	}
+
+	/* Make the socket non-blocking */
+	flags = fcntl(priv->sd, F_GETFL, 0);
+	fcntl(priv->sd, F_SETFL, flags | O_NONBLOCK);
+
+	/* Enable promiscuous mode to receive responses meant for us */
+	mr.mr_ifindex = device->sll_ifindex;
+	mr.mr_type = PACKET_MR_PROMISC;
+	ret = setsockopt(priv->sd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
+		   &mr, sizeof(mr));
+	if (ret < 0) {
+		struct ifreq ifr;
+
+		printf("Failed to set promiscuous mode: %d %s\n"
+		       "Falling back to the old \"flags\" way...\n",
+			errno, strerror(errno));
+		strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+		if (ioctl(priv->sd, SIOCGIFFLAGS, &ifr) < 0) {
+			printf("Failed to read flags: %d %s\n", errno,
+			       strerror(errno));
+			return -errno;
+		}
+		ifr.ifr_flags |= IFF_PROMISC;
+		if (ioctl(priv->sd, SIOCSIFFLAGS, &ifr) < 0) {
+			printf("Failed to write flags: %d %s\n", errno,
+			       strerror(errno));
+			return -errno;
+		}
+	}
+	return 0;
+}
+
+int sandbox_eth_raw_os_send(void *packet, int length,
+			    const struct eth_sandbox_raw_priv *priv)
+{
+	int retval;
+
+	if (!priv->sd || !priv->device)
+		return -EINVAL;
+
+	retval = sendto(priv->sd, packet, length, 0,
+			(struct sockaddr *)priv->device,
+			sizeof(struct sockaddr_ll));
+	if (retval < 0) {
+		printf("Failed to send packet: %d %s\n", errno,
+		       strerror(errno));
+		return -errno;
+	}
+	return retval;
+}
+
+int sandbox_eth_raw_os_recv(void *packet, int *length,
+			    const struct eth_sandbox_raw_priv *priv)
+{
+	int retval;
+	int saddr_size;
+
+	if (!priv->sd || !priv->device)
+		return -EINVAL;
+	saddr_size = sizeof(struct sockaddr);
+	retval = recvfrom(priv->sd, packet, 1536, 0,
+			  (struct sockaddr *)priv->device,
+			  (socklen_t *)&saddr_size);
+	*length = 0;
+	if (retval >= 0) {
+		*length = retval;
+		return 0;
+	}
+	/* The socket is non-blocking, so expect EAGAIN when there is no data */
+	if (errno == EAGAIN)
+		return 0;
+	return -errno;
+}
+
+void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv)
+{
+	free(priv->device);
+	priv->device = NULL;
+	close(priv->sd);
+	priv->sd = -1;
+}
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index c2a3304..8002196 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -186,4 +186,10 @@
 		reg = <0x10002000 0x1000>;
 		fake-host-hwaddr = [00 00 66 44 22 00];
 	};
+
+	eth at 80000000 {
+		compatible = "sandbox,eth-raw";
+		reg = <0x80000000 0x1000>;
+		host-raw-interface = "eth0";
+	};
 };
diff --git a/arch/sandbox/include/asm/eth-raw-os.h b/arch/sandbox/include/asm/eth-raw-os.h
new file mode 100644
index 0000000..df60c4f
--- /dev/null
+++ b/arch/sandbox/include/asm/eth-raw-os.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __ETH_RAW_OS_H
+#define __ETH_RAW_OS_H
+
+/**
+ * struct eth_sandbox_raw_priv - raw socket session
+ *
+ * sd: socket descriptor - the open socket during a session
+ * device: struct sockaddr_ll - the host interface packets move to/from
+ */
+struct eth_sandbox_raw_priv {
+	int sd;
+	void *device;
+};
+
+int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
+			    struct eth_sandbox_raw_priv *priv);
+int sandbox_eth_raw_os_send(void *packet, int length,
+			    const struct eth_sandbox_raw_priv *priv);
+int sandbox_eth_raw_os_recv(void *packet, int *length,
+			    const struct eth_sandbox_raw_priv *priv);
+void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv);
+
+#endif /* __ETH_RAW_OS_H */
diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
index c1f5f7e..aedf05a 100644
--- a/board/sandbox/README.sandbox
+++ b/board/sandbox/README.sandbox
@@ -190,6 +190,58 @@ Also sandbox uses generic board (CONFIG_SYS_GENERIC_BOARD) and supports
 driver model (CONFIG_DM) and associated commands.
 
 
+Linux RAW Networking Bridge
+---------------------------
+
+The sandbox_eth_raw driver bridges traffic between the bottom of the network
+stack and the RAW sockets API in Linux. This allows much of the u-boot network
+functionality to be tested in sandbox against real network traffic.
+
+For Ethernet network adapters, the bridge utilizes the RAW AF_PACKET API.  This
+is needed to get access to the lowest level of the network stack in Linux. This
+means that all of the Ethernet frame is included. This allows the u-boot network
+stack to be fully used. In other words, nothing about the Linux network stack is
+involved in forming the packets that end up on the wire. To receive the
+responses to packets sent from U-Boot the network interface has to be set to
+promiscuous mode so that the network card won't filter out packets not destined
+for its configured (on Linux) MAC address.
+
+The RAW sockets Ethernet API requires elevated privileges in Linux. You can
+either run as root, or you can add the capability needed like so:
+
+sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot
+
+The default device tree for sandbox includes an entry for eth0 on the sandbox
+host machine whose alias is "eth1". The following are a few examples of network
+operations being tested on the eth0 interface.
+
+sudo u-boot -d u-boot.dtb
+
+DHCP
+....
+
+set autoload no
+set ethact eth1
+dhcp
+
+PING
+....
+
+set autoload no
+set ethact eth1
+dhcp
+ping $gatewayip
+
+TFTP
+....
+
+set autoload no
+set ethact eth1
+dhcp
+set serverip WWW.XXX.YYY.ZZZ
+tftpboot u-boot.bin
+
+
 SPI Emulation
 -------------
 
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index e46e57b..601366f 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -29,4 +29,14 @@ config ETH_SANDBOX
 
 	  This driver is particularly useful in the test/dm/eth.c tests
 
+config ETH_SANDBOX_RAW
+	depends on DM_ETH && SANDBOX
+	default y
+	bool "Sandbox: Bridge to Linux Raw Sockets"
+	help
+	  This driver is a bridge from the bottom of the network stack
+	  in u-boot to the RAW AF_PACKET API in Linux. This allows real
+	  network traffic to be tested from within sandbox. See
+	  board/sandbox/README.sandbox for more details.
+
 endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 15dc431..2659a8a 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_PCNET) += pcnet.o
 obj-$(CONFIG_RTL8139) += rtl8139.o
 obj-$(CONFIG_RTL8169) += rtl8169.o
 obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
+obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o
 obj-$(CONFIG_SH_ETHER) += sh_eth.o
 obj-$(CONFIG_SMC91111) += smc91111.o
 obj-$(CONFIG_SMC911X) += smc911x.o
diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
new file mode 100644
index 0000000..435b874
--- /dev/null
+++ b/drivers/net/sandbox-raw.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <asm/eth-raw-os.h>
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+
+static int sb_eth_raw_start(struct udevice *dev)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	const char *interface;
+
+	debug("eth_sandbox_raw: Start\n");
+
+	interface = fdt_getprop(gd->fdt_blob, dev->of_offset,
+					    "host-raw-interface", NULL);
+	if (interface == NULL)
+		return -EINVAL;
+
+	return sandbox_eth_raw_os_start(interface, pdata->enetaddr, priv);
+}
+
+static int sb_eth_raw_send(struct udevice *dev, void *packet, int length)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+
+	debug("eth_sandbox_raw: Send packet %d\n", length);
+
+	return sandbox_eth_raw_os_send(packet, length, priv);
+}
+
+static int sb_eth_raw_recv(struct udevice *dev, uchar **packetp)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+	int retval;
+	int length;
+
+	retval = sandbox_eth_raw_os_recv(net_rx_packets[0], &length, priv);
+
+	if (!retval && length) {
+		debug("eth_sandbox_raw: received packet %d\n",
+		      length);
+		*packetp = net_rx_packets[0];
+		return length;
+	}
+	return retval;
+}
+
+static void sb_eth_raw_stop(struct udevice *dev)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+
+	debug("eth_sandbox_raw: Stop\n");
+
+	sandbox_eth_raw_os_stop(priv);
+}
+
+static const struct eth_ops sb_eth_raw_ops = {
+	.start			= sb_eth_raw_start,
+	.send			= sb_eth_raw_send,
+	.recv			= sb_eth_raw_recv,
+	.stop			= sb_eth_raw_stop,
+};
+
+static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	pdata->iobase = dev_get_addr(dev);
+	return 0;
+}
+
+static const struct udevice_id sb_eth_raw_ids[] = {
+	{ .compatible = "sandbox,eth-raw" },
+	{ }
+};
+
+U_BOOT_DRIVER(eth_sandbox_raw) = {
+	.name	= "eth_sandbox_raw",
+	.id	= UCLASS_ETH,
+	.of_match = sb_eth_raw_ids,
+	.ofdata_to_platdata = sb_eth_raw_ofdata_to_platdata,
+	.ops	= &sb_eth_raw_ops,
+	.priv_auto_alloc_size = sizeof(struct eth_sandbox_raw_priv),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 25/27] sandbox: Enable DHCP and IP defrag
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (23 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 24/27] sandbox: eth: Add a bridge to a real network for sandbox Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 26/27] sandbox: eth: Add support for using the 'lo' interface Joe Hershberger
                           ` (2 subsequent siblings)
  27 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

This is now testable via the eth-raw interface

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v5: None
Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 include/configs/sandbox.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index caf9f5a..034050e 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -127,6 +127,14 @@
 #include <config_cmd_default.h>
 
 #define CONFIG_CMD_PING
+#define CONFIG_CMD_DHCP
+#define CONFIG_BOOTP_DNS
+#define CONFIG_BOOTP_DNS2
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_SEND_HOSTNAME
+#define CONFIG_BOOTP_SERVERIP
+#define CONFIG_BOOTP_SUBNETMASK
+#define CONFIG_IP_DEFRAG
 
 #define CONFIG_CMD_HASH
 #define CONFIG_HASH_VERIFY
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 26/27] sandbox: eth: Add support for using the 'lo' interface
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (24 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 25/27] sandbox: Enable DHCP and IP defrag Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04 18:35           ` Simon Glass
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 27/27] net: Improve error handling Joe Hershberger
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
  27 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

The 'lo' interface on Linux doesn't support thinks like ARP or
link-layer access like we use to talk to a normal network interface.
A higher-level network API must be used to access localhost.

As written, this interface is limited to not supporting ICMP since the
API doesn't allow the socket to be opened for all IP traffic and be able
to receive at the same time. UDP is far more useful to test with, so it
was selected over ICMP. Ping won't work, but things like TFTP should
work.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v5:
-Add details about lo support to the README
-Remove socket timeout
-Separate init to 2 helper static functions
-Set the socket to non-blocking
-Use INADDR_LOOPBACK
-Use more verbose comments

Changes in v4:
-Added support for the 'lo' network interface

Changes in v3: None
Changes in v2: None

 arch/sandbox/cpu/eth-raw-os.c         | 113 +++++++++++++++++++++++++++++++++-
 arch/sandbox/dts/sandbox.dts          |  10 +++
 arch/sandbox/include/asm/eth-raw-os.h |  10 ++-
 board/sandbox/README.sandbox          |  22 +++++++
 drivers/net/sandbox-raw.c             |  71 ++++++++++++++++++++-
 5 files changed, 221 insertions(+), 5 deletions(-)

diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c
index 601205a..b76a731 100644
--- a/arch/sandbox/cpu/eth-raw-os.c
+++ b/arch/sandbox/cpu/eth-raw-os.c
@@ -12,6 +12,8 @@
 #include <fcntl.h>
 #include <net/if.h>
 #include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -20,10 +22,11 @@
 #include <sys/socket.h>
 #include <unistd.h>
 
+#include <arpa/inet.h>
 #include <linux/if_ether.h>
 #include <linux/if_packet.h>
 
-int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
+static int _raw_packet_start(const char *ifname, unsigned char *ethmac,
 			    struct eth_sandbox_raw_priv *priv)
 {
 	struct sockaddr_ll *device;
@@ -89,14 +92,114 @@ int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
 	return 0;
 }
 
+static int _local_inet_start(struct eth_sandbox_raw_priv *priv)
+{
+	struct sockaddr_in *device;
+	int ret;
+	int flags;
+	int one = 1;
+
+	/* Prepare device struct */
+	priv->device = malloc(sizeof(struct sockaddr_in));
+	if (priv->device == NULL)
+		return -ENOMEM;
+	device = priv->device;
+	memset(device, 0, sizeof(struct sockaddr_in));
+	device->sin_family = AF_INET;
+	device->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+	/**
+	 * Open socket
+	 *  Since we specify UDP here, any incoming ICMP packets will
+	 *  not be received, so things like ping will not work on this
+	 *  localhost interface.
+	 */
+	priv->sd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
+	if (priv->sd < 0) {
+		printf("Failed to open socket: %d %s\n", errno,
+		       strerror(errno));
+		return -errno;
+	}
+
+	/* Make the socket non-blocking */
+	flags = fcntl(priv->sd, F_GETFL, 0);
+	fcntl(priv->sd, F_SETFL, flags | O_NONBLOCK);
+
+	/* Include the UDP/IP headers on send and receive */
+	ret = setsockopt(priv->sd, IPPROTO_IP, IP_HDRINCL, &one,
+			 sizeof(one));
+	if (ret < 0) {
+		printf("Failed to set header include option: %d %s\n", errno,
+		       strerror(errno));
+		return -errno;
+	}
+	priv->local_bind_sd = -1;
+	priv->local_bind_udp_port = 0;
+	return 0;
+}
+
+int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
+			    struct eth_sandbox_raw_priv *priv)
+{
+	if (priv->local)
+		return _local_inet_start(priv);
+	else
+		return _raw_packet_start(ifname, ethmac, priv);
+}
+
 int sandbox_eth_raw_os_send(void *packet, int length,
-			    const struct eth_sandbox_raw_priv *priv)
+			    struct eth_sandbox_raw_priv *priv)
 {
 	int retval;
+	struct udphdr *udph = packet + sizeof(struct iphdr);
 
 	if (!priv->sd || !priv->device)
 		return -EINVAL;
 
+	/*
+	 * This block of code came about when testing tftp on the localhost
+	 * interface. When using the RAW AF_INET API, the network stack is still
+	 * in play responding to incoming traffic based on open "ports". Since
+	 * it is raw (at the IP layer, no Ethernet) the network stack tells the
+	 * TFTP server that the port it responded to is closed. This causes the
+	 * TFTP transfer to be aborted. This block of code inspects the outgoing
+	 * packet as formulated by the u-boot network stack to determine the
+	 * source port (that the TFTP server will send packets back to) and
+	 * opens a typical UDP socket on that port, thus preventing the network
+	 * stack from sending that ICMP message claiming that the port has no
+	 * bound socket.
+	 */
+	if (priv->local && (priv->local_bind_sd == -1 ||
+			    priv->local_bind_udp_port != udph->source)) {
+		struct iphdr *iph = packet;
+		struct sockaddr_in addr;
+
+		if (priv->local_bind_sd != -1)
+			close(priv->local_bind_sd);
+
+		/* A normal UDP socket is required to bind */
+		priv->local_bind_sd = socket(AF_INET, SOCK_DGRAM, 0);
+		if (priv->local_bind_sd < 0) {
+			printf("Failed to open bind sd: %d %s\n", errno,
+			       strerror(errno));
+			return -errno;
+		}
+		priv->local_bind_udp_port = udph->source;
+
+		/**
+		 * Bind the UDP port that we intend to use as our source port
+		 * so that the kernel will not send an ICMP port unreachable
+		 * message to the server
+		 */
+		addr.sin_family = AF_INET;
+		addr.sin_port = udph->source;
+		addr.sin_addr.s_addr = iph->saddr;
+		retval = bind(priv->local_bind_sd, &addr, sizeof(addr));
+		if (retval < 0)
+			printf("Failed to bind: %d %s\n", errno,
+			       strerror(errno));
+	}
+
 	retval = sendto(priv->sd, packet, length, 0,
 			(struct sockaddr *)priv->device,
 			sizeof(struct sockaddr_ll));
@@ -137,4 +240,10 @@ void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv)
 	priv->device = NULL;
 	close(priv->sd);
 	priv->sd = -1;
+	if (priv->local) {
+		if (priv->local_bind_sd != -1)
+			close(priv->local_bind_sd);
+		priv->local_bind_sd = -1;
+		priv->local_bind_udp_port = 0;
+	}
 }
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 8002196..0eaa5a5 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -4,6 +4,10 @@
 	#address-cells = <1>;
 	#size-cells = <0>;
 
+	aliases {
+		eth5 = "/eth at 90000000";
+	};
+
 	chosen {
 		stdout-path = "/serial";
 	};
@@ -192,4 +196,10 @@
 		reg = <0x80000000 0x1000>;
 		host-raw-interface = "eth0";
 	};
+
+	eth at 90000000 {
+		compatible = "sandbox,eth-raw";
+		reg = <0x90000000 0x1000>;
+		host-raw-interface = "lo";
+	};
 };
diff --git a/arch/sandbox/include/asm/eth-raw-os.h b/arch/sandbox/include/asm/eth-raw-os.h
index df60c4f..ed4b2e2 100644
--- a/arch/sandbox/include/asm/eth-raw-os.h
+++ b/arch/sandbox/include/asm/eth-raw-os.h
@@ -15,16 +15,24 @@
  *
  * sd: socket descriptor - the open socket during a session
  * device: struct sockaddr_ll - the host interface packets move to/from
+ * local: 1 or 0 to select the local interface ('lo') or not
+ * local_bindsd: socket descriptor to prevent the kernel from sending
+ *		 a message to the server claiming the port is
+ *		 unreachable
+ * local_bind_udp_port: The UDP port number that we bound to
  */
 struct eth_sandbox_raw_priv {
 	int sd;
 	void *device;
+	int local;
+	int local_bind_sd;
+	unsigned short local_bind_udp_port;
 };
 
 int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
 			    struct eth_sandbox_raw_priv *priv);
 int sandbox_eth_raw_os_send(void *packet, int length,
-			    const struct eth_sandbox_raw_priv *priv);
+			    struct eth_sandbox_raw_priv *priv);
 int sandbox_eth_raw_os_recv(void *packet, int *length,
 			    const struct eth_sandbox_raw_priv *priv);
 void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv);
diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
index aedf05a..73743e0 100644
--- a/board/sandbox/README.sandbox
+++ b/board/sandbox/README.sandbox
@@ -241,6 +241,28 @@ dhcp
 set serverip WWW.XXX.YYY.ZZZ
 tftpboot u-boot.bin
 
+The bridge also support (to a lesser extent) the localhost inderface, 'lo'.
+
+The 'lo' interface cannot use the RAW AF_PACKET API because the lo interface
+doesn't support Ethernet-level traffic. It is a higher-level interface that is
+expected only to be used at the AF_INET level of the API. As such, the most raw
+we can get on that interface is the RAW AF_INET API on UDP. This allows us to
+set the IP_HDRINCL option to include everything except the Ethernet header in
+the packets we send and receive.
+
+Because only UDP is supported, ICMP traffic will not work, so expect that ping
+commands will time out.
+
+The default device tree for sandbox includes an entry for lo on the sandbox
+host machine whose alias is "eth5". The following is an example of a network
+operation being tested on the lo interface.
+
+TFTP
+....
+
+set ethact eth5
+tftpboot u-boot.bin
+
 
 SPI Emulation
 -------------
diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
index 435b874..91da5f5 100644
--- a/drivers/net/sandbox-raw.c
+++ b/drivers/net/sandbox-raw.c
@@ -15,6 +15,8 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static int reply_arp;
+static IPaddr_t arp_ip;
 
 static int sb_eth_raw_start(struct udevice *dev)
 {
@@ -29,6 +31,11 @@ static int sb_eth_raw_start(struct udevice *dev)
 	if (interface == NULL)
 		return -EINVAL;
 
+	if (strcmp(interface, "lo") == 0) {
+		priv->local = 1;
+		setenv("ipaddr", "127.0.0.1");
+		setenv("serverip", "127.0.0.1");
+	}
 	return sandbox_eth_raw_os_start(interface, pdata->enetaddr, priv);
 }
 
@@ -38,18 +45,78 @@ static int sb_eth_raw_send(struct udevice *dev, void *packet, int length)
 
 	debug("eth_sandbox_raw: Send packet %d\n", length);
 
+	if (priv->local) {
+		struct ethernet_hdr *eth = packet;
+
+		if (ntohs(eth->et_protlen) == PROT_ARP) {
+			struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
+
+			/**
+			 * localhost works on a higher-level API in Linux than
+			 * ARP packets, so fake it
+			 */
+			arp_ip = NetReadIP(&arp->ar_tpa);
+			reply_arp = 1;
+			return 0;
+		}
+		packet += ETHER_HDR_SIZE;
+		length -= ETHER_HDR_SIZE;
+	}
 	return sandbox_eth_raw_os_send(packet, length, priv);
 }
 
 static int sb_eth_raw_recv(struct udevice *dev, uchar **packetp)
 {
+	struct eth_pdata *pdata = dev_get_platdata(dev);
 	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
-	int retval;
+	int retval = 0;
 	int length;
 
-	retval = sandbox_eth_raw_os_recv(net_rx_packets[0], &length, priv);
+	if (reply_arp) {
+		struct arp_hdr *arp = (void *)net_rx_packets[0] +
+			ETHER_HDR_SIZE;
+
+		/*
+		 * Fake an ARP response. The u-boot network stack is sending an
+		 * ARP request (to find the MAC address to address the actual
+		 * packet to) and requires an ARP response to continue. Since
+		 * this is the localhost interface, there is no Etherent level
+		 * traffic at all, so there is no way to send an ARP request or
+		 * to get a response. For this reason we fake the response to
+		 * make the u-boot network stack happy.
+		 */
+		arp->ar_hrd = htons(ARP_ETHER);
+		arp->ar_pro = htons(PROT_IP);
+		arp->ar_hln = ARP_HLEN;
+		arp->ar_pln = ARP_PLEN;
+		arp->ar_op = htons(ARPOP_REPLY);
+		/* Any non-zero MAC address will work */
+		memset(&arp->ar_sha, 0x01, ARP_HLEN);
+		/* Use whatever IP we were looking for (always 127.0.0.1?) */
+		NetWriteIP(&arp->ar_spa, arp_ip);
+		memcpy(&arp->ar_tha, pdata->enetaddr, ARP_HLEN);
+		NetWriteIP(&arp->ar_tpa, NetOurIP);
+		length = ARP_HDR_SIZE;
+	} else {
+		/* If local, the Ethernet header won't be included; skip it */
+		uchar *pktptr = priv->local ?
+			net_rx_packets[0] + ETHER_HDR_SIZE : net_rx_packets[0];
+
+		retval = sandbox_eth_raw_os_recv(pktptr, &length, priv);
+	}
 
 	if (!retval && length) {
+		if (priv->local) {
+			struct ethernet_hdr *eth = (void *)net_rx_packets[0];
+
+			/* Fill in enough of the missing Ethernet header */
+			memcpy(eth->et_dest, pdata->enetaddr, ARP_HLEN);
+			memset(eth->et_src, 0x01, ARP_HLEN);
+			eth->et_protlen = htons(reply_arp ? PROT_ARP : PROT_IP);
+			reply_arp = 0;
+			length += ETHER_HDR_SIZE;
+		}
+
 		debug("eth_sandbox_raw: received packet %d\n",
 		      length);
 		*packetp = net_rx_packets[0];
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 27/27] net: Improve error handling
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (25 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 26/27] sandbox: eth: Add support for using the 'lo' interface Joe Hershberger
@ 2015-03-04  2:41         ` Joe Hershberger
  2015-03-04 18:35           ` Simon Glass
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
  27 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-04  2:41 UTC (permalink / raw)
  To: u-boot

Take a pass at plumbing errors through to the users of the network stack

Currently only the start() function errors will be returned from
NetLoop(). recv() tends not to have errors, so that is likely not worth
adding. send() certainly can return errors, but this patch does not
attempt to plumb them yet. halt() is not expected to error.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v5:
-New to v5

Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/net.h |  3 ++-
 net/eth.c     | 56 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 net/net.c     | 26 ++++++++++++++++++--------
 test/dm/eth.c |  4 ++--
 4 files changed, 70 insertions(+), 19 deletions(-)

diff --git a/include/net.h b/include/net.h
index 5846dfb..c702f2f 100644
--- a/include/net.h
+++ b/include/net.h
@@ -539,7 +539,7 @@ int NetLoop(enum proto_t);
 void	NetStop(void);
 
 /* Load failed.	 Start again. */
-void	NetStartAgain(void);
+int	NetStartAgain(void);
 
 /* Get size of the ethernet header when we send */
 int	NetEthHdrSize(void);
@@ -609,6 +609,7 @@ static inline void net_set_state(enum net_loop_state state)
 /* Transmit a packet */
 static inline void NetSendPacket(uchar *pkt, int len)
 {
+	/* Currently no way to return errors from eth_send() */
 	(void) eth_send(pkt, len);
 }
 
diff --git a/net/eth.c b/net/eth.c
index 9966cf0..81ca436 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -98,6 +98,9 @@ struct eth_uclass_priv {
 	struct udevice *current;
 };
 
+/* eth_errno - This stores the most recent failure code from DM functions */
+static int eth_errno;
+
 static struct eth_uclass_priv *eth_get_uclass_priv(void)
 {
 	struct uclass *uc;
@@ -118,20 +121,32 @@ static void eth_set_current_to_next(void)
 		uclass_first_device(UCLASS_ETH, &uc_priv->current);
 }
 
+/*
+ * Typically this will simply return the active device.
+ * In the case where the most recent active device was unset, this will attempt
+ * to return the first device. If that device doesn't exist or fails to probe,
+ * this function will return NULL.
+ */
 struct udevice *eth_get_dev(void)
 {
 	struct eth_uclass_priv *uc_priv;
 
 	uc_priv = eth_get_uclass_priv();
 	if (!uc_priv->current)
-		uclass_first_device(UCLASS_ETH,
+		eth_errno = uclass_first_device(UCLASS_ETH,
 				    &uc_priv->current);
 	return uc_priv->current;
 }
 
+/*
+ * Typically this will just store a device pointer.
+ * In case it was not probed, we will attempt to do so.
+ * dev may be NULL to unset the active device.
+ */
 static void eth_set_dev(struct udevice *dev)
 {
-	device_probe(dev);
+	if (dev && !device_active(dev))
+		eth_errno = device_probe(dev);
 	eth_get_uclass_priv()->current = dev;
 }
 
@@ -155,7 +170,14 @@ struct udevice *eth_get_dev_by_name(const char *devname)
 
 	uclass_get(UCLASS_ETH, &uc);
 	uclass_foreach_dev(it, uc) {
-		/* We need the seq to be valid, so make sure it's probed */
+		/*
+		 * We need the seq to be valid, so try to probe it.
+		 * If the probe fails, the seq will not match since it will be
+		 * -1 instead of what we are looking for.
+		 * We don't care about errors from probe here. Either they won't
+		 * match an alias or it will match a literal name and we'll pick
+		 * up the error when we try to probe again in eth_set_dev().
+		 */
 		device_probe(it);
 		/*
 		 * Check for the name or the sequence number to match
@@ -221,6 +243,7 @@ int eth_init(void)
 {
 	struct udevice *current;
 	struct udevice *old_current;
+	int ret = -ENODEV;
 
 	current = eth_get_dev();
 	if (!current) {
@@ -243,22 +266,29 @@ int eth_init(void)
 			else
 				memset(pdata->enetaddr, 0, 6);
 
-			if (eth_get_ops(current)->start(current) >= 0) {
+			ret = eth_get_ops(current)->start(current);
+			if (ret >= 0) {
 				struct eth_device_priv *priv =
 					current->uclass_priv;
 
 				priv->state = ETH_STATE_ACTIVE;
 				return 0;
 			}
-		}
+		} else
+			ret = eth_errno;
+
 		debug("FAIL\n");
 
-		/* This will ensure the new "current" attempted to probe */
+		/*
+		 * If ethrotate is enabled, this will change "current",
+		 * otherwise we will drop out of this while loop immediately
+		 */
 		eth_try_another(0);
+		/* This will ensure the new "current" attempted to probe */
 		current = eth_get_dev();
 	} while (old_current != current);
 
-	return -ENODEV;
+	return ret;
 }
 
 void eth_halt(void)
@@ -278,6 +308,7 @@ void eth_halt(void)
 int eth_send(void *packet, int length)
 {
 	struct udevice *current;
+	int ret;
 
 	current = eth_get_dev();
 	if (!current)
@@ -286,7 +317,12 @@ int eth_send(void *packet, int length)
 	if (!device_active(current))
 		return -EINVAL;
 
-	return eth_get_ops(current)->send(current, packet, length);
+	ret = eth_get_ops(current)->send(current, packet, length);
+	if (ret < 0) {
+		/* We cannot completely return the error at present */
+		debug("%s: send() returned error %d\n", __func__, ret);
+	}
+	return ret;
 }
 
 int eth_rx(void)
@@ -311,6 +347,10 @@ int eth_rx(void)
 		else
 			break;
 	}
+	if (ret < 0) {
+		/* We cannot completely return the error@present */
+		debug("%s: recv() returned error %d\n", __func__, ret);
+	}
 	return ret;
 }
 
diff --git a/net/net.c b/net/net.c
index afec443..69f38f7 100644
--- a/net/net.c
+++ b/net/net.c
@@ -84,6 +84,7 @@
 #include <common.h>
 #include <command.h>
 #include <environment.h>
+#include <errno.h>
 #include <net.h>
 #if defined(CONFIG_STATUS_LED)
 #include <miiphy.h>
@@ -333,7 +334,7 @@ void net_init(void)
 
 int NetLoop(enum proto_t protocol)
 {
-	int ret = -1;
+	int ret = -EINVAL;
 
 	NetRestarted = 0;
 	NetDevExists = 0;
@@ -345,9 +346,10 @@ int NetLoop(enum proto_t protocol)
 	if (eth_is_on_demand_init() || protocol != NETCONS) {
 		eth_halt();
 		eth_set_current();
-		if (eth_init() < 0) {
+		ret = eth_init();
+		if (ret < 0) {
 			eth_halt();
-			return -1;
+			return ret;
 		}
 	} else
 		eth_init_state_only();
@@ -370,7 +372,7 @@ restart:
 	case 1:
 		/* network not configured */
 		eth_halt();
-		return -1;
+		return -ENODEV;
 
 	case 2:
 		/* network device not configured */
@@ -484,6 +486,8 @@ restart:
 		/*
 		 *	Check the ethernet for a new packet.  The ethernet
 		 *	receive routine will process it.
+		 *	Most drivers return the most recent packet size, but not
+		 *	errors that may have happened.
 		 */
 		eth_rx();
 
@@ -537,7 +541,7 @@ restart:
 		}
 
 		if (net_state == NETLOOP_FAIL)
-			NetStartAgain();
+			ret = NetStartAgain();
 
 		switch (net_state) {
 
@@ -597,11 +601,12 @@ startAgainTimeout(void)
 	net_set_state(NETLOOP_RESTART);
 }
 
-void NetStartAgain(void)
+int NetStartAgain(void)
 {
 	char *nretry;
 	int retry_forever = 0;
 	unsigned long retrycnt = 0;
+	int ret;
 
 	nretry = getenv("netretry");
 	if (nretry) {
@@ -621,7 +626,11 @@ void NetStartAgain(void)
 	if ((!retry_forever) && (NetTryCount >= retrycnt)) {
 		eth_halt();
 		net_set_state(NETLOOP_FAIL);
-		return;
+		/*
+		 * We don't provide a way for the protocol to return an error,
+		 * but this is almost always the reason.
+		 */
+		return -ETIMEDOUT;
 	}
 
 	NetTryCount++;
@@ -630,7 +639,7 @@ void NetStartAgain(void)
 #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
 	eth_try_another(!NetRestarted);
 #endif
-	eth_init();
+	ret = eth_init();
 	if (NetRestartWrap) {
 		NetRestartWrap = 0;
 		if (NetDevExists) {
@@ -642,6 +651,7 @@ void NetStartAgain(void)
 	} else {
 		net_set_state(NETLOOP_RESTART);
 	}
+	return ret;
 }
 
 /**********************************************************************/
diff --git a/test/dm/eth.c b/test/dm/eth.c
index a0e9359..1923670 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -99,7 +99,7 @@ static int dm_test_eth_rotate(struct dm_test_state *dms)
 	/* If ethrotate is no, then we should fail on a bad MAC */
 	setenv("ethact", "eth at 10004000");
 	setenv("ethrotate", "no");
-	ut_asserteq(-1, NetLoop(PING));
+	ut_asserteq(-EINVAL, NetLoop(PING));
 	ut_asserteq_str("eth at 10004000", getenv("ethact"));
 
 	/* Restore the env */
@@ -144,7 +144,7 @@ static int dm_test_net_retry(struct dm_test_state *dms)
 	 */
 	setenv("ethact", "eth at 10004000");
 	setenv("netretry", "no");
-	ut_asserteq(-1, NetLoop(PING));
+	ut_asserteq(-ETIMEDOUT, NetLoop(PING));
 	ut_asserteq_str("eth at 10004000", getenv("ethact"));
 
 	/* Restore the env */
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 11/27] net: Access mapped physmem in net functions
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 11/27] net: Access mapped physmem in net functions Joe Hershberger
@ 2015-03-04 18:34           ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-04 18:34 UTC (permalink / raw)
  To: u-boot

On 3 March 2015 at 19:41, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Previously the net functions would access memory assuming physmem did
> not need to be mapped.  In sandbox, that's not the case.
>
> Now we map the physmem specified by the user in loadaddr to the buffer
> that represents that space.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v5:
> -Include new mapmem.h header
> -Unmap memory for consistency

Reviewed-by: Simon Glass <sjg@chromium.org>

>
> Changes in v4:
> -New to v4
>
> Changes in v3: None
> Changes in v2: None
>
>  net/nfs.c  | 6 +++++-
>  net/tftp.c | 6 +++++-
>  2 files changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/net/nfs.c b/net/nfs.c
> index 381b75f..8e05ae5 100644
> --- a/net/nfs.c
> +++ b/net/nfs.c
> @@ -26,6 +26,7 @@
>  #include <command.h>
>  #include <net.h>
>  #include <malloc.h>
> +#include <mapmem.h>
>  #include "nfs.h"
>  #include "bootp.h"
>
> @@ -93,7 +94,10 @@ store_block(uchar *src, unsigned offset, unsigned len)
>         } else
>  #endif /* CONFIG_SYS_DIRECT_FLASH_NFS */
>         {
> -               (void)memcpy((void *)(load_addr + offset), src, len);
> +               void *ptr = map_sysmem(load_addr + offset, len);
> +
> +               memcpy(ptr, src, len);
> +               unmap_sysmem(ptr);
>         }
>
>         if (NetBootFileXferSize < (offset+len))
> diff --git a/net/tftp.c b/net/tftp.c
> index 0a2c533..51c67be 100644
> --- a/net/tftp.c
> +++ b/net/tftp.c
> @@ -8,6 +8,7 @@
>
>  #include <common.h>
>  #include <command.h>
> +#include <mapmem.h>
>  #include <net.h>
>  #include "tftp.h"
>  #include "bootp.h"
> @@ -184,7 +185,10 @@ store_block(int block, uchar *src, unsigned len)
>         } else
>  #endif /* CONFIG_SYS_DIRECT_FLASH_TFTP */
>         {
> -               (void)memcpy((void *)(load_addr + offset), src, len);
> +               void *ptr = map_sysmem(load_addr + offset, len);
> +
> +               memcpy(ptr, src, len);
> +               unmap_sysmem(ptr);
>         }
>  #ifdef CONFIG_MCAST_TFTP
>         if (Multicast)
> --
> 1.7.11.5
>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 12/27] cmd: net: Clean up return codes
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 12/27] cmd: net: Clean up return codes Joe Hershberger
@ 2015-03-04 18:35           ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-04 18:35 UTC (permalink / raw)
  To: u-boot

On 3 March 2015 at 19:41, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The return codes in common/cmd_net.c had a number of inconsistencies.
> Update them to all use the enum from command.h
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v5:
> -New to v5
>
> Changes in v4: None
> Changes in v3: None
> Changes in v2: None
>
>  common/cmd_net.c | 45 +++++++++++++++++++++------------------------
>  1 file changed, 21 insertions(+), 24 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 13/27] dm: eth: Add basic driver model support to Ethernet stack
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 13/27] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
@ 2015-03-04 18:35           ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-04 18:35 UTC (permalink / raw)
  To: u-boot

On 3 March 2015 at 19:41, Joe Hershberger <joe.hershberger@ni.com> wrote:
> First just add support for MAC drivers.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v5:
> -Add a note to doc/README.drivers.eth about its obsolescence
> -Expanded the Kconfig help
> -Moved dm/ header
> -Use local var for priv in eth_get_dev()

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 14/27] net: Clean up network stack names used in DM drivers
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 14/27] net: Clean up network stack names used in DM drivers Joe Hershberger
@ 2015-03-04 18:35           ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-04 18:35 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 3 March 2015 at 19:41, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Take the opportunity to enforce better names on newly written or
> retrofitted Ethernet drivers.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v5:
> -New to v5
>
> Changes in v4: None
> Changes in v3: None
> Changes in v2: None
>
>  include/net.h |  9 ++++++++-
>  net/net.c     | 30 +++++++++++++++++++-----------
>  2 files changed, 27 insertions(+), 12 deletions(-)

Not entirely pleasant with the #ifdef, but I assume it would be an
easy follow-on patch to change this globally.

Reviewed-by: Simon Glass <sjg@chromium.org>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 15/27] dm: eth: Pass the packet pointer as a parameter to recv
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 15/27] dm: eth: Pass the packet pointer as a parameter to recv Joe Hershberger
@ 2015-03-04 18:35           ` Simon Glass
  2015-03-10 23:28             ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-03-04 18:35 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 3 March 2015 at 19:41, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Stop forcing drivers to call net_process_received_packet() - formerly
> called NetReceive(). Now the uclass will handle calling the driver for
> each packet until the driver errors or has nothing to return. The uclass
> will then pass the good packets off to the network stack by calling
> net_process_received_packet().
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v5:
> -New to v5
>
> Changes in v4: None
> Changes in v3: None
> Changes in v2: None
>
>  include/net.h |  2 +-
>  net/eth.c     | 13 ++++++++++++-
>  2 files changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/include/net.h b/include/net.h
> index 4e44832..37d1f36 100644
> --- a/include/net.h
> +++ b/include/net.h
> @@ -110,7 +110,7 @@ struct eth_pdata {
>  struct eth_ops {
>         int (*start)(struct udevice *dev);
>         int (*send)(struct udevice *dev, void *packet, int length);
> -       int (*recv)(struct udevice *dev);
> +       int (*recv)(struct udevice *dev, uchar **packetp);

Need to update docs above. With serial we return -EAGAIN when there is
nothing more to receive. So you might want to swallow that error
instead of returning it from eth_rx().

>         void (*stop)(struct udevice *dev);
>  #ifdef CONFIG_MCAST_TFTP
>         int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
> diff --git a/net/eth.c b/net/eth.c
> index 1abf027..b66d253 100644
> --- a/net/eth.c
> +++ b/net/eth.c
> @@ -259,6 +259,9 @@ int eth_send(void *packet, int length)
>  int eth_rx(void)
>  {
>         struct udevice *current;
> +       uchar *packet;
> +       int ret;
> +       int i;
>
>         current = eth_get_dev();
>         if (!current)
> @@ -267,7 +270,15 @@ int eth_rx(void)
>         if (!device_active(current))
>                 return -EINVAL;
>
> -       return eth_get_ops(current)->recv(current);
> +       /* Process up to 32 packets at one time */
> +       for (i = 0; i < 32; i++) {
> +               ret = eth_get_ops(current)->recv(current, &packet);
> +               if (ret > 0)
> +                       net_process_received_packet(packet, ret);
> +               else
> +                       break;
> +       }
> +       return ret;
>  }
>
>  static int eth_write_hwaddr(struct udevice *dev)
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 16/27] sandbox: eth: Add network support to sandbox
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 16/27] sandbox: eth: Add network support to sandbox Joe Hershberger
@ 2015-03-04 18:35           ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-04 18:35 UTC (permalink / raw)
  To: u-boot

On 3 March 2015 at 19:41, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Add basic network support to sandbox which includes a network driver.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v5:
> -Added help to the sandbox eth mock driver Kconfig entry

Looks good.

Reviewed-by: Simon Glass <sjg@chromium.org>

>
> Changes in v4:
> -Cleaned up sandbox EXTRA_ENV define
> -Moved config to Kconfig
>
> Changes in v3:
> -Added 2 more ethaddr to sandbox
> -Print which device in the debug write hwaddr
>
> Changes in v2:
> -Change printfs to debug in sandbox driver
> -Remove unused priv struct for sandbox driver
>
>  arch/sandbox/Kconfig         |  9 +++++
>  arch/sandbox/dts/sandbox.dts |  4 +++
>  board/sandbox/README.sandbox |  4 +--
>  drivers/net/Kconfig          | 23 ++++++++++++
>  drivers/net/Makefile         |  1 +
>  drivers/net/sandbox.c        | 84 ++++++++++++++++++++++++++++++++++++++++++++
>  include/configs/sandbox.h    | 16 +++++----
>  7 files changed, 133 insertions(+), 8 deletions(-)
>  create mode 100644 drivers/net/sandbox.c

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 19/27] dm: eth: Add support for aliases
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 19/27] dm: eth: Add support for aliases Joe Hershberger
@ 2015-03-04 18:35           ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-04 18:35 UTC (permalink / raw)
  To: u-boot

On 3 March 2015 at 19:41, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Allow network devices to be referred to as "eth0" instead of
> "eth at 12345678" when specified in ethact.
>
> Add tests to verify this behavior.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v5:
> -Added a comment about devname
> -Only check for alias if the name is long enough

Reviewed-by: Simon Glass <sjg@chromium.org>


>
> Changes in v4:
> -Use only the seq from DM to find aliases
>
> Changes in v3:
> -Added support for aliases
>
> Changes in v2: None
>
>  include/configs/sandbox.h |  2 +-
>  include/net.h             |  5 +++++
>  net/eth.c                 | 50 ++++++++++++++++++++++++++++++++++++++---------
>  test/dm/eth.c             | 24 +++++++++++++++++++++++
>  test/dm/test.dts          |  4 +++-
>  5 files changed, 74 insertions(+), 11 deletions(-)
>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 21/27] test: dm: eth: Add testing for ethrotate env var
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 21/27] test: dm: eth: Add testing for ethrotate " Joe Hershberger
@ 2015-03-04 18:35           ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-04 18:35 UTC (permalink / raw)
  To: u-boot

On 3 March 2015 at 19:41, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Make sure that the ethrotate behavior occurs as expected.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v5:
> -Added a test for skipping un-probe-able devices
>
> Changes in v4:
> -Added testing for ethrotate
>
> Changes in v3: None
> Changes in v2: None
>
>  test/dm/eth.c | 42 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 42 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 23/27] test: dm: net: Add a test of the netretry behavior
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 23/27] test: dm: net: Add a test of the netretry behavior Joe Hershberger
@ 2015-03-04 18:35           ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-04 18:35 UTC (permalink / raw)
  To: u-boot

On 3 March 2015 at 19:41, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The effect of the "netretry" env var was recently changed. This test
> checks that behavior.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 22/27] sandbox: eth: Add ability to disable ping reply in sandbox eth driver
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 22/27] sandbox: eth: Add ability to disable ping reply in sandbox eth driver Joe Hershberger
@ 2015-03-04 18:35           ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-04 18:35 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 3 March 2015 at 19:41, Joe Hershberger <joe.hershberger@ni.com> wrote:
> This is needed to test the netretry functionality (make the command fail
> on a sandbox eth device).
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

Reviewed-by: Simon Glass <sjg@chromium.org>

Please see nits below.

>
> ---
>
> Changes in v5:
> -Use a function call to change mock driver behavior
>
> Changes in v4:
> -Add ability to disable ping reply in sandbox eth driver
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/sandbox/include/asm/eth.h | 15 +++++++++++++++
>  drivers/net/sandbox.c          | 10 ++++++++++
>  2 files changed, 25 insertions(+)
>  create mode 100644 arch/sandbox/include/asm/eth.h
>
> diff --git a/arch/sandbox/include/asm/eth.h b/arch/sandbox/include/asm/eth.h
> new file mode 100644
> index 0000000..4b79ede
> --- /dev/null
> +++ b/arch/sandbox/include/asm/eth.h
> @@ -0,0 +1,15 @@
> +/*
> + * Copyright (c) 2015 National Instruments
> + *
> + * (C) Copyright 2015
> + * Joe Hershberger <joe.hershberger@ni.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0
> + */
> +
> +#ifndef __ETH_H
> +#define __ETH_H
> +
> +void sandbox_eth_disable_response(int index, bool disable);

Function comment - what is index? What does it disable?

> +
> +#endif /* __ETH_H */
> diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
> index cb69a95..0dfd144 100644
> --- a/drivers/net/sandbox.c
> +++ b/drivers/net/sandbox.c
> @@ -29,6 +29,13 @@ struct eth_sandbox_priv {
>         int recv_packet_length;
>  };
>
> +static bool disabled[8] = {false};
> +
> +void sandbox_eth_disable_response(int index, bool disable)
> +{
> +       disabled[index] = disable;
> +}
> +
>  static int sb_eth_start(struct udevice *dev)
>  {
>         struct eth_sandbox_priv *priv = dev_get_priv(dev);
> @@ -48,6 +55,9 @@ static int sb_eth_send(struct udevice *dev, void *packet, int length)
>
>         debug("eth_sandbox: Send packet %d\n", length);
>
> +       if (disabled[dev->seq])

if (dev->seq >= 0 && dev->seq <ARRAY_SIZE(disabled) && disabled[dev->seq])

> +               return 0;
> +
>         if (ntohs(eth->et_protlen) == PROT_ARP) {
>                 struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
>
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 24/27] sandbox: eth: Add a bridge to a real network for sandbox
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 24/27] sandbox: eth: Add a bridge to a real network for sandbox Joe Hershberger
@ 2015-03-04 18:35           ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-04 18:35 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 3 March 2015 at 19:41, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Implement a bridge between u-boot's network stack and Linux's raw packet
> API allowing the sandbox to send and receive packets using the host
> machine's network interface.
>
> This raw Ethernet API requires elevated privileges.  You can either run
> as root, or you can add the capability needed like so:
>
> sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

Reviewed-by: Simon Glass <sjg@chromium.org>

Nits below.

>
> ---
>
> Changes in v5:
> -Added fallback for setting promiscuous mode
> -Added help to Kconfig
> -Added more details and examples in the README
> -Check for NULL when reading fdt for host interface
> -Check for malloc failure
> -Remove cast of pointer passed to free
> -Remove the empty sb_eth_raw_remove function
> -Return -errno in from send and recv
> -Return errno from recv
> -Set the socket to non-blocking
> -Use net_rx_packets instead of a stack buffer
>
> Changes in v4:
> -Add comments to priv struct definition
> -Added comments to README.sandbox
> -Clean up the interface to sandbox's eth-raw-os by passing priv to raw-os
> -Cleanup var definition order
> -Fixed the MAC address limitation (now all traffic uses MAC address from env)
> -Move os file to arch
> -Moved config to Kconfig
> -Use accessors for platdata and priv
>
> Changes in v3:
> -Made the os raw packet support for sandbox eth build and work.
>
> Changes in v2:
> -Added the raw packet proof-of-concept patch.
>
>  arch/sandbox/Kconfig                  |   3 +
>  arch/sandbox/cpu/Makefile             |  10 +++
>  arch/sandbox/cpu/eth-raw-os.c         | 140 ++++++++++++++++++++++++++++++++++
>  arch/sandbox/dts/sandbox.dts          |   6 ++
>  arch/sandbox/include/asm/eth-raw-os.h |  32 ++++++++
>  board/sandbox/README.sandbox          |  52 +++++++++++++
>  drivers/net/Kconfig                   |  10 +++
>  drivers/net/Makefile                  |   1 +
>  drivers/net/sandbox-raw.c             |  98 ++++++++++++++++++++++++
>  9 files changed, 352 insertions(+)
>  create mode 100644 arch/sandbox/cpu/eth-raw-os.c
>  create mode 100644 arch/sandbox/include/asm/eth-raw-os.h
>  create mode 100644 drivers/net/sandbox-raw.c
>


> diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
> index c1f5f7e..aedf05a 100644
> --- a/board/sandbox/README.sandbox
> +++ b/board/sandbox/README.sandbox
> @@ -190,6 +190,58 @@ Also sandbox uses generic board (CONFIG_SYS_GENERIC_BOARD) and supports
>  driver model (CONFIG_DM) and associated commands.
>
>
> +Linux RAW Networking Bridge
> +---------------------------
> +
> +The sandbox_eth_raw driver bridges traffic between the bottom of the network
> +stack and the RAW sockets API in Linux. This allows much of the u-boot network

s/u-boot/U-Boot/g

(there's one in the Kconfig also)

> +functionality to be tested in sandbox against real network traffic.
> +
> +For Ethernet network adapters, the bridge utilizes the RAW AF_PACKET API.  This
> +is needed to get access to the lowest level of the network stack in Linux. This
> +means that all of the Ethernet frame is included. This allows the u-boot network
> +stack to be fully used. In other words, nothing about the Linux network stack is
> +involved in forming the packets that end up on the wire. To receive the
> +responses to packets sent from U-Boot the network interface has to be set to
> +promiscuous mode so that the network card won't filter out packets not destined
> +for its configured (on Linux) MAC address.
> +
> +The RAW sockets Ethernet API requires elevated privileges in Linux. You can
> +either run as root, or you can add the capability needed like so:
> +
> +sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot

I think the last param is the filename, is that right? Would be good
to clarify if this is a full path, etc.

> +
> +The default device tree for sandbox includes an entry for eth0 on the sandbox
> +host machine whose alias is "eth1". The following are a few examples of network
> +operations being tested on the eth0 interface.
> +
> +sudo u-boot -d u-boot.dtb

or sudo u-boot -D

> +
> +DHCP
> +....
> +
> +set autoload no
> +set ethact eth1
> +dhcp
> +
> +PING
> +....
> +
> +set autoload no
> +set ethact eth1
> +dhcp
> +ping $gatewayip
> +
> +TFTP
> +....
> +
> +set autoload no
> +set ethact eth1
> +dhcp
> +set serverip WWW.XXX.YYY.ZZZ
> +tftpboot u-boot.bin
> +
> +
>  SPI Emulation
>  -------------
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index e46e57b..601366f 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -29,4 +29,14 @@ config ETH_SANDBOX
>
>           This driver is particularly useful in the test/dm/eth.c tests
>
> +config ETH_SANDBOX_RAW
> +       depends on DM_ETH && SANDBOX
> +       default y
> +       bool "Sandbox: Bridge to Linux Raw Sockets"
> +       help
> +         This driver is a bridge from the bottom of the network stack
> +         in u-boot to the RAW AF_PACKET API in Linux. This allows real
> +         network traffic to be tested from within sandbox. See
> +         board/sandbox/README.sandbox for more details.
> +
>  endif # NETDEVICES

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 26/27] sandbox: eth: Add support for using the 'lo' interface
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 26/27] sandbox: eth: Add support for using the 'lo' interface Joe Hershberger
@ 2015-03-04 18:35           ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-04 18:35 UTC (permalink / raw)
  To: u-boot

On 3 March 2015 at 19:41, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The 'lo' interface on Linux doesn't support thinks like ARP or
> link-layer access like we use to talk to a normal network interface.
> A higher-level network API must be used to access localhost.
>
> As written, this interface is limited to not supporting ICMP since the
> API doesn't allow the socket to be opened for all IP traffic and be able
> to receive at the same time. UDP is far more useful to test with, so it
> was selected over ICMP. Ping won't work, but things like TFTP should
> work.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v5:
> -Add details about lo support to the README
> -Remove socket timeout
> -Separate init to 2 helper static functions
> -Set the socket to non-blocking
> -Use INADDR_LOOPBACK
> -Use more verbose comments

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 27/27] net: Improve error handling
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 27/27] net: Improve error handling Joe Hershberger
@ 2015-03-04 18:35           ` Simon Glass
  2015-03-10 23:10             ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-03-04 18:35 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 3 March 2015 at 19:41, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Take a pass at plumbing errors through to the users of the network stack
>
> Currently only the start() function errors will be returned from
> NetLoop(). recv() tends not to have errors, so that is likely not worth
> adding. send() certainly can return errors, but this patch does not
> attempt to plumb them yet. halt() is not expected to error.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

Nice patch!

Reviewed-by: Simon Glass <sjg@chromium.org>

>
> ---
>
> Changes in v5:
> -New to v5
>
> Changes in v4: None
> Changes in v3: None
> Changes in v2: None
>
>  include/net.h |  3 ++-
>  net/eth.c     | 56 ++++++++++++++++++++++++++++++++++++++++++++++++--------
>  net/net.c     | 26 ++++++++++++++++++--------
>  test/dm/eth.c |  4 ++--
>  4 files changed, 70 insertions(+), 19 deletions(-)
>
> diff --git a/include/net.h b/include/net.h
> index 5846dfb..c702f2f 100644
> --- a/include/net.h
> +++ b/include/net.h
> @@ -539,7 +539,7 @@ int NetLoop(enum proto_t);
>  void   NetStop(void);
>
>  /* Load failed.         Start again. */
> -void   NetStartAgain(void);
> +int    NetStartAgain(void);
>
>  /* Get size of the ethernet header when we send */
>  int    NetEthHdrSize(void);
> @@ -609,6 +609,7 @@ static inline void net_set_state(enum net_loop_state state)
>  /* Transmit a packet */
>  static inline void NetSendPacket(uchar *pkt, int len)
>  {
> +       /* Currently no way to return errors from eth_send() */
>         (void) eth_send(pkt, len);
>  }
>
> diff --git a/net/eth.c b/net/eth.c
> index 9966cf0..81ca436 100644
> --- a/net/eth.c
> +++ b/net/eth.c
> @@ -98,6 +98,9 @@ struct eth_uclass_priv {
>         struct udevice *current;
>  };
>
> +/* eth_errno - This stores the most recent failure code from DM functions */
> +static int eth_errno;
> +
>  static struct eth_uclass_priv *eth_get_uclass_priv(void)
>  {
>         struct uclass *uc;
> @@ -118,20 +121,32 @@ static void eth_set_current_to_next(void)
>                 uclass_first_device(UCLASS_ETH, &uc_priv->current);
>  }
>
> +/*
> + * Typically this will simply return the active device.
> + * In the case where the most recent active device was unset, this will attempt
> + * to return the first device. If that device doesn't exist or fails to probe,
> + * this function will return NULL.
> + */
>  struct udevice *eth_get_dev(void)
>  {
>         struct eth_uclass_priv *uc_priv;
>
>         uc_priv = eth_get_uclass_priv();
>         if (!uc_priv->current)
> -               uclass_first_device(UCLASS_ETH,
> +               eth_errno = uclass_first_device(UCLASS_ETH,
>                                     &uc_priv->current);
>         return uc_priv->current;
>  }
>
> +/*
> + * Typically this will just store a device pointer.
> + * In case it was not probed, we will attempt to do so.
> + * dev may be NULL to unset the active device.
> + */
>  static void eth_set_dev(struct udevice *dev)
>  {
> -       device_probe(dev);
> +       if (dev && !device_active(dev))
> +               eth_errno = device_probe(dev);
>         eth_get_uclass_priv()->current = dev;
>  }
>
> @@ -155,7 +170,14 @@ struct udevice *eth_get_dev_by_name(const char *devname)
>
>         uclass_get(UCLASS_ETH, &uc);
>         uclass_foreach_dev(it, uc) {
> -               /* We need the seq to be valid, so make sure it's probed */
> +               /*
> +                * We need the seq to be valid, so try to probe it.
> +                * If the probe fails, the seq will not match since it will be
> +                * -1 instead of what we are looking for.
> +                * We don't care about errors from probe here. Either they won't
> +                * match an alias or it will match a literal name and we'll pick
> +                * up the error when we try to probe again in eth_set_dev().
> +                */
>                 device_probe(it);
>                 /*
>                  * Check for the name or the sequence number to match
> @@ -221,6 +243,7 @@ int eth_init(void)
>  {
>         struct udevice *current;
>         struct udevice *old_current;
> +       int ret = -ENODEV;
>
>         current = eth_get_dev();
>         if (!current) {
> @@ -243,22 +266,29 @@ int eth_init(void)
>                         else
>                                 memset(pdata->enetaddr, 0, 6);
>
> -                       if (eth_get_ops(current)->start(current) >= 0) {
> +                       ret = eth_get_ops(current)->start(current);
> +                       if (ret >= 0) {
>                                 struct eth_device_priv *priv =
>                                         current->uclass_priv;
>
>                                 priv->state = ETH_STATE_ACTIVE;
>                                 return 0;
>                         }
> -               }
> +               } else
> +                       ret = eth_errno;
> +
>                 debug("FAIL\n");
>
> -               /* This will ensure the new "current" attempted to probe */
> +               /*
> +                * If ethrotate is enabled, this will change "current",
> +                * otherwise we will drop out of this while loop immediately
> +                */
>                 eth_try_another(0);
> +               /* This will ensure the new "current" attempted to probe */
>                 current = eth_get_dev();
>         } while (old_current != current);
>
> -       return -ENODEV;
> +       return ret;
>  }
>
>  void eth_halt(void)
> @@ -278,6 +308,7 @@ void eth_halt(void)
>  int eth_send(void *packet, int length)
>  {
>         struct udevice *current;
> +       int ret;
>
>         current = eth_get_dev();
>         if (!current)
> @@ -286,7 +317,12 @@ int eth_send(void *packet, int length)
>         if (!device_active(current))
>                 return -EINVAL;
>
> -       return eth_get_ops(current)->send(current, packet, length);
> +       ret = eth_get_ops(current)->send(current, packet, length);
> +       if (ret < 0) {
> +               /* We cannot completely return the error at present */
> +               debug("%s: send() returned error %d\n", __func__, ret);
> +       }
> +       return ret;
>  }
>
>  int eth_rx(void)
> @@ -311,6 +347,10 @@ int eth_rx(void)
>                 else
>                         break;
>         }
> +       if (ret < 0) {
> +               /* We cannot completely return the error at present */
> +               debug("%s: recv() returned error %d\n", __func__, ret);
> +       }
>         return ret;
>  }
>
> diff --git a/net/net.c b/net/net.c
> index afec443..69f38f7 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -84,6 +84,7 @@
>  #include <common.h>
>  #include <command.h>
>  #include <environment.h>
> +#include <errno.h>
>  #include <net.h>
>  #if defined(CONFIG_STATUS_LED)
>  #include <miiphy.h>
> @@ -333,7 +334,7 @@ void net_init(void)
>
>  int NetLoop(enum proto_t protocol)
>  {
> -       int ret = -1;
> +       int ret = -EINVAL;
>
>         NetRestarted = 0;
>         NetDevExists = 0;
> @@ -345,9 +346,10 @@ int NetLoop(enum proto_t protocol)
>         if (eth_is_on_demand_init() || protocol != NETCONS) {
>                 eth_halt();
>                 eth_set_current();
> -               if (eth_init() < 0) {
> +               ret = eth_init();
> +               if (ret < 0) {
>                         eth_halt();
> -                       return -1;
> +                       return ret;
>                 }
>         } else
>                 eth_init_state_only();
> @@ -370,7 +372,7 @@ restart:
>         case 1:
>                 /* network not configured */
>                 eth_halt();
> -               return -1;
> +               return -ENODEV;
>
>         case 2:
>                 /* network device not configured */
> @@ -484,6 +486,8 @@ restart:
>                 /*
>                  *      Check the ethernet for a new packet.  The ethernet
>                  *      receive routine will process it.
> +                *      Most drivers return the most recent packet size, but not
> +                *      errors that may have happened.
>                  */
>                 eth_rx();
>
> @@ -537,7 +541,7 @@ restart:
>                 }
>
>                 if (net_state == NETLOOP_FAIL)
> -                       NetStartAgain();
> +                       ret = NetStartAgain();

Where does this 'ret' get used?

>
>                 switch (net_state) {
>
> @@ -597,11 +601,12 @@ startAgainTimeout(void)
>         net_set_state(NETLOOP_RESTART);
>  }
>
> -void NetStartAgain(void)
> +int NetStartAgain(void)
>  {
>         char *nretry;
>         int retry_forever = 0;
>         unsigned long retrycnt = 0;
> +       int ret;
>
>         nretry = getenv("netretry");
>         if (nretry) {
> @@ -621,7 +626,11 @@ void NetStartAgain(void)
>         if ((!retry_forever) && (NetTryCount >= retrycnt)) {
>                 eth_halt();
>                 net_set_state(NETLOOP_FAIL);
> -               return;
> +               /*
> +                * We don't provide a way for the protocol to return an error,
> +                * but this is almost always the reason.
> +                */
> +               return -ETIMEDOUT;
>         }
>
>         NetTryCount++;
> @@ -630,7 +639,7 @@ void NetStartAgain(void)
>  #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
>         eth_try_another(!NetRestarted);
>  #endif
> -       eth_init();
> +       ret = eth_init();
>         if (NetRestartWrap) {
>                 NetRestartWrap = 0;
>                 if (NetDevExists) {
> @@ -642,6 +651,7 @@ void NetStartAgain(void)
>         } else {
>                 net_set_state(NETLOOP_RESTART);
>         }
> +       return ret;
>  }
>
>  /**********************************************************************/
> diff --git a/test/dm/eth.c b/test/dm/eth.c
> index a0e9359..1923670 100644
> --- a/test/dm/eth.c
> +++ b/test/dm/eth.c
> @@ -99,7 +99,7 @@ static int dm_test_eth_rotate(struct dm_test_state *dms)
>         /* If ethrotate is no, then we should fail on a bad MAC */
>         setenv("ethact", "eth at 10004000");
>         setenv("ethrotate", "no");
> -       ut_asserteq(-1, NetLoop(PING));
> +       ut_asserteq(-EINVAL, NetLoop(PING));
>         ut_asserteq_str("eth at 10004000", getenv("ethact"));
>
>         /* Restore the env */
> @@ -144,7 +144,7 @@ static int dm_test_net_retry(struct dm_test_state *dms)
>          */
>         setenv("ethact", "eth at 10004000");
>         setenv("netretry", "no");
> -       ut_asserteq(-1, NetLoop(PING));
> +       ut_asserteq(-ETIMEDOUT, NetLoop(PING));
>         ut_asserteq_str("eth at 10004000", getenv("ethact"));
>
>         /* Restore the env */
> --
> 1.7.11.5
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 02/27] common: Make sure arch-specific map_sysmem() is defined
  2015-03-04  2:40         ` [U-Boot] [PATCH v5 02/27] common: Make sure arch-specific map_sysmem() is defined Joe Hershberger
@ 2015-03-04 19:18           ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-04 19:18 UTC (permalink / raw)
  To: u-boot

On 3 March 2015 at 19:40, Joe Hershberger <joe.hershberger@ni.com> wrote:
> In the case where the arch defines a custom map_sysmem(), make sure that
> including just common.h is sufficient to have these functions as they
> are when the arch does not override it.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v5:
> -Moved to a separate header mapmem.h

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 27/27] net: Improve error handling
  2015-03-04 18:35           ` Simon Glass
@ 2015-03-10 23:10             ` Joe Hershberger
  0 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-10 23:10 UTC (permalink / raw)
  To: u-boot

On Wed, Mar 4, 2015 at 12:35 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 3 March 2015 at 19:41, Joe Hershberger <joe.hershberger@ni.com> wrote:
> > Take a pass at plumbing errors through to the users of the network stack
> >
> > Currently only the start() function errors will be returned from
> > NetLoop(). recv() tends not to have errors, so that is likely not worth
> > adding. send() certainly can return errors, but this patch does not
> > attempt to plumb them yet. halt() is not expected to error.
> >
> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> Nice patch!
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> >
> > ---
> >
> > Changes in v5:
> > -New to v5
> >
> > Changes in v4: None
> > Changes in v3: None
> > Changes in v2: None
> >
> >  include/net.h |  3 ++-
> >  net/eth.c     | 56
++++++++++++++++++++++++++++++++++++++++++++++++--------
> >  net/net.c     | 26 ++++++++++++++++++--------
> >  test/dm/eth.c |  4 ++--
> >  4 files changed, 70 insertions(+), 19 deletions(-)
> >

[snip]

> > diff --git a/net/net.c b/net/net.c
> > index afec443..69f38f7 100644
> > --- a/net/net.c
> > +++ b/net/net.c
> > @@ -84,6 +84,7 @@
> >  #include <common.h>
> >  #include <command.h>
> >  #include <environment.h>
> > +#include <errno.h>
> >  #include <net.h>
> >  #if defined(CONFIG_STATUS_LED)
> >  #include <miiphy.h>
> > @@ -333,7 +334,7 @@ void net_init(void)
> >
> >  int NetLoop(enum proto_t protocol)
> >  {
> > -       int ret = -1;
> > +       int ret = -EINVAL;
> >
> >         NetRestarted = 0;
> >         NetDevExists = 0;
> > @@ -345,9 +346,10 @@ int NetLoop(enum proto_t protocol)
> >         if (eth_is_on_demand_init() || protocol != NETCONS) {
> >                 eth_halt();
> >                 eth_set_current();
> > -               if (eth_init() < 0) {
> > +               ret = eth_init();
> > +               if (ret < 0) {
> >                         eth_halt();
> > -                       return -1;
> > +                       return ret;
> >                 }
> >         } else
> >                 eth_init_state_only();
> > @@ -370,7 +372,7 @@ restart:
> >         case 1:
> >                 /* network not configured */
> >                 eth_halt();
> > -               return -1;
> > +               return -ENODEV;
> >
> >         case 2:
> >                 /* network device not configured */
> > @@ -484,6 +486,8 @@ restart:
> >                 /*
> >                  *      Check the ethernet for a new packet.  The
ethernet
> >                  *      receive routine will process it.
> > +                *      Most drivers return the most recent packet
size, but not
> > +                *      errors that may have happened.
> >                  */
> >                 eth_rx();
> >
> > @@ -537,7 +541,7 @@ restart:
> >                 }
> >
> >                 if (net_state == NETLOOP_FAIL)
> > -                       NetStartAgain();
> > +                       ret = NetStartAgain();
>
> Where does this 'ret' get used?

This is part of the NetLoop() function, the top-most interface to the
network stack in net.c.

If the net_state remains "NETLOOP_FAIL" after calling NetStartAgain, then
the case structure following this if will "goto done".

At the end of done: is:

       return ret;

We need to pass the return value out of NetStartAgain, since it can
possibly call eth_ops->start() on a new device.

> >
> >                 switch (net_state) {
> >
> > @@ -597,11 +601,12 @@ startAgainTimeout(void)
> >         net_set_state(NETLOOP_RESTART);
> >  }
> >
> > -void NetStartAgain(void)
> > +int NetStartAgain(void)
> >  {
> >         char *nretry;
> >         int retry_forever = 0;
> >         unsigned long retrycnt = 0;
> > +       int ret;
> >
> >         nretry = getenv("netretry");
> >         if (nretry) {
> > @@ -621,7 +626,11 @@ void NetStartAgain(void)
> >         if ((!retry_forever) && (NetTryCount >= retrycnt)) {
> >                 eth_halt();
> >                 net_set_state(NETLOOP_FAIL);
> > -               return;
> > +               /*
> > +                * We don't provide a way for the protocol to return an
error,
> > +                * but this is almost always the reason.
> > +                */
> > +               return -ETIMEDOUT;
> >         }
> >
> >         NetTryCount++;
> > @@ -630,7 +639,7 @@ void NetStartAgain(void)
> >  #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
> >         eth_try_another(!NetRestarted);
> >  #endif
> > -       eth_init();
> > +       ret = eth_init();
> >         if (NetRestartWrap) {
> >                 NetRestartWrap = 0;
> >                 if (NetDevExists) {
> > @@ -642,6 +651,7 @@ void NetStartAgain(void)
> >         } else {
> >                 net_set_state(NETLOOP_RESTART);
> >         }
> > +       return ret;
> >  }
> >
> >
 /**********************************************************************/

[snip]

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 15/27] dm: eth: Pass the packet pointer as a parameter to recv
  2015-03-04 18:35           ` Simon Glass
@ 2015-03-10 23:28             ` Joe Hershberger
  2015-03-10 23:31               ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-10 23:28 UTC (permalink / raw)
  To: u-boot

On Wed, Mar 4, 2015 at 12:35 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 3 March 2015 at 19:41, Joe Hershberger <joe.hershberger@ni.com> wrote:
> > Stop forcing drivers to call net_process_received_packet() - formerly
> > called NetReceive(). Now the uclass will handle calling the driver for
> > each packet until the driver errors or has nothing to return. The uclass
> > will then pass the good packets off to the network stack by calling
> > net_process_received_packet().
> >
> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> >
> > ---
> >
> > Changes in v5:
> > -New to v5
> >
> > Changes in v4: None
> > Changes in v3: None
> > Changes in v2: None
> >
> >  include/net.h |  2 +-
> >  net/eth.c     | 13 ++++++++++++-
> >  2 files changed, 13 insertions(+), 2 deletions(-)
> >
> > diff --git a/include/net.h b/include/net.h
> > index 4e44832..37d1f36 100644
> > --- a/include/net.h
> > +++ b/include/net.h
> > @@ -110,7 +110,7 @@ struct eth_pdata {
> >  struct eth_ops {
> >         int (*start)(struct udevice *dev);
> >         int (*send)(struct udevice *dev, void *packet, int length);
> > -       int (*recv)(struct udevice *dev);
> > +       int (*recv)(struct udevice *dev, uchar **packetp);
>
> Need to update docs above. With serial we return -EAGAIN when there is
> nothing more to receive. So you might want to swallow that error
> instead of returning it from eth_rx().

I was doing this filtering in the sandbox-raw driver, but I can easily to
it here instead (or too) so that it doesn't leak through from other drivers
that do not do this check in the future.

> >         void (*stop)(struct udevice *dev);
> >  #ifdef CONFIG_MCAST_TFTP
> >         int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
> > diff --git a/net/eth.c b/net/eth.c
> > index 1abf027..b66d253 100644
> > --- a/net/eth.c
> > +++ b/net/eth.c
> > @@ -259,6 +259,9 @@ int eth_send(void *packet, int length)
> >  int eth_rx(void)
> >  {
> >         struct udevice *current;
> > +       uchar *packet;
> > +       int ret;
> > +       int i;
> >
> >         current = eth_get_dev();
> >         if (!current)
> > @@ -267,7 +270,15 @@ int eth_rx(void)
> >         if (!device_active(current))
> >                 return -EINVAL;
> >
> > -       return eth_get_ops(current)->recv(current);
> > +       /* Process up to 32 packets at one time */
> > +       for (i = 0; i < 32; i++) {
> > +               ret = eth_get_ops(current)->recv(current, &packet);
> > +               if (ret > 0)
> > +                       net_process_received_packet(packet, ret);
> > +               else
> > +                       break;
> > +       }
> > +       return ret;
> >  }
> >
> >  static int eth_write_hwaddr(struct udevice *dev)
> > --
> > 1.7.11.5
> >
>
> Regards,
> Simon
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 15/27] dm: eth: Pass the packet pointer as a parameter to recv
  2015-03-10 23:28             ` Joe Hershberger
@ 2015-03-10 23:31               ` Simon Glass
  2015-03-10 23:41                 ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-03-10 23:31 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 10 March 2015 at 16:28, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> On Wed, Mar 4, 2015 at 12:35 PM, Simon Glass <sjg@chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 3 March 2015 at 19:41, Joe Hershberger <joe.hershberger@ni.com> wrote:
>> > Stop forcing drivers to call net_process_received_packet() - formerly
>> > called NetReceive(). Now the uclass will handle calling the driver for
>> > each packet until the driver errors or has nothing to return. The uclass
>> > will then pass the good packets off to the network stack by calling
>> > net_process_received_packet().
>> >
>> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>> >
>> > ---
>> >
>> > Changes in v5:
>> > -New to v5
>> >
>> > Changes in v4: None
>> > Changes in v3: None
>> > Changes in v2: None
>> >
>> >  include/net.h |  2 +-
>> >  net/eth.c     | 13 ++++++++++++-
>> >  2 files changed, 13 insertions(+), 2 deletions(-)
>> >
>> > diff --git a/include/net.h b/include/net.h
>> > index 4e44832..37d1f36 100644
>> > --- a/include/net.h
>> > +++ b/include/net.h
>> > @@ -110,7 +110,7 @@ struct eth_pdata {
>> >  struct eth_ops {
>> >         int (*start)(struct udevice *dev);
>> >         int (*send)(struct udevice *dev, void *packet, int length);
>> > -       int (*recv)(struct udevice *dev);
>> > +       int (*recv)(struct udevice *dev, uchar **packetp);
>>
>> Need to update docs above. With serial we return -EAGAIN when there is
>> nothing more to receive. So you might want to swallow that error
>> instead of returning it from eth_rx().
>
> I was doing this filtering in the sandbox-raw driver, but I can easily to it
> here instead (or too) so that it doesn't leak through from other drivers
> that do not do this check in the future.

OK. My main concerns are:

1. Avoid wait loops in drivers (if needed they should be in the uclass
triggered by -EAGAIN)
2. Ensure that uclass ops methods are clearly documented as to
purpose, parameters, return value, etc, so people don't have to resort
to archaeology to do the right thing :-)

>
>> >         void (*stop)(struct udevice *dev);
>> >  #ifdef CONFIG_MCAST_TFTP
>> >         int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
>> > diff --git a/net/eth.c b/net/eth.c
>> > index 1abf027..b66d253 100644
>> > --- a/net/eth.c
>> > +++ b/net/eth.c
>> > @@ -259,6 +259,9 @@ int eth_send(void *packet, int length)
>> >  int eth_rx(void)
>> >  {
>> >         struct udevice *current;
>> > +       uchar *packet;
>> > +       int ret;
>> > +       int i;
>> >
>> >         current = eth_get_dev();
>> >         if (!current)
>> > @@ -267,7 +270,15 @@ int eth_rx(void)
>> >         if (!device_active(current))
>> >                 return -EINVAL;
>> >
>> > -       return eth_get_ops(current)->recv(current);
>> > +       /* Process up to 32 packets at one time */
>> > +       for (i = 0; i < 32; i++) {
>> > +               ret = eth_get_ops(current)->recv(current, &packet);
>> > +               if (ret > 0)
>> > +                       net_process_received_packet(packet, ret);
>> > +               else
>> > +                       break;
>> > +       }
>> > +       return ret;
>> >  }
>> >
>> >  static int eth_write_hwaddr(struct udevice *dev)
>> > --

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v5 15/27] dm: eth: Pass the packet pointer as a parameter to recv
  2015-03-10 23:31               ` Simon Glass
@ 2015-03-10 23:41                 ` Joe Hershberger
  0 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-10 23:41 UTC (permalink / raw)
  To: u-boot

On Tue, Mar 10, 2015 at 6:31 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 10 March 2015 at 16:28, Joe Hershberger <joe.hershberger@gmail.com>
wrote:
> > On Wed, Mar 4, 2015 at 12:35 PM, Simon Glass <sjg@chromium.org> wrote:
> >>
> >> Hi Joe,
> >>
> >> On 3 March 2015 at 19:41, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> >> > Stop forcing drivers to call net_process_received_packet() - formerly
> >> > called NetReceive(). Now the uclass will handle calling the driver
for
> >> > each packet until the driver errors or has nothing to return. The
uclass
> >> > will then pass the good packets off to the network stack by calling
> >> > net_process_received_packet().
> >> >
> >> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> >> >
> >> > ---
> >> >
> >> > Changes in v5:
> >> > -New to v5
> >> >
> >> > Changes in v4: None
> >> > Changes in v3: None
> >> > Changes in v2: None
> >> >
> >> >  include/net.h |  2 +-
> >> >  net/eth.c     | 13 ++++++++++++-
> >> >  2 files changed, 13 insertions(+), 2 deletions(-)
> >> >
> >> > diff --git a/include/net.h b/include/net.h
> >> > index 4e44832..37d1f36 100644
> >> > --- a/include/net.h
> >> > +++ b/include/net.h
> >> > @@ -110,7 +110,7 @@ struct eth_pdata {
> >> >  struct eth_ops {
> >> >         int (*start)(struct udevice *dev);
> >> >         int (*send)(struct udevice *dev, void *packet, int length);
> >> > -       int (*recv)(struct udevice *dev);
> >> > +       int (*recv)(struct udevice *dev, uchar **packetp);
> >>
> >> Need to update docs above. With serial we return -EAGAIN when there is
> >> nothing more to receive. So you might want to swallow that error
> >> instead of returning it from eth_rx().
> >
> > I was doing this filtering in the sandbox-raw driver, but I can easily
to it
> > here instead (or too) so that it doesn't leak through from other drivers
> > that do not do this check in the future.
>
> OK. My main concerns are:
>
> 1. Avoid wait loops in drivers (if needed they should be in the uclass
> triggered by -EAGAIN)

Drivers are expected to return and not wait. I've made this more clear in
the function comment.

> 2. Ensure that uclass ops methods are clearly documented as to
> purpose, parameters, return value, etc, so people don't have to resort
> to archaeology to do the right thing :-)

The new function comment looks like this:

+ * recv: Check if the hardware received a packet. If so, set the pointer
to the
+ *      packet buffer in the packetp parameter. If not, return an error or
0 to
+ *      indicate that the hardware receive FIFO is empty

> >
> >> >         void (*stop)(struct udevice *dev);
> >> >  #ifdef CONFIG_MCAST_TFTP
> >> >         int (*mcast)(struct udevice *dev, const u8 *enetaddr, int
join);
> >> > diff --git a/net/eth.c b/net/eth.c
> >> > index 1abf027..b66d253 100644
> >> > --- a/net/eth.c
> >> > +++ b/net/eth.c
> >> > @@ -259,6 +259,9 @@ int eth_send(void *packet, int length)
> >> >  int eth_rx(void)
> >> >  {
> >> >         struct udevice *current;
> >> > +       uchar *packet;
> >> > +       int ret;
> >> > +       int i;
> >> >
> >> >         current = eth_get_dev();
> >> >         if (!current)
> >> > @@ -267,7 +270,15 @@ int eth_rx(void)
> >> >         if (!device_active(current))
> >> >                 return -EINVAL;
> >> >
> >> > -       return eth_get_ops(current)->recv(current);
> >> > +       /* Process up to 32 packets at one time */
> >> > +       for (i = 0; i < 32; i++) {
> >> > +               ret = eth_get_ops(current)->recv(current, &packet);
> >> > +               if (ret > 0)
> >> > +                       net_process_received_packet(packet, ret);
> >> > +               else
> >> > +                       break;
> >> > +       }
> >> > +       return ret;
> >> >  }
> >> >
> >> >  static int eth_write_hwaddr(struct udevice *dev)
> >> > --
>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack
  2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
                           ` (26 preceding siblings ...)
  2015-03-04  2:41         ` [U-Boot] [PATCH v5 27/27] net: Improve error handling Joe Hershberger
@ 2015-03-11 23:43         ` Joe Hershberger
  2015-03-11 23:43           ` [U-Boot] [PATCH v6 01/27] test: dm: Reorder the objects to build Joe Hershberger
                             ` (28 more replies)
  27 siblings, 29 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:43 UTC (permalink / raw)
  To: u-boot

Add support for the Ethernet MAC controllers.  Phy support will come later.

Switching from RFC to a patch series to be applied to dm/master as a staging
area for this series to make it happen more quickly when the window opens.

If desired, let me know which of the non-DM related prerequisite patches are
wanted for this release.

I've added unit tests to verify functionality.

There is an additional driver for sandbox that bridges to the RAW
Ethernet API in Linux which lets you test with real traffic. It now
supports localhost as well (the 'lo' interface).

Changes in v6:
-Add function comments
-Addressed nits
-Check array index bounds
-Fix compile error on boards with CONFIG_API enabled
-Fix compile errors for other boards due to removed parameters
-Swallow -EAGAIN error in eth_rx()
-Updated function documentation

Changes in v5:
-Add a note to doc/README.drivers.eth about its obsolescence
-Add details about lo support to the README
-Added a comment about devname
-Added a test for skipping un-probe-able devices
-Added comments about test cases
-Added fallback for setting promiscuous mode
-Added help to Kconfig
-Added help to the sandbox eth mock driver Kconfig entry
-Added more details and examples in the README
-Check for NULL when reading fdt for host interface
-Check for malloc failure
-Expanded the Kconfig help
-Fix compile error on !DM_ETH
-Fixed warning from missing declaration
-Include new mapmem.h header
-Moved dm/ header
-Moved to a separate header mapmem.h
-New to v5
-Only check for alias if the name is long enough
-Remove cast of pointer passed to free
-Remove socket timeout
-Remove the empty sb_eth_raw_remove function
-Return -errno in from send and recv
-Return errno from recv
-Separate init to 2 helper static functions
-Set the socket to non-blocking
-Simplify sandbox eth driver by switching from int array to byte array
-Switch priv from packet buffer to a pointer to net_rx_packets[0]
-Switched to function to control state of mock driver
-Unmap memory for consistency
-Use INADDR_LOOPBACK
-Use a function call to change mock driver behavior
-Use local var for priv in eth_get_dev()
-Use more verbose comments
-Use net_rx_packets instead of a stack buffer

Changes in v4:
--Don't prevent eth_initialize on driver model
--If current == NULL, always check if there is a device available in eth_get_dev
--Include ethprime handling in eth_initialize
--Look up MAC address in post-probe
--Move env init call from uclass init to eth_initialize
--Print the alias in eth_initialize
--Use eth_initialize to probe all devices and write_hwaddr
-Add a helper function for eth_uclass_priv
-Add ability to disable ping reply in sandbox eth driver
-Add comments to priv struct definition
-Add documentation to the structures
-Add eth_get_ops helper
-Added comments to README.sandbox
-Added support for the 'lo' network interface
-Added testing for ethrotate
-Change -1 returns to error constants
-Change puts to printf
-Clean up the interface to sandbox's eth-raw-os by passing priv to raw-os
-Cleaned up sandbox EXTRA_ENV define
-Cleanup var definition order
-Fix compile regression in !DM_ETH case
-Fixed the MAC address limitation (now all traffic uses MAC address from env)
-Load from ethprime on eth_initialize()
-Move os file to arch
-Moved config to Kconfig
-New to v4
-Redo the seq / probe implementation
-Remove bd_t *bis from dm eth_ops init function
-Remove checks for driver==NULL
-Remove priv pointer in per-device priv struct (drivers already get their own directly from DM)
-Removed checks on priv != NULL and added protection in uclass instead
-Rename halt() to stop() in ops
-Rename init() to start() in ops
-Stop handling selecting a new "current" in pre-unbind as it will now work itself out by clearing the pointer
-Updated expected behavior based on changes to the NetLoop
-Use accessors for platdata and priv
-Use only the seq from DM to find aliases

Changes in v3:
--Fail init if not activated
--Fail probe if ethaddr not set
-Added 2 more ethaddr to sandbox
-Added dm eth testing
-Added support for aliases
-Added support for ethprime
-Added testing for netretry
-Allow current eth dev to be NULL
-Correct failure chaining from bind to probe to init
-Correct the pre_unbind logic
-Fixed blank line formatting for variable declaration
-Made the os raw packet support for sandbox eth build and work.
-Move the get_dev_by_* protos to also be !DM_ETH like the impl
-Prevent a crash if memory is not allocated
-Print which device in the debug write hwaddr
-Reorder dm test makefile
-Update ethaddr from env unconditionally on init
-Use set current to select the current device regardless of the previous selection

Changes in v2:
-Added the raw packet proof-of-concept patch.
-Cause an invalid name to fail binding
-Change printfs to debug in sandbox driver
-Changed eth_uclass_priv local var names to be uc_priv
-Move fake hwaddr to the device tree
-Move static data to priv
-Move the hwaddr to platdata so that its memory is allocated at bind when we need it
-Prevent device from being probed before used by a command (i.e. before eth_init()).
-Rebase on top of dm/master
-Remove unused priv struct for sandbox driver
-Removed extra parentheses
-Stop maintaining our own index and use DM seq now that it works for our needs
-Update error codes
-Updated comments

Joe Hershberger (27):
  test: dm: Reorder the objects to build
  common: Make sure arch-specific map_sysmem() is defined
  net: Provide a function to get the current MAC address
  net: Rename helper function to be more clear
  net: Remove unneeded "extern" in net.h
  net: Refactor in preparation for driver model
  net: Change return codes from net/eth.c to use errorno constants
  net: Use int instead of u8 for boolean flag
  net: Remove the bd* parameter from net stack functions
  net: Make netretry actually do something
  net: Access mapped physmem in net functions
  cmd: net: Clean up return codes
  dm: eth: Add basic driver model support to Ethernet stack
  net: Clean up network stack names used in DM drivers
  dm: eth: Pass the packet pointer as a parameter to recv
  sandbox: eth: Add network support to sandbox
  sandbox: eth: Add ARP and PING response to sandbox driver
  test: dm: eth: Add tests for the eth dm implementation
  dm: eth: Add support for aliases
  dm: eth: Add support for ethprime env var
  test: dm: eth: Add testing for ethrotate env var
  sandbox: eth: Add ability to disable ping reply in sandbox eth driver
  test: dm: net: Add a test of the netretry behavior
  sandbox: eth: Add a bridge to a real network for sandbox
  sandbox: Enable DHCP and IP defrag
  sandbox: eth: Add support for using the 'lo' interface
  net: Improve error handling

 api/api_net.c                             |   2 +-
 arch/arm/lib/board.c                      |   2 +-
 arch/arm/lib/bootm.c                      |   1 +
 arch/avr32/lib/board.c                    |   2 +-
 arch/m68k/lib/board.c                     |   4 +-
 arch/mips/mach-au1x00/au1x00_eth.c        |   2 +-
 arch/nds32/lib/board.c                    |   2 +-
 arch/openrisc/lib/board.c                 |   2 +-
 arch/powerpc/cpu/mpc8260/ether_fcc.c      |   2 +-
 arch/powerpc/cpu/mpc85xx/ether_fcc.c      |   2 +-
 arch/powerpc/cpu/mpc8xx/scc.c             |   2 +-
 arch/powerpc/lib/board.c                  |   2 +-
 arch/sandbox/Kconfig                      |  12 +
 arch/sandbox/cpu/Makefile                 |  10 +
 arch/sandbox/cpu/eth-raw-os.c             | 249 +++++++++++++
 arch/sandbox/dts/sandbox.dts              |  21 ++
 arch/sandbox/include/asm/eth-raw-os.h     |  40 +++
 arch/sandbox/include/asm/eth.h            |  15 +
 arch/sh/lib/board.c                       |   2 +-
 arch/sparc/lib/board.c                    |   2 +-
 board/BuS/eb_cpux9k2/cpux9k2.c            |   2 +-
 board/BuS/vl_ma2sc/vl_ma2sc.c             |   2 +-
 board/atmel/at91sam9261ek/at91sam9261ek.c |   2 +-
 board/egnite/ethernut5/ethernut5.c        |   2 +-
 board/ronetix/pm9261/pm9261.c             |   2 +-
 board/ronetix/pm9g45/pm9g45.c             |   2 +-
 board/sandbox/README.sandbox              |  78 +++-
 common/board_f.c                          |   1 +
 common/board_r.c                          |   3 +-
 common/bootm.c                            |   1 +
 common/cmd_bdinfo.c                       |   2 +
 common/cmd_bootm.c                        |   1 +
 common/cmd_demo.c                         |   1 +
 common/cmd_fat.c                          |   1 +
 common/cmd_fdt.c                          |   1 +
 common/cmd_lzmadec.c                      |   1 +
 common/cmd_md5sum.c                       |   1 +
 common/cmd_mem.c                          |   1 +
 common/cmd_net.c                          |  45 ++-
 common/cmd_nvedit.c                       |   1 +
 common/cmd_pxe.c                          |   1 +
 common/cmd_sf.c                           |   1 +
 common/cmd_source.c                       |   1 +
 common/cmd_trace.c                        |   1 +
 common/cmd_ximg.c                         |   1 +
 common/hash.c                             |   1 +
 common/image-fdt.c                        |   1 +
 common/image-fit.c                        |   1 +
 common/image.c                            |   1 +
 common/iotrace.c                          |   1 +
 common/lcd.c                              |   1 +
 common/malloc_simple.c                    |   1 +
 common/spl/spl_net.c                      |   2 +-
 doc/README.drivers.eth                    |   6 +
 drivers/demo/demo-simple.c                |   1 +
 drivers/i2c/i2c-uniphier-f.c              |   1 +
 drivers/i2c/i2c-uniphier.c                |   1 +
 drivers/mtd/spi/sf_probe.c                |   1 +
 drivers/net/Kconfig                       |  42 +++
 drivers/net/Makefile                      |   2 +
 drivers/net/netconsole.c                  |   4 +-
 drivers/net/sandbox-raw.c                 | 165 +++++++++
 drivers/net/sandbox.c                     | 208 +++++++++++
 drivers/serial/ns16550.c                  |   1 +
 drivers/serial/serial_uniphier.c          |   1 +
 fs/fs.c                                   |   1 +
 include/common.h                          |  17 -
 include/configs/sandbox.h                 |  25 +-
 include/dm/uclass-id.h                    |   1 +
 include/mapmem.h                          |  32 ++
 include/net.h                             | 201 +++++++----
 lib/trace.c                               |   1 +
 net/eth.c                                 | 580 ++++++++++++++++++++++++++----
 net/net.c                                 |  67 ++--
 net/nfs.c                                 |   6 +-
 net/tftp.c                                |   6 +-
 test/compression.c                        |   1 +
 test/dm/Makefile                          |   5 +-
 test/dm/cmd_dm.c                          |   1 +
 test/dm/eth.c                             | 156 ++++++++
 test/dm/test.dts                          |  20 ++
 81 files changed, 1866 insertions(+), 227 deletions(-)
 create mode 100644 arch/sandbox/cpu/eth-raw-os.c
 create mode 100644 arch/sandbox/include/asm/eth-raw-os.h
 create mode 100644 arch/sandbox/include/asm/eth.h
 create mode 100644 drivers/net/sandbox-raw.c
 create mode 100644 drivers/net/sandbox.c
 create mode 100644 include/mapmem.h
 create mode 100644 test/dm/eth.c

-- 
1.7.11.5

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 01/27] test: dm: Reorder the objects to build
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
@ 2015-03-11 23:43           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 02/27] common: Make sure arch-specific map_sysmem() is defined Joe Hershberger
                             ` (27 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:43 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Acked-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
-Reorder dm test makefile

Changes in v2: None

 test/dm/Makefile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/dm/Makefile b/test/dm/Makefile
index 612aa95..1d9148f 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -18,7 +18,7 @@ obj-$(CONFIG_DM_TEST) += core.o
 obj-$(CONFIG_DM_TEST) += ut.o
 ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_DM_GPIO) += gpio.o
-obj-$(CONFIG_DM_SPI) += spi.o
-obj-$(CONFIG_DM_SPI_FLASH) += sf.o
 obj-$(CONFIG_DM_I2C) += i2c.o
+obj-$(CONFIG_DM_SPI_FLASH) += sf.o
+obj-$(CONFIG_DM_SPI) += spi.o
 endif
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 02/27] common: Make sure arch-specific map_sysmem() is defined
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
  2015-03-11 23:43           ` [U-Boot] [PATCH v6 01/27] test: dm: Reorder the objects to build Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 03/27] net: Provide a function to get the current MAC address Joe Hershberger
                             ` (26 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

In the case where the arch defines a custom map_sysmem(), make sure that
including just mapmem.h is sufficient to have these functions as they
are when the arch does not override it.

Also split the non-arch specific functions out of common.h

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5:
-Moved to a separate header mapmem.h

Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 arch/arm/lib/bootm.c             |  1 +
 common/board_f.c                 |  1 +
 common/board_r.c                 |  1 +
 common/bootm.c                   |  1 +
 common/cmd_bootm.c               |  1 +
 common/cmd_demo.c                |  1 +
 common/cmd_fat.c                 |  1 +
 common/cmd_fdt.c                 |  1 +
 common/cmd_lzmadec.c             |  1 +
 common/cmd_md5sum.c              |  1 +
 common/cmd_mem.c                 |  1 +
 common/cmd_nvedit.c              |  1 +
 common/cmd_pxe.c                 |  1 +
 common/cmd_sf.c                  |  1 +
 common/cmd_source.c              |  1 +
 common/cmd_trace.c               |  1 +
 common/cmd_ximg.c                |  1 +
 common/hash.c                    |  1 +
 common/image-fdt.c               |  1 +
 common/image-fit.c               |  1 +
 common/image.c                   |  1 +
 common/iotrace.c                 |  1 +
 common/lcd.c                     |  1 +
 common/malloc_simple.c           |  1 +
 drivers/demo/demo-simple.c       |  1 +
 drivers/i2c/i2c-uniphier-f.c     |  1 +
 drivers/i2c/i2c-uniphier.c       |  1 +
 drivers/mtd/spi/sf_probe.c       |  1 +
 drivers/serial/ns16550.c         |  1 +
 drivers/serial/serial_uniphier.c |  1 +
 fs/fs.c                          |  1 +
 include/common.h                 | 17 -----------------
 include/mapmem.h                 | 32 ++++++++++++++++++++++++++++++++
 lib/trace.c                      |  1 +
 test/compression.c               |  1 +
 test/dm/cmd_dm.c                 |  1 +
 36 files changed, 66 insertions(+), 17 deletions(-)
 create mode 100644 include/mapmem.h

diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 2d6b676..b1bff8c 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -18,6 +18,7 @@
 #include <u-boot/zlib.h>
 #include <asm/byteorder.h>
 #include <libfdt.h>
+#include <mapmem.h>
 #include <fdt_support.h>
 #include <asm/bootm.h>
 #include <asm/secure.h>
diff --git a/common/board_f.c b/common/board_f.c
index 4d8b8a6..1b7e7d9 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -23,6 +23,7 @@
 #include <i2c.h>
 #include <initcall.h>
 #include <logbuff.h>
+#include <mapmem.h>
 
 /* TODO: Can we move these into arch/ headers? */
 #ifdef CONFIG_8xx
diff --git a/common/board_r.c b/common/board_r.c
index 4fcd4f6..af0f274 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -33,6 +33,7 @@
 #endif
 #include <logbuff.h>
 #include <malloc.h>
+#include <mapmem.h>
 #ifdef CONFIG_BITBANGMII
 #include <miiphy.h>
 #endif
diff --git a/common/bootm.c b/common/bootm.c
index 34f60bb..6842029 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -13,6 +13,7 @@
 #include <fdt_support.h>
 #include <lmb.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <asm/io.h>
 #include <linux/lzo.h>
 #include <lzma/LzmaTypes.h>
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index 48199bf..b3d3968 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -16,6 +16,7 @@
 #include <image.h>
 #include <lmb.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <nand.h>
 #include <asm/byteorder.h>
 #include <linux/compiler.h>
diff --git a/common/cmd_demo.c b/common/cmd_demo.c
index 8a10bdf..209dc4a 100644
--- a/common/cmd_demo.c
+++ b/common/cmd_demo.c
@@ -9,6 +9,7 @@
 
 #include <common.h>
 #include <dm-demo.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 struct udevice *demo_dev;
diff --git a/common/cmd_fat.c b/common/cmd_fat.c
index c00fb28..aae993d 100644
--- a/common/cmd_fat.c
+++ b/common/cmd_fat.c
@@ -14,6 +14,7 @@
 #include <net.h>
 #include <ata.h>
 #include <asm/io.h>
+#include <mapmem.h>
 #include <part.h>
 #include <fat.h>
 #include <fs.h>
diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c
index 48b3e70..682b655 100644
--- a/common/cmd_fdt.c
+++ b/common/cmd_fdt.c
@@ -15,6 +15,7 @@
 #include <asm/global_data.h>
 #include <libfdt.h>
 #include <fdt_support.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 #define MAX_LEVEL	32		/* how deeply nested we will go */
diff --git a/common/cmd_lzmadec.c b/common/cmd_lzmadec.c
index 7b0b3fd..1ad9ed6 100644
--- a/common/cmd_lzmadec.c
+++ b/common/cmd_lzmadec.c
@@ -12,6 +12,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 #include <lzma/LzmaTools.h>
diff --git a/common/cmd_md5sum.c b/common/cmd_md5sum.c
index d22ace5..23bb81e 100644
--- a/common/cmd_md5sum.c
+++ b/common/cmd_md5sum.c
@@ -10,6 +10,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <mapmem.h>
 #include <u-boot/md5.h>
 #include <asm/io.h>
 
diff --git a/common/cmd_mem.c b/common/cmd_mem.c
index bcb3ee3..66a41da 100644
--- a/common/cmd_mem.c
+++ b/common/cmd_mem.c
@@ -20,6 +20,7 @@
 #endif
 #include <hash.h>
 #include <inttypes.h>
+#include <mapmem.h>
 #include <watchdog.h>
 #include <asm/io.h>
 #include <linux/compiler.h>
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 855808c..be792ae 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -31,6 +31,7 @@
 #include <search.h>
 #include <errno.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <watchdog.h>
 #include <linux/stddef.h>
 #include <asm/byteorder.h>
diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c
index 7e32c95..96f963d 100644
--- a/common/cmd_pxe.c
+++ b/common/cmd_pxe.c
@@ -8,6 +8,7 @@
 #include <common.h>
 #include <command.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <errno.h>
diff --git a/common/cmd_sf.c b/common/cmd_sf.c
index 5c788e9..01c37de 100644
--- a/common/cmd_sf.c
+++ b/common/cmd_sf.c
@@ -10,6 +10,7 @@
 #include <div64.h>
 #include <dm.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <spi.h>
 #include <spi_flash.h>
 
diff --git a/common/cmd_source.c b/common/cmd_source.c
index 6881bc9..d2a881d 100644
--- a/common/cmd_source.c
+++ b/common/cmd_source.c
@@ -19,6 +19,7 @@
 #include <command.h>
 #include <image.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #if defined(CONFIG_8xx)
diff --git a/common/cmd_trace.c b/common/cmd_trace.c
index 8c630e6..1e62a1a 100644
--- a/common/cmd_trace.c
+++ b/common/cmd_trace.c
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <mapmem.h>
 #include <trace.h>
 #include <asm/io.h>
 
diff --git a/common/cmd_ximg.c b/common/cmd_ximg.c
index 64b9186..8b8645c 100644
--- a/common/cmd_ximg.c
+++ b/common/cmd_ximg.c
@@ -15,6 +15,7 @@
 #include <common.h>
 #include <command.h>
 #include <image.h>
+#include <mapmem.h>
 #include <watchdog.h>
 #if defined(CONFIG_BZIP2)
 #include <bzlib.h>
diff --git a/common/hash.c b/common/hash.c
index 9e9f84b..c94c98b 100644
--- a/common/hash.c
+++ b/common/hash.c
@@ -14,6 +14,7 @@
 #include <common.h>
 #include <command.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <hw_sha.h>
 #include <asm/io.h>
 #include <asm/errno.h>
diff --git a/common/image-fdt.c b/common/image-fdt.c
index d9e4728..7e2da7b 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -14,6 +14,7 @@
 #include <errno.h>
 #include <image.h>
 #include <libfdt.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 #ifndef CONFIG_SYS_FDT_PAD
diff --git a/common/image-fit.c b/common/image-fit.c
index 778d2a1..4eb4d42 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -16,6 +16,7 @@
 #else
 #include <common.h>
 #include <errno.h>
+#include <mapmem.h>
 #include <asm/io.h>
 DECLARE_GLOBAL_DATA_PTR;
 #endif /* !USE_HOSTCC*/
diff --git a/common/image.c b/common/image.c
index a911aa9..f3277c9 100644
--- a/common/image.c
+++ b/common/image.c
@@ -27,6 +27,7 @@
 
 #include <environment.h>
 #include <image.h>
+#include <mapmem.h>
 
 #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
 #include <libfdt.h>
diff --git a/common/iotrace.c b/common/iotrace.c
index ced426e..2725563 100644
--- a/common/iotrace.c
+++ b/common/iotrace.c
@@ -7,6 +7,7 @@
 #define IOTRACE_IMPL
 
 #include <common.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 DECLARE_GLOBAL_DATA_PTR;
diff --git a/common/lcd.c b/common/lcd.c
index f33942c..6982759 100644
--- a/common/lcd.c
+++ b/common/lcd.c
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <stdio_dev.h>
 #include <lcd.h>
+#include <mapmem.h>
 #include <watchdog.h>
 #include <asm/unaligned.h>
 #include <splash.h>
diff --git a/common/malloc_simple.c b/common/malloc_simple.c
index 64ae036..d445199 100644
--- a/common/malloc_simple.c
+++ b/common/malloc_simple.c
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 DECLARE_GLOBAL_DATA_PTR;
diff --git a/drivers/demo/demo-simple.c b/drivers/demo/demo-simple.c
index 2bcb7df..f069748 100644
--- a/drivers/demo/demo-simple.c
+++ b/drivers/demo/demo-simple.c
@@ -10,6 +10,7 @@
 #include <common.h>
 #include <dm.h>
 #include <dm-demo.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 static int simple_hello(struct udevice *dev, int ch)
diff --git a/drivers/i2c/i2c-uniphier-f.c b/drivers/i2c/i2c-uniphier-f.c
index 6707edd..ffa6ce5 100644
--- a/drivers/i2c/i2c-uniphier-f.c
+++ b/drivers/i2c/i2c-uniphier-f.c
@@ -13,6 +13,7 @@
 #include <dm/root.h>
 #include <i2c.h>
 #include <fdtdec.h>
+#include <mapmem.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
diff --git a/drivers/i2c/i2c-uniphier.c b/drivers/i2c/i2c-uniphier.c
index 64a9ed8..760457f 100644
--- a/drivers/i2c/i2c-uniphier.c
+++ b/drivers/i2c/i2c-uniphier.c
@@ -13,6 +13,7 @@
 #include <dm/root.h>
 #include <i2c.h>
 #include <fdtdec.h>
+#include <mapmem.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 4103723..ffc4caa 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -13,6 +13,7 @@
 #include <errno.h>
 #include <fdtdec.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <spi.h>
 #include <spi_flash.h>
 #include <asm/io.h>
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 03beab5..67b1d60 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -8,6 +8,7 @@
 #include <dm.h>
 #include <errno.h>
 #include <fdtdec.h>
+#include <mapmem.h>
 #include <ns16550.h>
 #include <serial.h>
 #include <watchdog.h>
diff --git a/drivers/serial/serial_uniphier.c b/drivers/serial/serial_uniphier.c
index a6bd27f..2a12250 100644
--- a/drivers/serial/serial_uniphier.c
+++ b/drivers/serial/serial_uniphier.c
@@ -10,6 +10,7 @@
 #include <asm/errno.h>
 #include <dm/device.h>
 #include <dm/platform_data/serial-uniphier.h>
+#include <mapmem.h>
 #include <serial.h>
 #include <fdtdec.h>
 
diff --git a/fs/fs.c b/fs/fs.c
index 483273f..ac0897d 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -17,6 +17,7 @@
 #include <config.h>
 #include <errno.h>
 #include <common.h>
+#include <mapmem.h>
 #include <part.h>
 #include <ext4fs.h>
 #include <fat.h>
diff --git a/include/common.h b/include/common.h
index 77c55c6..3ccc6f3 100644
--- a/include/common.h
+++ b/include/common.h
@@ -845,23 +845,6 @@ int cpu_disable(int nr);
 int cpu_release(int nr, int argc, char * const argv[]);
 #endif
 
-/* Define a null map_sysmem() if the architecture doesn't use it */
-# ifndef CONFIG_ARCH_MAP_SYSMEM
-static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
-{
-	return (void *)(uintptr_t)paddr;
-}
-
-static inline void unmap_sysmem(const void *vaddr)
-{
-}
-
-static inline phys_addr_t map_to_sysmem(const void *ptr)
-{
-	return (phys_addr_t)(uintptr_t)ptr;
-}
-# endif
-
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_PPC
diff --git a/include/mapmem.h b/include/mapmem.h
new file mode 100644
index 0000000..42ef3e8
--- /dev/null
+++ b/include/mapmem.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef __MAPMEM_H
+#define __MAPMEM_H
+
+/* Define a null map_sysmem() if the architecture doesn't use it */
+# ifdef CONFIG_ARCH_MAP_SYSMEM
+#include <asm/io.h>
+# else
+static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
+{
+	return (void *)(uintptr_t)paddr;
+}
+
+static inline void unmap_sysmem(const void *vaddr)
+{
+}
+
+static inline phys_addr_t map_to_sysmem(const void *ptr)
+{
+	return (phys_addr_t)(uintptr_t)ptr;
+}
+# endif
+
+#endif /* __MAPMEM_H */
diff --git a/lib/trace.c b/lib/trace.c
index 711e5b5..ad5e07b 100644
--- a/lib/trace.c
+++ b/lib/trace.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <mapmem.h>
 #include <trace.h>
 #include <asm/io.h>
 #include <asm/sections.h>
diff --git a/test/compression.c b/test/compression.c
index ea2e4ad..7ef3a8c 100644
--- a/test/compression.c
+++ b/test/compression.c
@@ -10,6 +10,7 @@
 #include <bootm.h>
 #include <command.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 #include <u-boot/zlib.h>
diff --git a/test/dm/cmd_dm.c b/test/dm/cmd_dm.c
index 79a674e..195815e 100644
--- a/test/dm/cmd_dm.c
+++ b/test/dm/cmd_dm.c
@@ -10,6 +10,7 @@
 #include <common.h>
 #include <dm.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <errno.h>
 #include <asm/io.h>
 #include <dm/root.h>
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 03/27] net: Provide a function to get the current MAC address
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
  2015-03-11 23:43           ` [U-Boot] [PATCH v6 01/27] test: dm: Reorder the objects to build Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 02/27] common: Make sure arch-specific map_sysmem() is defined Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 04/27] net: Rename helper function to be more clear Joe Hershberger
                             ` (25 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

The current implementation exposes the eth_device struct to code that
needs to access the MAC address.  Add a wrapper function for this to
abstract away the pointer for this operation.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 arch/mips/mach-au1x00/au1x00_eth.c   | 2 +-
 arch/powerpc/cpu/mpc8260/ether_fcc.c | 2 +-
 arch/powerpc/cpu/mpc85xx/ether_fcc.c | 2 +-
 arch/powerpc/cpu/mpc8xx/scc.c        | 2 +-
 include/net.h                        | 8 ++++++++
 net/net.c                            | 2 +-
 6 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/arch/mips/mach-au1x00/au1x00_eth.c b/arch/mips/mach-au1x00/au1x00_eth.c
index 39c5b6b..a47f088 100644
--- a/arch/mips/mach-au1x00/au1x00_eth.c
+++ b/arch/mips/mach-au1x00/au1x00_eth.c
@@ -238,7 +238,7 @@ static int au1x00_init(struct eth_device* dev, bd_t * bd){
 	}
 
 	/* Put mac addr in little endian */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
 	*mac_addr_high	=	(ea[5] <<  8) | (ea[4]	    ) ;
 	*mac_addr_low	=	(ea[3] << 24) | (ea[2] << 16) |
 		(ea[1] <<  8) | (ea[0]	    ) ;
diff --git a/arch/powerpc/cpu/mpc8260/ether_fcc.c b/arch/powerpc/cpu/mpc8260/ether_fcc.c
index f9f15b5..f777ba1 100644
--- a/arch/powerpc/cpu/mpc8260/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc8260/ether_fcc.c
@@ -299,7 +299,7 @@ static int fec_init(struct eth_device* dev, bd_t *bis)
      * it unique by setting a few bits in the upper byte of the
      * non-static part of the address.
      */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
     pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
     pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
     pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/arch/powerpc/cpu/mpc85xx/ether_fcc.c b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
index 166dc9e..58d4bfb 100644
--- a/arch/powerpc/cpu/mpc85xx/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
@@ -338,7 +338,7 @@ static int fec_init(struct eth_device* dev, bd_t *bis)
      * it unique by setting a few bits in the upper byte of the
      * non-static part of the address.
      */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
     pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
     pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
     pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/arch/powerpc/cpu/mpc8xx/scc.c b/arch/powerpc/cpu/mpc8xx/scc.c
index 251966b..66e4014 100644
--- a/arch/powerpc/cpu/mpc8xx/scc.c
+++ b/arch/powerpc/cpu/mpc8xx/scc.c
@@ -339,7 +339,7 @@ static int scc_init (struct eth_device *dev, bd_t * bis)
 	pram_ptr->sen_gaddr3 = 0x0;	/* Group Address Filter 3 (unused) */
 	pram_ptr->sen_gaddr4 = 0x0;	/* Group Address Filter 4 (unused) */
 
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
 	pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4];
 	pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2];
 	pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/include/net.h b/include/net.h
index 43e3d28..6c76976 100644
--- a/include/net.h
+++ b/include/net.h
@@ -111,6 +111,14 @@ struct eth_device *eth_get_dev(void)
 {
 	return eth_current;
 }
+
+static inline unsigned char *eth_get_ethaddr(void)
+{
+	if (eth_current)
+		return eth_current->enetaddr;
+	return NULL;
+}
+
 extern struct eth_device *eth_get_dev_by_name(const char *devname);
 extern struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
 extern int eth_get_dev_index(void);		/* get the device index */
diff --git a/net/net.c b/net/net.c
index b60ce62..4b3c90e 100644
--- a/net/net.c
+++ b/net/net.c
@@ -275,7 +275,7 @@ static void NetInitLoop(void)
 		env_changed_id = env_id;
 	}
 	if (eth_get_dev())
-		memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
+		memcpy(NetOurEther, eth_get_ethaddr(), 6);
 
 	return;
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 04/27] net: Rename helper function to be more clear
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (2 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 03/27] net: Provide a function to get the current MAC address Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 05/27] net: Remove unneeded "extern" in net.h Joe Hershberger
                             ` (24 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

Make it clear that the helper is checking the addr, not setting it.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 net/eth.c | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/net/eth.c b/net/eth.c
index eac4f7b..65e8c77 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -153,11 +153,6 @@ static void eth_current_changed(void)
 		setenv("ethact", NULL);
 }
 
-static int eth_address_set(unsigned char *addr)
-{
-	return memcmp(addr, "\0\0\0\0\0\0", 6);
-}
-
 int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		   int eth_number)
 {
@@ -166,9 +161,9 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 
 	eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
 
-	if (eth_address_set(env_enetaddr)) {
-		if (eth_address_set(dev->enetaddr) &&
-				memcmp(dev->enetaddr, env_enetaddr, 6)) {
+	if (!is_zero_ether_addr(env_enetaddr)) {
+		if (!is_zero_ether_addr(dev->enetaddr) &&
+		    memcmp(dev->enetaddr, env_enetaddr, 6)) {
 			printf("\nWarning: %s MAC addresses don't match:\n",
 				dev->name);
 			printf("Address in SROM is         %pM\n",
@@ -183,7 +178,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 					     dev->enetaddr);
 		printf("\nWarning: %s using MAC address from net device\n",
 			dev->name);
-	} else if (!(eth_address_set(dev->enetaddr))) {
+	} else if (is_zero_ether_addr(dev->enetaddr)) {
 		printf("\nError: %s address not set.\n",
 		       dev->name);
 		return -EINVAL;
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 05/27] net: Remove unneeded "extern" in net.h
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (3 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 04/27] net: Rename helper function to be more clear Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 06/27] net: Refactor in preparation for driver model Joe Hershberger
                             ` (23 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

Many of the functions in net.h were preceded extern needlessly. Removing
them to limit the number of checkpatch.pl complaints.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6:
-Fix compile error on boards with CONFIG_API enabled

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/net.h | 90 +++++++++++++++++++++++++++++------------------------------
 1 file changed, 45 insertions(+), 45 deletions(-)

diff --git a/include/net.h b/include/net.h
index 6c76976..51ed5b0 100644
--- a/include/net.h
+++ b/include/net.h
@@ -97,11 +97,11 @@ struct eth_device {
 	void *priv;
 };
 
-extern int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
-extern int eth_register(struct eth_device* dev);/* Register network device */
-extern int eth_unregister(struct eth_device *dev);/* Remove network device */
-extern void eth_try_another(int first_restart);	/* Change the device */
-extern void eth_set_current(void);		/* set nterface to ethcur var */
+int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
+int eth_register(struct eth_device *dev);/* Register network device */
+int eth_unregister(struct eth_device *dev);/* Remove network device */
+void eth_try_another(int first_restart);	/* Change the device */
+void eth_set_current(void);		/* set nterface to ethcur var */
 
 /* get the current device MAC */
 extern struct eth_device *eth_current;
@@ -119,12 +119,12 @@ static inline unsigned char *eth_get_ethaddr(void)
 	return NULL;
 }
 
-extern struct eth_device *eth_get_dev_by_name(const char *devname);
-extern struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
-extern int eth_get_dev_index(void);		/* get the device index */
-extern void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
-extern int eth_getenv_enetaddr(char *name, uchar *enetaddr);
-extern int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
+struct eth_device *eth_get_dev_by_name(const char *devname);
+struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
+int eth_get_dev_index(void);		/* get the device index */
+void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
+int eth_getenv_enetaddr(char *name, uchar *enetaddr);
+int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 
 /*
  * Get the hardware address for an ethernet interface .
@@ -135,20 +135,20 @@ extern int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
  * Returns:
  *	Return true if the address is valid.
  */
-extern int eth_getenv_enetaddr_by_index(const char *base_name, int index,
-					uchar *enetaddr);
+int eth_getenv_enetaddr_by_index(const char *base_name, int index,
+				 uchar *enetaddr);
 
-extern int usb_eth_initialize(bd_t *bi);
-extern int eth_init(bd_t *bis);			/* Initialize the device */
-extern int eth_send(void *packet, int length);	   /* Send a packet */
+int usb_eth_initialize(bd_t *bi);
+int eth_init(bd_t *bis);			/* Initialize the device */
+int eth_send(void *packet, int length);	   /* Send a packet */
 
 #ifdef CONFIG_API
-extern int eth_receive(void *packet, int length); /* Receive a packet*/
+int eth_receive(void *packet, int length); /* Receive a packet*/
 extern void (*push_packet)(void *packet, int length);
 #endif
-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 */
+int eth_rx(void);			/* Check for received packets */
+void eth_halt(void);			/* stop SCC */
+char *eth_get_name(void);		/* get name of current device */
 
 /* Set active state */
 static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
@@ -469,25 +469,25 @@ extern IPaddr_t Mcast_addr;
 #endif
 
 /* Initialize the network adapter */
-extern void net_init(void);
-extern int NetLoop(enum proto_t);
+void net_init(void);
+int NetLoop(enum proto_t);
 
 /* Shutdown adapters and cleanup */
-extern void	NetStop(void);
+void	NetStop(void);
 
 /* Load failed.	 Start again. */
-extern void	NetStartAgain(void);
+void	NetStartAgain(void);
 
 /* Get size of the ethernet header when we send */
-extern int	NetEthHdrSize(void);
+int	NetEthHdrSize(void);
 
 /* Set ethernet header; returns the size of the header */
-extern int NetSetEther(uchar *, uchar *, uint);
-extern int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot);
+int NetSetEther(uchar *, uchar *, uint);
+int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot);
 
 /* Set IP header */
-extern void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source);
-extern void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport,
+void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source);
+void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport,
 				int sport, int len);
 
 /**
@@ -521,12 +521,12 @@ unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new_sum);
 int ip_checksum_ok(const void *addr, unsigned nbytes);
 
 /* Callbacks */
-extern rxhand_f *net_get_udp_handler(void);	/* Get UDP RX packet handler */
-extern void net_set_udp_handler(rxhand_f *);	/* Set UDP RX packet handler */
-extern rxhand_f *net_get_arp_handler(void);	/* Get ARP RX packet handler */
-extern void net_set_arp_handler(rxhand_f *);	/* Set ARP RX packet handler */
-extern void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
-extern void	NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
+rxhand_f *net_get_udp_handler(void);	/* Get UDP RX packet handler */
+void net_set_udp_handler(rxhand_f *);	/* Set UDP RX packet handler */
+rxhand_f *net_get_arp_handler(void);	/* Get ARP RX packet handler */
+void net_set_arp_handler(rxhand_f *);	/* Set ARP RX packet handler */
+void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
+void	NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
 
 /* Network loop state */
 enum net_loop_state {
@@ -559,11 +559,11 @@ static inline void NetSendPacket(uchar *pkt, int len)
  * @param sport Source UDP port
  * @param payload_len Length of data after the UDP header
  */
-extern int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport,
+int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport,
 			int sport, int payload_len);
 
 /* Processes a received packet */
-extern void NetReceive(uchar *, int);
+void NetReceive(uchar *, int);
 
 #ifdef CONFIG_NETCONSOLE
 void NcStart(void);
@@ -711,28 +711,28 @@ static inline void eth_random_addr(uchar *addr)
 }
 
 /* Convert an IP address to a string */
-extern void ip_to_string(IPaddr_t x, char *s);
+void ip_to_string(IPaddr_t x, char *s);
 
 /* Convert a string to ip address */
-extern IPaddr_t string_to_ip(const char *s);
+IPaddr_t string_to_ip(const char *s);
 
 /* Convert a VLAN id to a string */
-extern void VLAN_to_string(ushort x, char *s);
+void VLAN_to_string(ushort x, char *s);
 
 /* Convert a string to a vlan id */
-extern ushort string_to_VLAN(const char *s);
+ushort string_to_VLAN(const char *s);
 
 /* read a VLAN id from an environment variable */
-extern ushort getenv_VLAN(char *);
+ushort getenv_VLAN(char *);
 
 /* copy a filename (allow for "..." notation, limit length) */
-extern void copy_filename(char *dst, const char *src, int size);
+void copy_filename(char *dst, const char *src, int size);
 
 /* get a random source port */
-extern unsigned int random_port(void);
+unsigned int random_port(void);
 
 /* Update U-Boot over TFTP */
-extern int update_tftp(ulong addr);
+int update_tftp(ulong addr);
 
 /**********************************************************************/
 
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 06/27] net: Refactor in preparation for driver model
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (4 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 05/27] net: Remove unneeded "extern" in net.h Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 07/27] net: Change return codes from net/eth.c to use errorno constants Joe Hershberger
                             ` (22 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

Move some things around and organize things so that the driver model
implementation will fit in more easily.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5:
-Fixed warning from missing declaration

Changes in v4:
-Fix compile regression in !DM_ETH case

Changes in v3:
-Move the get_dev_by_* protos to also be !DM_ETH like the impl

Changes in v2: None

 include/net.h | 68 +++++++++++++++++++++++++-------------------------
 net/eth.c     | 79 ++++++++++++++++++++++++++++++++---------------------------
 2 files changed, 78 insertions(+), 69 deletions(-)

diff --git a/include/net.h b/include/net.h
index 51ed5b0..fdf6860 100644
--- a/include/net.h
+++ b/include/net.h
@@ -97,13 +97,9 @@ struct eth_device {
 	void *priv;
 };
 
-int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
 int eth_register(struct eth_device *dev);/* Register network device */
 int eth_unregister(struct eth_device *dev);/* Remove network device */
-void eth_try_another(int first_restart);	/* Change the device */
-void eth_set_current(void);		/* set nterface to ethcur var */
 
-/* get the current device MAC */
 extern struct eth_device *eth_current;
 
 static inline __attribute__((always_inline))
@@ -111,7 +107,10 @@ struct eth_device *eth_get_dev(void)
 {
 	return eth_current;
 }
+struct eth_device *eth_get_dev_by_name(const char *devname);
+struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
 
+/* get the current device MAC */
 static inline unsigned char *eth_get_ethaddr(void)
 {
 	if (eth_current)
@@ -119,8 +118,37 @@ static inline unsigned char *eth_get_ethaddr(void)
 	return NULL;
 }
 
-struct eth_device *eth_get_dev_by_name(const char *devname);
-struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
+/* Set active state */
+static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
+{
+	eth_get_dev()->state = ETH_STATE_ACTIVE;
+
+	return 0;
+}
+/* Set passive state */
+static inline __attribute__((always_inline)) void eth_halt_state_only(void)
+{
+	eth_get_dev()->state = ETH_STATE_PASSIVE;
+}
+
+/*
+ * Set the hardware address for an ethernet interface based on 'eth%daddr'
+ * environment variable (or just 'ethaddr' if eth_number is 0).
+ * Args:
+ *	base_name - base name for device (normally "eth")
+ *	eth_number - value of %d (0 for first device of this type)
+ * Returns:
+ *	0 is success, non-zero is error status from driver.
+ */
+int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
+		     int eth_number);
+
+int usb_eth_initialize(bd_t *bi);
+
+int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
+void eth_try_another(int first_restart);	/* Change the device */
+void eth_set_current(void);		/* set nterface to ethcur var */
+
 int eth_get_dev_index(void);		/* get the device index */
 void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
 int eth_getenv_enetaddr(char *name, uchar *enetaddr);
@@ -138,7 +166,6 @@ int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 int eth_getenv_enetaddr_by_index(const char *base_name, int index,
 				 uchar *enetaddr);
 
-int usb_eth_initialize(bd_t *bi);
 int eth_init(bd_t *bis);			/* Initialize the device */
 int eth_send(void *packet, int length);	   /* Send a packet */
 
@@ -148,32 +175,7 @@ extern void (*push_packet)(void *packet, int length);
 #endif
 int eth_rx(void);			/* Check for received packets */
 void eth_halt(void);			/* stop SCC */
-char *eth_get_name(void);		/* get name of current device */
-
-/* Set active state */
-static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
-{
-	eth_get_dev()->state = ETH_STATE_ACTIVE;
-
-	return 0;
-}
-/* Set passive state */
-static inline __attribute__((always_inline)) void eth_halt_state_only(void)
-{
-	eth_get_dev()->state = ETH_STATE_PASSIVE;
-}
-
-/*
- * Set the hardware address for an ethernet interface based on 'eth%daddr'
- * environment variable (or just 'ethaddr' if eth_number is 0).
- * Args:
- *	base_name - base name for device (normally "eth")
- *	eth_number - value of %d (0 for first device of this type)
- * Returns:
- *	0 is success, non-zero is error status from driver.
- */
-int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
-		     int eth_number);
+const char *eth_get_name(void);		/* get name of current device */
 
 #ifdef CONFIG_MCAST_TFTP
 int eth_mcast_join(IPaddr_t mcast_addr, u8 join);
diff --git a/net/eth.c b/net/eth.c
index 65e8c77..84919e0 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -55,6 +55,14 @@ static inline int eth_setenv_enetaddr_by_index(const char *base_name, int index,
 	return eth_setenv_enetaddr(enetvar, enetaddr);
 }
 
+static void eth_env_init(void)
+{
+	const char *s;
+
+	s = getenv("bootfile");
+	if (s != NULL)
+		copy_filename(BootFile, s, sizeof(BootFile));
+}
 
 static int eth_mac_skip(int index)
 {
@@ -64,6 +72,8 @@ static int eth_mac_skip(int index)
 	return ((skip_state = getenv(enetvar)) != NULL);
 }
 
+static void eth_current_changed(void);
+
 /*
  * CPU and board-specific Ethernet initializations.  Aliased function
  * signals caller to move on
@@ -87,6 +97,11 @@ static unsigned int eth_rcv_current, eth_rcv_last;
 static struct eth_device *eth_devices;
 struct eth_device *eth_current;
 
+static void eth_set_current_to_next(void)
+{
+	eth_current = eth_current->next;
+}
+
 struct eth_device *eth_get_dev_by_name(const char *devname)
 {
 	struct eth_device *dev, *target_dev;
@@ -137,22 +152,6 @@ int eth_get_dev_index(void)
 	return eth_current->index;
 }
 
-static void eth_current_changed(void)
-{
-	char *act = getenv("ethact");
-	/* update current ethernet name */
-	if (eth_current) {
-		if (act == NULL || strcmp(act, eth_current->name) != 0)
-			setenv("ethact", eth_current->name);
-	}
-	/*
-	 * remove the variable completely if there is no active
-	 * interface
-	 */
-	else if (act != NULL)
-		setenv("ethact", NULL);
-}
-
 int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		   int eth_number)
 {
@@ -251,14 +250,6 @@ int eth_unregister(struct eth_device *dev)
 	return 0;
 }
 
-static void eth_env_init(bd_t *bis)
-{
-	const char *s;
-
-	if ((s = getenv("bootfile")) != NULL)
-		copy_filename(BootFile, s, sizeof(BootFile));
-}
-
 int eth_initialize(bd_t *bis)
 {
 	int num_devices = 0;
@@ -274,7 +265,7 @@ int eth_initialize(bd_t *bis)
 	phy_init();
 #endif
 
-	eth_env_init(bis);
+	eth_env_init();
 
 	/*
 	 * If board-specific initialization exists, call it.
@@ -479,6 +470,22 @@ int eth_receive(void *packet, int length)
 }
 #endif /* CONFIG_API */
 
+static void eth_current_changed(void)
+{
+	char *act = getenv("ethact");
+	/* update current ethernet name */
+	if (eth_get_dev()) {
+		if (act == NULL || strcmp(act, eth_get_name()) != 0)
+			setenv("ethact", eth_get_name());
+	}
+	/*
+	 * remove the variable completely if there is no active
+	 * interface
+	 */
+	else if (act != NULL)
+		setenv("ethact", NULL);
+}
+
 void eth_try_another(int first_restart)
 {
 	static struct eth_device *first_failed;
@@ -492,17 +499,17 @@ void eth_try_another(int first_restart)
 	if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
 		return;
 
-	if (!eth_current)
+	if (!eth_get_dev())
 		return;
 
 	if (first_restart)
-		first_failed = eth_current;
+		first_failed = eth_get_dev();
 
-	eth_current = eth_current->next;
+	eth_set_current_to_next();
 
 	eth_current_changed();
 
-	if (first_failed == eth_current)
+	if (first_failed == eth_get_dev())
 		NetRestartWrap = 1;
 }
 
@@ -513,7 +520,7 @@ void eth_set_current(void)
 	struct eth_device *old_current;
 	int	env_id;
 
-	if (!eth_current)	/* XXX no current */
+	if (!eth_get_dev())	/* XXX no current */
 		return;
 
 	env_id = get_env_id();
@@ -522,18 +529,18 @@ void eth_set_current(void)
 		env_changed_id = env_id;
 	}
 	if (act != NULL) {
-		old_current = eth_current;
+		old_current = eth_get_dev();
 		do {
-			if (strcmp(eth_current->name, act) == 0)
+			if (strcmp(eth_get_name(), act) == 0)
 				return;
-			eth_current = eth_current->next;
-		} while (old_current != eth_current);
+			eth_set_current_to_next();
+		} while (old_current != eth_get_dev());
 	}
 
 	eth_current_changed();
 }
 
-char *eth_get_name(void)
+const char *eth_get_name(void)
 {
-	return eth_current ? eth_current->name : "unknown";
+	return eth_get_dev() ? eth_get_dev()->name : "unknown";
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 07/27] net: Change return codes from net/eth.c to use errorno constants
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (5 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 06/27] net: Refactor in preparation for driver model Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 08/27] net: Use int instead of u8 for boolean flag Joe Hershberger
                             ` (21 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

Many functions returned -1 previously. Change them to return appropriate error
codes.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reported-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5: None
Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 net/eth.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/net/eth.c b/net/eth.c
index 84919e0..9ad15cd 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -227,7 +227,7 @@ int eth_unregister(struct eth_device *dev)
 
 	/* No device */
 	if (!eth_devices)
-		return -1;
+		return -ENODEV;
 
 	for (cur = eth_devices; cur->next != eth_devices && cur->next != dev;
 	     cur = cur->next)
@@ -235,7 +235,7 @@ int eth_unregister(struct eth_device *dev)
 
 	/* Device not found */
 	if (cur->next != dev)
-		return -1;
+		return -ENODEV;
 
 	cur->next = dev->next;
 
@@ -368,7 +368,7 @@ int eth_init(bd_t *bis)
 
 	if (!eth_current) {
 		puts("No ethernet found.\n");
-		return -1;
+		return -ENODEV;
 	}
 
 	/* Sync environment with network devices */
@@ -397,7 +397,7 @@ int eth_init(bd_t *bis)
 		eth_try_another(0);
 	} while (old_current != eth_current);
 
-	return -1;
+	return -ETIMEDOUT;
 }
 
 void eth_halt(void)
@@ -413,7 +413,7 @@ void eth_halt(void)
 int eth_send(void *packet, int length)
 {
 	if (!eth_current)
-		return -1;
+		return -ENODEV;
 
 	return eth_current->send(eth_current, packet, length);
 }
@@ -421,7 +421,7 @@ int eth_send(void *packet, int length)
 int eth_rx(void)
 {
 	if (!eth_current)
-		return -1;
+		return -ENODEV;
 
 	return eth_current->recv(eth_current);
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 08/27] net: Use int instead of u8 for boolean flag
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (6 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 07/27] net: Change return codes from net/eth.c to use errorno constants Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 09/27] net: Remove the bd* parameter from net stack functions Joe Hershberger
                             ` (20 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

On some archs masking the parameter is inefficient, so don't use u8.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reported-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5: None
Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 include/net.h | 2 +-
 net/eth.c     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/net.h b/include/net.h
index fdf6860..cec5612 100644
--- a/include/net.h
+++ b/include/net.h
@@ -178,7 +178,7 @@ void eth_halt(void);			/* stop SCC */
 const char *eth_get_name(void);		/* get name of current device */
 
 #ifdef CONFIG_MCAST_TFTP
-int eth_mcast_join(IPaddr_t mcast_addr, u8 join);
+int eth_mcast_join(IPaddr_t mcast_addr, int join);
 u32 ether_crc(size_t len, unsigned char const *p);
 #endif
 
diff --git a/net/eth.c b/net/eth.c
index 9ad15cd..b86994e 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -321,7 +321,7 @@ int eth_initialize(bd_t *bis)
  * mcast_addr: multicast ipaddr from which multicast Mac is made
  * join: 1=join, 0=leave.
  */
-int eth_mcast_join(IPaddr_t mcast_ip, u8 join)
+int eth_mcast_join(IPaddr_t mcast_ip, int join)
 {
 	u8 mcast_mac[6];
 	if (!eth_current || !eth_current->mcast)
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 09/27] net: Remove the bd* parameter from net stack functions
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (7 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 08/27] net: Use int instead of u8 for boolean flag Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-20 23:01             ` Simon Glass
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 10/27] net: Make netretry actually do something Joe Hershberger
                             ` (19 subsequent siblings)
  28 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

This value is not used by the network stack and is available in the
global data, so stop passing it around.  For the one legacy function
that still expects it (init op on old Ethernet drivers) pass in the
global pointer version directly to avoid changing that interface.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reported-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6:
-Fix compile errors for other boards due to removed parameters

Changes in v5: None
Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 api/api_net.c                             |  2 +-
 arch/arm/lib/board.c                      |  2 +-
 arch/avr32/lib/board.c                    |  2 +-
 arch/m68k/lib/board.c                     |  4 ++--
 arch/nds32/lib/board.c                    |  2 +-
 arch/openrisc/lib/board.c                 |  2 +-
 arch/powerpc/lib/board.c                  |  2 +-
 arch/sh/lib/board.c                       |  2 +-
 arch/sparc/lib/board.c                    |  2 +-
 board/BuS/eb_cpux9k2/cpux9k2.c            |  2 +-
 board/BuS/vl_ma2sc/vl_ma2sc.c             |  2 +-
 board/atmel/at91sam9261ek/at91sam9261ek.c |  2 +-
 board/egnite/ethernut5/ethernut5.c        |  2 +-
 board/ronetix/pm9261/pm9261.c             |  2 +-
 board/ronetix/pm9g45/pm9g45.c             |  2 +-
 common/board_r.c                          |  2 +-
 common/spl/spl_net.c                      |  2 +-
 drivers/net/netconsole.c                  |  4 ++--
 include/net.h                             |  6 +++---
 net/eth.c                                 | 12 +++++++-----
 net/net.c                                 |  7 +++----
 21 files changed, 33 insertions(+), 32 deletions(-)

diff --git a/api/api_net.c b/api/api_net.c
index 7b3805e..04e4f4a 100644
--- a/api/api_net.c
+++ b/api/api_net.c
@@ -37,7 +37,7 @@ int dev_open_net(void *cookie)
 	if (!dev_valid_net(cookie))
 		return API_ENODEV;
 
-	if (eth_init(gd->bd) < 0)
+	if (eth_init() < 0)
 		return API_EIO;
 
 	return 0;
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
index f606255..37ea6e9 100644
--- a/arch/arm/lib/board.c
+++ b/arch/arm/lib/board.c
@@ -644,7 +644,7 @@ void board_init_r(gd_t *id, ulong dest_addr)
 #endif
 #if defined(CONFIG_CMD_NET)
 	puts("Net:   ");
-	eth_initialize(gd->bd);
+	eth_initialize();
 #if defined(CONFIG_RESET_PHY_R)
 	debug("Reset Ethernet PHY\n");
 	reset_phy();
diff --git a/arch/avr32/lib/board.c b/arch/avr32/lib/board.c
index 99aa96e..aacfcbf 100644
--- a/arch/avr32/lib/board.c
+++ b/arch/avr32/lib/board.c
@@ -244,7 +244,7 @@ void board_init_r(gd_t *new_gd, ulong dest_addr)
 #endif
 #if defined(CONFIG_CMD_NET)
 	puts("Net:   ");
-	eth_initialize(gd->bd);
+	eth_initialize();
 #endif
 
 #ifdef CONFIG_GENERIC_ATMEL_MCI
diff --git a/arch/m68k/lib/board.c b/arch/m68k/lib/board.c
index 9caff73..c54a3f7 100644
--- a/arch/m68k/lib/board.c
+++ b/arch/m68k/lib/board.c
@@ -566,10 +566,10 @@ void board_init_r (gd_t *id, ulong dest_addr)
 #if defined(CONFIG_CMD_NET)
 	WATCHDOG_RESET();
 #if defined(FEC_ENET)
-	eth_init(bd);
+	eth_init();
 #endif
 	puts ("Net:   ");
-	eth_initialize (bd);
+	eth_initialize();
 #endif
 
 #ifdef CONFIG_POST
diff --git a/arch/nds32/lib/board.c b/arch/nds32/lib/board.c
index 4c06a48..24a09bc 100644
--- a/arch/nds32/lib/board.c
+++ b/arch/nds32/lib/board.c
@@ -383,7 +383,7 @@ void board_init_r(gd_t *id, ulong dest_addr)
 #if defined(CONFIG_CMD_NET)
 	puts("Net:   ");
 
-	eth_initialize(gd->bd);
+	eth_initialize();
 #if defined(CONFIG_RESET_PHY_R)
 	debug("Reset Ethernet PHY\n");
 	reset_phy();
diff --git a/arch/openrisc/lib/board.c b/arch/openrisc/lib/board.c
index 2346685..c26cc8f 100644
--- a/arch/openrisc/lib/board.c
+++ b/arch/openrisc/lib/board.c
@@ -128,7 +128,7 @@ void board_init(void)
 
 #if defined(CONFIG_CMD_NET)
 	puts("NET:   ");
-	eth_initialize(bd);
+	eth_initialize();
 #endif
 
 	/* main_loop */
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
index 91645d3..5ea29cc 100644
--- a/arch/powerpc/lib/board.c
+++ b/arch/powerpc/lib/board.c
@@ -890,7 +890,7 @@ void board_init_r(gd_t *id, ulong dest_addr)
 #if defined(CONFIG_CMD_NET)
 	WATCHDOG_RESET();
 	puts("Net:   ");
-	eth_initialize(bd);
+	eth_initialize();
 #endif
 
 #if defined(CONFIG_CMD_NET) && defined(CONFIG_RESET_PHY_R)
diff --git a/arch/sh/lib/board.c b/arch/sh/lib/board.c
index 1eb7afb..6dad3c7 100644
--- a/arch/sh/lib/board.c
+++ b/arch/sh/lib/board.c
@@ -178,7 +178,7 @@ void sh_generic_init(void)
 #endif
 #if defined(CONFIG_CMD_NET)
 	puts("Net:   ");
-	eth_initialize(gd->bd);
+	eth_initialize();
 #endif /* CONFIG_CMD_NET */
 
 	while (1) {
diff --git a/arch/sparc/lib/board.c b/arch/sparc/lib/board.c
index b311a94..d2ac6bc 100644
--- a/arch/sparc/lib/board.c
+++ b/arch/sparc/lib/board.c
@@ -351,7 +351,7 @@ void board_init_f(ulong bootflag)
 #if defined(CONFIG_CMD_NET)
 	WATCHDOG_RESET();
 	puts("Net:   ");
-	eth_initialize(bd);
+	eth_initialize();
 #endif
 
 #if defined(CONFIG_CMD_NET) && defined(CONFIG_RESET_PHY_R)
diff --git a/board/BuS/eb_cpux9k2/cpux9k2.c b/board/BuS/eb_cpux9k2/cpux9k2.c
index 76ad7c4..3880a06 100644
--- a/board/BuS/eb_cpux9k2/cpux9k2.c
+++ b/board/BuS/eb_cpux9k2/cpux9k2.c
@@ -111,7 +111,7 @@ int misc_init_r(void)
 void reset_phy(void)
 {
 	udelay(10000);
-	eth_init(gd->bd);
+	eth_init();
 }
 #endif
 
diff --git a/board/BuS/vl_ma2sc/vl_ma2sc.c b/board/BuS/vl_ma2sc/vl_ma2sc.c
index da39c86..e4e1a85 100644
--- a/board/BuS/vl_ma2sc/vl_ma2sc.c
+++ b/board/BuS/vl_ma2sc/vl_ma2sc.c
@@ -280,7 +280,7 @@ void reset_phy(void)
 	 * Initialize ethernet HW addr prior to starting Linux,
 	 * needed for nfsroot
 	 */
-	eth_init(gd->bd);
+	eth_init();
 #endif
 }
 #endif
diff --git a/board/atmel/at91sam9261ek/at91sam9261ek.c b/board/atmel/at91sam9261ek/at91sam9261ek.c
index a301d72..5250474 100644
--- a/board/atmel/at91sam9261ek/at91sam9261ek.c
+++ b/board/atmel/at91sam9261ek/at91sam9261ek.c
@@ -275,7 +275,7 @@ void reset_phy(void)
 	 * Initialize ethernet HW addr prior to starting Linux,
 	 * needed for nfsroot
 	 */
-	eth_init(gd->bd);
+	eth_init();
 #endif
 }
 #endif
diff --git a/board/egnite/ethernut5/ethernut5.c b/board/egnite/ethernut5/ethernut5.c
index b45213c..67d3984 100644
--- a/board/egnite/ethernut5/ethernut5.c
+++ b/board/egnite/ethernut5/ethernut5.c
@@ -204,7 +204,7 @@ int board_eth_init(bd_t *bis)
 		miiphy_write(devname, 0, MII_BMCR, BMCR_RESET);
 	}
 	/* Sync environment with network devices, needed for nfsroot. */
-	return eth_init(gd->bd);
+	return eth_init();
 }
 #endif
 
diff --git a/board/ronetix/pm9261/pm9261.c b/board/ronetix/pm9261/pm9261.c
index 1f7679a..b96f745 100644
--- a/board/ronetix/pm9261/pm9261.c
+++ b/board/ronetix/pm9261/pm9261.c
@@ -288,7 +288,7 @@ void reset_phy(void)
 	 * Initialize ethernet HW addr prior to starting Linux,
 	 * needed for nfsroot
 	 */
-	eth_init(gd->bd);
+	eth_init();
 #endif
 }
 #endif
diff --git a/board/ronetix/pm9g45/pm9g45.c b/board/ronetix/pm9g45/pm9g45.c
index 15aa4ac..efc4133 100644
--- a/board/ronetix/pm9g45/pm9g45.c
+++ b/board/ronetix/pm9g45/pm9g45.c
@@ -166,7 +166,7 @@ void reset_phy(void)
 	 * Initialize ethernet HW addr prior to starting Linux,
 	 * needed for nfsroot
 	 */
-	eth_init(gd->bd);
+	eth_init();
 #endif
 }
 #endif
diff --git a/common/board_r.c b/common/board_r.c
index af0f274..b882d9b 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -585,7 +585,7 @@ static int initr_bbmii(void)
 static int initr_net(void)
 {
 	puts("Net:   ");
-	eth_initialize(gd->bd);
+	eth_initialize();
 #if defined(CONFIG_RESET_PHY_R)
 	debug("Reset Ethernet PHY\n");
 	reset_phy();
diff --git a/common/spl/spl_net.c b/common/spl/spl_net.c
index ff53705..af4952f 100644
--- a/common/spl/spl_net.c
+++ b/common/spl/spl_net.c
@@ -21,7 +21,7 @@ void spl_net_load_image(const char *device)
 	env_relocate();
 	setenv("autoload", "yes");
 	load_addr = CONFIG_SYS_TEXT_BASE - sizeof(struct image_header);
-	rv = eth_initialize(gd->bd);
+	rv = eth_initialize();
 	if (rv == 0) {
 		printf("No Ethernet devices found\n");
 		hang();
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 677c89f..87cea7a 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -193,11 +193,11 @@ static void nc_send_packet(const char *buf, int len)
 
 	if (eth->state != ETH_STATE_ACTIVE) {
 		if (eth_is_on_demand_init()) {
-			if (eth_init(gd->bd) < 0)
+			if (eth_init() < 0)
 				return;
 			eth_set_last_protocol(NETCONS);
 		} else
-			eth_init_state_only(gd->bd);
+			eth_init_state_only();
 
 		inited = 1;
 	}
diff --git a/include/net.h b/include/net.h
index cec5612..ae0f31a 100644
--- a/include/net.h
+++ b/include/net.h
@@ -119,7 +119,7 @@ static inline unsigned char *eth_get_ethaddr(void)
 }
 
 /* Set active state */
-static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
+static inline __attribute__((always_inline)) int eth_init_state_only(void)
 {
 	eth_get_dev()->state = ETH_STATE_ACTIVE;
 
@@ -145,7 +145,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 
 int usb_eth_initialize(bd_t *bi);
 
-int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
+int eth_initialize(void);		/* Initialize network subsystem */
 void eth_try_another(int first_restart);	/* Change the device */
 void eth_set_current(void);		/* set nterface to ethcur var */
 
@@ -166,7 +166,7 @@ int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 int eth_getenv_enetaddr_by_index(const char *base_name, int index,
 				 uchar *enetaddr);
 
-int eth_init(bd_t *bis);			/* Initialize the device */
+int eth_init(void);			/* Initialize the device */
 int eth_send(void *packet, int length);	   /* Send a packet */
 
 #ifdef CONFIG_API
diff --git a/net/eth.c b/net/eth.c
index b86994e..66ecb79 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -12,6 +12,8 @@
 #include <phy.h>
 #include <asm/errno.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 void eth_parse_enetaddr(const char *addr, uchar *enetaddr)
 {
 	char *end;
@@ -250,7 +252,7 @@ int eth_unregister(struct eth_device *dev)
 	return 0;
 }
 
-int eth_initialize(bd_t *bis)
+int eth_initialize(void)
 {
 	int num_devices = 0;
 	eth_devices = NULL;
@@ -272,10 +274,10 @@ int eth_initialize(bd_t *bis)
 	 * If not, call a CPU-specific one
 	 */
 	if (board_eth_init != __def_eth_init) {
-		if (board_eth_init(bis) < 0)
+		if (board_eth_init(gd->bd) < 0)
 			printf("Board Net Initialization Failed\n");
 	} else if (cpu_eth_init != __def_eth_init) {
-		if (cpu_eth_init(bis) < 0)
+		if (cpu_eth_init(gd->bd) < 0)
 			printf("CPU Net Initialization Failed\n");
 	} else
 		printf("Net Initialization Skipped\n");
@@ -362,7 +364,7 @@ u32 ether_crc(size_t len, unsigned char const *p)
 #endif
 
 
-int eth_init(bd_t *bis)
+int eth_init(void)
 {
 	struct eth_device *old_current, *dev;
 
@@ -387,7 +389,7 @@ int eth_init(bd_t *bis)
 	do {
 		debug("Trying %s\n", eth_current->name);
 
-		if (eth_current->init(eth_current, bis) >= 0) {
+		if (eth_current->init(eth_current, gd->bd) >= 0) {
 			eth_current->state = ETH_STATE_ACTIVE;
 
 			return 0;
diff --git a/net/net.c b/net/net.c
index 4b3c90e..e5ab07c 100644
--- a/net/net.c
+++ b/net/net.c
@@ -324,7 +324,6 @@ void net_init(void)
 
 int NetLoop(enum proto_t protocol)
 {
-	bd_t *bd = gd->bd;
 	int ret = -1;
 
 	NetRestarted = 0;
@@ -337,12 +336,12 @@ int NetLoop(enum proto_t protocol)
 	if (eth_is_on_demand_init() || protocol != NETCONS) {
 		eth_halt();
 		eth_set_current();
-		if (eth_init(bd) < 0) {
+		if (eth_init() < 0) {
 			eth_halt();
 			return -1;
 		}
 	} else
-		eth_init_state_only(bd);
+		eth_init_state_only();
 
 restart:
 #ifdef CONFIG_USB_KEYBOARD
@@ -618,7 +617,7 @@ void NetStartAgain(void)
 #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
 	eth_try_another(!NetRestarted);
 #endif
-	eth_init(gd->bd);
+	eth_init();
 	if (NetRestartWrap) {
 		NetRestartWrap = 0;
 		if (NetDevExists) {
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 10/27] net: Make netretry actually do something
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (8 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 09/27] net: Remove the bd* parameter from net stack functions Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 11/27] net: Access mapped physmem in net functions Joe Hershberger
                             ` (18 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

netretry previously would only retry in one specific case (your MAC
address is not set) and no other. This is basically useless. In the DM
implementation for eth it turns this into a completely useless case
since an un-configured MAC address results in not even entering the
NetLoop. The behavior is now changed to retry any failed command
(rotating through the eth adapters if ethrotate != no).

It also defaulted to retry forever. It is now changed to default to not
retry

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5: None
Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 net/net.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/net/net.c b/net/net.c
index e5ab07c..37b4aab 100644
--- a/net/net.c
+++ b/net/net.c
@@ -527,6 +527,8 @@ restart:
 			(*x)();
 		}
 
+		if (net_state == NETLOOP_FAIL)
+			NetStartAgain();
 
 		switch (net_state) {
 
@@ -602,8 +604,10 @@ void NetStartAgain(void)
 			retrycnt = 1;
 		else
 			retrycnt = simple_strtoul(nretry, NULL, 0);
-	} else
-		retry_forever = 1;
+	} else {
+		retrycnt = 0;
+		retry_forever = 0;
+	}
 
 	if ((!retry_forever) && (NetTryCount >= retrycnt)) {
 		eth_halt();
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 11/27] net: Access mapped physmem in net functions
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (9 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 10/27] net: Make netretry actually do something Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 12/27] cmd: net: Clean up return codes Joe Hershberger
                             ` (17 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

Previously the net functions would access memory assuming physmem did
not need to be mapped.  In sandbox, that's not the case.

Now we map the physmem specified by the user in loadaddr to the buffer
that represents that space.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5:
-Include new mapmem.h header
-Unmap memory for consistency

Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 net/nfs.c  | 6 +++++-
 net/tftp.c | 6 +++++-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/net/nfs.c b/net/nfs.c
index 381b75f..8e05ae5 100644
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -26,6 +26,7 @@
 #include <command.h>
 #include <net.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include "nfs.h"
 #include "bootp.h"
 
@@ -93,7 +94,10 @@ store_block(uchar *src, unsigned offset, unsigned len)
 	} else
 #endif /* CONFIG_SYS_DIRECT_FLASH_NFS */
 	{
-		(void)memcpy((void *)(load_addr + offset), src, len);
+		void *ptr = map_sysmem(load_addr + offset, len);
+
+		memcpy(ptr, src, len);
+		unmap_sysmem(ptr);
 	}
 
 	if (NetBootFileXferSize < (offset+len))
diff --git a/net/tftp.c b/net/tftp.c
index 0a2c533..51c67be 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <mapmem.h>
 #include <net.h>
 #include "tftp.h"
 #include "bootp.h"
@@ -184,7 +185,10 @@ store_block(int block, uchar *src, unsigned len)
 	} else
 #endif /* CONFIG_SYS_DIRECT_FLASH_TFTP */
 	{
-		(void)memcpy((void *)(load_addr + offset), src, len);
+		void *ptr = map_sysmem(load_addr + offset, len);
+
+		memcpy(ptr, src, len);
+		unmap_sysmem(ptr);
 	}
 #ifdef CONFIG_MCAST_TFTP
 	if (Multicast)
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 12/27] cmd: net: Clean up return codes
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (10 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 11/27] net: Access mapped physmem in net functions Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 13/27] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
                             ` (16 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

The return codes in common/cmd_net.c had a number of inconsistencies.
Update them to all use the enum from command.h

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5:
-New to v5

Changes in v4: None
Changes in v3: None
Changes in v2: None

 common/cmd_net.c | 45 +++++++++++++++++++++------------------------
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/common/cmd_net.c b/common/cmd_net.c
index 09489d4..3f52edc 100644
--- a/common/cmd_net.c
+++ b/common/cmd_net.c
@@ -44,10 +44,7 @@ U_BOOT_CMD(
 #ifdef CONFIG_CMD_TFTPPUT
 int do_tftpput(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	int ret;
-
-	ret = netboot_common(TFTPPUT, cmdtp, argc, argv);
-	return ret;
+	return netboot_common(TFTPPUT, cmdtp, argc, argv);
 }
 
 U_BOOT_CMD(
@@ -217,7 +214,7 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 		if (strict_strtoul(argv[1], 16, &save_addr) < 0 ||
 			strict_strtoul(argv[2], 16, &save_size) < 0) {
 			printf("Invalid address/size\n");
-			return cmd_usage(cmdtp);
+			return CMD_RET_USAGE;
 		}
 		copy_filename(BootFile, argv[3], sizeof(BootFile));
 		break;
@@ -230,7 +227,7 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 
 	if ((size = NetLoop(proto)) < 0) {
 		bootstage_error(BOOTSTAGE_ID_NET_NETLOOP_OK);
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 	bootstage_mark(BOOTSTAGE_ID_NET_NETLOOP_OK);
 
@@ -240,7 +237,7 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 	/* done if no file was loaded (no errors though) */
 	if (size == 0) {
 		bootstage_error(BOOTSTAGE_ID_NET_LOADED);
-		return 0;
+		return CMD_RET_SUCCESS;
 	}
 
 	/* flush cache */
@@ -250,10 +247,10 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 
 	rcode = bootm_maybe_autostart(cmdtp, argv[0]);
 
-	if (rcode < 0)
-		bootstage_error(BOOTSTAGE_ID_NET_DONE_ERR);
-	else
+	if (rcode == CMD_RET_SUCCESS)
 		bootstage_mark(BOOTSTAGE_ID_NET_DONE);
+	else
+		bootstage_error(BOOTSTAGE_ID_NET_DONE_ERR);
 	return rcode;
 }
 
@@ -261,7 +258,7 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 static int do_ping(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	if (argc < 2)
-		return -1;
+		return CMD_RET_USAGE;
 
 	NetPingIP = string_to_ip(argv[1]);
 	if (NetPingIP == 0)
@@ -269,12 +266,12 @@ static int do_ping(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 	if (NetLoop(PING) < 0) {
 		printf("ping failed; host %s is not alive\n", argv[1]);
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 
 	printf("host %s is alive\n", argv[1]);
 
-	return 0;
+	return CMD_RET_SUCCESS;
 }
 
 U_BOOT_CMD(
@@ -313,12 +310,12 @@ int do_cdp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	r = NetLoop(CDP);
 	if (r < 0) {
 		printf("cdp failed; perhaps not a CISCO switch?\n");
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 
 	cdp_update_env();
 
-	return 0;
+	return CMD_RET_SUCCESS;
 }
 
 U_BOOT_CMD(
@@ -337,13 +334,13 @@ int do_sntp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		NetNtpServerIP = getenv_IPaddr("ntpserverip");
 		if (NetNtpServerIP == 0) {
 			printf("ntpserverip not set\n");
-			return (1);
+			return CMD_RET_FAILURE;
 		}
 	} else {
 		NetNtpServerIP = string_to_ip(argv[1]);
 		if (NetNtpServerIP == 0) {
 			printf("Bad NTP server IP address\n");
-			return (1);
+			return CMD_RET_FAILURE;
 		}
 	}
 
@@ -356,10 +353,10 @@ int do_sntp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	if (NetLoop(SNTP) < 0) {
 		printf("SNTP failed: host %pI4 not responding\n",
 			&NetNtpServerIP);
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 
-	return 0;
+	return CMD_RET_SUCCESS;
 }
 
 U_BOOT_CMD(
@@ -389,7 +386,7 @@ int do_dns(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	 */
 	if (strlen(argv[1]) >= 255) {
 		printf("dns error: hostname too long\n");
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 
 	NetDNSResolve = argv[1];
@@ -401,10 +398,10 @@ int do_dns(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 	if (NetLoop(DNS) < 0) {
 		printf("dns lookup of %s failed, check setup\n", argv[1]);
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 
-	return 0;
+	return CMD_RET_SUCCESS;
 }
 
 U_BOOT_CMD(
@@ -422,7 +419,7 @@ static int do_link_local(cmd_tbl_t *cmdtp, int flag, int argc,
 	char tmp[22];
 
 	if (NetLoop(LINKLOCAL) < 0)
-		return 1;
+		return CMD_RET_FAILURE;
 
 	NetOurGatewayIP = 0;
 	ip_to_string(NetOurGatewayIP, tmp);
@@ -435,7 +432,7 @@ static int do_link_local(cmd_tbl_t *cmdtp, int flag, int argc,
 	setenv("ipaddr", tmp);
 	setenv("llipaddr", tmp); /* store this for next time */
 
-	return 0;
+	return CMD_RET_SUCCESS;
 }
 
 U_BOOT_CMD(
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 13/27] dm: eth: Add basic driver model support to Ethernet stack
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (11 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 12/27] cmd: net: Clean up return codes Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 14/27] net: Clean up network stack names used in DM drivers Joe Hershberger
                             ` (15 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

First just add support for MAC drivers.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5:
-Add a note to doc/README.drivers.eth about its obsolescence
-Expanded the Kconfig help
-Moved dm/ header
-Use local var for priv in eth_get_dev()

Changes in v4:
--Don't prevent eth_initialize on driver model
--If current == NULL, always check if there is a device available in eth_get_dev
--Include ethprime handling in eth_initialize
--Look up MAC address in post-probe
--Move env init call from uclass init to eth_initialize
--Print the alias in eth_initialize
--Use eth_initialize to probe all devices and write_hwaddr
-Add a helper function for eth_uclass_priv
-Add documentation to the structures
-Add eth_get_ops helper
-Change -1 returns to error constants
-Change puts to printf
-Redo the seq / probe implementation
-Remove bd_t *bis from dm eth_ops init function
-Remove checks for driver==NULL
-Remove priv pointer in per-device priv struct (drivers already get their own directly from DM)
-Rename halt() to stop() in ops
-Rename init() to start() in ops
-Stop handling selecting a new "current" in pre-unbind as it will now work itself out by clearing the pointer

Changes in v3:
--Fail init if not activated
--Fail probe if ethaddr not set
-Allow current eth dev to be NULL
-Correct failure chaining from bind to probe to init
-Correct the pre_unbind logic
-Fixed blank line formatting for variable declaration
-Update ethaddr from env unconditionally on init
-Use set current to select the current device regardless of the previous selection

Changes in v2:
-Cause an invalid name to fail binding
-Changed eth_uclass_priv local var names to be uc_priv
-Move the hwaddr to platdata so that its memory is allocated at bind when we need it
-Prevent device from being probed before used by a command (i.e. before eth_init()).
-Rebase on top of dm/master
-Removed extra parentheses
-Stop maintaining our own index and use DM seq now that it works for our needs
-Update error codes
-Updated comments

 common/cmd_bdinfo.c    |   2 +
 doc/README.drivers.eth |   6 +
 drivers/net/Kconfig    |   9 ++
 include/dm/uclass-id.h |   1 +
 include/net.h          |  52 ++++++++
 net/eth.c              | 346 ++++++++++++++++++++++++++++++++++++++++++++++++-
 6 files changed, 410 insertions(+), 6 deletions(-)

diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
index aa81da2..b4cce25 100644
--- a/common/cmd_bdinfo.c
+++ b/common/cmd_bdinfo.c
@@ -34,6 +34,7 @@ static void print_eth(int idx)
 	printf("%-12s= %s\n", name, val);
 }
 
+#ifndef CONFIG_DM_ETH
 __maybe_unused
 static void print_eths(void)
 {
@@ -52,6 +53,7 @@ static void print_eths(void)
 	printf("current eth = %s\n", eth_get_name());
 	printf("ip_addr     = %s\n", getenv("ipaddr"));
 }
+#endif
 
 __maybe_unused
 static void print_lnum(const char *name, unsigned long long value)
diff --git a/doc/README.drivers.eth b/doc/README.drivers.eth
index eb83038..98728bc 100644
--- a/doc/README.drivers.eth
+++ b/doc/README.drivers.eth
@@ -1,3 +1,9 @@
+!!! WARNING !!!
+
+This guide describes to the old way of doing things. No new Ethernet drivers
+should be implemented this way. All new drivers should be written against the
+U-Boot core driver model. See doc/driver-model/README.txt
+
 -----------------------
  Ethernet Driver Guide
 -----------------------
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index e69de29..94cf099 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -0,0 +1,9 @@
+config DM_ETH
+	bool "Enable Driver Model for Ethernet drivers"
+	depends on DM
+	help
+	  Enable driver model for Ethernet.
+
+	  The eth_*() interface will be implemented by the UC_ETH class
+	  This is currently implemented in net/eth.c
+	  Look in include/net.h for details.
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 91bb90d..ad96682 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -34,6 +34,7 @@ enum uclass_id {
 	UCLASS_I2C_GENERIC,	/* Generic I2C device */
 	UCLASS_I2C_EEPROM,	/* I2C EEPROM device */
 	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
+	UCLASS_ETH,		/* Ethernet device */
 
 	UCLASS_COUNT,
 	UCLASS_INVALID = -1,
diff --git a/include/net.h b/include/net.h
index ae0f31a..fff82cb 100644
--- a/include/net.h
+++ b/include/net.h
@@ -78,6 +78,57 @@ enum eth_state_t {
 	ETH_STATE_ACTIVE
 };
 
+#ifdef CONFIG_DM_ETH
+/**
+ * struct eth_pdata - Platform data for Ethernet MAC controllers
+ *
+ * @iobase: The base address of the hardware registers
+ * @enetaddr: The Ethernet MAC address that is loaded from EEPROM or env
+ */
+struct eth_pdata {
+	phys_addr_t iobase;
+	unsigned char enetaddr[6];
+};
+
+/**
+ * struct eth_ops - functions of Ethernet MAC controllers
+ *
+ * start: Prepare the hardware to send and receive packets
+ * send: Send the bytes passed in "packet" as a packet on the wire
+ * recv: Check if the hardware received a packet. Call the network stack if so
+ * stop: Stop the hardware from looking for packets - may be called even if
+ *	 state == PASSIVE
+ * mcast: Join or leave a multicast group (for TFTP) - optional
+ * write_hwaddr: Write a MAC address to the hardware (used to pass it to Linux
+ *		 on some platforms like ARM). This function expects the
+ *		 eth_pdata::enetaddr field to be populated - optional
+ * read_rom_hwaddr: Some devices have a backup of the MAC address stored in a
+ *		    ROM on the board. This is how the driver should expose it
+ *		    to the network stack. This function should fill in the
+ *		    eth_pdata::enetaddr field - optional
+ */
+struct eth_ops {
+	int (*start)(struct udevice *dev);
+	int (*send)(struct udevice *dev, void *packet, int length);
+	int (*recv)(struct udevice *dev);
+	void (*stop)(struct udevice *dev);
+#ifdef CONFIG_MCAST_TFTP
+	int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
+#endif
+	int (*write_hwaddr)(struct udevice *dev);
+	int (*read_rom_hwaddr)(struct udevice *dev);
+};
+
+#define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
+
+struct udevice *eth_get_dev(void); /* get the current device */
+unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
+/* Used only when NetConsole is enabled */
+int eth_init_state_only(void); /* Set active state */
+void eth_halt_state_only(void); /* Set passive state */
+#endif
+
+#ifndef CONFIG_DM_ETH
 struct eth_device {
 	char name[16];
 	unsigned char enetaddr[6];
@@ -144,6 +195,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		     int eth_number);
 
 int usb_eth_initialize(bd_t *bi);
+#endif
 
 int eth_initialize(void);		/* Initialize network subsystem */
 void eth_try_another(int first_restart);	/* Change the device */
diff --git a/net/eth.c b/net/eth.c
index 66ecb79..1abf027 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -1,16 +1,19 @@
 /*
- * (C) Copyright 2001-2010
+ * (C) Copyright 2001-2015
  * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ * Joe Hershberger, National Instruments
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #include <common.h>
 #include <command.h>
+#include <dm.h>
 #include <net.h>
 #include <miiphy.h>
 #include <phy.h>
 #include <asm/errno.h>
+#include <dm/device-internal.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -76,6 +79,339 @@ static int eth_mac_skip(int index)
 
 static void eth_current_changed(void);
 
+#ifdef CONFIG_DM_ETH
+/**
+ * struct eth_device_priv - private structure for each Ethernet device
+ *
+ * @state: The state of the Ethernet MAC driver (defined by enum eth_state_t)
+ */
+struct eth_device_priv {
+	enum eth_state_t state;
+};
+
+/**
+ * struct eth_uclass_priv - The structure attached to the uclass itself
+ *
+ * @current: The Ethernet device that the network functions are using
+ */
+struct eth_uclass_priv {
+	struct udevice *current;
+};
+
+static struct eth_uclass_priv *eth_get_uclass_priv(void)
+{
+	struct uclass *uc;
+
+	uclass_get(UCLASS_ETH, &uc);
+	assert(uc);
+	return uc->priv;
+}
+
+static void eth_set_current_to_next(void)
+{
+	struct eth_uclass_priv *uc_priv;
+
+	uc_priv = eth_get_uclass_priv();
+	if (uc_priv->current)
+		uclass_next_device(&uc_priv->current);
+	if (!uc_priv->current)
+		uclass_first_device(UCLASS_ETH, &uc_priv->current);
+}
+
+struct udevice *eth_get_dev(void)
+{
+	struct eth_uclass_priv *uc_priv;
+
+	uc_priv = eth_get_uclass_priv();
+	if (!uc_priv->current)
+		uclass_first_device(UCLASS_ETH,
+				    &uc_priv->current);
+	return uc_priv->current;
+}
+
+static void eth_set_dev(struct udevice *dev)
+{
+	device_probe(dev);
+	eth_get_uclass_priv()->current = dev;
+}
+
+unsigned char *eth_get_ethaddr(void)
+{
+	struct eth_pdata *pdata;
+
+	if (eth_get_dev()) {
+		pdata = eth_get_dev()->platdata;
+		return pdata->enetaddr;
+	}
+
+	return NULL;
+}
+
+/* Set active state without calling start on the driver */
+int eth_init_state_only(void)
+{
+	struct udevice *current;
+	struct eth_device_priv *priv;
+
+	current = eth_get_dev();
+	if (!current || !device_active(current))
+		return -EINVAL;
+
+	priv = current->uclass_priv;
+	priv->state = ETH_STATE_ACTIVE;
+
+	return 0;
+}
+
+/* Set passive state without calling stop on the driver */
+void eth_halt_state_only(void)
+{
+	struct udevice *current;
+	struct eth_device_priv *priv;
+
+	current = eth_get_dev();
+	if (!current || !device_active(current))
+		return;
+
+	priv = current->uclass_priv;
+	priv->state = ETH_STATE_PASSIVE;
+}
+
+int eth_get_dev_index(void)
+{
+	if (eth_get_dev())
+		return eth_get_dev()->seq;
+	return -1;
+}
+
+int eth_init(void)
+{
+	struct udevice *current;
+	struct udevice *old_current;
+
+	current = eth_get_dev();
+	if (!current) {
+		printf("No ethernet found.\n");
+		return -ENODEV;
+	}
+
+	old_current = current;
+	do {
+		debug("Trying %s\n", current->name);
+
+		if (device_active(current)) {
+			uchar env_enetaddr[6];
+			struct eth_pdata *pdata = current->platdata;
+
+			/* Sync environment with network device */
+			if (eth_getenv_enetaddr_by_index("eth", current->seq,
+							 env_enetaddr))
+				memcpy(pdata->enetaddr, env_enetaddr, 6);
+			else
+				memset(pdata->enetaddr, 0, 6);
+
+			if (eth_get_ops(current)->start(current) >= 0) {
+				struct eth_device_priv *priv =
+					current->uclass_priv;
+
+				priv->state = ETH_STATE_ACTIVE;
+				return 0;
+			}
+		}
+		debug("FAIL\n");
+
+		/* This will ensure the new "current" attempted to probe */
+		eth_try_another(0);
+		current = eth_get_dev();
+	} while (old_current != current);
+
+	return -ENODEV;
+}
+
+void eth_halt(void)
+{
+	struct udevice *current;
+	struct eth_device_priv *priv;
+
+	current = eth_get_dev();
+	if (!current || !device_active(current))
+		return;
+
+	eth_get_ops(current)->stop(current);
+	priv = current->uclass_priv;
+	priv->state = ETH_STATE_PASSIVE;
+}
+
+int eth_send(void *packet, int length)
+{
+	struct udevice *current;
+
+	current = eth_get_dev();
+	if (!current)
+		return -ENODEV;
+
+	if (!device_active(current))
+		return -EINVAL;
+
+	return eth_get_ops(current)->send(current, packet, length);
+}
+
+int eth_rx(void)
+{
+	struct udevice *current;
+
+	current = eth_get_dev();
+	if (!current)
+		return -ENODEV;
+
+	if (!device_active(current))
+		return -EINVAL;
+
+	return eth_get_ops(current)->recv(current);
+}
+
+static int eth_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev->platdata;
+	int ret = 0;
+
+	if (!dev || !device_active(dev))
+		return -EINVAL;
+
+	/* seq is valid since the device is active */
+	if (eth_get_ops(dev)->write_hwaddr && !eth_mac_skip(dev->seq)) {
+		if (!is_valid_ether_addr(pdata->enetaddr)) {
+			printf("\nError: %s address %pM illegal value\n",
+			       dev->name, pdata->enetaddr);
+			return -EINVAL;
+		}
+
+		ret = eth_get_ops(dev)->write_hwaddr(dev);
+		if (ret)
+			printf("\nWarning: %s failed to set MAC address\n",
+			       dev->name);
+	}
+
+	return ret;
+}
+
+int eth_initialize(void)
+{
+	int num_devices = 0;
+	struct udevice *dev;
+
+	bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
+	eth_env_init();
+
+	/*
+	 * Devices need to write the hwaddr even if not started so that Linux
+	 * will have access to the hwaddr that u-boot stored for the device.
+	 * This is accomplished by attempting to probe each device and calling
+	 * their write_hwaddr() operation.
+	 */
+	uclass_first_device(UCLASS_ETH, &dev);
+	if (!dev) {
+		printf("No ethernet found.\n");
+		bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
+	} else {
+		bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
+		do {
+			if (num_devices)
+				printf(", ");
+
+			printf("eth%d: %s", dev->seq, dev->name);
+
+			eth_write_hwaddr(dev);
+
+			uclass_next_device(&dev);
+			num_devices++;
+		} while (dev);
+
+		putc('\n');
+	}
+
+	return num_devices;
+}
+
+static int eth_post_bind(struct udevice *dev)
+{
+	if (strchr(dev->name, ' ')) {
+		printf("\nError: eth device name \"%s\" has a space!\n",
+		       dev->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int eth_pre_unbind(struct udevice *dev)
+{
+	/* Don't hang onto a pointer that is going away */
+	if (dev == eth_get_uclass_priv()->current)
+		eth_set_dev(NULL);
+
+	return 0;
+}
+
+static int eth_post_probe(struct udevice *dev)
+{
+	struct eth_device_priv *priv = dev->uclass_priv;
+	struct eth_pdata *pdata = dev->platdata;
+	unsigned char env_enetaddr[6];
+
+	priv->state = ETH_STATE_INIT;
+
+	/* Check if the device has a MAC address in ROM */
+	if (eth_get_ops(dev)->read_rom_hwaddr)
+		eth_get_ops(dev)->read_rom_hwaddr(dev);
+
+	eth_getenv_enetaddr_by_index("eth", dev->seq, env_enetaddr);
+	if (!is_zero_ether_addr(env_enetaddr)) {
+		if (!is_zero_ether_addr(pdata->enetaddr) &&
+		    memcmp(pdata->enetaddr, env_enetaddr, 6)) {
+			printf("\nWarning: %s MAC addresses don't match:\n",
+			       dev->name);
+			printf("Address in SROM is         %pM\n",
+			       pdata->enetaddr);
+			printf("Address in environment is  %pM\n",
+			       env_enetaddr);
+		}
+
+		/* Override the ROM MAC address */
+		memcpy(pdata->enetaddr, env_enetaddr, 6);
+	} else if (is_valid_ether_addr(pdata->enetaddr)) {
+		eth_setenv_enetaddr_by_index("eth", dev->seq, pdata->enetaddr);
+		printf("\nWarning: %s using MAC address from ROM\n",
+		       dev->name);
+	} else if (is_zero_ether_addr(pdata->enetaddr)) {
+		printf("\nError: %s address not set.\n",
+		       dev->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int eth_pre_remove(struct udevice *dev)
+{
+	eth_get_ops(dev)->stop(dev);
+
+	return 0;
+}
+
+UCLASS_DRIVER(eth) = {
+	.name		= "eth",
+	.id		= UCLASS_ETH,
+	.post_bind	= eth_post_bind,
+	.pre_unbind	= eth_pre_unbind,
+	.post_probe	= eth_post_probe,
+	.pre_remove	= eth_pre_remove,
+	.priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
+	.per_device_auto_alloc_size = sizeof(struct eth_device_priv),
+};
+#endif
+
+#ifndef CONFIG_DM_ETH
 /*
  * CPU and board-specific Ethernet initializations.  Aliased function
  * signals caller to move on
@@ -427,6 +763,7 @@ int eth_rx(void)
 
 	return eth_current->recv(eth_current);
 }
+#endif /* ifndef CONFIG_DM_ETH */
 
 #ifdef CONFIG_API
 static void eth_save_packet(void *packet, int length)
@@ -490,7 +827,7 @@ static void eth_current_changed(void)
 
 void eth_try_another(int first_restart)
 {
-	static struct eth_device *first_failed;
+	static void *first_failed;
 	char *ethrotate;
 
 	/*
@@ -519,12 +856,9 @@ void eth_set_current(void)
 {
 	static char *act;
 	static int  env_changed_id;
-	struct eth_device *old_current;
+	void *old_current;
 	int	env_id;
 
-	if (!eth_get_dev())	/* XXX no current */
-		return;
-
 	env_id = get_env_id();
 	if ((act == NULL) || (env_changed_id != env_id)) {
 		act = getenv("ethact");
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 14/27] net: Clean up network stack names used in DM drivers
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (12 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 13/27] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 15/27] dm: eth: Pass the packet pointer as a parameter to recv Joe Hershberger
                             ` (14 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

Take the opportunity to enforce better names on newly written or
retrofitted Ethernet drivers.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5:
-New to v5

Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/net.h |  9 ++++++++-
 net/net.c     | 30 +++++++++++++++++++-----------
 2 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/include/net.h b/include/net.h
index fff82cb..31ef1ff 100644
--- a/include/net.h
+++ b/include/net.h
@@ -466,7 +466,11 @@ extern uchar		NetServerEther[6];	/* Boot server enet address */
 extern IPaddr_t		NetOurIP;	/* Our    IP addr (0 = unknown) */
 extern IPaddr_t		NetServerIP;	/* Server IP addr (0 = unknown) */
 extern uchar		*NetTxPacket;		/* THE transmit packet */
+#ifdef CONFIG_DM_ETH
+extern uchar		*net_rx_packets[PKTBUFSRX]; /* Receive packets */
+#else
 extern uchar		*NetRxPackets[PKTBUFSRX]; /* Receive packets */
+#endif
 extern uchar		*NetRxPacket;		/* Current receive packet */
 extern int		NetRxPacketLen;		/* Current rx packet length */
 extern unsigned		NetIPID;		/* IP ID (counting) */
@@ -616,8 +620,11 @@ static inline void NetSendPacket(uchar *pkt, int len)
 int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport,
 			int sport, int payload_len);
 
+#ifndef CONFIG_DM_ETH
+#define NetReceive(in_packet, len) net_process_received_packet(in_packet, len)
+#endif
 /* Processes a received packet */
-void NetReceive(uchar *, int);
+void net_process_received_packet(uchar *in_packet, int len);
 
 #ifdef CONFIG_NETCONSOLE
 void NcStart(void);
diff --git a/net/net.c b/net/net.c
index 37b4aab..afec443 100644
--- a/net/net.c
+++ b/net/net.c
@@ -183,10 +183,13 @@ int		NetTimeOffset;
 #endif
 
 static uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
-
+#ifdef CONFIG_DM_ETH
+/* Receive packets */
+uchar *net_rx_packets[PKTBUFSRX];
+#else
 /* Receive packet */
 uchar *NetRxPackets[PKTBUFSRX];
-
+#endif
 /* Current UDP RX packet handler */
 static rxhand_f *udp_packet_handler;
 /* Current ARP RX packet handler */
@@ -304,9 +307,15 @@ void net_init(void)
 
 		NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
 		NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
+#ifdef CONFIG_DM_ETH
+		for (i = 0; i < PKTBUFSRX; i++) {
+			net_rx_packets[i] = NetTxPacket + (i + 1) *
+				PKTSIZE_ALIGN;
+		}
+#else
 		for (i = 0; i < PKTBUFSRX; i++)
 			NetRxPackets[i] = NetTxPacket + (i + 1) * PKTSIZE_ALIGN;
-
+#endif
 		ArpInit();
 		net_clear_handlers();
 
@@ -952,8 +961,7 @@ static void receive_icmp(struct ip_udp_hdr *ip, int len,
 	}
 }
 
-void
-NetReceive(uchar *inpkt, int len)
+void net_process_received_packet(uchar *in_packet, int len)
 {
 	struct ethernet_hdr *et;
 	struct ip_udp_hdr *ip;
@@ -967,9 +975,9 @@ NetReceive(uchar *inpkt, int len)
 
 	debug_cond(DEBUG_NET_PKT, "packet received\n");
 
-	NetRxPacket = inpkt;
+	NetRxPacket = in_packet;
 	NetRxPacketLen = len;
-	et = (struct ethernet_hdr *)inpkt;
+	et = (struct ethernet_hdr *)in_packet;
 
 	/* too small packet? */
 	if (len < ETHER_HDR_SIZE)
@@ -977,7 +985,7 @@ NetReceive(uchar *inpkt, int len)
 
 #ifdef CONFIG_API
 	if (push_packet) {
-		(*push_packet)(inpkt, len);
+		(*push_packet)(in_packet, len);
 		return;
 	}
 #endif
@@ -1004,11 +1012,11 @@ NetReceive(uchar *inpkt, int len)
 		 */
 		eth_proto = ntohs(et802->et_prot);
 
-		ip = (struct ip_udp_hdr *)(inpkt + E802_HDR_SIZE);
+		ip = (struct ip_udp_hdr *)(in_packet + E802_HDR_SIZE);
 		len -= E802_HDR_SIZE;
 
 	} else if (eth_proto != PROT_VLAN) {	/* normal packet */
-		ip = (struct ip_udp_hdr *)(inpkt + ETHER_HDR_SIZE);
+		ip = (struct ip_udp_hdr *)(in_packet + ETHER_HDR_SIZE);
 		len -= ETHER_HDR_SIZE;
 
 	} else {			/* VLAN packet */
@@ -1033,7 +1041,7 @@ NetReceive(uchar *inpkt, int len)
 		vlanid = cti & VLAN_IDMASK;
 		eth_proto = ntohs(vet->vet_type);
 
-		ip = (struct ip_udp_hdr *)(inpkt + VLAN_ETHER_HDR_SIZE);
+		ip = (struct ip_udp_hdr *)(in_packet + VLAN_ETHER_HDR_SIZE);
 		len -= VLAN_ETHER_HDR_SIZE;
 	}
 
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 15/27] dm: eth: Pass the packet pointer as a parameter to recv
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (13 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 14/27] net: Clean up network stack names used in DM drivers Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-20 12:10             ` Simon Glass
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 16/27] sandbox: eth: Add network support to sandbox Joe Hershberger
                             ` (13 subsequent siblings)
  28 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

Stop forcing drivers to call net_process_received_packet() - formerly
called NetReceive(). Now the uclass will handle calling the driver for
each packet until the driver errors or has nothing to return. The uclass
will then pass the good packets off to the network stack by calling
net_process_received_packet().

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v6:
-Swallow -EAGAIN error in eth_rx()
-Updated function documentation

Changes in v5:
-New to v5

Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/net.h |  6 ++++--
 net/eth.c     | 15 ++++++++++++++-
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/include/net.h b/include/net.h
index 31ef1ff..241a096 100644
--- a/include/net.h
+++ b/include/net.h
@@ -95,7 +95,9 @@ struct eth_pdata {
  *
  * start: Prepare the hardware to send and receive packets
  * send: Send the bytes passed in "packet" as a packet on the wire
- * recv: Check if the hardware received a packet. Call the network stack if so
+ * recv: Check if the hardware received a packet. If so, set the pointer to the
+ *	 packet buffer in the packetp parameter. If not, return an error or 0 to
+ *	 indicate that the hardware receive FIFO is empty
  * stop: Stop the hardware from looking for packets - may be called even if
  *	 state == PASSIVE
  * mcast: Join or leave a multicast group (for TFTP) - optional
@@ -110,7 +112,7 @@ struct eth_pdata {
 struct eth_ops {
 	int (*start)(struct udevice *dev);
 	int (*send)(struct udevice *dev, void *packet, int length);
-	int (*recv)(struct udevice *dev);
+	int (*recv)(struct udevice *dev, uchar **packetp);
 	void (*stop)(struct udevice *dev);
 #ifdef CONFIG_MCAST_TFTP
 	int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
diff --git a/net/eth.c b/net/eth.c
index 1abf027..058c55a 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -259,6 +259,9 @@ int eth_send(void *packet, int length)
 int eth_rx(void)
 {
 	struct udevice *current;
+	uchar *packet;
+	int ret;
+	int i;
 
 	current = eth_get_dev();
 	if (!current)
@@ -267,7 +270,17 @@ int eth_rx(void)
 	if (!device_active(current))
 		return -EINVAL;
 
-	return eth_get_ops(current)->recv(current);
+	/* Process up to 32 packets at one time */
+	for (i = 0; i < 32; i++) {
+		ret = eth_get_ops(current)->recv(current, &packet);
+		if (ret > 0)
+			net_process_received_packet(packet, ret);
+		else
+			break;
+	}
+	if (ret == -EAGAIN)
+		ret = 0;
+	return ret;
 }
 
 static int eth_write_hwaddr(struct udevice *dev)
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 16/27] sandbox: eth: Add network support to sandbox
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (14 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 15/27] dm: eth: Pass the packet pointer as a parameter to recv Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 17/27] sandbox: eth: Add ARP and PING response to sandbox driver Joe Hershberger
                             ` (12 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

Add basic network support to sandbox which includes a network driver.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5:
-Added help to the sandbox eth mock driver Kconfig entry

Changes in v4:
-Cleaned up sandbox EXTRA_ENV define
-Moved config to Kconfig

Changes in v3:
-Added 2 more ethaddr to sandbox
-Print which device in the debug write hwaddr

Changes in v2:
-Change printfs to debug in sandbox driver
-Remove unused priv struct for sandbox driver

 arch/sandbox/Kconfig         |  9 +++++
 arch/sandbox/dts/sandbox.dts |  4 +++
 board/sandbox/README.sandbox |  4 +--
 drivers/net/Kconfig          | 23 ++++++++++++
 drivers/net/Makefile         |  1 +
 drivers/net/sandbox.c        | 84 ++++++++++++++++++++++++++++++++++++++++++++
 include/configs/sandbox.h    | 16 +++++----
 7 files changed, 133 insertions(+), 8 deletions(-)
 create mode 100644 drivers/net/sandbox.c

diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index 2098b9c..186b58d 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -34,4 +34,13 @@ config DM_I2C
 config DM_TEST
 	default y
 
+config NET
+	default y
+
+config NETDEVICES
+	default y
+
+config DM_ETH
+	default y
+
 endmenu
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 9ce31bf..36b3bd8 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -181,4 +181,8 @@
 		};
 	};
 
+	eth at 10002000 {
+		compatible = "sandbox,eth";
+		reg = <0x10002000 0x1000>;
+	};
 };
diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
index 3c0df17..c1f5f7e 100644
--- a/board/sandbox/README.sandbox
+++ b/board/sandbox/README.sandbox
@@ -173,16 +173,16 @@ U-Boot sandbox supports these emulations:
 - Chrome OS EC
 - GPIO
 - Host filesystem (access files on the host from within U-Boot)
+- I2C
 - Keyboard (Chrome OS)
 - LCD
+- Network
 - Serial (for console only)
 - Sound (incomplete - see sandbox_sdl_sound_init() for details)
 - SPI
 - SPI flash
 - TPM (Trusted Platform Module)
 
-Notable omissions are networking and I2C.
-
 A wide range of commands is implemented. Filesystems which use a block
 device are supported.
 
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 94cf099..e46e57b 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -7,3 +7,26 @@ config DM_ETH
 	  The eth_*() interface will be implemented by the UC_ETH class
 	  This is currently implemented in net/eth.c
 	  Look in include/net.h for details.
+
+menuconfig NETDEVICES
+	bool "Network device support"
+	depends on NET
+	help
+	  You must select Y to enable any network device support
+	  Generally if you have any networking support this is a given
+
+	  If unsure, say Y
+
+if NETDEVICES
+
+config ETH_SANDBOX
+	depends on DM_ETH && SANDBOX
+	default y
+	bool "Sandbox: Mocked Ethernet driver"
+	help
+	  This driver simply responds with fake ARP replies and ping
+	  replies that are used to verify network stack functionality
+
+	  This driver is particularly useful in the test/dm/eth.c tests
+
+endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index b8b0803..a17198c 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_NS8382X) += ns8382x.o
 obj-$(CONFIG_PCNET) += pcnet.o
 obj-$(CONFIG_RTL8139) += rtl8139.o
 obj-$(CONFIG_RTL8169) += rtl8169.o
+obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
 obj-$(CONFIG_SH_ETHER) += sh_eth.o
 obj-$(CONFIG_SMC91111) += smc91111.o
 obj-$(CONFIG_SMC911X) += smc911x.o
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
new file mode 100644
index 0000000..522990d
--- /dev/null
+++ b/drivers/net/sandbox.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int sb_eth_start(struct udevice *dev)
+{
+	debug("eth_sandbox: Start\n");
+
+	return 0;
+}
+
+static int sb_eth_send(struct udevice *dev, void *packet, int length)
+{
+	debug("eth_sandbox: Send packet %d\n", length);
+
+	return 0;
+}
+
+static int sb_eth_recv(struct udevice *dev, uchar **packetp)
+{
+	return 0;
+}
+
+static void sb_eth_stop(struct udevice *dev)
+{
+	debug("eth_sandbox: Stop\n");
+}
+
+static int sb_eth_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	debug("eth_sandbox %s: Write HW ADDR - %pM\n", dev->name,
+	      pdata->enetaddr);
+	return 0;
+}
+
+static const struct eth_ops sb_eth_ops = {
+	.start			= sb_eth_start,
+	.send			= sb_eth_send,
+	.recv			= sb_eth_recv,
+	.stop			= sb_eth_stop,
+	.write_hwaddr		= sb_eth_write_hwaddr,
+};
+
+static int sb_eth_remove(struct udevice *dev)
+{
+	return 0;
+}
+
+static int sb_eth_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	pdata->iobase = dev_get_addr(dev);
+	return 0;
+}
+
+static const struct udevice_id sb_eth_ids[] = {
+	{ .compatible = "sandbox,eth" },
+	{ }
+};
+
+U_BOOT_DRIVER(eth_sandbox) = {
+	.name	= "eth_sandbox",
+	.id	= UCLASS_ETH,
+	.of_match = sb_eth_ids,
+	.ofdata_to_platdata = sb_eth_ofdata_to_platdata,
+	.remove	= sb_eth_remove,
+	.ops	= &sb_eth_ops,
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index febbfb6..664b984 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -126,9 +126,6 @@
 /* include default commands */
 #include <config_cmd_default.h>
 
-/* We don't have networking support yet */
-#undef CONFIG_CMD_NET
-#undef CONFIG_CMD_NFS
 
 #define CONFIG_CMD_HASH
 #define CONFIG_HASH_VERIFY
@@ -165,16 +162,23 @@
 
 #define CONFIG_KEYBOARD
 
-#define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial,cros-ec-keyb\0" \
+#define SANDBOX_SERIAL_SETTINGS		"stdin=serial,cros-ec-keyb\0" \
 					"stdout=serial,lcd\0" \
 					"stderr=serial,lcd\0"
 #else
-
-#define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial\0" \
+#define SANDBOX_SERIAL_SETTINGS		"stdin=serial\0" \
 					"stdout=serial,lcd\0" \
 					"stderr=serial,lcd\0"
 #endif
 
+#define SANDBOX_ETH_SETTINGS		"ethaddr=00:00:11:22:33:44\0" \
+					"eth1addr=00:00:11:22:33:45\0" \
+					"eth2addr=00:00:11:22:33:46\0" \
+					"ipaddr=1.2.3.4\0"
+
+#define CONFIG_EXTRA_ENV_SETTINGS	SANDBOX_SERIAL_SETTINGS \
+					SANDBOX_ETH_SETTINGS
+
 #define CONFIG_GZIP_COMPRESSED
 #define CONFIG_BZIP2
 #define CONFIG_LZO
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 17/27] sandbox: eth: Add ARP and PING response to sandbox driver
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (15 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 16/27] sandbox: eth: Add network support to sandbox Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 18/27] test: dm: eth: Add tests for the eth dm implementation Joe Hershberger
                             ` (11 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

The sandbox driver will now generate response traffic to exercise the
ping command even when no network exists.  This allows the basic data
pathways of the DM to be tested.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v6: None
Changes in v5:
-Simplify sandbox eth driver by switching from int array to byte array
-Switch priv from packet buffer to a pointer to net_rx_packets[0]

Changes in v4:
-Removed checks on priv != NULL and added protection in uclass instead

Changes in v3:
-Prevent a crash if memory is not allocated

Changes in v2:
-Change printfs to debug in sandbox driver
-Move fake hwaddr to the device tree
-Move static data to priv

 arch/sandbox/dts/sandbox.dts |   1 +
 drivers/net/sandbox.c        | 107 +++++++++++++++++++++++++++++++++++++++++++
 include/configs/sandbox.h    |   1 +
 3 files changed, 109 insertions(+)

diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 36b3bd8..c2a3304 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -184,5 +184,6 @@
 	eth at 10002000 {
 		compatible = "sandbox,eth";
 		reg = <0x10002000 0x1000>;
+		fake-host-hwaddr = [00 00 66 44 22 00];
 	};
 };
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
index 522990d..cb69a95 100644
--- a/drivers/net/sandbox.c
+++ b/drivers/net/sandbox.c
@@ -14,22 +14,128 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/**
+ * struct eth_sandbox_priv - memory for sandbox mock driver
+ *
+ * fake_host_hwaddr: MAC address of mocked machine
+ * fake_host_ipaddr: IP address of mocked machine
+ * recv_packet_buffer: buffer of the packet returned as received
+ * recv_packet_length: length of the packet returned as received
+ */
+struct eth_sandbox_priv {
+	uchar fake_host_hwaddr[ARP_HLEN];
+	IPaddr_t fake_host_ipaddr;
+	uchar *recv_packet_buffer;
+	int recv_packet_length;
+};
+
 static int sb_eth_start(struct udevice *dev)
 {
+	struct eth_sandbox_priv *priv = dev_get_priv(dev);
+
 	debug("eth_sandbox: Start\n");
 
+	fdtdec_get_byte_array(gd->fdt_blob, dev->of_offset, "fake-host-hwaddr",
+			      priv->fake_host_hwaddr, ARP_HLEN);
+	priv->recv_packet_buffer = net_rx_packets[0];
 	return 0;
 }
 
 static int sb_eth_send(struct udevice *dev, void *packet, int length)
 {
+	struct eth_sandbox_priv *priv = dev_get_priv(dev);
+	struct ethernet_hdr *eth = packet;
+
 	debug("eth_sandbox: Send packet %d\n", length);
 
+	if (ntohs(eth->et_protlen) == PROT_ARP) {
+		struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
+
+		if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
+			struct ethernet_hdr *eth_recv;
+			struct arp_hdr *arp_recv;
+
+			/* store this as the assumed IP of the fake host */
+			priv->fake_host_ipaddr = NetReadIP(&arp->ar_tpa);
+			/* Formulate a fake response */
+			eth_recv = (void *)priv->recv_packet_buffer;
+			memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
+			memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
+			       ARP_HLEN);
+			eth_recv->et_protlen = htons(PROT_ARP);
+
+			arp_recv = (void *)priv->recv_packet_buffer +
+				ETHER_HDR_SIZE;
+			arp_recv->ar_hrd = htons(ARP_ETHER);
+			arp_recv->ar_pro = htons(PROT_IP);
+			arp_recv->ar_hln = ARP_HLEN;
+			arp_recv->ar_pln = ARP_PLEN;
+			arp_recv->ar_op = htons(ARPOP_REPLY);
+			memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr,
+			       ARP_HLEN);
+			NetWriteIP(&arp_recv->ar_spa, priv->fake_host_ipaddr);
+			memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN);
+			NetCopyIP(&arp_recv->ar_tpa, &arp->ar_spa);
+
+			priv->recv_packet_length = ETHER_HDR_SIZE +
+				ARP_HDR_SIZE;
+		}
+	} else if (ntohs(eth->et_protlen) == PROT_IP) {
+		struct ip_udp_hdr *ip = packet + ETHER_HDR_SIZE;
+
+		if (ip->ip_p == IPPROTO_ICMP) {
+			struct icmp_hdr *icmp = (struct icmp_hdr *)&ip->udp_src;
+
+			if (icmp->type == ICMP_ECHO_REQUEST) {
+				struct ethernet_hdr *eth_recv;
+				struct ip_udp_hdr *ipr;
+				struct icmp_hdr *icmpr;
+
+				/* reply to the ping */
+				memcpy(priv->recv_packet_buffer, packet,
+				       length);
+				eth_recv = (void *)priv->recv_packet_buffer;
+				ipr = (void *)priv->recv_packet_buffer +
+					ETHER_HDR_SIZE;
+				icmpr = (struct icmp_hdr *)&ipr->udp_src;
+				memcpy(eth_recv->et_dest, eth->et_src,
+				       ARP_HLEN);
+				memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
+				       ARP_HLEN);
+				ipr->ip_sum = 0;
+				ipr->ip_off = 0;
+				NetCopyIP((void *)&ipr->ip_dst, &ip->ip_src);
+				NetWriteIP((void *)&ipr->ip_src,
+					   priv->fake_host_ipaddr);
+				ipr->ip_sum = compute_ip_checksum(ipr,
+					IP_HDR_SIZE);
+
+				icmpr->type = ICMP_ECHO_REPLY;
+				icmpr->checksum = 0;
+				icmpr->checksum = compute_ip_checksum(icmpr,
+					ICMP_HDR_SIZE);
+
+				priv->recv_packet_length = length;
+			}
+		}
+	}
+
 	return 0;
 }
 
 static int sb_eth_recv(struct udevice *dev, uchar **packetp)
 {
+	struct eth_sandbox_priv *priv = dev_get_priv(dev);
+
+	if (priv->recv_packet_length) {
+		int lcl_recv_packet_length = priv->recv_packet_length;
+
+		debug("eth_sandbox: received packet %d\n",
+		      priv->recv_packet_length);
+		priv->recv_packet_length = 0;
+		*packetp = priv->recv_packet_buffer;
+		return lcl_recv_packet_length;
+	}
 	return 0;
 }
 
@@ -80,5 +186,6 @@ U_BOOT_DRIVER(eth_sandbox) = {
 	.ofdata_to_platdata = sb_eth_ofdata_to_platdata,
 	.remove	= sb_eth_remove,
 	.ops	= &sb_eth_ops,
+	.priv_auto_alloc_size = sizeof(struct eth_sandbox_priv),
 	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
 };
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 664b984..9189f6a 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -126,6 +126,7 @@
 /* include default commands */
 #include <config_cmd_default.h>
 
+#define CONFIG_CMD_PING
 
 #define CONFIG_CMD_HASH
 #define CONFIG_HASH_VERIFY
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 18/27] test: dm: eth: Add tests for the eth dm implementation
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (16 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 17/27] sandbox: eth: Add ARP and PING response to sandbox driver Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 19/27] dm: eth: Add support for aliases Joe Hershberger
                             ` (10 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

Add a test for the eth uclass using the sandbox eth driver. Verify basic
functionality of the network stack / eth uclass by exercising the ping
function.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
-Added dm eth testing

Changes in v2: None

 test/dm/Makefile |  1 +
 test/dm/eth.c    | 38 ++++++++++++++++++++++++++++++++++++++
 test/dm/test.dts | 18 ++++++++++++++++++
 3 files changed, 57 insertions(+)
 create mode 100644 test/dm/eth.c

diff --git a/test/dm/Makefile b/test/dm/Makefile
index 1d9148f..b2eb989 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_DM_TEST) += ut.o
 obj-$(CONFIG_DM_TEST) += core.o
 obj-$(CONFIG_DM_TEST) += ut.o
 ifneq ($(CONFIG_SANDBOX),)
+obj-$(CONFIG_DM_ETH) += eth.o
 obj-$(CONFIG_DM_GPIO) += gpio.o
 obj-$(CONFIG_DM_I2C) += i2c.o
 obj-$(CONFIG_DM_SPI_FLASH) += sf.o
diff --git a/test/dm/eth.c b/test/dm/eth.c
new file mode 100644
index 0000000..04ccf49
--- /dev/null
+++ b/test/dm/eth.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <dm/ut.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int dm_test_eth(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+
+	setenv("ethact", "eth at 10002000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	setenv("ethact", "eth at 10003000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10003000", getenv("ethact"));
+
+	setenv("ethact", "eth at 10004000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	return 0;
+}
+DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
diff --git a/test/dm/test.dts b/test/dm/test.dts
index 84024a4..2f68cdf 100644
--- a/test/dm/test.dts
+++ b/test/dm/test.dts
@@ -149,4 +149,22 @@
 		};
 	};
 
+	eth at 10002000 {
+		compatible = "sandbox,eth";
+		reg = <0x10002000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
+	};
+
+	eth at 10003000 {
+		compatible = "sandbox,eth";
+		reg = <0x10003000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
+	};
+
+	eth at 10004000 {
+		compatible = "sandbox,eth";
+		reg = <0x10004000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x22>;
+	};
+
 };
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 19/27] dm: eth: Add support for aliases
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (17 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 18/27] test: dm: eth: Add tests for the eth dm implementation Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 20/27] dm: eth: Add support for ethprime env var Joe Hershberger
                             ` (9 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

Allow network devices to be referred to as "eth0" instead of
"eth at 12345678" when specified in ethact.

Add tests to verify this behavior.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5:
-Added a comment about devname
-Only check for alias if the name is long enough

Changes in v4:
-Use only the seq from DM to find aliases

Changes in v3:
-Added support for aliases

Changes in v2: None

 include/configs/sandbox.h |  2 +-
 include/net.h             |  5 +++++
 net/eth.c                 | 50 ++++++++++++++++++++++++++++++++++++++---------
 test/dm/eth.c             | 24 +++++++++++++++++++++++
 test/dm/test.dts          |  4 +++-
 5 files changed, 74 insertions(+), 11 deletions(-)

diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 9189f6a..caf9f5a 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -174,7 +174,7 @@
 
 #define SANDBOX_ETH_SETTINGS		"ethaddr=00:00:11:22:33:44\0" \
 					"eth1addr=00:00:11:22:33:45\0" \
-					"eth2addr=00:00:11:22:33:46\0" \
+					"eth5addr=00:00:11:22:33:46\0" \
 					"ipaddr=1.2.3.4\0"
 
 #define CONFIG_EXTRA_ENV_SETTINGS	SANDBOX_SERIAL_SETTINGS \
diff --git a/include/net.h b/include/net.h
index 241a096..baccd47 100644
--- a/include/net.h
+++ b/include/net.h
@@ -124,6 +124,11 @@ struct eth_ops {
 #define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
 
 struct udevice *eth_get_dev(void); /* get the current device */
+/*
+ * The devname can be either an exact name given by the driver or device tree
+ * or it can be an alias of the form "eth%d"
+ */
+struct udevice *eth_get_dev_by_name(const char *devname);
 unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
 /* Used only when NetConsole is enabled */
 int eth_init_state_only(void); /* Set active state */
diff --git a/net/eth.c b/net/eth.c
index 058c55a..a2e6f34 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -135,6 +135,39 @@ static void eth_set_dev(struct udevice *dev)
 	eth_get_uclass_priv()->current = dev;
 }
 
+/*
+ * Find the udevice that either has the name passed in as devname or has an
+ * alias named devname.
+ */
+struct udevice *eth_get_dev_by_name(const char *devname)
+{
+	int seq = -1;
+	char *endp = NULL;
+	const char *startp = NULL;
+	struct udevice *it;
+	struct uclass *uc;
+
+	/* Must be longer than 3 to be an alias */
+	if (strlen(devname) > strlen("eth")) {
+		startp = devname + strlen("eth");
+		seq = simple_strtoul(startp, &endp, 10);
+	}
+
+	uclass_get(UCLASS_ETH, &uc);
+	uclass_foreach_dev(it, uc) {
+		/* We need the seq to be valid, so make sure it's probed */
+		device_probe(it);
+		/*
+		 * Check for the name or the sequence number to match
+		 */
+		if (strcmp(it->name, devname) == 0 ||
+		    (endp > startp && it->seq == seq))
+			return it;
+	}
+
+	return NULL;
+}
+
 unsigned char *eth_get_ethaddr(void)
 {
 	struct eth_pdata *pdata;
@@ -421,6 +454,7 @@ UCLASS_DRIVER(eth) = {
 	.pre_remove	= eth_pre_remove,
 	.priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
 	.per_device_auto_alloc_size = sizeof(struct eth_device_priv),
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 };
 #endif
 
@@ -453,6 +487,11 @@ static void eth_set_current_to_next(void)
 	eth_current = eth_current->next;
 }
 
+static void eth_set_dev(struct eth_device *dev)
+{
+	eth_current = dev;
+}
+
 struct eth_device *eth_get_dev_by_name(const char *devname)
 {
 	struct eth_device *dev, *target_dev;
@@ -869,7 +908,6 @@ void eth_set_current(void)
 {
 	static char *act;
 	static int  env_changed_id;
-	void *old_current;
 	int	env_id;
 
 	env_id = get_env_id();
@@ -877,14 +915,8 @@ void eth_set_current(void)
 		act = getenv("ethact");
 		env_changed_id = env_id;
 	}
-	if (act != NULL) {
-		old_current = eth_get_dev();
-		do {
-			if (strcmp(eth_get_name(), act) == 0)
-				return;
-			eth_set_current_to_next();
-		} while (old_current != eth_get_dev());
-	}
+	if (act != NULL)
+		eth_set_dev(eth_get_dev_by_name(act));
 
 	eth_current_changed();
 }
diff --git a/test/dm/eth.c b/test/dm/eth.c
index 04ccf49..5688b71 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -36,3 +36,27 @@ static int dm_test_eth(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
+
+static int dm_test_eth_alias(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+	setenv("ethact", "eth0");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	setenv("ethact", "eth1");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	/* Expected to fail since eth2 is not defined in the device tree */
+	setenv("ethact", "eth2");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	setenv("ethact", "eth5");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10003000", getenv("ethact"));
+
+	return 0;
+}
+DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
diff --git a/test/dm/test.dts b/test/dm/test.dts
index 2f68cdf..bc2409d 100644
--- a/test/dm/test.dts
+++ b/test/dm/test.dts
@@ -17,6 +17,8 @@
 		testfdt3 = "/b-test";
 		testfdt5 = "/some-bus/c-test at 5";
 		testfdt8 = "/a-test";
+		eth0 = "/eth at 10002000";
+		eth5 = &eth_5;
 	};
 
 	uart0: serial {
@@ -155,7 +157,7 @@
 		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
 	};
 
-	eth at 10003000 {
+	eth_5: eth at 10003000 {
 		compatible = "sandbox,eth";
 		reg = <0x10003000 0x1000>;
 		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 20/27] dm: eth: Add support for ethprime env var
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (18 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 19/27] dm: eth: Add support for aliases Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 21/27] test: dm: eth: Add testing for ethrotate " Joe Hershberger
                             ` (8 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

The ethprime env var is used to indicate the starting device if none is
specified in ethact. Also support aliases specified in the ethprime var.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5:
-Fix compile error on !DM_ETH

Changes in v4:
-Load from ethprime on eth_initialize()

Changes in v3:
-Added support for ethprime

Changes in v2: None

 net/eth.c     | 29 ++++++++++++++++++++++++++++-
 test/dm/eth.c | 20 ++++++++++++++++++++
 2 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/net/eth.c b/net/eth.c
index a2e6f34..b6c2af3 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -360,6 +360,18 @@ int eth_initialize(void)
 		printf("No ethernet found.\n");
 		bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
 	} else {
+		char *ethprime = getenv("ethprime");
+		struct udevice *prime_dev = NULL;
+
+		if (ethprime)
+			prime_dev = eth_get_dev_by_name(ethprime);
+		if (prime_dev) {
+			eth_set_dev(prime_dev);
+			eth_current_changed();
+		} else {
+			eth_set_dev(NULL);
+		}
+
 		bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
 		do {
 			if (num_devices)
@@ -367,6 +379,9 @@ int eth_initialize(void)
 
 			printf("eth%d: %s", dev->seq, dev->name);
 
+			if (ethprime && dev == prime_dev)
+				printf(" [PRIME]");
+
 			eth_write_hwaddr(dev);
 
 			uclass_next_device(&dev);
@@ -915,8 +930,20 @@ void eth_set_current(void)
 		act = getenv("ethact");
 		env_changed_id = env_id;
 	}
-	if (act != NULL)
+
+	if (act == NULL) {
+		char *ethprime = getenv("ethprime");
+		void *dev = NULL;
+
+		if (ethprime)
+			dev = eth_get_dev_by_name(ethprime);
+		if (dev)
+			eth_set_dev(dev);
+		else
+			eth_set_dev(NULL);
+	} else {
 		eth_set_dev(eth_get_dev_by_name(act));
+	}
 
 	eth_current_changed();
 }
diff --git a/test/dm/eth.c b/test/dm/eth.c
index 5688b71..96e3c46 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -60,3 +60,23 @@ static int dm_test_eth_alias(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
+
+static int dm_test_eth_prime(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+
+	/* Expected to be "eth at 10003000" because of ethprime variable */
+	setenv("ethact", NULL);
+	setenv("ethprime", "eth5");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10003000", getenv("ethact"));
+
+	/* Expected to be "eth at 10002000" because it is first */
+	setenv("ethact", NULL);
+	setenv("ethprime", NULL);
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	return 0;
+}
+DM_TEST(dm_test_eth_prime, DM_TESTF_SCAN_FDT);
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 21/27] test: dm: eth: Add testing for ethrotate env var
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (19 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 20/27] dm: eth: Add support for ethprime env var Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 22/27] sandbox: eth: Add ability to disable ping reply in sandbox eth driver Joe Hershberger
                             ` (7 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

Make sure that the ethrotate behavior occurs as expected.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5:
-Added a test for skipping un-probe-able devices

Changes in v4:
-Added testing for ethrotate

Changes in v3: None
Changes in v2: None

 test/dm/eth.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/test/dm/eth.c b/test/dm/eth.c
index 96e3c46..9b55013 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -80,3 +80,45 @@ static int dm_test_eth_prime(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_eth_prime, DM_TESTF_SCAN_FDT);
+
+static int dm_test_eth_rotate(struct dm_test_state *dms)
+{
+	char ethaddr[18];
+
+	/* Invalidate eth1's MAC address */
+	NetPingIP = string_to_ip("1.1.2.2");
+	strcpy(ethaddr, getenv("eth1addr"));
+	setenv("eth1addr", NULL);
+
+	/* Make sure that the default is to rotate to the next interface */
+	setenv("ethact", "eth at 10004000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	/* If ethrotate is no, then we should fail on a bad MAC */
+	setenv("ethact", "eth at 10004000");
+	setenv("ethrotate", "no");
+	ut_asserteq(-1, NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	/* Restore the env */
+	setenv("eth1addr", ethaddr);
+	setenv("ethrotate", NULL);
+
+	/* Invalidate eth0's MAC address */
+	strcpy(ethaddr, getenv("ethaddr"));
+	setenv(".flags", "ethaddr");
+	setenv("ethaddr", NULL);
+
+	/* Make sure we can skip invalid devices */
+	setenv("ethact", "eth at 10004000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	/* Restore the env */
+	setenv("ethaddr", ethaddr);
+	setenv(".flags", NULL);
+
+	return 0;
+}
+DM_TEST(dm_test_eth_rotate, DM_TESTF_SCAN_FDT);
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 22/27] sandbox: eth: Add ability to disable ping reply in sandbox eth driver
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (20 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 21/27] test: dm: eth: Add testing for ethrotate " Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 23/27] test: dm: net: Add a test of the netretry behavior Joe Hershberger
                             ` (6 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

This is needed to test the netretry functionality (make the command fail
on a sandbox eth device).

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6:
-Add function comments
-Check array index bounds

Changes in v5:
-Use a function call to change mock driver behavior

Changes in v4:
-Add ability to disable ping reply in sandbox eth driver

Changes in v3: None
Changes in v2: None

 arch/sandbox/include/asm/eth.h | 15 +++++++++++++++
 drivers/net/sandbox.c          | 17 +++++++++++++++++
 2 files changed, 32 insertions(+)
 create mode 100644 arch/sandbox/include/asm/eth.h

diff --git a/arch/sandbox/include/asm/eth.h b/arch/sandbox/include/asm/eth.h
new file mode 100644
index 0000000..4b79ede
--- /dev/null
+++ b/arch/sandbox/include/asm/eth.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __ETH_H
+#define __ETH_H
+
+void sandbox_eth_disable_response(int index, bool disable);
+
+#endif /* __ETH_H */
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
index cb69a95..db115d0 100644
--- a/drivers/net/sandbox.c
+++ b/drivers/net/sandbox.c
@@ -29,6 +29,19 @@ struct eth_sandbox_priv {
 	int recv_packet_length;
 };
 
+static bool disabled[8] = {false};
+
+/*
+ * sandbox_eth_disable_response()
+ *
+ * index - The alias index (also DM seq number)
+ * disable - If non-zero, ignore sent packets and don't send mock response
+ */
+void sandbox_eth_disable_response(int index, bool disable)
+{
+	disabled[index] = disable;
+}
+
 static int sb_eth_start(struct udevice *dev)
 {
 	struct eth_sandbox_priv *priv = dev_get_priv(dev);
@@ -48,6 +61,10 @@ static int sb_eth_send(struct udevice *dev, void *packet, int length)
 
 	debug("eth_sandbox: Send packet %d\n", length);
 
+	if (dev->seq >= 0 && dev->seq < ARRAY_SIZE(disabled) &&
+	    disabled[dev->seq])
+		return 0;
+
 	if (ntohs(eth->et_protlen) == PROT_ARP) {
 		struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
 
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 23/27] test: dm: net: Add a test of the netretry behavior
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (21 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 22/27] sandbox: eth: Add ability to disable ping reply in sandbox eth driver Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 24/27] sandbox: eth: Add a bridge to a real network for sandbox Joe Hershberger
                             ` (5 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

The effect of the "netretry" env var was recently changed. This test
checks that behavior.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5:
-Added comments about test cases
-Switched to function to control state of mock driver

Changes in v4:
-Updated expected behavior based on changes to the NetLoop

Changes in v3:
-Added testing for netretry

Changes in v2: None

 test/dm/eth.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/test/dm/eth.c b/test/dm/eth.c
index 9b55013..a0e9359 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -14,6 +14,7 @@
 #include <fdtdec.h>
 #include <malloc.h>
 #include <net.h>
+#include <asm/eth.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -122,3 +123,34 @@ static int dm_test_eth_rotate(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_eth_rotate, DM_TESTF_SCAN_FDT);
+
+static int dm_test_net_retry(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+
+	/*
+	 * eth1 is disabled and netretry is yes, so the ping should succeed and
+	 * the active device should be eth0
+	 */
+	sandbox_eth_disable_response(1, true);
+	setenv("ethact", "eth at 10004000");
+	setenv("netretry", "yes");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	/*
+	 * eth1 is disabled and netretry is no, so the ping should fail and the
+	 * active device should be eth1
+	 */
+	setenv("ethact", "eth at 10004000");
+	setenv("netretry", "no");
+	ut_asserteq(-1, NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	/* Restore the env */
+	setenv("netretry", NULL);
+	sandbox_eth_disable_response(1, false);
+
+	return 0;
+}
+DM_TEST(dm_test_net_retry, DM_TESTF_SCAN_FDT);
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 24/27] sandbox: eth: Add a bridge to a real network for sandbox
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (22 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 23/27] test: dm: net: Add a test of the netretry behavior Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 25/27] sandbox: Enable DHCP and IP defrag Joe Hershberger
                             ` (4 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

Implement a bridge between U-Boot's network stack and Linux's raw packet
API allowing the sandbox to send and receive packets using the host
machine's network interface.

This raw Ethernet API requires elevated privileges.  You can either run
as root, or you can add the capability needed like so:

sudo /sbin/setcap "CAP_NET_RAW+ep" /path/to/u-boot

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6:
-Addressed nits

Changes in v5:
-Added fallback for setting promiscuous mode
-Added help to Kconfig
-Added more details and examples in the README
-Check for NULL when reading fdt for host interface
-Check for malloc failure
-Remove cast of pointer passed to free
-Remove the empty sb_eth_raw_remove function
-Return -errno in from send and recv
-Return errno from recv
-Set the socket to non-blocking
-Use net_rx_packets instead of a stack buffer

Changes in v4:
-Add comments to priv struct definition
-Added comments to README.sandbox
-Clean up the interface to sandbox's eth-raw-os by passing priv to raw-os
-Cleanup var definition order
-Fixed the MAC address limitation (now all traffic uses MAC address from env)
-Move os file to arch
-Moved config to Kconfig
-Use accessors for platdata and priv

Changes in v3:
-Made the os raw packet support for sandbox eth build and work.

Changes in v2:
-Added the raw packet proof-of-concept patch.

 arch/sandbox/Kconfig                  |   3 +
 arch/sandbox/cpu/Makefile             |  10 +++
 arch/sandbox/cpu/eth-raw-os.c         | 140 ++++++++++++++++++++++++++++++++++
 arch/sandbox/dts/sandbox.dts          |   6 ++
 arch/sandbox/include/asm/eth-raw-os.h |  32 ++++++++
 board/sandbox/README.sandbox          |  52 +++++++++++++
 drivers/net/Kconfig                   |  10 +++
 drivers/net/Makefile                  |   1 +
 drivers/net/sandbox-raw.c             |  98 ++++++++++++++++++++++++
 9 files changed, 352 insertions(+)
 create mode 100644 arch/sandbox/cpu/eth-raw-os.c
 create mode 100644 arch/sandbox/include/asm/eth-raw-os.h
 create mode 100644 drivers/net/sandbox-raw.c

diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index 186b58d..f84b3fc 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -43,4 +43,7 @@ config NETDEVICES
 config DM_ETH
 	default y
 
+config ETH_SANDBOX_RAW
+	default y
+
 endmenu
diff --git a/arch/sandbox/cpu/Makefile b/arch/sandbox/cpu/Makefile
index 7d4410c..1b42fee 100644
--- a/arch/sandbox/cpu/Makefile
+++ b/arch/sandbox/cpu/Makefile
@@ -8,6 +8,7 @@
 #
 
 obj-y	:= cpu.o os.o start.o state.o
+obj-$(CONFIG_ETH_SANDBOX_RAW)	+= eth-raw-os.o
 obj-$(CONFIG_SANDBOX_SDL)	+= sdl.o
 
 # os.c is build in the system environment, so needs standard includes
@@ -20,3 +21,12 @@ $(obj)/os.o: $(src)/os.c FORCE
 	$(call if_changed_dep,cc_os.o)
 $(obj)/sdl.o: $(src)/sdl.c FORCE
 	$(call if_changed_dep,cc_os.o)
+
+# eth-raw-os.c is built in the system env, so needs standard includes
+# CFLAGS_REMOVE_eth-raw-os.o cannot be used to drop header include path
+quiet_cmd_cc_eth-raw-os.o = CC $(quiet_modtag)  $@
+cmd_cc_eth-raw-os.o = $(CC) $(filter-out -nostdinc, \
+	$(patsubst -I%,-idirafter%,$(c_flags))) -c -o $@ $<
+
+$(obj)/eth-raw-os.o: $(src)/eth-raw-os.c FORCE
+	$(call if_changed_dep,cc_eth-raw-os.o)
diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c
new file mode 100644
index 0000000..601205a
--- /dev/null
+++ b/arch/sandbox/cpu/eth-raw-os.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <asm/eth-raw-os.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+
+int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
+			    struct eth_sandbox_raw_priv *priv)
+{
+	struct sockaddr_ll *device;
+	struct packet_mreq mr;
+	int ret;
+	int flags;
+
+	/* Prepare device struct */
+	priv->device = malloc(sizeof(struct sockaddr_ll));
+	if (priv->device == NULL)
+		return -ENOMEM;
+	device = priv->device;
+	memset(device, 0, sizeof(struct sockaddr_ll));
+	device->sll_ifindex = if_nametoindex(ifname);
+	device->sll_family = AF_PACKET;
+	memcpy(device->sll_addr, ethmac, 6);
+	device->sll_halen = htons(6);
+
+	/* Open socket */
+	priv->sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+	if (priv->sd < 0) {
+		printf("Failed to open socket: %d %s\n", errno,
+		       strerror(errno));
+		return -errno;
+	}
+	/* Bind to the specified interface */
+	ret = setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
+		   strlen(ifname) + 1);
+	if (ret < 0) {
+		printf("Failed to bind to '%s': %d %s\n", ifname, errno,
+		       strerror(errno));
+		return -errno;
+	}
+
+	/* Make the socket non-blocking */
+	flags = fcntl(priv->sd, F_GETFL, 0);
+	fcntl(priv->sd, F_SETFL, flags | O_NONBLOCK);
+
+	/* Enable promiscuous mode to receive responses meant for us */
+	mr.mr_ifindex = device->sll_ifindex;
+	mr.mr_type = PACKET_MR_PROMISC;
+	ret = setsockopt(priv->sd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
+		   &mr, sizeof(mr));
+	if (ret < 0) {
+		struct ifreq ifr;
+
+		printf("Failed to set promiscuous mode: %d %s\n"
+		       "Falling back to the old \"flags\" way...\n",
+			errno, strerror(errno));
+		strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+		if (ioctl(priv->sd, SIOCGIFFLAGS, &ifr) < 0) {
+			printf("Failed to read flags: %d %s\n", errno,
+			       strerror(errno));
+			return -errno;
+		}
+		ifr.ifr_flags |= IFF_PROMISC;
+		if (ioctl(priv->sd, SIOCSIFFLAGS, &ifr) < 0) {
+			printf("Failed to write flags: %d %s\n", errno,
+			       strerror(errno));
+			return -errno;
+		}
+	}
+	return 0;
+}
+
+int sandbox_eth_raw_os_send(void *packet, int length,
+			    const struct eth_sandbox_raw_priv *priv)
+{
+	int retval;
+
+	if (!priv->sd || !priv->device)
+		return -EINVAL;
+
+	retval = sendto(priv->sd, packet, length, 0,
+			(struct sockaddr *)priv->device,
+			sizeof(struct sockaddr_ll));
+	if (retval < 0) {
+		printf("Failed to send packet: %d %s\n", errno,
+		       strerror(errno));
+		return -errno;
+	}
+	return retval;
+}
+
+int sandbox_eth_raw_os_recv(void *packet, int *length,
+			    const struct eth_sandbox_raw_priv *priv)
+{
+	int retval;
+	int saddr_size;
+
+	if (!priv->sd || !priv->device)
+		return -EINVAL;
+	saddr_size = sizeof(struct sockaddr);
+	retval = recvfrom(priv->sd, packet, 1536, 0,
+			  (struct sockaddr *)priv->device,
+			  (socklen_t *)&saddr_size);
+	*length = 0;
+	if (retval >= 0) {
+		*length = retval;
+		return 0;
+	}
+	/* The socket is non-blocking, so expect EAGAIN when there is no data */
+	if (errno == EAGAIN)
+		return 0;
+	return -errno;
+}
+
+void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv)
+{
+	free(priv->device);
+	priv->device = NULL;
+	close(priv->sd);
+	priv->sd = -1;
+}
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index c2a3304..8002196 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -186,4 +186,10 @@
 		reg = <0x10002000 0x1000>;
 		fake-host-hwaddr = [00 00 66 44 22 00];
 	};
+
+	eth at 80000000 {
+		compatible = "sandbox,eth-raw";
+		reg = <0x80000000 0x1000>;
+		host-raw-interface = "eth0";
+	};
 };
diff --git a/arch/sandbox/include/asm/eth-raw-os.h b/arch/sandbox/include/asm/eth-raw-os.h
new file mode 100644
index 0000000..df60c4f
--- /dev/null
+++ b/arch/sandbox/include/asm/eth-raw-os.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __ETH_RAW_OS_H
+#define __ETH_RAW_OS_H
+
+/**
+ * struct eth_sandbox_raw_priv - raw socket session
+ *
+ * sd: socket descriptor - the open socket during a session
+ * device: struct sockaddr_ll - the host interface packets move to/from
+ */
+struct eth_sandbox_raw_priv {
+	int sd;
+	void *device;
+};
+
+int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
+			    struct eth_sandbox_raw_priv *priv);
+int sandbox_eth_raw_os_send(void *packet, int length,
+			    const struct eth_sandbox_raw_priv *priv);
+int sandbox_eth_raw_os_recv(void *packet, int *length,
+			    const struct eth_sandbox_raw_priv *priv);
+void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv);
+
+#endif /* __ETH_RAW_OS_H */
diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
index c1f5f7e..9f5d3f7 100644
--- a/board/sandbox/README.sandbox
+++ b/board/sandbox/README.sandbox
@@ -190,6 +190,58 @@ Also sandbox uses generic board (CONFIG_SYS_GENERIC_BOARD) and supports
 driver model (CONFIG_DM) and associated commands.
 
 
+Linux RAW Networking Bridge
+---------------------------
+
+The sandbox_eth_raw driver bridges traffic between the bottom of the network
+stack and the RAW sockets API in Linux. This allows much of the U-Boot network
+functionality to be tested in sandbox against real network traffic.
+
+For Ethernet network adapters, the bridge utilizes the RAW AF_PACKET API.  This
+is needed to get access to the lowest level of the network stack in Linux. This
+means that all of the Ethernet frame is included. This allows the U-Boot network
+stack to be fully used. In other words, nothing about the Linux network stack is
+involved in forming the packets that end up on the wire. To receive the
+responses to packets sent from U-Boot the network interface has to be set to
+promiscuous mode so that the network card won't filter out packets not destined
+for its configured (on Linux) MAC address.
+
+The RAW sockets Ethernet API requires elevated privileges in Linux. You can
+either run as root, or you can add the capability needed like so:
+
+sudo /sbin/setcap "CAP_NET_RAW+ep" /path/to/u-boot
+
+The default device tree for sandbox includes an entry for eth0 on the sandbox
+host machine whose alias is "eth1". The following are a few examples of network
+operations being tested on the eth0 interface.
+
+sudo /path/to/u-boot -D
+
+DHCP
+....
+
+set autoload no
+set ethact eth1
+dhcp
+
+PING
+....
+
+set autoload no
+set ethact eth1
+dhcp
+ping $gatewayip
+
+TFTP
+....
+
+set autoload no
+set ethact eth1
+dhcp
+set serverip WWW.XXX.YYY.ZZZ
+tftpboot u-boot.bin
+
+
 SPI Emulation
 -------------
 
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index e46e57b..5bd66ea 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -29,4 +29,14 @@ config ETH_SANDBOX
 
 	  This driver is particularly useful in the test/dm/eth.c tests
 
+config ETH_SANDBOX_RAW
+	depends on DM_ETH && SANDBOX
+	default y
+	bool "Sandbox: Bridge to Linux Raw Sockets"
+	help
+	  This driver is a bridge from the bottom of the network stack
+	  in U-Boot to the RAW AF_PACKET API in Linux. This allows real
+	  network traffic to be tested from within sandbox. See
+	  board/sandbox/README.sandbox for more details.
+
 endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a17198c..7d32519 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_PCNET) += pcnet.o
 obj-$(CONFIG_RTL8139) += rtl8139.o
 obj-$(CONFIG_RTL8169) += rtl8169.o
 obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
+obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o
 obj-$(CONFIG_SH_ETHER) += sh_eth.o
 obj-$(CONFIG_SMC91111) += smc91111.o
 obj-$(CONFIG_SMC911X) += smc911x.o
diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
new file mode 100644
index 0000000..435b874
--- /dev/null
+++ b/drivers/net/sandbox-raw.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <asm/eth-raw-os.h>
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+
+static int sb_eth_raw_start(struct udevice *dev)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	const char *interface;
+
+	debug("eth_sandbox_raw: Start\n");
+
+	interface = fdt_getprop(gd->fdt_blob, dev->of_offset,
+					    "host-raw-interface", NULL);
+	if (interface == NULL)
+		return -EINVAL;
+
+	return sandbox_eth_raw_os_start(interface, pdata->enetaddr, priv);
+}
+
+static int sb_eth_raw_send(struct udevice *dev, void *packet, int length)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+
+	debug("eth_sandbox_raw: Send packet %d\n", length);
+
+	return sandbox_eth_raw_os_send(packet, length, priv);
+}
+
+static int sb_eth_raw_recv(struct udevice *dev, uchar **packetp)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+	int retval;
+	int length;
+
+	retval = sandbox_eth_raw_os_recv(net_rx_packets[0], &length, priv);
+
+	if (!retval && length) {
+		debug("eth_sandbox_raw: received packet %d\n",
+		      length);
+		*packetp = net_rx_packets[0];
+		return length;
+	}
+	return retval;
+}
+
+static void sb_eth_raw_stop(struct udevice *dev)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+
+	debug("eth_sandbox_raw: Stop\n");
+
+	sandbox_eth_raw_os_stop(priv);
+}
+
+static const struct eth_ops sb_eth_raw_ops = {
+	.start			= sb_eth_raw_start,
+	.send			= sb_eth_raw_send,
+	.recv			= sb_eth_raw_recv,
+	.stop			= sb_eth_raw_stop,
+};
+
+static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	pdata->iobase = dev_get_addr(dev);
+	return 0;
+}
+
+static const struct udevice_id sb_eth_raw_ids[] = {
+	{ .compatible = "sandbox,eth-raw" },
+	{ }
+};
+
+U_BOOT_DRIVER(eth_sandbox_raw) = {
+	.name	= "eth_sandbox_raw",
+	.id	= UCLASS_ETH,
+	.of_match = sb_eth_raw_ids,
+	.ofdata_to_platdata = sb_eth_raw_ofdata_to_platdata,
+	.ops	= &sb_eth_raw_ops,
+	.priv_auto_alloc_size = sizeof(struct eth_sandbox_raw_priv),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 25/27] sandbox: Enable DHCP and IP defrag
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (23 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 24/27] sandbox: eth: Add a bridge to a real network for sandbox Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 26/27] sandbox: eth: Add support for using the 'lo' interface Joe Hershberger
                             ` (3 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

This is now testable via the eth-raw interface

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5: None
Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 include/configs/sandbox.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index caf9f5a..034050e 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -127,6 +127,14 @@
 #include <config_cmd_default.h>
 
 #define CONFIG_CMD_PING
+#define CONFIG_CMD_DHCP
+#define CONFIG_BOOTP_DNS
+#define CONFIG_BOOTP_DNS2
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_SEND_HOSTNAME
+#define CONFIG_BOOTP_SERVERIP
+#define CONFIG_BOOTP_SUBNETMASK
+#define CONFIG_IP_DEFRAG
 
 #define CONFIG_CMD_HASH
 #define CONFIG_HASH_VERIFY
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 26/27] sandbox: eth: Add support for using the 'lo' interface
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (24 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 25/27] sandbox: Enable DHCP and IP defrag Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 27/27] net: Improve error handling Joe Hershberger
                             ` (2 subsequent siblings)
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

The 'lo' interface on Linux doesn't support thinks like ARP or
link-layer access like we use to talk to a normal network interface.
A higher-level network API must be used to access localhost.

As written, this interface is limited to not supporting ICMP since the
API doesn't allow the socket to be opened for all IP traffic and be able
to receive at the same time. UDP is far more useful to test with, so it
was selected over ICMP. Ping won't work, but things like TFTP should
work.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5:
-Add details about lo support to the README
-Remove socket timeout
-Separate init to 2 helper static functions
-Set the socket to non-blocking
-Use INADDR_LOOPBACK
-Use more verbose comments

Changes in v4:
-Added support for the 'lo' network interface

Changes in v3: None
Changes in v2: None

 arch/sandbox/cpu/eth-raw-os.c         | 113 +++++++++++++++++++++++++++++++++-
 arch/sandbox/dts/sandbox.dts          |  10 +++
 arch/sandbox/include/asm/eth-raw-os.h |  10 ++-
 board/sandbox/README.sandbox          |  22 +++++++
 drivers/net/sandbox-raw.c             |  71 ++++++++++++++++++++-
 5 files changed, 221 insertions(+), 5 deletions(-)

diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c
index 601205a..b76a731 100644
--- a/arch/sandbox/cpu/eth-raw-os.c
+++ b/arch/sandbox/cpu/eth-raw-os.c
@@ -12,6 +12,8 @@
 #include <fcntl.h>
 #include <net/if.h>
 #include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -20,10 +22,11 @@
 #include <sys/socket.h>
 #include <unistd.h>
 
+#include <arpa/inet.h>
 #include <linux/if_ether.h>
 #include <linux/if_packet.h>
 
-int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
+static int _raw_packet_start(const char *ifname, unsigned char *ethmac,
 			    struct eth_sandbox_raw_priv *priv)
 {
 	struct sockaddr_ll *device;
@@ -89,14 +92,114 @@ int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
 	return 0;
 }
 
+static int _local_inet_start(struct eth_sandbox_raw_priv *priv)
+{
+	struct sockaddr_in *device;
+	int ret;
+	int flags;
+	int one = 1;
+
+	/* Prepare device struct */
+	priv->device = malloc(sizeof(struct sockaddr_in));
+	if (priv->device == NULL)
+		return -ENOMEM;
+	device = priv->device;
+	memset(device, 0, sizeof(struct sockaddr_in));
+	device->sin_family = AF_INET;
+	device->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+	/**
+	 * Open socket
+	 *  Since we specify UDP here, any incoming ICMP packets will
+	 *  not be received, so things like ping will not work on this
+	 *  localhost interface.
+	 */
+	priv->sd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
+	if (priv->sd < 0) {
+		printf("Failed to open socket: %d %s\n", errno,
+		       strerror(errno));
+		return -errno;
+	}
+
+	/* Make the socket non-blocking */
+	flags = fcntl(priv->sd, F_GETFL, 0);
+	fcntl(priv->sd, F_SETFL, flags | O_NONBLOCK);
+
+	/* Include the UDP/IP headers on send and receive */
+	ret = setsockopt(priv->sd, IPPROTO_IP, IP_HDRINCL, &one,
+			 sizeof(one));
+	if (ret < 0) {
+		printf("Failed to set header include option: %d %s\n", errno,
+		       strerror(errno));
+		return -errno;
+	}
+	priv->local_bind_sd = -1;
+	priv->local_bind_udp_port = 0;
+	return 0;
+}
+
+int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
+			    struct eth_sandbox_raw_priv *priv)
+{
+	if (priv->local)
+		return _local_inet_start(priv);
+	else
+		return _raw_packet_start(ifname, ethmac, priv);
+}
+
 int sandbox_eth_raw_os_send(void *packet, int length,
-			    const struct eth_sandbox_raw_priv *priv)
+			    struct eth_sandbox_raw_priv *priv)
 {
 	int retval;
+	struct udphdr *udph = packet + sizeof(struct iphdr);
 
 	if (!priv->sd || !priv->device)
 		return -EINVAL;
 
+	/*
+	 * This block of code came about when testing tftp on the localhost
+	 * interface. When using the RAW AF_INET API, the network stack is still
+	 * in play responding to incoming traffic based on open "ports". Since
+	 * it is raw (at the IP layer, no Ethernet) the network stack tells the
+	 * TFTP server that the port it responded to is closed. This causes the
+	 * TFTP transfer to be aborted. This block of code inspects the outgoing
+	 * packet as formulated by the u-boot network stack to determine the
+	 * source port (that the TFTP server will send packets back to) and
+	 * opens a typical UDP socket on that port, thus preventing the network
+	 * stack from sending that ICMP message claiming that the port has no
+	 * bound socket.
+	 */
+	if (priv->local && (priv->local_bind_sd == -1 ||
+			    priv->local_bind_udp_port != udph->source)) {
+		struct iphdr *iph = packet;
+		struct sockaddr_in addr;
+
+		if (priv->local_bind_sd != -1)
+			close(priv->local_bind_sd);
+
+		/* A normal UDP socket is required to bind */
+		priv->local_bind_sd = socket(AF_INET, SOCK_DGRAM, 0);
+		if (priv->local_bind_sd < 0) {
+			printf("Failed to open bind sd: %d %s\n", errno,
+			       strerror(errno));
+			return -errno;
+		}
+		priv->local_bind_udp_port = udph->source;
+
+		/**
+		 * Bind the UDP port that we intend to use as our source port
+		 * so that the kernel will not send an ICMP port unreachable
+		 * message to the server
+		 */
+		addr.sin_family = AF_INET;
+		addr.sin_port = udph->source;
+		addr.sin_addr.s_addr = iph->saddr;
+		retval = bind(priv->local_bind_sd, &addr, sizeof(addr));
+		if (retval < 0)
+			printf("Failed to bind: %d %s\n", errno,
+			       strerror(errno));
+	}
+
 	retval = sendto(priv->sd, packet, length, 0,
 			(struct sockaddr *)priv->device,
 			sizeof(struct sockaddr_ll));
@@ -137,4 +240,10 @@ void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv)
 	priv->device = NULL;
 	close(priv->sd);
 	priv->sd = -1;
+	if (priv->local) {
+		if (priv->local_bind_sd != -1)
+			close(priv->local_bind_sd);
+		priv->local_bind_sd = -1;
+		priv->local_bind_udp_port = 0;
+	}
 }
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 8002196..0eaa5a5 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -4,6 +4,10 @@
 	#address-cells = <1>;
 	#size-cells = <0>;
 
+	aliases {
+		eth5 = "/eth at 90000000";
+	};
+
 	chosen {
 		stdout-path = "/serial";
 	};
@@ -192,4 +196,10 @@
 		reg = <0x80000000 0x1000>;
 		host-raw-interface = "eth0";
 	};
+
+	eth at 90000000 {
+		compatible = "sandbox,eth-raw";
+		reg = <0x90000000 0x1000>;
+		host-raw-interface = "lo";
+	};
 };
diff --git a/arch/sandbox/include/asm/eth-raw-os.h b/arch/sandbox/include/asm/eth-raw-os.h
index df60c4f..ed4b2e2 100644
--- a/arch/sandbox/include/asm/eth-raw-os.h
+++ b/arch/sandbox/include/asm/eth-raw-os.h
@@ -15,16 +15,24 @@
  *
  * sd: socket descriptor - the open socket during a session
  * device: struct sockaddr_ll - the host interface packets move to/from
+ * local: 1 or 0 to select the local interface ('lo') or not
+ * local_bindsd: socket descriptor to prevent the kernel from sending
+ *		 a message to the server claiming the port is
+ *		 unreachable
+ * local_bind_udp_port: The UDP port number that we bound to
  */
 struct eth_sandbox_raw_priv {
 	int sd;
 	void *device;
+	int local;
+	int local_bind_sd;
+	unsigned short local_bind_udp_port;
 };
 
 int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
 			    struct eth_sandbox_raw_priv *priv);
 int sandbox_eth_raw_os_send(void *packet, int length,
-			    const struct eth_sandbox_raw_priv *priv);
+			    struct eth_sandbox_raw_priv *priv);
 int sandbox_eth_raw_os_recv(void *packet, int *length,
 			    const struct eth_sandbox_raw_priv *priv);
 void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv);
diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
index 9f5d3f7..08489e3 100644
--- a/board/sandbox/README.sandbox
+++ b/board/sandbox/README.sandbox
@@ -241,6 +241,28 @@ dhcp
 set serverip WWW.XXX.YYY.ZZZ
 tftpboot u-boot.bin
 
+The bridge also support (to a lesser extent) the localhost inderface, 'lo'.
+
+The 'lo' interface cannot use the RAW AF_PACKET API because the lo interface
+doesn't support Ethernet-level traffic. It is a higher-level interface that is
+expected only to be used at the AF_INET level of the API. As such, the most raw
+we can get on that interface is the RAW AF_INET API on UDP. This allows us to
+set the IP_HDRINCL option to include everything except the Ethernet header in
+the packets we send and receive.
+
+Because only UDP is supported, ICMP traffic will not work, so expect that ping
+commands will time out.
+
+The default device tree for sandbox includes an entry for lo on the sandbox
+host machine whose alias is "eth5". The following is an example of a network
+operation being tested on the lo interface.
+
+TFTP
+....
+
+set ethact eth5
+tftpboot u-boot.bin
+
 
 SPI Emulation
 -------------
diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
index 435b874..91da5f5 100644
--- a/drivers/net/sandbox-raw.c
+++ b/drivers/net/sandbox-raw.c
@@ -15,6 +15,8 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static int reply_arp;
+static IPaddr_t arp_ip;
 
 static int sb_eth_raw_start(struct udevice *dev)
 {
@@ -29,6 +31,11 @@ static int sb_eth_raw_start(struct udevice *dev)
 	if (interface == NULL)
 		return -EINVAL;
 
+	if (strcmp(interface, "lo") == 0) {
+		priv->local = 1;
+		setenv("ipaddr", "127.0.0.1");
+		setenv("serverip", "127.0.0.1");
+	}
 	return sandbox_eth_raw_os_start(interface, pdata->enetaddr, priv);
 }
 
@@ -38,18 +45,78 @@ static int sb_eth_raw_send(struct udevice *dev, void *packet, int length)
 
 	debug("eth_sandbox_raw: Send packet %d\n", length);
 
+	if (priv->local) {
+		struct ethernet_hdr *eth = packet;
+
+		if (ntohs(eth->et_protlen) == PROT_ARP) {
+			struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
+
+			/**
+			 * localhost works on a higher-level API in Linux than
+			 * ARP packets, so fake it
+			 */
+			arp_ip = NetReadIP(&arp->ar_tpa);
+			reply_arp = 1;
+			return 0;
+		}
+		packet += ETHER_HDR_SIZE;
+		length -= ETHER_HDR_SIZE;
+	}
 	return sandbox_eth_raw_os_send(packet, length, priv);
 }
 
 static int sb_eth_raw_recv(struct udevice *dev, uchar **packetp)
 {
+	struct eth_pdata *pdata = dev_get_platdata(dev);
 	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
-	int retval;
+	int retval = 0;
 	int length;
 
-	retval = sandbox_eth_raw_os_recv(net_rx_packets[0], &length, priv);
+	if (reply_arp) {
+		struct arp_hdr *arp = (void *)net_rx_packets[0] +
+			ETHER_HDR_SIZE;
+
+		/*
+		 * Fake an ARP response. The u-boot network stack is sending an
+		 * ARP request (to find the MAC address to address the actual
+		 * packet to) and requires an ARP response to continue. Since
+		 * this is the localhost interface, there is no Etherent level
+		 * traffic at all, so there is no way to send an ARP request or
+		 * to get a response. For this reason we fake the response to
+		 * make the u-boot network stack happy.
+		 */
+		arp->ar_hrd = htons(ARP_ETHER);
+		arp->ar_pro = htons(PROT_IP);
+		arp->ar_hln = ARP_HLEN;
+		arp->ar_pln = ARP_PLEN;
+		arp->ar_op = htons(ARPOP_REPLY);
+		/* Any non-zero MAC address will work */
+		memset(&arp->ar_sha, 0x01, ARP_HLEN);
+		/* Use whatever IP we were looking for (always 127.0.0.1?) */
+		NetWriteIP(&arp->ar_spa, arp_ip);
+		memcpy(&arp->ar_tha, pdata->enetaddr, ARP_HLEN);
+		NetWriteIP(&arp->ar_tpa, NetOurIP);
+		length = ARP_HDR_SIZE;
+	} else {
+		/* If local, the Ethernet header won't be included; skip it */
+		uchar *pktptr = priv->local ?
+			net_rx_packets[0] + ETHER_HDR_SIZE : net_rx_packets[0];
+
+		retval = sandbox_eth_raw_os_recv(pktptr, &length, priv);
+	}
 
 	if (!retval && length) {
+		if (priv->local) {
+			struct ethernet_hdr *eth = (void *)net_rx_packets[0];
+
+			/* Fill in enough of the missing Ethernet header */
+			memcpy(eth->et_dest, pdata->enetaddr, ARP_HLEN);
+			memset(eth->et_src, 0x01, ARP_HLEN);
+			eth->et_protlen = htons(reply_arp ? PROT_ARP : PROT_IP);
+			reply_arp = 0;
+			length += ETHER_HDR_SIZE;
+		}
+
 		debug("eth_sandbox_raw: received packet %d\n",
 		      length);
 		*packetp = net_rx_packets[0];
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 27/27] net: Improve error handling
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (25 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 26/27] sandbox: eth: Add support for using the 'lo' interface Joe Hershberger
@ 2015-03-11 23:44           ` Joe Hershberger
  2015-03-20 12:17           ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Simon Glass
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
  28 siblings, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-11 23:44 UTC (permalink / raw)
  To: u-boot

Take a pass at plumbing errors through to the users of the network stack

Currently only the start() function errors will be returned from
NetLoop(). recv() tends not to have errors, so that is likely not worth
adding. send() certainly can return errors, but this patch does not
attempt to plumb them yet. halt() is not expected to error.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v6: None
Changes in v5:
-New to v5

Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/net.h |  3 ++-
 net/eth.c     | 56 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 net/net.c     | 26 ++++++++++++++++++--------
 test/dm/eth.c |  4 ++--
 4 files changed, 70 insertions(+), 19 deletions(-)

diff --git a/include/net.h b/include/net.h
index baccd47..a60ff03 100644
--- a/include/net.h
+++ b/include/net.h
@@ -541,7 +541,7 @@ int NetLoop(enum proto_t);
 void	NetStop(void);
 
 /* Load failed.	 Start again. */
-void	NetStartAgain(void);
+int	NetStartAgain(void);
 
 /* Get size of the ethernet header when we send */
 int	NetEthHdrSize(void);
@@ -611,6 +611,7 @@ static inline void net_set_state(enum net_loop_state state)
 /* Transmit a packet */
 static inline void NetSendPacket(uchar *pkt, int len)
 {
+	/* Currently no way to return errors from eth_send() */
 	(void) eth_send(pkt, len);
 }
 
diff --git a/net/eth.c b/net/eth.c
index b6c2af3..13b7723 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -98,6 +98,9 @@ struct eth_uclass_priv {
 	struct udevice *current;
 };
 
+/* eth_errno - This stores the most recent failure code from DM functions */
+static int eth_errno;
+
 static struct eth_uclass_priv *eth_get_uclass_priv(void)
 {
 	struct uclass *uc;
@@ -118,20 +121,32 @@ static void eth_set_current_to_next(void)
 		uclass_first_device(UCLASS_ETH, &uc_priv->current);
 }
 
+/*
+ * Typically this will simply return the active device.
+ * In the case where the most recent active device was unset, this will attempt
+ * to return the first device. If that device doesn't exist or fails to probe,
+ * this function will return NULL.
+ */
 struct udevice *eth_get_dev(void)
 {
 	struct eth_uclass_priv *uc_priv;
 
 	uc_priv = eth_get_uclass_priv();
 	if (!uc_priv->current)
-		uclass_first_device(UCLASS_ETH,
+		eth_errno = uclass_first_device(UCLASS_ETH,
 				    &uc_priv->current);
 	return uc_priv->current;
 }
 
+/*
+ * Typically this will just store a device pointer.
+ * In case it was not probed, we will attempt to do so.
+ * dev may be NULL to unset the active device.
+ */
 static void eth_set_dev(struct udevice *dev)
 {
-	device_probe(dev);
+	if (dev && !device_active(dev))
+		eth_errno = device_probe(dev);
 	eth_get_uclass_priv()->current = dev;
 }
 
@@ -155,7 +170,14 @@ struct udevice *eth_get_dev_by_name(const char *devname)
 
 	uclass_get(UCLASS_ETH, &uc);
 	uclass_foreach_dev(it, uc) {
-		/* We need the seq to be valid, so make sure it's probed */
+		/*
+		 * We need the seq to be valid, so try to probe it.
+		 * If the probe fails, the seq will not match since it will be
+		 * -1 instead of what we are looking for.
+		 * We don't care about errors from probe here. Either they won't
+		 * match an alias or it will match a literal name and we'll pick
+		 * up the error when we try to probe again in eth_set_dev().
+		 */
 		device_probe(it);
 		/*
 		 * Check for the name or the sequence number to match
@@ -221,6 +243,7 @@ int eth_init(void)
 {
 	struct udevice *current;
 	struct udevice *old_current;
+	int ret = -ENODEV;
 
 	current = eth_get_dev();
 	if (!current) {
@@ -243,22 +266,29 @@ int eth_init(void)
 			else
 				memset(pdata->enetaddr, 0, 6);
 
-			if (eth_get_ops(current)->start(current) >= 0) {
+			ret = eth_get_ops(current)->start(current);
+			if (ret >= 0) {
 				struct eth_device_priv *priv =
 					current->uclass_priv;
 
 				priv->state = ETH_STATE_ACTIVE;
 				return 0;
 			}
-		}
+		} else
+			ret = eth_errno;
+
 		debug("FAIL\n");
 
-		/* This will ensure the new "current" attempted to probe */
+		/*
+		 * If ethrotate is enabled, this will change "current",
+		 * otherwise we will drop out of this while loop immediately
+		 */
 		eth_try_another(0);
+		/* This will ensure the new "current" attempted to probe */
 		current = eth_get_dev();
 	} while (old_current != current);
 
-	return -ENODEV;
+	return ret;
 }
 
 void eth_halt(void)
@@ -278,6 +308,7 @@ void eth_halt(void)
 int eth_send(void *packet, int length)
 {
 	struct udevice *current;
+	int ret;
 
 	current = eth_get_dev();
 	if (!current)
@@ -286,7 +317,12 @@ int eth_send(void *packet, int length)
 	if (!device_active(current))
 		return -EINVAL;
 
-	return eth_get_ops(current)->send(current, packet, length);
+	ret = eth_get_ops(current)->send(current, packet, length);
+	if (ret < 0) {
+		/* We cannot completely return the error at present */
+		debug("%s: send() returned error %d\n", __func__, ret);
+	}
+	return ret;
 }
 
 int eth_rx(void)
@@ -313,6 +349,10 @@ int eth_rx(void)
 	}
 	if (ret == -EAGAIN)
 		ret = 0;
+	if (ret < 0) {
+		/* We cannot completely return the error@present */
+		debug("%s: recv() returned error %d\n", __func__, ret);
+	}
 	return ret;
 }
 
diff --git a/net/net.c b/net/net.c
index afec443..69f38f7 100644
--- a/net/net.c
+++ b/net/net.c
@@ -84,6 +84,7 @@
 #include <common.h>
 #include <command.h>
 #include <environment.h>
+#include <errno.h>
 #include <net.h>
 #if defined(CONFIG_STATUS_LED)
 #include <miiphy.h>
@@ -333,7 +334,7 @@ void net_init(void)
 
 int NetLoop(enum proto_t protocol)
 {
-	int ret = -1;
+	int ret = -EINVAL;
 
 	NetRestarted = 0;
 	NetDevExists = 0;
@@ -345,9 +346,10 @@ int NetLoop(enum proto_t protocol)
 	if (eth_is_on_demand_init() || protocol != NETCONS) {
 		eth_halt();
 		eth_set_current();
-		if (eth_init() < 0) {
+		ret = eth_init();
+		if (ret < 0) {
 			eth_halt();
-			return -1;
+			return ret;
 		}
 	} else
 		eth_init_state_only();
@@ -370,7 +372,7 @@ restart:
 	case 1:
 		/* network not configured */
 		eth_halt();
-		return -1;
+		return -ENODEV;
 
 	case 2:
 		/* network device not configured */
@@ -484,6 +486,8 @@ restart:
 		/*
 		 *	Check the ethernet for a new packet.  The ethernet
 		 *	receive routine will process it.
+		 *	Most drivers return the most recent packet size, but not
+		 *	errors that may have happened.
 		 */
 		eth_rx();
 
@@ -537,7 +541,7 @@ restart:
 		}
 
 		if (net_state == NETLOOP_FAIL)
-			NetStartAgain();
+			ret = NetStartAgain();
 
 		switch (net_state) {
 
@@ -597,11 +601,12 @@ startAgainTimeout(void)
 	net_set_state(NETLOOP_RESTART);
 }
 
-void NetStartAgain(void)
+int NetStartAgain(void)
 {
 	char *nretry;
 	int retry_forever = 0;
 	unsigned long retrycnt = 0;
+	int ret;
 
 	nretry = getenv("netretry");
 	if (nretry) {
@@ -621,7 +626,11 @@ void NetStartAgain(void)
 	if ((!retry_forever) && (NetTryCount >= retrycnt)) {
 		eth_halt();
 		net_set_state(NETLOOP_FAIL);
-		return;
+		/*
+		 * We don't provide a way for the protocol to return an error,
+		 * but this is almost always the reason.
+		 */
+		return -ETIMEDOUT;
 	}
 
 	NetTryCount++;
@@ -630,7 +639,7 @@ void NetStartAgain(void)
 #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
 	eth_try_another(!NetRestarted);
 #endif
-	eth_init();
+	ret = eth_init();
 	if (NetRestartWrap) {
 		NetRestartWrap = 0;
 		if (NetDevExists) {
@@ -642,6 +651,7 @@ void NetStartAgain(void)
 	} else {
 		net_set_state(NETLOOP_RESTART);
 	}
+	return ret;
 }
 
 /**********************************************************************/
diff --git a/test/dm/eth.c b/test/dm/eth.c
index a0e9359..1923670 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -99,7 +99,7 @@ static int dm_test_eth_rotate(struct dm_test_state *dms)
 	/* If ethrotate is no, then we should fail on a bad MAC */
 	setenv("ethact", "eth at 10004000");
 	setenv("ethrotate", "no");
-	ut_asserteq(-1, NetLoop(PING));
+	ut_asserteq(-EINVAL, NetLoop(PING));
 	ut_asserteq_str("eth at 10004000", getenv("ethact"));
 
 	/* Restore the env */
@@ -144,7 +144,7 @@ static int dm_test_net_retry(struct dm_test_state *dms)
 	 */
 	setenv("ethact", "eth at 10004000");
 	setenv("netretry", "no");
-	ut_asserteq(-1, NetLoop(PING));
+	ut_asserteq(-ETIMEDOUT, NetLoop(PING));
 	ut_asserteq_str("eth at 10004000", getenv("ethact"));
 
 	/* Restore the env */
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 15/27] dm: eth: Pass the packet pointer as a parameter to recv
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 15/27] dm: eth: Pass the packet pointer as a parameter to recv Joe Hershberger
@ 2015-03-20 12:10             ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-20 12:10 UTC (permalink / raw)
  To: u-boot

On 11 March 2015 at 17:44, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Stop forcing drivers to call net_process_received_packet() - formerly
> called NetReceive(). Now the uclass will handle calling the driver for
> each packet until the driver errors or has nothing to return. The uclass
> will then pass the good packets off to the network stack by calling
> net_process_received_packet().
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (26 preceding siblings ...)
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 27/27] net: Improve error handling Joe Hershberger
@ 2015-03-20 12:17           ` Simon Glass
  2015-03-20 12:45             ` Joe Hershberger
  2015-03-20 13:21             ` Tom Rini
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
  28 siblings, 2 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-20 12:17 UTC (permalink / raw)
  To: u-boot

+Tom, Vivek, Marek

Hi Joe,

On 11 March 2015 at 17:43, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Add support for the Ethernet MAC controllers.  Phy support will come later.
>
> Switching from RFC to a patch series to be applied to dm/master as a staging
> area for this series to make it happen more quickly when the window opens.
>
> If desired, let me know which of the non-DM related prerequisite patches are
> wanted for this release.
>
> I've added unit tests to verify functionality.
>
> There is an additional driver for sandbox that bridges to the RAW
> Ethernet API in Linux which lets you test with real traffic. It now
> supports localhost as well (the 'lo' interface).
>
> Changes in v6:
> -Add function comments
> -Addressed nits
> -Check array index bounds
> -Fix compile error on boards with CONFIG_API enabled
> -Fix compile errors for other boards due to removed parameters
> -Swallow -EAGAIN error in eth_rx()
> -Updated function documentation
>

Looks great! I'm going to pick this up for u-boot-dm/next soon,
putting it on top of the PCI series.

Small USB update:

I've been fiddling with USB. I became inspired by your more ambitious
conversion of Ethernet and decided to take USB a bit further (using
driver model for all devices, not just controllers).

I have something I am becoming happy with but it does not support USB
networking. Once I apply your series I will see if I can use driver
model for that also either before or after I send the next version.

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack
  2015-03-20 12:17           ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Simon Glass
@ 2015-03-20 12:45             ` Joe Hershberger
  2015-03-20 13:21             ` Tom Rini
  1 sibling, 0 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-20 12:45 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Fri, Mar 20, 2015 at 7:17 AM, Simon Glass <sjg@chromium.org> wrote:
>
> +Tom, Vivek, Marek
>
> Hi Joe,
>
> On 11 March 2015 at 17:43, Joe Hershberger <joe.hershberger@ni.com> wrote:
> > Add support for the Ethernet MAC controllers.  Phy support will come
later.
> >
> > Switching from RFC to a patch series to be applied to dm/master as a
staging
> > area for this series to make it happen more quickly when the window
opens.
> >
> > If desired, let me know which of the non-DM related prerequisite
patches are
> > wanted for this release.
> >
> > I've added unit tests to verify functionality.
> >
> > There is an additional driver for sandbox that bridges to the RAW
> > Ethernet API in Linux which lets you test with real traffic. It now
> > supports localhost as well (the 'lo' interface).
> >
> > Changes in v6:
> > -Add function comments
> > -Addressed nits
> > -Check array index bounds
> > -Fix compile error on boards with CONFIG_API enabled
> > -Fix compile errors for other boards due to removed parameters
> > -Swallow -EAGAIN error in eth_rx()
> > -Updated function documentation
> >
>
> Looks great! I'm going to pick this up for u-boot-dm/next soon,
> putting it on top of the PCI series.

Excellent! I'm glad we were able to get this wrapped up before the merge
window opened. :D

> Small USB update:
>
> I've been fiddling with USB. I became inspired by your more ambitious
> conversion of Ethernet and decided to take USB a bit further (using
> driver model for all devices, not just controllers).

Cool!

> I have something I am becoming happy with but it does not support USB
> networking. Once I apply your series I will see if I can use driver
> model for that also either before or after I send the next version.

Awesome. I can't wait to get rid of usb_eth_initialize() and the usbethaddr
in the env. It should fit very cleanly into the DM.

Thanks,
-Joe

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack
  2015-03-20 12:17           ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Simon Glass
  2015-03-20 12:45             ` Joe Hershberger
@ 2015-03-20 13:21             ` Tom Rini
  2015-03-20 14:33               ` Joe Hershberger
  1 sibling, 1 reply; 282+ messages in thread
From: Tom Rini @ 2015-03-20 13:21 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 20, 2015 at 06:17:50AM -0600, Simon Glass wrote:
> +Tom, Vivek, Marek
> 
> Hi Joe,
> 
> On 11 March 2015 at 17:43, Joe Hershberger <joe.hershberger@ni.com> wrote:
> > Add support for the Ethernet MAC controllers.  Phy support will come later.
> >
> > Switching from RFC to a patch series to be applied to dm/master as a staging
> > area for this series to make it happen more quickly when the window opens.
> >
> > If desired, let me know which of the non-DM related prerequisite patches are
> > wanted for this release.
> >
> > I've added unit tests to verify functionality.
> >
> > There is an additional driver for sandbox that bridges to the RAW
> > Ethernet API in Linux which lets you test with real traffic. It now
> > supports localhost as well (the 'lo' interface).
> >
> > Changes in v6:
> > -Add function comments
> > -Addressed nits
> > -Check array index bounds
> > -Fix compile error on boards with CONFIG_API enabled
> > -Fix compile errors for other boards due to removed parameters
> > -Swallow -EAGAIN error in eth_rx()
> > -Updated function documentation
> >
> 
> Looks great! I'm going to pick this up for u-boot-dm/next soon,
> putting it on top of the PCI series.
> 
> Small USB update:
> 
> I've been fiddling with USB. I became inspired by your more ambitious
> conversion of Ethernet and decided to take USB a bit further (using
> driver model for all devices, not just controllers).
> 
> I have something I am becoming happy with but it does not support USB
> networking. Once I apply your series I will see if I can use driver
> model for that also either before or after I send the next version.

Nice!  And please feel free to hassle me at ELC next week :)

-- 
Tom

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack
  2015-03-20 13:21             ` Tom Rini
@ 2015-03-20 14:33               ` Joe Hershberger
  2015-03-22 22:16                 ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-20 14:33 UTC (permalink / raw)
  To: u-boot

Hi Tom,

On Fri, Mar 20, 2015 at 8:21 AM, Tom Rini <trini@konsulko.com> wrote:
>
> On Fri, Mar 20, 2015 at 06:17:50AM -0600, Simon Glass wrote:
> > +Tom, Vivek, Marek
> >
> > Hi Joe,
> >
> > On 11 March 2015 at 17:43, Joe Hershberger <joe.hershberger@ni.com>
wrote:
> > > Add support for the Ethernet MAC controllers.  Phy support will come
later.
> > >
> > > Switching from RFC to a patch series to be applied to dm/master as a
staging
> > > area for this series to make it happen more quickly when the window
opens.
> > >
> > > If desired, let me know which of the non-DM related prerequisite
patches are
> > > wanted for this release.
> > >
> > > I've added unit tests to verify functionality.
> > >
> > > There is an additional driver for sandbox that bridges to the RAW
> > > Ethernet API in Linux which lets you test with real traffic. It now
> > > supports localhost as well (the 'lo' interface).
> > >
> > > Changes in v6:
> > > -Add function comments
> > > -Addressed nits
> > > -Check array index bounds
> > > -Fix compile error on boards with CONFIG_API enabled
> > > -Fix compile errors for other boards due to removed parameters
> > > -Swallow -EAGAIN error in eth_rx()
> > > -Updated function documentation
> > >
> >
> > Looks great! I'm going to pick this up for u-boot-dm/next soon,
> > putting it on top of the PCI series.
> >
> > Small USB update:
> >
> > I've been fiddling with USB. I became inspired by your more ambitious
> > conversion of Ethernet and decided to take USB a bit further (using
> > driver model for all devices, not just controllers).
> >
> > I have something I am becoming happy with but it does not support USB
> > networking. Once I apply your series I will see if I can use driver
> > model for that also either before or after I send the next version.
>
> Nice!  And please feel free to hassle me at ELC next week :)

Cool. I'll be there next week. Do you know who else will be there?

-Joe

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 09/27] net: Remove the bd* parameter from net stack functions
  2015-03-11 23:44           ` [U-Boot] [PATCH v6 09/27] net: Remove the bd* parameter from net stack functions Joe Hershberger
@ 2015-03-20 23:01             ` Simon Glass
  2015-03-22  3:42               ` Joe Hershberger
  0 siblings, 1 reply; 282+ messages in thread
From: Simon Glass @ 2015-03-20 23:01 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 11 March 2015 at 17:44, Joe Hershberger <joe.hershberger@ni.com> wrote:
> This value is not used by the network stack and is available in the
> global data, so stop passing it around.  For the one legacy function
> that still expects it (init op on old Ethernet drivers) pass in the
> global pointer version directly to avoid changing that interface.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reported-by: Simon Glass <sjg@chromium.org>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v6:
> -Fix compile errors for other boards due to removed parameters

Unfortunately this causes several build failures:

38: net: Remove the bd* parameter from net stack functions
   powerpc:  +   PLU405 PMC440 sc3 neo acadia csb472 devconcenter
sequoia arches lwmon5 t3corp walnut PMC405DE redwood katmai
gdppc440etx p3p440 sycamore MIP405 zeus rainier_ramboot canyonlands
MIP405T haleakala dlvision csb272 xpedite1000 io yosemite yucca makalu
sequoia_ramboot dlvision-10g pcs440ep CPCI4052 sbc405 iocon ebony
glacier_ramboot VOM405 bamboo luan io64 PIP405 intip glacier
lcd4_lwmon5 bubinga yellowstone icon kilauea rainier

e.g:

$ buildman -b dm-push -s PLU405 -e
...
38: net: Remove the bd* parameter from net stack functions
  powerpc:  +   PLU405
+../drivers/net/4xx_enet.c: In function 'mal_err':
+../drivers/net/4xx_enet.c:1734:2: error: too many arguments to
function 'eth_init'
+../include/net.h:169:5: note: declared here
+make[2]: *** [drivers/net/4xx_enet.o] Error 1
+make[1]: *** [drivers/net] Error 2
+make: *** [sub-make] Error 2
...

Can you please check this and respin?

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 09/27] net: Remove the bd* parameter from net stack functions
  2015-03-20 23:01             ` Simon Glass
@ 2015-03-22  3:42               ` Joe Hershberger
  2015-03-22 21:09                 ` Simon Glass
  0 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22  3:42 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Fri, Mar 20, 2015 at 6:01 PM, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Joe,
>
> On 11 March 2015 at 17:44, Joe Hershberger <joe.hershberger@ni.com> wrote:
> > This value is not used by the network stack and is available in the
> > global data, so stop passing it around.  For the one legacy function
> > that still expects it (init op on old Ethernet drivers) pass in the
> > global pointer version directly to avoid changing that interface.
> >
> > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> > Reported-by: Simon Glass <sjg@chromium.org>
> > Reviewed-by: Simon Glass <sjg@chromium.org>
> >
> > ---
> >
> > Changes in v6:
> > -Fix compile errors for other boards due to removed parameters
>
> Unfortunately this causes several build failures:
>
> 38: net: Remove the bd* parameter from net stack functions
>    powerpc:  +   PLU405 PMC440 sc3 neo acadia csb472 devconcenter
> sequoia arches lwmon5 t3corp walnut PMC405DE redwood katmai
> gdppc440etx p3p440 sycamore MIP405 zeus rainier_ramboot canyonlands
> MIP405T haleakala dlvision csb272 xpedite1000 io yosemite yucca makalu
> sequoia_ramboot dlvision-10g pcs440ep CPCI4052 sbc405 iocon ebony
> glacier_ramboot VOM405 bamboo luan io64 PIP405 intip glacier
> lcd4_lwmon5 bubinga yellowstone icon kilauea rainier
>
> e.g:
>
> $ buildman -b dm-push -s PLU405 -e
> ...
> 38: net: Remove the bd* parameter from net stack functions
>   powerpc:  +   PLU405
> +../drivers/net/4xx_enet.c: In function 'mal_err':
> +../drivers/net/4xx_enet.c:1734:2: error: too many arguments to
> function 'eth_init'
> +../include/net.h:169:5: note: declared here
> +make[2]: *** [drivers/net/4xx_enet.o] Error 1
> +make[1]: *** [drivers/net] Error 2
> +make: *** [sub-make] Error 2
> ...
>
> Can you please check this and respin?

Sorry about that. Are you aware of anything other than the 4xx_enet.c
error? I grepped around and didn't find anything else, but I also missed
this one previously using the same method.

Thanks,
-Joe

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 09/27] net: Remove the bd* parameter from net stack functions
  2015-03-22  3:42               ` Joe Hershberger
@ 2015-03-22 21:09                 ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-22 21:09 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 21 March 2015 at 21:42, Joe Hershberger <joe.hershberger@gmail.com> wrote:
>
> Hi Simon,
>
>
> On Fri, Mar 20, 2015 at 6:01 PM, Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Joe,
> >
> > On 11 March 2015 at 17:44, Joe Hershberger <joe.hershberger@ni.com> wrote:
> > > This value is not used by the network stack and is available in the
> > > global data, so stop passing it around.  For the one legacy function
> > > that still expects it (init op on old Ethernet drivers) pass in the
> > > global pointer version directly to avoid changing that interface.
> > >
> > > Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> > > Reported-by: Simon Glass <sjg@chromium.org>
> > > Reviewed-by: Simon Glass <sjg@chromium.org>
> > >
> > > ---
> > >
> > > Changes in v6:
> > > -Fix compile errors for other boards due to removed parameters
> >
> > Unfortunately this causes several build failures:
> >
> > 38: net: Remove the bd* parameter from net stack functions
> >    powerpc:  +   PLU405 PMC440 sc3 neo acadia csb472 devconcenter
> > sequoia arches lwmon5 t3corp walnut PMC405DE redwood katmai
> > gdppc440etx p3p440 sycamore MIP405 zeus rainier_ramboot canyonlands
> > MIP405T haleakala dlvision csb272 xpedite1000 io yosemite yucca makalu
> > sequoia_ramboot dlvision-10g pcs440ep CPCI4052 sbc405 iocon ebony
> > glacier_ramboot VOM405 bamboo luan io64 PIP405 intip glacier
> > lcd4_lwmon5 bubinga yellowstone icon kilauea rainier
> >
> > e.g:
> >
> > $ buildman -b dm-push -s PLU405 -e
> > ...
> > 38: net: Remove the bd* parameter from net stack functions
> >   powerpc:  +   PLU405
> > +../drivers/net/4xx_enet.c: In function 'mal_err':
> > +../drivers/net/4xx_enet.c:1734:2: error: too many arguments to
> > function 'eth_init'
> > +../include/net.h:169:5: note: declared here
> > +make[2]: *** [drivers/net/4xx_enet.o] Error 1
> > +make[1]: *** [drivers/net] Error 2
> > +make: *** [sub-make] Error 2
> > ...
> >
> > Can you please check this and respin?
>
> Sorry about that. Are you aware of anything other than the 4xx_enet.c error? I grepped around and didn't find anything else, but I also missed this one previously using the same method.

Unfortunately I don't have that build anymore. Given the board names
it seems likely.

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 0/27] Add Driver Model support to network stack
  2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
                             ` (27 preceding siblings ...)
  2015-03-20 12:17           ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Simon Glass
@ 2015-03-22 22:08           ` Joe Hershberger
  2015-03-22 22:08             ` [U-Boot] [PATCH v7 01/27] test: dm: Reorder the objects to build Joe Hershberger
                               ` (26 more replies)
  28 siblings, 27 replies; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:08 UTC (permalink / raw)
  To: u-boot

Add support for the Ethernet MAC controllers.  Phy support will come later.

Switching from RFC to a patch series to be applied to dm/master as a staging
area for this series to make it happen more quickly when the window opens.

If desired, let me know which of the non-DM related prerequisite patches are
wanted for this release.

I've added unit tests to verify functionality.

There is an additional driver for sandbox that bridges to the RAW
Ethernet API in Linux which lets you test with real traffic. It now
supports localhost as well (the 'lo' interface).

Changes in v7:
-Fixed compile error in 4xx_enet.c

Changes in v6:
-Add function comments
-Addressed nits
-Check array index bounds
-Fix compile error on boards with CONFIG_API enabled
-Fix compile errors for other boards due to removed parameters
-Swallow -EAGAIN error in eth_rx()
-Updated function documentation

Changes in v5:
-Add a note to doc/README.drivers.eth about its obsolescence
-Add details about lo support to the README
-Added a comment about devname
-Added a test for skipping un-probe-able devices
-Added comments about test cases
-Added fallback for setting promiscuous mode
-Added help to Kconfig
-Added help to the sandbox eth mock driver Kconfig entry
-Added more details and examples in the README
-Check for NULL when reading fdt for host interface
-Check for malloc failure
-Expanded the Kconfig help
-Fix compile error on !DM_ETH
-Fixed warning from missing declaration
-Include new mapmem.h header
-Moved dm/ header
-Moved to a separate header mapmem.h
-New to v5
-Only check for alias if the name is long enough
-Remove cast of pointer passed to free
-Remove socket timeout
-Remove the empty sb_eth_raw_remove function
-Return -errno in from send and recv
-Return errno from recv
-Separate init to 2 helper static functions
-Set the socket to non-blocking
-Simplify sandbox eth driver by switching from int array to byte array
-Switch priv from packet buffer to a pointer to net_rx_packets[0]
-Switched to function to control state of mock driver
-Unmap memory for consistency
-Use INADDR_LOOPBACK
-Use a function call to change mock driver behavior
-Use local var for priv in eth_get_dev()
-Use more verbose comments
-Use net_rx_packets instead of a stack buffer

Changes in v4:
--Don't prevent eth_initialize on driver model
--If current == NULL, always check if there is a device available in eth_get_dev
--Include ethprime handling in eth_initialize
--Look up MAC address in post-probe
--Move env init call from uclass init to eth_initialize
--Print the alias in eth_initialize
--Use eth_initialize to probe all devices and write_hwaddr
-Add a helper function for eth_uclass_priv
-Add ability to disable ping reply in sandbox eth driver
-Add comments to priv struct definition
-Add documentation to the structures
-Add eth_get_ops helper
-Added comments to README.sandbox
-Added support for the 'lo' network interface
-Added testing for ethrotate
-Change -1 returns to error constants
-Change puts to printf
-Clean up the interface to sandbox's eth-raw-os by passing priv to raw-os
-Cleaned up sandbox EXTRA_ENV define
-Cleanup var definition order
-Fix compile regression in !DM_ETH case
-Fixed the MAC address limitation (now all traffic uses MAC address from env)
-Load from ethprime on eth_initialize()
-Move os file to arch
-Moved config to Kconfig
-New to v4
-Redo the seq / probe implementation
-Remove bd_t *bis from dm eth_ops init function
-Remove checks for driver==NULL
-Remove priv pointer in per-device priv struct (drivers already get their own directly from DM)
-Removed checks on priv != NULL and added protection in uclass instead
-Rename halt() to stop() in ops
-Rename init() to start() in ops
-Stop handling selecting a new "current" in pre-unbind as it will now work itself out by clearing the pointer
-Updated expected behavior based on changes to the NetLoop
-Use accessors for platdata and priv
-Use only the seq from DM to find aliases

Changes in v3:
--Fail init if not activated
--Fail probe if ethaddr not set
-Added 2 more ethaddr to sandbox
-Added dm eth testing
-Added support for aliases
-Added support for ethprime
-Added testing for netretry
-Allow current eth dev to be NULL
-Correct failure chaining from bind to probe to init
-Correct the pre_unbind logic
-Fixed blank line formatting for variable declaration
-Made the os raw packet support for sandbox eth build and work.
-Move the get_dev_by_* protos to also be !DM_ETH like the impl
-Prevent a crash if memory is not allocated
-Print which device in the debug write hwaddr
-Reorder dm test makefile
-Update ethaddr from env unconditionally on init
-Use set current to select the current device regardless of the previous selection

Changes in v2:
-Added the raw packet proof-of-concept patch.
-Cause an invalid name to fail binding
-Change printfs to debug in sandbox driver
-Changed eth_uclass_priv local var names to be uc_priv
-Move fake hwaddr to the device tree
-Move static data to priv
-Move the hwaddr to platdata so that its memory is allocated at bind when we need it
-Prevent device from being probed before used by a command (i.e. before eth_init()).
-Rebase on top of dm/master
-Remove unused priv struct for sandbox driver
-Removed extra parentheses
-Stop maintaining our own index and use DM seq now that it works for our needs
-Update error codes
-Updated comments

Joe Hershberger (27):
  test: dm: Reorder the objects to build
  common: Make sure arch-specific map_sysmem() is defined
  net: Provide a function to get the current MAC address
  net: Rename helper function to be more clear
  net: Remove unneeded "extern" in net.h
  net: Refactor in preparation for driver model
  net: Change return codes from net/eth.c to use errorno constants
  net: Use int instead of u8 for boolean flag
  net: Remove the bd* parameter from net stack functions
  net: Make netretry actually do something
  net: Access mapped physmem in net functions
  cmd: net: Clean up return codes
  dm: eth: Add basic driver model support to Ethernet stack
  net: Clean up network stack names used in DM drivers
  dm: eth: Pass the packet pointer as a parameter to recv
  sandbox: eth: Add network support to sandbox
  sandbox: eth: Add ARP and PING response to sandbox driver
  test: dm: eth: Add tests for the eth dm implementation
  dm: eth: Add support for aliases
  dm: eth: Add support for ethprime env var
  test: dm: eth: Add testing for ethrotate env var
  sandbox: eth: Add ability to disable ping reply in sandbox eth driver
  test: dm: net: Add a test of the netretry behavior
  sandbox: eth: Add a bridge to a real network for sandbox
  sandbox: Enable DHCP and IP defrag
  sandbox: eth: Add support for using the 'lo' interface
  net: Improve error handling

 api/api_net.c                             |   2 +-
 arch/arm/lib/board.c                      |   2 +-
 arch/arm/lib/bootm.c                      |   1 +
 arch/avr32/lib/board.c                    |   2 +-
 arch/m68k/lib/board.c                     |   4 +-
 arch/mips/mach-au1x00/au1x00_eth.c        |   2 +-
 arch/nds32/lib/board.c                    |   2 +-
 arch/openrisc/lib/board.c                 |   2 +-
 arch/powerpc/cpu/mpc8260/ether_fcc.c      |   2 +-
 arch/powerpc/cpu/mpc85xx/ether_fcc.c      |   2 +-
 arch/powerpc/cpu/mpc8xx/scc.c             |   2 +-
 arch/powerpc/lib/board.c                  |   2 +-
 arch/sandbox/Kconfig                      |  12 +
 arch/sandbox/cpu/Makefile                 |  10 +
 arch/sandbox/cpu/eth-raw-os.c             | 249 +++++++++++++
 arch/sandbox/dts/sandbox.dts              |  21 ++
 arch/sandbox/include/asm/eth-raw-os.h     |  40 +++
 arch/sandbox/include/asm/eth.h            |  15 +
 arch/sh/lib/board.c                       |   2 +-
 arch/sparc/lib/board.c                    |   2 +-
 board/BuS/eb_cpux9k2/cpux9k2.c            |   2 +-
 board/BuS/vl_ma2sc/vl_ma2sc.c             |   2 +-
 board/atmel/at91sam9261ek/at91sam9261ek.c |   2 +-
 board/egnite/ethernut5/ethernut5.c        |   2 +-
 board/ronetix/pm9261/pm9261.c             |   2 +-
 board/ronetix/pm9g45/pm9g45.c             |   2 +-
 board/sandbox/README.sandbox              |  78 +++-
 common/board_f.c                          |   1 +
 common/board_r.c                          |   3 +-
 common/bootm.c                            |   1 +
 common/cmd_bdinfo.c                       |   2 +
 common/cmd_bootm.c                        |   1 +
 common/cmd_demo.c                         |   1 +
 common/cmd_fat.c                          |   1 +
 common/cmd_fdt.c                          |   1 +
 common/cmd_lzmadec.c                      |   1 +
 common/cmd_md5sum.c                       |   1 +
 common/cmd_mem.c                          |   1 +
 common/cmd_net.c                          |  45 ++-
 common/cmd_nvedit.c                       |   1 +
 common/cmd_pxe.c                          |   1 +
 common/cmd_sf.c                           |   1 +
 common/cmd_source.c                       |   1 +
 common/cmd_trace.c                        |   1 +
 common/cmd_ximg.c                         |   1 +
 common/hash.c                             |   1 +
 common/image-fdt.c                        |   1 +
 common/image-fit.c                        |   1 +
 common/image.c                            |   1 +
 common/iotrace.c                          |   1 +
 common/lcd.c                              |   1 +
 common/malloc_simple.c                    |   1 +
 common/spl/spl_net.c                      |   2 +-
 doc/README.drivers.eth                    |   6 +
 drivers/demo/demo-simple.c                |   1 +
 drivers/i2c/i2c-uniphier-f.c              |   1 +
 drivers/i2c/i2c-uniphier.c                |   1 +
 drivers/mtd/spi/sf_probe.c                |   1 +
 drivers/net/4xx_enet.c                    |   5 +-
 drivers/net/Kconfig                       |  42 +++
 drivers/net/Makefile                      |   2 +
 drivers/net/netconsole.c                  |   4 +-
 drivers/net/sandbox-raw.c                 | 165 +++++++++
 drivers/net/sandbox.c                     | 208 +++++++++++
 drivers/serial/ns16550.c                  |   1 +
 drivers/serial/serial_uniphier.c          |   1 +
 fs/fs.c                                   |   1 +
 include/common.h                          |  17 -
 include/configs/sandbox.h                 |  25 +-
 include/dm/uclass-id.h                    |   1 +
 include/mapmem.h                          |  32 ++
 include/net.h                             | 201 +++++++----
 lib/trace.c                               |   1 +
 net/eth.c                                 | 580 ++++++++++++++++++++++++++----
 net/net.c                                 |  67 ++--
 net/nfs.c                                 |   6 +-
 net/tftp.c                                |   6 +-
 test/compression.c                        |   1 +
 test/dm/Makefile                          |   5 +-
 test/dm/cmd_dm.c                          |   1 +
 test/dm/eth.c                             | 156 ++++++++
 test/dm/test.dts                          |  20 ++
 82 files changed, 1869 insertions(+), 229 deletions(-)
 create mode 100644 arch/sandbox/cpu/eth-raw-os.c
 create mode 100644 arch/sandbox/include/asm/eth-raw-os.h
 create mode 100644 arch/sandbox/include/asm/eth.h
 create mode 100644 drivers/net/sandbox-raw.c
 create mode 100644 drivers/net/sandbox.c
 create mode 100644 include/mapmem.h
 create mode 100644 test/dm/eth.c

-- 
1.7.11.5

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 01/27] test: dm: Reorder the objects to build
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
@ 2015-03-22 22:08             ` Joe Hershberger
  2015-03-23 16:01               ` Simon Glass
  2015-03-22 22:08             ` [U-Boot] [PATCH v7 02/27] common: Make sure arch-specific map_sysmem() is defined Joe Hershberger
                               ` (25 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:08 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Acked-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
-Reorder dm test makefile

Changes in v2: None

 test/dm/Makefile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/dm/Makefile b/test/dm/Makefile
index 612aa95..1d9148f 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -18,7 +18,7 @@ obj-$(CONFIG_DM_TEST) += core.o
 obj-$(CONFIG_DM_TEST) += ut.o
 ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_DM_GPIO) += gpio.o
-obj-$(CONFIG_DM_SPI) += spi.o
-obj-$(CONFIG_DM_SPI_FLASH) += sf.o
 obj-$(CONFIG_DM_I2C) += i2c.o
+obj-$(CONFIG_DM_SPI_FLASH) += sf.o
+obj-$(CONFIG_DM_SPI) += spi.o
 endif
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 02/27] common: Make sure arch-specific map_sysmem() is defined
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
  2015-03-22 22:08             ` [U-Boot] [PATCH v7 01/27] test: dm: Reorder the objects to build Joe Hershberger
@ 2015-03-22 22:08             ` Joe Hershberger
  2015-03-23 16:03               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 03/27] net: Provide a function to get the current MAC address Joe Hershberger
                               ` (24 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:08 UTC (permalink / raw)
  To: u-boot

In the case where the arch defines a custom map_sysmem(), make sure that
including just mapmem.h is sufficient to have these functions as they
are when the arch does not override it.

Also split the non-arch specific functions out of common.h

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5:
-Moved to a separate header mapmem.h

Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 arch/arm/lib/bootm.c             |  1 +
 common/board_f.c                 |  1 +
 common/board_r.c                 |  1 +
 common/bootm.c                   |  1 +
 common/cmd_bootm.c               |  1 +
 common/cmd_demo.c                |  1 +
 common/cmd_fat.c                 |  1 +
 common/cmd_fdt.c                 |  1 +
 common/cmd_lzmadec.c             |  1 +
 common/cmd_md5sum.c              |  1 +
 common/cmd_mem.c                 |  1 +
 common/cmd_nvedit.c              |  1 +
 common/cmd_pxe.c                 |  1 +
 common/cmd_sf.c                  |  1 +
 common/cmd_source.c              |  1 +
 common/cmd_trace.c               |  1 +
 common/cmd_ximg.c                |  1 +
 common/hash.c                    |  1 +
 common/image-fdt.c               |  1 +
 common/image-fit.c               |  1 +
 common/image.c                   |  1 +
 common/iotrace.c                 |  1 +
 common/lcd.c                     |  1 +
 common/malloc_simple.c           |  1 +
 drivers/demo/demo-simple.c       |  1 +
 drivers/i2c/i2c-uniphier-f.c     |  1 +
 drivers/i2c/i2c-uniphier.c       |  1 +
 drivers/mtd/spi/sf_probe.c       |  1 +
 drivers/serial/ns16550.c         |  1 +
 drivers/serial/serial_uniphier.c |  1 +
 fs/fs.c                          |  1 +
 include/common.h                 | 17 -----------------
 include/mapmem.h                 | 32 ++++++++++++++++++++++++++++++++
 lib/trace.c                      |  1 +
 test/compression.c               |  1 +
 test/dm/cmd_dm.c                 |  1 +
 36 files changed, 66 insertions(+), 17 deletions(-)
 create mode 100644 include/mapmem.h

diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 2d6b676..b1bff8c 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -18,6 +18,7 @@
 #include <u-boot/zlib.h>
 #include <asm/byteorder.h>
 #include <libfdt.h>
+#include <mapmem.h>
 #include <fdt_support.h>
 #include <asm/bootm.h>
 #include <asm/secure.h>
diff --git a/common/board_f.c b/common/board_f.c
index 4d8b8a6..1b7e7d9 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -23,6 +23,7 @@
 #include <i2c.h>
 #include <initcall.h>
 #include <logbuff.h>
+#include <mapmem.h>
 
 /* TODO: Can we move these into arch/ headers? */
 #ifdef CONFIG_8xx
diff --git a/common/board_r.c b/common/board_r.c
index 4fcd4f6..af0f274 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -33,6 +33,7 @@
 #endif
 #include <logbuff.h>
 #include <malloc.h>
+#include <mapmem.h>
 #ifdef CONFIG_BITBANGMII
 #include <miiphy.h>
 #endif
diff --git a/common/bootm.c b/common/bootm.c
index 34f60bb..6842029 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -13,6 +13,7 @@
 #include <fdt_support.h>
 #include <lmb.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <asm/io.h>
 #include <linux/lzo.h>
 #include <lzma/LzmaTypes.h>
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index 48199bf..b3d3968 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -16,6 +16,7 @@
 #include <image.h>
 #include <lmb.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <nand.h>
 #include <asm/byteorder.h>
 #include <linux/compiler.h>
diff --git a/common/cmd_demo.c b/common/cmd_demo.c
index 8a10bdf..209dc4a 100644
--- a/common/cmd_demo.c
+++ b/common/cmd_demo.c
@@ -9,6 +9,7 @@
 
 #include <common.h>
 #include <dm-demo.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 struct udevice *demo_dev;
diff --git a/common/cmd_fat.c b/common/cmd_fat.c
index c00fb28..aae993d 100644
--- a/common/cmd_fat.c
+++ b/common/cmd_fat.c
@@ -14,6 +14,7 @@
 #include <net.h>
 #include <ata.h>
 #include <asm/io.h>
+#include <mapmem.h>
 #include <part.h>
 #include <fat.h>
 #include <fs.h>
diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c
index 48b3e70..682b655 100644
--- a/common/cmd_fdt.c
+++ b/common/cmd_fdt.c
@@ -15,6 +15,7 @@
 #include <asm/global_data.h>
 #include <libfdt.h>
 #include <fdt_support.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 #define MAX_LEVEL	32		/* how deeply nested we will go */
diff --git a/common/cmd_lzmadec.c b/common/cmd_lzmadec.c
index 7b0b3fd..1ad9ed6 100644
--- a/common/cmd_lzmadec.c
+++ b/common/cmd_lzmadec.c
@@ -12,6 +12,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 #include <lzma/LzmaTools.h>
diff --git a/common/cmd_md5sum.c b/common/cmd_md5sum.c
index d22ace5..23bb81e 100644
--- a/common/cmd_md5sum.c
+++ b/common/cmd_md5sum.c
@@ -10,6 +10,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <mapmem.h>
 #include <u-boot/md5.h>
 #include <asm/io.h>
 
diff --git a/common/cmd_mem.c b/common/cmd_mem.c
index bcb3ee3..66a41da 100644
--- a/common/cmd_mem.c
+++ b/common/cmd_mem.c
@@ -20,6 +20,7 @@
 #endif
 #include <hash.h>
 #include <inttypes.h>
+#include <mapmem.h>
 #include <watchdog.h>
 #include <asm/io.h>
 #include <linux/compiler.h>
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 855808c..be792ae 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -31,6 +31,7 @@
 #include <search.h>
 #include <errno.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <watchdog.h>
 #include <linux/stddef.h>
 #include <asm/byteorder.h>
diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c
index 7e32c95..96f963d 100644
--- a/common/cmd_pxe.c
+++ b/common/cmd_pxe.c
@@ -8,6 +8,7 @@
 #include <common.h>
 #include <command.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <errno.h>
diff --git a/common/cmd_sf.c b/common/cmd_sf.c
index 5c788e9..01c37de 100644
--- a/common/cmd_sf.c
+++ b/common/cmd_sf.c
@@ -10,6 +10,7 @@
 #include <div64.h>
 #include <dm.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <spi.h>
 #include <spi_flash.h>
 
diff --git a/common/cmd_source.c b/common/cmd_source.c
index 6881bc9..d2a881d 100644
--- a/common/cmd_source.c
+++ b/common/cmd_source.c
@@ -19,6 +19,7 @@
 #include <command.h>
 #include <image.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #if defined(CONFIG_8xx)
diff --git a/common/cmd_trace.c b/common/cmd_trace.c
index 8c630e6..1e62a1a 100644
--- a/common/cmd_trace.c
+++ b/common/cmd_trace.c
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <mapmem.h>
 #include <trace.h>
 #include <asm/io.h>
 
diff --git a/common/cmd_ximg.c b/common/cmd_ximg.c
index 64b9186..8b8645c 100644
--- a/common/cmd_ximg.c
+++ b/common/cmd_ximg.c
@@ -15,6 +15,7 @@
 #include <common.h>
 #include <command.h>
 #include <image.h>
+#include <mapmem.h>
 #include <watchdog.h>
 #if defined(CONFIG_BZIP2)
 #include <bzlib.h>
diff --git a/common/hash.c b/common/hash.c
index 9e9f84b..c94c98b 100644
--- a/common/hash.c
+++ b/common/hash.c
@@ -14,6 +14,7 @@
 #include <common.h>
 #include <command.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <hw_sha.h>
 #include <asm/io.h>
 #include <asm/errno.h>
diff --git a/common/image-fdt.c b/common/image-fdt.c
index d9e4728..7e2da7b 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -14,6 +14,7 @@
 #include <errno.h>
 #include <image.h>
 #include <libfdt.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 #ifndef CONFIG_SYS_FDT_PAD
diff --git a/common/image-fit.c b/common/image-fit.c
index 778d2a1..4eb4d42 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -16,6 +16,7 @@
 #else
 #include <common.h>
 #include <errno.h>
+#include <mapmem.h>
 #include <asm/io.h>
 DECLARE_GLOBAL_DATA_PTR;
 #endif /* !USE_HOSTCC*/
diff --git a/common/image.c b/common/image.c
index a911aa9..f3277c9 100644
--- a/common/image.c
+++ b/common/image.c
@@ -27,6 +27,7 @@
 
 #include <environment.h>
 #include <image.h>
+#include <mapmem.h>
 
 #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
 #include <libfdt.h>
diff --git a/common/iotrace.c b/common/iotrace.c
index ced426e..2725563 100644
--- a/common/iotrace.c
+++ b/common/iotrace.c
@@ -7,6 +7,7 @@
 #define IOTRACE_IMPL
 
 #include <common.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 DECLARE_GLOBAL_DATA_PTR;
diff --git a/common/lcd.c b/common/lcd.c
index f33942c..6982759 100644
--- a/common/lcd.c
+++ b/common/lcd.c
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <stdio_dev.h>
 #include <lcd.h>
+#include <mapmem.h>
 #include <watchdog.h>
 #include <asm/unaligned.h>
 #include <splash.h>
diff --git a/common/malloc_simple.c b/common/malloc_simple.c
index 64ae036..d445199 100644
--- a/common/malloc_simple.c
+++ b/common/malloc_simple.c
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 DECLARE_GLOBAL_DATA_PTR;
diff --git a/drivers/demo/demo-simple.c b/drivers/demo/demo-simple.c
index 2bcb7df..f069748 100644
--- a/drivers/demo/demo-simple.c
+++ b/drivers/demo/demo-simple.c
@@ -10,6 +10,7 @@
 #include <common.h>
 #include <dm.h>
 #include <dm-demo.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 static int simple_hello(struct udevice *dev, int ch)
diff --git a/drivers/i2c/i2c-uniphier-f.c b/drivers/i2c/i2c-uniphier-f.c
index 6707edd..ffa6ce5 100644
--- a/drivers/i2c/i2c-uniphier-f.c
+++ b/drivers/i2c/i2c-uniphier-f.c
@@ -13,6 +13,7 @@
 #include <dm/root.h>
 #include <i2c.h>
 #include <fdtdec.h>
+#include <mapmem.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
diff --git a/drivers/i2c/i2c-uniphier.c b/drivers/i2c/i2c-uniphier.c
index 64a9ed8..760457f 100644
--- a/drivers/i2c/i2c-uniphier.c
+++ b/drivers/i2c/i2c-uniphier.c
@@ -13,6 +13,7 @@
 #include <dm/root.h>
 #include <i2c.h>
 #include <fdtdec.h>
+#include <mapmem.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 4103723..ffc4caa 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -13,6 +13,7 @@
 #include <errno.h>
 #include <fdtdec.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <spi.h>
 #include <spi_flash.h>
 #include <asm/io.h>
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 03beab5..67b1d60 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -8,6 +8,7 @@
 #include <dm.h>
 #include <errno.h>
 #include <fdtdec.h>
+#include <mapmem.h>
 #include <ns16550.h>
 #include <serial.h>
 #include <watchdog.h>
diff --git a/drivers/serial/serial_uniphier.c b/drivers/serial/serial_uniphier.c
index a6bd27f..2a12250 100644
--- a/drivers/serial/serial_uniphier.c
+++ b/drivers/serial/serial_uniphier.c
@@ -10,6 +10,7 @@
 #include <asm/errno.h>
 #include <dm/device.h>
 #include <dm/platform_data/serial-uniphier.h>
+#include <mapmem.h>
 #include <serial.h>
 #include <fdtdec.h>
 
diff --git a/fs/fs.c b/fs/fs.c
index 483273f..ac0897d 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -17,6 +17,7 @@
 #include <config.h>
 #include <errno.h>
 #include <common.h>
+#include <mapmem.h>
 #include <part.h>
 #include <ext4fs.h>
 #include <fat.h>
diff --git a/include/common.h b/include/common.h
index 77c55c6..3ccc6f3 100644
--- a/include/common.h
+++ b/include/common.h
@@ -845,23 +845,6 @@ int cpu_disable(int nr);
 int cpu_release(int nr, int argc, char * const argv[]);
 #endif
 
-/* Define a null map_sysmem() if the architecture doesn't use it */
-# ifndef CONFIG_ARCH_MAP_SYSMEM
-static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
-{
-	return (void *)(uintptr_t)paddr;
-}
-
-static inline void unmap_sysmem(const void *vaddr)
-{
-}
-
-static inline phys_addr_t map_to_sysmem(const void *ptr)
-{
-	return (phys_addr_t)(uintptr_t)ptr;
-}
-# endif
-
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_PPC
diff --git a/include/mapmem.h b/include/mapmem.h
new file mode 100644
index 0000000..42ef3e8
--- /dev/null
+++ b/include/mapmem.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef __MAPMEM_H
+#define __MAPMEM_H
+
+/* Define a null map_sysmem() if the architecture doesn't use it */
+# ifdef CONFIG_ARCH_MAP_SYSMEM
+#include <asm/io.h>
+# else
+static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
+{
+	return (void *)(uintptr_t)paddr;
+}
+
+static inline void unmap_sysmem(const void *vaddr)
+{
+}
+
+static inline phys_addr_t map_to_sysmem(const void *ptr)
+{
+	return (phys_addr_t)(uintptr_t)ptr;
+}
+# endif
+
+#endif /* __MAPMEM_H */
diff --git a/lib/trace.c b/lib/trace.c
index 711e5b5..ad5e07b 100644
--- a/lib/trace.c
+++ b/lib/trace.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <mapmem.h>
 #include <trace.h>
 #include <asm/io.h>
 #include <asm/sections.h>
diff --git a/test/compression.c b/test/compression.c
index ea2e4ad..7ef3a8c 100644
--- a/test/compression.c
+++ b/test/compression.c
@@ -10,6 +10,7 @@
 #include <bootm.h>
 #include <command.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <asm/io.h>
 
 #include <u-boot/zlib.h>
diff --git a/test/dm/cmd_dm.c b/test/dm/cmd_dm.c
index 79a674e..195815e 100644
--- a/test/dm/cmd_dm.c
+++ b/test/dm/cmd_dm.c
@@ -10,6 +10,7 @@
 #include <common.h>
 #include <dm.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <errno.h>
 #include <asm/io.h>
 #include <dm/root.h>
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 03/27] net: Provide a function to get the current MAC address
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
  2015-03-22 22:08             ` [U-Boot] [PATCH v7 01/27] test: dm: Reorder the objects to build Joe Hershberger
  2015-03-22 22:08             ` [U-Boot] [PATCH v7 02/27] common: Make sure arch-specific map_sysmem() is defined Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:03               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 04/27] net: Rename helper function to be more clear Joe Hershberger
                               ` (23 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

The current implementation exposes the eth_device struct to code that
needs to access the MAC address.  Add a wrapper function for this to
abstract away the pointer for this operation.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 arch/mips/mach-au1x00/au1x00_eth.c   | 2 +-
 arch/powerpc/cpu/mpc8260/ether_fcc.c | 2 +-
 arch/powerpc/cpu/mpc85xx/ether_fcc.c | 2 +-
 arch/powerpc/cpu/mpc8xx/scc.c        | 2 +-
 include/net.h                        | 8 ++++++++
 net/net.c                            | 2 +-
 6 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/arch/mips/mach-au1x00/au1x00_eth.c b/arch/mips/mach-au1x00/au1x00_eth.c
index 39c5b6b..a47f088 100644
--- a/arch/mips/mach-au1x00/au1x00_eth.c
+++ b/arch/mips/mach-au1x00/au1x00_eth.c
@@ -238,7 +238,7 @@ static int au1x00_init(struct eth_device* dev, bd_t * bd){
 	}
 
 	/* Put mac addr in little endian */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
 	*mac_addr_high	=	(ea[5] <<  8) | (ea[4]	    ) ;
 	*mac_addr_low	=	(ea[3] << 24) | (ea[2] << 16) |
 		(ea[1] <<  8) | (ea[0]	    ) ;
diff --git a/arch/powerpc/cpu/mpc8260/ether_fcc.c b/arch/powerpc/cpu/mpc8260/ether_fcc.c
index f9f15b5..f777ba1 100644
--- a/arch/powerpc/cpu/mpc8260/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc8260/ether_fcc.c
@@ -299,7 +299,7 @@ static int fec_init(struct eth_device* dev, bd_t *bis)
      * it unique by setting a few bits in the upper byte of the
      * non-static part of the address.
      */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
     pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
     pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
     pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/arch/powerpc/cpu/mpc85xx/ether_fcc.c b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
index 166dc9e..58d4bfb 100644
--- a/arch/powerpc/cpu/mpc85xx/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
@@ -338,7 +338,7 @@ static int fec_init(struct eth_device* dev, bd_t *bis)
      * it unique by setting a few bits in the upper byte of the
      * non-static part of the address.
      */
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
     pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
     pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
     pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/arch/powerpc/cpu/mpc8xx/scc.c b/arch/powerpc/cpu/mpc8xx/scc.c
index 251966b..66e4014 100644
--- a/arch/powerpc/cpu/mpc8xx/scc.c
+++ b/arch/powerpc/cpu/mpc8xx/scc.c
@@ -339,7 +339,7 @@ static int scc_init (struct eth_device *dev, bd_t * bis)
 	pram_ptr->sen_gaddr3 = 0x0;	/* Group Address Filter 3 (unused) */
 	pram_ptr->sen_gaddr4 = 0x0;	/* Group Address Filter 4 (unused) */
 
-#define ea eth_get_dev()->enetaddr
+#define ea eth_get_ethaddr()
 	pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4];
 	pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2];
 	pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0];
diff --git a/include/net.h b/include/net.h
index 43e3d28..6c76976 100644
--- a/include/net.h
+++ b/include/net.h
@@ -111,6 +111,14 @@ struct eth_device *eth_get_dev(void)
 {
 	return eth_current;
 }
+
+static inline unsigned char *eth_get_ethaddr(void)
+{
+	if (eth_current)
+		return eth_current->enetaddr;
+	return NULL;
+}
+
 extern struct eth_device *eth_get_dev_by_name(const char *devname);
 extern struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
 extern int eth_get_dev_index(void);		/* get the device index */
diff --git a/net/net.c b/net/net.c
index b60ce62..4b3c90e 100644
--- a/net/net.c
+++ b/net/net.c
@@ -275,7 +275,7 @@ static void NetInitLoop(void)
 		env_changed_id = env_id;
 	}
 	if (eth_get_dev())
-		memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
+		memcpy(NetOurEther, eth_get_ethaddr(), 6);
 
 	return;
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 04/27] net: Rename helper function to be more clear
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (2 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 03/27] net: Provide a function to get the current MAC address Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:03               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 05/27] net: Remove unneeded "extern" in net.h Joe Hershberger
                               ` (22 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

Make it clear that the helper is checking the addr, not setting it.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 net/eth.c | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/net/eth.c b/net/eth.c
index eac4f7b..65e8c77 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -153,11 +153,6 @@ static void eth_current_changed(void)
 		setenv("ethact", NULL);
 }
 
-static int eth_address_set(unsigned char *addr)
-{
-	return memcmp(addr, "\0\0\0\0\0\0", 6);
-}
-
 int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		   int eth_number)
 {
@@ -166,9 +161,9 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 
 	eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
 
-	if (eth_address_set(env_enetaddr)) {
-		if (eth_address_set(dev->enetaddr) &&
-				memcmp(dev->enetaddr, env_enetaddr, 6)) {
+	if (!is_zero_ether_addr(env_enetaddr)) {
+		if (!is_zero_ether_addr(dev->enetaddr) &&
+		    memcmp(dev->enetaddr, env_enetaddr, 6)) {
 			printf("\nWarning: %s MAC addresses don't match:\n",
 				dev->name);
 			printf("Address in SROM is         %pM\n",
@@ -183,7 +178,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 					     dev->enetaddr);
 		printf("\nWarning: %s using MAC address from net device\n",
 			dev->name);
-	} else if (!(eth_address_set(dev->enetaddr))) {
+	} else if (is_zero_ether_addr(dev->enetaddr)) {
 		printf("\nError: %s address not set.\n",
 		       dev->name);
 		return -EINVAL;
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 05/27] net: Remove unneeded "extern" in net.h
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (3 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 04/27] net: Rename helper function to be more clear Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:03               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 06/27] net: Refactor in preparation for driver model Joe Hershberger
                               ` (21 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

Many of the functions in net.h were preceded extern needlessly. Removing
them to limit the number of checkpatch.pl complaints.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6:
-Fix compile error on boards with CONFIG_API enabled

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/net.h | 90 +++++++++++++++++++++++++++++------------------------------
 1 file changed, 45 insertions(+), 45 deletions(-)

diff --git a/include/net.h b/include/net.h
index 6c76976..51ed5b0 100644
--- a/include/net.h
+++ b/include/net.h
@@ -97,11 +97,11 @@ struct eth_device {
 	void *priv;
 };
 
-extern int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
-extern int eth_register(struct eth_device* dev);/* Register network device */
-extern int eth_unregister(struct eth_device *dev);/* Remove network device */
-extern void eth_try_another(int first_restart);	/* Change the device */
-extern void eth_set_current(void);		/* set nterface to ethcur var */
+int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
+int eth_register(struct eth_device *dev);/* Register network device */
+int eth_unregister(struct eth_device *dev);/* Remove network device */
+void eth_try_another(int first_restart);	/* Change the device */
+void eth_set_current(void);		/* set nterface to ethcur var */
 
 /* get the current device MAC */
 extern struct eth_device *eth_current;
@@ -119,12 +119,12 @@ static inline unsigned char *eth_get_ethaddr(void)
 	return NULL;
 }
 
-extern struct eth_device *eth_get_dev_by_name(const char *devname);
-extern struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
-extern int eth_get_dev_index(void);		/* get the device index */
-extern void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
-extern int eth_getenv_enetaddr(char *name, uchar *enetaddr);
-extern int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
+struct eth_device *eth_get_dev_by_name(const char *devname);
+struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
+int eth_get_dev_index(void);		/* get the device index */
+void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
+int eth_getenv_enetaddr(char *name, uchar *enetaddr);
+int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 
 /*
  * Get the hardware address for an ethernet interface .
@@ -135,20 +135,20 @@ extern int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
  * Returns:
  *	Return true if the address is valid.
  */
-extern int eth_getenv_enetaddr_by_index(const char *base_name, int index,
-					uchar *enetaddr);
+int eth_getenv_enetaddr_by_index(const char *base_name, int index,
+				 uchar *enetaddr);
 
-extern int usb_eth_initialize(bd_t *bi);
-extern int eth_init(bd_t *bis);			/* Initialize the device */
-extern int eth_send(void *packet, int length);	   /* Send a packet */
+int usb_eth_initialize(bd_t *bi);
+int eth_init(bd_t *bis);			/* Initialize the device */
+int eth_send(void *packet, int length);	   /* Send a packet */
 
 #ifdef CONFIG_API
-extern int eth_receive(void *packet, int length); /* Receive a packet*/
+int eth_receive(void *packet, int length); /* Receive a packet*/
 extern void (*push_packet)(void *packet, int length);
 #endif
-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 */
+int eth_rx(void);			/* Check for received packets */
+void eth_halt(void);			/* stop SCC */
+char *eth_get_name(void);		/* get name of current device */
 
 /* Set active state */
 static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
@@ -469,25 +469,25 @@ extern IPaddr_t Mcast_addr;
 #endif
 
 /* Initialize the network adapter */
-extern void net_init(void);
-extern int NetLoop(enum proto_t);
+void net_init(void);
+int NetLoop(enum proto_t);
 
 /* Shutdown adapters and cleanup */
-extern void	NetStop(void);
+void	NetStop(void);
 
 /* Load failed.	 Start again. */
-extern void	NetStartAgain(void);
+void	NetStartAgain(void);
 
 /* Get size of the ethernet header when we send */
-extern int	NetEthHdrSize(void);
+int	NetEthHdrSize(void);
 
 /* Set ethernet header; returns the size of the header */
-extern int NetSetEther(uchar *, uchar *, uint);
-extern int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot);
+int NetSetEther(uchar *, uchar *, uint);
+int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot);
 
 /* Set IP header */
-extern void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source);
-extern void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport,
+void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source);
+void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport,
 				int sport, int len);
 
 /**
@@ -521,12 +521,12 @@ unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new_sum);
 int ip_checksum_ok(const void *addr, unsigned nbytes);
 
 /* Callbacks */
-extern rxhand_f *net_get_udp_handler(void);	/* Get UDP RX packet handler */
-extern void net_set_udp_handler(rxhand_f *);	/* Set UDP RX packet handler */
-extern rxhand_f *net_get_arp_handler(void);	/* Get ARP RX packet handler */
-extern void net_set_arp_handler(rxhand_f *);	/* Set ARP RX packet handler */
-extern void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
-extern void	NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
+rxhand_f *net_get_udp_handler(void);	/* Get UDP RX packet handler */
+void net_set_udp_handler(rxhand_f *);	/* Set UDP RX packet handler */
+rxhand_f *net_get_arp_handler(void);	/* Get ARP RX packet handler */
+void net_set_arp_handler(rxhand_f *);	/* Set ARP RX packet handler */
+void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
+void	NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
 
 /* Network loop state */
 enum net_loop_state {
@@ -559,11 +559,11 @@ static inline void NetSendPacket(uchar *pkt, int len)
  * @param sport Source UDP port
  * @param payload_len Length of data after the UDP header
  */
-extern int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport,
+int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport,
 			int sport, int payload_len);
 
 /* Processes a received packet */
-extern void NetReceive(uchar *, int);
+void NetReceive(uchar *, int);
 
 #ifdef CONFIG_NETCONSOLE
 void NcStart(void);
@@ -711,28 +711,28 @@ static inline void eth_random_addr(uchar *addr)
 }
 
 /* Convert an IP address to a string */
-extern void ip_to_string(IPaddr_t x, char *s);
+void ip_to_string(IPaddr_t x, char *s);
 
 /* Convert a string to ip address */
-extern IPaddr_t string_to_ip(const char *s);
+IPaddr_t string_to_ip(const char *s);
 
 /* Convert a VLAN id to a string */
-extern void VLAN_to_string(ushort x, char *s);
+void VLAN_to_string(ushort x, char *s);
 
 /* Convert a string to a vlan id */
-extern ushort string_to_VLAN(const char *s);
+ushort string_to_VLAN(const char *s);
 
 /* read a VLAN id from an environment variable */
-extern ushort getenv_VLAN(char *);
+ushort getenv_VLAN(char *);
 
 /* copy a filename (allow for "..." notation, limit length) */
-extern void copy_filename(char *dst, const char *src, int size);
+void copy_filename(char *dst, const char *src, int size);
 
 /* get a random source port */
-extern unsigned int random_port(void);
+unsigned int random_port(void);
 
 /* Update U-Boot over TFTP */
-extern int update_tftp(ulong addr);
+int update_tftp(ulong addr);
 
 /**********************************************************************/
 
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 06/27] net: Refactor in preparation for driver model
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (4 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 05/27] net: Remove unneeded "extern" in net.h Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:04               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 07/27] net: Change return codes from net/eth.c to use errorno constants Joe Hershberger
                               ` (20 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

Move some things around and organize things so that the driver model
implementation will fit in more easily.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5:
-Fixed warning from missing declaration

Changes in v4:
-Fix compile regression in !DM_ETH case

Changes in v3:
-Move the get_dev_by_* protos to also be !DM_ETH like the impl

Changes in v2: None

 include/net.h | 68 +++++++++++++++++++++++++-------------------------
 net/eth.c     | 79 ++++++++++++++++++++++++++++++++---------------------------
 2 files changed, 78 insertions(+), 69 deletions(-)

diff --git a/include/net.h b/include/net.h
index 51ed5b0..fdf6860 100644
--- a/include/net.h
+++ b/include/net.h
@@ -97,13 +97,9 @@ struct eth_device {
 	void *priv;
 };
 
-int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
 int eth_register(struct eth_device *dev);/* Register network device */
 int eth_unregister(struct eth_device *dev);/* Remove network device */
-void eth_try_another(int first_restart);	/* Change the device */
-void eth_set_current(void);		/* set nterface to ethcur var */
 
-/* get the current device MAC */
 extern struct eth_device *eth_current;
 
 static inline __attribute__((always_inline))
@@ -111,7 +107,10 @@ struct eth_device *eth_get_dev(void)
 {
 	return eth_current;
 }
+struct eth_device *eth_get_dev_by_name(const char *devname);
+struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
 
+/* get the current device MAC */
 static inline unsigned char *eth_get_ethaddr(void)
 {
 	if (eth_current)
@@ -119,8 +118,37 @@ static inline unsigned char *eth_get_ethaddr(void)
 	return NULL;
 }
 
-struct eth_device *eth_get_dev_by_name(const char *devname);
-struct eth_device *eth_get_dev_by_index(int index); /* get dev @ index */
+/* Set active state */
+static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
+{
+	eth_get_dev()->state = ETH_STATE_ACTIVE;
+
+	return 0;
+}
+/* Set passive state */
+static inline __attribute__((always_inline)) void eth_halt_state_only(void)
+{
+	eth_get_dev()->state = ETH_STATE_PASSIVE;
+}
+
+/*
+ * Set the hardware address for an ethernet interface based on 'eth%daddr'
+ * environment variable (or just 'ethaddr' if eth_number is 0).
+ * Args:
+ *	base_name - base name for device (normally "eth")
+ *	eth_number - value of %d (0 for first device of this type)
+ * Returns:
+ *	0 is success, non-zero is error status from driver.
+ */
+int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
+		     int eth_number);
+
+int usb_eth_initialize(bd_t *bi);
+
+int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
+void eth_try_another(int first_restart);	/* Change the device */
+void eth_set_current(void);		/* set nterface to ethcur var */
+
 int eth_get_dev_index(void);		/* get the device index */
 void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
 int eth_getenv_enetaddr(char *name, uchar *enetaddr);
@@ -138,7 +166,6 @@ int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 int eth_getenv_enetaddr_by_index(const char *base_name, int index,
 				 uchar *enetaddr);
 
-int usb_eth_initialize(bd_t *bi);
 int eth_init(bd_t *bis);			/* Initialize the device */
 int eth_send(void *packet, int length);	   /* Send a packet */
 
@@ -148,32 +175,7 @@ extern void (*push_packet)(void *packet, int length);
 #endif
 int eth_rx(void);			/* Check for received packets */
 void eth_halt(void);			/* stop SCC */
-char *eth_get_name(void);		/* get name of current device */
-
-/* Set active state */
-static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
-{
-	eth_get_dev()->state = ETH_STATE_ACTIVE;
-
-	return 0;
-}
-/* Set passive state */
-static inline __attribute__((always_inline)) void eth_halt_state_only(void)
-{
-	eth_get_dev()->state = ETH_STATE_PASSIVE;
-}
-
-/*
- * Set the hardware address for an ethernet interface based on 'eth%daddr'
- * environment variable (or just 'ethaddr' if eth_number is 0).
- * Args:
- *	base_name - base name for device (normally "eth")
- *	eth_number - value of %d (0 for first device of this type)
- * Returns:
- *	0 is success, non-zero is error status from driver.
- */
-int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
-		     int eth_number);
+const char *eth_get_name(void);		/* get name of current device */
 
 #ifdef CONFIG_MCAST_TFTP
 int eth_mcast_join(IPaddr_t mcast_addr, u8 join);
diff --git a/net/eth.c b/net/eth.c
index 65e8c77..84919e0 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -55,6 +55,14 @@ static inline int eth_setenv_enetaddr_by_index(const char *base_name, int index,
 	return eth_setenv_enetaddr(enetvar, enetaddr);
 }
 
+static void eth_env_init(void)
+{
+	const char *s;
+
+	s = getenv("bootfile");
+	if (s != NULL)
+		copy_filename(BootFile, s, sizeof(BootFile));
+}
 
 static int eth_mac_skip(int index)
 {
@@ -64,6 +72,8 @@ static int eth_mac_skip(int index)
 	return ((skip_state = getenv(enetvar)) != NULL);
 }
 
+static void eth_current_changed(void);
+
 /*
  * CPU and board-specific Ethernet initializations.  Aliased function
  * signals caller to move on
@@ -87,6 +97,11 @@ static unsigned int eth_rcv_current, eth_rcv_last;
 static struct eth_device *eth_devices;
 struct eth_device *eth_current;
 
+static void eth_set_current_to_next(void)
+{
+	eth_current = eth_current->next;
+}
+
 struct eth_device *eth_get_dev_by_name(const char *devname)
 {
 	struct eth_device *dev, *target_dev;
@@ -137,22 +152,6 @@ int eth_get_dev_index(void)
 	return eth_current->index;
 }
 
-static void eth_current_changed(void)
-{
-	char *act = getenv("ethact");
-	/* update current ethernet name */
-	if (eth_current) {
-		if (act == NULL || strcmp(act, eth_current->name) != 0)
-			setenv("ethact", eth_current->name);
-	}
-	/*
-	 * remove the variable completely if there is no active
-	 * interface
-	 */
-	else if (act != NULL)
-		setenv("ethact", NULL);
-}
-
 int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		   int eth_number)
 {
@@ -251,14 +250,6 @@ int eth_unregister(struct eth_device *dev)
 	return 0;
 }
 
-static void eth_env_init(bd_t *bis)
-{
-	const char *s;
-
-	if ((s = getenv("bootfile")) != NULL)
-		copy_filename(BootFile, s, sizeof(BootFile));
-}
-
 int eth_initialize(bd_t *bis)
 {
 	int num_devices = 0;
@@ -274,7 +265,7 @@ int eth_initialize(bd_t *bis)
 	phy_init();
 #endif
 
-	eth_env_init(bis);
+	eth_env_init();
 
 	/*
 	 * If board-specific initialization exists, call it.
@@ -479,6 +470,22 @@ int eth_receive(void *packet, int length)
 }
 #endif /* CONFIG_API */
 
+static void eth_current_changed(void)
+{
+	char *act = getenv("ethact");
+	/* update current ethernet name */
+	if (eth_get_dev()) {
+		if (act == NULL || strcmp(act, eth_get_name()) != 0)
+			setenv("ethact", eth_get_name());
+	}
+	/*
+	 * remove the variable completely if there is no active
+	 * interface
+	 */
+	else if (act != NULL)
+		setenv("ethact", NULL);
+}
+
 void eth_try_another(int first_restart)
 {
 	static struct eth_device *first_failed;
@@ -492,17 +499,17 @@ void eth_try_another(int first_restart)
 	if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
 		return;
 
-	if (!eth_current)
+	if (!eth_get_dev())
 		return;
 
 	if (first_restart)
-		first_failed = eth_current;
+		first_failed = eth_get_dev();
 
-	eth_current = eth_current->next;
+	eth_set_current_to_next();
 
 	eth_current_changed();
 
-	if (first_failed == eth_current)
+	if (first_failed == eth_get_dev())
 		NetRestartWrap = 1;
 }
 
@@ -513,7 +520,7 @@ void eth_set_current(void)
 	struct eth_device *old_current;
 	int	env_id;
 
-	if (!eth_current)	/* XXX no current */
+	if (!eth_get_dev())	/* XXX no current */
 		return;
 
 	env_id = get_env_id();
@@ -522,18 +529,18 @@ void eth_set_current(void)
 		env_changed_id = env_id;
 	}
 	if (act != NULL) {
-		old_current = eth_current;
+		old_current = eth_get_dev();
 		do {
-			if (strcmp(eth_current->name, act) == 0)
+			if (strcmp(eth_get_name(), act) == 0)
 				return;
-			eth_current = eth_current->next;
-		} while (old_current != eth_current);
+			eth_set_current_to_next();
+		} while (old_current != eth_get_dev());
 	}
 
 	eth_current_changed();
 }
 
-char *eth_get_name(void)
+const char *eth_get_name(void)
 {
-	return eth_current ? eth_current->name : "unknown";
+	return eth_get_dev() ? eth_get_dev()->name : "unknown";
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 07/27] net: Change return codes from net/eth.c to use errorno constants
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (5 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 06/27] net: Refactor in preparation for driver model Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:04               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 08/27] net: Use int instead of u8 for boolean flag Joe Hershberger
                               ` (19 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

Many functions returned -1 previously. Change them to return appropriate error
codes.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reported-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 net/eth.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/net/eth.c b/net/eth.c
index 84919e0..9ad15cd 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -227,7 +227,7 @@ int eth_unregister(struct eth_device *dev)
 
 	/* No device */
 	if (!eth_devices)
-		return -1;
+		return -ENODEV;
 
 	for (cur = eth_devices; cur->next != eth_devices && cur->next != dev;
 	     cur = cur->next)
@@ -235,7 +235,7 @@ int eth_unregister(struct eth_device *dev)
 
 	/* Device not found */
 	if (cur->next != dev)
-		return -1;
+		return -ENODEV;
 
 	cur->next = dev->next;
 
@@ -368,7 +368,7 @@ int eth_init(bd_t *bis)
 
 	if (!eth_current) {
 		puts("No ethernet found.\n");
-		return -1;
+		return -ENODEV;
 	}
 
 	/* Sync environment with network devices */
@@ -397,7 +397,7 @@ int eth_init(bd_t *bis)
 		eth_try_another(0);
 	} while (old_current != eth_current);
 
-	return -1;
+	return -ETIMEDOUT;
 }
 
 void eth_halt(void)
@@ -413,7 +413,7 @@ void eth_halt(void)
 int eth_send(void *packet, int length)
 {
 	if (!eth_current)
-		return -1;
+		return -ENODEV;
 
 	return eth_current->send(eth_current, packet, length);
 }
@@ -421,7 +421,7 @@ int eth_send(void *packet, int length)
 int eth_rx(void)
 {
 	if (!eth_current)
-		return -1;
+		return -ENODEV;
 
 	return eth_current->recv(eth_current);
 }
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 08/27] net: Use int instead of u8 for boolean flag
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (6 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 07/27] net: Change return codes from net/eth.c to use errorno constants Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:04               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 09/27] net: Remove the bd* parameter from net stack functions Joe Hershberger
                               ` (18 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

On some archs masking the parameter is inefficient, so don't use u8.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reported-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 include/net.h | 2 +-
 net/eth.c     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/net.h b/include/net.h
index fdf6860..cec5612 100644
--- a/include/net.h
+++ b/include/net.h
@@ -178,7 +178,7 @@ void eth_halt(void);			/* stop SCC */
 const char *eth_get_name(void);		/* get name of current device */
 
 #ifdef CONFIG_MCAST_TFTP
-int eth_mcast_join(IPaddr_t mcast_addr, u8 join);
+int eth_mcast_join(IPaddr_t mcast_addr, int join);
 u32 ether_crc(size_t len, unsigned char const *p);
 #endif
 
diff --git a/net/eth.c b/net/eth.c
index 9ad15cd..b86994e 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -321,7 +321,7 @@ int eth_initialize(bd_t *bis)
  * mcast_addr: multicast ipaddr from which multicast Mac is made
  * join: 1=join, 0=leave.
  */
-int eth_mcast_join(IPaddr_t mcast_ip, u8 join)
+int eth_mcast_join(IPaddr_t mcast_ip, int join)
 {
 	u8 mcast_mac[6];
 	if (!eth_current || !eth_current->mcast)
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 09/27] net: Remove the bd* parameter from net stack functions
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (7 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 08/27] net: Use int instead of u8 for boolean flag Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:04               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 10/27] net: Make netretry actually do something Joe Hershberger
                               ` (17 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

This value is not used by the network stack and is available in the
global data, so stop passing it around.  For the one legacy function
that still expects it (init op on old Ethernet drivers) pass in the
global pointer version directly to avoid changing that interface.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reported-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7:
-Fixed compile error in 4xx_enet.c

Changes in v6:
-Fix compile errors for other boards due to removed parameters

Changes in v5: None
Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 api/api_net.c                             |  2 +-
 arch/arm/lib/board.c                      |  2 +-
 arch/avr32/lib/board.c                    |  2 +-
 arch/m68k/lib/board.c                     |  4 ++--
 arch/nds32/lib/board.c                    |  2 +-
 arch/openrisc/lib/board.c                 |  2 +-
 arch/powerpc/lib/board.c                  |  2 +-
 arch/sh/lib/board.c                       |  2 +-
 arch/sparc/lib/board.c                    |  2 +-
 board/BuS/eb_cpux9k2/cpux9k2.c            |  2 +-
 board/BuS/vl_ma2sc/vl_ma2sc.c             |  2 +-
 board/atmel/at91sam9261ek/at91sam9261ek.c |  2 +-
 board/egnite/ethernut5/ethernut5.c        |  2 +-
 board/ronetix/pm9261/pm9261.c             |  2 +-
 board/ronetix/pm9g45/pm9g45.c             |  2 +-
 common/board_r.c                          |  2 +-
 common/spl/spl_net.c                      |  2 +-
 drivers/net/4xx_enet.c                    |  5 +++--
 drivers/net/netconsole.c                  |  4 ++--
 include/net.h                             |  6 +++---
 net/eth.c                                 | 12 +++++++-----
 net/net.c                                 |  7 +++----
 22 files changed, 36 insertions(+), 34 deletions(-)

diff --git a/api/api_net.c b/api/api_net.c
index 7b3805e..04e4f4a 100644
--- a/api/api_net.c
+++ b/api/api_net.c
@@ -37,7 +37,7 @@ int dev_open_net(void *cookie)
 	if (!dev_valid_net(cookie))
 		return API_ENODEV;
 
-	if (eth_init(gd->bd) < 0)
+	if (eth_init() < 0)
 		return API_EIO;
 
 	return 0;
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
index f606255..37ea6e9 100644
--- a/arch/arm/lib/board.c
+++ b/arch/arm/lib/board.c
@@ -644,7 +644,7 @@ void board_init_r(gd_t *id, ulong dest_addr)
 #endif
 #if defined(CONFIG_CMD_NET)
 	puts("Net:   ");
-	eth_initialize(gd->bd);
+	eth_initialize();
 #if defined(CONFIG_RESET_PHY_R)
 	debug("Reset Ethernet PHY\n");
 	reset_phy();
diff --git a/arch/avr32/lib/board.c b/arch/avr32/lib/board.c
index 99aa96e..aacfcbf 100644
--- a/arch/avr32/lib/board.c
+++ b/arch/avr32/lib/board.c
@@ -244,7 +244,7 @@ void board_init_r(gd_t *new_gd, ulong dest_addr)
 #endif
 #if defined(CONFIG_CMD_NET)
 	puts("Net:   ");
-	eth_initialize(gd->bd);
+	eth_initialize();
 #endif
 
 #ifdef CONFIG_GENERIC_ATMEL_MCI
diff --git a/arch/m68k/lib/board.c b/arch/m68k/lib/board.c
index 9caff73..c54a3f7 100644
--- a/arch/m68k/lib/board.c
+++ b/arch/m68k/lib/board.c
@@ -566,10 +566,10 @@ void board_init_r (gd_t *id, ulong dest_addr)
 #if defined(CONFIG_CMD_NET)
 	WATCHDOG_RESET();
 #if defined(FEC_ENET)
-	eth_init(bd);
+	eth_init();
 #endif
 	puts ("Net:   ");
-	eth_initialize (bd);
+	eth_initialize();
 #endif
 
 #ifdef CONFIG_POST
diff --git a/arch/nds32/lib/board.c b/arch/nds32/lib/board.c
index 4c06a48..24a09bc 100644
--- a/arch/nds32/lib/board.c
+++ b/arch/nds32/lib/board.c
@@ -383,7 +383,7 @@ void board_init_r(gd_t *id, ulong dest_addr)
 #if defined(CONFIG_CMD_NET)
 	puts("Net:   ");
 
-	eth_initialize(gd->bd);
+	eth_initialize();
 #if defined(CONFIG_RESET_PHY_R)
 	debug("Reset Ethernet PHY\n");
 	reset_phy();
diff --git a/arch/openrisc/lib/board.c b/arch/openrisc/lib/board.c
index 2346685..c26cc8f 100644
--- a/arch/openrisc/lib/board.c
+++ b/arch/openrisc/lib/board.c
@@ -128,7 +128,7 @@ void board_init(void)
 
 #if defined(CONFIG_CMD_NET)
 	puts("NET:   ");
-	eth_initialize(bd);
+	eth_initialize();
 #endif
 
 	/* main_loop */
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
index 91645d3..5ea29cc 100644
--- a/arch/powerpc/lib/board.c
+++ b/arch/powerpc/lib/board.c
@@ -890,7 +890,7 @@ void board_init_r(gd_t *id, ulong dest_addr)
 #if defined(CONFIG_CMD_NET)
 	WATCHDOG_RESET();
 	puts("Net:   ");
-	eth_initialize(bd);
+	eth_initialize();
 #endif
 
 #if defined(CONFIG_CMD_NET) && defined(CONFIG_RESET_PHY_R)
diff --git a/arch/sh/lib/board.c b/arch/sh/lib/board.c
index 1eb7afb..6dad3c7 100644
--- a/arch/sh/lib/board.c
+++ b/arch/sh/lib/board.c
@@ -178,7 +178,7 @@ void sh_generic_init(void)
 #endif
 #if defined(CONFIG_CMD_NET)
 	puts("Net:   ");
-	eth_initialize(gd->bd);
+	eth_initialize();
 #endif /* CONFIG_CMD_NET */
 
 	while (1) {
diff --git a/arch/sparc/lib/board.c b/arch/sparc/lib/board.c
index b311a94..d2ac6bc 100644
--- a/arch/sparc/lib/board.c
+++ b/arch/sparc/lib/board.c
@@ -351,7 +351,7 @@ void board_init_f(ulong bootflag)
 #if defined(CONFIG_CMD_NET)
 	WATCHDOG_RESET();
 	puts("Net:   ");
-	eth_initialize(bd);
+	eth_initialize();
 #endif
 
 #if defined(CONFIG_CMD_NET) && defined(CONFIG_RESET_PHY_R)
diff --git a/board/BuS/eb_cpux9k2/cpux9k2.c b/board/BuS/eb_cpux9k2/cpux9k2.c
index 76ad7c4..3880a06 100644
--- a/board/BuS/eb_cpux9k2/cpux9k2.c
+++ b/board/BuS/eb_cpux9k2/cpux9k2.c
@@ -111,7 +111,7 @@ int misc_init_r(void)
 void reset_phy(void)
 {
 	udelay(10000);
-	eth_init(gd->bd);
+	eth_init();
 }
 #endif
 
diff --git a/board/BuS/vl_ma2sc/vl_ma2sc.c b/board/BuS/vl_ma2sc/vl_ma2sc.c
index da39c86..e4e1a85 100644
--- a/board/BuS/vl_ma2sc/vl_ma2sc.c
+++ b/board/BuS/vl_ma2sc/vl_ma2sc.c
@@ -280,7 +280,7 @@ void reset_phy(void)
 	 * Initialize ethernet HW addr prior to starting Linux,
 	 * needed for nfsroot
 	 */
-	eth_init(gd->bd);
+	eth_init();
 #endif
 }
 #endif
diff --git a/board/atmel/at91sam9261ek/at91sam9261ek.c b/board/atmel/at91sam9261ek/at91sam9261ek.c
index a301d72..5250474 100644
--- a/board/atmel/at91sam9261ek/at91sam9261ek.c
+++ b/board/atmel/at91sam9261ek/at91sam9261ek.c
@@ -275,7 +275,7 @@ void reset_phy(void)
 	 * Initialize ethernet HW addr prior to starting Linux,
 	 * needed for nfsroot
 	 */
-	eth_init(gd->bd);
+	eth_init();
 #endif
 }
 #endif
diff --git a/board/egnite/ethernut5/ethernut5.c b/board/egnite/ethernut5/ethernut5.c
index b45213c..67d3984 100644
--- a/board/egnite/ethernut5/ethernut5.c
+++ b/board/egnite/ethernut5/ethernut5.c
@@ -204,7 +204,7 @@ int board_eth_init(bd_t *bis)
 		miiphy_write(devname, 0, MII_BMCR, BMCR_RESET);
 	}
 	/* Sync environment with network devices, needed for nfsroot. */
-	return eth_init(gd->bd);
+	return eth_init();
 }
 #endif
 
diff --git a/board/ronetix/pm9261/pm9261.c b/board/ronetix/pm9261/pm9261.c
index 1f7679a..b96f745 100644
--- a/board/ronetix/pm9261/pm9261.c
+++ b/board/ronetix/pm9261/pm9261.c
@@ -288,7 +288,7 @@ void reset_phy(void)
 	 * Initialize ethernet HW addr prior to starting Linux,
 	 * needed for nfsroot
 	 */
-	eth_init(gd->bd);
+	eth_init();
 #endif
 }
 #endif
diff --git a/board/ronetix/pm9g45/pm9g45.c b/board/ronetix/pm9g45/pm9g45.c
index 15aa4ac..efc4133 100644
--- a/board/ronetix/pm9g45/pm9g45.c
+++ b/board/ronetix/pm9g45/pm9g45.c
@@ -166,7 +166,7 @@ void reset_phy(void)
 	 * Initialize ethernet HW addr prior to starting Linux,
 	 * needed for nfsroot
 	 */
-	eth_init(gd->bd);
+	eth_init();
 #endif
 }
 #endif
diff --git a/common/board_r.c b/common/board_r.c
index af0f274..b882d9b 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -585,7 +585,7 @@ static int initr_bbmii(void)
 static int initr_net(void)
 {
 	puts("Net:   ");
-	eth_initialize(gd->bd);
+	eth_initialize();
 #if defined(CONFIG_RESET_PHY_R)
 	debug("Reset Ethernet PHY\n");
 	reset_phy();
diff --git a/common/spl/spl_net.c b/common/spl/spl_net.c
index ff53705..af4952f 100644
--- a/common/spl/spl_net.c
+++ b/common/spl/spl_net.c
@@ -21,7 +21,7 @@ void spl_net_load_image(const char *device)
 	env_relocate();
 	setenv("autoload", "yes");
 	load_addr = CONFIG_SYS_TEXT_BASE - sizeof(struct image_header);
-	rv = eth_initialize(gd->bd);
+	rv = eth_initialize();
 	if (rv == 0) {
 		printf("No Ethernet devices found\n");
 		hang();
diff --git a/drivers/net/4xx_enet.c b/drivers/net/4xx_enet.c
index 381ec42..8023f3d 100644
--- a/drivers/net/4xx_enet.c
+++ b/drivers/net/4xx_enet.c
@@ -1728,10 +1728,11 @@ static void mal_err (struct eth_device *dev, unsigned long isr,
 	mtdcr (MAL0_RXDEIR, 0x80000000);
 
 #ifdef INFO_4XX_ENET
-	printf ("\nMAL error occured.... ISR = %lx UIC = = %lx	MAL_DEF = %lx  MAL_ERR= %lx \n", isr, uic, maldef, mal_errr);
+	printf("\nMAL error occured.... ISR = %lx UIC = = %lx	MAL_DEF = %lx  MAL_ERR= %lx\n",
+	       isr, uic, maldef, mal_errr);
 #endif
 
-	eth_init (hw_p->bis);	/* start again... */
+	eth_init();	/* start again... */
 }
 
 /*-----------------------------------------------------------------------------+
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 677c89f..87cea7a 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -193,11 +193,11 @@ static void nc_send_packet(const char *buf, int len)
 
 	if (eth->state != ETH_STATE_ACTIVE) {
 		if (eth_is_on_demand_init()) {
-			if (eth_init(gd->bd) < 0)
+			if (eth_init() < 0)
 				return;
 			eth_set_last_protocol(NETCONS);
 		} else
-			eth_init_state_only(gd->bd);
+			eth_init_state_only();
 
 		inited = 1;
 	}
diff --git a/include/net.h b/include/net.h
index cec5612..ae0f31a 100644
--- a/include/net.h
+++ b/include/net.h
@@ -119,7 +119,7 @@ static inline unsigned char *eth_get_ethaddr(void)
 }
 
 /* Set active state */
-static inline __attribute__((always_inline)) int eth_init_state_only(bd_t *bis)
+static inline __attribute__((always_inline)) int eth_init_state_only(void)
 {
 	eth_get_dev()->state = ETH_STATE_ACTIVE;
 
@@ -145,7 +145,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 
 int usb_eth_initialize(bd_t *bi);
 
-int eth_initialize(bd_t *bis);	/* Initialize network subsystem */
+int eth_initialize(void);		/* Initialize network subsystem */
 void eth_try_another(int first_restart);	/* Change the device */
 void eth_set_current(void);		/* set nterface to ethcur var */
 
@@ -166,7 +166,7 @@ int eth_setenv_enetaddr(char *name, const uchar *enetaddr);
 int eth_getenv_enetaddr_by_index(const char *base_name, int index,
 				 uchar *enetaddr);
 
-int eth_init(bd_t *bis);			/* Initialize the device */
+int eth_init(void);			/* Initialize the device */
 int eth_send(void *packet, int length);	   /* Send a packet */
 
 #ifdef CONFIG_API
diff --git a/net/eth.c b/net/eth.c
index b86994e..66ecb79 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -12,6 +12,8 @@
 #include <phy.h>
 #include <asm/errno.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 void eth_parse_enetaddr(const char *addr, uchar *enetaddr)
 {
 	char *end;
@@ -250,7 +252,7 @@ int eth_unregister(struct eth_device *dev)
 	return 0;
 }
 
-int eth_initialize(bd_t *bis)
+int eth_initialize(void)
 {
 	int num_devices = 0;
 	eth_devices = NULL;
@@ -272,10 +274,10 @@ int eth_initialize(bd_t *bis)
 	 * If not, call a CPU-specific one
 	 */
 	if (board_eth_init != __def_eth_init) {
-		if (board_eth_init(bis) < 0)
+		if (board_eth_init(gd->bd) < 0)
 			printf("Board Net Initialization Failed\n");
 	} else if (cpu_eth_init != __def_eth_init) {
-		if (cpu_eth_init(bis) < 0)
+		if (cpu_eth_init(gd->bd) < 0)
 			printf("CPU Net Initialization Failed\n");
 	} else
 		printf("Net Initialization Skipped\n");
@@ -362,7 +364,7 @@ u32 ether_crc(size_t len, unsigned char const *p)
 #endif
 
 
-int eth_init(bd_t *bis)
+int eth_init(void)
 {
 	struct eth_device *old_current, *dev;
 
@@ -387,7 +389,7 @@ int eth_init(bd_t *bis)
 	do {
 		debug("Trying %s\n", eth_current->name);
 
-		if (eth_current->init(eth_current, bis) >= 0) {
+		if (eth_current->init(eth_current, gd->bd) >= 0) {
 			eth_current->state = ETH_STATE_ACTIVE;
 
 			return 0;
diff --git a/net/net.c b/net/net.c
index 4b3c90e..e5ab07c 100644
--- a/net/net.c
+++ b/net/net.c
@@ -324,7 +324,6 @@ void net_init(void)
 
 int NetLoop(enum proto_t protocol)
 {
-	bd_t *bd = gd->bd;
 	int ret = -1;
 
 	NetRestarted = 0;
@@ -337,12 +336,12 @@ int NetLoop(enum proto_t protocol)
 	if (eth_is_on_demand_init() || protocol != NETCONS) {
 		eth_halt();
 		eth_set_current();
-		if (eth_init(bd) < 0) {
+		if (eth_init() < 0) {
 			eth_halt();
 			return -1;
 		}
 	} else
-		eth_init_state_only(bd);
+		eth_init_state_only();
 
 restart:
 #ifdef CONFIG_USB_KEYBOARD
@@ -618,7 +617,7 @@ void NetStartAgain(void)
 #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
 	eth_try_another(!NetRestarted);
 #endif
-	eth_init(gd->bd);
+	eth_init();
 	if (NetRestartWrap) {
 		NetRestartWrap = 0;
 		if (NetDevExists) {
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 10/27] net: Make netretry actually do something
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (8 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 09/27] net: Remove the bd* parameter from net stack functions Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:04               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 11/27] net: Access mapped physmem in net functions Joe Hershberger
                               ` (16 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

netretry previously would only retry in one specific case (your MAC
address is not set) and no other. This is basically useless. In the DM
implementation for eth it turns this into a completely useless case
since an un-configured MAC address results in not even entering the
NetLoop. The behavior is now changed to retry any failed command
(rotating through the eth adapters if ethrotate != no).

It also defaulted to retry forever. It is now changed to default to not
retry

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 net/net.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/net/net.c b/net/net.c
index e5ab07c..37b4aab 100644
--- a/net/net.c
+++ b/net/net.c
@@ -527,6 +527,8 @@ restart:
 			(*x)();
 		}
 
+		if (net_state == NETLOOP_FAIL)
+			NetStartAgain();
 
 		switch (net_state) {
 
@@ -602,8 +604,10 @@ void NetStartAgain(void)
 			retrycnt = 1;
 		else
 			retrycnt = simple_strtoul(nretry, NULL, 0);
-	} else
-		retry_forever = 1;
+	} else {
+		retrycnt = 0;
+		retry_forever = 0;
+	}
 
 	if ((!retry_forever) && (NetTryCount >= retrycnt)) {
 		eth_halt();
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 11/27] net: Access mapped physmem in net functions
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (9 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 10/27] net: Make netretry actually do something Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:05               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 12/27] cmd: net: Clean up return codes Joe Hershberger
                               ` (15 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

Previously the net functions would access memory assuming physmem did
not need to be mapped.  In sandbox, that's not the case.

Now we map the physmem specified by the user in loadaddr to the buffer
that represents that space.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5:
-Include new mapmem.h header
-Unmap memory for consistency

Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 net/nfs.c  | 6 +++++-
 net/tftp.c | 6 +++++-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/net/nfs.c b/net/nfs.c
index 381b75f..8e05ae5 100644
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -26,6 +26,7 @@
 #include <command.h>
 #include <net.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include "nfs.h"
 #include "bootp.h"
 
@@ -93,7 +94,10 @@ store_block(uchar *src, unsigned offset, unsigned len)
 	} else
 #endif /* CONFIG_SYS_DIRECT_FLASH_NFS */
 	{
-		(void)memcpy((void *)(load_addr + offset), src, len);
+		void *ptr = map_sysmem(load_addr + offset, len);
+
+		memcpy(ptr, src, len);
+		unmap_sysmem(ptr);
 	}
 
 	if (NetBootFileXferSize < (offset+len))
diff --git a/net/tftp.c b/net/tftp.c
index 0a2c533..51c67be 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <mapmem.h>
 #include <net.h>
 #include "tftp.h"
 #include "bootp.h"
@@ -184,7 +185,10 @@ store_block(int block, uchar *src, unsigned len)
 	} else
 #endif /* CONFIG_SYS_DIRECT_FLASH_TFTP */
 	{
-		(void)memcpy((void *)(load_addr + offset), src, len);
+		void *ptr = map_sysmem(load_addr + offset, len);
+
+		memcpy(ptr, src, len);
+		unmap_sysmem(ptr);
 	}
 #ifdef CONFIG_MCAST_TFTP
 	if (Multicast)
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 12/27] cmd: net: Clean up return codes
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (10 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 11/27] net: Access mapped physmem in net functions Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:05               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 13/27] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
                               ` (14 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

The return codes in common/cmd_net.c had a number of inconsistencies.
Update them to all use the enum from command.h

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5:
-New to v5

Changes in v4: None
Changes in v3: None
Changes in v2: None

 common/cmd_net.c | 45 +++++++++++++++++++++------------------------
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/common/cmd_net.c b/common/cmd_net.c
index 09489d4..3f52edc 100644
--- a/common/cmd_net.c
+++ b/common/cmd_net.c
@@ -44,10 +44,7 @@ U_BOOT_CMD(
 #ifdef CONFIG_CMD_TFTPPUT
 int do_tftpput(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	int ret;
-
-	ret = netboot_common(TFTPPUT, cmdtp, argc, argv);
-	return ret;
+	return netboot_common(TFTPPUT, cmdtp, argc, argv);
 }
 
 U_BOOT_CMD(
@@ -217,7 +214,7 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 		if (strict_strtoul(argv[1], 16, &save_addr) < 0 ||
 			strict_strtoul(argv[2], 16, &save_size) < 0) {
 			printf("Invalid address/size\n");
-			return cmd_usage(cmdtp);
+			return CMD_RET_USAGE;
 		}
 		copy_filename(BootFile, argv[3], sizeof(BootFile));
 		break;
@@ -230,7 +227,7 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 
 	if ((size = NetLoop(proto)) < 0) {
 		bootstage_error(BOOTSTAGE_ID_NET_NETLOOP_OK);
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 	bootstage_mark(BOOTSTAGE_ID_NET_NETLOOP_OK);
 
@@ -240,7 +237,7 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 	/* done if no file was loaded (no errors though) */
 	if (size == 0) {
 		bootstage_error(BOOTSTAGE_ID_NET_LOADED);
-		return 0;
+		return CMD_RET_SUCCESS;
 	}
 
 	/* flush cache */
@@ -250,10 +247,10 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 
 	rcode = bootm_maybe_autostart(cmdtp, argv[0]);
 
-	if (rcode < 0)
-		bootstage_error(BOOTSTAGE_ID_NET_DONE_ERR);
-	else
+	if (rcode == CMD_RET_SUCCESS)
 		bootstage_mark(BOOTSTAGE_ID_NET_DONE);
+	else
+		bootstage_error(BOOTSTAGE_ID_NET_DONE_ERR);
 	return rcode;
 }
 
@@ -261,7 +258,7 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 static int do_ping(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	if (argc < 2)
-		return -1;
+		return CMD_RET_USAGE;
 
 	NetPingIP = string_to_ip(argv[1]);
 	if (NetPingIP == 0)
@@ -269,12 +266,12 @@ static int do_ping(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 	if (NetLoop(PING) < 0) {
 		printf("ping failed; host %s is not alive\n", argv[1]);
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 
 	printf("host %s is alive\n", argv[1]);
 
-	return 0;
+	return CMD_RET_SUCCESS;
 }
 
 U_BOOT_CMD(
@@ -313,12 +310,12 @@ int do_cdp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	r = NetLoop(CDP);
 	if (r < 0) {
 		printf("cdp failed; perhaps not a CISCO switch?\n");
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 
 	cdp_update_env();
 
-	return 0;
+	return CMD_RET_SUCCESS;
 }
 
 U_BOOT_CMD(
@@ -337,13 +334,13 @@ int do_sntp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		NetNtpServerIP = getenv_IPaddr("ntpserverip");
 		if (NetNtpServerIP == 0) {
 			printf("ntpserverip not set\n");
-			return (1);
+			return CMD_RET_FAILURE;
 		}
 	} else {
 		NetNtpServerIP = string_to_ip(argv[1]);
 		if (NetNtpServerIP == 0) {
 			printf("Bad NTP server IP address\n");
-			return (1);
+			return CMD_RET_FAILURE;
 		}
 	}
 
@@ -356,10 +353,10 @@ int do_sntp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	if (NetLoop(SNTP) < 0) {
 		printf("SNTP failed: host %pI4 not responding\n",
 			&NetNtpServerIP);
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 
-	return 0;
+	return CMD_RET_SUCCESS;
 }
 
 U_BOOT_CMD(
@@ -389,7 +386,7 @@ int do_dns(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	 */
 	if (strlen(argv[1]) >= 255) {
 		printf("dns error: hostname too long\n");
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 
 	NetDNSResolve = argv[1];
@@ -401,10 +398,10 @@ int do_dns(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 	if (NetLoop(DNS) < 0) {
 		printf("dns lookup of %s failed, check setup\n", argv[1]);
-		return 1;
+		return CMD_RET_FAILURE;
 	}
 
-	return 0;
+	return CMD_RET_SUCCESS;
 }
 
 U_BOOT_CMD(
@@ -422,7 +419,7 @@ static int do_link_local(cmd_tbl_t *cmdtp, int flag, int argc,
 	char tmp[22];
 
 	if (NetLoop(LINKLOCAL) < 0)
-		return 1;
+		return CMD_RET_FAILURE;
 
 	NetOurGatewayIP = 0;
 	ip_to_string(NetOurGatewayIP, tmp);
@@ -435,7 +432,7 @@ static int do_link_local(cmd_tbl_t *cmdtp, int flag, int argc,
 	setenv("ipaddr", tmp);
 	setenv("llipaddr", tmp); /* store this for next time */
 
-	return 0;
+	return CMD_RET_SUCCESS;
 }
 
 U_BOOT_CMD(
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 13/27] dm: eth: Add basic driver model support to Ethernet stack
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (11 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 12/27] cmd: net: Clean up return codes Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:05               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 14/27] net: Clean up network stack names used in DM drivers Joe Hershberger
                               ` (13 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

First just add support for MAC drivers.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5:
-Add a note to doc/README.drivers.eth about its obsolescence
-Expanded the Kconfig help
-Moved dm/ header
-Use local var for priv in eth_get_dev()

Changes in v4:
--Don't prevent eth_initialize on driver model
--If current == NULL, always check if there is a device available in eth_get_dev
--Include ethprime handling in eth_initialize
--Look up MAC address in post-probe
--Move env init call from uclass init to eth_initialize
--Print the alias in eth_initialize
--Use eth_initialize to probe all devices and write_hwaddr
-Add a helper function for eth_uclass_priv
-Add documentation to the structures
-Add eth_get_ops helper
-Change -1 returns to error constants
-Change puts to printf
-Redo the seq / probe implementation
-Remove bd_t *bis from dm eth_ops init function
-Remove checks for driver==NULL
-Remove priv pointer in per-device priv struct (drivers already get their own directly from DM)
-Rename halt() to stop() in ops
-Rename init() to start() in ops
-Stop handling selecting a new "current" in pre-unbind as it will now work itself out by clearing the pointer

Changes in v3:
--Fail init if not activated
--Fail probe if ethaddr not set
-Allow current eth dev to be NULL
-Correct failure chaining from bind to probe to init
-Correct the pre_unbind logic
-Fixed blank line formatting for variable declaration
-Update ethaddr from env unconditionally on init
-Use set current to select the current device regardless of the previous selection

Changes in v2:
-Cause an invalid name to fail binding
-Changed eth_uclass_priv local var names to be uc_priv
-Move the hwaddr to platdata so that its memory is allocated at bind when we need it
-Prevent device from being probed before used by a command (i.e. before eth_init()).
-Rebase on top of dm/master
-Removed extra parentheses
-Stop maintaining our own index and use DM seq now that it works for our needs
-Update error codes
-Updated comments

 common/cmd_bdinfo.c    |   2 +
 doc/README.drivers.eth |   6 +
 drivers/net/Kconfig    |   9 ++
 include/dm/uclass-id.h |   1 +
 include/net.h          |  52 ++++++++
 net/eth.c              | 346 ++++++++++++++++++++++++++++++++++++++++++++++++-
 6 files changed, 410 insertions(+), 6 deletions(-)

diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
index aa81da2..b4cce25 100644
--- a/common/cmd_bdinfo.c
+++ b/common/cmd_bdinfo.c
@@ -34,6 +34,7 @@ static void print_eth(int idx)
 	printf("%-12s= %s\n", name, val);
 }
 
+#ifndef CONFIG_DM_ETH
 __maybe_unused
 static void print_eths(void)
 {
@@ -52,6 +53,7 @@ static void print_eths(void)
 	printf("current eth = %s\n", eth_get_name());
 	printf("ip_addr     = %s\n", getenv("ipaddr"));
 }
+#endif
 
 __maybe_unused
 static void print_lnum(const char *name, unsigned long long value)
diff --git a/doc/README.drivers.eth b/doc/README.drivers.eth
index eb83038..98728bc 100644
--- a/doc/README.drivers.eth
+++ b/doc/README.drivers.eth
@@ -1,3 +1,9 @@
+!!! WARNING !!!
+
+This guide describes to the old way of doing things. No new Ethernet drivers
+should be implemented this way. All new drivers should be written against the
+U-Boot core driver model. See doc/driver-model/README.txt
+
 -----------------------
  Ethernet Driver Guide
 -----------------------
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index e69de29..94cf099 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -0,0 +1,9 @@
+config DM_ETH
+	bool "Enable Driver Model for Ethernet drivers"
+	depends on DM
+	help
+	  Enable driver model for Ethernet.
+
+	  The eth_*() interface will be implemented by the UC_ETH class
+	  This is currently implemented in net/eth.c
+	  Look in include/net.h for details.
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 91bb90d..ad96682 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -34,6 +34,7 @@ enum uclass_id {
 	UCLASS_I2C_GENERIC,	/* Generic I2C device */
 	UCLASS_I2C_EEPROM,	/* I2C EEPROM device */
 	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
+	UCLASS_ETH,		/* Ethernet device */
 
 	UCLASS_COUNT,
 	UCLASS_INVALID = -1,
diff --git a/include/net.h b/include/net.h
index ae0f31a..fff82cb 100644
--- a/include/net.h
+++ b/include/net.h
@@ -78,6 +78,57 @@ enum eth_state_t {
 	ETH_STATE_ACTIVE
 };
 
+#ifdef CONFIG_DM_ETH
+/**
+ * struct eth_pdata - Platform data for Ethernet MAC controllers
+ *
+ * @iobase: The base address of the hardware registers
+ * @enetaddr: The Ethernet MAC address that is loaded from EEPROM or env
+ */
+struct eth_pdata {
+	phys_addr_t iobase;
+	unsigned char enetaddr[6];
+};
+
+/**
+ * struct eth_ops - functions of Ethernet MAC controllers
+ *
+ * start: Prepare the hardware to send and receive packets
+ * send: Send the bytes passed in "packet" as a packet on the wire
+ * recv: Check if the hardware received a packet. Call the network stack if so
+ * stop: Stop the hardware from looking for packets - may be called even if
+ *	 state == PASSIVE
+ * mcast: Join or leave a multicast group (for TFTP) - optional
+ * write_hwaddr: Write a MAC address to the hardware (used to pass it to Linux
+ *		 on some platforms like ARM). This function expects the
+ *		 eth_pdata::enetaddr field to be populated - optional
+ * read_rom_hwaddr: Some devices have a backup of the MAC address stored in a
+ *		    ROM on the board. This is how the driver should expose it
+ *		    to the network stack. This function should fill in the
+ *		    eth_pdata::enetaddr field - optional
+ */
+struct eth_ops {
+	int (*start)(struct udevice *dev);
+	int (*send)(struct udevice *dev, void *packet, int length);
+	int (*recv)(struct udevice *dev);
+	void (*stop)(struct udevice *dev);
+#ifdef CONFIG_MCAST_TFTP
+	int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
+#endif
+	int (*write_hwaddr)(struct udevice *dev);
+	int (*read_rom_hwaddr)(struct udevice *dev);
+};
+
+#define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
+
+struct udevice *eth_get_dev(void); /* get the current device */
+unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
+/* Used only when NetConsole is enabled */
+int eth_init_state_only(void); /* Set active state */
+void eth_halt_state_only(void); /* Set passive state */
+#endif
+
+#ifndef CONFIG_DM_ETH
 struct eth_device {
 	char name[16];
 	unsigned char enetaddr[6];
@@ -144,6 +195,7 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		     int eth_number);
 
 int usb_eth_initialize(bd_t *bi);
+#endif
 
 int eth_initialize(void);		/* Initialize network subsystem */
 void eth_try_another(int first_restart);	/* Change the device */
diff --git a/net/eth.c b/net/eth.c
index 66ecb79..1abf027 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -1,16 +1,19 @@
 /*
- * (C) Copyright 2001-2010
+ * (C) Copyright 2001-2015
  * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ * Joe Hershberger, National Instruments
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #include <common.h>
 #include <command.h>
+#include <dm.h>
 #include <net.h>
 #include <miiphy.h>
 #include <phy.h>
 #include <asm/errno.h>
+#include <dm/device-internal.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -76,6 +79,339 @@ static int eth_mac_skip(int index)
 
 static void eth_current_changed(void);
 
+#ifdef CONFIG_DM_ETH
+/**
+ * struct eth_device_priv - private structure for each Ethernet device
+ *
+ * @state: The state of the Ethernet MAC driver (defined by enum eth_state_t)
+ */
+struct eth_device_priv {
+	enum eth_state_t state;
+};
+
+/**
+ * struct eth_uclass_priv - The structure attached to the uclass itself
+ *
+ * @current: The Ethernet device that the network functions are using
+ */
+struct eth_uclass_priv {
+	struct udevice *current;
+};
+
+static struct eth_uclass_priv *eth_get_uclass_priv(void)
+{
+	struct uclass *uc;
+
+	uclass_get(UCLASS_ETH, &uc);
+	assert(uc);
+	return uc->priv;
+}
+
+static void eth_set_current_to_next(void)
+{
+	struct eth_uclass_priv *uc_priv;
+
+	uc_priv = eth_get_uclass_priv();
+	if (uc_priv->current)
+		uclass_next_device(&uc_priv->current);
+	if (!uc_priv->current)
+		uclass_first_device(UCLASS_ETH, &uc_priv->current);
+}
+
+struct udevice *eth_get_dev(void)
+{
+	struct eth_uclass_priv *uc_priv;
+
+	uc_priv = eth_get_uclass_priv();
+	if (!uc_priv->current)
+		uclass_first_device(UCLASS_ETH,
+				    &uc_priv->current);
+	return uc_priv->current;
+}
+
+static void eth_set_dev(struct udevice *dev)
+{
+	device_probe(dev);
+	eth_get_uclass_priv()->current = dev;
+}
+
+unsigned char *eth_get_ethaddr(void)
+{
+	struct eth_pdata *pdata;
+
+	if (eth_get_dev()) {
+		pdata = eth_get_dev()->platdata;
+		return pdata->enetaddr;
+	}
+
+	return NULL;
+}
+
+/* Set active state without calling start on the driver */
+int eth_init_state_only(void)
+{
+	struct udevice *current;
+	struct eth_device_priv *priv;
+
+	current = eth_get_dev();
+	if (!current || !device_active(current))
+		return -EINVAL;
+
+	priv = current->uclass_priv;
+	priv->state = ETH_STATE_ACTIVE;
+
+	return 0;
+}
+
+/* Set passive state without calling stop on the driver */
+void eth_halt_state_only(void)
+{
+	struct udevice *current;
+	struct eth_device_priv *priv;
+
+	current = eth_get_dev();
+	if (!current || !device_active(current))
+		return;
+
+	priv = current->uclass_priv;
+	priv->state = ETH_STATE_PASSIVE;
+}
+
+int eth_get_dev_index(void)
+{
+	if (eth_get_dev())
+		return eth_get_dev()->seq;
+	return -1;
+}
+
+int eth_init(void)
+{
+	struct udevice *current;
+	struct udevice *old_current;
+
+	current = eth_get_dev();
+	if (!current) {
+		printf("No ethernet found.\n");
+		return -ENODEV;
+	}
+
+	old_current = current;
+	do {
+		debug("Trying %s\n", current->name);
+
+		if (device_active(current)) {
+			uchar env_enetaddr[6];
+			struct eth_pdata *pdata = current->platdata;
+
+			/* Sync environment with network device */
+			if (eth_getenv_enetaddr_by_index("eth", current->seq,
+							 env_enetaddr))
+				memcpy(pdata->enetaddr, env_enetaddr, 6);
+			else
+				memset(pdata->enetaddr, 0, 6);
+
+			if (eth_get_ops(current)->start(current) >= 0) {
+				struct eth_device_priv *priv =
+					current->uclass_priv;
+
+				priv->state = ETH_STATE_ACTIVE;
+				return 0;
+			}
+		}
+		debug("FAIL\n");
+
+		/* This will ensure the new "current" attempted to probe */
+		eth_try_another(0);
+		current = eth_get_dev();
+	} while (old_current != current);
+
+	return -ENODEV;
+}
+
+void eth_halt(void)
+{
+	struct udevice *current;
+	struct eth_device_priv *priv;
+
+	current = eth_get_dev();
+	if (!current || !device_active(current))
+		return;
+
+	eth_get_ops(current)->stop(current);
+	priv = current->uclass_priv;
+	priv->state = ETH_STATE_PASSIVE;
+}
+
+int eth_send(void *packet, int length)
+{
+	struct udevice *current;
+
+	current = eth_get_dev();
+	if (!current)
+		return -ENODEV;
+
+	if (!device_active(current))
+		return -EINVAL;
+
+	return eth_get_ops(current)->send(current, packet, length);
+}
+
+int eth_rx(void)
+{
+	struct udevice *current;
+
+	current = eth_get_dev();
+	if (!current)
+		return -ENODEV;
+
+	if (!device_active(current))
+		return -EINVAL;
+
+	return eth_get_ops(current)->recv(current);
+}
+
+static int eth_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev->platdata;
+	int ret = 0;
+
+	if (!dev || !device_active(dev))
+		return -EINVAL;
+
+	/* seq is valid since the device is active */
+	if (eth_get_ops(dev)->write_hwaddr && !eth_mac_skip(dev->seq)) {
+		if (!is_valid_ether_addr(pdata->enetaddr)) {
+			printf("\nError: %s address %pM illegal value\n",
+			       dev->name, pdata->enetaddr);
+			return -EINVAL;
+		}
+
+		ret = eth_get_ops(dev)->write_hwaddr(dev);
+		if (ret)
+			printf("\nWarning: %s failed to set MAC address\n",
+			       dev->name);
+	}
+
+	return ret;
+}
+
+int eth_initialize(void)
+{
+	int num_devices = 0;
+	struct udevice *dev;
+
+	bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
+	eth_env_init();
+
+	/*
+	 * Devices need to write the hwaddr even if not started so that Linux
+	 * will have access to the hwaddr that u-boot stored for the device.
+	 * This is accomplished by attempting to probe each device and calling
+	 * their write_hwaddr() operation.
+	 */
+	uclass_first_device(UCLASS_ETH, &dev);
+	if (!dev) {
+		printf("No ethernet found.\n");
+		bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
+	} else {
+		bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
+		do {
+			if (num_devices)
+				printf(", ");
+
+			printf("eth%d: %s", dev->seq, dev->name);
+
+			eth_write_hwaddr(dev);
+
+			uclass_next_device(&dev);
+			num_devices++;
+		} while (dev);
+
+		putc('\n');
+	}
+
+	return num_devices;
+}
+
+static int eth_post_bind(struct udevice *dev)
+{
+	if (strchr(dev->name, ' ')) {
+		printf("\nError: eth device name \"%s\" has a space!\n",
+		       dev->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int eth_pre_unbind(struct udevice *dev)
+{
+	/* Don't hang onto a pointer that is going away */
+	if (dev == eth_get_uclass_priv()->current)
+		eth_set_dev(NULL);
+
+	return 0;
+}
+
+static int eth_post_probe(struct udevice *dev)
+{
+	struct eth_device_priv *priv = dev->uclass_priv;
+	struct eth_pdata *pdata = dev->platdata;
+	unsigned char env_enetaddr[6];
+
+	priv->state = ETH_STATE_INIT;
+
+	/* Check if the device has a MAC address in ROM */
+	if (eth_get_ops(dev)->read_rom_hwaddr)
+		eth_get_ops(dev)->read_rom_hwaddr(dev);
+
+	eth_getenv_enetaddr_by_index("eth", dev->seq, env_enetaddr);
+	if (!is_zero_ether_addr(env_enetaddr)) {
+		if (!is_zero_ether_addr(pdata->enetaddr) &&
+		    memcmp(pdata->enetaddr, env_enetaddr, 6)) {
+			printf("\nWarning: %s MAC addresses don't match:\n",
+			       dev->name);
+			printf("Address in SROM is         %pM\n",
+			       pdata->enetaddr);
+			printf("Address in environment is  %pM\n",
+			       env_enetaddr);
+		}
+
+		/* Override the ROM MAC address */
+		memcpy(pdata->enetaddr, env_enetaddr, 6);
+	} else if (is_valid_ether_addr(pdata->enetaddr)) {
+		eth_setenv_enetaddr_by_index("eth", dev->seq, pdata->enetaddr);
+		printf("\nWarning: %s using MAC address from ROM\n",
+		       dev->name);
+	} else if (is_zero_ether_addr(pdata->enetaddr)) {
+		printf("\nError: %s address not set.\n",
+		       dev->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int eth_pre_remove(struct udevice *dev)
+{
+	eth_get_ops(dev)->stop(dev);
+
+	return 0;
+}
+
+UCLASS_DRIVER(eth) = {
+	.name		= "eth",
+	.id		= UCLASS_ETH,
+	.post_bind	= eth_post_bind,
+	.pre_unbind	= eth_pre_unbind,
+	.post_probe	= eth_post_probe,
+	.pre_remove	= eth_pre_remove,
+	.priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
+	.per_device_auto_alloc_size = sizeof(struct eth_device_priv),
+};
+#endif
+
+#ifndef CONFIG_DM_ETH
 /*
  * CPU and board-specific Ethernet initializations.  Aliased function
  * signals caller to move on
@@ -427,6 +763,7 @@ int eth_rx(void)
 
 	return eth_current->recv(eth_current);
 }
+#endif /* ifndef CONFIG_DM_ETH */
 
 #ifdef CONFIG_API
 static void eth_save_packet(void *packet, int length)
@@ -490,7 +827,7 @@ static void eth_current_changed(void)
 
 void eth_try_another(int first_restart)
 {
-	static struct eth_device *first_failed;
+	static void *first_failed;
 	char *ethrotate;
 
 	/*
@@ -519,12 +856,9 @@ void eth_set_current(void)
 {
 	static char *act;
 	static int  env_changed_id;
-	struct eth_device *old_current;
+	void *old_current;
 	int	env_id;
 
-	if (!eth_get_dev())	/* XXX no current */
-		return;
-
 	env_id = get_env_id();
 	if ((act == NULL) || (env_changed_id != env_id)) {
 		act = getenv("ethact");
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 14/27] net: Clean up network stack names used in DM drivers
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (12 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 13/27] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:05               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 15/27] dm: eth: Pass the packet pointer as a parameter to recv Joe Hershberger
                               ` (12 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

Take the opportunity to enforce better names on newly written or
retrofitted Ethernet drivers.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5:
-New to v5

Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/net.h |  9 ++++++++-
 net/net.c     | 30 +++++++++++++++++++-----------
 2 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/include/net.h b/include/net.h
index fff82cb..31ef1ff 100644
--- a/include/net.h
+++ b/include/net.h
@@ -466,7 +466,11 @@ extern uchar		NetServerEther[6];	/* Boot server enet address */
 extern IPaddr_t		NetOurIP;	/* Our    IP addr (0 = unknown) */
 extern IPaddr_t		NetServerIP;	/* Server IP addr (0 = unknown) */
 extern uchar		*NetTxPacket;		/* THE transmit packet */
+#ifdef CONFIG_DM_ETH
+extern uchar		*net_rx_packets[PKTBUFSRX]; /* Receive packets */
+#else
 extern uchar		*NetRxPackets[PKTBUFSRX]; /* Receive packets */
+#endif
 extern uchar		*NetRxPacket;		/* Current receive packet */
 extern int		NetRxPacketLen;		/* Current rx packet length */
 extern unsigned		NetIPID;		/* IP ID (counting) */
@@ -616,8 +620,11 @@ static inline void NetSendPacket(uchar *pkt, int len)
 int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport,
 			int sport, int payload_len);
 
+#ifndef CONFIG_DM_ETH
+#define NetReceive(in_packet, len) net_process_received_packet(in_packet, len)
+#endif
 /* Processes a received packet */
-void NetReceive(uchar *, int);
+void net_process_received_packet(uchar *in_packet, int len);
 
 #ifdef CONFIG_NETCONSOLE
 void NcStart(void);
diff --git a/net/net.c b/net/net.c
index 37b4aab..afec443 100644
--- a/net/net.c
+++ b/net/net.c
@@ -183,10 +183,13 @@ int		NetTimeOffset;
 #endif
 
 static uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
-
+#ifdef CONFIG_DM_ETH
+/* Receive packets */
+uchar *net_rx_packets[PKTBUFSRX];
+#else
 /* Receive packet */
 uchar *NetRxPackets[PKTBUFSRX];
-
+#endif
 /* Current UDP RX packet handler */
 static rxhand_f *udp_packet_handler;
 /* Current ARP RX packet handler */
@@ -304,9 +307,15 @@ void net_init(void)
 
 		NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
 		NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
+#ifdef CONFIG_DM_ETH
+		for (i = 0; i < PKTBUFSRX; i++) {
+			net_rx_packets[i] = NetTxPacket + (i + 1) *
+				PKTSIZE_ALIGN;
+		}
+#else
 		for (i = 0; i < PKTBUFSRX; i++)
 			NetRxPackets[i] = NetTxPacket + (i + 1) * PKTSIZE_ALIGN;
-
+#endif
 		ArpInit();
 		net_clear_handlers();
 
@@ -952,8 +961,7 @@ static void receive_icmp(struct ip_udp_hdr *ip, int len,
 	}
 }
 
-void
-NetReceive(uchar *inpkt, int len)
+void net_process_received_packet(uchar *in_packet, int len)
 {
 	struct ethernet_hdr *et;
 	struct ip_udp_hdr *ip;
@@ -967,9 +975,9 @@ NetReceive(uchar *inpkt, int len)
 
 	debug_cond(DEBUG_NET_PKT, "packet received\n");
 
-	NetRxPacket = inpkt;
+	NetRxPacket = in_packet;
 	NetRxPacketLen = len;
-	et = (struct ethernet_hdr *)inpkt;
+	et = (struct ethernet_hdr *)in_packet;
 
 	/* too small packet? */
 	if (len < ETHER_HDR_SIZE)
@@ -977,7 +985,7 @@ NetReceive(uchar *inpkt, int len)
 
 #ifdef CONFIG_API
 	if (push_packet) {
-		(*push_packet)(inpkt, len);
+		(*push_packet)(in_packet, len);
 		return;
 	}
 #endif
@@ -1004,11 +1012,11 @@ NetReceive(uchar *inpkt, int len)
 		 */
 		eth_proto = ntohs(et802->et_prot);
 
-		ip = (struct ip_udp_hdr *)(inpkt + E802_HDR_SIZE);
+		ip = (struct ip_udp_hdr *)(in_packet + E802_HDR_SIZE);
 		len -= E802_HDR_SIZE;
 
 	} else if (eth_proto != PROT_VLAN) {	/* normal packet */
-		ip = (struct ip_udp_hdr *)(inpkt + ETHER_HDR_SIZE);
+		ip = (struct ip_udp_hdr *)(in_packet + ETHER_HDR_SIZE);
 		len -= ETHER_HDR_SIZE;
 
 	} else {			/* VLAN packet */
@@ -1033,7 +1041,7 @@ NetReceive(uchar *inpkt, int len)
 		vlanid = cti & VLAN_IDMASK;
 		eth_proto = ntohs(vet->vet_type);
 
-		ip = (struct ip_udp_hdr *)(inpkt + VLAN_ETHER_HDR_SIZE);
+		ip = (struct ip_udp_hdr *)(in_packet + VLAN_ETHER_HDR_SIZE);
 		len -= VLAN_ETHER_HDR_SIZE;
 	}
 
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 15/27] dm: eth: Pass the packet pointer as a parameter to recv
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (13 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 14/27] net: Clean up network stack names used in DM drivers Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:05               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 16/27] sandbox: eth: Add network support to sandbox Joe Hershberger
                               ` (11 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

Stop forcing drivers to call net_process_received_packet() - formerly
called NetReceive(). Now the uclass will handle calling the driver for
each packet until the driver errors or has nothing to return. The uclass
will then pass the good packets off to the network stack by calling
net_process_received_packet().

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v7: None
Changes in v6:
-Swallow -EAGAIN error in eth_rx()
-Updated function documentation

Changes in v5:
-New to v5

Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/net.h |  6 ++++--
 net/eth.c     | 15 ++++++++++++++-
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/include/net.h b/include/net.h
index 31ef1ff..241a096 100644
--- a/include/net.h
+++ b/include/net.h
@@ -95,7 +95,9 @@ struct eth_pdata {
  *
  * start: Prepare the hardware to send and receive packets
  * send: Send the bytes passed in "packet" as a packet on the wire
- * recv: Check if the hardware received a packet. Call the network stack if so
+ * recv: Check if the hardware received a packet. If so, set the pointer to the
+ *	 packet buffer in the packetp parameter. If not, return an error or 0 to
+ *	 indicate that the hardware receive FIFO is empty
  * stop: Stop the hardware from looking for packets - may be called even if
  *	 state == PASSIVE
  * mcast: Join or leave a multicast group (for TFTP) - optional
@@ -110,7 +112,7 @@ struct eth_pdata {
 struct eth_ops {
 	int (*start)(struct udevice *dev);
 	int (*send)(struct udevice *dev, void *packet, int length);
-	int (*recv)(struct udevice *dev);
+	int (*recv)(struct udevice *dev, uchar **packetp);
 	void (*stop)(struct udevice *dev);
 #ifdef CONFIG_MCAST_TFTP
 	int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
diff --git a/net/eth.c b/net/eth.c
index 1abf027..058c55a 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -259,6 +259,9 @@ int eth_send(void *packet, int length)
 int eth_rx(void)
 {
 	struct udevice *current;
+	uchar *packet;
+	int ret;
+	int i;
 
 	current = eth_get_dev();
 	if (!current)
@@ -267,7 +270,17 @@ int eth_rx(void)
 	if (!device_active(current))
 		return -EINVAL;
 
-	return eth_get_ops(current)->recv(current);
+	/* Process up to 32 packets at one time */
+	for (i = 0; i < 32; i++) {
+		ret = eth_get_ops(current)->recv(current, &packet);
+		if (ret > 0)
+			net_process_received_packet(packet, ret);
+		else
+			break;
+	}
+	if (ret == -EAGAIN)
+		ret = 0;
+	return ret;
 }
 
 static int eth_write_hwaddr(struct udevice *dev)
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 16/27] sandbox: eth: Add network support to sandbox
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (14 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 15/27] dm: eth: Pass the packet pointer as a parameter to recv Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:05               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 17/27] sandbox: eth: Add ARP and PING response to sandbox driver Joe Hershberger
                               ` (10 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

Add basic network support to sandbox which includes a network driver.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5:
-Added help to the sandbox eth mock driver Kconfig entry

Changes in v4:
-Cleaned up sandbox EXTRA_ENV define
-Moved config to Kconfig

Changes in v3:
-Added 2 more ethaddr to sandbox
-Print which device in the debug write hwaddr

Changes in v2:
-Change printfs to debug in sandbox driver
-Remove unused priv struct for sandbox driver

 arch/sandbox/Kconfig         |  9 +++++
 arch/sandbox/dts/sandbox.dts |  4 +++
 board/sandbox/README.sandbox |  4 +--
 drivers/net/Kconfig          | 23 ++++++++++++
 drivers/net/Makefile         |  1 +
 drivers/net/sandbox.c        | 84 ++++++++++++++++++++++++++++++++++++++++++++
 include/configs/sandbox.h    | 16 +++++----
 7 files changed, 133 insertions(+), 8 deletions(-)
 create mode 100644 drivers/net/sandbox.c

diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index 2098b9c..186b58d 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -34,4 +34,13 @@ config DM_I2C
 config DM_TEST
 	default y
 
+config NET
+	default y
+
+config NETDEVICES
+	default y
+
+config DM_ETH
+	default y
+
 endmenu
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 9ce31bf..36b3bd8 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -181,4 +181,8 @@
 		};
 	};
 
+	eth at 10002000 {
+		compatible = "sandbox,eth";
+		reg = <0x10002000 0x1000>;
+	};
 };
diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
index 3c0df17..c1f5f7e 100644
--- a/board/sandbox/README.sandbox
+++ b/board/sandbox/README.sandbox
@@ -173,16 +173,16 @@ U-Boot sandbox supports these emulations:
 - Chrome OS EC
 - GPIO
 - Host filesystem (access files on the host from within U-Boot)
+- I2C
 - Keyboard (Chrome OS)
 - LCD
+- Network
 - Serial (for console only)
 - Sound (incomplete - see sandbox_sdl_sound_init() for details)
 - SPI
 - SPI flash
 - TPM (Trusted Platform Module)
 
-Notable omissions are networking and I2C.
-
 A wide range of commands is implemented. Filesystems which use a block
 device are supported.
 
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 94cf099..e46e57b 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -7,3 +7,26 @@ config DM_ETH
 	  The eth_*() interface will be implemented by the UC_ETH class
 	  This is currently implemented in net/eth.c
 	  Look in include/net.h for details.
+
+menuconfig NETDEVICES
+	bool "Network device support"
+	depends on NET
+	help
+	  You must select Y to enable any network device support
+	  Generally if you have any networking support this is a given
+
+	  If unsure, say Y
+
+if NETDEVICES
+
+config ETH_SANDBOX
+	depends on DM_ETH && SANDBOX
+	default y
+	bool "Sandbox: Mocked Ethernet driver"
+	help
+	  This driver simply responds with fake ARP replies and ping
+	  replies that are used to verify network stack functionality
+
+	  This driver is particularly useful in the test/dm/eth.c tests
+
+endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index b8b0803..a17198c 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_NS8382X) += ns8382x.o
 obj-$(CONFIG_PCNET) += pcnet.o
 obj-$(CONFIG_RTL8139) += rtl8139.o
 obj-$(CONFIG_RTL8169) += rtl8169.o
+obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
 obj-$(CONFIG_SH_ETHER) += sh_eth.o
 obj-$(CONFIG_SMC91111) += smc91111.o
 obj-$(CONFIG_SMC911X) += smc911x.o
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
new file mode 100644
index 0000000..522990d
--- /dev/null
+++ b/drivers/net/sandbox.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int sb_eth_start(struct udevice *dev)
+{
+	debug("eth_sandbox: Start\n");
+
+	return 0;
+}
+
+static int sb_eth_send(struct udevice *dev, void *packet, int length)
+{
+	debug("eth_sandbox: Send packet %d\n", length);
+
+	return 0;
+}
+
+static int sb_eth_recv(struct udevice *dev, uchar **packetp)
+{
+	return 0;
+}
+
+static void sb_eth_stop(struct udevice *dev)
+{
+	debug("eth_sandbox: Stop\n");
+}
+
+static int sb_eth_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	debug("eth_sandbox %s: Write HW ADDR - %pM\n", dev->name,
+	      pdata->enetaddr);
+	return 0;
+}
+
+static const struct eth_ops sb_eth_ops = {
+	.start			= sb_eth_start,
+	.send			= sb_eth_send,
+	.recv			= sb_eth_recv,
+	.stop			= sb_eth_stop,
+	.write_hwaddr		= sb_eth_write_hwaddr,
+};
+
+static int sb_eth_remove(struct udevice *dev)
+{
+	return 0;
+}
+
+static int sb_eth_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	pdata->iobase = dev_get_addr(dev);
+	return 0;
+}
+
+static const struct udevice_id sb_eth_ids[] = {
+	{ .compatible = "sandbox,eth" },
+	{ }
+};
+
+U_BOOT_DRIVER(eth_sandbox) = {
+	.name	= "eth_sandbox",
+	.id	= UCLASS_ETH,
+	.of_match = sb_eth_ids,
+	.ofdata_to_platdata = sb_eth_ofdata_to_platdata,
+	.remove	= sb_eth_remove,
+	.ops	= &sb_eth_ops,
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index febbfb6..664b984 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -126,9 +126,6 @@
 /* include default commands */
 #include <config_cmd_default.h>
 
-/* We don't have networking support yet */
-#undef CONFIG_CMD_NET
-#undef CONFIG_CMD_NFS
 
 #define CONFIG_CMD_HASH
 #define CONFIG_HASH_VERIFY
@@ -165,16 +162,23 @@
 
 #define CONFIG_KEYBOARD
 
-#define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial,cros-ec-keyb\0" \
+#define SANDBOX_SERIAL_SETTINGS		"stdin=serial,cros-ec-keyb\0" \
 					"stdout=serial,lcd\0" \
 					"stderr=serial,lcd\0"
 #else
-
-#define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial\0" \
+#define SANDBOX_SERIAL_SETTINGS		"stdin=serial\0" \
 					"stdout=serial,lcd\0" \
 					"stderr=serial,lcd\0"
 #endif
 
+#define SANDBOX_ETH_SETTINGS		"ethaddr=00:00:11:22:33:44\0" \
+					"eth1addr=00:00:11:22:33:45\0" \
+					"eth2addr=00:00:11:22:33:46\0" \
+					"ipaddr=1.2.3.4\0"
+
+#define CONFIG_EXTRA_ENV_SETTINGS	SANDBOX_SERIAL_SETTINGS \
+					SANDBOX_ETH_SETTINGS
+
 #define CONFIG_GZIP_COMPRESSED
 #define CONFIG_BZIP2
 #define CONFIG_LZO
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 17/27] sandbox: eth: Add ARP and PING response to sandbox driver
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (15 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 16/27] sandbox: eth: Add network support to sandbox Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:06               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 18/27] test: dm: eth: Add tests for the eth dm implementation Joe Hershberger
                               ` (9 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

The sandbox driver will now generate response traffic to exercise the
ping command even when no network exists.  This allows the basic data
pathways of the DM to be tested.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v7: None
Changes in v6: None
Changes in v5:
-Simplify sandbox eth driver by switching from int array to byte array
-Switch priv from packet buffer to a pointer to net_rx_packets[0]

Changes in v4:
-Removed checks on priv != NULL and added protection in uclass instead

Changes in v3:
-Prevent a crash if memory is not allocated

Changes in v2:
-Change printfs to debug in sandbox driver
-Move fake hwaddr to the device tree
-Move static data to priv

 arch/sandbox/dts/sandbox.dts |   1 +
 drivers/net/sandbox.c        | 107 +++++++++++++++++++++++++++++++++++++++++++
 include/configs/sandbox.h    |   1 +
 3 files changed, 109 insertions(+)

diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 36b3bd8..c2a3304 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -184,5 +184,6 @@
 	eth at 10002000 {
 		compatible = "sandbox,eth";
 		reg = <0x10002000 0x1000>;
+		fake-host-hwaddr = [00 00 66 44 22 00];
 	};
 };
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
index 522990d..cb69a95 100644
--- a/drivers/net/sandbox.c
+++ b/drivers/net/sandbox.c
@@ -14,22 +14,128 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/**
+ * struct eth_sandbox_priv - memory for sandbox mock driver
+ *
+ * fake_host_hwaddr: MAC address of mocked machine
+ * fake_host_ipaddr: IP address of mocked machine
+ * recv_packet_buffer: buffer of the packet returned as received
+ * recv_packet_length: length of the packet returned as received
+ */
+struct eth_sandbox_priv {
+	uchar fake_host_hwaddr[ARP_HLEN];
+	IPaddr_t fake_host_ipaddr;
+	uchar *recv_packet_buffer;
+	int recv_packet_length;
+};
+
 static int sb_eth_start(struct udevice *dev)
 {
+	struct eth_sandbox_priv *priv = dev_get_priv(dev);
+
 	debug("eth_sandbox: Start\n");
 
+	fdtdec_get_byte_array(gd->fdt_blob, dev->of_offset, "fake-host-hwaddr",
+			      priv->fake_host_hwaddr, ARP_HLEN);
+	priv->recv_packet_buffer = net_rx_packets[0];
 	return 0;
 }
 
 static int sb_eth_send(struct udevice *dev, void *packet, int length)
 {
+	struct eth_sandbox_priv *priv = dev_get_priv(dev);
+	struct ethernet_hdr *eth = packet;
+
 	debug("eth_sandbox: Send packet %d\n", length);
 
+	if (ntohs(eth->et_protlen) == PROT_ARP) {
+		struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
+
+		if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
+			struct ethernet_hdr *eth_recv;
+			struct arp_hdr *arp_recv;
+
+			/* store this as the assumed IP of the fake host */
+			priv->fake_host_ipaddr = NetReadIP(&arp->ar_tpa);
+			/* Formulate a fake response */
+			eth_recv = (void *)priv->recv_packet_buffer;
+			memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
+			memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
+			       ARP_HLEN);
+			eth_recv->et_protlen = htons(PROT_ARP);
+
+			arp_recv = (void *)priv->recv_packet_buffer +
+				ETHER_HDR_SIZE;
+			arp_recv->ar_hrd = htons(ARP_ETHER);
+			arp_recv->ar_pro = htons(PROT_IP);
+			arp_recv->ar_hln = ARP_HLEN;
+			arp_recv->ar_pln = ARP_PLEN;
+			arp_recv->ar_op = htons(ARPOP_REPLY);
+			memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr,
+			       ARP_HLEN);
+			NetWriteIP(&arp_recv->ar_spa, priv->fake_host_ipaddr);
+			memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN);
+			NetCopyIP(&arp_recv->ar_tpa, &arp->ar_spa);
+
+			priv->recv_packet_length = ETHER_HDR_SIZE +
+				ARP_HDR_SIZE;
+		}
+	} else if (ntohs(eth->et_protlen) == PROT_IP) {
+		struct ip_udp_hdr *ip = packet + ETHER_HDR_SIZE;
+
+		if (ip->ip_p == IPPROTO_ICMP) {
+			struct icmp_hdr *icmp = (struct icmp_hdr *)&ip->udp_src;
+
+			if (icmp->type == ICMP_ECHO_REQUEST) {
+				struct ethernet_hdr *eth_recv;
+				struct ip_udp_hdr *ipr;
+				struct icmp_hdr *icmpr;
+
+				/* reply to the ping */
+				memcpy(priv->recv_packet_buffer, packet,
+				       length);
+				eth_recv = (void *)priv->recv_packet_buffer;
+				ipr = (void *)priv->recv_packet_buffer +
+					ETHER_HDR_SIZE;
+				icmpr = (struct icmp_hdr *)&ipr->udp_src;
+				memcpy(eth_recv->et_dest, eth->et_src,
+				       ARP_HLEN);
+				memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
+				       ARP_HLEN);
+				ipr->ip_sum = 0;
+				ipr->ip_off = 0;
+				NetCopyIP((void *)&ipr->ip_dst, &ip->ip_src);
+				NetWriteIP((void *)&ipr->ip_src,
+					   priv->fake_host_ipaddr);
+				ipr->ip_sum = compute_ip_checksum(ipr,
+					IP_HDR_SIZE);
+
+				icmpr->type = ICMP_ECHO_REPLY;
+				icmpr->checksum = 0;
+				icmpr->checksum = compute_ip_checksum(icmpr,
+					ICMP_HDR_SIZE);
+
+				priv->recv_packet_length = length;
+			}
+		}
+	}
+
 	return 0;
 }
 
 static int sb_eth_recv(struct udevice *dev, uchar **packetp)
 {
+	struct eth_sandbox_priv *priv = dev_get_priv(dev);
+
+	if (priv->recv_packet_length) {
+		int lcl_recv_packet_length = priv->recv_packet_length;
+
+		debug("eth_sandbox: received packet %d\n",
+		      priv->recv_packet_length);
+		priv->recv_packet_length = 0;
+		*packetp = priv->recv_packet_buffer;
+		return lcl_recv_packet_length;
+	}
 	return 0;
 }
 
@@ -80,5 +186,6 @@ U_BOOT_DRIVER(eth_sandbox) = {
 	.ofdata_to_platdata = sb_eth_ofdata_to_platdata,
 	.remove	= sb_eth_remove,
 	.ops	= &sb_eth_ops,
+	.priv_auto_alloc_size = sizeof(struct eth_sandbox_priv),
 	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
 };
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 664b984..9189f6a 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -126,6 +126,7 @@
 /* include default commands */
 #include <config_cmd_default.h>
 
+#define CONFIG_CMD_PING
 
 #define CONFIG_CMD_HASH
 #define CONFIG_HASH_VERIFY
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 18/27] test: dm: eth: Add tests for the eth dm implementation
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (16 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 17/27] sandbox: eth: Add ARP and PING response to sandbox driver Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:06               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 19/27] dm: eth: Add support for aliases Joe Hershberger
                               ` (8 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

Add a test for the eth uclass using the sandbox eth driver. Verify basic
functionality of the network stack / eth uclass by exercising the ping
function.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
-Added dm eth testing

Changes in v2: None

 test/dm/Makefile |  1 +
 test/dm/eth.c    | 38 ++++++++++++++++++++++++++++++++++++++
 test/dm/test.dts | 18 ++++++++++++++++++
 3 files changed, 57 insertions(+)
 create mode 100644 test/dm/eth.c

diff --git a/test/dm/Makefile b/test/dm/Makefile
index 1d9148f..b2eb989 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_DM_TEST) += ut.o
 obj-$(CONFIG_DM_TEST) += core.o
 obj-$(CONFIG_DM_TEST) += ut.o
 ifneq ($(CONFIG_SANDBOX),)
+obj-$(CONFIG_DM_ETH) += eth.o
 obj-$(CONFIG_DM_GPIO) += gpio.o
 obj-$(CONFIG_DM_I2C) += i2c.o
 obj-$(CONFIG_DM_SPI_FLASH) += sf.o
diff --git a/test/dm/eth.c b/test/dm/eth.c
new file mode 100644
index 0000000..04ccf49
--- /dev/null
+++ b/test/dm/eth.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <dm/ut.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int dm_test_eth(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+
+	setenv("ethact", "eth at 10002000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	setenv("ethact", "eth at 10003000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10003000", getenv("ethact"));
+
+	setenv("ethact", "eth at 10004000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	return 0;
+}
+DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
diff --git a/test/dm/test.dts b/test/dm/test.dts
index 84024a4..2f68cdf 100644
--- a/test/dm/test.dts
+++ b/test/dm/test.dts
@@ -149,4 +149,22 @@
 		};
 	};
 
+	eth at 10002000 {
+		compatible = "sandbox,eth";
+		reg = <0x10002000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
+	};
+
+	eth at 10003000 {
+		compatible = "sandbox,eth";
+		reg = <0x10003000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
+	};
+
+	eth at 10004000 {
+		compatible = "sandbox,eth";
+		reg = <0x10004000 0x1000>;
+		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x22>;
+	};
+
 };
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 19/27] dm: eth: Add support for aliases
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (17 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 18/27] test: dm: eth: Add tests for the eth dm implementation Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:06               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 20/27] dm: eth: Add support for ethprime env var Joe Hershberger
                               ` (7 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

Allow network devices to be referred to as "eth0" instead of
"eth at 12345678" when specified in ethact.

Add tests to verify this behavior.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5:
-Added a comment about devname
-Only check for alias if the name is long enough

Changes in v4:
-Use only the seq from DM to find aliases

Changes in v3:
-Added support for aliases

Changes in v2: None

 include/configs/sandbox.h |  2 +-
 include/net.h             |  5 +++++
 net/eth.c                 | 50 ++++++++++++++++++++++++++++++++++++++---------
 test/dm/eth.c             | 24 +++++++++++++++++++++++
 test/dm/test.dts          |  4 +++-
 5 files changed, 74 insertions(+), 11 deletions(-)

diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 9189f6a..caf9f5a 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -174,7 +174,7 @@
 
 #define SANDBOX_ETH_SETTINGS		"ethaddr=00:00:11:22:33:44\0" \
 					"eth1addr=00:00:11:22:33:45\0" \
-					"eth2addr=00:00:11:22:33:46\0" \
+					"eth5addr=00:00:11:22:33:46\0" \
 					"ipaddr=1.2.3.4\0"
 
 #define CONFIG_EXTRA_ENV_SETTINGS	SANDBOX_SERIAL_SETTINGS \
diff --git a/include/net.h b/include/net.h
index 241a096..baccd47 100644
--- a/include/net.h
+++ b/include/net.h
@@ -124,6 +124,11 @@ struct eth_ops {
 #define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
 
 struct udevice *eth_get_dev(void); /* get the current device */
+/*
+ * The devname can be either an exact name given by the driver or device tree
+ * or it can be an alias of the form "eth%d"
+ */
+struct udevice *eth_get_dev_by_name(const char *devname);
 unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
 /* Used only when NetConsole is enabled */
 int eth_init_state_only(void); /* Set active state */
diff --git a/net/eth.c b/net/eth.c
index 058c55a..a2e6f34 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -135,6 +135,39 @@ static void eth_set_dev(struct udevice *dev)
 	eth_get_uclass_priv()->current = dev;
 }
 
+/*
+ * Find the udevice that either has the name passed in as devname or has an
+ * alias named devname.
+ */
+struct udevice *eth_get_dev_by_name(const char *devname)
+{
+	int seq = -1;
+	char *endp = NULL;
+	const char *startp = NULL;
+	struct udevice *it;
+	struct uclass *uc;
+
+	/* Must be longer than 3 to be an alias */
+	if (strlen(devname) > strlen("eth")) {
+		startp = devname + strlen("eth");
+		seq = simple_strtoul(startp, &endp, 10);
+	}
+
+	uclass_get(UCLASS_ETH, &uc);
+	uclass_foreach_dev(it, uc) {
+		/* We need the seq to be valid, so make sure it's probed */
+		device_probe(it);
+		/*
+		 * Check for the name or the sequence number to match
+		 */
+		if (strcmp(it->name, devname) == 0 ||
+		    (endp > startp && it->seq == seq))
+			return it;
+	}
+
+	return NULL;
+}
+
 unsigned char *eth_get_ethaddr(void)
 {
 	struct eth_pdata *pdata;
@@ -421,6 +454,7 @@ UCLASS_DRIVER(eth) = {
 	.pre_remove	= eth_pre_remove,
 	.priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
 	.per_device_auto_alloc_size = sizeof(struct eth_device_priv),
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 };
 #endif
 
@@ -453,6 +487,11 @@ static void eth_set_current_to_next(void)
 	eth_current = eth_current->next;
 }
 
+static void eth_set_dev(struct eth_device *dev)
+{
+	eth_current = dev;
+}
+
 struct eth_device *eth_get_dev_by_name(const char *devname)
 {
 	struct eth_device *dev, *target_dev;
@@ -869,7 +908,6 @@ void eth_set_current(void)
 {
 	static char *act;
 	static int  env_changed_id;
-	void *old_current;
 	int	env_id;
 
 	env_id = get_env_id();
@@ -877,14 +915,8 @@ void eth_set_current(void)
 		act = getenv("ethact");
 		env_changed_id = env_id;
 	}
-	if (act != NULL) {
-		old_current = eth_get_dev();
-		do {
-			if (strcmp(eth_get_name(), act) == 0)
-				return;
-			eth_set_current_to_next();
-		} while (old_current != eth_get_dev());
-	}
+	if (act != NULL)
+		eth_set_dev(eth_get_dev_by_name(act));
 
 	eth_current_changed();
 }
diff --git a/test/dm/eth.c b/test/dm/eth.c
index 04ccf49..5688b71 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -36,3 +36,27 @@ static int dm_test_eth(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
+
+static int dm_test_eth_alias(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+	setenv("ethact", "eth0");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	setenv("ethact", "eth1");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	/* Expected to fail since eth2 is not defined in the device tree */
+	setenv("ethact", "eth2");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	setenv("ethact", "eth5");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10003000", getenv("ethact"));
+
+	return 0;
+}
+DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
diff --git a/test/dm/test.dts b/test/dm/test.dts
index 2f68cdf..bc2409d 100644
--- a/test/dm/test.dts
+++ b/test/dm/test.dts
@@ -17,6 +17,8 @@
 		testfdt3 = "/b-test";
 		testfdt5 = "/some-bus/c-test at 5";
 		testfdt8 = "/a-test";
+		eth0 = "/eth at 10002000";
+		eth5 = &eth_5;
 	};
 
 	uart0: serial {
@@ -155,7 +157,7 @@
 		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
 	};
 
-	eth at 10003000 {
+	eth_5: eth at 10003000 {
 		compatible = "sandbox,eth";
 		reg = <0x10003000 0x1000>;
 		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 20/27] dm: eth: Add support for ethprime env var
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (18 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 19/27] dm: eth: Add support for aliases Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:06               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 21/27] test: dm: eth: Add testing for ethrotate " Joe Hershberger
                               ` (6 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

The ethprime env var is used to indicate the starting device if none is
specified in ethact. Also support aliases specified in the ethprime var.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5:
-Fix compile error on !DM_ETH

Changes in v4:
-Load from ethprime on eth_initialize()

Changes in v3:
-Added support for ethprime

Changes in v2: None

 net/eth.c     | 29 ++++++++++++++++++++++++++++-
 test/dm/eth.c | 20 ++++++++++++++++++++
 2 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/net/eth.c b/net/eth.c
index a2e6f34..b6c2af3 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -360,6 +360,18 @@ int eth_initialize(void)
 		printf("No ethernet found.\n");
 		bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
 	} else {
+		char *ethprime = getenv("ethprime");
+		struct udevice *prime_dev = NULL;
+
+		if (ethprime)
+			prime_dev = eth_get_dev_by_name(ethprime);
+		if (prime_dev) {
+			eth_set_dev(prime_dev);
+			eth_current_changed();
+		} else {
+			eth_set_dev(NULL);
+		}
+
 		bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
 		do {
 			if (num_devices)
@@ -367,6 +379,9 @@ int eth_initialize(void)
 
 			printf("eth%d: %s", dev->seq, dev->name);
 
+			if (ethprime && dev == prime_dev)
+				printf(" [PRIME]");
+
 			eth_write_hwaddr(dev);
 
 			uclass_next_device(&dev);
@@ -915,8 +930,20 @@ void eth_set_current(void)
 		act = getenv("ethact");
 		env_changed_id = env_id;
 	}
-	if (act != NULL)
+
+	if (act == NULL) {
+		char *ethprime = getenv("ethprime");
+		void *dev = NULL;
+
+		if (ethprime)
+			dev = eth_get_dev_by_name(ethprime);
+		if (dev)
+			eth_set_dev(dev);
+		else
+			eth_set_dev(NULL);
+	} else {
 		eth_set_dev(eth_get_dev_by_name(act));
+	}
 
 	eth_current_changed();
 }
diff --git a/test/dm/eth.c b/test/dm/eth.c
index 5688b71..96e3c46 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -60,3 +60,23 @@ static int dm_test_eth_alias(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
+
+static int dm_test_eth_prime(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+
+	/* Expected to be "eth at 10003000" because of ethprime variable */
+	setenv("ethact", NULL);
+	setenv("ethprime", "eth5");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10003000", getenv("ethact"));
+
+	/* Expected to be "eth at 10002000" because it is first */
+	setenv("ethact", NULL);
+	setenv("ethprime", NULL);
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	return 0;
+}
+DM_TEST(dm_test_eth_prime, DM_TESTF_SCAN_FDT);
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 21/27] test: dm: eth: Add testing for ethrotate env var
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (19 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 20/27] dm: eth: Add support for ethprime env var Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:07               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 22/27] sandbox: eth: Add ability to disable ping reply in sandbox eth driver Joe Hershberger
                               ` (5 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

Make sure that the ethrotate behavior occurs as expected.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5:
-Added a test for skipping un-probe-able devices

Changes in v4:
-Added testing for ethrotate

Changes in v3: None
Changes in v2: None

 test/dm/eth.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/test/dm/eth.c b/test/dm/eth.c
index 96e3c46..9b55013 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -80,3 +80,45 @@ static int dm_test_eth_prime(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_eth_prime, DM_TESTF_SCAN_FDT);
+
+static int dm_test_eth_rotate(struct dm_test_state *dms)
+{
+	char ethaddr[18];
+
+	/* Invalidate eth1's MAC address */
+	NetPingIP = string_to_ip("1.1.2.2");
+	strcpy(ethaddr, getenv("eth1addr"));
+	setenv("eth1addr", NULL);
+
+	/* Make sure that the default is to rotate to the next interface */
+	setenv("ethact", "eth at 10004000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	/* If ethrotate is no, then we should fail on a bad MAC */
+	setenv("ethact", "eth at 10004000");
+	setenv("ethrotate", "no");
+	ut_asserteq(-1, NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	/* Restore the env */
+	setenv("eth1addr", ethaddr);
+	setenv("ethrotate", NULL);
+
+	/* Invalidate eth0's MAC address */
+	strcpy(ethaddr, getenv("ethaddr"));
+	setenv(".flags", "ethaddr");
+	setenv("ethaddr", NULL);
+
+	/* Make sure we can skip invalid devices */
+	setenv("ethact", "eth at 10004000");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	/* Restore the env */
+	setenv("ethaddr", ethaddr);
+	setenv(".flags", NULL);
+
+	return 0;
+}
+DM_TEST(dm_test_eth_rotate, DM_TESTF_SCAN_FDT);
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 22/27] sandbox: eth: Add ability to disable ping reply in sandbox eth driver
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (20 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 21/27] test: dm: eth: Add testing for ethrotate " Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:07               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 23/27] test: dm: net: Add a test of the netretry behavior Joe Hershberger
                               ` (4 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

This is needed to test the netretry functionality (make the command fail
on a sandbox eth device).

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6:
-Add function comments
-Check array index bounds

Changes in v5:
-Use a function call to change mock driver behavior

Changes in v4:
-Add ability to disable ping reply in sandbox eth driver

Changes in v3: None
Changes in v2: None

 arch/sandbox/include/asm/eth.h | 15 +++++++++++++++
 drivers/net/sandbox.c          | 17 +++++++++++++++++
 2 files changed, 32 insertions(+)
 create mode 100644 arch/sandbox/include/asm/eth.h

diff --git a/arch/sandbox/include/asm/eth.h b/arch/sandbox/include/asm/eth.h
new file mode 100644
index 0000000..4b79ede
--- /dev/null
+++ b/arch/sandbox/include/asm/eth.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __ETH_H
+#define __ETH_H
+
+void sandbox_eth_disable_response(int index, bool disable);
+
+#endif /* __ETH_H */
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
index cb69a95..db115d0 100644
--- a/drivers/net/sandbox.c
+++ b/drivers/net/sandbox.c
@@ -29,6 +29,19 @@ struct eth_sandbox_priv {
 	int recv_packet_length;
 };
 
+static bool disabled[8] = {false};
+
+/*
+ * sandbox_eth_disable_response()
+ *
+ * index - The alias index (also DM seq number)
+ * disable - If non-zero, ignore sent packets and don't send mock response
+ */
+void sandbox_eth_disable_response(int index, bool disable)
+{
+	disabled[index] = disable;
+}
+
 static int sb_eth_start(struct udevice *dev)
 {
 	struct eth_sandbox_priv *priv = dev_get_priv(dev);
@@ -48,6 +61,10 @@ static int sb_eth_send(struct udevice *dev, void *packet, int length)
 
 	debug("eth_sandbox: Send packet %d\n", length);
 
+	if (dev->seq >= 0 && dev->seq < ARRAY_SIZE(disabled) &&
+	    disabled[dev->seq])
+		return 0;
+
 	if (ntohs(eth->et_protlen) == PROT_ARP) {
 		struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
 
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 23/27] test: dm: net: Add a test of the netretry behavior
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (21 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 22/27] sandbox: eth: Add ability to disable ping reply in sandbox eth driver Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:07               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 24/27] sandbox: eth: Add a bridge to a real network for sandbox Joe Hershberger
                               ` (3 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

The effect of the "netretry" env var was recently changed. This test
checks that behavior.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5:
-Added comments about test cases
-Switched to function to control state of mock driver

Changes in v4:
-Updated expected behavior based on changes to the NetLoop

Changes in v3:
-Added testing for netretry

Changes in v2: None

 test/dm/eth.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/test/dm/eth.c b/test/dm/eth.c
index 9b55013..a0e9359 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -14,6 +14,7 @@
 #include <fdtdec.h>
 #include <malloc.h>
 #include <net.h>
+#include <asm/eth.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -122,3 +123,34 @@ static int dm_test_eth_rotate(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_eth_rotate, DM_TESTF_SCAN_FDT);
+
+static int dm_test_net_retry(struct dm_test_state *dms)
+{
+	NetPingIP = string_to_ip("1.1.2.2");
+
+	/*
+	 * eth1 is disabled and netretry is yes, so the ping should succeed and
+	 * the active device should be eth0
+	 */
+	sandbox_eth_disable_response(1, true);
+	setenv("ethact", "eth at 10004000");
+	setenv("netretry", "yes");
+	ut_assertok(NetLoop(PING));
+	ut_asserteq_str("eth at 10002000", getenv("ethact"));
+
+	/*
+	 * eth1 is disabled and netretry is no, so the ping should fail and the
+	 * active device should be eth1
+	 */
+	setenv("ethact", "eth at 10004000");
+	setenv("netretry", "no");
+	ut_asserteq(-1, NetLoop(PING));
+	ut_asserteq_str("eth at 10004000", getenv("ethact"));
+
+	/* Restore the env */
+	setenv("netretry", NULL);
+	sandbox_eth_disable_response(1, false);
+
+	return 0;
+}
+DM_TEST(dm_test_net_retry, DM_TESTF_SCAN_FDT);
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 24/27] sandbox: eth: Add a bridge to a real network for sandbox
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (22 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 23/27] test: dm: net: Add a test of the netretry behavior Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:07               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 25/27] sandbox: Enable DHCP and IP defrag Joe Hershberger
                               ` (2 subsequent siblings)
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

Implement a bridge between U-Boot's network stack and Linux's raw packet
API allowing the sandbox to send and receive packets using the host
machine's network interface.

This raw Ethernet API requires elevated privileges.  You can either run
as root, or you can add the capability needed like so:

sudo /sbin/setcap "CAP_NET_RAW+ep" /path/to/u-boot

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6:
-Addressed nits

Changes in v5:
-Added fallback for setting promiscuous mode
-Added help to Kconfig
-Added more details and examples in the README
-Check for NULL when reading fdt for host interface
-Check for malloc failure
-Remove cast of pointer passed to free
-Remove the empty sb_eth_raw_remove function
-Return -errno in from send and recv
-Return errno from recv
-Set the socket to non-blocking
-Use net_rx_packets instead of a stack buffer

Changes in v4:
-Add comments to priv struct definition
-Added comments to README.sandbox
-Clean up the interface to sandbox's eth-raw-os by passing priv to raw-os
-Cleanup var definition order
-Fixed the MAC address limitation (now all traffic uses MAC address from env)
-Move os file to arch
-Moved config to Kconfig
-Use accessors for platdata and priv

Changes in v3:
-Made the os raw packet support for sandbox eth build and work.

Changes in v2:
-Added the raw packet proof-of-concept patch.

 arch/sandbox/Kconfig                  |   3 +
 arch/sandbox/cpu/Makefile             |  10 +++
 arch/sandbox/cpu/eth-raw-os.c         | 140 ++++++++++++++++++++++++++++++++++
 arch/sandbox/dts/sandbox.dts          |   6 ++
 arch/sandbox/include/asm/eth-raw-os.h |  32 ++++++++
 board/sandbox/README.sandbox          |  52 +++++++++++++
 drivers/net/Kconfig                   |  10 +++
 drivers/net/Makefile                  |   1 +
 drivers/net/sandbox-raw.c             |  98 ++++++++++++++++++++++++
 9 files changed, 352 insertions(+)
 create mode 100644 arch/sandbox/cpu/eth-raw-os.c
 create mode 100644 arch/sandbox/include/asm/eth-raw-os.h
 create mode 100644 drivers/net/sandbox-raw.c

diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index 186b58d..f84b3fc 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -43,4 +43,7 @@ config NETDEVICES
 config DM_ETH
 	default y
 
+config ETH_SANDBOX_RAW
+	default y
+
 endmenu
diff --git a/arch/sandbox/cpu/Makefile b/arch/sandbox/cpu/Makefile
index 7d4410c..1b42fee 100644
--- a/arch/sandbox/cpu/Makefile
+++ b/arch/sandbox/cpu/Makefile
@@ -8,6 +8,7 @@
 #
 
 obj-y	:= cpu.o os.o start.o state.o
+obj-$(CONFIG_ETH_SANDBOX_RAW)	+= eth-raw-os.o
 obj-$(CONFIG_SANDBOX_SDL)	+= sdl.o
 
 # os.c is build in the system environment, so needs standard includes
@@ -20,3 +21,12 @@ $(obj)/os.o: $(src)/os.c FORCE
 	$(call if_changed_dep,cc_os.o)
 $(obj)/sdl.o: $(src)/sdl.c FORCE
 	$(call if_changed_dep,cc_os.o)
+
+# eth-raw-os.c is built in the system env, so needs standard includes
+# CFLAGS_REMOVE_eth-raw-os.o cannot be used to drop header include path
+quiet_cmd_cc_eth-raw-os.o = CC $(quiet_modtag)  $@
+cmd_cc_eth-raw-os.o = $(CC) $(filter-out -nostdinc, \
+	$(patsubst -I%,-idirafter%,$(c_flags))) -c -o $@ $<
+
+$(obj)/eth-raw-os.o: $(src)/eth-raw-os.c FORCE
+	$(call if_changed_dep,cc_eth-raw-os.o)
diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c
new file mode 100644
index 0000000..601205a
--- /dev/null
+++ b/arch/sandbox/cpu/eth-raw-os.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <asm/eth-raw-os.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+
+int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
+			    struct eth_sandbox_raw_priv *priv)
+{
+	struct sockaddr_ll *device;
+	struct packet_mreq mr;
+	int ret;
+	int flags;
+
+	/* Prepare device struct */
+	priv->device = malloc(sizeof(struct sockaddr_ll));
+	if (priv->device == NULL)
+		return -ENOMEM;
+	device = priv->device;
+	memset(device, 0, sizeof(struct sockaddr_ll));
+	device->sll_ifindex = if_nametoindex(ifname);
+	device->sll_family = AF_PACKET;
+	memcpy(device->sll_addr, ethmac, 6);
+	device->sll_halen = htons(6);
+
+	/* Open socket */
+	priv->sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+	if (priv->sd < 0) {
+		printf("Failed to open socket: %d %s\n", errno,
+		       strerror(errno));
+		return -errno;
+	}
+	/* Bind to the specified interface */
+	ret = setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
+		   strlen(ifname) + 1);
+	if (ret < 0) {
+		printf("Failed to bind to '%s': %d %s\n", ifname, errno,
+		       strerror(errno));
+		return -errno;
+	}
+
+	/* Make the socket non-blocking */
+	flags = fcntl(priv->sd, F_GETFL, 0);
+	fcntl(priv->sd, F_SETFL, flags | O_NONBLOCK);
+
+	/* Enable promiscuous mode to receive responses meant for us */
+	mr.mr_ifindex = device->sll_ifindex;
+	mr.mr_type = PACKET_MR_PROMISC;
+	ret = setsockopt(priv->sd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
+		   &mr, sizeof(mr));
+	if (ret < 0) {
+		struct ifreq ifr;
+
+		printf("Failed to set promiscuous mode: %d %s\n"
+		       "Falling back to the old \"flags\" way...\n",
+			errno, strerror(errno));
+		strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+		if (ioctl(priv->sd, SIOCGIFFLAGS, &ifr) < 0) {
+			printf("Failed to read flags: %d %s\n", errno,
+			       strerror(errno));
+			return -errno;
+		}
+		ifr.ifr_flags |= IFF_PROMISC;
+		if (ioctl(priv->sd, SIOCSIFFLAGS, &ifr) < 0) {
+			printf("Failed to write flags: %d %s\n", errno,
+			       strerror(errno));
+			return -errno;
+		}
+	}
+	return 0;
+}
+
+int sandbox_eth_raw_os_send(void *packet, int length,
+			    const struct eth_sandbox_raw_priv *priv)
+{
+	int retval;
+
+	if (!priv->sd || !priv->device)
+		return -EINVAL;
+
+	retval = sendto(priv->sd, packet, length, 0,
+			(struct sockaddr *)priv->device,
+			sizeof(struct sockaddr_ll));
+	if (retval < 0) {
+		printf("Failed to send packet: %d %s\n", errno,
+		       strerror(errno));
+		return -errno;
+	}
+	return retval;
+}
+
+int sandbox_eth_raw_os_recv(void *packet, int *length,
+			    const struct eth_sandbox_raw_priv *priv)
+{
+	int retval;
+	int saddr_size;
+
+	if (!priv->sd || !priv->device)
+		return -EINVAL;
+	saddr_size = sizeof(struct sockaddr);
+	retval = recvfrom(priv->sd, packet, 1536, 0,
+			  (struct sockaddr *)priv->device,
+			  (socklen_t *)&saddr_size);
+	*length = 0;
+	if (retval >= 0) {
+		*length = retval;
+		return 0;
+	}
+	/* The socket is non-blocking, so expect EAGAIN when there is no data */
+	if (errno == EAGAIN)
+		return 0;
+	return -errno;
+}
+
+void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv)
+{
+	free(priv->device);
+	priv->device = NULL;
+	close(priv->sd);
+	priv->sd = -1;
+}
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index c2a3304..8002196 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -186,4 +186,10 @@
 		reg = <0x10002000 0x1000>;
 		fake-host-hwaddr = [00 00 66 44 22 00];
 	};
+
+	eth at 80000000 {
+		compatible = "sandbox,eth-raw";
+		reg = <0x80000000 0x1000>;
+		host-raw-interface = "eth0";
+	};
 };
diff --git a/arch/sandbox/include/asm/eth-raw-os.h b/arch/sandbox/include/asm/eth-raw-os.h
new file mode 100644
index 0000000..df60c4f
--- /dev/null
+++ b/arch/sandbox/include/asm/eth-raw-os.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __ETH_RAW_OS_H
+#define __ETH_RAW_OS_H
+
+/**
+ * struct eth_sandbox_raw_priv - raw socket session
+ *
+ * sd: socket descriptor - the open socket during a session
+ * device: struct sockaddr_ll - the host interface packets move to/from
+ */
+struct eth_sandbox_raw_priv {
+	int sd;
+	void *device;
+};
+
+int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
+			    struct eth_sandbox_raw_priv *priv);
+int sandbox_eth_raw_os_send(void *packet, int length,
+			    const struct eth_sandbox_raw_priv *priv);
+int sandbox_eth_raw_os_recv(void *packet, int *length,
+			    const struct eth_sandbox_raw_priv *priv);
+void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv);
+
+#endif /* __ETH_RAW_OS_H */
diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
index c1f5f7e..9f5d3f7 100644
--- a/board/sandbox/README.sandbox
+++ b/board/sandbox/README.sandbox
@@ -190,6 +190,58 @@ Also sandbox uses generic board (CONFIG_SYS_GENERIC_BOARD) and supports
 driver model (CONFIG_DM) and associated commands.
 
 
+Linux RAW Networking Bridge
+---------------------------
+
+The sandbox_eth_raw driver bridges traffic between the bottom of the network
+stack and the RAW sockets API in Linux. This allows much of the U-Boot network
+functionality to be tested in sandbox against real network traffic.
+
+For Ethernet network adapters, the bridge utilizes the RAW AF_PACKET API.  This
+is needed to get access to the lowest level of the network stack in Linux. This
+means that all of the Ethernet frame is included. This allows the U-Boot network
+stack to be fully used. In other words, nothing about the Linux network stack is
+involved in forming the packets that end up on the wire. To receive the
+responses to packets sent from U-Boot the network interface has to be set to
+promiscuous mode so that the network card won't filter out packets not destined
+for its configured (on Linux) MAC address.
+
+The RAW sockets Ethernet API requires elevated privileges in Linux. You can
+either run as root, or you can add the capability needed like so:
+
+sudo /sbin/setcap "CAP_NET_RAW+ep" /path/to/u-boot
+
+The default device tree for sandbox includes an entry for eth0 on the sandbox
+host machine whose alias is "eth1". The following are a few examples of network
+operations being tested on the eth0 interface.
+
+sudo /path/to/u-boot -D
+
+DHCP
+....
+
+set autoload no
+set ethact eth1
+dhcp
+
+PING
+....
+
+set autoload no
+set ethact eth1
+dhcp
+ping $gatewayip
+
+TFTP
+....
+
+set autoload no
+set ethact eth1
+dhcp
+set serverip WWW.XXX.YYY.ZZZ
+tftpboot u-boot.bin
+
+
 SPI Emulation
 -------------
 
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index e46e57b..5bd66ea 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -29,4 +29,14 @@ config ETH_SANDBOX
 
 	  This driver is particularly useful in the test/dm/eth.c tests
 
+config ETH_SANDBOX_RAW
+	depends on DM_ETH && SANDBOX
+	default y
+	bool "Sandbox: Bridge to Linux Raw Sockets"
+	help
+	  This driver is a bridge from the bottom of the network stack
+	  in U-Boot to the RAW AF_PACKET API in Linux. This allows real
+	  network traffic to be tested from within sandbox. See
+	  board/sandbox/README.sandbox for more details.
+
 endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a17198c..7d32519 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_PCNET) += pcnet.o
 obj-$(CONFIG_RTL8139) += rtl8139.o
 obj-$(CONFIG_RTL8169) += rtl8169.o
 obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
+obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o
 obj-$(CONFIG_SH_ETHER) += sh_eth.o
 obj-$(CONFIG_SMC91111) += smc91111.o
 obj-$(CONFIG_SMC911X) += smc911x.o
diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
new file mode 100644
index 0000000..435b874
--- /dev/null
+++ b/drivers/net/sandbox-raw.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <asm/eth-raw-os.h>
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+
+static int sb_eth_raw_start(struct udevice *dev)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	const char *interface;
+
+	debug("eth_sandbox_raw: Start\n");
+
+	interface = fdt_getprop(gd->fdt_blob, dev->of_offset,
+					    "host-raw-interface", NULL);
+	if (interface == NULL)
+		return -EINVAL;
+
+	return sandbox_eth_raw_os_start(interface, pdata->enetaddr, priv);
+}
+
+static int sb_eth_raw_send(struct udevice *dev, void *packet, int length)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+
+	debug("eth_sandbox_raw: Send packet %d\n", length);
+
+	return sandbox_eth_raw_os_send(packet, length, priv);
+}
+
+static int sb_eth_raw_recv(struct udevice *dev, uchar **packetp)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+	int retval;
+	int length;
+
+	retval = sandbox_eth_raw_os_recv(net_rx_packets[0], &length, priv);
+
+	if (!retval && length) {
+		debug("eth_sandbox_raw: received packet %d\n",
+		      length);
+		*packetp = net_rx_packets[0];
+		return length;
+	}
+	return retval;
+}
+
+static void sb_eth_raw_stop(struct udevice *dev)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+
+	debug("eth_sandbox_raw: Stop\n");
+
+	sandbox_eth_raw_os_stop(priv);
+}
+
+static const struct eth_ops sb_eth_raw_ops = {
+	.start			= sb_eth_raw_start,
+	.send			= sb_eth_raw_send,
+	.recv			= sb_eth_raw_recv,
+	.stop			= sb_eth_raw_stop,
+};
+
+static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	pdata->iobase = dev_get_addr(dev);
+	return 0;
+}
+
+static const struct udevice_id sb_eth_raw_ids[] = {
+	{ .compatible = "sandbox,eth-raw" },
+	{ }
+};
+
+U_BOOT_DRIVER(eth_sandbox_raw) = {
+	.name	= "eth_sandbox_raw",
+	.id	= UCLASS_ETH,
+	.of_match = sb_eth_raw_ids,
+	.ofdata_to_platdata = sb_eth_raw_ofdata_to_platdata,
+	.ops	= &sb_eth_raw_ops,
+	.priv_auto_alloc_size = sizeof(struct eth_sandbox_raw_priv),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 25/27] sandbox: Enable DHCP and IP defrag
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (23 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 24/27] sandbox: eth: Add a bridge to a real network for sandbox Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:08               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 26/27] sandbox: eth: Add support for using the 'lo' interface Joe Hershberger
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 27/27] net: Improve error handling Joe Hershberger
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

This is now testable via the eth-raw interface

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4:
-New to v4

Changes in v3: None
Changes in v2: None

 include/configs/sandbox.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index caf9f5a..034050e 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -127,6 +127,14 @@
 #include <config_cmd_default.h>
 
 #define CONFIG_CMD_PING
+#define CONFIG_CMD_DHCP
+#define CONFIG_BOOTP_DNS
+#define CONFIG_BOOTP_DNS2
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_SEND_HOSTNAME
+#define CONFIG_BOOTP_SERVERIP
+#define CONFIG_BOOTP_SUBNETMASK
+#define CONFIG_IP_DEFRAG
 
 #define CONFIG_CMD_HASH
 #define CONFIG_HASH_VERIFY
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 26/27] sandbox: eth: Add support for using the 'lo' interface
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (24 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 25/27] sandbox: Enable DHCP and IP defrag Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:08               ` Simon Glass
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 27/27] net: Improve error handling Joe Hershberger
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

The 'lo' interface on Linux doesn't support thinks like ARP or
link-layer access like we use to talk to a normal network interface.
A higher-level network API must be used to access localhost.

As written, this interface is limited to not supporting ICMP since the
API doesn't allow the socket to be opened for all IP traffic and be able
to receive at the same time. UDP is far more useful to test with, so it
was selected over ICMP. Ping won't work, but things like TFTP should
work.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5:
-Add details about lo support to the README
-Remove socket timeout
-Separate init to 2 helper static functions
-Set the socket to non-blocking
-Use INADDR_LOOPBACK
-Use more verbose comments

Changes in v4:
-Added support for the 'lo' network interface

Changes in v3: None
Changes in v2: None

 arch/sandbox/cpu/eth-raw-os.c         | 113 +++++++++++++++++++++++++++++++++-
 arch/sandbox/dts/sandbox.dts          |  10 +++
 arch/sandbox/include/asm/eth-raw-os.h |  10 ++-
 board/sandbox/README.sandbox          |  22 +++++++
 drivers/net/sandbox-raw.c             |  71 ++++++++++++++++++++-
 5 files changed, 221 insertions(+), 5 deletions(-)

diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c
index 601205a..b76a731 100644
--- a/arch/sandbox/cpu/eth-raw-os.c
+++ b/arch/sandbox/cpu/eth-raw-os.c
@@ -12,6 +12,8 @@
 #include <fcntl.h>
 #include <net/if.h>
 #include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -20,10 +22,11 @@
 #include <sys/socket.h>
 #include <unistd.h>
 
+#include <arpa/inet.h>
 #include <linux/if_ether.h>
 #include <linux/if_packet.h>
 
-int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
+static int _raw_packet_start(const char *ifname, unsigned char *ethmac,
 			    struct eth_sandbox_raw_priv *priv)
 {
 	struct sockaddr_ll *device;
@@ -89,14 +92,114 @@ int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
 	return 0;
 }
 
+static int _local_inet_start(struct eth_sandbox_raw_priv *priv)
+{
+	struct sockaddr_in *device;
+	int ret;
+	int flags;
+	int one = 1;
+
+	/* Prepare device struct */
+	priv->device = malloc(sizeof(struct sockaddr_in));
+	if (priv->device == NULL)
+		return -ENOMEM;
+	device = priv->device;
+	memset(device, 0, sizeof(struct sockaddr_in));
+	device->sin_family = AF_INET;
+	device->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+	/**
+	 * Open socket
+	 *  Since we specify UDP here, any incoming ICMP packets will
+	 *  not be received, so things like ping will not work on this
+	 *  localhost interface.
+	 */
+	priv->sd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
+	if (priv->sd < 0) {
+		printf("Failed to open socket: %d %s\n", errno,
+		       strerror(errno));
+		return -errno;
+	}
+
+	/* Make the socket non-blocking */
+	flags = fcntl(priv->sd, F_GETFL, 0);
+	fcntl(priv->sd, F_SETFL, flags | O_NONBLOCK);
+
+	/* Include the UDP/IP headers on send and receive */
+	ret = setsockopt(priv->sd, IPPROTO_IP, IP_HDRINCL, &one,
+			 sizeof(one));
+	if (ret < 0) {
+		printf("Failed to set header include option: %d %s\n", errno,
+		       strerror(errno));
+		return -errno;
+	}
+	priv->local_bind_sd = -1;
+	priv->local_bind_udp_port = 0;
+	return 0;
+}
+
+int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
+			    struct eth_sandbox_raw_priv *priv)
+{
+	if (priv->local)
+		return _local_inet_start(priv);
+	else
+		return _raw_packet_start(ifname, ethmac, priv);
+}
+
 int sandbox_eth_raw_os_send(void *packet, int length,
-			    const struct eth_sandbox_raw_priv *priv)
+			    struct eth_sandbox_raw_priv *priv)
 {
 	int retval;
+	struct udphdr *udph = packet + sizeof(struct iphdr);
 
 	if (!priv->sd || !priv->device)
 		return -EINVAL;
 
+	/*
+	 * This block of code came about when testing tftp on the localhost
+	 * interface. When using the RAW AF_INET API, the network stack is still
+	 * in play responding to incoming traffic based on open "ports". Since
+	 * it is raw (at the IP layer, no Ethernet) the network stack tells the
+	 * TFTP server that the port it responded to is closed. This causes the
+	 * TFTP transfer to be aborted. This block of code inspects the outgoing
+	 * packet as formulated by the u-boot network stack to determine the
+	 * source port (that the TFTP server will send packets back to) and
+	 * opens a typical UDP socket on that port, thus preventing the network
+	 * stack from sending that ICMP message claiming that the port has no
+	 * bound socket.
+	 */
+	if (priv->local && (priv->local_bind_sd == -1 ||
+			    priv->local_bind_udp_port != udph->source)) {
+		struct iphdr *iph = packet;
+		struct sockaddr_in addr;
+
+		if (priv->local_bind_sd != -1)
+			close(priv->local_bind_sd);
+
+		/* A normal UDP socket is required to bind */
+		priv->local_bind_sd = socket(AF_INET, SOCK_DGRAM, 0);
+		if (priv->local_bind_sd < 0) {
+			printf("Failed to open bind sd: %d %s\n", errno,
+			       strerror(errno));
+			return -errno;
+		}
+		priv->local_bind_udp_port = udph->source;
+
+		/**
+		 * Bind the UDP port that we intend to use as our source port
+		 * so that the kernel will not send an ICMP port unreachable
+		 * message to the server
+		 */
+		addr.sin_family = AF_INET;
+		addr.sin_port = udph->source;
+		addr.sin_addr.s_addr = iph->saddr;
+		retval = bind(priv->local_bind_sd, &addr, sizeof(addr));
+		if (retval < 0)
+			printf("Failed to bind: %d %s\n", errno,
+			       strerror(errno));
+	}
+
 	retval = sendto(priv->sd, packet, length, 0,
 			(struct sockaddr *)priv->device,
 			sizeof(struct sockaddr_ll));
@@ -137,4 +240,10 @@ void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv)
 	priv->device = NULL;
 	close(priv->sd);
 	priv->sd = -1;
+	if (priv->local) {
+		if (priv->local_bind_sd != -1)
+			close(priv->local_bind_sd);
+		priv->local_bind_sd = -1;
+		priv->local_bind_udp_port = 0;
+	}
 }
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 8002196..0eaa5a5 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -4,6 +4,10 @@
 	#address-cells = <1>;
 	#size-cells = <0>;
 
+	aliases {
+		eth5 = "/eth at 90000000";
+	};
+
 	chosen {
 		stdout-path = "/serial";
 	};
@@ -192,4 +196,10 @@
 		reg = <0x80000000 0x1000>;
 		host-raw-interface = "eth0";
 	};
+
+	eth at 90000000 {
+		compatible = "sandbox,eth-raw";
+		reg = <0x90000000 0x1000>;
+		host-raw-interface = "lo";
+	};
 };
diff --git a/arch/sandbox/include/asm/eth-raw-os.h b/arch/sandbox/include/asm/eth-raw-os.h
index df60c4f..ed4b2e2 100644
--- a/arch/sandbox/include/asm/eth-raw-os.h
+++ b/arch/sandbox/include/asm/eth-raw-os.h
@@ -15,16 +15,24 @@
  *
  * sd: socket descriptor - the open socket during a session
  * device: struct sockaddr_ll - the host interface packets move to/from
+ * local: 1 or 0 to select the local interface ('lo') or not
+ * local_bindsd: socket descriptor to prevent the kernel from sending
+ *		 a message to the server claiming the port is
+ *		 unreachable
+ * local_bind_udp_port: The UDP port number that we bound to
  */
 struct eth_sandbox_raw_priv {
 	int sd;
 	void *device;
+	int local;
+	int local_bind_sd;
+	unsigned short local_bind_udp_port;
 };
 
 int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
 			    struct eth_sandbox_raw_priv *priv);
 int sandbox_eth_raw_os_send(void *packet, int length,
-			    const struct eth_sandbox_raw_priv *priv);
+			    struct eth_sandbox_raw_priv *priv);
 int sandbox_eth_raw_os_recv(void *packet, int *length,
 			    const struct eth_sandbox_raw_priv *priv);
 void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv);
diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
index 9f5d3f7..08489e3 100644
--- a/board/sandbox/README.sandbox
+++ b/board/sandbox/README.sandbox
@@ -241,6 +241,28 @@ dhcp
 set serverip WWW.XXX.YYY.ZZZ
 tftpboot u-boot.bin
 
+The bridge also support (to a lesser extent) the localhost inderface, 'lo'.
+
+The 'lo' interface cannot use the RAW AF_PACKET API because the lo interface
+doesn't support Ethernet-level traffic. It is a higher-level interface that is
+expected only to be used at the AF_INET level of the API. As such, the most raw
+we can get on that interface is the RAW AF_INET API on UDP. This allows us to
+set the IP_HDRINCL option to include everything except the Ethernet header in
+the packets we send and receive.
+
+Because only UDP is supported, ICMP traffic will not work, so expect that ping
+commands will time out.
+
+The default device tree for sandbox includes an entry for lo on the sandbox
+host machine whose alias is "eth5". The following is an example of a network
+operation being tested on the lo interface.
+
+TFTP
+....
+
+set ethact eth5
+tftpboot u-boot.bin
+
 
 SPI Emulation
 -------------
diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
index 435b874..91da5f5 100644
--- a/drivers/net/sandbox-raw.c
+++ b/drivers/net/sandbox-raw.c
@@ -15,6 +15,8 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static int reply_arp;
+static IPaddr_t arp_ip;
 
 static int sb_eth_raw_start(struct udevice *dev)
 {
@@ -29,6 +31,11 @@ static int sb_eth_raw_start(struct udevice *dev)
 	if (interface == NULL)
 		return -EINVAL;
 
+	if (strcmp(interface, "lo") == 0) {
+		priv->local = 1;
+		setenv("ipaddr", "127.0.0.1");
+		setenv("serverip", "127.0.0.1");
+	}
 	return sandbox_eth_raw_os_start(interface, pdata->enetaddr, priv);
 }
 
@@ -38,18 +45,78 @@ static int sb_eth_raw_send(struct udevice *dev, void *packet, int length)
 
 	debug("eth_sandbox_raw: Send packet %d\n", length);
 
+	if (priv->local) {
+		struct ethernet_hdr *eth = packet;
+
+		if (ntohs(eth->et_protlen) == PROT_ARP) {
+			struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
+
+			/**
+			 * localhost works on a higher-level API in Linux than
+			 * ARP packets, so fake it
+			 */
+			arp_ip = NetReadIP(&arp->ar_tpa);
+			reply_arp = 1;
+			return 0;
+		}
+		packet += ETHER_HDR_SIZE;
+		length -= ETHER_HDR_SIZE;
+	}
 	return sandbox_eth_raw_os_send(packet, length, priv);
 }
 
 static int sb_eth_raw_recv(struct udevice *dev, uchar **packetp)
 {
+	struct eth_pdata *pdata = dev_get_platdata(dev);
 	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
-	int retval;
+	int retval = 0;
 	int length;
 
-	retval = sandbox_eth_raw_os_recv(net_rx_packets[0], &length, priv);
+	if (reply_arp) {
+		struct arp_hdr *arp = (void *)net_rx_packets[0] +
+			ETHER_HDR_SIZE;
+
+		/*
+		 * Fake an ARP response. The u-boot network stack is sending an
+		 * ARP request (to find the MAC address to address the actual
+		 * packet to) and requires an ARP response to continue. Since
+		 * this is the localhost interface, there is no Etherent level
+		 * traffic at all, so there is no way to send an ARP request or
+		 * to get a response. For this reason we fake the response to
+		 * make the u-boot network stack happy.
+		 */
+		arp->ar_hrd = htons(ARP_ETHER);
+		arp->ar_pro = htons(PROT_IP);
+		arp->ar_hln = ARP_HLEN;
+		arp->ar_pln = ARP_PLEN;
+		arp->ar_op = htons(ARPOP_REPLY);
+		/* Any non-zero MAC address will work */
+		memset(&arp->ar_sha, 0x01, ARP_HLEN);
+		/* Use whatever IP we were looking for (always 127.0.0.1?) */
+		NetWriteIP(&arp->ar_spa, arp_ip);
+		memcpy(&arp->ar_tha, pdata->enetaddr, ARP_HLEN);
+		NetWriteIP(&arp->ar_tpa, NetOurIP);
+		length = ARP_HDR_SIZE;
+	} else {
+		/* If local, the Ethernet header won't be included; skip it */
+		uchar *pktptr = priv->local ?
+			net_rx_packets[0] + ETHER_HDR_SIZE : net_rx_packets[0];
+
+		retval = sandbox_eth_raw_os_recv(pktptr, &length, priv);
+	}
 
 	if (!retval && length) {
+		if (priv->local) {
+			struct ethernet_hdr *eth = (void *)net_rx_packets[0];
+
+			/* Fill in enough of the missing Ethernet header */
+			memcpy(eth->et_dest, pdata->enetaddr, ARP_HLEN);
+			memset(eth->et_src, 0x01, ARP_HLEN);
+			eth->et_protlen = htons(reply_arp ? PROT_ARP : PROT_IP);
+			reply_arp = 0;
+			length += ETHER_HDR_SIZE;
+		}
+
 		debug("eth_sandbox_raw: received packet %d\n",
 		      length);
 		*packetp = net_rx_packets[0];
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 27/27] net: Improve error handling
  2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
                               ` (25 preceding siblings ...)
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 26/27] sandbox: eth: Add support for using the 'lo' interface Joe Hershberger
@ 2015-03-22 22:09             ` Joe Hershberger
  2015-03-23 16:08               ` Simon Glass
  26 siblings, 1 reply; 282+ messages in thread
From: Joe Hershberger @ 2015-03-22 22:09 UTC (permalink / raw)
  To: u-boot

Take a pass at plumbing errors through to the users of the network stack

Currently only the start() function errors will be returned from
NetLoop(). recv() tends not to have errors, so that is likely not worth
adding. send() certainly can return errors, but this patch does not
attempt to plumb them yet. halt() is not expected to error.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5:
-New to v5

Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/net.h |  3 ++-
 net/eth.c     | 56 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 net/net.c     | 26 ++++++++++++++++++--------
 test/dm/eth.c |  4 ++--
 4 files changed, 70 insertions(+), 19 deletions(-)

diff --git a/include/net.h b/include/net.h
index baccd47..a60ff03 100644
--- a/include/net.h
+++ b/include/net.h
@@ -541,7 +541,7 @@ int NetLoop(enum proto_t);
 void	NetStop(void);
 
 /* Load failed.	 Start again. */
-void	NetStartAgain(void);
+int	NetStartAgain(void);
 
 /* Get size of the ethernet header when we send */
 int	NetEthHdrSize(void);
@@ -611,6 +611,7 @@ static inline void net_set_state(enum net_loop_state state)
 /* Transmit a packet */
 static inline void NetSendPacket(uchar *pkt, int len)
 {
+	/* Currently no way to return errors from eth_send() */
 	(void) eth_send(pkt, len);
 }
 
diff --git a/net/eth.c b/net/eth.c
index b6c2af3..13b7723 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -98,6 +98,9 @@ struct eth_uclass_priv {
 	struct udevice *current;
 };
 
+/* eth_errno - This stores the most recent failure code from DM functions */
+static int eth_errno;
+
 static struct eth_uclass_priv *eth_get_uclass_priv(void)
 {
 	struct uclass *uc;
@@ -118,20 +121,32 @@ static void eth_set_current_to_next(void)
 		uclass_first_device(UCLASS_ETH, &uc_priv->current);
 }
 
+/*
+ * Typically this will simply return the active device.
+ * In the case where the most recent active device was unset, this will attempt
+ * to return the first device. If that device doesn't exist or fails to probe,
+ * this function will return NULL.
+ */
 struct udevice *eth_get_dev(void)
 {
 	struct eth_uclass_priv *uc_priv;
 
 	uc_priv = eth_get_uclass_priv();
 	if (!uc_priv->current)
-		uclass_first_device(UCLASS_ETH,
+		eth_errno = uclass_first_device(UCLASS_ETH,
 				    &uc_priv->current);
 	return uc_priv->current;
 }
 
+/*
+ * Typically this will just store a device pointer.
+ * In case it was not probed, we will attempt to do so.
+ * dev may be NULL to unset the active device.
+ */
 static void eth_set_dev(struct udevice *dev)
 {
-	device_probe(dev);
+	if (dev && !device_active(dev))
+		eth_errno = device_probe(dev);
 	eth_get_uclass_priv()->current = dev;
 }
 
@@ -155,7 +170,14 @@ struct udevice *eth_get_dev_by_name(const char *devname)
 
 	uclass_get(UCLASS_ETH, &uc);
 	uclass_foreach_dev(it, uc) {
-		/* We need the seq to be valid, so make sure it's probed */
+		/*
+		 * We need the seq to be valid, so try to probe it.
+		 * If the probe fails, the seq will not match since it will be
+		 * -1 instead of what we are looking for.
+		 * We don't care about errors from probe here. Either they won't
+		 * match an alias or it will match a literal name and we'll pick
+		 * up the error when we try to probe again in eth_set_dev().
+		 */
 		device_probe(it);
 		/*
 		 * Check for the name or the sequence number to match
@@ -221,6 +243,7 @@ int eth_init(void)
 {
 	struct udevice *current;
 	struct udevice *old_current;
+	int ret = -ENODEV;
 
 	current = eth_get_dev();
 	if (!current) {
@@ -243,22 +266,29 @@ int eth_init(void)
 			else
 				memset(pdata->enetaddr, 0, 6);
 
-			if (eth_get_ops(current)->start(current) >= 0) {
+			ret = eth_get_ops(current)->start(current);
+			if (ret >= 0) {
 				struct eth_device_priv *priv =
 					current->uclass_priv;
 
 				priv->state = ETH_STATE_ACTIVE;
 				return 0;
 			}
-		}
+		} else
+			ret = eth_errno;
+
 		debug("FAIL\n");
 
-		/* This will ensure the new "current" attempted to probe */
+		/*
+		 * If ethrotate is enabled, this will change "current",
+		 * otherwise we will drop out of this while loop immediately
+		 */
 		eth_try_another(0);
+		/* This will ensure the new "current" attempted to probe */
 		current = eth_get_dev();
 	} while (old_current != current);
 
-	return -ENODEV;
+	return ret;
 }
 
 void eth_halt(void)
@@ -278,6 +308,7 @@ void eth_halt(void)
 int eth_send(void *packet, int length)
 {
 	struct udevice *current;
+	int ret;
 
 	current = eth_get_dev();
 	if (!current)
@@ -286,7 +317,12 @@ int eth_send(void *packet, int length)
 	if (!device_active(current))
 		return -EINVAL;
 
-	return eth_get_ops(current)->send(current, packet, length);
+	ret = eth_get_ops(current)->send(current, packet, length);
+	if (ret < 0) {
+		/* We cannot completely return the error at present */
+		debug("%s: send() returned error %d\n", __func__, ret);
+	}
+	return ret;
 }
 
 int eth_rx(void)
@@ -313,6 +349,10 @@ int eth_rx(void)
 	}
 	if (ret == -EAGAIN)
 		ret = 0;
+	if (ret < 0) {
+		/* We cannot completely return the error@present */
+		debug("%s: recv() returned error %d\n", __func__, ret);
+	}
 	return ret;
 }
 
diff --git a/net/net.c b/net/net.c
index afec443..69f38f7 100644
--- a/net/net.c
+++ b/net/net.c
@@ -84,6 +84,7 @@
 #include <common.h>
 #include <command.h>
 #include <environment.h>
+#include <errno.h>
 #include <net.h>
 #if defined(CONFIG_STATUS_LED)
 #include <miiphy.h>
@@ -333,7 +334,7 @@ void net_init(void)
 
 int NetLoop(enum proto_t protocol)
 {
-	int ret = -1;
+	int ret = -EINVAL;
 
 	NetRestarted = 0;
 	NetDevExists = 0;
@@ -345,9 +346,10 @@ int NetLoop(enum proto_t protocol)
 	if (eth_is_on_demand_init() || protocol != NETCONS) {
 		eth_halt();
 		eth_set_current();
-		if (eth_init() < 0) {
+		ret = eth_init();
+		if (ret < 0) {
 			eth_halt();
-			return -1;
+			return ret;
 		}
 	} else
 		eth_init_state_only();
@@ -370,7 +372,7 @@ restart:
 	case 1:
 		/* network not configured */
 		eth_halt();
-		return -1;
+		return -ENODEV;
 
 	case 2:
 		/* network device not configured */
@@ -484,6 +486,8 @@ restart:
 		/*
 		 *	Check the ethernet for a new packet.  The ethernet
 		 *	receive routine will process it.
+		 *	Most drivers return the most recent packet size, but not
+		 *	errors that may have happened.
 		 */
 		eth_rx();
 
@@ -537,7 +541,7 @@ restart:
 		}
 
 		if (net_state == NETLOOP_FAIL)
-			NetStartAgain();
+			ret = NetStartAgain();
 
 		switch (net_state) {
 
@@ -597,11 +601,12 @@ startAgainTimeout(void)
 	net_set_state(NETLOOP_RESTART);
 }
 
-void NetStartAgain(void)
+int NetStartAgain(void)
 {
 	char *nretry;
 	int retry_forever = 0;
 	unsigned long retrycnt = 0;
+	int ret;
 
 	nretry = getenv("netretry");
 	if (nretry) {
@@ -621,7 +626,11 @@ void NetStartAgain(void)
 	if ((!retry_forever) && (NetTryCount >= retrycnt)) {
 		eth_halt();
 		net_set_state(NETLOOP_FAIL);
-		return;
+		/*
+		 * We don't provide a way for the protocol to return an error,
+		 * but this is almost always the reason.
+		 */
+		return -ETIMEDOUT;
 	}
 
 	NetTryCount++;
@@ -630,7 +639,7 @@ void NetStartAgain(void)
 #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
 	eth_try_another(!NetRestarted);
 #endif
-	eth_init();
+	ret = eth_init();
 	if (NetRestartWrap) {
 		NetRestartWrap = 0;
 		if (NetDevExists) {
@@ -642,6 +651,7 @@ void NetStartAgain(void)
 	} else {
 		net_set_state(NETLOOP_RESTART);
 	}
+	return ret;
 }
 
 /**********************************************************************/
diff --git a/test/dm/eth.c b/test/dm/eth.c
index a0e9359..1923670 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -99,7 +99,7 @@ static int dm_test_eth_rotate(struct dm_test_state *dms)
 	/* If ethrotate is no, then we should fail on a bad MAC */
 	setenv("ethact", "eth at 10004000");
 	setenv("ethrotate", "no");
-	ut_asserteq(-1, NetLoop(PING));
+	ut_asserteq(-EINVAL, NetLoop(PING));
 	ut_asserteq_str("eth at 10004000", getenv("ethact"));
 
 	/* Restore the env */
@@ -144,7 +144,7 @@ static int dm_test_net_retry(struct dm_test_state *dms)
 	 */
 	setenv("ethact", "eth at 10004000");
 	setenv("netretry", "no");
-	ut_asserteq(-1, NetLoop(PING));
+	ut_asserteq(-ETIMEDOUT, NetLoop(PING));
 	ut_asserteq_str("eth at 10004000", getenv("ethact"));
 
 	/* Restore the env */
-- 
1.7.11.5

^ permalink raw reply related	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack
  2015-03-20 14:33               ` Joe Hershberger
@ 2015-03-22 22:16                 ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-22 22:16 UTC (permalink / raw)
  To: u-boot

On 20 March 2015 at 08:33, Joe Hershberger <joe.hershberger@gmail.com> wrote:
> Hi Tom,
>
>
> On Fri, Mar 20, 2015 at 8:21 AM, Tom Rini <trini@konsulko.com> wrote:
>>
>> On Fri, Mar 20, 2015 at 06:17:50AM -0600, Simon Glass wrote:
>> > +Tom, Vivek, Marek
>> >
>> > Hi Joe,
>> >
>> > On 11 March 2015 at 17:43, Joe Hershberger <joe.hershberger@ni.com>
>> > wrote:
>> > > Add support for the Ethernet MAC controllers.  Phy support will come
>> > > later.
>> > >
>> > > Switching from RFC to a patch series to be applied to dm/master as a
>> > > staging
>> > > area for this series to make it happen more quickly when the window
>> > > opens.
>> > >
>> > > If desired, let me know which of the non-DM related prerequisite
>> > > patches are
>> > > wanted for this release.
>> > >
>> > > I've added unit tests to verify functionality.
>> > >
>> > > There is an additional driver for sandbox that bridges to the RAW
>> > > Ethernet API in Linux which lets you test with real traffic. It now
>> > > supports localhost as well (the 'lo' interface).
>> > >
>> > > Changes in v6:
>> > > -Add function comments
>> > > -Addressed nits
>> > > -Check array index bounds
>> > > -Fix compile error on boards with CONFIG_API enabled
>> > > -Fix compile errors for other boards due to removed parameters
>> > > -Swallow -EAGAIN error in eth_rx()
>> > > -Updated function documentation
>> > >
>> >
>> > Looks great! I'm going to pick this up for u-boot-dm/next soon,
>> > putting it on top of the PCI series.
>> >
>> > Small USB update:
>> >
>> > I've been fiddling with USB. I became inspired by your more ambitious
>> > conversion of Ethernet and decided to take USB a bit further (using
>> > driver model for all devices, not just controllers).
>> >
>> > I have something I am becoming happy with but it does not support USB
>> > networking. Once I apply your series I will see if I can use driver
>> > model for that also either before or after I send the next version.
>>
>> Nice!  And please feel free to hassle me at ELC next week :)
>
> Cool. I'll be there next week. Do you know who else will be there?

Not me this time.

Regards,
Simon

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 01/27] test: dm: Reorder the objects to build
  2015-03-22 22:08             ` [U-Boot] [PATCH v7 01/27] test: dm: Reorder the objects to build Joe Hershberger
@ 2015-03-23 16:01               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:01 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:08, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Acked-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 02/27] common: Make sure arch-specific map_sysmem() is defined
  2015-03-22 22:08             ` [U-Boot] [PATCH v7 02/27] common: Make sure arch-specific map_sysmem() is defined Joe Hershberger
@ 2015-03-23 16:03               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:03 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:08, Joe Hershberger <joe.hershberger@ni.com> wrote:
> In the case where the arch defines a custom map_sysmem(), make sure that
> including just mapmem.h is sufficient to have these functions as they
> are when the arch does not override it.
>
> Also split the non-arch specific functions out of common.h
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 03/27] net: Provide a function to get the current MAC address
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 03/27] net: Provide a function to get the current MAC address Joe Hershberger
@ 2015-03-23 16:03               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:03 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The current implementation exposes the eth_device struct to code that
> needs to access the MAC address.  Add a wrapper function for this to
> abstract away the pointer for this operation.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 04/27] net: Rename helper function to be more clear
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 04/27] net: Rename helper function to be more clear Joe Hershberger
@ 2015-03-23 16:03               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:03 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Make it clear that the helper is checking the addr, not setting it.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 05/27] net: Remove unneeded "extern" in net.h
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 05/27] net: Remove unneeded "extern" in net.h Joe Hershberger
@ 2015-03-23 16:03               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:03 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Many of the functions in net.h were preceded extern needlessly. Removing
> them to limit the number of checkpatch.pl complaints.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 06/27] net: Refactor in preparation for driver model
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 06/27] net: Refactor in preparation for driver model Joe Hershberger
@ 2015-03-23 16:04               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:04 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Move some things around and organize things so that the driver model
> implementation will fit in more easily.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 07/27] net: Change return codes from net/eth.c to use errorno constants
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 07/27] net: Change return codes from net/eth.c to use errorno constants Joe Hershberger
@ 2015-03-23 16:04               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:04 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Many functions returned -1 previously. Change them to return appropriate error
> codes.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reported-by: Simon Glass <sjg@chromium.org>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 08/27] net: Use int instead of u8 for boolean flag
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 08/27] net: Use int instead of u8 for boolean flag Joe Hershberger
@ 2015-03-23 16:04               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:04 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> On some archs masking the parameter is inefficient, so don't use u8.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reported-by: Simon Glass <sjg@chromium.org>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 09/27] net: Remove the bd* parameter from net stack functions
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 09/27] net: Remove the bd* parameter from net stack functions Joe Hershberger
@ 2015-03-23 16:04               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:04 UTC (permalink / raw)
  To: u-boot

Hi Joe,

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> This value is not used by the network stack and is available in the
> global data, so stop passing it around.  For the one legacy function
> that still expects it (init op on old Ethernet drivers) pass in the
> global pointer version directly to avoid changing that interface.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reported-by: Simon Glass <sjg@chromium.org>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7:
> -Fixed compile error in 4xx_enet.c

This fixes the compile error but introduced a warning. However the fix
was trivial (just removing a variable declaration). So I applied that
fix to your patch.

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 10/27] net: Make netretry actually do something
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 10/27] net: Make netretry actually do something Joe Hershberger
@ 2015-03-23 16:04               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:04 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> netretry previously would only retry in one specific case (your MAC
> address is not set) and no other. This is basically useless. In the DM
> implementation for eth it turns this into a completely useless case
> since an un-configured MAC address results in not even entering the
> NetLoop. The behavior is now changed to retry any failed command
> (rotating through the eth adapters if ethrotate != no).
>
> It also defaulted to retry forever. It is now changed to default to not
> retry
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 11/27] net: Access mapped physmem in net functions
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 11/27] net: Access mapped physmem in net functions Joe Hershberger
@ 2015-03-23 16:05               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:05 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Previously the net functions would access memory assuming physmem did
> not need to be mapped.  In sandbox, that's not the case.
>
> Now we map the physmem specified by the user in loadaddr to the buffer
> that represents that space.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 12/27] cmd: net: Clean up return codes
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 12/27] cmd: net: Clean up return codes Joe Hershberger
@ 2015-03-23 16:05               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:05 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The return codes in common/cmd_net.c had a number of inconsistencies.
> Update them to all use the enum from command.h
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 13/27] dm: eth: Add basic driver model support to Ethernet stack
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 13/27] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
@ 2015-03-23 16:05               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:05 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> First just add support for MAC drivers.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 14/27] net: Clean up network stack names used in DM drivers
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 14/27] net: Clean up network stack names used in DM drivers Joe Hershberger
@ 2015-03-23 16:05               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:05 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Take the opportunity to enforce better names on newly written or
> retrofitted Ethernet drivers.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 15/27] dm: eth: Pass the packet pointer as a parameter to recv
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 15/27] dm: eth: Pass the packet pointer as a parameter to recv Joe Hershberger
@ 2015-03-23 16:05               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:05 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Stop forcing drivers to call net_process_received_packet() - formerly
> called NetReceive(). Now the uclass will handle calling the driver for
> each packet until the driver errors or has nothing to return. The uclass
> will then pass the good packets off to the network stack by calling
> net_process_received_packet().
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 16/27] sandbox: eth: Add network support to sandbox
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 16/27] sandbox: eth: Add network support to sandbox Joe Hershberger
@ 2015-03-23 16:05               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:05 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Add basic network support to sandbox which includes a network driver.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 17/27] sandbox: eth: Add ARP and PING response to sandbox driver
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 17/27] sandbox: eth: Add ARP and PING response to sandbox driver Joe Hershberger
@ 2015-03-23 16:06               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:06 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The sandbox driver will now generate response traffic to exercise the
> ping command even when no network exists.  This allows the basic data
> pathways of the DM to be tested.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 18/27] test: dm: eth: Add tests for the eth dm implementation
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 18/27] test: dm: eth: Add tests for the eth dm implementation Joe Hershberger
@ 2015-03-23 16:06               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:06 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Add a test for the eth uclass using the sandbox eth driver. Verify basic
> functionality of the network stack / eth uclass by exercising the ping
> function.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 19/27] dm: eth: Add support for aliases
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 19/27] dm: eth: Add support for aliases Joe Hershberger
@ 2015-03-23 16:06               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:06 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Allow network devices to be referred to as "eth0" instead of
> "eth at 12345678" when specified in ethact.
>
> Add tests to verify this behavior.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 20/27] dm: eth: Add support for ethprime env var
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 20/27] dm: eth: Add support for ethprime env var Joe Hershberger
@ 2015-03-23 16:06               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:06 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The ethprime env var is used to indicate the starting device if none is
> specified in ethact. Also support aliases specified in the ethprime var.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 21/27] test: dm: eth: Add testing for ethrotate env var
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 21/27] test: dm: eth: Add testing for ethrotate " Joe Hershberger
@ 2015-03-23 16:07               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:07 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Make sure that the ethrotate behavior occurs as expected.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 22/27] sandbox: eth: Add ability to disable ping reply in sandbox eth driver
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 22/27] sandbox: eth: Add ability to disable ping reply in sandbox eth driver Joe Hershberger
@ 2015-03-23 16:07               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:07 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> This is needed to test the netretry functionality (make the command fail
> on a sandbox eth device).
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 23/27] test: dm: net: Add a test of the netretry behavior
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 23/27] test: dm: net: Add a test of the netretry behavior Joe Hershberger
@ 2015-03-23 16:07               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:07 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The effect of the "netretry" env var was recently changed. This test
> checks that behavior.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 24/27] sandbox: eth: Add a bridge to a real network for sandbox
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 24/27] sandbox: eth: Add a bridge to a real network for sandbox Joe Hershberger
@ 2015-03-23 16:07               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:07 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Implement a bridge between U-Boot's network stack and Linux's raw packet
> API allowing the sandbox to send and receive packets using the host
> machine's network interface.
>
> This raw Ethernet API requires elevated privileges.  You can either run
> as root, or you can add the capability needed like so:
>
> sudo /sbin/setcap "CAP_NET_RAW+ep" /path/to/u-boot
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 25/27] sandbox: Enable DHCP and IP defrag
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 25/27] sandbox: Enable DHCP and IP defrag Joe Hershberger
@ 2015-03-23 16:08               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:08 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> This is now testable via the eth-raw interface
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 26/27] sandbox: eth: Add support for using the 'lo' interface
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 26/27] sandbox: eth: Add support for using the 'lo' interface Joe Hershberger
@ 2015-03-23 16:08               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:08 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> The 'lo' interface on Linux doesn't support thinks like ARP or
> link-layer access like we use to talk to a normal network interface.
> A higher-level network API must be used to access localhost.
>
> As written, this interface is limited to not supporting ICMP since the
> API doesn't allow the socket to be opened for all IP traffic and be able
> to receive at the same time. UDP is far more useful to test with, so it
> was selected over ICMP. Ping won't work, but things like TFTP should
> work.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

* [U-Boot] [PATCH v7 27/27] net: Improve error handling
  2015-03-22 22:09             ` [U-Boot] [PATCH v7 27/27] net: Improve error handling Joe Hershberger
@ 2015-03-23 16:08               ` Simon Glass
  0 siblings, 0 replies; 282+ messages in thread
From: Simon Glass @ 2015-03-23 16:08 UTC (permalink / raw)
  To: u-boot

On 22 March 2015 at 16:09, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Take a pass at plumbing errors through to the users of the network stack
>
> Currently only the start() function errors will be returned from
> NetLoop(). recv() tends not to have errors, so that is likely not worth
> adding. send() certainly can return errors, but this patch does not
> attempt to plumb them yet. halt() is not expected to error.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v7: None

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 282+ messages in thread

end of thread, other threads:[~2015-03-23 16:08 UTC | newest]

Thread overview: 282+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-27 23:27 [U-Boot] [RFC PATCH 0/7] Add Driver Model support to network stack Joe Hershberger
2015-01-27 23:27 ` [U-Boot] [RFC PATCH 1/7] net: Provide a function to get the current MAC address Joe Hershberger
2015-01-28  2:33   ` Simon Glass
2015-01-28  9:45     ` Joe Hershberger
2015-01-29  1:46       ` Simon Glass
2015-01-27 23:27 ` [U-Boot] [RFC PATCH 2/7] net: Rename helper function to be more clear Joe Hershberger
2015-01-28  2:34   ` Simon Glass
2015-01-27 23:27 ` [U-Boot] [RFC PATCH 3/7] net: Remove unneeded "extern" in net.h Joe Hershberger
2015-01-28  2:34   ` Simon Glass
2015-01-27 23:27 ` [U-Boot] [RFC PATCH 4/7] net: Refactor in preparation for driver model Joe Hershberger
2015-01-28  2:34   ` Simon Glass
2015-01-27 23:27 ` [U-Boot] [RFC PATCH 5/7] net: Add basic driver model support to Ethernet stack Joe Hershberger
2015-01-28  2:34   ` Simon Glass
2015-01-28 10:22     ` Joe Hershberger
2015-01-29  1:56       ` Simon Glass
2015-01-27 23:27 ` [U-Boot] [RFC PATCH 6/7] net: Add network support to sandbox Joe Hershberger
2015-01-28  2:34   ` Simon Glass
2015-01-28 10:24     ` Joe Hershberger
2015-01-27 23:27 ` [U-Boot] [RFC PATCH 7/7] net: Add ARP and PING response to sandbox driver Joe Hershberger
2015-01-28  2:34   ` Simon Glass
     [not found]     ` <CANr=Z=YcT=OvcA8ggaMCrOfyS5ShjFzgK6AW9gpfsNsZqcgfPA@mail.gmail.com>
2015-01-29  1:58       ` Simon Glass
2015-01-28  2:33 ` [U-Boot] [RFC PATCH 0/7] Add Driver Model support to network stack Simon Glass
2015-02-03  0:38 ` [U-Boot] [RFC PATCH v2 0/8] " Joe Hershberger
2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 1/8] net: Provide a function to get the current MAC address Joe Hershberger
2015-02-07  1:25     ` Simon Glass
2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 2/8] net: Rename helper function to be more clear Joe Hershberger
2015-02-07  1:25     ` Simon Glass
2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 3/8] net: Remove unneeded "extern" in net.h Joe Hershberger
2015-02-07  1:25     ` Simon Glass
2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 4/8] net: Refactor in preparation for driver model Joe Hershberger
2015-02-07  1:25     ` Simon Glass
2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 5/8] net: Add basic driver model support to Ethernet stack Joe Hershberger
2015-02-07  1:25     ` Simon Glass
2015-02-11  6:25       ` Joe Hershberger
2015-02-13  5:20         ` Simon Glass
2015-02-14  2:43           ` Joe Hershberger
2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 6/8] net: Add network support to sandbox Joe Hershberger
2015-02-07  1:25     ` Simon Glass
2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 7/8] net: Add ARP and PING response to sandbox driver Joe Hershberger
2015-02-07  1:25     ` Simon Glass
2015-02-03  0:38   ` [U-Boot] [RFC PATCH v2 8/8] net: Add actual networking support to sandbox's driver Joe Hershberger
2015-02-07  1:25     ` Simon Glass
2015-02-11  1:30   ` [U-Boot] [RFC PATCH v3 0/14] Add Driver Model support to network stack Joe Hershberger
2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 01/14] dm: core: Allow seq numbers to be resolved before probe Joe Hershberger
2015-02-11  4:39       ` Simon Glass
2015-02-11  6:08         ` Joe Hershberger
2015-02-13  5:14           ` Simon Glass
2015-02-14  2:33             ` Joe Hershberger
2015-02-15 15:59               ` Simon Glass
2015-02-17  4:17                 ` Joe Hershberger
2015-02-18  5:02                   ` Simon Glass
2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 02/14] test: dm: Reorder the objects to build Joe Hershberger
2015-02-11  4:39       ` Simon Glass
2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 03/14] net: Provide a function to get the current MAC address Joe Hershberger
2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 04/14] net: Rename helper function to be more clear Joe Hershberger
2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 05/14] net: Remove unneeded "extern" in net.h Joe Hershberger
2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 06/14] net: Refactor in preparation for driver model Joe Hershberger
2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 07/14] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
2015-02-15 15:49       ` Simon Glass
2015-02-17  4:37         ` Joe Hershberger
2015-02-18  5:02           ` Simon Glass
2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 08/14] dm: eth: Add network support to sandbox Joe Hershberger
2015-02-15 15:49       ` Simon Glass
2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 09/14] dm: eth: Add ARP and PING response to sandbox driver Joe Hershberger
2015-02-15 15:49       ` Simon Glass
2015-02-17  4:46         ` Joe Hershberger
2015-02-18  5:02           ` Simon Glass
2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 10/14] test: dm: eth: Add tests for the eth dm implementation Joe Hershberger
2015-02-15 15:50       ` Simon Glass
2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 11/14] dm: eth: Add support for aliases Joe Hershberger
2015-02-15 15:50       ` Simon Glass
2015-02-17  5:04         ` Joe Hershberger
2015-02-18  5:02           ` Simon Glass
2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 12/14] dm: eth: Add support for ethprime env var Joe Hershberger
2015-02-15 15:50       ` Simon Glass
2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 13/14] dm: eth: Add testing for netretry " Joe Hershberger
2015-02-15 15:50       ` Simon Glass
2015-02-11  1:30     ` [U-Boot] [RFC PATCH v3 14/14] dm: eth: Add a bridge to a real network for sandbox Joe Hershberger
2015-02-15 15:50       ` Simon Glass
2015-02-17  5:16         ` Joe Hershberger
2015-02-18  5:02           ` Simon Glass
2015-02-19 23:44             ` Joe Hershberger
2015-02-20 19:33               ` Simon Glass
2015-02-25  0:02     ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Joe Hershberger
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 01/23] test: dm: Reorder the objects to build Joe Hershberger
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 02/23] common: Make sure arch-specific map_sysmem() is defined Joe Hershberger
2015-03-01 18:07         ` Simon Glass
2015-03-01 21:16           ` Joe Hershberger
2015-03-02  2:24             ` Simon Glass
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 03/23] net: Provide a function to get the current MAC address Joe Hershberger
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 04/23] net: Rename helper function to be more clear Joe Hershberger
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 05/23] net: Remove unneeded "extern" in net.h Joe Hershberger
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 06/23] net: Refactor in preparation for driver model Joe Hershberger
2015-03-01 18:08         ` Simon Glass
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 07/23] net: Change return codes from net/eth.c to use errorno constants Joe Hershberger
2015-02-26  0:53         ` Simon Glass
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 08/23] net: Use int instead of u8 for boolean flag Joe Hershberger
2015-02-26  0:53         ` Simon Glass
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 09/23] net: Remove the bd* parameter from net stack functions Joe Hershberger
2015-03-01 18:07         ` Simon Glass
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 10/23] net: Make netretry actually do something Joe Hershberger
2015-03-01 18:07         ` Simon Glass
2015-03-01 21:53           ` Joe Hershberger
2015-03-02  2:24             ` Simon Glass
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 11/23] net: Access mapped physmem in net functions Joe Hershberger
2015-03-01 18:07         ` Simon Glass
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 12/23] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
2015-03-01 18:07         ` Simon Glass
2015-03-01 21:45           ` Joe Hershberger
2015-03-02  2:26             ` Simon Glass
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 13/23] sandbox: eth: Add network support to sandbox Joe Hershberger
2015-03-01 18:07         ` Simon Glass
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 14/23] sandbox: eth: Add ARP and PING response to sandbox driver Joe Hershberger
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 15/23] test: dm: eth: Add tests for the eth dm implementation Joe Hershberger
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 16/23] dm: eth: Add support for aliases Joe Hershberger
2015-03-01 18:07         ` Simon Glass
2015-03-01 22:04           ` Joe Hershberger
2015-03-02  2:23             ` Simon Glass
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 17/23] dm: eth: Add support for ethprime env var Joe Hershberger
2015-03-01 18:07         ` Simon Glass
2015-03-01 22:06           ` Joe Hershberger
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 18/23] test: dm: eth: Add testing for ethrotate " Joe Hershberger
2015-03-01 18:07         ` Simon Glass
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 19/23] sandbox: eth: Add ability to disable ping reply in sandbox eth driver Joe Hershberger
2015-03-01 18:07         ` Simon Glass
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 20/23] test: dm: net: Add a test of the netretry behavior Joe Hershberger
2015-03-01 18:07         ` Simon Glass
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 21/23] sandbox: eth: Add a bridge to a real network for sandbox Joe Hershberger
2015-03-01 18:07         ` Simon Glass
2015-03-02  7:17           ` Joe Hershberger
2015-03-02 15:48             ` Simon Glass
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 22/23] sandbox: Enable DHCP and IP defrag Joe Hershberger
2015-03-01 18:07         ` Simon Glass
2015-02-25  0:02       ` [U-Boot] [RFC PATCH v4 23/23] sandbox: eth: Add support for using the 'lo' interface Joe Hershberger
2015-03-01 18:07         ` Simon Glass
2015-03-02  7:18           ` Joe Hershberger
2015-03-02 22:16             ` Simon Glass
2015-03-01 16:13       ` [U-Boot] [RFC PATCH v4 0/23] Add Driver Model support to network stack Simon Glass
2015-03-01 22:12         ` Joe Hershberger
2015-03-02  2:23           ` Simon Glass
2015-03-03 22:29         ` Joe Hershberger
2015-03-03 23:14           ` Simon Glass
2015-03-03 23:32             ` Joe Hershberger
2015-03-03 23:40               ` Simon Glass
2015-03-04  2:40       ` [U-Boot] [PATCH v5 0/27] " Joe Hershberger
2015-03-04  2:40         ` [U-Boot] [PATCH v5 01/27] test: dm: Reorder the objects to build Joe Hershberger
2015-03-04  2:40         ` [U-Boot] [PATCH v5 02/27] common: Make sure arch-specific map_sysmem() is defined Joe Hershberger
2015-03-04 19:18           ` Simon Glass
2015-03-04  2:40         ` [U-Boot] [PATCH v5 03/27] net: Provide a function to get the current MAC address Joe Hershberger
2015-03-04  2:40         ` [U-Boot] [PATCH v5 04/27] net: Rename helper function to be more clear Joe Hershberger
2015-03-04  2:40         ` [U-Boot] [PATCH v5 05/27] net: Remove unneeded "extern" in net.h Joe Hershberger
2015-03-04  2:41         ` [U-Boot] [PATCH v5 06/27] net: Refactor in preparation for driver model Joe Hershberger
2015-03-04  2:41         ` [U-Boot] [PATCH v5 07/27] net: Change return codes from net/eth.c to use errorno constants Joe Hershberger
2015-03-04  2:41         ` [U-Boot] [PATCH v5 08/27] net: Use int instead of u8 for boolean flag Joe Hershberger
2015-03-04  2:41         ` [U-Boot] [PATCH v5 09/27] net: Remove the bd* parameter from net stack functions Joe Hershberger
2015-03-04  2:41         ` [U-Boot] [PATCH v5 10/27] net: Make netretry actually do something Joe Hershberger
2015-03-04  2:41         ` [U-Boot] [PATCH v5 11/27] net: Access mapped physmem in net functions Joe Hershberger
2015-03-04 18:34           ` Simon Glass
2015-03-04  2:41         ` [U-Boot] [PATCH v5 12/27] cmd: net: Clean up return codes Joe Hershberger
2015-03-04 18:35           ` Simon Glass
2015-03-04  2:41         ` [U-Boot] [PATCH v5 13/27] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
2015-03-04 18:35           ` Simon Glass
2015-03-04  2:41         ` [U-Boot] [PATCH v5 14/27] net: Clean up network stack names used in DM drivers Joe Hershberger
2015-03-04 18:35           ` Simon Glass
2015-03-04  2:41         ` [U-Boot] [PATCH v5 15/27] dm: eth: Pass the packet pointer as a parameter to recv Joe Hershberger
2015-03-04 18:35           ` Simon Glass
2015-03-10 23:28             ` Joe Hershberger
2015-03-10 23:31               ` Simon Glass
2015-03-10 23:41                 ` Joe Hershberger
2015-03-04  2:41         ` [U-Boot] [PATCH v5 16/27] sandbox: eth: Add network support to sandbox Joe Hershberger
2015-03-04 18:35           ` Simon Glass
2015-03-04  2:41         ` [U-Boot] [PATCH v5 17/27] sandbox: eth: Add ARP and PING response to sandbox driver Joe Hershberger
2015-03-04  2:41         ` [U-Boot] [PATCH v5 18/27] test: dm: eth: Add tests for the eth dm implementation Joe Hershberger
2015-03-04  2:41         ` [U-Boot] [PATCH v5 19/27] dm: eth: Add support for aliases Joe Hershberger
2015-03-04 18:35           ` Simon Glass
2015-03-04  2:41         ` [U-Boot] [PATCH v5 20/27] dm: eth: Add support for ethprime env var Joe Hershberger
2015-03-04  2:41         ` [U-Boot] [PATCH v5 21/27] test: dm: eth: Add testing for ethrotate " Joe Hershberger
2015-03-04 18:35           ` Simon Glass
2015-03-04  2:41         ` [U-Boot] [PATCH v5 22/27] sandbox: eth: Add ability to disable ping reply in sandbox eth driver Joe Hershberger
2015-03-04 18:35           ` Simon Glass
2015-03-04  2:41         ` [U-Boot] [PATCH v5 23/27] test: dm: net: Add a test of the netretry behavior Joe Hershberger
2015-03-04 18:35           ` Simon Glass
2015-03-04  2:41         ` [U-Boot] [PATCH v5 24/27] sandbox: eth: Add a bridge to a real network for sandbox Joe Hershberger
2015-03-04 18:35           ` Simon Glass
2015-03-04  2:41         ` [U-Boot] [PATCH v5 25/27] sandbox: Enable DHCP and IP defrag Joe Hershberger
2015-03-04  2:41         ` [U-Boot] [PATCH v5 26/27] sandbox: eth: Add support for using the 'lo' interface Joe Hershberger
2015-03-04 18:35           ` Simon Glass
2015-03-04  2:41         ` [U-Boot] [PATCH v5 27/27] net: Improve error handling Joe Hershberger
2015-03-04 18:35           ` Simon Glass
2015-03-10 23:10             ` Joe Hershberger
2015-03-11 23:43         ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Joe Hershberger
2015-03-11 23:43           ` [U-Boot] [PATCH v6 01/27] test: dm: Reorder the objects to build Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 02/27] common: Make sure arch-specific map_sysmem() is defined Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 03/27] net: Provide a function to get the current MAC address Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 04/27] net: Rename helper function to be more clear Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 05/27] net: Remove unneeded "extern" in net.h Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 06/27] net: Refactor in preparation for driver model Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 07/27] net: Change return codes from net/eth.c to use errorno constants Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 08/27] net: Use int instead of u8 for boolean flag Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 09/27] net: Remove the bd* parameter from net stack functions Joe Hershberger
2015-03-20 23:01             ` Simon Glass
2015-03-22  3:42               ` Joe Hershberger
2015-03-22 21:09                 ` Simon Glass
2015-03-11 23:44           ` [U-Boot] [PATCH v6 10/27] net: Make netretry actually do something Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 11/27] net: Access mapped physmem in net functions Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 12/27] cmd: net: Clean up return codes Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 13/27] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 14/27] net: Clean up network stack names used in DM drivers Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 15/27] dm: eth: Pass the packet pointer as a parameter to recv Joe Hershberger
2015-03-20 12:10             ` Simon Glass
2015-03-11 23:44           ` [U-Boot] [PATCH v6 16/27] sandbox: eth: Add network support to sandbox Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 17/27] sandbox: eth: Add ARP and PING response to sandbox driver Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 18/27] test: dm: eth: Add tests for the eth dm implementation Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 19/27] dm: eth: Add support for aliases Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 20/27] dm: eth: Add support for ethprime env var Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 21/27] test: dm: eth: Add testing for ethrotate " Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 22/27] sandbox: eth: Add ability to disable ping reply in sandbox eth driver Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 23/27] test: dm: net: Add a test of the netretry behavior Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 24/27] sandbox: eth: Add a bridge to a real network for sandbox Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 25/27] sandbox: Enable DHCP and IP defrag Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 26/27] sandbox: eth: Add support for using the 'lo' interface Joe Hershberger
2015-03-11 23:44           ` [U-Boot] [PATCH v6 27/27] net: Improve error handling Joe Hershberger
2015-03-20 12:17           ` [U-Boot] [PATCH v6 0/27] Add Driver Model support to network stack Simon Glass
2015-03-20 12:45             ` Joe Hershberger
2015-03-20 13:21             ` Tom Rini
2015-03-20 14:33               ` Joe Hershberger
2015-03-22 22:16                 ` Simon Glass
2015-03-22 22:08           ` [U-Boot] [PATCH v7 " Joe Hershberger
2015-03-22 22:08             ` [U-Boot] [PATCH v7 01/27] test: dm: Reorder the objects to build Joe Hershberger
2015-03-23 16:01               ` Simon Glass
2015-03-22 22:08             ` [U-Boot] [PATCH v7 02/27] common: Make sure arch-specific map_sysmem() is defined Joe Hershberger
2015-03-23 16:03               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 03/27] net: Provide a function to get the current MAC address Joe Hershberger
2015-03-23 16:03               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 04/27] net: Rename helper function to be more clear Joe Hershberger
2015-03-23 16:03               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 05/27] net: Remove unneeded "extern" in net.h Joe Hershberger
2015-03-23 16:03               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 06/27] net: Refactor in preparation for driver model Joe Hershberger
2015-03-23 16:04               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 07/27] net: Change return codes from net/eth.c to use errorno constants Joe Hershberger
2015-03-23 16:04               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 08/27] net: Use int instead of u8 for boolean flag Joe Hershberger
2015-03-23 16:04               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 09/27] net: Remove the bd* parameter from net stack functions Joe Hershberger
2015-03-23 16:04               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 10/27] net: Make netretry actually do something Joe Hershberger
2015-03-23 16:04               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 11/27] net: Access mapped physmem in net functions Joe Hershberger
2015-03-23 16:05               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 12/27] cmd: net: Clean up return codes Joe Hershberger
2015-03-23 16:05               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 13/27] dm: eth: Add basic driver model support to Ethernet stack Joe Hershberger
2015-03-23 16:05               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 14/27] net: Clean up network stack names used in DM drivers Joe Hershberger
2015-03-23 16:05               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 15/27] dm: eth: Pass the packet pointer as a parameter to recv Joe Hershberger
2015-03-23 16:05               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 16/27] sandbox: eth: Add network support to sandbox Joe Hershberger
2015-03-23 16:05               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 17/27] sandbox: eth: Add ARP and PING response to sandbox driver Joe Hershberger
2015-03-23 16:06               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 18/27] test: dm: eth: Add tests for the eth dm implementation Joe Hershberger
2015-03-23 16:06               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 19/27] dm: eth: Add support for aliases Joe Hershberger
2015-03-23 16:06               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 20/27] dm: eth: Add support for ethprime env var Joe Hershberger
2015-03-23 16:06               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 21/27] test: dm: eth: Add testing for ethrotate " Joe Hershberger
2015-03-23 16:07               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 22/27] sandbox: eth: Add ability to disable ping reply in sandbox eth driver Joe Hershberger
2015-03-23 16:07               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 23/27] test: dm: net: Add a test of the netretry behavior Joe Hershberger
2015-03-23 16:07               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 24/27] sandbox: eth: Add a bridge to a real network for sandbox Joe Hershberger
2015-03-23 16:07               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 25/27] sandbox: Enable DHCP and IP defrag Joe Hershberger
2015-03-23 16:08               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 26/27] sandbox: eth: Add support for using the 'lo' interface Joe Hershberger
2015-03-23 16:08               ` Simon Glass
2015-03-22 22:09             ` [U-Boot] [PATCH v7 27/27] net: Improve error handling Joe Hershberger
2015-03-23 16:08               ` Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.