ath9k_htc: Set the BSSID mask for multiple interfaces
authorSujith Manoharan <Sujith.Manoharan@atheros.com>
Mon, 21 Feb 2011 02:18:46 +0000 (07:48 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 23 Feb 2011 21:25:26 +0000 (16:25 -0500)
Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/htc.h
drivers/net/wireless/ath/ath9k/htc_drv_main.c

index eecb42b24bc5360d2095a45bc7f4dcb42cf2fd20..11d028f2156ebb64b553cebaae41f13b029c1bb9 100644 (file)
@@ -210,6 +210,11 @@ struct ath9k_htc_vif {
        u8 index;
 };
 
+struct ath9k_vif_iter_data {
+       const u8 *hw_macaddr;
+       u8 mask[ETH_ALEN];
+};
+
 #define ATH9K_HTC_MAX_STA 8
 #define ATH9K_HTC_MAX_TID 8
 
index 5ef076978181d7a59d6eccde3f7cbd6da55a4801..9620f4532f022a8ca6275bc41c5a31fae4ab0acc 100644 (file)
@@ -133,6 +133,39 @@ static void ath9k_htc_vif_reconfig(struct ath9k_htc_priv *priv)
        }
 }
 
+static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+       struct ath9k_vif_iter_data *iter_data = data;
+       int i;
+
+       for (i = 0; i < ETH_ALEN; i++)
+               iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
+}
+
+static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
+                                    struct ieee80211_vif *vif)
+{
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       struct ath9k_vif_iter_data iter_data;
+
+       /*
+        * Use the hardware MAC address as reference, the hardware uses it
+        * together with the BSSID mask when matching addresses.
+        */
+       iter_data.hw_macaddr = common->macaddr;
+       memset(&iter_data.mask, 0xff, ETH_ALEN);
+
+       if (vif)
+               ath9k_htc_bssid_iter(&iter_data, vif->addr, vif);
+
+       /* Get list of all active MAC addresses */
+       ieee80211_iterate_active_interfaces_atomic(priv->hw, ath9k_htc_bssid_iter,
+                                                  &iter_data);
+
+       memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
+       ath_hw_setbssidmask(common);
+}
+
 void ath9k_htc_reset(struct ath9k_htc_priv *priv)
 {
        struct ath_hw *ah = priv->ah;
@@ -1200,6 +1233,8 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
                goto out;
        }
 
+       ath9k_htc_set_bssid_mask(priv, vif);
+
        priv->ah->opmode = vif->type;
        priv->vif_slot |= (1 << avp->index);
        priv->nvifs++;