aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorRajkumar Manoharan <rmanoharan@atheros.com>2011-04-04 13:26:19 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-04-07 15:49:40 -0400
commit99e4d43ad5ff5778f92ee3bc40a29ac7cd8a28f4 (patch)
tree35f19c1d608a4abff349f68529f8e8ce817837cc /drivers/net/wireless/ath
parent4f5ef75b155955bf92adc772c6660787151fc78c (diff)
ath9k: configure beacons based on hw opmode
Current ath9k code does not handle beacon timers on opmode specific. One such example is that a STA beacon config overwrites already configured AP vif's beacon timers during scan. On multi station vif case, configure beacon timers beased on primary vif selected. This also helps while moving back to single STA vif from multi STA vifs, where the power save is enabled and hw has to be reconfigured with proper beacon and bssid/aid. Otherwise connection poll will be triggered so frequently due to beacon loss. Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-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)) {