From b2f58d8ee090ccf15b1366ac46a075c02a01f4fc Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Mon, 2 Jul 2018 20:06:48 -0500 Subject: console: Remember if ctrlc is disabled in console_tstc() We don't necessarily want to re-enable ctrl-c if it was already disabled when calling tstc(). Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass --- common/console.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/common/console.c b/common/console.c index 2ba33dc5740..36c0568dbff 100644 --- a/common/console.c +++ b/common/console.c @@ -196,20 +196,21 @@ static int console_tstc(int file) { int i, ret; struct stdio_dev *dev; + int prev; - disable_ctrlc(1); + prev = disable_ctrlc(1); for (i = 0; i < cd_count[file]; i++) { dev = console_devices[file][i]; if (dev->tstc != NULL) { ret = dev->tstc(dev); if (ret > 0) { tstcdev = dev; - disable_ctrlc(0); + disable_ctrlc(prev); return ret; } } } - disable_ctrlc(0); + disable_ctrlc(prev); return 0; } -- cgit v1.2.3 From 82a115fdec875d7e8dc601fe0e1b12859814c91c Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Mon, 2 Jul 2018 20:06:49 -0500 Subject: sandbox: Don't disable ctrlc() on sandbox if in raw mode In raw mode, handle ctrl-c as normal. This allows normal ctrl-c behavior such as aborting a command that is timing out without completely terminating the sandbox executable. In [1], Simon disabled this. His reason for it was that it interferes with piping test scripts. Piping should be done in cooked mode, so this change should still not interfere. [1] commit 8969ea3e9f2db04a6b3675 ("sandbox: Disable Ctrl-C") Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass --- common/console.c | 2 -- drivers/serial/sandbox.c | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/common/console.c b/common/console.c index 36c0568dbff..7aa58d0a636 100644 --- a/common/console.c +++ b/common/console.c @@ -604,7 +604,6 @@ static int ctrlc_disabled = 0; /* see disable_ctrl() */ static int ctrlc_was_pressed = 0; int ctrlc(void) { -#ifndef CONFIG_SANDBOX if (!ctrlc_disabled && gd->have_console) { if (tstc()) { switch (getc()) { @@ -616,7 +615,6 @@ int ctrlc(void) } } } -#endif return 0; } diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c index d2e007284c4..a60dabe5883 100644 --- a/drivers/serial/sandbox.c +++ b/drivers/serial/sandbox.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include @@ -69,6 +70,9 @@ static int sandbox_serial_probe(struct udevice *dev) os_tty_raw(0, state->term_raw == STATE_TERM_RAW_WITH_SIGS); priv->start_of_line = 0; + if (state->term_raw != STATE_TERM_RAW) + disable_ctrlc(1); + return 0; } -- cgit v1.2.3 From 97367df109b845d0bd93eef3f507d259668e8843 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Mon, 2 Jul 2018 14:47:44 -0500 Subject: sandbox: eth-raw: Correct valid socket test in send/recv In open, the socket is correctly checked to be -1 in the error case. In send and recv, we checked for 0, but that is a valid socket number. Correct this by checking for -1 as a bad socket everywhere. Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass --- arch/sandbox/cpu/eth-raw-os.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c index e054a0702a6..61f23ed2104 100644 --- a/arch/sandbox/cpu/eth-raw-os.c +++ b/arch/sandbox/cpu/eth-raw-os.c @@ -156,7 +156,7 @@ int sandbox_eth_raw_os_send(void *packet, int length, int retval; struct udphdr *udph = packet + sizeof(struct iphdr); - if (!priv->sd || !priv->device) + if (priv->sd < 0 || !priv->device) return -EINVAL; /* @@ -221,7 +221,7 @@ int sandbox_eth_raw_os_recv(void *packet, int *length, int retval; int saddr_size; - if (!priv->sd || !priv->device) + if (priv->sd < 0 || !priv->device) return -EINVAL; saddr_size = sizeof(struct sockaddr); retval = recvfrom(priv->sd, packet, 1536, 0, -- cgit v1.2.3 From c6fa51a4997714dbd9a4ef64ffe25f4435ee93ef Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Mon, 2 Jul 2018 14:47:45 -0500 Subject: sandbox: Fix format of fake-host-hwaddr in test.dts test.dts specified the fake MAC address as a u32 array. Instead it should be a u8 array. Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass --- arch/sandbox/dts/test.dts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 01e6bc03670..137679abea9 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -155,25 +155,25 @@ eth@10002000 { compatible = "sandbox,eth"; reg = <0x10002000 0x1000>; - fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>; + fake-host-hwaddr = [00 00 66 44 22 00]; }; eth_5: eth@10003000 { compatible = "sandbox,eth"; reg = <0x10003000 0x1000>; - fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>; + fake-host-hwaddr = [00 00 66 44 22 11]; }; eth_3: sbe5 { compatible = "sandbox,eth"; reg = <0x10005000 0x1000>; - fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x33>; + fake-host-hwaddr = [00 00 66 44 22 33]; }; eth@10004000 { compatible = "sandbox,eth"; reg = <0x10004000 0x1000>; - fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x22>; + fake-host-hwaddr = [00 00 66 44 22 22]; }; gpio_a: base-gpios { -- cgit v1.2.3 From 68acb51f442f08152f79772af3d41ff1e4c817cd Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Mon, 2 Jul 2018 14:47:46 -0500 Subject: net: Only call halt on a driver that has been init'ed With driver model, we were not checking if the state of the device was marked as active before calling the halt function. Check that the device is probed and also marked as active. This avoids the case where we were calling halt on the first device in net_init() and the driver would operate on bogus data structures causing problems. In this case, the priv was all 0, so halt() would close STDIN. Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass --- net/eth-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/eth-uclass.c b/net/eth-uclass.c index e4b49229e38..fa3f5497a29 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -307,7 +307,7 @@ void eth_halt(void) struct eth_device_priv *priv; current = eth_get_dev(); - if (!current || !device_active(current)) + if (!current || !eth_is_active(current)) return; eth_get_ops(current)->stop(current); -- cgit v1.2.3 From 50ed0ef832c55a7d088df3d96b7046cf6acf0ff6 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Mon, 2 Jul 2018 14:47:47 -0500 Subject: sandbox: eth-raw: Make sure descriptors are always initialized If we let descriptors equal 0, we can end up closing STDIN. Make sure they start out as -1. Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass --- arch/sandbox/cpu/eth-raw-os.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c index 61f23ed2104..4263d8829a3 100644 --- a/arch/sandbox/cpu/eth-raw-os.c +++ b/arch/sandbox/cpu/eth-raw-os.c @@ -34,6 +34,7 @@ static int _raw_packet_start(const char *ifname, unsigned char *ethmac, int flags; /* Prepare device struct */ + priv->local_bind_sd = -1; priv->device = malloc(sizeof(struct sockaddr_ll)); if (priv->device == NULL) return -ENOMEM; @@ -103,6 +104,8 @@ static int _local_inet_start(struct eth_sandbox_raw_priv *priv) int one = 1; /* Prepare device struct */ + priv->local_bind_sd = -1; + priv->local_bind_udp_port = 0; priv->device = malloc(sizeof(struct sockaddr_in)); if (priv->device == NULL) return -ENOMEM; @@ -136,8 +139,6 @@ static int _local_inet_start(struct eth_sandbox_raw_priv *priv) strerror(errno)); return -errno; } - priv->local_bind_sd = -1; - priv->local_bind_udp_port = 0; return 0; } -- cgit v1.2.3 From c25f40627ff8352858032b92a3fb2bae7b051c53 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Mon, 2 Jul 2018 14:47:48 -0500 Subject: net: Correct comment in Kconfig Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass --- drivers/net/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index e88f056d844..79eef2d7556 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -7,8 +7,8 @@ config DM_ETH 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 + The eth_*() interface will be implemented by the UCLASS_ETH class + This is currently implemented in net/eth-uclass.c Look in include/net.h for details. config DRIVER_TI_CPSW -- cgit v1.2.3 From b32dd183c2d50d897e6ec736ddb3ada0563b9243 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Mon, 2 Jul 2018 14:47:49 -0500 Subject: net: sandbox: Convert sandbox mock eth driver to livetree Use the dev_ functions to access DT properties. Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass --- drivers/net/sandbox.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c index b34712bd06f..b71c8f88d94 100644 --- a/drivers/net/sandbox.c +++ b/drivers/net/sandbox.c @@ -59,10 +59,8 @@ static int sb_eth_start(struct udevice *dev) debug("eth_sandbox: Start\n"); - fdtdec_get_byte_array(gd->fdt_blob, dev_of_offset(dev), - "fake-host-hwaddr", priv->fake_host_hwaddr, - ARP_HLEN); priv->recv_packet_buffer = net_rx_packets[0]; + return 0; } @@ -203,8 +201,18 @@ static int sb_eth_remove(struct udevice *dev) static int sb_eth_ofdata_to_platdata(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); + struct eth_sandbox_priv *priv = dev_get_priv(dev); + const u8 *mac; + + pdata->iobase = dev_read_addr(dev); + + mac = dev_read_u8_array_ptr(dev, "fake-host-hwaddr", ARP_HLEN); + if (!mac) { + printf("'fake-host-hwaddr' is missing from the DT\n"); + return -EINVAL; + } + memcpy(priv->fake_host_hwaddr, mac, ARP_HLEN); - pdata->iobase = devfdt_get_addr(dev); return 0; } -- cgit v1.2.3 From 8c7988b6dbfb0aa05a935e602b8cdb67f7dd60b2 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Mon, 2 Jul 2018 14:47:50 -0500 Subject: net: sandbox-raw: Convert raw eth driver to livetree Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass --- arch/sandbox/cpu/eth-raw-os.c | 28 +++++++++++++++------------- arch/sandbox/include/asm/eth-raw-os.h | 10 ++++++++-- drivers/net/sandbox-raw.c | 26 ++++++++++++++++---------- 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c index 4263d8829a3..82bf6668863 100644 --- a/arch/sandbox/cpu/eth-raw-os.c +++ b/arch/sandbox/cpu/eth-raw-os.c @@ -25,8 +25,8 @@ #include #include -static int _raw_packet_start(const char *ifname, unsigned char *ethmac, - struct eth_sandbox_raw_priv *priv) +static int _raw_packet_start(struct eth_sandbox_raw_priv *priv, + unsigned char *ethmac) { struct sockaddr_ll *device; struct packet_mreq mr; @@ -40,7 +40,8 @@ static int _raw_packet_start(const char *ifname, unsigned char *ethmac, return -ENOMEM; device = priv->device; memset(device, 0, sizeof(struct sockaddr_ll)); - device->sll_ifindex = if_nametoindex(ifname); + device->sll_ifindex = if_nametoindex(priv->host_ifname); + priv->host_ifindex = device->sll_ifindex; device->sll_family = AF_PACKET; memcpy(device->sll_addr, ethmac, 6); device->sll_halen = htons(6); @@ -53,11 +54,11 @@ static int _raw_packet_start(const char *ifname, unsigned char *ethmac, return -errno; } /* Bind to the specified interface */ - ret = setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE, ifname, - strlen(ifname) + 1); + ret = setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE, + priv->host_ifname, strlen(priv->host_ifname) + 1); if (ret < 0) { - printf("Failed to bind to '%s': %d %s\n", ifname, errno, - strerror(errno)); + printf("Failed to bind to '%s': %d %s\n", priv->host_ifname, + errno, strerror(errno)); return -errno; } @@ -76,11 +77,12 @@ static int _raw_packet_start(const char *ifname, unsigned char *ethmac, printf("Failed to set promiscuous mode: %d %s\n" "Falling back to the old \"flags\" way...\n", errno, strerror(errno)); - if (strlen(ifname) >= IFNAMSIZ) { - printf("Interface name %s is too long.\n", ifname); + if (strlen(priv->host_ifname) >= IFNAMSIZ) { + printf("Interface name %s is too long.\n", + priv->host_ifname); return -EINVAL; } - strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + strncpy(ifr.ifr_name, priv->host_ifname, IFNAMSIZ); if (ioctl(priv->sd, SIOCGIFFLAGS, &ifr) < 0) { printf("Failed to read flags: %d %s\n", errno, strerror(errno)); @@ -142,13 +144,13 @@ static int _local_inet_start(struct eth_sandbox_raw_priv *priv) return 0; } -int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac, - struct eth_sandbox_raw_priv *priv) +int sandbox_eth_raw_os_start(struct eth_sandbox_raw_priv *priv, + unsigned char *ethmac) { if (priv->local) return _local_inet_start(priv); else - return _raw_packet_start(ifname, ethmac, priv); + return _raw_packet_start(priv, ethmac); } int sandbox_eth_raw_os_send(void *packet, int length, diff --git a/arch/sandbox/include/asm/eth-raw-os.h b/arch/sandbox/include/asm/eth-raw-os.h index f986d3142dc..760f5fbedd1 100644 --- a/arch/sandbox/include/asm/eth-raw-os.h +++ b/arch/sandbox/include/asm/eth-raw-os.h @@ -9,10 +9,14 @@ #ifndef __ETH_RAW_OS_H #define __ETH_RAW_OS_H +#define IFNAMSIZ 16 + /** * struct eth_sandbox_raw_priv - raw socket session * * sd: socket descriptor - the open socket during a session + * host_ifname: interface name on the host to use for sending our packets + * host_ifindex: interface index number on the host * 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 @@ -22,14 +26,16 @@ */ struct eth_sandbox_raw_priv { int sd; + char host_ifname[IFNAMSIZ]; + unsigned int host_ifindex; 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_start(struct eth_sandbox_raw_priv *priv, + unsigned char *ethmac); int sandbox_eth_raw_os_send(void *packet, int length, struct eth_sandbox_raw_priv *priv); int sandbox_eth_raw_os_recv(void *packet, int *length, diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c index 3f8020f629d..317e9640191 100644 --- a/drivers/net/sandbox-raw.c +++ b/drivers/net/sandbox-raw.c @@ -21,21 +21,16 @@ 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; + int ret; debug("eth_sandbox_raw: Start\n"); - interface = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), - "host-raw-interface", NULL); - if (interface == NULL) - return -EINVAL; - - if (strcmp(interface, "lo") == 0) { - priv->local = 1; + ret = sandbox_eth_raw_os_start(priv, pdata->enetaddr); + if (priv->local) { env_set("ipaddr", "127.0.0.1"); env_set("serverip", "127.0.0.1"); } - return sandbox_eth_raw_os_start(interface, pdata->enetaddr, priv); + return ret; } static int sb_eth_raw_send(struct udevice *dev, void *packet, int length) @@ -143,8 +138,19 @@ static const struct eth_ops sb_eth_raw_ops = { static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); + struct eth_sandbox_raw_priv *priv = dev_get_priv(dev); + const char *ifname; + + pdata->iobase = dev_read_addr(dev); + + ifname = dev_read_string(dev, "host-raw-interface"); + if (ifname) { + strncpy(priv->host_ifname, ifname, IFNAMSIZ); + printf(": Using %s from DT\n", priv->host_ifname); + if (strcmp(ifname, "lo") == 0) + priv->local = 1; + } - pdata->iobase = devfdt_get_addr(dev); return 0; } -- cgit v1.2.3 From ac13270b49d55677aeea5a64dfbf1764118820e3 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Mon, 2 Jul 2018 14:47:51 -0500 Subject: sandbox: eth-raw: Add a function to ask the host about localhost Instead of doing a simple string compare against "lo", look for the flag that indicates a localhost interface. Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass --- arch/sandbox/cpu/eth-raw-os.c | 27 +++++++++++++++++++++++---- arch/sandbox/include/asm/eth-raw-os.h | 8 ++++++++ drivers/net/sandbox-raw.c | 10 ++++++++-- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c index 82bf6668863..12ddb345d92 100644 --- a/arch/sandbox/cpu/eth-raw-os.c +++ b/arch/sandbox/cpu/eth-raw-os.c @@ -1,9 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2015 National Instruments - * - * (C) Copyright 2015 - * Joe Hershberger + * Copyright (c) 2015-2018 National Instruments + * Copyright (c) 2015-2018 Joe Hershberger */ #include @@ -25,6 +23,27 @@ #include #include +int sandbox_eth_raw_os_is_local(const char *ifname) +{ + int fd = socket(AF_INET, SOCK_DGRAM, 0); + struct ifreq ifr; + int ret = 0; + + if (fd < 0) + return -errno; + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + ret = ioctl(fd, SIOCGIFFLAGS, &ifr); + if (ret < 0) { + ret = -errno; + goto out; + } + ret = !!(ifr.ifr_flags & IFF_LOOPBACK); +out: + close(fd); + return ret; +} + static int _raw_packet_start(struct eth_sandbox_raw_priv *priv, unsigned char *ethmac) { diff --git a/arch/sandbox/include/asm/eth-raw-os.h b/arch/sandbox/include/asm/eth-raw-os.h index 760f5fbedd1..edd09d2e084 100644 --- a/arch/sandbox/include/asm/eth-raw-os.h +++ b/arch/sandbox/include/asm/eth-raw-os.h @@ -34,6 +34,14 @@ struct eth_sandbox_raw_priv { unsigned short local_bind_udp_port; }; +/* + * Check if the interface named "ifname" is a localhost interface or not. + * ifname - the interface name on the host to check + * + * returns - 0 if real interface, 1 if local, negative if error + */ +int sandbox_eth_raw_os_is_local(const char *ifname); + int sandbox_eth_raw_os_start(struct eth_sandbox_raw_priv *priv, unsigned char *ethmac); int sandbox_eth_raw_os_send(void *packet, int length, diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c index 317e9640191..c04b94c6e18 100644 --- a/drivers/net/sandbox-raw.c +++ b/drivers/net/sandbox-raw.c @@ -29,6 +29,8 @@ static int sb_eth_raw_start(struct udevice *dev) if (priv->local) { env_set("ipaddr", "127.0.0.1"); env_set("serverip", "127.0.0.1"); + net_ip = string_to_ip("127.0.0.1"); + net_server_ip = net_ip; } return ret; } @@ -140,6 +142,7 @@ static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev) struct eth_pdata *pdata = dev_get_platdata(dev); struct eth_sandbox_raw_priv *priv = dev_get_priv(dev); const char *ifname; + u32 local; pdata->iobase = dev_read_addr(dev); @@ -147,10 +150,13 @@ static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev) if (ifname) { strncpy(priv->host_ifname, ifname, IFNAMSIZ); printf(": Using %s from DT\n", priv->host_ifname); - if (strcmp(ifname, "lo") == 0) - priv->local = 1; } + local = sandbox_eth_raw_os_is_local(priv->host_ifname); + if (local < 0) + return local; + priv->local = local; + return 0; } -- cgit v1.2.3 From c9e2caff8503b0dfa750b5ed08f882919fd3b510 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Mon, 2 Jul 2018 14:47:52 -0500 Subject: sandbox: eth-raw: Allow interface to be specified by index With systemd stable interface names, eth0 will almost never exist. Instead of using that name in the sandbox.dts, use an index. Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass --- arch/sandbox/cpu/eth-raw-os.c | 7 +++++++ arch/sandbox/include/asm/eth-raw-os.h | 9 +++++++++ drivers/net/sandbox-raw.c | 11 +++++++++++ 3 files changed, 27 insertions(+) diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c index 12ddb345d92..df7acaa0bc8 100644 --- a/arch/sandbox/cpu/eth-raw-os.c +++ b/arch/sandbox/cpu/eth-raw-os.c @@ -44,6 +44,13 @@ out: return ret; } +int sandbox_eth_raw_os_idx_to_name(struct eth_sandbox_raw_priv *priv) +{ + if (!if_indextoname(priv->host_ifindex, priv->host_ifname)) + return -errno; + return 0; +} + static int _raw_packet_start(struct eth_sandbox_raw_priv *priv, unsigned char *ethmac) { diff --git a/arch/sandbox/include/asm/eth-raw-os.h b/arch/sandbox/include/asm/eth-raw-os.h index edd09d2e084..99f674e82e6 100644 --- a/arch/sandbox/include/asm/eth-raw-os.h +++ b/arch/sandbox/include/asm/eth-raw-os.h @@ -42,6 +42,15 @@ struct eth_sandbox_raw_priv { */ int sandbox_eth_raw_os_is_local(const char *ifname); +/* + * Look up the name of the interface based on the ifindex populated in priv. + * + * Overwrite the host_ifname member in priv based on looking up host_ifindex + * + * returns - 0 if success, negative if error + */ +int sandbox_eth_raw_os_idx_to_name(struct eth_sandbox_raw_priv *priv); + int sandbox_eth_raw_os_start(struct eth_sandbox_raw_priv *priv, unsigned char *ethmac); int sandbox_eth_raw_os_send(void *packet, int length, diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c index c04b94c6e18..0d1fd4d9311 100644 --- a/drivers/net/sandbox-raw.c +++ b/drivers/net/sandbox-raw.c @@ -143,6 +143,7 @@ static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev) struct eth_sandbox_raw_priv *priv = dev_get_priv(dev); const char *ifname; u32 local; + int ret; pdata->iobase = dev_read_addr(dev); @@ -151,6 +152,16 @@ static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev) strncpy(priv->host_ifname, ifname, IFNAMSIZ); printf(": Using %s from DT\n", priv->host_ifname); } + if (dev_read_u32(dev, "host-raw-interface-idx", + &priv->host_ifindex) < 0) { + priv->host_ifindex = 0; + } else { + ret = sandbox_eth_raw_os_idx_to_name(priv); + if (ret < 0) + return ret; + printf(": Using interface index %d from DT (%s)\n", + priv->host_ifindex, priv->host_ifname); + } local = sandbox_eth_raw_os_is_local(priv->host_ifname); if (local < 0) -- cgit v1.2.3 From b96ced9cdb6bbba1ef4e0087eec799127a22afab Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Mon, 2 Jul 2018 14:47:53 -0500 Subject: sandbox: eth-raw: Make random MAC addresses available to eth-raw We don't necessarily know how many MAC addresses we'll need, so implement a ROM read so we always have something valid. Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass --- drivers/net/sandbox-raw.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c index 0d1fd4d9311..09cc678ebde 100644 --- a/drivers/net/sandbox-raw.c +++ b/drivers/net/sandbox-raw.c @@ -130,11 +130,21 @@ static void sb_eth_raw_stop(struct udevice *dev) sandbox_eth_raw_os_stop(priv); } +static int sb_eth_raw_read_rom_hwaddr(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + + net_random_ethaddr(pdata->enetaddr); + + return 0; +} + 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, + .read_rom_hwaddr = sb_eth_raw_read_rom_hwaddr, }; static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev) -- cgit v1.2.3 From f40a31e695638e0422fdce3c4c6eb39cd1f11f91 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Mon, 2 Jul 2018 14:47:54 -0500 Subject: sandbox: eth-raw: Add a SIMPLE_BUS to enumerate host interfaces Ask the OS for each of its interfaces and for each one, bind a U-Boot device and then probe it. This will allocate the priv data structure that is then populated. Signed-off-by: Joe Hershberger Reviewed-by: Simon Glass --- arch/sandbox/cpu/eth-raw-os.c | 10 ++++++ arch/sandbox/dts/sandbox.dts | 18 +++------- arch/sandbox/dts/sandbox64.dts | 18 +++------- arch/sandbox/include/asm/eth-raw-os.h | 11 ++++++ drivers/net/Makefile | 1 + drivers/net/sandbox-raw-bus.c | 66 +++++++++++++++++++++++++++++++++++ 6 files changed, 98 insertions(+), 26 deletions(-) create mode 100644 drivers/net/sandbox-raw-bus.c diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c index df7acaa0bc8..75bfaa4c90a 100644 --- a/arch/sandbox/cpu/eth-raw-os.c +++ b/arch/sandbox/cpu/eth-raw-os.c @@ -23,6 +23,16 @@ #include #include +struct sandbox_eth_raw_if_nameindex *sandbox_eth_raw_if_nameindex(void) +{ + return (struct sandbox_eth_raw_if_nameindex *)if_nameindex(); +} + +void sandbox_eth_raw_if_freenameindex(struct sandbox_eth_raw_if_nameindex *ptr) +{ + if_freenameindex((struct if_nameindex *)ptr); +} + int sandbox_eth_raw_os_is_local(const char *ifname) { int fd = socket(AF_INET, SOCK_DGRAM, 0); diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts index 0ea2452742d..9f444c96a9e 100644 --- a/arch/sandbox/dts/sandbox.dts +++ b/arch/sandbox/dts/sandbox.dts @@ -8,7 +8,6 @@ model = "sandbox"; aliases { - eth5 = "/eth@90000000"; i2c0 = &i2c_0; pci0 = &pci; rtc0 = &rtc_0; @@ -47,24 +46,17 @@ }; }; + ethrawbus { + compatible = "sandbox,eth-raw-bus"; + skip-localhost = <0>; + }; + eth@10002000 { compatible = "sandbox,eth"; reg = <0x10002000 0x1000>; fake-host-hwaddr = [00 00 66 44 22 00]; }; - eth@80000000 { - compatible = "sandbox,eth-raw"; - reg = <0x80000000 0x1000>; - host-raw-interface = "eth0"; - }; - - eth@90000000 { - compatible = "sandbox,eth-raw"; - reg = <0x90000000 0x1000>; - host-raw-interface = "lo"; - }; - gpio_a: gpios@0 { gpio-controller; compatible = "sandbox,gpio"; diff --git a/arch/sandbox/dts/sandbox64.dts b/arch/sandbox/dts/sandbox64.dts index 48e420e721e..9e65d2fda3d 100644 --- a/arch/sandbox/dts/sandbox64.dts +++ b/arch/sandbox/dts/sandbox64.dts @@ -8,7 +8,6 @@ model = "sandbox"; aliases { - eth5 = "/eth@90000000"; i2c0 = &i2c_0; pci0 = &pci; rtc0 = &rtc_0; @@ -47,24 +46,17 @@ }; }; + ethrawbus { + compatible = "sandbox,eth-raw-bus"; + skip-localhost = <1>; + }; + eth@10002000 { compatible = "sandbox,eth"; reg = <0x0 0x10002000 0x0 0x1000>; fake-host-hwaddr = [00 00 66 44 22 00]; }; - eth@80000000 { - compatible = "sandbox,eth-raw"; - reg = <0x0 0x80000000 0x0 0x1000>; - host-raw-interface = "eth0"; - }; - - eth@90000000 { - compatible = "sandbox,eth-raw"; - reg = <0x0 0x90000000 0x0 0x1000>; - host-raw-interface = "lo"; - }; - gpio_a: gpios@0 { gpio-controller; compatible = "sandbox,gpio"; diff --git a/arch/sandbox/include/asm/eth-raw-os.h b/arch/sandbox/include/asm/eth-raw-os.h index 99f674e82e6..0b511db70c3 100644 --- a/arch/sandbox/include/asm/eth-raw-os.h +++ b/arch/sandbox/include/asm/eth-raw-os.h @@ -34,6 +34,17 @@ struct eth_sandbox_raw_priv { unsigned short local_bind_udp_port; }; +/* A struct to mimic if_nameindex but that does not depend on Linux headers */ +struct sandbox_eth_raw_if_nameindex { + unsigned int if_index; /* Index of interface (1, 2, ...) */ + char *if_name; /* Null-terminated name ("eth0", etc.) */ +}; + +/* Enumerate host network interfaces */ +struct sandbox_eth_raw_if_nameindex *sandbox_eth_raw_if_nameindex(void); +/* Free the data structure of enumerated network interfaces */ +void sandbox_eth_raw_if_freenameindex(struct sandbox_eth_raw_if_nameindex *ptr); + /* * Check if the interface named "ifname" is a localhost interface or not. * ifname - the interface name on the host to check diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 058dd007688..c1ed44e21f1 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -50,6 +50,7 @@ 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-bus.o obj-$(CONFIG_SH_ETHER) += sh_eth.o obj-$(CONFIG_RENESAS_RAVB) += ravb.o obj-$(CONFIG_SMC91111) += smc91111.o diff --git a/drivers/net/sandbox-raw-bus.c b/drivers/net/sandbox-raw-bus.c new file mode 100644 index 00000000000..76d65afe6c8 --- /dev/null +++ b/drivers/net/sandbox-raw-bus.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2018 National Instruments + * Copyright (c) 2018 Joe Hershberger + */ + +#include +#include +#include +#include +#include +#include + +static int eth_raw_bus_post_bind(struct udevice *dev) +{ + struct sandbox_eth_raw_if_nameindex *ni, *i; + struct udevice *child; + struct eth_sandbox_raw_priv *priv; + char *ub_ifname; + static const char ub_ifname_pfx[] = "host_"; + u32 skip_localhost = 0; + + ni = sandbox_eth_raw_if_nameindex(); + if (!ni) + return -EINVAL; + + dev_read_u32(dev, "skip-localhost", &skip_localhost); + for (i = ni; !(i->if_index == 0 && !i->if_name); i++) { + int local = sandbox_eth_raw_os_is_local(i->if_name); + + if (local < 0) + continue; + if (skip_localhost && local) + continue; + + ub_ifname = calloc(IFNAMSIZ + sizeof(ub_ifname_pfx), 1); + strcpy(ub_ifname, ub_ifname_pfx); + strncat(ub_ifname, i->if_name, IFNAMSIZ); + device_bind_driver(dev, "eth_sandbox_raw", ub_ifname, &child); + + device_set_name_alloced(child); + device_probe(child); + priv = dev_get_priv(child); + if (priv) { + memcpy(priv->host_ifname, i->if_name, IFNAMSIZ); + priv->host_ifindex = i->if_index; + priv->local = local; + } + } + + sandbox_eth_raw_if_freenameindex(ni); + + return 0; +} + +static const struct udevice_id sandbox_eth_raw_bus_ids[] = { + { .compatible = "sandbox,eth-raw-bus" }, + { } +}; + +U_BOOT_DRIVER(sandbox_eth_raw_bus) = { + .name = "sb_eth_raw_bus", + .id = UCLASS_SIMPLE_BUS, + .of_match = sandbox_eth_raw_bus_ids, + .bind = eth_raw_bus_post_bind, +}; -- cgit v1.2.3 From 2d114b83a7e44d448b6ffe1bf5e2ced11b769ab2 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Tue, 3 Jul 2018 19:22:54 -0500 Subject: net: Correct size of NFS buffers Reported-by: Coverity (CID: 152888) Signed-off-by: Joe Hershberger --- net/nfs.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/nfs.h b/net/nfs.h index 6359cd2848e..a377c900883 100644 --- a/net/nfs.h +++ b/net/nfs.h @@ -42,6 +42,7 @@ * case, most NFS servers are optimized for a power of 2. */ #define NFS_READ_SIZE 1024 /* biggest power of two that fits Ether frame */ +#define NFS_MAX_ATTRS 26 /* Values for Accept State flag on RPC answers (See: rfc1831) */ enum rpc_accept_stat { @@ -55,7 +56,8 @@ enum rpc_accept_stat { struct rpc_t { union { - uint8_t data[2048]; + uint8_t data[NFS_READ_SIZE + (6 + NFS_MAX_ATTRS) * + sizeof(uint32_t)]; struct { uint32_t id; uint32_t type; @@ -72,7 +74,8 @@ struct rpc_t { uint32_t verifier; uint32_t v2; uint32_t astatus; - uint32_t data[NFS_READ_SIZE]; + uint32_t data[NFS_READ_SIZE / sizeof(uint32_t) + + NFS_MAX_ATTRS]; } reply; } u; } __attribute__((packed)); -- cgit v1.2.3 From 347e32b01db7bf4d24d21cf775021f9b70d6448a Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Tue, 3 Jul 2018 19:22:55 -0500 Subject: net: Check subnet against the actual ip address in use for nfs The check for sending to the gateway was not using the correct variable for comparison, so it was reporting that packets are sent to the gateway when they were not. Signed-off-by: Joe Hershberger --- net/nfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/nfs.c b/net/nfs.c index 9a16765ba15..7e8af28e9f5 100644 --- a/net/nfs.c +++ b/net/nfs.c @@ -896,7 +896,7 @@ void nfs_start(void) struct in_addr server_net; our_net.s_addr = net_ip.s_addr & net_netmask.s_addr; - server_net.s_addr = net_server_ip.s_addr & net_netmask.s_addr; + server_net.s_addr = nfs_server_ip.s_addr & net_netmask.s_addr; if (our_net.s_addr != server_net.s_addr) debug("; sending through gateway %pI4", &net_gateway); -- cgit v1.2.3 From faecf84ab14d38e9316275775097caeea73b1f32 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Tue, 3 Jul 2018 19:22:56 -0500 Subject: net: Always print basic info for nfs, just like tftp nfs was only printing basic info about the transfer in the case of a DEBUG build. Print the same level of detail as tftp always. Signed-off-by: Joe Hershberger --- net/nfs.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/net/nfs.c b/net/nfs.c index 7e8af28e9f5..86dfe9a494a 100644 --- a/net/nfs.c +++ b/net/nfs.c @@ -533,7 +533,7 @@ static int nfs_lookup_reply(uchar *pkt, unsigned len) switch (ntohl(rpc_pkt.u.reply.data[0])) { /* Minimal supported NFS version */ case 3: - debug("*** Waring: NFS version not supported: Requested: V%d, accepted: min V%d - max V%d\n", + debug("*** Warning: NFS version not supported: Requested: V%d, accepted: min V%d - max V%d\n", (supported_nfs_versions & NFSV2_FLAG) ? 2 : 3, ntohl(rpc_pkt.u.reply.data[0]), @@ -855,7 +855,7 @@ void nfs_start(void) if (nfs_path == NULL) { net_set_state(NETLOOP_FAIL); - debug("*** ERROR: Fail allocate memory\n"); + printf("*** ERROR: Fail allocate memory\n"); return; } @@ -866,8 +866,8 @@ void nfs_start(void) (net_ip.s_addr >> 16) & 0xFF, (net_ip.s_addr >> 24) & 0xFF); - debug("*** Warning: no boot file name; using '%s'\n", - nfs_path); + printf("*** Warning: no boot file name; using '%s'\n", + nfs_path); } else { char *p = net_boot_file_name; @@ -885,10 +885,10 @@ void nfs_start(void) nfs_filename = basename(nfs_path); nfs_path = dirname(nfs_path); - debug("Using %s device\n", eth_get_name()); + printf("Using %s device\n", eth_get_name()); - debug("File transfer via NFS from server %pI4; our IP address is %pI4", - &nfs_server_ip, &net_ip); + printf("File transfer via NFS from server %pI4; our IP address is %pI4", + &nfs_server_ip, &net_ip); /* Check if we need to send across this subnet */ if (net_gateway.s_addr && net_netmask.s_addr) { @@ -898,17 +898,17 @@ void nfs_start(void) our_net.s_addr = net_ip.s_addr & net_netmask.s_addr; server_net.s_addr = nfs_server_ip.s_addr & net_netmask.s_addr; if (our_net.s_addr != server_net.s_addr) - debug("; sending through gateway %pI4", - &net_gateway); + printf("; sending through gateway %pI4", + &net_gateway); } - debug("\nFilename '%s/%s'.", nfs_path, nfs_filename); + printf("\nFilename '%s/%s'.", nfs_path, nfs_filename); if (net_boot_file_expected_size_in_blocks) { - debug(" Size is 0x%x Bytes = ", - net_boot_file_expected_size_in_blocks << 9); + printf(" Size is 0x%x Bytes = ", + net_boot_file_expected_size_in_blocks << 9); print_size(net_boot_file_expected_size_in_blocks << 9, ""); } - debug("\nLoad address: 0x%lx\nLoading: *\b", load_addr); + printf("\nLoad address: 0x%lx\nLoading: *\b", load_addr); net_set_timeout_handler(nfs_timeout, nfs_timeout_handler); net_set_udp_handler(nfs_handler); -- cgit v1.2.3 From 3a66fcb7c3dd3297d7e49185a8da2cbe77ffa431 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Tue, 3 Jul 2018 19:36:39 -0500 Subject: net: When checking prerequisites, consider boot_file_name For net_boot_common, we allow the serverip to be specified as part of the boot file name. For net commands that require serverip, include that source as a valid specification of serverip. Signed-off-by: Joe Hershberger Reviewed-by: Alexander Graf --- include/net.h | 3 +++ net/net.c | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/net.h b/include/net.h index f9984ae86ca..de2d7bba19d 100644 --- a/include/net.h +++ b/include/net.h @@ -839,6 +839,9 @@ ushort env_get_vlan(char *); /* copy a filename (allow for "..." notation, limit length) */ void copy_filename(char *dst, const char *src, int size); +/* check if serverip is specified in filename from the command line */ +int is_serverip_in_cmd(void); + /* get a random source port */ unsigned int random_port(void); diff --git a/net/net.c b/net/net.c index f35695b4fc9..bff3e9c5b53 100644 --- a/net/net.c +++ b/net/net.c @@ -1341,7 +1341,7 @@ static int net_check_prereq(enum proto_t protocol) /* Fall through */ case TFTPGET: case TFTPPUT: - if (net_server_ip.s_addr == 0) { + if (net_server_ip.s_addr == 0 && !is_serverip_in_cmd()) { puts("*** ERROR: `serverip' not set\n"); return 1; } @@ -1512,6 +1512,11 @@ void copy_filename(char *dst, const char *src, int size) *dst = '\0'; } +int is_serverip_in_cmd(void) +{ + return !!strchr(net_boot_file_name, ':'); +} + #if defined(CONFIG_CMD_NFS) || \ defined(CONFIG_CMD_SNTP) || \ defined(CONFIG_CMD_DNS) -- cgit v1.2.3 From 3855cad62342c3268465bc760e2bd7e6d0ce7f31 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Tue, 3 Jul 2018 19:36:40 -0500 Subject: net: Re-check prerequisites when autoloading With net autoload, we check the prerequisites for the initial command, but the greater prerequisites when autoloading are not checked. If we would attempt to autoload, check those prerequisites too. If we are not expecting a serverip from the server, then don't worry about it not being set, but don't attempt to load if it isn't. Signed-off-by: Joe Hershberger --- net/net.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/net/net.c b/net/net.c index bff3e9c5b53..42a50e60f84 100644 --- a/net/net.c +++ b/net/net.c @@ -332,6 +332,16 @@ void net_auto_load(void) const char *s = env_get("autoload"); if (s != NULL && strcmp(s, "NFS") == 0) { + if (net_check_prereq(NFS)) { +/* We aren't expecting to get a serverip, so just accept the assigned IP */ +#ifdef CONFIG_BOOTP_SERVERIP + net_set_state(NETLOOP_SUCCESS); +#else + printf("Cannot autoload with NFS\n"); + net_set_state(NETLOOP_FAIL); +#endif + return; + } /* * Use NFS to load the bootfile. */ @@ -347,6 +357,16 @@ void net_auto_load(void) net_set_state(NETLOOP_SUCCESS); return; } + if (net_check_prereq(TFTPGET)) { +/* We aren't expecting to get a serverip, so just accept the assigned IP */ +#ifdef CONFIG_BOOTP_SERVERIP + net_set_state(NETLOOP_SUCCESS); +#else + printf("Cannot autoload with TFTPGET\n"); + net_set_state(NETLOOP_FAIL); +#endif + return; + } tftp_start(TFTPGET); } -- cgit v1.2.3 From 16cf145fd659a01c5db7f286e8c9a4700f736920 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Tue, 3 Jul 2018 19:36:41 -0500 Subject: net: Make copy_filename() accept NULL src Rather than crashing, check the src ptr and set dst to empty string. Signed-off-by: Joe Hershberger --- net/net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/net.c b/net/net.c index 42a50e60f84..333102ea79e 100644 --- a/net/net.c +++ b/net/net.c @@ -1522,12 +1522,12 @@ void net_set_udp_header(uchar *pkt, struct in_addr dest, int dport, int sport, void copy_filename(char *dst, const char *src, int size) { - if (*src && (*src == '"')) { + if (src && *src && (*src == '"')) { ++src; --size; } - while ((--size > 0) && *src && (*src != '"')) + while ((--size > 0) && src && *src && (*src != '"')) *dst++ = *src++; *dst = '\0'; } -- cgit v1.2.3 From f43308fa0c7834d9707a2c212591275d1e095e50 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Tue, 3 Jul 2018 19:36:42 -0500 Subject: net: Read bootfile from env on netboot_common() Instead of depending on a env callback for bootfile, read it explicitly. We do this because the bootfile can be specified on the command line and if it is, we will overwrite the internal variable. If a netboot_common() is called again with no bootfile parameter, we want to use the one in the environment. Signed-off-by: Joe Hershberger --- cmd/net.c | 6 ++++++ net/net.c | 20 -------------------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/cmd/net.c b/cmd/net.c index eca6dd8918e..89721b8f8be 100644 --- a/cmd/net.c +++ b/cmd/net.c @@ -192,6 +192,9 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc, switch (argc) { case 1: + /* refresh bootfile name from env */ + copy_filename(net_boot_file_name, env_get("bootfile"), + sizeof(net_boot_file_name)); break; case 2: /* @@ -203,6 +206,9 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc, addr = simple_strtoul(argv[1], &end, 16); if (end == (argv[1] + strlen(argv[1]))) { load_addr = addr; + /* refresh bootfile name from env */ + copy_filename(net_boot_file_name, env_get("bootfile"), + sizeof(net_boot_file_name)); } else { net_boot_file_name_explicit = true; copy_filename(net_boot_file_name, argv[1], diff --git a/net/net.c b/net/net.c index 333102ea79e..1b6781d358f 100644 --- a/net/net.c +++ b/net/net.c @@ -216,26 +216,6 @@ int __maybe_unused net_busy_flag; /**********************************************************************/ -static int on_bootfile(const char *name, const char *value, enum env_op op, - int flags) -{ - if (flags & H_PROGRAMMATIC) - return 0; - - switch (op) { - case env_op_create: - case env_op_overwrite: - copy_filename(net_boot_file_name, value, - sizeof(net_boot_file_name)); - break; - default: - break; - } - - return 0; -} -U_BOOT_ENV_CALLBACK(bootfile, on_bootfile); - static int on_ipaddr(const char *name, const char *value, enum env_op op, int flags) { -- cgit v1.2.3 From 6ab12830921c1de4eb90a0d471bf5f4677af734c Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Tue, 3 Jul 2018 19:36:43 -0500 Subject: net: Consolidate the parsing of bootfile The same basic parsing was implemented in tftp and nfs, so add a helper function to do the work once. Signed-off-by: Joe Hershberger --- include/net.h | 11 +++++++++++ net/net.c | 20 ++++++++++++++++++++ net/nfs.c | 15 ++------------- net/tftp.c | 13 +------------ 4 files changed, 34 insertions(+), 25 deletions(-) diff --git a/include/net.h b/include/net.h index de2d7bba19d..62f82c4dca7 100644 --- a/include/net.h +++ b/include/net.h @@ -842,6 +842,17 @@ void copy_filename(char *dst, const char *src, int size); /* check if serverip is specified in filename from the command line */ int is_serverip_in_cmd(void); +/** + * net_parse_bootfile - Parse the bootfile env var / cmd line param + * + * @param ipaddr - a pointer to the ipaddr to populate if included in bootfile + * @param filename - a pointer to the string to save the filename part + * @param max_len - The longest - 1 that the filename part can be + * + * return 1 if parsed, 0 if bootfile is empty + */ +int net_parse_bootfile(struct in_addr *ipaddr, char *filename, int max_len); + /* get a random source port */ unsigned int random_port(void); diff --git a/net/net.c b/net/net.c index 1b6781d358f..31cf306ae71 100644 --- a/net/net.c +++ b/net/net.c @@ -1517,6 +1517,26 @@ int is_serverip_in_cmd(void) return !!strchr(net_boot_file_name, ':'); } +int net_parse_bootfile(struct in_addr *ipaddr, char *filename, int max_len) +{ + char *colon; + + if (net_boot_file_name[0] == '\0') + return 0; + + colon = strchr(net_boot_file_name, ':'); + if (colon) { + if (ipaddr) + *ipaddr = string_to_ip(net_boot_file_name); + strncpy(filename, colon + 1, max_len); + } else { + strncpy(filename, net_boot_file_name, max_len); + } + filename[max_len - 1] = '\0'; + + return 1; +} + #if defined(CONFIG_CMD_NFS) || \ defined(CONFIG_CMD_SNTP) || \ defined(CONFIG_CMD_DNS) diff --git a/net/nfs.c b/net/nfs.c index 86dfe9a494a..d6a7f8e827a 100644 --- a/net/nfs.c +++ b/net/nfs.c @@ -859,7 +859,8 @@ void nfs_start(void) return; } - if (net_boot_file_name[0] == '\0') { + if (!net_parse_bootfile(&nfs_server_ip, nfs_path, + sizeof(nfs_path_buff))) { sprintf(nfs_path, "/nfsroot/%02X%02X%02X%02X.img", net_ip.s_addr & 0xFF, (net_ip.s_addr >> 8) & 0xFF, @@ -868,18 +869,6 @@ void nfs_start(void) printf("*** Warning: no boot file name; using '%s'\n", nfs_path); - } else { - char *p = net_boot_file_name; - - p = strchr(p, ':'); - - if (p != NULL) { - nfs_server_ip = string_to_ip(net_boot_file_name); - ++p; - strcpy(nfs_path, p); - } else { - strcpy(nfs_path, net_boot_file_name); - } } nfs_filename = basename(nfs_path); diff --git a/net/tftp.c b/net/tftp.c index 6671b1f7ca7..68ffd814146 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -735,7 +735,7 @@ void tftp_start(enum proto_t protocol) tftp_block_size_option, timeout_ms); tftp_remote_ip = net_server_ip; - if (net_boot_file_name[0] == '\0') { + if (!net_parse_bootfile(&tftp_remote_ip, tftp_filename, MAX_LEN)) { sprintf(default_filename, "%02X%02X%02X%02X.img", net_ip.s_addr & 0xFF, (net_ip.s_addr >> 8) & 0xFF, @@ -747,17 +747,6 @@ void tftp_start(enum proto_t protocol) printf("*** Warning: no boot file name; using '%s'\n", tftp_filename); - } else { - char *p = strchr(net_boot_file_name, ':'); - - if (p == NULL) { - strncpy(tftp_filename, net_boot_file_name, MAX_LEN); - tftp_filename[MAX_LEN - 1] = 0; - } else { - tftp_remote_ip = string_to_ip(net_boot_file_name); - strncpy(tftp_filename, p + 1, MAX_LEN); - tftp_filename[MAX_LEN - 1] = 0; - } } printf("Using %s device\n", eth_get_name()); -- cgit v1.2.3 From f25ddca16c96f13c3f7cf7968566d1ff03917012 Mon Sep 17 00:00:00 2001 From: Andrew Thomas Date: Thu, 21 Jun 2018 16:21:01 -0700 Subject: initialize net_mode.if_type if_type is not correctly initialized Failure to initialize if_type means that grub2/efinet sends a bogus arp request. It therefore gets no response. On Raspberry Pi 3B+ this leads to a pause at: lan78xx_eth Waiting for PHY auto negotiation to complete....... done lan78xx_eth Waiting for PHY auto negotiation to complete....... done Signed-off-by: Andrew Thomas Acked-by: Joe Hershberger --- lib/efi_loader/efi_net.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index e1139501d1f..5a3d7be86cf 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -361,6 +361,7 @@ efi_status_t efi_net_register(void) memcpy(netobj->net_mode.current_address.mac_addr, eth_get_ethaddr(), 6); netobj->net_mode.hwaddr_size = ARP_HLEN; netobj->net_mode.max_packet_size = PKTSIZE; + netobj->net_mode.if_type = ARP_ETHER; netobj->pxe.mode = &netobj->pxe_mode; if (dhcp_ack) -- cgit v1.2.3 From e9bf75c9d3b2494c985fd4a21db8036b493fbd11 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Mon, 9 Jul 2018 21:33:59 +1200 Subject: net: mvgbe: prepare for conversion to driver model Extract some function bodies to helper functions that can be reused in the DM/non-DM implementations. Signed-off-by: Chris Packham Acked-by: Joe Hershberger --- drivers/net/mvgbe.c | 115 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 83 insertions(+), 32 deletions(-) diff --git a/drivers/net/mvgbe.c b/drivers/net/mvgbe.c index e6585ef8b3e..aad1d279915 100644 --- a/drivers/net/mvgbe.c +++ b/drivers/net/mvgbe.c @@ -55,20 +55,13 @@ static int smi_wait_ready(struct mvgbe_device *dmvgbe) return 0; } -/* - * smi_reg_read - miiphy_read callback function. - * - * Returns 16bit phy register value, or -EFAULT on error - */ -static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad, - int reg_ofs) +static int __mvgbe_mdio_read(struct mvgbe_device *dmvgbe, int phy_adr, + int devad, int reg_ofs) { - u16 data = 0; - struct eth_device *dev = eth_get_dev_by_name(bus->name); - struct mvgbe_device *dmvgbe = to_mvgbe(dev); struct mvgbe_registers *regs = dmvgbe->regs; u32 smi_reg; u32 timeout; + u16 data = 0; /* Phyadr read request */ if (phy_adr == MV_PHY_ADR_REQUEST && @@ -127,15 +120,22 @@ static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad, } /* - * smi_reg_write - miiphy_write callback function. + * smi_reg_read - miiphy_read callback function. * - * Returns 0 if write succeed, -EFAULT on error + * Returns 16bit phy register value, or -EFAULT on error */ -static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad, - int reg_ofs, u16 data) +static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad, + int reg_ofs) { struct eth_device *dev = eth_get_dev_by_name(bus->name); struct mvgbe_device *dmvgbe = to_mvgbe(dev); + + return __mvgbe_mdio_read(dmvgbe, phy_adr, devad, reg_ofs); +} + +static int __mvgbe_mdio_write(struct mvgbe_device *dmvgbe, int phy_adr, + int devad, int reg_ofs, u16 data) +{ struct mvgbe_registers *regs = dmvgbe->regs; u32 smi_reg; @@ -171,6 +171,20 @@ static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad, return 0; } + +/* + * smi_reg_write - miiphy_write callback function. + * + * Returns 0 if write succeed, -EFAULT on error + */ +static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad, + int reg_ofs, u16 data) +{ + struct eth_device *dev = eth_get_dev_by_name(bus->name); + struct mvgbe_device *dmvgbe = to_mvgbe(dev); + + return __mvgbe_mdio_write(dmvgbe, phy_adr, devad, reg_ofs, data); +} #endif /* Stop and checks all queues */ @@ -357,8 +371,9 @@ static int port_uc_addr(struct mvgbe_registers *regs, u8 uc_nibble, /* * port_uc_addr_set - This function Set the port Unicast address. */ -static void port_uc_addr_set(struct mvgbe_registers *regs, u8 * p_addr) +static void port_uc_addr_set(struct mvgbe_device *dmvgbe, u8 *p_addr) { + struct mvgbe_registers *regs = dmvgbe->regs; u32 mac_h; u32 mac_l; @@ -400,9 +415,8 @@ static void mvgbe_init_rx_desc_ring(struct mvgbe_device *dmvgbe) dmvgbe->p_rxdesc_curr = dmvgbe->p_rxdesc; } -static int mvgbe_init(struct eth_device *dev) +static int __mvgbe_init(struct mvgbe_device *dmvgbe) { - struct mvgbe_device *dmvgbe = to_mvgbe(dev); struct mvgbe_registers *regs = dmvgbe->regs; #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \ !defined(CONFIG_PHYLIB) && \ @@ -422,7 +436,7 @@ static int mvgbe_init(struct eth_device *dev) set_dram_access(regs); port_init_mac_tables(regs); - port_uc_addr_set(regs, dmvgbe->dev.enetaddr); + port_uc_addr_set(dmvgbe, dmvgbe->dev.enetaddr); /* Assign port configuration and command. */ MVGBE_REG_WR(regs->pxc, PRT_CFG_VAL); @@ -464,23 +478,29 @@ static int mvgbe_init(struct eth_device *dev) for (i = 0; i < 5; i++) { u16 phyadr; - miiphy_read(dev->name, MV_PHY_ADR_REQUEST, + miiphy_read(dmvgbe->dev.name, MV_PHY_ADR_REQUEST, MV_PHY_ADR_REQUEST, &phyadr); /* Return if we get link up */ - if (miiphy_link(dev->name, phyadr)) + if (miiphy_link(dmvgbe->dev.name, phyadr)) return 0; udelay(1000000); } - printf("No link on %s\n", dev->name); + printf("No link on %s\n", dmvgbe->dev.name); return -1; #endif return 0; } -static int mvgbe_halt(struct eth_device *dev) +static int mvgbe_init(struct eth_device *dev) { struct mvgbe_device *dmvgbe = to_mvgbe(dev); + + return __mvgbe_init(dmvgbe); +} + +static void __mvgbe_halt(struct mvgbe_device *dmvgbe) +{ struct mvgbe_registers *regs = dmvgbe->regs; /* Disable all gigE address decoder */ @@ -502,6 +522,13 @@ static int mvgbe_halt(struct eth_device *dev) MVGBE_REG_WR(regs->ice, 0); MVGBE_REG_WR(regs->pim, 0); MVGBE_REG_WR(regs->peim, 0); +} + +static int mvgbe_halt(struct eth_device *dev) +{ + struct mvgbe_device *dmvgbe = to_mvgbe(dev); + + __mvgbe_halt(dmvgbe); return 0; } @@ -509,16 +536,15 @@ static int mvgbe_halt(struct eth_device *dev) static int mvgbe_write_hwaddr(struct eth_device *dev) { struct mvgbe_device *dmvgbe = to_mvgbe(dev); - struct mvgbe_registers *regs = dmvgbe->regs; /* Programs net device MAC address after initialization */ - port_uc_addr_set(regs, dmvgbe->dev.enetaddr); + port_uc_addr_set(dmvgbe, dmvgbe->dev.enetaddr); return 0; } -static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize) +static int __mvgbe_send(struct mvgbe_device *dmvgbe, void *dataptr, + int datasize) { - struct mvgbe_device *dmvgbe = to_mvgbe(dev); struct mvgbe_registers *regs = dmvgbe->regs; struct mvgbe_txdesc *p_txdesc = dmvgbe->p_txdesc; void *p = (void *)dataptr; @@ -571,13 +597,23 @@ static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize) return 0; } -static int mvgbe_recv(struct eth_device *dev) +static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize) { struct mvgbe_device *dmvgbe = to_mvgbe(dev); + + return __mvgbe_send(dmvgbe, dataptr, datasize); +} + +static int __mvgbe_recv(struct mvgbe_device *dmvgbe, uchar **packetp) +{ struct mvgbe_rxdesc *p_rxdesc_curr = dmvgbe->p_rxdesc_curr; u32 cmd_sts; u32 timeout = 0; u32 rxdesc_curr_addr; + unsigned char *data; + int rx_bytes = 0; + + *packetp = NULL; /* wait untill rx packet available or timeout */ do { @@ -621,11 +657,11 @@ static int mvgbe_recv(struct eth_device *dev) " upper layer (net_process_received_packet)\n", __func__); - /* let the upper layer handle the packet */ - net_process_received_packet((p_rxdesc_curr->buf_ptr + - RX_BUF_OFFSET), - (int)(p_rxdesc_curr->byte_cnt - - RX_BUF_OFFSET)); + data = (p_rxdesc_curr->buf_ptr + RX_BUF_OFFSET); + rx_bytes = (int)(p_rxdesc_curr->byte_cnt - + RX_BUF_OFFSET); + + *packetp = data; } /* * free these descriptors and point next in the ring @@ -638,6 +674,21 @@ static int mvgbe_recv(struct eth_device *dev) rxdesc_curr_addr = (u32)&dmvgbe->p_rxdesc_curr; writel((unsigned)p_rxdesc_curr->nxtdesc_p, rxdesc_curr_addr); + return rx_bytes; +} + +static int mvgbe_recv(struct eth_device *dev) +{ + struct mvgbe_device *dmvgbe = to_mvgbe(dev); + uchar *packet; + int ret; + + ret = __mvgbe_recv(dmvgbe, &packet); + if (ret < 0) + return ret; + + net_process_received_packet(packet, ret); + return 0; } -- cgit v1.2.3 From fb7310769882c2fb9716352a78744327e72c2430 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Mon, 9 Jul 2018 21:34:00 +1200 Subject: net: mvgbe: convert to DM Add driver model support to the mvgbe driver. As a temporary measure both DM and non-DM uses are supported. Once all the users have been converted the non-DM support can be dropped. Signed-off-by: Chris Packham Tested-by: Michael Walle Acked-by: Joe Hershberger --- drivers/net/Kconfig | 1 + drivers/net/mvgbe.c | 313 +++++++++++++++++++++++++++++++++++++++++++--------- drivers/net/mvgbe.h | 16 +++ 3 files changed, 279 insertions(+), 51 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 79eef2d7556..f762b0898d7 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -181,6 +181,7 @@ config FTMAC100 config MVGBE bool "Marvell Orion5x/Kirkwood network interface support" depends on KIRKWOOD || ORION5X + select PHYLIB if DM_ETH help This driver supports the network interface units in the Marvell Orion5x and Kirkwood SoCs diff --git a/drivers/net/mvgbe.c b/drivers/net/mvgbe.c index aad1d279915..74fed7abd83 100644 --- a/drivers/net/mvgbe.c +++ b/drivers/net/mvgbe.c @@ -12,6 +12,7 @@ */ #include +#include #include #include #include @@ -127,8 +128,12 @@ static int __mvgbe_mdio_read(struct mvgbe_device *dmvgbe, int phy_adr, static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad, int reg_ofs) { +#ifdef CONFIG_DM_ETH + struct mvgbe_device *dmvgbe = bus->priv; +#else struct eth_device *dev = eth_get_dev_by_name(bus->name); struct mvgbe_device *dmvgbe = to_mvgbe(dev); +#endif return __mvgbe_mdio_read(dmvgbe, phy_adr, devad, reg_ofs); } @@ -180,8 +185,12 @@ static int __mvgbe_mdio_write(struct mvgbe_device *dmvgbe, int phy_adr, static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad, int reg_ofs, u16 data) { +#ifdef CONFIG_DM_ETH + struct mvgbe_device *dmvgbe = bus->priv; +#else struct eth_device *dev = eth_get_dev_by_name(bus->name); struct mvgbe_device *dmvgbe = to_mvgbe(dev); +#endif return __mvgbe_mdio_write(dmvgbe, phy_adr, devad, reg_ofs, data); } @@ -415,11 +424,13 @@ static void mvgbe_init_rx_desc_ring(struct mvgbe_device *dmvgbe) dmvgbe->p_rxdesc_curr = dmvgbe->p_rxdesc; } -static int __mvgbe_init(struct mvgbe_device *dmvgbe) +static int __mvgbe_init(struct mvgbe_device *dmvgbe, u8 *enetaddr, + const char *name) { struct mvgbe_registers *regs = dmvgbe->regs; #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \ !defined(CONFIG_PHYLIB) && \ + !defined(CONFIG_DM_ETH) && \ defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) int i; #endif @@ -436,7 +447,7 @@ static int __mvgbe_init(struct mvgbe_device *dmvgbe) set_dram_access(regs); port_init_mac_tables(regs); - port_uc_addr_set(dmvgbe, dmvgbe->dev.enetaddr); + port_uc_addr_set(dmvgbe, enetaddr); /* Assign port configuration and command. */ MVGBE_REG_WR(regs->pxc, PRT_CFG_VAL); @@ -473,31 +484,34 @@ static int __mvgbe_init(struct mvgbe_device *dmvgbe) #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \ !defined(CONFIG_PHYLIB) && \ + !defined(CONFIG_DM_ETH) && \ defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) /* Wait up to 5s for the link status */ for (i = 0; i < 5; i++) { u16 phyadr; - miiphy_read(dmvgbe->dev.name, MV_PHY_ADR_REQUEST, + miiphy_read(name, MV_PHY_ADR_REQUEST, MV_PHY_ADR_REQUEST, &phyadr); /* Return if we get link up */ - if (miiphy_link(dmvgbe->dev.name, phyadr)) + if (miiphy_link(name, phyadr)) return 0; udelay(1000000); } - printf("No link on %s\n", dmvgbe->dev.name); + printf("No link on %s\n", name); return -1; #endif return 0; } +#ifndef CONFIG_DM_ETH static int mvgbe_init(struct eth_device *dev) { struct mvgbe_device *dmvgbe = to_mvgbe(dev); - return __mvgbe_init(dmvgbe); + return __mvgbe_init(dmvgbe, dmvgbe->dev.enetaddr, dmvgbe->dev.name); } +#endif static void __mvgbe_halt(struct mvgbe_device *dmvgbe) { @@ -524,6 +538,7 @@ static void __mvgbe_halt(struct mvgbe_device *dmvgbe) MVGBE_REG_WR(regs->peim, 0); } +#ifndef CONFIG_DM_ETH static int mvgbe_halt(struct eth_device *dev) { struct mvgbe_device *dmvgbe = to_mvgbe(dev); @@ -532,7 +547,18 @@ static int mvgbe_halt(struct eth_device *dev) return 0; } +#endif +#ifdef CONFIG_DM_ETH +static int mvgbe_write_hwaddr(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + + port_uc_addr_set(dev_get_priv(dev), pdata->enetaddr); + + return 0; +} +#else static int mvgbe_write_hwaddr(struct eth_device *dev) { struct mvgbe_device *dmvgbe = to_mvgbe(dev); @@ -541,6 +567,7 @@ static int mvgbe_write_hwaddr(struct eth_device *dev) port_uc_addr_set(dmvgbe, dmvgbe->dev.enetaddr); return 0; } +#endif static int __mvgbe_send(struct mvgbe_device *dmvgbe, void *dataptr, int datasize) @@ -597,12 +624,14 @@ static int __mvgbe_send(struct mvgbe_device *dmvgbe, void *dataptr, return 0; } +#ifndef CONFIG_DM_ETH static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize) { struct mvgbe_device *dmvgbe = to_mvgbe(dev); return __mvgbe_send(dmvgbe, dataptr, datasize); } +#endif static int __mvgbe_recv(struct mvgbe_device *dmvgbe, uchar **packetp) { @@ -677,6 +706,7 @@ static int __mvgbe_recv(struct mvgbe_device *dmvgbe, uchar **packetp) return rx_bytes; } +#ifndef CONFIG_DM_ETH static int mvgbe_recv(struct eth_device *dev) { struct mvgbe_device *dmvgbe = to_mvgbe(dev); @@ -691,8 +721,41 @@ static int mvgbe_recv(struct eth_device *dev) return 0; } +#endif -#if defined(CONFIG_PHYLIB) +#if defined(CONFIG_PHYLIB) || defined(CONFIG_DM_ETH) +#if defined(CONFIG_DM_ETH) +static struct phy_device *__mvgbe_phy_init(struct udevice *dev, + struct mii_dev *bus, + phy_interface_t phy_interface, + int phyid) +#else +static struct phy_device *__mvgbe_phy_init(struct eth_device *dev, + struct mii_dev *bus, + phy_interface_t phy_interface, + int phyid) +#endif +{ + struct phy_device *phydev; + + /* Set phy address of the port */ + miiphy_write(dev->name, MV_PHY_ADR_REQUEST, MV_PHY_ADR_REQUEST, + phyid); + + phydev = phy_connect(bus, phyid, dev, phy_interface); + if (!phydev) { + printf("phy_connect failed\n"); + return NULL; + } + + phy_config(phydev); + phy_startup(phydev); + + return phydev; +} +#endif /* CONFIG_PHYLIB || CONFIG_DM_ETH */ + +#if defined(CONFIG_PHYLIB) && !defined(CONFIG_DM_ETH) int mvgbe_phylib_init(struct eth_device *dev, int phyid) { struct mii_dev *bus; @@ -715,27 +778,53 @@ int mvgbe_phylib_init(struct eth_device *dev, int phyid) return -ENOMEM; } - /* Set phy address of the port */ - smi_reg_write(bus, MV_PHY_ADR_REQUEST, 0, MV_PHY_ADR_REQUEST, phyid); - - phydev = phy_connect(bus, phyid, dev, PHY_INTERFACE_MODE_RGMII); - if (!phydev) { - printf("phy_connect failed\n"); + phydev = __mvgbe_phy_init(dev, bus, PHY_INTERFACE_MODE_RGMII, phyid); + if (!phydev) return -ENODEV; - } - - phy_config(phydev); - phy_startup(phydev); return 0; } #endif +static int mvgbe_alloc_buffers(struct mvgbe_device *dmvgbe) +{ + dmvgbe->p_rxdesc = memalign(PKTALIGN, + MV_RXQ_DESC_ALIGNED_SIZE * RINGSZ + 1); + if (!dmvgbe->p_rxdesc) + goto error1; + + dmvgbe->p_rxbuf = memalign(PKTALIGN, + RINGSZ * PKTSIZE_ALIGN + 1); + if (!dmvgbe->p_rxbuf) + goto error2; + + dmvgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN); + if (!dmvgbe->p_aligned_txbuf) + goto error3; + + dmvgbe->p_txdesc = memalign(PKTALIGN, sizeof(struct mvgbe_txdesc) + 1); + if (!dmvgbe->p_txdesc) + goto error4; + + return 0; + +error4: + free(dmvgbe->p_aligned_txbuf); +error3: + free(dmvgbe->p_rxbuf); +error2: + free(dmvgbe->p_rxdesc); +error1: + return -ENOMEM; +} + +#ifndef CONFIG_DM_ETH int mvgbe_initialize(bd_t *bis) { struct mvgbe_device *dmvgbe; struct eth_device *dev; int devnum; + int ret; u8 used_ports[MAX_MVGBE_DEVS] = CONFIG_MVGBE_PORTS; for (devnum = 0; devnum < MAX_MVGBE_DEVS; devnum++) { @@ -744,45 +833,16 @@ int mvgbe_initialize(bd_t *bis) continue; dmvgbe = malloc(sizeof(struct mvgbe_device)); - if (!dmvgbe) - goto error1; + return -ENOMEM; memset(dmvgbe, 0, sizeof(struct mvgbe_device)); - - dmvgbe->p_rxdesc = - (struct mvgbe_rxdesc *)memalign(PKTALIGN, - MV_RXQ_DESC_ALIGNED_SIZE*RINGSZ + 1); - - if (!dmvgbe->p_rxdesc) - goto error2; - - dmvgbe->p_rxbuf = (u8 *) memalign(PKTALIGN, - RINGSZ*PKTSIZE_ALIGN + 1); - - if (!dmvgbe->p_rxbuf) - goto error3; - - dmvgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN); - - if (!dmvgbe->p_aligned_txbuf) - goto error4; - - dmvgbe->p_txdesc = (struct mvgbe_txdesc *) memalign( - PKTALIGN, sizeof(struct mvgbe_txdesc) + 1); - - if (!dmvgbe->p_txdesc) { - free(dmvgbe->p_aligned_txbuf); -error4: - free(dmvgbe->p_rxbuf); -error3: - free(dmvgbe->p_rxdesc); -error2: - free(dmvgbe); -error1: + ret = mvgbe_alloc_buffers(dmvgbe); + if (ret) { printf("Err.. %s Failed to allocate memory\n", __func__); - return -1; + free(dmvgbe); + return ret; } dev = &dmvgbe->dev; @@ -834,3 +894,154 @@ error1: } return 0; } +#endif + +#ifdef CONFIG_DM_ETH +static int mvgbe_port_is_fixed_link(struct mvgbe_device *dmvgbe) +{ + return dmvgbe->phyaddr > PHY_MAX_ADDR; +} + +static int mvgbe_start(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + struct mvgbe_device *dmvgbe = dev_get_priv(dev); + int ret; + + ret = __mvgbe_init(dmvgbe, pdata->enetaddr, dev->name); + if (ret) + return ret; + + if (!mvgbe_port_is_fixed_link(dmvgbe)) { + dmvgbe->phydev = __mvgbe_phy_init(dev, dmvgbe->bus, + dmvgbe->phy_interface, + dmvgbe->phyaddr); + if (!dmvgbe->phydev) + return -ENODEV; + } + + return 0; +} + +static int mvgbe_send(struct udevice *dev, void *packet, int length) +{ + struct mvgbe_device *dmvgbe = dev_get_priv(dev); + + return __mvgbe_send(dmvgbe, packet, length); +} + +static int mvgbe_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct mvgbe_device *dmvgbe = dev_get_priv(dev); + + return __mvgbe_recv(dmvgbe, packetp); +} + +static void mvgbe_stop(struct udevice *dev) +{ + struct mvgbe_device *dmvgbe = dev_get_priv(dev); + + __mvgbe_halt(dmvgbe); +} + +static int mvgbe_probe(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + struct mvgbe_device *dmvgbe = dev_get_priv(dev); + struct mii_dev *bus; + int ret; + + ret = mvgbe_alloc_buffers(dmvgbe); + if (ret) + return ret; + + dmvgbe->regs = (void __iomem *)pdata->iobase; + + bus = mdio_alloc(); + if (!bus) { + printf("Failed to allocate MDIO bus\n"); + return -ENOMEM; + } + + bus->read = smi_reg_read; + bus->write = smi_reg_write; + snprintf(bus->name, sizeof(bus->name), dev->name); + bus->priv = dmvgbe; + dmvgbe->bus = bus; + + ret = mdio_register(bus); + if (ret < 0) + return ret; + + return 0; +} + +static const struct eth_ops mvgbe_ops = { + .start = mvgbe_start, + .send = mvgbe_send, + .recv = mvgbe_recv, + .stop = mvgbe_stop, + .write_hwaddr = mvgbe_write_hwaddr, +}; + +static int mvgbe_ofdata_to_platdata(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + struct mvgbe_device *dmvgbe = dev_get_priv(dev); + void *blob = (void *)gd->fdt_blob; + int node = dev_of_offset(dev); + const char *phy_mode; + int fl_node; + int pnode; + unsigned long addr; + + pdata->iobase = devfdt_get_addr(dev); + pdata->phy_interface = -1; + + pnode = fdt_node_offset_by_compatible(blob, node, + "marvell,kirkwood-eth-port"); + + /* Get phy-mode / phy_interface from DT */ + phy_mode = fdt_getprop(gd->fdt_blob, pnode, "phy-mode", NULL); + if (phy_mode) + pdata->phy_interface = phy_get_interface_by_name(phy_mode); + if (pdata->phy_interface == -1) { + debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode); + return -EINVAL; + } + + dmvgbe->phy_interface = pdata->phy_interface; + + /* fetch 'fixed-link' property */ + fl_node = fdt_subnode_offset(blob, pnode, "fixed-link"); + if (fl_node != -FDT_ERR_NOTFOUND) { + /* set phy_addr to invalid value for fixed link */ + dmvgbe->phyaddr = PHY_MAX_ADDR + 1; + dmvgbe->duplex = fdtdec_get_bool(blob, fl_node, "full-duplex"); + dmvgbe->speed = fdtdec_get_int(blob, fl_node, "speed", 0); + } else { + /* Now read phyaddr from DT */ + addr = fdtdec_lookup_phandle(blob, pnode, "phy-handle"); + if (addr > 0) + dmvgbe->phyaddr = fdtdec_get_int(blob, addr, "reg", 0); + } + + return 0; +} + +static const struct udevice_id mvgbe_ids[] = { + { .compatible = "marvell,kirkwood-eth" }, + { } +}; + +U_BOOT_DRIVER(mvgbe) = { + .name = "mvgbe", + .id = UCLASS_ETH, + .of_match = mvgbe_ids, + .ofdata_to_platdata = mvgbe_ofdata_to_platdata, + .probe = mvgbe_probe, + .ops = &mvgbe_ops, + .priv_auto_alloc_size = sizeof(struct mvgbe_device), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), +}; +#endif /* CONFIG_DM_ETH */ diff --git a/drivers/net/mvgbe.h b/drivers/net/mvgbe.h index 1dc9bbea2f4..44541c0a85e 100644 --- a/drivers/net/mvgbe.h +++ b/drivers/net/mvgbe.h @@ -30,7 +30,9 @@ #define RXUQ 0 /* Used Rx queue */ #define TXUQ 0 /* Used Rx queue */ +#ifndef CONFIG_DM_ETH #define to_mvgbe(_d) container_of(_d, struct mvgbe_device, dev) +#endif #define MVGBE_REG_WR(adr, val) writel(val, &adr) #define MVGBE_REG_RD(adr) readl(&adr) #define MVGBE_REG_BITS_RESET(adr, val) writel(readl(&adr) & ~(val), &adr) @@ -479,13 +481,27 @@ struct mvgbe_txdesc { /* port device data struct */ struct mvgbe_device { +#ifndef CONFIG_DM_ETH struct eth_device dev; +#endif struct mvgbe_registers *regs; struct mvgbe_txdesc *p_txdesc; struct mvgbe_rxdesc *p_rxdesc; struct mvgbe_rxdesc *p_rxdesc_curr; u8 *p_rxbuf; u8 *p_aligned_txbuf; + +#ifdef CONFIG_DM_ETH + phy_interface_t phy_interface; + unsigned int link; + unsigned int duplex; + unsigned int speed; + + int init; + int phyaddr; + struct phy_device *phydev; + struct mii_dev *bus; +#endif }; #endif /* __MVGBE_H__ */ -- cgit v1.2.3 From 63d319298452084d7aed2fe066d916605601939e Mon Sep 17 00:00:00 2001 From: Murali Karicheri Date: Thu, 28 Jun 2018 14:26:34 -0500 Subject: net: phy: dp83867: add workaround for incorrect RX_CTRL pin strap The data manual for DP83867IR/CR, SNLS484E[1], revised march 2017, advises that strapping RX_DV/RX_CTRL pin in mode 1 and 2 is not supported (see note below Table 5 (4-Level Strap Pins)). It further advises that if a board has this pin strapped in mode 1 and mode 2, then bit[7] of Configuration Register 4 (address 0x0031) must be cleared to 0. This is to ensure proper operation of PHY. Since it is not possible to detect in software if RX_DV/RX_CTRL pin is incorrectly strapped, add a device-tree property to advertise this and allow corrective action in software. [1] http://www.ti.com/lit/ds/snls484e/snls484e.pdf Signed-off-by: Murali Karicheri Reviewed-by: Hannes Schmelzer Acked-by: Joe Hershberger Tested-by: Siva Durga Prasad Paladugu --- drivers/net/phy/ti.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c index 8f3ed8a9833..f1c9f7bafe2 100644 --- a/drivers/net/phy/ti.c +++ b/drivers/net/phy/ti.c @@ -24,6 +24,7 @@ DECLARE_GLOBAL_DATA_PTR; #define DP83867_CTRL 0x1f /* Extended Registers */ +#define DP83867_CFG4 0x0031 #define DP83867_RGMIICTL 0x0032 #define DP83867_RGMIIDCTL 0x0086 #define DP83867_IO_MUX_CFG 0x0170 @@ -95,6 +96,7 @@ struct dp83867_private { int tx_id_delay; int fifo_depth; int io_impedance; + bool rxctrl_strap_quirk; }; /** @@ -183,6 +185,8 @@ static int dp83867_of_init(struct phy_device *phydev) else dp83867->io_impedance = -EINVAL; + if (fdtdec_get_bool(fdt, node, "ti,dp83867-rxctrl-strap-quirk")) + dp83867->rxctrl_strap_quirk = true; dp83867->rx_id_delay = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), "ti,rx-internal-delay", -1); @@ -232,6 +236,15 @@ static int dp83867_config(struct phy_device *phydev) phy_write(phydev, MDIO_DEVAD_NONE, DP83867_CTRL, val | DP83867_SW_RESTART); + /* Mode 1 or 2 workaround */ + if (dp83867->rxctrl_strap_quirk) { + val = phy_read_mmd_indirect(phydev, DP83867_CFG4, + DP83867_DEVADDR, phydev->addr); + val &= ~BIT(7); + phy_write_mmd_indirect(phydev, DP83867_CFG4, + DP83867_DEVADDR, phydev->addr, val); + } + if (phy_interface_is_rgmii(phydev)) { ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL, (DP83867_MDI_CROSSOVER_AUTO << DP83867_MDI_CROSSOVER) | -- cgit v1.2.3 From 3ab75cf76e78d2ce729896625504cdfff1d3d8a5 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 28 Jun 2018 14:26:35 -0500 Subject: net: phy: dp83867: switch to use ofnode api Switch to use more generic ofnode API instead of FDT API. Signed-off-by: Grygorii Strashko Acked-by: Joe Hershberger Tested-by: Siva Durga Prasad Paladugu --- drivers/net/phy/ti.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c index f1c9f7bafe2..655f46d22f9 100644 --- a/drivers/net/phy/ti.c +++ b/drivers/net/phy/ti.c @@ -8,11 +8,9 @@ #include #include -#include #include #include -DECLARE_GLOBAL_DATA_PTR; /* TI DP83867 */ #define DP83867_DEVADDR 0x1f @@ -175,26 +173,27 @@ static int dp83867_of_init(struct phy_device *phydev) { struct dp83867_private *dp83867 = phydev->priv; struct udevice *dev = phydev->dev; - int node = dev_of_offset(dev); - const void *fdt = gd->fdt_blob; + ofnode node = dev_ofnode(dev); - if (fdtdec_get_bool(fdt, node, "ti,max-output-impedance")) + if (ofnode_read_bool(node, "ti,max-output-impedance")) dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX; - else if (fdtdec_get_bool(fdt, node, "ti,min-output-impedance")) + else if (ofnode_read_bool(node, "ti,min-output-impedance")) dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN; else dp83867->io_impedance = -EINVAL; - if (fdtdec_get_bool(fdt, node, "ti,dp83867-rxctrl-strap-quirk")) + if (ofnode_read_bool(node, "ti,dp83867-rxctrl-strap-quirk")) dp83867->rxctrl_strap_quirk = true; - dp83867->rx_id_delay = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), - "ti,rx-internal-delay", -1); + dp83867->rx_id_delay = ofnode_read_u32_default(node, + "ti,rx-internal-delay", + -1); - dp83867->tx_id_delay = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), - "ti,tx-internal-delay", -1); + dp83867->tx_id_delay = ofnode_read_u32_default(node, + "ti,tx-internal-delay", + -1); - dp83867->fifo_depth = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), - "ti,fifo-depth", -1); + dp83867->fifo_depth = ofnode_read_u32_default(node, "ti,fifo-depth", + -1); return 0; } -- cgit v1.2.3 From 9cce5663218ed35262b66c132cd65f42d27c7825 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Mon, 16 Jul 2018 15:33:51 -0500 Subject: arm: Prevent redefinition error in fsl-layerscape The include/phy.h will start including dm.h, which pulls in linux/compat.h after the attempted redefinition in arch/arm/include/asm/armv8/mmu.h, so move this include to allow redefinition. Signed-off-by: Joe Hershberger --- arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c index 40c2c3a1cfe..052e0708d45 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -18,7 +19,6 @@ #include #include #include -#include #include #ifdef CONFIG_FSL_ESDHC #include -- cgit v1.2.3 From f070b1a27ac91c334f68425002a7db72d30213e7 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Tue, 17 Jul 2018 15:02:30 -0500 Subject: phy: Break include cycle Because some phy wants to export some functions [1], export.h was including the whole phy subsystem which pulls in lots of stuff that causes some ordering and redefinition issues. Split out the only part that is actually needed in export.h and include it there and in phy.h. [1] commit 95279315076c ("board/ls2085rdb: Export functions for standalone AQ FW load apps") Signed-off-by: Joe Hershberger --- include/exports.h | 3 +-- include/phy.h | 55 +---------------------------------------- include/phy_interface.h | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 56 deletions(-) create mode 100644 include/phy_interface.h diff --git a/include/exports.h b/include/exports.h index ebe81d914cb..a4b862f1917 100644 --- a/include/exports.h +++ b/include/exports.h @@ -3,8 +3,7 @@ #ifndef __ASSEMBLY__ #ifdef CONFIG_PHY_AQUANTIA -#include -#include +#include #endif struct spi_slave; diff --git a/include/phy.h b/include/phy.h index 7c3fc5ce40c..09645a8ddb0 100644 --- a/include/phy.h +++ b/include/phy.h @@ -13,6 +13,7 @@ #include #include #include +#include #define PHY_FIXED_ID 0xa5a55a5a @@ -48,60 +49,6 @@ #endif -typedef enum { - PHY_INTERFACE_MODE_MII, - PHY_INTERFACE_MODE_GMII, - PHY_INTERFACE_MODE_SGMII, - PHY_INTERFACE_MODE_SGMII_2500, - PHY_INTERFACE_MODE_QSGMII, - PHY_INTERFACE_MODE_TBI, - PHY_INTERFACE_MODE_RMII, - PHY_INTERFACE_MODE_RGMII, - PHY_INTERFACE_MODE_RGMII_ID, - PHY_INTERFACE_MODE_RGMII_RXID, - PHY_INTERFACE_MODE_RGMII_TXID, - PHY_INTERFACE_MODE_RTBI, - PHY_INTERFACE_MODE_XGMII, - PHY_INTERFACE_MODE_XAUI, - PHY_INTERFACE_MODE_RXAUI, - PHY_INTERFACE_MODE_SFI, - PHY_INTERFACE_MODE_INTERNAL, - PHY_INTERFACE_MODE_NONE, /* Must be last */ - - PHY_INTERFACE_MODE_COUNT, -} phy_interface_t; - -static const char *phy_interface_strings[] = { - [PHY_INTERFACE_MODE_MII] = "mii", - [PHY_INTERFACE_MODE_GMII] = "gmii", - [PHY_INTERFACE_MODE_SGMII] = "sgmii", - [PHY_INTERFACE_MODE_SGMII_2500] = "sgmii-2500", - [PHY_INTERFACE_MODE_QSGMII] = "qsgmii", - [PHY_INTERFACE_MODE_TBI] = "tbi", - [PHY_INTERFACE_MODE_RMII] = "rmii", - [PHY_INTERFACE_MODE_RGMII] = "rgmii", - [PHY_INTERFACE_MODE_RGMII_ID] = "rgmii-id", - [PHY_INTERFACE_MODE_RGMII_RXID] = "rgmii-rxid", - [PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid", - [PHY_INTERFACE_MODE_RTBI] = "rtbi", - [PHY_INTERFACE_MODE_XGMII] = "xgmii", - [PHY_INTERFACE_MODE_XAUI] = "xaui", - [PHY_INTERFACE_MODE_RXAUI] = "rxaui", - [PHY_INTERFACE_MODE_SFI] = "sfi", - [PHY_INTERFACE_MODE_INTERNAL] = "internal", - [PHY_INTERFACE_MODE_NONE] = "", -}; - -static inline const char *phy_string_for_interface(phy_interface_t i) -{ - /* Default to unknown */ - if (i > PHY_INTERFACE_MODE_NONE) - i = PHY_INTERFACE_MODE_NONE; - - return phy_interface_strings[i]; -} - - struct phy_device; #define MDIO_NAME_LEN 32 diff --git a/include/phy_interface.h b/include/phy_interface.h new file mode 100644 index 00000000000..0760d65de51 --- /dev/null +++ b/include/phy_interface.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2011 Freescale Semiconductor, Inc. + * Andy Fleming + * + * This file pretty much stolen from Linux's mii.h/ethtool.h/phy.h + */ + +#ifndef _PHY_INTERFACE_H +#define _PHY_INTERFACE_H + +typedef enum { + PHY_INTERFACE_MODE_MII, + PHY_INTERFACE_MODE_GMII, + PHY_INTERFACE_MODE_SGMII, + PHY_INTERFACE_MODE_SGMII_2500, + PHY_INTERFACE_MODE_QSGMII, + PHY_INTERFACE_MODE_TBI, + PHY_INTERFACE_MODE_RMII, + PHY_INTERFACE_MODE_RGMII, + PHY_INTERFACE_MODE_RGMII_ID, + PHY_INTERFACE_MODE_RGMII_RXID, + PHY_INTERFACE_MODE_RGMII_TXID, + PHY_INTERFACE_MODE_RTBI, + PHY_INTERFACE_MODE_XGMII, + PHY_INTERFACE_MODE_XAUI, + PHY_INTERFACE_MODE_RXAUI, + PHY_INTERFACE_MODE_SFI, + PHY_INTERFACE_MODE_INTERNAL, + PHY_INTERFACE_MODE_NONE, /* Must be last */ + + PHY_INTERFACE_MODE_COUNT, +} phy_interface_t; + +static const char * const phy_interface_strings[] = { + [PHY_INTERFACE_MODE_MII] = "mii", + [PHY_INTERFACE_MODE_GMII] = "gmii", + [PHY_INTERFACE_MODE_SGMII] = "sgmii", + [PHY_INTERFACE_MODE_SGMII_2500] = "sgmii-2500", + [PHY_INTERFACE_MODE_QSGMII] = "qsgmii", + [PHY_INTERFACE_MODE_TBI] = "tbi", + [PHY_INTERFACE_MODE_RMII] = "rmii", + [PHY_INTERFACE_MODE_RGMII] = "rgmii", + [PHY_INTERFACE_MODE_RGMII_ID] = "rgmii-id", + [PHY_INTERFACE_MODE_RGMII_RXID] = "rgmii-rxid", + [PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid", + [PHY_INTERFACE_MODE_RTBI] = "rtbi", + [PHY_INTERFACE_MODE_XGMII] = "xgmii", + [PHY_INTERFACE_MODE_XAUI] = "xaui", + [PHY_INTERFACE_MODE_RXAUI] = "rxaui", + [PHY_INTERFACE_MODE_SFI] = "sfi", + [PHY_INTERFACE_MODE_INTERNAL] = "internal", + [PHY_INTERFACE_MODE_NONE] = "", +}; + +static inline const char *phy_string_for_interface(phy_interface_t i) +{ + /* Default to unknown */ + if (i > PHY_INTERFACE_MODE_NONE) + i = PHY_INTERFACE_MODE_NONE; + + return phy_interface_strings[i]; +} + +#endif /* _PHY_INTERFACE_H */ -- cgit v1.2.3 From 05b60ac549bbb1cc0738b96d2ee0e342d90bbc1f Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Wed, 25 Jul 2018 12:59:22 -0500 Subject: net: phy: Clean up includes of common.h We want to be able to include some other system headers in phy.h but that requires us to have included common.h in the top-level first. Also, common.h includes config.h as the first thing it does, so don't include it directly. Series-to: u-boot Series-cc: Grygorii Strashko Seried-cc: ti Series-process-log: sort, uniq Cover-letter: Prepare for net: phy: prevent uclass_eth device "node" field overwriting Prepare for [1] so that it doesn't break the build for a bunch of boards. There are a number of reasons this series broke the build but none of them depend on changes in the series, so fix up those situations ahead of applying that series. [1] https://patchwork.ozlabs.org/cover/940104/ END Signed-off-by: Joe Hershberger --- drivers/net/phy/atheros.c | 1 + drivers/net/phy/broadcom.c | 1 - drivers/net/phy/davicom.c | 1 + drivers/net/phy/generic_10g.c | 2 -- drivers/net/phy/lxt.c | 1 + drivers/net/phy/marvell.c | 1 - drivers/net/phy/micrel_ksz8xxx.c | 1 - drivers/net/phy/micrel_ksz90x1.c | 2 -- drivers/net/phy/natsemi.c | 1 + drivers/net/phy/phy.c | 2 -- drivers/net/phy/realtek.c | 1 - drivers/net/phy/smsc.c | 1 + drivers/net/phy/teranetics.c | 1 - drivers/net/phy/vitesse.c | 1 + 14 files changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index 79f68af14c0..3783d155e79 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -5,6 +5,7 @@ * Copyright 2011, 2013 Freescale Semiconductor, Inc. * author Andy Fleming */ +#include #include #define AR803x_PHY_DEBUG_ADDR_REG 0x1d diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 202e3dd487f..3399fd23662 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -5,7 +5,6 @@ * Copyright 2010-2011 Freescale Semiconductor, Inc. * author Andy Fleming */ -#include #include #include diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c index 27c7788493d..4666497d44f 100644 --- a/drivers/net/phy/davicom.c +++ b/drivers/net/phy/davicom.c @@ -5,6 +5,7 @@ * Copyright 2010-2011 Freescale Semiconductor, Inc. * author Andy Fleming */ +#include #include #define MIIM_DM9161_SCR 0x10 diff --git a/drivers/net/phy/generic_10g.c b/drivers/net/phy/generic_10g.c index 1024d7db7b9..b4384e1f781 100644 --- a/drivers/net/phy/generic_10g.c +++ b/drivers/net/phy/generic_10g.c @@ -7,8 +7,6 @@ * * Based loosely off of Linux's PHY Lib */ - -#include #include #include #include diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c index 5942664f1c3..2618deb0096 100644 --- a/drivers/net/phy/lxt.c +++ b/drivers/net/phy/lxt.c @@ -5,6 +5,7 @@ * Copyright 2010-2011 Freescale Semiconductor, Inc. * author Andy Fleming */ +#include #include /* LXT971 Status 2 registers */ diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 436ff572fea..efbbd31ff71 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -5,7 +5,6 @@ * Copyright 2010-2011 Freescale Semiconductor, Inc. * author Andy Fleming */ -#include #include #include #include diff --git a/drivers/net/phy/micrel_ksz8xxx.c b/drivers/net/phy/micrel_ksz8xxx.c index c70c0364b86..3411150ab9d 100644 --- a/drivers/net/phy/micrel_ksz8xxx.c +++ b/drivers/net/phy/micrel_ksz8xxx.c @@ -6,7 +6,6 @@ * author Andy Fleming * (C) 2012 NetModule AG, David Andrey, added KSZ9031 */ -#include #include #include #include diff --git a/drivers/net/phy/micrel_ksz90x1.c b/drivers/net/phy/micrel_ksz90x1.c index 5462532be63..3951535bf1f 100644 --- a/drivers/net/phy/micrel_ksz90x1.c +++ b/drivers/net/phy/micrel_ksz90x1.c @@ -8,8 +8,6 @@ * (C) Copyright 2017 Adaptrum, Inc. * Written by Alexandru Gagniuc for Adaptrum, Inc. */ - -#include #include #include #include diff --git a/drivers/net/phy/natsemi.c b/drivers/net/phy/natsemi.c index 05c7e7c0890..efde4574deb 100644 --- a/drivers/net/phy/natsemi.c +++ b/drivers/net/phy/natsemi.c @@ -5,6 +5,7 @@ * Copyright 2010-2011 Freescale Semiconductor, Inc. * author Andy Fleming */ +#include #include /* NatSemi DP83630 */ diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 4e610bf054b..a88c13ac587 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -7,8 +7,6 @@ * * Based loosely off of Linux's PHY Lib */ - -#include #include #include #include diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index b0867af2206..b3e6578df9a 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -6,7 +6,6 @@ * author Andy Fleming * Copyright 2016 Karsten Merker */ -#include #include #include #include diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index 2f92957a5a7..7740a2510d2 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -9,6 +9,7 @@ * Some code copied from linux kernel * Copyright (c) 2006 Herbert Valerio Riedel */ +#include #include /* This code does not check the partner abilities. */ diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c index d674e8f8574..49d6a1ad901 100644 --- a/drivers/net/phy/teranetics.c +++ b/drivers/net/phy/teranetics.c @@ -5,7 +5,6 @@ * Copyright 2010-2011 Freescale Semiconductor, Inc. * author Andy Fleming */ -#include #include #include diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index 9df4a3fae5c..eca26c98938 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -6,6 +6,7 @@ * Original Author: Andy Fleming * Add vsc8662 phy support - Priyanka Jain */ +#include #include /* Cicada Auxiliary Control/Status Register */ -- cgit v1.2.3 From eef0b8a930d1a8799b8ebd26e67e27401df6a9f7 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 5 Jul 2018 12:02:48 -0500 Subject: net: phy: add ofnode node to struct phy_device Now the UCLASS_ETH device "node" field is owerwritten by some network drivers in case of Ethernet PHYs which are linked to UCLASS_ETH device using "phy-handle" DT property and when Ethernet PHY driver needs to read some additional information from DT. In such cases following happens (in general): - network drivers priv->phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface); <-- phydev is connected to dev which is UCLASS_ETH device if (priv->phy_of_handle > 0) dev_set_of_offset(priv->phydev->dev, priv->phy_of_handle); <-- phydev->dev->node is overwritten by phy-handle DT node - PHY driver in .config() callback int node = dev_of_offset(dev); <-- PHY driver uses overwritten dev->node const void *fdt = gd->fdt_blob; if (fdtdec_get_bool(fdt, node, "property")) ... As result, UCLASS_ETH device can't be used any more for DT accessing. This patch adds additional ofnode node field to struct phy_device which can be set explicitly by network drivers and used by PHY drivers, so overwriting can be avoided. Also add helper function phy_get_ofnode() which will check and return phy_device->node or dev_ofnode(phydev->dev) for backward compatibility with existing drivers. Signed-off-by: Grygorii Strashko Acked-by: Joe Hershberger --- drivers/net/phy/phy.c | 4 ++++ include/phy.h | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index a88c13ac587..e837eb7688c 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -642,6 +642,10 @@ static struct phy_device *phy_device_create(struct mii_dev *bus, int addr, dev->link = 0; dev->interface = interface; +#ifdef CONFIG_DM_ETH + dev->node = ofnode_null(); +#endif + dev->autoneg = AUTONEG_ENABLE; dev->addr = addr; diff --git a/include/phy.h b/include/phy.h index 09645a8ddb0..d6a83150cf6 100644 --- a/include/phy.h +++ b/include/phy.h @@ -9,6 +9,7 @@ #ifndef _PHY_H #define _PHY_H +#include #include #include #include @@ -112,6 +113,7 @@ struct phy_device { #ifdef CONFIG_DM_ETH struct udevice *dev; + ofnode node; #else struct eth_device *dev; #endif @@ -182,11 +184,22 @@ void phy_connect_dev(struct phy_device *phydev, struct udevice *dev); struct phy_device *phy_connect(struct mii_dev *bus, int addr, struct udevice *dev, phy_interface_t interface); +static inline ofnode phy_get_ofnode(struct phy_device *phydev) +{ + if (ofnode_valid(phydev->node)) + return phydev->node; + else + return dev_ofnode(phydev->dev); +} #else void phy_connect_dev(struct phy_device *phydev, struct eth_device *dev); struct phy_device *phy_connect(struct mii_dev *bus, int addr, struct eth_device *dev, phy_interface_t interface); +static inline ofnode phy_get_ofnode(struct phy_device *phydev) +{ + return ofnode_null(); +} #endif int phy_startup(struct phy_device *phydev); int phy_config(struct phy_device *phydev); -- cgit v1.2.3 From b8d7ec782f3b969d828831359411203adfc20dd0 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 5 Jul 2018 12:02:49 -0500 Subject: net: phy: dp83867: switch to use phy_get_ofnode() Use PHY API phy_get_ofnode() helper to get PHY DT node. Signed-off-by: Grygorii Strashko Acked-by: Joe Hershberger Tested-by: Siva Durga Prasad Paladugu --- drivers/net/phy/ti.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c index 655f46d22f9..f870e6d6620 100644 --- a/drivers/net/phy/ti.c +++ b/drivers/net/phy/ti.c @@ -172,8 +172,11 @@ void phy_write_mmd_indirect(struct phy_device *phydev, int prtad, static int dp83867_of_init(struct phy_device *phydev) { struct dp83867_private *dp83867 = phydev->priv; - struct udevice *dev = phydev->dev; - ofnode node = dev_ofnode(dev); + ofnode node; + + node = phy_get_ofnode(phydev); + if (!ofnode_valid(node)) + return -EINVAL; if (ofnode_read_bool(node, "ti,max-output-impedance")) dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX; -- cgit v1.2.3 From aadbd97843f6cb50aaf4a9f3790058416d98f3b4 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 5 Jul 2018 12:02:50 -0500 Subject: net: phy: xilinx: switch to use phy_get_ofnode() Use PHY API phy_get_ofnode() helper to get PHY DT node. Signed-off-by: Grygorii Strashko Acked-by: Joe Hershberger --- drivers/net/phy/xilinx_phy.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/phy/xilinx_phy.c b/drivers/net/phy/xilinx_phy.c index 004cfcf6472..3aa8891efe4 100644 --- a/drivers/net/phy/xilinx_phy.c +++ b/drivers/net/phy/xilinx_phy.c @@ -10,8 +10,6 @@ #include #include -DECLARE_GLOBAL_DATA_PTR; - #define MII_PHY_STATUS_SPD_MASK 0x0C00 #define MII_PHY_STATUS_FULLDUPLEX 0x1000 #define MII_PHY_STATUS_1000 0x0800 @@ -101,10 +99,14 @@ static int xilinxphy_startup(struct phy_device *phydev) static int xilinxphy_of_init(struct phy_device *phydev) { u32 phytype; + ofnode node; debug("%s\n", __func__); - phytype = fdtdec_get_int(gd->fdt_blob, dev_of_offset(phydev->dev), - "xlnx,phy-type", -1); + node = phy_get_ofnode(phydev); + if (!ofnode_valid(node)) + return -EINVAL; + + phytype = ofnode_read_u32_default(node, "xlnx,phy-type", -1); if (phytype == XAE_PHY_TYPE_1000BASE_X) phydev->flags |= XAE_PHY_TYPE_1000BASE_X; -- cgit v1.2.3 From d4bb98170006ed98d651fabefab1c0c2b6aac234 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 5 Jul 2018 12:02:51 -0500 Subject: drivers: net: cpsw: fix phy dt node setting Now CPSW driver will overwrite UCLASS_ETH node when PHY is connected and configured which is not correct. Use struct phydev->node instead. Signed-off-by: Grygorii Strashko Acked-by: Joe Hershberger --- drivers/net/cpsw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c index 9919d3919fa..c31695eba9d 100644 --- a/drivers/net/cpsw.c +++ b/drivers/net/cpsw.c @@ -999,7 +999,7 @@ static int cpsw_phy_init(struct cpsw_priv *priv, struct cpsw_slave *slave) #ifdef CONFIG_DM_ETH if (slave->data->phy_of_handle) - dev_set_of_offset(phydev->dev, slave->data->phy_of_handle); + phydev->node = offset_to_ofnode(slave->data->phy_of_handle); #endif priv->phydev = phydev; -- cgit v1.2.3 From 41080e180c2249a0da586b3e79f15ae7515b8a18 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 5 Jul 2018 12:02:52 -0500 Subject: drivers: net: zynq_gem: fix phy dt node setting Now zynq_gem driver will overwrite UCLASS_ETH node when PHY is connected and configured which is not correct. Use struct phydev->node instead. Signed-off-by: Grygorii Strashko Acked-by: Joe Hershberger Tested-by: Siva Durga Prasad Paladugu --- drivers/net/zynq_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index d1138fe0903..0f56cda1689 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -350,7 +350,7 @@ static int zynq_phy_init(struct udevice *dev) priv->phydev->advertising = priv->phydev->supported; if (priv->phy_of_handle > 0) - dev_set_of_offset(priv->phydev->dev, priv->phy_of_handle); + priv->phydev->node = offset_to_ofnode(priv->phy_of_handle); return phy_config(priv->phydev); } -- cgit v1.2.3 From 26026e695afa794ac018a09e79a48120d322b60d Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Mon, 16 Jul 2018 18:25:45 +0530 Subject: net: zynq_gem: convert to use livetree This patch updates the zynq gem driver to support livetree. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Vipul Kumar Acked-by: Joe Hershberger --- drivers/net/zynq_gem.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 0f56cda1689..68d1c2fceaf 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -178,7 +178,7 @@ struct zynq_gem_priv { struct zynq_gem_regs *iobase; phy_interface_t interface; struct phy_device *phydev; - int phy_of_handle; + ofnode phy_of_node; struct mii_dev *bus; struct clk clk; u32 max_speed; @@ -348,9 +348,7 @@ static int zynq_phy_init(struct udevice *dev) } priv->phydev->advertising = priv->phydev->supported; - - if (priv->phy_of_handle > 0) - priv->phydev->node = offset_to_ofnode(priv->phy_of_handle); + priv->phydev->node = priv->phy_of_node; return phy_config(priv->phydev); } @@ -693,21 +691,23 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); struct zynq_gem_priv *priv = dev_get_priv(dev); - int node = dev_of_offset(dev); + struct ofnode_phandle_args phandle_args; const char *phy_mode; - pdata->iobase = (phys_addr_t)devfdt_get_addr(dev); + pdata->iobase = (phys_addr_t)dev_read_addr(dev); priv->iobase = (struct zynq_gem_regs *)pdata->iobase; /* Hardcode for now */ priv->phyaddr = -1; - priv->phy_of_handle = fdtdec_lookup_phandle(gd->fdt_blob, node, - "phy-handle"); - if (priv->phy_of_handle > 0) - priv->phyaddr = fdtdec_get_int(gd->fdt_blob, - priv->phy_of_handle, "reg", -1); + if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0, + &phandle_args)) { + debug("phy-handle does not exist %s\n", dev->name); + return -ENOENT; + } - phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL); + priv->phyaddr = ofnode_read_u32_default(phandle_args.node, "reg", -1); + priv->phy_of_node = phandle_args.node; + phy_mode = dev_read_prop(dev, "phy-mode", NULL); if (phy_mode) pdata->phy_interface = phy_get_interface_by_name(phy_mode); if (pdata->phy_interface == -1) { @@ -716,10 +716,8 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev) } priv->interface = pdata->phy_interface; - priv->max_speed = fdtdec_get_uint(gd->fdt_blob, priv->phy_of_handle, - "max-speed", SPEED_1000); - priv->int_pcs = fdtdec_get_bool(gd->fdt_blob, node, - "is-internal-pcspma"); + priv->max_speed = dev_read_u32_default(dev, "max-speed", SPEED_1000); + priv->int_pcs = dev_read_bool(dev, "is-internal-pcspma"); printf("ZYNQ GEM: %lx, phyaddr %x, interface %s\n", (ulong)priv->iobase, priv->phyaddr, phy_string_for_interface(priv->interface)); -- cgit v1.2.3