xref: /wlan-dirver/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_defrag.c (revision 8ddef7dd9a290d4a9b1efd5d3efacf51d78a1a0d)
1 /*
2  * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include "hal_hw_headers.h"
20 #include "dp_types.h"
21 #include "dp_rx.h"
22 #include "dp_peer.h"
23 #include "hal_api.h"
24 #include "qdf_trace.h"
25 #include "qdf_nbuf.h"
26 #include "dp_internal.h"
27 #include "dp_rx_defrag.h"
28 #include <enet.h>	/* LLC_SNAP_HDR_LEN */
29 #include "dp_rx_defrag.h"
30 
31 const struct dp_rx_defrag_cipher dp_f_ccmp = {
32 	"AES-CCM",
33 	IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_EXTIVLEN,
34 	IEEE80211_WEP_MICLEN,
35 	0,
36 };
37 
38 const struct dp_rx_defrag_cipher dp_f_tkip = {
39 	"TKIP",
40 	IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_EXTIVLEN,
41 	IEEE80211_WEP_CRCLEN,
42 	IEEE80211_WEP_MICLEN,
43 };
44 
45 const struct dp_rx_defrag_cipher dp_f_wep = {
46 	"WEP",
47 	IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN,
48 	IEEE80211_WEP_CRCLEN,
49 	0,
50 };
51 
52 /*
53  * dp_rx_defrag_frames_free(): Free fragment chain
54  * @frames: Fragment chain
55  *
56  * Iterates through the fragment chain and frees them
57  * Returns: None
58  */
59 static void dp_rx_defrag_frames_free(qdf_nbuf_t frames)
60 {
61 	qdf_nbuf_t next, frag = frames;
62 
63 	while (frag) {
64 		next = qdf_nbuf_next(frag);
65 		qdf_nbuf_free(frag);
66 		frag = next;
67 	}
68 }
69 
70 /*
71  * dp_rx_clear_saved_desc_info(): Clears descriptor info
72  * @peer: Pointer to the peer data structure
73  * @tid: Transmit ID (TID)
74  *
75  * Saves MPDU descriptor info and MSDU link pointer from REO
76  * ring descriptor. The cache is created per peer, per TID
77  *
78  * Returns: None
79  */
80 static void dp_rx_clear_saved_desc_info(struct dp_peer *peer, unsigned tid)
81 {
82 	if (peer->rx_tid[tid].dst_ring_desc)
83 		qdf_mem_free(peer->rx_tid[tid].dst_ring_desc);
84 
85 	peer->rx_tid[tid].dst_ring_desc = NULL;
86 }
87 
88 static void dp_rx_return_head_frag_desc(struct dp_peer *peer,
89 					unsigned int tid)
90 {
91 	struct dp_soc *soc;
92 	struct dp_pdev *pdev;
93 	struct dp_srng *dp_rxdma_srng;
94 	struct rx_desc_pool *rx_desc_pool;
95 	union dp_rx_desc_list_elem_t *head = NULL;
96 	union dp_rx_desc_list_elem_t *tail = NULL;
97 
98 	if (peer->rx_tid[tid].head_frag_desc) {
99 		pdev = peer->vdev->pdev;
100 		soc = pdev->soc;
101 		dp_rxdma_srng = &pdev->rx_refill_buf_ring;
102 		rx_desc_pool = &soc->rx_desc_buf[pdev->pdev_id];
103 
104 		dp_rx_add_to_free_desc_list(&head, &tail,
105 					    peer->rx_tid[tid].head_frag_desc);
106 		dp_rx_buffers_replenish(soc, 0, dp_rxdma_srng, rx_desc_pool,
107 					1, &head, &tail);
108 	}
109 }
110 
111 /*
112  * dp_rx_reorder_flush_frag(): Flush the frag list
113  * @peer: Pointer to the peer data structure
114  * @tid: Transmit ID (TID)
115  *
116  * Flush the per-TID frag list
117  *
118  * Returns: None
119  */
120 void dp_rx_reorder_flush_frag(struct dp_peer *peer,
121 			 unsigned int tid)
122 {
123 	struct dp_soc *soc;
124 
125 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH,
126 		  FL("Flushing TID %d"), tid);
127 
128 	if (!peer) {
129 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
130 					"%s: NULL peer", __func__);
131 		return;
132 	}
133 
134 	soc = peer->vdev->pdev->soc;
135 
136 	if (peer->rx_tid[tid].dst_ring_desc) {
137 		if (dp_rx_link_desc_return(soc,
138 					peer->rx_tid[tid].dst_ring_desc,
139 					HAL_BM_ACTION_PUT_IN_IDLE_LIST) !=
140 					QDF_STATUS_SUCCESS)
141 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
142 					"%s: Failed to return link desc",
143 					__func__);
144 	}
145 
146 	dp_rx_return_head_frag_desc(peer, tid);
147 	dp_rx_defrag_cleanup(peer, tid);
148 }
149 
150 /*
151  * dp_rx_defrag_waitlist_flush(): Flush SOC defrag wait list
152  * @soc: DP SOC
153  *
154  * Flush fragments of all waitlisted TID's
155  *
156  * Returns: None
157  */
158 void dp_rx_defrag_waitlist_flush(struct dp_soc *soc)
159 {
160 	struct dp_rx_tid *rx_reorder = NULL;
161 	struct dp_rx_tid *tmp;
162 	uint32_t now_ms = qdf_system_ticks_to_msecs(qdf_system_ticks());
163 	TAILQ_HEAD(, dp_rx_tid) temp_list;
164 
165 	TAILQ_INIT(&temp_list);
166 
167 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
168 		  FL("Current time  %u"), now_ms);
169 
170 	qdf_spin_lock_bh(&soc->rx.defrag.defrag_lock);
171 	TAILQ_FOREACH_SAFE(rx_reorder, &soc->rx.defrag.waitlist,
172 			   defrag_waitlist_elem, tmp) {
173 		uint32_t tid;
174 
175 		if (rx_reorder->defrag_timeout_ms > now_ms)
176 			break;
177 
178 		tid = rx_reorder->tid;
179 		if (tid >= DP_MAX_TIDS) {
180 			qdf_assert(0);
181 			continue;
182 		}
183 
184 		TAILQ_REMOVE(&soc->rx.defrag.waitlist, rx_reorder,
185 			     defrag_waitlist_elem);
186 		DP_STATS_DEC(soc, rx.rx_frag_wait, 1);
187 
188 		/* Move to temp list and clean-up later */
189 		TAILQ_INSERT_TAIL(&temp_list, rx_reorder,
190 				  defrag_waitlist_elem);
191 	}
192 	if (rx_reorder) {
193 		soc->rx.defrag.next_flush_ms =
194 			rx_reorder->defrag_timeout_ms;
195 	} else {
196 		soc->rx.defrag.next_flush_ms =
197 			now_ms + soc->rx.defrag.timeout_ms;
198 	}
199 
200 	qdf_spin_unlock_bh(&soc->rx.defrag.defrag_lock);
201 
202 	TAILQ_FOREACH_SAFE(rx_reorder, &temp_list,
203 			   defrag_waitlist_elem, tmp) {
204 		struct dp_peer *peer, *temp_peer = NULL;
205 
206 		qdf_spin_lock_bh(&rx_reorder->tid_lock);
207 		TAILQ_REMOVE(&temp_list, rx_reorder,
208 			     defrag_waitlist_elem);
209 		/* get address of current peer */
210 		peer =
211 			container_of(rx_reorder, struct dp_peer,
212 				     rx_tid[rx_reorder->tid]);
213 		qdf_spin_unlock_bh(&rx_reorder->tid_lock);
214 
215 		temp_peer = dp_peer_find_by_id(soc, peer->peer_ids[0]);
216 		if (temp_peer == peer) {
217 			qdf_spin_lock_bh(&rx_reorder->tid_lock);
218 			dp_rx_reorder_flush_frag(peer, rx_reorder->tid);
219 			qdf_spin_unlock_bh(&rx_reorder->tid_lock);
220 		}
221 
222 		if (temp_peer)
223 			dp_peer_unref_del_find_by_id(temp_peer);
224 
225 	}
226 }
227 
228 /*
229  * dp_rx_defrag_waitlist_add(): Update per-PDEV defrag wait list
230  * @peer: Pointer to the peer data structure
231  * @tid: Transmit ID (TID)
232  *
233  * Appends per-tid fragments to global fragment wait list
234  *
235  * Returns: None
236  */
237 static void dp_rx_defrag_waitlist_add(struct dp_peer *peer, unsigned tid)
238 {
239 	struct dp_soc *psoc = peer->vdev->pdev->soc;
240 	struct dp_rx_tid *rx_reorder = &peer->rx_tid[tid];
241 
242 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH,
243 		  FL("Adding TID %u to waitlist for peer %pK"),
244 		  tid, peer);
245 
246 	/* TODO: use LIST macros instead of TAIL macros */
247 	qdf_spin_lock_bh(&psoc->rx.defrag.defrag_lock);
248 	if (TAILQ_EMPTY(&psoc->rx.defrag.waitlist))
249 		psoc->rx.defrag.next_flush_ms = rx_reorder->defrag_timeout_ms;
250 	TAILQ_INSERT_TAIL(&psoc->rx.defrag.waitlist, rx_reorder,
251 				defrag_waitlist_elem);
252 	DP_STATS_INC(psoc, rx.rx_frag_wait, 1);
253 	qdf_spin_unlock_bh(&psoc->rx.defrag.defrag_lock);
254 }
255 
256 /*
257  * dp_rx_defrag_waitlist_remove(): Remove fragments from waitlist
258  * @peer: Pointer to the peer data structure
259  * @tid: Transmit ID (TID)
260  *
261  * Remove fragments from waitlist
262  *
263  * Returns: None
264  */
265 void dp_rx_defrag_waitlist_remove(struct dp_peer *peer, unsigned tid)
266 {
267 	struct dp_pdev *pdev = peer->vdev->pdev;
268 	struct dp_soc *soc = pdev->soc;
269 	struct dp_rx_tid *rx_reorder;
270 	struct dp_rx_tid *tmp;
271 
272 	if (tid > DP_MAX_TIDS) {
273 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH,
274 			  "TID out of bounds: %d", tid);
275 		qdf_assert(0);
276 		return;
277 	}
278 
279 	qdf_spin_lock_bh(&soc->rx.defrag.defrag_lock);
280 	TAILQ_FOREACH_SAFE(rx_reorder, &soc->rx.defrag.waitlist,
281 			   defrag_waitlist_elem, tmp) {
282 		struct dp_peer *peer_on_waitlist;
283 
284 		/* get address of current peer */
285 		peer_on_waitlist =
286 			container_of(rx_reorder, struct dp_peer,
287 				     rx_tid[rx_reorder->tid]);
288 
289 		/* Ensure it is TID for same peer */
290 		if (peer_on_waitlist == peer && rx_reorder->tid == tid) {
291 			TAILQ_REMOVE(&soc->rx.defrag.waitlist,
292 				rx_reorder, defrag_waitlist_elem);
293 			DP_STATS_DEC(soc, rx.rx_frag_wait, 1);
294 		}
295 	}
296 	qdf_spin_unlock_bh(&soc->rx.defrag.defrag_lock);
297 }
298 
299 /*
300  * dp_rx_defrag_fraglist_insert(): Create a per-sequence fragment list
301  * @peer: Pointer to the peer data structure
302  * @tid: Transmit ID (TID)
303  * @head_addr: Pointer to head list
304  * @tail_addr: Pointer to tail list
305  * @frag: Incoming fragment
306  * @all_frag_present: Flag to indicate whether all fragments are received
307  *
308  * Build a per-tid, per-sequence fragment list.
309  *
310  * Returns: Success, if inserted
311  */
312 static QDF_STATUS dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned tid,
313 	qdf_nbuf_t *head_addr, qdf_nbuf_t *tail_addr, qdf_nbuf_t frag,
314 	uint8_t *all_frag_present)
315 {
316 	qdf_nbuf_t next;
317 	qdf_nbuf_t prev = NULL;
318 	qdf_nbuf_t cur;
319 	uint16_t head_fragno, cur_fragno, next_fragno;
320 	uint8_t last_morefrag = 1, count = 0;
321 	struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
322 	uint8_t *rx_desc_info;
323 
324 
325 	qdf_assert(frag);
326 	qdf_assert(head_addr);
327 	qdf_assert(tail_addr);
328 
329 	*all_frag_present = 0;
330 	rx_desc_info = qdf_nbuf_data(frag);
331 	cur_fragno = dp_rx_frag_get_mpdu_frag_number(rx_desc_info);
332 
333 	/* If this is the first fragment */
334 	if (!(*head_addr)) {
335 		*head_addr = *tail_addr = frag;
336 		qdf_nbuf_set_next(*tail_addr, NULL);
337 		rx_tid->curr_frag_num = cur_fragno;
338 
339 		goto insert_done;
340 	}
341 
342 	/* In sequence fragment */
343 	if (cur_fragno > rx_tid->curr_frag_num) {
344 		qdf_nbuf_set_next(*tail_addr, frag);
345 		*tail_addr = frag;
346 		qdf_nbuf_set_next(*tail_addr, NULL);
347 		rx_tid->curr_frag_num = cur_fragno;
348 	} else {
349 		/* Out of sequence fragment */
350 		cur = *head_addr;
351 		rx_desc_info = qdf_nbuf_data(cur);
352 		head_fragno = dp_rx_frag_get_mpdu_frag_number(rx_desc_info);
353 
354 		if (cur_fragno == head_fragno) {
355 			qdf_nbuf_free(frag);
356 			goto insert_fail;
357 		} else if (head_fragno > cur_fragno) {
358 			qdf_nbuf_set_next(frag, cur);
359 			cur = frag;
360 			*head_addr = frag; /* head pointer to be updated */
361 		} else {
362 			while ((cur_fragno > head_fragno) && cur != NULL) {
363 				prev = cur;
364 				cur = qdf_nbuf_next(cur);
365 				rx_desc_info = qdf_nbuf_data(cur);
366 				head_fragno =
367 					dp_rx_frag_get_mpdu_frag_number(
368 								rx_desc_info);
369 			}
370 
371 			if (cur_fragno == head_fragno) {
372 				qdf_nbuf_free(frag);
373 				goto insert_fail;
374 			}
375 
376 			qdf_nbuf_set_next(prev, frag);
377 			qdf_nbuf_set_next(frag, cur);
378 		}
379 	}
380 
381 	next = qdf_nbuf_next(*head_addr);
382 
383 	rx_desc_info = qdf_nbuf_data(*tail_addr);
384 	last_morefrag = dp_rx_frag_get_more_frag_bit(rx_desc_info);
385 
386 	/* TODO: optimize the loop */
387 	if (!last_morefrag) {
388 		/* Check if all fragments are present */
389 		do {
390 			rx_desc_info = qdf_nbuf_data(next);
391 			next_fragno =
392 				dp_rx_frag_get_mpdu_frag_number(rx_desc_info);
393 			count++;
394 
395 			if (next_fragno != count)
396 				break;
397 
398 			next = qdf_nbuf_next(next);
399 		} while (next);
400 
401 		if (!next) {
402 			*all_frag_present = 1;
403 			return QDF_STATUS_SUCCESS;
404 		}
405 	}
406 
407 insert_done:
408 	return QDF_STATUS_SUCCESS;
409 
410 insert_fail:
411 	return QDF_STATUS_E_FAILURE;
412 }
413 
414 
415 /*
416  * dp_rx_defrag_tkip_decap(): decap tkip encrypted fragment
417  * @msdu: Pointer to the fragment
418  * @hdrlen: 802.11 header length (mostly useful in 4 addr frames)
419  *
420  * decap tkip encrypted fragment
421  *
422  * Returns: QDF_STATUS
423  */
424 static QDF_STATUS dp_rx_defrag_tkip_decap(qdf_nbuf_t msdu, uint16_t hdrlen)
425 {
426 	uint8_t *ivp, *orig_hdr;
427 	int rx_desc_len = sizeof(struct rx_pkt_tlvs);
428 
429 	/* start of 802.11 header info */
430 	orig_hdr = (uint8_t *)(qdf_nbuf_data(msdu) + rx_desc_len);
431 
432 	/* TKIP header is located post 802.11 header */
433 	ivp = orig_hdr + hdrlen;
434 	if (!(ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV)) {
435 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
436 			"IEEE80211_WEP_EXTIV is missing in TKIP fragment");
437 		return QDF_STATUS_E_DEFRAG_ERROR;
438 	}
439 
440 	qdf_nbuf_trim_tail(msdu, dp_f_tkip.ic_trailer);
441 
442 	return QDF_STATUS_SUCCESS;
443 }
444 
445 /*
446  * dp_rx_defrag_ccmp_demic(): Remove MIC information from CCMP fragment
447  * @nbuf: Pointer to the fragment buffer
448  * @hdrlen: 802.11 header length (mostly useful in 4 addr frames)
449  *
450  * Remove MIC information from CCMP fragment
451  *
452  * Returns: QDF_STATUS
453  */
454 static QDF_STATUS dp_rx_defrag_ccmp_demic(qdf_nbuf_t nbuf, uint16_t hdrlen)
455 {
456 	uint8_t *ivp, *orig_hdr;
457 	int rx_desc_len = sizeof(struct rx_pkt_tlvs);
458 
459 	/* start of the 802.11 header */
460 	orig_hdr = (uint8_t *)(qdf_nbuf_data(nbuf) + rx_desc_len);
461 
462 	/* CCMP header is located after 802.11 header */
463 	ivp = orig_hdr + hdrlen;
464 	if (!(ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV))
465 		return QDF_STATUS_E_DEFRAG_ERROR;
466 
467 	qdf_nbuf_trim_tail(nbuf, dp_f_ccmp.ic_trailer);
468 
469 	return QDF_STATUS_SUCCESS;
470 }
471 
472 /*
473  * dp_rx_defrag_ccmp_decap(): decap CCMP encrypted fragment
474  * @nbuf: Pointer to the fragment
475  * @hdrlen: length of the header information
476  *
477  * decap CCMP encrypted fragment
478  *
479  * Returns: QDF_STATUS
480  */
481 static QDF_STATUS dp_rx_defrag_ccmp_decap(qdf_nbuf_t nbuf, uint16_t hdrlen)
482 {
483 	uint8_t *ivp, *origHdr;
484 	int rx_desc_len = sizeof(struct rx_pkt_tlvs);
485 
486 	origHdr = (uint8_t *) (qdf_nbuf_data(nbuf) + rx_desc_len);
487 	ivp = origHdr + hdrlen;
488 
489 	if (!(ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV))
490 		return QDF_STATUS_E_DEFRAG_ERROR;
491 
492 	/* Let's pull the header later */
493 
494 	return QDF_STATUS_SUCCESS;
495 }
496 
497 /*
498  * dp_rx_defrag_wep_decap(): decap WEP encrypted fragment
499  * @msdu: Pointer to the fragment
500  * @hdrlen: length of the header information
501  *
502  * decap WEP encrypted fragment
503  *
504  * Returns: QDF_STATUS
505  */
506 static QDF_STATUS dp_rx_defrag_wep_decap(qdf_nbuf_t msdu, uint16_t hdrlen)
507 {
508 	uint8_t *origHdr;
509 	int rx_desc_len = sizeof(struct rx_pkt_tlvs);
510 
511 	origHdr = (uint8_t *) (qdf_nbuf_data(msdu) + rx_desc_len);
512 	qdf_mem_move(origHdr + dp_f_wep.ic_header, origHdr, hdrlen);
513 
514 	qdf_nbuf_trim_tail(msdu, dp_f_wep.ic_trailer);
515 
516 	return QDF_STATUS_SUCCESS;
517 }
518 
519 /*
520  * dp_rx_defrag_hdrsize(): Calculate the header size of the received fragment
521  * @nbuf: Pointer to the fragment
522  *
523  * Calculate the header size of the received fragment
524  *
525  * Returns: header size (uint16_t)
526  */
527 static uint16_t dp_rx_defrag_hdrsize(qdf_nbuf_t nbuf)
528 {
529 	uint8_t *rx_tlv_hdr = qdf_nbuf_data(nbuf);
530 	uint16_t size = sizeof(struct ieee80211_frame);
531 	uint16_t fc = 0;
532 	uint32_t to_ds, fr_ds;
533 	uint8_t frm_ctrl_valid;
534 	uint16_t frm_ctrl_field;
535 
536 	to_ds = hal_rx_mpdu_get_to_ds(rx_tlv_hdr);
537 	fr_ds = hal_rx_mpdu_get_fr_ds(rx_tlv_hdr);
538 	frm_ctrl_valid = hal_rx_get_mpdu_frame_control_valid(rx_tlv_hdr);
539 	frm_ctrl_field = hal_rx_get_frame_ctrl_field(rx_tlv_hdr);
540 
541 	if (to_ds && fr_ds)
542 		size += IEEE80211_ADDR_LEN;
543 
544 	if (frm_ctrl_valid) {
545 		fc = frm_ctrl_field;
546 
547 		/* use 1-st byte for validation */
548 		if (DP_RX_DEFRAG_IEEE80211_QOS_HAS_SEQ(fc & 0xff)) {
549 			size += sizeof(uint16_t);
550 			/* use 2-nd byte for validation */
551 			if (((fc & 0xff00) >> 8) & IEEE80211_FC1_ORDER)
552 				size += sizeof(struct ieee80211_htc);
553 		}
554 	}
555 
556 	return size;
557 }
558 
559 /*
560  * dp_rx_defrag_michdr(): Calculate a pseudo MIC header
561  * @wh0: Pointer to the wireless header of the fragment
562  * @hdr: Array to hold the pseudo header
563  *
564  * Calculate a pseudo MIC header
565  *
566  * Returns: None
567  */
568 static void dp_rx_defrag_michdr(const struct ieee80211_frame *wh0,
569 				uint8_t hdr[])
570 {
571 	const struct ieee80211_frame_addr4 *wh =
572 		(const struct ieee80211_frame_addr4 *)wh0;
573 
574 	switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
575 	case IEEE80211_FC1_DIR_NODS:
576 		DP_RX_DEFRAG_IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */
577 		DP_RX_DEFRAG_IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN,
578 					   wh->i_addr2);
579 		break;
580 	case IEEE80211_FC1_DIR_TODS:
581 		DP_RX_DEFRAG_IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */
582 		DP_RX_DEFRAG_IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN,
583 					   wh->i_addr2);
584 		break;
585 	case IEEE80211_FC1_DIR_FROMDS:
586 		DP_RX_DEFRAG_IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */
587 		DP_RX_DEFRAG_IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN,
588 					   wh->i_addr3);
589 		break;
590 	case IEEE80211_FC1_DIR_DSTODS:
591 		DP_RX_DEFRAG_IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */
592 		DP_RX_DEFRAG_IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN,
593 					   wh->i_addr4);
594 		break;
595 	}
596 
597 	/*
598 	 * Bit 7 is IEEE80211_FC0_SUBTYPE_QOS for data frame, but
599 	 * it could also be set for deauth, disassoc, action, etc. for
600 	 * a mgt type frame. It comes into picture for MFP.
601 	 */
602 	if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) {
603 		if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) ==
604 				IEEE80211_FC1_DIR_DSTODS) {
605 			const struct ieee80211_qosframe_addr4 *qwh =
606 				(const struct ieee80211_qosframe_addr4 *)wh;
607 			hdr[12] = qwh->i_qos[0] & IEEE80211_QOS_TID;
608 		} else {
609 			const struct ieee80211_qosframe *qwh =
610 				(const struct ieee80211_qosframe *)wh;
611 			hdr[12] = qwh->i_qos[0] & IEEE80211_QOS_TID;
612 		}
613 	} else {
614 		hdr[12] = 0;
615 	}
616 
617 	hdr[13] = hdr[14] = hdr[15] = 0;	/* reserved */
618 }
619 
620 /*
621  * dp_rx_defrag_mic(): Calculate MIC header
622  * @key: Pointer to the key
623  * @wbuf: fragment buffer
624  * @off: Offset
625  * @data_len: Data length
626  * @mic: Array to hold MIC
627  *
628  * Calculate a pseudo MIC header
629  *
630  * Returns: QDF_STATUS
631  */
632 static QDF_STATUS dp_rx_defrag_mic(const uint8_t *key, qdf_nbuf_t wbuf,
633 		uint16_t off, uint16_t data_len, uint8_t mic[])
634 {
635 	uint8_t hdr[16] = { 0, };
636 	uint32_t l, r;
637 	const uint8_t *data;
638 	uint32_t space;
639 	int rx_desc_len = sizeof(struct rx_pkt_tlvs);
640 
641 	dp_rx_defrag_michdr((struct ieee80211_frame *)(qdf_nbuf_data(wbuf)
642 		+ rx_desc_len), hdr);
643 
644 	l = dp_rx_get_le32(key);
645 	r = dp_rx_get_le32(key + 4);
646 
647 	/* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
648 	l ^= dp_rx_get_le32(hdr);
649 	dp_rx_michael_block(l, r);
650 	l ^= dp_rx_get_le32(&hdr[4]);
651 	dp_rx_michael_block(l, r);
652 	l ^= dp_rx_get_le32(&hdr[8]);
653 	dp_rx_michael_block(l, r);
654 	l ^= dp_rx_get_le32(&hdr[12]);
655 	dp_rx_michael_block(l, r);
656 
657 	/* first buffer has special handling */
658 	data = (uint8_t *)qdf_nbuf_data(wbuf) + off;
659 	space = qdf_nbuf_len(wbuf) - off;
660 
661 	for (;; ) {
662 		if (space > data_len)
663 			space = data_len;
664 
665 		/* collect 32-bit blocks from current buffer */
666 		while (space >= sizeof(uint32_t)) {
667 			l ^= dp_rx_get_le32(data);
668 			dp_rx_michael_block(l, r);
669 			data += sizeof(uint32_t);
670 			space -= sizeof(uint32_t);
671 			data_len -= sizeof(uint32_t);
672 		}
673 		if (data_len < sizeof(uint32_t))
674 			break;
675 
676 		wbuf = qdf_nbuf_next(wbuf);
677 		if (wbuf == NULL)
678 			return QDF_STATUS_E_DEFRAG_ERROR;
679 
680 		if (space != 0) {
681 			const uint8_t *data_next;
682 			/*
683 			 * Block straddles buffers, split references.
684 			 */
685 			data_next =
686 				(uint8_t *)qdf_nbuf_data(wbuf) + off;
687 			if ((qdf_nbuf_len(wbuf)) <
688 				sizeof(uint32_t) - space) {
689 				return QDF_STATUS_E_DEFRAG_ERROR;
690 			}
691 			switch (space) {
692 			case 1:
693 				l ^= dp_rx_get_le32_split(data[0],
694 					data_next[0], data_next[1],
695 					data_next[2]);
696 				data = data_next + 3;
697 				space = (qdf_nbuf_len(wbuf) - off) - 3;
698 				break;
699 			case 2:
700 				l ^= dp_rx_get_le32_split(data[0], data[1],
701 						    data_next[0], data_next[1]);
702 				data = data_next + 2;
703 				space = (qdf_nbuf_len(wbuf) - off) - 2;
704 				break;
705 			case 3:
706 				l ^= dp_rx_get_le32_split(data[0], data[1],
707 					data[2], data_next[0]);
708 				data = data_next + 1;
709 				space = (qdf_nbuf_len(wbuf) - off) - 1;
710 				break;
711 			}
712 			dp_rx_michael_block(l, r);
713 			data_len -= sizeof(uint32_t);
714 		} else {
715 			/*
716 			 * Setup for next buffer.
717 			 */
718 			data = (uint8_t *)qdf_nbuf_data(wbuf) + off;
719 			space = qdf_nbuf_len(wbuf) - off;
720 		}
721 	}
722 	/* Last block and padding (0x5a, 4..7 x 0) */
723 	switch (data_len) {
724 	case 0:
725 		l ^= dp_rx_get_le32_split(0x5a, 0, 0, 0);
726 		break;
727 	case 1:
728 		l ^= dp_rx_get_le32_split(data[0], 0x5a, 0, 0);
729 		break;
730 	case 2:
731 		l ^= dp_rx_get_le32_split(data[0], data[1], 0x5a, 0);
732 		break;
733 	case 3:
734 		l ^= dp_rx_get_le32_split(data[0], data[1], data[2], 0x5a);
735 		break;
736 	}
737 	dp_rx_michael_block(l, r);
738 	dp_rx_michael_block(l, r);
739 	dp_rx_put_le32(mic, l);
740 	dp_rx_put_le32(mic + 4, r);
741 
742 	return QDF_STATUS_SUCCESS;
743 }
744 
745 /*
746  * dp_rx_defrag_tkip_demic(): Remove MIC header from the TKIP frame
747  * @key: Pointer to the key
748  * @msdu: fragment buffer
749  * @hdrlen: Length of the header information
750  *
751  * Remove MIC information from the TKIP frame
752  *
753  * Returns: QDF_STATUS
754  */
755 static QDF_STATUS dp_rx_defrag_tkip_demic(const uint8_t *key,
756 					qdf_nbuf_t msdu, uint16_t hdrlen)
757 {
758 	QDF_STATUS status;
759 	uint32_t pktlen = 0;
760 	uint8_t mic[IEEE80211_WEP_MICLEN];
761 	uint8_t mic0[IEEE80211_WEP_MICLEN];
762 	qdf_nbuf_t prev = NULL, next;
763 
764 	next = msdu;
765 	while (next) {
766 		pktlen += (qdf_nbuf_len(next) - hdrlen);
767 		prev = next;
768 		dp_debug("%s pktlen %u", __func__,
769 			 (uint32_t)(qdf_nbuf_len(next) - hdrlen));
770 		next = qdf_nbuf_next(next);
771 	}
772 
773 	if (!prev) {
774 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
775 			  "%s Defrag chaining failed !\n", __func__);
776 		return QDF_STATUS_E_DEFRAG_ERROR;
777 	}
778 
779 	qdf_nbuf_copy_bits(prev, qdf_nbuf_len(prev) - dp_f_tkip.ic_miclen,
780 			   dp_f_tkip.ic_miclen, (caddr_t)mic0);
781 	qdf_nbuf_trim_tail(prev, dp_f_tkip.ic_miclen);
782 	pktlen -= dp_f_tkip.ic_miclen;
783 
784 	status = dp_rx_defrag_mic(key, msdu, hdrlen,
785 				pktlen, mic);
786 
787 	if (QDF_IS_STATUS_ERROR(status))
788 		return status;
789 
790 	if (qdf_mem_cmp(mic, mic0, dp_f_tkip.ic_miclen))
791 		return QDF_STATUS_E_DEFRAG_ERROR;
792 
793 	return QDF_STATUS_SUCCESS;
794 }
795 
796 /*
797  * dp_rx_frag_pull_hdr(): Pulls the RXTLV & the 802.11 headers
798  * @nbuf: buffer pointer
799  * @hdrsize: size of the header to be pulled
800  *
801  * Pull the RXTLV & the 802.11 headers
802  *
803  * Returns: None
804  */
805 static void dp_rx_frag_pull_hdr(qdf_nbuf_t nbuf, uint16_t hdrsize)
806 {
807 	qdf_nbuf_pull_head(nbuf,
808 			RX_PKT_TLVS_LEN + hdrsize);
809 
810 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
811 		  "%s: final pktlen %d .11len %d",
812 		  __func__, (uint32_t)qdf_nbuf_len(nbuf), hdrsize);
813 }
814 
815 /*
816  * dp_rx_construct_fraglist(): Construct a nbuf fraglist
817  * @peer: Pointer to the peer
818  * @head: Pointer to list of fragments
819  * @hdrsize: Size of the header to be pulled
820  *
821  * Construct a nbuf fraglist
822  *
823  * Returns: None
824  */
825 static void
826 dp_rx_construct_fraglist(struct dp_peer *peer,
827 		qdf_nbuf_t head, uint16_t hdrsize)
828 {
829 	qdf_nbuf_t msdu = qdf_nbuf_next(head);
830 	qdf_nbuf_t rx_nbuf = msdu;
831 	uint32_t len = 0;
832 
833 	while (msdu) {
834 		dp_rx_frag_pull_hdr(msdu, hdrsize);
835 		len += qdf_nbuf_len(msdu);
836 		msdu = qdf_nbuf_next(msdu);
837 	}
838 
839 	qdf_nbuf_append_ext_list(head, rx_nbuf, len);
840 	qdf_nbuf_set_next(head, NULL);
841 
842 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
843 		  "%s: head len %d ext len %d data len %d ",
844 		  __func__,
845 		  (uint32_t)qdf_nbuf_len(head),
846 		  (uint32_t)qdf_nbuf_len(rx_nbuf),
847 		  (uint32_t)(head->data_len));
848 }
849 
850 /**
851  * dp_rx_defrag_err() - rx err handler
852  * @pdev: handle to pdev object
853  * @vdev_id: vdev id
854  * @peer_mac_addr: peer mac address
855  * @tid: TID
856  * @tsf32: TSF
857  * @err_type: error type
858  * @rx_frame: rx frame
859  * @pn: PN Number
860  * @key_id: key id
861  *
862  * This function handles rx error and send MIC error notification
863  *
864  * Return: None
865  */
866 static void dp_rx_defrag_err(struct dp_vdev *vdev, qdf_nbuf_t nbuf)
867 {
868 	struct ol_if_ops *tops = NULL;
869 	struct dp_pdev *pdev = vdev->pdev;
870 	int rx_desc_len = sizeof(struct rx_pkt_tlvs);
871 	uint8_t *orig_hdr;
872 	struct ieee80211_frame *wh;
873 
874 	orig_hdr = (uint8_t *)(qdf_nbuf_data(nbuf) + rx_desc_len);
875 	wh = (struct ieee80211_frame *)orig_hdr;
876 
877 	tops = pdev->soc->cdp_soc.ol_ops;
878 	if (tops->rx_mic_error)
879 		tops->rx_mic_error(pdev->ctrl_pdev, vdev->vdev_id, wh);
880 }
881 
882 
883 /*
884  * dp_rx_defrag_nwifi_to_8023(): Transcap 802.11 to 802.3
885  * @nbuf: Pointer to the fragment buffer
886  * @hdrsize: Size of headers
887  *
888  * Transcap the fragment from 802.11 to 802.3
889  *
890  * Returns: None
891  */
892 static void
893 dp_rx_defrag_nwifi_to_8023(qdf_nbuf_t nbuf, uint16_t hdrsize)
894 {
895 	struct llc_snap_hdr_t *llchdr;
896 	struct ethernet_hdr_t *eth_hdr;
897 	uint8_t ether_type[2];
898 	uint16_t fc = 0;
899 	union dp_align_mac_addr mac_addr;
900 	uint8_t *rx_desc_info = qdf_mem_malloc(RX_PKT_TLVS_LEN);
901 
902 	if (rx_desc_info == NULL) {
903 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
904 			"%s: Memory alloc failed ! ", __func__);
905 		QDF_ASSERT(0);
906 		return;
907 	}
908 
909 	qdf_mem_copy(rx_desc_info, qdf_nbuf_data(nbuf), RX_PKT_TLVS_LEN);
910 
911 	llchdr = (struct llc_snap_hdr_t *)(qdf_nbuf_data(nbuf) +
912 					RX_PKT_TLVS_LEN + hdrsize);
913 	qdf_mem_copy(ether_type, llchdr->ethertype, 2);
914 
915 	qdf_nbuf_pull_head(nbuf, (RX_PKT_TLVS_LEN + hdrsize +
916 				  sizeof(struct llc_snap_hdr_t) -
917 				  sizeof(struct ethernet_hdr_t)));
918 
919 	eth_hdr = (struct ethernet_hdr_t *)(qdf_nbuf_data(nbuf));
920 
921 	if (hal_rx_get_mpdu_frame_control_valid(rx_desc_info))
922 		fc = hal_rx_get_frame_ctrl_field(rx_desc_info);
923 
924 	dp_debug("%s: frame control type: 0x%x", __func__, fc);
925 
926 	switch (((fc & 0xff00) >> 8) & IEEE80211_FC1_DIR_MASK) {
927 	case IEEE80211_FC1_DIR_NODS:
928 		hal_rx_mpdu_get_addr1(rx_desc_info,
929 			&mac_addr.raw[0]);
930 		qdf_mem_copy(eth_hdr->dest_addr, &mac_addr.raw[0],
931 			IEEE80211_ADDR_LEN);
932 		hal_rx_mpdu_get_addr2(rx_desc_info,
933 			&mac_addr.raw[0]);
934 		qdf_mem_copy(eth_hdr->src_addr, &mac_addr.raw[0],
935 			IEEE80211_ADDR_LEN);
936 		break;
937 	case IEEE80211_FC1_DIR_TODS:
938 		hal_rx_mpdu_get_addr3(rx_desc_info,
939 			&mac_addr.raw[0]);
940 		qdf_mem_copy(eth_hdr->dest_addr, &mac_addr.raw[0],
941 			IEEE80211_ADDR_LEN);
942 		hal_rx_mpdu_get_addr2(rx_desc_info,
943 			&mac_addr.raw[0]);
944 		qdf_mem_copy(eth_hdr->src_addr, &mac_addr.raw[0],
945 			IEEE80211_ADDR_LEN);
946 		break;
947 	case IEEE80211_FC1_DIR_FROMDS:
948 		hal_rx_mpdu_get_addr1(rx_desc_info,
949 			&mac_addr.raw[0]);
950 		qdf_mem_copy(eth_hdr->dest_addr, &mac_addr.raw[0],
951 			IEEE80211_ADDR_LEN);
952 		hal_rx_mpdu_get_addr3(rx_desc_info,
953 			&mac_addr.raw[0]);
954 		qdf_mem_copy(eth_hdr->src_addr, &mac_addr.raw[0],
955 			IEEE80211_ADDR_LEN);
956 		break;
957 
958 	case IEEE80211_FC1_DIR_DSTODS:
959 		hal_rx_mpdu_get_addr3(rx_desc_info,
960 			&mac_addr.raw[0]);
961 		qdf_mem_copy(eth_hdr->dest_addr, &mac_addr.raw[0],
962 			IEEE80211_ADDR_LEN);
963 		hal_rx_mpdu_get_addr4(rx_desc_info,
964 			&mac_addr.raw[0]);
965 		qdf_mem_copy(eth_hdr->src_addr, &mac_addr.raw[0],
966 			IEEE80211_ADDR_LEN);
967 		break;
968 
969 	default:
970 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
971 		"%s: Unknown frame control type: 0x%x", __func__, fc);
972 	}
973 
974 	qdf_mem_copy(eth_hdr->ethertype, ether_type,
975 			sizeof(ether_type));
976 
977 	qdf_nbuf_push_head(nbuf, RX_PKT_TLVS_LEN);
978 	qdf_mem_copy(qdf_nbuf_data(nbuf), rx_desc_info, RX_PKT_TLVS_LEN);
979 	qdf_mem_free(rx_desc_info);
980 }
981 
982 /*
983  * dp_rx_defrag_reo_reinject(): Reinject the fragment chain back into REO
984  * @peer: Pointer to the peer
985  * @tid: Transmit Identifier
986  * @head: Buffer to be reinjected back
987  *
988  * Reinject the fragment chain back into REO
989  *
990  * Returns: QDF_STATUS
991  */
992  static QDF_STATUS dp_rx_defrag_reo_reinject(struct dp_peer *peer,
993 					unsigned tid, qdf_nbuf_t head)
994 {
995 	struct dp_pdev *pdev = peer->vdev->pdev;
996 	struct dp_soc *soc = pdev->soc;
997 	struct hal_buf_info buf_info;
998 	void *link_desc_va;
999 	void *msdu0, *msdu_desc_info;
1000 	void *ent_ring_desc, *ent_mpdu_desc_info, *ent_qdesc_addr;
1001 	void *dst_mpdu_desc_info, *dst_qdesc_addr;
1002 	qdf_dma_addr_t paddr;
1003 	uint32_t nbuf_len, seq_no, dst_ind;
1004 	uint32_t *mpdu_wrd;
1005 	uint32_t ret, cookie;
1006 
1007 	void *dst_ring_desc =
1008 		peer->rx_tid[tid].dst_ring_desc;
1009 	void *hal_srng = soc->reo_reinject_ring.hal_srng;
1010 
1011 	ent_ring_desc = hal_srng_src_get_next(soc->hal_soc, hal_srng);
1012 	if (!ent_ring_desc) {
1013 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
1014 			  "HAL src ring next entry NULL");
1015 		return QDF_STATUS_E_FAILURE;
1016 	}
1017 
1018 	hal_rx_reo_buf_paddr_get(dst_ring_desc, &buf_info);
1019 
1020 	link_desc_va = dp_rx_cookie_2_link_desc_va(soc, &buf_info);
1021 
1022 	qdf_assert(link_desc_va);
1023 
1024 	msdu0 = (uint8_t *)link_desc_va +
1025 		RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET;
1026 
1027 	nbuf_len = qdf_nbuf_len(head) - RX_PKT_TLVS_LEN;
1028 
1029 	HAL_RX_UNIFORM_HDR_SET(link_desc_va, OWNER, UNI_DESC_OWNER_SW);
1030 	HAL_RX_UNIFORM_HDR_SET(link_desc_va, BUFFER_TYPE,
1031 			UNI_DESC_BUF_TYPE_RX_MSDU_LINK);
1032 
1033 	/* msdu reconfig */
1034 	msdu_desc_info = (uint8_t *)msdu0 +
1035 		RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET;
1036 
1037 	dst_ind = hal_rx_msdu_reo_dst_ind_get(soc->hal_soc, link_desc_va);
1038 
1039 	qdf_mem_zero(msdu_desc_info, sizeof(struct rx_msdu_desc_info));
1040 
1041 	HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info,
1042 			FIRST_MSDU_IN_MPDU_FLAG, 1);
1043 	HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info,
1044 			LAST_MSDU_IN_MPDU_FLAG, 1);
1045 	HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info,
1046 			MSDU_CONTINUATION, 0x0);
1047 	HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info,
1048 			REO_DESTINATION_INDICATION, dst_ind);
1049 	HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info,
1050 			MSDU_LENGTH, nbuf_len);
1051 	HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info,
1052 			SA_IS_VALID, 1);
1053 	HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info,
1054 			DA_IS_VALID, 1);
1055 
1056 	/* change RX TLV's */
1057 	hal_rx_msdu_start_msdu_len_set(
1058 			qdf_nbuf_data(head), nbuf_len);
1059 
1060 	cookie = HAL_RX_BUF_COOKIE_GET(msdu0);
1061 
1062 	/* map the nbuf before reinject it into HW */
1063 	ret = qdf_nbuf_map_single(soc->osdev, head,
1064 					QDF_DMA_BIDIRECTIONAL);
1065 
1066 	if (qdf_unlikely(ret == QDF_STATUS_E_FAILURE)) {
1067 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
1068 				"%s: nbuf map failed !", __func__);
1069 		return QDF_STATUS_E_FAILURE;
1070 	}
1071 
1072 	paddr = qdf_nbuf_get_frag_paddr(head, 0);
1073 
1074 	ret = check_x86_paddr(soc, &head, &paddr, pdev);
1075 
1076 	if (ret == QDF_STATUS_E_FAILURE) {
1077 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
1078 				"%s: x86 check failed !", __func__);
1079 		return QDF_STATUS_E_FAILURE;
1080 	}
1081 
1082 	hal_rxdma_buff_addr_info_set(msdu0, paddr, cookie, DP_WBM2SW_RBM);
1083 
1084 	/* Lets fill entrance ring now !!! */
1085 	if (qdf_unlikely(hal_srng_access_start(soc->hal_soc, hal_srng))) {
1086 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
1087 		"HAL RING Access For REO entrance SRNG Failed: %pK",
1088 		hal_srng);
1089 
1090 		return QDF_STATUS_E_FAILURE;
1091 	}
1092 
1093 	paddr = (uint64_t)buf_info.paddr;
1094 	/* buf addr */
1095 	hal_rxdma_buff_addr_info_set(ent_ring_desc, paddr,
1096 				     buf_info.sw_cookie,
1097 				     HAL_RX_BUF_RBM_WBM_IDLE_DESC_LIST);
1098 	/* mpdu desc info */
1099 	ent_mpdu_desc_info = (uint8_t *)ent_ring_desc +
1100 	RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET;
1101 
1102 	dst_mpdu_desc_info = (uint8_t *)dst_ring_desc +
1103 	REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET;
1104 
1105 	qdf_mem_copy(ent_mpdu_desc_info, dst_mpdu_desc_info,
1106 				sizeof(struct rx_mpdu_desc_info));
1107 	qdf_mem_zero(ent_mpdu_desc_info, sizeof(uint32_t));
1108 
1109 	mpdu_wrd = (uint32_t *)dst_mpdu_desc_info;
1110 	seq_no = HAL_RX_MPDU_SEQUENCE_NUMBER_GET(mpdu_wrd);
1111 
1112 	HAL_RX_MPDU_DESC_INFO_SET(ent_mpdu_desc_info,
1113 			MSDU_COUNT, 0x1);
1114 	HAL_RX_MPDU_DESC_INFO_SET(ent_mpdu_desc_info,
1115 			MPDU_SEQUENCE_NUMBER, seq_no);
1116 
1117 	/* unset frag bit */
1118 	HAL_RX_MPDU_DESC_INFO_SET(ent_mpdu_desc_info,
1119 			FRAGMENT_FLAG, 0x0);
1120 
1121 	/* set sa/da valid bits */
1122 	HAL_RX_MPDU_DESC_INFO_SET(ent_mpdu_desc_info,
1123 			SA_IS_VALID, 0x1);
1124 	HAL_RX_MPDU_DESC_INFO_SET(ent_mpdu_desc_info,
1125 			DA_IS_VALID, 0x1);
1126 	HAL_RX_MPDU_DESC_INFO_SET(ent_mpdu_desc_info,
1127 			RAW_MPDU, 0x0);
1128 
1129 	/* qdesc addr */
1130 	ent_qdesc_addr = (uint8_t *)ent_ring_desc +
1131 		REO_ENTRANCE_RING_4_RX_REO_QUEUE_DESC_ADDR_31_0_OFFSET;
1132 
1133 	dst_qdesc_addr = (uint8_t *)dst_ring_desc +
1134 		REO_DESTINATION_RING_6_RX_REO_QUEUE_DESC_ADDR_31_0_OFFSET;
1135 
1136 	qdf_mem_copy(ent_qdesc_addr, dst_qdesc_addr, 8);
1137 
1138 	HAL_RX_FLD_SET(ent_ring_desc, REO_ENTRANCE_RING_5,
1139 			REO_DESTINATION_INDICATION, dst_ind);
1140 
1141 	hal_srng_access_end(soc->hal_soc, hal_srng);
1142 
1143 	DP_STATS_INC(soc, rx.reo_reinject, 1);
1144 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
1145 		  "%s: reinjection done !", __func__);
1146 	return QDF_STATUS_SUCCESS;
1147 }
1148 
1149 /*
1150  * dp_rx_defrag(): Defragment the fragment chain
1151  * @peer: Pointer to the peer
1152  * @tid: Transmit Identifier
1153  * @frag_list_head: Pointer to head list
1154  * @frag_list_tail: Pointer to tail list
1155  *
1156  * Defragment the fragment chain
1157  *
1158  * Returns: QDF_STATUS
1159  */
1160 static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
1161 			qdf_nbuf_t frag_list_head, qdf_nbuf_t frag_list_tail)
1162 {
1163 	qdf_nbuf_t tmp_next, prev;
1164 	qdf_nbuf_t cur = frag_list_head, msdu;
1165 	uint32_t index, tkip_demic = 0;
1166 	uint16_t hdr_space;
1167 	uint8_t key[DEFRAG_IEEE80211_KEY_LEN];
1168 	struct dp_vdev *vdev = peer->vdev;
1169 	struct dp_soc *soc = vdev->pdev->soc;
1170 	uint8_t status = 0;
1171 
1172 	hdr_space = dp_rx_defrag_hdrsize(cur);
1173 	index = hal_rx_msdu_is_wlan_mcast(cur) ?
1174 		dp_sec_mcast : dp_sec_ucast;
1175 
1176 	/* Remove FCS from all fragments */
1177 	while (cur) {
1178 		tmp_next = qdf_nbuf_next(cur);
1179 		qdf_nbuf_set_next(cur, NULL);
1180 		qdf_nbuf_trim_tail(cur, DEFRAG_IEEE80211_FCS_LEN);
1181 		prev = cur;
1182 		qdf_nbuf_set_next(cur, tmp_next);
1183 		cur = tmp_next;
1184 	}
1185 	cur = frag_list_head;
1186 
1187 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1188 		  "%s: index %d Security type: %d", __func__,
1189 		  index, peer->security[index].sec_type);
1190 
1191 	switch (peer->security[index].sec_type) {
1192 	case cdp_sec_type_tkip:
1193 		tkip_demic = 1;
1194 
1195 	case cdp_sec_type_tkip_nomic:
1196 		while (cur) {
1197 			tmp_next = qdf_nbuf_next(cur);
1198 			if (dp_rx_defrag_tkip_decap(cur, hdr_space)) {
1199 
1200 				QDF_TRACE(QDF_MODULE_ID_TXRX,
1201 					QDF_TRACE_LEVEL_ERROR,
1202 					"dp_rx_defrag: TKIP decap failed");
1203 
1204 				return QDF_STATUS_E_DEFRAG_ERROR;
1205 			}
1206 			cur = tmp_next;
1207 		}
1208 
1209 		/* If success, increment header to be stripped later */
1210 		hdr_space += dp_f_tkip.ic_header;
1211 		break;
1212 
1213 	case cdp_sec_type_aes_ccmp:
1214 		while (cur) {
1215 			tmp_next = qdf_nbuf_next(cur);
1216 			if (dp_rx_defrag_ccmp_demic(cur, hdr_space)) {
1217 
1218 				QDF_TRACE(QDF_MODULE_ID_TXRX,
1219 					QDF_TRACE_LEVEL_ERROR,
1220 					"dp_rx_defrag: CCMP demic failed");
1221 
1222 				return QDF_STATUS_E_DEFRAG_ERROR;
1223 			}
1224 			if (dp_rx_defrag_ccmp_decap(cur, hdr_space)) {
1225 
1226 				QDF_TRACE(QDF_MODULE_ID_TXRX,
1227 					QDF_TRACE_LEVEL_ERROR,
1228 					"dp_rx_defrag: CCMP decap failed");
1229 
1230 				return QDF_STATUS_E_DEFRAG_ERROR;
1231 			}
1232 			cur = tmp_next;
1233 		}
1234 
1235 		/* If success, increment header to be stripped later */
1236 		hdr_space += dp_f_ccmp.ic_header;
1237 		break;
1238 
1239 	case cdp_sec_type_wep40:
1240 	case cdp_sec_type_wep104:
1241 	case cdp_sec_type_wep128:
1242 		while (cur) {
1243 			tmp_next = qdf_nbuf_next(cur);
1244 			if (dp_rx_defrag_wep_decap(cur, hdr_space)) {
1245 
1246 				QDF_TRACE(QDF_MODULE_ID_TXRX,
1247 					QDF_TRACE_LEVEL_ERROR,
1248 					"dp_rx_defrag: WEP decap failed");
1249 
1250 				return QDF_STATUS_E_DEFRAG_ERROR;
1251 			}
1252 			cur = tmp_next;
1253 		}
1254 
1255 		/* If success, increment header to be stripped later */
1256 		hdr_space += dp_f_wep.ic_header;
1257 		break;
1258 	default:
1259 		QDF_TRACE(QDF_MODULE_ID_TXRX,
1260 			QDF_TRACE_LEVEL_ERROR,
1261 			"dp_rx_defrag: Did not match any security type");
1262 		break;
1263 	}
1264 
1265 	if (tkip_demic) {
1266 		msdu = frag_list_head;
1267 		if (soc->cdp_soc.ol_ops->rx_frag_tkip_demic) {
1268 			status = soc->cdp_soc.ol_ops->rx_frag_tkip_demic(
1269 				(void *)peer->ctrl_peer, msdu, hdr_space);
1270 		} else {
1271 			qdf_mem_copy(key,
1272 				     &peer->security[index].michael_key[0],
1273 				IEEE80211_WEP_MICLEN);
1274 			status = dp_rx_defrag_tkip_demic(key, msdu,
1275 							 RX_PKT_TLVS_LEN +
1276 							 hdr_space);
1277 
1278 			if (status) {
1279 				dp_rx_defrag_err(vdev, frag_list_head);
1280 
1281 				QDF_TRACE(QDF_MODULE_ID_TXRX,
1282 					  QDF_TRACE_LEVEL_ERROR,
1283 					  "%s: TKIP demic failed status %d",
1284 					  __func__, status);
1285 
1286 				return QDF_STATUS_E_DEFRAG_ERROR;
1287 			}
1288 		}
1289 	}
1290 
1291 	/* Convert the header to 802.3 header */
1292 	dp_rx_defrag_nwifi_to_8023(frag_list_head, hdr_space);
1293 	dp_rx_construct_fraglist(peer, frag_list_head, hdr_space);
1294 
1295 	return QDF_STATUS_SUCCESS;
1296 }
1297 
1298 /*
1299  * dp_rx_defrag_cleanup(): Clean up activities
1300  * @peer: Pointer to the peer
1301  * @tid: Transmit Identifier
1302  *
1303  * Returns: None
1304  */
1305 void dp_rx_defrag_cleanup(struct dp_peer *peer, unsigned tid)
1306 {
1307 	struct dp_rx_reorder_array_elem *rx_reorder_array_elem =
1308 				peer->rx_tid[tid].array;
1309 
1310 	if (!rx_reorder_array_elem) {
1311 		/*
1312 		 * if this condition is hit then somebody
1313 		 * must have reset this pointer to NULL.
1314 		 * array pointer usually points to base variable
1315 		 * of TID queue structure: "struct dp_rx_tid"
1316 		 */
1317 		QDF_ASSERT(0);
1318 		return;
1319 	}
1320 	/* Free up nbufs */
1321 	dp_rx_defrag_frames_free(rx_reorder_array_elem->head);
1322 
1323 	/* Free up saved ring descriptors */
1324 	dp_rx_clear_saved_desc_info(peer, tid);
1325 
1326 	rx_reorder_array_elem->head = NULL;
1327 	rx_reorder_array_elem->tail = NULL;
1328 	peer->rx_tid[tid].defrag_timeout_ms = 0;
1329 	peer->rx_tid[tid].curr_frag_num = 0;
1330 	peer->rx_tid[tid].curr_seq_num = 0;
1331 	peer->rx_tid[tid].head_frag_desc = NULL;
1332 }
1333 
1334 /*
1335  * dp_rx_defrag_save_info_from_ring_desc(): Save info from REO ring descriptor
1336  * @ring_desc: Pointer to the dst ring descriptor
1337  * @peer: Pointer to the peer
1338  * @tid: Transmit Identifier
1339  *
1340  * Returns: None
1341  */
1342 static QDF_STATUS dp_rx_defrag_save_info_from_ring_desc(void *ring_desc,
1343 	struct dp_rx_desc *rx_desc, struct dp_peer *peer, unsigned tid)
1344 {
1345 	void *dst_ring_desc = qdf_mem_malloc(
1346 			sizeof(struct reo_destination_ring));
1347 
1348 	if (dst_ring_desc == NULL) {
1349 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
1350 			"%s: Memory alloc failed !", __func__);
1351 		QDF_ASSERT(0);
1352 		return QDF_STATUS_E_NOMEM;
1353 	}
1354 
1355 	qdf_mem_copy(dst_ring_desc, ring_desc,
1356 		       sizeof(struct reo_destination_ring));
1357 
1358 	peer->rx_tid[tid].dst_ring_desc = dst_ring_desc;
1359 	peer->rx_tid[tid].head_frag_desc = rx_desc;
1360 
1361 	return QDF_STATUS_SUCCESS;
1362 }
1363 
1364 /*
1365  * dp_rx_defrag_store_fragment(): Store incoming fragments
1366  * @soc: Pointer to the SOC data structure
1367  * @ring_desc: Pointer to the ring descriptor
1368  * @mpdu_desc_info: MPDU descriptor info
1369  * @tid: Traffic Identifier
1370  * @rx_desc: Pointer to rx descriptor
1371  * @rx_bfs: Number of bfs consumed
1372  *
1373  * Returns: QDF_STATUS
1374  */
1375 static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
1376 			void *ring_desc,
1377 			union dp_rx_desc_list_elem_t **head,
1378 			union dp_rx_desc_list_elem_t **tail,
1379 			struct hal_rx_mpdu_desc_info *mpdu_desc_info,
1380 			unsigned tid, struct dp_rx_desc *rx_desc,
1381 			uint32_t *rx_bfs)
1382 {
1383 	struct dp_rx_reorder_array_elem *rx_reorder_array_elem;
1384 	struct dp_pdev *pdev;
1385 	struct dp_peer *peer;
1386 	uint16_t peer_id;
1387 	uint8_t fragno, more_frag, all_frag_present = 0;
1388 	uint16_t rxseq = mpdu_desc_info->mpdu_seq;
1389 	QDF_STATUS status;
1390 	struct dp_rx_tid *rx_tid;
1391 	uint8_t mpdu_sequence_control_valid;
1392 	uint8_t mpdu_frame_control_valid;
1393 	qdf_nbuf_t frag = rx_desc->nbuf;
1394 
1395 	/* Check if the packet is from a valid peer */
1396 	peer_id = DP_PEER_METADATA_PEER_ID_GET(
1397 					mpdu_desc_info->peer_meta_data);
1398 	peer = dp_peer_find_by_id(soc, peer_id);
1399 
1400 	if (!peer) {
1401 		/* We should not receive anything from unknown peer
1402 		 * however, that might happen while we are in the monitor mode.
1403 		 * We don't need to handle that here
1404 		 */
1405 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1406 			"Unknown peer, dropping the fragment");
1407 
1408 		qdf_nbuf_free(frag);
1409 		dp_rx_add_to_free_desc_list(head, tail, rx_desc);
1410 		*rx_bfs = 1;
1411 
1412 		goto end;
1413 	}
1414 
1415 	pdev = peer->vdev->pdev;
1416 	rx_tid = &peer->rx_tid[tid];
1417 
1418 	mpdu_sequence_control_valid =
1419 		hal_rx_get_mpdu_sequence_control_valid(rx_desc->rx_buf_start);
1420 
1421 	/* Invalid MPDU sequence control field, MPDU is of no use */
1422 	if (!mpdu_sequence_control_valid) {
1423 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1424 			"Invalid MPDU seq control field, dropping MPDU");
1425 		qdf_nbuf_free(frag);
1426 		dp_rx_add_to_free_desc_list(head, tail, rx_desc);
1427 		*rx_bfs = 1;
1428 
1429 		qdf_assert(0);
1430 		goto end;
1431 	}
1432 
1433 	mpdu_frame_control_valid =
1434 		hal_rx_get_mpdu_frame_control_valid(rx_desc->rx_buf_start);
1435 
1436 	/* Invalid frame control field */
1437 	if (!mpdu_frame_control_valid) {
1438 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1439 			"Invalid frame control field, dropping MPDU");
1440 		qdf_nbuf_free(frag);
1441 		dp_rx_add_to_free_desc_list(head, tail, rx_desc);
1442 		*rx_bfs = 1;
1443 
1444 		qdf_assert(0);
1445 		goto end;
1446 	}
1447 
1448 	/* Current mpdu sequence */
1449 	more_frag = dp_rx_frag_get_more_frag_bit(rx_desc->rx_buf_start);
1450 
1451 	/* HW does not populate the fragment number as of now
1452 	 * need to get from the 802.11 header
1453 	 */
1454 	fragno = dp_rx_frag_get_mpdu_frag_number(rx_desc->rx_buf_start);
1455 
1456 	rx_reorder_array_elem = peer->rx_tid[tid].array;
1457 	if (!rx_reorder_array_elem) {
1458 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1459 			  "Rcvd Fragmented pkt before peer_tid is setup");
1460 		qdf_nbuf_free(frag);
1461 		dp_rx_add_to_free_desc_list(head, tail, rx_desc);
1462 		*rx_bfs = 1;
1463 		goto end;
1464 	}
1465 
1466 	/*
1467 	 * !more_frag: no more fragments to be delivered
1468 	 * !frag_no: packet is not fragmented
1469 	 * !rx_reorder_array_elem->head: no saved fragments so far
1470 	 */
1471 	if ((!more_frag) && (!fragno) && (!rx_reorder_array_elem->head)) {
1472 		/* We should not get into this situation here.
1473 		 * It means an unfragmented packet with fragment flag
1474 		 * is delivered over the REO exception ring.
1475 		 * Typically it follows normal rx path.
1476 		 */
1477 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1478 			"Rcvd unfragmented pkt on REO Err srng, dropping");
1479 		qdf_nbuf_free(frag);
1480 		dp_rx_add_to_free_desc_list(head, tail, rx_desc);
1481 		*rx_bfs = 1;
1482 
1483 		qdf_assert(0);
1484 		goto end;
1485 	}
1486 
1487 	/* Check if the fragment is for the same sequence or a different one */
1488 	if (rx_reorder_array_elem->head) {
1489 		if (rxseq != rx_tid->curr_seq_num) {
1490 
1491 			/* Drop stored fragments if out of sequence
1492 			 * fragment is received
1493 			 */
1494 			dp_rx_reorder_flush_frag(peer, tid);
1495 
1496 			DP_STATS_INC(soc, rx.rx_frag_err, 1);
1497 			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1498 				"%s mismatch, dropping earlier sequence ",
1499 				(rxseq == rx_tid->curr_seq_num)
1500 				? "address"
1501 				: "seq number");
1502 
1503 			/*
1504 			 * The sequence number for this fragment becomes the
1505 			 * new sequence number to be processed
1506 			 */
1507 			rx_tid->curr_seq_num = rxseq;
1508 		}
1509 	} else {
1510 		/* Start of a new sequence */
1511 		dp_rx_defrag_cleanup(peer, tid);
1512 		rx_tid->curr_seq_num = rxseq;
1513 	}
1514 
1515 	/*
1516 	 * If the earlier sequence was dropped, this will be the fresh start.
1517 	 * Else, continue with next fragment in a given sequence
1518 	 */
1519 	status = dp_rx_defrag_fraglist_insert(peer, tid, &rx_reorder_array_elem->head,
1520 			&rx_reorder_array_elem->tail, frag,
1521 			&all_frag_present);
1522 
1523 	/*
1524 	 * Currently, we can have only 6 MSDUs per-MPDU, if the current
1525 	 * packet sequence has more than 6 MSDUs for some reason, we will
1526 	 * have to use the next MSDU link descriptor and chain them together
1527 	 * before reinjection
1528 	 */
1529 	if ((fragno == 0) && (status == QDF_STATUS_SUCCESS) &&
1530 			(rx_reorder_array_elem->head == frag)) {
1531 
1532 		status = dp_rx_defrag_save_info_from_ring_desc(ring_desc,
1533 					rx_desc, peer, tid);
1534 
1535 		if (status != QDF_STATUS_SUCCESS) {
1536 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
1537 				"%s: Unable to store ring desc !", __func__);
1538 			goto end;
1539 		}
1540 	} else {
1541 		dp_rx_add_to_free_desc_list(head, tail, rx_desc);
1542 		*rx_bfs = 1;
1543 
1544 		/* Return the non-head link desc */
1545 		if (dp_rx_link_desc_return(soc, ring_desc,
1546 					HAL_BM_ACTION_PUT_IN_IDLE_LIST) !=
1547 				QDF_STATUS_SUCCESS)
1548 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
1549 					"%s: Failed to return link desc",
1550 					__func__);
1551 
1552 	}
1553 
1554 	if (pdev->soc->rx.flags.defrag_timeout_check)
1555 		dp_rx_defrag_waitlist_remove(peer, tid);
1556 
1557 	/* Yet to receive more fragments for this sequence number */
1558 	if (!all_frag_present) {
1559 		uint32_t now_ms =
1560 			qdf_system_ticks_to_msecs(qdf_system_ticks());
1561 
1562 		peer->rx_tid[tid].defrag_timeout_ms =
1563 			now_ms + pdev->soc->rx.defrag.timeout_ms;
1564 
1565 		dp_rx_defrag_waitlist_add(peer, tid);
1566 		dp_peer_unref_del_find_by_id(peer);
1567 
1568 		return QDF_STATUS_SUCCESS;
1569 	}
1570 
1571 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1572 		  "All fragments received for sequence: %d", rxseq);
1573 
1574 	/* Process the fragments */
1575 	status = dp_rx_defrag(peer, tid, rx_reorder_array_elem->head,
1576 		rx_reorder_array_elem->tail);
1577 	if (QDF_IS_STATUS_ERROR(status)) {
1578 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1579 			"Fragment processing failed");
1580 
1581 		dp_rx_add_to_free_desc_list(head, tail,
1582 				peer->rx_tid[tid].head_frag_desc);
1583 		*rx_bfs = 1;
1584 
1585 		if (dp_rx_link_desc_return(soc,
1586 					peer->rx_tid[tid].dst_ring_desc,
1587 					HAL_BM_ACTION_PUT_IN_IDLE_LIST) !=
1588 				QDF_STATUS_SUCCESS)
1589 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
1590 					"%s: Failed to return link desc",
1591 					__func__);
1592 		dp_rx_defrag_cleanup(peer, tid);
1593 		goto end;
1594 	}
1595 
1596 	/* Re-inject the fragments back to REO for further processing */
1597 	status = dp_rx_defrag_reo_reinject(peer, tid,
1598 			rx_reorder_array_elem->head);
1599 	if (QDF_IS_STATUS_SUCCESS(status)) {
1600 		rx_reorder_array_elem->head = NULL;
1601 		rx_reorder_array_elem->tail = NULL;
1602 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1603 			  "Fragmented sequence successfully reinjected");
1604 	} else {
1605 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1606 		"Fragmented sequence reinjection failed");
1607 		dp_rx_return_head_frag_desc(peer, tid);
1608 	}
1609 
1610 	dp_rx_defrag_cleanup(peer, tid);
1611 
1612 	dp_peer_unref_del_find_by_id(peer);
1613 
1614 	return QDF_STATUS_SUCCESS;
1615 
1616 end:
1617 	if (peer)
1618 		dp_peer_unref_del_find_by_id(peer);
1619 
1620 	DP_STATS_INC(soc, rx.rx_frag_err, 1);
1621 	return QDF_STATUS_E_DEFRAG_ERROR;
1622 }
1623 
1624 /**
1625  * dp_rx_frag_handle() - Handles fragmented Rx frames
1626  *
1627  * @soc: core txrx main context
1628  * @ring_desc: opaque pointer to the REO error ring descriptor
1629  * @mpdu_desc_info: MPDU descriptor information from ring descriptor
1630  * @head: head of the local descriptor free-list
1631  * @tail: tail of the local descriptor free-list
1632  * @quota: No. of units (packets) that can be serviced in one shot.
1633  *
1634  * This function implements RX 802.11 fragmentation handling
1635  * The handling is mostly same as legacy fragmentation handling.
1636  * If required, this function can re-inject the frames back to
1637  * REO ring (with proper setting to by-pass fragmentation check
1638  * but use duplicate detection / re-ordering and routing these frames
1639  * to a different core.
1640  *
1641  * Return: uint32_t: No. of elements processed
1642  */
1643 uint32_t dp_rx_frag_handle(struct dp_soc *soc, void *ring_desc,
1644 		struct hal_rx_mpdu_desc_info *mpdu_desc_info,
1645 		uint8_t *mac_id,
1646 		uint32_t quota)
1647 {
1648 	uint32_t rx_bufs_used = 0;
1649 	void *link_desc_va;
1650 	struct hal_buf_info buf_info;
1651 	struct hal_rx_msdu_list msdu_list; /* per MPDU list of MSDUs */
1652 	qdf_nbuf_t msdu = NULL;
1653 	uint32_t tid, msdu_len;
1654 	int idx, rx_bfs = 0;
1655 	struct dp_pdev *pdev;
1656 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1657 	struct dp_rx_desc *rx_desc = NULL;
1658 
1659 	qdf_assert(soc);
1660 	qdf_assert(mpdu_desc_info);
1661 
1662 	/* Fragment from a valid peer */
1663 	hal_rx_reo_buf_paddr_get(ring_desc, &buf_info);
1664 
1665 	link_desc_va = dp_rx_cookie_2_link_desc_va(soc, &buf_info);
1666 
1667 	qdf_assert(link_desc_va);
1668 
1669 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH,
1670 		"Number of MSDUs to process, num_msdus: %d",
1671 		mpdu_desc_info->msdu_count);
1672 
1673 
1674 	if (qdf_unlikely(mpdu_desc_info->msdu_count == 0)) {
1675 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1676 			"Not sufficient MSDUs to process");
1677 		return rx_bufs_used;
1678 	}
1679 
1680 	/* Get msdu_list for the given MPDU */
1681 	hal_rx_msdu_list_get(soc->hal_soc, link_desc_va, &msdu_list,
1682 			     &mpdu_desc_info->msdu_count);
1683 
1684 	/* Process all MSDUs in the current MPDU */
1685 	for (idx = 0; (idx < mpdu_desc_info->msdu_count); idx++) {
1686 		struct dp_rx_desc *rx_desc =
1687 			dp_rx_cookie_2_va_rxdma_buf(soc,
1688 				msdu_list.sw_cookie[idx]);
1689 
1690 		qdf_assert_always(rx_desc);
1691 
1692 		/* all buffers in MSDU link belong to same pdev */
1693 		pdev = soc->pdev_list[rx_desc->pool_id];
1694 		*mac_id = rx_desc->pool_id;
1695 
1696 		msdu = rx_desc->nbuf;
1697 
1698 		qdf_nbuf_unmap_single(soc->osdev, msdu,
1699 				QDF_DMA_BIDIRECTIONAL);
1700 
1701 		rx_desc->rx_buf_start = qdf_nbuf_data(msdu);
1702 
1703 		msdu_len = hal_rx_msdu_start_msdu_len_get(
1704 				rx_desc->rx_buf_start);
1705 
1706 		qdf_nbuf_set_pktlen(msdu, (msdu_len + RX_PKT_TLVS_LEN));
1707 		qdf_nbuf_append_ext_list(msdu, NULL, 0);
1708 
1709 		tid = hal_rx_mpdu_start_tid_get(soc->hal_soc,
1710 						rx_desc->rx_buf_start);
1711 
1712 		/* Process fragment-by-fragment */
1713 		status = dp_rx_defrag_store_fragment(soc, ring_desc,
1714 						     &pdev->free_list_head,
1715 						     &pdev->free_list_tail,
1716 						     mpdu_desc_info,
1717 						     tid, rx_desc, &rx_bfs);
1718 
1719 		if (rx_bfs)
1720 			rx_bufs_used++;
1721 
1722 		if (!QDF_IS_STATUS_SUCCESS(status)) {
1723 			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1724 				"Rx Defrag err seq#:0x%x msdu_count:%d flags:%d",
1725 				mpdu_desc_info->mpdu_seq,
1726 				mpdu_desc_info->msdu_count,
1727 				mpdu_desc_info->mpdu_flags);
1728 
1729 			/* No point in processing rest of the fragments */
1730 			break;
1731 		}
1732 	}
1733 
1734 	if (!QDF_IS_STATUS_SUCCESS(status)) {
1735 		/* drop any remaining buffers in current descriptor */
1736 		idx++;
1737 		for (; (idx < mpdu_desc_info->msdu_count); idx++) {
1738 			rx_desc =
1739 				dp_rx_cookie_2_va_rxdma_buf(soc,
1740 							    msdu_list.sw_cookie[idx]);
1741 			qdf_assert(rx_desc);
1742 			msdu = rx_desc->nbuf;
1743 			qdf_nbuf_unmap_single(soc->osdev, msdu,
1744 					      QDF_DMA_BIDIRECTIONAL);
1745 			qdf_nbuf_free(msdu);
1746 			dp_rx_add_to_free_desc_list(&pdev->free_list_head,
1747 						    &pdev->free_list_tail,
1748 						    rx_desc);
1749 			rx_bufs_used++;
1750 		}
1751 		if (dp_rx_link_desc_return(soc, ring_desc,
1752 					   HAL_BM_ACTION_PUT_IN_IDLE_LIST) !=
1753 					   QDF_STATUS_SUCCESS)
1754 			dp_err("Failed to return link desc");
1755 	}
1756 
1757 	return rx_bufs_used;
1758 }
1759 
1760 QDF_STATUS dp_rx_defrag_add_last_frag(struct dp_soc *soc,
1761 				      struct dp_peer *peer, uint16_t tid,
1762 		uint16_t rxseq, qdf_nbuf_t nbuf)
1763 {
1764 	struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
1765 	struct dp_rx_reorder_array_elem *rx_reorder_array_elem;
1766 	uint8_t all_frag_present;
1767 	uint32_t msdu_len;
1768 	QDF_STATUS status;
1769 
1770 	rx_reorder_array_elem = peer->rx_tid[tid].array;
1771 
1772 	if (rx_reorder_array_elem->head &&
1773 	    rxseq != rx_tid->curr_seq_num) {
1774 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
1775 			  "%s: No list found for TID %d Seq# %d",
1776 				__func__, tid, rxseq);
1777 		qdf_nbuf_free(nbuf);
1778 		goto fail;
1779 	}
1780 
1781 	msdu_len = hal_rx_msdu_start_msdu_len_get(qdf_nbuf_data(nbuf));
1782 
1783 	qdf_nbuf_set_pktlen(nbuf, (msdu_len + RX_PKT_TLVS_LEN));
1784 
1785 	status = dp_rx_defrag_fraglist_insert(peer, tid,
1786 					      &rx_reorder_array_elem->head,
1787 			&rx_reorder_array_elem->tail, nbuf,
1788 			&all_frag_present);
1789 
1790 	if (QDF_IS_STATUS_ERROR(status)) {
1791 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1792 			  "%s Fragment insert failed", __func__);
1793 
1794 		goto fail;
1795 	}
1796 
1797 	if (soc->rx.flags.defrag_timeout_check)
1798 		dp_rx_defrag_waitlist_remove(peer, tid);
1799 
1800 	if (!all_frag_present) {
1801 		uint32_t now_ms =
1802 			qdf_system_ticks_to_msecs(qdf_system_ticks());
1803 
1804 		peer->rx_tid[tid].defrag_timeout_ms =
1805 			now_ms + soc->rx.defrag.timeout_ms;
1806 
1807 		dp_rx_defrag_waitlist_add(peer, tid);
1808 
1809 		return QDF_STATUS_SUCCESS;
1810 	}
1811 
1812 	status = dp_rx_defrag(peer, tid, rx_reorder_array_elem->head,
1813 			      rx_reorder_array_elem->tail);
1814 
1815 	if (QDF_IS_STATUS_ERROR(status)) {
1816 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1817 			  "%s Fragment processing failed", __func__);
1818 
1819 		dp_rx_return_head_frag_desc(peer, tid);
1820 		dp_rx_defrag_cleanup(peer, tid);
1821 
1822 		goto fail;
1823 	}
1824 
1825 	/* Re-inject the fragments back to REO for further processing */
1826 	status = dp_rx_defrag_reo_reinject(peer, tid,
1827 					   rx_reorder_array_elem->head);
1828 	if (QDF_IS_STATUS_SUCCESS(status)) {
1829 		rx_reorder_array_elem->head = NULL;
1830 		rx_reorder_array_elem->tail = NULL;
1831 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
1832 			  "%s: Frag seq successfully reinjected",
1833 			__func__);
1834 	} else {
1835 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1836 			  "%s: Frag seq reinjection failed",
1837 			__func__);
1838 		dp_rx_return_head_frag_desc(peer, tid);
1839 	}
1840 
1841 	dp_rx_defrag_cleanup(peer, tid);
1842 	return QDF_STATUS_SUCCESS;
1843 
1844 fail:
1845 	return QDF_STATUS_E_DEFRAG_ERROR;
1846 }
1847