diff options
-rw-r--r-- | net/mac80211/agg-rx.c | 8 | ||||
-rw-r--r-- | net/mac80211/rx.c | 47 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 2 |
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 | */ |
100 | struct tid_ampdu_rx { | 101 | struct 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; |