| 832 | } |
| 833 | |
| 834 | static void |
| 835 | ampdu_rx_moveup(struct ieee80211_rx_ampdu *rap, struct ieee80211_node *ni, |
| 836 | int i, int winstart) |
| 837 | { |
| 838 | struct ieee80211vap *vap = ni->ni_vap; |
| 839 | |
| 840 | /* |
| 841 | * If frames remain, copy the mbuf pointers down so |
| 842 | * they correspond to the offsets in the new window. |
| 843 | */ |
| 844 | if (rap->rxa_qframes != 0) { |
| 845 | int n = rap->rxa_qframes, j; |
| 846 | for (j = i+1; j < rap->rxa_wnd; j++) { |
| 847 | /* |
| 848 | * Concat the list contents over, which will |
| 849 | * blank the source list for us. |
| 850 | */ |
| 851 | if (mbufq_len(&rap->rxa_mq[j]) != 0) { |
| 852 | n = n - mbufq_len(&rap->rxa_mq[j]); |
| 853 | mbufq_concat(&rap->rxa_mq[j-i], &rap->rxa_mq[j]); |
| 854 | KASSERT(n >= 0, ("%s: n < 0 (%d)", __func__, n)); |
| 855 | if (n == 0) |
| 856 | break; |
| 857 | } |
| 858 | } |
| 859 | KASSERT(n == 0, ("%s: lost %d frames, qframes %d off %d " |
| 860 | "BA win <%d:%d> winstart %d", |
| 861 | __func__, n, rap->rxa_qframes, i, rap->rxa_start, |
| 862 | IEEE80211_SEQ_ADD(rap->rxa_start, rap->rxa_wnd-1), |
| 863 | winstart)); |
| 864 | vap->iv_stats.is_ampdu_rx_copy += rap->rxa_qframes; |
| 865 | } |
| 866 | } |
| 867 | |
| 868 | /* |
| 869 | * Dispatch as many frames as possible from the re-order queue. |
no test coverage detected