2 * Copyright (c) 2014 Qualcomm Atheros, Inc.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #define SEQ_MODULO 0x1000
21 #define SEQ_MASK 0xfff
23 static inline int seq_less(u16 sq1
, u16 sq2
)
25 return ((sq1
- sq2
) & SEQ_MASK
) > (SEQ_MODULO
>> 1);
28 static inline u16
seq_inc(u16 sq
)
30 return (sq
+ 1) & SEQ_MASK
;
33 static inline u16
seq_sub(u16 sq1
, u16 sq2
)
35 return (sq1
- sq2
) & SEQ_MASK
;
38 static inline int reorder_index(struct wil_tid_ampdu_rx
*r
, u16 seq
)
40 return seq_sub(seq
, r
->ssn
) % r
->buf_size
;
43 static void wil_release_reorder_frame(struct wil6210_priv
*wil
,
44 struct wil_tid_ampdu_rx
*r
,
47 struct net_device
*ndev
= wil_to_ndev(wil
);
48 struct sk_buff
*skb
= r
->reorder_buf
[index
];
53 /* release the frame from the reorder ring buffer */
55 r
->reorder_buf
[index
] = NULL
;
56 wil_netif_rx_any(skb
, ndev
);
59 r
->head_seq_num
= seq_inc(r
->head_seq_num
);
62 static void wil_release_reorder_frames(struct wil6210_priv
*wil
,
63 struct wil_tid_ampdu_rx
*r
,
68 /* note: this function is never called with
69 * hseq preceding r->head_seq_num, i.e it is always true
70 * !seq_less(hseq, r->head_seq_num)
71 * and thus on loop exit it should be
72 * r->head_seq_num == hseq
74 while (seq_less(r
->head_seq_num
, hseq
) && r
->stored_mpdu_num
) {
75 index
= reorder_index(r
, r
->head_seq_num
);
76 wil_release_reorder_frame(wil
, r
, index
);
78 r
->head_seq_num
= hseq
;
81 static void wil_reorder_release(struct wil6210_priv
*wil
,
82 struct wil_tid_ampdu_rx
*r
)
84 int index
= reorder_index(r
, r
->head_seq_num
);
86 while (r
->reorder_buf
[index
]) {
87 wil_release_reorder_frame(wil
, r
, index
);
88 index
= reorder_index(r
, r
->head_seq_num
);
92 void wil_rx_reorder(struct wil6210_priv
*wil
, struct sk_buff
*skb
)
94 struct net_device
*ndev
= wil_to_ndev(wil
);
95 struct vring_rx_desc
*d
= wil_skb_rxdesc(skb
);
96 int tid
= wil_rxdesc_tid(d
);
97 int cid
= wil_rxdesc_cid(d
);
98 int mid
= wil_rxdesc_mid(d
);
99 u16 seq
= wil_rxdesc_seq(d
);
100 struct wil_sta_info
*sta
= &wil
->sta
[cid
];
101 struct wil_tid_ampdu_rx
*r
;
106 wil_dbg_txrx(wil
, "MID %d CID %d TID %d Seq 0x%03x\n",
109 spin_lock_irqsave(&sta
->tid_rx_lock
, flags
);
111 r
= sta
->tid_rx
[tid
];
113 spin_unlock_irqrestore(&sta
->tid_rx_lock
, flags
);
114 wil_netif_rx_any(skb
, ndev
);
118 hseq
= r
->head_seq_num
;
120 /** Due to the race between WMI events, where BACK establishment
121 * reported, and data Rx, few packets may be pass up before reorder
122 * buffer get allocated. Catch up by pretending SSN is what we
123 * see in the 1-st Rx packet
126 r
->first_time
= false;
127 if (seq
!= r
->head_seq_num
) {
128 wil_err(wil
, "Error: 1-st frame with wrong sequence"
129 " %d, should be %d. Fixing...\n", seq
,
131 r
->head_seq_num
= seq
;
136 /* frame with out of date sequence number */
137 if (seq_less(seq
, r
->head_seq_num
)) {
138 r
->ssn_last_drop
= seq
;
144 * If frame the sequence number exceeds our buffering window
145 * size release some previous frames to make room for this one.
147 if (!seq_less(seq
, r
->head_seq_num
+ r
->buf_size
)) {
148 hseq
= seq_inc(seq_sub(seq
, r
->buf_size
));
149 /* release stored frames up to new head to stack */
150 wil_release_reorder_frames(wil
, r
, hseq
);
153 /* Now the new frame is always in the range of the reordering buffer */
155 index
= reorder_index(r
, seq
);
157 /* check if we already stored this frame */
158 if (r
->reorder_buf
[index
]) {
164 * If the current MPDU is in the right order and nothing else
165 * is stored we can process it directly, no need to buffer it.
166 * If it is first but there's something stored, we may be able
167 * to release frames after this one.
169 if (seq
== r
->head_seq_num
&& r
->stored_mpdu_num
== 0) {
170 r
->head_seq_num
= seq_inc(r
->head_seq_num
);
171 wil_netif_rx_any(skb
, ndev
);
175 /* put the frame in the reordering buffer */
176 r
->reorder_buf
[index
] = skb
;
177 r
->reorder_time
[index
] = jiffies
;
178 r
->stored_mpdu_num
++;
179 wil_reorder_release(wil
, r
);
182 spin_unlock_irqrestore(&sta
->tid_rx_lock
, flags
);
185 struct wil_tid_ampdu_rx
*wil_tid_ampdu_rx_alloc(struct wil6210_priv
*wil
,
188 struct wil_tid_ampdu_rx
*r
= kzalloc(sizeof(*r
), GFP_KERNEL
);
194 kcalloc(size
, sizeof(struct sk_buff
*), GFP_KERNEL
);
196 kcalloc(size
, sizeof(unsigned long), GFP_KERNEL
);
197 if (!r
->reorder_buf
|| !r
->reorder_time
) {
198 kfree(r
->reorder_buf
);
199 kfree(r
->reorder_time
);
205 r
->head_seq_num
= ssn
;
207 r
->stored_mpdu_num
= 0;
208 r
->first_time
= true;
212 void wil_tid_ampdu_rx_free(struct wil6210_priv
*wil
,
213 struct wil_tid_ampdu_rx
*r
)
217 wil_release_reorder_frames(wil
, r
, r
->head_seq_num
+ r
->buf_size
);
218 kfree(r
->reorder_buf
);
219 kfree(r
->reorder_time
);
This page took 0.048527 seconds and 5 git commands to generate.