From: Sujith Manoharan <sujith@msujith.org>
To: John Linville <linville@tuxdriver.com>
Cc: linux-wireless@vger.kernel.org, ath9k-devel@qca.qualcomm.com
Subject: [PATCH 1/4] ath9k: Fix channel context transition
Date: Wed, 27 Aug 2014 12:07:22 +0530 [thread overview]
Message-ID: <1409121445-11484-2-git-send-email-sujith@msujith.org> (raw)
In-Reply-To: <1409121445-11484-1-git-send-email-sujith@msujith.org>
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
next prev parent reply other threads:[~2014-08-27 6:37 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-27 6:37 [PATCH 0/4] ath9k patches Sujith Manoharan
2014-08-27 6:37 ` Sujith Manoharan [this message]
2014-08-27 8:38 ` [PATCH 1/4] ath9k: Fix channel context transition 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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1409121445-11484-2-git-send-email-sujith@msujith.org \
--to=sujith@msujith.org \
--cc=ath9k-devel@qca.qualcomm.com \
--cc=linux-wireless@vger.kernel.org \
--cc=linville@tuxdriver.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).