net: emaclite: Use indirect access in emaclite_recv
[oweals/u-boot.git] / net / eth.c
index c542f4aa3b3b1e4f2e6fbb5db4c0ea579aefe45e..45fe6e3c1c08408d6245d4803df6a5f7ed8f4ced 100644 (file)
--- a/net/eth.c
+++ b/net/eth.c
@@ -337,14 +337,30 @@ U_BOOT_ENV_CALLBACK(ethaddr, on_ethaddr);
 
 int eth_init(void)
 {
-       struct udevice *current;
+       char *ethact = getenv("ethact");
+       char *ethrotate = getenv("ethrotate");
+       struct udevice *current = NULL;
        struct udevice *old_current;
        int ret = -ENODEV;
 
-       current = eth_get_dev();
+       /*
+        * When 'ethrotate' variable is set to 'no' and 'ethact' variable
+        * is already set to an ethernet device, we should stick to 'ethact'.
+        */
+       if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0)) {
+               if (ethact) {
+                       current = eth_get_dev_by_name(ethact);
+                       if (!current)
+                               return -EINVAL;
+               }
+       }
+
        if (!current) {
-               printf("No ethernet found.\n");
-               return -ENODEV;
+               current = eth_get_dev();
+               if (!current) {
+                       printf("No ethernet found.\n");
+                       return -ENODEV;
+               }
        }
 
        old_current = current;
@@ -541,6 +557,34 @@ static int eth_post_probe(struct udevice *dev)
        struct eth_pdata *pdata = dev->platdata;
        unsigned char env_enetaddr[6];
 
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
+       struct eth_ops *ops = eth_get_ops(dev);
+       static int reloc_done;
+
+       if (!reloc_done) {
+               if (ops->start)
+                       ops->start += gd->reloc_off;
+               if (ops->send)
+                       ops->send += gd->reloc_off;
+               if (ops->recv)
+                       ops->recv += gd->reloc_off;
+               if (ops->free_pkt)
+                       ops->free_pkt += gd->reloc_off;
+               if (ops->stop)
+                       ops->stop += gd->reloc_off;
+#ifdef CONFIG_MCAST_TFTP
+               if (ops->mcast)
+                       ops->mcast += gd->reloc_off;
+#endif
+               if (ops->write_hwaddr)
+                       ops->write_hwaddr += gd->reloc_off;
+               if (ops->read_rom_hwaddr)
+                       ops->read_rom_hwaddr += gd->reloc_off;
+
+               reloc_done++;
+       }
+#endif
+
        priv->state = ETH_STATE_INIT;
 
        /* Check if the device has a MAC address in ROM */
@@ -733,8 +777,6 @@ int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
        } 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_ethaddr(dev->enetaddr)) {
 #ifdef CONFIG_NET_RANDOM_ETHADDR
                net_random_ethaddr(dev->enetaddr);
@@ -1011,6 +1053,17 @@ int eth_receive(void *packet, int length)
 static void eth_current_changed(void)
 {
        char *act = getenv("ethact");
+       char *ethrotate;
+
+       /*
+        * The call to eth_get_dev() below has a side effect of rotating
+        * ethernet device if uc_priv->current == NULL. This is not what
+        * we want when 'ethrotate' variable is 'no'.
+        */
+       ethrotate = getenv("ethrotate");
+       if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
+               return;
+
        /* update current ethernet name */
        if (eth_get_dev()) {
                if (act == NULL || strcmp(act, eth_get_name()) != 0)