diff options
author | Rajkumar Manoharan <rmanoharan@atheros.com> | 2011-04-04 13:26:18 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-04-07 15:34:15 -0400 |
commit | 4f5ef75b155955bf92adc772c6660787151fc78c (patch) | |
tree | 8b274c152875ac445b1de352709f9bc371253b48 /drivers | |
parent | 66da424177db4f4f2fa7a462db5912655aad966f (diff) |
ath9k: Handle BSSID/AID for multiple interfaces
As of now bssid/aid is overridden with recently changed vif's
bss config. This may cause improper beacon updation due to
bssid/aid mismatch. On station mode, select an associated
sta vif as primary vif and configure that vif's bss into hw.
Update the primary vif on interface change and bss info change.
Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 70 |
2 files changed, 63 insertions, 10 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index f3a753096d7d..a972396049e5 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -344,7 +344,7 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid | |||
344 | 344 | ||
345 | struct ath_vif { | 345 | struct ath_vif { |
346 | int av_bslot; | 346 | int av_bslot; |
347 | bool is_bslot_active; | 347 | bool is_bslot_active, primary_sta_vif; |
348 | __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ | 348 | __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ |
349 | struct ath_buf *av_bcbuf; | 349 | struct ath_buf *av_bcbuf; |
350 | }; | 350 | }; |
@@ -546,6 +546,7 @@ struct ath_ant_comb { | |||
546 | #define SC_OP_BT_SCAN BIT(13) | 546 | #define SC_OP_BT_SCAN BIT(13) |
547 | #define SC_OP_ANI_RUN BIT(14) | 547 | #define SC_OP_ANI_RUN BIT(14) |
548 | #define SC_OP_ENABLE_APM BIT(15) | 548 | #define SC_OP_ENABLE_APM BIT(15) |
549 | #define SC_OP_PRIM_STA_VIF BIT(16) | ||
549 | 550 | ||
550 | /* Powersave flags */ | 551 | /* Powersave flags */ |
551 | #define PS_WAIT_FOR_BEACON BIT(0) | 552 | #define PS_WAIT_FOR_BEACON BIT(0) |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 6f300d7df88e..3181211ae248 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -841,10 +841,6 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, | |||
841 | "Bss Info ASSOC %d, bssid: %pM\n", | 841 | "Bss Info ASSOC %d, bssid: %pM\n", |
842 | bss_conf->aid, common->curbssid); | 842 | bss_conf->aid, common->curbssid); |
843 | 843 | ||
844 | /* New association, store aid */ | ||
845 | common->curaid = bss_conf->aid; | ||
846 | ath9k_hw_write_associd(ah); | ||
847 | |||
848 | /* | 844 | /* |
849 | * Request a re-configuration of Beacon related timers | 845 | * Request a re-configuration of Beacon related timers |
850 | * on the receipt of the first Beacon frame (i.e., | 846 | * on the receipt of the first Beacon frame (i.e., |
@@ -863,7 +859,6 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, | |||
863 | ath_start_ani(common); | 859 | ath_start_ani(common); |
864 | } else { | 860 | } else { |
865 | ath_dbg(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); | 861 | ath_dbg(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); |
866 | common->curaid = 0; | ||
867 | /* Stop ANI */ | 862 | /* Stop ANI */ |
868 | sc->sc_flags &= ~SC_OP_ANI_RUN; | 863 | sc->sc_flags &= ~SC_OP_ANI_RUN; |
869 | del_timer_sync(&common->ani.timer); | 864 | del_timer_sync(&common->ani.timer); |
@@ -1886,6 +1881,66 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1886 | 1881 | ||
1887 | return ret; | 1882 | return ret; |
1888 | } | 1883 | } |
1884 | static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
1885 | { | ||
1886 | struct ath_softc *sc = data; | ||
1887 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1888 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
1889 | struct ath_vif *avp = (void *)vif->drv_priv; | ||
1890 | |||
1891 | switch (sc->sc_ah->opmode) { | ||
1892 | case NL80211_IFTYPE_ADHOC: | ||
1893 | /* There can be only one vif available */ | ||
1894 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | ||
1895 | common->curaid = bss_conf->aid; | ||
1896 | ath9k_hw_write_associd(sc->sc_ah); | ||
1897 | break; | ||
1898 | case NL80211_IFTYPE_STATION: | ||
1899 | /* | ||
1900 | * Skip iteration if primary station vif's bss info | ||
1901 | * was not changed | ||
1902 | */ | ||
1903 | if (sc->sc_flags & SC_OP_PRIM_STA_VIF) | ||
1904 | break; | ||
1905 | |||
1906 | if (bss_conf->assoc) { | ||
1907 | sc->sc_flags |= SC_OP_PRIM_STA_VIF; | ||
1908 | avp->primary_sta_vif = true; | ||
1909 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | ||
1910 | common->curaid = bss_conf->aid; | ||
1911 | ath9k_hw_write_associd(sc->sc_ah); | ||
1912 | } | ||
1913 | break; | ||
1914 | default: | ||
1915 | break; | ||
1916 | } | ||
1917 | } | ||
1918 | |||
1919 | static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif) | ||
1920 | { | ||
1921 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1922 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
1923 | struct ath_vif *avp = (void *)vif->drv_priv; | ||
1924 | |||
1925 | /* Reconfigure bss info */ | ||
1926 | if (avp->primary_sta_vif && !bss_conf->assoc) { | ||
1927 | sc->sc_flags &= ~SC_OP_PRIM_STA_VIF; | ||
1928 | avp->primary_sta_vif = false; | ||
1929 | memset(common->curbssid, 0, ETH_ALEN); | ||
1930 | common->curaid = 0; | ||
1931 | } | ||
1932 | |||
1933 | ieee80211_iterate_active_interfaces_atomic( | ||
1934 | sc->hw, ath9k_bss_iter, sc); | ||
1935 | |||
1936 | /* | ||
1937 | * None of station vifs are associated. | ||
1938 | * Clear bssid & aid | ||
1939 | */ | ||
1940 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && | ||
1941 | !(sc->sc_flags & SC_OP_PRIM_STA_VIF)) | ||
1942 | ath9k_hw_write_associd(sc->sc_ah); | ||
1943 | } | ||
1889 | 1944 | ||
1890 | static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | 1945 | static void ath9k_bss_info_changed(struct ieee80211_hw *hw, |
1891 | struct ieee80211_vif *vif, | 1946 | struct ieee80211_vif *vif, |
@@ -1903,10 +1958,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
1903 | mutex_lock(&sc->mutex); | 1958 | mutex_lock(&sc->mutex); |
1904 | 1959 | ||
1905 | if (changed & BSS_CHANGED_BSSID) { | 1960 | if (changed & BSS_CHANGED_BSSID) { |
1906 | /* Set BSSID */ | 1961 | ath9k_config_bss(sc, vif); |
1907 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | ||
1908 | common->curaid = 0; | ||
1909 | ath9k_hw_write_associd(ah); | ||
1910 | 1962 | ||
1911 | /* Set aggregation protection mode parameters */ | 1963 | /* Set aggregation protection mode parameters */ |
1912 | sc->config.ath_aggr_prot = 0; | 1964 | sc->config.ath_aggr_prot = 0; |