aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2010-08-04 19:36:04 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-08-16 15:26:39 -0400
commitaa0c86364f925c6f12195072562b18c5609ff082 (patch)
treed32f3bff00334ecc49d74a0ecd4d36c3e7bdd78f /net/mac80211/rx.c
parent6044474ed86484b899d46e040ade3872e83fc9f7 (diff)
mac80211: put rx handlers into separate functions
This patch takes the reorder logic from the RX path and moves it into separate routines to make the expired frame release accessible. Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c214
1 files changed, 128 insertions, 86 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 225e8ee682e3..8301b4a980a2 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -583,6 +583,57 @@ static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw,
583 */ 583 */
584#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) 584#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10)
585 585
586static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
587 struct tid_ampdu_rx *tid_agg_rx,
588 struct sk_buff_head *frames)
589{
590 int index;
591
592 /* release the buffer until next missing frame */
593 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
594 tid_agg_rx->buf_size;
595 if (!tid_agg_rx->reorder_buf[index] &&
596 tid_agg_rx->stored_mpdu_num > 1) {
597 /*
598 * No buffers ready to be released, but check whether any
599 * frames in the reorder buffer have timed out.
600 */
601 int j;
602 int skipped = 1;
603 for (j = (index + 1) % tid_agg_rx->buf_size; j != index;
604 j = (j + 1) % tid_agg_rx->buf_size) {
605 if (!tid_agg_rx->reorder_buf[j]) {
606 skipped++;
607 continue;
608 }
609 if (!time_after(jiffies, tid_agg_rx->reorder_time[j] +
610 HT_RX_REORDER_BUF_TIMEOUT))
611 break;
612
613#ifdef CONFIG_MAC80211_HT_DEBUG
614 if (net_ratelimit())
615 printk(KERN_DEBUG "%s: release an RX reorder "
616 "frame due to timeout on earlier "
617 "frames\n",
618 wiphy_name(hw->wiphy));
619#endif
620 ieee80211_release_reorder_frame(hw, tid_agg_rx,
621 j, frames);
622
623 /*
624 * Increment the head seq# also for the skipped slots.
625 */
626 tid_agg_rx->head_seq_num =
627 (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK;
628 skipped = 0;
629 }
630 } else while (tid_agg_rx->reorder_buf[index]) {
631 ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames);
632 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
633 tid_agg_rx->buf_size;
634 }
635}
636
586/* 637/*
587 * As this function belongs to the RX path it must be under 638 * As this function belongs to the RX path it must be under
588 * rcu_read_lock protection. It returns false if the frame 639 * rcu_read_lock protection. It returns false if the frame
@@ -643,49 +694,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
643 tid_agg_rx->reorder_buf[index] = skb; 694 tid_agg_rx->reorder_buf[index] = skb;
644 tid_agg_rx->reorder_time[index] = jiffies; 695 tid_agg_rx->reorder_time[index] = jiffies;
645 tid_agg_rx->stored_mpdu_num++; 696 tid_agg_rx->stored_mpdu_num++;
646 /* release the buffer until next missing frame */ 697 ieee80211_sta_reorder_release(hw, tid_agg_rx, frames);
647 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
648 tid_agg_rx->buf_size;
649 if (!tid_agg_rx->reorder_buf[index] &&
650 tid_agg_rx->stored_mpdu_num > 1) {
651 /*
652 * No buffers ready to be released, but check whether any
653 * frames in the reorder buffer have timed out.
654 */
655 int j;
656 int skipped = 1;
657 for (j = (index + 1) % tid_agg_rx->buf_size; j != index;
658 j = (j + 1) % tid_agg_rx->buf_size) {
659 if (!tid_agg_rx->reorder_buf[j]) {
660 skipped++;
661 continue;
662 }
663 if (!time_after(jiffies, tid_agg_rx->reorder_time[j] +
664 HT_RX_REORDER_BUF_TIMEOUT))
665 break;
666
667#ifdef CONFIG_MAC80211_HT_DEBUG
668 if (net_ratelimit())
669 printk(KERN_DEBUG "%s: release an RX reorder "
670 "frame due to timeout on earlier "
671 "frames\n",
672 wiphy_name(hw->wiphy));
673#endif
674 ieee80211_release_reorder_frame(hw, tid_agg_rx,
675 j, frames);
676
677 /*
678 * Increment the head seq# also for the skipped slots.
679 */
680 tid_agg_rx->head_seq_num =
681 (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK;
682 skipped = 0;
683 }
684 } else while (tid_agg_rx->reorder_buf[index]) {
685 ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames);
686 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
687 tid_agg_rx->buf_size;
688 }
689 698
690 return true; 699 return true;
691} 700}
@@ -2267,19 +2276,46 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
2267 dev_kfree_skb(skb); 2276 dev_kfree_skb(skb);
2268} 2277}
2269 2278
2270 2279static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx,
2271static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, 2280 ieee80211_rx_result res)
2272 struct ieee80211_rx_data *rx,
2273 struct sk_buff *skb,
2274 struct ieee80211_rate *rate)
2275{ 2281{
2276 struct sk_buff_head reorder_release; 2282 switch (res) {
2277 ieee80211_rx_result res = RX_DROP_MONITOR; 2283 case RX_DROP_MONITOR:
2284 I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop);
2285 if (rx->sta)
2286 rx->sta->rx_dropped++;
2287 /* fall through */
2288 case RX_CONTINUE: {
2289 struct ieee80211_rate *rate = NULL;
2290 struct ieee80211_supported_band *sband;
2291 struct ieee80211_rx_status *status;
2292
2293 status = IEEE80211_SKB_RXCB((rx->skb));
2294
2295 sband = rx->local->hw.wiphy->bands[status->band];
2296 if (!(status->flag & RX_FLAG_HT))
2297 rate = &sband->bitrates[status->rate_idx];
2278 2298
2279 __skb_queue_head_init(&reorder_release); 2299 ieee80211_rx_cooked_monitor(rx, rate);
2300 break;
2301 }
2302 case RX_DROP_UNUSABLE:
2303 I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop);
2304 if (rx->sta)
2305 rx->sta->rx_dropped++;
2306 dev_kfree_skb(rx->skb);
2307 break;
2308 case RX_QUEUED:
2309 I802_DEBUG_INC(rx->sdata->local->rx_handlers_queued);
2310 break;
2311 }
2312}
2280 2313
2281 rx->skb = skb; 2314static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
2282 rx->sdata = sdata; 2315 struct sk_buff_head *frames)
2316{
2317 ieee80211_rx_result res = RX_DROP_MONITOR;
2318 struct sk_buff *skb;
2283 2319
2284#define CALL_RXH(rxh) \ 2320#define CALL_RXH(rxh) \
2285 do { \ 2321 do { \
@@ -2288,17 +2324,7 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
2288 goto rxh_next; \ 2324 goto rxh_next; \
2289 } while (0); 2325 } while (0);
2290 2326
2291 /* 2327 while ((skb = __skb_dequeue(frames))) {
2292 * NB: the rxh_next label works even if we jump
2293 * to it from here because then the list will
2294 * be empty, which is a trivial check
2295 */
2296 CALL_RXH(ieee80211_rx_h_passive_scan)
2297 CALL_RXH(ieee80211_rx_h_check)
2298
2299 ieee80211_rx_reorder_ampdu(rx, &reorder_release);
2300
2301 while ((skb = __skb_dequeue(&reorder_release))) {
2302 /* 2328 /*
2303 * all the other fields are valid across frames 2329 * all the other fields are valid across frames
2304 * that belong to an aMPDU since they are on the 2330 * that belong to an aMPDU since they are on the
@@ -2316,42 +2342,58 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
2316 CALL_RXH(ieee80211_rx_h_remove_qos_control) 2342 CALL_RXH(ieee80211_rx_h_remove_qos_control)
2317 CALL_RXH(ieee80211_rx_h_amsdu) 2343 CALL_RXH(ieee80211_rx_h_amsdu)
2318#ifdef CONFIG_MAC80211_MESH 2344#ifdef CONFIG_MAC80211_MESH
2319 if (ieee80211_vif_is_mesh(&sdata->vif)) 2345 if (ieee80211_vif_is_mesh(&rx->sdata->vif))
2320 CALL_RXH(ieee80211_rx_h_mesh_fwding); 2346 CALL_RXH(ieee80211_rx_h_mesh_fwding);
2321#endif 2347#endif
2322 CALL_RXH(ieee80211_rx_h_data) 2348 CALL_RXH(ieee80211_rx_h_data)
2323 2349
2324 /* special treatment -- needs the queue */ 2350 /* special treatment -- needs the queue */
2325 res = ieee80211_rx_h_ctrl(rx, &reorder_release); 2351 res = ieee80211_rx_h_ctrl(rx, frames);
2326 if (res != RX_CONTINUE) 2352 if (res != RX_CONTINUE)
2327 goto rxh_next; 2353 goto rxh_next;
2328 2354
2329 CALL_RXH(ieee80211_rx_h_action) 2355 CALL_RXH(ieee80211_rx_h_action)
2330 CALL_RXH(ieee80211_rx_h_mgmt) 2356 CALL_RXH(ieee80211_rx_h_mgmt)
2331 2357
2358 rxh_next:
2359 ieee80211_rx_handlers_result(rx, res);
2360
2332#undef CALL_RXH 2361#undef CALL_RXH
2362 }
2363}
2364
2365static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
2366 struct ieee80211_rx_data *rx,
2367 struct sk_buff *skb,
2368 struct ieee80211_rate *rate)
2369{
2370 struct sk_buff_head reorder_release;
2371 ieee80211_rx_result res = RX_DROP_MONITOR;
2372
2373 __skb_queue_head_init(&reorder_release);
2374
2375 rx->skb = skb;
2376 rx->sdata = sdata;
2377
2378#define CALL_RXH(rxh) \
2379 do { \
2380 res = rxh(rx); \
2381 if (res != RX_CONTINUE) \
2382 goto rxh_next; \
2383 } while (0);
2384
2385 CALL_RXH(ieee80211_rx_h_passive_scan)
2386 CALL_RXH(ieee80211_rx_h_check)
2387
2388 ieee80211_rx_reorder_ampdu(rx, &reorder_release);
2389
2390 ieee80211_rx_handlers(rx, &reorder_release);
2391 return;
2333 2392
2334 rxh_next: 2393 rxh_next:
2335 switch (res) { 2394 ieee80211_rx_handlers_result(rx, res);
2336 case RX_DROP_MONITOR: 2395
2337 I802_DEBUG_INC(sdata->local->rx_handlers_drop); 2396#undef CALL_RXH
2338 if (rx->sta)
2339 rx->sta->rx_dropped++;
2340 /* fall through */
2341 case RX_CONTINUE:
2342 ieee80211_rx_cooked_monitor(rx, rate);
2343 break;
2344 case RX_DROP_UNUSABLE:
2345 I802_DEBUG_INC(sdata->local->rx_handlers_drop);
2346 if (rx->sta)
2347 rx->sta->rx_dropped++;
2348 dev_kfree_skb(rx->skb);
2349 break;
2350 case RX_QUEUED:
2351 I802_DEBUG_INC(sdata->local->rx_handlers_queued);
2352 break;
2353 }
2354 }
2355} 2397}
2356 2398
2357/* main receive path */ 2399/* main receive path */