summaryrefslogtreecommitdiffstats
path: root/net/mac80211/agg-rx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-02-10 21:25:51 +0100
committerJohn W. Linville <linville@tuxdriver.com>2009-02-13 13:45:43 -0500
commit55687e380a3965ac448e03281e027553a6ae6dac (patch)
treeba7c079d3ce4d7278eeb45317ba3baf54f45c96c /net/mac80211/agg-rx.c
parent23e6a7ea5cb1a902d37ab0c783709c178fa834df (diff)
downloadlinux-55687e380a3965ac448e03281e027553a6ae6dac.tar.gz
linux-55687e380a3965ac448e03281e027553a6ae6dac.tar.bz2
linux-55687e380a3965ac448e03281e027553a6ae6dac.zip
mac80211: fix aggregation timer lockups
As far as I can tell, there are possible lockups because both the RX session_timer and TX addba_resp_timer are del_timer_sync'ed under the sta spinlock which both timer functions take. Additionally, the TX agg code seems to leak memory when TX aggregation is not disabled before the sta_info is freed. Fix this by making the free code a little smarter in the RX agg case, and actually make the sta_info_destroy code free the TX agg info in the TX agg case. We won't notify the peer, but it'll notice something is wrong anyway, and normally this only happens after we've told it in some other way we will no longer talk to it. 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.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index d7afd0956970..4b571b211625 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -78,11 +78,18 @@ void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *r
sta->ampdu_mlme.tid_rx[tid]->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]);
- sta->ampdu_mlme.tid_rx[tid] = NULL;
+
+ if (!sta->ampdu_mlme.tid_rx[tid]->shutdown) {
+ kfree(sta->ampdu_mlme.tid_rx[tid]);
+ sta->ampdu_mlme.tid_rx[tid] = NULL;
+ }
+
sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE;
+ spin_unlock_bh(&sta->lock);
rcu_read_unlock();
}