wilc1000: added 'ndo_set_mac_address' callback support
authorAjay Singh <ajay.kathat@microchip.com>
Wed, 25 Nov 2020 11:41:08 +0000 (11:41 +0000)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 2 Dec 2020 19:38:07 +0000 (21:38 +0200)
Added support for 'ndo_set_mac_address call' callback to allow change of
interface MAC address.

Signed-off-by: Ajay Singh <ajay.kathat@microchip.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20201125114059.10006-2-ajay.kathat@microchip.com
drivers/net/wireless/microchip/wilc1000/hif.c
drivers/net/wireless/microchip/wilc1000/hif.h
drivers/net/wireless/microchip/wilc1000/netdev.c

index d025a30..a133736 100644 (file)
@@ -1276,6 +1276,23 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
        return result;
 }
 
+int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr)
+{
+       struct wid wid;
+       int result;
+
+       wid.id = WID_MAC_ADDR;
+       wid.type = WID_STR;
+       wid.size = ETH_ALEN;
+       wid.val = mac_addr;
+
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result)
+               netdev_err(vif->ndev, "Failed to get mac address\n");
+
+       return result;
+}
+
 int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies,
                      size_t ies_len)
 {
index db91791..5881191 100644 (file)
@@ -168,6 +168,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
                    u8 cipher_mode);
 int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid);
 int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr);
+int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr);
 int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies,
                      size_t ies_len);
 int wilc_disconnect(struct wilc_vif *vif);
index 20615c7..2a1fbbd 100644 (file)
@@ -628,6 +628,43 @@ static struct net_device_stats *mac_stats(struct net_device *dev)
        return &vif->netstats;
 }
 
+static int wilc_set_mac_addr(struct net_device *dev, void *p)
+{
+       int result;
+       struct wilc_vif *vif = netdev_priv(dev);
+       struct wilc *wilc = vif->wilc;
+       struct sockaddr *addr = (struct sockaddr *)p;
+       unsigned char mac_addr[ETH_ALEN];
+       struct wilc_vif *tmp_vif;
+       int srcu_idx;
+
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EINVAL;
+
+       srcu_idx = srcu_read_lock(&wilc->srcu);
+       list_for_each_entry_rcu(tmp_vif, &wilc->vif_list, list) {
+               wilc_get_mac_address(tmp_vif, mac_addr);
+               if (ether_addr_equal(addr->sa_data, mac_addr)) {
+                       if (vif != tmp_vif) {
+                               srcu_read_unlock(&wilc->srcu, srcu_idx);
+                               return -EINVAL;
+                       }
+                       srcu_read_unlock(&wilc->srcu, srcu_idx);
+                       return 0;
+               }
+       }
+       srcu_read_unlock(&wilc->srcu, srcu_idx);
+
+       result = wilc_set_mac_address(vif, (u8 *)addr->sa_data);
+       if (result)
+               return result;
+
+       ether_addr_copy(vif->bssid, addr->sa_data);
+       ether_addr_copy(vif->ndev->dev_addr, addr->sa_data);
+
+       return result;
+}
+
 static void wilc_set_multicast_list(struct net_device *dev)
 {
        struct netdev_hw_addr *ha;
@@ -813,6 +850,7 @@ static const struct net_device_ops wilc_netdev_ops = {
        .ndo_init = mac_init_fn,
        .ndo_open = wilc_mac_open,
        .ndo_stop = wilc_mac_close,
+       .ndo_set_mac_address = wilc_set_mac_addr,
        .ndo_start_xmit = wilc_mac_xmit,
        .ndo_get_stats = mac_stats,
        .ndo_set_rx_mode  = wilc_set_multicast_list,