ath9k: avoid enabling interrupts while processing rx
authorRajkumar Manoharan <rmanoharan@atheros.com>
Fri, 6 May 2011 12:57:46 +0000 (18:27 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 10 May 2011 19:54:45 +0000 (15:54 -0400)
The assumsion is that while processing ath9k tasklet,
interrupts were already disabled and it will be enabled
at the completion of ath9k tasklet. But whenever TSFOOR is raised,
the driver configures the beacon timers after having received a
beacon frame from the AP which inturn enables the interrupts.

Cc: stable@kernel.org
Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/beacon.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/recv.c

index 1bffd156b15564927a7bd0b7c47c46dcfabeb6cf..f2f672bc5966b6c9d5cbd69fad5212321a10ebdc 100644 (file)
@@ -564,6 +564,7 @@ struct ath_ant_comb {
 #define PS_WAIT_FOR_PSPOLL_DATA   BIT(2)
 #define PS_WAIT_FOR_TX_ACK        BIT(3)
 #define PS_BEACON_SYNC            BIT(4)
+#define PS_TSFOOR_SYNC            BIT(5)
 
 struct ath_rate_table;
 
index 22cd241a098b31bdfe7dff1950bebf499df6773b..637dbc5f7b67478e975e81a33a33ab5785fc5d84 100644 (file)
@@ -620,7 +620,13 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
        ath9k_hw_disable_interrupts(ah);
        ath9k_hw_set_sta_beacon_timers(ah, &bs);
        ah->imask |= ATH9K_INT_BMISS;
-       ath9k_hw_set_interrupts(ah, ah->imask);
+
+       /*
+        * If the beacon config is called beacause of TSFOOR,
+        * Interrupts will be enabled back at the end of ath9k_tasklet
+        */
+       if (!(sc->ps_flags & PS_TSFOOR_SYNC))
+               ath9k_hw_set_interrupts(ah, ah->imask);
 }
 
 static void ath_beacon_config_adhoc(struct ath_softc *sc,
@@ -661,7 +667,12 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
        ath9k_hw_disable_interrupts(ah);
        ath9k_beacon_init(sc, nexttbtt, intval);
        sc->beacon.bmisscnt = 0;
-       ath9k_hw_set_interrupts(ah, ah->imask);
+       /*
+        * If the beacon config is called beacause of TSFOOR,
+        * Interrupts will be enabled back at the end of ath9k_tasklet
+        */
+       if (!(sc->ps_flags & PS_TSFOOR_SYNC))
+               ath9k_hw_set_interrupts(ah, ah->imask);
 }
 
 static bool ath9k_allow_beacon_config(struct ath_softc *sc,
index 3de115df91641c79d485fe6287209c5dab0da095..c171d111ecf7458037b185430312b7536c47577c 100644 (file)
@@ -718,7 +718,8 @@ void ath9k_tasklet(unsigned long data)
                 */
                ath_dbg(common, ATH_DBG_PS,
                        "TSFOOR - Sync with next Beacon\n");
-               sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC;
+               sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC |
+                               PS_TSFOOR_SYNC;
        }
 
        if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
index c5b7cbe59bfafe8aa1dea63256c5aa2dbe69aa5b..a485c040bf80de06174fbc003efe061f80226f86 100644 (file)
@@ -572,6 +572,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
                ath_dbg(common, ATH_DBG_PS,
                        "Reconfigure Beacon timers based on timestamp from the AP\n");
                ath_set_beacon(sc);
+               sc->ps_flags &= ~PS_TSFOOR_SYNC;
        }
 
        if (ath_beacon_dtim_pending_cab(skb)) {