aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/agg-rx.c8
-rw-r--r--net/mac80211/rx.c47
-rw-r--r--net/mac80211/sta_info.h2
3 files changed, 55 insertions, 2 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index fff24c3d6460..bc064d7933ff 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -68,6 +68,7 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
68 spin_lock_bh(&sta->lock); 68 spin_lock_bh(&sta->lock);
69 /* free resources */ 69 /* free resources */
70 kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); 70 kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf);
71 kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_time);
71 72
72 if (!sta->ampdu_mlme.tid_rx[tid]->shutdown) { 73 if (!sta->ampdu_mlme.tid_rx[tid]->shutdown) {
73 kfree(sta->ampdu_mlme.tid_rx[tid]); 74 kfree(sta->ampdu_mlme.tid_rx[tid]);
@@ -268,13 +269,18 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
268 /* prepare reordering buffer */ 269 /* prepare reordering buffer */
269 tid_agg_rx->reorder_buf = 270 tid_agg_rx->reorder_buf =
270 kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); 271 kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC);
271 if (!tid_agg_rx->reorder_buf) { 272 tid_agg_rx->reorder_time =
273 kcalloc(buf_size, sizeof(unsigned long), GFP_ATOMIC);
274 if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) {
272#ifdef CONFIG_MAC80211_HT_DEBUG 275#ifdef CONFIG_MAC80211_HT_DEBUG
273 if (net_ratelimit()) 276 if (net_ratelimit())
274 printk(KERN_ERR "can not allocate reordering buffer " 277 printk(KERN_ERR "can not allocate reordering buffer "
275 "to tid %d\n", tid); 278 "to tid %d\n", tid);
276#endif 279#endif
280 kfree(tid_agg_rx->reorder_buf);
281 kfree(tid_agg_rx->reorder_time);
277 kfree(sta->ampdu_mlme.tid_rx[tid]); 282 kfree(sta->ampdu_mlme.tid_rx[tid]);
283 sta->ampdu_mlme.tid_rx[tid] = NULL;
278 goto end; 284 goto end;
279 } 285 }
280 286
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 9f2a29d1890b..24d41705ac0b 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2313,6 +2313,15 @@ no_frame:
2313 2313
2314 2314
2315/* 2315/*
2316 * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If
2317 * the skb was added to the buffer longer than this time ago, the earlier
2318 * frames that have not yet been received are assumed to be lost and the skb
2319 * can be released for processing. This may also release other skb's from the
2320 * reorder buffer if there are no additional gaps between the frames.
2321 */
2322#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10)
2323
2324/*
2316 * As it function blongs to Rx path it must be called with 2325 * As it function blongs to Rx path it must be called with
2317 * the proper rcu_read_lock protection for its flow. 2326 * the proper rcu_read_lock protection for its flow.
2318 */ 2327 */
@@ -2377,13 +2386,49 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
2377 2386
2378 /* put the frame in the reordering buffer */ 2387 /* put the frame in the reordering buffer */
2379 tid_agg_rx->reorder_buf[index] = skb; 2388 tid_agg_rx->reorder_buf[index] = skb;
2389 tid_agg_rx->reorder_time[index] = jiffies;
2380 memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus, 2390 memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus,
2381 sizeof(*rxstatus)); 2391 sizeof(*rxstatus));
2382 tid_agg_rx->stored_mpdu_num++; 2392 tid_agg_rx->stored_mpdu_num++;
2383 /* release the buffer until next missing frame */ 2393 /* release the buffer until next missing frame */
2384 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) 2394 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn)
2385 % tid_agg_rx->buf_size; 2395 % tid_agg_rx->buf_size;
2386 while (tid_agg_rx->reorder_buf[index]) { 2396 if (!tid_agg_rx->reorder_buf[index] &&
2397 tid_agg_rx->stored_mpdu_num > 1) {
2398 /*
2399 * No buffers ready to be released, but check whether any
2400 * frames in the reorder buffer have timed out.
2401 */
2402 int j;
2403 int skipped = 1;
2404 for (j = (index + 1) % tid_agg_rx->buf_size; j != index;
2405 j = (j + 1) % tid_agg_rx->buf_size) {
2406 if (tid_agg_rx->reorder_buf[j] == NULL) {
2407 skipped++;
2408 continue;
2409 }
2410 if (!time_after(jiffies, tid_agg_rx->reorder_time[j] +
2411 HZ / 10))
2412 break;
2413
2414#ifdef CONFIG_MAC80211_HT_DEBUG
2415 if (net_ratelimit())
2416 printk(KERN_DEBUG "%s: release an RX reorder "
2417 "frame due to timeout on earlier "
2418 "frames\n",
2419 wiphy_name(hw->wiphy));
2420#endif
2421 ieee80211_release_reorder_frame(hw, tid_agg_rx, j);
2422
2423 /*
2424 * Increment the head seq# also for the skipped slots.
2425 */
2426 tid_agg_rx->head_seq_num =
2427 (tid_agg_rx->head_seq_num + skipped) &
2428 SEQ_MASK;
2429 skipped = 0;
2430 }
2431 } else while (tid_agg_rx->reorder_buf[index]) {
2387 ieee80211_release_reorder_frame(hw, tid_agg_rx, index); 2432 ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
2388 index = seq_sub(tid_agg_rx->head_seq_num, 2433 index = seq_sub(tid_agg_rx->head_seq_num,
2389 tid_agg_rx->ssn) % tid_agg_rx->buf_size; 2434 tid_agg_rx->ssn) % tid_agg_rx->buf_size;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 31a8990ce401..164b16cbe0a5 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -88,6 +88,7 @@ struct tid_ampdu_tx {
88 * struct tid_ampdu_rx - TID aggregation information (Rx). 88 * struct tid_ampdu_rx - TID aggregation information (Rx).
89 * 89 *
90 * @reorder_buf: buffer to reorder incoming aggregated MPDUs 90 * @reorder_buf: buffer to reorder incoming aggregated MPDUs
91 * @reorder_time: jiffies when skb was added
91 * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) 92 * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
92 * @head_seq_num: head sequence number in reordering buffer. 93 * @head_seq_num: head sequence number in reordering buffer.
93 * @stored_mpdu_num: number of MPDUs in reordering buffer 94 * @stored_mpdu_num: number of MPDUs in reordering buffer
@@ -99,6 +100,7 @@ struct tid_ampdu_tx {
99 */ 100 */
100struct tid_ampdu_rx { 101struct tid_ampdu_rx {
101 struct sk_buff **reorder_buf; 102 struct sk_buff **reorder_buf;
103 unsigned long *reorder_time;
102 struct timer_list session_timer; 104 struct timer_list session_timer;
103 u16 head_seq_num; 105 u16 head_seq_num;
104 u16 stored_mpdu_num; 106 u16 stored_mpdu_num;