summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorAhmad Fatoum <a.fatoum@pengutronix.de>2023-01-30 08:20:55 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2023-02-03 09:05:26 +0100
commit8c49e53208bbbf68fdb27250d98ca20e267602e6 (patch)
treeec32eba2add13872ab2c461a4fb606de7a196aa4 /net
parent0275cbae004d3f8510589d486645cd5d205cc525 (diff)
downloadbarebox-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>
Diffstat (limited to 'net')
-rw-r--r--net/eth.c28
-rw-r--r--net/ifup.c103
2 files changed, 102 insertions, 29 deletions
diff --git a/net/eth.c b/net/eth.c
index 6fb64afea0..ccac5e2a64 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 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)