diff options
author | Ahmad Fatoum <a.fatoum@pengutronix.de> | 2023-01-30 08:20:55 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2023-02-03 09:05:26 +0100 |
commit | 8c49e53208bbbf68fdb27250d98ca20e267602e6 (patch) | |
tree | ec32eba2add13872ab2c461a4fb606de7a196aa4 | |
parent | 0275cbae004d3f8510589d486645cd5d205cc525 (diff) | |
download | barebox-8c49e53208bbbf68fdb27250d98ca20e267602e6.tar.gz |
net: ifup: have ifup -a poll for link up in parallel
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@pengutronix.de>
Link: https://lore.barebox.org/20230130072057.34349-2-a.fatoum@pengutronix.de
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r-- | include/net.h | 3 | ||||
-rw-r--r-- | net/eth.c | 28 | ||||
-rw-r--r-- | net/ifup.c | 103 |
3 files changed, 105 insertions, 29 deletions
diff --git a/include/net.h b/include/net.h index 0555b0bd6b..a7da282412 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); @@ -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 e4d5374db3..c491ea03c1 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) |