wilc1000: Bring MAC address setting in line with typical Linux behavior
authorDavid Mosberger-Tang <davidm@egauge.net>
Wed, 3 Mar 2021 19:50:07 +0000 (19:50 +0000)
committerKalle Valo <kvalo@codeaurora.org>
Sat, 17 Apr 2021 17:51:06 +0000 (20:51 +0300)
Linux network drivers normally disallow changing the MAC address when
the interface is up.  This driver has been different in that it allows
to change the MAC address *only* when it's up.  This patch brings
wilc1000 behavior more in line with other network drivers.  We could
have replaced wilc_set_mac_addr() with eth_mac_addr() but that would
break existing documentation on how to change the MAC address.
Likewise, return -EADDRNOTAVAIL (not -EINVAL) when the specified MAC
address is invalid or unavailable.

Signed-off-by: David Mosberger-Tang <davidm@egauge.net>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20210303194846.1823596-1-davidm@egauge.net
drivers/net/wireless/microchip/wilc1000/netdev.c

index 9928e91..7e4d923 100644 (file)
@@ -571,7 +571,6 @@ static int wilc_mac_open(struct net_device *ndev)
 {
        struct wilc_vif *vif = netdev_priv(ndev);
        struct wilc *wl = vif->wilc;
-       unsigned char mac_add[ETH_ALEN] = {0};
        int ret = 0;
        struct mgmt_frame_regs mgmt_regs = {};
 
@@ -594,9 +593,12 @@ static int wilc_mac_open(struct net_device *ndev)
 
        wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype,
                                vif->idx);
-       wilc_get_mac_address(vif, mac_add);
-       netdev_dbg(ndev, "Mac address: %pM\n", mac_add);
-       ether_addr_copy(ndev->dev_addr, mac_add);
+
+       if (is_valid_ether_addr(ndev->dev_addr))
+               wilc_set_mac_address(vif, ndev->dev_addr);
+       else
+               wilc_get_mac_address(vif, ndev->dev_addr);
+       netdev_dbg(ndev, "Mac address: %pM\n", ndev->dev_addr);
 
        if (!is_valid_ether_addr(ndev->dev_addr)) {
                netdev_err(ndev, "Wrong MAC address\n");
@@ -635,7 +637,14 @@ static int wilc_set_mac_addr(struct net_device *dev, void *p)
        int srcu_idx;
 
        if (!is_valid_ether_addr(addr->sa_data))
-               return -EINVAL;
+               return -EADDRNOTAVAIL;
+
+       if (!vif->mac_opened) {
+               eth_commit_mac_addr_change(dev, p);
+               return 0;
+       }
+
+       /* Verify MAC Address is not already in use: */
 
        srcu_idx = srcu_read_lock(&wilc->srcu);
        list_for_each_entry_rcu(tmp_vif, &wilc->vif_list, list) {
@@ -643,7 +652,7 @@ static int wilc_set_mac_addr(struct net_device *dev, void *p)
                if (ether_addr_equal(addr->sa_data, mac_addr)) {
                        if (vif != tmp_vif) {
                                srcu_read_unlock(&wilc->srcu, srcu_idx);
-                               return -EINVAL;
+                               return -EADDRNOTAVAIL;
                        }
                        srcu_read_unlock(&wilc->srcu, srcu_idx);
                        return 0;
@@ -655,9 +664,7 @@ static int wilc_set_mac_addr(struct net_device *dev, void *p)
        if (result)
                return result;
 
-       ether_addr_copy(vif->bssid, addr->sa_data);
-       ether_addr_copy(vif->ndev->dev_addr, addr->sa_data);
-
+       eth_commit_mac_addr_change(dev, p);
        return result;
 }