mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-12-29 20:26:47 +02:00
ath9k: fix multi-bss operation (fixes #7914)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@23059 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
1c358226eb
commit
4c0c6cd520
117
package/mac80211/patches/550-ath9k_bssid_mask_fix.patch
Normal file
117
package/mac80211/patches/550-ath9k_bssid_mask_fix.patch
Normal file
@ -0,0 +1,117 @@
|
||||
--- a/drivers/net/wireless/ath/ath9k/virtual.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/virtual.c
|
||||
@@ -19,45 +19,36 @@
|
||||
#include "ath9k.h"
|
||||
|
||||
struct ath9k_vif_iter_data {
|
||||
- int count;
|
||||
- u8 *addr;
|
||||
+ const u8 *hw_macaddr;
|
||||
+ u8 mask[ETH_ALEN];
|
||||
};
|
||||
|
||||
static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath9k_vif_iter_data *iter_data = data;
|
||||
- u8 *nbuf;
|
||||
-
|
||||
- nbuf = krealloc(iter_data->addr, (iter_data->count + 1) * ETH_ALEN,
|
||||
- GFP_ATOMIC);
|
||||
- if (nbuf == NULL)
|
||||
- return;
|
||||
+ int i;
|
||||
|
||||
- memcpy(nbuf + iter_data->count * ETH_ALEN, mac, ETH_ALEN);
|
||||
- iter_data->addr = nbuf;
|
||||
- iter_data->count++;
|
||||
+ for (i = 0; i < ETH_ALEN; i++)
|
||||
+ iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
|
||||
}
|
||||
|
||||
-void ath9k_set_bssid_mask(struct ieee80211_hw *hw)
|
||||
+void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath9k_vif_iter_data iter_data;
|
||||
- int i, j;
|
||||
- u8 mask[ETH_ALEN];
|
||||
+ int i;
|
||||
|
||||
/*
|
||||
- * Add primary MAC address even if it is not in active use since it
|
||||
- * will be configured to the hardware as the starting point and the
|
||||
- * BSSID mask will need to be changed if another address is active.
|
||||
+ * Use the hardware MAC address as reference, the hardware uses it
|
||||
+ * together with the BSSID mask when matching addresses.
|
||||
*/
|
||||
- iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC);
|
||||
- if (iter_data.addr) {
|
||||
- memcpy(iter_data.addr, common->macaddr, ETH_ALEN);
|
||||
- iter_data.count = 1;
|
||||
- } else
|
||||
- iter_data.count = 0;
|
||||
+ iter_data.hw_macaddr = common->macaddr;
|
||||
+ memset(&iter_data.mask, 0xff, ETH_ALEN);
|
||||
+
|
||||
+ if (vif)
|
||||
+ ath9k_vif_iter(&iter_data, vif->addr, vif);
|
||||
|
||||
/* Get list of all active MAC addresses */
|
||||
spin_lock_bh(&sc->wiphy_lock);
|
||||
@@ -71,31 +62,7 @@ void ath9k_set_bssid_mask(struct ieee802
|
||||
}
|
||||
spin_unlock_bh(&sc->wiphy_lock);
|
||||
|
||||
- /* Generate an address mask to cover all active addresses */
|
||||
- memset(mask, 0, ETH_ALEN);
|
||||
- for (i = 0; i < iter_data.count; i++) {
|
||||
- u8 *a1 = iter_data.addr + i * ETH_ALEN;
|
||||
- for (j = i + 1; j < iter_data.count; j++) {
|
||||
- u8 *a2 = iter_data.addr + j * ETH_ALEN;
|
||||
- mask[0] |= a1[0] ^ a2[0];
|
||||
- mask[1] |= a1[1] ^ a2[1];
|
||||
- mask[2] |= a1[2] ^ a2[2];
|
||||
- mask[3] |= a1[3] ^ a2[3];
|
||||
- mask[4] |= a1[4] ^ a2[4];
|
||||
- mask[5] |= a1[5] ^ a2[5];
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- kfree(iter_data.addr);
|
||||
-
|
||||
- /* Invert the mask and configure hardware */
|
||||
- common->bssidmask[0] = ~mask[0];
|
||||
- common->bssidmask[1] = ~mask[1];
|
||||
- common->bssidmask[2] = ~mask[2];
|
||||
- common->bssidmask[3] = ~mask[3];
|
||||
- common->bssidmask[4] = ~mask[4];
|
||||
- common->bssidmask[5] = ~mask[5];
|
||||
-
|
||||
+ memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
|
||||
ath_hw_setbssidmask(common);
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -666,7 +666,7 @@ static inline void ath_ahb_exit(void) {}
|
||||
void ath9k_ps_wakeup(struct ath_softc *sc);
|
||||
void ath9k_ps_restore(struct ath_softc *sc);
|
||||
|
||||
-void ath9k_set_bssid_mask(struct ieee80211_hw *hw);
|
||||
+void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
int ath9k_wiphy_add(struct ath_softc *sc);
|
||||
int ath9k_wiphy_del(struct ath_wiphy *aphy);
|
||||
void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -1416,7 +1416,7 @@ static int ath9k_add_interface(struct ie
|
||||
sc->nvifs++;
|
||||
|
||||
if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
|
||||
- ath9k_set_bssid_mask(hw);
|
||||
+ ath9k_set_bssid_mask(hw, vif);
|
||||
|
||||
if (sc->nvifs > 1)
|
||||
goto out; /* skip global settings for secondary vif */
|
Loading…
Reference in New Issue
Block a user