summaryrefslogtreecommitdiff
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorSujith Manoharan <c_manoha@qca.qualcomm.com>2014-11-16 03:41:07 +0300
committerJohn W. Linville <linville@tuxdriver.com>2014-11-17 23:32:16 +0300
commit6185672abad996fa520b0b4c77c30258634ee07f (patch)
treef48d05675041026bcfbd44aaa3c481a9122537b3 /drivers/net/wireless
parente21a1d8b2b92e78fca0b4ee48681aa03dd671f88 (diff)
downloadlinux-6185672abad996fa520b0b4c77c30258634ee07f.tar.xz
ath9k: Cancel pending offchannel operations
This patch makes sure that pending roc/scan operations are cancelled properly when a new context is assigned/unassigned. The flush_work() call to flush out any scheduled channel context work is removed, instead, sc->mutex is dropped to allow any pending work to get a chance to complete by the channel scheduler. Also, increase the timeout to allow a switch to an active GO. Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c43
1 files changed, 30 insertions, 13 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 5a2a8d288487..a6cb15c96052 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -2196,6 +2196,28 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
+static void ath9k_cancel_pending_offchannel(struct ath_softc *sc)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+ if (sc->offchannel.roc_vif) {
+ ath_dbg(common, CHAN_CTX,
+ "%s: Aborting RoC\n", __func__);
+
+ del_timer_sync(&sc->offchannel.timer);
+ if (sc->offchannel.state >= ATH_OFFCHANNEL_ROC_START)
+ ath_roc_complete(sc, true);
+ }
+
+ if (test_bit(ATH_OP_SCANNING, &common->op_flags)) {
+ ath_dbg(common, CHAN_CTX,
+ "%s: Aborting HW scan\n", __func__);
+
+ del_timer_sync(&sc->offchannel.timer);
+ ath_scan_complete(sc, true);
+ }
+}
+
static int ath9k_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_scan_request *hw_req)
{
@@ -2382,6 +2404,8 @@ static int ath9k_assign_vif_chanctx(struct ieee80211_hw *hw,
struct ath_chanctx *ctx = ath_chanctx_get(conf);
int i;
+ ath9k_cancel_pending_offchannel(sc);
+
mutex_lock(&sc->mutex);
ath_dbg(common, CHAN_CTX,
@@ -2411,6 +2435,8 @@ static void ath9k_unassign_vif_chanctx(struct ieee80211_hw *hw,
struct ath_chanctx *ctx = ath_chanctx_get(conf);
int ac;
+ ath9k_cancel_pending_offchannel(sc);
+
mutex_lock(&sc->mutex);
ath_dbg(common, CHAN_CTX,
@@ -2456,18 +2482,7 @@ static void ath9k_mgd_prepare_tx(struct ieee80211_hw *hw,
if (!changed)
goto out;
- if (test_bit(ATH_OP_SCANNING, &common->op_flags)) {
- ath_dbg(common, CHAN_CTX,
- "%s: Aborting HW scan\n", __func__);
-
- mutex_unlock(&sc->mutex);
-
- del_timer_sync(&sc->offchannel.timer);
- ath_scan_complete(sc, true);
- flush_work(&sc->chanctx_work);
-
- mutex_lock(&sc->mutex);
- }
+ ath9k_cancel_pending_offchannel(sc);
go_ctx = ath_is_go_chanctx_present(sc);
@@ -2482,13 +2497,15 @@ static void ath9k_mgd_prepare_tx(struct ieee80211_hw *hw,
beacon_int = TU_TO_USEC(cur_conf->beacon_interval);
spin_unlock_bh(&sc->chan_lock);
- timeout = usecs_to_jiffies(beacon_int);
+ timeout = usecs_to_jiffies(beacon_int * 2);
init_completion(&sc->go_beacon);
+ mutex_unlock(&sc->mutex);
if (wait_for_completion_timeout(&sc->go_beacon,
timeout) == 0)
ath_dbg(common, CHAN_CTX,
"Failed to send new NoA\n");
+ mutex_lock(&sc->mutex);
}
ath_dbg(common, CHAN_CTX,