From cde9070d9970eef1f7ec2360586c802a16230ad8 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 10 May 2024 07:43:50 +0000
Subject: [PATCH] rtl88x2CE_WiFi_linux driver

---
 kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/dhd_debug.c | 2389 +++++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 1,657 insertions(+), 732 deletions(-)

diff --git a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/dhd_debug.c b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/dhd_debug.c
index 1c08830..e4b50cb 100644
--- a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/dhd_debug.c
+++ b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/dhd_debug.c
@@ -1,15 +1,18 @@
-/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * DHD debugability support
  *
- * Copyright (C) 1999-2019, Broadcom Corporation
- * 
+ * <<Broadcom-WL-IPTag/Open:>>
+ *
+ * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
+ *
+ * Copyright (C) 1999-2017, Broadcom Corporation
+ *
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
  * under the terms of the GNU General Public License version 2 (the "GPL"),
  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
  * following added to such license:
- * 
+ *
  *      As a special exception, the copyright holders of this software give you
  * permission to link this software with independent modules, and to copy and
  * distribute the resulting executable under terms of your choice, provided that
@@ -17,12 +20,12 @@
  * the license of that module.  An independent module is a module which is not
  * derived from this software.  The special exception does not apply to any
  * modifications of the software.
- * 
+ *
  *      Notwithstanding the above, under no circumstances may you combine this
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: dhd_debug.c 560028 2015-05-29 10:50:33Z $
+ * $Id: dhd_debug.c 701420 2017-05-24 23:20:58Z $
  */
 
 #include <typedefs.h>
@@ -31,28 +34,22 @@
 #include <bcmendian.h>
 #include <dngl_stats.h>
 #include <dhd.h>
+#include <dhd_linux.h>
 #include <dhd_dbg.h>
+#include <dhd_dbg_ring.h>
 #include <dhd_debug.h>
+#include <dhd_mschdbg.h>
+#include <dhd_bus.h>
 
 #include <event_log.h>
 #include <event_trace.h>
 #include <msgtrace.h>
 
-#define DBGRING_FLUSH_THRESHOLD(ring)		(ring->ring_size / 3)
-#define RING_STAT_TO_STATUS(ring, status) \
-	do {               \
-		strncpy(status.name, ring->name, \
-			sizeof(status.name) - 1);  \
-		status.ring_id = ring->id;     \
-		status.ring_buffer_byte_size = ring->ring_size;  \
-		status.written_bytes = ring->stat.written_bytes; \
-		status.written_records = ring->stat.written_records; \
-		status.read_bytes = ring->stat.read_bytes; \
-		status.verbose_level = ring->log_level; \
-	} while (0)
+#if defined(DHD_EVENT_LOG_FILTER)
+#include <dhd_event_log_filter.h>
+#endif /* DHD_EVENT_LOG_FILTER */
 
-#define READ_AVAIL_SPACE(w, r, d)	((w >= r) ? (w - r) : (d - r))
-
+#define DHD_PKT_INFO DHD_ERROR
 struct map_table {
 	uint16 fw_id;
 	uint16 host_id;
@@ -123,80 +120,22 @@
 	{2, EVENT_LOG_TAG_WL_ROAM_LOG, "ROAM_LOG"},
 	{1, EVENT_LOG_TAG_TRACE_WL_INFO, "WL INFO"},
 	{1, EVENT_LOG_TAG_TRACE_BTCOEX_INFO, "BTCOEX INFO"},
+#ifdef CUSTOMER_HW4_DEBUG
+	{3, EVENT_LOG_TAG_SCAN_WARN, "SCAN_WARN"},
+#else
 	{1, EVENT_LOG_TAG_SCAN_WARN, "SCAN_WARN"},
+#endif /* CUSTOMER_HW4_DEBUG */
 	{1, EVENT_LOG_TAG_SCAN_ERROR, "SCAN_ERROR"},
 	{2, EVENT_LOG_TAG_SCAN_TRACE_LOW, "SCAN_TRACE_LOW"},
 	{2, EVENT_LOG_TAG_SCAN_TRACE_HIGH, "SCAN_TRACE_HIGH"}
 };
 
-struct log_level_table fw_event_level_map[] = {
-	{1, EVENT_LOG_TAG_TRACE_WL_INFO, "WL_INFO"},
-	{1, EVENT_LOG_TAG_TRACE_BTCOEX_INFO, "BTCOEX_INFO"},
-	{2, EVENT_LOG_TAG_BEACON_LOG, "BEACON LOG"},
-};
-
-struct map_table nan_event_map[] = {
-	{TRACE_NAN_CLUSTER_STARTED, NAN_EVENT_CLUSTER_STARTED, "NAN_CLUSTER_STARTED"},
-	{TRACE_NAN_CLUSTER_JOINED, NAN_EVENT_CLUSTER_JOINED, "NAN_CLUSTER_JOINED"},
-	{TRACE_NAN_CLUSTER_MERGED, NAN_EVENT_CLUSTER_MERGED, "NAN_CLUSTER_MERGED"},
-	{TRACE_NAN_ROLE_CHANGED, NAN_EVENT_ROLE_CHANGED, "NAN_ROLE_CHANGED"},
-	{TRACE_NAN_SCAN_COMPLETE, NAN_EVENT_SCAN_COMPLETE, "NAN_SCAN_COMPLETE"},
-	{TRACE_NAN_STATUS_CHNG, NAN_EVENT_STATUS_CHNG, "NAN_STATUS_CHNG"},
-};
-
-struct log_level_table nan_event_level_map[] = {
-	{1, EVENT_LOG_TAG_NAN_ERROR, "NAN_ERROR"},
-	{2, EVENT_LOG_TAG_NAN_INFO, "NAN_INFO"},
-	{3, EVENT_LOG_TAG_NAN_DBG, "NAN_DEBUG"},
-};
-
-struct map_table nan_evt_tag_map[] = {
-	{TRACE_TAG_BSSID, WIFI_TAG_BSSID, "BSSID"},
-	{TRACE_TAG_ADDR, WIFI_TAG_ADDR, "ADDR_0"},
-};
-
 /* reference tab table */
 uint ref_tag_tbl[EVENT_LOG_TAG_MAX + 1] = {0};
 
-enum dbg_ring_state {
-	RING_STOP	= 0,	/* ring is not initialized */
-	RING_ACTIVE,	/* ring is live and logging */
-	RING_SUSPEND	/* ring is initialized but not logging */
-};
-
-struct ring_statistics {
-	/* number of bytes that was written to the buffer by driver */
-	uint32 written_bytes;
-	/* number of bytes that was read from the buffer by user land */
-	uint32 read_bytes;
-	/* number of records that was written to the buffer by driver */
-	uint32 written_records;
-};
-
-typedef struct dhd_dbg_ring {
-	int	id;		/* ring id */
-	uint8	name[DBGRING_NAME_MAX];	/* name string */
-	uint32	ring_size;	/* numbers of item in ring */
-	uint32	wp;		/* write pointer */
-	uint32	rp;		/* read pointer */
-	uint32  log_level; /* log_level */
-	uint32	threshold; /* threshold bytes */
-	void *	ring_buf;	/* pointer of actually ring buffer */
-	void *	lock;		/* spin lock for ring access */
-	struct ring_statistics stat; /* statistics */
-	enum dbg_ring_state state;	/* ring state enum */
-} dhd_dbg_ring_t;
-
-typedef struct dhd_dbg {
-	dhd_dbg_ring_t dbg_rings[DEBUG_RING_ID_MAX];
-	void *private;		/* os private_data */
-	dbg_pullreq_t pullreq;
-	dbg_urgent_noti_t urgent_notifier;
-} dhd_dbg_t;
-
 typedef struct dhddbg_loglist_item {
 	dll_t list;
-	event_log_hdr_t *hdr;
+	prcd_event_log_hdr_t prcd_log_hdr;
 } loglist_item_t;
 
 typedef struct dhbdbg_pending_item {
@@ -205,147 +144,91 @@
 	dhd_dbg_ring_entry_t *ring_entry;
 } pending_item_t;
 
-/* get next entry; offset must point to valid entry */
-static uint32
-next_entry(dhd_dbg_ring_t *ring, int32 offset)
-{
-	dhd_dbg_ring_entry_t *entry =
-		(dhd_dbg_ring_entry_t *)((uint8 *)ring->ring_buf + offset);
-
-	/*
-	 * A length == 0 record is the end of buffer marker. Wrap around and
-	 * read the message at the start of the buffer as *this* one, and
-	 * return the one after that.
-	 */
-	if (!entry->len) {
-		entry = (dhd_dbg_ring_entry_t *)ring->ring_buf;
-		return ENTRY_LENGTH(entry);
-	}
-	return offset + ENTRY_LENGTH(entry);
-}
-
-/* get record by offset; idx must point to valid entry */
-static dhd_dbg_ring_entry_t *
-get_entry(dhd_dbg_ring_t *ring, int32 offset)
-{
-	dhd_dbg_ring_entry_t *entry =
-		(dhd_dbg_ring_entry_t *)((uint8 *)ring->ring_buf + offset);
-
-	/*
-	 * A length == 0 record is the end of buffer marker. Wrap around and
-	 * read the message at the start of the buffer.
-	 */
-	if (!entry->len)
-		return (dhd_dbg_ring_entry_t *)ring->ring_buf;
-	return entry;
-}
+/* trace log entry header user space processing */
+struct tracelog_header {
+	int magic_num;
+	int buf_size;
+	int seq_num;
+};
+#define TRACE_LOG_MAGIC_NUMBER 0xEAE47C06
 
 int
-dhd_dbg_ring_pull(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len)
+dhd_dbg_push_to_ring(dhd_pub_t *dhdp, int ring_id, dhd_dbg_ring_entry_t *hdr, void *data)
 {
-	uint32 avail_len, r_len = 0;
-	unsigned long flags;
 	dhd_dbg_ring_t *ring;
-	dhd_dbg_ring_entry_t *hdr;
+	int ret = 0;
+	uint32 pending_len = 0;
 
-	if (!dhdp || !dhdp->dbg)
-		return r_len;
-	ring = &dhdp->dbg->dbg_rings[ring_id];
-	if (ring->state != RING_ACTIVE)
-		return r_len;
-
-	flags = dhd_os_spin_lock(ring->lock);
-
-	/* get a fresh pending length */
-	avail_len = READ_AVAIL_SPACE(ring->wp, ring->rp, ring->ring_size);
-	while (avail_len > 0 && buf_len > 0) {
-		hdr = get_entry(ring, ring->rp);
-		memcpy(data, hdr, ENTRY_LENGTH(hdr));
-		r_len += ENTRY_LENGTH(hdr);
-		/* update read pointer */
-		ring->rp = next_entry(ring, ring->rp);
-		data = (uint8 *)data + ENTRY_LENGTH(hdr);
-		avail_len -= ENTRY_LENGTH(hdr);
-		buf_len -= ENTRY_LENGTH(hdr);
-		ring->stat.read_bytes += ENTRY_LENGTH(hdr);
-		DHD_DBGIF(("%s read_bytes  %d\n", __FUNCTION__,
-			ring->stat.read_bytes));
-	}
-	dhd_os_spin_unlock(ring->lock, flags);
-
-	return r_len;
-}
-
-int
-dhd_dbg_ring_push(dhd_pub_t *dhdp, int ring_id, dhd_dbg_ring_entry_t *hdr, void *data)
-{
-	unsigned long flags;
-	uint32 w_len;
-	dhd_dbg_ring_t *ring;
-	dhd_dbg_ring_entry_t *w_entry;
-	if (!dhdp || !dhdp->dbg)
+	if (!dhdp || !dhdp->dbg) {
 		return BCME_BADADDR;
+	}
+
+	if (!VALID_RING(ring_id)) {
+		DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id));
+		return BCME_RANGE;
+	}
 
 	ring = &dhdp->dbg->dbg_rings[ring_id];
 
-	if (ring->state != RING_ACTIVE)
-		return BCME_OK;
+	ret = dhd_dbg_ring_push(ring, hdr, data);
+	if (ret != BCME_OK)
+		return ret;
 
-	flags = dhd_os_spin_lock(ring->lock);
+	pending_len = dhd_dbg_ring_get_pending_len(ring);
+	dhd_dbg_ring_sched_pull(ring, pending_len, dhdp->dbg->pullreq,
+			dhdp->dbg->private, ring->id);
 
-	w_len = ENTRY_LENGTH(hdr);
-	/* prep the space */
-	do {
-		if (ring->rp == ring->wp)
-			break;
-		if (ring->rp < ring->wp) {
-			if (ring->ring_size - ring->wp == w_len) {
-				if (ring->rp == 0)
-					ring->rp = next_entry(ring, ring->rp);
-				break;
-			} else if (ring->ring_size - ring->wp < w_len) {
-				if (ring->rp == 0)
-					ring->rp = next_entry(ring, ring->rp);
-				/* 0 pad insufficient tail space */
-				memset((uint8 *)ring->ring_buf + ring->wp, 0,
-				       DBG_RING_ENTRY_SIZE);
-				ring->wp = 0;
-				continue;
-			} else {
-				break;
-			}
-		}
-		if (ring->rp > ring->wp) {
-			if (ring->rp - ring->wp <= w_len) {
-				ring->rp = next_entry(ring, ring->rp);
-				continue;
-			} else {
-				break;
-			}
-		}
-	} while (1);
+	return ret;
+}
 
-	w_entry = (dhd_dbg_ring_entry_t *)((uint8 *)ring->ring_buf + ring->wp);
-	/* header */
-	memcpy(w_entry, hdr, DBG_RING_ENTRY_SIZE);
-	w_entry->len = hdr->len;
-	/* payload */
-	memcpy((char *)w_entry + DBG_RING_ENTRY_SIZE, data, w_entry->len);
-	/* update write pointer */
-	ring->wp += w_len;
-	/* update statistics */
-	ring->stat.written_records++;
-	ring->stat.written_bytes += w_len;
-	dhd_os_spin_unlock(ring->lock, flags);
-	DHD_DBGIF(("%s : written_records %d, written_bytes %d\n", __FUNCTION__,
-		ring->stat.written_records, ring->stat.written_bytes));
+dhd_dbg_ring_t *
+dhd_dbg_get_ring_from_ring_id(dhd_pub_t *dhdp, int ring_id)
+{
+	if (!dhdp || !dhdp->dbg) {
+		return NULL;
+	}
 
-	/* if the current pending size is bigger than threshold */
-	if (ring->threshold > 0 &&
-		(READ_AVAIL_SPACE(ring->wp, ring->rp, ring->ring_size) >=
-	    ring->threshold))
-		dhdp->dbg->pullreq(dhdp->dbg->private, ring->id);
-	return  BCME_OK;
+	if (!VALID_RING(ring_id)) {
+		DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id));
+		return NULL;
+	}
+
+	return &dhdp->dbg->dbg_rings[ring_id];
+}
+
+int
+dhd_dbg_pull_single_from_ring(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len,
+	bool strip_header)
+{
+	dhd_dbg_ring_t *ring;
+
+	if (!dhdp || !dhdp->dbg) {
+		return 0;
+	}
+
+	if (!VALID_RING(ring_id)) {
+		DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id));
+		return BCME_RANGE;
+	}
+
+	ring = &dhdp->dbg->dbg_rings[ring_id];
+
+	return dhd_dbg_ring_pull_single(ring, data, buf_len, strip_header);
+}
+
+int
+dhd_dbg_pull_from_ring(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len)
+{
+	dhd_dbg_ring_t *ring;
+
+	if (!dhdp || !dhdp->dbg)
+		return 0;
+	if (!VALID_RING(ring_id)) {
+		DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id));
+		return BCME_RANGE;
+	}
+	ring = &dhdp->dbg->dbg_rings[ring_id];
+	return dhd_dbg_ring_pull(ring, data, buf_len, FALSE);
 }
 
 static int
@@ -368,12 +251,18 @@
 	return 0;
 }
 
+#ifndef MACOSX_DHD
 static void
 dhd_dbg_msgtrace_msg_parser(void *event_data)
 {
 	msgtrace_hdr_t *hdr;
 	char *data, *s;
 	static uint32 seqnum_prev = 0;
+
+	if (!event_data) {
+		DHD_ERROR(("%s: event_data is NULL\n", __FUNCTION__));
+		return;
+	}
 
 	hdr = (msgtrace_hdr_t *)event_data;
 	data = (char *)event_data + MSGTRACE_HDRLEN;
@@ -403,293 +292,255 @@
 	if (*data)
 		DHD_FWLOG(("[FWLOG] %s", data));
 }
-
+#endif /* MACOSX_DHD */
 #ifdef SHOW_LOGTRACE
-static const uint8 *
-event_get_tlv(uint16 id, const char* tlvs, uint tlvs_len)
-{
-	const uint8 *pos = tlvs;
-	const uint8 *end = pos + tlvs_len;
-	tlv_log *tlv;
-	int rest;
-
-	while (pos + 1 < end) {
-		if (pos + 4 + pos[1] > end)
-			break;
-		tlv = (tlv_log *) pos;
-		if (tlv->tag == id)
-			return pos;
-		rest = tlv->len % 4; /* padding values */
-		pos += 4 + tlv->len + rest;
-	}
-	return NULL;
-}
-
 #define DATA_UNIT_FOR_LOG_CNT 4
-static int
-dhd_dbg_nan_event_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, uint32 *data)
+
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif // endif
+
+int
+replace_percent_p_to_x(char *fmt)
 {
-	int ret = BCME_OK;
-	wl_event_log_id_t nan_hdr;
-	log_nan_event_t *evt_payload;
-	uint16 evt_payload_len = 0, tot_payload_len = 0;
-	dhd_dbg_ring_entry_t msg_hdr;
-	bool evt_match = FALSE;
-	event_log_hdr_t *ts_hdr;
-	uint32 *ts_data;
-	char *tlvs, *dest_tlvs;
-	tlv_log *tlv_data;
-	int tlv_len = 0;
-	int i = 0, evt_idx = 0;
-	char eaddr_buf[ETHER_ADDR_STR_LEN];
+	int p_to_x_done = FALSE;
 
-	BCM_REFERENCE(eaddr_buf);
+	while (*fmt != '\0')
+	{
+		/* Skip characters will we see a % */
+		if (*fmt++ != '%')
+		{
+			continue;
+		}
 
-	nan_hdr.t = *data;
-	DHD_DBGIF(("%s: version %u event %x\n", __FUNCTION__, nan_hdr.version,
-		nan_hdr.event));
+		/*
+		 * Skip any flags, field width and precision:
+		 *Flags: Followed by %
+		 * #, 0, -, ' ', +
+		 */
+		if (*fmt == '#')
+			fmt++;
 
-	if (nan_hdr.version != DIAG_VERSION) {
-		DHD_ERROR(("Event payload version %u mismatch with current version %u\n",
-			nan_hdr.version, DIAG_VERSION));
-		return BCME_VERSION;
-	}
-	memset(&msg_hdr, 0, sizeof(dhd_dbg_ring_entry_t));
-	ts_hdr = (event_log_hdr_t *)((uint8 *)data - sizeof(event_log_hdr_t));
-	if (ts_hdr->tag == EVENT_LOG_TAG_TS) {
-		ts_data = (uint32 *)ts_hdr - ts_hdr->count;
-		msg_hdr.timestamp = (uint64)ts_data[0];
-		msg_hdr.flags |= DBG_RING_ENTRY_FLAGS_HAS_TIMESTAMP;
-	}
-	msg_hdr.type = DBG_RING_ENTRY_NAN_EVENT_TYPE;
-	for (i = 0; i < ARRAYSIZE(nan_event_map); i++) {
-		if (nan_event_map[i].fw_id == nan_hdr.event) {
-			evt_match = TRUE;
-			evt_idx = i;
-			break;
+		if (*fmt == '0' || *fmt == '-' || *fmt == '+')
+			fmt++;
+
+		/*
+		 * Field width:
+		 * An optional decimal digit string (with non-zero first digit)
+		 * specifying a minimum field width
+		 */
+		while (*fmt && bcm_isdigit(*fmt))
+			fmt++;
+
+		/*
+		 * Precision:
+		 * An optional precision, in the form of a period ('.')  followed by an
+		 * optional decimal digit string.
+		 */
+		if (*fmt == '.')
+		{
+			fmt++;
+			while (*fmt && bcm_isdigit(*fmt)) fmt++;
 		}
-	}
-	if (evt_match) {
-		DHD_DBGIF(("%s : event (%s)\n", __FUNCTION__, nan_event_map[evt_idx].desc));
-		/* payload length for nan event data */
-		evt_payload_len = sizeof(log_nan_event_t) +
-			(hdr->count - 2) * DATA_UNIT_FOR_LOG_CNT;
-		if ((evt_payload = MALLOC(dhdp->osh, evt_payload_len)) == NULL) {
-			DHD_ERROR(("Memory allocation failed for nan evt log (%u)\n",
-				evt_payload_len));
-			return BCME_NOMEM;
+
+		/* If %p is seen, change it to %x */
+		if (*fmt == 'p')
+		{
+			*fmt = 'x';
+			p_to_x_done = TRUE;
 		}
-		evt_payload->version = NAN_EVENT_VERSION;
-		evt_payload->event = nan_event_map[evt_idx].host_id;
-		dest_tlvs = (char *)evt_payload->tlvs;
-		tot_payload_len = sizeof(log_nan_event_t);
-		tlvs = (char *)(&data[1]);
-		tlv_len = (hdr->count - 2) * DATA_UNIT_FOR_LOG_CNT;
-		for (i = 0; i < ARRAYSIZE(nan_evt_tag_map); i++) {
-			tlv_data = (tlv_log *)event_get_tlv(nan_evt_tag_map[i].fw_id,
-				tlvs, tlv_len);
-			if (tlv_data) {
-				DHD_DBGIF(("NAN evt tlv.tag(%s), tlv.len : %d, tlv.data :  ",
-					nan_evt_tag_map[i].desc, tlv_data->len));
-				memcpy(dest_tlvs, tlv_data, sizeof(tlv_log) + tlv_data->len);
-				tot_payload_len += tlv_data->len + sizeof(tlv_log);
-				switch (tlv_data->tag) {
-					case TRACE_TAG_BSSID:
-					case TRACE_TAG_ADDR:
-						DHD_DBGIF(("%s\n",
-						bcm_ether_ntoa(
-							(const struct ether_addr *)tlv_data->value,
-							eaddr_buf)));
-					break;
-					default:
-						if (DHD_DBGIF_ON()) {
-							prhex(NULL, &tlv_data->value[0],
-								tlv_data->len);
-						}
-					break;
-				}
-				dest_tlvs += tlv_data->len + sizeof(tlv_log);
-			}
-		}
-		msg_hdr.flags |= DBG_RING_ENTRY_FLAGS_HAS_BINARY;
-		msg_hdr.len = tot_payload_len;
-		dhd_dbg_ring_push(dhdp, NAN_EVENT_RING_ID, &msg_hdr, evt_payload);
-		MFREE(dhdp->osh, evt_payload, evt_payload_len);
+		if (*fmt)
+			fmt++;
 	}
-	return ret;
+
+	return p_to_x_done;
 }
 
-static int
-dhd_dbg_custom_evnt_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, uint32 *data)
+/* To identify format of types %Ns where N >= 0 is a number */
+bool
+check_valid_string_format(char *curr_ptr)
 {
-	int i = 0, match_idx = 0;
-	int payload_len, tlv_len;
-	uint16 tot_payload_len = 0;
-	int ret = BCME_OK;
-	int log_level;
-	wl_event_log_id_t wl_log_id;
-	dhd_dbg_ring_entry_t msg_hdr;
-	log_conn_event_t *event_data;
-	bool evt_match = FALSE;
-	event_log_hdr_t *ts_hdr;
-	uint32 *ts_data;
-	char *tlvs, *dest_tlvs;
-	tlv_log *tlv_data;
-	static uint64 ts_saved = 0;
-	char eabuf[ETHER_ADDR_STR_LEN];
-	char chanbuf[CHANSPEC_STR_LEN];
-
-	BCM_REFERENCE(eabuf);
-	BCM_REFERENCE(chanbuf);
-	/* get a event type and version */
-	wl_log_id.t = *data;
-	if (wl_log_id.version != DIAG_VERSION)
-		return BCME_VERSION;
-
-	ts_hdr = (event_log_hdr_t *)((uint8 *)data - sizeof(event_log_hdr_t));
-	if (ts_hdr->tag == EVENT_LOG_TAG_TS) {
-		ts_data = (uint32 *)ts_hdr - ts_hdr->count;
-		ts_saved = (uint64)ts_data[0];
-	}
-	memset(&msg_hdr, 0, sizeof(dhd_dbg_ring_entry_t));
-	msg_hdr.timestamp = ts_saved;
-
-	DHD_DBGIF(("Android Event ver %d, payload %d words, ts %llu\n",
-		(*data >> 16), hdr->count - 1, ts_saved));
-
-	/* Perform endian convertion */
-	for (i = 0; i < hdr->count; i++) {
-		/* *(data + i) = ntoh32(*(data + i)); */
-		DHD_DATA(("%08x ", *(data + i)));
-	}
-	DHD_DATA(("\n"));
-	msg_hdr.flags |= DBG_RING_ENTRY_FLAGS_HAS_TIMESTAMP;
-	msg_hdr.flags |= DBG_RING_ENTRY_FLAGS_HAS_BINARY;
-	msg_hdr.type = DBG_RING_ENTRY_EVENT_TYPE;
-
-	/* convert the data to log_conn_event_t format */
-	for (i = 0; i < ARRAYSIZE(event_map); i++) {
-		if (event_map[i].fw_id == wl_log_id.event) {
-			evt_match = TRUE;
-			match_idx = i;
-			break;
+	char *next_ptr;
+	if ((next_ptr = bcmstrstr(curr_ptr, "s")) != NULL) {
+		/* Default %s format */
+		if (curr_ptr == next_ptr) {
+			return TRUE;
 		}
-	}
-	if (evt_match) {
-		log_level = dhdp->dbg->dbg_rings[FW_EVENT_RING_ID].log_level;
-		/* filter the data based on log_level */
-		for (i = 0; i < ARRAYSIZE(fw_event_level_map); i++) {
-			if ((fw_event_level_map[i].tag == hdr->tag) &&
-				(fw_event_level_map[i].log_level > log_level)) {
-				return BCME_OK;
+
+		/* Verify each charater between '%' and 's' is a valid number */
+		while (curr_ptr < next_ptr) {
+			if (bcm_isdigit(*curr_ptr) == FALSE) {
+				return FALSE;
 			}
+			curr_ptr++;
 		}
-		DHD_DBGIF(("%s : event (%s)\n", __FUNCTION__, event_map[match_idx].desc));
-		/* get the payload length for event data (skip : log header + timestamp) */
-		payload_len = sizeof(log_conn_event_t) + DATA_UNIT_FOR_LOG_CNT * (hdr->count - 2);
-		event_data = MALLOC(dhdp->osh, payload_len);
-		if (!event_data) {
-			DHD_ERROR(("failed to allocate the log_conn_event_t with length(%d)\n",
-				payload_len));
-			return BCME_NOMEM;
-		}
-		event_data->event = event_map[match_idx].host_id;
-		dest_tlvs = (char *)event_data->tlvs;
-		tot_payload_len = sizeof(log_conn_event_t);
-		tlvs = (char *)(&data[1]);
-		tlv_len = (hdr->count - 2) * DATA_UNIT_FOR_LOG_CNT;
-		for (i = 0; i < ARRAYSIZE(event_tag_map); i++) {
-			tlv_data = (tlv_log *)event_get_tlv(event_tag_map[i].fw_id, tlvs, tlv_len);
-			if (tlv_data) {
-				DHD_DBGIF(("tlv.tag(%s), tlv.len : %d, tlv.data :  ",
-					event_tag_map[i].desc, tlv_data->len));
-				memcpy(dest_tlvs, tlv_data, sizeof(tlv_log) + tlv_data->len);
-				tot_payload_len += tlv_data->len + sizeof(tlv_log);
-				switch (tlv_data->tag) {
-				case TRACE_TAG_BSSID:
-				case TRACE_TAG_ADDR:
-				case TRACE_TAG_ADDR1:
-				case TRACE_TAG_ADDR2:
-				case TRACE_TAG_ADDR3:
-				case TRACE_TAG_ADDR4:
-					DHD_DBGIF(("%s\n",
-					bcm_ether_ntoa((const struct ether_addr *)tlv_data->value,
-							eabuf)));
-					break;
-				case TRACE_TAG_SSID:
-					DHD_DBGIF(("%s\n", tlv_data->value));
-					break;
-				case TRACE_TAG_STATUS:
-					DHD_DBGIF(("%d\n", ltoh32_ua(&tlv_data->value[0])));
-					break;
-				case TRACE_TAG_REASON_CODE:
-					DHD_DBGIF(("%d\n", ltoh16_ua(&tlv_data->value[0])));
-					break;
-				case TRACE_TAG_RATE_MBPS:
-					DHD_DBGIF(("%d Kbps\n",
-						ltoh16_ua(&tlv_data->value[0]) * 500));
-					break;
-				case TRACE_TAG_CHANNEL_SPEC:
-					DHD_DBGIF(("%s\n",
-						wf_chspec_ntoa(
-							ltoh16_ua(&tlv_data->value[0]), chanbuf)));
-					break;
-				default:
-					if (DHD_DBGIF_ON()) {
-						prhex(NULL, &tlv_data->value[0], tlv_data->len);
-					}
+
+		return TRUE;
+	} else {
+		return FALSE;
+	}
+}
+
+/* To identify format of non string format types */
+bool
+check_valid_non_string_format(char *curr_ptr)
+{
+	char *next_ptr;
+	char *next_fmt_stptr;
+	char valid_fmt_types[17] = {'d', 'i', 'x', 'X', 'c', 'p', 'u',
+			'f', 'F', 'e', 'E', 'g', 'G', 'o',
+			'a', 'A', 'n'};
+	int i;
+	bool valid = FALSE;
+
+	/* Check for next % in the fmt str */
+	next_fmt_stptr = bcmstrstr(curr_ptr, "%");
+
+	for (next_ptr = curr_ptr; *next_ptr != '\0'; next_ptr++) {
+		for (i = 0; i < (int)((sizeof(valid_fmt_types))/sizeof(valid_fmt_types[0])); i++) {
+			if (*next_ptr == valid_fmt_types[i]) {
+				/* Check whether format type found corresponds to current %
+				 * and not the next one, if exists.
+				 */
+				if ((next_fmt_stptr == NULL) ||
+						(next_fmt_stptr && (next_ptr < next_fmt_stptr))) {
+					/* Not validating for length/width fields in
+					 * format specifier.
+					 */
+					valid = TRUE;
 				}
-				dest_tlvs += tlv_data->len + sizeof(tlv_log);
+				goto done;
 			}
 		}
-		msg_hdr.len = tot_payload_len;
-		dhd_dbg_ring_push(dhdp, FW_EVENT_RING_ID, &msg_hdr, event_data);
-		MFREE(dhdp->osh, event_data, payload_len);
 	}
-	return ret;
+
+done:
+	return valid;
 }
 
 #define MAX_NO_OF_ARG	16
-#define FMTSTR_SIZE	132
-#define ROMSTR_SIZE	200
+#define FMTSTR_SIZE	200
+#define ROMSTR_SIZE	268
 #define SIZE_LOC_STR	50
-static void
-dhd_dbg_verboselog_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr,
-		void *raw_event_ptr)
-{
-	dhd_event_log_t *raw_event = (dhd_event_log_t *)raw_event_ptr;
-	event_log_hdr_t *ts_hdr;
-	uint32 *log_ptr = (uint32 *)hdr - hdr->count;
-	uint16 count;
-	int log_level, id;
-	char fmtstr_loc_buf[ROMSTR_SIZE] = { 0 };
-	uint32 rom_str_len = 0;
-	char (*str_buf)[SIZE_LOC_STR] = NULL;
-	char *str_tmpptr = NULL;
-	uint32 addr = 0;
-	typedef union {
-		uint32 val;
-		char * addr;
-	} u_arg;
-	u_arg arg[MAX_NO_OF_ARG] = {{0}};
-	char *c_ptr = NULL;
-	uint32 *ts_data;
-	static uint64 ts_saved = 0;
-	dhd_dbg_ring_entry_t msg_hdr;
-	struct bcmstrbuf b;
-	UNUSED_PARAMETER(arg);
+#define LOG_PRINT_CNT_MAX	16u
+#define EL_PARSE_VER	"V02"
+#define EL_MSEC_PER_SEC	1000
+#ifdef DHD_LOG_PRINT_RATE_LIMIT
+#define MAX_LOG_PRINT_COUNT 100u
+#define LOG_PRINT_THRESH (1u * USEC_PER_SEC)
+#endif // endif
 
-	/* Get time stamp if it's updated */
-	ts_hdr = (void *)log_ptr - sizeof(event_log_hdr_t);
-	if (ts_hdr->tag == EVENT_LOG_TAG_TS) {
-		ts_data = (uint32 *)ts_hdr - ts_hdr->count;
-		ts_saved = (uint64)ts_data[0];
-		DHD_MSGTRACE_LOG(("EVENT_LOG_TS[0x%08x]: SYS:%08x CPU:%08x\n",
-			ts_data[ts_hdr->count - 1], ts_data[0], ts_data[1]));
+bool
+dhd_dbg_process_event_log_hdr(event_log_hdr_t *log_hdr, prcd_event_log_hdr_t *prcd_log_hdr)
+{
+	event_log_extended_hdr_t *ext_log_hdr;
+	uint16 event_log_fmt_num;
+	uint8 event_log_hdr_type;
+
+	/* Identify the type of event tag, payload type etc..  */
+	event_log_hdr_type = log_hdr->fmt_num & DHD_EVENT_LOG_HDR_MASK;
+	event_log_fmt_num = (log_hdr->fmt_num >> DHD_EVENT_LOG_FMT_NUM_OFFSET) &
+		DHD_EVENT_LOG_FMT_NUM_MASK;
+
+	switch (event_log_hdr_type) {
+		case DHD_OW_NB_EVENT_LOG_HDR:
+			prcd_log_hdr->ext_event_log_hdr = FALSE;
+			prcd_log_hdr->binary_payload = FALSE;
+			break;
+		case DHD_TW_NB_EVENT_LOG_HDR:
+			prcd_log_hdr->ext_event_log_hdr = TRUE;
+			prcd_log_hdr->binary_payload = FALSE;
+			break;
+		case DHD_BI_EVENT_LOG_HDR:
+			if (event_log_fmt_num == DHD_OW_BI_EVENT_FMT_NUM) {
+				prcd_log_hdr->ext_event_log_hdr = FALSE;
+				prcd_log_hdr->binary_payload = TRUE;
+			} else if (event_log_fmt_num == DHD_TW_BI_EVENT_FMT_NUM) {
+				prcd_log_hdr->ext_event_log_hdr = TRUE;
+				prcd_log_hdr->binary_payload = TRUE;
+			} else {
+				DHD_ERROR(("%s: invalid format number 0x%X\n",
+					__FUNCTION__, event_log_fmt_num));
+				return FALSE;
+			}
+			break;
+		case DHD_INVALID_EVENT_LOG_HDR:
+		default:
+			DHD_ERROR(("%s: invalid event log header type 0x%X\n",
+				__FUNCTION__, event_log_hdr_type));
+			return FALSE;
 	}
 
-	if (hdr->tag == EVENT_LOG_TAG_ROM_PRINTF) {
-		rom_str_len = (hdr->count - 1) * sizeof(uint32);
+	/* Parse extended and legacy event log headers and populate prcd_event_log_hdr_t */
+	if (prcd_log_hdr->ext_event_log_hdr) {
+		ext_log_hdr = (event_log_extended_hdr_t *)
+			((uint8 *)log_hdr - sizeof(event_log_hdr_t));
+		prcd_log_hdr->tag = ((ext_log_hdr->extended_tag &
+			DHD_TW_VALID_TAG_BITS_MASK) << DHD_TW_EVENT_LOG_TAG_OFFSET) | log_hdr->tag;
+	} else {
+		prcd_log_hdr->tag = log_hdr->tag;
+	}
+	prcd_log_hdr->count = log_hdr->count;
+	prcd_log_hdr->fmt_num_raw = log_hdr->fmt_num;
+	prcd_log_hdr->fmt_num = event_log_fmt_num;
+
+	/* update arm cycle */
+	/*
+	 * For loegacy event tag :-
+	 * |payload........|Timestamp| Tag
+	 *
+	 * For extended event tag:-
+	 * |payload........|Timestamp|extended Tag| Tag.
+	 *
+	 */
+	prcd_log_hdr->armcycle = prcd_log_hdr->ext_event_log_hdr ?
+		*(uint32 *)(log_hdr - EVENT_TAG_TIMESTAMP_EXT_OFFSET) :
+		*(uint32 *)(log_hdr - EVENT_TAG_TIMESTAMP_OFFSET);
+
+	/* update event log data pointer address */
+	prcd_log_hdr->log_ptr =
+		(uint32 *)log_hdr - log_hdr->count - prcd_log_hdr->ext_event_log_hdr;
+
+	/* handle error cases above this */
+	return TRUE;
+}
+
+static void
+dhd_dbg_verboselog_handler(dhd_pub_t *dhdp, prcd_event_log_hdr_t *plog_hdr,
+		void *raw_event_ptr, uint32 logset, uint16 block, uint32* data)
+{
+	event_log_hdr_t *ts_hdr;
+	uint32 *log_ptr = plog_hdr->log_ptr;
+	char fmtstr_loc_buf[ROMSTR_SIZE] = { 0 };
+	uint32 rom_str_len = 0;
+	uint32 *ts_data;
+
+	if (!raw_event_ptr) {
+		return;
+	}
+
+	if (log_ptr < data) {
+		DHD_ERROR(("Invalid log pointer, logptr : %p data : %p \n", log_ptr, data));
+		return;
+	}
+
+	BCM_REFERENCE(ts_hdr);
+	BCM_REFERENCE(ts_data);
+
+	if (log_ptr > data) {
+		/* Get time stamp if it's updated */
+		ts_hdr = (event_log_hdr_t *)((char *)log_ptr - sizeof(event_log_hdr_t));
+		if (ts_hdr->tag == EVENT_LOG_TAG_TS) {
+			ts_data = (uint32 *)ts_hdr - ts_hdr->count;
+			if (ts_data >= data) {
+				DHD_MSGTRACE_LOG(("EVENT_LOG_TS[0x%08x]: SYS:%08x CPU:%08x\n",
+					ts_data[ts_hdr->count - 1], ts_data[0], ts_data[1]));
+			}
+		}
+	}
+
+	if (plog_hdr->tag == EVENT_LOG_TAG_ROM_PRINTF) {
+		rom_str_len = (plog_hdr->count - 1) * sizeof(uint32);
 		if (rom_str_len >= (ROMSTR_SIZE -1))
 			rom_str_len = ROMSTR_SIZE - 1;
 
@@ -699,7 +550,7 @@
 		fmtstr_loc_buf[rom_str_len] = '\0';
 
 		DHD_MSGTRACE_LOG(("EVENT_LOG_ROM[0x%08x]: %s",
-				log_ptr[hdr->count - 1], fmtstr_loc_buf));
+				log_ptr[plog_hdr->count - 1], fmtstr_loc_buf));
 
 		/* Add newline if missing */
 		if (fmtstr_loc_buf[strlen(fmtstr_loc_buf) - 1] != '\n')
@@ -708,36 +559,121 @@
 		return;
 	}
 
+	if (plog_hdr->tag == EVENT_LOG_TAG_MSCHPROFILE ||
+		plog_hdr->tag == EVENT_LOG_TAG_MSCHPROFILE_TLV) {
+		wl_mschdbg_verboselog_handler(dhdp, raw_event_ptr, plog_hdr, log_ptr);
+		return;
+	}
+
 	/* print the message out in a logprint  */
-	if (!(((raw_event->raw_sstr) || (raw_event->rom_raw_sstr)) &&
-		raw_event->fmts) || hdr->fmt_num == 0xffff) {
+	dhd_dbg_verboselog_printf(dhdp, plog_hdr, raw_event_ptr, log_ptr, logset, block);
+}
+
+void
+dhd_dbg_verboselog_printf(dhd_pub_t *dhdp, prcd_event_log_hdr_t *plog_hdr,
+	void *raw_event_ptr, uint32 *log_ptr, uint32 logset, uint16 block)
+{
+	dhd_event_log_t *raw_event = (dhd_event_log_t *)raw_event_ptr;
+	uint16 count;
+	int log_level, id;
+	char fmtstr_loc_buf[ROMSTR_SIZE] = { 0 };
+	char (*str_buf)[SIZE_LOC_STR] = NULL;
+	char *str_tmpptr = NULL;
+	uint32 addr = 0;
+	typedef union {
+		uint32 val;
+		char * addr;
+	} u_arg;
+	u_arg arg[MAX_NO_OF_ARG] = {{0}};
+	char *c_ptr = NULL;
+	struct bcmstrbuf b;
+#ifdef DHD_LOG_PRINT_RATE_LIMIT
+	static int log_print_count = 0;
+	static uint64 ts0 = 0;
+	uint64 ts1 = 0;
+#endif /* DHD_LOG_PRINT_RATE_LIMIT */
+
+	BCM_REFERENCE(arg);
+
+#ifdef DHD_LOG_PRINT_RATE_LIMIT
+	if (!ts0)
+		ts0 = OSL_SYSUPTIME_US();
+
+	ts1 = OSL_SYSUPTIME_US();
+
+	if (((ts1 - ts0) <= LOG_PRINT_THRESH) && (log_print_count >= MAX_LOG_PRINT_COUNT)) {
+		log_print_threshold = 1;
+		ts0 = 0;
+		log_print_count = 0;
+		DHD_ERROR(("%s: Log print water mark is reached,"
+			" console logs are dumped only to debug_dump file\n", __FUNCTION__));
+	} else if ((ts1 - ts0) > LOG_PRINT_THRESH) {
+		log_print_threshold = 0;
+		ts0 = 0;
+		log_print_count = 0;
+	}
+
+#endif /* DHD_LOG_PRINT_RATE_LIMIT */
+	/* print the message out in a logprint. Logprint expects raw format number */
+	if (!(raw_event->fmts)) {
 		if (dhdp->dbg) {
 			log_level = dhdp->dbg->dbg_rings[FW_VERBOSE_RING_ID].log_level;
 			for (id = 0; id < ARRAYSIZE(fw_verbose_level_map); id++) {
-				if ((fw_verbose_level_map[id].tag == hdr->tag) &&
+				if ((fw_verbose_level_map[id].tag == plog_hdr->tag) &&
 					(fw_verbose_level_map[id].log_level > log_level))
 					return;
 			}
 		}
 
-		bcm_binit(&b, fmtstr_loc_buf, FMTSTR_SIZE);
-		bcm_bprintf(&b, "%d.%d EL: %x %x", (uint32)ts_saved / 1000,
-			(uint32)ts_saved % 1000,
-			hdr->tag & EVENT_LOG_TAG_FLAG_SET_MASK,
-			hdr->fmt_num);
-		for (count = 0; count < (hdr->count - 1); count++)
-			bcm_bprintf(&b, " %x", log_ptr[count]);
-		bcm_bprintf(&b, "\n");
-		DHD_MSGTRACE_LOG(("%s\n", b.origbuf));
-		if (!dhdp->dbg)
-			return;
-		memset(&msg_hdr, 0, sizeof(dhd_dbg_ring_entry_t));
-		msg_hdr.timestamp = ts_saved;
-		msg_hdr.flags |= DBG_RING_ENTRY_FLAGS_HAS_TIMESTAMP;
-		msg_hdr.type = DBG_RING_ENTRY_DATA_TYPE;
-		msg_hdr.len = b.origsize - b.size;
-		dhd_dbg_ring_push(dhdp, FW_VERBOSE_RING_ID, &msg_hdr,
-				b.origbuf);
+		if (plog_hdr->binary_payload) {
+			DHD_ECNTR_LOG(("%06d.%03d EL:tag=%d len=%d fmt=0x%x",
+				(uint32)(log_ptr[plog_hdr->count - 1] / EL_MSEC_PER_SEC),
+				(uint32)(log_ptr[plog_hdr->count - 1] % EL_MSEC_PER_SEC),
+				plog_hdr->tag,
+				plog_hdr->count,
+				plog_hdr->fmt_num_raw));
+
+			for (count = 0; count < (plog_hdr->count - 1); count++) {
+				if (count && (count % LOG_PRINT_CNT_MAX == 0)) {
+					DHD_ECNTR_LOG(("\n\t%08x", log_ptr[count]));
+				} else {
+					DHD_ECNTR_LOG((" %08x", log_ptr[count]));
+				}
+			}
+			DHD_ECNTR_LOG(("\n"));
+		}
+		else {
+			bcm_binit(&b, fmtstr_loc_buf, FMTSTR_SIZE);
+#ifndef OEM_ANDROID
+			bcm_bprintf(&b, "%06d.%03d EL: %d 0x%x",
+				(uint32)(log_ptr[plog_hdr->count - 1] / EL_MSEC_PER_SEC),
+				(uint32)(log_ptr[plog_hdr->count - 1] % EL_MSEC_PER_SEC),
+				plog_hdr->tag,
+				plog_hdr->fmt_num_raw);
+#else
+			bcm_bprintf(&b, "%06d.%03d EL:%s:%u:%u %d %d 0x%x",
+				(uint32)(log_ptr[plog_hdr->count - 1] / EL_MSEC_PER_SEC),
+				(uint32)(log_ptr[plog_hdr->count - 1] % EL_MSEC_PER_SEC),
+				EL_PARSE_VER, logset, block,
+				plog_hdr->tag,
+				plog_hdr->count,
+				plog_hdr->fmt_num_raw);
+#endif /* !OEM_ANDROID */
+			for (count = 0; count < (plog_hdr->count - 1); count++) {
+				bcm_bprintf(&b, " %x", log_ptr[count]);
+			}
+
+			/* ensure preserve fw logs go to debug_dump only in case of customer4 */
+			if (logset < dhdp->event_log_max_sets &&
+				((0x01u << logset) & dhdp->logset_prsrv_mask)) {
+				DHD_PRSRV_MEM(("%s\n", b.origbuf));
+			} else {
+				DHD_FWLOG(("%s\n", b.origbuf));
+#ifdef DHD_LOG_PRINT_RATE_LIMIT
+				log_print_count++;
+#endif /* DHD_LOG_PRINT_RATE_LIMIT */
+			}
+		}
 		return;
 	}
 
@@ -747,96 +683,248 @@
 		return;
 	}
 
-	if ((hdr->fmt_num >> 2) < raw_event->num_fmts) {
-		snprintf(fmtstr_loc_buf, FMTSTR_SIZE, "CONSOLE_E: [0x%x] %s",
-			log_ptr[hdr->count-1],
-			raw_event->fmts[hdr->fmt_num >> 2]);
+	if ((plog_hdr->fmt_num) < raw_event->num_fmts) {
+		if (plog_hdr->tag == EVENT_LOG_TAG_MSCHPROFILE) {
+			snprintf(fmtstr_loc_buf, FMTSTR_SIZE, "%s",
+				raw_event->fmts[plog_hdr->fmt_num]);
+			plog_hdr->count++;
+		} else {
+			snprintf(fmtstr_loc_buf, FMTSTR_SIZE, "CONSOLE_E:%u:%u %06d.%03d %s",
+				logset, block,
+				(uint32)(log_ptr[plog_hdr->count - 1] / EL_MSEC_PER_SEC),
+				(uint32)(log_ptr[plog_hdr->count - 1] % EL_MSEC_PER_SEC),
+				raw_event->fmts[plog_hdr->fmt_num]);
+		}
 		c_ptr = fmtstr_loc_buf;
 	} else {
-		DHD_ERROR(("%s: fmt number out of range \n", __FUNCTION__));
+		/* for ecounters, don't print the error as it will flood */
+		if ((plog_hdr->fmt_num != DHD_OW_BI_EVENT_FMT_NUM) &&
+			(plog_hdr->fmt_num != DHD_TW_BI_EVENT_FMT_NUM)) {
+			DHD_ERROR(("%s: fmt number: 0x%x out of range\n",
+				__FUNCTION__, plog_hdr->fmt_num));
+		} else {
+			DHD_INFO(("%s: fmt number: 0x%x out of range\n",
+				__FUNCTION__, plog_hdr->fmt_num));
+		}
+
 		goto exit;
 	}
 
-	for (count = 0; count < (hdr->count - 1); count++) {
+	if (plog_hdr->count > MAX_NO_OF_ARG) {
+		DHD_ERROR(("%s: plog_hdr->count(%d) out of range\n",
+			__FUNCTION__, plog_hdr->count));
+		goto exit;
+	}
+
+	/* print the format string which will be needed for debugging incorrect formats */
+	DHD_INFO(("%s: fmtstr_loc_buf = %s\n", __FUNCTION__, fmtstr_loc_buf));
+
+	/* Replace all %p to %x to handle 32 bit %p */
+	replace_percent_p_to_x(fmtstr_loc_buf);
+
+	for (count = 0; count < (plog_hdr->count - 1); count++) {
 		if (c_ptr != NULL)
-			if ((c_ptr = strstr(c_ptr, "%")) != NULL)
+			if ((c_ptr = bcmstrstr(c_ptr, "%")) != NULL)
 				c_ptr++;
 
-		if ((c_ptr != NULL) && (*c_ptr == 's')) {
-			if ((raw_event->raw_sstr) &&
-				((log_ptr[count] > raw_event->rodata_start) &&
-				(log_ptr[count] < raw_event->rodata_end))) {
-				/* ram static string */
-				addr = log_ptr[count] - raw_event->rodata_start;
-				str_tmpptr = raw_event->raw_sstr + addr;
-				memcpy(str_buf[count], str_tmpptr,
-					SIZE_LOC_STR);
-				str_buf[count][SIZE_LOC_STR-1] = '\0';
-				arg[count].addr = str_buf[count];
-			} else if ((raw_event->rom_raw_sstr) &&
-					((log_ptr[count] >
-					raw_event->rom_rodata_start) &&
-					(log_ptr[count] <
-					raw_event->rom_rodata_end))) {
-				/* rom static string */
-				addr = log_ptr[count] - raw_event->rom_rodata_start;
-				str_tmpptr = raw_event->rom_raw_sstr + addr;
-				memcpy(str_buf[count], str_tmpptr,
-					SIZE_LOC_STR);
-				str_buf[count][SIZE_LOC_STR-1] = '\0';
-				arg[count].addr = str_buf[count];
+		if (c_ptr != NULL) {
+			if (check_valid_string_format(c_ptr)) {
+				if ((raw_event->raw_sstr) &&
+					((log_ptr[count] > raw_event->rodata_start) &&
+					(log_ptr[count] < raw_event->rodata_end))) {
+					/* ram static string */
+					addr = log_ptr[count] - raw_event->rodata_start;
+					str_tmpptr = raw_event->raw_sstr + addr;
+					memcpy(str_buf[count], str_tmpptr,
+						SIZE_LOC_STR);
+					str_buf[count][SIZE_LOC_STR-1] = '\0';
+					arg[count].addr = str_buf[count];
+				} else if ((raw_event->rom_raw_sstr) &&
+						((log_ptr[count] >
+						raw_event->rom_rodata_start) &&
+						(log_ptr[count] <
+						raw_event->rom_rodata_end))) {
+					/* rom static string */
+					addr = log_ptr[count] - raw_event->rom_rodata_start;
+					str_tmpptr = raw_event->rom_raw_sstr + addr;
+					memcpy(str_buf[count], str_tmpptr,
+						SIZE_LOC_STR);
+					str_buf[count][SIZE_LOC_STR-1] = '\0';
+					arg[count].addr = str_buf[count];
+				} else {
+					/*
+					*  Dynamic string OR
+					* No data for static string.
+					* So store all string's address as string.
+					*/
+					snprintf(str_buf[count], SIZE_LOC_STR,
+						"(s)0x%x", log_ptr[count]);
+					arg[count].addr = str_buf[count];
+				}
+			} else if (check_valid_non_string_format(c_ptr)) {
+				/* Other than string format */
+				arg[count].val = log_ptr[count];
 			} else {
-				/*
-				*  Dynamic string OR
-				* No data for static string.
-				* So store all string's address as string.
-				*/
-				snprintf(str_buf[count], SIZE_LOC_STR,
-					"(s)0x%x", log_ptr[count]);
-				arg[count].addr = str_buf[count];
+				*(c_ptr - 1) = '\0';
+				break;
 			}
-		} else {
-			/* Other than string */
-			arg[count].val = log_ptr[count];
 		}
-		DHD_DBGIF(("Arg val = %d and address = %p\n", arg[count].val, arg[count].addr));
 	}
-	DHD_EVENT((fmtstr_loc_buf, arg[0], arg[1], arg[2], arg[3],
-		arg[4], arg[5], arg[6], arg[7], arg[8], arg[9], arg[10],
-		arg[11], arg[12], arg[13], arg[14], arg[15]));
+
+	/* ensure preserve fw logs go to debug_dump only in case of customer4 */
+	if (logset < dhdp->event_log_max_sets &&
+			((0x01u << logset) & dhdp->logset_prsrv_mask)) {
+		DHD_PRSRV_MEM((fmtstr_loc_buf, arg[0], arg[1], arg[2], arg[3],
+			arg[4], arg[5], arg[6], arg[7], arg[8], arg[9], arg[10],
+			arg[11], arg[12], arg[13], arg[14], arg[15]));
+	} else {
+		DHD_FWLOG((fmtstr_loc_buf, arg[0], arg[1], arg[2], arg[3],
+			arg[4], arg[5], arg[6], arg[7], arg[8], arg[9], arg[10],
+			arg[11], arg[12], arg[13], arg[14], arg[15]));
+#ifdef DHD_LOG_PRINT_RATE_LIMIT
+		log_print_count++;
+#endif /* DHD_LOG_PRINT_RATE_LIMIT */
+	}
 
 exit:
 	MFREE(dhdp->osh, str_buf, (MAX_NO_OF_ARG * SIZE_LOC_STR));
 }
 
-static void
+void
 dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data,
-	void *raw_event_ptr, uint datalen)
+	void *raw_event_ptr, uint datalen, bool msgtrace_hdr_present,
+	uint32 msgtrace_seqnum)
 {
 	msgtrace_hdr_t *hdr;
-	char *data;
-	int id;
-	uint32 hdrlen = sizeof(event_log_hdr_t);
+	char *data, *tmpdata;
+	const uint32 log_hdr_len = sizeof(event_log_hdr_t);
+	uint32 log_pyld_len;
 	static uint32 seqnum_prev = 0;
 	event_log_hdr_t *log_hdr;
 	bool msg_processed = FALSE;
-	uint32 *log_ptr =  NULL;
+	prcd_event_log_hdr_t prcd_log_hdr;
+	prcd_event_log_hdr_t *plog_hdr;
 	dll_t list_head, *cur;
 	loglist_item_t *log_item;
-	uint32 nan_evt_ring_log_level = 0;
+	dhd_dbg_ring_entry_t msg_hdr;
+	char *logbuf;
+	struct tracelog_header *logentry_header;
+	uint ring_data_len = 0;
+	bool ecntr_pushed = FALSE;
+	bool rtt_pushed = FALSE;
+	bool dll_inited = FALSE;
+	uint32 logset = 0;
+	uint16 block = 0;
+	bool event_log_max_sets_queried;
+	uint32 event_log_max_sets;
+	uint min_expected_len = 0;
+	uint16 len_chk = 0;
 
-	hdr = (msgtrace_hdr_t *)event_data;
-	data = (char *)event_data + MSGTRACE_HDRLEN;
-	datalen -= MSGTRACE_HDRLEN;
+	BCM_REFERENCE(ecntr_pushed);
+	BCM_REFERENCE(rtt_pushed);
+	BCM_REFERENCE(len_chk);
 
-	if (dhd_dbg_msgtrace_seqchk(&seqnum_prev, ntoh32(hdr->seqnum)))
+	/* store event_logset_queried and event_log_max_sets in local variables
+	 * to avoid race conditions as they were set from different contexts(preinit)
+	 */
+	event_log_max_sets_queried = dhdp->event_log_max_sets_queried;
+	/* Make sure queried is read first with wmb and then max_sets,
+	 * as it is done in reverse order during preinit ioctls.
+	 */
+	OSL_SMP_WMB();
+	event_log_max_sets = dhdp->event_log_max_sets;
+
+	if (msgtrace_hdr_present)
+		min_expected_len = (MSGTRACE_HDRLEN + EVENT_LOG_BLOCK_LEN);
+	else
+		min_expected_len = EVENT_LOG_BLOCK_LEN;
+
+	/* log trace event consists of:
+	 * msgtrace header
+	 * event log block header
+	 * event log payload
+	 */
+	if (!event_data || (datalen <= min_expected_len)) {
+		DHD_ERROR(("%s: Not processing due to invalid event_data : %p or length : %d\n",
+			__FUNCTION__, event_data, datalen));
+		if (event_data && msgtrace_hdr_present) {
+			prhex("event_data dump", event_data, datalen);
+			tmpdata = (char *)event_data + MSGTRACE_HDRLEN;
+			if (tmpdata) {
+				DHD_ERROR(("EVENT_LOG_HDR[0x%x]: Set: 0x%08x length = %d\n",
+					ltoh16(*((uint16 *)(tmpdata+2))),
+					ltoh32(*((uint32 *)(tmpdata + 4))),
+					ltoh16(*((uint16 *)(tmpdata)))));
+			}
+		} else if (!event_data) {
+			DHD_ERROR(("%s: event_data is NULL, cannot dump prhex\n", __FUNCTION__));
+		}
+		return;
+	}
+
+	if (msgtrace_hdr_present) {
+		hdr = (msgtrace_hdr_t *)event_data;
+		data = (char *)event_data + MSGTRACE_HDRLEN;
+		datalen -= MSGTRACE_HDRLEN;
+		msgtrace_seqnum = ntoh32(hdr->seqnum);
+	} else {
+		data = (char *)event_data;
+	}
+
+	if (dhd_dbg_msgtrace_seqchk(&seqnum_prev, msgtrace_seqnum))
 		return;
 
-	DHD_MSGTRACE_LOG(("EVENT_LOG_HDR[No.%d]: timestamp 0x%08x length = %d\n",
-		ltoh16(*((uint16 *)data)), ltoh16(*((uint16 *)(data + 2))),
-		ltoh32(*((uint32 *)(data+4)))));
-	data += 8;
-	datalen -= 8;
+	/* Save the whole message to event log ring */
+	memset(&msg_hdr, 0, sizeof(dhd_dbg_ring_entry_t));
+	logbuf = VMALLOC(dhdp->osh, sizeof(*logentry_header) + datalen);
+	if (logbuf == NULL)
+		return;
+	logentry_header = (struct tracelog_header *)logbuf;
+	logentry_header->magic_num = TRACE_LOG_MAGIC_NUMBER;
+	logentry_header->buf_size = datalen;
+	logentry_header->seq_num = msgtrace_seqnum;
+	msg_hdr.type = DBG_RING_ENTRY_DATA_TYPE;
+
+	ring_data_len = datalen + sizeof(*logentry_header);
+
+	if ((sizeof(*logentry_header) + datalen) > PAYLOAD_MAX_LEN) {
+		DHD_ERROR(("%s:Payload len=%u exceeds max len\n", __FUNCTION__,
+			((uint)sizeof(*logentry_header) + datalen)));
+		goto exit;
+	}
+
+	msg_hdr.len = sizeof(*logentry_header) + datalen;
+	memcpy(logbuf + sizeof(*logentry_header), data, datalen);
+	DHD_DBGIF(("%s: datalen %d %d\n", __FUNCTION__, msg_hdr.len, datalen));
+	dhd_dbg_push_to_ring(dhdp, FW_VERBOSE_RING_ID, &msg_hdr, logbuf);
+
+	/* Print sequence number, originating set and length of received
+	 * event log buffer. Refer to event log buffer structure in
+	 * event_log.h
+	 */
+	DHD_MSGTRACE_LOG(("EVENT_LOG_HDR[0x%x]: Set: 0x%08x length = %d\n",
+		ltoh16(*((uint16 *)(data+2))), ltoh32(*((uint32 *)(data + 4))),
+		ltoh16(*((uint16 *)(data)))));
+
+	logset = ltoh32(*((uint32 *)(data + 4)));
+
+	if (logset >= event_log_max_sets) {
+		DHD_ERROR(("%s logset: %d max: %d out of range queried: %d\n",
+			__FUNCTION__, logset, event_log_max_sets, event_log_max_sets_queried));
+#ifdef DHD_FW_COREDUMP
+		if (event_log_max_sets_queried) {
+			DHD_ERROR(("%s: collect socram for DUMP_TYPE_LOGSET_BEYOND_RANGE\n",
+				__FUNCTION__));
+			dhdp->memdump_type = DUMP_TYPE_LOGSET_BEYOND_RANGE;
+			dhd_bus_mem_dump(dhdp);
+		}
+#endif /* DHD_FW_COREDUMP */
+	}
+
+	block = ltoh16(*((uint16 *)(data+2)));
+
+	data += EVENT_LOG_BLOCK_HDRLEN;
+	datalen -= EVENT_LOG_BLOCK_HDRLEN;
 
 	/* start parsing from the tail of packet
 	 * Sameple format of a meessage
@@ -845,27 +933,53 @@
 	 * 0x0c580439 -- 39 is tag, 04 is count, 580c is format number
 	 * all these uint32 values comes in reverse order as group as EL data
 	 * while decoding we can only parse from last to first
+	 * |<-                     datalen                     ->|
+	 * |----(payload and maybe more logs)----|event_log_hdr_t|
+	 * data                                  log_hdr
 	 */
 	dll_init(&list_head);
-	while (datalen > 0) {
-		log_hdr = (event_log_hdr_t *)(data + datalen - hdrlen);
-		/* pratially overwritten entries */
-		if ((uint32 *)log_hdr - (uint32 *)data < log_hdr->count)
-			break;
-		/* Check argument count (only when format is valid) */
-		if ((log_hdr->count > MAX_NO_OF_ARG) &&
-		    (log_hdr->fmt_num != 0xffff))
-			break;
-		/* end of frame? */
-		if (log_hdr->tag == EVENT_LOG_TAG_NULL) {
-			log_hdr--;
-			datalen -= hdrlen;
+	dll_inited = TRUE;
+
+	while (datalen > log_hdr_len) {
+		log_hdr = (event_log_hdr_t *)(data + datalen - log_hdr_len);
+		memset(&prcd_log_hdr, 0, sizeof(prcd_log_hdr));
+		if (!dhd_dbg_process_event_log_hdr(log_hdr, &prcd_log_hdr)) {
+			DHD_ERROR(("%s: Error while parsing event log header\n",
+				__FUNCTION__));
+		}
+
+		/* skip zero padding at end of frame */
+		if (prcd_log_hdr.tag == EVENT_LOG_TAG_NULL) {
+			datalen -= log_hdr_len;
 			continue;
 		}
+		/* Check argument count (for non-ecounter events only),
+		 * any event log should contain at least
+		 * one argument (4 bytes) for arm cycle count and up to 16
+		 * arguments except EVENT_LOG_TAG_STATS which could use the
+		 * whole payload of 256 words
+		 */
+		if (prcd_log_hdr.count == 0) {
+			break;
+		}
+		/* Both tag_stats and proxd are binary payloads so skip
+		 * argument count check for these.
+		 */
+		if ((prcd_log_hdr.tag != EVENT_LOG_TAG_STATS) &&
+			(prcd_log_hdr.tag != EVENT_LOG_TAG_PROXD_SAMPLE_COLLECT) &&
+			(prcd_log_hdr.count > MAX_NO_OF_ARG)) {
+			break;
+		}
+
+		log_pyld_len = (prcd_log_hdr.count + prcd_log_hdr.ext_event_log_hdr) *
+			DATA_UNIT_FOR_LOG_CNT;
+		/* log data should not cross the event data boundary */
+		if ((uint32)((char *)log_hdr - data) < log_pyld_len) {
+			break;
+		}
 		/* skip 4 bytes time stamp packet */
-		if (log_hdr->tag == EVENT_LOG_TAG_TS) {
-			datalen -= log_hdr->count * 4 + hdrlen;
-			log_hdr -= log_hdr->count + hdrlen / 4;
+		if (prcd_log_hdr.tag == EVENT_LOG_TAG_TS) {
+			datalen -= (log_pyld_len + log_hdr_len);
 			continue;
 		}
 		if (!(log_item = MALLOC(dhdp->osh, sizeof(*log_item)))) {
@@ -873,79 +987,132 @@
 				__FUNCTION__));
 			break;
 		}
-		log_item->hdr = log_hdr;
+
+		log_item->prcd_log_hdr.tag = prcd_log_hdr.tag;
+		log_item->prcd_log_hdr.count = prcd_log_hdr.count;
+		log_item->prcd_log_hdr.fmt_num = prcd_log_hdr.fmt_num;
+		log_item->prcd_log_hdr.fmt_num_raw = prcd_log_hdr.fmt_num_raw;
+		log_item->prcd_log_hdr.armcycle = prcd_log_hdr.armcycle;
+		log_item->prcd_log_hdr.log_ptr = prcd_log_hdr.log_ptr;
+		log_item->prcd_log_hdr.payload_len = prcd_log_hdr.payload_len;
+		log_item->prcd_log_hdr.ext_event_log_hdr = prcd_log_hdr.ext_event_log_hdr;
+		log_item->prcd_log_hdr.binary_payload = prcd_log_hdr.binary_payload;
+
 		dll_insert(&log_item->list, &list_head);
-		datalen -= (log_hdr->count * 4 + hdrlen);
+		datalen -= (log_pyld_len + log_hdr_len);
 	}
 
 	while (!dll_empty(&list_head)) {
 		msg_processed = FALSE;
 		cur = dll_head_p(&list_head);
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
+#endif // endif
 		log_item = (loglist_item_t *)container_of(cur, loglist_item_t, list);
-		log_hdr = log_item->hdr;
-		log_ptr = (uint32 *)log_hdr - log_hdr->count;
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif // endif
+
+		plog_hdr = &log_item->prcd_log_hdr;
+
+#if defined(EWP_ECNTRS_LOGGING) && defined(DHD_LOG_DUMP)
+		/* Ecounter tag can be time_data or log_stats+binary paloaod */
+		if ((plog_hdr->tag == EVENT_LOG_TAG_ECOUNTERS_TIME_DATA) ||
+				((plog_hdr->tag == EVENT_LOG_TAG_STATS) &&
+				(plog_hdr->binary_payload))) {
+			if (!ecntr_pushed && dhd_log_dump_ecntr_enabled()) {
+				/*
+				 * check msg hdr len before pushing.
+				 * FW msg_hdr.len includes length of event log hdr,
+				 * logentry header and payload.
+				 */
+				len_chk = (sizeof(*logentry_header) + sizeof(*log_hdr) +
+					PAYLOAD_ECNTR_MAX_LEN);
+				/* account extended event log header(extended_event_log_hdr) */
+				if (plog_hdr->ext_event_log_hdr) {
+					len_chk += sizeof(*log_hdr);
+				}
+				if (msg_hdr.len > len_chk) {
+					DHD_ERROR(("%s: EVENT_LOG_VALIDATION_FAILS: "
+						"msg_hdr.len=%u, max allowed for ecntrs=%u\n",
+						__FUNCTION__, msg_hdr.len, len_chk));
+					goto exit;
+				}
+				dhd_dbg_ring_push(dhdp->ecntr_dbg_ring, &msg_hdr, logbuf);
+				ecntr_pushed = TRUE;
+			}
+		}
+#endif /* EWP_ECNTRS_LOGGING && DHD_LOG_DUMP */
+
+#if defined(EWP_RTT_LOGGING) && defined(DHD_LOG_DUMP)
+		if ((plog_hdr->tag == EVENT_LOG_TAG_PROXD_SAMPLE_COLLECT) &&
+				plog_hdr->binary_payload) {
+			if (!rtt_pushed && dhd_log_dump_rtt_enabled()) {
+				/*
+				 * check msg hdr len before pushing.
+				 * FW msg_hdr.len includes length of event log hdr,
+				 * logentry header and payload.
+				 */
+				len_chk = (sizeof(*logentry_header) + sizeof(*log_hdr) +
+					PAYLOAD_RTT_MAX_LEN);
+				/* account extended event log header(extended_event_log_hdr) */
+				if (plog_hdr->ext_event_log_hdr) {
+					len_chk += sizeof(*log_hdr);
+				}
+				if (msg_hdr.len > len_chk) {
+					DHD_ERROR(("%s: EVENT_LOG_VALIDATION_FAILS: "
+						"msg_hdr.len=%u, max allowed for ecntrs=%u\n",
+						__FUNCTION__, msg_hdr.len, len_chk));
+					goto exit;
+				}
+				dhd_dbg_ring_push(dhdp->rtt_dbg_ring, &msg_hdr, logbuf);
+				rtt_pushed = TRUE;
+			}
+		}
+#endif /* EWP_RTT_LOGGING && DHD_LOG_DUMP */
+
+#if defined(DHD_EVENT_LOG_FILTER)
+		if (plog_hdr->tag == EVENT_LOG_TAG_STATS) {
+			dhd_event_log_filter_event_handler(dhdp, plog_hdr, plog_hdr->log_ptr);
+		}
+#endif /* DHD_EVENT_LOG_FILTER */
+
+		if (!msg_processed) {
+			dhd_dbg_verboselog_handler(dhdp, plog_hdr, raw_event_ptr,
+			logset, block, (uint32 *)data);
+		}
 		dll_delete(cur);
 		MFREE(dhdp->osh, log_item, sizeof(*log_item));
 
-		/* Before DHD debugability is implemented WLC_E_TRACE had been
-		 * used to carry verbose logging from firmware. We need to
-		 * be able to handle those messages even without a initialized
-		 * debug layer.
-		 */
-		if (dhdp->dbg) {
-			/* check the data for NAN event ring; keeping first as small table */
-			/* process only user configured to log */
-			nan_evt_ring_log_level = dhdp->dbg->dbg_rings[NAN_EVENT_RING_ID].log_level;
-			if (dhdp->dbg->dbg_rings[NAN_EVENT_RING_ID].log_level) {
-				for (id = 0; id < ARRAYSIZE(nan_event_level_map); id++) {
-					if (nan_event_level_map[id].tag == log_hdr->tag) {
-						/* dont process if tag log level is greater
-						 * than ring log level
-						 */
-						if (nan_event_level_map[id].log_level >
-							nan_evt_ring_log_level) {
-							msg_processed = TRUE;
-							break;
-						}
-						/* In case of BCME_VERSION error,
-						 * this is not NAN event type data
-						 */
-						if (dhd_dbg_nan_event_handler(dhdp,
-							log_hdr, log_ptr) != BCME_VERSION) {
-							msg_processed = TRUE;
-						}
-						break;
-					}
-				}
-			}
-			if (!msg_processed) {
-				/* check the data for event ring */
-				for (id = 0; id < ARRAYSIZE(fw_event_level_map); id++) {
-					if (fw_event_level_map[id].tag == log_hdr->tag) {
-						/* In case of BCME_VERSION error,
-						 * this is not event type data
-						 */
-						if (dhd_dbg_custom_evnt_handler(dhdp,
-							log_hdr, log_ptr) != BCME_VERSION) {
-							msg_processed = TRUE;
-						}
-						break;
-					}
-				}
-			}
-		}
-		if (!msg_processed)
-			dhd_dbg_verboselog_handler(dhdp, log_hdr, raw_event_ptr);
-
 	}
+	BCM_REFERENCE(log_hdr);
+
+exit:
+	while (dll_inited && (!dll_empty(&list_head))) {
+		cur = dll_head_p(&list_head);
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
+#endif // endif
+		log_item = (loglist_item_t *)container_of(cur, loglist_item_t, list);
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif // endif
+		dll_delete(cur);
+		MFREE(dhdp->osh, log_item, sizeof(*log_item));
+	}
+	VMFREE(dhdp->osh, logbuf, ring_data_len);
 }
 #else /* !SHOW_LOGTRACE */
 static INLINE void dhd_dbg_verboselog_handler(dhd_pub_t *dhdp,
-	event_log_hdr_t *hdr, void *raw_event_ptr) {};
-static INLINE void dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp,
-	void *event_data, void *raw_event_ptr, uint datalen) {};
+	prcd_event_log_hdr_t *plog_hdr, void *raw_event_ptr, uint32 logset, uint16 block,
+	uint32 *data) {};
+INLINE void dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp,
+	void *event_data, void *raw_event_ptr, uint datalen,
+	bool msgtrace_hdr_present, uint32 msgtrace_seqnum) {};
 #endif /* SHOW_LOGTRACE */
-
+#ifndef MACOSX_DHD
 void
 dhd_dbg_trace_evnt_handler(dhd_pub_t *dhdp, void *event_data,
 		void *raw_event_ptr, uint datalen)
@@ -963,63 +1130,11 @@
 	if (hdr->trace_type == MSGTRACE_HDR_TYPE_MSG)
 		dhd_dbg_msgtrace_msg_parser(event_data);
 	else if (hdr->trace_type == MSGTRACE_HDR_TYPE_LOG)
-		dhd_dbg_msgtrace_log_parser(dhdp, event_data, raw_event_ptr, datalen);
+		dhd_dbg_msgtrace_log_parser(dhdp, event_data, raw_event_ptr, datalen,
+			TRUE, 0);
 }
 
-static int
-dhd_dbg_ring_init(dhd_pub_t *dhdp, dhd_dbg_ring_t *ring, uint16 id, uint8 *name,
-		uint32 ring_sz)
-{
-	void *buf;
-	unsigned long flags;
-
-	buf = MALLOCZ(dhdp->osh, ring_sz);
-	if (!buf)
-		return BCME_NOMEM;
-
-	ring->lock = dhd_os_spin_lock_init(dhdp->osh);
-
-	flags = dhd_os_spin_lock(ring->lock);
-	ring->id = id;
-	strncpy(ring->name, name, DBGRING_NAME_MAX);
-	ring->name[DBGRING_NAME_MAX - 1] = 0;
-	ring->ring_size = ring_sz;
-	ring->wp = ring->rp = 0;
-	ring->ring_buf = buf;
-	ring->threshold = DBGRING_FLUSH_THRESHOLD(ring);
-	ring->state = RING_SUSPEND;
-	dhd_os_spin_unlock(ring->lock, flags);
-
-	return BCME_OK;
-}
-
-static void
-dhd_dbg_ring_deinit(dhd_pub_t *dhdp, dhd_dbg_ring_t *ring)
-{
-	void *buf;
-	uint32 ring_sz;
-	unsigned long flags;
-
-	if (!ring->ring_buf)
-		return;
-
-	flags = dhd_os_spin_lock(ring->lock);
-	ring->id = 0;
-	ring->name[0] = 0;
-	ring_sz = ring->ring_size;
-	ring->ring_size = 0;
-	ring->wp = ring->rp = 0;
-	buf = ring->ring_buf;
-	ring->ring_buf = NULL;
-	memset(&ring->stat, 0, sizeof(ring->stat));
-	ring->threshold = 0;
-	ring->state = RING_STOP;
-	dhd_os_spin_unlock(ring->lock, flags);
-
-	dhd_os_spin_lock_deinit(dhdp->osh, ring->lock);
-
-	MFREE(dhdp->osh, buf, ring_sz);
-}
+#endif /* MACOSX_DHD */
 
 /*
  * dhd_dbg_set_event_log_tag : modify the state of an event log tag
@@ -1053,38 +1168,26 @@
 {
 	dhd_dbg_ring_t *ring;
 	uint8 set = 1;
-	unsigned long lock_flags;
 	int i, array_len = 0;
 	struct log_level_table *log_level_tbl = NULL;
+
 	if (!dhdp || !dhdp->dbg)
 		return BCME_BADADDR;
 
+	if (!VALID_RING(ring_id)) {
+		DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id));
+		return BCME_RANGE;
+	}
+
 	ring = &dhdp->dbg->dbg_rings[ring_id];
+	dhd_dbg_ring_config(ring, log_level, threshold);
 
-	if (ring->state == RING_STOP)
-		return BCME_UNSUPPORTED;
-
-	lock_flags = dhd_os_spin_lock(ring->lock);
-	if (log_level == 0)
-		ring->state = RING_SUSPEND;
-	else
-		ring->state = RING_ACTIVE;
-	ring->log_level = log_level;
-
-	ring->threshold = (threshold > ring->threshold) ? ring->ring_size : threshold;
-	dhd_os_spin_unlock(ring->lock, lock_flags);
 	if (log_level > 0)
 		set = TRUE;
 
-	if (ring->id == FW_EVENT_RING_ID) {
-		log_level_tbl = fw_event_level_map;
-		array_len = ARRAYSIZE(fw_event_level_map);
-	} else if (ring->id == FW_VERBOSE_RING_ID) {
+	if (ring->id == FW_VERBOSE_RING_ID) {
 		log_level_tbl = fw_verbose_level_map;
 		array_len = ARRAYSIZE(fw_verbose_level_map);
-	} else if (ring->id == NAN_EVENT_RING_ID) {
-		log_level_tbl = nan_event_level_map;
-		array_len = ARRAYSIZE(nan_event_level_map);
 	}
 
 	for (i = 0; i < array_len; i++) {
@@ -1103,6 +1206,23 @@
 	return BCME_OK;
 }
 
+int
+__dhd_dbg_get_ring_status(dhd_dbg_ring_t *ring, dhd_dbg_ring_status_t *get_ring_status)
+{
+	dhd_dbg_ring_status_t ring_status;
+	int ret = BCME_OK;
+
+	if (ring == NULL) {
+		return BCME_BADADDR;
+	}
+
+	bzero(&ring_status, sizeof(dhd_dbg_ring_status_t));
+	RING_STAT_TO_STATUS(ring, ring_status);
+	*get_ring_status = ring_status;
+
+	return ret;
+}
+
 /*
 * dhd_dbg_get_ring_status : get the ring status from the coresponding ring buffer
 * Return: An error code or 0 on success.
@@ -1115,17 +1235,14 @@
 	int id = 0;
 	dhd_dbg_t *dbg;
 	dhd_dbg_ring_t *dbg_ring;
-	dhd_dbg_ring_status_t ring_status;
 	if (!dhdp || !dhdp->dbg)
 		return BCME_BADADDR;
 	dbg = dhdp->dbg;
 
-	memset(&ring_status, 0, sizeof(dhd_dbg_ring_status_t));
 	for (id = DEBUG_RING_ID_INVALID + 1; id < DEBUG_RING_ID_MAX; id++) {
 		dbg_ring = &dbg->dbg_rings[id];
 		if (VALID_RING(dbg_ring->id) && (dbg_ring->id == ring_id)) {
-			RING_STAT_TO_STATUS(dbg_ring, ring_status);
-			*dbg_ring_status = ring_status;
+			__dhd_dbg_get_ring_status(dbg_ring, dbg_ring_status);
 			break;
 		}
 	}
@@ -1135,6 +1252,30 @@
 	}
 	return ret;
 }
+
+#ifdef SHOW_LOGTRACE
+void
+dhd_dbg_read_ring_into_trace_buf(dhd_dbg_ring_t *ring, trace_buf_info_t *trace_buf_info)
+{
+	dhd_dbg_ring_status_t ring_status;
+	uint32 rlen = 0;
+
+	rlen = dhd_dbg_ring_pull_single(ring, trace_buf_info->buf, TRACE_LOG_BUF_MAX_SIZE, TRUE);
+
+	trace_buf_info->size = rlen;
+	trace_buf_info->availability = NEXT_BUF_NOT_AVAIL;
+	if (rlen == 0) {
+		trace_buf_info->availability = BUF_NOT_AVAILABLE;
+		return;
+	}
+
+	__dhd_dbg_get_ring_status(ring, &ring_status);
+
+	if (ring_status.written_bytes != ring_status.read_bytes) {
+		trace_buf_info->availability = NEXT_BUF_AVAIL;
+	}
+}
+#endif /* SHOW_LOGTRACE */
 
 /*
 * dhd_dbg_find_ring_id : return ring_id based on ring_name
@@ -1154,7 +1295,7 @@
 	dbg = dhdp->dbg;
 	for (id = DEBUG_RING_ID_INVALID + 1; id < DEBUG_RING_ID_MAX; id++) {
 		ring = &dbg->dbg_rings[id];
-		if (!strncmp(ring->name, ring_name, sizeof(ring->name) - 1))
+		if (!strncmp((char *)ring->name, ring_name, sizeof(ring->name) - 1))
 			break;
 	}
 	return id;
@@ -1183,7 +1324,7 @@
 	int ring_id;
 	dhd_dbg_t *dbg;
 	dhd_dbg_ring_t *dbg_ring;
-	if (!dhdp || !dhdp->dbg)
+	if (!dhdp)
 		return BCME_BADARG;
 	dbg = dhdp->dbg;
 
@@ -1191,13 +1332,7 @@
 		dbg_ring = &dbg->dbg_rings[ring_id];
 		if (!start) {
 			if (VALID_RING(dbg_ring->id)) {
-				/* Initialize the information for the ring */
-				dbg_ring->state = RING_SUSPEND;
-				dbg_ring->log_level = 0;
-				dbg_ring->rp = dbg_ring->wp = 0;
-				dbg_ring->threshold = 0;
-				memset(&dbg_ring->stat, 0, sizeof(struct ring_statistics));
-				memset(dbg_ring->ring_buf, 0, dbg_ring->ring_size);
+				dhd_dbg_ring_start(dbg_ring);
 			}
 		}
 	}
@@ -1224,6 +1359,784 @@
 	}
 	return ret;
 }
+
+#if defined(DBG_PKT_MON) || defined(DHD_PKT_LOGGING)
+uint32
+__dhd_dbg_pkt_hash(uintptr_t pkt, uint32 pktid)
+{
+	uint32 __pkt;
+	uint32 __pktid;
+
+	__pkt = ((int)pkt) >= 0 ? (2 * pkt) : (-2 * pkt - 1);
+	__pktid = ((int)pktid) >= 0 ? (2 * pktid) : (-2 * pktid - 1);
+
+	return (__pkt >= __pktid ? (__pkt * __pkt + __pkt + __pktid) :
+			(__pkt + __pktid * __pktid));
+}
+
+#define __TIMESPEC_TO_US(ts) \
+	(((uint32)(ts).tv_sec * USEC_PER_SEC) + ((ts).tv_nsec / NSEC_PER_USEC))
+
+uint32
+__dhd_dbg_driver_ts_usec(void)
+{
+	struct timespec64 ts;
+
+	ts = ktime_to_timespec64(ktime_get_boottime());
+	return ((uint32)(__TIMESPEC_TO_US(ts)));
+}
+
+wifi_tx_packet_fate
+__dhd_dbg_map_tx_status_to_pkt_fate(uint16 status)
+{
+	wifi_tx_packet_fate pkt_fate;
+
+	switch (status) {
+		case WLFC_CTL_PKTFLAG_DISCARD:
+			pkt_fate = TX_PKT_FATE_ACKED;
+			break;
+		case WLFC_CTL_PKTFLAG_D11SUPPRESS:
+			/* intensional fall through */
+		case WLFC_CTL_PKTFLAG_WLSUPPRESS:
+			pkt_fate = TX_PKT_FATE_FW_QUEUED;
+			break;
+		case WLFC_CTL_PKTFLAG_TOSSED_BYWLC:
+			pkt_fate = TX_PKT_FATE_FW_DROP_INVALID;
+			break;
+		case WLFC_CTL_PKTFLAG_DISCARD_NOACK:
+			pkt_fate = TX_PKT_FATE_SENT;
+			break;
+		case WLFC_CTL_PKTFLAG_EXPIRED:
+			pkt_fate = TX_PKT_FATE_FW_DROP_EXPTIME;
+			break;
+		case WLFC_CTL_PKTFLAG_MKTFREE:
+			pkt_fate = TX_PKT_FATE_FW_PKT_FREE;
+			break;
+		default:
+			pkt_fate = TX_PKT_FATE_FW_DROP_OTHER;
+			break;
+	}
+
+	return pkt_fate;
+}
+#endif /* DBG_PKT_MON || DHD_PKT_LOGGING */
+
+#ifdef DBG_PKT_MON
+static int
+__dhd_dbg_free_tx_pkts(dhd_pub_t *dhdp, dhd_dbg_tx_info_t *tx_pkts,
+	uint16 pkt_count)
+{
+	uint16 count;
+
+	DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__));
+	count = 0;
+	while ((count < pkt_count) && tx_pkts) {
+		if (tx_pkts->info.pkt) {
+			PKTFREE(dhdp->osh, tx_pkts->info.pkt, TRUE);
+		}
+		tx_pkts++;
+		count++;
+	}
+
+	return BCME_OK;
+}
+
+static int
+__dhd_dbg_free_rx_pkts(dhd_pub_t *dhdp, dhd_dbg_rx_info_t *rx_pkts,
+	uint16 pkt_count)
+{
+	uint16 count;
+
+	DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__));
+	count = 0;
+	while ((count < pkt_count) && rx_pkts) {
+		if (rx_pkts->info.pkt) {
+			PKTFREE(dhdp->osh, rx_pkts->info.pkt, TRUE);
+		}
+		rx_pkts++;
+		count++;
+	}
+
+	return BCME_OK;
+}
+
+void
+__dhd_dbg_dump_pkt_info(dhd_pub_t *dhdp, dhd_dbg_pkt_info_t *info)
+{
+	if (DHD_PKT_MON_DUMP_ON()) {
+		DHD_PKT_MON(("payload type   = %d\n", info->payload_type));
+		DHD_PKT_MON(("driver ts      = %u\n", info->driver_ts));
+		DHD_PKT_MON(("firmware ts    = %u\n", info->firmware_ts));
+		DHD_PKT_MON(("packet hash    = %u\n", info->pkt_hash));
+		DHD_PKT_MON(("packet length  = %zu\n", info->pkt_len));
+		DHD_PKT_MON(("packet address = %p\n", info->pkt));
+		DHD_PKT_MON(("packet data    = \n"));
+		if (DHD_PKT_MON_ON()) {
+			prhex(NULL, PKTDATA(dhdp->osh, info->pkt), info->pkt_len);
+		}
+	}
+}
+
+void
+__dhd_dbg_dump_tx_pkt_info(dhd_pub_t *dhdp, dhd_dbg_tx_info_t *tx_pkt,
+	uint16 count)
+{
+	if (DHD_PKT_MON_DUMP_ON()) {
+		DHD_PKT_MON(("\nTX (count: %d)\n", ++count));
+		DHD_PKT_MON(("packet fate    = %d\n", tx_pkt->fate));
+		__dhd_dbg_dump_pkt_info(dhdp, &tx_pkt->info);
+	}
+}
+
+void
+__dhd_dbg_dump_rx_pkt_info(dhd_pub_t *dhdp, dhd_dbg_rx_info_t *rx_pkt,
+	uint16 count)
+{
+	if (DHD_PKT_MON_DUMP_ON()) {
+		DHD_PKT_MON(("\nRX (count: %d)\n", ++count));
+		DHD_PKT_MON(("packet fate    = %d\n", rx_pkt->fate));
+		__dhd_dbg_dump_pkt_info(dhdp, &rx_pkt->info);
+	}
+}
+
+int
+dhd_dbg_attach_pkt_monitor(dhd_pub_t *dhdp,
+	dbg_mon_tx_pkts_t tx_pkt_mon,
+	dbg_mon_tx_status_t tx_status_mon,
+	dbg_mon_rx_pkts_t rx_pkt_mon)
+{
+
+	dhd_dbg_tx_report_t *tx_report = NULL;
+	dhd_dbg_rx_report_t *rx_report = NULL;
+	dhd_dbg_tx_info_t *tx_pkts = NULL;
+	dhd_dbg_rx_info_t *rx_pkts = NULL;
+	dhd_dbg_pkt_mon_state_t tx_pkt_state;
+	dhd_dbg_pkt_mon_state_t tx_status_state;
+	dhd_dbg_pkt_mon_state_t rx_pkt_state;
+	uint32 alloc_len;
+	int ret = BCME_OK;
+	unsigned long flags;
+
+	DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__));
+	if (!dhdp || !dhdp->dbg) {
+		DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
+			dhdp, (dhdp ? dhdp->dbg : NULL)));
+		return -EINVAL;
+	}
+
+	DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
+	tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
+	tx_status_state = dhdp->dbg->pkt_mon.tx_pkt_state;
+	rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
+
+	if (PKT_MON_ATTACHED(tx_pkt_state) || PKT_MON_ATTACHED(tx_status_state) ||
+			PKT_MON_ATTACHED(rx_pkt_state)) {
+		DHD_PKT_MON(("%s(): packet monitor is already attached, "
+			"tx_pkt_state=%d, tx_status_state=%d, rx_pkt_state=%d\n",
+			__FUNCTION__, tx_pkt_state, tx_status_state, rx_pkt_state));
+		DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
+		/* return success as the intention was to initialize packet monitor */
+		return BCME_OK;
+	}
+
+	/* allocate and initialize tx packet monitoring */
+	alloc_len = sizeof(*tx_report);
+	tx_report = (dhd_dbg_tx_report_t *)MALLOCZ(dhdp->osh, alloc_len);
+	if (unlikely(!tx_report)) {
+		DHD_ERROR(("%s(): could not allocate memory for - "
+			"dhd_dbg_tx_report_t\n", __FUNCTION__));
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	alloc_len = (sizeof(*tx_pkts) * MAX_FATE_LOG_LEN);
+	tx_pkts = (dhd_dbg_tx_info_t *)MALLOCZ(dhdp->osh, alloc_len);
+	if (unlikely(!tx_pkts)) {
+		DHD_ERROR(("%s(): could not allocate memory for - "
+			"dhd_dbg_tx_info_t\n", __FUNCTION__));
+		ret = -ENOMEM;
+		goto fail;
+	}
+	dhdp->dbg->pkt_mon.tx_report = tx_report;
+	dhdp->dbg->pkt_mon.tx_report->tx_pkts = tx_pkts;
+	dhdp->dbg->pkt_mon.tx_pkt_mon = tx_pkt_mon;
+	dhdp->dbg->pkt_mon.tx_status_mon = tx_status_mon;
+	dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_ATTACHED;
+	dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_ATTACHED;
+
+	/* allocate and initialze rx packet monitoring */
+	alloc_len = sizeof(*rx_report);
+	rx_report = (dhd_dbg_rx_report_t *)MALLOCZ(dhdp->osh, alloc_len);
+	if (unlikely(!rx_report)) {
+		DHD_ERROR(("%s(): could not allocate memory for - "
+			"dhd_dbg_rx_report_t\n", __FUNCTION__));
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	alloc_len = (sizeof(*rx_pkts) * MAX_FATE_LOG_LEN);
+	rx_pkts = (dhd_dbg_rx_info_t *)MALLOCZ(dhdp->osh, alloc_len);
+	if (unlikely(!rx_pkts)) {
+		DHD_ERROR(("%s(): could not allocate memory for - "
+			"dhd_dbg_rx_info_t\n", __FUNCTION__));
+		ret = -ENOMEM;
+		goto fail;
+	}
+	dhdp->dbg->pkt_mon.rx_report = rx_report;
+	dhdp->dbg->pkt_mon.rx_report->rx_pkts = rx_pkts;
+	dhdp->dbg->pkt_mon.rx_pkt_mon = rx_pkt_mon;
+	dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_ATTACHED;
+
+	DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
+	DHD_PKT_MON(("%s(): packet monitor attach succeeded\n", __FUNCTION__));
+	return ret;
+
+fail:
+	/* tx packet monitoring */
+	if (tx_pkts) {
+		alloc_len = (sizeof(*tx_pkts) * MAX_FATE_LOG_LEN);
+		MFREE(dhdp->osh, tx_pkts, alloc_len);
+	}
+	if (tx_report) {
+		alloc_len = sizeof(*tx_report);
+		MFREE(dhdp->osh, tx_report, alloc_len);
+	}
+	dhdp->dbg->pkt_mon.tx_report = NULL;
+	dhdp->dbg->pkt_mon.tx_report->tx_pkts = NULL;
+	dhdp->dbg->pkt_mon.tx_pkt_mon = NULL;
+	dhdp->dbg->pkt_mon.tx_status_mon = NULL;
+	dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_DETACHED;
+	dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_DETACHED;
+
+	/* rx packet monitoring */
+	if (rx_pkts) {
+		alloc_len = (sizeof(*rx_pkts) * MAX_FATE_LOG_LEN);
+		MFREE(dhdp->osh, rx_pkts, alloc_len);
+	}
+	if (rx_report) {
+		alloc_len = sizeof(*rx_report);
+		MFREE(dhdp->osh, rx_report, alloc_len);
+	}
+	dhdp->dbg->pkt_mon.rx_report = NULL;
+	dhdp->dbg->pkt_mon.rx_report->rx_pkts = NULL;
+	dhdp->dbg->pkt_mon.rx_pkt_mon = NULL;
+	dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_DETACHED;
+
+	DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
+	DHD_ERROR(("%s(): packet monitor attach failed\n", __FUNCTION__));
+	return ret;
+}
+
+int
+dhd_dbg_start_pkt_monitor(dhd_pub_t *dhdp)
+{
+	dhd_dbg_tx_report_t *tx_report;
+	dhd_dbg_rx_report_t *rx_report;
+	dhd_dbg_pkt_mon_state_t tx_pkt_state;
+	dhd_dbg_pkt_mon_state_t tx_status_state;
+	dhd_dbg_pkt_mon_state_t rx_pkt_state;
+	unsigned long flags;
+
+	DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__));
+	if (!dhdp || !dhdp->dbg) {
+		DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
+			dhdp, (dhdp ? dhdp->dbg : NULL)));
+		return -EINVAL;
+	}
+
+	DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
+	tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
+	tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
+	rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
+
+	if (PKT_MON_DETACHED(tx_pkt_state) || PKT_MON_DETACHED(tx_status_state) ||
+			PKT_MON_DETACHED(rx_pkt_state)) {
+		DHD_PKT_MON(("%s(): packet monitor is not yet enabled, "
+			"tx_pkt_state=%d, tx_status_state=%d, rx_pkt_state=%d\n",
+			__FUNCTION__, tx_pkt_state, tx_status_state, rx_pkt_state));
+		DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
+		return -EINVAL;
+	}
+
+	dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_STARTING;
+	dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_STARTING;
+	dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_STARTING;
+
+	tx_report = dhdp->dbg->pkt_mon.tx_report;
+	rx_report = dhdp->dbg->pkt_mon.rx_report;
+	if (!tx_report || !rx_report) {
+		DHD_PKT_MON(("%s(): tx_report=%p, rx_report=%p\n",
+			__FUNCTION__, tx_report, rx_report));
+		DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
+		return -EINVAL;
+	}
+
+	tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
+	tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
+	rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
+
+	/* Safe to free packets as state pkt_state is STARTING */
+	__dhd_dbg_free_tx_pkts(dhdp, tx_report->tx_pkts, tx_report->pkt_pos);
+
+	__dhd_dbg_free_rx_pkts(dhdp, rx_report->rx_pkts, rx_report->pkt_pos);
+
+	/* reset array postion */
+	tx_report->pkt_pos = 0;
+	tx_report->status_pos = 0;
+	dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_STARTED;
+	dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_STARTED;
+
+	rx_report->pkt_pos = 0;
+	dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_STARTED;
+	DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
+
+	DHD_PKT_MON(("%s(): packet monitor started\n", __FUNCTION__));
+	return BCME_OK;
+}
+
+int
+dhd_dbg_monitor_tx_pkts(dhd_pub_t *dhdp, void *pkt, uint32 pktid)
+{
+	dhd_dbg_tx_report_t *tx_report;
+	dhd_dbg_tx_info_t *tx_pkts;
+	dhd_dbg_pkt_mon_state_t tx_pkt_state;
+	uint32 pkt_hash, driver_ts;
+	uint16 pkt_pos;
+	unsigned long flags;
+
+	if (!dhdp || !dhdp->dbg) {
+		DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
+			dhdp, (dhdp ? dhdp->dbg : NULL)));
+		return -EINVAL;
+	}
+
+	DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
+	tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
+	if (PKT_MON_STARTED(tx_pkt_state)) {
+		tx_report = dhdp->dbg->pkt_mon.tx_report;
+		pkt_pos = tx_report->pkt_pos;
+
+		if (!PKT_MON_PKT_FULL(pkt_pos)) {
+			tx_pkts = tx_report->tx_pkts;
+			pkt_hash = __dhd_dbg_pkt_hash((uintptr_t)pkt, pktid);
+			driver_ts = __dhd_dbg_driver_ts_usec();
+
+			tx_pkts[pkt_pos].info.pkt = PKTDUP(dhdp->osh, pkt);
+			tx_pkts[pkt_pos].info.pkt_len = PKTLEN(dhdp->osh, pkt);
+			tx_pkts[pkt_pos].info.pkt_hash = pkt_hash;
+			tx_pkts[pkt_pos].info.driver_ts = driver_ts;
+			tx_pkts[pkt_pos].info.firmware_ts = 0U;
+			tx_pkts[pkt_pos].info.payload_type = FRAME_TYPE_ETHERNET_II;
+			tx_pkts[pkt_pos].fate = TX_PKT_FATE_DRV_QUEUED;
+
+			tx_report->pkt_pos++;
+		} else {
+			dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_STOPPED;
+			DHD_PKT_MON(("%s(): tx pkt logging stopped, reached "
+				"max limit\n", __FUNCTION__));
+		}
+	}
+
+	DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
+	return BCME_OK;
+}
+
+int
+dhd_dbg_monitor_tx_status(dhd_pub_t *dhdp, void *pkt, uint32 pktid,
+		uint16 status)
+{
+	dhd_dbg_tx_report_t *tx_report;
+	dhd_dbg_tx_info_t *tx_pkt;
+	dhd_dbg_pkt_mon_state_t tx_status_state;
+	wifi_tx_packet_fate pkt_fate;
+	uint32 pkt_hash, temp_hash;
+	uint16 pkt_pos, status_pos;
+	int16 count;
+	bool found = FALSE;
+	unsigned long flags;
+
+	if (!dhdp || !dhdp->dbg) {
+		DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
+			dhdp, (dhdp ? dhdp->dbg : NULL)));
+		return -EINVAL;
+	}
+
+	DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
+	tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
+	if (PKT_MON_STARTED(tx_status_state)) {
+		tx_report = dhdp->dbg->pkt_mon.tx_report;
+		pkt_pos = tx_report->pkt_pos;
+		status_pos = tx_report->status_pos;
+
+		if (!PKT_MON_STATUS_FULL(pkt_pos, status_pos)) {
+			pkt_hash = __dhd_dbg_pkt_hash((uintptr_t)pkt, pktid);
+			pkt_fate = __dhd_dbg_map_tx_status_to_pkt_fate(status);
+
+			/* best bet (in-order tx completion) */
+			count = status_pos;
+			tx_pkt = (((dhd_dbg_tx_info_t *)tx_report->tx_pkts) + status_pos);
+			while ((count < pkt_pos) && tx_pkt) {
+				temp_hash = tx_pkt->info.pkt_hash;
+				if (temp_hash == pkt_hash) {
+					tx_pkt->fate = pkt_fate;
+					tx_report->status_pos++;
+					found = TRUE;
+					break;
+				}
+				tx_pkt++;
+				count++;
+			}
+
+			/* search until beginning (handles out-of-order completion) */
+			if (!found) {
+				count = status_pos - 1;
+				tx_pkt = (((dhd_dbg_tx_info_t *)tx_report->tx_pkts) + count);
+				while ((count >= 0) && tx_pkt) {
+					temp_hash = tx_pkt->info.pkt_hash;
+					if (temp_hash == pkt_hash) {
+						tx_pkt->fate = pkt_fate;
+						tx_report->status_pos++;
+						found = TRUE;
+						break;
+					}
+					tx_pkt--;
+					count--;
+				}
+
+				if (!found) {
+					/* still couldn't match tx_status */
+					DHD_ERROR(("%s(): couldn't match tx_status, pkt_pos=%u, "
+						"status_pos=%u, pkt_fate=%u\n", __FUNCTION__,
+						pkt_pos, status_pos, pkt_fate));
+				}
+			}
+		} else {
+			dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_STOPPED;
+			DHD_PKT_MON(("%s(): tx_status logging stopped, reached "
+				"max limit\n", __FUNCTION__));
+		}
+	}
+
+	DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
+	return BCME_OK;
+}
+
+int
+dhd_dbg_monitor_rx_pkts(dhd_pub_t *dhdp, void *pkt)
+{
+	dhd_dbg_rx_report_t *rx_report;
+	dhd_dbg_rx_info_t *rx_pkts;
+	dhd_dbg_pkt_mon_state_t rx_pkt_state;
+	uint32 driver_ts;
+	uint16 pkt_pos;
+	unsigned long flags;
+
+	if (!dhdp || !dhdp->dbg) {
+		DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
+			dhdp, (dhdp ? dhdp->dbg : NULL)));
+		return -EINVAL;
+	}
+
+	DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
+	rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
+	if (PKT_MON_STARTED(rx_pkt_state)) {
+		rx_report = dhdp->dbg->pkt_mon.rx_report;
+		pkt_pos = rx_report->pkt_pos;
+
+		if (!PKT_MON_PKT_FULL(pkt_pos)) {
+			rx_pkts = rx_report->rx_pkts;
+			driver_ts = __dhd_dbg_driver_ts_usec();
+
+			rx_pkts[pkt_pos].info.pkt = PKTDUP(dhdp->osh, pkt);
+			rx_pkts[pkt_pos].info.pkt_len = PKTLEN(dhdp->osh, pkt);
+			rx_pkts[pkt_pos].info.pkt_hash = 0U;
+			rx_pkts[pkt_pos].info.driver_ts = driver_ts;
+			rx_pkts[pkt_pos].info.firmware_ts = 0U;
+			rx_pkts[pkt_pos].info.payload_type = FRAME_TYPE_ETHERNET_II;
+			rx_pkts[pkt_pos].fate = RX_PKT_FATE_SUCCESS;
+
+			rx_report->pkt_pos++;
+		} else {
+			dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_STOPPED;
+			DHD_PKT_MON(("%s(): rx pkt logging stopped, reached "
+					"max limit\n", __FUNCTION__));
+		}
+	}
+
+	DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
+	return BCME_OK;
+}
+
+int
+dhd_dbg_stop_pkt_monitor(dhd_pub_t *dhdp)
+{
+	dhd_dbg_pkt_mon_state_t tx_pkt_state;
+	dhd_dbg_pkt_mon_state_t tx_status_state;
+	dhd_dbg_pkt_mon_state_t rx_pkt_state;
+	unsigned long flags;
+
+	DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__));
+	if (!dhdp || !dhdp->dbg) {
+		DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
+			dhdp, (dhdp ? dhdp->dbg : NULL)));
+		return -EINVAL;
+	}
+
+	DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
+	tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
+	tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
+	rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
+
+	if (PKT_MON_DETACHED(tx_pkt_state) || PKT_MON_DETACHED(tx_status_state) ||
+			PKT_MON_DETACHED(rx_pkt_state)) {
+		DHD_PKT_MON(("%s(): packet monitor is not yet enabled, "
+			"tx_pkt_state=%d, tx_status_state=%d, rx_pkt_state=%d\n",
+			__FUNCTION__, tx_pkt_state, tx_status_state, rx_pkt_state));
+		DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
+		return -EINVAL;
+	}
+	dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_STOPPED;
+	dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_STOPPED;
+	dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_STOPPED;
+	DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
+
+	DHD_PKT_MON(("%s(): packet monitor stopped\n", __FUNCTION__));
+	return BCME_OK;
+}
+
+#define __COPY_TO_USER(to, from, n) \
+	do { \
+		int __ret; \
+		__ret = copy_to_user((void __user *)(to), (void *)(from), \
+				(unsigned long)(n)); \
+		if (unlikely(__ret)) { \
+			DHD_ERROR(("%s():%d: copy_to_user failed, ret=%d\n", \
+				__FUNCTION__, __LINE__, __ret)); \
+			return __ret; \
+		} \
+	} while (0);
+
+int
+dhd_dbg_monitor_get_tx_pkts(dhd_pub_t *dhdp, void __user *user_buf,
+		uint16 req_count, uint16 *resp_count)
+{
+	dhd_dbg_tx_report_t *tx_report;
+	dhd_dbg_tx_info_t *tx_pkt;
+	wifi_tx_report_t *ptr;
+	compat_wifi_tx_report_t *cptr;
+	dhd_dbg_pkt_mon_state_t tx_pkt_state;
+	dhd_dbg_pkt_mon_state_t tx_status_state;
+	uint16 pkt_count, count;
+	unsigned long flags;
+
+	DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__));
+	BCM_REFERENCE(ptr);
+	BCM_REFERENCE(cptr);
+
+	if (!dhdp || !dhdp->dbg) {
+		DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
+			dhdp, (dhdp ? dhdp->dbg : NULL)));
+		return -EINVAL;
+	}
+
+	DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
+	tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
+	tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
+	if (PKT_MON_NOT_OPERATIONAL(tx_pkt_state) ||
+			PKT_MON_NOT_OPERATIONAL(tx_status_state)) {
+		DHD_PKT_MON(("%s(): packet monitor is not yet enabled, "
+			"tx_pkt_state=%d, tx_status_state=%d\n", __FUNCTION__,
+			tx_pkt_state, tx_status_state));
+		DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
+		return -EINVAL;
+	}
+
+	count = 0;
+	tx_report = dhdp->dbg->pkt_mon.tx_report;
+	tx_pkt = tx_report->tx_pkts;
+	pkt_count = MIN(req_count, tx_report->status_pos);
+
+	{
+		ptr = (wifi_tx_report_t *)user_buf;
+		while ((count < pkt_count) && tx_pkt && ptr) {
+			__dhd_dbg_dump_tx_pkt_info(dhdp, tx_pkt, count);
+			__COPY_TO_USER(&ptr->fate, &tx_pkt->fate, sizeof(tx_pkt->fate));
+			__COPY_TO_USER(&ptr->frame_inf.payload_type,
+				&tx_pkt->info.payload_type,
+				OFFSETOF(dhd_dbg_pkt_info_t, pkt_hash));
+			__COPY_TO_USER(ptr->frame_inf.frame_content.ethernet_ii,
+				PKTDATA(dhdp->osh, tx_pkt->info.pkt), tx_pkt->info.pkt_len);
+
+			ptr++;
+			tx_pkt++;
+			count++;
+		}
+	}
+	*resp_count = pkt_count;
+
+	DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
+	if (!pkt_count) {
+		DHD_ERROR(("%s(): no tx_status in tx completion messages, "
+			"make sure that 'd11status' is enabled in firmware, "
+			"status_pos=%u", __FUNCTION__, pkt_count));
+	}
+
+	return BCME_OK;
+}
+
+int
+dhd_dbg_monitor_get_rx_pkts(dhd_pub_t *dhdp, void __user *user_buf,
+		uint16 req_count, uint16 *resp_count)
+{
+	dhd_dbg_rx_report_t *rx_report;
+	dhd_dbg_rx_info_t *rx_pkt;
+	wifi_rx_report_t *ptr;
+	compat_wifi_rx_report_t *cptr;
+	dhd_dbg_pkt_mon_state_t rx_pkt_state;
+	uint16 pkt_count, count;
+	unsigned long flags;
+
+	DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__));
+	BCM_REFERENCE(ptr);
+	BCM_REFERENCE(cptr);
+
+	if (!dhdp || !dhdp->dbg) {
+		DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
+			dhdp, (dhdp ? dhdp->dbg : NULL)));
+		return -EINVAL;
+	}
+
+	DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
+	rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
+	if (PKT_MON_NOT_OPERATIONAL(rx_pkt_state)) {
+		DHD_PKT_MON(("%s(): packet fetch is not allowed , "
+			"rx_pkt_state=%d\n", __FUNCTION__, rx_pkt_state));
+		DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
+		return -EINVAL;
+	}
+
+	count = 0;
+	rx_report = dhdp->dbg->pkt_mon.rx_report;
+	rx_pkt = rx_report->rx_pkts;
+	pkt_count = MIN(req_count, rx_report->pkt_pos);
+
+	{
+		ptr = (wifi_rx_report_t *)user_buf;
+		while ((count < pkt_count) && rx_pkt && ptr) {
+			__dhd_dbg_dump_rx_pkt_info(dhdp, rx_pkt, count);
+
+			__COPY_TO_USER(&ptr->fate, &rx_pkt->fate, sizeof(rx_pkt->fate));
+			__COPY_TO_USER(&ptr->frame_inf.payload_type,
+				&rx_pkt->info.payload_type,
+				OFFSETOF(dhd_dbg_pkt_info_t, pkt_hash));
+			__COPY_TO_USER(ptr->frame_inf.frame_content.ethernet_ii,
+				PKTDATA(dhdp->osh, rx_pkt->info.pkt), rx_pkt->info.pkt_len);
+
+			ptr++;
+			rx_pkt++;
+			count++;
+		}
+	}
+
+	*resp_count = pkt_count;
+	DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
+
+	return BCME_OK;
+}
+
+int
+dhd_dbg_detach_pkt_monitor(dhd_pub_t *dhdp)
+{
+	dhd_dbg_tx_report_t *tx_report;
+	dhd_dbg_rx_report_t *rx_report;
+	dhd_dbg_pkt_mon_state_t tx_pkt_state;
+	dhd_dbg_pkt_mon_state_t tx_status_state;
+	dhd_dbg_pkt_mon_state_t rx_pkt_state;
+	unsigned long flags;
+
+	DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__));
+	if (!dhdp || !dhdp->dbg) {
+		DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
+			dhdp, (dhdp ? dhdp->dbg : NULL)));
+		return -EINVAL;
+	}
+
+	DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
+	tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
+	tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
+	rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
+
+	if (PKT_MON_DETACHED(tx_pkt_state) || PKT_MON_DETACHED(tx_status_state) ||
+			PKT_MON_DETACHED(rx_pkt_state)) {
+		DHD_PKT_MON(("%s(): packet monitor is already detached, "
+			"tx_pkt_state=%d, tx_status_state=%d, rx_pkt_state=%d\n",
+			__FUNCTION__, tx_pkt_state, tx_status_state, rx_pkt_state));
+		DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
+		return -EINVAL;
+	}
+
+	tx_report = dhdp->dbg->pkt_mon.tx_report;
+	rx_report = dhdp->dbg->pkt_mon.rx_report;
+
+	/* free and de-initalize tx packet monitoring */
+	dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_DETACHED;
+	dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_DETACHED;
+	if (tx_report) {
+		if (tx_report->tx_pkts) {
+			__dhd_dbg_free_tx_pkts(dhdp, tx_report->tx_pkts,
+				tx_report->pkt_pos);
+			MFREE(dhdp->osh, tx_report->tx_pkts,
+				(sizeof(*tx_report->tx_pkts) * MAX_FATE_LOG_LEN));
+			dhdp->dbg->pkt_mon.tx_report->tx_pkts = NULL;
+		}
+		MFREE(dhdp->osh, tx_report, sizeof(*tx_report));
+		dhdp->dbg->pkt_mon.tx_report = NULL;
+	}
+	dhdp->dbg->pkt_mon.tx_pkt_mon = NULL;
+	dhdp->dbg->pkt_mon.tx_status_mon = NULL;
+
+	/* free and de-initalize rx packet monitoring */
+	dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_DETACHED;
+	if (rx_report) {
+		if (rx_report->rx_pkts) {
+			__dhd_dbg_free_rx_pkts(dhdp, rx_report->rx_pkts,
+				rx_report->pkt_pos);
+			MFREE(dhdp->osh, rx_report->rx_pkts,
+				(sizeof(*rx_report->rx_pkts) * MAX_FATE_LOG_LEN));
+			dhdp->dbg->pkt_mon.rx_report->rx_pkts = NULL;
+		}
+		MFREE(dhdp->osh, rx_report, sizeof(*rx_report));
+		dhdp->dbg->pkt_mon.rx_report = NULL;
+	}
+	dhdp->dbg->pkt_mon.rx_pkt_mon = NULL;
+
+	DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
+	DHD_PKT_MON(("%s(): packet monitor detach succeeded\n", __FUNCTION__));
+	return BCME_OK;
+}
+#endif /* DBG_PKT_MON */
+
+#if defined(DBG_PKT_MON) || defined(DHD_PKT_LOGGING)
+bool
+dhd_dbg_process_tx_status(dhd_pub_t *dhdp, void *pkt, uint32 pktid,
+		uint16 status)
+{
+	bool pkt_fate = TRUE;
+	if (dhdp->d11_tx_status) {
+		pkt_fate = (status == WLFC_CTL_PKTFLAG_DISCARD) ? TRUE : FALSE;
+		DHD_DBG_PKT_MON_TX_STATUS(dhdp, pkt, pktid, status);
+	}
+	return pkt_fate;
+}
+#else /* DBG_PKT_MON || DHD_PKT_LOGGING */
+bool
+dhd_dbg_process_tx_status(dhd_pub_t *dhdp, void *pkt,
+		uint32 pktid, uint16 status)
+{
+	return TRUE;
+}
+#endif /* DBG_PKT_MON || DHD_PKT_LOGGING */
+
 /*
  * dhd_dbg_attach: initialziation of dhd dbugability module
  *
@@ -1233,30 +2146,28 @@
 dhd_dbg_attach(dhd_pub_t *dhdp, dbg_pullreq_t os_pullreq,
 	dbg_urgent_noti_t os_urgent_notifier, void *os_priv)
 {
-	dhd_dbg_t *dbg;
-	int ret, ring_id;
+	dhd_dbg_t *dbg = NULL;
+	dhd_dbg_ring_t *ring = NULL;
+	int ret = BCME_ERROR, ring_id = 0;
+	void *buf = NULL;
 
 	dbg = MALLOCZ(dhdp->osh, sizeof(dhd_dbg_t));
 	if (!dbg)
 		return BCME_NOMEM;
 
+	buf = MALLOCZ(dhdp->osh, FW_VERBOSE_RING_SIZE);
+	if (!buf)
+		goto error;
 	ret = dhd_dbg_ring_init(dhdp, &dbg->dbg_rings[FW_VERBOSE_RING_ID], FW_VERBOSE_RING_ID,
-			FW_VERBOSE_RING_NAME, FW_VERBOSE_RING_SIZE);
+			(uint8 *)FW_VERBOSE_RING_NAME, FW_VERBOSE_RING_SIZE, buf, FALSE);
 	if (ret)
 		goto error;
 
-	ret = dhd_dbg_ring_init(dhdp, &dbg->dbg_rings[FW_EVENT_RING_ID], FW_EVENT_RING_ID,
-			FW_EVENT_RING_NAME, FW_EVENT_RING_SIZE);
-	if (ret)
+	buf = MALLOCZ(dhdp->osh, DHD_EVENT_RING_SIZE);
+	if (!buf)
 		goto error;
-
 	ret = dhd_dbg_ring_init(dhdp, &dbg->dbg_rings[DHD_EVENT_RING_ID], DHD_EVENT_RING_ID,
-			DHD_EVENT_RING_NAME, DHD_EVENT_RING_SIZE);
-	if (ret)
-		goto error;
-
-	ret = dhd_dbg_ring_init(dhdp, &dbg->dbg_rings[NAN_EVENT_RING_ID], NAN_EVENT_RING_ID,
-			NAN_EVENT_RING_NAME, NAN_EVENT_RING_SIZE);
+			(uint8 *)DHD_EVENT_RING_NAME, DHD_EVENT_RING_SIZE, buf, FALSE);
 	if (ret)
 		goto error;
 
@@ -1270,7 +2181,13 @@
 error:
 	for (ring_id = DEBUG_RING_ID_INVALID + 1; ring_id < DEBUG_RING_ID_MAX; ring_id++) {
 		if (VALID_RING(dbg->dbg_rings[ring_id].id)) {
-			dhd_dbg_ring_deinit(dhdp, &dbg->dbg_rings[ring_id]);
+			ring = &dbg->dbg_rings[ring_id];
+			dhd_dbg_ring_deinit(dhdp, ring);
+			if (ring->ring_buf) {
+				MFREE(dhdp->osh, ring->ring_buf, ring->ring_size);
+				ring->ring_buf = NULL;
+			}
+			ring->ring_size = 0;
 		}
 	}
 	MFREE(dhdp->osh, dhdp->dbg, sizeof(dhd_dbg_t));
@@ -1285,13 +2202,21 @@
 dhd_dbg_detach(dhd_pub_t *dhdp)
 {
 	int ring_id;
+	dhd_dbg_ring_t *ring = NULL;
 	dhd_dbg_t *dbg;
+
 	if (!dhdp->dbg)
 		return;
 	dbg = dhdp->dbg;
 	for (ring_id = DEBUG_RING_ID_INVALID + 1; ring_id < DEBUG_RING_ID_MAX; ring_id++) {
 		if (VALID_RING(dbg->dbg_rings[ring_id].id)) {
-			dhd_dbg_ring_deinit(dhdp, &dbg->dbg_rings[ring_id]);
+			ring = &dbg->dbg_rings[ring_id];
+			dhd_dbg_ring_deinit(dhdp, ring);
+			if (ring->ring_buf) {
+				MFREE(dhdp->osh, ring->ring_buf, ring->ring_size);
+				ring->ring_buf = NULL;
+			}
+			ring->ring_size = 0;
 		}
 	}
 	MFREE(dhdp->osh, dhdp->dbg, sizeof(dhd_dbg_t));

--
Gitblit v1.6.2