xref: /wlan-driver/qcacld-3.0/core/dp/txrx/ol_rx_defrag.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
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