qcacmn: Move mgmt descriptors per pdev for probe response throttling

Mgmt tx rx descriptors are now used instead of WMI descriptors
for management Tx/Rx.
Since WMI descriptors were per radio to support probe response throttling
the mgmt descriptors should also be moved from per psoc to per pdev.

The reason for this is probe response throttling should happen per radio
and not per psoc since if the mgmt frames peding counter is
maintained per psoc, it could affect other radios of the same psoc also.

The maximum number of mgmt descriptors per psoc was 50.
This is also changed to 512 mgmt descriptors per pdev which is the
same as WMI descriptors per radio as used earlier to support
probe response throttling.

Change-Id: Ibb46082e0acf340800418a7e9689a29cd688bdab
CRs-Fixed: 2146177
diff --git a/umac/cmn_services/inc/wlan_cmn.h b/umac/cmn_services/inc/wlan_cmn.h
index 701cfc7..4471084 100644
--- a/umac/cmn_services/inc/wlan_cmn.h
+++ b/umac/cmn_services/inc/wlan_cmn.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 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,10 @@
 /* Invalid pdev_id */
 #define WLAN_INVALID_PDEV_ID 0xFFFFFFFF
 
+/* Invalid free descriptor count */
+#define WLAN_INVALID_MGMT_DESC_COUNT 0xFFFFFFFF
+
+/* 802.11 cap info */
 /* 802.11 cap info */
 #define WLAN_CAPINFO_ESS               0x0001
 #define WLAN_CAPINFO_IBSS              0x0002
diff --git a/umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main.c b/umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main.c
index c3b3372..9c4edcd 100644
--- a/umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main.c
+++ b/umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 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
@@ -26,7 +26,7 @@
 #include "qdf_nbuf.h"
 
 QDF_STATUS wlan_mgmt_txrx_desc_pool_init(
-			struct mgmt_txrx_priv_context *mgmt_txrx_ctx,
+			struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx,
 			uint32_t pool_size)
 {
 	uint32_t i;
@@ -37,88 +37,93 @@
 		return QDF_STATUS_E_INVAL;
 	}
 
-	mgmt_txrx_info("mgmt_txrx ctx: %pK psoc: %pK, initialize mgmt desc pool of size %d",
-				mgmt_txrx_ctx, mgmt_txrx_ctx->psoc, pool_size);
-	mgmt_txrx_ctx->mgmt_desc_pool.pool = qdf_mem_malloc(pool_size *
-					sizeof(struct mgmt_txrx_desc_elem_t));
+	mgmt_txrx_info(
+			"mgmt_txrx ctx: %pK pdev: %pK"
+			"initialize mgmt desc pool of size %d",
+			mgmt_txrx_pdev_ctx, mgmt_txrx_pdev_ctx->pdev, pool_size);
+	mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool = qdf_mem_malloc(pool_size *
+			sizeof(struct mgmt_txrx_desc_elem_t));
 
-	if (!mgmt_txrx_ctx->mgmt_desc_pool.pool) {
+	if (!mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool) {
 		mgmt_txrx_err("Failed to allocate desc pool");
 		return QDF_STATUS_E_NOMEM;
 	}
-	qdf_list_create(&mgmt_txrx_ctx->mgmt_desc_pool.free_list, pool_size);
+	qdf_list_create(&mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list,
+					pool_size);
 
 	for (i = 0; i < pool_size; i++) {
-		mgmt_txrx_ctx->mgmt_desc_pool.pool[i].desc_id = i;
-		mgmt_txrx_ctx->mgmt_desc_pool.pool[i].in_use = false;
-		qdf_list_insert_front(&mgmt_txrx_ctx->mgmt_desc_pool.free_list,
-				&mgmt_txrx_ctx->mgmt_desc_pool.pool[i].entry);
+		mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[i].desc_id = i;
+		mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[i].in_use = false;
+		qdf_list_insert_front(
+				&mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list,
+				&mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[i].entry);
 	}
 
 	qdf_spinlock_create(
-		&mgmt_txrx_ctx->mgmt_desc_pool.desc_pool_lock);
+		&mgmt_txrx_pdev_ctx->mgmt_desc_pool.desc_pool_lock);
 
 	return QDF_STATUS_SUCCESS;
 }
 
 void wlan_mgmt_txrx_desc_pool_deinit(
-			struct mgmt_txrx_priv_context *mgmt_txrx_ctx)
+			struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx)
 {
-	uint8_t i;
+	uint32_t i;
 	uint32_t pool_size;
 	QDF_STATUS status;
 
-	if (!mgmt_txrx_ctx->mgmt_desc_pool.pool) {
+	if (!mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool) {
 		mgmt_txrx_err("Empty mgmt descriptor pool");
 		qdf_assert_always(0);
 		return;
 	}
 
-	pool_size = mgmt_txrx_ctx->mgmt_desc_pool.free_list.max_size;
+	pool_size = mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list.max_size;
 	for (i = 0; i < pool_size; i++) {
 		status = qdf_list_remove_node(
-				&mgmt_txrx_ctx->mgmt_desc_pool.free_list,
-				&mgmt_txrx_ctx->mgmt_desc_pool.pool[i].entry);
+				&mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list,
+				&mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[i].entry);
 		if (status != QDF_STATUS_SUCCESS)
-			mgmt_txrx_err("Failed to get mgmt descriptor from freelist, desc id: %d with status %d",
-					i, status);
+			mgmt_txrx_err(
+				"Failed to get mgmt desc from freelist, desc id: %d: status %d",
+				i, status);
 	}
 
-	qdf_list_destroy(&mgmt_txrx_ctx->mgmt_desc_pool.free_list);
-	qdf_mem_free(mgmt_txrx_ctx->mgmt_desc_pool.pool);
-	mgmt_txrx_ctx->mgmt_desc_pool.pool = NULL;
+	qdf_list_destroy(&mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list);
+	qdf_mem_free(mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool);
+	mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool = NULL;
 
 	qdf_spinlock_destroy(
-		&mgmt_txrx_ctx->mgmt_desc_pool.desc_pool_lock);
+		&mgmt_txrx_pdev_ctx->mgmt_desc_pool.desc_pool_lock);
 }
 
 struct mgmt_txrx_desc_elem_t *wlan_mgmt_txrx_desc_get(
-			struct mgmt_txrx_priv_context *mgmt_txrx_ctx)
+			struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx)
 {
 	QDF_STATUS status;
 	qdf_list_node_t *desc_node;
 	struct mgmt_txrx_desc_elem_t *mgmt_txrx_desc;
 
-	qdf_spin_lock_bh(&mgmt_txrx_ctx->mgmt_desc_pool.desc_pool_lock);
-	if (qdf_list_peek_front(&mgmt_txrx_ctx->mgmt_desc_pool.free_list,
+	qdf_spin_lock_bh(&mgmt_txrx_pdev_ctx->mgmt_desc_pool.desc_pool_lock);
+	if (qdf_list_peek_front(&mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list,
 			    &desc_node)
 			!= QDF_STATUS_SUCCESS) {
 		qdf_spin_unlock_bh(
-			&mgmt_txrx_ctx->mgmt_desc_pool.desc_pool_lock);
+			&mgmt_txrx_pdev_ctx->mgmt_desc_pool.desc_pool_lock);
 		mgmt_txrx_err("Descriptor freelist empty for mgmt_txrx_ctx %pK",
-				mgmt_txrx_ctx);
+				mgmt_txrx_pdev_ctx);
 		return NULL;
 	}
 
-	status = qdf_list_remove_node(&mgmt_txrx_ctx->mgmt_desc_pool.free_list,
-			     desc_node);
+	status = qdf_list_remove_node(
+				&mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list,
+				desc_node);
 	if (status != QDF_STATUS_SUCCESS) {
 		qdf_spin_unlock_bh(
-			&mgmt_txrx_ctx->mgmt_desc_pool.desc_pool_lock);
+			&mgmt_txrx_pdev_ctx->mgmt_desc_pool.desc_pool_lock);
 		mgmt_txrx_err("Failed to get descriptor from list: status %d",
 					status);
 		qdf_assert_always(0);
-		return NULL;
 	}
 
 	mgmt_txrx_desc = qdf_container_of(desc_node,
@@ -127,34 +132,35 @@
 	mgmt_txrx_desc->in_use = true;
 
 	/* acquire the wakelock when there are pending mgmt tx frames */
-	qdf_wake_lock_timeout_acquire(&mgmt_txrx_ctx->wakelock_tx_cmp,
+	qdf_wake_lock_timeout_acquire(&mgmt_txrx_pdev_ctx->wakelock_tx_cmp,
 				      MGMT_TXRX_WAKELOCK_TIMEOUT_TX_CMP);
 
-	qdf_spin_unlock_bh(&mgmt_txrx_ctx->mgmt_desc_pool.desc_pool_lock);
+	qdf_spin_unlock_bh(&mgmt_txrx_pdev_ctx->mgmt_desc_pool.desc_pool_lock);
 
 	mgmt_txrx_info("retrieved mgmt desc: %pK with desc id: %d",
 			mgmt_txrx_desc, mgmt_txrx_desc->desc_id);
 	return mgmt_txrx_desc;
 }
 
-void wlan_mgmt_txrx_desc_put(struct mgmt_txrx_priv_context *mgmt_txrx_ctx,
+void wlan_mgmt_txrx_desc_put(
+			struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx,
 			uint32_t desc_id)
 {
 	struct mgmt_txrx_desc_elem_t *desc;
 
-	desc = &mgmt_txrx_ctx->mgmt_desc_pool.pool[desc_id];
-	qdf_spin_lock_bh(&mgmt_txrx_ctx->mgmt_desc_pool.desc_pool_lock);
+	desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[desc_id];
+	qdf_spin_lock_bh(&mgmt_txrx_pdev_ctx->mgmt_desc_pool.desc_pool_lock);
 	desc->in_use = false;
-	qdf_list_insert_front(&mgmt_txrx_ctx->mgmt_desc_pool.free_list,
+	qdf_list_insert_front(&mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list,
 			      &desc->entry);
 
 	/* release the wakelock if there are no pending mgmt tx frames */
-	if (mgmt_txrx_ctx->mgmt_desc_pool.free_list.count ==
-	    mgmt_txrx_ctx->mgmt_desc_pool.free_list.max_size)
-		qdf_wake_lock_release(&mgmt_txrx_ctx->wakelock_tx_cmp,
+	if (mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list.count ==
+	    mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list.max_size)
+		qdf_wake_lock_release(&mgmt_txrx_pdev_ctx->wakelock_tx_cmp,
 				      MGMT_TXRX_WAKELOCK_REASON_TX_CMP);
 
-	qdf_spin_unlock_bh(&mgmt_txrx_ctx->mgmt_desc_pool.desc_pool_lock);
+	qdf_spin_unlock_bh(&mgmt_txrx_pdev_ctx->mgmt_desc_pool.desc_pool_lock);
 
 	mgmt_txrx_info("put mgmt desc: %pK with desc id: %d into freelist",
 			desc, desc->desc_id);
diff --git a/umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main_i.h b/umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main_i.h
index c6ae58c..d293944 100644
--- a/umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main_i.h
+++ b/umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main_i.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 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
@@ -170,26 +170,35 @@
 };
 
 /**
- * struct mgmt_txrx_priv_context - mgmt txrx private context
- * @psoc_context:     psoc context
- * @mgmt_rx_comp_cb:  array of pointers of mgmt rx cbs
+ * struct mgmt_txrx_priv_psoc_context - mgmt txrx private psoc context
+ * @psoc:                psoc context
+ * @mgmt_rx_comp_cb:     array of pointers of mgmt rx cbs
+ * @mgmt_txrx_psoc_ctx_lock:  mgmt txrx psoc ctx lock
+ */
+struct mgmt_txrx_priv_psoc_context {
+	struct wlan_objmgr_psoc *psoc;
+	struct mgmt_rx_handler *mgmt_rx_comp_cb[MGMT_MAX_FRAME_TYPE];
+	qdf_spinlock_t mgmt_txrx_psoc_ctx_lock;
+};
+
+/**
+ * struct mgmt_txrx_priv_context_dev - mgmt txrx private context
+ * @pdev:     pdev context
  * @mgmt_desc_pool:   pointer to mgmt desc. pool
  * @mgmt_txrx_stats:  pointer to mgmt txrx stats
  * @wakelock_tx_cmp:  mgmt tx complete wake lock
  */
-struct mgmt_txrx_priv_context {
-	struct wlan_objmgr_psoc *psoc;
-	struct mgmt_rx_handler *mgmt_rx_comp_cb[MGMT_MAX_FRAME_TYPE];
+struct mgmt_txrx_priv_pdev_context {
+	struct wlan_objmgr_pdev *pdev;
 	struct mgmt_desc_pool_t mgmt_desc_pool;
 	struct mgmt_txrx_stats_t *mgmt_txrx_stats;
-	qdf_spinlock_t mgmt_txrx_ctx_lock;
 	qdf_wake_lock_t wakelock_tx_cmp;
 };
 
 
 /**
  * wlan_mgmt_txrx_desc_pool_init() - initializes mgmt. desc. pool
- * @mgmt_txrx_ctx: mgmt txrx context
+ * @mgmt_txrx_pdev_ctx: mgmt txrx pdev context
  * @pool_size: desc. pool size
  *
  * This function initializes the mgmt descriptor pool.
@@ -197,23 +206,23 @@
  * Return: QDF_STATUS_SUCCESS - in case of success
  */
 QDF_STATUS wlan_mgmt_txrx_desc_pool_init(
-			struct mgmt_txrx_priv_context *mgmt_txrx_ctx,
+			struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx,
 			uint32_t pool_size);
 
 /**
  * wlan_mgmt_txrx_desc_pool_deinit() - deinitializes mgmt. desc. pool
- * @mgmt_txrx_ctx: mgmt txrx context
+ * @mgmt_txrx_pdev_ctx: mgmt txrx pdev context
  *
  * This function deinitializes the mgmt descriptor pool.
  *
  * Return: void
  */
 void wlan_mgmt_txrx_desc_pool_deinit(
-			struct mgmt_txrx_priv_context *mgmt_txrx_ctx);
+			struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx);
 
 /**
  * wlan_mgmt_txrx_desc_get() - gets mgmt. descriptor from freelist
- * @mgmt_txrx_ctx: mgmt txrx context
+ * @mgmt_txrx_pdev_ctx: mgmt txrx pdev context
  *
  * This function retrieves the mgmt. descriptor for mgmt. tx frames
  * from the mgmt. descriptor freelist.
@@ -221,18 +230,19 @@
  * Return: mgmt. descriptor retrieved.
  */
 struct mgmt_txrx_desc_elem_t *wlan_mgmt_txrx_desc_get(
-			struct mgmt_txrx_priv_context *mgmt_txrx_ctx);
+			struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx);
 
 /**
  * wlan_mgmt_txrx_desc_put() - puts mgmt. descriptor back in freelist
- * @mgmt_txrx_ctx: mgmt txrx context
+ * @mgmt_txrx_pdev_ctx: mgmt txrx pdev context
  * @desc_id: mgmt txrx descriptor id
  *
  * This function puts the mgmt. descriptor back in to the freelist.
  *
  * Return: void
  */
-void wlan_mgmt_txrx_desc_put(struct mgmt_txrx_priv_context *mgmt_txrx_ctx,
-			     uint32_t desc_id);
+void wlan_mgmt_txrx_desc_put(
+			struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx,
+			uint32_t desc_id);
 
 #endif
diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_tgt_api.h b/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_tgt_api.h
index 91fdff3..9505cea 100644
--- a/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_tgt_api.h
+++ b/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_tgt_api.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 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,7 +50,7 @@
 
 /**
  * tgt_mgmt_txrx_tx_completion_handler() - handles mgmt. tx completions
- * @psoc: psoc context
+ * @pdev: pdev context
  * @desc_id: mgmt desc. id
  * @status: status of download of tx packet
  * @tx_compl_params: tx completion params
@@ -62,13 +62,13 @@
  * Return: QDF_STATUS_SUCCESS - in case of success
  */
 QDF_STATUS tgt_mgmt_txrx_tx_completion_handler(
-			struct wlan_objmgr_psoc *psoc,
+			struct wlan_objmgr_pdev *pdev,
 			uint32_t desc_id, uint32_t status,
 			void *tx_compl_params);
 
 /**
  * tgt_mgmt_txrx_get_nbuf_from_desc_id() - extracts nbuf from mgmt desc
- * @psoc: psoc context
+ * @pdev: pdev context
  * @desc_id: desc_id
  *
  * This function extracts nbuf from mgmt desc extracted from desc id.
@@ -77,12 +77,12 @@
  *         NULL - in case of failure
  */
 qdf_nbuf_t tgt_mgmt_txrx_get_nbuf_from_desc_id(
-			struct wlan_objmgr_psoc *psoc,
+			struct wlan_objmgr_pdev *pdev,
 			uint32_t desc_id);
 
 /**
  * tgt_mgmt_txrx_get_peer_from_desc_id() - extracts peer from mgmt desc
- * @psoc: psoc context
+ * @pdev: pdev context
  * @desc_id: desc_id
  *
  * This function extracts peer from mgmt desc extracted from desc id.
@@ -92,12 +92,12 @@
  */
 struct wlan_objmgr_peer *
 tgt_mgmt_txrx_get_peer_from_desc_id(
-			struct wlan_objmgr_psoc *psoc,
+			struct wlan_objmgr_pdev *pdev,
 			uint32_t desc_id);
 
 /**
  * tgt_mgmt_txrx_get_vdev_id_from_desc_id() - extracts vdev id from mgmt desc
- * @psoc: psoc context
+ * @pdev: pdev context
  * @desc_id: desc_id
  *
  * This function extracts vdev id from mgmt desc extracted from desc id.
@@ -106,7 +106,18 @@
  *         WLAN_UMAC_VDEV_ID_MAX - in case of failure
  */
 uint8_t tgt_mgmt_txrx_get_vdev_id_from_desc_id(
-			struct wlan_objmgr_psoc *psoc,
+			struct wlan_objmgr_pdev *pdev,
 			uint32_t desc_id);
 
+/**
+ * tgt_mgmt_txrx_get_free_desc_pool_count() - get free mgmt desc count
+ * @pdev: pdev context
+ *
+ * This function returns the count of free mgmt descriptors.
+ *
+ * Return:  free descpriptor count
+ */
+uint32_t tgt_mgmt_txrx_get_free_desc_pool_count(
+			struct wlan_objmgr_pdev *pdev);
+
 #endif
diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h b/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h
index db96b25..fcbbf28 100644
--- a/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h
+++ b/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 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
@@ -30,11 +30,7 @@
 #include "wlan_objmgr_cmn.h"
 #include "qdf_nbuf.h"
 
-/**
- * Current HTC credit is 2 so pool size of 50 is sufficient as non
- * converged code will still be using similar implementation from WMA path
- */
-#define MGMT_DESC_POOL_MAX 50
+#define MGMT_DESC_POOL_MAX 512
 
 #define mgmt_txrx_log(level, args...) \
 			QDF_TRACE(QDF_MODULE_ID_MGMT_TXRX, level, ## args)
diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c
index 2750953..59981c8 100644
--- a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c
+++ b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 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 "../../core/src/wlan_mgmt_txrx_main_i.h"
 #include "wlan_objmgr_psoc_obj.h"
 #include "wlan_objmgr_peer_obj.h"
+#include "wlan_objmgr_pdev_obj.h"
 
 
 /**
@@ -809,7 +810,7 @@
 			qdf_nbuf_t buf,
 			struct mgmt_rx_event_params *mgmt_rx_params)
 {
-	struct mgmt_txrx_priv_context *mgmt_txrx_ctx;
+	struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx;
 	struct ieee80211_frame *wh;
 	qdf_nbuf_t copy_buf;
 	struct wlan_objmgr_peer *peer = NULL;
@@ -876,45 +877,46 @@
 		goto dec_peer_ref_cnt;
 	}
 
-	mgmt_txrx_info("Rcvd mgmt frame, mgmt txrx frm type: %u, seq. no.: %u, peer: %pK",
+	mgmt_txrx_info("Rcvd mgmt frame, mgmt txrx frm type: %u"
+			"seq. no.: %u, peer: %pK",
 			frm_type, *(uint16_t *)wh->i_seq, peer);
 
-	mgmt_txrx_ctx = (struct mgmt_txrx_priv_context *)
+	mgmt_txrx_psoc_ctx = (struct mgmt_txrx_priv_psoc_context *)
 			wlan_objmgr_psoc_get_comp_private_obj(psoc,
 				WLAN_UMAC_COMP_MGMT_TXRX);
 
-	qdf_spin_lock_bh(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
-	rx_handler = mgmt_txrx_ctx->mgmt_rx_comp_cb[frm_type];
+	qdf_spin_lock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
+	rx_handler = mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[frm_type];
 	if (rx_handler) {
 		status = wlan_mgmt_txrx_rx_handler_list_copy(rx_handler,
 				&rx_handler_head, &rx_handler_tail);
 		if (status != QDF_STATUS_SUCCESS) {
-			qdf_spin_unlock_bh(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
+			qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
 			qdf_nbuf_free(buf);
 			goto rx_handler_mem_free;
 		}
 	}
 
-	rx_handler = mgmt_txrx_ctx->mgmt_rx_comp_cb[MGMT_FRAME_TYPE_ALL];
+	rx_handler = mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[MGMT_FRAME_TYPE_ALL];
 	if (rx_handler) {
 		status = wlan_mgmt_txrx_rx_handler_list_copy(rx_handler,
 				&rx_handler_head, &rx_handler_tail);
 		if (status != QDF_STATUS_SUCCESS) {
-			qdf_spin_unlock_bh(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
+			qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
 			qdf_nbuf_free(buf);
 			goto rx_handler_mem_free;
 		}
 	}
 
 	if (!rx_handler_head) {
-		qdf_spin_unlock_bh(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
+		qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
 		mgmt_txrx_info("No rx callback registered for frm_type: %d",
 			frm_type);
 		qdf_nbuf_free(buf);
 		status = QDF_STATUS_E_FAILURE;
 		goto dec_peer_ref_cnt;
 	}
-	qdf_spin_unlock_bh(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
+	qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
 
 	rx_handler = rx_handler_head;
 	while (rx_handler->next) {
@@ -940,28 +942,28 @@
 }
 
 QDF_STATUS tgt_mgmt_txrx_tx_completion_handler(
-			struct wlan_objmgr_psoc *psoc,
+			struct wlan_objmgr_pdev *pdev,
 			uint32_t desc_id, uint32_t status,
 			void *tx_compl_params)
 {
-	struct mgmt_txrx_priv_context *mgmt_txrx_ctx;
+	struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx;
 	struct mgmt_txrx_desc_elem_t *mgmt_desc;
 	void *cb_context;
 	mgmt_tx_download_comp_cb tx_compl_cb;
 	mgmt_ota_comp_cb  ota_comp_cb;
 	qdf_nbuf_t nbuf;
 
-	mgmt_txrx_ctx = (struct mgmt_txrx_priv_context *)
-			wlan_objmgr_psoc_get_comp_private_obj(psoc,
+	mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *)
+			wlan_objmgr_pdev_get_comp_private_obj(pdev,
 				WLAN_UMAC_COMP_MGMT_TXRX);
-	if (!mgmt_txrx_ctx) {
-		mgmt_txrx_err("Mgmt txrx context empty for psoc %pK", psoc);
+	if (!mgmt_txrx_pdev_ctx) {
+		mgmt_txrx_err("Mgmt txrx context empty for pdev %pK", pdev);
 		return QDF_STATUS_E_NULL_VALUE;
 	}
-	mgmt_desc = &mgmt_txrx_ctx->mgmt_desc_pool.pool[desc_id];
+	mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[desc_id];
 	if (!mgmt_desc) {
-		mgmt_txrx_err("Mgmt desc empty for id %d psoc %pK ",
-				desc_id, psoc);
+		mgmt_txrx_err("Mgmt desc empty for id %d pdev %pK ",
+				desc_id, pdev);
 		return QDF_STATUS_E_NULL_VALUE;
 	}
 	tx_compl_cb = mgmt_desc->tx_dwnld_cmpl_cb;
@@ -1006,29 +1008,29 @@
 	 * accessing peer in wlan_mgmt_txrx_mgmt_frame_tx
 	 */
 	wlan_objmgr_peer_release_ref(mgmt_desc->peer, WLAN_MGMT_SB_ID);
-	wlan_mgmt_txrx_desc_put(mgmt_txrx_ctx, desc_id);
+	wlan_mgmt_txrx_desc_put(mgmt_txrx_pdev_ctx, desc_id);
 	return QDF_STATUS_SUCCESS;
 }
 
 qdf_nbuf_t tgt_mgmt_txrx_get_nbuf_from_desc_id(
-			struct wlan_objmgr_psoc *psoc,
+			struct wlan_objmgr_pdev *pdev,
 			uint32_t desc_id)
 {
-	struct mgmt_txrx_priv_context *mgmt_txrx_ctx;
+	struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx;
 	struct mgmt_txrx_desc_elem_t *mgmt_desc;
 	qdf_nbuf_t buf;
 
-	mgmt_txrx_ctx = (struct mgmt_txrx_priv_context *)
-			wlan_objmgr_psoc_get_comp_private_obj(psoc,
+	mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *)
+			wlan_objmgr_pdev_get_comp_private_obj(pdev,
 				WLAN_UMAC_COMP_MGMT_TXRX);
-	if (!mgmt_txrx_ctx) {
-		mgmt_txrx_err("Mgmt txrx context empty for psoc %pK", psoc);
+	if (!mgmt_txrx_pdev_ctx) {
+		mgmt_txrx_err("Mgmt txrx context empty for pdev %pK", pdev);
 		goto fail;
 	}
-	mgmt_desc = &mgmt_txrx_ctx->mgmt_desc_pool.pool[desc_id];
+	mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[desc_id];
 	if (!mgmt_desc) {
-		mgmt_txrx_err("Mgmt descriptor unavailable for id %d psoc %pK",
-				desc_id, psoc);
+		mgmt_txrx_err("Mgmt descriptor unavailable for id %d pdev %pK",
+				desc_id, pdev);
 		goto fail;
 	}
 	buf = mgmt_desc->nbuf;
@@ -1040,25 +1042,25 @@
 
 struct wlan_objmgr_peer *
 tgt_mgmt_txrx_get_peer_from_desc_id(
-			struct wlan_objmgr_psoc *psoc,
+			struct wlan_objmgr_pdev *pdev,
 			uint32_t desc_id)
 {
-	struct mgmt_txrx_priv_context *mgmt_txrx_ctx;
+	struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx;
 	struct mgmt_txrx_desc_elem_t *mgmt_desc;
 	struct wlan_objmgr_peer *peer;
 
-	mgmt_txrx_ctx = (struct mgmt_txrx_priv_context *)
-			wlan_objmgr_psoc_get_comp_private_obj(psoc,
+	mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *)
+			wlan_objmgr_pdev_get_comp_private_obj(pdev,
 				WLAN_UMAC_COMP_MGMT_TXRX);
-	if (!mgmt_txrx_ctx) {
-		mgmt_txrx_err("Mgmt txrx context empty for psoc %pK", psoc);
+	if (!mgmt_txrx_pdev_ctx) {
+		mgmt_txrx_err("Mgmt txrx context empty for pdev %pK", pdev);
 		goto fail;
 	}
 
-	mgmt_desc = &mgmt_txrx_ctx->mgmt_desc_pool.pool[desc_id];
+	mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[desc_id];
 	if (!mgmt_desc) {
-		mgmt_txrx_err("Mgmt descriptor unavailable for id %d psoc %pK",
-				desc_id, psoc);
+		mgmt_txrx_err("Mgmt descriptor unavailable for id %d pdev %pK",
+				desc_id, pdev);
 		goto fail;
 	}
 
@@ -1070,25 +1072,25 @@
 }
 
 uint8_t tgt_mgmt_txrx_get_vdev_id_from_desc_id(
-			struct wlan_objmgr_psoc *psoc,
+			struct wlan_objmgr_pdev *pdev,
 			uint32_t desc_id)
 {
-	struct mgmt_txrx_priv_context *mgmt_txrx_ctx;
+	struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx;
 	struct mgmt_txrx_desc_elem_t *mgmt_desc;
 	uint8_t vdev_id;
 
-	mgmt_txrx_ctx = (struct mgmt_txrx_priv_context *)
-			wlan_objmgr_psoc_get_comp_private_obj(psoc,
+	mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *)
+			wlan_objmgr_pdev_get_comp_private_obj(pdev,
 				WLAN_UMAC_COMP_MGMT_TXRX);
-	if (!mgmt_txrx_ctx) {
-		mgmt_txrx_err("Mgmt txrx context empty for psoc %pK", psoc);
+	if (!mgmt_txrx_pdev_ctx) {
+		mgmt_txrx_err("Mgmt txrx context empty for pdev %pK", pdev);
 		goto fail;
 	}
 
-	mgmt_desc = &mgmt_txrx_ctx->mgmt_desc_pool.pool[desc_id];
+	mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[desc_id];
 	if (!mgmt_desc) {
-		mgmt_txrx_err("Mgmt descriptor unavailable for id %d psoc %pK",
-				desc_id, psoc);
+		mgmt_txrx_err("Mgmt descriptor unavailable for id %d pdev %pK",
+				desc_id, pdev);
 		goto fail;
 	}
 
@@ -1098,3 +1100,24 @@
 fail:
 	return WLAN_UMAC_VDEV_ID_MAX;
 }
+
+uint32_t tgt_mgmt_txrx_get_free_desc_pool_count(
+			struct wlan_objmgr_pdev *pdev)
+{
+	struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx;
+	uint32_t free_desc_count = WLAN_INVALID_MGMT_DESC_COUNT;
+
+	mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *)
+			wlan_objmgr_pdev_get_comp_private_obj(pdev,
+			WLAN_UMAC_COMP_MGMT_TXRX);
+	if (!mgmt_txrx_pdev_ctx) {
+		mgmt_txrx_err("Mgmt txrx context empty for pdev %pK", pdev);
+		goto fail;
+	}
+
+	free_desc_count = qdf_list_size(
+		&(mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list));
+
+fail:
+	return free_desc_count;
+}
diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c
index f3fed81..b9473a6 100644
--- a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c
+++ b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 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
@@ -46,46 +46,29 @@
 			struct wlan_objmgr_psoc *psoc,
 			void *arg)
 {
-	struct mgmt_txrx_priv_context *mgmt_txrx_ctx;
-	struct mgmt_txrx_stats_t *mgmt_txrx_stats;
+	struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx;
 	QDF_STATUS status;
 
 	if (!psoc) {
 		mgmt_txrx_err("psoc context passed is NULL");
-		return QDF_STATUS_E_INVAL;
+		status = QDF_STATUS_E_INVAL;
+		goto err_return;
 	}
 
-	mgmt_txrx_ctx = qdf_mem_malloc(sizeof(*mgmt_txrx_ctx));
-	if (!mgmt_txrx_ctx) {
+	mgmt_txrx_psoc_ctx = qdf_mem_malloc(sizeof(*mgmt_txrx_psoc_ctx));
+	if (!mgmt_txrx_psoc_ctx) {
 		mgmt_txrx_err("Failed to allocate mgmt txrx context");
-		return QDF_STATUS_E_NOMEM;
-	}
-
-	mgmt_txrx_ctx->psoc = psoc;
-
-	status = wlan_mgmt_txrx_desc_pool_init(mgmt_txrx_ctx,
-					       MGMT_DESC_POOL_MAX);
-	if (status != QDF_STATUS_SUCCESS) {
-		mgmt_txrx_err("Failed to initialize mgmt desc. pool with status: %u",
-				status);
-		goto err_desc_pool_init;
-	}
-
-	mgmt_txrx_stats = qdf_mem_malloc(sizeof(*mgmt_txrx_stats));
-	if (!mgmt_txrx_stats) {
-		mgmt_txrx_err("Failed to allocate memory for mgmt txrx stats structure");
 		status = QDF_STATUS_E_NOMEM;
-		goto err_mgmt_txrx_stats;
+		goto err_return;
 	}
-	mgmt_txrx_ctx->mgmt_txrx_stats = mgmt_txrx_stats;
 
-	qdf_spinlock_create(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
-	qdf_wake_lock_create(&mgmt_txrx_ctx->wakelock_tx_cmp,
-			     "mgmt_txrx tx_cmp");
+	mgmt_txrx_psoc_ctx->psoc = psoc;
+
+	qdf_spinlock_create(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
 
 	if (wlan_objmgr_psoc_component_obj_attach(psoc,
 				WLAN_UMAC_COMP_MGMT_TXRX,
-				mgmt_txrx_ctx, QDF_STATUS_SUCCESS)
+				mgmt_txrx_psoc_ctx, QDF_STATUS_SUCCESS)
 			!= QDF_STATUS_SUCCESS) {
 		mgmt_txrx_err("Failed to attach mgmt txrx ctx in psoc ctx");
 		status = QDF_STATUS_E_FAILURE;
@@ -93,18 +76,14 @@
 	}
 
 	mgmt_txrx_info("Mgmt txrx creation successful, mgmt txrx ctx: %pK, psoc: %pK",
-			mgmt_txrx_ctx, psoc);
+			mgmt_txrx_psoc_ctx, psoc);
 
 	return QDF_STATUS_SUCCESS;
 
 err_psoc_attach:
-	qdf_spinlock_destroy(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
-	qdf_wake_lock_destroy(&mgmt_txrx_ctx->wakelock_tx_cmp);
-	qdf_mem_free(mgmt_txrx_stats);
-err_mgmt_txrx_stats:
-	wlan_mgmt_txrx_desc_pool_deinit(mgmt_txrx_ctx);
-err_desc_pool_init:
-	qdf_mem_free(mgmt_txrx_ctx);
+	qdf_spinlock_destroy(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
+	qdf_mem_free(mgmt_txrx_psoc_ctx);
+err_return:
 	return status;
 }
 
@@ -123,40 +102,168 @@
 			struct wlan_objmgr_psoc *psoc,
 			void *arg)
 {
-	struct mgmt_txrx_priv_context *mgmt_txrx_ctx;
+	struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx;
 
 	if (!psoc) {
 		mgmt_txrx_err("psoc context passed is NULL");
 		return QDF_STATUS_E_INVAL;
 	}
 
-	mgmt_txrx_ctx = wlan_objmgr_psoc_get_comp_private_obj(
+	mgmt_txrx_psoc_ctx = wlan_objmgr_psoc_get_comp_private_obj(
 			psoc, WLAN_UMAC_COMP_MGMT_TXRX);
-	if (!mgmt_txrx_ctx) {
+	if (!mgmt_txrx_psoc_ctx) {
 		mgmt_txrx_err("mgmt txrx context is already NULL");
 		return QDF_STATUS_E_FAILURE;
 	}
 
 	mgmt_txrx_info("deleting mgmt txrx psoc obj, mgmt txrx ctx: %pK, psoc: %pK",
-			mgmt_txrx_ctx, psoc);
+			mgmt_txrx_psoc_ctx, psoc);
 	if (wlan_objmgr_psoc_component_obj_detach(psoc,
-				WLAN_UMAC_COMP_MGMT_TXRX, mgmt_txrx_ctx)
+				WLAN_UMAC_COMP_MGMT_TXRX, mgmt_txrx_psoc_ctx)
 			!= QDF_STATUS_SUCCESS) {
 		mgmt_txrx_err("Failed to detach mgmt txrx ctx in psoc ctx");
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	wlan_mgmt_txrx_desc_pool_deinit(mgmt_txrx_ctx);
-	qdf_mem_free(mgmt_txrx_ctx->mgmt_txrx_stats);
-	qdf_spinlock_destroy(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
-	qdf_wake_lock_destroy(&mgmt_txrx_ctx->wakelock_tx_cmp);
-	qdf_mem_free(mgmt_txrx_ctx);
+	qdf_spinlock_destroy(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
+	qdf_mem_free(mgmt_txrx_psoc_ctx);
 
 	mgmt_txrx_info("mgmt txrx deletion successful, psoc: %pK", psoc);
 
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * wlan_mgmt_txrx_pdev_obj_create_notification() - called from objmgr when pdev
+ *                                                 is created
+ * @pdev: pdev context
+ * @arg: argument
+ *
+ * This function gets called from object manager when pdev is being created and
+ * creates mgmt_txrx context, mgmt desc pool.
+ *
+ * Return: QDF_STATUS_SUCCESS - in case of success
+ */
+static QDF_STATUS wlan_mgmt_txrx_pdev_obj_create_notification(
+			struct wlan_objmgr_pdev *pdev,
+			void *arg)
+{
+	struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx;
+	struct mgmt_txrx_stats_t *mgmt_txrx_stats;
+	QDF_STATUS status;
+
+	if (!pdev) {
+		mgmt_txrx_err("pdev context passed is NULL");
+		status = QDF_STATUS_E_INVAL;
+		goto err_return;
+
+	}
+
+	mgmt_txrx_pdev_ctx = qdf_mem_malloc(sizeof(*mgmt_txrx_pdev_ctx));
+	if (!mgmt_txrx_pdev_ctx) {
+		mgmt_txrx_err("Failed to allocate mgmt txrx context");
+		status = QDF_STATUS_E_NOMEM;
+		goto err_return;
+	}
+
+	mgmt_txrx_pdev_ctx->pdev = pdev;
+
+	status = wlan_mgmt_txrx_desc_pool_init(mgmt_txrx_pdev_ctx,
+					       MGMT_DESC_POOL_MAX);
+	if (status != QDF_STATUS_SUCCESS) {
+		mgmt_txrx_err(
+			"Failed to initialize mgmt desc. pool with status: %u",
+			status);
+		goto err_desc_pool_init;
+	}
+
+	mgmt_txrx_stats = qdf_mem_malloc(sizeof(*mgmt_txrx_stats));
+	if (!mgmt_txrx_stats) {
+		mgmt_txrx_err(
+			"Failed to allocate memory for mgmt txrx stats structure");
+		status = QDF_STATUS_E_NOMEM;
+		goto err_mgmt_txrx_stats;
+	}
+	mgmt_txrx_pdev_ctx->mgmt_txrx_stats = mgmt_txrx_stats;
+
+	qdf_wake_lock_create(&mgmt_txrx_pdev_ctx->wakelock_tx_cmp,
+			     "mgmt_txrx tx_cmp");
+
+	if (wlan_objmgr_pdev_component_obj_attach(pdev,
+			WLAN_UMAC_COMP_MGMT_TXRX,
+			mgmt_txrx_pdev_ctx, QDF_STATUS_SUCCESS)
+			!= QDF_STATUS_SUCCESS) {
+		mgmt_txrx_err("Failed to attach mgmt txrx ctx in pdev ctx");
+		status = QDF_STATUS_E_FAILURE;
+		goto err_pdev_attach;
+	}
+
+	mgmt_txrx_info(
+		"Mgmt txrx creation successful, mgmt txrx ctx: %pK, pdev: %pK",
+		mgmt_txrx_pdev_ctx, pdev);
+
+	return QDF_STATUS_SUCCESS;
+
+err_pdev_attach:
+	qdf_wake_lock_destroy(&mgmt_txrx_pdev_ctx->wakelock_tx_cmp);
+	qdf_mem_free(mgmt_txrx_stats);
+err_mgmt_txrx_stats:
+	wlan_mgmt_txrx_desc_pool_deinit(mgmt_txrx_pdev_ctx);
+err_desc_pool_init:
+	qdf_mem_free(mgmt_txrx_pdev_ctx);
+err_return:
+	return status;
+}
+
+/**
+ * wlan_mgmt_txrx_pdev_obj_destroy_notification() - called from objmgr when
+ *                                                  pdev is destroyed
+ * @pdev: pdev context
+ * @arg: argument
+ *
+ * This function gets called from object manager when pdev is being destroyed
+ * pdev deletes mgmt_txrx context, mgmt desc pool.
+ *
+ * Return: QDF_STATUS_SUCCESS - in case of success
+ */
+static QDF_STATUS wlan_mgmt_txrx_pdev_obj_destroy_notification(
+			struct wlan_objmgr_pdev *pdev,
+			void *arg)
+{
+	struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx;
+
+	if (!pdev) {
+		mgmt_txrx_err("pdev context passed is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	mgmt_txrx_pdev_ctx = wlan_objmgr_pdev_get_comp_private_obj(
+			pdev, WLAN_UMAC_COMP_MGMT_TXRX);
+	if (!mgmt_txrx_pdev_ctx) {
+		mgmt_txrx_err("mgmt txrx context is already NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	mgmt_txrx_info("deleting mgmt txrx pdev obj, mgmt txrx ctx: %pK, pdev: %pK",
+			mgmt_txrx_pdev_ctx, pdev);
+	if (wlan_objmgr_pdev_component_obj_detach(pdev,
+				WLAN_UMAC_COMP_MGMT_TXRX, mgmt_txrx_pdev_ctx)
+			!= QDF_STATUS_SUCCESS) {
+		mgmt_txrx_err("Failed to detach mgmt txrx ctx in pdev ctx");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	wlan_mgmt_txrx_desc_pool_deinit(mgmt_txrx_pdev_ctx);
+	qdf_mem_free(mgmt_txrx_pdev_ctx->mgmt_txrx_stats);
+	qdf_wake_lock_destroy(&mgmt_txrx_pdev_ctx->wakelock_tx_cmp);
+	qdf_mem_free(mgmt_txrx_pdev_ctx);
+
+	mgmt_txrx_info("mgmt txrx deletion successful, pdev: %pK", pdev);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+
 QDF_STATUS wlan_mgmt_txrx_init(void)
 {
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
@@ -166,7 +273,7 @@
 				wlan_mgmt_txrx_psoc_obj_create_notification,
 				NULL);
 	if (status != QDF_STATUS_SUCCESS) {
-		mgmt_txrx_err("Failed to register mgmt txrx obj create handler");
+		mgmt_txrx_err("Failed to register mgmt txrx psoc create handler");
 		goto err_psoc_create;
 	}
 
@@ -175,13 +282,37 @@
 				wlan_mgmt_txrx_psoc_obj_destroy_notification,
 				NULL);
 	if (status != QDF_STATUS_SUCCESS) {
-		mgmt_txrx_err("Failed to register mgmt txrx obj destroy handler");
+		mgmt_txrx_err("Failed to register mgmt txrx psoc destroy handler");
 		goto err_psoc_delete;
 	}
 
+	status = wlan_objmgr_register_pdev_create_handler(
+				WLAN_UMAC_COMP_MGMT_TXRX,
+				wlan_mgmt_txrx_pdev_obj_create_notification,
+				NULL);
+	if (status != QDF_STATUS_SUCCESS) {
+		mgmt_txrx_err("Failed to register mgmt txrx pdev obj create handler");
+		goto err_pdev_create;
+	}
+
+	status = wlan_objmgr_register_pdev_destroy_handler(
+				WLAN_UMAC_COMP_MGMT_TXRX,
+				wlan_mgmt_txrx_pdev_obj_destroy_notification,
+				NULL);
+	if (status != QDF_STATUS_SUCCESS) {
+		mgmt_txrx_err("Failed to register mgmt txrx obj destroy handler");
+		goto err_pdev_delete;
+	}
+
 	mgmt_txrx_info("Successfully registered create and destroy handlers with objmgr");
 	return QDF_STATUS_SUCCESS;
 
+err_pdev_delete:
+	wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_MGMT_TXRX,
+			wlan_mgmt_txrx_pdev_obj_create_notification, NULL);
+err_pdev_create:
+	wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_MGMT_TXRX,
+			wlan_mgmt_txrx_psoc_obj_destroy_notification, NULL);
 err_psoc_delete:
 	wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_MGMT_TXRX,
 			wlan_mgmt_txrx_psoc_obj_create_notification, NULL);
@@ -206,6 +337,22 @@
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	if (wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_MGMT_TXRX,
+				wlan_mgmt_txrx_pdev_obj_create_notification,
+				NULL)
+			!= QDF_STATUS_SUCCESS) {
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (wlan_objmgr_unregister_pdev_destroy_handler(
+				WLAN_UMAC_COMP_MGMT_TXRX,
+				wlan_mgmt_txrx_pdev_obj_destroy_notification,
+				NULL)
+			!= QDF_STATUS_SUCCESS) {
+		return QDF_STATUS_E_FAILURE;
+	}
+
+
 	mgmt_txrx_info("Successfully unregistered create and destroy handlers with objmgr");
 	return QDF_STATUS_SUCCESS;
 }
@@ -220,7 +367,8 @@
 {
 	struct mgmt_txrx_desc_elem_t *desc;
 	struct wlan_objmgr_psoc *psoc;
-	struct mgmt_txrx_priv_context *txrx_ctx;
+	struct wlan_objmgr_pdev *pdev;
+	struct mgmt_txrx_priv_pdev_context *txrx_ctx;
 	struct wlan_objmgr_vdev *vdev;
 
 	if (!peer) {
@@ -245,12 +393,20 @@
 		return QDF_STATUS_E_NULL_VALUE;
 	}
 
-	txrx_ctx = (struct mgmt_txrx_priv_context *)
-			wlan_objmgr_psoc_get_comp_private_obj(psoc,
+	pdev = wlan_vdev_get_pdev(vdev);
+	if (!pdev) {
+		mgmt_txrx_err("pdev unavailable for peer %pK vdev %pK",
+				peer, vdev);
+		wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_SB_ID);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	txrx_ctx = (struct mgmt_txrx_priv_pdev_context *)
+			wlan_objmgr_pdev_get_comp_private_obj(pdev,
 				WLAN_UMAC_COMP_MGMT_TXRX);
 	if (!txrx_ctx) {
-		mgmt_txrx_err("No txrx context for peer %pK psoc %pK",
-				peer, psoc);
+		mgmt_txrx_err("No txrx context for peer %pK pdev %pK",
+				peer, pdev);
 		wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_SB_ID);
 		return QDF_STATUS_E_NULL_VALUE;
 	}
@@ -269,7 +425,8 @@
 	desc->context = context;
 
 	if (!psoc->soc_cb.tx_ops.mgmt_txrx_tx_ops.mgmt_tx_send) {
-		mgmt_txrx_err("mgmt txrx tx op to send mgmt frame is NULL for psoc: %pK",
+		mgmt_txrx_err(
+				"mgmt txrx txop to send mgmt frame is NULL for psoc: %pK",
 				psoc);
 		wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_SB_ID);
 		desc->nbuf = NULL;
@@ -279,8 +436,8 @@
 
 	if (psoc->soc_cb.tx_ops.mgmt_txrx_tx_ops.mgmt_tx_send(
 			vdev, buf, desc->desc_id, mgmt_tx_params)) {
-		mgmt_txrx_err("Mgmt send fail for peer %pK psoc %pK",
-				peer, psoc);
+		mgmt_txrx_err("Mgmt send fail for peer %pK psoc %pK pdev: %pK",
+				peer, psoc, pdev);
 		wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_SB_ID);
 		desc->nbuf = NULL;
 		wlan_mgmt_txrx_desc_put(txrx_ctx, desc->desc_id);
@@ -324,7 +481,7 @@
 
 /**
  * wlan_mgmt_txrx_create_rx_handler() - creates rx handler node for umac comp.
- * @mgmt_txrx_ctx: mgmt txrx context
+ * @mgmt_txrx_psoc_ctx: mgmt txrx context
  * @mgmt_rx_cb: mgmt rx callback to be registered
  * @comp_id: umac component id
  * @frm_type: mgmt. frame for which cb to be registered.
@@ -335,7 +492,7 @@
  * Return: QDF_STATUS_SUCCESS - in case of success
  */
 static QDF_STATUS wlan_mgmt_txrx_create_rx_handler(
-				struct mgmt_txrx_priv_context *mgmt_txrx_ctx,
+				struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx,
 				mgmt_frame_rx_callback mgmt_rx_cb,
 				enum wlan_umac_comp_id comp_id,
 				enum mgmt_frame_type frm_type)
@@ -351,10 +508,10 @@
 	rx_handler->comp_id = comp_id;
 	rx_handler->rx_cb = mgmt_rx_cb;
 
-	qdf_spin_lock_bh(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
-	rx_handler->next = mgmt_txrx_ctx->mgmt_rx_comp_cb[frm_type];
-	mgmt_txrx_ctx->mgmt_rx_comp_cb[frm_type] = rx_handler;
-	qdf_spin_unlock_bh(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
+	qdf_spin_lock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
+	rx_handler->next = mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[frm_type];
+	mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[frm_type] = rx_handler;
+	qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
 
 	mgmt_txrx_info("Callback registered for comp_id: %d, frm_type: %d",
 			comp_id, frm_type);
@@ -363,7 +520,7 @@
 
 /**
  * wlan_mgmt_txrx_delete_rx_handler() - deletes rx handler node for umac comp.
- * @mgmt_txrx_ctx: mgmt txrx context
+ * @mgmt_txrx_psoc_ctx: mgmt txrx context
  * @mgmt_rx_cb: mgmt rx callback to be deregistered
  * @comp_id: umac component id
  * @frm_type: mgmt. frame for which cb to be registered.
@@ -374,16 +531,16 @@
  * Return: QDF_STATUS_SUCCESS - in case of success
  */
 static QDF_STATUS wlan_mgmt_txrx_delete_rx_handler(
-				struct mgmt_txrx_priv_context *mgmt_txrx_ctx,
-				mgmt_frame_rx_callback mgmt_rx_cb,
-				enum wlan_umac_comp_id comp_id,
-				enum mgmt_frame_type frm_type)
+		struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx,
+		mgmt_frame_rx_callback mgmt_rx_cb,
+		enum wlan_umac_comp_id comp_id,
+		enum mgmt_frame_type frm_type)
 {
-	struct mgmt_rx_handler *rx_handler, *rx_handler_prev = NULL;
+	struct mgmt_rx_handler *rx_handler = NULL, *rx_handler_prev = NULL;
 	bool delete = false;
 
-	qdf_spin_lock_bh(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
-	rx_handler = mgmt_txrx_ctx->mgmt_rx_comp_cb[frm_type];
+	qdf_spin_lock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
+	rx_handler = mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[frm_type];
 	while (rx_handler) {
 		if (rx_handler->comp_id == comp_id &&
 				rx_handler->rx_cb == mgmt_rx_cb) {
@@ -391,7 +548,7 @@
 				rx_handler_prev->next =
 					rx_handler->next;
 			else
-				mgmt_txrx_ctx->mgmt_rx_comp_cb[frm_type] =
+				mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[frm_type] =
 					rx_handler->next;
 
 			qdf_mem_free(rx_handler);
@@ -402,7 +559,7 @@
 		rx_handler_prev = rx_handler;
 		rx_handler = rx_handler->next;
 	}
-	qdf_spin_unlock_bh(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
+	qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
 
 	if (!delete) {
 		mgmt_txrx_err("No callback registered for comp_id: %d, frm_type: %d",
@@ -421,7 +578,7 @@
 			struct mgmt_txrx_mgmt_frame_cb_info *frm_cb_info,
 			uint8_t num_entries)
 {
-	struct mgmt_txrx_priv_context *mgmt_txrx_ctx;
+	struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx;
 	QDF_STATUS status;
 	uint8_t i, j;
 
@@ -446,22 +603,22 @@
 		return QDF_STATUS_E_INVAL;
 	}
 
-	mgmt_txrx_ctx = (struct mgmt_txrx_priv_context *)
+	mgmt_txrx_psoc_ctx = (struct mgmt_txrx_priv_psoc_context *)
 			wlan_objmgr_psoc_get_comp_private_obj(psoc,
 				WLAN_UMAC_COMP_MGMT_TXRX);
-	if (!mgmt_txrx_ctx) {
+	if (!mgmt_txrx_psoc_ctx) {
 		mgmt_txrx_err("mgmt txrx context is NULL");
 		return QDF_STATUS_E_FAILURE;
 	}
 
 	for (i = 0; i < num_entries; i++) {
-		status = wlan_mgmt_txrx_create_rx_handler(mgmt_txrx_ctx,
+		status = wlan_mgmt_txrx_create_rx_handler(mgmt_txrx_psoc_ctx,
 				frm_cb_info[i].mgmt_rx_cb, comp_id,
 				frm_cb_info[i].frm_type);
 		if (status != QDF_STATUS_SUCCESS) {
 			for (j = 0; j < i; j++) {
 				wlan_mgmt_txrx_delete_rx_handler(
-					mgmt_txrx_ctx,
+					mgmt_txrx_psoc_ctx,
 					frm_cb_info[j].mgmt_rx_cb,
 					comp_id, frm_cb_info[j].frm_type);
 			}
@@ -478,7 +635,7 @@
 			struct mgmt_txrx_mgmt_frame_cb_info *frm_cb_info,
 			uint8_t num_entries)
 {
-	struct mgmt_txrx_priv_context *mgmt_txrx_ctx;
+	struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx;
 	uint8_t i;
 
 	if (!psoc) {
@@ -502,16 +659,16 @@
 		return QDF_STATUS_E_INVAL;
 	}
 
-	mgmt_txrx_ctx = (struct mgmt_txrx_priv_context *)
+	mgmt_txrx_psoc_ctx = (struct mgmt_txrx_priv_psoc_context *)
 			wlan_objmgr_psoc_get_comp_private_obj(psoc,
 				WLAN_UMAC_COMP_MGMT_TXRX);
-	if (!mgmt_txrx_ctx) {
+	if (!mgmt_txrx_psoc_ctx) {
 		mgmt_txrx_err("mgmt txrx context is NULL");
 		return QDF_STATUS_E_FAILURE;
 	}
 
 	for (i = 0; i < num_entries; i++) {
-		wlan_mgmt_txrx_delete_rx_handler(mgmt_txrx_ctx,
+		wlan_mgmt_txrx_delete_rx_handler(mgmt_txrx_psoc_ctx,
 				frm_cb_info[i].mgmt_rx_cb, comp_id,
 				frm_cb_info[i].frm_type);
 	}
@@ -526,41 +683,53 @@
 
 QDF_STATUS wlan_mgmt_txrx_psoc_close(struct wlan_objmgr_psoc *psoc)
 {
-	struct mgmt_txrx_priv_context *mgmt_txrx_ctx;
+	struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx;
 	struct mgmt_txrx_desc_elem_t *mgmt_desc;
-	uint8_t i;
+	uint16_t i;
 	uint32_t pool_size;
+	uint8_t pdev_count, index;
+	struct wlan_objmgr_pdev *pdev;
 
 	if (!psoc) {
 		mgmt_txrx_err("psoc context is NULL");
 		return QDF_STATUS_E_INVAL;
 	}
 
-	mgmt_txrx_ctx = (struct mgmt_txrx_priv_context *)
-			wlan_objmgr_psoc_get_comp_private_obj(psoc,
+	pdev_count = wlan_psoc_get_pdev_count(psoc);
+
+	for (index = 0; index < pdev_count; index++) {
+		pdev = psoc->soc_objmgr.wlan_pdev_list[index];
+
+		if (!pdev) {
+			mgmt_txrx_err("pdev context is NULL");
+			return QDF_STATUS_E_INVAL;
+		}
+		mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *)
+			wlan_objmgr_pdev_get_comp_private_obj(pdev,
 				WLAN_UMAC_COMP_MGMT_TXRX);
-	if (!mgmt_txrx_ctx) {
-		mgmt_txrx_err("mgmt txrx context is NULL");
+		if (!mgmt_txrx_pdev_ctx) {
+			mgmt_txrx_err("mgmt txrx context is NULL");
 		return QDF_STATUS_E_FAILURE;
-	}
+		}
 
-	pool_size = mgmt_txrx_ctx->mgmt_desc_pool.free_list.max_size;
-	if (!pool_size) {
-		mgmt_txrx_err("pool size is 0");
-		return QDF_STATUS_E_FAILURE;
-	}
+		pool_size = mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list.max_size;
+		if (!pool_size) {
+			mgmt_txrx_err("pool size is 0");
+			return QDF_STATUS_E_FAILURE;
+		}
 
-	for (i = 0; i < pool_size; i++) {
-		if (mgmt_txrx_ctx->mgmt_desc_pool.pool[i].in_use) {
-			mgmt_txrx_info("mgmt descriptor with desc id: %d not in freelist",
-				       i);
-			mgmt_desc = &mgmt_txrx_ctx->mgmt_desc_pool.pool[i];
-			qdf_nbuf_free(mgmt_desc->nbuf);
-			wlan_objmgr_peer_release_ref(mgmt_desc->peer,
+		for (i = 0; i < pool_size; i++) {
+			if (mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[i].in_use) {
+				mgmt_txrx_info(
+					"mgmt descriptor with desc id: %d not in freelist",
+					i);
+				mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[i];
+				qdf_nbuf_free(mgmt_desc->nbuf);
+				wlan_objmgr_peer_release_ref(mgmt_desc->peer,
 						     WLAN_MGMT_SB_ID);
-			wlan_mgmt_txrx_desc_put(mgmt_txrx_ctx, i);
+				wlan_mgmt_txrx_desc_put(mgmt_txrx_pdev_ctx, i);
+			}
 		}
 	}
-
 	return QDF_STATUS_SUCCESS;
 }
diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c b/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c
index 598e873..b4b442a 100644
--- a/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c
+++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 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
@@ -1724,7 +1724,7 @@
 						wlan_objmgr_ref_dbgid id)
 {
 	if (psoc == NULL) {
-		obj_mgr_err("psoc obj is NULLi for id:%d", id);
+		obj_mgr_err("psoc obj is NULL for id:%d", id);
 		QDF_ASSERT(0);
 		return;
 	}