summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/net.h3
-rw-r--r--net/eth.c28
-rw-r--r--net/ifup.c103
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);
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)