[U-Boot] [PATCH 0/8] net: Split out the Ethernet uclass into its own file

Every other uclass is in its own file. It makes sense to put the Ethernet uclass code into its own file too. The result is less code in each file, and it becomes easier to see which code is related to driver model.
This series creates a new common file to hold the common code, moves the driver-model into its own file and tidies up.
Some boards use PCI to obtain Ethernet. With driver model, unless this is mentioned in the device tree, the Ethernet device will not be present on initial startup. So we need to probe PCI just in case there is a device there.
Simon Glass (8): tegra: Report errors from PCI init net: Don't call board/cpu_eth_init() with driver model net: Move common init into a new eth_common.c file net: Move environment functions to the common file net: Move remaining common functions to eth_common.c net: Move driver-model code into its own file net: Rename eth.c to eth_lecacy.c net: Probe PCI before looking for ethernet devices
drivers/pci/pci_tegra.c | 6 +- net/Makefile | 7 +- net/{eth.c => eth-uclass.c} | 601 +------------------------------------------- net/eth_common.c | 166 ++++++++++++ net/eth_internal.h | 40 +++ net/eth_legacy.c | 439 ++++++++++++++++++++++++++++++++ 6 files changed, 664 insertions(+), 595 deletions(-) rename net/{eth.c => eth-uclass.c} (50%) create mode 100644 net/eth_common.c create mode 100644 net/eth_internal.h create mode 100644 net/eth_legacy.c

This function can fail, so be sure to report any errors that occur.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/pci/pci_tegra.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index 5a7fefe..5dadf6f 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -465,7 +465,11 @@ static int tegra_pcie_parse_dt(const void *fdt, int node, enum tegra_pci_id id, return err; }
- tegra_pcie_board_init(); + err = tegra_pcie_board_init(); + if (err < 0) { + error("tegra_pcie_board_init() failed: err=%d", err); + return err; + }
pcie->phy = tegra_xusb_phy_get(TEGRA_XUSB_PADCTL_PCIE); if (pcie->phy) {

Hi Simon,
On Sun, Jan 17, 2016 at 3:51 PM, Simon Glass sjg@chromium.org wrote:
This function can fail, so be sure to report any errors that occur.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Joe Hershberger joe.hershberger@ni.com


We should avoid weak functions with driver model. Existing boards that use driver model don't need them, so let's kill them off.
Signed-off-by: Simon Glass sjg@chromium.org ---
net/eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/eth.c b/net/eth.c index 45fe6e3..d96d3a5 100644 --- a/net/eth.c +++ b/net/eth.c @@ -96,6 +96,7 @@ static void eth_common_init(void) phy_init(); #endif
+#ifndef CONFIG_DM_ETH /* * If board-specific initialization exists, call it. * If not, call a CPU-specific one @@ -107,10 +108,9 @@ static void eth_common_init(void) if (cpu_eth_init(gd->bd) < 0) printf("CPU Net Initialization Failed\n"); } else { -#ifndef CONFIG_DM_ETH printf("Net Initialization Skipped\n"); -#endif } +#endif }
#ifdef CONFIG_DM_ETH

Hi Simon,
On Mon, Jan 18, 2016 at 5:51 AM, Simon Glass sjg@chromium.org wrote:
We should avoid weak functions with driver model. Existing boards that use driver model don't need them, so let's kill them off.
Signed-off-by: Simon Glass sjg@chromium.org
net/eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/eth.c b/net/eth.c index 45fe6e3..d96d3a5 100644 --- a/net/eth.c +++ b/net/eth.c @@ -96,6 +96,7 @@ static void eth_common_init(void) phy_init(); #endif
+#ifndef CONFIG_DM_ETH /* * If board-specific initialization exists, call it. * If not, call a CPU-specific one @@ -107,10 +108,9 @@ static void eth_common_init(void) if (cpu_eth_init(gd->bd) < 0) printf("CPU Net Initialization Failed\n"); } else { -#ifndef CONFIG_DM_ETH printf("Net Initialization Skipped\n"); -#endif } +#endif }
#ifdef CONFIG_DM_ETH
I posted the same patch [1] before. But you and Joe mentioned that this is still needed on some cases. And even if it is not needed, we may still have a chance to insert some board-specific stuff into these two routines.
[1] http://patchwork.ozlabs.org/patch/510391/
Regards, Bin

Hi Bin,
On 17 January 2016 at 20:25, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Mon, Jan 18, 2016 at 5:51 AM, Simon Glass sjg@chromium.org wrote:
We should avoid weak functions with driver model. Existing boards that use driver model don't need them, so let's kill them off.
Signed-off-by: Simon Glass sjg@chromium.org
net/eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/eth.c b/net/eth.c index 45fe6e3..d96d3a5 100644 --- a/net/eth.c +++ b/net/eth.c @@ -96,6 +96,7 @@ static void eth_common_init(void) phy_init(); #endif
+#ifndef CONFIG_DM_ETH /* * If board-specific initialization exists, call it. * If not, call a CPU-specific one @@ -107,10 +108,9 @@ static void eth_common_init(void) if (cpu_eth_init(gd->bd) < 0) printf("CPU Net Initialization Failed\n"); } else { -#ifndef CONFIG_DM_ETH printf("Net Initialization Skipped\n"); -#endif } +#endif }
#ifdef CONFIG_DM_ETH
I posted the same patch [1] before. But you and Joe mentioned that this is still needed on some cases. And even if it is not needed, we may still have a chance to insert some board-specific stuff into these two routines.
Well I think I was on your side :-) We really don't want this with driver model as calling weak functions is skirting around driver model. If there is a feature that is needed we should model it properly with a uclass (e.g. pinctrl, GPIOs).
Regards, Simon

Hi Simon,
On Mon, Jan 18, 2016 at 11:58 AM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 17 January 2016 at 20:25, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Mon, Jan 18, 2016 at 5:51 AM, Simon Glass sjg@chromium.org wrote:
We should avoid weak functions with driver model. Existing boards that use driver model don't need them, so let's kill them off.
Signed-off-by: Simon Glass sjg@chromium.org
net/eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/eth.c b/net/eth.c index 45fe6e3..d96d3a5 100644 --- a/net/eth.c +++ b/net/eth.c @@ -96,6 +96,7 @@ static void eth_common_init(void) phy_init(); #endif
+#ifndef CONFIG_DM_ETH /* * If board-specific initialization exists, call it. * If not, call a CPU-specific one @@ -107,10 +108,9 @@ static void eth_common_init(void) if (cpu_eth_init(gd->bd) < 0) printf("CPU Net Initialization Failed\n"); } else { -#ifndef CONFIG_DM_ETH printf("Net Initialization Skipped\n"); -#endif } +#endif }
#ifdef CONFIG_DM_ETH
I posted the same patch [1] before. But you and Joe mentioned that this is still needed on some cases. And even if it is not needed, we may still have a chance to insert some board-specific stuff into these two routines.
Well I think I was on your side :-) We really don't want this with driver model as calling weak functions is skirting around driver model. If there is a feature that is needed we should model it properly with a uclass (e.g. pinctrl, GPIOs).
OK, unless Joe has different opinion :)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Regards, Bin

On Sun, Jan 17, 2016 at 10:29 PM, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Mon, Jan 18, 2016 at 11:58 AM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 17 January 2016 at 20:25, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Mon, Jan 18, 2016 at 5:51 AM, Simon Glass sjg@chromium.org wrote:
We should avoid weak functions with driver model. Existing boards that use driver model don't need them, so let's kill them off.
Signed-off-by: Simon Glass sjg@chromium.org
net/eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/eth.c b/net/eth.c index 45fe6e3..d96d3a5 100644 --- a/net/eth.c +++ b/net/eth.c @@ -96,6 +96,7 @@ static void eth_common_init(void) phy_init(); #endif
+#ifndef CONFIG_DM_ETH /* * If board-specific initialization exists, call it. * If not, call a CPU-specific one @@ -107,10 +108,9 @@ static void eth_common_init(void) if (cpu_eth_init(gd->bd) < 0) printf("CPU Net Initialization Failed\n"); } else { -#ifndef CONFIG_DM_ETH printf("Net Initialization Skipped\n"); -#endif } +#endif }
#ifdef CONFIG_DM_ETH
I posted the same patch [1] before. But you and Joe mentioned that this is still needed on some cases. And even if it is not needed, we may still have a chance to insert some board-specific stuff into these two routines.
Well I think I was on your side :-) We really don't want this with driver model as calling weak functions is skirting around driver model. If there is a feature that is needed we should model it properly with a uclass (e.g. pinctrl, GPIOs).
OK, unless Joe has different opinion :)
Only problem I would have is if it is breaking other boards in the mean time until all clocking and pinmux stuff is supported... but like I said before (in your [1]), if a person finds they need this when porting an eth driver to DM and they don't have the needed other DM driver yet, this can easily be reverted when that situation comes up.
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Regards, Bin _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

On Sun, Jan 17, 2016 at 3:51 PM, Simon Glass sjg@chromium.org wrote:
We should avoid weak functions with driver model. Existing boards that use driver model don't need them, so let's kill them off.
Signed-off-by: Simon Glass sjg@chromium.org
Acked-by: Joe Hershberger joe.hershberger@ni.com


Only half of the init is actually common. Move that part into a new common file and call it from driver-model and legacy code. More common functions will be added in future patches.
Signed-off-by: Simon Glass sjg@chromium.org ---
net/Makefile | 1 + net/eth.c | 42 ++++++++++++++---------------------------- net/eth_common.c | 23 +++++++++++++++++++++++ net/eth_internal.h | 15 +++++++++++++++ 4 files changed, 53 insertions(+), 28 deletions(-) create mode 100644 net/eth_common.c create mode 100644 net/eth_internal.h
diff --git a/net/Makefile b/net/Makefile index e9cc8ad..b3a22c2 100644 --- a/net/Makefile +++ b/net/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_CMD_NET) += bootp.o obj-$(CONFIG_CMD_CDP) += cdp.o obj-$(CONFIG_CMD_DNS) += dns.o obj-$(CONFIG_CMD_NET) += eth.o +obj-$(CONFIG_CMD_NET) += eth_common.o obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o obj-$(CONFIG_CMD_NET) += net.o obj-$(CONFIG_CMD_NFS) += nfs.o diff --git a/net/eth.c b/net/eth.c index d96d3a5..602925d 100644 --- a/net/eth.c +++ b/net/eth.c @@ -16,6 +16,7 @@ #include <asm/errno.h> #include <dm/device-internal.h> #include <dm/uclass-internal.h> +#include "eth_internal.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -85,34 +86,6 @@ static int __def_eth_init(bd_t *bis) int cpu_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init"))); int board_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init")));
-static void eth_common_init(void) -{ - bootstage_mark(BOOTSTAGE_ID_NET_ETH_START); -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) - miiphy_init(); -#endif - -#ifdef CONFIG_PHYLIB - phy_init(); -#endif - -#ifndef CONFIG_DM_ETH - /* - * If board-specific initialization exists, call it. - * If not, call a CPU-specific one - */ - if (board_eth_init != __def_eth_init) { - 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(gd->bd) < 0) - printf("CPU Net Initialization Failed\n"); - } else { - printf("Net Initialization Skipped\n"); - } -#endif -} - #ifdef CONFIG_DM_ETH /** * struct eth_device_priv - private structure for each Ethernet device @@ -865,6 +838,19 @@ int eth_initialize(void) eth_devices = NULL; eth_current = NULL; eth_common_init(); + /* + * If board-specific initialization exists, call it. + * If not, call a CPU-specific one + */ + if (board_eth_init != __def_eth_init) { + 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(gd->bd) < 0) + printf("CPU Net Initialization Failed\n"); + } else { + printf("Net Initialization Skipped\n"); + }
if (!eth_devices) { puts("No ethernet found.\n"); diff --git a/net/eth_common.c b/net/eth_common.c new file mode 100644 index 0000000..ee0b6df --- /dev/null +++ b/net/eth_common.c @@ -0,0 +1,23 @@ +/* + * (C) Copyright 2001-2015 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Joe Hershberger, National Instruments + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <miiphy.h> +#include "eth_internal.h" + +void eth_common_init(void) +{ + bootstage_mark(BOOTSTAGE_ID_NET_ETH_START); +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) + miiphy_init(); +#endif + +#ifdef CONFIG_PHYLIB + phy_init(); +#endif +} diff --git a/net/eth_internal.h b/net/eth_internal.h new file mode 100644 index 0000000..e65d898 --- /dev/null +++ b/net/eth_internal.h @@ -0,0 +1,15 @@ +/* + * (C) Copyright 2001-2015 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Joe Hershberger, National Instruments + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __ETH_INTERNAL_H +#define __ETH_INTERNAL_H + +/* Do init that is common to driver model and legacy networking */ +void eth_common_init(void); + +#endif

On Mon, Jan 18, 2016 at 5:51 AM, Simon Glass sjg@chromium.org wrote:
Only half of the init is actually common. Move that part into a new common file and call it from driver-model and legacy code. More common functions will be added in future patches.
Signed-off-by: Simon Glass sjg@chromium.org
net/Makefile | 1 + net/eth.c | 42 ++++++++++++++---------------------------- net/eth_common.c | 23 +++++++++++++++++++++++ net/eth_internal.h | 15 +++++++++++++++ 4 files changed, 53 insertions(+), 28 deletions(-) create mode 100644 net/eth_common.c create mode 100644 net/eth_internal.h
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Sun, Jan 17, 2016 at 3:51 PM, Simon Glass sjg@chromium.org wrote:
Only half of the init is actually common. Move that part into a new common file and call it from driver-model and legacy code. More common functions will be added in future patches.
Signed-off-by: Simon Glass sjg@chromium.org
Acked-by: Joe Hershberger joe.hershberger@ni.com


Move the functions which set ethernet environment variables to the common file.
Signed-off-by: Simon Glass sjg@chromium.org ---
net/eth.c | 43 ------------------------------------------- net/eth_common.c | 43 +++++++++++++++++++++++++++++++++++++++++++ net/eth_internal.h | 16 ++++++++++++++++ 3 files changed, 59 insertions(+), 43 deletions(-)
diff --git a/net/eth.c b/net/eth.c index 602925d..af8fcae 100644 --- a/net/eth.c +++ b/net/eth.c @@ -20,49 +20,6 @@
DECLARE_GLOBAL_DATA_PTR;
-void eth_parse_enetaddr(const char *addr, uchar *enetaddr) -{ - char *end; - int i; - - for (i = 0; i < 6; ++i) { - enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0; - if (addr) - addr = (*end) ? end + 1 : end; - } -} - -int eth_getenv_enetaddr(const char *name, uchar *enetaddr) -{ - eth_parse_enetaddr(getenv(name), enetaddr); - return is_valid_ethaddr(enetaddr); -} - -int eth_setenv_enetaddr(const char *name, const uchar *enetaddr) -{ - char buf[20]; - - sprintf(buf, "%pM", enetaddr); - - return setenv(name, buf); -} - -int eth_getenv_enetaddr_by_index(const char *base_name, int index, - uchar *enetaddr) -{ - char enetvar[32]; - sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index); - return eth_getenv_enetaddr(enetvar, enetaddr); -} - -static inline int eth_setenv_enetaddr_by_index(const char *base_name, int index, - uchar *enetaddr) -{ - char enetvar[32]; - sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index); - return eth_setenv_enetaddr(enetvar, enetaddr); -} - static int eth_mac_skip(int index) { char enetvar[15]; diff --git a/net/eth_common.c b/net/eth_common.c index ee0b6df..3fa6d83 100644 --- a/net/eth_common.c +++ b/net/eth_common.c @@ -10,6 +10,49 @@ #include <miiphy.h> #include "eth_internal.h"
+void eth_parse_enetaddr(const char *addr, uchar *enetaddr) +{ + char *end; + int i; + + for (i = 0; i < 6; ++i) { + enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0; + if (addr) + addr = (*end) ? end + 1 : end; + } +} + +int eth_getenv_enetaddr(const char *name, uchar *enetaddr) +{ + eth_parse_enetaddr(getenv(name), enetaddr); + return is_valid_ethaddr(enetaddr); +} + +int eth_setenv_enetaddr(const char *name, const uchar *enetaddr) +{ + char buf[20]; + + sprintf(buf, "%pM", enetaddr); + + return setenv(name, buf); +} + +int eth_getenv_enetaddr_by_index(const char *base_name, int index, + uchar *enetaddr) +{ + char enetvar[32]; + sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index); + return eth_getenv_enetaddr(enetvar, enetaddr); +} + +int eth_setenv_enetaddr_by_index(const char *base_name, int index, + uchar *enetaddr) +{ + char enetvar[32]; + sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index); + return eth_setenv_enetaddr(enetvar, enetaddr); +} + void eth_common_init(void) { bootstage_mark(BOOTSTAGE_ID_NET_ETH_START); diff --git a/net/eth_internal.h b/net/eth_internal.h index e65d898..38d8420 100644 --- a/net/eth_internal.h +++ b/net/eth_internal.h @@ -12,4 +12,20 @@ /* Do init that is common to driver model and legacy networking */ void eth_common_init(void);
+/** + * eth_setenv_enetaddr_by_index() - set the MAC address envrionment variable + * + * This sets up an environment variable with the given MAC address (@enetaddr). + * The environment variable to be set is defined by <@base_name><@index>addr. + * If @index is 0 it is omitted. For common Ethernet this means ethaddr, + * eth1addr, etc. + * + * @base_name: Base name for variable, typically "eth" + * @index: Index of interface being updated (>=0) + * @enetaddr: Pointer to MAC address to put into the variable + * @return 0 if OK, other value on error + */ +int eth_setenv_enetaddr_by_index(const char *base_name, int index, + uchar *enetaddr); + #endif

Hi Simon,
On Mon, Jan 18, 2016 at 5:51 AM, Simon Glass sjg@chromium.org wrote:
Move the functions which set ethernet environment variables to the common file.
Signed-off-by: Simon Glass sjg@chromium.org
net/eth.c | 43 ------------------------------------------- net/eth_common.c | 43 +++++++++++++++++++++++++++++++++++++++++++ net/eth_internal.h | 16 ++++++++++++++++ 3 files changed, 59 insertions(+), 43 deletions(-)
diff --git a/net/eth.c b/net/eth.c index 602925d..af8fcae 100644 --- a/net/eth.c +++ b/net/eth.c @@ -20,49 +20,6 @@
DECLARE_GLOBAL_DATA_PTR;
-void eth_parse_enetaddr(const char *addr, uchar *enetaddr) -{
char *end;
int i;
for (i = 0; i < 6; ++i) {
enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0;
if (addr)
addr = (*end) ? end + 1 : end;
}
-}
-int eth_getenv_enetaddr(const char *name, uchar *enetaddr) -{
eth_parse_enetaddr(getenv(name), enetaddr);
return is_valid_ethaddr(enetaddr);
-}
-int eth_setenv_enetaddr(const char *name, const uchar *enetaddr) -{
char buf[20];
sprintf(buf, "%pM", enetaddr);
return setenv(name, buf);
-}
-int eth_getenv_enetaddr_by_index(const char *base_name, int index,
uchar *enetaddr)
-{
char enetvar[32];
sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index);
return eth_getenv_enetaddr(enetvar, enetaddr);
-}
-static inline int eth_setenv_enetaddr_by_index(const char *base_name, int index,
uchar *enetaddr)
-{
char enetvar[32];
sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index);
return eth_setenv_enetaddr(enetvar, enetaddr);
-}
static int eth_mac_skip(int index) { char enetvar[15]; diff --git a/net/eth_common.c b/net/eth_common.c index ee0b6df..3fa6d83 100644 --- a/net/eth_common.c +++ b/net/eth_common.c @@ -10,6 +10,49 @@ #include <miiphy.h> #include "eth_internal.h"
+void eth_parse_enetaddr(const char *addr, uchar *enetaddr) +{
char *end;
int i;
for (i = 0; i < 6; ++i) {
enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0;
if (addr)
addr = (*end) ? end + 1 : end;
}
+}
+int eth_getenv_enetaddr(const char *name, uchar *enetaddr) +{
eth_parse_enetaddr(getenv(name), enetaddr);
return is_valid_ethaddr(enetaddr);
+}
+int eth_setenv_enetaddr(const char *name, const uchar *enetaddr) +{
char buf[20];
sprintf(buf, "%pM", enetaddr);
return setenv(name, buf);
+}
+int eth_getenv_enetaddr_by_index(const char *base_name, int index,
uchar *enetaddr)
+{
char enetvar[32];
sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index);
return eth_getenv_enetaddr(enetvar, enetaddr);
+}
+int eth_setenv_enetaddr_by_index(const char *base_name, int index,
uchar *enetaddr)
+{
char enetvar[32];
sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index);
return eth_setenv_enetaddr(enetvar, enetaddr);
+}
void eth_common_init(void) { bootstage_mark(BOOTSTAGE_ID_NET_ETH_START); diff --git a/net/eth_internal.h b/net/eth_internal.h index e65d898..38d8420 100644 --- a/net/eth_internal.h +++ b/net/eth_internal.h @@ -12,4 +12,20 @@ /* Do init that is common to driver model and legacy networking */ void eth_common_init(void);
+/**
- eth_setenv_enetaddr_by_index() - set the MAC address envrionment variable
- This sets up an environment variable with the given MAC address (@enetaddr).
- The environment variable to be set is defined by <@base_name><@index>addr.
- If @index is 0 it is omitted. For common Ethernet this means ethaddr,
- eth1addr, etc.
- @base_name: Base name for variable, typically "eth"
- @index: Index of interface being updated (>=0)
- @enetaddr: Pointer to MAC address to put into the variable
- @return 0 if OK, other value on error
- */
+int eth_setenv_enetaddr_by_index(const char *base_name, int index,
uchar *enetaddr);
#endif
Could you add some comments about the other routines (eth_parse_enetaddr, eth_getenv_enetaddr, eth_setenv_enetaddr, eth_getenv_enetaddr_by_index)?
Regards, Bin

Hi Bin,
On Sun, Jan 17, 2016 at 10:41 PM, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Mon, Jan 18, 2016 at 5:51 AM, Simon Glass sjg@chromium.org wrote:
Move the functions which set ethernet environment variables to the common file.
Signed-off-by: Simon Glass sjg@chromium.org
net/eth.c | 43 ------------------------------------------- net/eth_common.c | 43 +++++++++++++++++++++++++++++++++++++++++++ net/eth_internal.h | 16 ++++++++++++++++ 3 files changed, 59 insertions(+), 43 deletions(-)
<snip>
diff --git a/net/eth_internal.h b/net/eth_internal.h index e65d898..38d8420 100644 --- a/net/eth_internal.h +++ b/net/eth_internal.h @@ -12,4 +12,20 @@ /* Do init that is common to driver model and legacy networking */ void eth_common_init(void);
+/**
- eth_setenv_enetaddr_by_index() - set the MAC address envrionment variable
- This sets up an environment variable with the given MAC address (@enetaddr).
- The environment variable to be set is defined by <@base_name><@index>addr.
- If @index is 0 it is omitted. For common Ethernet this means ethaddr,
- eth1addr, etc.
- @base_name: Base name for variable, typically "eth"
- @index: Index of interface being updated (>=0)
- @enetaddr: Pointer to MAC address to put into the variable
- @return 0 if OK, other value on error
- */
+int eth_setenv_enetaddr_by_index(const char *base_name, int index,
uchar *enetaddr);
#endif
Could you add some comments about the other routines (eth_parse_enetaddr, eth_getenv_enetaddr, eth_setenv_enetaddr, eth_getenv_enetaddr_by_index)?
That would be great, but those are already defined in include/net.h with poor / incomplete comments. I don't think fixing that *needs* to be part of this patch, but it would be welcomed.
Regards, Bin _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Hi Joe,
On Sat, Jan 23, 2016 at 6:32 AM, Joe Hershberger joe.hershberger@gmail.com wrote:
Hi Bin,
On Sun, Jan 17, 2016 at 10:41 PM, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Mon, Jan 18, 2016 at 5:51 AM, Simon Glass sjg@chromium.org wrote:
Move the functions which set ethernet environment variables to the common file.
Signed-off-by: Simon Glass sjg@chromium.org
net/eth.c | 43 ------------------------------------------- net/eth_common.c | 43 +++++++++++++++++++++++++++++++++++++++++++ net/eth_internal.h | 16 ++++++++++++++++ 3 files changed, 59 insertions(+), 43 deletions(-)
<snip>
diff --git a/net/eth_internal.h b/net/eth_internal.h index e65d898..38d8420 100644 --- a/net/eth_internal.h +++ b/net/eth_internal.h @@ -12,4 +12,20 @@ /* Do init that is common to driver model and legacy networking */ void eth_common_init(void);
+/**
- eth_setenv_enetaddr_by_index() - set the MAC address envrionment variable
- This sets up an environment variable with the given MAC address (@enetaddr).
- The environment variable to be set is defined by <@base_name><@index>addr.
- If @index is 0 it is omitted. For common Ethernet this means ethaddr,
- eth1addr, etc.
- @base_name: Base name for variable, typically "eth"
- @index: Index of interface being updated (>=0)
- @enetaddr: Pointer to MAC address to put into the variable
- @return 0 if OK, other value on error
- */
+int eth_setenv_enetaddr_by_index(const char *base_name, int index,
uchar *enetaddr);
#endif
Could you add some comments about the other routines (eth_parse_enetaddr, eth_getenv_enetaddr, eth_setenv_enetaddr, eth_getenv_enetaddr_by_index)?
That would be great, but those are already defined in include/net.h with poor / incomplete comments. I don't think fixing that *needs* to be part of this patch, but it would be welcomed.
Simon added comments for eth_setenv_enetaddr_by_index() which did not have any comments before, so I'd assume we should add comments for others in the same patch. Otherwise it looks odd to me.
Regards, Bin

On Sun, Jan 17, 2016 at 3:51 PM, Simon Glass sjg@chromium.org wrote:
Move the functions which set ethernet environment variables to the common file.
Signed-off-by: Simon Glass sjg@chromium.org
Acked-by: Joe Hershberger joe.hershberger@ni.com


Move eth_current_changed(), eth_set_current(), eth_mac_skip() and eth_get_name() into the common file.
Signed-off-by: Simon Glass sjg@chromium.org ---
net/eth.c | 108 ++--------------------------------------------------- net/eth_common.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++ net/eth_internal.h | 9 +++++ 3 files changed, 113 insertions(+), 104 deletions(-)
diff --git a/net/eth.c b/net/eth.c index af8fcae..907eb11 100644 --- a/net/eth.c +++ b/net/eth.c @@ -20,18 +20,6 @@
DECLARE_GLOBAL_DATA_PTR;
-static int eth_mac_skip(int index) -{ - char enetvar[15]; - char *skip_state; - - sprintf(enetvar, index ? "eth%dmacskip" : "ethmacskip", index); - skip_state = getenv(enetvar); - return skip_state != NULL; -} - -static void eth_current_changed(void); - /* * CPU and board-specific Ethernet initializations. Aliased function * signals caller to move on @@ -74,7 +62,7 @@ static struct eth_uclass_priv *eth_get_uclass_priv(void) return uc->priv; }
-static void eth_set_current_to_next(void) +void eth_set_current_to_next(void) { struct eth_uclass_priv *uc_priv;
@@ -107,7 +95,7 @@ struct udevice *eth_get_dev(void) * 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) +void eth_set_dev(struct udevice *dev) { if (dev && !device_active(dev)) { eth_errno = device_probe(dev); @@ -593,12 +581,12 @@ 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) +void eth_set_current_to_next(void) { eth_current = eth_current->next; }
-static void eth_set_dev(struct eth_device *dev) +void eth_set_dev(struct eth_device *dev) { eth_current = dev; } @@ -992,91 +980,3 @@ int eth_receive(void *packet, int length) return length; } #endif /* CONFIG_API */ - -static void eth_current_changed(void) -{ - char *act = getenv("ethact"); - char *ethrotate; - - /* - * The call to eth_get_dev() below has a side effect of rotating - * ethernet device if uc_priv->current == NULL. This is not what - * we want when 'ethrotate' variable is 'no'. - */ - ethrotate = getenv("ethrotate"); - if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0)) - return; - - /* 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 void *first_failed; - char *ethrotate; - - /* - * Do not rotate between network interfaces when - * 'ethrotate' variable is set to 'no'. - */ - ethrotate = getenv("ethrotate"); - if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0)) - return; - - if (!eth_get_dev()) - return; - - if (first_restart) - first_failed = eth_get_dev(); - - eth_set_current_to_next(); - - eth_current_changed(); - - if (first_failed == eth_get_dev()) - net_restart_wrap = 1; -} - -void eth_set_current(void) -{ - static char *act; - static int env_changed_id; - int env_id; - - env_id = get_env_id(); - if ((act == NULL) || (env_changed_id != env_id)) { - act = getenv("ethact"); - env_changed_id = env_id; - } - - 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(); -} - -const char *eth_get_name(void) -{ - return eth_get_dev() ? eth_get_dev()->name : "unknown"; -} diff --git a/net/eth_common.c b/net/eth_common.c index 3fa6d83..2880901 100644 --- a/net/eth_common.c +++ b/net/eth_common.c @@ -7,7 +7,9 @@ */
#include <common.h> +#include <dm.h> #include <miiphy.h> +#include <net.h> #include "eth_internal.h"
void eth_parse_enetaddr(const char *addr, uchar *enetaddr) @@ -64,3 +66,101 @@ void eth_common_init(void) phy_init(); #endif } + +int eth_mac_skip(int index) +{ + char enetvar[15]; + char *skip_state; + + sprintf(enetvar, index ? "eth%dmacskip" : "ethmacskip", index); + skip_state = getenv(enetvar); + return skip_state != NULL; +} + +void eth_current_changed(void) +{ + char *act = getenv("ethact"); + char *ethrotate; + + /* + * The call to eth_get_dev() below has a side effect of rotating + * ethernet device if uc_priv->current == NULL. This is not what + * we want when 'ethrotate' variable is 'no'. + */ + ethrotate = getenv("ethrotate"); + if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0)) + return; + + /* 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 void *first_failed; + char *ethrotate; + + /* + * Do not rotate between network interfaces when + * 'ethrotate' variable is set to 'no'. + */ + ethrotate = getenv("ethrotate"); + if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0)) + return; + + if (!eth_get_dev()) + return; + + if (first_restart) + first_failed = eth_get_dev(); + + eth_set_current_to_next(); + + eth_current_changed(); + + if (first_failed == eth_get_dev()) + net_restart_wrap = 1; +} + +void eth_set_current(void) +{ + static char *act; + static int env_changed_id; + int env_id; + + env_id = get_env_id(); + if ((act == NULL) || (env_changed_id != env_id)) { + act = getenv("ethact"); + env_changed_id = env_id; + } + + 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(); +} + +const char *eth_get_name(void) +{ + return eth_get_dev() ? eth_get_dev()->name : "unknown"; +} diff --git a/net/eth_internal.h b/net/eth_internal.h index 38d8420..6e4753c 100644 --- a/net/eth_internal.h +++ b/net/eth_internal.h @@ -28,4 +28,13 @@ void eth_common_init(void); int eth_setenv_enetaddr_by_index(const char *base_name, int index, uchar *enetaddr);
+int eth_mac_skip(int index); +void eth_current_changed(void); +#ifdef CONFIG_DM_ETH +void eth_set_dev(struct udevice *dev); +#else +void eth_set_dev(struct eth_device *dev); +#endif +void eth_set_current_to_next(void); + #endif

On Mon, Jan 18, 2016 at 5:51 AM, Simon Glass sjg@chromium.org wrote:
Move eth_current_changed(), eth_set_current(), eth_mac_skip() and eth_get_name() into the common file.
Signed-off-by: Simon Glass sjg@chromium.org
net/eth.c | 108 ++--------------------------------------------------- net/eth_common.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++ net/eth_internal.h | 9 +++++ 3 files changed, 113 insertions(+), 104 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Sun, Jan 17, 2016 at 3:51 PM, Simon Glass sjg@chromium.org wrote:
Move eth_current_changed(), eth_set_current(), eth_mac_skip() and eth_get_name() into the common file.
Signed-off-by: Simon Glass sjg@chromium.org
net/eth.c | 108 ++--------------------------------------------------- net/eth_common.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++ net/eth_internal.h | 9 +++++ 3 files changed, 113 insertions(+), 104 deletions(-)
diff --git a/net/eth.c b/net/eth.c index af8fcae..907eb11 100644 --- a/net/eth.c +++ b/net/eth.c @@ -20,18 +20,6 @@
DECLARE_GLOBAL_DATA_PTR;
-static int eth_mac_skip(int index) -{
char enetvar[15];
char *skip_state;
sprintf(enetvar, index ? "eth%dmacskip" : "ethmacskip", index);
skip_state = getenv(enetvar);
return skip_state != NULL;
-}
-static void eth_current_changed(void);
/*
- CPU and board-specific Ethernet initializations. Aliased function
- signals caller to move on
@@ -74,7 +62,7 @@ static struct eth_uclass_priv *eth_get_uclass_priv(void) return uc->priv; }
-static void eth_set_current_to_next(void) +void eth_set_current_to_next(void) { struct eth_uclass_priv *uc_priv;
@@ -107,7 +95,7 @@ struct udevice *eth_get_dev(void)
- 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) +void eth_set_dev(struct udevice *dev) { if (dev && !device_active(dev)) { eth_errno = device_probe(dev); @@ -593,12 +581,12 @@ 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) +void eth_set_current_to_next(void) { eth_current = eth_current->next; }
-static void eth_set_dev(struct eth_device *dev) +void eth_set_dev(struct eth_device *dev) { eth_current = dev; } @@ -992,91 +980,3 @@ int eth_receive(void *packet, int length) return length; } #endif /* CONFIG_API */
-static void eth_current_changed(void) -{
char *act = getenv("ethact");
char *ethrotate;
/*
* The call to eth_get_dev() below has a side effect of rotating
* ethernet device if uc_priv->current == NULL. This is not what
* we want when 'ethrotate' variable is 'no'.
*/
ethrotate = getenv("ethrotate");
if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
return;
/* 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 void *first_failed;
char *ethrotate;
/*
* Do not rotate between network interfaces when
* 'ethrotate' variable is set to 'no'.
*/
ethrotate = getenv("ethrotate");
if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
return;
if (!eth_get_dev())
return;
if (first_restart)
first_failed = eth_get_dev();
eth_set_current_to_next();
eth_current_changed();
if (first_failed == eth_get_dev())
net_restart_wrap = 1;
-}
-void eth_set_current(void) -{
static char *act;
static int env_changed_id;
int env_id;
env_id = get_env_id();
if ((act == NULL) || (env_changed_id != env_id)) {
act = getenv("ethact");
env_changed_id = env_id;
}
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();
-}
-const char *eth_get_name(void) -{
return eth_get_dev() ? eth_get_dev()->name : "unknown";
-} diff --git a/net/eth_common.c b/net/eth_common.c index 3fa6d83..2880901 100644 --- a/net/eth_common.c +++ b/net/eth_common.c @@ -7,7 +7,9 @@ */
#include <common.h> +#include <dm.h>
Why would common code need the DM header?
#include <miiphy.h> +#include <net.h> #include "eth_internal.h"
void eth_parse_enetaddr(const char *addr, uchar *enetaddr) @@ -64,3 +66,101 @@ void eth_common_init(void) phy_init(); #endif }
+int eth_mac_skip(int index) +{
char enetvar[15];
char *skip_state;
sprintf(enetvar, index ? "eth%dmacskip" : "ethmacskip", index);
skip_state = getenv(enetvar);
return skip_state != NULL;
+}
+void eth_current_changed(void) +{
char *act = getenv("ethact");
char *ethrotate;
/*
* The call to eth_get_dev() below has a side effect of rotating
* ethernet device if uc_priv->current == NULL. This is not what
* we want when 'ethrotate' variable is 'no'.
*/
ethrotate = getenv("ethrotate");
if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
return;
/* 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 void *first_failed;
char *ethrotate;
/*
* Do not rotate between network interfaces when
* 'ethrotate' variable is set to 'no'.
*/
ethrotate = getenv("ethrotate");
if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
return;
if (!eth_get_dev())
return;
if (first_restart)
first_failed = eth_get_dev();
eth_set_current_to_next();
eth_current_changed();
if (first_failed == eth_get_dev())
net_restart_wrap = 1;
+}
+void eth_set_current(void) +{
static char *act;
static int env_changed_id;
int env_id;
env_id = get_env_id();
if ((act == NULL) || (env_changed_id != env_id)) {
act = getenv("ethact");
env_changed_id = env_id;
}
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();
+}
+const char *eth_get_name(void) +{
return eth_get_dev() ? eth_get_dev()->name : "unknown";
+} diff --git a/net/eth_internal.h b/net/eth_internal.h index 38d8420..6e4753c 100644 --- a/net/eth_internal.h +++ b/net/eth_internal.h @@ -28,4 +28,13 @@ void eth_common_init(void); int eth_setenv_enetaddr_by_index(const char *base_name, int index, uchar *enetaddr);
+int eth_mac_skip(int index); +void eth_current_changed(void); +#ifdef CONFIG_DM_ETH +void eth_set_dev(struct udevice *dev);
Seems like the DM header should be included in this header, since this is likely the source of the need.
+#else +void eth_set_dev(struct eth_device *dev); +#endif +void eth_set_current_to_next(void);
#endif
Otherwise...
Acked-by: Joe Hershberger joe.hershberger@ni.com


Every other uclass is in its own file. Create a new eth-uclass.c file and move the driver-model code into it, so that networking is consistent.
Signed-off-by: Simon Glass sjg@chromium.org ---
net/Makefile | 4 + net/eth-uclass.c | 549 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ net/eth.c | 543 ------------------------------------------------------ 3 files changed, 553 insertions(+), 543 deletions(-) create mode 100644 net/eth-uclass.c
diff --git a/net/Makefile b/net/Makefile index b3a22c2..943de14 100644 --- a/net/Makefile +++ b/net/Makefile @@ -12,7 +12,11 @@ obj-$(CONFIG_CMD_NET) += arp.o obj-$(CONFIG_CMD_NET) += bootp.o obj-$(CONFIG_CMD_CDP) += cdp.o obj-$(CONFIG_CMD_DNS) += dns.o +ifdef CONFIG_DM_ETH +obj-$(CONFIG_CMD_NET) += eth-uclass.o +else obj-$(CONFIG_CMD_NET) += eth.o +endif obj-$(CONFIG_CMD_NET) += eth_common.o obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o obj-$(CONFIG_CMD_NET) += net.o diff --git a/net/eth-uclass.c b/net/eth-uclass.c new file mode 100644 index 0000000..a356a08 --- /dev/null +++ b/net/eth-uclass.c @@ -0,0 +1,549 @@ +/* + * (C) Copyright 2001-2015 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Joe Hershberger, National Instruments + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <environment.h> +#include <net.h> +#include <dm/device-internal.h> +#include <dm/uclass-internal.h> +#include "eth_internal.h" + +/** + * 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; +}; + +/* 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; + + uclass_get(UCLASS_ETH, &uc); + assert(uc); + return uc->priv; +} + +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); +} + +/* + * 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) + 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. + */ +void eth_set_dev(struct udevice *dev) +{ + if (dev && !device_active(dev)) { + eth_errno = device_probe(dev); + if (eth_errno) + dev = NULL; + } + + 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; + int len = strlen("eth"); + + /* Must be longer than 3 to be an alias */ + if (!strncmp(devname, "eth", len) && strlen(devname) > len) { + startp = devname + len; + seq = simple_strtoul(startp, &endp, 10); + } + + uclass_get(UCLASS_ETH, &uc); + uclass_foreach_dev(it, uc) { + /* + * 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(). + */ + if (device_probe(it)) + continue; + /* 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; + + 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; +} + +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_ethaddr(pdata->enetaddr)) { + printf("\nError: %s address %pM illegal value\n", + dev->name, pdata->enetaddr); + return -EINVAL; + } + + /* + * Drivers are allowed to decide not to implement this at + * run-time. E.g. Some devices may use it and some may not. + */ + ret = eth_get_ops(dev)->write_hwaddr(dev); + if (ret == -ENOSYS) + ret = 0; + if (ret) + printf("\nWarning: %s failed to set MAC address\n", + dev->name); + } + + return ret; +} + +static int on_ethaddr(const char *name, const char *value, enum env_op op, + int flags) +{ + int index; + int retval; + struct udevice *dev; + + /* look for an index after "eth" */ + index = simple_strtoul(name + 3, NULL, 10); + + retval = uclass_find_device_by_seq(UCLASS_ETH, index, false, &dev); + if (!retval) { + struct eth_pdata *pdata = dev->platdata; + switch (op) { + case env_op_create: + case env_op_overwrite: + eth_parse_enetaddr(value, pdata->enetaddr); + break; + case env_op_delete: + memset(pdata->enetaddr, 0, 6); + } + } + + return 0; +} +U_BOOT_ENV_CALLBACK(ethaddr, on_ethaddr); + +int eth_init(void) +{ + char *ethact = getenv("ethact"); + char *ethrotate = getenv("ethrotate"); + struct udevice *current = NULL; + struct udevice *old_current; + int ret = -ENODEV; + + /* + * When 'ethrotate' variable is set to 'no' and 'ethact' variable + * is already set to an ethernet device, we should stick to 'ethact'. + */ + if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0)) { + if (ethact) { + current = eth_get_dev_by_name(ethact); + if (!current) + return -EINVAL; + } + } + + if (!current) { + current = eth_get_dev(); + if (!current) { + printf("No ethernet found.\n"); + return -ENODEV; + } + } + + old_current = current; + do { + if (current) { + debug("Trying %s\n", current->name); + + if (device_active(current)) { + 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"); + } else { + debug("PROBE FAIL\n"); + } + + /* + * 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 ret; +} + +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_is_active(struct udevice *dev) +{ + struct eth_device_priv *priv; + + if (!dev || !device_active(dev)) + return 0; + + priv = dev_get_uclass_priv(dev); + return priv->state == ETH_STATE_ACTIVE; +} + +int eth_send(void *packet, int length) +{ + struct udevice *current; + int ret; + + current = eth_get_dev(); + if (!current) + return -ENODEV; + + if (!device_active(current)) + return -EINVAL; + + 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) +{ + struct udevice *current; + uchar *packet; + int flags; + int ret; + int i; + + current = eth_get_dev(); + if (!current) + return -ENODEV; + + if (!device_active(current)) + return -EINVAL; + + /* Process up to 32 packets at one time */ + flags = ETH_RECV_CHECK_DEVICE; + for (i = 0; i < 32; i++) { + ret = eth_get_ops(current)->recv(current, flags, &packet); + flags = 0; + if (ret > 0) + net_process_received_packet(packet, ret); + if (ret >= 0 && eth_get_ops(current)->free_pkt) + eth_get_ops(current)->free_pkt(current, packet, ret); + if (ret <= 0) + break; + } + if (ret == -EAGAIN) + ret = 0; + if (ret < 0) { + /* We cannot completely return the error at present */ + debug("%s: recv() returned error %d\n", __func__, ret); + } + return ret; +} + +int eth_initialize(void) +{ + int num_devices = 0; + struct udevice *dev; + + eth_common_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 { + 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) + printf(", "); + + printf("eth%d: %s", dev->seq, dev->name); + + if (ethprime && dev == prime_dev) + printf(" [PRIME]"); + + 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]; + +#if defined(CONFIG_NEEDS_MANUAL_RELOC) + struct eth_ops *ops = eth_get_ops(dev); + static int reloc_done; + + if (!reloc_done) { + if (ops->start) + ops->start += gd->reloc_off; + if (ops->send) + ops->send += gd->reloc_off; + if (ops->recv) + ops->recv += gd->reloc_off; + if (ops->free_pkt) + ops->free_pkt += gd->reloc_off; + if (ops->stop) + ops->stop += gd->reloc_off; +#ifdef CONFIG_MCAST_TFTP + if (ops->mcast) + ops->mcast += gd->reloc_off; +#endif + if (ops->write_hwaddr) + ops->write_hwaddr += gd->reloc_off; + if (ops->read_rom_hwaddr) + ops->read_rom_hwaddr += gd->reloc_off; + + reloc_done++; + } +#endif + + 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_ethaddr(env_enetaddr)) { + if (!is_zero_ethaddr(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_ethaddr(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_ethaddr(pdata->enetaddr)) { +#ifdef CONFIG_NET_RANDOM_ETHADDR + net_random_ethaddr(pdata->enetaddr); + printf("\nWarning: %s (eth%d) using random MAC address - %pM\n", + dev->name, dev->seq, pdata->enetaddr); +#else + printf("\nError: %s address not set.\n", + dev->name); + return -EINVAL; +#endif + } + + return 0; +} + +static int eth_pre_remove(struct udevice *dev) +{ + struct eth_pdata *pdata = dev->platdata; + + eth_get_ops(dev)->stop(dev); + + /* clear the MAC address */ + memset(pdata->enetaddr, 0, 6); + + 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), + .flags = DM_UC_FLAG_SEQ_ALIAS, +}; diff --git a/net/eth.c b/net/eth.c index 907eb11..bdcd6ea 100644 --- a/net/eth.c +++ b/net/eth.c @@ -8,14 +8,10 @@
#include <common.h> #include <command.h> -#include <dm.h> #include <environment.h> #include <net.h> -#include <miiphy.h> #include <phy.h> #include <asm/errno.h> -#include <dm/device-internal.h> -#include <dm/uclass-internal.h> #include "eth_internal.h"
DECLARE_GLOBAL_DATA_PTR; @@ -31,544 +27,6 @@ static int __def_eth_init(bd_t *bis) int cpu_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init"))); int board_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init")));
-#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; -}; - -/* 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; - - uclass_get(UCLASS_ETH, &uc); - assert(uc); - return uc->priv; -} - -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); -} - -/* - * 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) - 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. - */ -void eth_set_dev(struct udevice *dev) -{ - if (dev && !device_active(dev)) { - eth_errno = device_probe(dev); - if (eth_errno) - dev = NULL; - } - - 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; - int len = strlen("eth"); - - /* Must be longer than 3 to be an alias */ - if (!strncmp(devname, "eth", len) && strlen(devname) > len) { - startp = devname + len; - seq = simple_strtoul(startp, &endp, 10); - } - - uclass_get(UCLASS_ETH, &uc); - uclass_foreach_dev(it, uc) { - /* - * 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(). - */ - if (device_probe(it)) - continue; - /* 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; - - 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; -} - -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_ethaddr(pdata->enetaddr)) { - printf("\nError: %s address %pM illegal value\n", - dev->name, pdata->enetaddr); - return -EINVAL; - } - - /* - * Drivers are allowed to decide not to implement this at - * run-time. E.g. Some devices may use it and some may not. - */ - ret = eth_get_ops(dev)->write_hwaddr(dev); - if (ret == -ENOSYS) - ret = 0; - if (ret) - printf("\nWarning: %s failed to set MAC address\n", - dev->name); - } - - return ret; -} - -static int on_ethaddr(const char *name, const char *value, enum env_op op, - int flags) -{ - int index; - int retval; - struct udevice *dev; - - /* look for an index after "eth" */ - index = simple_strtoul(name + 3, NULL, 10); - - retval = uclass_find_device_by_seq(UCLASS_ETH, index, false, &dev); - if (!retval) { - struct eth_pdata *pdata = dev->platdata; - switch (op) { - case env_op_create: - case env_op_overwrite: - eth_parse_enetaddr(value, pdata->enetaddr); - break; - case env_op_delete: - memset(pdata->enetaddr, 0, 6); - } - } - - return 0; -} -U_BOOT_ENV_CALLBACK(ethaddr, on_ethaddr); - -int eth_init(void) -{ - char *ethact = getenv("ethact"); - char *ethrotate = getenv("ethrotate"); - struct udevice *current = NULL; - struct udevice *old_current; - int ret = -ENODEV; - - /* - * When 'ethrotate' variable is set to 'no' and 'ethact' variable - * is already set to an ethernet device, we should stick to 'ethact'. - */ - if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0)) { - if (ethact) { - current = eth_get_dev_by_name(ethact); - if (!current) - return -EINVAL; - } - } - - if (!current) { - current = eth_get_dev(); - if (!current) { - printf("No ethernet found.\n"); - return -ENODEV; - } - } - - old_current = current; - do { - if (current) { - debug("Trying %s\n", current->name); - - if (device_active(current)) { - 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"); - } else { - debug("PROBE FAIL\n"); - } - - /* - * 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 ret; -} - -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_is_active(struct udevice *dev) -{ - struct eth_device_priv *priv; - - if (!dev || !device_active(dev)) - return 0; - - priv = dev_get_uclass_priv(dev); - return priv->state == ETH_STATE_ACTIVE; -} - -int eth_send(void *packet, int length) -{ - struct udevice *current; - int ret; - - current = eth_get_dev(); - if (!current) - return -ENODEV; - - if (!device_active(current)) - return -EINVAL; - - 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) -{ - struct udevice *current; - uchar *packet; - int flags; - int ret; - int i; - - current = eth_get_dev(); - if (!current) - return -ENODEV; - - if (!device_active(current)) - return -EINVAL; - - /* Process up to 32 packets at one time */ - flags = ETH_RECV_CHECK_DEVICE; - for (i = 0; i < 32; i++) { - ret = eth_get_ops(current)->recv(current, flags, &packet); - flags = 0; - if (ret > 0) - net_process_received_packet(packet, ret); - if (ret >= 0 && eth_get_ops(current)->free_pkt) - eth_get_ops(current)->free_pkt(current, packet, ret); - if (ret <= 0) - break; - } - if (ret == -EAGAIN) - ret = 0; - if (ret < 0) { - /* We cannot completely return the error at present */ - debug("%s: recv() returned error %d\n", __func__, ret); - } - return ret; -} - -int eth_initialize(void) -{ - int num_devices = 0; - struct udevice *dev; - - eth_common_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 { - 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) - printf(", "); - - printf("eth%d: %s", dev->seq, dev->name); - - if (ethprime && dev == prime_dev) - printf(" [PRIME]"); - - 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]; - -#if defined(CONFIG_NEEDS_MANUAL_RELOC) - struct eth_ops *ops = eth_get_ops(dev); - static int reloc_done; - - if (!reloc_done) { - if (ops->start) - ops->start += gd->reloc_off; - if (ops->send) - ops->send += gd->reloc_off; - if (ops->recv) - ops->recv += gd->reloc_off; - if (ops->free_pkt) - ops->free_pkt += gd->reloc_off; - if (ops->stop) - ops->stop += gd->reloc_off; -#ifdef CONFIG_MCAST_TFTP - if (ops->mcast) - ops->mcast += gd->reloc_off; -#endif - if (ops->write_hwaddr) - ops->write_hwaddr += gd->reloc_off; - if (ops->read_rom_hwaddr) - ops->read_rom_hwaddr += gd->reloc_off; - - reloc_done++; - } -#endif - - 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_ethaddr(env_enetaddr)) { - if (!is_zero_ethaddr(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_ethaddr(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_ethaddr(pdata->enetaddr)) { -#ifdef CONFIG_NET_RANDOM_ETHADDR - net_random_ethaddr(pdata->enetaddr); - printf("\nWarning: %s (eth%d) using random MAC address - %pM\n", - dev->name, dev->seq, pdata->enetaddr); -#else - printf("\nError: %s address not set.\n", - dev->name); - return -EINVAL; -#endif - } - - return 0; -} - -static int eth_pre_remove(struct udevice *dev) -{ - struct eth_pdata *pdata = dev->platdata; - - eth_get_ops(dev)->stop(dev); - - /* clear the MAC address */ - memset(pdata->enetaddr, 0, 6); - - 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), - .flags = DM_UC_FLAG_SEQ_ALIAS, -}; -#endif /* #ifdef CONFIG_DM_ETH */ - -#ifndef CONFIG_DM_ETH - #ifdef CONFIG_API static struct { uchar data[PKTSIZE]; @@ -935,7 +393,6 @@ 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)

On Mon, Jan 18, 2016 at 5:52 AM, Simon Glass sjg@chromium.org wrote:
Every other uclass is in its own file. Create a new eth-uclass.c file and move the driver-model code into it, so that networking is consistent.
Signed-off-by: Simon Glass sjg@chromium.org
net/Makefile | 4 + net/eth-uclass.c | 549 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ net/eth.c | 543 ------------------------------------------------------ 3 files changed, 553 insertions(+), 543 deletions(-) create mode 100644 net/eth-uclass.c
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Sun, Jan 17, 2016 at 3:52 PM, Simon Glass sjg@chromium.org wrote:
Every other uclass is in its own file. Create a new eth-uclass.c file and move the driver-model code into it, so that networking is consistent.
Signed-off-by: Simon Glass sjg@chromium.org
Acked-by: Joe Hershberger joe.hershberger@ni.com


Rename this file to make it clear it is for the old networking drivers and not for use with driver model.
Signed-off-by: Simon Glass sjg@chromium.org ---
net/Makefile | 2 +- net/{eth.c => eth_legacy.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename net/{eth.c => eth_legacy.c} (100%)
diff --git a/net/Makefile b/net/Makefile index 943de14..f03d608 100644 --- a/net/Makefile +++ b/net/Makefile @@ -15,7 +15,7 @@ obj-$(CONFIG_CMD_DNS) += dns.o ifdef CONFIG_DM_ETH obj-$(CONFIG_CMD_NET) += eth-uclass.o else -obj-$(CONFIG_CMD_NET) += eth.o +obj-$(CONFIG_CMD_NET) += eth_legacy.o endif obj-$(CONFIG_CMD_NET) += eth_common.o obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o diff --git a/net/eth.c b/net/eth_legacy.c similarity index 100% rename from net/eth.c rename to net/eth_legacy.c

On Mon, Jan 18, 2016 at 5:52 AM, Simon Glass sjg@chromium.org wrote:
Rename this file to make it clear it is for the old networking drivers and not for use with driver model.
Signed-off-by: Simon Glass sjg@chromium.org
net/Makefile | 2 +- net/{eth.c => eth_legacy.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename net/{eth.c => eth_legacy.c} (100%)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Sun, Jan 17, 2016 at 3:52 PM, Simon Glass sjg@chromium.org wrote:
Rename this file to make it clear it is for the old networking drivers and not for use with driver model.
Signed-off-by: Simon Glass sjg@chromium.org
Acked-by: Joe Hershberger joe.hershberger@ni.com


Some ethernet devices may be on a PCI bus. Probe the first PCI controller to find these, so that ethernet init will complete correctly.
Signed-off-by: Simon Glass sjg@chromium.org ---
net/eth-uclass.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/net/eth-uclass.c b/net/eth-uclass.c index a356a08..817c6e0 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -383,7 +383,12 @@ int eth_initialize(void) { int num_devices = 0; struct udevice *dev; +#ifdef CONFIG_DM_PCI + struct udevice *pci_dev;
+ /* Start PCI since it may have a network interface */ + uclass_first_device(UCLASS_PCI, &pci_dev); +#endif eth_common_init();
/*

Hi Simon,
On Mon, Jan 18, 2016 at 5:52 AM, Simon Glass sjg@chromium.org wrote:
Some ethernet devices may be on a PCI bus. Probe the first PCI controller to find these, so that ethernet init will complete correctly.
Signed-off-by: Simon Glass sjg@chromium.org
net/eth-uclass.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/net/eth-uclass.c b/net/eth-uclass.c index a356a08..817c6e0 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -383,7 +383,12 @@ int eth_initialize(void) { int num_devices = 0; struct udevice *dev; +#ifdef CONFIG_DM_PCI
struct udevice *pci_dev;
/* Start PCI since it may have a network interface */
uclass_first_device(UCLASS_PCI, &pci_dev);
+#endif
Why do we need this? With driver model, the PCI will be automatically started, see eth_designware.c which supports both PCI and non-PCI variants.
eth_common_init(); /*
--
Regards, Bin

On Sun, Jan 17, 2016 at 3:52 PM, Simon Glass sjg@chromium.org wrote:
Some ethernet devices may be on a PCI bus. Probe the first PCI controller to find these, so that ethernet init will complete correctly.
Signed-off-by: Simon Glass sjg@chromium.org
net/eth-uclass.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/net/eth-uclass.c b/net/eth-uclass.c index a356a08..817c6e0 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -383,7 +383,12 @@ int eth_initialize(void) { int num_devices = 0; struct udevice *dev; +#ifdef CONFIG_DM_PCI
struct udevice *pci_dev;
/* Start PCI since it may have a network interface */
uclass_first_device(UCLASS_PCI, &pci_dev);
I see this is still under discussion, so it probably makes sense to leave it off of this series.
+#endif eth_common_init();
/*
-- 2.6.0.rc2.230.g3dd15c0
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

On Fri, Jan 22, 2016 at 4:42 PM, Joe Hershberger joe.hershberger@gmail.com wrote:
On Sun, Jan 17, 2016 at 3:52 PM, Simon Glass sjg@chromium.org wrote:
Some ethernet devices may be on a PCI bus. Probe the first PCI controller to find these, so that ethernet init will complete correctly.
Signed-off-by: Simon Glass sjg@chromium.org
net/eth-uclass.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/net/eth-uclass.c b/net/eth-uclass.c index a356a08..817c6e0 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -383,7 +383,12 @@ int eth_initialize(void) { int num_devices = 0; struct udevice *dev; +#ifdef CONFIG_DM_PCI
struct udevice *pci_dev;
/* Start PCI since it may have a network interface */
uclass_first_device(UCLASS_PCI, &pci_dev);
I see this is still under discussion, so it probably makes sense to leave it off of this series.
Any update on this?
+#endif eth_common_init();
/*
-- 2.6.0.rc2.230.g3dd15c0
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Hi,
On 26 April 2016 at 13:32, Joe Hershberger joe.hershberger@gmail.com wrote:
On Fri, Jan 22, 2016 at 4:42 PM, Joe Hershberger joe.hershberger@gmail.com wrote:
On Sun, Jan 17, 2016 at 3:52 PM, Simon Glass sjg@chromium.org wrote:
Some ethernet devices may be on a PCI bus. Probe the first PCI controller to find these, so that ethernet init will complete correctly.
Signed-off-by: Simon Glass sjg@chromium.org
net/eth-uclass.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/net/eth-uclass.c b/net/eth-uclass.c index a356a08..817c6e0 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -383,7 +383,12 @@ int eth_initialize(void) { int num_devices = 0; struct udevice *dev; +#ifdef CONFIG_DM_PCI
struct udevice *pci_dev;
/* Start PCI since it may have a network interface */
uclass_first_device(UCLASS_PCI, &pci_dev);
I see this is still under discussion, so it probably makes sense to leave it off of this series.
Any update on this?
Not from my side. The PCI network driver will only be probed if it is mentioned in the device tree. Perhaps this is good practice in an embedded system. But there may be cases where someone adds a network card without a device tree node. In that case we can only find out about the network card's existence by probing PCI (or USB if it is a USB Ethernet device, etc.).
So I think we need to figure this out out. I'm OK with the solution I proposed, or if there is a better and more general method (such as allowing a board to mark which hot-pluggable buses must be scanned to find devices) then we could go that way.
Regards, Simon
participants (4)
-
Bin Meng
-
Joe Hershberger
-
Joe Hershberger
-
Simon Glass