net: Update hardware MAC address if it changes in env
authorJoe Hershberger <joe.hershberger@ni.com>
Tue, 24 Mar 2015 07:41:49 +0000 (02:41 -0500)
committerJoe Hershberger <joe.hershberger@ni.com>
Tue, 19 May 2015 18:33:21 +0000 (13:33 -0500)
When the ethaddr changes in the env, the hardware should also be updated
so that MAC filtering will work properly without resetting U-Boot.

Also remove the manual calls to set the hwaddr that was included in a
few drivers as a result of the framework not doing it.

Reported-by: Michal Simek <michal.simek@xilinx.com>
Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Tested-by: Michal Simek <michal.simek@xilinx.com>
drivers/net/bcm-sf2-eth.c
drivers/net/designware.c
drivers/net/macb.c
net/eth.c

index 51d5146363084a6e3a052acd9fd7e2382c6d4d17..eab4c1f9003258d3926318d69b60f8c061e53c76 100644 (file)
@@ -154,12 +154,6 @@ static int bcm_sf2_eth_open(struct eth_device *dev, bd_t *bt)
 
        debug("Enabling BCM SF2 Ethernet.\n");
 
-       /* Set MAC address from env */
-       if (bcm_sf2_eth_write_hwaddr(dev) != 0) {
-               error("%s: MAC set error when opening !\n", __func__);
-               return -1;
-       }
-
        eth->enable_mac();
 
        /* enable tx and rx DMA */
index 07281a6ce9d2fa204e30c1cfee3e1b5258739485..ae51cf378162b0500edc2152a4b3db4a86604c8e 100644 (file)
@@ -243,10 +243,6 @@ static int _dw_eth_init(struct dw_eth_dev *priv, u8 *enetaddr)
                mdelay(100);
        };
 
-       /* Soft reset above clears HW address registers.
-        * So we have to set it here once again */
-       _dw_write_hwaddr(priv, enetaddr);
-
        rx_descs_init(priv);
        tx_descs_init(priv);
 
index 4e1a7fe58398843a6192da01522d8d9a24c278b2..f9491617382ca2659078d047d6d4f31a794f4f64 100644 (file)
@@ -525,7 +525,6 @@ static int macb_phy_init(struct macb_device *macb)
        return 1;
 }
 
-static int macb_write_hwaddr(struct eth_device *dev);
 static int macb_init(struct eth_device *netdev, bd_t *bd)
 {
        struct macb_device *macb = to_macb(netdev);
@@ -594,14 +593,6 @@ static int macb_init(struct eth_device *netdev, bd_t *bd)
 #endif /* CONFIG_RMII */
        }
 
-       /* update the ethaddr */
-       if (is_valid_ethaddr(netdev->enetaddr)) {
-               macb_write_hwaddr(netdev);
-       } else {
-               printf("%s: mac address is not valid\n", netdev->name);
-               return -1;
-       }
-
        if (!macb_phy_init(macb))
                return -1;
 
index 8e6acfef89c25170f79728aad5e1ab3c9d7445b4..04a544c872a07c8e17ee003262a9d50f7bf3f8b1 100644 (file)
--- a/net/eth.c
+++ b/net/eth.c
@@ -281,6 +281,31 @@ int eth_get_dev_index(void)
        return -1;
 }
 
+static int eth_write_hwaddr(struct udevice *dev)
+{
+       struct eth_pdata *pdata = dev->platdata;
+       int ret = 0;
+
+       if (!dev || !device_active(dev))
+               return -EINVAL;
+
+       /* seq is valid since the device is active */
+       if (eth_get_ops(dev)->write_hwaddr && !eth_mac_skip(dev->seq)) {
+               if (!is_valid_ethaddr(pdata->enetaddr)) {
+                       printf("\nError: %s address %pM illegal value\n",
+                              dev->name, pdata->enetaddr);
+                       return -EINVAL;
+               }
+
+               ret = eth_get_ops(dev)->write_hwaddr(dev);
+               if (ret)
+                       printf("\nWarning: %s failed to set MAC address\n",
+                              dev->name);
+       }
+
+       return ret;
+}
+
 int eth_init(void)
 {
        struct udevice *current;
@@ -300,13 +325,22 @@ int eth_init(void)
                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))
+                                                        env_enetaddr)) {
+                               enetaddr_changed = memcmp(pdata->enetaddr,
+                                       env_enetaddr, 6);
                                memcpy(pdata->enetaddr, env_enetaddr, 6);
-                       else
+                       } else {
+                               memset(env_enetaddr, 0, 6);
+                               enetaddr_changed = memcmp(pdata->enetaddr,
+                                       env_enetaddr, 6);
                                memset(pdata->enetaddr, 0, 6);
+                       }
+                       if (enetaddr_changed)
+                               eth_write_hwaddr(current);
 
                        ret = eth_get_ops(current)->start(current);
                        if (ret >= 0) {
@@ -401,31 +435,6 @@ int eth_rx(void)
        return ret;
 }
 
-static int eth_write_hwaddr(struct udevice *dev)
-{
-       struct eth_pdata *pdata = dev->platdata;
-       int ret = 0;
-
-       if (!dev || !device_active(dev))
-               return -EINVAL;
-
-       /* seq is valid since the device is active */
-       if (eth_get_ops(dev)->write_hwaddr && !eth_mac_skip(dev->seq)) {
-               if (!is_valid_ethaddr(pdata->enetaddr)) {
-                       printf("\nError: %s address %pM illegal value\n",
-                              dev->name, pdata->enetaddr);
-                       return -EINVAL;
-               }
-
-               ret = eth_get_ops(dev)->write_hwaddr(dev);
-               if (ret)
-                       printf("\nWarning: %s failed to set MAC address\n",
-                              dev->name);
-       }
-
-       return ret;
-}
-
 int eth_initialize(void)
 {
        int num_devices = 0;
@@ -834,10 +843,21 @@ int eth_init(void)
        dev = eth_devices;
        do {
                uchar env_enetaddr[6];
+               int enetaddr_changed = 0;
 
                if (eth_getenv_enetaddr_by_index("eth", dev->index,
-                                                env_enetaddr))
+                                                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);