summaryrefslogtreecommitdiffstats
path: root/net/mac80211/agg-rx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2010-04-06 11:18:47 +0200
committerJohn W. Linville <linville@tuxdriver.com>2010-04-07 14:38:05 -0400
commit098a607091426e79178b9a6c318d993fea131791 (patch)
treed62c9993e49f90ca962cd763b096911d22d7e051 /net/mac80211/agg-rx.c
parent618f356b95e37ca0c30b3b513898fda54abd52a6 (diff)
downloadlinux-098a607091426e79178b9a6c318d993fea131791.tar.gz
linux-098a607091426e79178b9a6c318d993fea131791.tar.bz2
linux-098a607091426e79178b9a6c318d993fea131791.zip
mac80211: clean up/fix aggregation code
The aggregation code has a number of quirks, like inventing an unneeded WLAN_BACK_TIMER value and leaking memory under certain circumstances during station destruction. Fix these issues by using the regular aggregation session teardown code and blocking new aggregation sessions, all before the station is really destructed. As a side effect, this gets rid of the long code block to destroy aggregation safely. Additionally, rename tid_state_rx which can only have the values IDLE and OPERATIONAL to tid_active_rx to make it easier to understand that there is no bitwise stuff going on on the RX side -- the TX side remains because it needs to keep track of the driver and peer states. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/agg-rx.c')
-rw-r--r--net/mac80211/agg-rx.c48
1 files changed, 21 insertions, 27 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 7d87f446f030..53233ab50f65 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -22,19 +22,20 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
u16 initiator, u16 reason)
{
struct ieee80211_local *local = sta->local;
+ struct tid_ampdu_rx *tid_rx;
int i;
- /* check if TID is in operational state */
spin_lock_bh(&sta->lock);
- if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) {
+
+ /* check if TID is in operational state */
+ if (!sta->ampdu_mlme.tid_active_rx[tid]) {
spin_unlock_bh(&sta->lock);
return;
}
- sta->ampdu_mlme.tid_state_rx[tid] =
- HT_AGG_STATE_REQ_STOP_BA_MSK |
- (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
- spin_unlock_bh(&sta->lock);
+ sta->ampdu_mlme.tid_active_rx[tid] = false;
+
+ tid_rx = sta->ampdu_mlme.tid_rx[tid];
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n",
@@ -46,37 +47,30 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
printk(KERN_DEBUG "HW problem - can not stop rx "
"aggregation for tid %d\n", tid);
- /* shutdown timer has not expired */
- if (initiator != WLAN_BACK_TIMER)
- del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
-
/* check if this is a self generated aggregation halt */
- if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER)
+ if (initiator == WLAN_BACK_RECIPIENT)
ieee80211_send_delba(sta->sdata, sta->sta.addr,
tid, 0, reason);
/* free the reordering buffer */
- for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) {
- if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) {
+ for (i = 0; i < tid_rx->buf_size; i++) {
+ if (tid_rx->reorder_buf[i]) {
/* release the reordered frames */
- dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]);
- sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--;
- sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL;
+ dev_kfree_skb(tid_rx->reorder_buf[i]);
+ tid_rx->stored_mpdu_num--;
+ tid_rx->reorder_buf[i] = NULL;
}
}
- spin_lock_bh(&sta->lock);
/* free resources */
- kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf);
- kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_time);
-
- if (!sta->ampdu_mlme.tid_rx[tid]->shutdown) {
- kfree(sta->ampdu_mlme.tid_rx[tid]);
- sta->ampdu_mlme.tid_rx[tid] = NULL;
- }
+ kfree(tid_rx->reorder_buf);
+ kfree(tid_rx->reorder_time);
+ sta->ampdu_mlme.tid_rx[tid] = NULL;
- sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE;
spin_unlock_bh(&sta->lock);
+
+ del_timer_sync(&tid_rx->session_timer);
+ kfree(tid_rx);
}
/*
@@ -211,7 +205,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
/* examine state machine */
spin_lock_bh(&sta->lock);
- if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) {
+ if (sta->ampdu_mlme.tid_active_rx[tid]) {
#ifdef CONFIG_MAC80211_HT_DEBUG
if (net_ratelimit())
printk(KERN_DEBUG "unexpected AddBA Req from "
@@ -273,7 +267,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
}
/* change state and send addba resp */
- sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL;
+ sta->ampdu_mlme.tid_active_rx[tid] = true;
tid_agg_rx->dialog_token = dialog_token;
tid_agg_rx->ssn = start_seq_num;
tid_agg_rx->head_seq_num = start_seq_num;