aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/agg-rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/agg-rx.c')
-rw-r--r--net/mac80211/agg-rx.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 965b272499f..720b7a84af5 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -56,7 +56,7 @@ static void ieee80211_free_tid_rx(struct rcu_head *h)
56} 56}
57 57
58void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, 58void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
59 u16 initiator, u16 reason) 59 u16 initiator, u16 reason, bool tx)
60{ 60{
61 struct ieee80211_local *local = sta->local; 61 struct ieee80211_local *local = sta->local;
62 struct tid_ampdu_rx *tid_rx; 62 struct tid_ampdu_rx *tid_rx;
@@ -81,20 +81,21 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
81 "aggregation for tid %d\n", tid); 81 "aggregation for tid %d\n", tid);
82 82
83 /* check if this is a self generated aggregation halt */ 83 /* check if this is a self generated aggregation halt */
84 if (initiator == WLAN_BACK_RECIPIENT) 84 if (initiator == WLAN_BACK_RECIPIENT && tx)
85 ieee80211_send_delba(sta->sdata, sta->sta.addr, 85 ieee80211_send_delba(sta->sdata, sta->sta.addr,
86 tid, 0, reason); 86 tid, 0, reason);
87 87
88 del_timer_sync(&tid_rx->session_timer); 88 del_timer_sync(&tid_rx->session_timer);
89 del_timer_sync(&tid_rx->reorder_timer);
89 90
90 call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); 91 call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx);
91} 92}
92 93
93void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, 94void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
94 u16 initiator, u16 reason) 95 u16 initiator, u16 reason, bool tx)
95{ 96{
96 mutex_lock(&sta->ampdu_mlme.mtx); 97 mutex_lock(&sta->ampdu_mlme.mtx);
97 ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason); 98 ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, tx);
98 mutex_unlock(&sta->ampdu_mlme.mtx); 99 mutex_unlock(&sta->ampdu_mlme.mtx);
99} 100}
100 101
@@ -120,6 +121,20 @@ static void sta_rx_agg_session_timer_expired(unsigned long data)
120 ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); 121 ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
121} 122}
122 123
124static void sta_rx_agg_reorder_timer_expired(unsigned long data)
125{
126 u8 *ptid = (u8 *)data;
127 u8 *timer_to_id = ptid - *ptid;
128 struct sta_info *sta = container_of(timer_to_id, struct sta_info,
129 timer_to_tid[0]);
130
131 rcu_read_lock();
132 spin_lock(&sta->lock);
133 ieee80211_release_reorder_timeout(sta, *ptid);
134 spin_unlock(&sta->lock);
135 rcu_read_unlock();
136}
137
123static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, 138static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid,
124 u8 dialog_token, u16 status, u16 policy, 139 u8 dialog_token, u16 status, u16 policy,
125 u16 buf_size, u16 timeout) 140 u16 buf_size, u16 timeout)
@@ -251,11 +266,18 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
251 goto end; 266 goto end;
252 } 267 }
253 268
269 spin_lock_init(&tid_agg_rx->reorder_lock);
270
254 /* rx timer */ 271 /* rx timer */
255 tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired; 272 tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired;
256 tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; 273 tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid];
257 init_timer(&tid_agg_rx->session_timer); 274 init_timer(&tid_agg_rx->session_timer);
258 275
276 /* rx reorder timer */
277 tid_agg_rx->reorder_timer.function = sta_rx_agg_reorder_timer_expired;
278 tid_agg_rx->reorder_timer.data = (unsigned long)&sta->timer_to_tid[tid];
279 init_timer(&tid_agg_rx->reorder_timer);
280
259 /* prepare reordering buffer */ 281 /* prepare reordering buffer */
260 tid_agg_rx->reorder_buf = 282 tid_agg_rx->reorder_buf =
261 kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); 283 kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC);