All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/5] ath9k patches
@ 2014-09-10  7:18 Sujith Manoharan
  2014-09-10  7:18 ` [RFC 1/5] ath9k: Assign offchannel duration properly Sujith Manoharan
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Sujith Manoharan @ 2014-09-10  7:18 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, ath9k-devel

From: Sujith Manoharan <c_manoha@qca.qualcomm.com>

MCC fixes. Please review.

Sujith Manoharan (5):
  ath9k: Assign offchannel duration properly
  ath9k: Fix Notice of Absence issues
  ath9k: Clear offchannel duration properly
  ath9k: Fix channel switch time duration
  ath9k: Fix beacon miss handling

 drivers/net/wireless/ath/ath9k/ath9k.h   |   8 +-
 drivers/net/wireless/ath/ath9k/channel.c | 143 ++++++++++++++++++++++---------
 2 files changed, 109 insertions(+), 42 deletions(-)

-- 
2.1.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC 1/5] ath9k: Assign offchannel duration properly
  2014-09-10  7:18 [RFC 0/5] ath9k patches Sujith Manoharan
@ 2014-09-10  7:18 ` Sujith Manoharan
  2014-09-10  7:18 ` [RFC 2/5] ath9k: Fix Notice of Absence issues Sujith Manoharan
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Sujith Manoharan @ 2014-09-10  7:18 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, ath9k-devel

From: Sujith Manoharan <c_manoha@qca.qualcomm.com>

In multi-channel mode, an offchannel request will
be deferred if both contexts are active. The duration
of the offchannel operation is calculated but is
not stored in the scheduler state. Fix this.

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath9k/channel.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index 522894b..ae575cb 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -588,10 +588,15 @@ static void ath_chanctx_switch(struct ath_softc *sc, struct ath_chanctx *ctx,
 
 	if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags) &&
 	    (sc->cur_chan != ctx) && (ctx == &sc->offchannel.chan)) {
-		sc->sched.offchannel_pending = true;
-		sc->sched.wait_switch = true;
 		if (chandef)
 			ctx->chandef = *chandef;
+
+		sc->sched.offchannel_pending = true;
+		sc->sched.wait_switch = true;
+		sc->sched.offchannel_duration =
+			jiffies_to_usecs(sc->offchannel.duration) +
+			sc->sched.channel_switch_time;
+
 		spin_unlock_bh(&sc->chan_lock);
 		ath_dbg(common, CHAN_CTX,
 			"Set offchannel_pending to true\n");
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [RFC 2/5] ath9k: Fix Notice of Absence issues
  2014-09-10  7:18 [RFC 0/5] ath9k patches Sujith Manoharan
  2014-09-10  7:18 ` [RFC 1/5] ath9k: Assign offchannel duration properly Sujith Manoharan
@ 2014-09-10  7:18 ` Sujith Manoharan
  2014-09-10  7:18 ` [RFC 3/5] ath9k: Clear offchannel duration properly Sujith Manoharan
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Sujith Manoharan @ 2014-09-10  7:18 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, ath9k-devel

From: Sujith Manoharan <c_manoha@qca.qualcomm.com>

* The index has to incremented only when advertising
  a new NoA schedule.

* Switch to non-periodic NoA when starting a scan operation
  and multiple channel contexts are active.

* Make sure that periodic NoA is advertised again when
  scan ends. Since the offchannel timer moves the offchannel
  state to IDLE after the GO operating channel becomes
  active, use a flag "force_noa_update" to update the
  NoA contents.

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath9k/ath9k.h   |   7 ++-
 drivers/net/wireless/ath/ath9k/channel.c | 105 ++++++++++++++++++++-----------
 2 files changed, 75 insertions(+), 37 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 0c071b0..305db1a 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -379,6 +379,7 @@ struct ath_chanctx_sched {
 	bool beacon_pending;
 	bool offchannel_pending;
 	bool wait_switch;
+	bool force_noa_update;
 	enum ath_chanctx_state state;
 	u8 beacon_miss;
 
@@ -595,8 +596,10 @@ struct ath_vif {
 	u32 offchannel_start;
 	u32 offchannel_duration;
 
-	u32 periodic_noa_start;
-	u32 periodic_noa_duration;
+	/* These are used for both periodic and one-shot */
+	u32 noa_start;
+	u32 noa_duration;
+	bool periodic_noa;
 };
 
 struct ath9k_vif_iter_data {
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index ae575cb..ab3d29d 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -310,7 +310,6 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
 	struct ath_chanctx *ctx;
 	u32 tsf_time;
 	u32 beacon_int;
-	bool noa_changed = false;
 
 	if (vif)
 		avp = (struct ath_vif *) vif->drv_priv;
@@ -372,22 +371,6 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
 		sc->sched.switch_start_time = tsf_time;
 		sc->cur_chan->last_beacon = sc->sched.next_tbtt;
 
-		/* Prevent wrap-around issues */
-		if (avp->periodic_noa_duration &&
-		    tsf_time - avp->periodic_noa_start > BIT(30))
-			avp->periodic_noa_duration = 0;
-
-		if (ctx->active) {
-			avp->periodic_noa_start = tsf_time;
-			avp->periodic_noa_duration =
-				TU_TO_USEC(cur_conf->beacon_interval) / 2 -
-				sc->sched.channel_switch_time;
-			noa_changed = true;
-		} else if (!ctx->active) {
-			avp->periodic_noa_duration = 0;
-			noa_changed = true;
-		}
-
 		/* If at least two consecutive beacons were missed on the STA
 		 * chanctx, stay on the STA channel for one extra beacon period,
 		 * to resync the timer properly.
@@ -395,21 +378,65 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
 		if (ctx->active && sc->sched.beacon_miss >= 2)
 			sc->sched.offchannel_duration = 3 * beacon_int / 2;
 
-		if (sc->sched.offchannel_duration) {
-			noa_changed = true;
+		/*
+		 * If an offchannel switch is scheduled to happen after
+		 * a beacon transmission, update the NoA with one-shot
+		 * values and increment the index.
+		 */
+		if (sc->next_chan == &sc->offchannel.chan) {
+			avp->noa_index++;
 			avp->offchannel_start = tsf_time;
-			avp->offchannel_duration =
-				sc->sched.offchannel_duration;
+			avp->offchannel_duration = sc->sched.offchannel_duration;
+
+			ath_dbg(common, CHAN_CTX,
+				"offchannel noa_duration: %d, noa_start: %d, noa_index: %d\n",
+				avp->offchannel_duration,
+				avp->offchannel_start,
+				avp->noa_index);
+
+			/*
+			 * When multiple contexts are active, the NoA
+			 * has to be recalculated and advertised after
+			 * an offchannel operation.
+			 */
+			if (ctx->active && avp->noa_duration)
+				avp->noa_duration = 0;
+
+			break;
 		}
 
-		if (noa_changed)
+		/* Prevent wrap-around issues */
+		if (avp->noa_duration && tsf_time - avp->noa_start > BIT(30))
+			avp->noa_duration = 0;
+
+		/*
+		 * If multiple contexts are active, start periodic
+		 * NoA and increment the index for the first
+		 * announcement.
+		 */
+		if (ctx->active &&
+		    (!avp->noa_duration || sc->sched.force_noa_update)) {
 			avp->noa_index++;
+			avp->noa_start = tsf_time;
+			avp->noa_duration =
+				TU_TO_USEC(cur_conf->beacon_interval) / 2 -
+				sc->sched.channel_switch_time;
 
-		ath_dbg(common, CHAN_CTX,
-			"periodic_noa_duration: %d, periodic_noa_start: %d, noa_index: %d\n",
-			avp->periodic_noa_duration,
-			avp->periodic_noa_start,
-			avp->noa_index);
+			if (test_bit(ATH_OP_SCANNING, &common->op_flags))
+				avp->periodic_noa = false;
+			else
+				avp->periodic_noa = true;
+
+			ath_dbg(common, CHAN_CTX,
+				"noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n",
+				avp->noa_duration,
+				avp->noa_start,
+				avp->noa_index,
+				avp->periodic_noa);
+		}
+
+		if (ctx->active && sc->sched.force_noa_update)
+			sc->sched.force_noa_update = false;
 
 		break;
 	case ATH_CHANCTX_EVENT_BEACON_SENT:
@@ -736,6 +763,10 @@ void ath_scan_complete(struct ath_softc *sc, bool abort)
 	sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
 	ieee80211_scan_completed(sc->hw, abort);
 	clear_bit(ATH_OP_SCANNING, &common->op_flags);
+	spin_lock_bh(&sc->chan_lock);
+	if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
+		sc->sched.force_noa_update = true;
+	spin_unlock_bh(&sc->chan_lock);
 	ath_offchannel_next(sc);
 	ath9k_ps_restore(sc);
 }
@@ -1218,10 +1249,10 @@ void ath9k_beacon_add_noa(struct ath_softc *sc, struct ath_vif *avp,
 	int noa_len, noa_desc, i = 0;
 	u8 *hdr;
 
-	if (!avp->offchannel_duration && !avp->periodic_noa_duration)
+	if (!avp->offchannel_duration && !avp->noa_duration)
 		return;
 
-	noa_desc = !!avp->offchannel_duration + !!avp->periodic_noa_duration;
+	noa_desc = !!avp->offchannel_duration + !!avp->noa_duration;
 	noa_len = 2 + sizeof(struct ieee80211_p2p_noa_desc) * noa_desc;
 
 	hdr = skb_put(skb, sizeof(noa_ie_hdr));
@@ -1235,13 +1266,17 @@ void ath9k_beacon_add_noa(struct ath_softc *sc, struct ath_vif *avp,
 	noa->index = avp->noa_index;
 	noa->oppps_ctwindow = ath9k_get_ctwin(sc, avp);
 
-	if (avp->periodic_noa_duration) {
-		u32 interval = TU_TO_USEC(sc->cur_chan->beacon.beacon_interval);
+	if (avp->noa_duration) {
+		if (avp->periodic_noa) {
+			u32 interval = TU_TO_USEC(sc->cur_chan->beacon.beacon_interval);
+			noa->desc[i].count = 255;
+			noa->desc[i].interval = cpu_to_le32(interval);
+		} else {
+			noa->desc[i].count = 1;
+		}
 
-		noa->desc[i].count = 255;
-		noa->desc[i].start_time = cpu_to_le32(avp->periodic_noa_start);
-		noa->desc[i].duration = cpu_to_le32(avp->periodic_noa_duration);
-		noa->desc[i].interval = cpu_to_le32(interval);
+		noa->desc[i].start_time = cpu_to_le32(avp->noa_start);
+		noa->desc[i].duration = cpu_to_le32(avp->noa_duration);
 		i++;
 	}
 
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [RFC 3/5] ath9k: Clear offchannel duration properly
  2014-09-10  7:18 [RFC 0/5] ath9k patches Sujith Manoharan
  2014-09-10  7:18 ` [RFC 1/5] ath9k: Assign offchannel duration properly Sujith Manoharan
  2014-09-10  7:18 ` [RFC 2/5] ath9k: Fix Notice of Absence issues Sujith Manoharan
@ 2014-09-10  7:18 ` Sujith Manoharan
  2014-09-10  7:18 ` [RFC 4/5] ath9k: Fix channel switch time duration Sujith Manoharan
  2014-09-10  7:18 ` [RFC 5/5] ath9k: Fix beacon miss handling Sujith Manoharan
  4 siblings, 0 replies; 6+ messages in thread
From: Sujith Manoharan @ 2014-09-10  7:18 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, ath9k-devel

From: Sujith Manoharan <c_manoha@qca.qualcomm.com>

Clearing the offchannel duration value in the
scheduler unconditionally breaks NoA when
multiple contexts are active and an offchannel
request is deferred, for example, in a scan run.

Fix this by clearing the duration only if there
is no pending offchannel request.

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath9k/channel.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index ab3d29d..09ff8a6 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -1065,7 +1065,10 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
 	sc->cur_chan = sc->next_chan;
 	sc->cur_chan->stopped = false;
 	sc->next_chan = NULL;
-	sc->sched.offchannel_duration = 0;
+
+	if (!sc->sched.offchannel_pending)
+		sc->sched.offchannel_duration = 0;
+
 	if (sc->sched.state != ATH_CHANCTX_STATE_FORCE_ACTIVE)
 		sc->sched.state = ATH_CHANCTX_STATE_IDLE;
 
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [RFC 4/5] ath9k: Fix channel switch time duration
  2014-09-10  7:18 [RFC 0/5] ath9k patches Sujith Manoharan
                   ` (2 preceding siblings ...)
  2014-09-10  7:18 ` [RFC 3/5] ath9k: Clear offchannel duration properly Sujith Manoharan
@ 2014-09-10  7:18 ` Sujith Manoharan
  2014-09-10  7:18 ` [RFC 5/5] ath9k: Fix beacon miss handling Sujith Manoharan
  4 siblings, 0 replies; 6+ messages in thread
From: Sujith Manoharan @ 2014-09-10  7:18 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, ath9k-devel

From: Sujith Manoharan <c_manoha@qca.qualcomm.com>

Since the NoA duration is the maximum time the GO interface
can be offline, it needs to include the time take to
switch channels in the HW.

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath9k/channel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index 09ff8a6..a42fd85 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -419,7 +419,7 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
 			avp->noa_index++;
 			avp->noa_start = tsf_time;
 			avp->noa_duration =
-				TU_TO_USEC(cur_conf->beacon_interval) / 2 -
+				TU_TO_USEC(cur_conf->beacon_interval) / 2 +
 				sc->sched.channel_switch_time;
 
 			if (test_bit(ATH_OP_SCANNING, &common->op_flags))
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [RFC 5/5] ath9k: Fix beacon miss handling
  2014-09-10  7:18 [RFC 0/5] ath9k patches Sujith Manoharan
                   ` (3 preceding siblings ...)
  2014-09-10  7:18 ` [RFC 4/5] ath9k: Fix channel switch time duration Sujith Manoharan
@ 2014-09-10  7:18 ` Sujith Manoharan
  4 siblings, 0 replies; 6+ messages in thread
From: Sujith Manoharan @ 2014-09-10  7:18 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, ath9k-devel

From: Sujith Manoharan <c_manoha@qca.qualcomm.com>

The NoA duration for a GO is half the beacon interval
and a concurrent context like a STA can be active only
for that duration, before switching back to the GO's
operating channel.

Currently, when multiple beacons are missed, the dwell
time for the STA context is extended to improve the
chances of receiving a beacon. But the NoA is not updated
and this will cause problems since the GO is offline
for a period that is longer than the advertised duration.

Fix this by ensuring that the NoA is updated first before
extending the time slot for the STA context. Also make
sure that non-periodic NoA is used for a one-time, longer
absence period.

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath9k/ath9k.h   |  1 +
 drivers/net/wireless/ath/ath9k/channel.c | 44 +++++++++++++++++++++++---------
 2 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 305db1a..660c151 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -380,6 +380,7 @@ struct ath_chanctx_sched {
 	bool offchannel_pending;
 	bool wait_switch;
 	bool force_noa_update;
+	bool extend_absence;
 	enum ath_chanctx_state state;
 	u8 beacon_miss;
 
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index a42fd85..a1b3282 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -371,13 +371,6 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
 		sc->sched.switch_start_time = tsf_time;
 		sc->cur_chan->last_beacon = sc->sched.next_tbtt;
 
-		/* If at least two consecutive beacons were missed on the STA
-		 * chanctx, stay on the STA channel for one extra beacon period,
-		 * to resync the timer properly.
-		 */
-		if (ctx->active && sc->sched.beacon_miss >= 2)
-			sc->sched.offchannel_duration = 3 * beacon_int / 2;
-
 		/*
 		 * If an offchannel switch is scheduled to happen after
 		 * a beacon transmission, update the NoA with one-shot
@@ -405,6 +398,26 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
 			break;
 		}
 
+
+		/*
+		 * Clear the extend_absence flag if it had been
+		 * set during the previous beacon transmission,
+		 * since we need to revert to the normal NoA
+		 * schedule.
+		 */
+		if (ctx->active && sc->sched.extend_absence) {
+			avp->noa_duration = 0;
+			sc->sched.extend_absence = false;
+		}
+
+		/* If at least two consecutive beacons were missed on the STA
+		 * chanctx, stay on the STA channel for one extra beacon period,
+		 * to resync the timer properly.
+		 */
+		if (ctx->active && sc->sched.beacon_miss >= 2) {
+			avp->noa_duration = 0;
+			sc->sched.extend_absence = true;
+		}
 		/* Prevent wrap-around issues */
 		if (avp->noa_duration && tsf_time - avp->noa_start > BIT(30))
 			avp->noa_duration = 0;
@@ -418,11 +431,17 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
 		    (!avp->noa_duration || sc->sched.force_noa_update)) {
 			avp->noa_index++;
 			avp->noa_start = tsf_time;
-			avp->noa_duration =
-				TU_TO_USEC(cur_conf->beacon_interval) / 2 +
-				sc->sched.channel_switch_time;
 
-			if (test_bit(ATH_OP_SCANNING, &common->op_flags))
+			if (sc->sched.extend_absence)
+				avp->noa_duration = (3 * beacon_int / 2) +
+					sc->sched.channel_switch_time;
+			else
+				avp->noa_duration =
+					TU_TO_USEC(cur_conf->beacon_interval) / 2 +
+					sc->sched.channel_switch_time;
+
+			if (test_bit(ATH_OP_SCANNING, &common->op_flags) ||
+			    sc->sched.extend_absence)
 				avp->periodic_noa = false;
 			else
 				avp->periodic_noa = true;
@@ -520,7 +539,8 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
 		sc->sched.wait_switch = false;
 
 		tsf_time = TU_TO_USEC(cur_conf->beacon_interval) / 2;
-		if (sc->sched.beacon_miss >= 2) {
+
+		if (sc->sched.extend_absence) {
 			sc->sched.beacon_miss = 0;
 			tsf_time *= 3;
 		}
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2014-09-10  7:18 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-10  7:18 [RFC 0/5] ath9k patches Sujith Manoharan
2014-09-10  7:18 ` [RFC 1/5] ath9k: Assign offchannel duration properly Sujith Manoharan
2014-09-10  7:18 ` [RFC 2/5] ath9k: Fix Notice of Absence issues Sujith Manoharan
2014-09-10  7:18 ` [RFC 3/5] ath9k: Clear offchannel duration properly Sujith Manoharan
2014-09-10  7:18 ` [RFC 4/5] ath9k: Fix channel switch time duration Sujith Manoharan
2014-09-10  7:18 ` [RFC 5/5] ath9k: Fix beacon miss handling Sujith Manoharan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.