diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2010-04-19 05:00:24 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-04-19 16:41:42 -0400 |
commit | 2aab4c273ad837fbcf2955aee32b9ec4706c2521 (patch) | |
tree | d2457aa623177d2b7c18b35a81f91ac268699999 /net/mac80211/agg-rx.c | |
parent | 93d95b12b3ba06e0e1f3e43a370ee61539d8cb90 (diff) |
mac80211: fix stopping RX BA session from timer
Kalle reported that his system deadlocks since my
recent work in this area. The reason quickly became
apparent: we try to cancel_timer_sync() a timer
from within itself. Fix that by making the function
aware of the context it is called from.
Reported-by: Kalle Valo <kvalo@adurom.com>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Tested-by: Kalle Valo <kvalo@adurom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/agg-rx.c')
-rw-r--r-- | net/mac80211/agg-rx.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 53233ab50f65..1771dd9bd137 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -18,8 +18,9 @@ | |||
18 | #include "ieee80211_i.h" | 18 | #include "ieee80211_i.h" |
19 | #include "driver-ops.h" | 19 | #include "driver-ops.h" |
20 | 20 | ||
21 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 21 | static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
22 | u16 initiator, u16 reason) | 22 | u16 initiator, u16 reason, |
23 | bool from_timer) | ||
23 | { | 24 | { |
24 | struct ieee80211_local *local = sta->local; | 25 | struct ieee80211_local *local = sta->local; |
25 | struct tid_ampdu_rx *tid_rx; | 26 | struct tid_ampdu_rx *tid_rx; |
@@ -69,10 +70,17 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
69 | 70 | ||
70 | spin_unlock_bh(&sta->lock); | 71 | spin_unlock_bh(&sta->lock); |
71 | 72 | ||
72 | del_timer_sync(&tid_rx->session_timer); | 73 | if (!from_timer) |
74 | del_timer_sync(&tid_rx->session_timer); | ||
73 | kfree(tid_rx); | 75 | kfree(tid_rx); |
74 | } | 76 | } |
75 | 77 | ||
78 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | ||
79 | u16 initiator, u16 reason) | ||
80 | { | ||
81 | ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, false); | ||
82 | } | ||
83 | |||
76 | /* | 84 | /* |
77 | * After accepting the AddBA Request we activated a timer, | 85 | * After accepting the AddBA Request we activated a timer, |
78 | * resetting it after each frame that arrives from the originator. | 86 | * resetting it after each frame that arrives from the originator. |
@@ -91,8 +99,8 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) | |||
91 | #ifdef CONFIG_MAC80211_HT_DEBUG | 99 | #ifdef CONFIG_MAC80211_HT_DEBUG |
92 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | 100 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); |
93 | #endif | 101 | #endif |
94 | __ieee80211_stop_rx_ba_session(sta, *ptid, WLAN_BACK_RECIPIENT, | 102 | ___ieee80211_stop_rx_ba_session(sta, *ptid, WLAN_BACK_RECIPIENT, |
95 | WLAN_REASON_QSTA_TIMEOUT); | 103 | WLAN_REASON_QSTA_TIMEOUT, true); |
96 | } | 104 | } |
97 | 105 | ||
98 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, | 106 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, |