Merge "qca-wifi: CFR: Change format-specifiers while printing CFR metadata"
diff --git a/configs/wlan_cfg/ap_wlan_cfg.config b/configs/wlan_cfg/ap_wlan_cfg.config
index 525791c..dd0ffb8 100644
--- a/configs/wlan_cfg/ap_wlan_cfg.config
+++ b/configs/wlan_cfg/ap_wlan_cfg.config
@@ -34,3 +34,6 @@
 EXTRA_CFLAGS += -DRX_DATA_BUFFER_SIZE=1792
 EXTRA_CFLAGS += -DRX_DATA_BUFFER_ALIGNMENT=0
 endif
+
+EXTRA_CFLAGS += -DWLAN_PSOC_MAX_VDEVS=60
+EXTRA_CFLAGS += -DWLAN_PDEV_MAX_VDEVS=30
diff --git a/dp/wifi3.0/dp_rx_mon_feature.c b/dp/wifi3.0/dp_rx_mon_feature.c
index 121714e..4a4c66b 100644
--- a/dp/wifi3.0/dp_rx_mon_feature.c
+++ b/dp/wifi3.0/dp_rx_mon_feature.c
@@ -684,9 +684,19 @@
 	return dp_mon_filter_update(pdev);
 }
 
-void
-dp_peer_set_rx_capture_enabled(struct dp_peer *peer, bool value)
+QDF_STATUS
+dp_peer_set_rx_capture_enabled(struct dp_pdev *pdev, struct dp_peer *peer,
+			       bool value, uint8_t *mac_addr)
 {
+	if (!peer) {
+		dp_err("Invalid Peer");
+		if (value)
+			return QDF_STATUS_E_FAILURE;
+		return QDF_STATUS_SUCCESS;
+	}
+
 	peer->rx_cap_enabled = value;
+
+	return QDF_STATUS_SUCCESS;
 }
 #endif /* WLAN_RX_PKT_CAPTURE_ENH */
diff --git a/dp/wifi3.0/dp_rx_mon_feature.h b/dp/wifi3.0/dp_rx_mon_feature.h
index f21135a..41b2296 100644
--- a/dp/wifi3.0/dp_rx_mon_feature.h
+++ b/dp/wifi3.0/dp_rx_mon_feature.h
@@ -76,12 +76,15 @@
 
 /**
  * dp_peer_set_rx_capture_enabled: Set rx_cap_enabled bit in peer
+ * @pdev: DP_PDEV handle
  * @peer_handle: Peer handle
  * @value: Enable/disable setting for rx_cap_enabled
+ * @mac_addr: peer mac address
  *
- * Return: None
+ * Return: status
  */
-void
-dp_peer_set_rx_capture_enabled(struct dp_peer *peer, bool value);
+QDF_STATUS dp_peer_set_rx_capture_enabled(struct dp_pdev *pdev,
+					  struct dp_peer *peer_handle,
+					  bool value, uint8_t *mac_addr);
 #endif /* WLAN_RX_PKT_CAPTURE_ENH */
 #endif /* _DP_RX_MON_FEATURE_H_ */
diff --git a/dp/wifi3.0/dp_rx_tag.c b/dp/wifi3.0/dp_rx_tag.c
index 0b3f600..9eb5e0a 100644
--- a/dp/wifi3.0/dp_rx_tag.c
+++ b/dp/wifi3.0/dp_rx_tag.c
@@ -284,7 +284,7 @@
 	if (qdf_likely(1 != dp_pdev->ppdu_info.rx_status.rxpcu_filter_pass))
 		return;
 
-	msdu_ppdu_id = hal_rx_hw_desc_get_ppduid_get(soc->hal_soc, rx_desc);
+	msdu_ppdu_id = hal_rx_get_ppdu_id(soc->hal_soc, rx_desc);
 
 	if (msdu_ppdu_id != dp_pdev->ppdu_info.com_info.ppdu_id) {
 		QDF_TRACE(QDF_MODULE_ID_DP,
diff --git a/dp/wifi3.0/dp_tx_capture.c b/dp/wifi3.0/dp_tx_capture.c
index 8d2ac96..e54de49 100644
--- a/dp/wifi3.0/dp_tx_capture.c
+++ b/dp/wifi3.0/dp_tx_capture.c
@@ -34,7 +34,8 @@
 #define MAX_MONITOR_HEADER (512)
 #define MAX_DUMMY_FRM_BODY (128)
 #define DP_BA_ACK_FRAME_SIZE (sizeof(struct ieee80211_ctlframe_addr2) + 36)
-#define DP_ACK_FRAME_SIZE (struct ieee80211_frame_min_one)
+#define DP_ACK_FRAME_SIZE (sizeof(struct ieee80211_frame_min_one))
+#define DP_CTS_FRAME_SIZE (sizeof(struct ieee80211_frame_min_one))
 #define DP_MAX_MPDU_64 64
 #define DP_NUM_WORDS_PER_PPDU_BITMAP_64 (DP_MAX_MPDU_64 >> 5)
 #define DP_NUM_BYTES_PER_PPDU_BITMAP_64 (DP_MAX_MPDU_64 >> 3)
@@ -154,20 +155,27 @@
  * based on global per-pdev setting or per-peer setting
  * @pdev: Datapath pdev handle
  * @peer: Datapath peer
+ * @mac_addr: peer mac address
  *
  * Return: true if feature is enabled on a per-pdev basis or if
  * enabled for the given peer when per-peer mode is set, false otherwise
  */
 inline bool
 dp_peer_or_pdev_tx_cap_enabled(struct dp_pdev *pdev,
-			       struct dp_peer *peer)
+			       struct dp_peer *peer, uint8_t *mac_addr)
 {
 	if ((pdev->tx_capture_enabled ==
 	     CDP_TX_ENH_CAPTURE_ENABLE_ALL_PEERS) ||
-	    ((pdev->tx_capture_enabled ==
-	      CDP_TX_ENH_CAPTURE_ENDIS_PER_PEER) &&
-	     peer->tx_cap_enabled))
-		return true;
+	    (pdev->tx_capture_enabled ==
+	      CDP_TX_ENH_CAPTURE_ENDIS_PER_PEER)) {
+		if (peer && peer->tx_cap_enabled)
+			return true;
+
+		/* do search based on mac address */
+		return is_dp_peer_mgmt_pkt_filter(pdev,
+						  HTT_INVALID_PEER,
+						  mac_addr);
+	}
 	return false;
 }
 
@@ -304,6 +312,11 @@
 			return;
 		}
 
+		if (!dp_peer_or_pdev_tx_cap_enabled(pdev, NULL, wh->i_addr1)) {
+			qdf_nbuf_free(nbuf);
+			return;
+		}
+
 		qdf_spin_lock_bh(
 			&pdev->tx_capture.ctl_mgmt_lock[type][subtype]);
 		qdf_nbuf_queue_add(&pdev->tx_capture.ctl_mgmt_q[type][subtype],
@@ -317,6 +330,208 @@
 	}
 }
 
+static inline int dp_peer_compare_mac_addr(void *addr1, void *addr2)
+{
+	union dp_align_mac_addr *mac_addr1 = (union dp_align_mac_addr *)addr1;
+	union dp_align_mac_addr *mac_addr2 = (union dp_align_mac_addr *)addr2;
+
+	return !((mac_addr1->align4.bytes_abcd == mac_addr2->align4.bytes_abcd)
+		 & (mac_addr1->align4.bytes_ef == mac_addr2->align4.bytes_ef));
+}
+
+/*
+ * dp_peer_tx_cap_search: filter mgmt pkt based on peer and mac address
+ * @pdev: DP PDEV handle
+ * @peer_id: DP PEER ID
+ * @mac_addr: pointer to mac address
+ *
+ * return: true on matched and false on not found
+ */
+static
+bool dp_peer_tx_cap_search(struct dp_pdev *pdev,
+			   uint16_t peer_id, uint8_t *mac_addr)
+{
+	struct dp_pdev_tx_capture *tx_capture;
+	struct dp_peer_mgmt_list *ptr_peer_mgmt_list;
+	uint8_t i = 0;
+	bool found = false;
+
+	tx_capture = &pdev->tx_capture;
+
+	/* search based on mac address */
+	for (i = 0; i < MAX_MGMT_PEER_FILTER; i++) {
+		uint8_t *peer_mac_addr;
+
+		ptr_peer_mgmt_list = &tx_capture->ptr_peer_mgmt_list[i];
+		if (ptr_peer_mgmt_list->avail)
+			continue;
+		peer_mac_addr = ptr_peer_mgmt_list->mac_addr;
+		if (!dp_peer_compare_mac_addr(mac_addr,
+					      peer_mac_addr)) {
+			found = true;
+			break;
+		}
+	}
+	return found;
+}
+
+/*
+ * dp_peer_tx_cap_add_filter: add peer filter mgmt pkt based on peer
+ * and mac address
+ * @pdev: DP PDEV handle
+ * @peer_id: DP PEER ID
+ * @mac_addr: pointer to mac address
+ *
+ * return: true on added and false on not failed
+ */
+bool dp_peer_tx_cap_add_filter(struct dp_pdev *pdev,
+			       uint16_t peer_id, uint8_t *mac_addr)
+{
+	struct dp_pdev_tx_capture *tx_capture;
+	struct dp_peer_mgmt_list *ptr_peer_mgmt_list;
+	uint8_t i = 0;
+	bool status = false;
+
+	tx_capture = &pdev->tx_capture;
+
+	if (dp_peer_tx_cap_search(pdev, peer_id, mac_addr)) {
+		/* mac address and peer_id already there */
+		QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE, QDF_TRACE_LEVEL_INFO_LOW,
+			  "%s: %d peer_id[%d] mac_addr[%pM] already there\n",
+			  __func__, __LINE__, peer_id, mac_addr);
+		return status;
+	}
+
+	for (i = 0; i < MAX_MGMT_PEER_FILTER; i++) {
+		ptr_peer_mgmt_list = &tx_capture->ptr_peer_mgmt_list[i];
+		if (!ptr_peer_mgmt_list->avail)
+			continue;
+		qdf_mem_copy(ptr_peer_mgmt_list->mac_addr,
+			     mac_addr, QDF_MAC_ADDR_SIZE);
+		ptr_peer_mgmt_list->avail = false;
+		ptr_peer_mgmt_list->peer_id = peer_id;
+		status = true;
+		break;
+	}
+
+	return status;
+}
+
+/*
+ * dp_peer_tx_cap_del_all_filter: delete all peer filter mgmt pkt based on peer
+ * and mac address
+ * @pdev: DP PDEV handle
+ * @peer_id: DP PEER ID
+ * @mac_addr: pointer to mac address
+ *
+ * return: void
+ */
+void dp_peer_tx_cap_del_all_filter(struct dp_pdev *pdev)
+{
+	struct dp_pdev_tx_capture *tx_capture;
+	struct dp_peer_mgmt_list *ptr_peer_mgmt_list;
+	uint8_t i = 0;
+
+	tx_capture = &pdev->tx_capture;
+
+	for (i = 0; i < MAX_MGMT_PEER_FILTER; i++) {
+		ptr_peer_mgmt_list = &tx_capture->ptr_peer_mgmt_list[i];
+		ptr_peer_mgmt_list->avail = true;
+		ptr_peer_mgmt_list->peer_id = HTT_INVALID_PEER;
+		qdf_mem_zero(ptr_peer_mgmt_list->mac_addr, QDF_MAC_ADDR_SIZE);
+	}
+}
+
+/*
+ * dp_peer_tx_cap_del_filter: delete peer filter mgmt pkt based on peer
+ * and mac address
+ * @pdev: DP PDEV handle
+ * @peer_id: DP PEER ID
+ * @mac_addr: pointer to mac address
+ *
+ * return: true on added and false on not failed
+ */
+bool dp_peer_tx_cap_del_filter(struct dp_pdev *pdev,
+			       uint16_t peer_id, uint8_t *mac_addr)
+{
+	struct dp_pdev_tx_capture *tx_capture;
+	struct dp_peer_mgmt_list *ptr_peer_mgmt_list;
+	uint8_t i = 0;
+	bool status = false;
+
+	tx_capture = &pdev->tx_capture;
+
+	for (i = 0; i < MAX_MGMT_PEER_FILTER; i++) {
+		ptr_peer_mgmt_list = &tx_capture->ptr_peer_mgmt_list[i];
+		if (!dp_peer_compare_mac_addr(mac_addr,
+					      ptr_peer_mgmt_list->mac_addr) &&
+		    (!ptr_peer_mgmt_list->avail)) {
+			ptr_peer_mgmt_list->avail = true;
+			ptr_peer_mgmt_list->peer_id = HTT_INVALID_PEER;
+			qdf_mem_zero(ptr_peer_mgmt_list->mac_addr,
+				     QDF_MAC_ADDR_SIZE);
+			status = true;
+			break;
+		}
+	}
+
+	if (!status)
+		QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE, QDF_TRACE_LEVEL_INFO_LOW,
+			  "unable to delete peer[%d] mac[%pM] filter list",
+			  peer_id, mac_addr);
+	return status;
+}
+
+/*
+ * dp_peer_tx_cap_print_mgmt_filter: pradd peer filter mgmt pkt based on peer
+ * and mac address
+ * @pdev: DP PDEV handle
+ * @peer_id: DP PEER ID
+ * @mac_addr: pointer to mac address
+ *
+ * return: true on added and false on not failed
+ */
+void dp_peer_tx_cap_print_mgmt_filter(struct dp_pdev *pdev,
+				      uint16_t peer_id, uint8_t *mac_addr)
+{
+	struct dp_pdev_tx_capture *tx_capture;
+	struct dp_peer_mgmt_list *ptr_peer_mgmt_list;
+	uint8_t i = 0;
+
+	tx_capture = &pdev->tx_capture;
+
+	QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE, QDF_TRACE_LEVEL_INFO_LOW,
+		  "peer filter list:");
+	for (i = 0; i < MAX_MGMT_PEER_FILTER; i++) {
+		ptr_peer_mgmt_list = &tx_capture->ptr_peer_mgmt_list[i];
+		QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE, QDF_TRACE_LEVEL_INFO_LOW,
+			  "peer_id[%d] mac_addr[%pM] avail[%d]",
+			  ptr_peer_mgmt_list->peer_id,
+			  ptr_peer_mgmt_list->mac_addr,
+			  ptr_peer_mgmt_list->avail);
+	}
+}
+
+/*
+ * dp_peer_mgmt_pkt_filter: filter mgmt pkt based on peer and mac address
+ * @pdev: DP PDEV handle
+ * @nbuf: buffer containing the ppdu_desc
+ *
+ * return: status
+ */
+bool is_dp_peer_mgmt_pkt_filter(struct dp_pdev *pdev,
+				uint32_t peer_id, uint8_t *mac_addr)
+{
+	bool found = false;
+
+	found = dp_peer_tx_cap_search(pdev, peer_id, mac_addr);
+	QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE, QDF_TRACE_LEVEL_INFO_LOW,
+		  "%s: %d peer_id[%d] mac_addr[%pM] found[%d]!",
+		  __func__, __LINE__, peer_id, mac_addr, found);
+
+	return found;
+}
+
 /**
  * dp_tx_ppdu_stats_attach - Initialize Tx PPDU stats and enhanced capture
  * @pdev: DP PDEV
@@ -325,7 +540,11 @@
  */
 void dp_tx_ppdu_stats_attach(struct dp_pdev *pdev)
 {
+	struct dp_peer_mgmt_list *ptr_peer_mgmt_list;
+	struct dp_pdev_tx_capture *tx_capture;
 	int i, j;
+
+	tx_capture = &pdev->tx_capture;
 	/* Work queue setup for HTT stats and tx capture handling */
 	qdf_create_work(0, &pdev->tx_capture.ppdu_stats_work,
 			dp_tx_ppdu_stats_process,
@@ -349,6 +568,14 @@
 	}
 	qdf_mem_zero(&pdev->tx_capture.dummy_ppdu_desc,
 		     sizeof(struct cdp_tx_completion_ppdu));
+
+	pdev->tx_capture.ptr_peer_mgmt_list = (struct dp_peer_mgmt_list *)
+			qdf_mem_malloc(sizeof(struct dp_peer_mgmt_list) *
+				       MAX_MGMT_PEER_FILTER);
+	for (i = 0; i < MAX_MGMT_PEER_FILTER; i++) {
+		ptr_peer_mgmt_list = &tx_capture->ptr_peer_mgmt_list[i];
+		ptr_peer_mgmt_list->avail = true;
+	}
 }
 
 /**
@@ -399,6 +626,8 @@
 				&pdev->tx_capture.ctl_mgmt_lock[i][j]);
 		}
 	}
+
+	qdf_mem_free(pdev->tx_capture.ptr_peer_mgmt_list);
 }
 
 /**
@@ -498,14 +727,15 @@
 				   struct dp_peer *peer)
 {
 	int ret = QDF_STATUS_E_FAILURE;
+	struct dp_pdev *pdev = desc->pdev;
 
-	if (peer && dp_peer_or_pdev_tx_cap_enabled(desc->pdev, peer) &&
+	if (peer &&
+	    dp_peer_or_pdev_tx_cap_enabled(pdev, peer, peer->mac_addr.raw) &&
 	    ((ts->status == HAL_TX_TQM_RR_FRAME_ACKED) ||
 	    (ts->status == HAL_TX_TQM_RR_REM_CMD_TX) ||
-	    ((ts->status == HAL_TX_TQM_RR_REM_CMD_AGED) && ts->transmit_cnt))) {
-		ret = dp_update_msdu_to_list(soc, desc->pdev,
-					     peer, ts, desc->nbuf);
-	}
+	    ((ts->status == HAL_TX_TQM_RR_REM_CMD_AGED) && ts->transmit_cnt)))
+		ret = dp_update_msdu_to_list(soc, pdev, peer, ts, desc->nbuf);
+
 	return ret;
 }
 
@@ -666,6 +896,8 @@
 			int tid;
 			struct dp_tx_tid *tx_tid;
 
+			/* set peer tx cap enabled to 0, when feature disable */
+			peer->tx_cap_enabled = 0;
 			for (tid = 0; tid < DP_MAX_TIDS; tid++) {
 				qdf_nbuf_t ppdu_nbuf = NULL;
 				struct cdp_tx_completion_ppdu *ppdu_desc =
@@ -742,6 +974,7 @@
 					&pdev->tx_capture.ctl_mgmt_lock[i][j]);
 			}
 		}
+		dp_peer_tx_cap_del_all_filter(pdev);
 	}
 
 	qdf_spin_unlock(&pdev->tx_capture.config_lock);
@@ -1411,6 +1644,7 @@
 					  void *desc)
 {
 	struct dp_peer *peer;
+	struct dp_vdev *vdev = NULL;
 	struct cdp_tx_completion_ppdu *ppdu_desc = desc;
 	struct cdp_tx_completion_ppdu_user *user = &ppdu_desc->user[0];
 	struct ieee80211_ctlframe_addr2 *wh_min;
@@ -1497,15 +1731,17 @@
 	else {
 		peer = dp_peer_find_by_id(pdev->soc, user->peer_id);
 		if (peer) {
-			struct dp_vdev *vdev = NULL;
-
 			vdev = peer->vdev;
-			if (vdev)
-				qdf_mem_copy(wh_min->i_addr2,
-					     vdev->mac_addr.raw,
-					     QDF_MAC_ADDR_SIZE);
 			dp_peer_unref_del_find_by_id(peer);
+		} else {
+			vdev =
+			dp_get_vdev_from_soc_vdev_id_wifi3(pdev->soc,
+							   ppdu_desc->vdev_id);
 		}
+		if (vdev)
+			qdf_mem_copy(wh_min->i_addr2,
+				     vdev->mac_addr.raw,
+				     QDF_MAC_ADDR_SIZE);
 		qdf_nbuf_set_pktlen(tx_capture_info.mpdu_nbuf, sizeof(*wh_min));
 	}
 
@@ -1544,6 +1780,7 @@
 	struct dp_pdev_tx_capture *ptr_tx_cap;
 	struct dp_peer *peer;
 	uint8_t rts_send;
+	struct dp_vdev *vdev = NULL;
 
 	rts_send = 0;
 	ptr_tx_cap = &pdev->tx_capture;
@@ -1595,16 +1832,20 @@
 		peer = dp_peer_find_by_id(pdev->soc,
 					  cur_ppdu_desc->user[0].peer_id);
 		if (peer) {
-			struct dp_vdev *vdev = NULL;
-
 			vdev = peer->vdev;
-			if (vdev)
-				qdf_mem_copy(&ppdu_desc->user[0].mac_addr,
-					     vdev->mac_addr.raw,
-					     QDF_MAC_ADDR_SIZE);
 			dp_peer_unref_del_find_by_id(peer);
+		} else {
+			uint8_t vdev_id;
+
+			vdev_id = ppdu_desc->vdev_id;
+			vdev = dp_get_vdev_from_soc_vdev_id_wifi3(pdev->soc,
+								  vdev_id);
 		}
 
+		if (vdev)
+			qdf_mem_copy(&ppdu_desc->user[0].mac_addr,
+				     vdev->mac_addr.raw, QDF_MAC_ADDR_SIZE);
+
 		dp_send_dummy_mpdu_info_to_stack(pdev, ppdu_desc);
 	}
 }
@@ -1730,7 +1971,9 @@
 			qdf_nbuf_free(tx_capture_info.mpdu_nbuf);
 	}
 
-	if (ppdu_desc->resp_type == HTT_PPDU_STATS_ACK_EXPECTED_E)
+	if (ppdu_desc->resp_type == HTT_PPDU_STATS_ACK_EXPECTED_E &&
+	    ppdu_desc->user[0].completion_status ==
+	    HTT_PPDU_STATS_USER_STATUS_OK)
 		dp_gen_ack_rx_frame(pdev, &tx_capture_info);
 }
 
@@ -2198,6 +2441,12 @@
 		subtype = 0;
 	}
 
+	if (!dp_peer_or_pdev_tx_cap_enabled(pdev, NULL,
+					    ppdu_desc->user[0].mac_addr)) {
+		qdf_nbuf_free(nbuf_ppdu_desc);
+		status = 0;
+		goto free_ppdu_desc;
+	}
 	switch (ppdu_desc->htt_frame_type) {
 	case HTT_STATS_FTYPE_TIDQ_DATA_SU:
 	case HTT_STATS_FTYPE_TIDQ_DATA_MU:
@@ -2275,7 +2524,7 @@
 			    HTT_PPDU_STATS_USER_STATUS_FILTERED) {
 				qdf_nbuf_free(nbuf_ppdu_desc);
 				status = 0;
-				goto free_ppdu_desc;
+				goto insert_mgmt_buf_to_queue;
 			}
 
 			/*
@@ -2284,6 +2533,7 @@
 			qdf_nbuf_queue_add(retries_q, nbuf_ppdu_desc);
 			status = 0;
 
+insert_mgmt_buf_to_queue:
 			/*
 			 * insert the mgmt_ctl buffer back to
 			 * the queue
@@ -2874,6 +3124,7 @@
 			uint16_t tid = 0;
 			uint32_t num_msdu = 0;
 			uint32_t qlen = 0;
+			uint16_t peer_id;
 
 			qdf_nbuf_queue_init(&head_msdu);
 			qdf_nbuf_queue_init(&head_xretries);
@@ -2937,19 +3188,19 @@
 				continue;
 			}
 
-			peer = dp_peer_find_by_id(pdev->soc,
-						  ppdu_desc->user[0].peer_id);
-			/**
-			 * peer can be NULL
-			 */
-			if (!peer) {
-				qdf_nbuf_free(nbuf);
-				continue;
-			}
-
 			if ((ppdu_desc->frame_type == CDP_PPDU_FTYPE_DATA) ||
 			    (ppdu_desc->num_mpdu &&
 			     ppdu_desc->frame_type == CDP_PPDU_FTYPE_BAR)) {
+				peer_id = ppdu_desc->user[0].peer_id;
+				peer = dp_peer_find_by_id(pdev->soc, peer_id);
+				/**
+				 * peer can be NULL
+				 */
+				if (!peer) {
+					qdf_nbuf_free(nbuf);
+					continue;
+				}
+
 				/**
 				 * check whether it is bss peer,
 				 * if bss_peer no need to process further
@@ -2958,7 +3209,7 @@
 				 */
 				if (peer->bss_peer ||
 				    !dp_peer_or_pdev_tx_cap_enabled(pdev,
-				    peer)) {
+				    peer, peer->mac_addr.raw)) {
 					dp_peer_unref_del_find_by_id(peer);
 					qdf_nbuf_free(nbuf);
 					continue;
@@ -3065,6 +3316,8 @@
 					  ppdu_desc->user[0].start_seq,
 					  ppdu_cnt,
 					  ppdu_desc_cnt);
+
+				dp_peer_unref_del_find_by_id(peer);
 			} else {
 				/*
 				 * other packet frame also added to
@@ -3073,7 +3326,6 @@
 				nbuf_ppdu_desc_list[ppdu_desc_cnt++] = nbuf;
 			}
 
-			dp_peer_unref_del_find_by_id(peer);
 		}
 
 		/*
@@ -3263,6 +3515,107 @@
 			    (frm - (uint8_t *)qdf_nbuf_data(mpdu_nbuf)));
 }
 
+static void dp_gen_cts_frame(struct hal_rx_ppdu_info *ppdu_info,
+			     struct dp_peer *peer,
+			     qdf_nbuf_t mpdu_nbuf)
+{
+	struct ieee80211_frame_min_one *wh_addr1;
+	uint16_t duration;
+
+	wh_addr1 = (struct ieee80211_frame_min_one *)
+		qdf_nbuf_data(mpdu_nbuf);
+
+	wh_addr1->i_fc[0] = 0;
+	wh_addr1->i_fc[1] = 0;
+	wh_addr1->i_fc[0] =  IEEE80211_FC0_VERSION_0 |
+		IEEE80211_FC0_TYPE_CTL |
+		IEEE80211_FC0_SUBTYPE_CTS;
+	qdf_mem_copy(wh_addr1->i_addr1, &peer->mac_addr.raw[0],
+		     QDF_MAC_ADDR_SIZE);
+	duration = (ppdu_info->rx_status.duration > SIFS_INTERVAL) ?
+		ppdu_info->rx_status.duration - SIFS_INTERVAL : 0;
+	wh_addr1->i_dur[0] = duration & 0xff;
+	wh_addr1->i_dur[1] = (duration >> 8) & 0xff;
+	qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_addr1));
+}
+
+/**
+ * dp_send_cts_frame_to_stack(): Function to deliver HW generated CTS frame
+ *	in reponse to RTS
+ * @soc: core txrx main context
+ * @pdev: DP pdev object
+ * @ppdu_info: HAL RX PPDU info retrieved from status ring TLV
+ *
+ * return: status
+ */
+QDF_STATUS dp_send_cts_frame_to_stack(struct dp_soc *soc,
+				      struct dp_pdev *pdev,
+				      struct hal_rx_ppdu_info *ppdu_info)
+{
+	struct cdp_tx_indication_info tx_capture_info;
+	struct mon_rx_user_status *rx_user_status =
+		&ppdu_info->rx_user_status[0];
+	struct dp_ast_entry *ast_entry;
+	uint32_t peer_id;
+	struct dp_peer *peer;
+
+	if (rx_user_status->ast_index >=
+	    wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx)) {
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	qdf_spin_lock_bh(&soc->ast_lock);
+	ast_entry = soc->ast_table[rx_user_status->ast_index];
+	if (!ast_entry) {
+		qdf_spin_unlock_bh(&soc->ast_lock);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	peer = ast_entry->peer;
+	if (!peer || peer->peer_ids[0] == HTT_INVALID_PEER) {
+		qdf_spin_unlock_bh(&soc->ast_lock);
+		return QDF_STATUS_E_FAILURE;
+	}
+	peer_id = peer->peer_ids[0];
+	qdf_spin_unlock_bh(&soc->ast_lock);
+
+	peer = dp_peer_find_by_id(soc, peer_id);
+	if (!peer)
+		return QDF_STATUS_E_FAILURE;
+
+	if (!dp_peer_or_pdev_tx_cap_enabled(pdev, NULL, peer->mac_addr.raw)) {
+		dp_peer_unref_del_find_by_id(peer);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	set_mpdu_info(&tx_capture_info,
+		      &ppdu_info->rx_status, rx_user_status);
+	tx_capture_info.mpdu_info.mcs = rx_user_status->mcs;
+	/* ppdu_desc is not required for legacy frames */
+	tx_capture_info.ppdu_desc = NULL;
+
+	tx_capture_info.mpdu_nbuf =
+		qdf_nbuf_alloc(pdev->soc->osdev,
+			       MAX_MONITOR_HEADER +
+			       DP_CTS_FRAME_SIZE,
+			       MAX_MONITOR_HEADER,
+			       4, FALSE);
+
+	if (!tx_capture_info.mpdu_nbuf) {
+		dp_peer_unref_del_find_by_id(peer);
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	dp_gen_cts_frame(ppdu_info, peer,
+				 tx_capture_info.mpdu_nbuf);
+	dp_peer_unref_del_find_by_id(peer);
+	dp_wdi_event_handler(WDI_EVENT_TX_DATA, pdev->soc,
+			     &tx_capture_info, HTT_INVALID_PEER,
+			     WDI_NO_VAL, pdev->pdev_id);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 /**
  * dp_send_ack_frame_to_stack(): Function to generate BA or ACK frame and
  * send to upper layer on received unicast frame
@@ -3286,6 +3639,7 @@
 	uint32_t ast_index;
 	uint32_t i;
 	bool bar_frame;
+	uint8_t *ptr_mac_addr;
 
 	rx_status = &ppdu_info->rx_status;
 
@@ -3301,6 +3655,10 @@
 		return QDF_STATUS_SUCCESS;
 	}
 
+	if (ppdu_info->sw_frame_group_id ==
+	    HAL_MPDU_SW_FRAME_GROUP_CTRL_RTS)
+		return dp_send_cts_frame_to_stack(soc, pdev, ppdu_info);
+
 	if (ppdu_info->sw_frame_group_id == HAL_MPDU_SW_FRAME_GROUP_CTRL_BAR)
 		bar_frame = true;
 	else
@@ -3324,6 +3682,10 @@
 		ast_index = rx_user_status->ast_index;
 		if (ast_index >=
 		    wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx)) {
+			ptr_mac_addr = &ppdu_info->nac_info.mac_addr2[0];
+			if (!dp_peer_or_pdev_tx_cap_enabled(pdev,
+							    NULL, ptr_mac_addr))
+				continue;
 			set_mpdu_info(&tx_capture_info,
 				      rx_status, rx_user_status);
 			tx_capture_info.mpdu_nbuf =
@@ -3362,7 +3724,8 @@
 			continue;
 
 		if (!dp_peer_or_pdev_tx_cap_enabled(pdev,
-						    peer)) {
+						    NULL,
+						    peer->mac_addr.raw)) {
 			dp_peer_unref_del_find_by_id(peer);
 			continue;
 		}
@@ -3406,16 +3769,56 @@
 
 /**
  * dp_peer_set_tx_capture_enabled: Set tx_cap_enabled bit in peer
+ * @pdev: DP PDEV handle
  * @peer: Peer handle
  * @value: Enable/disable setting for tx_cap_enabled
+ * @peer_mac: peer mac address
  *
- * Return: None
+ * Return: QDF_STATUS
  */
-void
-dp_peer_set_tx_capture_enabled(struct dp_peer *peer, bool value)
+QDF_STATUS
+dp_peer_set_tx_capture_enabled(struct dp_pdev *pdev,
+			       struct dp_peer *peer, uint8_t value,
+			       uint8_t *peer_mac)
 {
-	peer->tx_cap_enabled = value;
-	if (!value)
-		dp_peer_tx_cap_tid_queue_flush(peer);
+	uint32_t peer_id = HTT_INVALID_PEER;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+	if (value) {
+		if (dp_peer_tx_cap_add_filter(pdev, peer_id, peer_mac)) {
+			if (peer)
+				peer->tx_cap_enabled = value;
+			status = QDF_STATUS_SUCCESS;
+		}
+	} else {
+		if (dp_peer_tx_cap_del_filter(pdev, peer_id, peer_mac)) {
+			if (peer)
+				peer->tx_cap_enabled = value;
+			status = QDF_STATUS_SUCCESS;
+		}
+	}
+
+	return status;
+}
+
+/*
+ * dp_peer_tx_capture_filter_check: check filter is enable for the filter
+ * and update tx_cap_enabled flag
+ * @pdev: DP PDEV handle
+ * @peer: DP PEER handle
+ *
+ * return: void
+ */
+void dp_peer_tx_capture_filter_check(struct dp_pdev *pdev,
+				     struct dp_peer *peer)
+{
+	if (!peer)
+		return;
+
+	if (dp_peer_tx_cap_search(pdev, peer->peer_ids[0],
+				  peer->mac_addr.raw)) {
+		peer->tx_cap_enabled = 1;
+	}
+	return;
 }
 #endif
diff --git a/dp/wifi3.0/dp_tx_capture.h b/dp/wifi3.0/dp_tx_capture.h
index 6f85eaf..016675c 100644
--- a/dp/wifi3.0/dp_tx_capture.h
+++ b/dp/wifi3.0/dp_tx_capture.h
@@ -35,6 +35,16 @@
 #define TXCAP_MAX_SUBTYPE \
 	((IEEE80211_FC0_SUBTYPE_MASK >> IEEE80211_FC0_SUBTYPE_SHIFT) + 1)
 
+#define SIFS_INTERVAL 16
+
+#define MAX_MGMT_PEER_FILTER 16
+struct dp_peer_mgmt_list {
+	uint8_t mac_addr[QDF_MAC_ADDR_SIZE];
+	uint32_t mgmt_pkt_counter;
+	uint16_t peer_id;
+	bool avail;
+};
+
 struct dp_pdev_tx_capture {
 	/* For deferred PPDU status processing */
 	qdf_spinlock_t ppdu_stats_lock;
@@ -60,6 +70,7 @@
 	qdf_spinlock_t config_lock;
 	uint32_t htt_frame_type[TX_CAP_HTT_MAX_FTYPE];
 	struct cdp_tx_completion_ppdu dummy_ppdu_desc;
+	struct dp_peer_mgmt_list *ptr_peer_mgmt_list;
 };
 
 /* Tx TID */
@@ -261,12 +272,73 @@
 
 /**
  * dp_peer_set_tx_capture_enabled: Set tx_cap_enabled bit in peer
+ * @pdev: DP PDEV handle
  * @peer: Peer handle
  * @value: Enable/disable setting for tx_cap_enabled
+ * @peer_mac: peer_mac Enable/disable setting for tx_cap_enabled
  *
- * Return: None
+ * Return: QDF_STATUS
  */
-void
-dp_peer_set_tx_capture_enabled(struct dp_peer *peer, bool value);
+QDF_STATUS
+dp_peer_set_tx_capture_enabled(struct dp_pdev *pdev,
+			       struct dp_peer *peer, uint8_t value,
+			       uint8_t *peer_mac);
+
+/*
+ * dp_peer_tx_cap_add_filter: add peer filter mgmt pkt based on peer
+ * and mac address
+ * @pdev: DP PDEV handle
+ * @peer_id: DP PEER ID
+ * @mac_addr: pointer to mac address
+ *
+ * return: true on added and false on not failed
+ */
+bool dp_pdev_tx_cap_add_filter(struct dp_pdev *pdev,
+			       uint16_t peer_id, uint8_t *mac_addr);
+
+/*
+ * dp_peer_tx_cap_del_filter: delete peer filter mgmt pkt based on peer
+ * and mac address
+ * @pdev: DP PDEV handle
+ * @peer_id: DP PEER ID
+ * @mac_addr: pointer to mac address
+ *
+ * return: true on added and false on not failed
+ */
+bool dp_peer_tx_cap_del_filter(struct dp_pdev *pdev,
+			       uint16_t peer_id, uint8_t *mac_addr);
+
+/*
+ * dp_peer_tx_cap_print_mgmt_filter: pradd peer filter mgmt pkt based on peer
+ * and mac address
+ * @pdev: DP PDEV handle
+ * @peer_id: DP PEER ID
+ * @mac_addr: pointer to mac address
+ *
+ * return: true on added and false on not failed
+ */
+void dp_peer_tx_cap_print_mgmt_filter(struct dp_pdev *pdev,
+				      uint16_t peer_id, uint8_t *mac_addr);
+
+/*
+ * dp_peer_mgmt_pkt_filter: filter mgmt pkt based on peer and mac address
+ * @pdev: DP PDEV handle
+ * @nbuf: buffer containing the ppdu_desc
+ *
+ * return: status
+ */
+bool is_dp_peer_mgmt_pkt_filter(struct dp_pdev *pdev,
+				uint32_t peer_id, uint8_t *mac_addr);
+
+/*
+ * dp_peer_tx_capture_filter_check: check filter is enable for the filter
+ * and update tx_cap_enabled flag
+ * @pdev: DP PDEV handle
+ * @peer: DP PEER handle
+ *
+ * return: void
+ */
+void dp_peer_tx_capture_filter_check(struct dp_pdev *pdev,
+				     struct dp_peer *peer);
 #endif
 #endif
diff --git a/target_if/cfr/inc/target_if_cfr_6018.h b/target_if/cfr/inc/target_if_cfr_6018.h
index 5acbefd..510ad1d 100644
--- a/target_if/cfr/inc/target_if_cfr_6018.h
+++ b/target_if/cfr/inc/target_if_cfr_6018.h
@@ -59,8 +59,8 @@
 
 #define CYP_MAX_HEADER_LENGTH_WORDS 16
 
-/* Max(2048, 16016, 10240) */
-#define CYP_MAX_DATA_LENGTH_BYTES 16016
+/* payload_len = Max(2048, 16016, 10240) = 16064 (64-bit alignment) */
+#define CYP_MAX_DATA_LENGTH_BYTES 16064
 
 /* in ms */
 #define LUT_AGE_TIMER 3000
diff --git a/target_if/cfr/src/target_if_cfr_6018.c b/target_if/cfr/src/target_if_cfr_6018.c
index 8568749..afea3aa 100644
--- a/target_if/cfr/src/target_if_cfr_6018.c
+++ b/target_if/cfr/src/target_if_cfr_6018.c
@@ -171,60 +171,6 @@
 }
 
 /**
- * cfr_free_all_lut_entries() - Flush all pending DBR and TXRX events.
- * @pdev: objmgr pdev
- *
- * return: none
- */
-void cfr_free_all_lut_entries(struct wlan_objmgr_pdev *pdev)
-{
-	struct pdev_cfr *pcfr;
-	struct look_up_table *lut = NULL;
-	int i = 0;
-	QDF_STATUS retval = 0;
-	qdf_dma_addr_t buf_addr = 0, buf_addr_temp = 0;
-
-	retval = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID);
-	if (retval != QDF_STATUS_SUCCESS) {
-		cfr_err("failed to get pdev reference");
-		return;
-	}
-
-	pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev,
-						     WLAN_UMAC_COMP_CFR);
-	if (!pcfr) {
-		cfr_err("pdev object for CFR is null");
-		wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
-		return;
-	}
-
-	for (i = 0; i < NUM_LUT_ENTRIES; i++) {
-		lut = get_lut_entry(pcfr, i);
-		if (!lut)
-			continue;
-
-		if (lut->dbr_recv && !lut->tx_recv) {
-			target_if_dbr_buf_release(pdev, DBR_MODULE_CFR,
-						  lut->dbr_address,
-						  i, 0);
-			pcfr->flush_all_dbr_cnt++;
-			release_lut_entry_enh(pdev, lut);
-		} else if (lut->tx_recv && !lut->dbr_recv) {
-			buf_addr_temp = (lut->tx_address2 & 0x0f);
-			buf_addr = (lut->tx_address1
-				    | ((uint64_t)buf_addr_temp << 32));
-			target_if_dbr_buf_release(pdev,
-						  DBR_MODULE_CFR,
-						  buf_addr,
-						  i, 0);
-			pcfr->flush_all_txrx_cnt++;
-			release_lut_entry_enh(pdev, lut);
-		}
-	}
-	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
-}
-
-/**
  * dump_freeze_tlv() - Dump freeze TLV sent in enhanced DMA header
  * @freeze_tlv: Freeze TLV sent from MAC to PHY
  * @cookie: Index into lookup table
@@ -544,6 +490,8 @@
 						     WLAN_UMAC_COMP_CFR);
 
 	if (module_id == CORRELATE_TXRX_EV_MODULE_ID) {
+		if (lut->tx_recv)
+			pcfr->cfr_dma_aborts++;
 		lut->tx_recv = true;
 	} else if (module_id == CORRELATE_DBR_MODULE_ID) {
 		pcfr->dbr_evt_cnt++;
@@ -584,8 +532,13 @@
 				pcfr->invalid_dma_length_cnt++;
 				cfr_err("<CORRELATE><%u>:CFR buffers "
 					"received with invalid length "
-					"length : ppdu_id:0x%04x\n",
-					cookie, lut->tx_ppdu_id);
+					"header_length_words = %d "
+					"cfr_payload_length_bytes = %d "
+					"ppdu_id:0x%04x\n",
+					cookie,
+					lut->header_length,
+					lut->payload_length,
+					lut->tx_ppdu_id);
 				/*
 				 * Assert here as length exceeding the allowed
 				 * limit would anyway manifest as random crash
@@ -606,6 +559,7 @@
 			lut->tx_recv = false;
 			lut->tx_ppdu_id = 0;
 			pcfr->clear_txrx_event++;
+			pcfr->cfr_dma_aborts++;
 			status = STATUS_HOLD;
 		}
 	} else {
@@ -739,7 +693,7 @@
 
 	vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_CFR_ID);
 	if (qdf_unlikely(!vdev)) {
-		cfr_err("vdev is null\n");
+		cfr_debug("vdev is null\n");
 		goto done;
 	}
 
@@ -1253,6 +1207,7 @@
 	}
 
 	pcfr->tx_evt_cnt++;
+	pcfr->total_tx_evt_cnt++;
 
 	lut->tx_ppdu_id = (tx_evt_param.correlation_info_2 >> 16);
 	lut->tx_address1 = tx_evt_param.correlation_info_1;
@@ -1444,7 +1399,7 @@
 		if (lut->dbr_recv && !lut->tx_recv) {
 			diff = cur_tstamp - lut->dbr_tstamp;
 			if (diff > LUT_AGE_THRESHOLD) {
-				cfr_err("<%d>TXRX event not received for "
+				cfr_debug("<%d>TXRX event not received for "
 					"%llu ms, release lut entry : "
 					"dma_addr = 0x%pK\n", i, diff,
 					(void *)((uintptr_t)lut->dbr_address));
@@ -1457,6 +1412,8 @@
 		}
 	}
 
+	if (pcfr->lut_timer_init)
+		qdf_timer_mod(&pcfr->lut_age_timer, LUT_AGE_TIMER);
 	wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID);
 }
 
@@ -1474,7 +1431,9 @@
 	pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev,
 						     WLAN_UMAC_COMP_CFR);
 
-	qdf_timer_mod(&pcfr->lut_age_timer, LUT_AGE_TIMER);
+	if (pcfr->lut_timer_init)
+		qdf_timer_mod(&pcfr->lut_age_timer, LUT_AGE_TIMER);
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -1492,7 +1451,9 @@
 	pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev,
 						     WLAN_UMAC_COMP_CFR);
 
-	qdf_timer_stop(&pcfr->lut_age_timer);
+	if (pcfr->lut_timer_init)
+		qdf_timer_stop(&pcfr->lut_age_timer);
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -1535,6 +1496,7 @@
 		return status;
 	}
 
+	pcfr->is_cfr_rcc_capable = 1;
 	pcfr->rcc_param.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
 	pcfr->rcc_param.modified_in_curr_session = MAX_RESET_CFG_ENTRY;
 	pcfr->rcc_param.num_grp_tlvs = MAX_TA_RA_ENTRIES;
@@ -1561,14 +1523,6 @@
 		pcfr->lut_timer_init = 1;
 	}
 
-	pcfr->cfr_data_subscriber = (wdi_event_subscribe *)
-		qdf_mem_malloc(sizeof(wdi_event_subscribe));
-	if (!pcfr->cfr_data_subscriber) {
-		cfr_err("Failed to alloc cfr_data_subscriber object\n");
-		return QDF_STATUS_E_NULL_VALUE;
-	}
-
-
 	return status;
 }
 
@@ -1593,6 +1547,7 @@
 	}
 
 	if (pcfr->lut_timer_init) {
+		qdf_timer_stop(&pcfr->lut_age_timer);
 		qdf_timer_free(&(pcfr->lut_age_timer));
 		pcfr->lut_timer_init = 0;
 	}
@@ -1600,16 +1555,16 @@
 	pcfr->tx_evt_cnt = 0;
 	pcfr->dbr_evt_cnt = 0;
 	pcfr->release_cnt = 0;
+	pcfr->total_tx_evt_cnt = 0;
 	pcfr->rx_tlv_evt_cnt = 0;
 	pcfr->flush_dbr_cnt = 0;
-	pcfr->flush_all_dbr_cnt = 0;
-	pcfr->flush_all_txrx_cnt = 0;
 	pcfr->flush_timeout_dbr_cnt = 0;
 	pcfr->invalid_dma_length_cnt = 0;
 	pcfr->clear_txrx_event = 0;
 	pcfr->bb_captured_channel_cnt = 0;
 	pcfr->bb_captured_timeout_cnt = 0;
 	pcfr->rx_loc_info_valid_cnt = 0;
+	pcfr->cfr_dma_aborts = 0;
 	qdf_mem_zero(&pcfr->chan_capture_status,
 		     sizeof(uint64_t) * NUM_CHAN_CAPTURE_STATUS);
 	qdf_mem_zero(&pcfr->bb_captured_reason_cnt,
@@ -1628,11 +1583,5 @@
 	if (status != QDF_STATUS_SUCCESS)
 		cfr_err("Failed to register with dbr");
 
-	if (pcfr->cfr_data_subscriber) {
-		qdf_mem_free(pcfr->cfr_data_subscriber);
-		pcfr->cfr_data_subscriber = NULL;
-	}
-
-
 	return status;
 }
diff --git a/umac/cfr/dispatcher/inc/wlan_cfr_utils_api.h b/umac/cfr/dispatcher/inc/wlan_cfr_utils_api.h
index f467559..772b366 100644
--- a/umac/cfr/dispatcher/inc/wlan_cfr_utils_api.h
+++ b/umac/cfr/dispatcher/inc/wlan_cfr_utils_api.h
@@ -444,10 +444,26 @@
  * pdev_obj: pointer to pdev object
  * is_cfr_capable: flag to determine if cfr is enabled or not
  * cfr_timer_enable: flag to enable/disable timer
+ * cfr_mem_chunk: Region of memory used for storing cfr data
+ * cfr_max_sta_count: Maximum stations supported in one-shot capture mode
+ * num_subbufs: No. of sub-buffers used in relayfs
+ * subbuf_size: Size of sub-buffer used in relayfs
+ * chan_ptr: Channel in relayfs
+ * dir_ptr: Parent directory of relayfs file
+ * lut: lookup table used to store asynchronous DBR and TX/RX events for
+ * correlation
+ * dbr_buf_size: Size of DBR completion buffer
+ * dbr_num_bufs: No. of DBR completions
+ * tx_evt_cnt: No. of TX completion events till CFR stop was issued
+ * total_tx_evt_cnt: No. of Tx completion events since wifi was up
+ * dbr_evt_cnt: No. of WMI DBR completion events
+ * release_cnt: No. of CFR data buffers relayed to userspace
+ * rcc_param: Structure to store CFR config for the current commit session
+ * global: Structure to store accumulated CFR config
  * rx_tlv_evt_cnt: Number of CFR WDI events from datapath
  * lut_age_timer: Timer to flush pending TXRX/DBR events in lookup table
  * lut_timer_init: flag to determine if lut_age_timer is initialized or not
- * cfr_data_subscriber: CFR WDI subscriber object
+ * is_cfr_rcc_capable: Flag to determine if RCC is enabled or not.
  * bb_captured_channel_cnt: No. of PPDUs for which MAC sent Freeze TLV to PHY
  * bb_captured_timeout_cnt: No. of PPDUs for which CFR filter criteria matched
  * but MAC did not send Freeze TLV to PHY as time exceeded freeze tlv delay
@@ -466,10 +482,17 @@
  *	[3] - No. PPDUs filtered due to freeze_reason_TA_RA_TYPE_FILTER
  *	[4] - No. PPDUs filtered due to freeze_reason_NDPA_NDP
  *	[5] - No. PPDUs filtered due to freeze_reason_ALL_PACKET
- * release_err_cnt: No. of lookup table entries freed due to invalid CFR data
- * length
+ * flush_dbr_cnt: No. of un-correlated DBR completions flushed when a newer PPDU
+ * is correlated successfully with newer DBR completion
+ * invalid_dma_length_cnt: No. of buffers for which CFR DMA header length (or)
+ * data length was invalid
+ * flush_timeout_dbr_cnt: No. of DBR completion flushed out in ageout logic
+ * clear_txrx_event: No. of PPDU status TLVs over-written in LUT
+ * unassoc_pool: Pool of un-associated clients used when capture method is
+ * CFR_CAPTURE_METHOD_PROBE_RESPONSE
  * last_success_tstamp: DBR timestamp which indicates that both DBR and TX/RX
  * events have been received successfully.
+ * cfr_dma_aborts: No. of CFR DMA aborts in ucode
  */
 /*
  * To be extended if we get more capbality info
@@ -490,6 +513,7 @@
 	uint32_t dbr_buf_size;
 	uint32_t dbr_num_bufs;
 	uint64_t tx_evt_cnt;
+	uint64_t total_tx_evt_cnt;
 	uint64_t dbr_evt_cnt;
 	uint64_t release_cnt;
 #ifdef WLAN_ENH_CFR_ENABLE
@@ -498,19 +522,18 @@
 	uint64_t rx_tlv_evt_cnt;
 	qdf_timer_t lut_age_timer;
 	uint8_t lut_timer_init;
-	void *cfr_data_subscriber;
+	uint8_t is_cfr_rcc_capable;
 	uint64_t bb_captured_channel_cnt;
 	uint64_t bb_captured_timeout_cnt;
 	uint64_t rx_loc_info_valid_cnt;
 	uint64_t chan_capture_status[CAPTURE_MAX];
 	uint64_t bb_captured_reason_cnt[FREEZE_REASON_MAX];
 	uint64_t flush_dbr_cnt;
-	uint64_t flush_all_dbr_cnt;
-	uint64_t flush_all_txrx_cnt;
 	uint64_t invalid_dma_length_cnt;
 	uint64_t flush_timeout_dbr_cnt;
 	uint64_t clear_txrx_event;
 	uint64_t last_success_tstamp;
+	uint64_t cfr_dma_aborts;
 #endif
 	struct unassoc_pool_entry unassoc_pool[MAX_CFR_ENABLED_CLIENTS];
 };
diff --git a/umac/cfr/dispatcher/src/wlan_cfr_ucfg_api.c b/umac/cfr/dispatcher/src/wlan_cfr_ucfg_api.c
index c112b72..66da03a 100644
--- a/umac/cfr/dispatcher/src/wlan_cfr_ucfg_api.c
+++ b/umac/cfr/dispatcher/src/wlan_cfr_ucfg_api.c
@@ -312,7 +312,7 @@
 		return QDF_STATUS_E_NULL_VALUE;
 	}
 
-	if (!(*ppcfr)->is_cfr_capable) {
+	if (!(*ppcfr)->is_cfr_rcc_capable) {
 		cfr_err("cfr is not supported on this chip\n");
 		wlan_objmgr_pdev_release_ref(*ppdev, WLAN_CFR_ID);
 		return QDF_STATUS_E_NOSUPPORT;
@@ -800,33 +800,31 @@
 		return status;
 
 	cfr_err("bb_captured_channel_cnt = %llu\n",
-		 pcfr->bb_captured_channel_cnt);
+		pcfr->bb_captured_channel_cnt);
 	cfr_err("bb_captured_timeout_cnt = %llu\n",
-		 pcfr->bb_captured_timeout_cnt);
+		pcfr->bb_captured_timeout_cnt);
 	cfr_err("rx_loc_info_valid_cnt = %llu\n",
-		 pcfr->rx_loc_info_valid_cnt);
-	cfr_err("tx_evt_cnt = %llu\n",
-		 pcfr->tx_evt_cnt);
+		pcfr->rx_loc_info_valid_cnt);
+	cfr_err("total_tx_evt_cnt = %llu\n",
+		pcfr->total_tx_evt_cnt);
 	cfr_err("dbr_evt_cnt = %llu\n",
-		 pcfr->dbr_evt_cnt);
+		pcfr->dbr_evt_cnt);
 	cfr_err("rx_tlv_evt_cnt = %llu\n",
-		 pcfr->rx_tlv_evt_cnt);
+		pcfr->rx_tlv_evt_cnt);
 	cfr_err("release_cnt = %llu\n",
-		 pcfr->release_cnt);
+		pcfr->release_cnt);
 	cfr_err("Error cnt:\n");
 	cfr_err("flush_dbr_cnt = %llu\n",
-		 pcfr->flush_dbr_cnt);
+		pcfr->flush_dbr_cnt);
 	cfr_err("invalid_dma_length_cnt = %llu\n",
-		 pcfr->invalid_dma_length_cnt);
-	cfr_err("flush_all_dbr_cnt = %llu\n",
-		 pcfr->flush_all_dbr_cnt);
-	cfr_err("flush_all_txrx_cnt = %llu\n",
-		 pcfr->flush_all_txrx_cnt);
+		pcfr->invalid_dma_length_cnt);
 	cfr_err("flush_timeout_dbr_cnt = %llu\n",
-		 pcfr->flush_timeout_dbr_cnt);
+		pcfr->flush_timeout_dbr_cnt);
 	cfr_err("PPDU id mismatch for same cookie:\n");
 	cfr_err("clear_txrx_event = %llu\n",
-		 pcfr->clear_txrx_event);
+		pcfr->clear_txrx_event);
+	cfr_err("cfr_dma_aborts = %llu\n",
+		pcfr->cfr_dma_aborts);
 
 	cfr_err("Channel capture status:\n");
 	for (counter = 0; counter < CAPTURE_MAX; counter++) {
@@ -919,6 +917,7 @@
 {
 	struct pdev_cfr *pcfr = NULL;
 	struct wlan_objmgr_pdev *pdev = NULL;
+	struct wlan_objmgr_psoc *psoc = NULL;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 	struct cdp_monitor_filter filter_val = {0};
 
@@ -926,6 +925,12 @@
 	if (status != QDF_STATUS_SUCCESS)
 		return status;
 
+	psoc = wlan_pdev_get_psoc(pdev);
+
+	if (!psoc) {
+		cfr_err("psoc is null!");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
 	/*
 	 * If capture mode is valid, then Host:
 	 * Subscribes for PPDU status TLVs in monitor status ring.
@@ -990,11 +995,15 @@
 			filter_val.fp_ctrl |= FILTER_CTRL_VHT_NDP;
 		}
 
+		if (!cdp_get_cfr_rcc(wlan_psoc_get_dp_handle(psoc),
+				    wlan_objmgr_pdev_get_pdev_id(pdev)))
+			tgt_cfr_start_lut_age_timer(pdev);
 		cfr_set_filter(pdev, 1, &filter_val);
-		tgt_cfr_start_lut_age_timer(pdev);
 	} else {
+		if (cdp_get_cfr_rcc(wlan_psoc_get_dp_handle(psoc),
+				    wlan_objmgr_pdev_get_pdev_id(pdev)))
+			tgt_cfr_stop_lut_age_timer(pdev);
 		cfr_set_filter(pdev, 0, &filter_val);
-		tgt_cfr_stop_lut_age_timer(pdev);
 	}
 
 	/* Trigger wmi to start the TLV processing. */
diff --git a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_ic_ucfg_api.h b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_ic_ucfg_api.h
index 2831f2a..bfea671 100644
--- a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_ic_ucfg_api.h
+++ b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_ic_ucfg_api.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018, 2020 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
@@ -398,6 +398,10 @@
 UCFG_VDEV_CP_STATS_GET_FUNCS(rx_wrongbss);
 UCFG_VDEV_CP_STATS_GET_FUNCS(rx_wrongdir);
 UCFG_VDEV_CP_STATS_GET_FUNCS(rx_ssid_mismatch);
+UCFG_VDEV_CP_STATS_GET_FUNCS(peer_delete_req);
+UCFG_VDEV_CP_STATS_GET_FUNCS(peer_delete_resp);
+UCFG_VDEV_CP_STATS_GET_FUNCS(peer_delete_all_req);
+UCFG_VDEV_CP_STATS_GET_FUNCS(peer_delete_all_resp);
 
 #define UCFG_VDEV_UCAST_CP_STATS_SET_FUNCS(field) \
 	static inline void \
diff --git a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_ic_utils_api.h b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_ic_utils_api.h
index 0722380..002c0b7 100644
--- a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_ic_utils_api.h
+++ b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_ic_utils_api.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018, 2020 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
@@ -276,6 +276,10 @@
 VDEV_CP_STATS_GET_FUNCS(rx_wrongbss);
 VDEV_CP_STATS_GET_FUNCS(rx_wrongdir);
 VDEV_CP_STATS_GET_FUNCS(rx_ssid_mismatch);
+VDEV_CP_STATS_GET_FUNCS(peer_delete_req);
+VDEV_CP_STATS_GET_FUNCS(peer_delete_resp);
+VDEV_CP_STATS_GET_FUNCS(peer_delete_all_req);
+VDEV_CP_STATS_GET_FUNCS(peer_delete_all_resp);
 
 static inline void vdev_cp_stats_reset(struct wlan_objmgr_vdev *vdev)
 {
diff --git a/wmi/src/wmi_unified_ap_tlv.c b/wmi/src/wmi_unified_ap_tlv.c
index 9a1397e..cd60c68 100644
--- a/wmi/src/wmi_unified_ap_tlv.c
+++ b/wmi/src/wmi_unified_ap_tlv.c
@@ -2540,14 +2540,15 @@
 	if (!param_buf->num_vdev_ids_bitmap)
 		return QDF_STATUS_E_FAILURE;
 
-	if (param_buf->num_vdev_ids_bitmap > sizeof(param->vdev_id_bmap)) {
+	if ((param_buf->num_vdev_ids_bitmap * sizeof(uint32_t)) >
+			sizeof(param->vdev_id_bmap)) {
 		WMI_LOGE("vdevId bitmap overflow size:%d",
 			 param_buf->num_vdev_ids_bitmap);
 		return QDF_STATUS_E_FAILURE;
 	}
 
 	qdf_mem_copy(param->vdev_id_bmap, param_buf->vdev_ids_bitmap,
-		     param_buf->num_vdev_ids_bitmap);
+		     param_buf->num_vdev_ids_bitmap * sizeof(uint32_t));
 
 	WMI_LOGD("vdev_id_bmap :0x%x%x", param->vdev_id_bmap[1],
 		 param->vdev_id_bmap[0]);
diff --git a/wmi/src/wmi_unified_non_tlv.c b/wmi/src/wmi_unified_non_tlv.c
index 6a1c80d..2bfcbd3 100644
--- a/wmi/src/wmi_unified_non_tlv.c
+++ b/wmi/src/wmi_unified_non_tlv.c
@@ -10690,7 +10690,9 @@
 	wmi_service[wmi_service_cfr_capture_support] =
 		WMI_SERVICE_CFR_CAPTURE_SUPPORT;
 	wmi_service[wmi_service_rx_fse_support] = WMI_SERVICE_UNAVAILABLE;
-	wmi_service[wmi_service_bw_165mhz_support] =
+	wmi_service[wmi_service_bw_restricted_80p80_support] =
+		WMI_SERVICE_UNAVAILABLE;
+	wmi_service[wmi_service_nss_ratio_to_host_support] =
 		WMI_SERVICE_UNAVAILABLE;
 }