qcacmn: Packet log changes for wifi3.0

Change-Id: I82462f426e4e449c5bc65331e39f07a062e8e242
diff --git a/dp/wifi3.0/dp_htt.c b/dp/wifi3.0/dp_htt.c
index 97a8cd4..0ee09d9 100644
--- a/dp/wifi3.0/dp_htt.c
+++ b/dp/wifi3.0/dp_htt.c
@@ -24,10 +24,12 @@
 #include "dp_internal.h"
 #include "dp_rx_mon.h"
 #include "htt_stats.h"
+#include "qdf_mem.h"   /* qdf_mem_malloc,free */
 
 #define HTT_TLV_HDR_LEN HTT_T2H_EXT_STATS_CONF_TLV_HDR_SIZE
 
 #define HTT_HTC_PKT_POOL_INIT_SIZE 64
+#define HTT_T2H_MAX_MSG_SIZE 2048
 
 #define HTT_MSG_BUF_SIZE(msg_bytes) \
 	((msg_bytes) + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING)
@@ -1149,18 +1151,27 @@
 				msg_word, msg_word + 2);
 			break;
 		}
-#ifdef notyet
+#if defined(CONFIG_WIN) && WDI_EVENT_ENABLE
 #ifndef REMOVE_PKT_LOG
 	case HTT_T2H_MSG_TYPE_PKTLOG:
 		{
 			u_int32_t *pl_hdr;
 			pl_hdr = (msg_word + 1);
-			wdi_event_handler(WDI_EVENT_OFFLOAD_ALL, soc->dp_soc,
-				pl_hdr, HTT_INVALID_PEER, WDI_NO_VAL);
+			dp_wdi_event_handler(WDI_EVENT_OFFLOAD_ALL, soc->dp_soc,
+				(void *)pl_hdr, HTT_INVALID_PEER, WDI_NO_VAL, 0);
+			break;
+		}
+	case HTT_T2H_MSG_TYPE_PPDU_STATS_IND:
+		{
+			qdf_nbuf_set_pktlen(htt_t2h_msg, HTT_T2H_MAX_MSG_SIZE);
+			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
+				"received HTT_T2H_MSG_TYPE_PPDU_STATS_IND\n");
+			dp_wdi_event_handler(WDI_EVENT_LITE_T2H, soc->dp_soc,
+				htt_t2h_msg, HTT_INVALID_PEER, WDI_NO_VAL, 0);
 			break;
 		}
 #endif
-#endif /* notyet */
+#endif
 	case HTT_T2H_MSG_TYPE_VERSION_CONF:
 		{
 			soc->tgt_ver.major = HTT_VER_CONF_MAJOR_GET(*msg_word);
diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h
index b57eb9e..d703544 100644
--- a/dp/wifi3.0/dp_internal.h
+++ b/dp/wifi3.0/dp_internal.h
@@ -19,6 +19,10 @@
 #ifndef _DP_INTERNAL_H_
 #define _DP_INTERNAL_H_
 
+#include "dp_types.h"
+
+#define RX_BUFFER_SIZE_PKTLOG_LITE 1024
+
 #if DP_PRINT_ENABLE
 #include <stdarg.h>       /* va_list */
 #include <qdf_types.h> /* qdf_vprint */
@@ -220,6 +224,7 @@
 #endif
 
 
+
 extern int dp_peer_find_attach(struct dp_soc *soc);
 extern void dp_peer_find_detach(struct dp_soc *soc);
 extern void dp_peer_find_hash_add(struct dp_soc *soc, struct dp_peer *peer);
@@ -288,4 +293,59 @@
 void dp_set_pn_check_wifi3(struct cdp_vdev *vdev_handle,
 	struct cdp_peer *peer_handle, enum cdp_sec_type sec_type,
 	 uint32_t *rx_pn);
+
+#if defined(CONFIG_WIN) && WDI_EVENT_ENABLE
+int dp_wdi_event_unsub(struct cdp_pdev *txrx_pdev_handle,
+	void *event_cb_sub_handle,
+	uint32_t event);
+
+int dp_wdi_event_sub(struct cdp_pdev *txrx_pdev_handle,
+	void *event_cb_sub_handle,
+	uint32_t event);
+
+void dp_wdi_event_handler(enum WDI_EVENT event, void *soc,
+		void *data, u_int16_t peer_id,
+		int status, u_int8_t pdev_id);
+
+int dp_wdi_event_attach(struct dp_pdev *txrx_pdev);
+int dp_wdi_event_detach(struct dp_pdev *txrx_pdev);
+int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event,
+	bool enable);
+#else
+static inline int dp_wdi_event_unsub(struct cdp_pdev *txrx_pdev_handle,
+	void *event_cb_sub_handle,
+	uint32_t event)
+{
+	return -EPERM;
+}
+
+static inline int dp_wdi_event_sub(struct cdp_pdev *txrx_pdev_handle,
+	void *event_cb_sub_handle,
+	uint32_t event)
+{
+	return -EPERM;
+}
+
+static inline void dp_wdi_event_handler(enum WDI_EVENT event, void *soc,
+		void *data, u_int16_t peer_id,
+		int status, u_int8_t pdev_id)
+{
+}
+
+static inline int dp_wdi_event_attach(struct dp_pdev *txrx_pdev)
+{
+	return -EPERM;
+}
+
+static inline int dp_wdi_event_detach(struct dp_pdev *txrx_pdev)
+{
+	return -EPERM;
+}
+
+static inline int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event,
+	bool enable)
+{
+	return -EPERM;
+}
+#endif /* CONFIG_WIN */
 #endif /* #ifndef _DP_INTERNAL_H_ */
diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c
index 9216cb8..8971797 100644
--- a/dp/wifi3.0/dp_main.c
+++ b/dp/wifi3.0/dp_main.c
@@ -37,6 +37,7 @@
 #include "dp_peer.h"
 #include "dp_rx_mon.h"
 #include "htt_stats.h"
+#include "qdf_mem.h"   /* qdf_mem_malloc,free */
 
 #define DP_INTR_POLL_TIMER_MS	10
 #define DP_MCS_LENGTH (6*MAX_MCS)
@@ -468,7 +469,7 @@
 
 			if (rx_mon_mask & (1 << j)) {
 				irq_id_map[num_irq++] =
-					(rxdma2host_monitor_destination_mac1
+					(ppdu_end_interrupts_mac1
 					 - j);
 			}
 
@@ -1294,8 +1295,14 @@
 	/* Rx monitor mode specific init */
 	if (dp_rx_pdev_mon_attach(pdev)) {
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
-		"dp_rx_pdev_attach failed\n");
-		goto fail0;
+				"dp_rx_pdev_attach failed\n");
+		goto fail1;
+	}
+
+	if (dp_wdi_event_attach(pdev)) {
+		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+				"dp_wdi_evet_attach failed\n");
+		goto fail1;
 	}
 
 	/* set the reo destination to 1 during initialization */
@@ -1370,6 +1377,8 @@
 	struct dp_pdev *pdev = (struct dp_pdev *)txrx_pdev;
 	struct dp_soc *soc = pdev->soc;
 
+	dp_wdi_event_detach(pdev);
+
 	dp_tx_pdev_detach(pdev);
 
 	if (wlan_cfg_per_pdev_tx_ring(soc->wlan_cfg_ctx)) {
@@ -3872,6 +3881,8 @@
 	.txrx_update_filter_neighbour_peers =
 		dp_update_filter_neighbour_peers,
 	/* TODO: Add other functions */
+	.txrx_wdi_event_sub = dp_wdi_event_sub,
+	.txrx_wdi_event_unsub = dp_wdi_event_unsub,
 };
 
 static struct cdp_me_ops dp_ops_me = {
@@ -4103,3 +4114,106 @@
 fail0:
 	return NULL;
 }
+
+#if defined(CONFIG_WIN) && WDI_EVENT_ENABLE
+/*
+* dp_set_pktlog_wifi3() - attach txrx vdev
+* @pdev: Datapath PDEV handle
+* @event: which event's notifications are being subscribed to
+* @enable: WDI event subscribe or not. (True or False)
+*
+* Return: Success, NULL on failure
+*/
+int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event,
+	bool enable)
+{
+	struct dp_soc *soc = pdev->soc;
+	struct htt_rx_ring_tlv_filter htt_tlv_filter = {0};
+
+	if (enable) {
+		switch (event) {
+		case WDI_EVENT_RX_DESC:
+			if (pdev->monitor_vdev) {
+				/* Nothing needs to be done if monitor mode is
+				 * enabled
+				 */
+				return 0;
+			}
+			if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_FULL) {
+				pdev->rx_pktlog_mode = DP_RX_PKTLOG_FULL;
+				htt_tlv_filter.mpdu_start = 1;
+				htt_tlv_filter.msdu_start = 1;
+				htt_tlv_filter.msdu_end = 1;
+				htt_tlv_filter.mpdu_end = 1;
+				htt_tlv_filter.packet_header = 1;
+				htt_tlv_filter.attention = 1;
+				htt_tlv_filter.ppdu_start = 1;
+				htt_tlv_filter.ppdu_end = 1;
+				htt_tlv_filter.ppdu_end_user_stats = 1;
+				htt_tlv_filter.ppdu_end_user_stats_ext = 1;
+				htt_tlv_filter.ppdu_end_status_done = 1;
+				htt_tlv_filter.enable_fp = 1;
+
+				htt_h2t_rx_ring_cfg(soc->htt_handle,
+					pdev->pdev_id,
+					pdev->rxdma_mon_status_ring.hal_srng,
+					RXDMA_MONITOR_STATUS, RX_BUFFER_SIZE,
+					&htt_tlv_filter);
+			}
+			break;
+		case WDI_EVENT_LITE_RX:
+			if (pdev->monitor_vdev) {
+				/* Nothing needs to be done if monitor mode is
+				 * enabled
+				 */
+				return 0;
+			}
+			if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_LITE) {
+				pdev->rx_pktlog_mode = DP_RX_PKTLOG_LITE;
+				htt_tlv_filter.ppdu_start = 1;
+				htt_tlv_filter.ppdu_end = 1;
+				htt_tlv_filter.ppdu_end_user_stats = 1;
+				htt_tlv_filter.ppdu_end_user_stats_ext = 1;
+				htt_tlv_filter.ppdu_end_status_done = 1;
+				htt_tlv_filter.enable_fp = 1;
+
+				htt_h2t_rx_ring_cfg(soc->htt_handle,
+					pdev->pdev_id,
+					pdev->rxdma_mon_status_ring.hal_srng,
+					RXDMA_MONITOR_STATUS,
+					RX_BUFFER_SIZE_PKTLOG_LITE,
+					&htt_tlv_filter);
+			}
+			break;
+		default:
+			/* Nothing needs to be done for other pktlog types */
+			break;
+		}
+	} else {
+		switch (event) {
+		case WDI_EVENT_RX_DESC:
+		case WDI_EVENT_LITE_RX:
+			if (pdev->monitor_vdev) {
+				/* Nothing needs to be done if monitor mode is
+				 * enabled
+				 */
+				return 0;
+			}
+			if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED) {
+				pdev->rx_pktlog_mode = DP_RX_PKTLOG_DISABLED;
+				/* htt_tlv_filter is initialized to 0 */
+				htt_h2t_rx_ring_cfg(soc->htt_handle,
+					pdev->pdev_id,
+					pdev->rxdma_mon_status_ring.hal_srng,
+					RXDMA_MONITOR_STATUS, RX_BUFFER_SIZE,
+					&htt_tlv_filter);
+			}
+			break;
+		default:
+			/* Nothing needs to be done for other pktlog types */
+			break;
+		}
+	}
+	return 0;
+}
+#endif
diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h
index 72f33e0..50359eb 100644
--- a/dp/wifi3.0/dp_rx.h
+++ b/dp/wifi3.0/dp_rx.h
@@ -29,7 +29,7 @@
 #define RX_BUFFER_ALIGNMENT     4
 #endif /* RXDMA_OPTIMIZATION */
 
-#define RX_BUFFER_SIZE          2048
+#define RX_BUFFER_SIZE			2048
 #define RX_BUFFER_RESERVATION   0
 
 #define DP_PEER_METADATA_PEER_ID_MASK	0x0000ffff
diff --git a/dp/wifi3.0/dp_rx_mon_status.c b/dp/wifi3.0/dp_rx_mon_status.c
index 2e3d1a6..ef0eabc 100644
--- a/dp/wifi3.0/dp_rx_mon_status.c
+++ b/dp/wifi3.0/dp_rx_mon_status.c
@@ -25,6 +25,8 @@
 #include "hal_api_mon.h"
 #include "ieee80211.h"
 #include "dp_rx_mon.h"
+#include "dp_internal.h"
+#include "qdf_mem.h"   /* qdf_mem_malloc,free */
 
 
 /**
@@ -44,7 +46,7 @@
 	qdf_nbuf_t status_nbuf;
 	uint8_t *rx_tlv;
 	uint8_t *rx_tlv_start;
-	uint32_t tlv_status;
+	uint32_t tlv_status = HAL_TLV_STATUS_DUMMY;
 
 #ifdef DP_INTR_POLL_BASED
 	if (!pdev)
@@ -62,16 +64,24 @@
 		rx_tlv = qdf_nbuf_data(status_nbuf);
 		rx_tlv_start = rx_tlv;
 
-		do {
-			tlv_status = hal_rx_status_get_tlv_info(rx_tlv,
-				ppdu_info);
-			rx_tlv = hal_rx_status_get_next_tlv(rx_tlv);
+#if defined(CONFIG_WIN) && WDI_EVENT_ENABLE
+#ifndef REMOVE_PKT_LOG
+		dp_wdi_event_handler(WDI_EVENT_RX_DESC, soc,
+			status_nbuf, HTT_INVALID_PEER, WDI_NO_VAL, 0);
+#endif
+#endif
+		if (pdev->monitor_vdev != NULL) {
 
-			if ((rx_tlv - rx_tlv_start) >= RX_BUFFER_SIZE)
-				break;
+			do {
+				tlv_status = hal_rx_status_get_tlv_info(rx_tlv,
+						ppdu_info);
+				rx_tlv = hal_rx_status_get_next_tlv(rx_tlv);
 
-		} while (tlv_status == HAL_TLV_STATUS_PPDU_NOT_DONE);
+				if ((rx_tlv - rx_tlv_start) >= RX_BUFFER_SIZE)
+					break;
 
+			} while (tlv_status == HAL_TLV_STATUS_PPDU_NOT_DONE);
+		}
 		qdf_nbuf_free(status_nbuf);
 
 		if (tlv_status == HAL_TLV_STATUS_PPDU_DONE) {
diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h
index 9f907e2..d8ee9d4 100644
--- a/dp/wifi3.0/dp_types.h
+++ b/dp/wifi3.0/dp_types.h
@@ -89,6 +89,14 @@
 #define DP_MAX_INTERRUPT_CONTEXTS 8
 #define DP_MAX_MECT_ENTRIES 64
 
+#ifndef REMOVE_PKT_LOG
+enum rx_pktlog_mode {
+	DP_RX_PKTLOG_DISABLED = 0,
+	DP_RX_PKTLOG_FULL,
+	DP_RX_PKTLOG_LITE,
+};
+#endif
+
 struct dp_soc_cmn;
 struct dp_pdev;
 struct dp_vdev;
@@ -511,11 +519,6 @@
 	/* Rx ring map for interrupt processing */
 	struct dp_srng *rx_ring_map[DP_MAX_RX_RINGS];
 
-#ifndef CONFIG_WIN
-	/* WDI event handlers */
-	struct wdi_event_subscribe_t **wdi_event_list;
-#endif
-
 	/* peer ID to peer object map (array of pointers to peer objects) */
 	struct dp_peer **peer_id_to_obj_map;
 
@@ -822,6 +825,14 @@
 
 	/* map this pdev to a particular Reo Destination ring */
 	enum cdp_host_reo_dest_ring reo_dest;
+
+#ifndef REMOVE_PKT_LOG
+	/* Packet log mode */
+	uint8_t rx_pktlog_mode;
+#endif
+
+	/* WDI event handlers */
+	struct wdi_event_subscribe_t **wdi_event_list;
 };
 
 struct dp_peer;
diff --git a/dp/wifi3.0/dp_wdi_event.c b/dp/wifi3.0/dp_wdi_event.c
new file mode 100644
index 0000000..8bdc623
--- /dev/null
+++ b/dp/wifi3.0/dp_wdi_event.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#include "dp_internal.h"
+#include "qdf_mem.h"   /* qdf_mem_malloc,free */
+
+#if defined(CONFIG_WIN) && WDI_EVENT_ENABLE
+
+
+/*
+ * dp_wdi_event_next_sub() - Return handle for Next WDI event
+ * @wdi_sub: WDI Event handle
+ *
+ * Return handle for next WDI event in list
+ *
+ * Return: Next WDI event to be subscribe
+ */
+static inline wdi_event_subscribe *
+dp_wdi_event_next_sub(wdi_event_subscribe *wdi_sub)
+{
+	if (!wdi_sub) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			"Invalid subscriber in %s\n", __func__);
+		return NULL;
+	}
+	return wdi_sub->priv.next;
+}
+
+
+/*
+ * dp_wdi_event_del_subs() -Delete Event subscription
+ * @wdi_sub: WDI Event handle
+ * @event_index: Event index from list
+ *
+ * This API will delete subscribed event from list
+ * Return: None
+ */
+static inline void
+dp_wdi_event_del_subs(wdi_event_subscribe *wdi_sub, int event_index)
+{
+	/* Subscribers should take care of deletion */
+}
+
+
+/*
+ * dp_wdi_event_iter_sub() - Iterate through all WDI event in the list
+ * and pass WDI event to callback funtion
+ * @pdev: DP pdev handle
+ * @event_index: Event index in list
+ * @wdi_event: WDI event handle
+ * @data: pointer to data
+ * @peer_id: peer id number
+ * @status: HTT rx status
+ *
+ *
+ * Return: None
+ */
+static inline void
+dp_wdi_event_iter_sub(
+	struct dp_pdev *pdev,
+	uint32_t event_index,
+	wdi_event_subscribe *wdi_sub,
+	void *data,
+	uint16_t peer_id,
+	int status)
+{
+	enum WDI_EVENT event = event_index + WDI_EVENT_BASE;
+
+	if (wdi_sub) {
+		do {
+			wdi_sub->callback(wdi_sub->context, event, data,
+					peer_id, status);
+		} while ((wdi_sub = dp_wdi_event_next_sub(wdi_sub)));
+	}
+}
+
+
+/*
+ * dp_wdi_event_handler() - Event handler for WDI event
+ * @event: wdi event number
+ * @soc: soc handle
+ * @data: pointer to data
+ * @peer_id: peer id number
+ * @status: HTT rx status
+ * @pdev_id: id of pdev
+ *
+ * It will be called to register WDI event
+ *
+ * Return: None
+ */
+void
+dp_wdi_event_handler(
+	enum WDI_EVENT event,
+	void *soc,
+	void *data,
+	uint16_t peer_id,
+	int status, uint8_t pdev_id)
+{
+	uint32_t event_index;
+	wdi_event_subscribe *wdi_sub;
+	struct dp_pdev *txrx_pdev;
+	struct dp_soc *soc_t = (struct dp_soc *)soc;
+	txrx_pdev = (struct dp_pdev *)soc_t->pdev_list[pdev_id];
+
+	if (!event) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			"Invalid WDI event in %s\n", __func__);
+		return;
+	}
+	if (!txrx_pdev) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			"Invalid pdev in WDI event handler\n");
+		return;
+	}
+
+	/*
+	 *  There can be NULL data, so no validation for the data
+	 *  Subscribers must do the sanity based on the requirements
+	 */
+	event_index = event - WDI_EVENT_BASE;
+	if (!(txrx_pdev->wdi_event_list[event_index]) &&
+		(event == WDI_EVENT_RX_DESC)) {
+		/* WDI_EVEN_RX_DESC is indicated for RX_LITE also */
+		event_index = WDI_EVENT_LITE_RX - WDI_EVENT_BASE;
+	}
+	wdi_sub = txrx_pdev->wdi_event_list[event_index];
+
+	/* Find the subscriber */
+	dp_wdi_event_iter_sub(txrx_pdev, event_index, wdi_sub, data,
+			peer_id, status);
+}
+
+
+/*
+ * dp_wdi_event_sub() - Subscribe WDI event
+ * @txrx_pdev_handle: cdp_pdev handle
+ * @event_cb_sub_handle: subcribe evnet handle
+ * @event: Event to be subscribe
+ *
+ * Return: 0 for success. nonzero for failure.
+ */
+int
+dp_wdi_event_sub(
+	struct cdp_pdev *txrx_pdev_handle,
+	void *event_cb_sub_handle,
+	uint32_t event)
+{
+	uint32_t event_index;
+	wdi_event_subscribe *wdi_sub;
+	struct dp_pdev *txrx_pdev = (struct dp_pdev *)txrx_pdev_handle;
+	wdi_event_subscribe *event_cb_sub =
+		(wdi_event_subscribe *) event_cb_sub_handle;
+
+	if (!txrx_pdev) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			"Invalid txrx_pdev in %s", __func__);
+		return -EINVAL;
+	}
+	if (!event_cb_sub) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			"Invalid callback in %s", __func__);
+		return -EINVAL;
+	}
+	if ((!event) || (event >= WDI_EVENT_LAST) || (event < WDI_EVENT_BASE)) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			"Invalid event in %s", __func__);
+		return -EINVAL;
+	}
+	dp_set_pktlog_wifi3(txrx_pdev, event, true);
+	event_index = event - WDI_EVENT_BASE;
+	wdi_sub = txrx_pdev->wdi_event_list[event_index];
+
+	/*
+	 *  Check if it is the first subscriber of the event
+	 */
+	if (!wdi_sub) {
+		wdi_sub = event_cb_sub;
+		wdi_sub->priv.next = NULL;
+		wdi_sub->priv.prev = NULL;
+		txrx_pdev->wdi_event_list[event_index] = wdi_sub;
+		return 0;
+	}
+	event_cb_sub->priv.next = wdi_sub;
+	event_cb_sub->priv.prev = NULL;
+	wdi_sub->priv.prev = event_cb_sub;
+	txrx_pdev->wdi_event_list[event_index] = event_cb_sub;
+	return 0;
+
+}
+
+/*
+ * dp_wdi_event_unsub() - WDI event unsubscribe
+ * @txrx_pdev_handle: cdp_pdev handle
+ * @event_cb_sub_handle: subscribed event handle
+ * @event: Event to be unsubscribe
+ *
+ *
+ * Return: 0 for success. nonzero for failure.
+ */
+int
+dp_wdi_event_unsub(
+	struct cdp_pdev *txrx_pdev_handle,
+	void *event_cb_sub_handle,
+	uint32_t event)
+{
+	uint32_t event_index = event - WDI_EVENT_BASE;
+	struct dp_pdev *txrx_pdev = (struct dp_pdev *)txrx_pdev_handle;
+	wdi_event_subscribe *event_cb_sub =
+		(wdi_event_subscribe *) event_cb_sub_handle;
+
+	if (!event_cb_sub) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			"Invalid callback in %s", __func__);
+		return -EINVAL;
+	}
+
+	dp_set_pktlog_wifi3(txrx_pdev, event, false);
+
+	if (!event_cb_sub->priv.prev) {
+		txrx_pdev->wdi_event_list[event_index] = event_cb_sub->priv.next;
+	} else {
+		event_cb_sub->priv.prev->priv.next = event_cb_sub->priv.next;
+	}
+	if (event_cb_sub->priv.next) {
+		event_cb_sub->priv.next->priv.prev = event_cb_sub->priv.prev;
+	}
+
+	return 0;
+}
+
+
+/*
+ * dp_wdi_event_attach() - Attach wdi event
+ * @txrx_pdev: DP pdev handle
+ *
+ * Return: 0 for success. nonzero for failure.
+ */
+int
+dp_wdi_event_attach(struct dp_pdev *txrx_pdev)
+{
+	if (!txrx_pdev) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			"Invalid device in %s\nWDI event attach failed\n",
+			__func__);
+		return -EINVAL;
+	}
+	/* Separate subscriber list for each event */
+	txrx_pdev->wdi_event_list = (wdi_event_subscribe **)
+		qdf_mem_malloc(
+			sizeof(wdi_event_subscribe *) * WDI_NUM_EVENTS);
+	if (!txrx_pdev->wdi_event_list) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			"Insufficient memory for the WDI event lists\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+
+/*
+ * dp_wdi_event_detach() - Detach WDI event
+ * @txrx_pdev: DP pdev handle
+ *
+ * Return: 0 for success. nonzero for failure.
+ */
+int
+dp_wdi_event_detach(struct dp_pdev *txrx_pdev)
+{
+	int i;
+	wdi_event_subscribe *wdi_sub;
+	if (!txrx_pdev) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			"Invalid device in %s\nWDI attach failed", __func__);
+		return -EINVAL;
+	}
+	if (!txrx_pdev->wdi_event_list) {
+		return -EINVAL;
+	}
+	for (i = 0; i < WDI_NUM_EVENTS; i++) {
+		wdi_sub = txrx_pdev->wdi_event_list[i];
+		/* Delete all the subscribers */
+		dp_wdi_event_del_subs(wdi_sub, i);
+	}
+	if (txrx_pdev->wdi_event_list) {
+		qdf_mem_free(txrx_pdev->wdi_event_list);
+	}
+	return 0;
+}
+#endif /* CONFIG_WIN */
diff --git a/hif/src/ce/ce_assignment.h b/hif/src/ce/ce_assignment.h
index 7dfbe3c..18b3a83 100644
--- a/hif/src/ce/ce_assignment.h
+++ b/hif/src/ce/ce_assignment.h
@@ -569,9 +569,8 @@
 	/* host->target HTT */
 	{ /* CE4 */ (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0,
 		CE_HTT_H2T_MSG_SRC_NENTRIES, 256, 0, NULL,},
-	/* ipa_uc->target HTC control */
-	{ /* CE5 */ (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0,
-		1024, 512, 0, NULL,},
+	/* target -> host PKTLOG */
+	{ /* CE5 */ CE_ATTR_FLAGS, 0, 0, 2048, 512, NULL,},
 	/* Target autonomous HIF_memcpy */
 	{ /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,},
 	/* host->target WMI (mac1) */
@@ -582,8 +581,7 @@
 	{ /* CE9 */ CE_ATTR_FLAGS, 0, 32,  2048, 0, NULL,},
 	/* target->host HTT */
 	{ /* CE10 */ CE_ATTR_FLAGS, 0, 0,  2048, 512, NULL,},
-	/* target -> host PKTLOG */
-	{ /* CE11 */ CE_ATTR_FLAGS, 0, 0, 2048, 512, NULL,},
+	/* CE11 unused */
 };
 
 static struct CE_pipe_config target_ce_config_wlan_qca8074[] = {
@@ -628,9 +626,8 @@
 	/* host->target HTT */
 	{ /* CE4 */ (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0,
 		CE_HTT_H2T_MSG_SRC_NENTRIES, 256, 0, NULL,},
-	/* ipa_uc->target HTC control */
-	{ /* CE5 */ (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0,
-		1024, 512, 0, NULL,},
+	/* target -> host PKTLOG */
+	{ /* CE5 */ EPPING_CE_FLAGS_POLL, 0, 0, 2048, 512, NULL,},
 	/* Target autonomous HIF_memcpy */
 	{ /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,},
 	/* host->target WMI (mac1) */
@@ -641,9 +638,9 @@
 	{ /* CE9 */ EPPING_CE_FLAGS_POLL, 0, 32,  2048, 0, NULL,},
 	/* target->host HTT */
 	{ /* CE10 */ CE_ATTR_FLAGS, 0, 0,  2048, 512, NULL,},
-	/* target -> host PKTLOG */
-	{ /* CE11 */ CE_ATTR_FLAGS, 0, 0, 2048, 512, NULL,},
+	/* CE11 unused */
 };
+
 static struct CE_pipe_config target_ce_config_wlan_qca8074_pci[] = {
 	/* host->target HTC control and raw streams */
 	{ /* CE0 */ 0, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,},
diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h
index f413dd0..01dccc7 100644
--- a/wmi/inc/wmi_unified_api.h
+++ b/wmi/inc/wmi_unified_api.h
@@ -426,14 +426,14 @@
 
 #ifndef CONFIG_MCL
 QDF_STATUS wmi_unified_packet_log_enable_send(void *wmi_hdl,
-				WMI_HOST_PKTLOG_EVENT PKTLOG_EVENT);
+			WMI_HOST_PKTLOG_EVENT PKTLOG_EVENT, uint8_t mac_id);
 #else
 QDF_STATUS wmi_unified_packet_log_enable_send(void *wmi_hdl,
 				uint8_t macaddr[IEEE80211_ADDR_LEN],
 				struct packet_enable_params *param);
 #endif
 
-QDF_STATUS wmi_unified_packet_log_disable_send(void *wmi_hdl);
+QDF_STATUS wmi_unified_packet_log_disable_send(void *wmi_hdl, uint8_t mac_id);
 
 QDF_STATUS wmi_unified_suspend_send(void *wmi_hdl,
 				struct suspend_params *param,
diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h
index b35c2a6..65dc5bf 100644
--- a/wmi/inc/wmi_unified_priv.h
+++ b/wmi/inc/wmi_unified_priv.h
@@ -260,14 +260,15 @@
 
 #ifdef CONFIG_WIN
 QDF_STATUS (*send_packet_log_enable_cmd)(wmi_unified_t wmi_handle,
-				WMI_HOST_PKTLOG_EVENT PKTLOG_EVENT);
+			WMI_HOST_PKTLOG_EVENT PKTLOG_EVENT, uint8_t mac_id);
 #else
 QDF_STATUS (*send_packet_log_enable_cmd)(wmi_unified_t wmi_handle,
 				uint8_t macaddr[IEEE80211_ADDR_LEN],
 				struct packet_enable_params *param);
 #endif
 
-QDF_STATUS (*send_packet_log_disable_cmd)(wmi_unified_t wmi_handle);
+QDF_STATUS (*send_packet_log_disable_cmd)(wmi_unified_t wmi_handle,
+	uint8_t mac_id);
 
 QDF_STATUS (*send_beacon_send_cmd)(wmi_unified_t wmi_handle,
 				struct beacon_params *param);
diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c
index 2835a37..3d7192f 100644
--- a/wmi/src/wmi_unified_api.c
+++ b/wmi/src/wmi_unified_api.c
@@ -648,13 +648,13 @@
  *  Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
  */
 QDF_STATUS wmi_unified_packet_log_enable_send(void *wmi_hdl,
-				WMI_HOST_PKTLOG_EVENT PKTLOG_EVENT)
+			WMI_HOST_PKTLOG_EVENT PKTLOG_EVENT, uint8_t mac_id)
 {
 	wmi_unified_t wmi_handle = (wmi_unified_t) wmi_hdl;
 
 	if (wmi_handle->ops->send_packet_log_enable_cmd)
 		return wmi_handle->ops->send_packet_log_enable_cmd(wmi_handle,
-				  PKTLOG_EVENT);
+				  PKTLOG_EVENT, mac_id);
 
 	return QDF_STATUS_E_FAILURE;
 }
@@ -666,12 +666,13 @@
  *  @param PKTLOG_EVENT    : packet log event
  *  @return QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
  */
-QDF_STATUS wmi_unified_packet_log_disable_send(void *wmi_hdl)
+QDF_STATUS wmi_unified_packet_log_disable_send(void *wmi_hdl, uint8_t mac_id)
 {
 	wmi_unified_t wmi_handle = (wmi_unified_t) wmi_hdl;
 
 	if (wmi_handle->ops->send_packet_log_disable_cmd)
-		return wmi_handle->ops->send_packet_log_disable_cmd(wmi_handle);
+		return wmi_handle->ops->send_packet_log_disable_cmd(wmi_handle,
+			mac_id);
 
 	return QDF_STATUS_E_FAILURE;
 }
diff --git a/wmi/src/wmi_unified_non_tlv.c b/wmi/src/wmi_unified_non_tlv.c
index f96eb49..224d15d 100644
--- a/wmi/src/wmi_unified_non_tlv.c
+++ b/wmi/src/wmi_unified_non_tlv.c
@@ -1446,10 +1446,11 @@
  *
  *  @param wmi_handle	  : handle to WMI.
  *  @param PKTLOG_EVENT	: packet log event
+ *  @mac_id: mac id to have radio context
  *  @return QDF_STATUS_SUCCESS  on success and -ve on failure.
  */
 static QDF_STATUS send_packet_log_enable_cmd_non_tlv(wmi_unified_t wmi_handle,
-				WMI_HOST_PKTLOG_EVENT PKTLOG_EVENT)
+			WMI_HOST_PKTLOG_EVENT PKTLOG_EVENT, uint8_t mac_id)
 {
 	wmi_pdev_pktlog_enable_cmd *cmd;
 	int len = 0;
@@ -1474,9 +1475,11 @@
  *  send_packet_log_disable_cmd_non_tlv() - WMI disable packet log send function
  *
  *  @param wmi_handle	  : handle to WMI.
+ *  @mac_id: mac id to have radio context
  *  @return QDF_STATUS_SUCCESS  on success and -ve on failure.
  */
-static QDF_STATUS send_packet_log_disable_cmd_non_tlv(wmi_unified_t wmi_handle)
+static QDF_STATUS send_packet_log_disable_cmd_non_tlv(wmi_unified_t wmi_handle,
+	uint8_t mac_id)
 {
 	int len = 0;
 	wmi_buf_t buf;
diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c
index 37330c0..621369f 100644
--- a/wmi/src/wmi_unified_tlv.c
+++ b/wmi/src/wmi_unified_tlv.c
@@ -1575,17 +1575,79 @@
 
 #ifdef CONFIG_WIN
 /**
- *  send_packet_log_enable_cmd_tlv() - WMI request stats function
+ *  send_packet_log_enable_cmd_tlv() - Send WMI command to enable packet-log
  *  @param wmi_handle      : handle to WMI.
- *  @param macaddr        : MAC address
- *  @param param    : pointer to hold stats request parameter
+ *  @param PKTLOG_EVENT	: packet log event
+ *  @mac_id: mac id to have radio context
  *
  *  Return: 0  on success and -ve on failure.
  */
 static QDF_STATUS send_packet_log_enable_cmd_tlv(wmi_unified_t wmi_handle,
-				WMI_HOST_PKTLOG_EVENT PKTLOG_EVENT)
+			WMI_HOST_PKTLOG_EVENT PKTLOG_EVENT, uint8_t mac_id)
 {
-	return 0;
+	int32_t ret;
+	wmi_pdev_pktlog_enable_cmd_fixed_param *cmd;
+	wmi_buf_t buf;
+	uint16_t len = sizeof(wmi_pdev_pktlog_enable_cmd_fixed_param);
+
+	buf = wmi_buf_alloc(wmi_handle, len);
+	if (!buf) {
+		WMI_LOGE("%s: wmi_buf_alloc failed", __func__);
+		return -QDF_STATUS_E_NOMEM;
+	}
+
+	cmd = (wmi_pdev_pktlog_enable_cmd_fixed_param *) wmi_buf_data(buf);
+	WMITLV_SET_HDR(&cmd->tlv_header,
+		       WMITLV_TAG_STRUC_wmi_pdev_pktlog_enable_cmd_fixed_param,
+		       WMITLV_GET_STRUCT_TLVLEN
+			       (wmi_pdev_pktlog_enable_cmd_fixed_param));
+	cmd->evlist = PKTLOG_EVENT;
+	cmd->pdev_id = mac_id;
+	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
+					 WMI_PDEV_PKTLOG_ENABLE_CMDID);
+	if (ret) {
+		WMI_LOGE("Failed to send pktlog enable cmd to FW =%d", ret);
+		wmi_buf_free(buf);
+	}
+
+	return ret;
+}
+
+/**
+ *  send_packet_log_disable_cmd_tlv() - Send WMI command to disable packet-log
+ *  @param wmi_handle      : handle to WMI.
+ *  @mac_id: mac id to have radio context
+ *
+ *  Return: 0  on success and -ve on failure.
+ */
+static QDF_STATUS send_packet_log_disable_cmd_tlv(wmi_unified_t wmi_handle,
+			WMI_HOST_PKTLOG_EVENT PKTLOG_EVENT, uint8_t mac_id)
+{
+	int32_t ret;
+	wmi_pdev_pktlog_disable_cmd_fixed_param *cmd;
+	wmi_buf_t buf;
+	uint16_t len = sizeof(wmi_pdev_pktlog_disable_cmd_fixed_param);
+
+	buf = wmi_buf_alloc(wmi_handle, len);
+	if (!buf) {
+		WMI_LOGE("%s: wmi_buf_alloc failed", __func__);
+		return -QDF_STATUS_E_NOMEM;
+	}
+
+	cmd = (wmi_pdev_pktlog_disable_cmd_fixed_param *) wmi_buf_data(buf);
+	WMITLV_SET_HDR(&cmd->tlv_header,
+		       WMITLV_TAG_STRUC_wmi_pdev_pktlog_disable_cmd_fixed_param,
+		       WMITLV_GET_STRUCT_TLVLEN
+			       (wmi_pdev_pktlog_disable_cmd_fixed_param));
+	cmd->pdev_id = mac_id;
+	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
+					 WMI_PDEV_PKTLOG_DISABLE_CMDID);
+	if (ret) {
+		WMI_LOGE("Failed to send pktlog disable cmd to FW =%d", ret);
+		wmi_buf_free(buf);
+	}
+
+	return ret;
 }
 #else
 /**