Merge "qcacmn: CFR: Process PPDU status TLVs and extract CFR information"
diff --git a/dp/inc/cdp_txrx_stats_struct.h b/dp/inc/cdp_txrx_stats_struct.h
index 3676d53..289df96 100644
--- a/dp/inc/cdp_txrx_stats_struct.h
+++ b/dp/inc/cdp_txrx_stats_struct.h
@@ -1869,6 +1869,12 @@
 	OL_ATH_PARAM_CHAN_COEX = 427,
 	/* Out of Band Advertisement feature */
 	OL_ATH_PARAM_OOB_ENABLE = 428,
+	/* set/get opmode-notification timer for hw-mode switch */
+	OL_ATH_PARAM_HW_MODE_SWITCH_OMN_TIMER = 429,
+	/* enable opmode-notification when doing hw-mode switch */
+	OL_ATH_PARAM_HW_MODE_SWITCH_OMN_ENABLE = 430,
+	/* set primary interface for hw-mode switch */
+	OL_ATH_PARAM_HW_MODE_SWITCH_PRIMARY_IF = 431,
 };
 #endif
 /* Bitmasks for stats that can block */
diff --git a/dp/wifi3.0/dp_ipa.c b/dp/wifi3.0/dp_ipa.c
index 980e99e..c3f4fa3 100644
--- a/dp/wifi3.0/dp_ipa.c
+++ b/dp/wifi3.0/dp_ipa.c
@@ -1802,6 +1802,69 @@
 #endif
 
 /**
+ * dp_ipa_frag_nbuf_linearize - linearize nbuf for IPA
+ * @soc: soc
+ * @nbuf: source skb
+ *
+ * Return: new nbuf if success and otherwise NULL
+ */
+static qdf_nbuf_t dp_ipa_frag_nbuf_linearize(struct dp_soc *soc,
+					     qdf_nbuf_t nbuf)
+{
+	uint8_t *src_nbuf_data;
+	uint8_t *dst_nbuf_data;
+	qdf_nbuf_t dst_nbuf;
+	qdf_nbuf_t temp_nbuf = nbuf;
+	uint32_t nbuf_len = qdf_nbuf_len(nbuf);
+	bool is_nbuf_head = true;
+	uint32_t copy_len = 0;
+
+	dst_nbuf = qdf_nbuf_alloc(soc->osdev, RX_BUFFER_SIZE,
+				  RX_BUFFER_RESERVATION, RX_BUFFER_ALIGNMENT,
+				  FALSE);
+
+	if (!dst_nbuf) {
+		dp_err_rl("nbuf allocate fail");
+		return NULL;
+	}
+
+	if ((nbuf_len + L3_HEADER_PADDING) > RX_BUFFER_SIZE) {
+		qdf_nbuf_free(dst_nbuf);
+		dp_err_rl("nbuf is jumbo data");
+		return NULL;
+	}
+
+	/* prepeare to copy all data into new skb */
+	dst_nbuf_data = qdf_nbuf_data(dst_nbuf);
+	while (temp_nbuf) {
+		src_nbuf_data = qdf_nbuf_data(temp_nbuf);
+		/* first head nbuf */
+		if (is_nbuf_head) {
+			qdf_mem_copy(dst_nbuf_data, src_nbuf_data,
+				     RX_PKT_TLVS_LEN);
+			/* leave extra 2 bytes L3_HEADER_PADDING */
+			dst_nbuf_data += (RX_PKT_TLVS_LEN + L3_HEADER_PADDING);
+			src_nbuf_data += RX_PKT_TLVS_LEN;
+			copy_len = qdf_nbuf_headlen(temp_nbuf) -
+						RX_PKT_TLVS_LEN;
+			temp_nbuf = qdf_nbuf_get_ext_list(temp_nbuf);
+			is_nbuf_head = false;
+		} else {
+			copy_len = qdf_nbuf_len(temp_nbuf);
+			temp_nbuf = qdf_nbuf_queue_next(temp_nbuf);
+		}
+		qdf_mem_copy(dst_nbuf_data, src_nbuf_data, copy_len);
+		dst_nbuf_data += copy_len;
+	}
+
+	qdf_nbuf_set_len(dst_nbuf, nbuf_len);
+	/* copy is done, free original nbuf */
+	qdf_nbuf_free(nbuf);
+
+	return dst_nbuf;
+}
+
+/**
  * dp_ipa_handle_rx_reo_reinject - Handle RX REO reinject skb buffer
  * @soc: soc
  * @nbuf: skb
@@ -1810,7 +1873,6 @@
  */
 qdf_nbuf_t dp_ipa_handle_rx_reo_reinject(struct dp_soc *soc, qdf_nbuf_t nbuf)
 {
-	uint8_t *rx_pkt_tlvs;
 
 	if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
 		return nbuf;
@@ -1819,33 +1881,11 @@
 	if (!qdf_atomic_read(&soc->ipa_pipes_enabled))
 		return nbuf;
 
-	/* Linearize the skb since IPA assumes linear buffer */
-	if (qdf_likely(qdf_nbuf_is_frag(nbuf))) {
-		if (qdf_nbuf_linearize(nbuf)) {
-			dp_err_rl("nbuf linearize failed");
-			return NULL;
-		}
-	}
+	if (!qdf_nbuf_is_frag(nbuf))
+		return nbuf;
 
-	rx_pkt_tlvs = qdf_mem_malloc(RX_PKT_TLVS_LEN);
-	if (!rx_pkt_tlvs) {
-		dp_err_rl("rx_pkt_tlvs alloc failed");
-		return NULL;
-	}
-
-	qdf_mem_copy(rx_pkt_tlvs, qdf_nbuf_data(nbuf), RX_PKT_TLVS_LEN);
-
-	/* Pad L3_HEADER_PADDING before ethhdr and after rx_pkt_tlvs */
-	qdf_nbuf_push_head(nbuf, L3_HEADER_PADDING);
-
-	qdf_mem_copy(qdf_nbuf_data(nbuf), rx_pkt_tlvs, RX_PKT_TLVS_LEN);
-
-	/* L3_HEADDING_PADDING is not accounted for real skb length */
-	qdf_nbuf_set_len(nbuf, qdf_nbuf_len(nbuf) - L3_HEADER_PADDING);
-
-	qdf_mem_free(rx_pkt_tlvs);
-
-	return nbuf;
+	/* linearize skb for IPA */
+	return dp_ipa_frag_nbuf_linearize(soc, nbuf);
 }
 
 #endif
diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c
index c07eb1b..a4eb54a 100644
--- a/dp/wifi3.0/dp_peer.c
+++ b/dp/wifi3.0/dp_peer.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-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
@@ -1740,8 +1740,12 @@
 	} else {
 	    dp_set_ssn_valid_flag(&params, 0);
 	}
-	dp_reo_send_cmd(soc, CMD_UPDATE_RX_REO_QUEUE, &params,
-			dp_rx_tid_update_cb, rx_tid);
+
+	if (dp_reo_send_cmd(soc, CMD_UPDATE_RX_REO_QUEUE, &params,
+			    dp_rx_tid_update_cb, rx_tid)) {
+		dp_err_log("failed to send reo cmd CMD_UPDATE_RX_REO_QUEUE");
+		DP_STATS_INC(soc, rx.err.reo_cmd_send_fail, 1);
+	}
 
 	rx_tid->ba_win_size = ba_window_size;
 
@@ -2071,6 +2075,7 @@
 		desc->free_ts = qdf_get_system_timestamp();
 		qdf_list_insert_back(&soc->reo_desc_freelist,
 				     (qdf_list_node_t *)desc);
+		dp_err_log("failed to send reo cmd CMD_UPDATE_RX_REO_QUEUE");
 		DP_STATS_INC(soc, rx.err.reo_cmd_send_fail, 1);
 	}
 }
@@ -2158,9 +2163,10 @@
 							&params,
 							NULL,
 							NULL)) {
-				dp_err_log("fail to send CMD_CACHE_FLUSH:"
-					   "tid %d desc %pK", rx_tid->tid,
-					   (void *)(rx_tid->hw_qdesc_paddr));
+				dp_err_rl("fail to send CMD_CACHE_FLUSH:"
+					  "tid %d desc %pK", rx_tid->tid,
+					  (void *)(rx_tid->hw_qdesc_paddr));
+				DP_STATS_INC(soc, rx.err.reo_cmd_send_fail, 1);
 			}
 		}
 
@@ -2190,6 +2196,7 @@
 			dp_err_log("%s: fail to send REO cmd to flush cache: tid %d",
 				   __func__, rx_tid->tid);
 			dp_reo_desc_clean_up(soc, desc, &reo_status);
+			DP_STATS_INC(soc, rx.err.reo_cmd_send_fail, 1);
 		}
 	}
 	qdf_spin_unlock_bh(&soc->reo_desc_freelist_lock);
@@ -3017,9 +3024,16 @@
 				params.u.upd_queue_params.pn_127_96 = rx_pn[3];
 			}
 			rx_tid->pn_size = pn_size;
-			dp_reo_send_cmd((struct dp_soc *)soc,
-					CMD_UPDATE_RX_REO_QUEUE, &params,
-					dp_rx_tid_update_cb, rx_tid);
+			if (dp_reo_send_cmd(cdp_soc_t_to_dp_soc(soc),
+					    CMD_UPDATE_RX_REO_QUEUE,
+					    &params, dp_rx_tid_update_cb,
+					    rx_tid)) {
+				dp_err_log("fail to send CMD_UPDATE_RX_REO_QUEUE"
+					   "tid %d desc %pK", rx_tid->tid,
+					   (void *)(rx_tid->hw_qdesc_paddr));
+				DP_STATS_INC(cdp_soc_t_to_dp_soc(soc),
+					     rx.err.reo_cmd_send_fail, 1);
+			}
 		} else {
 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH,
 				  "PN Check not setup for TID :%d ", i);
@@ -3224,7 +3238,7 @@
 	}
 	peer->state = state;
 
-	DP_TRACE(INFO, "peer %pK state %d", peer, peer->state);
+	dp_info("peer %pK state %d", peer, peer->state);
 	/* ref_cnt is incremented inside dp_peer_find_hash_find().
 	 * Decrement it here.
 	 */
@@ -3309,7 +3323,7 @@
 	uint8_t *mac;
 
 	mac = peer->mac_addr.raw;
-	DP_TRACE(INFO, "peer %pK mac 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+	dp_info("peer %pK mac 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
 		peer, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
 	return peer->mac_addr.raw;
 }
@@ -3384,7 +3398,7 @@
 		pdev->local_peer_ids.map[i] = peer;
 	}
 	qdf_spin_unlock_bh(&pdev->local_peer_ids.lock);
-	DP_TRACE(INFO, "peer %pK, local id %d", peer, peer->local_id);
+	dp_info("peer %pK, local id %d", peer, peer->local_id);
 }
 
 /**
diff --git a/dp/wifi3.0/dp_reo.c b/dp/wifi3.0/dp_reo.c
index ff8d337..ba1db7f 100644
--- a/dp/wifi3.0/dp_reo.c
+++ b/dp/wifi3.0/dp_reo.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-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
@@ -91,13 +91,12 @@
 		break;
 	default:
 		dp_err_log("Invalid REO command type: %d", type);
-		return QDF_STATUS_E_FAILURE;
+		return QDF_STATUS_E_INVAL;
 	};
 
 	dp_reo_cmd_srng_event_record(soc, type, num);
 
 	if (num < 0) {
-		dp_err_log("Error with sending REO command type: %d", type);
 		return QDF_STATUS_E_FAILURE;
 	}
 
diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c
index 11dfaf6..5af6996 100644
--- a/dp/wifi3.0/dp_rx.c
+++ b/dp/wifi3.0/dp_rx.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-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
@@ -891,13 +891,6 @@
 	if (soc->cdp_soc.ol_ops->rx_invalid_peer)
 		soc->cdp_soc.ol_ops->rx_invalid_peer(vdev->vdev_id, wh);
 free:
-	/* reset the head and tail pointers */
-	pdev = dp_get_pdev_for_mac_id(soc, mac_id);
-	if (pdev) {
-		pdev->invalid_peer_head_msdu = NULL;
-		pdev->invalid_peer_tail_msdu = NULL;
-	}
-
 	/* Drop and free packet */
 	curr_nbuf = mpdu;
 	while (curr_nbuf) {
@@ -906,6 +899,13 @@
 		curr_nbuf = next_nbuf;
 	}
 
+	/* Reset the head and tail pointers */
+	pdev = dp_get_pdev_for_mac_id(soc, mac_id);
+	if (pdev) {
+		pdev->invalid_peer_head_msdu = NULL;
+		pdev->invalid_peer_tail_msdu = NULL;
+	}
+
 	return 0;
 }
 
diff --git a/dp/wifi3.0/dp_rx_defrag.c b/dp/wifi3.0/dp_rx_defrag.c
index 6538999..9c2ffe9 100644
--- a/dp/wifi3.0/dp_rx_defrag.c
+++ b/dp/wifi3.0/dp_rx_defrag.c
@@ -1026,13 +1026,23 @@
 		peer->rx_tid[tid].dst_ring_desc;
 	hal_ring_handle_t hal_srng = soc->reo_reinject_ring.hal_srng;
 	struct dp_rx_desc *rx_desc = peer->rx_tid[tid].head_frag_desc;
+	struct dp_rx_reorder_array_elem *rx_reorder_array_elem =
+						peer->rx_tid[tid].array;
+	qdf_nbuf_t nbuf_head;
 
-	head = dp_ipa_handle_rx_reo_reinject(soc, head);
-	if (qdf_unlikely(!head)) {
+	nbuf_head = dp_ipa_handle_rx_reo_reinject(soc, head);
+	if (qdf_unlikely(!nbuf_head)) {
 		dp_err_rl("IPA RX REO reinject failed");
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	/* update new allocated skb in case IPA is enabled */
+	if (nbuf_head != head) {
+		head = nbuf_head;
+		rx_desc->nbuf = head;
+		rx_reorder_array_elem->head = head;
+	}
+
 	ent_ring_desc = hal_srng_src_get_next(soc->hal_soc, hal_srng);
 	if (!ent_ring_desc) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c
index 29fd9ac..4e5e4a5 100644
--- a/dp/wifi3.0/dp_rx_err.c
+++ b/dp/wifi3.0/dp_rx_err.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-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
@@ -427,8 +427,8 @@
  *  Return: bool: true for last msdu of mpdu
  */
 static bool
-dp_rx_chain_msdus(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr,
-								uint8_t mac_id)
+dp_rx_chain_msdus(struct dp_soc *soc, qdf_nbuf_t nbuf,
+		  uint8_t *rx_tlv_hdr, uint8_t mac_id)
 {
 	bool mpdu_done = false;
 	qdf_nbuf_t curr_nbuf = NULL;
@@ -447,8 +447,9 @@
 	 * up
 	 */
 	if (!dp_pdev->first_nbuf ||
+	    (dp_pdev->invalid_peer_head_msdu &&
 	    QDF_NBUF_CB_RX_NUM_ELEMENTS_IN_LIST
-		(dp_pdev->invalid_peer_head_msdu) >= DP_MAX_INVALID_BUFFERS) {
+	    (dp_pdev->invalid_peer_head_msdu) >= DP_MAX_INVALID_BUFFERS)) {
 		qdf_nbuf_set_rx_chfrag_start(nbuf, 1);
 		dp_pdev->ppdu_id = hal_rx_hw_desc_get_ppduid_get(soc->hal_soc,
 								 rx_tlv_hdr);
@@ -804,6 +805,7 @@
 			pdev->invalid_peer_head_msdu = NULL;
 			pdev->invalid_peer_tail_msdu = NULL;
 		}
+
 		return QDF_STATUS_E_FAILURE;
 	}
 
@@ -1244,7 +1246,8 @@
 
 		if (qdf_unlikely((msdu_list.rbm[0] != DP_WBM2SW_RBM) &&
 				(msdu_list.rbm[0] !=
-					HAL_RX_BUF_RBM_WBM_IDLE_DESC_LIST))) {
+					HAL_RX_BUF_RBM_WBM_IDLE_DESC_LIST) &&
+				(msdu_list.rbm[0] != DP_DEFRAG_RBM))) {
 			/* TODO */
 			/* Call appropriate handler */
 			if (!wlan_cfg_get_dp_soc_nss_cfg(soc->wlan_cfg_ctx)) {
diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c
index 03739c8..1bae203 100644
--- a/dp/wifi3.0/dp_tx.c
+++ b/dp/wifi3.0/dp_tx.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-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
@@ -3810,26 +3810,6 @@
 
 #ifdef QCA_LL_TX_FLOW_CONTROL_V2
 /**
- * dp_tx_desc_reset_vdev() - reset vdev to NULL in TX Desc
- *
- * @soc: Handle to DP SoC structure
- * @tx_desc: pointer of one TX desc
- * @desc_pool_id: TX Desc pool id
- */
-static inline void
-dp_tx_desc_reset_vdev(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc,
-		      uint8_t desc_pool_id)
-{
-	struct dp_tx_desc_pool_s *pool = &soc->tx_desc[desc_pool_id];
-
-	qdf_spin_lock_bh(&pool->flow_pool_lock);
-
-	tx_desc->vdev = NULL;
-
-	qdf_spin_unlock_bh(&pool->flow_pool_lock);
-}
-
-/**
  * dp_tx_desc_flush() - release resources associated
  *                      to TX Desc
  *
@@ -3872,6 +3852,17 @@
 		    !(tx_desc_pool->desc_pages.cacheable_pages))
 			continue;
 
+		/*
+		 * Add flow pool lock protection in case pool is freed
+		 * due to all tx_desc is recycled when handle TX completion.
+		 * this is not necessary when do force flush as:
+		 * a. double lock will happen if dp_tx_desc_release is
+		 *    also trying to acquire it.
+		 * b. dp interrupt has been disabled before do force TX desc
+		 *    flush in dp_pdev_deinit().
+		 */
+		if (!force_free)
+			qdf_spin_lock_bh(&tx_desc_pool->flow_pool_lock);
 		num_desc = tx_desc_pool->pool_size;
 		num_desc_per_page =
 			tx_desc_pool->desc_pages.num_element_per_page;
@@ -3895,15 +3886,22 @@
 					dp_tx_comp_free_buf(soc, tx_desc);
 					dp_tx_desc_release(tx_desc, i);
 				} else {
-					dp_tx_desc_reset_vdev(soc, tx_desc,
-							      i);
+					tx_desc->vdev = NULL;
 				}
 			}
 		}
+		if (!force_free)
+			qdf_spin_unlock_bh(&tx_desc_pool->flow_pool_lock);
 	}
 }
 #else /* QCA_LL_TX_FLOW_CONTROL_V2! */
-
+/**
+ * dp_tx_desc_reset_vdev() - reset vdev to NULL in TX Desc
+ *
+ * @soc: Handle to DP soc structure
+ * @tx_desc: pointer of one TX desc
+ * @desc_pool_id: TX Desc pool id
+ */
 static inline void
 dp_tx_desc_reset_vdev(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc,
 		      uint8_t desc_pool_id)
diff --git a/hif/src/ce/ce_internal.h b/hif/src/ce/ce_internal.h
index a5edd14..0de6feb 100644
--- a/hif/src/ce/ce_internal.h
+++ b/hif/src/ce/ce_internal.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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
@@ -468,6 +468,8 @@
 	HIF_RX_DESC_PRE_NBUF_ALLOC,
 	HIF_RX_DESC_PRE_NBUF_MAP,
 	HIF_RX_DESC_POST_NBUF_MAP,
+
+	HIF_EVENT_TYPE_MAX,
 };
 
 void ce_init_ce_desc_event_log(struct hif_softc *scn, int ce_id, int size);
diff --git a/hif/src/ce/ce_main.c b/hif/src/ce/ce_main.c
index 69ca818..7be9a2f 100644
--- a/hif/src/ce/ce_main.c
+++ b/hif/src/ce/ce_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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
@@ -3194,6 +3194,7 @@
 		hif_state->target_ce_config_sz =
 					sizeof(target_ce_config_wlan_qcn9000);
 		scn->ce_count = QCN_9000_CE_COUNT;
+		scn->disable_wake_irq = 1;
 		break;
 	case TARGET_TYPE_QCA6390:
 		hif_state->host_ce_config = host_ce_config_wlan_qca6390;
diff --git a/hif/src/ce/ce_main.h b/hif/src/ce/ce_main.h
index c943feb..f3feb76 100644
--- a/hif/src/ce/ce_main.h
+++ b/hif/src/ce/ce_main.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-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
@@ -49,6 +49,7 @@
 #define CE_USEFUL_SIZE		0x00000058
 #define CE_ALL_BITMAP  0xFFFF
 
+#define HIF_REQUESTED_EVENTS 20
 /**
  * enum ce_id_type
  *
@@ -70,6 +71,30 @@
 	CE_ID_MAX
 };
 
+/**
+ * enum ce_buckets
+ *
+ * @ce_buckets: CE tasklet time buckets
+ * @CE_BUCKET_500_US: tasklet bucket to store 0-0.5ms
+ * @CE_BUCKET_1_MS: tasklet bucket to store 0.5-1ms
+ * @CE_BUCKET_2_MS: tasklet bucket to store 1-2ms
+ * @CE_BUCKET_5_MS: tasklet bucket to store 2-5ms
+ * @CE_BUCKET_10_MS: tasklet bucket to store 5-10ms
+ * @CE_BUCKET_BEYOND: tasklet bucket to store > 10ms
+ * @CE_BUCKET_MAX: enum max value
+ */
+#ifdef CE_TASKLET_DEBUG_ENABLE
+enum ce_buckets {
+	CE_BUCKET_500_US,
+	CE_BUCKET_1_MS,
+	CE_BUCKET_2_MS,
+	CE_BUCKET_5_MS,
+	CE_BUCKET_10_MS,
+	CE_BUCKET_BEYOND,
+	CE_BUCKET_MAX,
+};
+#endif
+
 enum ce_target_type {
 	CE_SVC_LEGACY,
 	CE_SVC_SRNG,
@@ -134,8 +159,33 @@
 extern struct hif_execution_ops tasklet_sched_ops;
 extern struct hif_execution_ops napi_sched_ops;
 
+/**
+ * struct ce_stats
+ *
+ * @ce_per_cpu: Stats of the CEs running per CPU
+ * @record_index: Current index to store in time record
+ * @tasklet_sched_entry_ts: Timestamp when tasklet is scheduled
+ * @tasklet_exec_entry_ts: Timestamp when tasklet is started execuiton
+ * @tasklet_exec_time_record: Last N number of tasklets execution time
+ * @tasklet_sched_time_record: Last N number of tasklets scheduled time
+ * @ce_tasklet_exec_bucket: Tasklet execution time buckets
+ * @ce_tasklet_sched_bucket: Tasklet time in queue buckets
+ * @ce_tasklet_exec_last_update: Latest timestamp when bucket is updated
+ * @ce_tasklet_sched_last_update: Latest timestamp when bucket is updated
+ */
 struct ce_stats {
 	uint32_t ce_per_cpu[CE_COUNT_MAX][QDF_MAX_AVAILABLE_CPU];
+#ifdef CE_TASKLET_DEBUG_ENABLE
+	uint32_t record_index[CE_COUNT_MAX];
+	uint64_t tasklet_sched_entry_ts[CE_COUNT_MAX];
+	uint64_t tasklet_exec_entry_ts[CE_COUNT_MAX];
+	uint64_t tasklet_exec_time_record[CE_COUNT_MAX][HIF_REQUESTED_EVENTS];
+	uint64_t tasklet_sched_time_record[CE_COUNT_MAX][HIF_REQUESTED_EVENTS];
+	uint64_t ce_tasklet_exec_bucket[CE_COUNT_MAX][CE_BUCKET_MAX];
+	uint64_t ce_tasklet_sched_bucket[CE_COUNT_MAX][CE_BUCKET_MAX];
+	uint64_t ce_tasklet_exec_last_update[CE_COUNT_MAX][CE_BUCKET_MAX];
+	uint64_t ce_tasklet_sched_last_update[CE_COUNT_MAX][CE_BUCKET_MAX];
+#endif
 };
 
 struct HIF_CE_state {
diff --git a/hif/src/ce/ce_tasklet.c b/hif/src/ce/ce_tasklet.c
index 9a5b615..ed3030c 100644
--- a/hif/src/ce/ce_tasklet.c
+++ b/hif/src/ce/ce_tasklet.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-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
@@ -35,7 +35,6 @@
 #include "hif_debug.h"
 #include "hif_napi.h"
 
-
 /**
  * struct tasklet_work
  *
@@ -139,6 +138,199 @@
 	tasklet_schedule(&tasklet_entry->intr_tq);
 }
 
+#ifdef CE_TASKLET_DEBUG_ENABLE
+/**
+ * hif_record_tasklet_exec_entry_ts() - Record ce tasklet execution
+ *                                      entry time
+ * @scn: hif_softc
+ * @ce_id: ce_id
+ *
+ * Return: None
+ */
+static inline void
+hif_record_tasklet_exec_entry_ts(struct hif_softc *scn, uint8_t ce_id)
+{
+	struct HIF_CE_state *hif_ce_state = HIF_GET_CE_STATE(scn);
+
+	hif_ce_state->stats.tasklet_exec_entry_ts[ce_id] =
+					qdf_get_log_timestamp_usecs();
+}
+
+/**
+ * hif_record_tasklet_sched_entry_ts() - Record ce tasklet scheduled
+ *                                       entry time
+ * @scn: hif_softc
+ * @ce_id: ce_id
+ *
+ * Return: None
+ */
+static inline void
+hif_record_tasklet_sched_entry_ts(struct hif_softc *scn, uint8_t ce_id)
+{
+	struct HIF_CE_state *hif_ce_state = HIF_GET_CE_STATE(scn);
+
+	hif_ce_state->stats.tasklet_sched_entry_ts[ce_id] =
+					qdf_get_log_timestamp_usecs();
+}
+
+/**
+ * hif_ce_latency_stats() - Display ce latency information
+ * @hif_ctx: hif_softc struct
+ *
+ * Return: None
+ */
+static void
+hif_ce_latency_stats(struct hif_softc *hif_ctx)
+{
+	uint8_t i, j;
+	uint32_t index, start_index;
+	static const char * const buck_str[] = {"0 - 0.5", "0.5 - 1", "1  -  2",
+					       "2  -  5", "5  - 10", "  >  10"};
+	struct HIF_CE_state *hif_ce_state = HIF_GET_CE_STATE(hif_ctx);
+	struct ce_stats *stats = &hif_ce_state->stats;
+
+	for (i = 0; i < CE_COUNT_MAX; i++) {
+		qdf_nofl_info("\n\t\tCE Ring %d Tasklet Execution Bucket", i);
+		for (j = 0; j < CE_BUCKET_MAX; j++) {
+			qdf_nofl_info("\t Bucket %sms :%llu\t last update:%llu",
+				      buck_str[j],
+				      stats->ce_tasklet_exec_bucket[i][j],
+				      stats->ce_tasklet_exec_last_update[i][j]);
+		}
+
+		qdf_nofl_info("\n\t\tCE Ring %d Tasklet Scheduled Bucket", i);
+		for (j = 0; j < CE_BUCKET_MAX; j++) {
+			qdf_nofl_info("\t Bucket %sms :%llu\t last update :%lld",
+				      buck_str[j],
+				      stats->ce_tasklet_sched_bucket[i][j],
+				      stats->
+					   ce_tasklet_sched_last_update[i][j]);
+		}
+
+		qdf_nofl_info("\n\t\t CE RING %d Last %d time records",
+			      i, HIF_REQUESTED_EVENTS);
+		index = stats->record_index[i];
+		start_index = stats->record_index[i];
+
+		for (j = 0; j < HIF_REQUESTED_EVENTS; j++) {
+			qdf_nofl_info("\t Execuiton time:  %luus Total Scheduled time: %luus",
+				      stats->tasklet_exec_time_record[i][index],
+				      stats->
+					   tasklet_sched_time_record[i][index]);
+			index = (index - 1) % HIF_REQUESTED_EVENTS;
+			if (index == start_index)
+				break;
+		}
+	}
+}
+
+/**
+ * ce_tasklet_update_bucket() - update ce execution and scehduled time latency
+ *                              in corresponding time buckets
+ * @stats: struct ce_stats
+ * @ce_id: ce_id_type
+ * @entry_us: timestamp when tasklet is started to execute
+ * @exit_us: timestamp when tasklet is completed execution
+ *
+ * Return: N/A
+ */
+static void ce_tasklet_update_bucket(struct HIF_CE_state *hif_ce_state,
+				     uint8_t ce_id)
+{
+	uint32_t index;
+	uint64_t exec_time, exec_ms;
+	uint64_t sched_time, sched_ms;
+	uint64_t curr_time = qdf_get_log_timestamp_usecs();
+	struct ce_stats *stats = &hif_ce_state->stats;
+
+	exec_time = curr_time - (stats->tasklet_exec_entry_ts[ce_id]);
+	sched_time = (stats->tasklet_exec_entry_ts[ce_id]) -
+		      (stats->tasklet_sched_entry_ts[ce_id]);
+
+	index = stats->record_index[ce_id];
+	index = (index + 1) % HIF_REQUESTED_EVENTS;
+
+	stats->tasklet_exec_time_record[ce_id][index] = exec_time;
+	stats->tasklet_sched_time_record[ce_id][index] = sched_time;
+	stats->record_index[ce_id] = index;
+
+	exec_ms = qdf_do_div(exec_time, 1000);
+	sched_ms = qdf_do_div(sched_time, 1000);
+
+	if (exec_ms > 10) {
+		stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_BEYOND]++;
+		stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_BEYOND]
+								= curr_time;
+	} else if (exec_ms > 5) {
+		stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_10_MS]++;
+		stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_10_MS]
+								= curr_time;
+	} else if (exec_ms > 2) {
+		stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_5_MS]++;
+		stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_5_MS]
+								= curr_time;
+	} else if (exec_ms > 1) {
+		stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_2_MS]++;
+		stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_2_MS]
+								= curr_time;
+	} else if (exec_time > 500) {
+		stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_1_MS]++;
+		stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_1_MS]
+								= curr_time;
+	} else {
+		stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_500_US]++;
+		stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_500_US]
+								= curr_time;
+	}
+
+	if (sched_ms > 10) {
+		stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_BEYOND]++;
+		stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_BEYOND]
+								= curr_time;
+	} else if (sched_ms > 5) {
+		stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_10_MS]++;
+		stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_10_MS]
+								= curr_time;
+	} else if (sched_ms > 2) {
+		stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_5_MS]++;
+		stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_5_MS]
+								= curr_time;
+	} else if (sched_ms > 1) {
+		stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_2_MS]++;
+		stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_2_MS]
+								= curr_time;
+	} else if (sched_time > 500) {
+		stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_1_MS]++;
+		stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_1_MS]
+								= curr_time;
+	} else {
+		stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_500_US]++;
+		stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_500_US]
+								= curr_time;
+	}
+}
+#else
+static inline void
+hif_record_tasklet_exec_entry_ts(struct hif_softc *scn, uint8_t ce_id)
+{
+}
+
+static void ce_tasklet_update_bucket(struct HIF_CE_state *hif_ce_state,
+				     uint8_t ce_id)
+{
+}
+
+static inline void
+hif_record_tasklet_sched_entry_ts(struct hif_softc *scn, uint8_t ce_id)
+{
+}
+
+static void
+hif_ce_latency_stats(struct hif_softc *hif_ctx)
+{
+}
+#endif /*CE_TASKLET_DEBUG_ENABLE*/
+
 /**
  * ce_tasklet() - ce_tasklet
  * @data: data
@@ -153,8 +345,9 @@
 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ce_state);
 	struct CE_state *CE_state = scn->ce_id_to_state[tasklet_entry->ce_id];
 
+	hif_record_tasklet_exec_entry_ts(scn, tasklet_entry->ce_id);
 	hif_record_ce_desc_event(scn, tasklet_entry->ce_id,
-			HIF_CE_TASKLET_ENTRY, NULL, NULL, -1, 0);
+				 HIF_CE_TASKLET_ENTRY, NULL, NULL, -1, 0);
 
 	if (qdf_atomic_read(&scn->link_suspended)) {
 		HIF_ERROR("%s: ce %d tasklet fired after link suspend.",
@@ -182,7 +375,7 @@
 
 	hif_record_ce_desc_event(scn, tasklet_entry->ce_id, HIF_CE_TASKLET_EXIT,
 				NULL, NULL, -1, 0);
-
+	ce_tasklet_update_bucket(hif_ce_state, tasklet_entry->ce_id);
 	qdf_atomic_dec(&scn->active_tasklet_cnt);
 }
 
@@ -339,12 +532,13 @@
  *
  * Return: none
  */
-void hif_display_ce_stats(struct HIF_CE_state *hif_ce_state)
+void hif_display_ce_stats(struct hif_softc *hif_ctx)
 {
 #define STR_SIZE 128
 	uint8_t i, j, pos;
 	char str_buffer[STR_SIZE];
 	int size, ret;
+	struct HIF_CE_state *hif_ce_state = HIF_GET_CE_STATE(hif_ctx);
 
 	qdf_debug("CE interrupt statistics:");
 	for (i = 0; i < CE_COUNT_MAX; i++) {
@@ -352,7 +546,7 @@
 		pos = 0;
 		for (j = 0; j < QDF_MAX_AVAILABLE_CPU; j++) {
 			ret = snprintf(str_buffer + pos, size, "[%d]:%d ",
-				j, hif_ce_state->stats.ce_per_cpu[i][j]);
+				       j, hif_ce_state->stats.ce_per_cpu[i][j]);
 			if (ret <= 0 || ret >= size)
 				break;
 			size -= ret;
@@ -360,6 +554,8 @@
 		}
 		qdf_debug("CE id[%2d] - %s", i, str_buffer);
 	}
+
+	hif_ce_latency_stats(hif_ctx);
 #undef STR_SIZE
 }
 
@@ -393,6 +589,7 @@
 	}
 
 	tasklet_schedule(&tasklet_entry->intr_tq);
+	hif_record_tasklet_sched_entry_ts(scn, tasklet_entry->ce_id);
 	return true;
 }
 
diff --git a/hif/src/ce/ce_tasklet.h b/hif/src/ce/ce_tasklet.h
index 05da168..d5ab58c 100644
--- a/hif/src/ce/ce_tasklet.h
+++ b/hif/src/ce/ce_tasklet.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016,2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016,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
@@ -28,6 +28,6 @@
 QDF_STATUS ce_unregister_irq(struct HIF_CE_state *hif_ce_state, uint32_t mask);
 irqreturn_t ce_dispatch_interrupt(int irq,
 				  struct ce_tasklet_entry *tasklet_entry);
-void hif_display_ce_stats(struct HIF_CE_state *hif_ce_state);
+void hif_display_ce_stats(struct hif_softc *hif_ctx);
 void hif_clear_ce_stats(struct HIF_CE_state *hif_ce_state);
 #endif /* __CE_TASKLET_H__ */
diff --git a/hif/src/dispatcher/ahb_api.h b/hif/src/dispatcher/ahb_api.h
index 103114b..1657cbc 100644
--- a/hif/src/dispatcher/ahb_api.h
+++ b/hif/src/dispatcher/ahb_api.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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
@@ -50,4 +50,6 @@
 int hif_ahb_configure_grp_irq(struct hif_softc *scn,
 			      struct hif_exec_context *hif_ext_grp);
 bool hif_ahb_needs_bmi(struct hif_softc *scn);
+void hif_ahb_display_stats(struct hif_softc *scn);
+void hif_ahb_clear_stats(struct hif_softc *scn);
 #endif
diff --git a/hif/src/dispatcher/multibus_ahb.c b/hif/src/dispatcher/multibus_ahb.c
index 04bf46d..fe46d5b 100644
--- a/hif/src/dispatcher/multibus_ahb.c
+++ b/hif/src/dispatcher/multibus_ahb.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-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
@@ -69,7 +69,8 @@
 	bus_ops->hif_grp_irq_configure = &hif_ahb_configure_grp_irq;
 	bus_ops->hif_addr_in_boundary = &hif_dummy_addr_in_boundary;
 	bus_ops->hif_needs_bmi = &hif_ahb_needs_bmi;
-
+	bus_ops->hif_display_stats = &hif_ahb_display_stats;
+	bus_ops->hif_clear_stats = &hif_ahb_clear_stats;
 	return QDF_STATUS_SUCCESS;
 }
 
diff --git a/hif/src/hif_main.h b/hif/src/hif_main.h
index 8c1d48e..7875593 100644
--- a/hif/src/hif_main.h
+++ b/hif/src/hif_main.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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
@@ -203,6 +203,7 @@
 	struct hif_ut_suspend_context ut_suspend_ctx;
 	uint32_t hif_attribute;
 	int wake_irq;
+	int disable_wake_irq;
 	void (*initial_wakeup_cb)(void *);
 	void *initial_wakeup_priv;
 #ifdef REMOVE_PKT_LOG
diff --git a/hif/src/pcie/if_pci.c b/hif/src/pcie/if_pci.c
index 36471e4..3cc2c70 100644
--- a/hif/src/pcie/if_pci.c
+++ b/hif/src/pcie/if_pci.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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
@@ -618,7 +618,7 @@
 	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
 
 	/* Check device ID from PCIe configuration space for link status */
-	pci_read_config_word(sc->pdev, PCI_DEVICE_ID, &device_id);
+	pfrm_read_config_word(sc->pdev, PCI_DEVICE_ID, &device_id);
 	if (device_id != sc->devid) {
 		HIF_ERROR("%s: device ID does match (read 0x%x, expect 0x%x)",
 			  __func__, device_id, sc->devid);
@@ -1302,8 +1302,8 @@
 	}
 
 	/* Disable ASPM when pkt log is enabled */
-	pci_read_config_dword(sc->pdev, 0x80, &sc->lcr_val);
-	pci_write_config_dword(sc->pdev, 0x80, (sc->lcr_val & 0xffffff00));
+	pfrm_read_config_dword(sc->pdev, 0x80, &sc->lcr_val);
+	pfrm_write_config_dword(sc->pdev, 0x80, (sc->lcr_val & 0xffffff00));
 }
 
 /**
@@ -1321,7 +1321,7 @@
 	}
 
 	/* Re-enable ASPM after firmware/OTP download is complete */
-	pci_write_config_dword(sc->pdev, 0x80, sc->lcr_val);
+	pfrm_write_config_dword(sc->pdev, 0x80, sc->lcr_val);
 }
 
 /**
@@ -1395,7 +1395,7 @@
 		HIF_ERROR("%s, hif_ctx null", __func__);
 		return;
 	}
-	hif_display_ce_stats(&pci_ctx->ce_sc);
+	hif_display_ce_stats(hif_ctx);
 
 	hif_print_pci_stats(pci_ctx);
 }
@@ -2370,7 +2370,7 @@
 		hif_debug("%s: (ce_id %d, msi_data %d, irq %d)", __func__,
 			  ce_id, msi_data, irq);
 
-		free_irq(irq, &ce_sc->tasklets[ce_id]);
+		pfrm_free_irq(scn->qdf_dev->dev, irq, &ce_sc->tasklets[ce_id]);
 	}
 
 	return ret;
@@ -2388,7 +2388,8 @@
 			hif_ext_group->irq_requested = false;
 			for (j = 0; j < hif_ext_group->numirq; j++) {
 				irq = hif_ext_group->os_irq[j];
-				free_irq(irq, hif_ext_group);
+				pfrm_free_irq(scn->qdf_dev->dev,
+					      irq, hif_ext_group);
 			}
 			hif_ext_group->numirq = 0;
 		}
@@ -2422,7 +2423,7 @@
 		/* ce irqs freed in hif_ce_srng_msi_free_irq */
 
 		if (scn->wake_irq)
-			free_irq(scn->wake_irq, scn);
+			pfrm_free_irq(scn->qdf_dev->dev, scn->wake_irq, scn);
 		scn->wake_irq = 0;
 	} else if (sc->num_msi_intrs > 0) {
 		/* MSI interrupt(s) */
@@ -2591,7 +2592,7 @@
 		return -EINVAL;
 	}
 
-	pci_read_config_word(sc->pdev, PCI_DEVICE_ID, &dev_id);
+	pfrm_read_config_word(sc->pdev, PCI_DEVICE_ID, &dev_id);
 
 	if (dev_id == sc->devid)
 		return 0;
@@ -3020,23 +3021,23 @@
 	HIF_ERROR("%s: keep_awake_count = %d",
 			__func__, hif_state->keep_awake_count);
 
-	pci_read_config_word(sc->pdev, PCI_VENDOR_ID, &val);
+	pfrm_read_config_word(sc->pdev, PCI_VENDOR_ID, &val);
 
 	HIF_ERROR("%s: PCI Vendor ID = 0x%04x", __func__, val);
 
-	pci_read_config_word(sc->pdev, PCI_DEVICE_ID, &val);
+	pfrm_read_config_word(sc->pdev, PCI_DEVICE_ID, &val);
 
 	HIF_ERROR("%s: PCI Device ID = 0x%04x", __func__, val);
 
-	pci_read_config_word(sc->pdev, PCI_COMMAND, &val);
+	pfrm_read_config_word(sc->pdev, PCI_COMMAND, &val);
 
 	HIF_ERROR("%s: PCI Command = 0x%04x", __func__, val);
 
-	pci_read_config_word(sc->pdev, PCI_STATUS, &val);
+	pfrm_read_config_word(sc->pdev, PCI_STATUS, &val);
 
 	HIF_ERROR("%s: PCI Status = 0x%04x", __func__, val);
 
-	pci_read_config_dword(sc->pdev, PCI_BASE_ADDRESS_0, &bar);
+	pfrm_read_config_dword(sc->pdev, PCI_BASE_ADDRESS_0, &bar);
 
 	HIF_ERROR("%s: PCI BAR 0 = 0x%08x", __func__, bar);
 
@@ -3331,12 +3332,14 @@
  */
 static void hif_ce_srng_msi_irq_disable(struct hif_softc *hif_sc, int ce_id)
 {
-	disable_irq_nosync(hif_ce_msi_map_ce_to_irq(hif_sc, ce_id));
+	pfrm_disable_irq_nosync(hif_sc->qdf_dev->dev,
+				hif_ce_msi_map_ce_to_irq(hif_sc, ce_id));
 }
 
 static void hif_ce_srng_msi_irq_enable(struct hif_softc *hif_sc, int ce_id)
 {
-	enable_irq(hif_ce_msi_map_ce_to_irq(hif_sc, ce_id));
+	pfrm_enable_irq(hif_sc->qdf_dev->dev,
+			hif_ce_msi_map_ce_to_irq(hif_sc, ce_id));
 }
 
 static void hif_ce_legacy_msi_irq_disable(struct hif_softc *hif_sc, int ce_id)
@@ -3360,18 +3363,25 @@
 	struct hif_pci_softc *pci_sc = HIF_GET_PCI_SOFTC(scn);
 	struct CE_attr *host_ce_conf = ce_sc->host_ce_config;
 
-	/* do wake irq assignment */
-	ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "WAKE",
-					  &msi_data_count, &msi_data_start,
-					  &msi_irq_start);
-	if (ret)
-		return ret;
+	if (!scn->disable_wake_irq) {
+		/* do wake irq assignment */
+		ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "WAKE",
+						  &msi_data_count,
+						  &msi_data_start,
+						  &msi_irq_start);
+		if (ret)
+			return ret;
 
-	scn->wake_irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_irq_start);
-	ret = request_irq(scn->wake_irq, hif_wake_interrupt_handler,
-			  IRQF_NO_SUSPEND, "wlan_wake_irq", scn);
-	if (ret)
-		return ret;
+		scn->wake_irq = pld_get_msi_irq(scn->qdf_dev->dev,
+						msi_irq_start);
+
+		ret = pfrm_request_irq(scn->qdf_dev->dev, scn->wake_irq,
+				       hif_wake_interrupt_handler,
+				       IRQF_NO_SUSPEND, "wlan_wake_irq", scn);
+
+		if (ret)
+			return ret;
+	}
 
 	/* do ce irq assignments */
 	ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE",
@@ -3408,10 +3418,11 @@
 			continue;
 
 		pci_sc->ce_msi_irq_num[ce_id] = irq;
-		ret = request_irq(irq, hif_ce_interrupt_handler,
-				  IRQF_SHARED,
-				  ce_name[ce_id],
-				  &ce_sc->tasklets[ce_id]);
+		ret = pfrm_request_irq(scn->qdf_dev->dev,
+				       irq, hif_ce_interrupt_handler,
+				       IRQF_SHARED,
+				       ce_name[ce_id],
+				       &ce_sc->tasklets[ce_id]);
 		if (ret)
 			goto free_irq;
 	}
@@ -3426,12 +3437,16 @@
 		ce_id--;
 		msi_data = (ce_id % msi_data_count) + msi_irq_start;
 		irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data);
-		free_irq(irq, &ce_sc->tasklets[ce_id]);
+		pfrm_free_irq(scn->qdf_dev->dev,
+			      irq, &ce_sc->tasklets[ce_id]);
 	}
 
 free_wake_irq:
-	free_irq(scn->wake_irq, scn->qdf_dev->dev);
-	scn->wake_irq = 0;
+	if (!scn->disable_wake_irq) {
+		pfrm_free_irq(scn->qdf_dev->dev,
+			      scn->wake_irq, scn->qdf_dev->dev);
+		scn->wake_irq = 0;
+	}
 
 	return ret;
 }
@@ -3439,17 +3454,20 @@
 static void hif_exec_grp_irq_disable(struct hif_exec_context *hif_ext_group)
 {
 	int i;
+	struct hif_softc *scn = HIF_GET_SOFTC(hif_ext_group->hif);
 
 	for (i = 0; i < hif_ext_group->numirq; i++)
-		disable_irq_nosync(hif_ext_group->os_irq[i]);
+		pfrm_disable_irq_nosync(scn->qdf_dev->dev,
+					hif_ext_group->os_irq[i]);
 }
 
 static void hif_exec_grp_irq_enable(struct hif_exec_context *hif_ext_group)
 {
 	int i;
+	struct hif_softc *scn = HIF_GET_SOFTC(hif_ext_group->hif);
 
 	for (i = 0; i < hif_ext_group->numirq; i++)
-		enable_irq(hif_ext_group->os_irq[i]);
+		pfrm_enable_irq(scn->qdf_dev->dev, hif_ext_group->os_irq[i]);
 }
 
 /**
@@ -3483,11 +3501,12 @@
 
 		hif_info("request_irq = %d for grp %d",
 			 irq, hif_ext_group->grp_id);
-		ret = request_irq(irq,
-				  hif_ext_group_interrupt_handler,
-				  IRQF_SHARED | IRQF_NO_SUSPEND,
-				  "wlan_EXT_GRP",
-				  hif_ext_group);
+		ret = pfrm_request_irq(
+				scn->qdf_dev->dev, irq,
+				hif_ext_group_interrupt_handler,
+				IRQF_SHARED | IRQF_NO_SUSPEND,
+				"wlan_EXT_GRP",
+				hif_ext_group);
 		if (ret) {
 			HIF_ERROR("%s: request_irq failed ret = %d",
 				  __func__, ret);
@@ -3770,7 +3789,7 @@
 	hif_disable_power_gating(hif_hdl);
 
 	device_disable_async_suspend(&pdev->dev);
-	pci_read_config_word(pdev, 0x08, &revision_id);
+	pfrm_read_config_word(pdev, 0x08, &revision_id);
 
 	ret = hif_get_device_type(id->device, revision_id,
 						&hif_type, &target_type);
diff --git a/hif/src/pcie/if_pci_internal.h b/hif/src/pcie/if_pci_internal.h
index 16aea4a..c334862 100644
--- a/hif/src/pcie/if_pci_internal.h
+++ b/hif/src/pcie/if_pci_internal.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016, 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, 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
@@ -23,8 +23,8 @@
 #define PCI_CFG_TO_DISABLE_L1SS_STATES(pdev, addr) \
 { \
 	uint32_t lcr_val; \
-	pci_read_config_dword(pdev, addr, &lcr_val); \
-	pci_write_config_dword(pdev, addr, (lcr_val & ~0x0000000f)); \
+	pfrm_read_config_dword(pdev, addr, &lcr_val); \
+	pfrm_write_config_dword(pdev, addr, (lcr_val & ~0x0000000f)); \
 }
 #else
 #define PCI_CFG_TO_DISABLE_L1SS_STATES(pdev, addr)
diff --git a/hif/src/snoc/if_ahb.c b/hif/src/snoc/if_ahb.c
index 3ec81c9..568f61e 100644
--- a/hif/src/snoc/if_ahb.c
+++ b/hif/src/snoc/if_ahb.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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
@@ -271,13 +271,21 @@
 	for (i = 0; i < scn->ce_count; i++) {
 		if (host_ce_conf[i].flags & CE_ATTR_DISABLE_INTR)
 			continue;
-		qal_vbus_get_irq((struct qdf_pfm_hndl *)pdev,
-				 ic_irqname[HIF_IC_CE0_IRQ_OFFSET + i], &irq);
+		ret = pfrm_get_irq(&pdev->dev, (struct qdf_pfm_hndl *)pdev,
+				   ic_irqname[HIF_IC_CE0_IRQ_OFFSET + i],
+				   HIF_IC_CE0_IRQ_OFFSET + i, &irq);
+		if (ret) {
+			dev_err(&pdev->dev, "get irq failed\n");
+			ret = -1;
+			goto end;
+		}
+
 		ic_irqnum[HIF_IC_CE0_IRQ_OFFSET + i] = irq;
-		ret = request_irq(irq ,
-				hif_ahb_interrupt_handler,
-				IRQF_TRIGGER_RISING, ic_irqname[HIF_IC_CE0_IRQ_OFFSET + i],
-				&hif_state->tasklets[i]);
+		ret = pfrm_request_irq(&pdev->dev, irq,
+				       hif_ahb_interrupt_handler,
+				       IRQF_TRIGGER_RISING,
+				       ic_irqname[HIF_IC_CE0_IRQ_OFFSET + i],
+				       &hif_state->tasklets[i]);
 		if (ret) {
 			dev_err(&pdev->dev, "ath_request_irq failed\n");
 			ret = -1;
@@ -308,18 +316,23 @@
 	qdf_spin_lock_irqsave(&hif_ext_group->irq_lock);
 
 	for (j = 0; j < hif_ext_group->numirq; j++) {
-		qal_vbus_get_irq((struct qdf_pfm_hndl *)pdev,
-				 ic_irqname[hif_ext_group->irq[j]], &irq);
-
+		ret = pfrm_get_irq(&pdev->dev, (struct qdf_pfm_hndl *)pdev,
+				   ic_irqname[hif_ext_group->irq[j]],
+				   hif_ext_group->irq[j], &irq);
+		if (ret) {
+			dev_err(&pdev->dev, "get irq failed\n");
+			ret = -1;
+			goto end;
+		}
 		ic_irqnum[hif_ext_group->irq[j]] = irq;
 		irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY);
-		ret = request_irq(irq, hif_ext_group_interrupt_handler,
-				  IRQF_TRIGGER_RISING,
-				  ic_irqname[hif_ext_group->irq[j]],
-				  hif_ext_group);
+		ret = pfrm_request_irq(scn->qdf_dev->dev,
+				       irq, hif_ext_group_interrupt_handler,
+				       IRQF_TRIGGER_RISING,
+				       ic_irqname[hif_ext_group->irq[j]],
+				       hif_ext_group);
 		if (ret) {
-			dev_err(&pdev->dev,
-				"ath_request_irq failed\n");
+			dev_err(&pdev->dev, "ath_request_irq failed\n");
 			ret = -1;
 			goto end;
 		}
@@ -363,7 +376,8 @@
 			 */
 			for (j = 0; j < hif_ext_group->numirq; j++) {
 				irq = hif_ext_group->os_irq[j];
-				free_irq(irq, hif_ext_group);
+				pfrm_free_irq(scn->qdf_dev->dev,
+					      irq, hif_ext_group);
 			}
 		}
 	}
@@ -450,19 +464,23 @@
 	int mem_pa_size = 0;
 	struct hif_target_info *tgt_info = NULL;
 	struct qdf_vbus_resource *vmres = NULL;
+	QDF_STATUS status;
 
 	tgt_info = &scn->target_info;
 	/*Disable WIFI clock input*/
 	if (sc->mem) {
-		qal_vbus_get_resource((struct qdf_pfm_hndl *)pdev, &vmres,
-				      IORESOURCE_MEM, 0);
-		memres = (struct resource *)vmres;
-		if (!memres) {
+		status = pfrm_platform_get_resource(
+				scn->qdf_dev->dev,
+				(struct qdf_pfm_hndl *)pdev, &vmres,
+				IORESOURCE_MEM, 0);
+		if (QDF_IS_STATUS_ERROR(status)) {
 			HIF_INFO("%s: Failed to get IORESOURCE_MEM\n",
-								__func__);
+				 __func__);
 			return;
 		}
-		mem_pa_size = memres->end - memres->start + 1;
+		memres = (struct resource *)vmres;
+		if (memres)
+			mem_pa_size = memres->end - memres->start + 1;
 
 		/* Should not be executed on 8074 platform */
 		if ((tgt_info->target_type != TARGET_TYPE_QCA8074) &&
@@ -474,9 +492,9 @@
 		}
 		mem = (void __iomem *)sc->mem;
 		if (mem) {
-			devm_iounmap(&pdev->dev, mem);
-			devm_release_mem_region(&pdev->dev, scn->mem_pa,
-								mem_pa_size);
+			pfrm_devm_iounmap(&pdev->dev, mem);
+			pfrm_devm_release_mem_region(&pdev->dev, scn->mem_pa,
+						     mem_pa_size);
 			sc->mem = NULL;
 		}
 	}
@@ -510,6 +528,8 @@
 	void __iomem *mem = NULL;
 	uint32_t revision_id = 0;
 	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(ol_sc);
+	QDF_STATUS status;
+	struct qdf_vbus_resource *vmres = NULL;
 
 	sc->pdev = (struct pci_dev *)pdev;
 	sc->dev = &pdev->dev;
@@ -523,22 +543,30 @@
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	status = pfrm_platform_get_resource(&pdev->dev,
+					    (struct qdf_pfm_hndl *)pdev,
+					    &vmres,
+					    IORESOURCE_MEM, 0);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		HIF_INFO("%s: Failed to get IORESOURCE_MEM\n", __func__);
+		return -EIO;
+	}
+	memres = (struct resource *)vmres;
 	if (!memres) {
 		HIF_INFO("%s: Failed to get IORESOURCE_MEM\n", __func__);
 		return -EIO;
 	}
 
-	ret = dma_set_mask(dev, DMA_BIT_MASK(32));
+	ret = pfrm_dma_set_mask(dev, 32);
 	if (ret) {
 		HIF_INFO("ath: 32-bit DMA not available\n");
 		goto err_cleanup1;
 	}
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
-	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+	ret = pfrm_dma_set_mask_and_coherent(dev, 32);
 #else
-	ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
+	ret = pfrm_dma_set_coherent_mask(dev, 32);
 #endif
 	if (ret) {
 		HIF_ERROR("%s: failed to set dma mask error = %d",
@@ -548,11 +576,16 @@
 
 	/* Arrange for access to Target SoC registers. */
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
-	mem = devm_ioremap_resource(&pdev->dev, memres);
+	status = pfrm_devm_ioremap_resource(dev,
+					    (struct qdf_vbus_resource *)memres,
+					    &mem);
 #else
-	mem = devm_request_and_ioremap(&pdev->dev, memres);
+	status = pfrm_devm_request_and_ioremap(
+					dev,
+					(struct qdf_vbus_resource *)memres,
+					&mem);
 #endif
-	if (IS_ERR(mem)) {
+	if (QDF_IS_STATUS_ERROR(status)) {
 		HIF_INFO("ath: ioremap error\n");
 		ret = PTR_ERR(mem);
 		goto err_cleanup1;
@@ -640,20 +673,22 @@
 	if (sc->num_msi_intrs > 0) {
 		/* MSI interrupt(s) */
 		for (i = 0; i < sc->num_msi_intrs; i++) {
-			free_irq(sc->irq + i, sc);
+			pfrm_free_irq(scn->qdf_dev->dev, sc->irq + i, sc);
 		}
 		sc->num_msi_intrs = 0;
 	} else {
 		if (!scn->per_ce_irq) {
-			free_irq(sc->irq, sc);
+			pfrm_free_irq(scn->qdf_dev->dev, sc->irq, sc);
 		} else {
 			for (i = 0; i < scn->ce_count; i++) {
 				if (host_ce_conf[i].flags
 						& CE_ATTR_DISABLE_INTR)
 					continue;
 
-				free_irq(ic_irqnum[HIF_IC_CE0_IRQ_OFFSET + i],
-						&hif_state->tasklets[i]);
+				pfrm_free_irq(
+					scn->qdf_dev->dev,
+					ic_irqnum[HIF_IC_CE0_IRQ_OFFSET + i],
+					&hif_state->tasklets[i]);
 			}
 			hif_ahb_deconfigure_grp_irq(scn);
 		}
@@ -800,3 +835,23 @@
 {
 	return !ce_srng_based(scn);
 }
+
+void hif_ahb_display_stats(struct hif_softc *scn)
+{
+	if (!scn) {
+		HIF_ERROR("%s, hif_scn null", __func__);
+		return;
+	}
+	hif_display_ce_stats(scn);
+}
+
+void hif_ahb_clear_stats(struct hif_softc *scn)
+{
+	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
+
+	if (!hif_state) {
+		HIF_ERROR("%s, hif_state null", __func__);
+		return;
+	}
+	hif_clear_ce_stats(hif_state);
+}
diff --git a/hif/src/snoc/if_snoc.c b/hif/src/snoc/if_snoc.c
index 119db8a..5135088 100644
--- a/hif/src/snoc/if_snoc.c
+++ b/hif/src/snoc/if_snoc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-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
@@ -78,13 +78,11 @@
 
 void hif_snoc_display_stats(struct hif_softc *hif_ctx)
 {
-	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_ctx);
-
-	if (!hif_state) {
+	if (!hif_ctx) {
 		HIF_ERROR("%s, hif_ctx null", __func__);
 		return;
 	}
-	hif_display_ce_stats(hif_state);
+	hif_display_ce_stats(hif_ctx);
 }
 
 void hif_snoc_clear_stats(struct hif_softc *hif_ctx)
diff --git a/htc/htc.c b/htc/htc.c
index 2a40fea..06c1ea4 100644
--- a/htc/htc.c
+++ b/htc/htc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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
@@ -134,6 +134,16 @@
 	hif_dump(target->hif_dev, CmdId, start);
 }
 
+void htc_ce_tasklet_debug_dump(HTC_HANDLE htc_handle)
+{
+	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
+
+	if (!target->hif_dev)
+		return;
+
+	hif_display_stats(target->hif_dev);
+}
+
 /* cleanup the HTC instance */
 static void htc_cleanup(HTC_TARGET *target)
 {
diff --git a/htc/htc_api.h b/htc/htc_api.h
index 9c06ac4..8adabc6 100644
--- a/htc/htc_api.h
+++ b/htc/htc_api.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014, 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, 2016-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
@@ -482,6 +482,15 @@
 void htc_dump(HTC_HANDLE HTCHandle, uint8_t CmdId, bool start);
 
 /**
+ * htc_ce_taklet_debug_dump - Dump ce tasklet rings debug data
+ * @HTCHandle - HTC handle
+ *
+ * Debug logs will be printed.
+ * Return: None
+ */
+void htc_ce_tasklet_debug_dump(HTC_HANDLE htc_handle);
+
+/**
  * htc_send_pkt - Send an HTC packet
  * @HTCHandle - HTC handle
  * @pPacket - packet to send
diff --git a/init_deinit/dispatcher/src/dispatcher_init_deinit.c b/init_deinit/dispatcher/src/dispatcher_init_deinit.c
index df71a65..0781988 100644
--- a/init_deinit/dispatcher/src/dispatcher_init_deinit.c
+++ b/init_deinit/dispatcher/src/dispatcher_init_deinit.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-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 above
@@ -72,6 +72,10 @@
 #include <wlan_cfr_utils_api.h>
 #endif
 
+#ifdef FEATURE_COEX
+#include <wlan_coex_utils_api.h>
+#endif
+
 /**
  * DOC: This file provides various init/deinit trigger point for new
  * components.
@@ -707,6 +711,50 @@
 }
 #endif /* WLAN_SUPPORT_FILS */
 
+#ifdef FEATURE_COEX
+static QDF_STATUS dispatcher_coex_init(void)
+{
+	return wlan_coex_init();
+}
+
+static QDF_STATUS dispatcher_coex_deinit(void)
+{
+	return wlan_coex_deinit();
+}
+
+static QDF_STATUS dispatcher_coex_psoc_open(struct wlan_objmgr_psoc *psoc)
+{
+	return wlan_coex_psoc_open(psoc);
+}
+
+static QDF_STATUS dispatcher_coex_psoc_close(struct wlan_objmgr_psoc *psoc)
+{
+	return wlan_coex_psoc_close(psoc);
+}
+#else
+static inline QDF_STATUS dispatcher_coex_init(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS dispatcher_coex_deinit(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS
+dispatcher_coex_psoc_open(struct wlan_objmgr_psoc *psoc)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS
+dispatcher_coex_psoc_close(struct wlan_objmgr_psoc *psoc)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* FEATURE_COEX */
+
 QDF_STATUS dispatcher_init(void)
 {
 	if (QDF_STATUS_SUCCESS != wlan_objmgr_global_obj_init())
@@ -772,6 +820,9 @@
 	if (QDF_STATUS_SUCCESS != dispatcher_init_cfr())
 		goto cfr_init_fail;
 
+	if (QDF_STATUS_SUCCESS != dispatcher_coex_init())
+		goto coex_init_fail;
+
 	/*
 	 * scheduler INIT has to be the last as each component's
 	 * initialization has to happen first and then at the end
@@ -783,6 +834,8 @@
 	return QDF_STATUS_SUCCESS;
 
 scheduler_init_fail:
+	dispatcher_coex_deinit();
+coex_init_fail:
 	dispatcher_deinit_cfr();
 cfr_init_fail:
 	wlan_cmn_mlme_deinit();
@@ -836,6 +889,8 @@
 
 	QDF_BUG(QDF_STATUS_SUCCESS == scheduler_deinit());
 
+	QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_coex_deinit());
+
 	QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_deinit_cfr());
 
 	QDF_BUG(QDF_STATUS_SUCCESS == wlan_cmn_mlme_deinit());
@@ -924,8 +979,13 @@
 	if (QDF_STATUS_SUCCESS != dispatcher_ftm_psoc_open(psoc))
 		goto ftm_psoc_open_fail;
 
+	if (QDF_STATUS_SUCCESS != dispatcher_coex_psoc_open(psoc))
+		goto coex_psoc_open_fail;
+
 	return QDF_STATUS_SUCCESS;
 
+coex_psoc_open_fail:
+	dispatcher_ftm_psoc_close(psoc);
 ftm_psoc_open_fail:
 	son_psoc_close(psoc);
 psoc_son_fail:
@@ -946,6 +1006,8 @@
 
 QDF_STATUS dispatcher_psoc_close(struct wlan_objmgr_psoc *psoc)
 {
+	QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_coex_psoc_close(psoc));
+
 	QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_ftm_psoc_close(psoc));
 
 	QDF_BUG(QDF_STATUS_SUCCESS == son_psoc_close(psoc));
diff --git a/os_if/linux/coex/inc/wlan_cfg80211_coex.h b/os_if/linux/coex/inc/wlan_cfg80211_coex.h
new file mode 100644
index 0000000..cd3e6bd
--- /dev/null
+++ b/os_if/linux/coex/inc/wlan_cfg80211_coex.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 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 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.
+ */
+
+/**
+ * DOC: declares driver functions interfacing with linux kernel
+ */
+
+#ifndef _WLAN_CFG80211_COEX_H_
+#define _WLAN_CFG80211_COEX_H_
+#include <wlan_cfg80211.h>
+#include <wlan_objmgr_cmn.h>
+
+#ifdef FEATURE_COEX
+int wlan_cfg80211_coex_set_btc_chain_mode(struct wlan_objmgr_vdev *vdev,
+					  const void *data, int data_len);
+#else
+static inline int
+wlan_cfg80211_coex_set_btc_chain_mode(struct wlan_objmgr_vdev *vdev,
+				      const void *data, int data_len)
+{
+	return -ENOTSUPP;
+}
+#endif
+#endif
diff --git a/os_if/linux/coex/src/wlan_cfg80211_coex.c b/os_if/linux/coex/src/wlan_cfg80211_coex.c
new file mode 100644
index 0000000..754b167
--- /dev/null
+++ b/os_if/linux/coex/src/wlan_cfg80211_coex.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 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 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.
+ */
+
+/**
+ * DOC: defines driver functions interfacing with linux kernel
+ */
+#include <wmi_unified_param.h>
+#include <wlan_osif_request_manager.h>
+#include <osif_sync.h>
+#include <wlan_objmgr_psoc_obj_i.h>
+#include <wlan_coex_main.h>
+#include <wlan_coex_ucfg_api.h>
+#include <wlan_cfg80211_coex.h>
+
+static const struct nla_policy
+btc_chain_mode_policy[QCA_VENDOR_ATTR_BTC_CHAIN_MODE_MAX + 1] = {
+	[QCA_VENDOR_ATTR_BTC_CHAIN_MODE] = {.type = NLA_U32},
+	[QCA_VENDOR_ATTR_BTC_CHAIN_MODE_RESTART] = {.type = NLA_FLAG},
+};
+
+static int
+__wlan_cfg80211_coex_set_btc_chain_mode(struct wlan_objmgr_vdev *vdev,
+					uint8_t mode, bool do_restart)
+{
+	QDF_STATUS status;
+	uint8_t cur_mode;
+	int err;
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_objmgr_vdev *vdev_tmp;
+	int vdev_id;
+	struct coex_psoc_obj *coex_obj;
+
+	if (!vdev) {
+		coex_err("Null vdev");
+		return -EINVAL;
+	}
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	if (!psoc) {
+		coex_err("NULL psoc");
+		return -EINVAL;
+	}
+
+	coex_obj = wlan_psoc_get_coex_obj(psoc);
+	if (!coex_obj)
+		return -EINVAL;
+
+	status = ucfg_coex_psoc_get_btc_chain_mode(psoc, &cur_mode);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		coex_err("failed to get cur BTC chain mode, status %d", status);
+		return -EFAULT;
+	}
+
+	if (cur_mode == mode)
+		return -EALREADY;
+
+	status = ucfg_coex_psoc_set_btc_chain_mode(psoc, mode);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		coex_err("unable to set BTC chain mode to %d", mode);
+		return -EFAULT;
+	}
+
+	wlan_objmgr_for_each_psoc_vdev(psoc, vdev_id, vdev_tmp) {
+		status = ucfg_coex_send_btc_chain_mode(vdev, mode);
+		err = qdf_status_to_os_return(status);
+		if (err) {
+			coex_err("Failed to set btc chain mode to %d for vdev %d",
+				 mode, vdev_id);
+			return err;
+		}
+		coex_debug("Set btc chain mode to %d for vdev %d",
+			   mode, vdev_id);
+
+		if (!do_restart)
+			continue;
+
+		wlan_coex_config_updated(vdev, COEX_CONFIG_BTC_CHAIN_MODE);
+	}
+
+	return 0;
+}
+
+/**
+ * wlan_hdd_cfg80211_set_btc_chain_mode() - set btc chain mode
+ * @wiphy: pointer to wireless wiphy structure.
+ * @wdev: pointer to wireless_dev structure.
+ * @data: pointer to btc chain mode command parameters.
+ * @data_len: the length in byte of btc chain mode command parameters.
+ *
+ * Return: An error code or 0 on success.
+ */
+int wlan_cfg80211_coex_set_btc_chain_mode(struct wlan_objmgr_vdev *vdev,
+					  const void *data, int data_len)
+{
+	struct nlattr *tb[QCA_VENDOR_ATTR_BTC_CHAIN_MODE_MAX + 1];
+	uint32_t mode;
+	bool restart;
+
+	if (wlan_cfg80211_nla_parse(tb, QCA_VENDOR_ATTR_BTC_CHAIN_MODE_MAX,
+				    data, data_len, btc_chain_mode_policy)) {
+		coex_err("Invalid btc chain mode ATTR");
+		return -EINVAL;
+	}
+
+	if (!tb[QCA_VENDOR_ATTR_BTC_CHAIN_MODE]) {
+		coex_err("btc chain mode - no attr mode");
+		return -EINVAL;
+	}
+
+	mode = nla_get_u32(tb[QCA_VENDOR_ATTR_BTC_CHAIN_MODE]);
+	if (mode < QCA_BTC_CHAIN_SHARED || mode > QCA_BTC_CHAIN_SEPARATED) {
+		coex_err("Invalid btc chain mode %d", mode);
+		return -EINVAL;
+	}
+
+	restart = nla_get_flag(tb[QCA_VENDOR_ATTR_BTC_CHAIN_MODE_RESTART]);
+
+	coex_debug("vdev_id %u mode %u restart %u",
+		   wlan_vdev_get_id(vdev), mode, restart);
+
+	return __wlan_cfg80211_coex_set_btc_chain_mode(vdev, mode, restart);
+}
diff --git a/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c b/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c
index 818689f..228c471 100644
--- a/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c
+++ b/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-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
@@ -98,7 +98,7 @@
 	nl_buf_len += QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
 				(NLMSG_HDRLEN + sizeof(uint32_t));
 
-	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, nl_buf_len);
+	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, nl_buf_len);
 
 	if (!skb) {
 		osif_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
@@ -202,11 +202,11 @@
 		goto nla_put_failure;
 	}
 
-	cfg80211_vendor_cmd_reply(skb);
+	wlan_cfg80211_vendor_cmd_reply(skb);
 	return 0;
 
 nla_put_failure:
-	kfree_skb(skb);
+	wlan_cfg80211_vendor_free_skb(skb);
 	return -EINVAL;
 }
 
diff --git a/os_if/linux/scan/inc/wlan_cfg80211_scan.h b/os_if/linux/scan/inc/wlan_cfg80211_scan.h
index aee2d3b..a43e057 100644
--- a/os_if/linux/scan/inc/wlan_cfg80211_scan.h
+++ b/os_if/linux/scan/inc/wlan_cfg80211_scan.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-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
@@ -128,6 +128,14 @@
  * @half_rate: Half rate flag
  * @quarter_rate: Quarter rate flag
  * @strict_pscan: strict passive scan flag
+ * @dwell_time_active: Active dwell time. Ignored if zero or inapplicable.
+ * @dwell_time_active_2g: 2.4 GHz specific active dwell time. Ignored if zero or
+ * inapplicable.
+ * @dwell_time_passive: Passive dwell time. Ignored if zero or inapplicable.
+ * @dwell_time_active_6g: 6 GHz specific active dwell time. Ignored if zero or
+ * inapplicable.
+ * @dwell_time_passive_6g: 6 GHz specific passive dwell time. Ignored if zero or
+ * inapplicable.
  */
 struct scan_params {
 	uint8_t source;
@@ -137,6 +145,11 @@
 	bool half_rate;
 	bool quarter_rate;
 	bool strict_pscan;
+	uint32_t dwell_time_active;
+	uint32_t dwell_time_active_2g;
+	uint32_t dwell_time_passive;
+	uint32_t dwell_time_active_6g;
+	uint32_t dwell_time_passive_6g;
 };
 
 /**
diff --git a/os_if/linux/scan/src/wlan_cfg80211_scan.c b/os_if/linux/scan/src/wlan_cfg80211_scan.c
index de69efe..a7f6616 100644
--- a/os_if/linux/scan/src/wlan_cfg80211_scan.c
+++ b/os_if/linux/scan/src/wlan_cfg80211_scan.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-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
@@ -839,11 +839,13 @@
 	int i;
 	uint8_t scan_status;
 	uint64_t cookie;
+	int index = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX;
 
-	skb = cfg80211_vendor_event_alloc(req->wdev->wiphy, req->wdev,
-			SCAN_DONE_EVENT_BUF_SIZE + 4 + NLMSG_HDRLEN,
-			QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX,
-			GFP_ATOMIC);
+	skb = wlan_cfg80211_vendor_event_alloc(req->wdev->wiphy, req->wdev,
+					       SCAN_DONE_EVENT_BUF_SIZE + 4 +
+					       NLMSG_HDRLEN,
+					       index,
+					       GFP_ATOMIC);
 
 	if (!skb) {
 		osif_err("skb alloc failed");
@@ -889,13 +891,13 @@
 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_SCAN_STATUS, scan_status))
 		goto nla_put_failure;
 
-	cfg80211_vendor_event(skb, GFP_ATOMIC);
+	wlan_cfg80211_vendor_event(skb, GFP_ATOMIC);
 	qdf_mem_free(req);
 
 	return;
 
 nla_put_failure:
-	kfree_skb(skb);
+	wlan_cfg80211_vendor_free_skb(skb);
 	qdf_mem_free(req);
 }
 
@@ -1405,6 +1407,24 @@
 	if (is_p2p_scan && request->no_cck)
 		req->scan_req.scan_type = SCAN_TYPE_P2P_SEARCH;
 
+	if (params->dwell_time_active)
+		req->scan_req.dwell_time_active = params->dwell_time_active;
+
+	if (params->dwell_time_active_2g)
+		req->scan_req.dwell_time_active_2g =
+			params->dwell_time_active_2g;
+
+	if (params->dwell_time_passive)
+		req->scan_req.dwell_time_passive = params->dwell_time_passive;
+
+	if (params->dwell_time_active_6g)
+		req->scan_req.dwell_time_active_6g =
+			params->dwell_time_active_6g;
+
+	if (params->dwell_time_passive_6g)
+		req->scan_req.dwell_time_passive_6g =
+			params->dwell_time_passive_6g;
+
 	/* Set dwell time mode according to scan policy type flags */
 	if (ucfg_scan_cfg_honour_nl_scan_policy_flags(psoc)) {
 		if (req->scan_req.scan_policy_high_accuracy)
diff --git a/os_if/linux/spectral/src/wlan_cfg80211_spectral.c b/os_if/linux/spectral/src/wlan_cfg80211_spectral.c
index 8173cee..b45efef 100644
--- a/os_if/linux/spectral/src/wlan_cfg80211_spectral.c
+++ b/os_if/linux/spectral/src/wlan_cfg80211_spectral.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-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
@@ -31,7 +31,6 @@
 #include <wlan_spectral_ucfg_api.h>
 #include <wlan_cfg80211_spectral.h>
 #include <spectral_ioctl.h>
-#include "qal_devcfg.h"
 
 static const struct nla_policy spectral_scan_policy[
 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1] = {
@@ -377,7 +376,8 @@
 	skb_len += NLA_HDRLEN + sizeof(u32);
 	/* QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE */
 	skb_len += NLA_HDRLEN + sizeof(u64);
-	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
+	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
+
 	if (!skb) {
 		osif_err(" reply skb alloc failed");
 		return -ENOMEM;
@@ -385,8 +385,10 @@
 
 	status = wlan_cfg80211_spectral_scan_dma_debug_config(
 			pdev, tb, sscan_mode);
-	if (QDF_IS_STATUS_ERROR(status))
-		return -EINVAL;
+	if (QDF_IS_STATUS_ERROR(status)) {
+		status = QDF_STATUS_E_INVAL;
+		goto free_skb_return_os_status;
+	}
 
 	if (CONFIG_REQUESTED(scan_req_type)) {
 		sscan_req.ss_mode = sscan_mode;
@@ -401,25 +403,23 @@
 
 			/* No error reasons populated, just return error */
 			if (sscan_req.config_req.sscan_err_code ==
-					SPECTRAL_SCAN_ERR_INVALID) {
-				kfree_skb(skb);
-				return qdf_status_to_os_return(status);
-			}
+					SPECTRAL_SCAN_ERR_INVALID)
+				goto free_skb_return_os_status;
 
 			status = convert_spectral_err_code_internal_to_nl
 					(sscan_req.config_req.sscan_err_code,
 					 &spectral_nl_err_code);
 			if (QDF_IS_STATUS_ERROR(status)) {
-				kfree_skb(skb);
-				return -EINVAL;
+				status = QDF_STATUS_E_INVAL;
+				goto free_skb_return_os_status;
 			}
 
 			if (nla_put_u32
 			    (skb,
 			     QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE,
 			     spectral_nl_err_code)) {
-				kfree_skb(skb);
-				return -EINVAL;
+				status = QDF_STATUS_E_INVAL;
+				goto free_skb_return_os_status;
 			}
 		}
 	}
@@ -434,25 +434,23 @@
 
 			/* No error reasons populated, just return error */
 			if (sscan_req.action_req.sscan_err_code ==
-					SPECTRAL_SCAN_ERR_INVALID) {
-				kfree_skb(skb);
-				return qdf_status_to_os_return(status);
-			}
+					SPECTRAL_SCAN_ERR_INVALID)
+				goto free_skb_return_os_status;
 
 			status = convert_spectral_err_code_internal_to_nl
 					(sscan_req.action_req.sscan_err_code,
 					 &spectral_nl_err_code);
 			if (QDF_IS_STATUS_ERROR(status)) {
-				kfree_skb(skb);
-				return -EINVAL;
+				status = QDF_STATUS_E_INVAL;
+				goto free_skb_return_os_status;
 			}
 
 			if (nla_put_u32
 			    (skb,
 			     QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE,
 			     spectral_nl_err_code)) {
-				kfree_skb(skb);
-				return -EINVAL;
+				status = QDF_STATUS_E_INVAL;
+				goto free_skb_return_os_status;
 			}
 		}
 	}
@@ -461,13 +459,15 @@
 	if (wlan_cfg80211_nla_put_u64(skb,
 				      QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE,
 				      cookie)) {
-		kfree_skb(skb);
-		return -EINVAL;
+		status = QDF_STATUS_E_INVAL;
+		goto free_skb_return_os_status;
 	}
 
-	qal_devcfg_send_response((qdf_nbuf_t)skb);
-
+	wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
 	return 0;
+free_skb_return_os_status:
+	wlan_cfg80211_vendor_free_skb(skb);
+	return qdf_status_to_os_return(status);
 }
 
 int wlan_cfg80211_spectral_scan_stop(struct wiphy *wiphy,
@@ -517,8 +517,9 @@
 		if (QDF_IS_STATUS_ERROR(status))
 			return -EINVAL;
 
-		skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, NLMSG_HDRLEN +
-					sizeof(u32) + NLA_HDRLEN);
+		skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
+				NLMSG_HDRLEN + sizeof(u32) + NLA_HDRLEN);
+
 		if (!skb) {
 			osif_err(" reply skb alloc failed");
 			return -ENOMEM;
@@ -528,10 +529,10 @@
 		    (skb,
 		     QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE,
 		     spectral_nl_err_code)) {
-			kfree_skb(skb);
+			wlan_cfg80211_vendor_free_skb(skb);
 			return -EINVAL;
 		}
-		qal_devcfg_send_response((qdf_nbuf_t)skb);
+		wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
 	}
 
 	return 0;
@@ -568,7 +569,8 @@
 			return -EINVAL;
 	}
 
-	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (sizeof(u32) +
+	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
+		(sizeof(u32) +
 		NLA_HDRLEN) * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX +
 		NLMSG_HDRLEN);
 	if (!skb) {
@@ -643,10 +645,8 @@
 			sconfig->ss_short_report) ||
 	    nla_put_u32(skb,
 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY,
-			sconfig->ss_frequency)) {
-		kfree_skb(skb);
-		return -EINVAL;
-	}
+			sconfig->ss_frequency))
+		goto fail;
 
 	sscan_req.ss_mode = sscan_mode;
 	sscan_req.req_id = SPECTRAL_GET_DEBUG_LEVEL;
@@ -654,13 +654,14 @@
 	spectral_dbg_level = sscan_req.debug_req.spectral_dbg_level;
 	if (nla_put_u32(skb,
 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL,
-			spectral_dbg_level)) {
-		kfree_skb(skb);
-		return -EINVAL;
-	}
-	qal_devcfg_send_response((qdf_nbuf_t)skb);
+			spectral_dbg_level))
+		goto fail;
 
+	wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
 	return 0;
+fail:
+	wlan_cfg80211_vendor_free_skb(skb);
+	return -EINVAL;
 }
 
 int wlan_cfg80211_spectral_scan_get_cap(struct wiphy *wiphy,
@@ -677,7 +678,8 @@
 	status = ucfg_spectral_control(pdev, &sscan_req);
 	scaps = &sscan_req.caps_req.sscan_caps;
 
-	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (sizeof(u32) +
+	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
+		(sizeof(u32) +
 		NLA_HDRLEN) * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_MAX +
 		NLMSG_HDRLEN);
 	if (!skb) {
@@ -773,12 +775,12 @@
 		if (ret)
 			goto fail;
 	}
-	qal_devcfg_send_response((qdf_nbuf_t)skb);
+	wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
 
 	return 0;
 
 fail:
-	kfree_skb(skb);
+	wlan_cfg80211_vendor_free_skb(skb);
 	return -EINVAL;
 }
 
@@ -796,8 +798,9 @@
 	status = ucfg_spectral_control(pdev, &sscan_req);
 	spetcral_diag = &sscan_req.diag_req.sscan_diag;
 
-	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (sizeof(u64) +
-		NLA_HDRLEN) * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_MAX +
+	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
+		(sizeof(u64) + NLA_HDRLEN) *
+		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_MAX +
 		NLMSG_HDRLEN);
 	if (!skb) {
 		osif_err(" reply skb alloc failed");
@@ -824,10 +827,10 @@
 		skb,
 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG2ID_MISMATCH,
 		spetcral_diag->spectral_vhtseg2id_mismatch)) {
-		kfree_skb(skb);
+		wlan_cfg80211_vendor_free_skb(skb);
 		return -EINVAL;
 	}
-	qal_devcfg_send_response((qdf_nbuf_t)skb);
+	wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
 
 	return 0;
 }
@@ -873,8 +876,8 @@
 	status = ucfg_spectral_control(pdev, &sscan_req);
 	sscan_state.is_enabled = sscan_req.status_req.is_enabled;
 
-	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 2 * (sizeof(u32) +
-		NLA_HDRLEN) + NLMSG_HDRLEN);
+	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
+		2 * (sizeof(u32) + NLA_HDRLEN) + NLMSG_HDRLEN);
 	if (!skb) {
 		osif_err(" reply skb alloc failed");
 		return -ENOMEM;
@@ -891,10 +894,10 @@
 			skb,
 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ACTIVE))
 			goto fail;
-	qal_devcfg_send_response((qdf_nbuf_t)skb);
+	wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
 
 	return 0;
 fail:
-	kfree_skb(skb);
+	wlan_cfg80211_vendor_free_skb(skb);
 	return -EINVAL;
 }
diff --git a/os_if/linux/wlan_cfg80211.h b/os_if/linux/wlan_cfg80211.h
index 8dee454..dd23408 100644
--- a/os_if/linux/wlan_cfg80211.h
+++ b/os_if/linux/wlan_cfg80211.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-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
@@ -29,6 +29,8 @@
 #include <net/netlink.h>
 #include <net/cfg80211.h>
 #include <qca_vendor.h>
+#include <qdf_nbuf.h>
+#include "qal_devcfg.h"
 
 #define osif_alert(params...) \
 	QDF_TRACE_FATAL(QDF_MODULE_ID_OS_IF, params)
@@ -56,6 +58,94 @@
 #define osif_nofl_debug(params...) \
 	QDF_TRACE_DEBUG_NO_FL(QDF_MODULE_ID_OS_IF, params)
 
+#if defined(NBUF_MEMORY_DEBUG) && defined(NETLINK_BUF_TRACK)
+#define wlan_cfg80211_vendor_free_skb(skb) \
+	qdf_nbuf_free(skb)
+
+#define wlan_cfg80211_vendor_event(skb, gfp) \
+{ \
+	qdf_nbuf_count_dec(skb); \
+	qdf_net_buf_debug_release_skb(skb); \
+	cfg80211_vendor_event(skb, gfp); \
+}
+
+#define wlan_cfg80211_vendor_cmd_reply(skb) \
+{ \
+	qdf_nbuf_count_dec(skb); \
+	qdf_net_buf_debug_release_skb(skb); \
+	cfg80211_vendor_cmd_reply(skb); \
+}
+
+static inline QDF_STATUS wlan_cfg80211_qal_devcfg_send_response(qdf_nbuf_t skb)
+{
+	qdf_nbuf_count_dec(skb);
+	qdf_net_buf_debug_release_skb(skb);
+	return qal_devcfg_send_response(skb);
+}
+
+static inline struct sk_buff *
+__cfg80211_vendor_cmd_alloc_reply_skb(struct wiphy *wiphy, int len,
+				      const char *func, uint32_t line)
+{
+	struct sk_buff *skb;
+
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
+	if (skb) {
+		qdf_nbuf_count_inc(skb);
+		qdf_net_buf_debug_acquire_skb(skb, func, line);
+	}
+	return skb;
+}
+#define wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len) \
+	__cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len, __func__, __LINE__)
+
+static inline struct sk_buff *
+__cfg80211_vendor_event_alloc(struct wiphy *wiphy,
+			      struct wireless_dev *wdev,
+			      int approxlen,
+			      int event_idx,
+			      gfp_t gfp,
+			      const char *func,
+			      uint32_t line)
+{
+	struct sk_buff *skb;
+
+	skb = cfg80211_vendor_event_alloc(wiphy, wdev,
+					  approxlen,
+					  event_idx,
+					  gfp);
+	if (skb) {
+		qdf_nbuf_count_inc(skb);
+		qdf_net_buf_debug_acquire_skb(skb, func, line);
+	}
+	return skb;
+}
+#define wlan_cfg80211_vendor_event_alloc(wiphy, wdev, len, idx, gfp) \
+	__cfg80211_vendor_event_alloc(wiphy, wdev, len, \
+				      idx, gfp, \
+				      __func__, __LINE__)
+#else /* NBUF_MEMORY_DEBUG && NETLINK_BUF_TRACK */
+#define wlan_cfg80211_vendor_free_skb(skb) \
+	kfree_skb(skb)
+
+#define wlan_cfg80211_vendor_event(skb, gfp) \
+	cfg80211_vendor_event(skb, gfp)
+
+#define wlan_cfg80211_vendor_cmd_reply(skb) \
+	cfg80211_vendor_cmd_reply(skb)
+
+#define wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len) \
+	cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len)
+
+#define wlan_cfg80211_vendor_event_alloc(wiphy, wdev, len, idx, gfp) \
+	cfg80211_vendor_event_alloc(wiphy, wdev, len, idx, gfp)
+
+static inline QDF_STATUS wlan_cfg80211_qal_devcfg_send_response( qdf_nbuf_t skb)
+{
+	return qal_devcfg_send_response(skb);
+}
+#endif /* NBUF_MEMORY_DEBUG && NETLINK_BUF_TRACK */
+
 #undef nla_parse
 #undef nla_parse_nested
 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
@@ -111,5 +201,4 @@
 	return nla_put_u64_64bit(skb, attrtype, value, NL80211_ATTR_PAD);
 }
 #endif
-
 #endif
diff --git a/qdf/inc/qdf_mem.h b/qdf/inc/qdf_mem.h
index 3f59b8f..63eba71 100644
--- a/qdf/inc/qdf_mem.h
+++ b/qdf/inc/qdf_mem.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-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
@@ -91,6 +91,13 @@
 
 #ifdef MEMORY_DEBUG
 /**
+ * qdf_mem_debug_config_get() - Get the user configuration of mem_debug_disabled
+ *
+ * Return: value of mem_debug_disabled qdf module argument
+ */
+bool qdf_mem_debug_config_get(void);
+
+/**
  * qdf_mem_malloc_debug() - debug version of QDF memory allocation API
  * @size: Number of bytes of memory to allocate.
  * @func: Function name of the call site
@@ -226,6 +233,10 @@
 	qdf_mem_free_consistent_debug(osdev, dev, size, vaddr, paddr, memctx, \
 				  __func__, __LINE__)
 #else
+static inline bool qdf_mem_debug_config_get(void)
+{
+	return false;
+}
 
 /**
  * qdf_mem_malloc() - allocation QDF memory
@@ -240,9 +251,10 @@
  * specified (for any reason) it returns NULL.
  */
 #define qdf_mem_malloc(size) \
-	qdf_mem_malloc_fl(size, __func__, __LINE__)
+	__qdf_mem_malloc(size, __func__, __LINE__)
 
-void *qdf_mem_malloc_fl(qdf_size_t size, const char *func, uint32_t line);
+#define qdf_mem_malloc_fl(size, func, line) \
+	__qdf_mem_malloc(size, func, line)
 
 /**
  * qdf_mem_malloc_atomic() - allocation QDF memory atomically
@@ -263,22 +275,16 @@
 			       const char *func,
 			       uint32_t line);
 
-/**
- * qdf_mem_free() - free QDF memory
- * @ptr: Pointer to the starting address of the memory to be freed.
- *
- * Return: None
- */
-void qdf_mem_free(void *ptr);
+#define qdf_mem_free(ptr) \
+	__qdf_mem_free(ptr)
 
 static inline void qdf_mem_check_for_leaks(void) { }
 
-void *qdf_mem_alloc_consistent(qdf_device_t osdev, void *dev,
-			       qdf_size_t size, qdf_dma_addr_t *paddr);
+#define qdf_mem_alloc_consistent(osdev, dev, size, paddr) \
+	__qdf_mem_alloc_consistent(osdev, dev, size, paddr, __func__, __LINE__)
 
-void qdf_mem_free_consistent(qdf_device_t osdev, void *dev,
-			     qdf_size_t size, void *vaddr,
-			     qdf_dma_addr_t paddr, qdf_dma_context_t memctx);
+#define qdf_mem_free_consistent(osdev, dev, size, vaddr, paddr, memctx) \
+	__qdf_mem_free_consistent(osdev, dev, size, vaddr, paddr, memctx)
 
 void qdf_mem_multi_pages_alloc(qdf_device_t osdev,
 			       struct qdf_mem_multi_page_t *pages,
diff --git a/qdf/inc/qdf_types.h b/qdf/inc/qdf_types.h
index d160847..2e159fc 100644
--- a/qdf/inc/qdf_types.h
+++ b/qdf/inc/qdf_types.h
@@ -377,6 +377,7 @@
  * @QDF_MODULE_ID_BLACKLIST_MGR: Blacklist Manager module
  * @QDF_MODULE_ID_QLD: QCA Live Debug module ID
  * @QDF_MODULE_ID_DYNAMIC_MODE_CHG: Dynamic mode change module ID
+ * @QDF_MODULE_ID_COEX: Coex related config module ID
  * @QDF_MODULE_ID_ANY: anything
  * @QDF_MODULE_ID_MAX: Max place holder module ID
  */
@@ -495,6 +496,7 @@
 	QDF_MODULE_ID_BLACKLIST_MGR,
 	QDF_MODULE_ID_QLD,
 	QDF_MODULE_ID_DYNAMIC_MODE_CHG,
+	QDF_MODULE_ID_COEX,
 	QDF_MODULE_ID_ANY,
 	QDF_MODULE_ID_MAX,
 } QDF_MODULE_ID;
diff --git a/qdf/linux/src/i_qdf_mem.h b/qdf/linux/src/i_qdf_mem.h
index c7ffdca..7843f07 100644
--- a/qdf/linux/src/i_qdf_mem.h
+++ b/qdf/linux/src/i_qdf_mem.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-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
@@ -100,6 +100,16 @@
 
 #define __qdf_align(a, mask) ALIGN(a, mask)
 
+#ifdef DISABLE_MEMDEBUG_PANIC
+#define QDF_MEMDEBUG_PANIC(reason_fmt, args...) \
+	do { \
+		/* no-op */ \
+	} while (false)
+#else
+#define QDF_MEMDEBUG_PANIC(reason_fmt, args...) \
+	QDF_DEBUG_PANIC(reason_fmt, ## args)
+#endif
+
 /* typedef for dma_data_direction */
 typedef enum dma_data_direction __dma_data_direction;
 
@@ -440,4 +450,61 @@
 {
 	mem_info->pa = dma_pa;
 }
+
+/**
+ * __qdf_mem_alloc_consistent() - allocates consistent qdf memory
+ * @osdev: OS device handle
+ * @dev: Pointer to device handle
+ * @size: Size to be allocated
+ * @paddr: Physical address
+ * @func: Function name of the call site
+ * @line: line numbe rof the call site
+ *
+ * Return: pointer of allocated memory or null if memory alloc fails
+ */
+void *__qdf_mem_alloc_consistent(qdf_device_t osdev, void *dev,
+				 qdf_size_t size, qdf_dma_addr_t *paddr,
+				 const char *func, uint32_t line);
+
+/**
+ * __qdf_mem_malloc() - allocates QDF memory
+ * @size: Number of bytes of memory to allocate.
+ *
+ * @func: Function name of the call site
+ * @line: line numbe rof the call site
+ *
+ * This function will dynamicallly allocate the specified number of bytes of
+ * memory.
+ *
+ * Return:
+ * Upon successful allocate, returns a non-NULL pointer to the allocated
+ * memory.  If this function is unable to allocate the amount of memory
+ * specified (for any reason) it returns NULL.
+ */
+void *__qdf_mem_malloc(qdf_size_t size, const char *func, uint32_t line);
+
+/**
+ * __qdf_mem_free() - free QDF memory
+ * @ptr: Pointer to the starting address of the memory to be freed.
+ *
+ * This function will free the memory pointed to by 'ptr'.
+ * Return: None
+ */
+void __qdf_mem_free(void *ptr);
+
+/**
+ * __qdf_mem_free_consistent() - free consistent qdf memory
+ * @osdev: OS device handle
+ * @dev: Pointer to device handle
+ * @size: Size to be allocated
+ * @vaddr: virtual address
+ * @paddr: Physical address
+ * @memctx: Pointer to DMA context
+ *
+ * Return: none
+ */
+void __qdf_mem_free_consistent(qdf_device_t osdev, void *dev,
+			       qdf_size_t size, void *vaddr,
+			       qdf_dma_addr_t paddr, qdf_dma_context_t memctx);
+
 #endif /* __I_QDF_MEM_H */
diff --git a/qdf/linux/src/qdf_mem.c b/qdf/linux/src/qdf_mem.c
index 33ec0fa..ea14a27 100644
--- a/qdf/linux/src/qdf_mem.c
+++ b/qdf/linux/src/qdf_mem.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-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
@@ -43,6 +43,13 @@
 #include <net/cnss_prealloc.h>
 #endif
 
+#if defined(MEMORY_DEBUG) || defined(NBUF_MEMORY_DEBUG)
+static bool mem_debug_disabled;
+qdf_declare_param(mem_debug_disabled, bool);
+qdf_export_symbol(mem_debug_disabled);
+static bool is_initial_mem_debug_disabled;
+#endif
+
 /* Preprocessor Definitions and Constants */
 #define QDF_MEM_MAX_MALLOC (4096 * 1024) /* 4 Mega Bytes */
 #define QDF_MEM_WARN_THRESHOLD 300 /* ms */
@@ -52,6 +59,39 @@
 #include "qdf_debug_domain.h"
 #include <qdf_list.h>
 
+enum list_type {
+	LIST_TYPE_MEM = 0,
+	LIST_TYPE_DMA = 1,
+	LIST_TYPE_MAX,
+};
+
+/**
+ * major_alloc_priv: private data registered to debugfs entry created to list
+ *                   the list major allocations
+ * @type:            type of the list to be parsed
+ * @threshold:       configured by user by overwriting the respective debugfs
+ *                   sys entry. This is to list the functions which requested
+ *                   memory/dma allocations more than threshold nubmer of times.
+ */
+struct major_alloc_priv {
+	enum list_type type;
+	uint32_t threshold;
+};
+
+static struct major_alloc_priv mem_priv = {
+	/* List type set to mem */
+	LIST_TYPE_MEM,
+	/* initial threshold to list APIs which allocates mem >= 50 times */
+	50
+};
+
+static struct major_alloc_priv dma_priv = {
+	/* List type set to DMA */
+	LIST_TYPE_DMA,
+	/* initial threshold to list APIs which allocates dma >= 50 times */
+	50
+};
+
 static qdf_list_t qdf_mem_domains[QDF_DEBUG_DOMAIN_COUNT];
 static qdf_spinlock_t qdf_mem_list_lock;
 
@@ -241,7 +281,7 @@
 			qdf_debug_domain_name(header->domain), header->domain,
 			qdf_debug_domain_name(current_domain), current_domain);
 
-	QDF_DEBUG_PANIC("Fatal memory error detected @ %s:%d", func, line);
+	QDF_MEMDEBUG_PANIC("Fatal memory error detected @ %s:%d", func, line);
 }
 #endif /* MEMORY_DEBUG */
 
@@ -346,15 +386,20 @@
 #define QDF_MEM_STAT_TABLE_SIZE 8
 
 /**
- * qdf_mem_domain_print_header() - memory domain header print logic
+ * qdf_mem_debug_print_header() - memory debug header print logic
  * @print: the print adapter function
  * @print_priv: the private data to be consumed by @print
+ * @threshold: the threshold value set by user to list top allocations
  *
  * Return: None
  */
-static void qdf_mem_domain_print_header(qdf_abstract_print print,
-					void *print_priv)
+static void qdf_mem_debug_print_header(qdf_abstract_print print,
+				       void *print_priv,
+				       uint32_t threshold)
 {
+	if (threshold)
+		print(print_priv, "APIs requested allocations >= %u no of time",
+		      threshold);
 	print(print_priv,
 	      "--------------------------------------------------------------");
 	print(print_priv,
@@ -368,12 +413,14 @@
  * @table: the memory metadata table to print
  * @print: the print adapter function
  * @print_priv: the private data to be consumed by @print
+ * @threshold: the threshold value set by user to list top allocations
  *
  * Return: None
  */
 static void qdf_mem_meta_table_print(struct __qdf_mem_info *table,
 				     qdf_abstract_print print,
-				     void *print_priv)
+				     void *print_priv,
+				     uint32_t threshold)
 {
 	int i;
 	char debug_str[QDF_DEBUG_STRING_SIZE];
@@ -406,6 +453,37 @@
 }
 
 /**
+ * qdf_print_major_alloc() - memory metadata table print logic
+ * @table: the memory metadata table to print
+ * @print: the print adapter function
+ * @print_priv: the private data to be consumed by @print
+ * @threshold: the threshold value set by uset to list top allocations
+ *
+ * Return: None
+ */
+static void qdf_print_major_alloc(struct __qdf_mem_info *table,
+				  qdf_abstract_print print,
+				  void *print_priv,
+				  uint32_t threshold)
+{
+	int i;
+
+	for (i = 0; i < QDF_MEM_STAT_TABLE_SIZE; i++) {
+		if (!table[i].count)
+			break;
+		if (table[i].count >= threshold)
+			print(print_priv,
+			      "%6u x %5u = %7uB @ %s:%u   %pS %llu",
+			      table[i].count,
+			      table[i].size,
+			      table[i].count * table[i].size,
+			      table[i].func,
+			      table[i].line, table[i].caller,
+			      table[i].time);
+	}
+}
+
+/**
  * qdf_mem_meta_table_insert() - insert memory metadata into the given table
  * @table: the memory metadata table to insert into
  * @meta: the memory metadata to insert
@@ -447,19 +525,25 @@
  * @domain: the memory domain to print
  * @print: the print adapter function
  * @print_priv: the private data to be consumed by @print
+ * @threshold: the threshold value set by uset to list top allocations
+ * @mem_print: pointer to function which prints the memory allocation data
  *
  * Return: None
  */
 static void qdf_mem_domain_print(qdf_list_t *domain,
 				 qdf_abstract_print print,
-				 void *print_priv)
+				 void *print_priv,
+				 uint32_t threshold,
+				 void (*mem_print)(struct __qdf_mem_info *,
+						   qdf_abstract_print,
+						   void *, uint32_t))
 {
 	QDF_STATUS status;
 	struct __qdf_mem_info table[QDF_MEM_STAT_TABLE_SIZE];
 	qdf_list_node_t *node;
 
 	qdf_mem_zero(table, sizeof(table));
-	qdf_mem_domain_print_header(print, print_priv);
+	qdf_mem_debug_print_header(print, print_priv, threshold);
 
 	/* hold lock while inserting to avoid use-after free of the metadata */
 	qdf_spin_lock(&qdf_mem_list_lock);
@@ -471,7 +555,7 @@
 		qdf_spin_unlock(&qdf_mem_list_lock);
 
 		if (is_full) {
-			qdf_mem_meta_table_print(table, print, print_priv);
+			(*mem_print)(table, print, print_priv, threshold);
 			qdf_mem_zero(table, sizeof(table));
 		}
 
@@ -480,7 +564,7 @@
 	}
 	qdf_spin_unlock(&qdf_mem_list_lock);
 
-	qdf_mem_meta_table_print(table, print, print_priv);
+	(*mem_print)(table, print, print_priv, threshold);
 }
 
 /**
@@ -541,7 +625,10 @@
 	seq_printf(seq, "\n%s Memory Domain (Id %d)\n",
 		   qdf_debug_domain_name(domain_id), domain_id);
 	qdf_mem_domain_print(qdf_mem_list_get(domain_id),
-			     seq_printf_printer, seq);
+			     seq_printf_printer,
+			     seq,
+			     0,
+			     qdf_mem_meta_table_print);
 
 	return 0;
 }
@@ -560,6 +647,99 @@
 	return seq_open(file, &qdf_mem_seq_ops);
 }
 
+/**
+ * qdf_major_alloc_show() - print sequential callback
+ * @seq: seq_file handle
+ * @v: current iterator
+ *
+ * Return: 0 - success
+ */
+static int qdf_major_alloc_show(struct seq_file *seq, void *v)
+{
+	enum qdf_debug_domain domain_id = *(enum qdf_debug_domain *)v;
+	struct major_alloc_priv *priv;
+	qdf_list_t *list;
+
+	priv = (struct major_alloc_priv *)seq->private;
+	seq_printf(seq, "\n%s Memory Domain (Id %d)\n",
+		   qdf_debug_domain_name(domain_id), domain_id);
+
+	switch (priv->type) {
+	case LIST_TYPE_MEM:
+		list = qdf_mem_list_get(domain_id);
+		break;
+	case LIST_TYPE_DMA:
+		list = qdf_mem_dma_list(domain_id);
+		break;
+	default:
+		list = NULL;
+		break;
+	}
+
+	if (list)
+		qdf_mem_domain_print(list,
+				     seq_printf_printer,
+				     seq,
+				     priv->threshold,
+				     qdf_print_major_alloc);
+
+	return 0;
+}
+
+/* sequential file operation table created to track major allocs */
+static const struct seq_operations qdf_major_allocs_seq_ops = {
+	.start = qdf_mem_seq_start,
+	.next = qdf_mem_seq_next,
+	.stop = qdf_mem_seq_stop,
+	.show = qdf_major_alloc_show,
+};
+
+static int qdf_major_allocs_open(struct inode *inode, struct file *file)
+{
+	void *private = inode->i_private;
+	struct seq_file *seq;
+	int rc;
+
+	rc = seq_open(file, &qdf_major_allocs_seq_ops);
+	if (rc == 0) {
+		seq = file->private_data;
+		seq->private = private;
+	}
+	return rc;
+}
+
+static ssize_t qdf_major_alloc_set_threshold(struct file *file,
+					     const char __user *user_buf,
+					     size_t count,
+					     loff_t *pos)
+{
+	char buf[32];
+	ssize_t buf_size;
+	uint32_t threshold;
+	struct seq_file *seq = file->private_data;
+	struct major_alloc_priv *priv = (struct major_alloc_priv *)seq->private;
+
+	buf_size = min(count, (sizeof(buf) - 1));
+	if (buf_size <= 0)
+		return 0;
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	buf[buf_size] = '\0';
+	if (!kstrtou32(buf, 10, &threshold))
+		priv->threshold = threshold;
+	return buf_size;
+}
+
+/* file operation table for listing major allocs */
+static const struct file_operations fops_qdf_major_allocs = {
+	.owner = THIS_MODULE,
+	.open = qdf_major_allocs_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+	.write = qdf_major_alloc_set_threshold,
+};
+
 /* debugfs file operation table */
 static const struct file_operations fops_qdf_mem_debugfs = {
 	.owner = THIS_MODULE,
@@ -571,6 +751,9 @@
 
 static QDF_STATUS qdf_mem_debug_debugfs_init(void)
 {
+	if (is_initial_mem_debug_disabled)
+		return QDF_STATUS_SUCCESS;
+
 	if (!qdf_mem_debugfs_root)
 		return QDF_STATUS_E_FAILURE;
 
@@ -580,6 +763,18 @@
 			    NULL,
 			    &fops_qdf_mem_debugfs);
 
+	debugfs_create_file("major_mem_allocs",
+			    0600,
+			    qdf_mem_debugfs_root,
+			    &mem_priv,
+			    &fops_qdf_major_allocs);
+
+	debugfs_create_file("major_dma_allocs",
+			    0600,
+			    qdf_mem_debugfs_root,
+			    &dma_priv,
+			    &fops_qdf_major_allocs);
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -893,6 +1088,15 @@
 
 /* External Function implementation */
 #ifdef MEMORY_DEBUG
+/**
+ * qdf_mem_debug_config_get() - Get the user configuration of mem_debug_disabled
+ *
+ * Return: value of mem_debug_disabled qdf module argument
+ */
+bool qdf_mem_debug_config_get(void)
+{
+	return mem_debug_disabled;
+}
 
 /**
  * qdf_mem_debug_init() - initialize qdf memory debug functionality
@@ -903,6 +1107,11 @@
 {
 	int i;
 
+	is_initial_mem_debug_disabled = qdf_mem_debug_config_get();
+
+	if (is_initial_mem_debug_disabled)
+		return;
+
 	/* Initalizing the list with maximum size of 60000 */
 	for (i = 0; i < QDF_DEBUG_DOMAIN_COUNT; ++i)
 		qdf_list_create(&qdf_mem_domains[i], 60000);
@@ -918,12 +1127,19 @@
 qdf_mem_domain_check_for_leaks(enum qdf_debug_domain domain,
 			       qdf_list_t *mem_list)
 {
+	if (is_initial_mem_debug_disabled)
+		return 0;
+
 	if (qdf_list_empty(mem_list))
 		return 0;
 
 	qdf_err("Memory leaks detected in %s domain!",
 		qdf_debug_domain_name(domain));
-	qdf_mem_domain_print(mem_list, qdf_err_printer, NULL);
+	qdf_mem_domain_print(mem_list,
+			     qdf_err_printer,
+			     NULL,
+			     0,
+			     qdf_mem_meta_table_print);
 
 	return mem_list->count;
 }
@@ -933,13 +1149,16 @@
 	uint32_t leak_count = 0;
 	int i;
 
+	if (is_initial_mem_debug_disabled)
+		return;
+
 	/* detect and print leaks */
 	for (i = 0; i < QDF_DEBUG_DOMAIN_COUNT; ++i)
 		leak_count += qdf_mem_domain_check_for_leaks(i, domains + i);
 
 	if (leak_count)
-		QDF_DEBUG_PANIC("%u fatal memory leaks detected!",
-				leak_count);
+		QDF_MEMDEBUG_PANIC("%u fatal memory leaks detected!",
+				   leak_count);
 }
 
 /**
@@ -951,6 +1170,9 @@
 {
 	int i;
 
+	if (is_initial_mem_debug_disabled)
+		return;
+
 	/* mem */
 	qdf_mem_domain_set_check_for_leaks(qdf_mem_domains);
 	for (i = 0; i < QDF_DEBUG_DOMAIN_COUNT; ++i)
@@ -975,6 +1197,9 @@
 	void *ptr;
 	unsigned long start, duration;
 
+	if (is_initial_mem_debug_disabled)
+		return __qdf_mem_malloc(size, func, line);
+
 	if (!size || size > QDF_MEM_MAX_MALLOC) {
 		qdf_err("Cannot malloc %zu bytes @ %s:%d", size, func, line);
 		return NULL;
@@ -1022,6 +1247,11 @@
 	struct qdf_mem_header *header;
 	enum qdf_mem_validation_bitmap error_bitmap;
 
+	if (is_initial_mem_debug_disabled) {
+		__qdf_mem_free(ptr);
+		return;
+	}
+
 	/* freeing a null pointer is valid */
 	if (qdf_unlikely(!ptr))
 		return;
@@ -1030,8 +1260,8 @@
 		return;
 
 	if (qdf_unlikely((qdf_size_t)ptr <= sizeof(*header)))
-		QDF_DEBUG_PANIC("Failed to free invalid memory location %pK",
-				ptr);
+		QDF_MEMDEBUG_PANIC("Failed to free invalid memory location %pK",
+				   ptr);
 
 	qdf_talloc_assert_no_children_fl(ptr, func, line);
 
@@ -1062,12 +1292,15 @@
 	qdf_list_t *dma_list = qdf_mem_dma_list(current_domain);
 	uint32_t leaks_count = 0;
 
+	if (is_initial_mem_debug_disabled)
+		return;
+
 	leaks_count += qdf_mem_domain_check_for_leaks(current_domain, mem_list);
 	leaks_count += qdf_mem_domain_check_for_leaks(current_domain, dma_list);
 
 	if (leaks_count)
-		QDF_DEBUG_PANIC("%u fatal memory leaks detected!",
-				leaks_count);
+		QDF_MEMDEBUG_PANIC("%u fatal memory leaks detected!",
+				   leaks_count);
 }
 
 /**
@@ -1232,33 +1465,6 @@
 
 static void qdf_mem_debug_exit(void) {}
 
-void *qdf_mem_malloc_fl(size_t size, const char *func, uint32_t line)
-{
-	void *ptr;
-
-	if (!size || size > QDF_MEM_MAX_MALLOC) {
-		qdf_nofl_err("Cannot malloc %zu bytes @ %s:%d", size, func,
-			     line);
-		return NULL;
-	}
-
-	ptr = qdf_mem_prealloc_get(size);
-	if (ptr)
-		return ptr;
-
-	ptr = kzalloc(size, qdf_mem_malloc_flags());
-	if (!ptr) {
-		qdf_nofl_err("Failed to malloc %zuB @ %s:%d",
-			     size, func, line);
-		return NULL;
-	}
-
-	qdf_mem_kmalloc_inc(ksize(ptr));
-
-	return ptr;
-}
-qdf_export_symbol(qdf_mem_malloc_fl);
-
 void *qdf_mem_malloc_atomic_fl(size_t size, const char *func, uint32_t line)
 {
 	void *ptr;
@@ -1281,29 +1487,6 @@
 qdf_export_symbol(qdf_mem_malloc_atomic_fl);
 
 /**
- * qdf_mem_free() - free QDF memory
- * @ptr: Pointer to the starting address of the memory to be free'd.
- *
- * This function will free the memory pointed to by 'ptr'.
- *
- * Return: None
- */
-void qdf_mem_free(void *ptr)
-{
-	if (!ptr)
-		return;
-
-	if (qdf_mem_prealloc_put(ptr))
-		return;
-
-	qdf_mem_kmalloc_dec(ksize(ptr));
-
-	kfree(ptr);
-}
-
-qdf_export_symbol(qdf_mem_free);
-
-/**
  * qdf_mem_multi_pages_alloc() - allocate large size of kernel memory
  * @osdev: OS device handle pointer
  * @pages: Multi page information storage
@@ -1444,6 +1627,46 @@
 qdf_export_symbol(qdf_mem_multi_pages_free);
 #endif
 
+void __qdf_mem_free(void *ptr)
+{
+	if (!ptr)
+		return;
+
+	if (qdf_mem_prealloc_put(ptr))
+		return;
+
+	qdf_mem_kmalloc_dec(ksize(ptr));
+
+	kfree(ptr);
+}
+
+qdf_export_symbol(__qdf_mem_free);
+
+void *__qdf_mem_malloc(size_t size, const char *func, uint32_t line)
+{
+	void *ptr;
+
+	if (!size || size > QDF_MEM_MAX_MALLOC) {
+		qdf_nofl_err("Cannot malloc %zu bytes @ %s:%d", size, func,
+			     line);
+		return NULL;
+	}
+
+	ptr = qdf_mem_prealloc_get(size);
+	if (ptr)
+		return ptr;
+
+	ptr = kzalloc(size, qdf_mem_malloc_flags());
+	if (!ptr)
+		return NULL;
+
+	qdf_mem_kmalloc_inc(ksize(ptr));
+
+	return ptr;
+}
+
+qdf_export_symbol(__qdf_mem_malloc);
+
 void *qdf_aligned_malloc_fl(uint32_t *size,
 			    void **vaddr_unaligned,
 				qdf_dma_addr_t *paddr_unaligned,
@@ -1797,6 +2020,11 @@
 	struct qdf_mem_header *header;
 	void *vaddr;
 
+	if (is_initial_mem_debug_disabled)
+		return __qdf_mem_alloc_consistent(osdev, dev,
+						  size, paddr,
+						  func, line);
+
 	if (!size || size > QDF_MEM_MAX_MALLOC) {
 		qdf_err("Cannot malloc %zu bytes @ %s:%d", size, func, line);
 		return NULL;
@@ -1840,6 +2068,14 @@
 	struct qdf_mem_header *header;
 	enum qdf_mem_validation_bitmap error_bitmap;
 
+	if (is_initial_mem_debug_disabled) {
+		__qdf_mem_free_consistent(
+					  osdev, dev,
+					  size, vaddr,
+					  paddr, memctx);
+		return;
+	}
+
 	/* freeing a null pointer is valid */
 	if (qdf_unlikely(!vaddr))
 		return;
@@ -1867,31 +2103,39 @@
 	qdf_mem_dma_free(dev, size + QDF_DMA_MEM_DEBUG_SIZE, vaddr, paddr);
 }
 qdf_export_symbol(qdf_mem_free_consistent_debug);
+#endif /* MEMORY_DEBUG */
 
-#else
-
-void *qdf_mem_alloc_consistent(qdf_device_t osdev, void *dev,
-			       qdf_size_t size, qdf_dma_addr_t *paddr)
+void __qdf_mem_free_consistent(qdf_device_t osdev, void *dev,
+			       qdf_size_t size, void *vaddr,
+			       qdf_dma_addr_t paddr, qdf_dma_context_t memctx)
 {
-	void *vaddr = qdf_mem_dma_alloc(osdev, dev, size, paddr);
+	qdf_mem_dma_dec(size);
+	qdf_mem_dma_free(dev, size, vaddr, paddr);
+}
+
+qdf_export_symbol(__qdf_mem_free_consistent);
+
+void *__qdf_mem_alloc_consistent(qdf_device_t osdev, void *dev,
+				 qdf_size_t size, qdf_dma_addr_t *paddr,
+				 const char *func, uint32_t line)
+{
+	void *vaddr;
+
+	if (!size || size > QDF_MEM_MAX_MALLOC) {
+		qdf_nofl_err("Cannot malloc %zu bytes @ %s:%d",
+			     size, func, line);
+		return NULL;
+	}
+
+	vaddr = qdf_mem_dma_alloc(osdev, dev, size, paddr);
 
 	if (vaddr)
 		qdf_mem_dma_inc(size);
 
 	return vaddr;
 }
-qdf_export_symbol(qdf_mem_alloc_consistent);
 
-void qdf_mem_free_consistent(qdf_device_t osdev, void *dev,
-			     qdf_size_t size, void *vaddr,
-			     qdf_dma_addr_t paddr, qdf_dma_context_t memctx)
-{
-	qdf_mem_dma_dec(size);
-	qdf_mem_dma_free(dev, size, vaddr, paddr);
-}
-qdf_export_symbol(qdf_mem_free_consistent);
-
-#endif /* MEMORY_DEBUG */
+qdf_export_symbol(__qdf_mem_alloc_consistent);
 
 void *qdf_aligned_mem_alloc_consistent_fl(
 	qdf_device_t osdev, uint32_t *size,
diff --git a/qdf/linux/src/qdf_nbuf.c b/qdf/linux/src/qdf_nbuf.c
index 91f4586..923654a 100644
--- a/qdf/linux/src/qdf_nbuf.c
+++ b/qdf/linux/src/qdf_nbuf.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-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
@@ -113,6 +113,10 @@
 static qdf_atomic_t nbuf_count;
 #endif
 
+#if defined(NBUF_MEMORY_DEBUG)
+static bool is_initial_mem_debug_disabled;
+#endif
+
 /**
  * qdf_nbuf_tx_desc_count_display() - Displays the packet counter
  *
@@ -616,6 +620,9 @@
 {
 	QDF_STATUS status;
 
+	if (is_initial_mem_debug_disabled)
+		return QDF_STATUS_SUCCESS;
+
 	status = qdf_tracker_track(&qdf_nbuf_map_tracker, nbuf, func, line);
 	if (QDF_IS_STATUS_ERROR(status))
 		return status;
@@ -628,6 +635,9 @@
 static void
 qdf_nbuf_untrack_map(qdf_nbuf_t nbuf, const char *func, uint32_t line)
 {
+	if (is_initial_mem_debug_disabled)
+		return;
+
 	qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_UNMAP);
 	qdf_tracker_untrack(&qdf_nbuf_map_tracker, nbuf, func, line);
 }
@@ -784,8 +794,8 @@
 				&map_func, &map_line))
 		return;
 
-	QDF_DEBUG_PANIC("Nbuf freed @ %s:%u while mapped from %s:%u",
-			func, line, map_func, map_line);
+	QDF_MEMDEBUG_PANIC("Nbuf freed @ %s:%u while mapped from %s:%u",
+			   func, line, map_func, map_line);
 }
 #else
 static inline void qdf_nbuf_map_tracking_init(void)
@@ -2325,6 +2335,11 @@
 {
 	uint32_t i;
 
+	is_initial_mem_debug_disabled = qdf_mem_debug_config_get();
+
+	if (is_initial_mem_debug_disabled)
+		return;
+
 	qdf_atomic_set(&qdf_nbuf_history_index, -1);
 
 	qdf_nbuf_map_tracking_init();
@@ -2354,6 +2369,9 @@
 	QDF_NBUF_TRACK *p_node;
 	QDF_NBUF_TRACK *p_prev;
 
+	if (is_initial_mem_debug_disabled)
+		return;
+
 	for (i = 0; i < QDF_NET_BUF_TRACK_MAX_SIZE; i++) {
 		spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag);
 		p_node = gp_qdf_net_buf_track_tbl[i];
@@ -2433,6 +2451,9 @@
 	QDF_NBUF_TRACK *p_node;
 	QDF_NBUF_TRACK *new_node;
 
+	if (is_initial_mem_debug_disabled)
+		return;
+
 	new_node = qdf_nbuf_track_alloc();
 
 	i = qdf_net_buf_debug_hash(net_buf);
@@ -2473,6 +2494,9 @@
 	unsigned long irq_flag;
 	QDF_NBUF_TRACK *p_node;
 
+	if (is_initial_mem_debug_disabled)
+		return;
+
 	i = qdf_net_buf_debug_hash(net_buf);
 	spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag);
 
@@ -2502,6 +2526,9 @@
 	unsigned long irq_flag;
 	QDF_NBUF_TRACK *p_prev;
 
+	if (is_initial_mem_debug_disabled)
+		return;
+
 	i = qdf_net_buf_debug_hash(net_buf);
 	spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag);
 
@@ -2547,6 +2574,9 @@
 {
 	qdf_nbuf_t ext_list = qdf_nbuf_get_ext_list(net_buf);
 
+	if (is_initial_mem_debug_disabled)
+		return;
+
 	while (ext_list) {
 		/*
 		 * Take care to add if it is Jumbo packet connected using
@@ -2576,6 +2606,9 @@
 {
 	qdf_nbuf_t ext_list = qdf_nbuf_get_ext_list(net_buf);
 
+	if (is_initial_mem_debug_disabled)
+		return;
+
 	while (ext_list) {
 		/*
 		 * Take care to free if it is Jumbo packet connected using
@@ -2607,6 +2640,11 @@
 {
 	qdf_nbuf_t nbuf;
 
+	if (is_initial_mem_debug_disabled)
+		return __qdf_nbuf_alloc(osdev, size,
+					reserve, align,
+					prio, func, line);
+
 	nbuf = __qdf_nbuf_alloc(osdev, size, reserve, align, prio, func, line);
 
 	/* Store SKB in internal QDF tracking table */
@@ -2628,6 +2666,9 @@
 	if (qdf_unlikely(!nbuf))
 		return;
 
+	if (is_initial_mem_debug_disabled)
+		goto free_buf;
+
 	if (qdf_nbuf_get_users(nbuf) > 1)
 		goto free_buf;
 
@@ -2656,6 +2697,9 @@
 {
 	qdf_nbuf_t cloned_buf = __qdf_nbuf_clone(buf);
 
+	if (is_initial_mem_debug_disabled)
+		return cloned_buf;
+
 	if (qdf_unlikely(!cloned_buf))
 		return NULL;
 
@@ -2671,6 +2715,9 @@
 {
 	qdf_nbuf_t copied_buf = __qdf_nbuf_copy(buf);
 
+	if (is_initial_mem_debug_disabled)
+		return copied_buf;
+
 	if (qdf_unlikely(!copied_buf))
 		return NULL;
 
@@ -2691,6 +2738,9 @@
 	if (qdf_unlikely(!copied_buf))
 		return NULL;
 
+	if (is_initial_mem_debug_disabled)
+		return copied_buf;
+
 	/* Store SKB in internal QDF tracking table */
 	qdf_net_buf_debug_add_node(copied_buf, 0, func, line);
 	qdf_nbuf_history_add(copied_buf, func, line,
diff --git a/qdf/linux/src/qdf_trace.c b/qdf/linux/src/qdf_trace.c
index 332976d..b0252a9 100644
--- a/qdf/linux/src/qdf_trace.c
+++ b/qdf/linux/src/qdf_trace.c
@@ -2819,6 +2819,7 @@
 	[QDF_MODULE_ID_BLACKLIST_MGR] = {"blm"},
 	[QDF_MODULE_ID_QLD] = {"QLD"},
 	[QDF_MODULE_ID_DYNAMIC_MODE_CHG] = {"Dynamic Mode Change"},
+	[QDF_MODULE_ID_COEX] = {"COEX"},
 	[QDF_MODULE_ID_ANY] = {"ANY"},
 };
 qdf_export_symbol(g_qdf_category_name);
@@ -3279,6 +3280,7 @@
 		[QDF_MODULE_ID_BLACKLIST_MGR] = QDF_TRACE_LEVEL_NONE,
 		[QDF_MODULE_ID_QLD] = QDF_TRACE_LEVEL_ERROR,
 		[QDF_MODULE_ID_DYNAMIC_MODE_CHG] = QDF_TRACE_LEVEL_INFO,
+		[QDF_MODULE_ID_COEX] = QDF_TRACE_LEVEL_ERROR,
 		[QDF_MODULE_ID_ANY] = QDF_TRACE_LEVEL_INFO,
 	};
 
diff --git a/scheduler/inc/scheduler_core.h b/scheduler/inc/scheduler_core.h
index 680ac20..0fe8d48 100644
--- a/scheduler/inc/scheduler_core.h
+++ b/scheduler/inc/scheduler_core.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-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
@@ -95,11 +95,11 @@
  * @resume_sch_event: scheduler resume wait event
  * @sch_thread_lock: scheduler thread lock
  * @sch_last_qidx: scheduler last qidx allocation
+ * @watchdog_msg_type: 'type' of the current msg being processed
  * @hdd_callback: os if suspend callback
  * @legacy_wma_handler: legacy wma message handler
  * @legacy_sys_handler: legacy sys message handler
  * @watchdog_timer: timer for triggering a scheduler watchdog bite
- * @watchdog_msg_type: 'type' of the current msg being processed
  * @watchdog_callback: the callback of the current msg being processed
  */
 struct scheduler_ctx {
@@ -112,11 +112,11 @@
 	qdf_event_t resume_sch_event;
 	qdf_spinlock_t sch_thread_lock;
 	uint8_t sch_last_qidx;
+	uint16_t watchdog_msg_type;
 	hdd_suspend_callback hdd_callback;
 	scheduler_msg_process_fn_t legacy_wma_handler;
 	scheduler_msg_process_fn_t legacy_sys_handler;
 	qdf_timer_t watchdog_timer;
-	uint16_t watchdog_msg_type;
 	void *watchdog_callback;
 };
 
diff --git a/target_if/coex/inc/target_if_coex.h b/target_if/coex/inc/target_if_coex.h
new file mode 100644
index 0000000..d496efa
--- /dev/null
+++ b/target_if/coex/inc/target_if_coex.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 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 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.
+ */
+
+/**
+ * DOC: contains coex target if declarations
+ */
+#ifndef __TARGET_IF_COEX_H__
+#define __TARGET_IF_COEX_H__
+
+#include <target_if.h>
+
+/**
+ * target_if_coex_register_tx_ops() - Register coex target_if tx ops
+ * @tx_ops: pointer to target if tx ops
+ *
+ * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
+ */
+QDF_STATUS
+target_if_coex_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops);
+#endif
diff --git a/target_if/coex/src/target_if_coex.c b/target_if/coex/src/target_if_coex.c
new file mode 100644
index 0000000..6dd3c70
--- /dev/null
+++ b/target_if/coex/src/target_if_coex.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 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 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.
+ */
+
+/**
+ * DOC: contains coex target if functions
+ */
+#include <wlan_coex_main.h>
+#include <target_if_coex.h>
+
+static QDF_STATUS
+target_if_coex_config_send(struct wlan_objmgr_pdev *pdev,
+			   struct coex_config_params *param)
+{
+	wmi_unified_t pdev_wmi_handle;
+
+	pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
+	if (!pdev_wmi_handle) {
+		coex_err("Invalid PDEV WMI handle");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return wmi_unified_send_coex_config_cmd(pdev_wmi_handle, param);
+}
+
+QDF_STATUS
+target_if_coex_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
+{
+	struct wlan_lmac_if_coex_tx_ops *coex_ops;
+
+	if (!tx_ops) {
+		coex_err("target if tx ops is NULL!");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	coex_ops = &tx_ops->coex_ops;
+	coex_ops->coex_config_send = target_if_coex_config_send;
+
+	return QDF_STATUS_SUCCESS;
+}
diff --git a/target_if/core/src/target_if_main.c b/target_if/core/src/target_if_main.c
index f860f59..a37f721 100644
--- a/target_if/core/src/target_if_main.c
+++ b/target_if/core/src/target_if_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-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
@@ -80,6 +80,10 @@
 #endif
 #include <target_if_vdev_mgr_tx_ops.h>
 
+#ifdef FEATURE_COEX
+#include <target_if_coex.h>
+#endif
+
 static struct target_if_ctx *g_target_if_ctx;
 
 struct target_if_ctx *target_if_get_ctx()
@@ -338,6 +342,20 @@
 }
 #endif
 
+#ifdef FEATURE_COEX
+static QDF_STATUS
+target_if_coex_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops)
+{
+	return target_if_coex_register_tx_ops(tx_ops);
+}
+#else
+static inline QDF_STATUS
+target_if_coex_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 static void target_if_target_tx_ops_register(
 		struct wlan_lmac_if_tx_ops *tx_ops)
 {
@@ -441,6 +459,8 @@
 
 	target_if_vdev_mgr_tx_ops_register(tx_ops);
 
+	target_if_coex_tx_ops_register(tx_ops);
+
 	/* Converged UMAC components to register their TX-ops here */
 	return QDF_STATUS_SUCCESS;
 }
diff --git a/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.c b/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.c
index 47f9e0f..c266a74 100644
--- a/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.c
+++ b/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.c
@@ -354,6 +354,7 @@
 	struct wlan_objmgr_pdev *pdev, void *data)
 {
 	struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
+	struct direct_buf_rx_psoc_obj *dbr_psoc_obj;
 	struct wlan_objmgr_psoc *psoc;
 	uint8_t num_modules;
 	QDF_STATUS status;
@@ -372,13 +373,20 @@
 		return QDF_STATUS_E_INVAL;
 	}
 
+	dbr_psoc_obj =
+	wlan_objmgr_psoc_get_comp_private_obj(psoc,
+					      WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
+
+	if (!dbr_psoc_obj) {
+		direct_buf_rx_err("dir buf rx psoc object is null");
+		return QDF_STATUS_E_FAILURE;
+	}
+
 	dbr_pdev_obj = qdf_mem_malloc(sizeof(*dbr_pdev_obj));
 
 	if (!dbr_pdev_obj)
 		return QDF_STATUS_E_NOMEM;
 
-	direct_buf_rx_info("Dbr pdev obj %pK", dbr_pdev_obj);
-
 	status = wlan_objmgr_pdev_component_obj_attach(pdev,
 					WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
 					dbr_pdev_obj, QDF_STATUS_SUCCESS);
@@ -390,9 +398,13 @@
 		return status;
 	}
 
+	dbr_psoc_obj->dbr_pdev_obj[wlan_objmgr_pdev_get_pdev_id(pdev)] =
+								dbr_pdev_obj;
+
 	num_modules = get_num_dbr_modules_per_pdev(pdev);
-	direct_buf_rx_info("Number of modules = %d pdev %d", num_modules,
-			   wlan_objmgr_pdev_get_pdev_id(pdev));
+	direct_buf_rx_info("Number of modules = %d pdev %d DBR pdev obj %pK",
+			   num_modules, wlan_objmgr_pdev_get_pdev_id(pdev),
+			   dbr_pdev_obj);
 	dbr_pdev_obj->num_modules = num_modules;
 
 	if (!dbr_pdev_obj->num_modules) {
diff --git a/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.h b/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.h
index 2828b97..a06375f 100644
--- a/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.h
+++ b/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.h
@@ -210,10 +210,12 @@
  * struct direct_buf_rx_psoc_obj - Direct Buf RX psoc object struct
  * @hal_soc: Opaque HAL SOC handle
  * @osdev: QDF os device handle
+ * @dbr_pdev_objs: array of DBR pdev objects
  */
 struct direct_buf_rx_psoc_obj {
 	void *hal_soc;
 	qdf_device_t osdev;
+	struct direct_buf_rx_pdev_obj *dbr_pdev_obj[WLAN_UMAC_MAX_PDEVS];
 };
 
 /**
diff --git a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c
index 22793fd..ce97b1c 100644
--- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c
+++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-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
@@ -3193,7 +3193,7 @@
 	if (opmode == QDF_STA_MODE) {
 		peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_CRYPTO_ID);
 		if (!peer) {
-			crypto_err("peer NULL");
+			crypto_debug("peer NULL");
 			return QDF_STATUS_E_INVAL;
 		}
 	}
diff --git a/umac/cmn_services/inc/wlan_cmn.h b/umac/cmn_services/inc/wlan_cmn.h
index 42e516d..494a0c0 100644
--- a/umac/cmn_services/inc/wlan_cmn.h
+++ b/umac/cmn_services/inc/wlan_cmn.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-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
@@ -272,6 +272,7 @@
  * @WLAN_UMAC_COMP_FWOL           FW Offload
  * @WLAN_UMAC_COMP_INTEROP_ISSUES_AP       interop issues ap component
  * @WLAN_UMAC_COMP_BLACKLIST_MGR:      Blacklist mgr component
+ * @WLAN_UMAC_COMP_COEX:          Coex config component
  * @WLAN_UMAC_COMP_ID_MAX:        Maximum components in UMAC
  *
  * This id is static.
@@ -311,6 +312,7 @@
 	WLAN_UMAC_COMP_CFR                = 30,
 	WLAN_UMAC_COMP_INTEROP_ISSUES_AP  = 31,
 	WLAN_UMAC_COMP_BLACKLIST_MGR      = 32,
+	WLAN_UMAC_COMP_COEX               = 33,
 	WLAN_UMAC_COMP_ID_MAX,
 };
 
diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h
index 7c7cd8d..3ea38ae 100644
--- a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h
+++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-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
@@ -166,6 +166,8 @@
 #define WLAN_VDEV_FEXT_MAT                  0x20000000
 	/* VDEV is wired PSTA*/
 #define WLAN_VDEV_FEXT_WIRED_PSTA           0x40000000
+	/* Fils discovery on 6G SAP*/
+#define WLAN_VDEV_FEXT_FILS_DISC_6G_SAP     0x80000000
 
 /* VDEV OP flags  */
   /* if the vap destroyed by user */
@@ -253,11 +255,11 @@
  * struct wlan_channel - channel structure
  * @ch_freq:      Channel in Mhz.
  * @ch_ieee:      IEEE channel number.
- * @ch_flags:     Channel flags.
- * @ch_flagext:   Channel extension flags.
- * @ch_maxpower:  Maximum tx power in dBm.
  * @ch_freq_seg1: Channel Center frequeny for VHT80/160 and HE80/160.
  * @ch_freq_seg2: Second channel Center frequency applicable for 80+80MHz mode.
+ * @ch_maxpower:  Maximum tx power in dBm.
+ * @ch_flagext:   Channel extension flags.
+ * @ch_flags:     Channel flags.
  * @ch_cfreq1:    channel center frequency for primary
  * @ch_cfreq2:    channel center frequency for secondary
  * @ch_width:     Channel width.
@@ -266,11 +268,11 @@
 struct wlan_channel {
 	uint16_t     ch_freq;
 	uint8_t      ch_ieee;
-	uint64_t     ch_flags;
-	uint16_t     ch_flagext;
-	int8_t       ch_maxpower;
 	uint8_t      ch_freq_seg1;
 	uint8_t      ch_freq_seg2;
+	int8_t       ch_maxpower;
+	uint16_t     ch_flagext;
+	uint64_t     ch_flags;
 	uint32_t     ch_cfreq1;
 	uint32_t     ch_cfreq2;
 	enum phy_ch_width ch_width;
diff --git a/umac/coex/core/inc/wlan_coex_main.h b/umac/coex/core/inc/wlan_coex_main.h
new file mode 100644
index 0000000..22cde21
--- /dev/null
+++ b/umac/coex/core/inc/wlan_coex_main.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 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 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.
+ */
+
+/*
+ * DOC: contains declarations for coex core functions
+ */
+
+#ifndef _WLAN_COEX_MAIN_API_H_
+#define _WLAN_COEX_MAIN_API_H_
+
+#ifdef FEATURE_COEX
+#include "wlan_coex_ucfg_api.h"
+#include "wmi_unified_param.h"
+#include "wlan_objmgr_psoc_obj.h"
+#include "wlan_objmgr_vdev_obj.h"
+
+#define coex_err(params...) \
+	QDF_TRACE_ERROR(QDF_MODULE_ID_COEX, params)
+#define coex_info(params...) \
+	QDF_TRACE_INFO(QDF_MODULE_ID_COEX, params)
+#define coex_debug(params...) \
+	QDF_TRACE_DEBUG(QDF_MODULE_ID_COEX, params)
+
+/**
+ * struct coex_psoc_obj - coex object definition
+ * @btc_chain_mode: BT Coex chain mode.
+ * @coex_config_updated: callback functions for each config type, which will
+ *  be called when config is updated.
+ */
+struct coex_psoc_obj {
+	uint8_t btc_chain_mode;
+	update_coex_cb coex_config_updated[COEX_CONFIG_TYPE_MAX];
+};
+
+/**
+ * wlan_psoc_get_coex_obj() - private API to get coex object from psoc
+ * @psoc: psoc object
+ *
+ * Return: coex object
+ */
+#define wlan_psoc_get_coex_obj(psoc) \
+	wlan_psoc_get_coex_obj_fl(psoc, __func__, __LINE__)
+
+static inline struct coex_psoc_obj *
+wlan_psoc_get_coex_obj_fl(struct wlan_objmgr_psoc *psoc,
+			  const char *func, uint32_t line)
+{
+	struct coex_psoc_obj *psoc_obj;
+
+	psoc_obj = (struct coex_psoc_obj *)
+		wlan_objmgr_psoc_get_comp_private_obj(psoc,
+						      WLAN_UMAC_COMP_COEX);
+	if (!psoc_obj) {
+		coex_err("%s:%u, Failed to get coex psoc object", func, line);
+		return NULL;
+	}
+	return psoc_obj;
+}
+
+/**
+ * wlan_coex_psoc_init() - API to initialize coex component
+ * @psoc: soc context
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+wlan_coex_psoc_init(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * wlan_coex_psoc_deinit() - API to deinitialize coex component
+ * @psoc: soc context
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+wlan_coex_psoc_deinit(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * wlan_coex_config_send() - private API to send coex config
+ * @vdev: pointer to vdev object
+ * @param: parameters of coex config
+ *
+ * Return: status of operation
+ */
+QDF_STATUS wlan_coex_config_send(struct wlan_objmgr_vdev *vdev,
+				 struct coex_config_params *param);
+
+/**
+ * wlan_coex_config_updated() - private API to notify that coex config
+ * is updated.
+ * @vdev: pointer to vdev object
+ * @type: type of coex config
+ *
+ * Return: status of operation
+ */
+QDF_STATUS
+wlan_coex_config_updated(struct wlan_objmgr_vdev *vdev, uint8_t type);
+
+/**
+ * wlan_coex_psoc_created_notification() - PSOC obj create callback
+ * @psoc: PSOC object
+ * @arg_list: Variable argument list
+ *
+ * This callback is registered with object manager during initialization to
+ * get notified when the object is created.
+ *
+ * Return: Success or Failure
+ */
+QDF_STATUS wlan_coex_psoc_created_notification(struct wlan_objmgr_psoc *psoc,
+					       void *arg_list);
+
+/**
+ * wlan_coex_psoc_destroyed_notification() - PSOC obj delete callback
+ * @psoc: PSOC object
+ * @arg_list: Variable argument list
+ *
+ * This callback is registered with object manager during initialization to
+ * get notified when the object is deleted.
+ *
+ * Return: Success or Failure
+ */
+QDF_STATUS wlan_coex_psoc_destroyed_notification(struct wlan_objmgr_psoc *psoc,
+						 void *arg_list);
+
+/**
+ * wlan_coex_psoc_set_btc_chain_mode() - private API to set BT coex chain mode
+ * for psoc
+ * @psoc: pointer to psoc object
+ * @val: BT coex chain mode
+ *
+ * Return : status of operation
+ */
+QDF_STATUS
+wlan_coex_psoc_set_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t val);
+
+/**
+ * wlan_coex_psoc_get_btc_chain_mode() - private API to get BT coex chain mode
+ * from psoc
+ * @psoc: pointer to psoc object
+ * @val: pointer to BT coex chain mode
+ *
+ * Return : status of operation
+ */
+QDF_STATUS
+wlan_coex_psoc_get_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t *val);
+#endif
+#endif
diff --git a/umac/coex/core/src/wlan_coex_main.c b/umac/coex/core/src/wlan_coex_main.c
new file mode 100644
index 0000000..d48b6e5
--- /dev/null
+++ b/umac/coex/core/src/wlan_coex_main.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 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 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.
+ */
+
+/*
+ * DOC: contains definitions for coex core functions
+ */
+
+#include <wlan_coex_ucfg_api.h>
+#include <wlan_coex_tgt_api.h>
+#include <wlan_coex_main.h>
+
+QDF_STATUS wlan_coex_psoc_created_notification(struct wlan_objmgr_psoc *psoc,
+					       void *arg_list)
+{
+	struct coex_psoc_obj *psoc_obj;
+	QDF_STATUS status;
+
+	psoc_obj = qdf_mem_malloc(sizeof(*psoc_obj));
+	if (!psoc_obj)
+		return QDF_STATUS_E_NOMEM;
+
+	/* Attach scan private date to psoc */
+	status = wlan_objmgr_psoc_component_obj_attach(psoc,
+						       WLAN_UMAC_COMP_COEX,
+						       psoc_obj,
+						       QDF_STATUS_SUCCESS);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		coex_err("Failed to attach psoc coex component");
+		qdf_mem_free(psoc_obj);
+	} else {
+		coex_debug("Coex object attach to psoc successful");
+	}
+
+	return status;
+}
+
+QDF_STATUS wlan_coex_psoc_destroyed_notification(struct wlan_objmgr_psoc *psoc,
+						 void *arg_list)
+{
+	void *psoc_obj;
+	QDF_STATUS status;
+
+	psoc_obj = wlan_psoc_get_coex_obj(psoc);
+	if (!psoc_obj)
+		return QDF_STATUS_E_FAILURE;
+
+	status = wlan_objmgr_psoc_component_obj_detach(psoc,
+						       WLAN_UMAC_COMP_COEX,
+						       psoc_obj);
+	if (QDF_IS_STATUS_ERROR(status))
+		coex_err("Failed to detach psoc coex component");
+
+	qdf_mem_free(psoc_obj);
+
+	return status;
+}
+
+QDF_STATUS
+wlan_coex_psoc_init(struct wlan_objmgr_psoc *psoc)
+{
+	struct coex_psoc_obj *coex_obj;
+
+	coex_obj = wlan_psoc_get_coex_obj(psoc);
+	if (!coex_obj)
+		return QDF_STATUS_E_INVAL;
+
+	coex_obj->btc_chain_mode = WLAN_COEX_BTC_CHAIN_MODE_UNSETTLED;
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+wlan_coex_psoc_deinit(struct wlan_objmgr_psoc *psoc)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlan_coex_config_send(struct wlan_objmgr_vdev *vdev,
+				 struct coex_config_params *param)
+{
+	QDF_STATUS status;
+
+	status = tgt_send_coex_config(vdev, param);
+	if (QDF_IS_STATUS_ERROR(status))
+		coex_err("failed to send coex config");
+
+	return status;
+}
+
+QDF_STATUS
+wlan_coex_config_updated(struct wlan_objmgr_vdev *vdev, uint8_t type)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct coex_psoc_obj *coex_obj;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	if (!vdev) {
+		coex_err("NULL vdev");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (type >= COEX_CONFIG_TYPE_MAX) {
+		coex_err("config type out of range: %d", type);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	if (!psoc) {
+		coex_err("NULL psoc");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	coex_obj = wlan_psoc_get_coex_obj(psoc);
+	if (!coex_obj)
+		return QDF_STATUS_E_INVAL;
+
+	if (coex_obj->coex_config_updated[type])
+		status = coex_obj->coex_config_updated[type](vdev);
+
+	return status;
+}
+
+QDF_STATUS
+wlan_coex_psoc_set_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t val)
+{
+	struct coex_psoc_obj *coex_obj;
+
+	coex_obj = wlan_psoc_get_coex_obj(psoc);
+	if (!coex_obj)
+		return QDF_STATUS_E_INVAL;
+
+	coex_obj->btc_chain_mode = val;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+wlan_coex_psoc_get_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t *val)
+{
+	struct coex_psoc_obj *coex_obj;
+
+	if (!val) {
+		coex_err("invalid param for getting btc chain mode");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	coex_obj = wlan_psoc_get_coex_obj(psoc);
+	if (!coex_obj)
+		return QDF_STATUS_E_INVAL;
+
+	*val = coex_obj->btc_chain_mode;
+	return QDF_STATUS_SUCCESS;
+}
diff --git a/umac/coex/dispatcher/inc/wlan_coex_tgt_api.h b/umac/coex/dispatcher/inc/wlan_coex_tgt_api.h
new file mode 100644
index 0000000..452ce1b
--- /dev/null
+++ b/umac/coex/dispatcher/inc/wlan_coex_tgt_api.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 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 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.
+ */
+
+/*
+ * DOC: contains coex south bound interface definitions
+ */
+
+#ifndef _WLAN_COEX_TGT_API_H_
+#define _WLAN_COEX_TGT_API_H_
+
+#ifdef FEATURE_COEX
+struct coex_config_params;
+
+/**
+ * tgt_send_coex_config() - invoke target_if send coex config
+ * @vdev: vdev object
+ * @param: coex config parameters
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+tgt_send_coex_config(struct wlan_objmgr_vdev *vdev,
+		     struct coex_config_params *param);
+#endif
+#endif
diff --git a/umac/coex/dispatcher/inc/wlan_coex_ucfg_api.h b/umac/coex/dispatcher/inc/wlan_coex_ucfg_api.h
new file mode 100644
index 0000000..2fd5a24
--- /dev/null
+++ b/umac/coex/dispatcher/inc/wlan_coex_ucfg_api.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 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 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.
+ */
+
+/*
+ * DOC: contains coex north bound interface declarations
+ */
+
+#ifndef _WLAN_COEX_UCFG_API_H_
+#define _WLAN_COEX_UCFG_API_H_
+
+#include "qdf_status.h"
+#include <wlan_objmgr_vdev_obj.h>
+#include <wlan_objmgr_psoc_obj.h>
+#include "qca_vendor.h"
+
+#define WLAN_COEX_BTC_CHAIN_MODE_SHARED QCA_BTC_CHAIN_SHARED
+#define WLAN_COEX_BTC_CHAIN_MODE_SEPARATED QCA_BTC_CHAIN_SEPARATED
+#define WLAN_COEX_BTC_CHAIN_MODE_UNSETTLED 0xFF
+
+/**
+ * enum coex_config_type - coex config type definitions
+ * @COEX_CONFIG_BTC_CHAIN_MODE: config BT coex chain mode
+ * @COEX_CONFIG_TYPE_MAX: max value
+ */
+enum coex_config_type {
+	COEX_CONFIG_BTC_CHAIN_MODE,
+	/* keep last */
+	COEX_CONFIG_TYPE_MAX,
+};
+
+/**
+ * typedef update_coex_cb() - cb to inform coex config
+ * @vdev: vdev pointer
+ *
+ * Return: void
+ */
+typedef QDF_STATUS (*update_coex_cb)(struct wlan_objmgr_vdev *vdev);
+
+#ifdef FEATURE_COEX
+/**
+ * ucfg_coex_register_cfg_updated_handler() - API to register coex config
+ * updated handler.
+ * @psoc: pointer to psoc object
+ * @type: type of coex config
+ * @handler: handler to be registered
+ *
+ * Return: status of operation
+ */
+QDF_STATUS
+ucfg_coex_register_cfg_updated_handler(struct wlan_objmgr_psoc *psoc,
+				       enum coex_config_type type,
+				       update_coex_cb handler);
+
+/**
+ * ucfg_coex_psoc_set_btc_chain_mode() - API to set BT coex chain mode for psoc
+ * @psoc: pointer to psoc object
+ * @val: BT coex chain mode
+ *
+ * Return : status of operation
+ */
+QDF_STATUS
+ucfg_coex_psoc_set_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t val);
+
+/**
+ * ucfg_coex_psoc_get_btc_chain_mode() - API to get BT coex chain mode from psoc
+ * @psoc: pointer to psoc object
+ * @val: pointer to BT coex chain mode
+ *
+ * Return : status of operation
+ */
+QDF_STATUS
+ucfg_coex_psoc_get_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t *val);
+
+/**
+ * ucfg_coex_send_btc_chain_mode() - API to send BT coex config to target if
+ * @vdev: pointer to vdev object
+ * @mode: BT coex chain mode
+ *
+ * Return: status of operation
+ */
+QDF_STATUS
+ucfg_coex_send_btc_chain_mode(struct wlan_objmgr_vdev *vdev, uint8_t mode);
+#else
+static inline QDF_STATUS
+ucfg_coex_register_cfg_updated_handler(struct wlan_objmgr_psoc *psoc,
+				       enum coex_config_type type,
+				       update_coex_cb handler)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS
+ucfg_coex_psoc_get_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t *val)
+{
+	if (val)
+		*val = WLAN_COEX_BTC_CHAIN_MODE_UNSETTLED;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS
+ucfg_coex_send_btc_chain_mode(struct wlan_objmgr_vdev *vdev, uint8_t mode)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+#endif
diff --git a/umac/coex/dispatcher/inc/wlan_coex_utils_api.h b/umac/coex/dispatcher/inc/wlan_coex_utils_api.h
new file mode 100644
index 0000000..76bb68d
--- /dev/null
+++ b/umac/coex/dispatcher/inc/wlan_coex_utils_api.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 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 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.
+ */
+
+/**
+ * DOC: wlan_coex_utils_api.h
+ *
+ * This header file provides declaration of public APIs exposed to other UMAC
+ * components.
+ */
+
+#ifndef _WLAN_COEX_UTILS_API_H_
+#define _WLAN_COEX_UTILS_API_H_
+#include <wlan_objmgr_psoc_obj.h>
+
+/*
+ * wlan_coex_init() - Coex module initialization API
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_coex_init(void);
+
+/*
+ * wlan_coex_deinit() - Coex module deinitialization API
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_coex_deinit(void);
+
+/**
+ * wlan_coex_psoc_open() - Open coex component
+ * @psoc: soc context
+ *
+ * This function gets called when dispatcher opening.
+ *
+ * Return: QDF_STATUS_SUCCESS - in case of success
+ */
+QDF_STATUS
+wlan_coex_psoc_open(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * wlan_coex_psoc_close() - Close coex component
+ * @psoc: soc context
+ *
+ * This function gets called when dispatcher closing.
+ *
+ * Return: QDF_STATUS_SUCCESS - in case of success
+ */
+QDF_STATUS
+wlan_coex_psoc_close(struct wlan_objmgr_psoc *psoc);
+#endif
diff --git a/umac/coex/dispatcher/src/wlan_coex_tgt_api.c b/umac/coex/dispatcher/src/wlan_coex_tgt_api.c
new file mode 100644
index 0000000..4022a7c
--- /dev/null
+++ b/umac/coex/dispatcher/src/wlan_coex_tgt_api.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 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 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.
+ */
+
+/*
+ * DOC: contains coex south bound interface definitions
+ */
+
+#include <wlan_coex_main.h>
+#include <wlan_coex_tgt_api.h>
+#include <wlan_lmac_if_def.h>
+#include "wlan_objmgr_pdev_obj.h"
+
+static inline struct wlan_lmac_if_coex_tx_ops *
+wlan_psoc_get_coex_txops(struct wlan_objmgr_psoc *psoc)
+{
+	return &psoc->soc_cb.tx_ops.coex_ops;
+}
+
+static inline struct wlan_lmac_if_coex_tx_ops *
+wlan_vdev_get_coex_txops(struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_objmgr_psoc *psoc;
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	if (!psoc) {
+		coex_err("NULL psoc");
+		return NULL;
+	}
+
+	return wlan_psoc_get_coex_txops(psoc);
+}
+
+QDF_STATUS
+tgt_send_coex_config(struct wlan_objmgr_vdev *vdev,
+		     struct coex_config_params *param)
+{
+	struct wlan_lmac_if_coex_tx_ops *coex_ops;
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_objmgr_pdev *pdev;
+
+	if (!vdev) {
+		coex_err("NULL vdev");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	if (!psoc) {
+		coex_err("NULL psoc");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	pdev = wlan_vdev_get_pdev(vdev);
+	if (!pdev) {
+		coex_err("NULL pdev");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	coex_ops = wlan_psoc_get_coex_txops(psoc);
+	QDF_ASSERT(coex_ops->coex_config_send);
+	if (coex_ops->coex_config_send)
+		return coex_ops->coex_config_send(pdev, param);
+
+	return QDF_STATUS_SUCCESS;
+}
diff --git a/umac/coex/dispatcher/src/wlan_coex_ucfg_api.c b/umac/coex/dispatcher/src/wlan_coex_ucfg_api.c
new file mode 100644
index 0000000..68321ee
--- /dev/null
+++ b/umac/coex/dispatcher/src/wlan_coex_ucfg_api.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 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 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.
+ */
+
+/*
+ * DOC: contains coex north bound interface definitions
+ */
+
+#include <wlan_coex_main.h>
+#include <wlan_coex_ucfg_api.h>
+#include "wmi_unified.h"
+
+QDF_STATUS
+ucfg_coex_register_cfg_updated_handler(struct wlan_objmgr_psoc *psoc,
+				       enum coex_config_type type,
+				       update_coex_cb handler)
+{
+	struct coex_psoc_obj *coex_obj;
+
+	if (type >= COEX_CONFIG_TYPE_MAX) {
+		coex_err("invalid coex type: %d", type);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	coex_obj = wlan_psoc_get_coex_obj(psoc);
+	if (!coex_obj)
+		return QDF_STATUS_E_INVAL;
+
+	coex_obj->coex_config_updated[type] = handler;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+ucfg_coex_psoc_set_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t val)
+{
+	return wlan_coex_psoc_set_btc_chain_mode(psoc, val);
+}
+
+QDF_STATUS
+ucfg_coex_psoc_get_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t *val)
+{
+	return wlan_coex_psoc_get_btc_chain_mode(psoc, val);
+}
+
+QDF_STATUS
+ucfg_coex_send_btc_chain_mode(struct wlan_objmgr_vdev *vdev, uint8_t mode)
+{
+	struct coex_config_params param = {0};
+
+	if (mode != WLAN_COEX_BTC_CHAIN_MODE_SHARED &&
+	    mode != WLAN_COEX_BTC_CHAIN_MODE_SEPARATED)
+		return QDF_STATUS_E_INVAL;
+
+	param.vdev_id = wlan_vdev_get_id(vdev);
+	param.config_type = WMI_COEX_CONFIG_BTCOEX_SEPARATE_CHAIN_MODE;
+	param.config_arg1 = mode;
+
+	coex_debug("send btc chain mode %d for vdev %d", mode, param.vdev_id);
+
+	return wlan_coex_config_send(vdev, &param);
+}
diff --git a/umac/coex/dispatcher/src/wlan_coex_utils_api.c b/umac/coex/dispatcher/src/wlan_coex_utils_api.c
new file mode 100644
index 0000000..3217878
--- /dev/null
+++ b/umac/coex/dispatcher/src/wlan_coex_utils_api.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 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 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.
+ */
+
+/**
+ * DOC: wlan_coex_utils_api.c
+ *
+ * This file provides definitions of public APIs exposed to other UMAC
+ * components.
+ */
+
+#include <wlan_coex_main.h>
+#include <wlan_objmgr_global_obj.h>
+#include <wlan_coex_utils_api.h>
+
+QDF_STATUS wlan_coex_init(void)
+{
+	QDF_STATUS status;
+
+	status = wlan_objmgr_register_psoc_create_handler(
+			WLAN_UMAC_COMP_COEX,
+			wlan_coex_psoc_created_notification, NULL);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		coex_err("Failed to register psoc create handler");
+		goto fail_create_psoc;
+	}
+
+	status = wlan_objmgr_register_psoc_destroy_handler(
+			WLAN_UMAC_COMP_COEX,
+			wlan_coex_psoc_destroyed_notification, NULL);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		coex_err("Failed to create psoc delete handler");
+		goto fail_psoc_destroy;
+	}
+
+	coex_debug("coex psoc create and delete handler registered");
+	return status;
+
+fail_psoc_destroy:
+	wlan_objmgr_unregister_psoc_create_handler(
+			WLAN_UMAC_COMP_COEX,
+			wlan_coex_psoc_created_notification, NULL);
+fail_create_psoc:
+	return status;
+}
+
+QDF_STATUS wlan_coex_deinit(void)
+{
+	QDF_STATUS status;
+
+	status = wlan_objmgr_unregister_psoc_destroy_handler(
+			WLAN_UMAC_COMP_COEX,
+			wlan_coex_psoc_destroyed_notification, NULL);
+	if (status != QDF_STATUS_SUCCESS)
+		coex_err("Failed to unregister psoc delete handler");
+
+	status = wlan_objmgr_unregister_psoc_create_handler(
+			WLAN_UMAC_COMP_COEX,
+			wlan_coex_psoc_created_notification, NULL);
+	if (status != QDF_STATUS_SUCCESS)
+		coex_err("Failed to unregister psoc create handler");
+
+	return status;
+}
+
+QDF_STATUS
+wlan_coex_psoc_open(struct wlan_objmgr_psoc *psoc)
+{
+	return wlan_coex_psoc_init(psoc);
+}
+
+QDF_STATUS
+wlan_coex_psoc_close(struct wlan_objmgr_psoc *psoc)
+{
+	return wlan_coex_psoc_deinit(psoc);
+}
diff --git a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h
index 2e8c7a8..15cf260 100644
--- a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h
+++ b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
@@ -912,6 +912,19 @@
 };
 #endif
 
+#ifdef FEATURE_COEX
+struct coex_config_params;
+
+/**
+ * struct wlan_lmac_if_coex_tx_ops - south bound tx function pointers for coex
+ * @coex_config_send: function pointer to send coex config to fw
+ */
+struct wlan_lmac_if_coex_tx_ops {
+	QDF_STATUS (*coex_config_send)(struct wlan_objmgr_pdev *pdev,
+				       struct coex_config_params *param);
+};
+#endif
+
 /**
  * struct wlan_lmac_if_tx_ops - south bound tx function pointers
  * @mgmt_txrx_tx_ops: mgmt txrx tx ops
@@ -919,9 +932,10 @@
  * @dfs_tx_ops: dfs tx ops.
  * @green_ap_tx_ops: green_ap tx_ops
  * @cp_stats_tx_ops: cp stats tx_ops
+ * @coex_ops: coex tx_ops
  *
  * Callback function tabled to be registered with umac.
- * umac will use the functional table to send events/frames to lmac/wmi
+ * umac will use the functional table to send events/frames to wmi
  */
 
 struct wlan_lmac_if_tx_ops {
@@ -990,6 +1004,10 @@
 #endif
 
 	struct wlan_lmac_if_ftm_tx_ops ftm_tx_ops;
+
+#ifdef FEATURE_COEX
+	struct wlan_lmac_if_coex_tx_ops coex_ops;
+#endif
 };
 
 /**
diff --git a/umac/mlme/vdev_mgr/core/src/vdev_mgr_ops.c b/umac/mlme/vdev_mgr/core/src/vdev_mgr_ops.c
index bc5912c..e4bac19 100644
--- a/umac/mlme/vdev_mgr/core/src/vdev_mgr_ops.c
+++ b/umac/mlme/vdev_mgr/core/src/vdev_mgr_ops.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-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
@@ -344,6 +344,7 @@
 	enum QDF_OPMODE opmode;
 	struct wlan_objmgr_vdev *vdev;
 	struct config_fils_params fils_param = {0};
+	uint8_t is_6g_sap_fd_enabled;
 
 	if (!mlme_obj) {
 		mlme_err("VDEV_MLME is NULL");
@@ -374,7 +375,11 @@
 	if (QDF_IS_STATUS_ERROR(status))
 		return status;
 
+	is_6g_sap_fd_enabled = wlan_vdev_mlme_feat_ext_cap_get(vdev,
+					WLAN_VDEV_FEXT_FILS_DISC_6G_SAP);
+	mlme_debug("SAP FD enabled %d", is_6g_sap_fd_enabled);
 	if (opmode == QDF_SAP_MODE && mlme_obj->vdev->vdev_mlme.des_chan &&
+	    is_6g_sap_fd_enabled &&
 	    WLAN_REG_IS_6GHZ_CHAN_FREQ(
 			mlme_obj->vdev->vdev_mlme.des_chan->ch_freq)) {
 		fils_param.vdev_id = wlan_vdev_get_id(mlme_obj->vdev);
diff --git a/umac/regulatory/core/src/reg_opclass.c b/umac/regulatory/core/src/reg_opclass.c
index d856f13..79505ce 100644
--- a/umac/regulatory/core/src/reg_opclass.c
+++ b/umac/regulatory/core/src/reg_opclass.c
@@ -590,8 +590,8 @@
 				     op_class_tbl->channels[i]); i++) {
 				if (op_class_tbl->channels[i] == chan) {
 					chan = op_class_tbl->channels[i];
-					return (op_class_tbl->start_freq +
-						(chan * FREQ_TO_CHAN_SCALE));
+					return op_class_tbl->start_freq +
+						(chan * FREQ_TO_CHAN_SCALE);
 				}
 			}
 			reg_err_rl("Channel not found");
@@ -602,4 +602,122 @@
 	reg_err_rl("Invalid opclass given as input");
 	return 0;
 }
+
+static void
+reg_get_op_class_tbl_by_chan_map(const struct
+				 reg_dmn_op_class_map_t **op_class_tbl)
+{
+	if (channel_map == channel_map_us)
+		*op_class_tbl = us_op_class;
+	else if (channel_map == channel_map_eu)
+		*op_class_tbl = euro_op_class;
+	else if (channel_map == channel_map_china)
+		*op_class_tbl = us_op_class;
+	else if (channel_map == channel_map_jp)
+		*op_class_tbl = japan_op_class;
+	else
+		*op_class_tbl = global_op_class;
+}
+
+/**
+ * reg_get_channels_from_opclassmap()- Get channels from the opclass map
+ * @pdev: Pointer to pdev
+ * @reg_ap_cap: Pointer to reg_ap_cap
+ * @index: Pointer to index of reg_ap_cap
+ * @op_class_tbl: Pointer to op_class_tbl
+ * @is_opclass_operable: Set true if opclass is operable, else set false
+ *
+ * Populate channels from opclass map to reg_ap_cap as supported and
+ * non-supported channels.
+ *
+ * Return: void.
+ */
+static void
+reg_get_channels_from_opclassmap(
+		struct wlan_objmgr_pdev *pdev,
+		struct regdmn_ap_cap_opclass_t *reg_ap_cap,
+		uint8_t index,
+		const struct reg_dmn_op_class_map_t *op_class_tbl,
+		bool *is_opclass_operable)
+{
+	uint8_t op_cls_chan;
+	qdf_freq_t search_freq;
+	bool is_freq_present;
+	uint8_t chan_idx = 0, n_sup_chans = 0, n_unsup_chans = 0;
+
+	while (op_class_tbl->channels[chan_idx]) {
+		op_cls_chan = op_class_tbl->channels[chan_idx];
+		search_freq = op_class_tbl->start_freq +
+					(FREQ_TO_CHAN_SCALE * op_cls_chan);
+		is_freq_present =
+			reg_is_freq_present_in_cur_chan_list(pdev, search_freq);
+
+		if (!is_freq_present) {
+			reg_ap_cap[index].
+					non_sup_chan_list[n_unsup_chans++] =
+					op_class_tbl->channels[chan_idx];
+			reg_ap_cap[index].num_non_supported_chan++;
+		} else {
+			reg_ap_cap[index].sup_chan_list[n_sup_chans++] =
+					op_class_tbl->channels[chan_idx];
+			reg_ap_cap[index].num_supported_chan++;
+		}
+
+		chan_idx++;
+	}
+
+	if (reg_ap_cap[index].num_supported_chan >= 1)
+		*is_opclass_operable = true;
+}
+
+QDF_STATUS reg_get_opclass_details(struct wlan_objmgr_pdev *pdev,
+				   struct regdmn_ap_cap_opclass_t *reg_ap_cap,
+				   uint8_t *n_opclasses,
+				   uint8_t max_supp_op_class,
+				   bool global_tbl_lookup)
+{
+	uint8_t max_reg_power = 0;
+	const struct reg_dmn_op_class_map_t *op_class_tbl;
+	uint8_t index = 0;
+
+	if (global_tbl_lookup)
+		op_class_tbl = global_op_class;
+	else
+		reg_get_op_class_tbl_by_chan_map(&op_class_tbl);
+
+	max_reg_power = reg_get_max_tx_power(pdev);
+
+	while (op_class_tbl->op_class && (index < max_supp_op_class)) {
+		bool is_opclass_operable = false;
+
+		qdf_mem_zero(reg_ap_cap[index].sup_chan_list,
+			     REG_MAX_CHANNELS_PER_OPERATING_CLASS);
+		reg_ap_cap[index].num_supported_chan = 0;
+		qdf_mem_zero(reg_ap_cap[index].non_sup_chan_list,
+			     REG_MAX_CHANNELS_PER_OPERATING_CLASS);
+		reg_ap_cap[index].num_non_supported_chan = 0;
+		reg_get_channels_from_opclassmap(pdev,
+						 reg_ap_cap,
+						 index,
+						 op_class_tbl,
+						 &is_opclass_operable);
+		if (is_opclass_operable) {
+			reg_ap_cap[index].op_class = op_class_tbl->op_class;
+			reg_ap_cap[index].ch_width =
+						op_class_tbl->chan_spacing;
+			reg_ap_cap[index].start_freq =
+						op_class_tbl->start_freq;
+			reg_ap_cap[index].max_tx_pwr_dbm = max_reg_power;
+			reg_ap_cap[index].behav_limit =
+						op_class_tbl->behav_limit;
+			index++;
+		}
+
+		op_class_tbl++;
+	}
+
+	*n_opclasses = index;
+
+	return QDF_STATUS_SUCCESS;
+}
 #endif
diff --git a/umac/regulatory/core/src/reg_opclass.h b/umac/regulatory/core/src/reg_opclass.h
index 834f3d7..3b5c8dc 100644
--- a/umac/regulatory/core/src/reg_opclass.h
+++ b/umac/regulatory/core/src/reg_opclass.h
@@ -89,6 +89,21 @@
  */
 uint16_t reg_dmn_get_curr_opclasses(uint8_t *num_classes, uint8_t *class);
 
+/**
+ * reg_get_opclass_details() - Get details about the current opclass table.
+ * @pdev: Pointer to pdev.
+ * @reg_ap_cap: Pointer to reg_ap_cap.
+ * @n_opclasses: Pointer to number of opclasses.
+ * @max_supp_op_class: Maximum number of operating classes supported.
+ * @global_tbl_lookup: Whether to lookup global op class table.
+ *
+ * Return: QDF_STATUS_SUCCESS if success, else return QDF_STATUS_FAILURE.
+ */
+QDF_STATUS reg_get_opclass_details(struct wlan_objmgr_pdev *pdev,
+				   struct regdmn_ap_cap_opclass_t *reg_ap_cap,
+				   uint8_t *n_opclasses,
+				   uint8_t max_supp_op_class,
+				   bool global_tbl_lookup);
 #ifdef CONFIG_CHAN_FREQ_API
 
 /**
@@ -195,6 +210,16 @@
 {
 }
 
+static inline
+QDF_STATUS reg_get_opclass_details(struct wlan_objmgr_pdev *pdev,
+				   struct regdmn_ap_cap_opclass_t *reg_ap_cap,
+				   uint8_t *n_opclasses,
+				   uint8_t max_supp_op_class,
+				   bool global_tbl_lookup)
+{
+	return QDF_STATUS_E_FAILURE;
+}
+
 #ifdef CONFIG_CHAN_FREQ_API
 
 static inline void
diff --git a/umac/regulatory/core/src/reg_services_common.c b/umac/regulatory/core/src/reg_services_common.c
index 1b61ab3..b43a54f 100644
--- a/umac/regulatory/core/src/reg_services_common.c
+++ b/umac/regulatory/core/src/reg_services_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-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
@@ -1071,6 +1071,8 @@
 		    reg_channels[i].chan_flags != REGULATORY_CHAN_DISABLED) {
 			ch_list[count].chan_num =
 				reg_channels[i].chan_num;
+			ch_list[count].center_freq =
+				reg_channels[i].center_freq;
 			ch_list[count++].tx_power =
 				reg_channels[i].tx_power;
 		}
@@ -2853,6 +2855,36 @@
 	return INVALID_CHANNEL;
 }
 
+bool
+reg_is_freq_present_in_cur_chan_list(struct wlan_objmgr_pdev *pdev,
+				     qdf_freq_t freq)
+{
+	enum channel_enum chan_enum;
+	struct regulatory_channel *cur_chan_list;
+	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
+
+	pdev_priv_obj = reg_get_pdev_obj(pdev);
+
+	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
+		reg_err_rl("pdev reg obj is NULL");
+		return false;
+	}
+
+	cur_chan_list = pdev_priv_obj->cur_chan_list;
+
+	for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++)
+		if (cur_chan_list[chan_enum].center_freq == freq)
+			if ((cur_chan_list[chan_enum].state !=
+			     CHANNEL_STATE_DISABLE) &&
+			    !(cur_chan_list[chan_enum].chan_flags &
+			      REGULATORY_CHAN_DISABLED))
+				return true;
+
+	reg_debug_rl("Channel center frequency %d not found", freq);
+
+	return false;
+}
+
 enum channel_state reg_get_channel_state_for_freq(struct wlan_objmgr_pdev *pdev,
 						  qdf_freq_t freq)
 {
@@ -3474,8 +3506,38 @@
 		return REG_BAND_6G;
 	return REG_BAND_UNKNOWN;
 }
+
 #endif /* CONFIG_CHAN_FREQ_API */
 
+uint8_t  reg_get_max_tx_power(struct wlan_objmgr_pdev *pdev)
+{
+	struct regulatory_channel *cur_chan_list;
+	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
+	uint8_t i, max_tx_power = 0;
+
+	pdev_priv_obj = reg_get_pdev_obj(pdev);
+
+	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
+		reg_err("reg pdev private obj is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	cur_chan_list = pdev_priv_obj->cur_chan_list;
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		if (cur_chan_list[i].state != CHANNEL_STATE_DISABLE &&
+		    cur_chan_list[i].chan_flags != REGULATORY_CHAN_DISABLED) {
+			if (cur_chan_list[i].tx_power > max_tx_power)
+				max_tx_power = cur_chan_list[i].tx_power;
+		}
+	}
+
+	if (!max_tx_power)
+		reg_err_rl("max_tx_power is zero");
+
+	return max_tx_power;
+}
+
 QDF_STATUS reg_set_ignore_fw_reg_offload_ind(struct wlan_objmgr_psoc *psoc)
 {
 	struct wlan_regulatory_psoc_priv_obj *psoc_reg;
diff --git a/umac/regulatory/core/src/reg_services_common.h b/umac/regulatory/core/src/reg_services_common.h
index d8e9d99..ffd0091 100644
--- a/umac/regulatory/core/src/reg_services_common.h
+++ b/umac/regulatory/core/src/reg_services_common.h
@@ -742,6 +742,21 @@
 
 #ifdef CONFIG_CHAN_FREQ_API
 /**
+ * reg_is_freq_present_in_cur_chan_list() - Check the input frequency
+ * @pdev: Pointer to pdev
+ * @freq: Channel center frequency in MHz
+ *
+ * Check if the input channel center frequency is present in the current
+ * channel list
+ *
+ * Return: Return true if channel center frequency is present in the current
+ * channel list, else return false.
+ */
+bool
+reg_is_freq_present_in_cur_chan_list(struct wlan_objmgr_pdev *pdev,
+				     qdf_freq_t freq);
+
+/**
  * reg_get_chan_enum_for_freq() - Get channel enum for given channel frequency
  * @freq: Channel Frequency
  *
@@ -936,6 +951,15 @@
 #endif /* CONFIG_CHAN_FREQ_API */
 
 /**
+ * reg_get_max_tx_power() - Get maximum tx power from the current channel list
+ * @pdev: Pointer to pdev
+ *
+ * Return: return the value of the maximum tx power in the current channel list
+ *
+ */
+uint8_t reg_get_max_tx_power(struct wlan_objmgr_pdev *pdev);
+
+/**
  * reg_set_ignore_fw_reg_offload_ind() - Set if regdb offload indication
  * needs to be ignored
  * @psoc: Pointer to psoc
diff --git a/umac/regulatory/core/src/reg_utils.h b/umac/regulatory/core/src/reg_utils.h
index dc714b0..059c1b3 100644
--- a/umac/regulatory/core/src/reg_utils.h
+++ b/umac/regulatory/core/src/reg_utils.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
@@ -516,7 +516,7 @@
  * Return: true or false
  */
 #ifdef CONFIG_CHAN_FREQ_API
-bool reg_is_dsrc_freq(uint16_t freq);
+bool reg_is_dsrc_freq(qdf_freq_t freq);
 #endif /* CONFIG_CHAN_FREQ_API*/
 
 #ifdef CONFIG_CHAN_NUM_API
@@ -567,7 +567,7 @@
 	return false;
 }
 
-static inline bool reg_is_dsrc_freq(uint16_t freq)
+static inline bool reg_is_dsrc_freq(qdf_freq_t freq)
 {
 	return false;
 }
@@ -612,7 +612,7 @@
 	return false;
 }
 
-static inline bool reg_is_dsrc_freq(uint16_t freq)
+static inline bool reg_is_dsrc_freq(qdf_freq_t freq)
 {
 	return false;
 }
diff --git a/umac/regulatory/dispatcher/inc/reg_services_public_struct.h b/umac/regulatory/dispatcher/inc/reg_services_public_struct.h
index 2617cd8..2400e69 100644
--- a/umac/regulatory/dispatcher/inc/reg_services_public_struct.h
+++ b/umac/regulatory/dispatcher/inc/reg_services_public_struct.h
@@ -528,8 +528,8 @@
 struct ch_params {
 	enum phy_ch_width ch_width;
 	uint8_t sec_ch_offset;
-	qdf_freq_t center_freq_seg0;
-	qdf_freq_t center_freq_seg1;
+	uint8_t center_freq_seg0;
+	uint8_t center_freq_seg1;
 	qdf_freq_t mhz_freq_seg0;
 	qdf_freq_t mhz_freq_seg1;
 };
@@ -598,6 +598,30 @@
 };
 
 /**
+ * struct regdmn_ap_cap_opclass_t: AP Cap operation class table
+ * @op_class: operating class number
+ * @ch_width: channel width in MHz
+ * @start_freq: Starting Frequency in MHz
+ * @behav_limit: OR of bitmaps of enum behav_limit
+ * @max_tx_pwr_dbm: Maximum tx power in dbm
+ * @num_supported_chan: Number of supported channels
+ * @num_non_supported_chan: Number of non-supported channels
+ * @sup_chan_list: Array of supported channel numbers
+ * @non_sup_chan_list: Array of non supported channel numbers
+ */
+struct regdmn_ap_cap_opclass_t {
+	uint8_t op_class;
+	uint8_t ch_width;
+	qdf_freq_t start_freq;
+	uint16_t behav_limit;
+	uint8_t max_tx_pwr_dbm;
+	uint8_t num_supported_chan;
+	uint8_t num_non_supported_chan;
+	uint8_t sup_chan_list[REG_MAX_CHANNELS_PER_OPERATING_CLASS];
+	uint8_t non_sup_chan_list[REG_MAX_CHANNELS_PER_OPERATING_CLASS];
+};
+
+/**
  * struct reg_dmn_supp_op_classes: operating classes
  * @num_classes: number of classes
  * @classes: classes
diff --git a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h
index dc89234..dca8d3b 100644
--- a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h
+++ b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h
@@ -606,6 +606,23 @@
 
 
 /**
+ * wlan_reg_get_opclass_details() - Get details about the current opclass table.
+ * @pdev: Pointer to pdev.
+ * @reg_ap_cap: Pointer to reg_ap_cap.
+ * @n_opclasses: Pointer to number of opclasses.
+ * @max_supp_op_class: Maximum number of operating classes supported.
+ * @global_tbl_lookup: Whether to lookup global op class tbl.
+ *
+ * Return: QDF_STATUS_SUCCESS if success, else return QDF_STATUS_FAILURE.
+ */
+QDF_STATUS
+wlan_reg_get_opclass_details(struct wlan_objmgr_pdev *pdev,
+			     struct regdmn_ap_cap_opclass_t *reg_ap_cap,
+			     uint8_t *n_opclasses,
+			     uint8_t max_supp_op_class,
+			     bool global_tbl_lookup);
+
+/**
  * wlan_regulatory_init() - init regulatory component
  *
  * Return: Success or Failure
diff --git a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c
index 22f2482..b21ec96 100644
--- a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c
+++ b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c
@@ -302,6 +302,18 @@
 	return reg_dmn_get_curr_opclasses(num_classes, class);
 }
 
+QDF_STATUS
+wlan_reg_get_opclass_details(struct wlan_objmgr_pdev *pdev,
+			     struct regdmn_ap_cap_opclass_t *reg_ap_cap,
+			     uint8_t *n_opclasses,
+			     uint8_t max_supp_op_class,
+			     bool global_tbl_lookup)
+{
+	return reg_get_opclass_details(pdev, reg_ap_cap, n_opclasses,
+				       max_supp_op_class,
+				       global_tbl_lookup);
+}
+
 QDF_STATUS wlan_regulatory_init(void)
 {
 	QDF_STATUS status;
diff --git a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h
index fde2a5a..dba1199 100644
--- a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h
+++ b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h
@@ -1246,7 +1246,7 @@
 
 /* Set PNO */
 #define SCAN_PNO_MAX_PLAN_REQUEST   2
-#define SCAN_PNO_MAX_NETW_CHANNELS_EX  60
+#define SCAN_PNO_MAX_NETW_CHANNELS_EX  (QDF_MAX_NUM_CHAN)
 #define SCAN_PNO_MAX_SUPP_NETWORKS  16
 #define SCAN_PNO_DEF_SLOW_SCAN_MULTIPLIER 6
 #define SCAN_PNO_DEF_SCAN_TIMER_REPEAT 20
diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c
index f9d23de..bfbe4f3 100644
--- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c
+++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-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
@@ -598,17 +598,15 @@
 static QDF_STATUS
 util_scan_update_rnr(struct rnr_bss_info *rnr,
 		     struct neighbor_ap_info_field *ap_info,
-		     uint8_t **data)
+		     uint8_t *data)
 {
-	uint16_t fieldtype;
-	uint8_t *tmp = *data;
+	uint8_t tbtt_info_length;
 
-	fieldtype = ap_info->tbtt_header.tbbt_info_fieldtype;
+	tbtt_info_length = ap_info->tbtt_header.tbtt_info_length;
 
-	switch (fieldtype) {
+	switch (tbtt_info_length) {
 	case TBTT_NEIGHBOR_AP_OFFSET_ONLY:
 		/* Dont store it skip*/
-		*data = tmp + NEIGHBOR_AP_LEN;
 		break;
 
 	case TBTT_NEIGHBOR_AP_BSS_PARAM:
@@ -618,51 +616,42 @@
 	case TBTT_NEIGHBOR_AP_SHORTSSID:
 		rnr->channel_number = ap_info->channel_number;
 		rnr->operating_class = ap_info->operting_class;
-		qdf_mem_copy(&rnr->short_ssid, &tmp[1], SHORT_SSID_LEN);
-		*data = tmp + NEIGHBOR_AP_LEN + SHORT_SSID_LEN;
+		qdf_mem_copy(&rnr->short_ssid, &data[1], SHORT_SSID_LEN);
 		break;
 
 	case TBTT_NEIGHBOR_AP_S_SSID_BSS_PARAM:
 		rnr->channel_number = ap_info->channel_number;
 		rnr->operating_class = ap_info->operting_class;
-		qdf_mem_copy(&rnr->short_ssid, &tmp[1], SHORT_SSID_LEN);
-		rnr->bss_params = tmp[5];
-		*data = tmp + NEIGHBOR_AP_LEN + SHORT_SSID_LEN + BSS_PARAMS_LEN;
+		qdf_mem_copy(&rnr->short_ssid, &data[1], SHORT_SSID_LEN);
+		rnr->bss_params = data[5];
 		break;
 
 	case TBTT_NEIGHBOR_AP_BSSID:
 		rnr->channel_number = ap_info->channel_number;
 		rnr->operating_class = ap_info->operting_class;
-		qdf_mem_copy(&rnr->bssid, &tmp[1], QDF_MAC_ADDR_SIZE);
-		*data = tmp + NEIGHBOR_AP_LEN + QDF_MAC_ADDR_SIZE;
+		qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
 		break;
 
 	case TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM:
 		rnr->channel_number = ap_info->channel_number;
 		rnr->operating_class = ap_info->operting_class;
-		qdf_mem_copy(&rnr->bssid, &tmp[1], QDF_MAC_ADDR_SIZE);
-		rnr->bss_params = tmp[7];
-		*data = tmp + NEIGHBOR_AP_LEN + QDF_MAC_ADDR_SIZE
-			+ BSS_PARAMS_LEN;
+		qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
+		rnr->bss_params = data[7];
 		break;
 
 	case TBTT_NEIGHBOR_AP_BSSSID_S_SSID:
 		rnr->channel_number = ap_info->channel_number;
 		rnr->operating_class = ap_info->operting_class;
-		qdf_mem_copy(&rnr->bssid, &tmp[1], QDF_MAC_ADDR_SIZE);
-		qdf_mem_copy(&rnr->short_ssid, &tmp[7], SHORT_SSID_LEN);
-		*data = tmp + NEIGHBOR_AP_LEN + QDF_MAC_ADDR_SIZE
-			+ SHORT_SSID_LEN;
+		qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
+		qdf_mem_copy(&rnr->short_ssid, &data[7], SHORT_SSID_LEN);
 		break;
 
 	case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM:
 		rnr->channel_number = ap_info->channel_number;
 		rnr->operating_class = ap_info->operting_class;
-		qdf_mem_copy(&rnr->bssid, &tmp[1], QDF_MAC_ADDR_SIZE);
-		qdf_mem_copy(&rnr->short_ssid, &tmp[7], SHORT_SSID_LEN);
-		rnr->bss_params = tmp[11];
-		*data = tmp + NEIGHBOR_AP_LEN + QDF_MAC_ADDR_SIZE
-			+ SHORT_SSID_LEN + BSS_PARAMS_LEN;
+		qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
+		qdf_mem_copy(&rnr->short_ssid, &data[7], SHORT_SSID_LEN);
+		rnr->bss_params = data[11];
 		break;
 
 	default:
@@ -684,7 +673,7 @@
 	rnr_ie_len = ie->ie_len;
 	data = (uint8_t *)ie + sizeof(struct ie_header);
 
-	while (data < (uint8_t *)ie + rnr_ie_len + 2) {
+	while (data < ((uint8_t *)ie + rnr_ie_len + 2)) {
 		neighbor_ap_info = (struct neighbor_ap_info_field *)data;
 		tbtt_count = neighbor_ap_info->tbtt_header.tbtt_info_count;
 		tbtt_length = neighbor_ap_info->tbtt_header.tbtt_info_length;
@@ -694,11 +683,14 @@
 			  neighbor_ap_info->operting_class);
 		scm_debug("tbtt_count %d, tbtt_length %d, fieldtype %d",
 			  tbtt_count, tbtt_length, fieldtype);
-		for (i = 0; i < (tbtt_count + 1) && i < MAX_RNR_BSS; i++) {
-			data = data + sizeof(struct neighbor_ap_info_field);
-			util_scan_update_rnr(&scan_entry->rnr.bss_info[i],
-					     neighbor_ap_info,
-					     &data);
+		data += sizeof(struct neighbor_ap_info_field);
+		for (i = 0; i < (tbtt_count + 1) ; i++) {
+			if (i < MAX_RNR_BSS)
+				util_scan_update_rnr(
+					&scan_entry->rnr.bss_info[i],
+					neighbor_ap_info,
+					data);
+			data += tbtt_length;
 		}
 	}
 
diff --git a/umac/wifi_pos/src/wifi_pos_main.c b/umac/wifi_pos/src/wifi_pos_main.c
index a8bba7c..d36c657 100644
--- a/umac/wifi_pos/src/wifi_pos_main.c
+++ b/umac/wifi_pos/src/wifi_pos_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-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
@@ -442,14 +442,66 @@
 	vdev_idx++;
 }
 
+#ifdef CNSS_GENL
+static uint8_t *
+wifi_pos_prepare_reg_resp(uint32_t *rsp_len,
+			  struct app_reg_rsp_vdev_info *vdevs_info)
+{
+	uint32_t *nl_sign;
+	uint8_t *resp_buf;
+	struct wifi_app_reg_rsp *app_reg_rsp;
+
+	/*
+	 * allocate ENHNC_FLAGS_LEN i.e. 4bytes extra memory in app_reg_resp
+	 * to indicate NLA type resoponse is supported for OEM request
+	 * commands.
+	 */
+	*rsp_len = (sizeof(struct app_reg_rsp_vdev_info) * vdev_idx)
+			+ sizeof(uint8_t) + ENHNC_FLAGS_LEN;
+	resp_buf = qdf_mem_malloc(*rsp_len);
+	if (!resp_buf)
+		return NULL;
+
+	app_reg_rsp = (struct wifi_app_reg_rsp *)resp_buf;
+	app_reg_rsp->num_inf = vdev_idx;
+	qdf_mem_copy(&app_reg_rsp->vdevs, vdevs_info,
+		     sizeof(struct app_reg_rsp_vdev_info) * vdev_idx);
+
+	nl_sign = (uint32_t *)&app_reg_rsp->vdevs[vdev_idx];
+	*nl_sign |= NL_ENABLE_OEM_REQ_RSP;
+
+	return resp_buf;
+}
+#else
+static uint8_t *
+wifi_pos_prepare_reg_resp(uint32_t *rsp_len,
+			  struct app_reg_rsp_vdev_info *vdevs_info)
+{
+	uint8_t *resp_buf;
+	struct wifi_app_reg_rsp *app_reg_rsp;
+
+	*rsp_len = (sizeof(struct app_reg_rsp_vdev_info) * vdev_idx)
+			+ sizeof(uint8_t);
+	resp_buf = qdf_mem_malloc(*rsp_len);
+	if (!resp_buf)
+		return NULL;
+
+	app_reg_rsp = (struct wifi_app_reg_rsp *)resp_buf;
+	app_reg_rsp->num_inf = vdev_idx;
+	qdf_mem_copy(&app_reg_rsp->vdevs, vdevs_info,
+		     sizeof(struct app_reg_rsp_vdev_info) * vdev_idx);
+
+	return resp_buf;
+}
+#endif
+
 static QDF_STATUS wifi_pos_process_app_reg_req(struct wlan_objmgr_psoc *psoc,
 					struct wifi_pos_req_msg *req)
 {
 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
-	uint8_t err = 0;
+	uint8_t err = 0, *app_reg_rsp;
 	uint32_t rsp_len;
 	char *sign_str = NULL;
-	struct wifi_app_reg_rsp *app_reg_rsp;
 	struct app_reg_rsp_vdev_info vdevs_info[WLAN_UMAC_PSOC_MAX_VDEVS]
 								= { { 0 } };
 	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
@@ -484,18 +536,14 @@
 	wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
 				     wifi_pos_vdev_iterator,
 				     vdevs_info, true, WLAN_WIFI_POS_CORE_ID);
-	rsp_len = (sizeof(struct app_reg_rsp_vdev_info) * vdev_idx)
-			+ sizeof(uint8_t);
-	app_reg_rsp = qdf_mem_malloc(rsp_len);
+
+	app_reg_rsp = wifi_pos_prepare_reg_resp(&rsp_len, vdevs_info);
 	if (!app_reg_rsp) {
 		ret = QDF_STATUS_E_NOMEM;
 		err = OEM_ERR_NULL_CONTEXT;
 		goto app_reg_failed;
 	}
 
-	app_reg_rsp->num_inf = vdev_idx;
-	qdf_mem_copy(&app_reg_rsp->vdevs, vdevs_info,
-		     sizeof(struct app_reg_rsp_vdev_info) * vdev_idx);
 	if (!vdev_idx)
 		wifi_pos_debug("no active vdev");
 
diff --git a/umac/wifi_pos/src/wifi_pos_main_i.h b/umac/wifi_pos/src/wifi_pos_main_i.h
index 864f709..227c2ce 100644
--- a/umac/wifi_pos/src/wifi_pos_main_i.h
+++ b/umac/wifi_pos/src/wifi_pos_main_i.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017, 2019-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
@@ -25,6 +25,11 @@
 #ifndef _WIFI_POS_MAIN_H_
 #define _WIFI_POS_MAIN_H_
 
+#ifdef CNSS_GENL
+#define ENHNC_FLAGS_LEN 4
+#define NL_ENABLE_OEM_REQ_RSP 0x00000001
+#endif
+
 /* forward reference */
 struct wlan_objmgr_psoc;
 
diff --git a/utils/host_diag_log/inc/host_diag_core_log.h b/utils/host_diag_log/inc/host_diag_core_log.h
index f9b47cb..5e5b363 100644
--- a/utils/host_diag_log/inc/host_diag_core_log.h
+++ b/utils/host_diag_log/inc/host_diag_core_log.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017, 2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2017, 2019-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
@@ -285,6 +285,272 @@
 	uint8_t cb_cal_data[HOST_LOG_MAX_COLD_BOOT_CAL_DATA_SIZE];
 };
 
+#define WLAN_MAX_ROAM_CANDIDATE_AP      8
+#define WLAN_MAX_ROAM_SCAN_CHAN         38
+#define WLAN_MAX_SSID_SIZE              32
+#define WLAN_MAC_ADDR_SIZE              6
+
+/**
+ * host_log_wlan_mgmt_tx_rx_info: To capture TX/RX mgmt frames' payload
+ * @hdr: Log header
+ * @version: Version number of the payload
+ * @vdev_id: Vdev id
+ * @is_tx: 1 - TX frame, 0 - RX frame
+ * @mgmt_type: type of frames, value: enum wifi_frm_type
+ * @mgmt_subtype: subtype of mgmt frame, value: enum mgmt_frm_subtype
+ * @mgmt_frame_seq_num: Frame sequence number in 802.11 header
+ * @operating_freq: operating frequency of AP
+ * @ssid_len: length of SSID, max 32 bytes long as per standard
+ * @ssid: SSID of connected AP
+ * @self_mac_addr: mac address of self interface
+ * @bssid: BSSID for which frame is received
+ * @mac_failure_reason: Internal driver failure reason
+ * @mgmt_status_code: 802.11 management frame response status code from
+ * section 9.4.1.9 IEEE 802.11 - 2016
+ * @auth_algo: Authentication algorithm number
+ * @auth_transaction_num: Authentication transaction sequence number
+ * @is_retry: Is retry frame
+ * @rssi: RSSI for the received frame
+ * @origin: 1- Sent by host. 2- sent by firmware
+ */
+struct host_log_wlan_mgmt_tx_rx_info {
+	log_hdr_type hdr;
+	uint8_t version;
+	uint8_t vdev_id;
+	bool is_tx;
+	uint8_t mgmt_type;
+	uint8_t mgmt_subtype;
+	uint16_t mgmt_frame_seq_num;
+	uint8_t operating_freq;
+	uint8_t ssid_len;
+	char ssid[WLAN_MAX_SSID_SIZE];
+	uint8_t self_mac_addr[WLAN_MAC_ADDR_SIZE];
+	uint8_t bssid[WLAN_MAC_ADDR_SIZE];
+	uint16_t mac_failure_reason;
+	uint16_t mgmt_status_code;
+	uint8_t auth_algo;
+	uint8_t auth_transaction_num;
+	uint8_t is_retry;
+	uint32_t rssi;
+	uint8_t origin;
+} qdf_packed;
+
+/**
+ * struct wlan_roam_btm_trigger_data - BTM roam trigger related information
+ * @btm_request_mode:      BTM request mode - solicited/unsolicited
+ * @disassoc_timer:        Number of TBTT before AP disassociates the STA in ms
+ * @validity_interval:     Preferred candidate list validity interval in ms
+ * @candidate_list_count:  Number of candidates in BTM request.
+ * @btm_resp_status:       Status code of the BTM response.
+ */
+struct wlan_roam_btm_trigger_data {
+	uint8_t btm_request_mode;
+	uint32_t disassoc_timer;
+	uint32_t validity_interval;
+	uint16_t candidate_list_count;
+	uint16_t btm_resp_status;
+} qdf_packed;
+
+/**
+ * struct wlan_roam_cu_trigger_data - BSS Load roam trigger parameters
+ * @cu_load: Connected AP CU load percentage
+ */
+struct wlan_roam_cu_trigger_data {
+	uint16_t cu_load;
+} qdf_packed;
+
+/**
+ * Struct wlan_roam_rssi_trigger_data - RSSI roam trigger related
+ * parameters
+ * @threshold: RSSI threshold value in dBm for LOW rssi roam trigger
+ */
+struct wlan_roam_rssi_trigger_data {
+	uint32_t threshold;
+} qdf_packed;
+
+/**
+ * struct wlan_roam_deauth_trigger_data - Deauth roaming trigger related
+ * parameters
+ * @type:   1- Deauthentication 2- Disassociation
+ * @reason: Status code of the Deauth/Disassoc received
+ */
+struct wlan_roam_deauth_trigger_data {
+	uint8_t type;
+	uint32_t reason;
+} qdf_packed;
+
+/**
+ * struct host_log_wlan_roam_trigger_info - Roam trigger
+ * related info
+ * @hdr: Log header
+ * @version: Version number of the payload
+ * @vdev_id: Vdev id
+ * @trigger_reason: Roaming trigger reason
+ * @trigger_sub_reason: Roaming trigger sub reason
+ * @current_rssi:  Current connected AP RSSI
+ * @timestamp: Host driver timestamp in msecs
+ * @btm_trig_data: BTM trigger related data
+ * @cu_load_data: CU load trigger related data
+ * @rssi_trig_data: RSSI roam trigger related data
+ * @deauth_trig_data: Deauth Roam trigger related data
+ */
+struct host_log_wlan_roam_trigger_info {
+	log_hdr_type hdr;
+	uint8_t version;
+	uint8_t vdev_id;
+	uint32_t trigger_reason;
+	uint32_t trigger_sub_reason;
+	uint32_t current_rssi;
+	uint32_t timestamp;
+	union {
+		struct wlan_roam_btm_trigger_data btm_trig_data;
+		struct wlan_roam_cu_trigger_data cu_load_data;
+		struct wlan_roam_rssi_trigger_data rssi_trig_data;
+		struct wlan_roam_deauth_trigger_data deauth_trig_data;
+	};
+} qdf_packed;
+
+/**
+ *  struct host_log_wlan_roam_candidate_info - Roam scan candidate APs related
+ *  info
+ *  @version:     Payload structure version
+ *  @timestamp:   Host timestamp in millisecs
+ *  @type:        0 - Candidate AP; 1 - Current connected AP.
+ *  @bssid:       AP bssid.
+ *  @freq:        Channel frquency
+ *  @cu_load:     Channel utilization load of the AP.
+ *  @cu_score:    Channel Utilization score.
+ *  @rssi:        Candidate AP rssi
+ *  @rssi_score:  AP RSSI score
+ *  @total_score: Total score of the candidate AP.
+ *  @etp:         Estimated throughput value of the AP in Mbps
+ */
+struct host_log_wlan_roam_candidate_info {
+	uint8_t version;
+	uint32_t timestamp;
+	uint8_t type;
+	uint8_t bssid[WLAN_MAC_ADDR_SIZE];
+	uint16_t freq;
+	uint32_t cu_load;
+	uint32_t cu_score;
+	uint32_t rssi;
+	uint32_t rssi_score;
+	uint32_t total_score;
+	uint32_t etp;
+} qdf_packed;
+
+/**
+ * struct host_log_wlan_roam_scan_data - Roam scan event details
+ * @hdr: Log header
+ * @version:   Version number of the diag log payload
+ * @vdev_id:   Vdev ID
+ * @type:      0 - Partial roam scan; 1 - Full roam scan
+ * @num_ap:    Number of candidate APs.
+ * @num_chan:  Number of channels.
+ * @timestamp: Time of day in milliseconds at which scan was triggered
+ * @trigger_reason: Roam scan trigger reason
+ * @next_rssi_threshold: Next roam can trigger rssi threshold
+ * @chan_freq: List of frequencies scanned as part of roam scan
+ * @ap: List of candidate AP info
+ */
+struct host_log_wlan_roam_scan_data {
+	log_hdr_type hdr;
+	uint8_t version;
+	uint8_t vdev_id;
+	uint16_t type;
+	uint8_t num_ap;
+	uint8_t num_chan;
+	uint32_t timestamp;
+	uint32_t trigger_reason;
+	uint32_t next_rssi_threshold;
+	uint16_t chan_freq[WLAN_MAX_ROAM_SCAN_CHAN];
+	struct host_log_wlan_roam_candidate_info ap[WLAN_MAX_ROAM_CANDIDATE_AP];
+} qdf_packed;
+
+/**
+ * struct host_log_wlan_roam_result_info - Roam result related info.
+ * @hdr:                Log header
+ * @version:            Payload strcuture version
+ * @vdev_id:            Vdev Id
+ * @status:             0 - Roaming is success ; 1 - Roaming failed
+ * @timestamp:          Host timestamp in millisecs
+ * @fail_reason:        One of WMI_ROAM_FAIL_REASON_ID
+ */
+struct host_log_wlan_roam_result_info {
+	log_hdr_type hdr;
+	uint8_t version;
+	uint8_t vdev_id;
+	bool status;
+	uint32_t timestamp;
+	uint32_t fail_reason;
+} qdf_packed;
+
+/**
+ * struct wlan_rrm_beacon_report - RRM beacon report related
+ * parameters
+ * @req_bssid: beacon report requestor BSSID
+ * @req_ssid: Requested SSID for beacon report
+ * @is_wildcard_bssid: Is the BSSID FF:FF:FF:FF:FF:FF
+ * @req_reg_class: Regulatory class mentioned in the request
+ * @req_measurement_mode: Measurement mode. Active/Passive/Beacon report Table
+ * @req_measurement_duration: Measurement duration requested.
+ * @num_reports_in_frame: Number of BSS scanned
+ * @is_last_frame_in_req: True if this frame is the last frame sent for the
+ * request
+ */
+struct wlan_rrm_beacon_report {
+	uint8_t req_bssid[WLAN_MAC_ADDR_SIZE];
+	uint8_t req_ssid[WLAN_MAX_SSID_SIZE];
+	bool is_wildcard_bssid;
+	uint8_t req_reg_class;
+	uint16_t req_measurement_mode;
+	uint16_t req_measurement_duration;
+	uint8_t num_reports_in_frame;
+	bool is_last_frame_in_req;
+} qdf_packed;
+
+/**
+ * struct host_log_wlan_rrm_tx_rx_info - RRM frame related details
+ * @hdr:     Log header
+ * @version: Version of the payload struture
+ * @vdev_id: Vdev id
+ * @orgin:   Sent by host or firmware
+ * @is_tx:   Is Tx frame or RX frame
+ * @roam_result: Roaming result
+ * @timestamp: Time of the day in milliseconds
+ * @mgmt_frame_seq_num: Frame sequence number
+ * @received_chan_freq: Frame received channel frequency
+ * @action_category: Action frame category
+ * @rrm_action_code: Radio measurement/Noise measurement
+ * @radio_measurement_type: Neighbor report/Beacon report
+ * @bssid: BSSID field in frame
+ * @req_num_freq: Number of frequencies provided in request
+ * @req_freq: Frequencies requested
+ * @fail_reason_code: response TX failure status code
+ * @rssi: Rx frame rssi
+ * @bcn_rpt: Beacon report related parameters
+ */
+struct host_log_wlan_rrm_tx_rx_info {
+	log_hdr_type hdr;
+	uint8_t version;
+	uint8_t vdev_id;
+	uint8_t origin;
+	bool is_tx;
+	bool roam_result;
+	uint32_t timestamp;
+	uint16_t mgmt_frame_seq_num;
+	uint16_t received_chan_freq;
+	uint8_t action_category;
+	uint8_t rrm_action_code;
+	uint8_t radio_measurement_type;
+	uint8_t bssid[WLAN_MAC_ADDR_SIZE];
+	uint8_t req_num_freq;
+	uint16_t req_freq[WLAN_MAX_ROAM_SCAN_CHAN];
+	uint8_t fail_reason_code;
+	uint32_t rssi;
+	struct wlan_rrm_beacon_report bcn_rpt;
+} qdf_packed;
+
 /*-------------------------------------------------------------------------
    Function declarations and documenation
    ------------------------------------------------------------------------*/
diff --git a/utils/host_diag_log/inc/log_codes.h b/utils/host_diag_log/inc/log_codes.h
index 9f3fe6c..11dfa6b 100644
--- a/utils/host_diag_log/inc/log_codes.h
+++ b/utils/host_diag_log/inc/log_codes.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-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
@@ -2003,6 +2003,12 @@
 
 #define LOG_WLAN_COLD_BOOT_CAL_DATA_C                  ((0xA18) + LOG_1X_BASE_C)
 
+#define LOG_WLAN_AUTH_ASSOC_TX_RX_INFO_C              ((0x1A19) + LOG_1X_BASE_C)
+#define LOG_WLAN_ROAM_TRIGGER_INFO_C                  ((0x1A1A) + LOG_1X_BASE_C)
+#define LOG_WLAN_ROAM_SCAN_INFO_C                     ((0x1A1B) + LOG_1X_BASE_C)
+#define LOG_WLAN_ROAM_RESULT_INFO_C                   ((0x1A1C) + LOG_1X_BASE_C)
+#define LOG_WLAN_RRM_TX_RX_INFO_C                     ((0x1A1D) + LOG_1X_BASE_C)
+
 /* This is only here for old (pre equipment ID update) logging code */
 #define LOG_LAST_C                                      (LOG_1X_LAST_C & 0xFFF)
 
diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h
index 79f75bc..d2c000e 100644
--- a/wmi/inc/wmi_unified_param.h
+++ b/wmi/inc/wmi_unified_param.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-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
@@ -881,13 +881,13 @@
 /**
  * struct fd_params - FD cmd parameter
  * @vdev_id: vdev id
- * @wbuf: FD buffer
  * @frame_ctrl: frame control field
+ * @wbuf: FD buffer
  */
 struct fd_params {
 	uint8_t vdev_id;
-	qdf_nbuf_t wbuf;
 	uint16_t frame_ctrl;
+	qdf_nbuf_t wbuf;
 };
 
 /**
@@ -1276,30 +1276,30 @@
  * @tx_frame: management tx frame
  * @frm_len: frame length
  * @vdev_id: vdev id
+ * @tx_type: type of management frame (determines what callback to use)
  * @chanfreq: channel frequency
- * @pdata: frame data
  * @desc_id: descriptor id relyaed back by target
+ * @pdata: frame data
  * @macaddr: macaddr of peer
  * @qdf_ctx: qdf context for qdf_nbuf_map
  * @tx_param: TX send parameters
  * @tx_params_valid: Flag that indicates if TX params are valid
  * @use_6mbps: specify whether management frame to transmit should
  *  use 6 Mbps rather than 1 Mbps min rate(for 5GHz band or P2P)
- * @tx_type: type of management frame (determines what callback to use)
  */
 struct wmi_mgmt_params {
 	void *tx_frame;
 	uint16_t frm_len;
 	uint8_t vdev_id;
+	uint8_t tx_type;
 	uint16_t chanfreq;
-	void *pdata;
 	uint16_t desc_id;
+	void *pdata;
 	uint8_t *macaddr;
 	void *qdf_ctx;
 	struct tx_send_params tx_param;
 	bool tx_params_valid;
 	uint8_t use_6mbps;
-	uint8_t tx_type;
 };
 
 /**
@@ -1307,25 +1307,25 @@
  * @tx_frame: management tx frame
  * @frm_len: frame length
  * @vdev_id: vdev id
+ * @tx_params_valid: Flag that indicates if TX params are valid
  * @chanfreq: channel frequency
- * @pdata: frame data
  * @desc_id: descriptor id relyaed back by target
+ * @pdata: frame data
  * @macaddr: macaddr of peer
  * @qdf_ctx: qdf context for qdf_nbuf_map
  * @tx_param: TX send parameters
- * @tx_params_valid: Flag that indicates if TX params are valid
  */
 struct wmi_offchan_data_tx_params {
 	void *tx_frame;
 	uint16_t frm_len;
 	uint8_t vdev_id;
+	bool tx_params_valid;
 	uint16_t chanfreq;
-	void *pdata;
 	uint16_t desc_id;
+	void *pdata;
 	uint8_t *macaddr;
 	void *qdf_ctx;
 	struct tx_send_params tx_param;
-	bool tx_params_valid;
 };
 
 /**
@@ -1348,14 +1348,14 @@
  * struct ta_uapsd_trig_params - uapsd trigger parameter
  * @vdevid: vdev id
  * @peer_addr: peer address
- * @auto_triggerparam: trigger parameters
  * @num_ac: no of access category
+ * @auto_triggerparam: trigger parameters
  */
 struct sta_uapsd_trig_params {
-		uint32_t vdevid;
-		uint8_t peer_addr[QDF_MAC_ADDR_SIZE];
-		struct sta_uapsd_params *auto_triggerparam;
-		uint32_t num_ac;
+	uint32_t vdevid;
+	uint8_t peer_addr[QDF_MAC_ADDR_SIZE];
+	uint32_t num_ac;
+	struct sta_uapsd_params *auto_triggerparam;
 };
 
 #define WMI_NUM_AC                     (4)
@@ -1531,14 +1531,15 @@
  * struct wifi_passpoint_network_param - passpoint network block
  * @id: identifier of this network block
  * @realm: null terminated UTF8 encoded realm, 0 if unspecified
- * @roaming_consortium_ids: roaming consortium ids to match, 0s if unspecified
  * @plmn: mcc/mnc combination as per rules, 0s if unspecified
+ * @roaming_consortium_ids: roaming consortium ids to match, 0s if unspecified
  */
 struct wifi_passpoint_network_param {
 	uint32_t id;
 	uint8_t  realm[WMI_PASSPOINT_REALM_LEN];
-	int64_t  roaming_consortium_ids[WMI_PASSPOINT_ROAMING_CONSORTIUM_ID_NUM];
 	uint8_t  plmn[WMI_PASSPOINT_PLMN_LEN];
+	int64_t  roaming_consortium_ids[
+			WMI_PASSPOINT_ROAMING_CONSORTIUM_ID_NUM];
 };
 
 /**
@@ -3241,13 +3242,16 @@
  * struct ctl_table_params - Ctl table params
  * @ctl_array: pointer to ctl array
  * @ctl_cmd_len: ctl command length
- * @is_acfg_ctl: is acfg_ctl table
+ * @is_2g: is 2G
+ * @target_type: target type
+ * @ctl_band: ctl band
+ * @pdev_id: pdev id
  */
 struct ctl_table_params {
 	uint8_t *ctl_array;
 	uint16_t ctl_cmd_len;
-	uint32_t target_type;
 	bool is_2g;
+	uint32_t target_type;
 	uint32_t ctl_band;
 	uint32_t pdev_id;
 };
@@ -3375,29 +3379,29 @@
  * @wildcard: iwldcard table entry?
  * @mcast_ip_addr: mcast ip address to be updated
  * @mcast_ip_addr_bytes: mcast ip addr bytes
- * @ucast_mac_addr: ucast peer mac subscribed to mcast ip
- * @filter_mode: filter mode
  * @nsrcs: number of entries in source list
+ * @filter_mode: filter mode
+ * @is_action_delete: is delete
+ * @is_filter_mode_snoop: is filter mode snoop
+ * @ucast_mac_addr: ucast peer mac subscribed to mcast ip
  * @srcs: source mac accpted
  * @mask: mask
  * @vap_id: vdev id
- * @is_action_delete: is delete
- * @is_filter_mode_snoop:
- * @is_mcast_addr_len:
+ * @is_mcast_addr_len: is mcast address length
  */
 struct mcast_group_update_params {
 	int action;
 	int wildcard;
 	uint8_t *mcast_ip_addr;
 	int mcast_ip_addr_bytes;
-	uint8_t *ucast_mac_addr;
-	uint8_t filter_mode;
 	uint8_t nsrcs;
+	uint8_t filter_mode;
+	bool is_action_delete;
+	bool is_filter_mode_snoop;
+	uint8_t *ucast_mac_addr;
 	uint8_t *srcs;
 	uint8_t *mask;
 	uint8_t vap_id;
-	bool is_action_delete;
-	bool is_filter_mode_snoop;
 	bool is_mcast_addr_len;
 };
 
@@ -3644,26 +3648,26 @@
  * struct rtt_meas_req_params - RTT measurement request params
  * @req_id: Request id
  * @vdev_id: vdev id
- * @sta_mac_addr: pointer to station mac address
- * @spoof_mac_addr: pointer to spoof mac address
  * @is_mode_na: 11NA
  * @is_mode_ac: AC
  * @is_bw_20: 20
  * @is_bw_40: 40
  * @is_bw_80: 80
+ * @sta_mac_addr: pointer to station mac address
+ * @spoof_mac_addr: pointer to spoof mac address
  * @num_probe_rqst: number of probe request
  * @channel_param: channel param
  */
 struct rtt_meas_req_params {
 	uint8_t req_id;
 	uint8_t vdev_id;
-	uint8_t *sta_mac_addr;
-	uint8_t *spoof_mac_addr;
 	bool is_mode_na;
 	bool is_mode_ac;
 	bool is_bw_20;
 	bool is_bw_40;
 	bool is_bw_80;
+	uint8_t *sta_mac_addr;
+	uint8_t *spoof_mac_addr;
 	uint32_t num_probe_rqst;
 	struct channel_param channel;
 };
@@ -3841,14 +3845,14 @@
  * struct wmi_host_peer_adv_stats - peer adv stats event structure
  * @peer_macaddr: mac address
  * @fcs_count: fcs count
- * @rx_bytes: rx bytes
  * @rx_count: rx count
+ * @rx_bytes: rx bytes
  */
 struct wmi_host_peer_adv_stats {
 	uint8_t peer_macaddr[QDF_MAC_ADDR_SIZE];
 	uint32_t fcs_count;
-	uint64_t rx_bytes;
 	uint32_t rx_count;
+	uint64_t rx_bytes;
 };
 
 /**
@@ -6874,13 +6878,13 @@
 /**
  * struct wmi_host_rf_characterization_event_param - rf characterization table
  * @freq: center frequency of primary channel (in MHz)
- * @bw: bandwidth of primary channel (in MHz)
  * @chan_metric: primary channel-specific metric
+ * @bw: bandwidth of primary channel (in MHz)
  */
 struct wmi_host_rf_characterization_event_param {
 	uint16_t freq;
-	wmi_host_channel_width bw;
 	uint8_t chan_metric;
+	wmi_host_channel_width bw;
 };
 
 /*
@@ -7680,6 +7684,38 @@
 	uint32_t vdev_id;
 	uint32_t map_precedence;
 };
+
+/**
+ * struct peer_vlan_config_param - peer vlan config command
+ * @tx_cmd: Tx command
+ * @rx_cmd: Rx command
+ * @tx_strip_insert: Strip or Insert vlan in Tx[0:Strip, 1: Insert]
+ * @tx_strip_insert_inner: Enable tx_strip_insert operation for inner vlan tag.
+ * @tx_strip_insert_outer: Enable tx_strip_insert operation for outer vlan tag.
+ * @rx_strip_c_tag: Strip c_tag
+ * @rx_strip_s_tag: Strip s_tag
+ * @rx_insert_c_tag: Insert c_tag
+ * @rx_insert_s_tag: Insert s_tag
+ *
+ * @insert_vlan_inner_tci: Vlan inner tci
+ * @insert_vlan_inner_tci: Vlan outer tci
+ *
+ * @vdev_id: vdev id corresponding to peer.
+ */
+struct peer_vlan_config_param {
+	uint16_t tx_cmd:1,
+		rx_cmd:1,
+		tx_strip_insert:1,
+		tx_strip_insert_inner:1,
+		tx_strip_insert_outer:1,
+		rx_strip_c_tag:1,
+		rx_strip_s_tag:1,
+		rx_insert_c_tag:1,
+		rx_insert_s_tag:1;
+	uint16_t insert_vlan_inner_tci;
+	uint16_t insert_vlan_outer_tci;
+	uint8_t vdev_id;
+};
 #endif
 
 /**
@@ -7747,27 +7783,27 @@
 /**
  * struct wmi_host_oem_indirect_data - Indirect OEM data
  * @pdev_id: pdev id
- * @addr: 36 bit address
  * @len: length of data in bytes
+ * @addr: 36 bit address
  */
 struct wmi_host_oem_indirect_data {
 	uint32_t pdev_id;
-	uint64_t addr;
 	uint32_t len;
+	uint64_t addr;
 };
 
 /**
  * struct wmi_oem_response_param - OEM response info
  * @num_data1: First data response length
- * @data_1: First data
  * @num_data2: Second data response length
+ * @data_1: First data
  * @data_2: Second data
  * @indirect_data: Indirect data
  */
 struct wmi_oem_response_param {
 	uint32_t num_data1;
-	uint8_t  *data_1;
 	uint32_t num_data2;
+	uint8_t  *data_1;
 	uint8_t  *data_2;
 	struct wmi_host_oem_indirect_data indirect_data;
 };
diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h
index 4713a5e..2b47c44 100644
--- a/wmi/inc/wmi_unified_priv.h
+++ b/wmi/inc/wmi_unified_priv.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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
@@ -2067,6 +2067,10 @@
 QDF_STATUS (*send_peer_ft_roam_cmd)(wmi_unified_t wmi_handle,
 				    uint8_t peer_addr[QDF_MAC_ADDR_SIZE],
 				    uint8_t vdev_id);
+QDF_STATUS (*send_peer_vlan_config_cmd)(wmi_unified_t wmi,
+					uint8_t peer_addr[QDF_MAC_ADDR_SIZE],
+					struct peer_vlan_config_param *param);
+
 #endif
 QDF_STATUS (*send_mws_coex_status_req_cmd)(wmi_unified_t wmi_handle,
 					   uint32_t vdev_id, uint32_t cmd_id);
diff --git a/wmi/src/wmi_unified.c b/wmi/src/wmi_unified.c
index f509dfa..f875249 100644
--- a/wmi/src/wmi_unified.c
+++ b/wmi/src/wmi_unified.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-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
@@ -27,6 +27,7 @@
 #include "qdf_platform.h"
 #ifdef WMI_EXT_DBG
 #include "qdf_list.h"
+#include "qdf_atomic.h"
 #endif
 
 #ifndef WMI_NON_TLV_SUPPORT
@@ -35,271 +36,6 @@
 
 #include <linux/debugfs.h>
 #include <target_if.h>
-#ifdef WMI_EXT_DBG
-#include "qdf_atomic.h"
-
-/**
- * wmi_ext_dbg_msg_enqueue() - enqueue wmi message
- *
- * @wmi_handle: wmi handler
- *
- * Return: size of wmi message queue after enqueue
- */
-static uint32_t wmi_ext_dbg_msg_enqueue(struct wmi_unified *wmi_handle,
-					struct wmi_ext_dbg_msg *msg)
-{
-	uint32_t list_size;
-
-	qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
-	qdf_list_insert_back_size(&wmi_handle->wmi_ext_dbg_msg_queue,
-				  &msg->node, &list_size);
-	qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
-
-	return list_size;
-}
-
-/**
- * wmi_ext_dbg_msg_dequeue() - dequeue wmi message
- *
- * @wmi_handle: wmi handler
- *
- * Return: wmi msg on success else NULL
- */
-static struct wmi_ext_dbg_msg *wmi_ext_dbg_msg_dequeue(struct wmi_unified
-						       *wmi_handle)
-{
-	qdf_list_node_t *list_node = NULL;
-
-	qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
-	qdf_list_remove_front(&wmi_handle->wmi_ext_dbg_msg_queue, &list_node);
-	qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
-
-	if (!list_node)
-		return NULL;
-
-	return qdf_container_of(list_node, struct wmi_ext_dbg_msg, node);
-}
-
-/**
- * wmi_ext_dbg_msg_record() - record wmi messages
- *
- * @wmi_handle: wmi handler
- * @buf: wmi message buffer
- * @len: wmi message length
- * @type: wmi message type
- *
- * Return: QDF_STATUS_SUCCESS on successful recording else failure.
- */
-static QDF_STATUS wmi_ext_dbg_msg_record(struct wmi_unified *wmi_handle,
-					 uint8_t *buf, uint32_t len,
-					 enum WMI_MSG_TYPE type)
-{
-	struct wmi_ext_dbg_msg *msg;
-	uint32_t list_size;
-
-	msg = wmi_ext_dbg_msg_get(len);
-	if (!msg)
-		return QDF_STATUS_E_NOMEM;
-
-	msg->len = len;
-	msg->type = type;
-	qdf_mem_copy(msg->buf, buf, len);
-	msg->ts = qdf_get_log_timestamp();
-	list_size = wmi_ext_dbg_msg_enqueue(wmi_handle, msg);
-
-	if (list_size >= wmi_handle->wmi_ext_dbg_msg_queue_size) {
-		msg = wmi_ext_dbg_msg_dequeue(wmi_handle);
-		wmi_ext_dbg_msg_put(msg);
-	}
-
-	return QDF_STATUS_SUCCESS;
-}
-
-/**
- * wmi_ext_dbg_msg_cmd_record() - record wmi command messages
- *
- * @wmi_handle: wmi handler
- * @buf: wmi command buffer
- * @len: wmi command message length
- *
- * Return: QDF_STATUS_SUCCESS on successful recording else failure.
- */
-static QDF_STATUS wmi_ext_dbg_msg_cmd_record(struct wmi_unified *wmi_handle,
-					     uint8_t *buf, uint32_t len)
-{
-	return wmi_ext_dbg_msg_record(wmi_handle, buf, len,
-				      WMI_MSG_TYPE_CMD);
-}
-
-/**
- * wmi_ext_dbg_msg_event_record() - record wmi event messages
- *
- * @wmi_handle: wmi handler
- * @buf: wmi event buffer
- * @len: wmi event message length
- *
- * Return: QDF_STATUS_SUCCESS on successful recording else failure.
- */
-static QDF_STATUS wmi_ext_dbg_msg_event_record(struct wmi_unified *wmi_handle,
-					       uint8_t *buf, uint32_t len)
-{
-	uint32_t id;
-
-	id = WMI_GET_FIELD(buf, WMI_CMD_HDR, COMMANDID);
-	if (id != wmi_handle->wmi_events[wmi_diag_event_id])
-		return wmi_ext_dbg_msg_record(wmi_handle, buf, len,
-					      WMI_MSG_TYPE_EVENT);
-
-	return QDF_STATUS_SUCCESS;
-}
-
-/**
- * wmi_ext_dbg_msg_queue_init() - create debugfs queue and associated lock
- *
- * @wmi_handle: wmi handler
- *
- * Return: none
- */
-static void wmi_ext_dbg_msg_queue_init(struct wmi_unified *wmi_handle)
-{
-	qdf_list_create(&wmi_handle->wmi_ext_dbg_msg_queue,
-			wmi_handle->wmi_ext_dbg_msg_queue_size);
-	qdf_spinlock_create(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
-}
-
-/**
- * wmi_ext_dbg_msg_queue_deinit() - destroy debugfs queue and associated lock
- *
- * @wmi_handle: wmi handler
- *
- * Return: none
- */
-static void wmi_ext_dbg_msg_queue_deinit(struct wmi_unified *wmi_handle)
-{
-	qdf_list_destroy(&wmi_handle->wmi_ext_dbg_msg_queue);
-	qdf_spinlock_destroy(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
-}
-
-/**
- * wmi_ext_dbg_msg_show() - debugfs function to display whole content of
- * wmi command/event messages including headers.
- *
- * @file: qdf debugfs file handler
- * @arg: pointer to wmi handler
- *
- * Return: QDF_STATUS_SUCCESS if all the messages are shown successfully,
- * else QDF_STATUS_E_AGAIN if more data to show.
- */
-static QDF_STATUS wmi_ext_dbg_msg_show(qdf_debugfs_file_t file, void *arg)
-{
-	struct wmi_unified *wmi_handle = (struct wmi_unified *)arg;
-	struct wmi_ext_dbg_msg *msg;
-	uint64_t secs, usecs;
-
-	msg = wmi_ext_dbg_msg_dequeue(wmi_handle);
-	if (!msg)
-		return QDF_STATUS_SUCCESS;
-
-	qdf_debugfs_printf(file, "%s: 0x%x\n",
-			   msg->type == WMI_MSG_TYPE_CMD ? "COMMAND" :
-			   "EVENT", WMI_GET_FIELD(msg->buf, WMI_CMD_HDR,
-						  COMMANDID));
-	qdf_log_timestamp_to_secs(msg->ts, &secs, &usecs);
-	qdf_debugfs_printf(file, "Time: %llu.%llu\n", secs, usecs);
-	qdf_debugfs_printf(file, "Length:%d\n", msg->len);
-	qdf_debugfs_hexdump(file, msg->buf, msg->len,
-			    WMI_EXT_DBG_DUMP_ROW_SIZE,
-			    WMI_EXT_DBG_DUMP_GROUP_SIZE);
-	qdf_debugfs_printf(file, "\n");
-
-	if (qdf_debugfs_overflow(file)) {
-		qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
-		qdf_list_insert_front(&wmi_handle->wmi_ext_dbg_msg_queue,
-				      &msg->node);
-		qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
-
-	} else {
-		wmi_ext_dbg_msg_put(msg);
-	}
-
-	return QDF_STATUS_E_AGAIN;
-}
-
-/**
- * wmi_ext_dbg_msg_write() - debugfs write not supported
- *
- * @priv: private data
- * @buf: received data buffer
- * @len: length of received buffer
- *
- * Return: QDF_STATUS_E_NOSUPPORT.
- */
-static QDF_STATUS wmi_ext_dbg_msg_write(void *priv, const char *buf,
-					qdf_size_t len)
-{
-	return QDF_STATUS_E_NOSUPPORT;
-}
-
-static struct qdf_debugfs_fops wmi_ext_dbgfs_ops = {
-	.show		= wmi_ext_dbg_msg_show,
-	.write		= wmi_ext_dbg_msg_write,
-	.priv		= NULL,
-};
-
-/**
- * wmi_ext_debugfs_init() - init debugfs items for extended wmi dump.
- *
- * @wmi_handle: wmi handler
- *
- * Return: QDF_STATUS_SUCCESS if debugfs is initialized else
- * QDF_STATUS_E_FAILURE
- */
-static QDF_STATUS wmi_ext_dbgfs_init(struct wmi_unified *wmi_handle)
-{
-	qdf_dentry_t dentry;
-
-	dentry  = qdf_debugfs_create_dir(WMI_EXT_DBG_DIR, NULL);
-	if (!dentry) {
-		WMI_LOGE("error while creating extended wmi debugfs dir");
-		return QDF_STATUS_E_FAILURE;
-	}
-
-	wmi_ext_dbgfs_ops.priv = wmi_handle;
-	if (!qdf_debugfs_create_file(WMI_EXT_DBG_FILE, WMI_EXT_DBG_FILE_PERM,
-				     dentry, &wmi_ext_dbgfs_ops)) {
-		qdf_debugfs_remove_dir(dentry);
-		WMI_LOGE("error while creating extended wmi debugfs file");
-		return QDF_STATUS_E_FAILURE;
-	}
-
-	wmi_handle->wmi_ext_dbg_dentry = dentry;
-	wmi_handle->wmi_ext_dbg_msg_queue_size = WMI_EXT_DBG_QUEUE_SIZE;
-	wmi_ext_dbg_msg_queue_init(wmi_handle);
-
-	return QDF_STATUS_SUCCESS;
-}
-
-/**
- * wmi_ext_debugfs_deinit() - cleanup/deinit debugfs items of extended wmi dump.
- *
- * @wmi_handle: wmi handler
- *
- * Return: QDF_STATUS_SUCCESS if cleanup is successful
- */
-static QDF_STATUS wmi_ext_dbgfs_deinit(struct wmi_unified *wmi_handle)
-{
-	struct wmi_ext_dbg_msg *msg;
-
-	while ((msg = wmi_ext_dbg_msg_dequeue(wmi_handle)))
-		wmi_ext_dbg_msg_put(msg);
-
-	wmi_ext_dbg_msg_queue_deinit(wmi_handle);
-	qdf_debugfs_remove_dir_recursive(wmi_handle->wmi_ext_dbg_dentry);
-
-	return QDF_STATUS_SUCCESS;
-}
-
-#endif /*WMI_EXT_DBG */
 
 /* This check for CONFIG_WIN temporary added due to redeclaration compilation
 error in MCL. Error is caused due to inclusion of wmi.h in wmi_unified_api.h
@@ -591,6 +327,271 @@
 uint32_t wmi_record_max_length = WMI_EVENT_DEBUG_ENTRY_MAX_LENGTH;
 uint32_t wmi_display_size = 100;
 
+#ifdef WMI_EXT_DBG
+
+/**
+ * wmi_ext_dbg_msg_enqueue() - enqueue wmi message
+ *
+ * @wmi_handle: wmi handler
+ *
+ * Return: size of wmi message queue after enqueue
+ */
+static uint32_t wmi_ext_dbg_msg_enqueue(struct wmi_unified *wmi_handle,
+					struct wmi_ext_dbg_msg *msg)
+{
+	uint32_t list_size;
+
+	qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
+	qdf_list_insert_back_size(&wmi_handle->wmi_ext_dbg_msg_queue,
+				  &msg->node, &list_size);
+	qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
+
+	return list_size;
+}
+
+/**
+ * wmi_ext_dbg_msg_dequeue() - dequeue wmi message
+ *
+ * @wmi_handle: wmi handler
+ *
+ * Return: wmi msg on success else NULL
+ */
+static struct wmi_ext_dbg_msg *wmi_ext_dbg_msg_dequeue(struct wmi_unified
+						       *wmi_handle)
+{
+	qdf_list_node_t *list_node = NULL;
+
+	qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
+	qdf_list_remove_front(&wmi_handle->wmi_ext_dbg_msg_queue, &list_node);
+	qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
+
+	if (!list_node)
+		return NULL;
+
+	return qdf_container_of(list_node, struct wmi_ext_dbg_msg, node);
+}
+
+/**
+ * wmi_ext_dbg_msg_record() - record wmi messages
+ *
+ * @wmi_handle: wmi handler
+ * @buf: wmi message buffer
+ * @len: wmi message length
+ * @type: wmi message type
+ *
+ * Return: QDF_STATUS_SUCCESS on successful recording else failure.
+ */
+static QDF_STATUS wmi_ext_dbg_msg_record(struct wmi_unified *wmi_handle,
+					 uint8_t *buf, uint32_t len,
+					 enum WMI_MSG_TYPE type)
+{
+	struct wmi_ext_dbg_msg *msg;
+	uint32_t list_size;
+
+	msg = wmi_ext_dbg_msg_get(len);
+	if (!msg)
+		return QDF_STATUS_E_NOMEM;
+
+	msg->len = len;
+	msg->type = type;
+	qdf_mem_copy(msg->buf, buf, len);
+	msg->ts = qdf_get_log_timestamp();
+	list_size = wmi_ext_dbg_msg_enqueue(wmi_handle, msg);
+
+	if (list_size >= wmi_handle->wmi_ext_dbg_msg_queue_size) {
+		msg = wmi_ext_dbg_msg_dequeue(wmi_handle);
+		wmi_ext_dbg_msg_put(msg);
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * wmi_ext_dbg_msg_cmd_record() - record wmi command messages
+ *
+ * @wmi_handle: wmi handler
+ * @buf: wmi command buffer
+ * @len: wmi command message length
+ *
+ * Return: QDF_STATUS_SUCCESS on successful recording else failure.
+ */
+static QDF_STATUS wmi_ext_dbg_msg_cmd_record(struct wmi_unified *wmi_handle,
+					     uint8_t *buf, uint32_t len)
+{
+	return wmi_ext_dbg_msg_record(wmi_handle, buf, len,
+				      WMI_MSG_TYPE_CMD);
+}
+
+/**
+ * wmi_ext_dbg_msg_event_record() - record wmi event messages
+ *
+ * @wmi_handle: wmi handler
+ * @buf: wmi event buffer
+ * @len: wmi event message length
+ *
+ * Return: QDF_STATUS_SUCCESS on successful recording else failure.
+ */
+static QDF_STATUS wmi_ext_dbg_msg_event_record(struct wmi_unified *wmi_handle,
+					       uint8_t *buf, uint32_t len)
+{
+	uint32_t id;
+
+	id = WMI_GET_FIELD(buf, WMI_CMD_HDR, COMMANDID);
+	if (id != wmi_handle->wmi_events[wmi_diag_event_id])
+		return wmi_ext_dbg_msg_record(wmi_handle, buf, len,
+					      WMI_MSG_TYPE_EVENT);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * wmi_ext_dbg_msg_queue_init() - create debugfs queue and associated lock
+ *
+ * @wmi_handle: wmi handler
+ *
+ * Return: none
+ */
+static void wmi_ext_dbg_msg_queue_init(struct wmi_unified *wmi_handle)
+{
+	qdf_list_create(&wmi_handle->wmi_ext_dbg_msg_queue,
+			wmi_handle->wmi_ext_dbg_msg_queue_size);
+	qdf_spinlock_create(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
+}
+
+/**
+ * wmi_ext_dbg_msg_queue_deinit() - destroy debugfs queue and associated lock
+ *
+ * @wmi_handle: wmi handler
+ *
+ * Return: none
+ */
+static void wmi_ext_dbg_msg_queue_deinit(struct wmi_unified *wmi_handle)
+{
+	qdf_list_destroy(&wmi_handle->wmi_ext_dbg_msg_queue);
+	qdf_spinlock_destroy(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
+}
+
+/**
+ * wmi_ext_dbg_msg_show() - debugfs function to display whole content of
+ * wmi command/event messages including headers.
+ *
+ * @file: qdf debugfs file handler
+ * @arg: pointer to wmi handler
+ *
+ * Return: QDF_STATUS_SUCCESS if all the messages are shown successfully,
+ * else QDF_STATUS_E_AGAIN if more data to show.
+ */
+static QDF_STATUS wmi_ext_dbg_msg_show(qdf_debugfs_file_t file, void *arg)
+{
+	struct wmi_unified *wmi_handle = (struct wmi_unified *)arg;
+	struct wmi_ext_dbg_msg *msg;
+	uint64_t secs, usecs;
+
+	msg = wmi_ext_dbg_msg_dequeue(wmi_handle);
+	if (!msg)
+		return QDF_STATUS_SUCCESS;
+
+	qdf_debugfs_printf(file, "%s: 0x%x\n",
+			   msg->type == WMI_MSG_TYPE_CMD ? "COMMAND" :
+			   "EVENT", WMI_GET_FIELD(msg->buf, WMI_CMD_HDR,
+						  COMMANDID));
+	qdf_log_timestamp_to_secs(msg->ts, &secs, &usecs);
+	qdf_debugfs_printf(file, "Time: %llu.%llu\n", secs, usecs);
+	qdf_debugfs_printf(file, "Length:%d\n", msg->len);
+	qdf_debugfs_hexdump(file, msg->buf, msg->len,
+			    WMI_EXT_DBG_DUMP_ROW_SIZE,
+			    WMI_EXT_DBG_DUMP_GROUP_SIZE);
+	qdf_debugfs_printf(file, "\n");
+
+	if (qdf_debugfs_overflow(file)) {
+		qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
+		qdf_list_insert_front(&wmi_handle->wmi_ext_dbg_msg_queue,
+				      &msg->node);
+		qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
+
+	} else {
+		wmi_ext_dbg_msg_put(msg);
+	}
+
+	return QDF_STATUS_E_AGAIN;
+}
+
+/**
+ * wmi_ext_dbg_msg_write() - debugfs write not supported
+ *
+ * @priv: private data
+ * @buf: received data buffer
+ * @len: length of received buffer
+ *
+ * Return: QDF_STATUS_E_NOSUPPORT.
+ */
+static QDF_STATUS wmi_ext_dbg_msg_write(void *priv, const char *buf,
+					qdf_size_t len)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+
+static struct qdf_debugfs_fops wmi_ext_dbgfs_ops = {
+	.show		= wmi_ext_dbg_msg_show,
+	.write		= wmi_ext_dbg_msg_write,
+	.priv		= NULL,
+};
+
+/**
+ * wmi_ext_debugfs_init() - init debugfs items for extended wmi dump.
+ *
+ * @wmi_handle: wmi handler
+ *
+ * Return: QDF_STATUS_SUCCESS if debugfs is initialized else
+ * QDF_STATUS_E_FAILURE
+ */
+static QDF_STATUS wmi_ext_dbgfs_init(struct wmi_unified *wmi_handle)
+{
+	qdf_dentry_t dentry;
+
+	dentry  = qdf_debugfs_create_dir(WMI_EXT_DBG_DIR, NULL);
+	if (!dentry) {
+		WMI_LOGE("error while creating extended wmi debugfs dir");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	wmi_ext_dbgfs_ops.priv = wmi_handle;
+	if (!qdf_debugfs_create_file(WMI_EXT_DBG_FILE, WMI_EXT_DBG_FILE_PERM,
+				     dentry, &wmi_ext_dbgfs_ops)) {
+		qdf_debugfs_remove_dir(dentry);
+		WMI_LOGE("error while creating extended wmi debugfs file");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	wmi_handle->wmi_ext_dbg_dentry = dentry;
+	wmi_handle->wmi_ext_dbg_msg_queue_size = WMI_EXT_DBG_QUEUE_SIZE;
+	wmi_ext_dbg_msg_queue_init(wmi_handle);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * wmi_ext_debugfs_deinit() - cleanup/deinit debugfs items of extended wmi dump.
+ *
+ * @wmi_handle: wmi handler
+ *
+ * Return: QDF_STATUS_SUCCESS if cleanup is successful
+ */
+static QDF_STATUS wmi_ext_dbgfs_deinit(struct wmi_unified *wmi_handle)
+{
+	struct wmi_ext_dbg_msg *msg;
+
+	while ((msg = wmi_ext_dbg_msg_dequeue(wmi_handle)))
+		wmi_ext_dbg_msg_put(msg);
+
+	wmi_ext_dbg_msg_queue_deinit(wmi_handle);
+	qdf_debugfs_remove_dir_recursive(wmi_handle->wmi_ext_dbg_dentry);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+#endif /*WMI_EXT_DBG */
+
 /**
  * wmi_log_init() - Initialize WMI event logging
  * @wmi_handle: WMI handle.
@@ -1808,6 +1809,7 @@
 		wmi_nofl_err("%s:%d, MAX %d WMI Pending cmds reached",
 			     func, line, wmi_handle->wmi_max_cmds);
 		wmi_unified_debug_dump(wmi_handle);
+		htc_ce_tasklet_debug_dump(wmi_handle->htc_handle);
 		qdf_trigger_self_recovery(QDF_WMI_EXCEED_MAX_PENDING_CMDS);
 		return QDF_STATUS_E_BUSY;
 	}