69 lines
2 KiB
Diff
69 lines
2 KiB
Diff
|
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||
|
Date: Fri, 17 Oct 2014 07:40:16 +0530
|
||
|
Subject: [PATCH] ath9k: Fix MCC flush timeout
|
||
|
|
||
|
In MCC mode, the duration for a channel context
|
||
|
is half the beacon interval and having a large
|
||
|
flush timeout will adversely affect GO operation,
|
||
|
since the default value of 200ms will overshoot
|
||
|
the advertised NoA absence duration.
|
||
|
|
||
|
The scheduler initiates a channel context switch
|
||
|
only when the slot duration for the current
|
||
|
context expires, so there is no possibility of
|
||
|
having a fixed timeout for flush.
|
||
|
|
||
|
Since the channel_switch_time is added to the
|
||
|
absence duration when the GO sets up the NoA
|
||
|
attribute, this is the maximum time that we
|
||
|
have to flush the TX queues. The duration is very
|
||
|
small, but we don't have a choice in MCC mode.
|
||
|
|
||
|
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||
|
---
|
||
|
|
||
|
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||
|
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||
|
@@ -199,6 +199,7 @@ static const char *chanctx_state_string(
|
||
|
void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx)
|
||
|
{
|
||
|
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||
|
+ struct ath_chanctx *ictx;
|
||
|
struct ath_vif *avp;
|
||
|
bool active = false;
|
||
|
u8 n_active = 0;
|
||
|
@@ -206,6 +207,8 @@ void ath_chanctx_check_active(struct ath
|
||
|
if (!ctx)
|
||
|
return;
|
||
|
|
||
|
+ ictx = ctx;
|
||
|
+
|
||
|
list_for_each_entry(avp, &ctx->vifs, list) {
|
||
|
struct ieee80211_vif *vif = avp->vif;
|
||
|
|
||
|
@@ -228,12 +231,23 @@ void ath_chanctx_check_active(struct ath
|
||
|
n_active++;
|
||
|
}
|
||
|
|
||
|
+ spin_lock_bh(&sc->chan_lock);
|
||
|
+
|
||
|
if (n_active <= 1) {
|
||
|
+ ictx->flush_timeout = HZ / 5;
|
||
|
clear_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags);
|
||
|
+ spin_unlock_bh(&sc->chan_lock);
|
||
|
return;
|
||
|
}
|
||
|
- if (test_and_set_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
|
||
|
+
|
||
|
+ ictx->flush_timeout = usecs_to_jiffies(sc->sched.channel_switch_time);
|
||
|
+
|
||
|
+ if (test_and_set_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) {
|
||
|
+ spin_unlock_bh(&sc->chan_lock);
|
||
|
return;
|
||
|
+ }
|
||
|
+
|
||
|
+ spin_unlock_bh(&sc->chan_lock);
|
||
|
|
||
|
if (ath9k_is_chanctx_enabled()) {
|
||
|
ath_chanctx_event(sc, NULL,
|