/* note: this function is never called with *hseqprecedingr->head_seq_num,i.eitisalwaystrue *!seq_less(hseq,r->head_seq_num) *andthusonloopexititshouldbe *r->head_seq_num==hseq
*/ while (seq_less(r->head_seq_num, hseq) && r->stored_mpdu_num) {
index = reorder_index(r, r->head_seq_num);
wil_release_reorder_frame(ndev, r, index);
}
r->head_seq_num = hseq;
}
staticvoid wil_reorder_release(struct net_device *ndev, struct wil_tid_ampdu_rx *r)
{ int index = reorder_index(r, r->head_seq_num);
while (r->reorder_buf[index]) {
wil_release_reorder_frame(ndev, r, index);
index = reorder_index(r, r->head_seq_num);
}
}
/* called in NAPI context */ void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb)
__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
{ struct wil6210_vif *vif; struct net_device *ndev; int tid, cid, mid, mcast, retry;
u16 seq; struct wil_sta_info *sta; struct wil_tid_ampdu_rx *r;
u16 hseq; int index;
/** Due to the race between WMI events, where BACK establishment *reported,anddataRx,fewpacketsmaybepassupbeforereorder *buffergetallocated.CatchupbypretendingSSNiswhatwe *seeinthe1-stRxpacket * *Anotherscenario,Rxgetdelayedandwegotpacketfrombefore *BACK.Passittothestackandwait.
*/ if (r->first_time) {
r->first_time = false; if (seq != r->head_seq_num) { if (seq_less(seq, r->head_seq_num)) {
wil_err(wil, "Error: frame with early sequence 0x%03x, should be 0x%03x. Waiting...\n",
seq, r->head_seq_num);
r->first_time = true;
wil_netif_rx_any(skb, ndev); goto out;
}
wil_err(wil, "Error: 1-st frame with wrong sequence 0x%03x, should be 0x%03x. Fixing...\n",
seq, r->head_seq_num);
r->head_seq_num = seq;
r->ssn = seq;
}
}
/* frame with out of date sequence number */ if (seq_less(seq, r->head_seq_num)) {
r->ssn_last_drop = seq;
r->drop_old++;
wil_dbg_txrx(wil, "Rx drop: old seq 0x%03x head 0x%03x\n",
seq, r->head_seq_num);
dev_kfree_skb(skb); goto out;
}
/* *Ifframethesequencenumberexceedsourbufferingwindow *sizereleasesomepreviousframestomakeroomforthisone.
*/ if (!seq_less(seq, r->head_seq_num + r->buf_size)) {
hseq = seq_inc(seq_sub(seq, r->buf_size)); /* release stored frames up to new head to stack */
wil_release_reorder_frames(ndev, r, hseq);
}
/* Now the new frame is always in the range of the reordering buffer */
index = reorder_index(r, seq);
/* check if we already stored this frame */ if (r->reorder_buf[index]) {
r->drop_dup++;
wil_dbg_txrx(wil, "Rx drop: dup seq 0x%03x\n", seq);
dev_kfree_skb(skb); goto out;
}
void wil_tid_ampdu_rx_free(struct wil6210_priv *wil, struct wil_tid_ampdu_rx *r)
{ int i;
if (!r) return;
/* Do not pass remaining frames to the network stack - it may be *notexpectingtogetanymoreRx.Rxfromheremayleadto *kernelOOPSsincesomeper-socketaccountinginfowasalready *released.
*/ for (i = 0; i < r->buf_size; i++)
kfree_skb(r->reorder_buf[i]);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.