diff options
Diffstat (limited to 'net/eth.c')
-rw-r--r-- | net/eth.c | 73 |
1 files changed, 58 insertions, 15 deletions
@@ -27,11 +27,12 @@ #include <driver.h> #include <init.h> #include <net.h> -#include <miidev.h> +#include <linux/phy.h> #include <errno.h> #include <malloc.h> static struct eth_device *eth_current; +static uint64_t last_link_check; static LIST_HEAD(netdev_list); @@ -128,20 +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->phydev) + return 0; - if (!eth_current->active) { - ret = eth_current->open(eth_current); + if (force || is_timeout(last_link_check, 5 * SECOND)) { + ret = phy_update_status(eth_current->phydev); if (ret) return ret; - 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); @@ -151,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); } |