1 /*
2 * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /*-
21 * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
22 * All rights reserved.
23 *
24 * Redistribution and use in source and binary forms, with or without
25 * modification, are permitted provided that the following conditions
26 * are met:
27 * 1. Redistributions of source code must retain the above copyright
28 * notice, this list of conditions and the following disclaimer.
29 * 2. Redistributions in binary form must reproduce the above copyright
30 * notice, this list of conditions and the following disclaimer in the
31 * documentation and/or other materials provided with the distribution.
32 *
33 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
34 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
36 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
37 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
38 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
39 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
40 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
41 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
42 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 */
44 #include <ol_htt_api.h>
45 #include <ol_txrx_api.h>
46 #include <ol_txrx_htt_api.h>
47 #include <ol_htt_rx_api.h>
48 #include <ol_rx_reorder.h>
49 #include <ol_rx_pn.h>
50 #include <ol_rx_fwd.h>
51 #include <ol_rx.h>
52 #include <ol_txrx_internal.h>
53 #include <ol_ctrl_txrx_api.h>
54 #include <ol_txrx_peer_find.h>
55 #include <qdf_nbuf.h>
56 #include <qdf_util.h>
57 #include <athdefs.h>
58 #include <qdf_mem.h>
59 #include <ol_rx_defrag.h>
60 #include <enet.h>
61 #include <qdf_time.h> /* qdf_system_time */
62 #include <wlan_pkt_capture_ucfg_api.h>
63
64 #define DEFRAG_IEEE80211_ADDR_EQ(a1, a2) \
65 (!qdf_mem_cmp(a1, a2, QDF_MAC_ADDR_SIZE))
66
67 #define DEFRAG_IEEE80211_ADDR_COPY(dst, src) \
68 qdf_mem_copy(dst, src, QDF_MAC_ADDR_SIZE)
69
70 #define DEFRAG_IEEE80211_QOS_HAS_SEQ(wh) \
71 (((wh)->i_fc[0] & \
72 (IEEE80211_FC0_TYPE_MASK | QDF_IEEE80211_FC0_SUBTYPE_QOS)) == \
73 (IEEE80211_FC0_TYPE_DATA | QDF_IEEE80211_FC0_SUBTYPE_QOS))
74
75 #define DEFRAG_IEEE80211_QOS_GET_TID(_x) \
76 ((_x)->i_qos[0] & IEEE80211_QOS_TID)
77
78 const struct ol_rx_defrag_cipher f_ccmp = {
79 "AES-CCM",
80 IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_EXTIVLEN,
81 IEEE80211_WEP_MICLEN,
82 0,
83 };
84
85 const struct ol_rx_defrag_cipher f_tkip = {
86 "TKIP",
87 IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_EXTIVLEN,
88 IEEE80211_WEP_CRCLEN,
89 IEEE80211_WEP_MICLEN,
90 };
91
92 const struct ol_rx_defrag_cipher f_wep = {
93 "WEP",
94 IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN,
95 IEEE80211_WEP_CRCLEN,
96 0,
97 };
98
99 const struct ol_rx_defrag_cipher f_gcmp = {
100 "AES-GCMP",
101 WLAN_IEEE80211_GCMP_HEADERLEN,
102 WLAN_IEEE80211_GCMP_MICLEN,
103 WLAN_IEEE80211_GCMP_MICLEN,
104 };
105
106 #if defined(CONFIG_HL_SUPPORT)
107
108 /**
109 * ol_rx_frag_get_mac_hdr() - retrieve mac header
110 * @htt_pdev: pointer to htt pdev handle
111 * @frag: rx fragment
112 *
113 * Return: pointer to ieee mac header of frag
114 */
ol_rx_frag_get_mac_hdr(htt_pdev_handle htt_pdev,qdf_nbuf_t frag)115 static struct ieee80211_frame *ol_rx_frag_get_mac_hdr(
116 htt_pdev_handle htt_pdev, qdf_nbuf_t frag)
117 {
118 void *rx_desc;
119 int rx_desc_len;
120
121 rx_desc = htt_rx_msdu_desc_retrieve(htt_pdev, frag);
122 rx_desc_len = htt_rx_msdu_rx_desc_size_hl(htt_pdev, rx_desc);
123 return (struct ieee80211_frame *)(qdf_nbuf_data(frag) + rx_desc_len);
124 }
125
126 /**
127 * ol_rx_frag_pull_hdr() - point to payload of rx frag
128 * @htt_pdev: pointer to htt pdev handle
129 * @frag: rx fragment
130 * @hdrsize: header size
131 *
132 * Return: None
133 */
ol_rx_frag_pull_hdr(htt_pdev_handle htt_pdev,qdf_nbuf_t frag,int hdrsize)134 static void ol_rx_frag_pull_hdr(htt_pdev_handle htt_pdev,
135 qdf_nbuf_t frag, int hdrsize)
136 {
137 void *rx_desc;
138 int rx_desc_len;
139
140 rx_desc = htt_rx_msdu_desc_retrieve(htt_pdev, frag);
141 rx_desc_len = htt_rx_msdu_rx_desc_size_hl(htt_pdev, rx_desc);
142 qdf_nbuf_pull_head(frag, rx_desc_len + hdrsize);
143 }
144
145 /**
146 * ol_rx_frag_desc_adjust() - adjust rx frag descriptor position
147 * @pdev: pointer to txrx handle
148 * @msdu: msdu
149 * @rx_desc_old_position: rx descriptor old position
150 * @ind_old_position:index of old position
151 * @rx_desc_len: rx descriptor length
152 *
153 * Return: None
154 */
155 static void
ol_rx_frag_desc_adjust(ol_txrx_pdev_handle pdev,qdf_nbuf_t msdu,void ** rx_desc_old_position,void ** ind_old_position,int * rx_desc_len)156 ol_rx_frag_desc_adjust(ol_txrx_pdev_handle pdev,
157 qdf_nbuf_t msdu,
158 void **rx_desc_old_position,
159 void **ind_old_position, int *rx_desc_len)
160 {
161 *rx_desc_old_position = htt_rx_msdu_desc_retrieve(pdev->htt_pdev,
162 msdu);
163 *ind_old_position = *rx_desc_old_position - HTT_RX_IND_HL_BYTES;
164 *rx_desc_len = htt_rx_msdu_rx_desc_size_hl(pdev->htt_pdev,
165 *rx_desc_old_position);
166 }
167
168 /**
169 * ol_rx_frag_restructure() - point to payload for HL
170 * @pdev: physical device object
171 * @msdu: the buffer containing the MSDU payload
172 * @rx_desc_old_position: rx MSDU descriptor
173 * @ind_old_position: rx msdu indication
174 * @f_type: pointing to rx defrag cipher
175 * @rx_desc_len: length by which rx descriptor to move
176 *
177 * Return: None
178 */
179 static void
ol_rx_frag_restructure(ol_txrx_pdev_handle pdev,qdf_nbuf_t msdu,void * rx_desc_old_position,void * ind_old_position,const struct ol_rx_defrag_cipher * f_type,int rx_desc_len)180 ol_rx_frag_restructure(
181 ol_txrx_pdev_handle pdev,
182 qdf_nbuf_t msdu,
183 void *rx_desc_old_position,
184 void *ind_old_position,
185 const struct ol_rx_defrag_cipher *f_type,
186 int rx_desc_len)
187 {
188 if ((!ind_old_position) || (!rx_desc_old_position)) {
189 ol_txrx_err("ind_old_position,rx_desc_old_position is NULL");
190 ASSERT(0);
191 return;
192 }
193 /* move rx description*/
194 qdf_mem_move(rx_desc_old_position + f_type->ic_header,
195 rx_desc_old_position, rx_desc_len);
196 /* move rx indication*/
197 qdf_mem_move(ind_old_position + f_type->ic_header, ind_old_position,
198 HTT_RX_IND_HL_BYTES);
199 }
200
201 /**
202 * ol_rx_get_desc_len() - point to payload for HL
203 * @htt_pdev: the HTT instance the rx data was received on
204 * @wbuf: buffer containing the MSDU payload
205 * @rx_desc_old_position: rx MSDU descriptor
206 *
207 * Return: Return the HL rx desc size
208 */
209 static
ol_rx_get_desc_len(htt_pdev_handle htt_pdev,qdf_nbuf_t wbuf,void ** rx_desc_old_position)210 int ol_rx_get_desc_len(htt_pdev_handle htt_pdev,
211 qdf_nbuf_t wbuf,
212 void **rx_desc_old_position)
213 {
214 int rx_desc_len = 0;
215 *rx_desc_old_position = htt_rx_msdu_desc_retrieve(htt_pdev, wbuf);
216 rx_desc_len = htt_rx_msdu_rx_desc_size_hl(htt_pdev,
217 *rx_desc_old_position);
218
219 return rx_desc_len;
220 }
221
222 /**
223 * ol_rx_defrag_push_rx_desc() - point to payload for HL
224 * @nbuf: buffer containing the MSDU payload
225 * @rx_desc_old_position: rx MSDU descriptor
226 * @ind_old_position: rx msdu indication
227 * @rx_desc_len: HL rx desc size
228 *
229 * Return: Return the HL rx desc size
230 */
231 static
ol_rx_defrag_push_rx_desc(qdf_nbuf_t nbuf,void * rx_desc_old_position,void * ind_old_position,int rx_desc_len)232 void ol_rx_defrag_push_rx_desc(qdf_nbuf_t nbuf,
233 void *rx_desc_old_position,
234 void *ind_old_position,
235 int rx_desc_len)
236 {
237 qdf_nbuf_push_head(nbuf, rx_desc_len);
238 qdf_mem_move(
239 qdf_nbuf_data(nbuf), rx_desc_old_position, rx_desc_len);
240 qdf_mem_move(
241 qdf_nbuf_data(nbuf) - HTT_RX_IND_HL_BYTES, ind_old_position,
242 HTT_RX_IND_HL_BYTES);
243 }
244 #else
245
ol_rx_frag_get_mac_hdr(htt_pdev_handle htt_pdev,qdf_nbuf_t frag)246 static inline struct ieee80211_frame *ol_rx_frag_get_mac_hdr(
247 htt_pdev_handle htt_pdev,
248 qdf_nbuf_t frag)
249 {
250 return
251 (struct ieee80211_frame *) qdf_nbuf_data(frag);
252 }
253
ol_rx_frag_pull_hdr(htt_pdev_handle htt_pdev,qdf_nbuf_t frag,int hdrsize)254 static inline void ol_rx_frag_pull_hdr(htt_pdev_handle htt_pdev,
255 qdf_nbuf_t frag, int hdrsize)
256 {
257 qdf_nbuf_pull_head(frag, hdrsize);
258 }
259
260 static inline void
ol_rx_frag_desc_adjust(ol_txrx_pdev_handle pdev,qdf_nbuf_t msdu,void ** rx_desc_old_position,void ** ind_old_position,int * rx_desc_len)261 ol_rx_frag_desc_adjust(ol_txrx_pdev_handle pdev,
262 qdf_nbuf_t msdu,
263 void **rx_desc_old_position,
264 void **ind_old_position, int *rx_desc_len)
265 {
266 *rx_desc_old_position = NULL;
267 *ind_old_position = NULL;
268 *rx_desc_len = 0;
269 }
270
271 static inline void
ol_rx_frag_restructure(ol_txrx_pdev_handle pdev,qdf_nbuf_t msdu,void * rx_desc_old_position,void * ind_old_position,const struct ol_rx_defrag_cipher * f_type,int rx_desc_len)272 ol_rx_frag_restructure(
273 ol_txrx_pdev_handle pdev,
274 qdf_nbuf_t msdu,
275 void *rx_desc_old_position,
276 void *ind_old_position,
277 const struct ol_rx_defrag_cipher *f_type,
278 int rx_desc_len)
279 {
280 /* no op */
281 }
282
283 static inline
ol_rx_get_desc_len(htt_pdev_handle htt_pdev,qdf_nbuf_t wbuf,void ** rx_desc_old_position)284 int ol_rx_get_desc_len(htt_pdev_handle htt_pdev,
285 qdf_nbuf_t wbuf,
286 void **rx_desc_old_position)
287 {
288 return 0;
289 }
290
291 static inline
ol_rx_defrag_push_rx_desc(qdf_nbuf_t nbuf,void * rx_desc_old_position,void * ind_old_position,int rx_desc_len)292 void ol_rx_defrag_push_rx_desc(qdf_nbuf_t nbuf,
293 void *rx_desc_old_position,
294 void *ind_old_position,
295 int rx_desc_len)
296 {
297 return;
298 }
299 #endif /* CONFIG_HL_SUPPORT */
300
301 /*
302 * Process incoming fragments
303 */
304 void
ol_rx_frag_indication_handler(ol_txrx_pdev_handle pdev,qdf_nbuf_t rx_frag_ind_msg,uint16_t peer_id,uint8_t tid)305 ol_rx_frag_indication_handler(ol_txrx_pdev_handle pdev,
306 qdf_nbuf_t rx_frag_ind_msg,
307 uint16_t peer_id, uint8_t tid)
308 {
309 uint16_t seq_num;
310 uint16_t seq_num_start, seq_num_end;
311 struct ol_txrx_peer_t *peer;
312 htt_pdev_handle htt_pdev;
313 qdf_nbuf_t head_msdu, tail_msdu;
314 void *rx_mpdu_desc;
315 uint8_t pktlog_bit;
316 uint32_t msdu_count = 0;
317 int ret;
318 void *rx_desc;
319
320 if (tid >= OL_TXRX_NUM_EXT_TIDS) {
321 ol_txrx_err("Invalid tid: %u", tid);
322 return;
323 }
324
325 htt_pdev = pdev->htt_pdev;
326 peer = ol_txrx_peer_find_by_id(pdev, peer_id);
327
328 if (!ol_cfg_is_full_reorder_offload(pdev->ctrl_pdev) &&
329 htt_rx_ind_flush(pdev->htt_pdev, rx_frag_ind_msg) && peer) {
330 htt_rx_frag_ind_flush_seq_num_range(pdev->htt_pdev,
331 rx_frag_ind_msg,
332 &seq_num_start,
333 &seq_num_end);
334 /*
335 * Assuming flush indication for frags sent from target is
336 * separate from normal frames
337 */
338 ol_rx_reorder_flush_frag(htt_pdev, peer, tid, seq_num_start);
339 } else {
340 uint32_t *msg_word;
341 uint8_t *rx_ind_data;
342
343 rx_ind_data = qdf_nbuf_data(rx_frag_ind_msg);
344 msg_word = (uint32_t *)rx_ind_data;
345 msdu_count = HTT_RX_IN_ORD_PADDR_IND_MSDU_CNT_GET(*(msg_word +
346 1));
347 }
348
349 pktlog_bit =
350 (htt_rx_amsdu_rx_in_order_get_pktlog(rx_frag_ind_msg) == 0x01);
351 ret = htt_rx_frag_pop(htt_pdev, rx_frag_ind_msg, &head_msdu,
352 &tail_msdu, &msdu_count);
353 /* Return if msdu pop fails from rx hash table, as recovery
354 * is triggered and we exit gracefully.
355 */
356 if (!ret)
357 return;
358 if (peer) {
359 qdf_assert(head_msdu == tail_msdu);
360 if (ol_cfg_is_full_reorder_offload(pdev->ctrl_pdev)) {
361 rx_mpdu_desc =
362 htt_rx_mpdu_desc_list_next(htt_pdev, head_msdu);
363 } else {
364 rx_mpdu_desc =
365 htt_rx_mpdu_desc_list_next(htt_pdev,
366 rx_frag_ind_msg);
367 }
368 seq_num = htt_rx_mpdu_desc_seq_num(htt_pdev,
369 rx_mpdu_desc, true);
370 OL_RX_ERR_STATISTICS_1(pdev, peer->vdev, peer, rx_mpdu_desc,
371 OL_RX_ERR_NONE_FRAG);
372 ol_rx_send_pktlog_event(pdev, peer, head_msdu, pktlog_bit);
373 rx_desc = htt_rx_msdu_desc_retrieve(pdev->htt_pdev, head_msdu);
374 ol_rx_timestamp(pdev->ctrl_pdev, rx_desc, head_msdu);
375 ol_rx_reorder_store_frag(pdev, peer, tid, seq_num, head_msdu);
376 } else {
377 /* invalid frame - discard it */
378 if (ol_cfg_is_full_reorder_offload(pdev->ctrl_pdev))
379 htt_rx_msdu_desc_retrieve(htt_pdev, head_msdu);
380 else
381 htt_rx_mpdu_desc_list_next(htt_pdev, rx_frag_ind_msg);
382
383 ol_rx_send_pktlog_event(pdev, peer, head_msdu, pktlog_bit);
384 htt_rx_desc_frame_free(htt_pdev, head_msdu);
385 }
386 /* request HTT to provide new rx MSDU buffers for the target to fill. */
387 if (ol_cfg_is_full_reorder_offload(pdev->ctrl_pdev) &&
388 !pdev->cfg.is_high_latency)
389 htt_rx_msdu_buff_in_order_replenish(htt_pdev, msdu_count);
390 else
391 htt_rx_msdu_buff_replenish(htt_pdev);
392 }
393
394 /*
395 * Flushing fragments
396 */
397 void
ol_rx_reorder_flush_frag(htt_pdev_handle htt_pdev,struct ol_txrx_peer_t * peer,unsigned int tid,uint16_t seq_num)398 ol_rx_reorder_flush_frag(htt_pdev_handle htt_pdev,
399 struct ol_txrx_peer_t *peer,
400 unsigned int tid, uint16_t seq_num)
401 {
402 struct ol_rx_reorder_array_elem_t *rx_reorder_array_elem;
403 int seq;
404
405 seq = seq_num & peer->tids_rx_reorder[tid].win_sz_mask;
406 rx_reorder_array_elem = &peer->tids_rx_reorder[tid].array[seq];
407 if (rx_reorder_array_elem->head) {
408 ol_rx_frames_free(htt_pdev, rx_reorder_array_elem->head);
409 rx_reorder_array_elem->head = NULL;
410 rx_reorder_array_elem->tail = NULL;
411 }
412 }
413
414 /*
415 * Reorder and store fragments
416 */
417 void
ol_rx_reorder_store_frag(ol_txrx_pdev_handle pdev,struct ol_txrx_peer_t * peer,unsigned int tid,uint16_t seq_num,qdf_nbuf_t frag)418 ol_rx_reorder_store_frag(ol_txrx_pdev_handle pdev,
419 struct ol_txrx_peer_t *peer,
420 unsigned int tid, uint16_t seq_num, qdf_nbuf_t frag)
421 {
422 struct ieee80211_frame *fmac_hdr, *mac_hdr;
423 uint8_t fragno, more_frag, all_frag_present = 0;
424 struct ol_rx_reorder_array_elem_t *rx_reorder_array_elem;
425 uint16_t frxseq, rxseq, seq;
426 htt_pdev_handle htt_pdev = pdev->htt_pdev;
427 void *rx_desc;
428 uint8_t index;
429
430 seq = seq_num & peer->tids_rx_reorder[tid].win_sz_mask;
431 qdf_assert(seq == 0);
432 rx_reorder_array_elem = &peer->tids_rx_reorder[tid].array[seq];
433
434 mac_hdr = (struct ieee80211_frame *)
435 ol_rx_frag_get_mac_hdr(htt_pdev, frag);
436 rxseq = qdf_le16_to_cpu(*(uint16_t *) mac_hdr->i_seq) >>
437 IEEE80211_SEQ_SEQ_SHIFT;
438 fragno = qdf_le16_to_cpu(*(uint16_t *) mac_hdr->i_seq) &
439 IEEE80211_SEQ_FRAG_MASK;
440 more_frag = mac_hdr->i_fc[1] & IEEE80211_FC1_MORE_FRAG;
441
442 rx_desc = htt_rx_msdu_desc_retrieve(htt_pdev, frag);
443 qdf_assert(htt_rx_msdu_has_wlan_mcast_flag(htt_pdev, rx_desc));
444 index = htt_rx_msdu_is_wlan_mcast(htt_pdev, rx_desc) ?
445 txrx_sec_mcast : txrx_sec_ucast;
446
447 /*
448 * Multicast/Broadcast frames should not be fragmented so drop
449 * such frames.
450 */
451 if (index != txrx_sec_ucast) {
452 ol_rx_frames_free(htt_pdev, frag);
453 return;
454 }
455
456 if (peer->security[index].sec_type != htt_sec_type_none &&
457 !htt_rx_mpdu_is_encrypted(htt_pdev, rx_desc)) {
458 ol_txrx_err("Unencrypted fragment received in security mode %d",
459 peer->security[index].sec_type);
460 ol_rx_frames_free(htt_pdev, frag);
461 return;
462 }
463
464 if ((!more_frag) && (!fragno) && (!rx_reorder_array_elem->head)) {
465 rx_reorder_array_elem->head = frag;
466 rx_reorder_array_elem->tail = frag;
467 qdf_nbuf_set_next(frag, NULL);
468 ol_rx_defrag(pdev, peer, tid, rx_reorder_array_elem->head);
469 rx_reorder_array_elem->head = NULL;
470 rx_reorder_array_elem->tail = NULL;
471 return;
472 }
473 if (rx_reorder_array_elem->head) {
474 fmac_hdr = (struct ieee80211_frame *)
475 ol_rx_frag_get_mac_hdr(htt_pdev,
476 rx_reorder_array_elem->head);
477 frxseq = qdf_le16_to_cpu(*(uint16_t *) fmac_hdr->i_seq) >>
478 IEEE80211_SEQ_SEQ_SHIFT;
479 if (rxseq != frxseq
480 || !DEFRAG_IEEE80211_ADDR_EQ(mac_hdr->i_addr1,
481 fmac_hdr->i_addr1)
482 || !DEFRAG_IEEE80211_ADDR_EQ(mac_hdr->i_addr2,
483 fmac_hdr->i_addr2)) {
484 ol_rx_frames_free(htt_pdev,
485 rx_reorder_array_elem->head);
486 rx_reorder_array_elem->head = NULL;
487 rx_reorder_array_elem->tail = NULL;
488 ol_txrx_err("ol_rx_reorder_store:%s mismatch",
489 (rxseq == frxseq)
490 ? "address"
491 : "seq number");
492 }
493 }
494
495 ol_rx_fraglist_insert(htt_pdev, &rx_reorder_array_elem->head,
496 &rx_reorder_array_elem->tail, frag,
497 &all_frag_present);
498
499 if (pdev->rx.flags.defrag_timeout_check)
500 ol_rx_defrag_waitlist_remove(peer, tid);
501
502 if (all_frag_present) {
503 ol_rx_defrag(pdev, peer, tid, rx_reorder_array_elem->head);
504 rx_reorder_array_elem->head = NULL;
505 rx_reorder_array_elem->tail = NULL;
506 peer->tids_rx_reorder[tid].defrag_timeout_ms = 0;
507 peer->tids_last_seq[tid] = seq_num;
508 } else if (pdev->rx.flags.defrag_timeout_check) {
509 uint32_t now_ms = qdf_system_ticks_to_msecs(qdf_system_ticks());
510
511 peer->tids_rx_reorder[tid].defrag_timeout_ms =
512 now_ms + pdev->rx.defrag.timeout_ms;
513 ol_rx_defrag_waitlist_add(peer, tid);
514 }
515 }
516
517 /*
518 * Insert and store fragments
519 */
520 void
ol_rx_fraglist_insert(htt_pdev_handle htt_pdev,qdf_nbuf_t * head_addr,qdf_nbuf_t * tail_addr,qdf_nbuf_t frag,uint8_t * all_frag_present)521 ol_rx_fraglist_insert(htt_pdev_handle htt_pdev,
522 qdf_nbuf_t *head_addr,
523 qdf_nbuf_t *tail_addr,
524 qdf_nbuf_t frag, uint8_t *all_frag_present)
525 {
526 qdf_nbuf_t next, prev = NULL, cur = *head_addr;
527 struct ieee80211_frame *mac_hdr, *cmac_hdr, *next_hdr, *lmac_hdr;
528 uint8_t fragno, cur_fragno, lfragno, next_fragno;
529 uint8_t last_morefrag = 1, count = 0;
530
531 qdf_assert(frag);
532
533 mac_hdr = (struct ieee80211_frame *)
534 ol_rx_frag_get_mac_hdr(htt_pdev, frag);
535 fragno = qdf_le16_to_cpu(*(uint16_t *) mac_hdr->i_seq) &
536 IEEE80211_SEQ_FRAG_MASK;
537
538 if (!(*head_addr)) {
539 *head_addr = frag;
540 *tail_addr = frag;
541 qdf_nbuf_set_next(*tail_addr, NULL);
542 return;
543 }
544 /* For efficiency, compare with tail first */
545 lmac_hdr = (struct ieee80211_frame *)
546 ol_rx_frag_get_mac_hdr(htt_pdev, *tail_addr);
547 lfragno = qdf_le16_to_cpu(*(uint16_t *) lmac_hdr->i_seq) &
548 IEEE80211_SEQ_FRAG_MASK;
549 if (fragno > lfragno) {
550 qdf_nbuf_set_next(*tail_addr, frag);
551 *tail_addr = frag;
552 qdf_nbuf_set_next(*tail_addr, NULL);
553 } else {
554 do {
555 cmac_hdr = (struct ieee80211_frame *)
556 ol_rx_frag_get_mac_hdr(htt_pdev, cur);
557 cur_fragno =
558 qdf_le16_to_cpu(*(uint16_t *) cmac_hdr->i_seq) &
559 IEEE80211_SEQ_FRAG_MASK;
560 prev = cur;
561 cur = qdf_nbuf_next(cur);
562 } while (fragno > cur_fragno);
563
564 if (fragno == cur_fragno) {
565 htt_rx_desc_frame_free(htt_pdev, frag);
566 *all_frag_present = 0;
567 return;
568 }
569
570 qdf_nbuf_set_next(prev, frag);
571 qdf_nbuf_set_next(frag, cur);
572 }
573 next = qdf_nbuf_next(*head_addr);
574 lmac_hdr = (struct ieee80211_frame *)ol_rx_frag_get_mac_hdr(htt_pdev,
575 *tail_addr);
576 last_morefrag = lmac_hdr->i_fc[1] & IEEE80211_FC1_MORE_FRAG;
577 if (!last_morefrag) {
578 do {
579 next_hdr =
580 (struct ieee80211_frame *)
581 ol_rx_frag_get_mac_hdr(htt_pdev, next);
582 next_fragno =
583 qdf_le16_to_cpu(*(uint16_t *) next_hdr->i_seq) &
584 IEEE80211_SEQ_FRAG_MASK;
585 count++;
586 if (next_fragno != count)
587 break;
588
589 next = qdf_nbuf_next(next);
590 } while (next);
591
592 if (!next) {
593 *all_frag_present = 1;
594 return;
595 }
596 }
597 *all_frag_present = 0;
598 }
599
600 /*
601 * add tid to pending fragment wait list
602 */
ol_rx_defrag_waitlist_add(struct ol_txrx_peer_t * peer,unsigned int tid)603 void ol_rx_defrag_waitlist_add(struct ol_txrx_peer_t *peer, unsigned int tid)
604 {
605 struct ol_txrx_pdev_t *pdev = peer->vdev->pdev;
606 struct ol_rx_reorder_t *rx_reorder = &peer->tids_rx_reorder[tid];
607
608 TAILQ_INSERT_TAIL(&pdev->rx.defrag.waitlist, rx_reorder,
609 defrag_waitlist_elem);
610 }
611
612 /*
613 * remove tid from pending fragment wait list
614 */
ol_rx_defrag_waitlist_remove(struct ol_txrx_peer_t * peer,unsigned int tid)615 void ol_rx_defrag_waitlist_remove(struct ol_txrx_peer_t *peer, unsigned int tid)
616 {
617 struct ol_txrx_pdev_t *pdev = peer->vdev->pdev;
618 struct ol_rx_reorder_t *rx_reorder = &peer->tids_rx_reorder[tid];
619
620 if (rx_reorder->defrag_waitlist_elem.tqe_next) {
621
622 TAILQ_REMOVE(&pdev->rx.defrag.waitlist, rx_reorder,
623 defrag_waitlist_elem);
624
625 rx_reorder->defrag_waitlist_elem.tqe_next = NULL;
626 rx_reorder->defrag_waitlist_elem.tqe_prev = NULL;
627 } else if (rx_reorder->defrag_waitlist_elem.tqe_next) {
628 ol_txrx_alert("waitlist->tqe_prv = NULL");
629 QDF_ASSERT(0);
630 rx_reorder->defrag_waitlist_elem.tqe_next = NULL;
631 }
632 }
633
634 #ifndef container_of
635 #define container_of(ptr, type, member) \
636 ((type *)((char *)(ptr) - (char *)(&((type *)0)->member)))
637 #endif
638
639 /*
640 * flush stale fragments from the waitlist
641 */
ol_rx_defrag_waitlist_flush(struct ol_txrx_pdev_t * pdev)642 void ol_rx_defrag_waitlist_flush(struct ol_txrx_pdev_t *pdev)
643 {
644 struct ol_rx_reorder_t *rx_reorder, *tmp;
645 uint32_t now_ms = qdf_system_ticks_to_msecs(qdf_system_ticks());
646
647 TAILQ_FOREACH_SAFE(rx_reorder, &pdev->rx.defrag.waitlist,
648 defrag_waitlist_elem, tmp) {
649 struct ol_txrx_peer_t *peer;
650 struct ol_rx_reorder_t *rx_reorder_base;
651 unsigned int tid;
652
653 if (rx_reorder->defrag_timeout_ms > now_ms)
654 break;
655
656 tid = rx_reorder->tid;
657 if (tid >= OL_TXRX_NUM_EXT_TIDS) {
658 ol_txrx_err("Invalid tid: %u", tid);
659 WARN_ON(1);
660 continue;
661 }
662 /* get index 0 of the rx_reorder array */
663 rx_reorder_base = rx_reorder - tid;
664 peer =
665 container_of(rx_reorder_base, struct ol_txrx_peer_t,
666 tids_rx_reorder[0]);
667
668 ol_rx_defrag_waitlist_remove(peer, tid);
669 ol_rx_reorder_flush_frag(pdev->htt_pdev, peer, tid,
670 0 /* frags always stored at seq 0 */);
671 }
672 }
673
674 /**
675 * ol_rx_frag_gcmp_decap() - Remove GCMP header from fragment
676 * @pdev : data path pdev handle
677 * @nbuf : network buffer
678 * @hdrlen : MAC header len
679 *
680 * Return: OL_RX_DEFRAG_OK on success else failure code
681 */
682 static int
ol_rx_frag_gcmp_decap(ol_txrx_pdev_handle pdev,qdf_nbuf_t nbuf,uint16_t hdrlen)683 ol_rx_frag_gcmp_decap(ol_txrx_pdev_handle pdev,
684 qdf_nbuf_t nbuf, uint16_t hdrlen)
685 {
686 uint8_t *ivp, *orig_hdr;
687 void *rx_desc_old_position = NULL;
688 void *ind_old_position = NULL;
689 int rx_desc_len = 0;
690
691 ol_rx_frag_desc_adjust(pdev,
692 nbuf,
693 &rx_desc_old_position,
694 &ind_old_position, &rx_desc_len);
695
696 orig_hdr = (uint8_t *)(qdf_nbuf_data(nbuf) + rx_desc_len);
697 ivp = orig_hdr + hdrlen;
698 if (!(ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV))
699 return OL_RX_DEFRAG_ERR;
700
701 qdf_mem_move(orig_hdr + f_gcmp.ic_header, orig_hdr, hdrlen);
702 ol_rx_frag_restructure(
703 pdev,
704 nbuf,
705 rx_desc_old_position,
706 ind_old_position,
707 &f_gcmp,
708 rx_desc_len);
709 qdf_nbuf_pull_head(nbuf, f_gcmp.ic_header);
710
711 return OL_RX_DEFRAG_OK;
712 }
713
714 /**
715 * ol_rx_frag_gcmp_demic() - Remove MIC info from GCMP fragment
716 * @pdev : data path pdev handle
717 * @nbuf : network buffer
718 * @hdrlen : MAC header len
719 *
720 * Return: OL_RX_DEFRAG_OK on success else failure code
721 */
722 static int
ol_rx_frag_gcmp_demic(ol_txrx_pdev_handle pdev,qdf_nbuf_t wbuf,uint16_t hdrlen)723 ol_rx_frag_gcmp_demic(ol_txrx_pdev_handle pdev,
724 qdf_nbuf_t wbuf, uint16_t hdrlen)
725 {
726 uint8_t *ivp, *orig_hdr;
727 void *rx_desc_old_position = NULL;
728 void *ind_old_position = NULL;
729 int rx_desc_len = 0;
730
731 ol_rx_frag_desc_adjust(pdev,
732 wbuf,
733 &rx_desc_old_position,
734 &ind_old_position, &rx_desc_len);
735
736 orig_hdr = (uint8_t *)(qdf_nbuf_data(wbuf) + rx_desc_len);
737
738 ivp = orig_hdr + hdrlen;
739 if (!(ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV))
740 return OL_RX_DEFRAG_ERR;
741
742 qdf_nbuf_trim_tail(wbuf, f_gcmp.ic_trailer);
743
744 return OL_RX_DEFRAG_OK;
745 }
746
747 /*
748 * Handling security checking and processing fragments
749 */
750 void
ol_rx_defrag(ol_txrx_pdev_handle pdev,struct ol_txrx_peer_t * peer,unsigned int tid,qdf_nbuf_t frag_list)751 ol_rx_defrag(ol_txrx_pdev_handle pdev,
752 struct ol_txrx_peer_t *peer, unsigned int tid,
753 qdf_nbuf_t frag_list)
754 {
755 struct ol_txrx_vdev_t *vdev = NULL;
756 qdf_nbuf_t tmp_next, msdu, prev = NULL, cur = frag_list;
757 uint8_t index, tkip_demic = 0;
758 uint16_t hdr_space;
759 void *rx_desc;
760 struct ieee80211_frame *wh;
761 uint8_t key[DEFRAG_IEEE80211_KEY_LEN];
762 htt_pdev_handle htt_pdev = pdev->htt_pdev;
763 struct ol_txrx_peer_t *peer_head = NULL;
764 uint8_t bssid[QDF_MAC_ADDR_SIZE];
765 struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
766
767 if (qdf_unlikely(!soc))
768 return;
769
770 vdev = peer->vdev;
771
772 /* bypass defrag for safe mode */
773 if (vdev->safemode) {
774 if (ol_cfg_is_full_reorder_offload(pdev->ctrl_pdev))
775 ol_rx_in_order_deliver(vdev, peer, tid, frag_list);
776 else
777 ol_rx_deliver(vdev, peer, tid, frag_list);
778 return;
779 }
780
781 while (cur) {
782 tmp_next = qdf_nbuf_next(cur);
783 qdf_nbuf_set_next(cur, NULL);
784 /*
785 * Strict PN check between the first fragment of the current
786 * frame and the last fragment of the previous frame is not
787 * necessary.
788 */
789 if (!ol_rx_pn_check_base(vdev, peer, tid, cur,
790 (cur == frag_list) ? false : true)) {
791 /* PN check failed,discard frags */
792 if (prev) {
793 qdf_nbuf_set_next(prev, NULL);
794 ol_rx_frames_free(htt_pdev, frag_list);
795 }
796 ol_rx_frames_free(htt_pdev, tmp_next);
797 ol_txrx_err("PN Check failed");
798 return;
799 }
800 /* remove FCS from each fragment */
801 qdf_nbuf_trim_tail(cur, DEFRAG_IEEE80211_FCS_LEN);
802 prev = cur;
803 qdf_nbuf_set_next(cur, tmp_next);
804 cur = tmp_next;
805 }
806 cur = frag_list;
807 wh = (struct ieee80211_frame *)ol_rx_frag_get_mac_hdr(htt_pdev, cur);
808 hdr_space = ol_rx_frag_hdrsize(wh);
809 rx_desc = htt_rx_msdu_desc_retrieve(htt_pdev, frag_list);
810 qdf_assert(htt_rx_msdu_has_wlan_mcast_flag(htt_pdev, rx_desc));
811 index = htt_rx_msdu_is_wlan_mcast(htt_pdev, rx_desc) ?
812 txrx_sec_mcast : txrx_sec_ucast;
813
814 switch (peer->security[index].sec_type) {
815 case htt_sec_type_tkip:
816 tkip_demic = 1;
817 fallthrough;
818 /* fall-through to rest of tkip ops */
819 case htt_sec_type_tkip_nomic:
820 while (cur) {
821 tmp_next = qdf_nbuf_next(cur);
822 if (!ol_rx_frag_tkip_decap(pdev, cur, hdr_space)) {
823 /* TKIP decap failed, discard frags */
824 ol_rx_frames_free(htt_pdev, frag_list);
825 ol_txrx_err("TKIP decap failed");
826 return;
827 }
828 cur = tmp_next;
829 }
830 break;
831
832 case htt_sec_type_aes_ccmp:
833 while (cur) {
834 tmp_next = qdf_nbuf_next(cur);
835 if (!ol_rx_frag_ccmp_demic(pdev, cur, hdr_space)) {
836 /* CCMP demic failed, discard frags */
837 ol_rx_frames_free(htt_pdev, frag_list);
838 ol_txrx_err("CCMP demic failed");
839 return;
840 }
841 if (!ol_rx_frag_ccmp_decap(pdev, cur, hdr_space)) {
842 /* CCMP decap failed, discard frags */
843 ol_rx_frames_free(htt_pdev, frag_list);
844 ol_txrx_err("CCMP decap failed");
845 return;
846 }
847 cur = tmp_next;
848 }
849 break;
850
851 case htt_sec_type_wep40:
852 case htt_sec_type_wep104:
853 case htt_sec_type_wep128:
854 while (cur) {
855 tmp_next = qdf_nbuf_next(cur);
856 if (!ol_rx_frag_wep_decap(pdev, cur, hdr_space)) {
857 /* wep decap failed, discard frags */
858 ol_rx_frames_free(htt_pdev, frag_list);
859 ol_txrx_err("wep decap failed");
860 return;
861 }
862 cur = tmp_next;
863 }
864 break;
865 case htt_sec_type_aes_gcmp:
866 case htt_sec_type_aes_gcmp_256:
867 while (cur) {
868 tmp_next = qdf_nbuf_next(cur);
869 if (!ol_rx_frag_gcmp_demic(pdev, cur, hdr_space)) {
870 ol_rx_frames_free(htt_pdev, frag_list);
871 ol_txrx_err("GCMP demic failed");
872 return;
873 }
874 if (!ol_rx_frag_gcmp_decap(pdev, cur, hdr_space)) {
875 ol_rx_frames_free(htt_pdev, frag_list);
876 ol_txrx_err("GCMP decap failed");
877 return;
878 }
879 cur = tmp_next;
880 }
881
882 break;
883 default:
884 break;
885 }
886
887 msdu = ol_rx_defrag_decap_recombine(htt_pdev, frag_list, hdr_space);
888 if (!msdu)
889 return;
890
891 if (tkip_demic) {
892 qdf_mem_copy(key,
893 peer->security[index].michael_key,
894 sizeof(peer->security[index].michael_key));
895 if (!ol_rx_frag_tkip_demic(pdev, key, msdu, hdr_space)) {
896 uint64_t pn = 0;
897 ol_rx_err(pdev->ctrl_pdev,
898 vdev->vdev_id, peer->mac_addr.raw, tid, 0,
899 OL_RX_ERR_TKIP_MIC, msdu, &pn, 0);
900 htt_rx_desc_frame_free(htt_pdev, msdu);
901 ol_txrx_err("TKIP demic failed");
902 return;
903 }
904 }
905 wh = (struct ieee80211_frame *)ol_rx_frag_get_mac_hdr(htt_pdev, msdu);
906 if (DEFRAG_IEEE80211_QOS_HAS_SEQ(wh))
907 ol_rx_defrag_qos_decap(pdev, msdu, hdr_space);
908 if (ol_cfg_frame_type(pdev->ctrl_pdev) == wlan_frm_fmt_802_3)
909 ol_rx_defrag_nwifi_to_8023(pdev, msdu);
910
911 /* Packet Capture Mode */
912
913 if ((ucfg_pkt_capture_get_pktcap_mode((void *)soc->psoc) &
914 PKT_CAPTURE_MODE_DATA_ONLY)) {
915 if (peer) {
916 if (peer->vdev) {
917 qdf_spin_lock_bh(&pdev->peer_ref_mutex);
918 peer_head = TAILQ_FIRST(&vdev->peer_list);
919 qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
920 if (peer_head) {
921 qdf_spin_lock_bh(
922 &peer_head->peer_info_lock);
923 qdf_mem_copy(bssid,
924 &peer_head->mac_addr.raw,
925 QDF_MAC_ADDR_SIZE);
926 qdf_spin_unlock_bh(
927 &peer_head->peer_info_lock);
928
929 ucfg_pkt_capture_rx_msdu_process(
930 bssid, msdu,
931 vdev->vdev_id,
932 htt_pdev);
933 }
934 }
935 }
936 }
937
938 ol_rx_fwd_check(vdev, peer, tid, msdu);
939 }
940
941 /*
942 * Handling TKIP processing for defragmentation
943 */
944 int
ol_rx_frag_tkip_decap(ol_txrx_pdev_handle pdev,qdf_nbuf_t msdu,uint16_t hdrlen)945 ol_rx_frag_tkip_decap(ol_txrx_pdev_handle pdev,
946 qdf_nbuf_t msdu, uint16_t hdrlen)
947 {
948 uint8_t *ivp, *origHdr;
949
950 void *rx_desc_old_position = NULL;
951 void *ind_old_position = NULL;
952 int rx_desc_len = 0;
953
954 ol_rx_frag_desc_adjust(pdev,
955 msdu,
956 &rx_desc_old_position,
957 &ind_old_position, &rx_desc_len);
958 /* Header should have extended IV */
959 origHdr = (uint8_t *) (qdf_nbuf_data(msdu) + rx_desc_len);
960
961 ivp = origHdr + hdrlen;
962 if (!(ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV))
963 return OL_RX_DEFRAG_ERR;
964
965 qdf_mem_move(origHdr + f_tkip.ic_header, origHdr, hdrlen);
966 ol_rx_frag_restructure(
967 pdev,
968 msdu,
969 rx_desc_old_position,
970 ind_old_position,
971 &f_tkip,
972 rx_desc_len);
973 qdf_nbuf_pull_head(msdu, f_tkip.ic_header);
974 qdf_nbuf_trim_tail(msdu, f_tkip.ic_trailer);
975 return OL_RX_DEFRAG_OK;
976 }
977
978 /*
979 * Handling WEP processing for defragmentation
980 */
981 int
ol_rx_frag_wep_decap(ol_txrx_pdev_handle pdev,qdf_nbuf_t msdu,uint16_t hdrlen)982 ol_rx_frag_wep_decap(ol_txrx_pdev_handle pdev, qdf_nbuf_t msdu, uint16_t hdrlen)
983 {
984 uint8_t *origHdr;
985 void *rx_desc_old_position = NULL;
986 void *ind_old_position = NULL;
987 int rx_desc_len = 0;
988
989 ol_rx_frag_desc_adjust(pdev,
990 msdu,
991 &rx_desc_old_position,
992 &ind_old_position, &rx_desc_len);
993 origHdr = (uint8_t *) (qdf_nbuf_data(msdu) + rx_desc_len);
994 qdf_mem_move(origHdr + f_wep.ic_header, origHdr, hdrlen);
995 ol_rx_frag_restructure(
996 pdev,
997 msdu,
998 rx_desc_old_position,
999 ind_old_position,
1000 &f_wep,
1001 rx_desc_len);
1002 qdf_nbuf_pull_head(msdu, f_wep.ic_header);
1003 qdf_nbuf_trim_tail(msdu, f_wep.ic_trailer);
1004 return OL_RX_DEFRAG_OK;
1005 }
1006
1007 /*
1008 * Verify and strip MIC from the frame.
1009 */
1010 int
ol_rx_frag_tkip_demic(ol_txrx_pdev_handle pdev,const uint8_t * key,qdf_nbuf_t msdu,uint16_t hdrlen)1011 ol_rx_frag_tkip_demic(ol_txrx_pdev_handle pdev, const uint8_t *key,
1012 qdf_nbuf_t msdu, uint16_t hdrlen)
1013 {
1014 int status;
1015 uint32_t pktlen;
1016 uint8_t mic[IEEE80211_WEP_MICLEN];
1017 uint8_t mic0[IEEE80211_WEP_MICLEN];
1018 void *rx_desc_old_position = NULL;
1019 void *ind_old_position = NULL;
1020 int rx_desc_len = 0;
1021
1022 ol_rx_frag_desc_adjust(pdev,
1023 msdu,
1024 &rx_desc_old_position,
1025 &ind_old_position, &rx_desc_len);
1026
1027 pktlen = ol_rx_defrag_len(msdu) - rx_desc_len;
1028
1029 status = ol_rx_defrag_mic(pdev, key, msdu, hdrlen,
1030 pktlen - (hdrlen + f_tkip.ic_miclen), mic);
1031 if (status != OL_RX_DEFRAG_OK)
1032 return OL_RX_DEFRAG_ERR;
1033
1034 ol_rx_defrag_copydata(msdu, pktlen - f_tkip.ic_miclen + rx_desc_len,
1035 f_tkip.ic_miclen, (caddr_t) mic0);
1036 if (qdf_mem_cmp(mic, mic0, f_tkip.ic_miclen))
1037 return OL_RX_DEFRAG_ERR;
1038
1039 qdf_nbuf_trim_tail(msdu, f_tkip.ic_miclen);
1040 return OL_RX_DEFRAG_OK;
1041 }
1042
1043 /*
1044 * Handling CCMP processing for defragmentation
1045 */
1046 int
ol_rx_frag_ccmp_decap(ol_txrx_pdev_handle pdev,qdf_nbuf_t nbuf,uint16_t hdrlen)1047 ol_rx_frag_ccmp_decap(ol_txrx_pdev_handle pdev,
1048 qdf_nbuf_t nbuf, uint16_t hdrlen)
1049 {
1050 uint8_t *ivp, *origHdr;
1051 void *rx_desc_old_position = NULL;
1052 void *ind_old_position = NULL;
1053 int rx_desc_len = 0;
1054
1055 ol_rx_frag_desc_adjust(pdev,
1056 nbuf,
1057 &rx_desc_old_position,
1058 &ind_old_position, &rx_desc_len);
1059
1060 origHdr = (uint8_t *) (qdf_nbuf_data(nbuf) + rx_desc_len);
1061 ivp = origHdr + hdrlen;
1062 if (!(ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV))
1063 return OL_RX_DEFRAG_ERR;
1064
1065 qdf_mem_move(origHdr + f_ccmp.ic_header, origHdr, hdrlen);
1066 ol_rx_frag_restructure(
1067 pdev,
1068 nbuf,
1069 rx_desc_old_position,
1070 ind_old_position,
1071 &f_ccmp,
1072 rx_desc_len);
1073 qdf_nbuf_pull_head(nbuf, f_ccmp.ic_header);
1074
1075 return OL_RX_DEFRAG_OK;
1076 }
1077
1078 /*
1079 * Verify and strip MIC from the frame.
1080 */
1081 int
ol_rx_frag_ccmp_demic(ol_txrx_pdev_handle pdev,qdf_nbuf_t wbuf,uint16_t hdrlen)1082 ol_rx_frag_ccmp_demic(ol_txrx_pdev_handle pdev,
1083 qdf_nbuf_t wbuf, uint16_t hdrlen)
1084 {
1085 uint8_t *ivp, *origHdr;
1086 void *rx_desc_old_position = NULL;
1087 void *ind_old_position = NULL;
1088 int rx_desc_len = 0;
1089
1090 ol_rx_frag_desc_adjust(pdev,
1091 wbuf,
1092 &rx_desc_old_position,
1093 &ind_old_position, &rx_desc_len);
1094
1095 origHdr = (uint8_t *) (qdf_nbuf_data(wbuf) + rx_desc_len);
1096
1097 ivp = origHdr + hdrlen;
1098 if (!(ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV))
1099 return OL_RX_DEFRAG_ERR;
1100
1101 qdf_nbuf_trim_tail(wbuf, f_ccmp.ic_trailer);
1102
1103 return OL_RX_DEFRAG_OK;
1104 }
1105
1106 /*
1107 * Craft pseudo header used to calculate the MIC.
1108 */
ol_rx_defrag_michdr(const struct ieee80211_frame * wh0,uint8_t hdr[])1109 void ol_rx_defrag_michdr(const struct ieee80211_frame *wh0, uint8_t hdr[])
1110 {
1111 const struct ieee80211_frame_addr4 *wh =
1112 (const struct ieee80211_frame_addr4 *)wh0;
1113
1114 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
1115 case IEEE80211_FC1_DIR_NODS:
1116 DEFRAG_IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */
1117 DEFRAG_IEEE80211_ADDR_COPY(hdr + QDF_MAC_ADDR_SIZE,
1118 wh->i_addr2);
1119 break;
1120 case IEEE80211_FC1_DIR_TODS:
1121 DEFRAG_IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */
1122 DEFRAG_IEEE80211_ADDR_COPY(hdr + QDF_MAC_ADDR_SIZE,
1123 wh->i_addr2);
1124 break;
1125 case IEEE80211_FC1_DIR_FROMDS:
1126 DEFRAG_IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */
1127 DEFRAG_IEEE80211_ADDR_COPY(hdr + QDF_MAC_ADDR_SIZE,
1128 wh->i_addr3);
1129 break;
1130 case IEEE80211_FC1_DIR_DSTODS:
1131 DEFRAG_IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */
1132 DEFRAG_IEEE80211_ADDR_COPY(hdr + QDF_MAC_ADDR_SIZE,
1133 wh->i_addr4);
1134 break;
1135 }
1136 /*
1137 * Bit 7 is QDF_IEEE80211_FC0_SUBTYPE_QOS for data frame, but
1138 * it could also be set for deauth, disassoc, action, etc. for
1139 * a mgt type frame. It comes into picture for MFP.
1140 */
1141 if (wh->i_fc[0] & QDF_IEEE80211_FC0_SUBTYPE_QOS) {
1142 const struct ieee80211_qosframe *qwh =
1143 (const struct ieee80211_qosframe *)wh;
1144 hdr[12] = qwh->i_qos[0] & IEEE80211_QOS_TID;
1145 } else {
1146 hdr[12] = 0;
1147 }
1148 hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
1149 }
1150
1151 /*
1152 * Michael_mic for defragmentation
1153 */
1154 int
ol_rx_defrag_mic(ol_txrx_pdev_handle pdev,const uint8_t * key,qdf_nbuf_t wbuf,uint16_t off,uint16_t data_len,uint8_t mic[])1155 ol_rx_defrag_mic(ol_txrx_pdev_handle pdev,
1156 const uint8_t *key,
1157 qdf_nbuf_t wbuf,
1158 uint16_t off, uint16_t data_len, uint8_t mic[])
1159 {
1160 uint8_t hdr[16] = { 0, };
1161 uint32_t l, r;
1162 const uint8_t *data;
1163 uint32_t space;
1164 void *rx_desc_old_position = NULL;
1165 void *ind_old_position = NULL;
1166 int rx_desc_len = 0;
1167 htt_pdev_handle htt_pdev = pdev->htt_pdev;
1168
1169 ol_rx_frag_desc_adjust(pdev,
1170 wbuf,
1171 &rx_desc_old_position,
1172 &ind_old_position, &rx_desc_len);
1173
1174 ol_rx_defrag_michdr((struct ieee80211_frame *)(qdf_nbuf_data(wbuf) +
1175 rx_desc_len), hdr);
1176 l = get_le32(key);
1177 r = get_le32(key + 4);
1178
1179 /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
1180 l ^= get_le32(hdr);
1181 michael_block(l, r);
1182 l ^= get_le32(&hdr[4]);
1183 michael_block(l, r);
1184 l ^= get_le32(&hdr[8]);
1185 michael_block(l, r);
1186 l ^= get_le32(&hdr[12]);
1187 michael_block(l, r);
1188
1189 /* first buffer has special handling */
1190 data = (uint8_t *) qdf_nbuf_data(wbuf) + rx_desc_len + off;
1191 space = ol_rx_defrag_len(wbuf) - rx_desc_len - off;
1192 for (;; ) {
1193 if (space > data_len)
1194 space = data_len;
1195
1196 /* collect 32-bit blocks from current buffer */
1197 while (space >= sizeof(uint32_t)) {
1198 l ^= get_le32(data);
1199 michael_block(l, r);
1200 data += sizeof(uint32_t);
1201 space -= sizeof(uint32_t);
1202 data_len -= sizeof(uint32_t);
1203 }
1204 if (data_len < sizeof(uint32_t))
1205 break;
1206
1207 wbuf = qdf_nbuf_next(wbuf);
1208 if (!wbuf)
1209 return OL_RX_DEFRAG_ERR;
1210
1211 rx_desc_len = ol_rx_get_desc_len(htt_pdev, wbuf,
1212 &rx_desc_old_position);
1213
1214 if (space != 0) {
1215 const uint8_t *data_next;
1216 /*
1217 * Block straddles buffers, split references.
1218 */
1219 data_next =
1220 (uint8_t *) qdf_nbuf_data(wbuf) + rx_desc_len;
1221 if ((ol_rx_defrag_len(wbuf) - rx_desc_len) <
1222 sizeof(uint32_t) - space) {
1223 return OL_RX_DEFRAG_ERR;
1224 }
1225 switch (space) {
1226 case 1:
1227 l ^= get_le32_split(data[0], data_next[0],
1228 data_next[1], data_next[2]);
1229 data = data_next + 3;
1230 space = (ol_rx_defrag_len(wbuf) - rx_desc_len)
1231 - 3;
1232 break;
1233 case 2:
1234 l ^= get_le32_split(data[0], data[1],
1235 data_next[0], data_next[1]);
1236 data = data_next + 2;
1237 space = (ol_rx_defrag_len(wbuf) - rx_desc_len)
1238 - 2;
1239 break;
1240 case 3:
1241 l ^= get_le32_split(data[0], data[1], data[2],
1242 data_next[0]);
1243 data = data_next + 1;
1244 space = (ol_rx_defrag_len(wbuf) - rx_desc_len)
1245 - 1;
1246 break;
1247 }
1248 michael_block(l, r);
1249 data_len -= sizeof(uint32_t);
1250 } else {
1251 /*
1252 * Setup for next buffer.
1253 */
1254 data = (uint8_t *) qdf_nbuf_data(wbuf) + rx_desc_len;
1255 space = ol_rx_defrag_len(wbuf) - rx_desc_len;
1256 }
1257 }
1258 /* Last block and padding (0x5a, 4..7 x 0) */
1259 switch (data_len) {
1260 case 0:
1261 l ^= get_le32_split(0x5a, 0, 0, 0);
1262 break;
1263 case 1:
1264 l ^= get_le32_split(data[0], 0x5a, 0, 0);
1265 break;
1266 case 2:
1267 l ^= get_le32_split(data[0], data[1], 0x5a, 0);
1268 break;
1269 case 3:
1270 l ^= get_le32_split(data[0], data[1], data[2], 0x5a);
1271 break;
1272 }
1273 michael_block(l, r);
1274 michael_block(l, r);
1275 put_le32(mic, l);
1276 put_le32(mic + 4, r);
1277
1278 return OL_RX_DEFRAG_OK;
1279 }
1280
1281 /*
1282 * Calculate headersize
1283 */
ol_rx_frag_hdrsize(const void * data)1284 uint16_t ol_rx_frag_hdrsize(const void *data)
1285 {
1286 const struct ieee80211_frame *wh = (const struct ieee80211_frame *)data;
1287 uint16_t size = sizeof(struct ieee80211_frame);
1288
1289 if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
1290 size += QDF_MAC_ADDR_SIZE;
1291
1292 if (DEFRAG_IEEE80211_QOS_HAS_SEQ(wh)) {
1293 size += sizeof(uint16_t);
1294 if (wh->i_fc[1] & IEEE80211_FC1_ORDER)
1295 size += sizeof(struct ieee80211_htc);
1296 }
1297 return size;
1298 }
1299
1300 /*
1301 * Recombine and decap fragments
1302 */
1303 qdf_nbuf_t
ol_rx_defrag_decap_recombine(htt_pdev_handle htt_pdev,qdf_nbuf_t frag_list,uint16_t hdrsize)1304 ol_rx_defrag_decap_recombine(htt_pdev_handle htt_pdev,
1305 qdf_nbuf_t frag_list, uint16_t hdrsize)
1306 {
1307 qdf_nbuf_t tmp;
1308 qdf_nbuf_t msdu = frag_list;
1309 qdf_nbuf_t rx_nbuf = frag_list;
1310 struct ieee80211_frame *wh;
1311
1312 msdu = qdf_nbuf_next(msdu);
1313 qdf_nbuf_set_next(rx_nbuf, NULL);
1314 while (msdu) {
1315 htt_rx_msdu_desc_free(htt_pdev, msdu);
1316 tmp = qdf_nbuf_next(msdu);
1317 qdf_nbuf_set_next(msdu, NULL);
1318 ol_rx_frag_pull_hdr(htt_pdev, msdu, hdrsize);
1319 if (!ol_rx_defrag_concat(rx_nbuf, msdu)) {
1320 ol_rx_frames_free(htt_pdev, tmp);
1321 htt_rx_desc_frame_free(htt_pdev, rx_nbuf);
1322 qdf_nbuf_free(msdu);
1323 /* msdu rx desc already freed above */
1324 return NULL;
1325 }
1326 msdu = tmp;
1327 }
1328 wh = (struct ieee80211_frame *)ol_rx_frag_get_mac_hdr(htt_pdev,
1329 rx_nbuf);
1330 wh->i_fc[1] &= ~IEEE80211_FC1_MORE_FRAG;
1331 *(uint16_t *) wh->i_seq &= ~IEEE80211_SEQ_FRAG_MASK;
1332
1333 return rx_nbuf;
1334 }
1335
ol_rx_defrag_nwifi_to_8023(ol_txrx_pdev_handle pdev,qdf_nbuf_t msdu)1336 void ol_rx_defrag_nwifi_to_8023(ol_txrx_pdev_handle pdev, qdf_nbuf_t msdu)
1337 {
1338 struct ieee80211_frame wh;
1339 uint32_t hdrsize;
1340 struct llc_snap_hdr_t llchdr;
1341 struct ethernet_hdr_t *eth_hdr;
1342 void *rx_desc_old_position = NULL;
1343 void *ind_old_position = NULL;
1344 int rx_desc_len = 0;
1345 struct ieee80211_frame *wh_ptr;
1346
1347 ol_rx_frag_desc_adjust(pdev,
1348 msdu,
1349 &rx_desc_old_position,
1350 &ind_old_position, &rx_desc_len);
1351
1352 wh_ptr = (struct ieee80211_frame *)(qdf_nbuf_data(msdu) + rx_desc_len);
1353 qdf_mem_copy(&wh, wh_ptr, sizeof(wh));
1354 hdrsize = sizeof(struct ieee80211_frame);
1355 qdf_mem_copy(&llchdr, ((uint8_t *) (qdf_nbuf_data(msdu) +
1356 rx_desc_len)) + hdrsize,
1357 sizeof(struct llc_snap_hdr_t));
1358
1359 /*
1360 * Now move the data pointer to the beginning of the mac header :
1361 * new-header = old-hdr + (wifhdrsize + llchdrsize - ethhdrsize)
1362 */
1363 qdf_nbuf_pull_head(msdu, (rx_desc_len + hdrsize +
1364 sizeof(struct llc_snap_hdr_t) -
1365 sizeof(struct ethernet_hdr_t)));
1366 eth_hdr = (struct ethernet_hdr_t *)(qdf_nbuf_data(msdu));
1367 switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
1368 case IEEE80211_FC1_DIR_NODS:
1369 qdf_mem_copy(eth_hdr->dest_addr, wh.i_addr1,
1370 QDF_MAC_ADDR_SIZE);
1371 qdf_mem_copy(eth_hdr->src_addr, wh.i_addr2, QDF_MAC_ADDR_SIZE);
1372 break;
1373 case IEEE80211_FC1_DIR_TODS:
1374 qdf_mem_copy(eth_hdr->dest_addr, wh.i_addr3,
1375 QDF_MAC_ADDR_SIZE);
1376 qdf_mem_copy(eth_hdr->src_addr, wh.i_addr2, QDF_MAC_ADDR_SIZE);
1377 break;
1378 case IEEE80211_FC1_DIR_FROMDS:
1379 qdf_mem_copy(eth_hdr->dest_addr, wh.i_addr1,
1380 QDF_MAC_ADDR_SIZE);
1381 qdf_mem_copy(eth_hdr->src_addr, wh.i_addr3, QDF_MAC_ADDR_SIZE);
1382 break;
1383 case IEEE80211_FC1_DIR_DSTODS:
1384 break;
1385 }
1386
1387 qdf_mem_copy(eth_hdr->ethertype, llchdr.ethertype,
1388 sizeof(llchdr.ethertype));
1389
1390 ol_rx_defrag_push_rx_desc(msdu, rx_desc_old_position,
1391 ind_old_position, rx_desc_len);
1392 }
1393
1394 /*
1395 * Handling QOS for defragmentation
1396 */
1397 void
ol_rx_defrag_qos_decap(ol_txrx_pdev_handle pdev,qdf_nbuf_t nbuf,uint16_t hdrlen)1398 ol_rx_defrag_qos_decap(ol_txrx_pdev_handle pdev,
1399 qdf_nbuf_t nbuf, uint16_t hdrlen)
1400 {
1401 struct ieee80211_frame *wh;
1402 uint16_t qoslen;
1403 void *rx_desc_old_position = NULL;
1404 void *ind_old_position = NULL;
1405 int rx_desc_len = 0;
1406
1407 ol_rx_frag_desc_adjust(pdev,
1408 nbuf,
1409 &rx_desc_old_position,
1410 &ind_old_position, &rx_desc_len);
1411
1412 wh = (struct ieee80211_frame *)(qdf_nbuf_data(nbuf) + rx_desc_len);
1413 if (DEFRAG_IEEE80211_QOS_HAS_SEQ(wh)) {
1414 qoslen = sizeof(struct ieee80211_qoscntl);
1415 /* Qos frame with Order bit set indicates a HTC frame */
1416 if (wh->i_fc[1] & IEEE80211_FC1_ORDER)
1417 qoslen += sizeof(struct ieee80211_htc);
1418
1419 /* remove QoS filed from header */
1420 hdrlen -= qoslen;
1421 qdf_mem_move((uint8_t *) wh + qoslen, wh, hdrlen);
1422 wh = (struct ieee80211_frame *)qdf_nbuf_pull_head(nbuf,
1423 rx_desc_len +
1424 qoslen);
1425 /* clear QoS bit */
1426 /*
1427 * KW# 6154 'qdf_nbuf_pull_head' in turn calls
1428 * __qdf_nbuf_pull_head,
1429 * which returns NULL if there is not sufficient data to pull.
1430 * It's guaranteed that qdf_nbuf_pull_head will succeed rather
1431 * than returning NULL, since the entire rx frame is already
1432 * present in the rx buffer.
1433 * However, to make it obvious to static analyzers that this
1434 * code is safe, add an explicit check that qdf_nbuf_pull_head
1435 * returns a non-NULL value.
1436 * Since this part of the code is not performance-critical,
1437 * adding this explicit check is okay.
1438 */
1439 if (wh)
1440 wh->i_fc[0] &= ~QDF_IEEE80211_FC0_SUBTYPE_QOS;
1441
1442 ol_rx_defrag_push_rx_desc(nbuf, rx_desc_old_position,
1443 ind_old_position, rx_desc_len);
1444
1445 }
1446 }
1447