All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] ath9k patches
@ 2014-08-27  6:37 Sujith Manoharan
  2014-08-27  6:37 ` [PATCH 1/4] ath9k: Fix channel context transition Sujith Manoharan
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Sujith Manoharan @ 2014-08-27  6:37 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, ath9k-devel

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

More channel context fixes.
Pending patches: http://msujith.org/dir/patches/wl/Aug-27-2014/

Sujith

Sujith Manoharan (4):
  ath9k: Fix channel context transition
  ath9k: Disable fastcc for channel context mode
  ath9k: Add more debug statements for channel context
  ath9k: Fix channel context timer

 drivers/net/wireless/ath/ath9k/ath9k.h   |  10 +-
 drivers/net/wireless/ath/ath9k/channel.c | 158 ++++++++++++++++++++++++++++---
 drivers/net/wireless/ath/ath9k/main.c    |   6 ++
 drivers/net/wireless/ath/ath9k/recv.c    |  12 +--
 4 files changed, 163 insertions(+), 23 deletions(-)

-- 
2.1.0


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

* [PATCH 1/4] ath9k: Fix channel context transition
  2014-08-27  6:37 [PATCH 0/4] ath9k patches Sujith Manoharan
@ 2014-08-27  6:37 ` Sujith Manoharan
  2014-08-27  8:38   ` Felix Fietkau
  2014-08-27  6:37 ` [PATCH 2/4] ath9k: Disable fastcc for channel context mode Sujith Manoharan
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 11+ messages in thread
From: Sujith Manoharan @ 2014-08-27  6:37 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, ath9k-devel

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

In channel context mode, a nullfunc is sent with
the PM bit enabled when we switch to a new channel
context from the current one. But, when the scheduler
switches back to the old context, sending a nullfunc
with PM bit cleared has to be done only if there is
buffered traffic at the AP.

Currently, this is not done and a nullfunc is sent
for every transition. Fix this by parsing the TIM IE
for a received beacon and checking if there is buffered
traffic.

Since the beacon frame has to be parsed, move the location
of the ATH_CHANCTX_EVENT_BEACON_RECEIVED after the frame
has been processed - in ath_rx_tasklet().

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath9k/ath9k.h   | 10 ++++-
 drivers/net/wireless/ath/ath9k/channel.c | 66 +++++++++++++++++++++++++++++++-
 drivers/net/wireless/ath/ath9k/recv.c    | 12 +++---
 3 files changed, 78 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index c690601..857e911 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -338,6 +338,7 @@ struct ath_chanctx {
 	/* do not dereference, use for comparison only */
 	struct ieee80211_vif *primary_sta;
 
+	struct sk_buff *beacon_skb;
 	struct ath_beacon_config beacon;
 	struct ath9k_hw_cal_data caldata;
 	struct timespec tsf_ts;
@@ -376,6 +377,7 @@ enum ath_chanctx_state {
 struct ath_chanctx_sched {
 	bool beacon_pending;
 	bool offchannel_pending;
+	bool tim_set;
 	enum ath_chanctx_state state;
 	u8 beacon_miss;
 
@@ -449,7 +451,9 @@ void ath9k_p2p_ps_timer(void *priv);
 void ath9k_chanctx_wake_queues(struct ath_softc *sc);
 void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx);
 
-void ath_chanctx_beacon_recv_ev(struct ath_softc *sc, u32 ts,
+void ath_chanctx_beacon_recv_ev(struct ath_softc *sc,
+				struct sk_buff *skb,
+				u32 ts,
 				enum ath_chanctx_event ev);
 void ath_chanctx_beacon_sent_ev(struct ath_softc *sc,
 				enum ath_chanctx_event ev);
@@ -478,7 +482,9 @@ static inline void ath9k_offchannel_init(struct ath_softc *sc)
 static inline void ath9k_deinit_channel_context(struct ath_softc *sc)
 {
 }
-static inline void ath_chanctx_beacon_recv_ev(struct ath_softc *sc, u32 ts,
+static inline void ath_chanctx_beacon_recv_ev(struct ath_softc *sc,
+					      struct sk_buff *skb,
+					      u32 ts,
 					      enum ath_chanctx_event ev)
 {
 }
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index b369c48..e1602bc 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -296,6 +296,55 @@ static void ath_chanctx_setup_timer(struct ath_softc *sc, u32 tsf_time)
 	mod_timer(&sc->sched.timer, tsf_time);
 }
 
+/*
+ * This will be called only when multi-channel is enabled
+ * and since the max. number of interfaces is limited to two,
+ * a channel context is guaranteed to have only one interface.
+ * So, we can get the aid by iterating over the vif list in
+ * the current channel context.
+ */
+static void ath_chanctx_check_tim(struct ath_softc *sc,
+				  struct sk_buff *skb)
+{
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	struct ieee80211_mgmt *mgmt;
+	struct ieee80211_vif *vif;
+	struct ath_vif *avp;
+	struct ieee80211_tim_ie *tim_ie;
+	const u8 *tim;
+	size_t ies_len;
+	u8 tim_len;
+	u8 *ies;
+
+	mgmt = (struct ieee80211_mgmt *)skb->data;
+	ies = mgmt->u.beacon.variable;
+	ies_len = (u8 *)skb_tail_pointer(skb) - ies;
+
+	tim = cfg80211_find_ie(WLAN_EID_TIM, ies, ies_len);
+	if (!tim)
+		return;
+
+	tim_len = tim[1];
+	tim_ie = (struct ieee80211_tim_ie *) &tim[2];
+
+	list_for_each_entry(avp, &sc->cur_chan->vifs, list) {
+		vif = avp->vif;
+
+		if (vif->type == NL80211_IFTYPE_STATION && vif->bss_conf.assoc) {
+			sc->sched.tim_set = ieee80211_check_tim(tim_ie,
+						tim_len, vif->bss_conf.aid);
+			if (sc->sched.tim_set) {
+				ath_dbg(common, CHAN_CTX,
+					"TIM bit set for aid: %d, vif: %pM\n",
+					vif->bss_conf.aid, vif->addr);
+			}
+			break;
+		}
+	}
+
+
+}
+
 void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
 		       enum ath_chanctx_event ev)
 {
@@ -427,7 +476,7 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
 			ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL);
 		tsf_time += ath9k_hw_gettsf32(ah);
 
-
+		ath_chanctx_check_tim(sc, sc->cur_chan->beacon_skb);
 		ath_chanctx_setup_timer(sc, tsf_time);
 		break;
 	case ATH_CHANCTX_EVENT_ASSOC:
@@ -521,10 +570,13 @@ void ath_chanctx_beacon_sent_ev(struct ath_softc *sc,
 		ath_chanctx_event(sc, NULL, ev);
 }
 
-void ath_chanctx_beacon_recv_ev(struct ath_softc *sc, u32 ts,
+void ath_chanctx_beacon_recv_ev(struct ath_softc *sc,
+				struct sk_buff *skb,
+				u32 ts,
 				enum ath_chanctx_event ev)
 {
 	sc->sched.next_tbtt = ts;
+	sc->cur_chan->beacon_skb = skb;
 	ath_chanctx_event(sc, NULL, ev);
 }
 
@@ -809,6 +861,16 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp,
 		if (!vif->bss_conf.assoc)
 			return false;
 
+		/*
+		 * When we are coming out of PS, send a nullfunc
+		 * with PM bit cleared only when we know there is
+		 * buffered traffic at the AP.
+		 */
+		if (!powersave) {
+			if (!sc->sched.tim_set)
+				return false;
+		}
+
 		skb = ieee80211_nullfunc_get(sc->hw, vif);
 		if (!skb)
 			return false;
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 2aaf233..1edf8cb 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -892,12 +892,6 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
 		return -EINVAL;
 	}
 
-	if (ath9k_is_chanctx_enabled()) {
-		if (rx_stats->is_mybeacon)
-			ath_chanctx_beacon_recv_ev(sc, rx_stats->rs_tstamp,
-					   ATH_CHANCTX_EVENT_BEACON_RECEIVED);
-	}
-
 	ath9k_cmn_process_rssi(common, hw, rx_stats, rx_status);
 
 	rx_status->band = ah->curchan->chan->band;
@@ -1117,6 +1111,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 			ath_rx_ps(sc, skb, rs.is_mybeacon);
 		spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 
+		if (ath9k_is_chanctx_enabled()) {
+			if (rs.is_mybeacon)
+				ath_chanctx_beacon_recv_ev(sc, skb, rs.rs_tstamp,
+					   ATH_CHANCTX_EVENT_BEACON_RECEIVED);
+		}
+
 		ath9k_antenna_check(sc, &rs);
 		ath9k_apply_ampdu_details(sc, &rs, rxs);
 		ath_debug_rate_stats(sc, &rs, skb);
-- 
2.1.0


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

* [PATCH 2/4] ath9k: Disable fastcc for channel context mode
  2014-08-27  6:37 [PATCH 0/4] ath9k patches Sujith Manoharan
  2014-08-27  6:37 ` [PATCH 1/4] ath9k: Fix channel context transition Sujith Manoharan
@ 2014-08-27  6:37 ` Sujith Manoharan
  2014-08-27  8:39   ` Felix Fietkau
  2014-08-27  6:37 ` [PATCH 3/4] ath9k: Add more debug statements for channel context Sujith Manoharan
  2014-08-27  6:37 ` [PATCH 4/4] ath9k: Fix channel context timer Sujith Manoharan
  3 siblings, 1 reply; 11+ messages in thread
From: Sujith Manoharan @ 2014-08-27  6:37 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, ath9k-devel

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

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

diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 2fcafa6..b823b5a 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -303,6 +303,9 @@ int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
 	if (!ath_prepare_reset(sc))
 		fastcc = false;
 
+	if (ath9k_is_chanctx_enabled())
+		fastcc = false;
+
 	spin_lock_bh(&sc->chan_lock);
 	sc->cur_chandef = sc->cur_chan->chandef;
 	spin_unlock_bh(&sc->chan_lock);
-- 
2.1.0


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

* [PATCH 3/4] ath9k: Add more debug statements for channel context
  2014-08-27  6:37 [PATCH 0/4] ath9k patches Sujith Manoharan
  2014-08-27  6:37 ` [PATCH 1/4] ath9k: Fix channel context transition Sujith Manoharan
  2014-08-27  6:37 ` [PATCH 2/4] ath9k: Disable fastcc for channel context mode Sujith Manoharan
@ 2014-08-27  6:37 ` Sujith Manoharan
  2014-08-27  6:37 ` [PATCH 4/4] ath9k: Fix channel context timer Sujith Manoharan
  3 siblings, 0 replies; 11+ messages in thread
From: Sujith Manoharan @ 2014-08-27  6:37 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, ath9k-devel

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

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

diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index e1602bc..8a70915 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -288,12 +288,16 @@ static void ath_chanctx_adjust_tbtt_delta(struct ath_softc *sc)
  */
 static void ath_chanctx_setup_timer(struct ath_softc *sc, u32 tsf_time)
 {
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_hw *ah = sc->sc_ah;
 
 	ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, tsf_time, 1000000);
 	tsf_time -= ath9k_hw_gettsf32(ah);
 	tsf_time = msecs_to_jiffies(tsf_time / 1000) + 1;
 	mod_timer(&sc->sched.timer, tsf_time);
+
+	ath_dbg(common, CHAN_CTX,
+		"Setup chanctx timer with timeout: %d ms\n", jiffies_to_msecs(tsf_time));
 }
 
 /*
@@ -357,42 +361,55 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
 	u32 beacon_int;
 	bool noa_changed = false;
 
-	ath_dbg(common, CHAN_CTX, "event: %s, state: %s\n",
-		chanctx_event_string(ev),
-		chanctx_state_string(sc->sched.state));
-
 	if (vif)
 		avp = (struct ath_vif *) vif->drv_priv;
 
 	spin_lock_bh(&sc->chan_lock);
 
+	ath_dbg(common, CHAN_CTX, "cur_chan: %d MHz, event: %s, state: %s\n",
+		sc->cur_chan->chandef.center_freq1,
+		chanctx_event_string(ev),
+		chanctx_state_string(sc->sched.state));
+
 	switch (ev) {
 	case ATH_CHANCTX_EVENT_BEACON_PREPARE:
 		if (avp->offchannel_duration)
 			avp->offchannel_duration = 0;
 
-		if (avp->chanctx != sc->cur_chan)
+		if (avp->chanctx != sc->cur_chan) {
+			ath_dbg(common, CHAN_CTX,
+				"Contexts differ, not preparing beacon\n");
 			break;
+		}
 
 		if (sc->sched.offchannel_pending) {
 			sc->sched.offchannel_pending = false;
 			sc->next_chan = &sc->offchannel.chan;
 			sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
+			ath_dbg(common, CHAN_CTX,
+				"Setting offchannel_pending to false\n");
 		}
 
 		ctx = ath_chanctx_get_next(sc, sc->cur_chan);
 		if (ctx->active && sc->sched.state == ATH_CHANCTX_STATE_IDLE) {
 			sc->next_chan = ctx;
 			sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
+			ath_dbg(common, CHAN_CTX,
+				"Set next context, move chanctx state to WAIT_FOR_BEACON\n");
 		}
 
 		/* if the timer missed its window, use the next interval */
-		if (sc->sched.state == ATH_CHANCTX_STATE_WAIT_FOR_TIMER)
+		if (sc->sched.state == ATH_CHANCTX_STATE_WAIT_FOR_TIMER) {
 			sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
+			ath_dbg(common, CHAN_CTX,
+				"Move chanctx state from WAIT_FOR_TIMER to WAIT_FOR_BEACON\n");
+		}
 
 		if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON)
 			break;
 
+		ath_dbg(common, CHAN_CTX, "Preparing beacon for vif: %pM\n", vif->addr);
+
 		sc->sched.beacon_pending = true;
 		sc->sched.next_tbtt = REG_READ(ah, AR_NEXT_TBTT_TIMER);
 
@@ -436,15 +453,28 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
 
 		if (noa_changed)
 			avp->noa_index++;
+
+		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);
+
 		break;
 	case ATH_CHANCTX_EVENT_BEACON_SENT:
-		if (!sc->sched.beacon_pending)
+		if (!sc->sched.beacon_pending) {
+			ath_dbg(common, CHAN_CTX,
+				"No pending beacon\n");
 			break;
+		}
 
 		sc->sched.beacon_pending = false;
 		if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON)
 			break;
 
+		ath_dbg(common, CHAN_CTX,
+			"Move chanctx state to WAIT_FOR_TIMER\n");
+
 		sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_TIMER;
 		ath_chanctx_setup_timer(sc, sc->sched.switch_start_time);
 		break;
@@ -456,6 +486,9 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
 		    sc->sched.beacon_pending)
 			sc->sched.beacon_miss++;
 
+		ath_dbg(common, CHAN_CTX,
+			"Move chanctx state to SWITCH\n");
+
 		sc->sched.state = ATH_CHANCTX_STATE_SWITCH;
 		ieee80211_queue_work(sc->hw, &sc->chanctx_work);
 		break;
@@ -484,6 +517,9 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
 		    avp->chanctx != sc->cur_chan)
 			break;
 
+		ath_dbg(common, CHAN_CTX,
+			"Move chanctx state from FORCE_ACTIVE to IDLE\n");
+
 		sc->sched.state = ATH_CHANCTX_STATE_IDLE;
 		/* fall through */
 	case ATH_CHANCTX_EVENT_SWITCH:
@@ -499,6 +535,9 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
 		sc->next_chan = ath_chanctx_get_next(sc, sc->cur_chan);
 		cur_conf = &sc->cur_chan->beacon;
 
+		ath_dbg(common, CHAN_CTX,
+			"Move chanctx state to WAIT_FOR_TIMER (event SWITCH)\n");
+
 		sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_TIMER;
 
 		tsf_time = TU_TO_USEC(cur_conf->beacon_interval) / 2;
@@ -668,7 +707,8 @@ ath_scan_next_channel(struct ath_softc *sc)
 
 	if (sc->offchannel.scan_idx >= req->n_channels) {
 		ath_dbg(common, CHAN_CTX,
-			"Moving to ATH_OFFCHANNEL_IDLE state, scan_idx: %d, n_channels: %d\n",
+			"Moving offchannel state to ATH_OFFCHANNEL_IDLE, "
+			"scan_idx: %d, n_channels: %d\n",
 			sc->offchannel.scan_idx,
 			req->n_channels);
 
@@ -679,7 +719,7 @@ ath_scan_next_channel(struct ath_softc *sc)
 	}
 
 	ath_dbg(common, CHAN_CTX,
-		"Moving to ATH_OFFCHANNEL_PROBE_SEND state, scan_idx: %d\n",
+		"Moving offchannel state to ATH_OFFCHANNEL_PROBE_SEND, scan_idx: %d\n",
 		sc->offchannel.scan_idx);
 
 	chan = req->channels[sc->offchannel.scan_idx++];
@@ -792,7 +832,7 @@ static void ath_scan_channel_start(struct ath_softc *sc)
 	}
 
 	ath_dbg(common, CHAN_CTX,
-		"Moving to ATH_OFFCHANNEL_PROBE_WAIT state\n");
+		"Moving offchannel state to ATH_OFFCHANNEL_PROBE_WAIT\n");
 
 	sc->offchannel.state = ATH_OFFCHANNEL_PROBE_WAIT;
 	mod_timer(&sc->offchannel.timer, jiffies + sc->offchannel.duration);
@@ -801,6 +841,10 @@ static void ath_scan_channel_start(struct ath_softc *sc)
 static void ath_chanctx_timer(unsigned long data)
 {
 	struct ath_softc *sc = (struct ath_softc *) data;
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+	ath_dbg(common, CHAN_CTX,
+		"Channel context timer invoked\n");
 
 	ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_TSF_TIMER);
 }
@@ -811,7 +855,7 @@ static void ath_offchannel_timer(unsigned long data)
 	struct ath_chanctx *ctx;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 
-	ath_dbg(common, CHAN_CTX, "%s: state: %s\n",
+	ath_dbg(common, CHAN_CTX, "%s: offchannel state: %s\n",
 		__func__, offchannel_state_string(sc->offchannel.state));
 
 	switch (sc->offchannel.state) {
@@ -822,6 +866,10 @@ static void ath_offchannel_timer(unsigned long data)
 		/* get first active channel context */
 		ctx = ath_chanctx_get_oper_chan(sc, true);
 		if (ctx->active) {
+			ath_dbg(common, CHAN_CTX,
+				"Switch to oper/active context, "
+				"move offchannel state to ATH_OFFCHANNEL_SUSPEND\n");
+
 			sc->offchannel.state = ATH_OFFCHANNEL_SUSPEND;
 			ath_chanctx_switch(sc, ctx, NULL);
 			mod_timer(&sc->offchannel.timer, jiffies + HZ / 10);
@@ -920,6 +968,8 @@ ath_chanctx_send_ps_frame(struct ath_softc *sc, bool powersave)
 
 static bool ath_chanctx_defer_switch(struct ath_softc *sc)
 {
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
 	if (sc->cur_chan == &sc->offchannel.chan)
 		return false;
 
@@ -930,6 +980,9 @@ static bool ath_chanctx_defer_switch(struct ath_softc *sc)
 		if (!sc->cur_chan->switch_after_beacon)
 			return false;
 
+		ath_dbg(common, CHAN_CTX,
+			"Defer switch, set chanctx state to WAIT_FOR_BEACON\n");
+
 		sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
 		break;
 	default:
@@ -943,7 +996,7 @@ static void ath_offchannel_channel_change(struct ath_softc *sc)
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 
-	ath_dbg(common, CHAN_CTX, "%s: state: %s\n",
+	ath_dbg(common, CHAN_CTX, "%s: offchannel state: %s\n",
 		__func__, offchannel_state_string(sc->offchannel.state));
 
 	switch (sc->offchannel.state) {
@@ -982,6 +1035,7 @@ static void ath_offchannel_channel_change(struct ath_softc *sc)
 
 void ath_chanctx_set_next(struct ath_softc *sc, bool force)
 {
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct timespec ts;
 	bool measure_time = false;
 	bool send_ps = false;
@@ -997,7 +1051,16 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
 		return;
 	}
 
+	ath_dbg(common, CHAN_CTX,
+		"%s: current: %d MHz, next: %d MHz\n",
+		__func__,
+		sc->cur_chan->chandef.center_freq1,
+		sc->next_chan->chandef.center_freq1);
+
 	if (sc->cur_chan != sc->next_chan) {
+		ath_dbg(common, CHAN_CTX,
+			"Stopping current chanctx: %d\n",
+			sc->cur_chan->chandef.center_freq1);
 		sc->cur_chan->stopped = true;
 		spin_unlock_bh(&sc->chan_lock);
 
@@ -1030,6 +1093,9 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
 	if (sc->sc_ah->chip_fullsleep ||
 	    memcmp(&sc->cur_chandef, &sc->cur_chan->chandef,
 		   sizeof(sc->cur_chandef))) {
+		ath_dbg(common, CHAN_CTX,
+			"%s: Set channel %d MHz\n",
+			__func__, sc->cur_chan->chandef.center_freq1);
 		ath_set_channel(sc);
 		if (measure_time)
 			sc->sched.channel_switch_time =
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index b823b5a..d9be831 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -2361,6 +2361,9 @@ static void ath9k_mgd_prepare_tx(struct ieee80211_hw *hw,
 		sc->next_chan = avp->chanctx;
 		changed = true;
 	}
+	ath_dbg(common, CHAN_CTX,
+		"%s: Set chanctx state to FORCE_ACTIVE, changed: %d\n",
+		__func__, changed);
 	sc->sched.state = ATH_CHANCTX_STATE_FORCE_ACTIVE;
 	spin_unlock_bh(&sc->chan_lock);
 
-- 
2.1.0


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

* [PATCH 4/4] ath9k: Fix channel context timer
  2014-08-27  6:37 [PATCH 0/4] ath9k patches Sujith Manoharan
                   ` (2 preceding siblings ...)
  2014-08-27  6:37 ` [PATCH 3/4] ath9k: Add more debug statements for channel context Sujith Manoharan
@ 2014-08-27  6:37 ` Sujith Manoharan
  3 siblings, 0 replies; 11+ messages in thread
From: Sujith Manoharan @ 2014-08-27  6:37 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, ath9k-devel

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

Setup the channel context correctly. Not doing this was
causing beacon loss in a P2P-GO/STA concurrent setup.

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 8a70915..a8082df 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -294,7 +294,7 @@ static void ath_chanctx_setup_timer(struct ath_softc *sc, u32 tsf_time)
 	ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, tsf_time, 1000000);
 	tsf_time -= ath9k_hw_gettsf32(ah);
 	tsf_time = msecs_to_jiffies(tsf_time / 1000) + 1;
-	mod_timer(&sc->sched.timer, tsf_time);
+	mod_timer(&sc->sched.timer, jiffies + tsf_time);
 
 	ath_dbg(common, CHAN_CTX,
 		"Setup chanctx timer with timeout: %d ms\n", jiffies_to_msecs(tsf_time));
-- 
2.1.0


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

* Re: [PATCH 1/4] ath9k: Fix channel context transition
  2014-08-27  6:37 ` [PATCH 1/4] ath9k: Fix channel context transition Sujith Manoharan
@ 2014-08-27  8:38   ` Felix Fietkau
  2014-08-27  9:55     ` Sujith Manoharan
  0 siblings, 1 reply; 11+ messages in thread
From: Felix Fietkau @ 2014-08-27  8:38 UTC (permalink / raw)
  To: Sujith Manoharan, John Linville; +Cc: linux-wireless, ath9k-devel

On 2014-08-27 08:37, Sujith Manoharan wrote:
> From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
> 
> In channel context mode, a nullfunc is sent with
> the PM bit enabled when we switch to a new channel
> context from the current one. But, when the scheduler
> switches back to the old context, sending a nullfunc
> with PM bit cleared has to be done only if there is
> buffered traffic at the AP.
> 
> Currently, this is not done and a nullfunc is sent
> for every transition. Fix this by parsing the TIM IE
> for a received beacon and checking if there is buffered
> traffic.
That does not make much sense to me. Why would you not inform the AP and
instead let it start buffering until the next beacon period?

- Felix

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

* Re: [PATCH 2/4] ath9k: Disable fastcc for channel context mode
  2014-08-27  6:37 ` [PATCH 2/4] ath9k: Disable fastcc for channel context mode Sujith Manoharan
@ 2014-08-27  8:39   ` Felix Fietkau
  2014-08-27  9:58     ` Sujith Manoharan
  0 siblings, 1 reply; 11+ messages in thread
From: Felix Fietkau @ 2014-08-27  8:39 UTC (permalink / raw)
  To: Sujith Manoharan, John Linville; +Cc: linux-wireless, ath9k-devel

On 2014-08-27 08:37, Sujith Manoharan wrote:
> From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
> 
> Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
> ---
>  drivers/net/wireless/ath/ath9k/main.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
> index 2fcafa6..b823b5a 100644
> --- a/drivers/net/wireless/ath/ath9k/main.c
> +++ b/drivers/net/wireless/ath/ath9k/main.c
> @@ -303,6 +303,9 @@ int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
>  	if (!ath_prepare_reset(sc))
>  		fastcc = false;
>  
> +	if (ath9k_is_chanctx_enabled())
> +		fastcc = false;
> +
Why?

- Felix

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

* Re: [PATCH 1/4] ath9k: Fix channel context transition
  2014-08-27  8:38   ` Felix Fietkau
@ 2014-08-27  9:55     ` Sujith Manoharan
  2014-08-27 10:40       ` Jouni Malinen
  0 siblings, 1 reply; 11+ messages in thread
From: Sujith Manoharan @ 2014-08-27  9:55 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: John Linville, linux-wireless, ath9k-devel

Felix Fietkau wrote:
> That does not make much sense to me. Why would you not inform the AP and
> instead let it start buffering until the next beacon period?

Is it correct to send a nullfunc to the AP with PM=0 when there is no
buffered traffic and the TIM doesn't indicate anything for the station's AID ?
This was the concern raised.

The mac80211 mlme does a similar thing too, in ieee80211_rx_mgmt_beacon().
A nullfunc with PM=0 is sent only when the aid is set in the TIM IE.

Sujith

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

* Re: [PATCH 2/4] ath9k: Disable fastcc for channel context mode
  2014-08-27  8:39   ` Felix Fietkau
@ 2014-08-27  9:58     ` Sujith Manoharan
  0 siblings, 0 replies; 11+ messages in thread
From: Sujith Manoharan @ 2014-08-27  9:58 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: John Linville, linux-wireless, ath9k-devel

Felix Fietkau wrote:
> > +	if (ath9k_is_chanctx_enabled())
> > +		fastcc = false;
> > +
> Why?

Constant switching of HW channels (and bgscan) appear to make things
go deaf after some time. We have never really tested fastcc and as
a preemptive measure, it can be disabled for MCC.

Sujith

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

* Re: [PATCH 1/4] ath9k: Fix channel context transition
  2014-08-27  9:55     ` Sujith Manoharan
@ 2014-08-27 10:40       ` Jouni Malinen
  2014-08-27 10:46         ` Sujith Manoharan
  0 siblings, 1 reply; 11+ messages in thread
From: Jouni Malinen @ 2014-08-27 10:40 UTC (permalink / raw)
  To: Sujith Manoharan
  Cc: Felix Fietkau, John Linville, linux-wireless, ath9k-devel

On Wed, Aug 27, 2014 at 03:25:08PM +0530, Sujith Manoharan wrote:
> Felix Fietkau wrote:
> > That does not make much sense to me. Why would you not inform the AP and
> > instead let it start buffering until the next beacon period?
> 
> Is it correct to send a nullfunc to the AP with PM=0 when there is no
> buffered traffic and the TIM doesn't indicate anything for the station's AID ?
> This was the concern raised.

You can send as many nullfunc Data frames as you want and pretty much
whenever you want.. If the AP has information indicating that the STA is
in power save mode, this frame needs to be sent. If the AP doesn't have
such information or the STA does not know what the state is, this frame
can still be sent. I would skip this only if the STA is reasonably
certain the AP does not have it recorded to be in power save mode.

In addition to power save management, nullfunc frames can be used for
number of other purposes, e.g., to check that the association is valid
and to trigger operations (well, that is related to power save). In any
case, there are no rules (other than normal Data frame rules) that
somehow limit the STA from sending this frame.

-- 
Jouni Malinen                                            PGP id EFC895FA

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

* Re: [PATCH 1/4] ath9k: Fix channel context transition
  2014-08-27 10:40       ` Jouni Malinen
@ 2014-08-27 10:46         ` Sujith Manoharan
  0 siblings, 0 replies; 11+ messages in thread
From: Sujith Manoharan @ 2014-08-27 10:46 UTC (permalink / raw)
  To: Jouni Malinen; +Cc: Felix Fietkau, John Linville, linux-wireless, ath9k-devel

Jouni Malinen wrote:
> You can send as many nullfunc Data frames as you want and pretty much
> whenever you want.. If the AP has information indicating that the STA is
> in power save mode, this frame needs to be sent. If the AP doesn't have
> such information or the STA does not know what the state is, this frame
> can still be sent. I would skip this only if the STA is reasonably
> certain the AP does not have it recorded to be in power save mode.
> 
> In addition to power save management, nullfunc frames can be used for
> number of other purposes, e.g., to check that the association is valid
> and to trigger operations (well, that is related to power save). In any
> case, there are no rules (other than normal Data frame rules) that
> somehow limit the STA from sending this frame.

Thanks for clarifying. This patch is unnecessary then.

John, please drop this patch.

Sujith

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

end of thread, other threads:[~2014-08-27 10:46 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-27  6:37 [PATCH 0/4] ath9k patches Sujith Manoharan
2014-08-27  6:37 ` [PATCH 1/4] ath9k: Fix channel context transition Sujith Manoharan
2014-08-27  8:38   ` Felix Fietkau
2014-08-27  9:55     ` Sujith Manoharan
2014-08-27 10:40       ` Jouni Malinen
2014-08-27 10:46         ` Sujith Manoharan
2014-08-27  6:37 ` [PATCH 2/4] ath9k: Disable fastcc for channel context mode Sujith Manoharan
2014-08-27  8:39   ` Felix Fietkau
2014-08-27  9:58     ` Sujith Manoharan
2014-08-27  6:37 ` [PATCH 3/4] ath9k: Add more debug statements for channel context Sujith Manoharan
2014-08-27  6:37 ` [PATCH 4/4] ath9k: Fix channel context timer 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.