From: Johannes Berg <johannes@sipsolutions.net>
To: linux-wireless@vger.kernel.org
Subject: [RFC 02/11] mac80211: unify TIM bit handling
Date: Wed, 07 Sep 2011 22:07:46 +0200 [thread overview]
Message-ID: <20110907200921.487835760@sipsolutions.net> (raw)
In-Reply-To: 20110907200744.076513799@sipsolutions.net
From: Johannes Berg <johannes.berg@intel.com>
Currently, the TIM bit for a given station is set
and cleared all over the place. Since the logic to
set/clear it will become much more complex when we
add uAPSD support, as a first step let's collect
the entire logic in one place. This requires a few
small adjustments to other places.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/sta_info.c | 92 +++++++++++++++++-------------------------------
net/mac80211/sta_info.h | 3 -
net/mac80211/status.c | 1
net/mac80211/tx.c | 15 +++----
4 files changed, 41 insertions(+), 70 deletions(-)
--- a/net/mac80211/sta_info.h 2011-09-07 14:31:59.000000000 +0200
+++ b/net/mac80211/sta_info.h 2011-09-07 14:32:37.000000000 +0200
@@ -518,8 +518,7 @@ int sta_info_destroy_addr(struct ieee802
int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata,
const u8 *addr);
-void sta_info_set_tim_bit(struct sta_info *sta);
-void sta_info_clear_tim_bit(struct sta_info *sta);
+void sta_info_recalc_tim(struct sta_info *sta);
void sta_info_init(struct ieee80211_local *local);
void sta_info_stop(struct ieee80211_local *local);
--- a/net/mac80211/tx.c 2011-09-07 14:31:59.000000000 +0200
+++ b/net/mac80211/tx.c 2011-09-07 14:32:37.000000000 +0200
@@ -469,15 +469,6 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
} else
tx->local->total_ps_buffered++;
- /*
- * Queue frame to be sent after STA wakes up/polls,
- * but don't set the TIM bit if the driver is blocking
- * wakeup or poll response transmissions anyway.
- */
- if (skb_queue_empty(&sta->ps_tx_buf) &&
- !(staflags & WLAN_STA_PS_DRIVER))
- sta_info_set_tim_bit(sta);
-
info->control.jiffies = jiffies;
info->control.vif = &tx->sdata->vif;
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
@@ -488,6 +479,12 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
round_jiffies(jiffies +
STA_INFO_CLEANUP_INTERVAL));
+ /*
+ * We queued up some frames, so the TIM bit might
+ * need to be set, recalculate it.
+ */
+ sta_info_recalc_tim(sta);
+
return TX_QUEUED;
}
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
--- a/net/mac80211/sta_info.c 2011-09-07 14:32:36.000000000 +0200
+++ b/net/mac80211/sta_info.c 2011-09-07 14:32:37.000000000 +0200
@@ -641,54 +641,35 @@ static inline void __bss_tim_clear(struc
bss->tim[aid / 8] &= ~(1 << (aid % 8));
}
-static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss,
- struct sta_info *sta)
-{
- BUG_ON(!bss);
-
- __bss_tim_set(bss, sta->sta.aid);
-
- if (sta->local->ops->set_tim) {
- sta->local->tim_in_locked_section = true;
- drv_set_tim(sta->local, &sta->sta, true);
- sta->local->tim_in_locked_section = false;
- }
-}
-
-void sta_info_set_tim_bit(struct sta_info *sta)
+void sta_info_recalc_tim(struct sta_info *sta)
{
+ struct ieee80211_local *local = sta->local;
+ struct ieee80211_if_ap *bss = sta->sdata->bss;
unsigned long flags;
+ bool have_data;
- BUG_ON(!sta->sdata->bss);
-
- spin_lock_irqsave(&sta->local->sta_lock, flags);
- __sta_info_set_tim_bit(sta->sdata->bss, sta);
- spin_unlock_irqrestore(&sta->local->sta_lock, flags);
-}
+ /* No need to do anything if the driver does all */
+ if (local->hw.flags & IEEE80211_HW_AP_LINK_PS)
+ return;
-static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss,
- struct sta_info *sta)
-{
- BUG_ON(!bss);
+ have_data = test_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF) ||
+ !skb_queue_empty(&sta->tx_filtered) ||
+ !skb_queue_empty(&sta->ps_tx_buf);
- __bss_tim_clear(bss, sta->sta.aid);
+ spin_lock_irqsave(&local->sta_lock, flags);
- if (sta->local->ops->set_tim) {
- sta->local->tim_in_locked_section = true;
- drv_set_tim(sta->local, &sta->sta, false);
- sta->local->tim_in_locked_section = false;
+ if (have_data)
+ __bss_tim_set(bss, sta->sta.aid);
+ else
+ __bss_tim_clear(bss, sta->sta.aid);
+
+ if (local->ops->set_tim) {
+ local->tim_in_locked_section = true;
+ drv_set_tim(local, &sta->sta, have_data);
+ local->tim_in_locked_section = false;
}
-}
-
-void sta_info_clear_tim_bit(struct sta_info *sta)
-{
- unsigned long flags;
- BUG_ON(!sta->sdata->bss);
-
- spin_lock_irqsave(&sta->local->sta_lock, flags);
- __sta_info_clear_tim_bit(sta->sdata->bss, sta);
- spin_unlock_irqrestore(&sta->local->sta_lock, flags);
+ spin_unlock_irqrestore(&local->sta_lock, flags);
}
static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb)
@@ -736,9 +717,9 @@ static bool sta_info_cleanup_expire_buff
#endif
dev_kfree_skb(skb);
- if (skb_queue_empty(&sta->ps_tx_buf) &&
- !test_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF))
- sta_info_clear_tim_bit(sta);
+ /* if the queue is now empty recalc TIM bit */
+ if (skb_queue_empty(&sta->ps_tx_buf))
+ sta_info_recalc_tim(sta);
}
return !skb_queue_empty(&sta->ps_tx_buf);
@@ -748,7 +729,6 @@ static int __must_check __sta_info_destr
{
struct ieee80211_local *local;
struct ieee80211_sub_if_data *sdata;
- struct sk_buff *skb;
unsigned long flags;
int ret, i;
@@ -787,12 +767,16 @@ static int __must_check __sta_info_destr
sta->dead = true;
+ local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf);
+ __skb_queue_purge(&sta->ps_tx_buf);
+ __skb_queue_purge(&sta->tx_filtered);
+
if (test_and_clear_sta_flags(sta,
WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) {
BUG_ON(!sdata->bss);
atomic_dec(&sdata->bss->num_sta_ps);
- sta_info_clear_tim_bit(sta);
+ sta_info_recalc_tim(sta);
}
local->num_sta--;
@@ -840,14 +824,6 @@ static int __must_check __sta_info_destr
}
#endif
- while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
- local->total_ps_buffered--;
- dev_kfree_skb_any(skb);
- }
-
- while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL)
- dev_kfree_skb_any(skb);
-
__sta_info_free(local, sta);
return 0;
@@ -1027,9 +1003,6 @@ void ieee80211_sta_ps_deliver_wakeup(str
if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
- if (!skb_queue_empty(&sta->ps_tx_buf))
- sta_info_clear_tim_bit(sta);
-
/* Send all buffered frames to the station */
sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered);
buffered = ieee80211_add_pending_skbs_fn(local, &sta->ps_tx_buf,
@@ -1037,6 +1010,8 @@ void ieee80211_sta_ps_deliver_wakeup(str
sent += buffered;
local->total_ps_buffered -= buffered;
+ sta_info_recalc_tim(sta);
+
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames "
"since STA not sleeping anymore\n", sdata->name,
@@ -1086,8 +1061,7 @@ void ieee80211_sta_ps_deliver_poll_respo
ieee80211_add_pending_skb(local, skb);
- if (no_pending_pkts)
- sta_info_clear_tim_bit(sta);
+ sta_info_recalc_tim(sta);
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
} else {
/*
@@ -1126,6 +1100,6 @@ void ieee80211_sta_set_buffered(struct i
return;
set_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF);
- sta_info_set_tim_bit(sta);
+ sta_info_recalc_tim(sta);
}
EXPORT_SYMBOL(ieee80211_sta_set_buffered);
--- a/net/mac80211/status.c 2011-09-07 14:31:59.000000000 +0200
+++ b/net/mac80211/status.c 2011-09-07 14:32:37.000000000 +0200
@@ -106,6 +106,7 @@ static void ieee80211_handle_filtered_fr
if (test_sta_flags(sta, WLAN_STA_PS_STA) &&
skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) {
skb_queue_tail(&sta->tx_filtered, skb);
+ sta_info_recalc_tim(sta);
return;
}
next prev parent reply other threads:[~2011-09-07 20:10 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-09-07 20:07 [RFC 00/11] AP powersaving clients changes Johannes Berg
2011-09-07 20:07 ` [RFC 01/11] mac80211: let drivers inform it about per TID buffered frames Johannes Berg
2011-09-07 20:07 ` Johannes Berg [this message]
2011-09-07 20:07 ` [RFC 03/11] mac80211: also expire filtered frames Johannes Berg
2011-09-07 20:07 ` [RFC 04/11] mac80211: split PS buffers into ACs Johannes Berg
2011-09-07 20:07 ` [RFC 05/11] mac80211: remove return value from add_pending_skbs Johannes Berg
2011-09-07 20:07 ` [RFC 06/11] mac80211: clear more-data bit on filtered frames Johannes Berg
2011-09-07 20:07 ` [RFC 07/11] mac80211: allow releasing driver-buffered frames Johannes Berg
2011-09-07 20:07 ` [RFC 08/11] mac80211: implement uAPSD Johannes Berg
2011-09-07 20:07 ` [RFC 09/11] mac80211: reply only once to each PS-poll Johannes Berg
2011-09-07 20:07 ` [RFC 10/11] mac80211: optimise station flags Johannes Berg
2011-09-07 20:07 ` [RFC 11/11] mac80211: add missing station flags to debugfs Johannes Berg
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=20110907200921.487835760@sipsolutions.net \
--to=johannes@sipsolutions.net \
--cc=linux-wireless@vger.kernel.org \
/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 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.