ath9k: fix enabling ANI / tx monitor after bg scan
authorLuis R. Rodriguez <lrodriguez@atheros.com>
Thu, 16 Sep 2010 19:12:28 +0000 (15:12 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 9 Dec 2010 21:32:03 +0000 (13:32 -0800)
commit 48a6a468198aadb54bc5d3fdd065364d43ff5197 upstream.

ath9k's entire logic with SC_OP_SCANNING is incorrect due to the
way mac80211 currently implements the scan complete callback and
we handle it in ath9k. This patch removes the flag completely in
preference for the SC_OP_OFFCHANNEL which is really what we wanted.

The scanning flag was used to ensure we reset ANI to the old values
when we go back to the home channel, but if we are offchannel we
use some defaults. The flag was also used to re-enable the TX monitor.

Without this patch we simply never re-enabled ANI and the TX monitor
after going offchannel. This means that after one background
scan we are prone to noise issues and if we had a TX hang we would
not recover. To get this to work properly we must enable ANI after
we have configured the beacon timers, otherwise hardware acts really
oddly.

This patch has stable fixes which apply down to [2.6.36+], there
*may* be a to fix this on older kernels but requires a bit of
work since this patch relies on the new mac80211 flag
IEEE80211_CONF_OFFCHANNEL which was introduced as of 2.6.36.

Cc: Paul Stewart <pstew@google.com>
Cc: Amod Bodas <amod.bodas@atheros.com>
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/recv.c

index ca8b8fa1139acf0c4b5ae36ebcf826bdb356021a..e7ab70234b545a45314a2da67f92ae22a5d472df 100644 (file)
@@ -516,7 +516,6 @@ void ath_deinit_leds(struct ath_softc *sc);
 #define SC_OP_RXFLUSH                BIT(7)
 #define SC_OP_LED_ASSOCIATED         BIT(8)
 #define SC_OP_LED_ON                 BIT(9)
-#define SC_OP_SCANNING               BIT(10)
 #define SC_OP_TSF_RESET              BIT(11)
 #define SC_OP_BT_PRIORITY_DETECTED   BIT(12)
 #define SC_OP_BT_SCAN               BIT(13)
index 883a71b92ba07ec665dc5f992e5350e308d27d39..725376b4c61116ad06b9108e062ceb9cf9a16c30 100644 (file)
@@ -254,14 +254,12 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
        ath_update_txpow(sc);
        ath9k_hw_set_interrupts(ah, ah->imask);
 
-       if (!(sc->sc_flags & (SC_OP_OFFCHANNEL | SC_OP_SCANNING))) {
-               ath_start_ani(common);
+       if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
+               ath_beacon_config(sc, NULL);
                ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+               ath_start_ani(common);
        }
 
-       if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)))
-               ath_beacon_config(sc, NULL);
-
  ps_restore:
        ath9k_ps_restore(sc);
        return r;
@@ -2040,7 +2038,6 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
 
        aphy->state = ATH_WIPHY_SCAN;
        ath9k_wiphy_pause_all_forced(sc, aphy);
-       sc->sc_flags |= SC_OP_SCANNING;
        mutex_unlock(&sc->mutex);
 }
 
@@ -2055,7 +2052,6 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
 
        mutex_lock(&sc->mutex);
        aphy->state = ATH_WIPHY_ACTIVE;
-       sc->sc_flags &= ~SC_OP_SCANNING;
        mutex_unlock(&sc->mutex);
 }
 
index a40651d1924ffc80de6dd0c7753eb35386495075..8b1b459447d26b5afa0c01b44a9d419be21522b5 100644 (file)
@@ -292,7 +292,7 @@ static void ath_edma_start_recv(struct ath_softc *sc)
 
        ath_opmode_init(sc);
 
-       ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_SCANNING));
+       ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
 }
 
 static void ath_edma_stop_recv(struct ath_softc *sc)
@@ -496,7 +496,7 @@ int ath_startrecv(struct ath_softc *sc)
 start_recv:
        spin_unlock_bh(&sc->rx.rxbuflock);
        ath_opmode_init(sc);
-       ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_SCANNING));
+       ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
 
        return 0;
 }