DHCP is usually fairly quick, but link up check timeout is 10 seconds, which adds up, especially on systems with bigger DSA switches. The workaround is to set ethX.mode=disabled for other ports, but let's improve the default a bit and have barebox poll link ups in parallel, so instead of (number_of_ports_wihout_link * 10s), we just wait 10s at most. For setups where this is a problem, users may revert to ifup in sequence by doing ifup -a -s. Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx> --- v1 -> v2: - new patch --- include/net.h | 3 ++ net/eth.c | 28 ++++++++++---- net/ifup.c | 103 ++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 105 insertions(+), 29 deletions(-) diff --git a/include/net.h b/include/net.h index 0555b0bd6bed..a7da282412fa 100644 --- a/include/net.h +++ b/include/net.h @@ -109,6 +109,7 @@ static inline int eth_send_raw(struct eth_device *edev, void *packet, int eth_register(struct eth_device* dev); /* Register network device */ void eth_unregister(struct eth_device* dev); /* Unregister network device */ int eth_set_ethaddr(struct eth_device *edev, const char *ethaddr); +int eth_carrier_poll_once(struct eth_device *edev); int eth_open(struct eth_device *edev); void eth_close(struct eth_device *edev); int eth_send(struct eth_device *edev, void *packet, int length); /* Send a packet */ @@ -511,6 +512,8 @@ int net_icmp_send(struct net_connection *con, int len); void led_trigger_network(enum led_trigger trigger); #define IFUP_FLAG_FORCE (1 << 0) +#define IFUP_FLAG_PARALLEL (1 << 1) +#define IFUP_FLAG_SKIP_CONF (1 << 2) int ifup_edev(struct eth_device *edev, unsigned flags); int ifup(const char *name, unsigned flags); diff --git a/net/eth.c b/net/eth.c index 6fb64afea024..ccac5e2a6488 100644 --- a/net/eth.c +++ b/net/eth.c @@ -176,13 +176,29 @@ int eth_complete(struct string_list *sl, char *instr) } #endif +int eth_carrier_poll_once(struct eth_device *edev) +{ + int ret; + + if (!IS_ENABLED(CONFIG_PHYLIB)) + return 0; + + if (!edev->phydev) + return 0; + + ret = phy_update_status(edev->phydev); + if (ret) + return ret; + + edev->last_link_check = get_time_ns(); + return edev->phydev->link ? 0 : -ENETDOWN; +} + /* * Check for link if we haven't done so for longer. */ static int eth_carrier_check(struct eth_device *edev, bool may_wait) { - int ret; - if (!IS_ENABLED(CONFIG_PHYLIB)) return 0; @@ -190,12 +206,8 @@ static int eth_carrier_check(struct eth_device *edev, bool may_wait) return 0; if (!edev->last_link_check || - is_timeout(edev->last_link_check, 5 * SECOND)) { - ret = phy_update_status(edev->phydev); - if (ret) - return ret; - edev->last_link_check = get_time_ns(); - } + is_timeout(edev->last_link_check, 5 * SECOND)) + eth_carrier_poll_once(edev); if (may_wait && !edev->phydev->link) { phy_wait_aneg_done(edev->phydev); diff --git a/net/ifup.c b/net/ifup.c index e4d5374db3ae..c491ea03c1c8 100644 --- a/net/ifup.c +++ b/net/ifup.c @@ -179,6 +179,28 @@ static void set_linux_bootarg(struct eth_device *edev) } } +static int ifup_edev_conf(struct eth_device *edev, unsigned flags) +{ + int ret; + + if (edev->global_mode == ETH_MODE_DHCP) { + if (IS_ENABLED(CONFIG_NET_DHCP)) { + ret = dhcp(edev, NULL); + } else { + dev_err(&edev->dev, "DHCP support not available\n"); + ret = -ENOSYS; + } + if (ret) + return ret; + } + + set_linux_bootarg(edev); + + edev->ifup = true; + + return 0; +} + int ifup_edev(struct eth_device *edev, unsigned flags) { int ret; @@ -205,22 +227,10 @@ int ifup_edev(struct eth_device *edev, unsigned flags) if (ret) return ret; - if (edev->global_mode == ETH_MODE_DHCP) { - if (IS_ENABLED(CONFIG_NET_DHCP)) { - ret = dhcp(edev, NULL); - } else { - dev_err(&edev->dev, "DHCP support not available\n"); - ret = -ENOSYS; - } - if (ret) - return ret; - } - - set_linux_bootarg(edev); - - edev->ifup = true; + if (flags & IFUP_FLAG_SKIP_CONF) + return 1; - return 0; + return ifup_edev_conf(edev, flags); } void ifdown_edev(struct eth_device *edev) @@ -260,9 +270,54 @@ int ifdown(const char *ethname) static int net_ifup_force_detect; -int ifup_all(unsigned flags) +static bool ifup_edev_need_conf(struct eth_device *edev) +{ + return edev->active && !edev->ifup && + edev->global_mode != ETH_MODE_DISABLED; +} + +static void __ifup_all_parallel(unsigned flags) { struct eth_device *edev; + unsigned netdev_count = 0; + u64 start; + int ret; + + for_each_netdev(edev) { + ret = ifup_edev(edev, flags | IFUP_FLAG_SKIP_CONF); + if (ret == 1) + netdev_count++; + } + + start = get_time_ns(); + while (netdev_count && !is_timeout(start, PHY_AN_TIMEOUT * SECOND)) { + for_each_netdev(edev) { + if (!ifup_edev_need_conf(edev)) + continue; + + ret = eth_carrier_poll_once(edev); + if (ret) + continue; + + ifup_edev_conf(edev, flags); + if (!edev->ifup) + continue; + + netdev_count--; + } + } +} + +static void __ifup_all_sequence(unsigned flags) +{ + struct eth_device *edev; + + for_each_netdev(edev) + ifup_edev(edev, flags); +} + +int ifup_all(unsigned flags) +{ DIR *dir; struct dirent *d; @@ -285,8 +340,10 @@ int ifup_all(unsigned flags) list_empty(&netdev_list)) device_detect_all(); - for_each_netdev(edev) - ifup_edev(edev, flags); + if (flags & IFUP_FLAG_PARALLEL) + __ifup_all_parallel(flags); + else + __ifup_all_sequence(flags); return 0; } @@ -315,14 +372,17 @@ BAREBOX_MAGICVAR(global.net.ifup_force_detect, static int do_ifup(int argc, char *argv[]) { int opt; - unsigned flags = 0; + unsigned flags = IFUP_FLAG_PARALLEL; int all = 0; - while ((opt = getopt(argc, argv, "af")) > 0) { + while ((opt = getopt(argc, argv, "asf")) > 0) { switch (opt) { case 'f': flags |= IFUP_FLAG_FORCE; break; + case 's': + flags &= ~IFUP_FLAG_PARALLEL; + break; case 'a': all = 1; break; @@ -346,13 +406,14 @@ BAREBOX_CMD_HELP_TEXT("/env/network/<intf> file. See Documentation/user/networki BAREBOX_CMD_HELP_TEXT("") BAREBOX_CMD_HELP_TEXT("Options:") BAREBOX_CMD_HELP_OPT ("-a", "bring up all interfaces") +BAREBOX_CMD_HELP_OPT ("-s", "bring up interfaces in sequence, not in parallel") BAREBOX_CMD_HELP_OPT ("-f", "Force. Configure even if ip already set") BAREBOX_CMD_HELP_END BAREBOX_CMD_START(ifup) .cmd = do_ifup, BAREBOX_CMD_DESC("bring a network interface up") - BAREBOX_CMD_OPTS("[-af] [INTF]") + BAREBOX_CMD_OPTS("[-asf] [INTF]") BAREBOX_CMD_GROUP(CMD_GRP_NET) BAREBOX_CMD_COMPLETE(eth_complete) BAREBOX_CMD_HELP(cmd_ifup_help) -- 2.30.2