X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=net%2Feth.c;h=c542f4aa3b3b1e4f2e6fbb5db4c0ea579aefe45e;hb=5e68ff3949a3eebf62ba639171814f39c8e46a84;hp=a40abb5f949dd36d721342afe4eca4f0d3246296;hpb=2d1febf7d5867cb5441c5d5081d042b61cc647eb;p=oweals%2Fu-boot.git diff --git a/net/eth.c b/net/eth.c index a40abb5f94..c542f4aa3b 100644 --- a/net/eth.c +++ b/net/eth.c @@ -9,11 +9,13 @@ #include #include #include +#include #include #include #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -29,13 +31,13 @@ void eth_parse_enetaddr(const char *addr, uchar *enetaddr) } } -int eth_getenv_enetaddr(char *name, uchar *enetaddr) +int eth_getenv_enetaddr(const char *name, uchar *enetaddr) { eth_parse_enetaddr(getenv(name), enetaddr); return is_valid_ethaddr(enetaddr); } -int eth_setenv_enetaddr(char *name, const uchar *enetaddr) +int eth_setenv_enetaddr(const char *name, const uchar *enetaddr) { char buf[20]; @@ -105,7 +107,9 @@ static void eth_common_init(void) if (cpu_eth_init(gd->bd) < 0) printf("CPU Net Initialization Failed\n"); } else { +#ifndef CONFIG_DM_ETH printf("Net Initialization Skipped\n"); +#endif } } @@ -175,8 +179,12 @@ struct udevice *eth_get_dev(void) */ static void eth_set_dev(struct udevice *dev) { - if (dev && !device_active(dev)) + if (dev && !device_active(dev)) { eth_errno = device_probe(dev); + if (eth_errno) + dev = NULL; + } + eth_get_uclass_priv()->current = dev; } @@ -191,10 +199,11 @@ struct udevice *eth_get_dev_by_name(const char *devname) const char *startp = NULL; struct udevice *it; struct uclass *uc; + int len = strlen("eth"); /* Must be longer than 3 to be an alias */ - if (strlen(devname) > strlen("eth")) { - startp = devname + strlen("eth"); + if (!strncmp(devname, "eth", len) && strlen(devname) > len) { + startp = devname + len; seq = simple_strtoul(startp, &endp, 10); } @@ -208,10 +217,9 @@ struct udevice *eth_get_dev_by_name(const char *devname) * match an alias or it will match a literal name and we'll pick * up the error when we try to probe again in eth_set_dev(). */ - device_probe(it); - /* - * Check for the name or the sequence number to match - */ + if (device_probe(it)) + continue; + /* Check for the name or the sequence number to match */ if (strcmp(it->name, devname) == 0 || (endp > startp && it->seq == seq)) return it; @@ -285,7 +293,13 @@ static int eth_write_hwaddr(struct udevice *dev) return -EINVAL; } + /* + * Drivers are allowed to decide not to implement this at + * run-time. E.g. Some devices may use it and some may not. + */ ret = eth_get_ops(dev)->write_hwaddr(dev); + if (ret == -ENOSYS) + ret = 0; if (ret) printf("\nWarning: %s failed to set MAC address\n", dev->name); @@ -294,6 +308,33 @@ static int eth_write_hwaddr(struct udevice *dev) return ret; } +static int on_ethaddr(const char *name, const char *value, enum env_op op, + int flags) +{ + int index; + int retval; + struct udevice *dev; + + /* look for an index after "eth" */ + index = simple_strtoul(name + 3, NULL, 10); + + retval = uclass_find_device_by_seq(UCLASS_ETH, index, false, &dev); + if (!retval) { + struct eth_pdata *pdata = dev->platdata; + switch (op) { + case env_op_create: + case env_op_overwrite: + eth_parse_enetaddr(value, pdata->enetaddr); + break; + case env_op_delete: + memset(pdata->enetaddr, 0, 6); + } + } + + return 0; +} +U_BOOT_ENV_CALLBACK(ethaddr, on_ethaddr); + int eth_init(void) { struct udevice *current; @@ -308,42 +349,27 @@ int eth_init(void) old_current = current; do { - debug("Trying %s\n", current->name); - - if (device_active(current)) { - uchar env_enetaddr[6]; - struct eth_pdata *pdata = current->platdata; - int enetaddr_changed = 0; - - /* Sync environment with network device */ - if (eth_getenv_enetaddr_by_index("eth", current->seq, - env_enetaddr)) { - enetaddr_changed = memcmp(pdata->enetaddr, - env_enetaddr, 6); - memcpy(pdata->enetaddr, env_enetaddr, 6); + if (current) { + debug("Trying %s\n", current->name); + + if (device_active(current)) { + ret = eth_get_ops(current)->start(current); + if (ret >= 0) { + struct eth_device_priv *priv = + current->uclass_priv; + + priv->state = ETH_STATE_ACTIVE; + return 0; + } } else { - memset(env_enetaddr, 0, 6); - enetaddr_changed = memcmp(pdata->enetaddr, - env_enetaddr, 6); - memset(pdata->enetaddr, 0, 6); + ret = eth_errno; } - if (enetaddr_changed) - eth_write_hwaddr(current); - - ret = eth_get_ops(current)->start(current); - if (ret >= 0) { - struct eth_device_priv *priv = - current->uclass_priv; - priv->state = ETH_STATE_ACTIVE; - return 0; - } + debug("FAIL\n"); } else { - ret = eth_errno; + debug("PROBE FAIL\n"); } - debug("FAIL\n"); - /* * If ethrotate is enabled, this will change "current", * otherwise we will drop out of this while loop immediately @@ -370,6 +396,17 @@ void eth_halt(void) priv->state = ETH_STATE_PASSIVE; } +int eth_is_active(struct udevice *dev) +{ + struct eth_device_priv *priv; + + if (!dev || !device_active(dev)) + return 0; + + priv = dev_get_uclass_priv(dev); + return priv->state == ETH_STATE_ACTIVE; +} + int eth_send(void *packet, int length) { struct udevice *current; @@ -394,6 +431,7 @@ int eth_rx(void) { struct udevice *current; uchar *packet; + int flags; int ret; int i; @@ -405,8 +443,10 @@ int eth_rx(void) return -EINVAL; /* Process up to 32 packets at one time */ + flags = ETH_RECV_CHECK_DEVICE; for (i = 0; i < 32; i++) { - ret = eth_get_ops(current)->recv(current, &packet); + ret = eth_get_ops(current)->recv(current, flags, &packet); + flags = 0; if (ret > 0) net_process_received_packet(packet, ret); if (ret >= 0 && eth_get_ops(current)->free_pkt) @@ -542,8 +582,13 @@ static int eth_post_probe(struct udevice *dev) static int eth_pre_remove(struct udevice *dev) { + struct eth_pdata *pdata = dev->platdata; + eth_get_ops(dev)->stop(dev); + /* clear the MAC address */ + memset(pdata->enetaddr, 0, 6); + return 0; } @@ -558,7 +603,7 @@ UCLASS_DRIVER(eth) = { .per_device_auto_alloc_size = sizeof(struct eth_device_priv), .flags = DM_UC_FLAG_SEQ_ALIAS, }; -#endif +#endif /* #ifdef CONFIG_DM_ETH */ #ifndef CONFIG_DM_ETH @@ -634,6 +679,37 @@ int eth_get_dev_index(void) return eth_current->index; } +static int on_ethaddr(const char *name, const char *value, enum env_op op, + int flags) +{ + int index; + struct eth_device *dev; + + if (!eth_devices) + return 0; + + /* look for an index after "eth" */ + index = simple_strtoul(name + 3, NULL, 10); + + dev = eth_devices; + do { + if (dev->index == index) { + switch (op) { + case env_op_create: + case env_op_overwrite: + eth_parse_enetaddr(value, dev->enetaddr); + break; + case env_op_delete: + memset(dev->enetaddr, 0, 6); + } + } + dev = dev->next; + } while (dev != eth_devices); + + return 0; +} +U_BOOT_ENV_CALLBACK(ethaddr, on_ethaddr); + int eth_write_hwaddr(struct eth_device *dev, const char *base_name, int eth_number) { @@ -832,36 +908,13 @@ u32 ether_crc(size_t len, unsigned char const *p) int eth_init(void) { - struct eth_device *old_current, *dev; + struct eth_device *old_current; if (!eth_current) { puts("No ethernet found.\n"); return -ENODEV; } - /* Sync environment with network devices */ - dev = eth_devices; - do { - uchar env_enetaddr[6]; - int enetaddr_changed = 0; - - if (eth_getenv_enetaddr_by_index("eth", dev->index, - env_enetaddr)) { - enetaddr_changed = memcmp(dev->enetaddr, - env_enetaddr, 6); - memcpy(dev->enetaddr, env_enetaddr, 6); - } else { - memset(env_enetaddr, 0, 6); - enetaddr_changed = memcmp(dev->enetaddr, - env_enetaddr, 6); - memset(dev->enetaddr, 0, 6); - } - if (enetaddr_changed) - eth_write_hwaddr(dev, "eth", dev->index); - - dev = dev->next; - } while (dev != eth_devices); - old_current = eth_current; do { debug("Trying %s\n", eth_current->name); @@ -889,6 +942,11 @@ void eth_halt(void) eth_current->state = ETH_STATE_PASSIVE; } +int eth_is_active(struct eth_device *dev) +{ + return dev && dev->state == ETH_STATE_ACTIVE; +} + int eth_send(void *packet, int length) { if (!eth_current)