]> git.karo-electronics.de Git - karo-tx-uboot.git/blobdiff - net/eth.c
net: Fix compile errors when SNTP enabled and not DATE
[karo-tx-uboot.git] / net / eth.c
index 1abf0274b489d98b79ef94885682fab0f18095e6..ff55e737eec02ac767f46c76e27c80145d0f45ca 100644 (file)
--- a/net/eth.c
+++ b/net/eth.c
@@ -32,7 +32,7 @@ void eth_parse_enetaddr(const char *addr, uchar *enetaddr)
 int eth_getenv_enetaddr(char *name, uchar *enetaddr)
 {
        eth_parse_enetaddr(getenv(name), enetaddr);
-       return is_valid_ether_addr(enetaddr);
+       return is_valid_ethaddr(enetaddr);
 }
 
 int eth_setenv_enetaddr(char *name, const uchar *enetaddr)
@@ -66,15 +66,18 @@ static void eth_env_init(void)
 
        s = getenv("bootfile");
        if (s != NULL)
-               copy_filename(BootFile, s, sizeof(BootFile));
+               copy_filename(net_boot_file_name, s,
+                             sizeof(net_boot_file_name));
 }
 
 static int eth_mac_skip(int index)
 {
        char enetvar[15];
        char *skip_state;
+
        sprintf(enetvar, index ? "eth%dmacskip" : "ethmacskip", index);
-       return ((skip_state = getenv(enetvar)) != NULL);
+       skip_state = getenv(enetvar);
+       return skip_state != NULL;
 }
 
 static void eth_current_changed(void);
@@ -98,6 +101,9 @@ struct eth_uclass_priv {
        struct udevice *current;
 };
 
+/* eth_errno - This stores the most recent failure code from DM functions */
+static int eth_errno;
+
 static struct eth_uclass_priv *eth_get_uclass_priv(void)
 {
        struct uclass *uc;
@@ -118,23 +124,75 @@ static void eth_set_current_to_next(void)
                uclass_first_device(UCLASS_ETH, &uc_priv->current);
 }
 
+/*
+ * Typically this will simply return the active device.
+ * In the case where the most recent active device was unset, this will attempt
+ * to return the first device. If that device doesn't exist or fails to probe,
+ * this function will return NULL.
+ */
 struct udevice *eth_get_dev(void)
 {
        struct eth_uclass_priv *uc_priv;
 
        uc_priv = eth_get_uclass_priv();
        if (!uc_priv->current)
-               uclass_first_device(UCLASS_ETH,
+               eth_errno = uclass_first_device(UCLASS_ETH,
                                    &uc_priv->current);
        return uc_priv->current;
 }
 
+/*
+ * Typically this will just store a device pointer.
+ * In case it was not probed, we will attempt to do so.
+ * dev may be NULL to unset the active device.
+ */
 static void eth_set_dev(struct udevice *dev)
 {
-       device_probe(dev);
+       if (dev && !device_active(dev))
+               eth_errno = device_probe(dev);
        eth_get_uclass_priv()->current = dev;
 }
 
+/*
+ * Find the udevice that either has the name passed in as devname or has an
+ * alias named devname.
+ */
+struct udevice *eth_get_dev_by_name(const char *devname)
+{
+       int seq = -1;
+       char *endp = NULL;
+       const char *startp = NULL;
+       struct udevice *it;
+       struct uclass *uc;
+
+       /* Must be longer than 3 to be an alias */
+       if (strlen(devname) > strlen("eth")) {
+               startp = devname + strlen("eth");
+               seq = simple_strtoul(startp, &endp, 10);
+       }
+
+       uclass_get(UCLASS_ETH, &uc);
+       uclass_foreach_dev(it, uc) {
+               /*
+                * We need the seq to be valid, so try to probe it.
+                * If the probe fails, the seq will not match since it will be
+                * -1 instead of what we are looking for.
+                * We don't care about errors from probe here. Either they won't
+                * 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 (strcmp(it->name, devname) == 0 ||
+                   (endp > startp && it->seq == seq))
+                       return it;
+       }
+
+       return NULL;
+}
+
 unsigned char *eth_get_ethaddr(void)
 {
        struct eth_pdata *pdata;
@@ -188,6 +246,7 @@ int eth_init(void)
 {
        struct udevice *current;
        struct udevice *old_current;
+       int ret = -ENODEV;
 
        current = eth_get_dev();
        if (!current) {
@@ -210,22 +269,30 @@ int eth_init(void)
                        else
                                memset(pdata->enetaddr, 0, 6);
 
-                       if (eth_get_ops(current)->start(current) >= 0) {
+                       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 {
+                       ret = eth_errno;
                }
+
                debug("FAIL\n");
 
-               /* This will ensure the new "current" attempted to probe */
+               /*
+                * If ethrotate is enabled, this will change "current",
+                * otherwise we will drop out of this while loop immediately
+                */
                eth_try_another(0);
+               /* This will ensure the new "current" attempted to probe */
                current = eth_get_dev();
        } while (old_current != current);
 
-       return -ENODEV;
+       return ret;
 }
 
 void eth_halt(void)
@@ -245,6 +312,7 @@ void eth_halt(void)
 int eth_send(void *packet, int length)
 {
        struct udevice *current;
+       int ret;
 
        current = eth_get_dev();
        if (!current)
@@ -253,12 +321,20 @@ int eth_send(void *packet, int length)
        if (!device_active(current))
                return -EINVAL;
 
-       return eth_get_ops(current)->send(current, packet, length);
+       ret = eth_get_ops(current)->send(current, packet, length);
+       if (ret < 0) {
+               /* We cannot completely return the error at present */
+               debug("%s: send() returned error %d\n", __func__, ret);
+       }
+       return ret;
 }
 
 int eth_rx(void)
 {
        struct udevice *current;
+       uchar *packet;
+       int ret;
+       int i;
 
        current = eth_get_dev();
        if (!current)
@@ -267,7 +343,23 @@ int eth_rx(void)
        if (!device_active(current))
                return -EINVAL;
 
-       return eth_get_ops(current)->recv(current);
+       /* Process up to 32 packets at one time */
+       for (i = 0; i < 32; i++) {
+               ret = eth_get_ops(current)->recv(current, &packet);
+               if (ret > 0)
+                       net_process_received_packet(packet, ret);
+               if (ret >= 0 && eth_get_ops(current)->free_pkt)
+                       eth_get_ops(current)->free_pkt(current, packet, ret);
+               if (ret <= 0)
+                       break;
+       }
+       if (ret == -EAGAIN)
+               ret = 0;
+       if (ret < 0) {
+               /* We cannot completely return the error at present */
+               debug("%s: recv() returned error %d\n", __func__, ret);
+       }
+       return ret;
 }
 
 static int eth_write_hwaddr(struct udevice *dev)
@@ -280,7 +372,7 @@ static int eth_write_hwaddr(struct udevice *dev)
 
        /* seq is valid since the device is active */
        if (eth_get_ops(dev)->write_hwaddr && !eth_mac_skip(dev->seq)) {
-               if (!is_valid_ether_addr(pdata->enetaddr)) {
+               if (!is_valid_ethaddr(pdata->enetaddr)) {
                        printf("\nError: %s address %pM illegal value\n",
                               dev->name, pdata->enetaddr);
                        return -EINVAL;
@@ -314,6 +406,18 @@ int eth_initialize(void)
                printf("No ethernet found.\n");
                bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
        } else {
+               char *ethprime = getenv("ethprime");
+               struct udevice *prime_dev = NULL;
+
+               if (ethprime)
+                       prime_dev = eth_get_dev_by_name(ethprime);
+               if (prime_dev) {
+                       eth_set_dev(prime_dev);
+                       eth_current_changed();
+               } else {
+                       eth_set_dev(NULL);
+               }
+
                bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
                do {
                        if (num_devices)
@@ -321,6 +425,9 @@ int eth_initialize(void)
 
                        printf("eth%d: %s", dev->seq, dev->name);
 
+                       if (ethprime && dev == prime_dev)
+                               printf(" [PRIME]");
+
                        eth_write_hwaddr(dev);
 
                        uclass_next_device(&dev);
@@ -366,8 +473,8 @@ static int eth_post_probe(struct udevice *dev)
                eth_get_ops(dev)->read_rom_hwaddr(dev);
 
        eth_getenv_enetaddr_by_index("eth", dev->seq, env_enetaddr);
-       if (!is_zero_ether_addr(env_enetaddr)) {
-               if (!is_zero_ether_addr(pdata->enetaddr) &&
+       if (!is_zero_ethaddr(env_enetaddr)) {
+               if (!is_zero_ethaddr(pdata->enetaddr) &&
                    memcmp(pdata->enetaddr, env_enetaddr, 6)) {
                        printf("\nWarning: %s MAC addresses don't match:\n",
                               dev->name);
@@ -379,11 +486,11 @@ static int eth_post_probe(struct udevice *dev)
 
                /* Override the ROM MAC address */
                memcpy(pdata->enetaddr, env_enetaddr, 6);
-       } else if (is_valid_ether_addr(pdata->enetaddr)) {
+       } else if (is_valid_ethaddr(pdata->enetaddr)) {
                eth_setenv_enetaddr_by_index("eth", dev->seq, pdata->enetaddr);
                printf("\nWarning: %s using MAC address from ROM\n",
                       dev->name);
-       } else if (is_zero_ether_addr(pdata->enetaddr)) {
+       } else if (is_zero_ethaddr(pdata->enetaddr)) {
                printf("\nError: %s address not set.\n",
                       dev->name);
                return -EINVAL;
@@ -408,6 +515,7 @@ UCLASS_DRIVER(eth) = {
        .pre_remove     = eth_pre_remove,
        .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
        .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
+       .flags          = DM_UC_FLAG_SEQ_ALIAS,
 };
 #endif
 
@@ -440,6 +548,11 @@ static void eth_set_current_to_next(void)
        eth_current = eth_current->next;
 }
 
+static void eth_set_dev(struct eth_device *dev)
+{
+       eth_current = dev;
+}
+
 struct eth_device *eth_get_dev_by_name(const char *devname)
 {
        struct eth_device *dev, *target_dev;
@@ -498,39 +611,40 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 
        eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
 
-       if (!is_zero_ether_addr(env_enetaddr)) {
-               if (!is_zero_ether_addr(dev->enetaddr) &&
+       if (!is_zero_ethaddr(env_enetaddr)) {
+               if (!is_zero_ethaddr(dev->enetaddr) &&
                    memcmp(dev->enetaddr, env_enetaddr, 6)) {
                        printf("\nWarning: %s MAC addresses don't match:\n",
-                               dev->name);
+                              dev->name);
                        printf("Address in SROM is         %pM\n",
-                               dev->enetaddr);
+                              dev->enetaddr);
                        printf("Address in environment is  %pM\n",
-                               env_enetaddr);
+                              env_enetaddr);
                }
 
                memcpy(dev->enetaddr, env_enetaddr, 6);
-       } else if (is_valid_ether_addr(dev->enetaddr)) {
+       } else if (is_valid_ethaddr(dev->enetaddr)) {
                eth_setenv_enetaddr_by_index(base_name, eth_number,
                                             dev->enetaddr);
                printf("\nWarning: %s using MAC address from net device\n",
-                       dev->name);
-       } else if (is_zero_ether_addr(dev->enetaddr)) {
+                      dev->name);
+       } else if (is_zero_ethaddr(dev->enetaddr)) {
                printf("\nError: %s address not set.\n",
                       dev->name);
                return -EINVAL;
        }
 
        if (dev->write_hwaddr && !eth_mac_skip(eth_number)) {
-               if (!is_valid_ether_addr(dev->enetaddr)) {
+               if (!is_valid_ethaddr(dev->enetaddr)) {
                        printf("\nError: %s address %pM illegal value\n",
-                                dev->name, dev->enetaddr);
+                              dev->name, dev->enetaddr);
                        return -EINVAL;
                }
 
                ret = dev->write_hwaddr(dev);
                if (ret)
-                       printf("\nWarning: %s failed to set MAC address\n", dev->name);
+                       printf("\nWarning: %s failed to set MAC address\n",
+                              dev->name);
        }
 
        return ret;
@@ -544,7 +658,8 @@ int eth_register(struct eth_device *dev)
        assert(strlen(dev->name) < sizeof(dev->name));
 
        if (!eth_devices) {
-               eth_current = eth_devices = dev;
+               eth_devices = dev;
+               eth_current = dev;
                eth_current_changed();
        } else {
                for (d = eth_devices; d->next != eth_devices; d = d->next)
@@ -615,8 +730,9 @@ int eth_initialize(void)
        } else if (cpu_eth_init != __def_eth_init) {
                if (cpu_eth_init(gd->bd) < 0)
                        printf("CPU Net Initialization Failed\n");
-       } else
+       } else {
                printf("Net Initialization Skipped\n");
+       }
 
        if (!eth_devices) {
                puts("No ethernet found.\n");
@@ -659,14 +775,14 @@ int eth_initialize(void)
  * mcast_addr: multicast ipaddr from which multicast Mac is made
  * join: 1=join, 0=leave.
  */
-int eth_mcast_join(IPaddr_t mcast_ip, int join)
+int eth_mcast_join(struct in_addr mcast_ip, int join)
 {
        u8 mcast_mac[6];
        if (!eth_current || !eth_current->mcast)
                return -1;
-       mcast_mac[5] = htonl(mcast_ip) & 0xff;
-       mcast_mac[4] = (htonl(mcast_ip)>>8) & 0xff;
-       mcast_mac[3] = (htonl(mcast_ip)>>16) & 0x7f;
+       mcast_mac[5] = htonl(mcast_ip.s_addr) & 0xff;
+       mcast_mac[4] = (htonl(mcast_ip.s_addr)>>8) & 0xff;
+       mcast_mac[3] = (htonl(mcast_ip.s_addr)>>16) & 0x7f;
        mcast_mac[2] = 0x5e;
        mcast_mac[1] = 0x0;
        mcast_mac[0] = 0x1;
@@ -849,14 +965,13 @@ void eth_try_another(int first_restart)
        eth_current_changed();
 
        if (first_failed == eth_get_dev())
-               NetRestartWrap = 1;
+               net_restart_wrap = 1;
 }
 
 void eth_set_current(void)
 {
        static char *act;
        static int  env_changed_id;
-       void *old_current;
        int     env_id;
 
        env_id = get_env_id();
@@ -864,13 +979,19 @@ void eth_set_current(void)
                act = getenv("ethact");
                env_changed_id = env_id;
        }
-       if (act != NULL) {
-               old_current = eth_get_dev();
-               do {
-                       if (strcmp(eth_get_name(), act) == 0)
-                               return;
-                       eth_set_current_to_next();
-               } while (old_current != eth_get_dev());
+
+       if (act == NULL) {
+               char *ethprime = getenv("ethprime");
+               void *dev = NULL;
+
+               if (ethprime)
+                       dev = eth_get_dev_by_name(ethprime);
+               if (dev)
+                       eth_set_dev(dev);
+               else
+                       eth_set_dev(NULL);
+       } else {
+               eth_set_dev(eth_get_dev_by_name(act));
        }
 
        eth_current_changed();