diff options
Diffstat (limited to 'net/eth.c')
-rw-r--r-- | net/eth.c | 111 |
1 files changed, 75 insertions, 36 deletions
@@ -10,6 +10,7 @@ #include <dhcp.h> #include <net.h> #include <dma.h> +#include <machine_id.h> #include <of.h> #include <of_net.h> #include <linux/phy.h> @@ -20,8 +21,6 @@ #include <linux/ctype.h> #include <linux/stat.h> -static uint64_t last_link_check; - LIST_HEAD(netdev_list); struct eth_ethaddr { @@ -33,6 +32,14 @@ struct eth_ethaddr { static LIST_HEAD(ethaddr_list); +int eth_set_promisc(struct eth_device *edev, bool enable) +{ + if (!edev->set_promisc) + return -EOPNOTSUPP; + + return edev->set_promisc(edev, enable); +} + int eth_set_ethaddr(struct eth_device *edev, const char *ethaddr) { int ret; @@ -48,11 +55,8 @@ int eth_set_ethaddr(struct eth_device *edev, const char *ethaddr) static void register_preset_mac_address(struct eth_device *edev, const char *ethaddr) { - unsigned char ethaddr_str[sizeof("xx:xx:xx:xx:xx:xx")]; - if (is_valid_ether_addr(ethaddr)) { - ethaddr_to_string(ethaddr, ethaddr_str); - dev_info(&edev->dev, "got preset MAC address: %s\n", ethaddr_str); + dev_info(&edev->dev, "got preset MAC address: %pM\n", ethaddr); eth_set_ethaddr(edev, ethaddr); } } @@ -63,7 +67,7 @@ static int eth_get_registered_ethaddr(struct eth_device *edev, void *buf) struct device_node *node = NULL; if (edev->parent) - node = edev->parent->device_node; + node = edev->parent->of_node; list_for_each_entry(addr, ðaddr_list, list) { if ((node && node == addr->node) || @@ -115,9 +119,9 @@ static struct eth_device *eth_get_by_node(struct device_node *node) for_each_netdev(edev) { if (!edev->parent) continue; - if (!edev->parent->device_node) + if (!edev->parent->of_node) continue; - if (edev->parent->device_node == node) + if (edev->parent->of_node == node) return edev; } return NULL; @@ -170,28 +174,42 @@ 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, int force) +static int eth_carrier_check(struct eth_device *edev, bool may_wait) { - int ret; - if (!IS_ENABLED(CONFIG_PHYLIB)) return 0; if (!edev->phydev) return 0; - if (force) - phy_wait_aneg_done(edev->phydev); + if (!edev->last_link_check || + is_timeout(edev->last_link_check, 5 * SECOND)) + eth_carrier_poll_once(edev); - if (force || is_timeout(last_link_check, 5 * SECOND) || - !edev->phydev->link) { - ret = phy_update_status(edev->phydev); - if (ret) - return ret; - last_link_check = get_time_ns(); + if (may_wait && !edev->phydev->link) { + phy_wait_aneg_done(edev->phydev); + edev->last_link_check = get_time_ns(); } return edev->phydev->link ? 0 : -ENETDOWN; @@ -237,7 +255,7 @@ int eth_send(struct eth_device *edev, void *packet, int length) if (slice_acquired(eth_device_slice(edev))) return eth_queue(edev, packet, length); - ret = eth_carrier_check(edev, 0); + ret = eth_carrier_check(edev, true); if (ret) return ret; @@ -258,7 +276,7 @@ static void eth_do_work(struct eth_device *edev) int ret; if (!phy_acquired(edev->phydev)) { - ret = eth_carrier_check(edev, 0); + ret = eth_carrier_check(edev, false); if (ret) return; } @@ -377,7 +395,7 @@ static const char * const eth_mode_names[] = { int eth_register(struct eth_device *edev) { - struct device_d *dev = &edev->dev; + struct device *dev = &edev->dev; unsigned char ethaddr[ETH_ALEN]; int ret, found = 0; @@ -391,8 +409,9 @@ int eth_register(struct eth_device *edev) if (edev->parent) edev->dev.parent = edev->parent; - if (edev->dev.parent && edev->dev.parent->device_node) { - edev->dev.id = of_alias_get_id(edev->dev.parent->device_node, "ethernet"); + if (edev->dev.parent && edev->dev.parent->of_node) { + edev->dev.id = of_alias_get_id(edev->dev.parent->of_node, + "ethernet"); if (edev->dev.id < 0) edev->dev.id = DEVICE_ID_DYNAMIC; } else { @@ -442,8 +461,8 @@ int eth_register(struct eth_device *edev) register_preset_mac_address(edev, ethaddr); if (IS_ENABLED(CONFIG_OFDEVICE) && edev->parent && - edev->parent->device_node) - edev->nodepath = xstrdup(edev->parent->device_node->full_name); + edev->parent->of_node) + edev->nodepath = xstrdup(edev->parent->of_node->full_name); return 0; } @@ -455,12 +474,12 @@ int eth_open(struct eth_device *edev) if (edev->active) return 0; + edev->last_link_check = 0; + ret = edev->open(edev); if (!ret) edev->active = 1; - eth_carrier_check(edev, 1); - return ret; } @@ -516,31 +535,51 @@ struct eth_device *of_find_eth_device_by_node(struct device_node *np) return NULL; list_for_each_entry(edev, &netdev_list, list) - if (edev->parent->device_node == np) + if (edev->parent->of_node == np) return edev; return NULL; } EXPORT_SYMBOL(of_find_eth_device_by_node); -static int of_populate_ethaddr(void) +void eth_open_all(void) { - char str[sizeof("xx:xx:xx:xx:xx:xx")]; struct eth_device *edev; + + list_for_each_entry(edev, &netdev_list, list) { + if (edev->global_mode == ETH_MODE_DISABLED) + continue; + eth_open(edev); + } +} + +static int populate_ethaddr(void) +{ + struct eth_device *edev; + bool generated = false; int ret; list_for_each_entry(edev, &netdev_list, list) { if (!edev->parent || is_valid_ether_addr(edev->ethaddr)) continue; - ret = of_get_mac_addr_nvmem(edev->parent->device_node, edev->ethaddr); + ret = of_get_mac_addr_nvmem(edev->parent->of_node, + edev->ethaddr); + if (IS_ENABLED(CONFIG_NET_ETHADDR_FROM_MACHINE_ID) && ret) { + ret = generate_ether_addr(edev->ethaddr, edev->dev.id); + generated = true; + } if (ret) continue; - ethaddr_to_string(edev->ethaddr, str); - dev_info(&edev->dev, "Got preset MAC address from device tree: %s\n", str); + if (generated) + dev_notice(&edev->dev, "Generated MAC address from unique id: %pM\n", + edev->ethaddr); + else + dev_info(&edev->dev, "Got preset MAC address from NVMEM: %pM\n", + edev->ethaddr); eth_set_ethaddr(edev, edev->ethaddr); } return 0; } -postenvironment_initcall(of_populate_ethaddr); +postenvironment_initcall(populate_ethaddr); |