aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
authorHelmut Schaa <helmut.schaa@googlemail.com>2012-03-07 17:20:30 +0100
committerJohn W. Linville <linville@tuxdriver.com>2012-03-12 14:19:35 -0400
commitaa4545806025c63ec12cfe17528de16dca36b785 (patch)
treea979799e3eb20b97f92483d327ea2f4115fe11af /net/mac80211/tx.c
parentcfg80211: Add background scan period attribute. (diff)
downloadlinux-dev-aa4545806025c63ec12cfe17528de16dca36b785.tar.xz
linux-dev-aa4545806025c63ec12cfe17528de16dca36b785.zip
mac80211: Limit TID buffering during BA session setup/teardown
While setting up or tearing down a BA session mac80211 is buffering pending frames for the according TID. However, there's currently no limit on how many frames are buffered possibly leading to an out-of- memory situation. This can happen on systems with little memory when the CPU is fully loaded since the BA session work is executed in process context while frames can still come via softirq. Apply a limitation to the TIDs pending queue to avoid consuming too much memory in this situation. Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r--net/mac80211/tx.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 570737df2d22..d9e791d2b543 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1065,6 +1065,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
{
bool queued = false;
bool reset_agg_timer = false;
+ struct sk_buff *purge_skb = NULL;
if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
info->flags |= IEEE80211_TX_CTL_AMPDU;
@@ -1106,8 +1107,13 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
info->control.vif = &tx->sdata->vif;
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
__skb_queue_tail(&tid_tx->pending, skb);
+ if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER)
+ purge_skb = __skb_dequeue(&tid_tx->pending);
}
spin_unlock(&tx->sta->lock);
+
+ if (purge_skb)
+ dev_kfree_skb(purge_skb);
}
/* reset session timer */