]> git.karo-electronics.de Git - karo-tx-uboot.git/blobdiff - net/eth.c
net: cosmetic: Clean up ARP variables and functions
[karo-tx-uboot.git] / net / eth.c
index 058c55a0e6e6ca0885040b957170958abb44e6f7..3f5cb7ec991d409b6098e01a768e37a389564dd6 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,7 +66,8 @@ 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)
@@ -98,6 +99,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 +122,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 +244,7 @@ int eth_init(void)
 {
        struct udevice *current;
        struct udevice *old_current;
+       int ret = -ENODEV;
 
        current = eth_get_dev();
        if (!current) {
@@ -210,22 +267,29 @@ 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 +309,7 @@ void eth_halt(void)
 int eth_send(void *packet, int length)
 {
        struct udevice *current;
+       int ret;
 
        current = eth_get_dev();
        if (!current)
@@ -253,7 +318,12 @@ 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)
@@ -275,11 +345,17 @@ int eth_rx(void)
                ret = eth_get_ops(current)->recv(current, &packet);
                if (ret > 0)
                        net_process_received_packet(packet, ret);
-               else
+               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;
 }
 
@@ -293,7 +369,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;
@@ -327,6 +403,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)
@@ -334,6 +422,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);
@@ -379,8 +470,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);
@@ -392,11 +483,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;
@@ -421,6 +512,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
 
@@ -453,6 +545,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;
@@ -511,8 +608,8 @@ 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);
@@ -523,19 +620,19 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
                }
 
                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)) {
+       } 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);
                        return -EINVAL;
@@ -672,14 +769,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;
@@ -869,7 +966,6 @@ void eth_set_current(void)
 {
        static char *act;
        static int  env_changed_id;
-       void *old_current;
        int     env_id;
 
        env_id = get_env_id();
@@ -877,13 +973,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();