diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2012-09-26 17:53:29 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2012-09-27 23:55:12 +0200 |
commit | 0dc9de2efd7ea6fb613afec822b52b4bfe5a7b2e (patch) | |
tree | ba3e5e30565806280a1ee22dd49875cf61fa9cbe /net | |
parent | 2263e27814f1db83745a9e65c373c957307c36a0 (diff) | |
download | barebox-0dc9de2efd7ea6fb613afec822b52b4bfe5a7b2e.tar.gz barebox-0dc9de2efd7ea6fb613afec822b52b4bfe5a7b2e.tar.xz |
net/eth: fix link handling
Check link status on eth device open time and then periodically
every 5 seconds.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'net')
-rw-r--r-- | net/eth.c | 75 |
1 files changed, 57 insertions, 18 deletions
@@ -32,6 +32,7 @@ #include <malloc.h> static struct eth_device *eth_current; +static uint64_t last_link_check; static LIST_HEAD(netdev_list); @@ -128,24 +129,64 @@ int eth_complete(struct string_list *sl, char *instr) } #endif -int eth_send(void *packet, int length) +/* + * Check for link if we haven't done so for longer. + */ +static int eth_carrier_check(int force) { int ret; - if (!eth_current) - return -ENODEV; + if (!IS_ENABLED(CONFIG_PHYLIB)) + return 0; - if (!eth_current->active) { - ret = eth_current->open(eth_current); + if (!eth_current->phydev) + return 0; + + if (force || is_timeout(last_link_check, 5 * SECOND)) { + ret = phy_update_status(eth_current->phydev); if (ret) return ret; - - if (eth_current->phydev) - eth_current->active = eth_current->phydev->link; - else - eth_current->active = 1; + last_link_check = get_time_ns(); } + return eth_current->phydev->link ? 0 : -ENETDOWN; +} + +/* + * Check if we have a current ethernet device and + * eventually open it if we have to. + */ +static int eth_check_open(void) +{ + int ret; + + if (!eth_current) + return -ENODEV; + + if (eth_current->active) + return 0; + + ret = eth_current->open(eth_current); + if (ret) + return ret; + + eth_current->active = 1; + + return eth_carrier_check(1); +} + +int eth_send(void *packet, int length) +{ + int ret; + + ret = eth_check_open(); + if (ret) + return ret; + + ret = eth_carrier_check(0); + if (ret) + return ret; + led_trigger_network(LED_TRIGGER_NET_TX); return eth_current->send(eth_current, packet, length); @@ -155,15 +196,13 @@ int eth_rx(void) { int ret; - if (!eth_current) - return -ENODEV; + ret = eth_check_open(); + if (ret) + return ret; - if (!eth_current->active) { - ret = eth_current->open(eth_current); - if (ret) - return ret; - eth_current->active = 1; - } + ret = eth_carrier_check(0); + if (ret) + return ret; return eth_current->recv(eth_current); } |