aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c99
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c84
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c2
4 files changed, 103 insertions, 83 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index a972396049e5..38835bc324b2 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -397,6 +397,7 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
397int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif); 397int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif);
398void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); 398void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp);
399int ath_beaconq_config(struct ath_softc *sc); 399int ath_beaconq_config(struct ath_softc *sc);
400void ath_set_beacon(struct ath_softc *sc);
400void ath9k_set_beaconing_status(struct ath_softc *sc, bool status); 401void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
401 402
402/*******/ 403/*******/
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index dfd1b98a086b..eccb0ec87adb 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -663,22 +663,63 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
663 ath9k_hw_set_interrupts(ah, ah->imask); 663 ath9k_hw_set_interrupts(ah, ah->imask);
664} 664}
665 665
666void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) 666static bool ath9k_allow_beacon_config(struct ath_softc *sc,
667 struct ieee80211_vif *vif)
667{ 668{
668 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; 669 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
669 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 670 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
670 enum nl80211_iftype iftype; 671 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
672 struct ath_vif *avp = (void *)vif->drv_priv;
671 673
672 /* Setup the beacon configuration parameters */ 674 /*
673 if (vif) { 675 * Can not have different beacon interval on multiple
674 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 676 * AP interface case
675 iftype = vif->type; 677 */
676 cur_conf->beacon_interval = bss_conf->beacon_int; 678 if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
677 cur_conf->dtim_period = bss_conf->dtim_period; 679 (sc->nbcnvifs > 1) &&
678 } else { 680 (vif->type == NL80211_IFTYPE_AP) &&
679 iftype = sc->sc_ah->opmode; 681 (cur_conf->beacon_interval != bss_conf->beacon_int)) {
682 ath_dbg(common, ATH_DBG_CONFIG,
683 "Changing beacon interval of multiple \
684 AP interfaces !\n");
685 return false;
686 }
687 /*
688 * Can not configure station vif's beacon config
689 * while on AP opmode
690 */
691 if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
692 (vif->type != NL80211_IFTYPE_AP)) {
693 ath_dbg(common, ATH_DBG_CONFIG,
694 "STA vif's beacon not allowed on AP mode\n");
695 return false;
696 }
697 /*
698 * Do not allow beacon config if HW was already configured
699 * with another STA vif
700 */
701 if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
702 (vif->type == NL80211_IFTYPE_STATION) &&
703 (sc->sc_flags & SC_OP_BEACONS) &&
704 !avp->primary_sta_vif) {
705 ath_dbg(common, ATH_DBG_CONFIG,
706 "Beacon already configured for a station interface\n");
707 return false;
680 } 708 }
709 return true;
710}
711
712void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
713{
714 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
715 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
681 716
717 if (!ath9k_allow_beacon_config(sc, vif))
718 return;
719
720 /* Setup the beacon configuration parameters */
721 cur_conf->beacon_interval = bss_conf->beacon_int;
722 cur_conf->dtim_period = bss_conf->dtim_period;
682 cur_conf->listen_interval = 1; 723 cur_conf->listen_interval = 1;
683 cur_conf->dtim_count = 1; 724 cur_conf->dtim_count = 1;
684 cur_conf->bmiss_timeout = 725 cur_conf->bmiss_timeout =
@@ -701,6 +742,15 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
701 if (cur_conf->dtim_period == 0) 742 if (cur_conf->dtim_period == 0)
702 cur_conf->dtim_period = 1; 743 cur_conf->dtim_period = 1;
703 744
745 ath_set_beacon(sc);
746 sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
747}
748
749void ath_set_beacon(struct ath_softc *sc)
750{
751 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
752 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
753
704 switch (sc->sc_ah->opmode) { 754 switch (sc->sc_ah->opmode) {
705 case NL80211_IFTYPE_AP: 755 case NL80211_IFTYPE_AP:
706 ath_beacon_config_ap(sc, cur_conf); 756 ath_beacon_config_ap(sc, cur_conf);
@@ -728,22 +778,23 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status)
728 int slot; 778 int slot;
729 bool found = false; 779 bool found = false;
730 780
731 ath9k_ps_wakeup(sc); 781 for (slot = 0; slot < ATH_BCBUF; slot++) {
732 if (status) { 782 if (sc->beacon.bslot[slot]) {
733 for (slot = 0; slot < ATH_BCBUF; slot++) { 783 avp = (void *)sc->beacon.bslot[slot]->drv_priv;
734 if (sc->beacon.bslot[slot]) { 784 if (avp->is_bslot_active) {
735 avp = (void *)sc->beacon.bslot[slot]->drv_priv; 785 found = true;
736 if (avp->is_bslot_active) { 786 break;
737 found = true;
738 break;
739 }
740 } 787 }
741 } 788 }
742 if (found) { 789 }
743 /* Re-enable beaconing */ 790 if (!found)
744 ah->imask |= ATH9K_INT_SWBA; 791 return;
745 ath9k_hw_set_interrupts(ah, ah->imask); 792
746 } 793 ath9k_ps_wakeup(sc);
794 if (status) {
795 /* Re-enable beaconing */
796 ah->imask |= ATH9K_INT_SWBA;
797 ath9k_hw_set_interrupts(ah, ah->imask);
747 } else { 798 } else {
748 /* Disable SWBA interrupt */ 799 /* Disable SWBA interrupt */
749 ah->imask &= ~ATH9K_INT_SWBA; 800 ah->imask &= ~ATH9K_INT_SWBA;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 3181211ae248..ddd5413c8da8 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -299,7 +299,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
299 299
300 if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) { 300 if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
301 if (sc->sc_flags & SC_OP_BEACONS) 301 if (sc->sc_flags & SC_OP_BEACONS)
302 ath_beacon_config(sc, NULL); 302 ath_set_beacon(sc);
303 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); 303 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
304 ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2); 304 ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
305 ath_start_ani(common); 305 ath_start_ani(common);
@@ -828,43 +828,6 @@ chip_reset:
828#undef SCHED_INTR 828#undef SCHED_INTR
829} 829}
830 830
831static void ath9k_bss_assoc_info(struct ath_softc *sc,
832 struct ieee80211_hw *hw,
833 struct ieee80211_vif *vif,
834 struct ieee80211_bss_conf *bss_conf)
835{
836 struct ath_hw *ah = sc->sc_ah;
837 struct ath_common *common = ath9k_hw_common(ah);
838
839 if (bss_conf->assoc) {
840 ath_dbg(common, ATH_DBG_CONFIG,
841 "Bss Info ASSOC %d, bssid: %pM\n",
842 bss_conf->aid, common->curbssid);
843
844 /*
845 * Request a re-configuration of Beacon related timers
846 * on the receipt of the first Beacon frame (i.e.,
847 * after time sync with the AP).
848 */
849 sc->ps_flags |= PS_BEACON_SYNC;
850
851 /* Configure the beacon */
852 ath_beacon_config(sc, vif);
853
854 /* Reset rssi stats */
855 sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
856 sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
857
858 sc->sc_flags |= SC_OP_ANI_RUN;
859 ath_start_ani(common);
860 } else {
861 ath_dbg(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
862 /* Stop ANI */
863 sc->sc_flags &= ~SC_OP_ANI_RUN;
864 del_timer_sync(&common->ani.timer);
865 }
866}
867
868void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) 831void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
869{ 832{
870 struct ath_hw *ah = sc->sc_ah; 833 struct ath_hw *ah = sc->sc_ah;
@@ -894,7 +857,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
894 goto out; 857 goto out;
895 } 858 }
896 if (sc->sc_flags & SC_OP_BEACONS) 859 if (sc->sc_flags & SC_OP_BEACONS)
897 ath_beacon_config(sc, NULL); /* restart beacons */ 860 ath_set_beacon(sc); /* restart beacons */
898 861
899 /* Re-Enable interrupts */ 862 /* Re-Enable interrupts */
900 ath9k_hw_set_interrupts(ah, ah->imask); 863 ath9k_hw_set_interrupts(ah, ah->imask);
@@ -1001,7 +964,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
1001 sc->config.txpowlimit, &sc->curtxpow); 964 sc->config.txpowlimit, &sc->curtxpow);
1002 965
1003 if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL))) 966 if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
1004 ath_beacon_config(sc, NULL); /* restart beacons */ 967 ath_set_beacon(sc); /* restart beacons */
1005 968
1006 ath9k_hw_set_interrupts(ah, ah->imask); 969 ath9k_hw_set_interrupts(ah, ah->imask);
1007 970
@@ -1408,9 +1371,6 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
1408 if ((iter_data.naps + iter_data.nadhocs) > 0) { 1371 if ((iter_data.naps + iter_data.nadhocs) > 0) {
1409 sc->sc_flags |= SC_OP_ANI_RUN; 1372 sc->sc_flags |= SC_OP_ANI_RUN;
1410 ath_start_ani(common); 1373 ath_start_ani(common);
1411 } else {
1412 sc->sc_flags &= ~SC_OP_ANI_RUN;
1413 del_timer_sync(&common->ani.timer);
1414 } 1374 }
1415} 1375}
1416 1376
@@ -1894,6 +1854,9 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
1894 memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); 1854 memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
1895 common->curaid = bss_conf->aid; 1855 common->curaid = bss_conf->aid;
1896 ath9k_hw_write_associd(sc->sc_ah); 1856 ath9k_hw_write_associd(sc->sc_ah);
1857 /* configure beacon */
1858 if (bss_conf->enable_beacon)
1859 ath_beacon_config(sc, vif);
1897 break; 1860 break;
1898 case NL80211_IFTYPE_STATION: 1861 case NL80211_IFTYPE_STATION:
1899 /* 1862 /*
@@ -1909,6 +1872,16 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
1909 memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); 1872 memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
1910 common->curaid = bss_conf->aid; 1873 common->curaid = bss_conf->aid;
1911 ath9k_hw_write_associd(sc->sc_ah); 1874 ath9k_hw_write_associd(sc->sc_ah);
1875 ath_dbg(common, ATH_DBG_CONFIG,
1876 "Bss Info ASSOC %d, bssid: %pM\n",
1877 bss_conf->aid, common->curbssid);
1878 ath_beacon_config(sc, vif);
1879 /* Reset rssi stats */
1880 sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
1881 sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
1882
1883 sc->sc_flags |= SC_OP_ANI_RUN;
1884 ath_start_ani(common);
1912 } 1885 }
1913 break; 1886 break;
1914 default: 1887 default:
@@ -1924,7 +1897,10 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)
1924 1897
1925 /* Reconfigure bss info */ 1898 /* Reconfigure bss info */
1926 if (avp->primary_sta_vif && !bss_conf->assoc) { 1899 if (avp->primary_sta_vif && !bss_conf->assoc) {
1927 sc->sc_flags &= ~SC_OP_PRIM_STA_VIF; 1900 ath_dbg(common, ATH_DBG_CONFIG,
1901 "Bss Info DISASSOC %d, bssid %pM\n",
1902 common->curaid, common->curbssid);
1903 sc->sc_flags &= ~(SC_OP_PRIM_STA_VIF | SC_OP_BEACONS);
1928 avp->primary_sta_vif = false; 1904 avp->primary_sta_vif = false;
1929 memset(common->curbssid, 0, ETH_ALEN); 1905 memset(common->curbssid, 0, ETH_ALEN);
1930 common->curaid = 0; 1906 common->curaid = 0;
@@ -1938,8 +1914,12 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)
1938 * Clear bssid & aid 1914 * Clear bssid & aid
1939 */ 1915 */
1940 if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && 1916 if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
1941 !(sc->sc_flags & SC_OP_PRIM_STA_VIF)) 1917 !(sc->sc_flags & SC_OP_PRIM_STA_VIF)) {
1942 ath9k_hw_write_associd(sc->sc_ah); 1918 ath9k_hw_write_associd(sc->sc_ah);
1919 /* Stop ANI */
1920 sc->sc_flags &= ~SC_OP_ANI_RUN;
1921 del_timer_sync(&common->ani.timer);
1922 }
1943} 1923}
1944 1924
1945static void ath9k_bss_info_changed(struct ieee80211_hw *hw, 1925static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
@@ -1948,7 +1928,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
1948 u32 changed) 1928 u32 changed)
1949{ 1929{
1950 struct ath_softc *sc = hw->priv; 1930 struct ath_softc *sc = hw->priv;
1951 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
1952 struct ath_hw *ah = sc->sc_ah; 1931 struct ath_hw *ah = sc->sc_ah;
1953 struct ath_common *common = ath9k_hw_common(ah); 1932 struct ath_common *common = ath9k_hw_common(ah);
1954 struct ath_vif *avp = (void *)vif->drv_priv; 1933 struct ath_vif *avp = (void *)vif->drv_priv;
@@ -1965,9 +1944,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
1965 1944
1966 ath_dbg(common, ATH_DBG_CONFIG, "BSSID: %pM aid: 0x%x\n", 1945 ath_dbg(common, ATH_DBG_CONFIG, "BSSID: %pM aid: 0x%x\n",
1967 common->curbssid, common->curaid); 1946 common->curbssid, common->curaid);
1968
1969 /* need to reconfigure the beacon */
1970 sc->sc_flags &= ~SC_OP_BEACONS ;
1971 } 1947 }
1972 1948
1973 /* Enable transmission of beacons (AP, IBSS, MESH) */ 1949 /* Enable transmission of beacons (AP, IBSS, MESH) */
@@ -2008,7 +1984,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
2008 } 1984 }
2009 1985
2010 if (changed & BSS_CHANGED_BEACON_INT) { 1986 if (changed & BSS_CHANGED_BEACON_INT) {
2011 cur_conf->beacon_interval = bss_conf->beacon_int;
2012 /* 1987 /*
2013 * In case of AP mode, the HW TSF has to be reset 1988 * In case of AP mode, the HW TSF has to be reset
2014 * when the beacon interval changes. 1989 * when the beacon interval changes.
@@ -2020,9 +1995,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
2020 if (!error) 1995 if (!error)
2021 ath_beacon_config(sc, vif); 1996 ath_beacon_config(sc, vif);
2022 ath9k_set_beaconing_status(sc, true); 1997 ath9k_set_beaconing_status(sc, true);
2023 } else { 1998 } else
2024 ath_beacon_config(sc, vif); 1999 ath_beacon_config(sc, vif);
2025 }
2026 } 2000 }
2027 2001
2028 if (changed & BSS_CHANGED_ERP_PREAMBLE) { 2002 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
@@ -2044,12 +2018,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
2044 sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; 2018 sc->sc_flags &= ~SC_OP_PROTECT_ENABLE;
2045 } 2019 }
2046 2020
2047 if (changed & BSS_CHANGED_ASSOC) {
2048 ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
2049 bss_conf->assoc);
2050 ath9k_bss_assoc_info(sc, hw, vif, bss_conf);
2051 }
2052
2053 mutex_unlock(&sc->mutex); 2021 mutex_unlock(&sc->mutex);
2054} 2022}
2055 2023
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index a9c3f4672aa0..3842b7518661 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -574,7 +574,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
574 sc->ps_flags &= ~PS_BEACON_SYNC; 574 sc->ps_flags &= ~PS_BEACON_SYNC;
575 ath_dbg(common, ATH_DBG_PS, 575 ath_dbg(common, ATH_DBG_PS,
576 "Reconfigure Beacon timers based on timestamp from the AP\n"); 576 "Reconfigure Beacon timers based on timestamp from the AP\n");
577 ath_beacon_config(sc, NULL); 577 ath_set_beacon(sc);
578 } 578 }
579 579
580 if (ath_beacon_dtim_pending_cab(skb)) { 580 if (ath_beacon_dtim_pending_cab(skb)) {