xref: /wlan-dirver/qca-wifi-host-cmn/utils/pktlog/pktlog_internal.c (revision 503663c6daafffe652fa360bde17243568cd6d2a)
1 /*
2  * Copyright (c) 2013-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 /*
20  *
21  * Permission to use, copy, modify, and/or distribute this software for any
22  * purpose with or without fee is hereby granted, provided that the above
23  * copyright notice and this permission notice appear in all copies.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
26  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
27  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
28  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
29  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
30  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
31  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32  */
33 
34 #ifndef REMOVE_PKT_LOG
35 #include "ol_txrx_types.h"
36 #include "ol_htt_tx_api.h"
37 #include "ol_tx_desc.h"
38 #include "qdf_mem.h"
39 #include "htt.h"
40 #include "htt_internal.h"
41 #include "pktlog_ac_i.h"
42 #include "wma_api.h"
43 #include "wlan_logging_sock_svc.h"
44 
45 #define TX_DESC_ID_LOW_MASK     0xffff
46 #define TX_DESC_ID_LOW_SHIFT    0
47 #define TX_DESC_ID_HIGH_MASK    0xffff0000
48 #define TX_DESC_ID_HIGH_SHIFT   16
49 
50 #ifdef PKTLOG_HAS_SPECIFIC_DATA
51 static inline void
52 pktlog_hdr_set_specific_data(struct ath_pktlog_hdr *log_hdr,
53 			     uint32_t type_specific_data)
54 {
55 	log_hdr->type_specific_data = type_specific_data;
56 }
57 
58 static inline uint32_t
59 pktlog_hdr_get_specific_data(struct ath_pktlog_hdr *log_hdr)
60 {
61 	return log_hdr->type_specific_data;
62 }
63 
64 static inline void
65 pktlog_arg_set_specific_data(struct ath_pktlog_arg *plarg,
66 			     uint32_t type_specific_data)
67 {
68 	plarg->type_specific_data = type_specific_data;
69 }
70 
71 static inline uint32_t
72 pktlog_arg_get_specific_data(struct ath_pktlog_arg *plarg)
73 {
74 	return plarg->type_specific_data;
75 }
76 
77 #else
78 static inline void
79 pktlog_hdr_set_specific_data(struct ath_pktlog_hdr *log_hdr,
80 			     uint32_t type_specific_data)
81 {
82 }
83 
84 static inline uint32_t
85 pktlog_hdr_get_specific_data(struct ath_pktlog_hdr *log_hdr)
86 {
87 	return 0;
88 }
89 
90 static inline void
91 pktlog_arg_set_specific_data(struct ath_pktlog_arg *plarg,
92 			     uint32_t type_specific_data)
93 {
94 }
95 
96 static inline uint32_t
97 pktlog_arg_get_specific_data(struct ath_pktlog_arg *plarg)
98 {
99 	return 0;
100 }
101 #endif
102 
103 void pktlog_getbuf_intsafe(struct ath_pktlog_arg *plarg)
104 {
105 	struct ath_pktlog_buf *log_buf;
106 	int32_t buf_size;
107 	struct ath_pktlog_hdr *log_hdr;
108 	int32_t cur_wr_offset;
109 	char *log_ptr;
110 	struct ath_pktlog_info *pl_info;
111 	uint16_t log_type;
112 	size_t log_size;
113 	uint32_t flags;
114 #ifdef HELIUMPLUS
115 	uint8_t mac_id;
116 #endif
117 
118 	if (!plarg) {
119 		qdf_nofl_info("Invalid parg in %s", __func__);
120 		return;
121 	}
122 
123 	pl_info = plarg->pl_info;
124 #ifdef HELIUMPLUS
125 	mac_id = plarg->macId;
126 	log_type = plarg->log_type;
127 #else
128 	log_type = plarg->log_type;
129 #endif
130 	log_size = plarg->log_size;
131 	log_buf = pl_info->buf;
132 	flags = plarg->flags;
133 
134 	if (!log_buf) {
135 		qdf_nofl_info("Invalid log_buf in %s", __func__);
136 		return;
137 	}
138 
139 
140 	buf_size = pl_info->buf_size;
141 	cur_wr_offset = log_buf->wr_offset;
142 	/* Move read offset to the next entry if there is a buffer overlap */
143 	if (log_buf->rd_offset >= 0) {
144 		if ((cur_wr_offset <= log_buf->rd_offset)
145 		    && (cur_wr_offset + sizeof(struct ath_pktlog_hdr)) >
146 		    log_buf->rd_offset) {
147 			PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf,
148 					  buf_size);
149 		}
150 	} else {
151 		log_buf->rd_offset = cur_wr_offset;
152 	}
153 
154 	log_hdr = (struct ath_pktlog_hdr *)(log_buf->log_data + cur_wr_offset);
155 
156 	log_hdr->flags = flags;
157 #ifdef HELIUMPLUS
158 	log_hdr->macId = mac_id;
159 	log_hdr->log_type = log_type;
160 #else
161 	log_hdr->log_type = log_type;
162 #endif
163 	log_hdr->size = (uint16_t) log_size;
164 	log_hdr->missed_cnt = plarg->missed_cnt;
165 	log_hdr->timestamp = plarg->timestamp;
166 	pktlog_hdr_set_specific_data(log_hdr,
167 				     pktlog_arg_get_specific_data(plarg));
168 	cur_wr_offset += sizeof(*log_hdr);
169 
170 	if ((buf_size - cur_wr_offset) < log_size) {
171 		while ((cur_wr_offset <= log_buf->rd_offset)
172 		       && (log_buf->rd_offset < buf_size)) {
173 			PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf,
174 					  buf_size);
175 		}
176 		cur_wr_offset = 0;
177 	}
178 
179 	while ((cur_wr_offset <= log_buf->rd_offset)
180 	       && (cur_wr_offset + log_size) > log_buf->rd_offset) {
181 		PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf, buf_size);
182 	}
183 
184 	log_ptr = &(log_buf->log_data[cur_wr_offset]);
185 	cur_wr_offset += log_hdr->size;
186 
187 	log_buf->wr_offset = ((buf_size - cur_wr_offset) >=
188 			      sizeof(struct ath_pktlog_hdr)) ? cur_wr_offset :
189 			     0;
190 
191 	plarg->buf = log_ptr;
192 }
193 
194 char *pktlog_getbuf(struct pktlog_dev_t *pl_dev,
195 		    struct ath_pktlog_info *pl_info,
196 		    size_t log_size, struct ath_pktlog_hdr *pl_hdr)
197 {
198 	struct ath_pktlog_arg plarg = { 0, };
199 	uint8_t flags = 0;
200 
201 	plarg.pl_info = pl_info;
202 #ifdef HELIUMPLUS
203 	plarg.macId = pl_hdr->macId;
204 	plarg.log_type = pl_hdr->log_type;
205 #else
206 	plarg.log_type = pl_hdr->log_type;
207 #endif
208 	plarg.log_size = log_size;
209 	plarg.flags = pl_hdr->flags;
210 	plarg.missed_cnt = pl_hdr->missed_cnt;
211 	plarg.timestamp = pl_hdr->timestamp;
212 	pktlog_arg_set_specific_data(&plarg,
213 				     pktlog_hdr_get_specific_data(pl_hdr));
214 
215 	if (flags & PHFLAGS_INTERRUPT_CONTEXT) {
216 		/*
217 		 * We are already in interrupt context, no need to make it
218 		 * intsafe. call the function directly.
219 		 */
220 		pktlog_getbuf_intsafe(&plarg);
221 	} else {
222 		PKTLOG_LOCK(pl_info);
223 		pktlog_getbuf_intsafe(&plarg);
224 		PKTLOG_UNLOCK(pl_info);
225 	}
226 
227 	return plarg.buf;
228 }
229 
230 static struct txctl_frm_hdr frm_hdr;
231 
232 #ifndef HELIUMPLUS
233 static void process_ieee_hdr(void *data)
234 {
235 	uint8_t dir;
236 	struct ieee80211_frame *wh = (struct ieee80211_frame *)(data);
237 
238 	frm_hdr.framectrl = *(uint16_t *) (wh->i_fc);
239 	frm_hdr.seqctrl = *(uint16_t *) (wh->i_seq);
240 	dir = (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK);
241 
242 	if (dir == IEEE80211_FC1_DIR_TODS) {
243 		frm_hdr.bssid_tail =
244 			(wh->i_addr1[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh->
245 								      i_addr1
246 								      [QDF_MAC_ADDR_SIZE
247 								       - 1]);
248 		frm_hdr.sa_tail =
249 			(wh->i_addr2[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh->
250 								      i_addr2
251 								      [QDF_MAC_ADDR_SIZE
252 								       - 1]);
253 		frm_hdr.da_tail =
254 			(wh->i_addr3[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh->
255 								      i_addr3
256 								      [QDF_MAC_ADDR_SIZE
257 								       - 1]);
258 	} else if (dir == IEEE80211_FC1_DIR_FROMDS) {
259 		frm_hdr.bssid_tail =
260 			(wh->i_addr2[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh->
261 								      i_addr2
262 								      [QDF_MAC_ADDR_SIZE
263 								       - 1]);
264 		frm_hdr.sa_tail =
265 			(wh->i_addr3[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh->
266 								      i_addr3
267 								      [QDF_MAC_ADDR_SIZE
268 								       - 1]);
269 		frm_hdr.da_tail =
270 			(wh->i_addr1[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh->
271 								      i_addr1
272 								      [QDF_MAC_ADDR_SIZE
273 								       - 1]);
274 	} else {
275 		frm_hdr.bssid_tail =
276 			(wh->i_addr3[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh->
277 								      i_addr3
278 								      [QDF_MAC_ADDR_SIZE
279 								       - 1]);
280 		frm_hdr.sa_tail =
281 			(wh->i_addr2[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh->
282 								      i_addr2
283 								      [QDF_MAC_ADDR_SIZE
284 								       - 1]);
285 		frm_hdr.da_tail =
286 			(wh->i_addr1[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh->
287 								      i_addr1
288 								      [QDF_MAC_ADDR_SIZE
289 								       - 1]);
290 	}
291 }
292 
293 /**
294  * fill_ieee80211_hdr_data() - fill ieee802.11 data header
295  * @txrx_pdev: txrx pdev
296  * @pl_msdu_info: msdu info
297  * @data: data received from event
298  *
299  * Return: none
300  */
301 /* TODO: Platform specific function */
302 static void
303 fill_ieee80211_hdr_data(struct cdp_pdev *pdev,
304 	struct ath_pktlog_msdu_info *pl_msdu_info, void *data)
305 {
306 	uint32_t i;
307 	uint32_t *htt_tx_desc;
308 	struct ol_tx_desc_t *tx_desc;
309 	uint8_t msdu_id_offset = MSDU_ID_INFO_ID_OFFSET;
310 	uint16_t tx_desc_id;
311 	uint32_t *msdu_id_info = (uint32_t *)
312 				 ((void *)data + sizeof(struct ath_pktlog_hdr));
313 	uint32_t *msdu_id = (uint32_t *) ((char *)msdu_id_info +
314 					  msdu_id_offset);
315 	uint8_t *addr, *vap_addr;
316 	uint8_t vdev_id;
317 	qdf_nbuf_t netbuf;
318 	uint32_t len;
319 	struct ol_txrx_pdev_t *txrx_pdev = (struct ol_txrx_pdev_t *)pdev;
320 
321 
322 	pl_msdu_info->num_msdu = *msdu_id_info;
323 	pl_msdu_info->priv_size = sizeof(uint32_t) *
324 				 pl_msdu_info->num_msdu + sizeof(uint32_t);
325 
326 	if (pl_msdu_info->num_msdu > MAX_PKT_INFO_MSDU_ID) {
327 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
328 			  "%s: Invalid num_msdu count",
329 			  __func__);
330 		qdf_assert(0);
331 		return;
332 	}
333 	for (i = 0; i < pl_msdu_info->num_msdu; i++) {
334 		/*
335 		 * Handle big endianness
336 		 * Increment msdu_id once after retrieving
337 		 * lower 16 bits and uppper 16 bits
338 		 */
339 		if (!(i % 2)) {
340 			tx_desc_id = ((*msdu_id & TX_DESC_ID_LOW_MASK)
341 				      >> TX_DESC_ID_LOW_SHIFT);
342 		} else {
343 			tx_desc_id = ((*msdu_id & TX_DESC_ID_HIGH_MASK)
344 				      >> TX_DESC_ID_HIGH_SHIFT);
345 			msdu_id += 1;
346 		}
347 		if (tx_desc_id >= txrx_pdev->tx_desc.pool_size) {
348 			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
349 				"%s: drop due to invalid msdu id = %x",
350 				__func__, tx_desc_id);
351 			return;
352 		}
353 		tx_desc = ol_tx_desc_find(txrx_pdev, tx_desc_id);
354 		qdf_assert(tx_desc);
355 		netbuf = tx_desc->netbuf;
356 		htt_tx_desc = (uint32_t *) tx_desc->htt_tx_desc;
357 		qdf_assert(htt_tx_desc);
358 
359 		qdf_nbuf_peek_header(netbuf, &addr, &len);
360 
361 		if (len < (2 * QDF_MAC_ADDR_SIZE)) {
362 			qdf_print("TX frame does not have a valid address");
363 			return;
364 		}
365 		/* Adding header information for the TX data frames */
366 		vdev_id = (uint8_t) (*(htt_tx_desc +
367 				       HTT_TX_VDEV_ID_WORD) >>
368 				     HTT_TX_VDEV_ID_SHIFT) &
369 			  HTT_TX_VDEV_ID_MASK;
370 
371 		vap_addr = wma_get_vdev_address_by_vdev_id(vdev_id);
372 
373 		frm_hdr.da_tail = (addr[QDF_MAC_ADDR_SIZE - 2] << 8) |
374 				  (addr[QDF_MAC_ADDR_SIZE - 1]);
375 		frm_hdr.sa_tail =
376 			(addr[2 * QDF_MAC_ADDR_SIZE - 2] << 8) |
377 			(addr[2 * QDF_MAC_ADDR_SIZE - 1]);
378 		if (vap_addr) {
379 			frm_hdr.bssid_tail =
380 				(vap_addr[QDF_MAC_ADDR_SIZE - 2] << 8) |
381 				(vap_addr[QDF_MAC_ADDR_SIZE - 1]);
382 		} else {
383 			frm_hdr.bssid_tail = 0x0000;
384 		}
385 		pl_msdu_info->priv.msdu_len[i] = *(htt_tx_desc +
386 						  HTT_TX_MSDU_LEN_DWORD)
387 						& HTT_TX_MSDU_LEN_MASK;
388 		/*
389 		 * Add more information per MSDU
390 		 * e.g., protocol information
391 		 */
392 	}
393 
394 }
395 #endif
396 
397 #ifdef HELIUMPLUS
398 A_STATUS process_tx_info(struct cdp_pdev *txrx_pdev, void *data)
399 {
400 	/*
401 	 * Must include to process different types
402 	 * TX_CTL, TX_STATUS, TX_MSDU_ID, TX_FRM_HDR
403 	 */
404 	struct pktlog_dev_t *pl_dev = get_pktlog_handle();
405 	struct ath_pktlog_hdr pl_hdr;
406 	struct ath_pktlog_info *pl_info;
407 	uint32_t *pl_tgt_hdr;
408 	struct ol_fw_data *fw_data;
409 	uint32_t len;
410 
411 	if (!txrx_pdev) {
412 		qdf_nofl_info("Invalid pdev in %s", __func__);
413 		return A_ERROR;
414 	}
415 
416 	if (!pl_dev) {
417 		qdf_nofl_err("Invalid pktlog handle in %s", __func__);
418 		qdf_assert(pl_dev);
419 		return A_ERROR;
420 	}
421 
422 	qdf_assert(data);
423 
424 	fw_data = (struct ol_fw_data *)data;
425 	len = fw_data->len;
426 	if (len < (sizeof(uint32_t) *
427 		   (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) ||
428 		len < (sizeof(uint32_t) *
429 		       (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) ||
430 		len < (sizeof(uint32_t) *
431 		       (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) ||
432 		len < (sizeof(uint32_t) *
433 		       (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) ||
434 		len < (sizeof(uint32_t) *
435 		       (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) ||
436 		len < (sizeof(uint32_t) *
437 		       (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) {
438 		qdf_print("Invalid msdu len in %s", __func__);
439 		qdf_assert(0);
440 		return A_ERROR;
441 	}
442 
443 	pl_tgt_hdr = (uint32_t *)fw_data->data;
444 	/*
445 	 * Makes the short words (16 bits) portable b/w little endian
446 	 * and big endian
447 	 */
448 	pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) &
449 			ATH_PKTLOG_HDR_FLAGS_MASK) >>
450 		       ATH_PKTLOG_HDR_FLAGS_SHIFT;
451 	pl_hdr.flags |= PKTLOG_HDR_SIZE_16;
452 	pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) &
453 			     ATH_PKTLOG_HDR_MISSED_CNT_MASK) >>
454 			    ATH_PKTLOG_HDR_MISSED_CNT_SHIFT;
455 	pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) &
456 		   ATH_PKTLOG_HDR_LOG_TYPE_MASK) >>
457 		  ATH_PKTLOG_HDR_LOG_TYPE_SHIFT;
458 	pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) &
459 		   ATH_PKTLOG_HDR_MAC_ID_MASK) >>
460 		  ATH_PKTLOG_HDR_MAC_ID_SHIFT;
461 	pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) &
462 		       ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT;
463 	pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET);
464 	pl_hdr.type_specific_data =
465 		*(pl_tgt_hdr + ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET);
466 	pl_info = pl_dev->pl_info;
467 
468 	if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) {
469 		qdf_assert(0);
470 		return A_ERROR;
471 	}
472 
473 	if (pl_hdr.log_type == PKTLOG_TYPE_TX_CTRL) {
474 		size_t log_size = sizeof(frm_hdr) + pl_hdr.size;
475 		void *txdesc_hdr_ctl = (void *)
476 		pktlog_getbuf(pl_dev, pl_info, log_size, &pl_hdr);
477 		qdf_assert(txdesc_hdr_ctl);
478 		qdf_assert(pl_hdr.size < (370 * sizeof(u_int32_t)));
479 
480 		qdf_mem_copy(txdesc_hdr_ctl, &frm_hdr, sizeof(frm_hdr));
481 		qdf_mem_copy((char *)txdesc_hdr_ctl + sizeof(frm_hdr),
482 					((void *)fw_data->data +
483 					 sizeof(struct ath_pktlog_hdr)),
484 					 pl_hdr.size);
485 		pl_hdr.size = log_size;
486 		cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
487 						txdesc_hdr_ctl);
488 	}
489 
490 	if (pl_hdr.log_type == PKTLOG_TYPE_TX_STAT) {
491 		struct ath_pktlog_tx_status txstat_log;
492 		size_t log_size = pl_hdr.size;
493 
494 		txstat_log.ds_status = (void *)
495 				       pktlog_getbuf(pl_dev, pl_info,
496 						     log_size, &pl_hdr);
497 		qdf_assert(txstat_log.ds_status);
498 		qdf_mem_copy(txstat_log.ds_status,
499 			     ((void *)fw_data->data +
500 			      sizeof(struct ath_pktlog_hdr)),
501 			     pl_hdr.size);
502 		/* TODO: MCL specific API */
503 		cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
504 						txstat_log.ds_status);
505 	}
506 	return A_OK;
507 }
508 #else
509 A_STATUS process_tx_info(struct cdp_pdev *txrx_pdev, void *data)
510 {
511 	/*
512 	 * Must include to process different types
513 	 * TX_CTL, TX_STATUS, TX_MSDU_ID, TX_FRM_HDR
514 	 */
515 	struct pktlog_dev_t *pl_dev = get_pktlog_handle();
516 	struct ath_pktlog_hdr pl_hdr;
517 	struct ath_pktlog_info *pl_info;
518 	uint32_t *pl_tgt_hdr;
519 	struct ol_fw_data *fw_data;
520 	uint32_t len;
521 
522 	if (!txrx_pdev) {
523 		qdf_print("Invalid pdev in %s", __func__);
524 		return A_ERROR;
525 	}
526 
527 	if (!pl_dev) {
528 		qdf_nofl_err("Invalid pktlog handle in %s", __func__);
529 		qdf_assert(pl_dev);
530 		return A_ERROR;
531 	}
532 
533 	qdf_assert(data);
534 
535 	fw_data = (struct ol_fw_data *)data;
536 	len = fw_data->len;
537 	if (len < (sizeof(uint32_t) *
538 		   (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) ||
539 		len < (sizeof(uint32_t) *
540 		       (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) ||
541 		len < (sizeof(uint32_t) *
542 		       (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) ||
543 		len < (sizeof(uint32_t) *
544 		       (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) ||
545 		len < (sizeof(uint32_t) *
546 		       (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) {
547 		qdf_print("Invalid msdu len in %s", __func__);
548 		qdf_assert(0);
549 		return A_ERROR;
550 	}
551 
552 	pl_tgt_hdr = (uint32_t *)fw_data->data;
553 	/*
554 	 * Makes the short words (16 bits) portable b/w little endian
555 	 * and big endian
556 	 */
557 	pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) &
558 			ATH_PKTLOG_HDR_FLAGS_MASK) >>
559 		       ATH_PKTLOG_HDR_FLAGS_SHIFT;
560 	pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) &
561 			     ATH_PKTLOG_HDR_MISSED_CNT_MASK) >>
562 			    ATH_PKTLOG_HDR_MISSED_CNT_SHIFT;
563 	pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) &
564 			   ATH_PKTLOG_HDR_LOG_TYPE_MASK) >>
565 			  ATH_PKTLOG_HDR_LOG_TYPE_SHIFT;
566 	pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) &
567 		       ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT;
568 	pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET);
569 
570 	pktlog_hdr_set_specific_data(&pl_hdr,
571 				     *(pl_tgt_hdr +
572 				     ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET));
573 
574 	pl_info = pl_dev->pl_info;
575 
576 	if (pl_hdr.log_type == PKTLOG_TYPE_TX_FRM_HDR) {
577 		/* Valid only for the TX CTL */
578 		process_ieee_hdr(fw_data->data + sizeof(pl_hdr));
579 	}
580 
581 	if (pl_hdr.log_type == PKTLOG_TYPE_TX_VIRT_ADDR) {
582 		uint32_t desc_id = (uint32_t) *((uint32_t *)(fw_data->data +
583 						 sizeof(pl_hdr)));
584 		uint32_t vdev_id = desc_id;
585 
586 		/* if the pkt log msg is for the bcn frame the vdev id
587 		 * is piggybacked in desc_id and the MSB of the desc ID
588 		 * would be set to FF
589 		 */
590 #define BCN_DESC_ID 0xFF
591 		if ((desc_id >> 24) == BCN_DESC_ID) {
592 			void *data;
593 			uint32_t buf_size;
594 
595 			vdev_id &= 0x00FFFFFF;
596 			/* TODO: MCL specific API */
597 			data = wma_get_beacon_buffer_by_vdev_id(vdev_id,
598 								&buf_size);
599 			if (data) {
600 				/* TODO: platform specific API */
601 				process_ieee_hdr(data);
602 				qdf_mem_free(data);
603 			}
604 		} else {
605 			/*
606 			 * TODO: get the hdr content for mgmt frames from
607 			 * Tx mgmt desc pool
608 			 */
609 		}
610 	}
611 
612 	if (pl_hdr.log_type == PKTLOG_TYPE_TX_CTRL) {
613 		struct ath_pktlog_txctl txctl_log;
614 		size_t log_size = sizeof(txctl_log.priv);
615 
616 		txctl_log.txdesc_hdr_ctl = (void *)pktlog_getbuf(pl_dev,
617 								 pl_info,
618 								 log_size,
619 								 &pl_hdr);
620 
621 		if (!txctl_log.txdesc_hdr_ctl) {
622 			qdf_nofl_info
623 				("failed to get txctl_log.txdesc_hdr_ctl buf");
624 			return A_ERROR;
625 		}
626 
627 		/*
628 		 * frm hdr is currently Valid only for local frames
629 		 * Add capability to include the fmr hdr for remote frames
630 		 */
631 		txctl_log.priv.frm_hdr = frm_hdr;
632 		qdf_assert(txctl_log.priv.txdesc_ctl);
633 		qdf_assert(pl_hdr.size < sizeof(txctl_log.priv.txdesc_ctl));
634 		pl_hdr.size = (pl_hdr.size > sizeof(txctl_log.priv.txdesc_ctl))
635 			       ? sizeof(txctl_log.priv.txdesc_ctl) :
636 			       pl_hdr.size;
637 
638 		if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) {
639 			qdf_assert(0);
640 			return A_ERROR;
641 		}
642 		qdf_mem_copy((void *)&txctl_log.priv.txdesc_ctl,
643 			     ((void *)fw_data->data +
644 			      sizeof(struct ath_pktlog_hdr)),
645 			     pl_hdr.size);
646 		qdf_assert(txctl_log.txdesc_hdr_ctl);
647 		qdf_mem_copy(txctl_log.txdesc_hdr_ctl, &txctl_log.priv,
648 			     sizeof(txctl_log.priv));
649 		pl_hdr.size = log_size;
650 		cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
651 						txctl_log.txdesc_hdr_ctl);
652 		/* Add Protocol information and HT specific information */
653 	}
654 
655 	if (pl_hdr.log_type == PKTLOG_TYPE_TX_STAT) {
656 		struct ath_pktlog_tx_status txstat_log;
657 		size_t log_size = pl_hdr.size;
658 
659 		txstat_log.ds_status = (void *)
660 				       pktlog_getbuf(pl_dev, pl_info, log_size, &pl_hdr);
661 		qdf_assert(txstat_log.ds_status);
662 		qdf_mem_copy(txstat_log.ds_status,
663 			     ((void *)fw_data->data +
664 			      sizeof(struct ath_pktlog_hdr)),
665 			     pl_hdr.size);
666 
667 		cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
668 						txstat_log.ds_status);
669 	}
670 
671 	if (pl_hdr.log_type == PKTLOG_TYPE_TX_MSDU_ID) {
672 		struct ath_pktlog_msdu_info pl_msdu_info;
673 		size_t log_size;
674 
675 		qdf_mem_zero(&pl_msdu_info, sizeof(pl_msdu_info));
676 		log_size = sizeof(pl_msdu_info.priv);
677 
678 		if (pl_dev->mt_pktlog_enabled == false)
679 			fill_ieee80211_hdr_data(txrx_pdev,
680 						&pl_msdu_info, fw_data->data);
681 
682 		pl_msdu_info.ath_msdu_info = pktlog_getbuf(pl_dev, pl_info,
683 							   log_size, &pl_hdr);
684 		qdf_mem_copy((void *)&pl_msdu_info.priv.msdu_id_info,
685 			     ((void *)fw_data->data +
686 			      sizeof(struct ath_pktlog_hdr)),
687 			     sizeof(pl_msdu_info.priv.msdu_id_info));
688 		qdf_mem_copy(pl_msdu_info.ath_msdu_info, &pl_msdu_info.priv,
689 			     sizeof(pl_msdu_info.priv));
690 		cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
691 						pl_msdu_info.ath_msdu_info);
692 	}
693 
694 	return A_OK;
695 }
696 #endif
697 
698 /**
699  * process_offload_pktlog() - Process full pktlog events
700  * pdev: abstract pdev handle
701  * data: pktlog buffer
702  *
703  * Return: zero on success, non-zero on failure
704  */
705 A_STATUS
706 process_offload_pktlog(struct cdp_pdev *pdev, void *data)
707 {
708 	struct pktlog_dev_t *pl_dev = get_pktlog_handle();
709 	struct ath_pktlog_info *pl_info;
710 	struct ath_pktlog_hdr pl_hdr;
711 	uint32_t *pl_tgt_hdr;
712 	void *txdesc_hdr_ctl = NULL;
713 	size_t log_size = 0;
714 	size_t tmp_log_size = 0;
715 
716 	if (!pl_dev) {
717 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
718 			  "Invalid context in %s\n", __func__);
719 		return A_ERROR;
720 	}
721 
722 	if (!data) {
723 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
724 			  "Invalid data in %s\n", __func__);
725 		return A_ERROR;
726 	}
727 
728 	pl_tgt_hdr = (uint32_t *)data;
729 
730 	pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) &
731 			ATH_PKTLOG_HDR_FLAGS_MASK) >>
732 				ATH_PKTLOG_HDR_FLAGS_SHIFT;
733 	pl_hdr.missed_cnt =  (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) &
734 			ATH_PKTLOG_HDR_MISSED_CNT_MASK) >>
735 				ATH_PKTLOG_HDR_MISSED_CNT_SHIFT;
736 	pl_hdr.log_type =  (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) &
737 			ATH_PKTLOG_HDR_LOG_TYPE_MASK) >>
738 				ATH_PKTLOG_HDR_LOG_TYPE_SHIFT;
739 	pl_hdr.size =  (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) &
740 			ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT;
741 	pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET);
742 
743 	pktlog_hdr_set_specific_data(&pl_hdr,
744 				     *(pl_tgt_hdr +
745 				     ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET));
746 
747 	if (pl_hdr.size > MAX_PKTLOG_RECV_BUF_SIZE) {
748 		pl_dev->invalid_packets++;
749 		return A_ERROR;
750 	}
751 
752 	/*
753 	 *  Must include to process different types
754 	 *  TX_CTL, TX_STATUS, TX_MSDU_ID, TX_FRM_HDR
755 	 */
756 	pl_info = pl_dev->pl_info;
757 	tmp_log_size = sizeof(frm_hdr) + pl_hdr.size;
758 	log_size = pl_hdr.size;
759 	txdesc_hdr_ctl =
760 		(void *)pktlog_getbuf(pl_dev, pl_info, log_size, &pl_hdr);
761 	if (!txdesc_hdr_ctl) {
762 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
763 			  "Failed to allocate pktlog descriptor");
764 		return A_NO_MEMORY;
765 	}
766 	qdf_assert(txdesc_hdr_ctl);
767 	qdf_assert(pl_hdr->size < PKTLOG_MAX_TX_WORDS * sizeof(u_int32_t));
768 	qdf_mem_copy(txdesc_hdr_ctl,
769 		     ((void *)data + sizeof(struct ath_pktlog_hdr)),
770 		     pl_hdr.size);
771 	cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, txdesc_hdr_ctl);
772 
773 	return A_OK;
774 }
775 
776 /* TODO: hardware dependent function */
777 A_STATUS process_rx_info_remote(void *pdev, void *data)
778 {
779 	struct pktlog_dev_t *pl_dev = get_pktlog_handle();
780 	struct ath_pktlog_info *pl_info;
781 	struct htt_host_rx_desc_base *rx_desc;
782 	struct ath_pktlog_hdr pl_hdr;
783 	struct ath_pktlog_rx_info rxstat_log;
784 	size_t log_size;
785 	struct ol_rx_remote_data *r_data = (struct ol_rx_remote_data *)data;
786 	qdf_nbuf_t msdu;
787 
788 	if (!pdev || !r_data || !pl_dev) {
789 		qdf_print("%s: Invalid handle", __func__);
790 		return A_ERROR;
791 	}
792 
793 	pl_info = pl_dev->pl_info;
794 	msdu = r_data->msdu;
795 
796 	while (msdu) {
797 		rx_desc =
798 		   (struct htt_host_rx_desc_base *)(qdf_nbuf_data(msdu)) - 1;
799 		log_size =
800 			sizeof(*rx_desc) - sizeof(struct htt_host_fw_desc_base);
801 
802 		/*
803 		 * Construct the pktlog header pl_hdr
804 		 * Because desc is DMA'd to the host memory
805 		 */
806 		pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S);
807 		pl_hdr.missed_cnt = 0;
808 #if defined(HELIUMPLUS)
809 		pl_hdr.macId = r_data->mac_id;
810 		pl_hdr.log_type = PKTLOG_TYPE_RX_STAT;
811 		pl_hdr.flags |= PKTLOG_HDR_SIZE_16;
812 #else
813 		pl_hdr.log_type = PKTLOG_TYPE_RX_STAT;
814 #endif
815 		pl_hdr.size = sizeof(*rx_desc) -
816 			      sizeof(struct htt_host_fw_desc_base);
817 #if defined(HELIUMPLUS)
818 		pl_hdr.timestamp =
819 			rx_desc->ppdu_end.rx_pkt_end.phy_timestamp_1_lower_32;
820 		pl_hdr.type_specific_data = 0xDEADAA;
821 #else
822 		pl_hdr.timestamp = rx_desc->ppdu_end.tsf_timestamp;
823 #endif /* !defined(HELIUMPLUS) */
824 
825 		pktlog_hdr_set_specific_data(&pl_hdr, 0xDEADAA);
826 
827 		rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info,
828 							   log_size, &pl_hdr);
829 		qdf_mem_copy(rxstat_log.rx_desc, (void *)rx_desc +
830 			     sizeof(struct htt_host_fw_desc_base), pl_hdr.size);
831 		cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
832 						rxstat_log.rx_desc);
833 		msdu = qdf_nbuf_next(msdu);
834 	}
835 	return A_OK;
836 }
837 
838 #ifdef HELIUMPLUS
839 A_STATUS process_rx_info(void *pdev, void *data)
840 {
841 	struct pktlog_dev_t *pl_dev = get_pktlog_handle();
842 	struct ath_pktlog_info *pl_info;
843 	struct ath_pktlog_rx_info rxstat_log;
844 	struct ath_pktlog_hdr pl_hdr;
845 	size_t log_size;
846 	uint32_t *pl_tgt_hdr;
847 	struct ol_fw_data *fw_data;
848 	uint32_t len;
849 
850 	if (!pdev) {
851 		qdf_nofl_info("Invalid pdev in %s", __func__);
852 		return A_ERROR;
853 	}
854 
855 	pl_dev = ((struct ol_txrx_pdev_t *)pdev)->pl_dev;
856 	if (!pl_dev) {
857 		qdf_nofl_info("Invalid pl_dev in %s", __func__);
858 		return A_ERROR;
859 	}
860 
861 	fw_data = (struct ol_fw_data *)data;
862 	len = fw_data->len;
863 	if (len < (sizeof(uint32_t) *
864 		   (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) ||
865 		len < (sizeof(uint32_t) *
866 		       (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) ||
867 		len < (sizeof(uint32_t) *
868 		       (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) ||
869 		len < (sizeof(uint32_t) *
870 		       (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) ||
871 		len < (sizeof(uint32_t) *
872 		       (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) ||
873 		len < (sizeof(uint32_t) *
874 		       (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) {
875 		qdf_print("Invalid msdu len in %s", __func__);
876 		qdf_assert(0);
877 		return A_ERROR;
878 	}
879 
880 	pl_info = pl_dev->pl_info;
881 	pl_tgt_hdr = (uint32_t *)fw_data->data;
882 
883 	qdf_mem_zero(&pl_hdr, sizeof(pl_hdr));
884 	pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) &
885 			ATH_PKTLOG_HDR_FLAGS_MASK) >>
886 		       ATH_PKTLOG_HDR_FLAGS_SHIFT;
887 	pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) &
888 			     ATH_PKTLOG_HDR_MISSED_CNT_MASK) >>
889 			    ATH_PKTLOG_HDR_MISSED_CNT_SHIFT;
890 	pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) &
891 			   ATH_PKTLOG_HDR_LOG_TYPE_MASK) >>
892 			  ATH_PKTLOG_HDR_LOG_TYPE_SHIFT;
893 	pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) &
894 			   ATH_PKTLOG_HDR_MAC_ID_MASK) >>
895 			  ATH_PKTLOG_HDR_MAC_ID_SHIFT;
896 	pl_hdr.flags |= PKTLOG_HDR_SIZE_16;
897 	pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) &
898 		       ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT;
899 	pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET);
900 	if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) {
901 		qdf_assert(0);
902 		return A_ERROR;
903 	}
904 
905 	log_size = pl_hdr.size;
906 	rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info,
907 						   log_size, &pl_hdr);
908 	qdf_mem_copy(rxstat_log.rx_desc,
909 		     (void *)fw_data->data + sizeof(struct ath_pktlog_hdr),
910 		     pl_hdr.size);
911 	cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rxstat_log.rx_desc);
912 
913 	return A_OK;
914 }
915 
916 #else
917 A_STATUS process_rx_info(void *pdev, void *data)
918 {
919 	struct pktlog_dev_t *pl_dev = get_pktlog_handle();
920 	struct ath_pktlog_info *pl_info;
921 	struct ath_pktlog_rx_info rxstat_log;
922 	struct ath_pktlog_hdr pl_hdr;
923 	size_t log_size;
924 	uint32_t *pl_tgt_hdr;
925 	struct ol_fw_data *fw_data;
926 	uint32_t len;
927 
928 	if (!pdev) {
929 		qdf_nofl_info("Invalid pdev in %s", __func__);
930 		return A_ERROR;
931 	}
932 
933 	pl_dev = ((struct ol_txrx_pdev_t *)pdev)->pl_dev;
934 	if (!pl_dev) {
935 		qdf_nofl_info("Invalid pl_dev in %s", __func__);
936 		return A_ERROR;
937 	}
938 
939 	fw_data = (struct ol_fw_data *)data;
940 	len = fw_data->len;
941 	if (len < (sizeof(uint32_t) *
942 		   (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) ||
943 		len < (sizeof(uint32_t) *
944 		       (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) ||
945 		len < (sizeof(uint32_t) *
946 		       (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) ||
947 		len < (sizeof(uint32_t) *
948 		       (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) ||
949 		len < (sizeof(uint32_t) *
950 		       (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) {
951 		qdf_print("Invalid msdu len in %s", __func__);
952 		qdf_assert(0);
953 		return A_ERROR;
954 	}
955 
956 	pl_info = pl_dev->pl_info;
957 	pl_tgt_hdr = (uint32_t *)fw_data->data;
958 	qdf_mem_zero(&pl_hdr, sizeof(pl_hdr));
959 	pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) &
960 			ATH_PKTLOG_HDR_FLAGS_MASK) >>
961 		       ATH_PKTLOG_HDR_FLAGS_SHIFT;
962 	pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) &
963 			     ATH_PKTLOG_HDR_MISSED_CNT_MASK) >>
964 			    ATH_PKTLOG_HDR_MISSED_CNT_SHIFT;
965 	pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) &
966 				   ATH_PKTLOG_HDR_LOG_TYPE_MASK) >>
967 				  ATH_PKTLOG_HDR_LOG_TYPE_SHIFT;
968 	pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) &
969 		       ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT;
970 	pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET);
971 	if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) {
972 		qdf_assert(0);
973 		return A_ERROR;
974 	}
975 
976 	log_size = pl_hdr.size;
977 	rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info,
978 						   log_size, &pl_hdr);
979 	qdf_mem_copy(rxstat_log.rx_desc,
980 		     (void *)fw_data->data + sizeof(struct ath_pktlog_hdr),
981 		     pl_hdr.size);
982 	cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rxstat_log.rx_desc);
983 
984 	return A_OK;
985 }
986 #endif
987 
988 #ifdef HELIUMPLUS
989 A_STATUS process_rate_find(void *pdev, void *data)
990 {
991 	struct pktlog_dev_t *pl_dev = get_pktlog_handle();
992 	struct ath_pktlog_hdr pl_hdr;
993 	struct ath_pktlog_info *pl_info;
994 	size_t log_size;
995 	uint32_t len;
996 	struct ol_fw_data *fw_data;
997 
998 	/*
999 	 * Will be uncommented when the rate control find
1000 	 * for pktlog is implemented in the firmware.
1001 	 * Currently derived from the TX PPDU status
1002 	 */
1003 	struct ath_pktlog_rc_find rcf_log;
1004 	uint32_t *pl_tgt_hdr;
1005 
1006 	if (!pdev || !data || !pl_dev) {
1007 		qdf_print("%s: Invalid handle", __func__);
1008 		return A_ERROR;
1009 	}
1010 
1011 	fw_data = (struct ol_fw_data *)data;
1012 	len = fw_data->len;
1013 	if (len < (sizeof(uint32_t) *
1014 		   (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) ||
1015 		len < (sizeof(uint32_t) *
1016 		       (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) ||
1017 		len < (sizeof(uint32_t) *
1018 		       (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) ||
1019 		len < (sizeof(uint32_t) *
1020 		       (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) ||
1021 		len < (sizeof(uint32_t) *
1022 		       (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) ||
1023 		len < (sizeof(uint32_t) *
1024 		       (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) {
1025 		qdf_print("Invalid msdu len in %s", __func__);
1026 		qdf_assert(0);
1027 		return A_ERROR;
1028 	}
1029 
1030 	pl_tgt_hdr = (uint32_t *)fw_data->data;
1031 	/*
1032 	 * Makes the short words (16 bits) portable b/w little endian
1033 	 * and big endian
1034 	 */
1035 
1036 	qdf_mem_zero(&pl_hdr, sizeof(pl_hdr));
1037 	pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) &
1038 			ATH_PKTLOG_HDR_FLAGS_MASK) >>
1039 		       ATH_PKTLOG_HDR_FLAGS_SHIFT;
1040 	pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) &
1041 			     ATH_PKTLOG_HDR_MISSED_CNT_MASK) >>
1042 			    ATH_PKTLOG_HDR_MISSED_CNT_SHIFT;
1043 	pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) &
1044 			   ATH_PKTLOG_HDR_LOG_TYPE_MASK) >>
1045 			  ATH_PKTLOG_HDR_LOG_TYPE_SHIFT;
1046 	pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) &
1047 			   ATH_PKTLOG_HDR_MAC_ID_MASK) >>
1048 			  ATH_PKTLOG_HDR_MAC_ID_SHIFT;
1049 	pl_hdr.flags |= PKTLOG_HDR_SIZE_16;
1050 	pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) &
1051 		       ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT;
1052 	pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET);
1053 	pl_info = pl_dev->pl_info;
1054 	log_size = pl_hdr.size;
1055 	rcf_log.rcFind = (void *)pktlog_getbuf(pl_dev, pl_info,
1056 					       log_size, &pl_hdr);
1057 
1058 	if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) {
1059 		qdf_assert(0);
1060 		return A_ERROR;
1061 	}
1062 	qdf_mem_copy(rcf_log.rcFind,
1063 		     ((char *)fw_data->data + sizeof(struct ath_pktlog_hdr)),
1064 		     pl_hdr.size);
1065 	cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcf_log.rcFind);
1066 
1067 	return A_OK;
1068 }
1069 
1070 #else
1071 A_STATUS process_rate_find(void *pdev, void *data)
1072 {
1073 	struct pktlog_dev_t *pl_dev = get_pktlog_handle();
1074 	struct ath_pktlog_hdr pl_hdr;
1075 	struct ath_pktlog_info *pl_info;
1076 	size_t log_size;
1077 	uint32_t len;
1078 	struct ol_fw_data *fw_data;
1079 
1080 	/*
1081 	 * Will be uncommented when the rate control find
1082 	 * for pktlog is implemented in the firmware.
1083 	 * Currently derived from the TX PPDU status
1084 	 */
1085 	struct ath_pktlog_rc_find rcf_log;
1086 	uint32_t *pl_tgt_hdr;
1087 
1088 	if (!pdev || !data || !pl_dev) {
1089 		qdf_print("%s: Invalid handle", __func__);
1090 		return A_ERROR;
1091 	}
1092 
1093 	fw_data = (struct ol_fw_data *)data;
1094 	len = fw_data->len;
1095 	if (len < (sizeof(uint32_t) *
1096 		   (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) ||
1097 		len < (sizeof(uint32_t) *
1098 		       (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) ||
1099 		len < (sizeof(uint32_t) *
1100 		       (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) ||
1101 		len < (sizeof(uint32_t) *
1102 		       (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) ||
1103 		len < (sizeof(uint32_t) *
1104 		       (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) {
1105 		qdf_print("Invalid msdu len in %s", __func__);
1106 		qdf_assert(0);
1107 		return A_ERROR;
1108 	}
1109 
1110 	pl_tgt_hdr = (uint32_t *)fw_data->data;
1111 	/*
1112 	 * Makes the short words (16 bits) portable b/w little endian
1113 	 * and big endian
1114 	 */
1115 
1116 	qdf_mem_zero(&pl_hdr, sizeof(pl_hdr));
1117 	pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) &
1118 			ATH_PKTLOG_HDR_FLAGS_MASK) >>
1119 		       ATH_PKTLOG_HDR_FLAGS_SHIFT;
1120 	pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) &
1121 			     ATH_PKTLOG_HDR_MISSED_CNT_MASK) >>
1122 			    ATH_PKTLOG_HDR_MISSED_CNT_SHIFT;
1123 	pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) &
1124 			   ATH_PKTLOG_HDR_LOG_TYPE_MASK) >>
1125 			  ATH_PKTLOG_HDR_LOG_TYPE_SHIFT;
1126 	pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) &
1127 		       ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT;
1128 	pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET);
1129 	pl_info = pl_dev->pl_info;
1130 	log_size = pl_hdr.size;
1131 	rcf_log.rcFind = (void *)pktlog_getbuf(pl_dev, pl_info,
1132 					       log_size, &pl_hdr);
1133 
1134 	if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) {
1135 		qdf_assert(0);
1136 		return A_ERROR;
1137 	}
1138 	qdf_mem_copy(rcf_log.rcFind,
1139 		     ((char *)fw_data->data + sizeof(struct ath_pktlog_hdr)),
1140 		     pl_hdr.size);
1141 	cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcf_log.rcFind);
1142 
1143 	return A_OK;
1144 }
1145 #endif
1146 
1147 #ifdef HELIUMPLUS
1148 A_STATUS process_sw_event(void *pdev, void *data)
1149 {
1150 	struct pktlog_dev_t *pl_dev = get_pktlog_handle();
1151 	struct ath_pktlog_hdr pl_hdr;
1152 	struct ath_pktlog_info *pl_info;
1153 	size_t log_size;
1154 	uint32_t len;
1155 	struct ol_fw_data *fw_data;
1156 
1157 	/*
1158 	 * Will be uncommented when the rate control find
1159 	 * for pktlog is implemented in the firmware.
1160 	 * Currently derived from the TX PPDU status
1161 	 */
1162 	struct ath_pktlog_sw_event sw_event;
1163 	uint32_t *pl_tgt_hdr;
1164 
1165 	if (!pdev) {
1166 		qdf_print("Invalid pdev in %s", __func__);
1167 		return A_ERROR;
1168 	}
1169 	if (!data) {
1170 		qdf_print("Invalid data in %s", __func__);
1171 		return A_ERROR;
1172 	}
1173 	if (!pl_dev) {
1174 		qdf_print("Invalid pl_dev in %s", __func__);
1175 		return A_ERROR;
1176 	}
1177 
1178 	fw_data = (struct ol_fw_data *)data;
1179 	len = fw_data->len;
1180 	if (len < (sizeof(uint32_t) *
1181 		   (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) ||
1182 		len < (sizeof(uint32_t) *
1183 		       (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) ||
1184 		len < (sizeof(uint32_t) *
1185 		       (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) ||
1186 		len < (sizeof(uint32_t) *
1187 		       (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) ||
1188 		len < (sizeof(uint32_t) *
1189 		       (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) ||
1190 		len < (sizeof(uint32_t) *
1191 		       (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) {
1192 		qdf_print("Invalid msdu len in %s", __func__);
1193 		qdf_assert(0);
1194 		return A_ERROR;
1195 	}
1196 
1197 	pl_tgt_hdr = (uint32_t *)fw_data->data;
1198 	/*
1199 	 * Makes the short words (16 bits) portable b/w little endian
1200 	 * and big endian
1201 	 */
1202 	pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) &
1203 			ATH_PKTLOG_HDR_FLAGS_MASK) >>
1204 		       ATH_PKTLOG_HDR_FLAGS_SHIFT;
1205 	pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) &
1206 			     ATH_PKTLOG_HDR_MISSED_CNT_MASK) >>
1207 			    ATH_PKTLOG_HDR_MISSED_CNT_SHIFT;
1208 	pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) &
1209 			   ATH_PKTLOG_HDR_LOG_TYPE_MASK) >>
1210 			  ATH_PKTLOG_HDR_LOG_TYPE_SHIFT;
1211 	pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) &
1212 			   ATH_PKTLOG_HDR_MAC_ID_MASK) >>
1213 			  ATH_PKTLOG_HDR_MAC_ID_SHIFT;
1214 	pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) &
1215 		       ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT;
1216 	pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET);
1217 
1218 	pl_hdr.type_specific_data =
1219 		*(pl_tgt_hdr + ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET);
1220 	pl_info = pl_dev->pl_info;
1221 	log_size = pl_hdr.size;
1222 	sw_event.sw_event = (void *)pktlog_getbuf(pl_dev, pl_info,
1223 					       log_size, &pl_hdr);
1224 	if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) {
1225 		qdf_assert(0);
1226 		return A_ERROR;
1227 	}
1228 	qdf_mem_copy(sw_event.sw_event,
1229 		     ((char *)fw_data->data + sizeof(struct ath_pktlog_hdr)),
1230 		     pl_hdr.size);
1231 
1232 	cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, sw_event.sw_event);
1233 
1234 	return A_OK;
1235 }
1236 
1237 #else
1238 A_STATUS process_sw_event(void *pdev, void *data)
1239 {
1240 	struct pktlog_dev_t *pl_dev = get_pktlog_handle();
1241 	struct ath_pktlog_hdr pl_hdr;
1242 	struct ath_pktlog_info *pl_info;
1243 	size_t log_size;
1244 	uint32_t len;
1245 	struct ol_fw_data *fw_data;
1246 
1247 	/*
1248 	 * Will be uncommented when the rate control find
1249 	 * for pktlog is implemented in the firmware.
1250 	 * Currently derived from the TX PPDU status
1251 	 */
1252 	struct ath_pktlog_sw_event sw_event;
1253 	uint32_t *pl_tgt_hdr;
1254 
1255 	if (!pdev) {
1256 		qdf_print("Invalid pdev in %s", __func__);
1257 		return A_ERROR;
1258 	}
1259 	if (!data) {
1260 		qdf_print("Invalid data in %s", __func__);
1261 		return A_ERROR;
1262 	}
1263 	if (!pl_dev) {
1264 		qdf_print("Invalid pl_dev in %s", __func__);
1265 		return A_ERROR;
1266 	}
1267 
1268 	fw_data = (struct ol_fw_data *)data;
1269 	len = fw_data->len;
1270 	if (len < (sizeof(uint32_t) *
1271 		   (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) ||
1272 		len < (sizeof(uint32_t) *
1273 		       (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) ||
1274 		len < (sizeof(uint32_t) *
1275 		       (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) ||
1276 		len < (sizeof(uint32_t) *
1277 		       (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) ||
1278 		len < (sizeof(uint32_t) *
1279 		       (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) {
1280 		qdf_print("Invalid msdu len in %s", __func__);
1281 		qdf_assert(0);
1282 		return A_ERROR;
1283 	}
1284 
1285 	pl_tgt_hdr = (uint32_t *)fw_data->data;
1286 	/*
1287 	 * Makes the short words (16 bits) portable b/w little endian
1288 	 * and big endian
1289 	 */
1290 	pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) &
1291 			ATH_PKTLOG_HDR_FLAGS_MASK) >>
1292 		       ATH_PKTLOG_HDR_FLAGS_SHIFT;
1293 	pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) &
1294 			     ATH_PKTLOG_HDR_MISSED_CNT_MASK) >>
1295 			    ATH_PKTLOG_HDR_MISSED_CNT_SHIFT;
1296 	pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) &
1297 				   ATH_PKTLOG_HDR_LOG_TYPE_MASK) >>
1298 				  ATH_PKTLOG_HDR_LOG_TYPE_SHIFT;
1299 	pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) &
1300 		       ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT;
1301 	pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET);
1302 
1303 	pktlog_hdr_set_specific_data(&pl_hdr,
1304 				     *(pl_tgt_hdr +
1305 				     ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET));
1306 
1307 	pl_info = pl_dev->pl_info;
1308 	log_size = pl_hdr.size;
1309 	sw_event.sw_event = (void *)pktlog_getbuf(pl_dev, pl_info,
1310 					       log_size, &pl_hdr);
1311 	if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) {
1312 		qdf_assert(0);
1313 		return A_ERROR;
1314 	}
1315 	qdf_mem_copy(sw_event.sw_event,
1316 		     ((char *)fw_data->data + sizeof(struct ath_pktlog_hdr)),
1317 		     pl_hdr.size);
1318 
1319 	cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, sw_event.sw_event);
1320 
1321 	return A_OK;
1322 }
1323 #endif
1324 
1325 #ifdef HELIUMPLUS
1326 A_STATUS process_rate_update(void *pdev, void *data)
1327 {
1328 	struct pktlog_dev_t *pl_dev = get_pktlog_handle();
1329 	struct ath_pktlog_hdr pl_hdr;
1330 	size_t log_size;
1331 	struct ath_pktlog_info *pl_info;
1332 	struct ath_pktlog_rc_update rcu_log;
1333 	uint32_t *pl_tgt_hdr;
1334 	struct ol_fw_data *fw_data;
1335 	uint32_t len;
1336 
1337 	if (!pdev || !data || !pl_dev) {
1338 		qdf_print("%s: Invalid handle", __func__);
1339 		return A_ERROR;
1340 	}
1341 
1342 	fw_data = (struct ol_fw_data *)data;
1343 	len = fw_data->len;
1344 	if (len < (sizeof(uint32_t) *
1345 		   (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) ||
1346 		len < (sizeof(uint32_t) *
1347 		       (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) ||
1348 		len < (sizeof(uint32_t) *
1349 		       (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) ||
1350 		len < (sizeof(uint32_t) *
1351 		       (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) ||
1352 		len < (sizeof(uint32_t) *
1353 		       (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) ||
1354 		len < (sizeof(uint32_t) *
1355 		       (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) {
1356 		qdf_print("Invalid msdu len in %s", __func__);
1357 		qdf_assert(0);
1358 		return A_ERROR;
1359 	}
1360 
1361 	pl_tgt_hdr = (uint32_t *)fw_data->data;
1362 	/*
1363 	 * Makes the short words (16 bits) portable b/w little endian
1364 	 * and big endian
1365 	 */
1366 	qdf_mem_zero(&pl_hdr, sizeof(pl_hdr));
1367 	pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) &
1368 			ATH_PKTLOG_HDR_FLAGS_MASK) >>
1369 		       ATH_PKTLOG_HDR_FLAGS_SHIFT;
1370 	pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) &
1371 			     ATH_PKTLOG_HDR_MISSED_CNT_MASK) >>
1372 			    ATH_PKTLOG_HDR_MISSED_CNT_SHIFT;
1373 	pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) &
1374 			   ATH_PKTLOG_HDR_LOG_TYPE_MASK) >>
1375 			  ATH_PKTLOG_HDR_LOG_TYPE_SHIFT;
1376 	pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) &
1377 			   ATH_PKTLOG_HDR_MAC_ID_MASK) >>
1378 			  ATH_PKTLOG_HDR_MAC_ID_SHIFT;
1379 	pl_hdr.flags |= PKTLOG_HDR_SIZE_16;
1380 	pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) &
1381 		       ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT;
1382 	pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET);
1383 	log_size = pl_hdr.size;
1384 	pl_info = pl_dev->pl_info;
1385 
1386 	/*
1387 	 * Will be uncommented when the rate control update
1388 	 * for pktlog is implemented in the firmware.
1389 	 * Currently derived from the TX PPDU status
1390 	 */
1391 	rcu_log.txRateCtrl = (void *)pktlog_getbuf(pl_dev, pl_info,
1392 						   log_size, &pl_hdr);
1393 	if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) {
1394 		qdf_assert(0);
1395 		return A_ERROR;
1396 	}
1397 	qdf_mem_copy(rcu_log.txRateCtrl,
1398 		     ((char *)fw_data->data +
1399 		      sizeof(struct ath_pktlog_hdr)),
1400 		     pl_hdr.size);
1401 	cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcu_log.txRateCtrl);
1402 	return A_OK;
1403 }
1404 
1405 #else
1406 A_STATUS process_rate_update(void *pdev, void *data)
1407 {
1408 	struct pktlog_dev_t *pl_dev = get_pktlog_handle();
1409 	struct ath_pktlog_hdr pl_hdr;
1410 	size_t log_size;
1411 	struct ath_pktlog_info *pl_info;
1412 	struct ath_pktlog_rc_update rcu_log;
1413 	uint32_t *pl_tgt_hdr;
1414 	struct ol_fw_data *fw_data;
1415 	uint32_t len;
1416 
1417 	if (!pdev || !data || !pl_dev) {
1418 		qdf_print("%s: Invalid handle", __func__);
1419 		return A_ERROR;
1420 	}
1421 
1422 	fw_data = (struct ol_fw_data *)data;
1423 	len = fw_data->len;
1424 	if (len < (sizeof(uint32_t) *
1425 		   (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) ||
1426 		len < (sizeof(uint32_t) *
1427 		       (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) ||
1428 		len < (sizeof(uint32_t) *
1429 		       (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) ||
1430 		len < (sizeof(uint32_t) *
1431 		       (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) ||
1432 		len < (sizeof(uint32_t) *
1433 		       (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) {
1434 		qdf_print("Invalid msdu len in %s", __func__);
1435 		qdf_assert(0);
1436 		return A_ERROR;
1437 	}
1438 
1439 	pl_tgt_hdr = (uint32_t *)fw_data->data;
1440 	/*
1441 	 * Makes the short words (16 bits) portable b/w little endian
1442 	 * and big endian
1443 	 */
1444 	qdf_mem_zero(&pl_hdr, sizeof(pl_hdr));
1445 	pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) &
1446 			ATH_PKTLOG_HDR_FLAGS_MASK) >>
1447 		       ATH_PKTLOG_HDR_FLAGS_SHIFT;
1448 	pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) &
1449 			     ATH_PKTLOG_HDR_MISSED_CNT_MASK) >>
1450 			    ATH_PKTLOG_HDR_MISSED_CNT_SHIFT;
1451 	pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) &
1452 				   ATH_PKTLOG_HDR_LOG_TYPE_MASK) >>
1453 				  ATH_PKTLOG_HDR_LOG_TYPE_SHIFT;
1454 	pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) &
1455 		       ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT;
1456 	pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET);
1457 	log_size = pl_hdr.size;
1458 	pl_info = pl_dev->pl_info;
1459 
1460 	/*
1461 	 * Will be uncommented when the rate control update
1462 	 * for pktlog is implemented in the firmware.
1463 	 * Currently derived from the TX PPDU status
1464 	 */
1465 	rcu_log.txRateCtrl = (void *)pktlog_getbuf(pl_dev, pl_info,
1466 						   log_size, &pl_hdr);
1467 	if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) {
1468 		qdf_assert(0);
1469 		return A_ERROR;
1470 	}
1471 	qdf_mem_copy(rcu_log.txRateCtrl,
1472 		     ((char *)fw_data->data +
1473 		      sizeof(struct ath_pktlog_hdr)),
1474 		     pl_hdr.size);
1475 	cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcu_log.txRateCtrl);
1476 	return A_OK;
1477 }
1478 #endif
1479 
1480 #if  defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390) || \
1481 defined(QCA_WIFI_QCA6490)
1482 int process_rx_desc_remote(void *pdev, void *data)
1483 {
1484 	struct pktlog_dev_t *pl_dev = get_pktlog_handle();
1485 	struct ath_pktlog_hdr pl_hdr;
1486 	struct ath_pktlog_rx_info rxstat_log;
1487 	size_t log_size;
1488 	struct ath_pktlog_info *pl_info;
1489 	qdf_nbuf_t log_nbuf = (qdf_nbuf_t)data;
1490 
1491 	if (!pl_dev) {
1492 		qdf_err("Pktlog handle is NULL");
1493 		return -EINVAL;
1494 	}
1495 
1496 	pl_info = pl_dev->pl_info;
1497 	qdf_mem_zero(&pl_hdr, sizeof(pl_hdr));
1498 	pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S);
1499 	pl_hdr.missed_cnt = 0;
1500 	pl_hdr.log_type = PKTLOG_TYPE_RX_STATBUF;
1501 	pl_hdr.size = qdf_nbuf_len(log_nbuf);
1502 	pl_hdr.timestamp = 0;
1503 	log_size = pl_hdr.size;
1504 	rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info,
1505 						  log_size, &pl_hdr);
1506 
1507 	if (!rxstat_log.rx_desc) {
1508 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG,
1509 				"%s: Rx descriptor is NULL", __func__);
1510 		return -EINVAL;
1511 	}
1512 
1513 	qdf_mem_copy(rxstat_log.rx_desc, qdf_nbuf_data(log_nbuf), pl_hdr.size);
1514 	cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
1515 						rxstat_log.rx_desc);
1516 	return 0;
1517 }
1518 
1519 int
1520 process_pktlog_lite(void *context, void *log_data, uint16_t log_type)
1521 {
1522 	struct pktlog_dev_t *pl_dev = get_pktlog_handle();
1523 	struct ath_pktlog_info *pl_info;
1524 	struct ath_pktlog_hdr pl_hdr;
1525 	struct ath_pktlog_rx_info rxstat_log;
1526 	size_t log_size;
1527 	qdf_nbuf_t log_nbuf = (qdf_nbuf_t)log_data;
1528 
1529 	if (!pl_dev) {
1530 		qdf_err("Pktlog handle is NULL");
1531 		return -EINVAL;
1532 	}
1533 
1534 	pl_info = pl_dev->pl_info;
1535 	qdf_mem_zero(&pl_hdr, sizeof(pl_hdr));
1536 	pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S);
1537 	pl_hdr.missed_cnt = 0;
1538 	pl_hdr.log_type = log_type;
1539 	pl_hdr.size = qdf_nbuf_len(log_nbuf);
1540 	pl_hdr.timestamp = 0;
1541 	log_size = pl_hdr.size;
1542 	rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info,
1543 						   log_size, &pl_hdr);
1544 	if (!rxstat_log.rx_desc) {
1545 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG,
1546 			"%s: Rx descriptor is NULL", __func__);
1547 		return -EINVAL;
1548 	}
1549 
1550 	qdf_mem_copy(rxstat_log.rx_desc, qdf_nbuf_data(log_nbuf), pl_hdr.size);
1551 
1552 	cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rxstat_log.rx_desc);
1553 	return 0;
1554 }
1555 #else
1556 int process_rx_desc_remote(void *pdev, void *data)
1557 {
1558 	return 0;
1559 }
1560 int
1561 process_pktlog_lite(void *context, void *log_data, uint16_t log_type)
1562 {
1563 	return 0;
1564 }
1565 #endif
1566 #endif /*REMOVE_PKT_LOG */
1567