Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 266517
b: refs/heads/master
c: c868cb3
h: refs/heads/master
i:
  266515: 5643917
v: v3
  • Loading branch information
Johannes Berg authored and John W. Linville committed Sep 30, 2011
1 parent 69bfd84 commit 1ee3dcb
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 69 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 042ec4533720122e6cb93dd9f3b6a75fe2fcff16
refs/heads/master: c868cb35d013896ab6a80a554fb88baef06cedcd
99 changes: 42 additions & 57 deletions trunk/net/mac80211/sta_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -641,54 +641,42 @@ static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid)
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 = false;

BUG_ON(!sta->sdata->bss);
if (WARN_ON_ONCE(!sta->sdata->bss))
return;

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);
if (sta->dead)
goto done;

__bss_tim_clear(bss, sta->sta.aid);
have_data = test_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF) ||
!skb_queue_empty(&sta->tx_filtered) ||
!skb_queue_empty(&sta->ps_tx_buf);

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;
}
}
done:
spin_lock_irqsave(&local->sta_lock, flags);

void sta_info_clear_tim_bit(struct sta_info *sta)
{
unsigned long flags;
if (have_data)
__bss_tim_set(bss, sta->sta.aid);
else
__bss_tim_clear(bss, sta->sta.aid);

BUG_ON(!sta->sdata->bss);
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;
}

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)
Expand Down Expand Up @@ -717,6 +705,10 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
unsigned long flags;
struct sk_buff *skb;

/* This is only necessary for stations on BSS interfaces */
if (!sta->sdata->bss)
return false;

for (;;) {
spin_lock_irqsave(&sta->ps_tx_buf.lock, flags);
skb = skb_peek(&sta->ps_tx_buf);
Expand All @@ -736,9 +728,9 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
#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);
Expand All @@ -748,7 +740,6 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
{
struct ieee80211_local *local;
struct ieee80211_sub_if_data *sdata;
struct sk_buff *skb;
unsigned long flags;
int ret, i;

Expand Down Expand Up @@ -792,7 +783,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
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--;
Expand All @@ -818,6 +809,10 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
*/
synchronize_rcu();

local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf);
__skb_queue_purge(&sta->ps_tx_buf);
__skb_queue_purge(&sta->tx_filtered);

#ifdef CONFIG_MAC80211_MESH
if (ieee80211_vif_is_mesh(&sdata->vif))
mesh_accept_plinks_update(sdata);
Expand All @@ -840,14 +835,6 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
}
#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;
Expand Down Expand Up @@ -1027,16 +1014,15 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
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,
clear_sta_ps_flags, sta);
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,
Expand Down Expand Up @@ -1086,8 +1072,7 @@ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta)

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 {
/*
Expand Down Expand Up @@ -1126,6 +1111,6 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta,
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);
3 changes: 1 addition & 2 deletions trunk/net/mac80211/sta_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -528,8 +528,7 @@ int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata,
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);
Expand Down
1 change: 1 addition & 0 deletions trunk/net/mac80211/status.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
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;
}

Expand Down
15 changes: 6 additions & 9 deletions trunk/net/mac80211/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -469,15 +469,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
} 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;
Expand All @@ -488,6 +479,12 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
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
Expand Down

0 comments on commit 1ee3dcb

Please sign in to comment.