ソースを参照

qcacmn: Add reference count support to PSOC/PDEV/VDEV/PEER objects

This change implements ref count mechanism, before accessing/storing object,
its ref count has to be incremented to avoid "use after free" scenarios.

1) Increments ref count of each object on its creation
2) Increments parent object on creation of child object (ex: on peer creation
	vdev object ref count gets incremented)
3) On get_obj() API, caller will be returned object after incrementing ref cnt

Change-Id: Ic01cb3217881d269cc451f0e63358e1e4decaaa7
CRS-Fixed: 1096009
Srinivas Pitla 8 年 前
コミット
10aa60c11f

+ 4 - 4
umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c

@@ -831,10 +831,10 @@ QDF_STATUS tgt_mgmt_txrx_rx_frame_handler(
 	 * scenario.
 	 */
 	mac_addr = (uint8_t *)wh->i_addr2;
-	peer = wlan_objmgr_find_peer(psoc, mac_addr);
+	peer = wlan_objmgr_get_peer(psoc, mac_addr, WLAN_MGMT_SB_ID);
 	if (!peer) {
 		mac_addr = (uint8_t *)wh->i_addr1;
-		peer = wlan_objmgr_find_peer(psoc, mac_addr);
+		peer = wlan_objmgr_get_peer(psoc, mac_addr, WLAN_MGMT_SB_ID);
 	}
 
 	/**
@@ -922,7 +922,7 @@ rx_handler_mem_free:
 	}
 dec_peer_ref_cnt:
 	if (peer)
-		wlan_objmgr_peer_unref_peer(peer);
+		wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_SB_ID);
 
 	return status;
 }
@@ -994,7 +994,7 @@ no_registered_cb:
 	 * passing peer in wlan_mgmt_txrx_mgmt_frame_tx or
 	 * wlan_mgmt_txrx_beacon_frame_tx APIs.
 	 */
-	wlan_objmgr_peer_unref_peer(mgmt_desc->peer);
+	wlan_objmgr_peer_release_ref(mgmt_desc->peer, WLAN_MGMT_NB_ID);
 	wlan_mgmt_txrx_desc_put(mgmt_txrx_ctx, desc_id);
 	return QDF_STATUS_SUCCESS;
 }

+ 13 - 12
umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c

@@ -106,17 +106,17 @@ err_desc_pool_init:
 }
 
 /**
- * wlan_mgmt_txrx_psoc_obj_delete_notification() - called from objmgr when psoc
- *                                                 is deleted
+ * wlan_mgmt_txrx_psoc_obj_destroy_notification() - called from objmgr when
+ *                                                  psoc is destroyed
  * @psoc: psoc context
  * @arg: argument
  *
- * This function gets called from object manager when psoc is being deleted and
- * deletes mgmt_txrx context, mgmt desc pool.
+ * This function gets called from object manager when psoc is being destroyed
+ * psoc deletes mgmt_txrx context, mgmt desc pool.
  *
  * Return: QDF_STATUS_SUCCESS - in case of success
  */
-static QDF_STATUS wlan_mgmt_txrx_psoc_obj_delete_notification(
+static QDF_STATUS wlan_mgmt_txrx_psoc_obj_destroy_notification(
 			struct wlan_objmgr_psoc *psoc,
 			void *arg)
 {
@@ -166,16 +166,16 @@ QDF_STATUS wlan_mgmt_txrx_init(void)
 		goto err_psoc_create;
 	}
 
-	status = wlan_objmgr_register_psoc_delete_handler(
+	status = wlan_objmgr_register_psoc_destroy_handler(
 				WLAN_UMAC_COMP_MGMT_TXRX,
-				wlan_mgmt_txrx_psoc_obj_delete_notification,
+				wlan_mgmt_txrx_psoc_obj_destroy_notification,
 				NULL);
 	if (status != QDF_STATUS_SUCCESS) {
-		mgmt_txrx_err("Failed to register mgmt txrx obj delete handler");
+		mgmt_txrx_err("Failed to register mgmt txrx obj destroy handler");
 		goto err_psoc_delete;
 	}
 
-	mgmt_txrx_info("Successfully registered create and delete handlers with objmgr");
+	mgmt_txrx_info("Successfully registered create and destroy handlers with objmgr");
 	return QDF_STATUS_SUCCESS;
 
 err_psoc_delete:
@@ -194,14 +194,15 @@ QDF_STATUS wlan_mgmt_txrx_deinit(void)
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	if (wlan_objmgr_unregister_psoc_delete_handler(WLAN_UMAC_COMP_MGMT_TXRX,
-				wlan_mgmt_txrx_psoc_obj_delete_notification,
+	if (wlan_objmgr_unregister_psoc_destroy_handler(
+				WLAN_UMAC_COMP_MGMT_TXRX,
+				wlan_mgmt_txrx_psoc_obj_destroy_notification,
 				NULL)
 			!= QDF_STATUS_SUCCESS) {
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	mgmt_txrx_info("Successfully unregistered create and delete handlers with objmgr");
+	mgmt_txrx_info("Successfully unregistered create and destroy handlers with objmgr");
 	return QDF_STATUS_SUCCESS;
 }
 

+ 38 - 12
umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -26,6 +26,7 @@
 #include "qdf_list.h"
 #include "qdf_status.h"
 #include "wlan_cmn.h"
+#include "qdf_atomic.h"
 
 /* No. of PSOCs can be supported */
 #define WLAN_OBJMGR_MAX_DEVICES 2
@@ -40,20 +41,23 @@
 /**
  * enum WLAN_OBJ_STATE - State of Object
  * @WLAN_OBJ_STATE_CREATED:             All component objects are created
- * @WLAN_OBJ_STATE_DELETED:             All component objects are deleted
+ * @WLAN_OBJ_STATE_DELETED:             All component objects are destroyed
  * @WLAN_OBJ_STATE_PARTIALLY_CREATED:   Few/All component objects creation is
  *                                      in progress
- * @WLAN_OBJ_STATE_PARTIALLY_DELETED:   Few/All component objects yet to be
- *                                      deleted
+ * @WLAN_OBJ_STATE_PARTIALLY_DELETED:   Component objects deletion is triggered,
+ *                                      they are yet to be destroyed
  * @WLAN_OBJ_STATE_COMP_DEL_PROGRESS:   If a component is disabled run time,
  *                                      and this state is used to represent the
  *                                      deletion in progress after that
- *                                      component object is deleted, object
+ *                                      component object is destroyed, object
  *                                      state would be moved to CREATED state
+ * @WLAN_OBJ_STATE_LOGICALLY_DELETED:   Object deletion has been initiated,
+ *                                      object destroy invoked once references
+ *                                      are released
  * @WLAN_OBJ_STATE_CREATION_FAILED:     any component object is failed to be
  *                                      created
  * @WLAN_OBJ_STATE_DELETION_FAILED:     any component object is failed to be
- *                                      deleted
+ *                                      destroyed
  */
 typedef enum {
 	WLAN_OBJ_STATE_CREATED            = 0,
@@ -61,8 +65,9 @@ typedef enum {
 	WLAN_OBJ_STATE_PARTIALLY_CREATED  = 2,
 	WLAN_OBJ_STATE_PARTIALLY_DELETED  = 3,
 	WLAN_OBJ_STATE_COMP_DEL_PROGRESS  = 4,
-	WLAN_OBJ_STATE_CREATION_FAILED    = 5,
-	WLAN_OBJ_STATE_DELETION_FAILED    = 6,
+	WLAN_OBJ_STATE_LOGICALLY_DELETED  = 5,
+	WLAN_OBJ_STATE_CREATION_FAILED    = 6,
+	WLAN_OBJ_STATE_DELETION_FAILED    = 7,
 } WLAN_OBJ_STATE;
 
 /* Object type is assigned with value */
@@ -116,14 +121,14 @@ struct wlan_objmgr_peer;
 */
 typedef QDF_STATUS (*wlan_objmgr_psoc_create_handler)(
 				struct wlan_objmgr_psoc *psoc, void *arg);
-typedef QDF_STATUS (*wlan_objmgr_psoc_delete_handler)(
+typedef QDF_STATUS (*wlan_objmgr_psoc_destroy_handler)(
 				struct wlan_objmgr_psoc *psoc, void *arg);
 typedef void (*wlan_objmgr_psoc_status_handler)(struct wlan_objmgr_psoc *psoc,
 					 void *arg, QDF_STATUS status);
 
 typedef QDF_STATUS (*wlan_objmgr_pdev_create_handler)(
 				struct wlan_objmgr_pdev *pdev, void *arg);
-typedef QDF_STATUS (*wlan_objmgr_pdev_delete_handler)(
+typedef QDF_STATUS (*wlan_objmgr_pdev_destroy_handler)(
 				struct wlan_objmgr_pdev *pdev, void *arg);
 typedef void (*wlan_objmgr_pdev_status_handler)(
 				struct wlan_objmgr_pdev *pdev, void *arg,
@@ -131,7 +136,7 @@ typedef void (*wlan_objmgr_pdev_status_handler)(
 
 typedef QDF_STATUS (*wlan_objmgr_vdev_create_handler)(
 				struct wlan_objmgr_vdev *vdev, void *arg);
-typedef QDF_STATUS (*wlan_objmgr_vdev_delete_handler)(
+typedef QDF_STATUS (*wlan_objmgr_vdev_destroy_handler)(
 				struct wlan_objmgr_vdev *vdev, void *arg);
 typedef void (*wlan_objmgr_vdev_status_handler)(
 				struct wlan_objmgr_vdev *vdev, void *arg,
@@ -139,10 +144,31 @@ typedef void (*wlan_objmgr_vdev_status_handler)(
 
 typedef QDF_STATUS (*wlan_objmgr_peer_create_handler)(
 				struct wlan_objmgr_peer *peer, void *arg);
-typedef QDF_STATUS (*wlan_objmgr_peer_delete_handler)(
+typedef QDF_STATUS (*wlan_objmgr_peer_destroy_handler)(
 				struct wlan_objmgr_peer *peer, void *arg);
 typedef void (*wlan_objmgr_peer_status_handler)(
 				struct wlan_objmgr_peer *peer, void *arg,
 						QDF_STATUS status);
 
+/**
+ * enum wlan_objmgr_ref_dbgid - ref count debug id
+ * @WLAN_OBJMGR_ID:             Object manager internal operations
+ * @WLAN_MLME_SB_ID:            MLME Southbound operations
+ * @WLAN_MLME_NB_ID:            MLME Northbound operations
+ * @WLAN_MGMT_SB_ID:            MGMT Northbound operations
+ * @WLAN_MGMT_NB_ID:            MGMT Southbound operations
+ */
+typedef enum {
+	WLAN_OBJMGR_ID      = 0,
+	WLAN_MLME_SB_ID     = 1,
+	WLAN_MLME_NB_ID     = 2,
+	WLAN_MGMT_SB_ID     = 3,
+	WLAN_MGMT_NB_ID     = 4,
+} wlan_objmgr_ref_dbgid;
+
+#ifdef WLAN_OBJMGR_DEBUG
+#define WLAN_OBJMGR_BUG(val) QDF_BUG(val)
+#else
+#define WLAN_OBJMGR_BUG(val)
+#endif
 #endif /* _WLAN_OBJMGR_CMN_H_*/

+ 29 - 29
umac/cmn_services/obj_mgr/inc/wlan_objmgr_global_obj.h

@@ -44,17 +44,17 @@ QDF_STATUS wlan_objmgr_global_obj_init(void);
 QDF_STATUS wlan_objmgr_global_obj_deinit(void);
 
 /**
- * wlan_objmgr_global_obj_can_deleted() - Checks whether global object
- *					  can be deleted
+ * wlan_objmgr_global_obj_can_destroyed() - Checks whether global object
+ *					  can be destroyed
  *
  * Checks the psoc table of global object, if psoc table is empty
  * returns the SUCCESS
  *
- * Return: SUCCESS  on can be deleted,
- *         FAILURE  on can't be deleted
+ * Return: SUCCESS  on can be destroyed,
+ *         FAILURE  on can't be destroyed
  *
  */
-QDF_STATUS wlan_objmgr_global_obj_can_deleted(void);
+QDF_STATUS wlan_objmgr_global_obj_can_destroyed(void);
 
 /**
  * wlan_objmgr_register_psoc_create_handler() - register psoc create handler
@@ -92,7 +92,7 @@ QDF_STATUS wlan_objmgr_unregister_psoc_create_handler(
 		void *args);
 
 /**
- * wlan_objmgr_register_psoc_delete_handler() - register delete handler
+ * wlan_objmgr_register_psoc_destroy_handler() - register destroy handler
  * @id: component id
  * @handler: function pointer of the component
  * @args: args, if component wants certain args to be passed on PSOC deletion
@@ -104,13 +104,13 @@ QDF_STATUS wlan_objmgr_unregister_psoc_create_handler(
  *         Failure (if registration fails, each failure has different error
  *         code)
  */
-QDF_STATUS wlan_objmgr_register_psoc_delete_handler(
+QDF_STATUS wlan_objmgr_register_psoc_destroy_handler(
 		enum wlan_umac_comp_id id,
-		wlan_objmgr_psoc_delete_handler handler,
+		wlan_objmgr_psoc_destroy_handler handler,
 		void *args);
 
 /**
- * wlan_objmgr_unregister_psoc_delete_handler() - unregister delete handler
+ * wlan_objmgr_unregister_psoc_destroy_handler() - unregister destroy handler
  * @id: component id
  * @handler: function pointer of the component
  * @args: args, if component wants certain args to be passed on PSOC deletion
@@ -121,9 +121,9 @@ QDF_STATUS wlan_objmgr_register_psoc_delete_handler(
  *         Failure (if handler is not present, each failure has different error
  *         code)
  */
-QDF_STATUS wlan_objmgr_unregister_psoc_delete_handler(
+QDF_STATUS wlan_objmgr_unregister_psoc_destroy_handler(
 		enum wlan_umac_comp_id id,
-		wlan_objmgr_psoc_delete_handler handler,
+		wlan_objmgr_psoc_destroy_handler handler,
 		void *args);
 
 /**
@@ -198,7 +198,7 @@ QDF_STATUS wlan_objmgr_unregister_pdev_create_handler(
 		void *args);
 
 /**
- * wlan_objmgr_register_pdev_delete_handler() - register pdev delete handler
+ * wlan_objmgr_register_pdev_destroy_handler() - register pdev destroy handler
  * @id: component id
  * @handler: function pointer of the component
  * @args: args, if component wants certain args to be passed on PDEV deletion
@@ -210,13 +210,13 @@ QDF_STATUS wlan_objmgr_unregister_pdev_create_handler(
  *         Failure (if registration fails, each failure has different error
  *         code)
  */
-QDF_STATUS wlan_objmgr_register_pdev_delete_handler(
+QDF_STATUS wlan_objmgr_register_pdev_destroy_handler(
 		enum wlan_umac_comp_id id,
-		wlan_objmgr_pdev_delete_handler handler,
+		wlan_objmgr_pdev_destroy_handler handler,
 		void *args);
 
 /**
- * wlan_objmgr_unregister_pdev_delete_handler() - unregister pdev delete handler
+ * wlan_objmgr_unregister_pdev_destroy_handler() - unregister pdev destroy handler
  * @id: component id
  * @handler: function pointer of the component
  * @args: args, if component wants certain args to be passed on PDEV deletion
@@ -227,9 +227,9 @@ QDF_STATUS wlan_objmgr_register_pdev_delete_handler(
  *         Failure (if handler is not present, each failure has different error
  *         code)
  */
-QDF_STATUS wlan_objmgr_unregister_pdev_delete_handler(
+QDF_STATUS wlan_objmgr_unregister_pdev_destroy_handler(
 		enum wlan_umac_comp_id id,
-		wlan_objmgr_pdev_delete_handler handler,
+		wlan_objmgr_pdev_destroy_handler handler,
 		void *args);
 
 /**
@@ -304,7 +304,7 @@ QDF_STATUS wlan_objmgr_unregister_vdev_create_handler(
 		void *args);
 
 /**
- * wlan_objmgr_register_vdev_delete_handler() - register vdev delete handler
+ * wlan_objmgr_register_vdev_destroy_handler() - register vdev destroy handler
  * @id: component id
  * @handler: function pointer of the component
  * @args: args, if component wants certain args to be passed on VDEV deletion
@@ -316,13 +316,13 @@ QDF_STATUS wlan_objmgr_unregister_vdev_create_handler(
  *         Failure (if registration fails, each failure has different error
  *         code)
  */
-QDF_STATUS wlan_objmgr_register_vdev_delete_handler(
+QDF_STATUS wlan_objmgr_register_vdev_destroy_handler(
 		enum wlan_umac_comp_id id,
-		wlan_objmgr_vdev_delete_handler handler,
+		wlan_objmgr_vdev_destroy_handler handler,
 		void *args);
 
 /**
- * wlan_objmgr_unregister_vdev_delete_handler() - unregister vdev delete handler
+ * wlan_objmgr_unregister_vdev_destroy_handler() - unregister vdev destroy handler
  * @id: component id
  * @handler: function pointer of the component
  * @args: args, if component wants certain args to be passed on VDEV deletion
@@ -333,9 +333,9 @@ QDF_STATUS wlan_objmgr_register_vdev_delete_handler(
  *         Failure (if handler is not present, each failure has different error
  *         code)
  */
-QDF_STATUS wlan_objmgr_unregister_vdev_delete_handler(
+QDF_STATUS wlan_objmgr_unregister_vdev_destroy_handler(
 		enum wlan_umac_comp_id id,
-		wlan_objmgr_vdev_delete_handler handler,
+		wlan_objmgr_vdev_destroy_handler handler,
 		void *args);
 
 /**
@@ -410,7 +410,7 @@ QDF_STATUS wlan_objmgr_unregister_peer_create_handler(
 		void *args);
 
 /**
- * wlan_objmgr_register_peer_delete_handler() - register peer delete handler
+ * wlan_objmgr_register_peer_destroy_handler() - register peer destroy handler
  * @id: component id
  * @handler: function pointer of the component
  * @args: args, if component wants certain args to be passed on PEER deletion
@@ -422,13 +422,13 @@ QDF_STATUS wlan_objmgr_unregister_peer_create_handler(
  *         Failure (if registration fails, each failure has different error
  *         code)
  */
-QDF_STATUS wlan_objmgr_register_peer_delete_handler(
+QDF_STATUS wlan_objmgr_register_peer_destroy_handler(
 		enum wlan_umac_comp_id id,
-		wlan_objmgr_peer_delete_handler handler,
+		wlan_objmgr_peer_destroy_handler handler,
 		void *args);
 
 /**
- * wlan_objmgr_unregister_peer_delete_handler() - unregister peer delete handler
+ * wlan_objmgr_unregister_peer_destroy_handler() - unregister peer destroy handler
  * @id: component id
  * @handler: function pointer of the component
  * @args: args, if component wants certain args to be passed on PEER deletion
@@ -439,9 +439,9 @@ QDF_STATUS wlan_objmgr_register_peer_delete_handler(
  *         Failure (if handler is not present, each failure has different error
  *         code)
  */
-QDF_STATUS wlan_objmgr_unregister_peer_delete_handler(
+QDF_STATUS wlan_objmgr_unregister_peer_destroy_handler(
 		enum wlan_umac_comp_id id,
-		wlan_objmgr_peer_delete_handler handler,
+		wlan_objmgr_peer_destroy_handler handler,
 		void *args);
 
 /**

+ 135 - 16
umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h

@@ -133,11 +133,12 @@ struct wlan_objmgr_pdev_mlme {
 
 /**
  * struct wlan_objmgr_pdev_objmgr - pdev object object manager structure
- * @wlan_pdev_id:    PDEV id
- * @wlan_vdev_list:  List maintains the VDEVs created on this PDEV
- * @wlan_vdev_count: VDEVs count
- * @max_vdev_count:  Max no. of VDEVs supported by this PDEV
- * @wlan_psoc:       back pointer to PSOC, its attached to
+ * @wlan_pdev_id:      PDEV id
+ * @wlan_vdev_list:    List maintains the VDEVs created on this PDEV
+ * @wlan_vdev_count:   VDEVs count
+ * @max_vdev_count:    Max no. of VDEVs supported by this PDEV
+ * @wlan_psoc:         back pointer to PSOC, its attached to
+ * @ref_cnt:           Ref count
  */
 struct wlan_objmgr_pdev_objmgr {
 	uint8_t wlan_pdev_id;
@@ -145,6 +146,7 @@ struct wlan_objmgr_pdev_objmgr {
 	uint8_t wlan_vdev_count;
 	uint8_t max_vdev_count;
 	struct wlan_objmgr_psoc *wlan_psoc;
+	qdf_atomic_t ref_cnt;
 };
 
 /**
@@ -192,8 +194,9 @@ struct wlan_objmgr_pdev *wlan_objmgr_pdev_obj_create(
  * wlan_objmgr_pdev_obj_delete() - pdev delete
  * @psoc: PDEV object
  *
- * Deletes PDEV object,
- * Invokes the registered notifiers to delete component objects
+ * Logically deletes PDEV object,
+ * Once all the references are released, object manager invokes the registered
+ * notifiers to destroy component objects
  *
  * Return: SUCCESS/FAILURE
  */
@@ -251,6 +254,7 @@ QDF_STATUS wlan_objmgr_pdev_component_obj_detach(
  * @lock_free_op: This gives provision to run this API with out lock protected
  *                It would be useful, for operations like Obj Delete, where
  *                lock should not be taken by caller.
+ * @dbg_id: id of the caller
  *
  * API to be used for performing the operations on all VDEV/PEER objects
  * of pdev
@@ -266,7 +270,8 @@ QDF_STATUS wlan_objmgr_pdev_iterate_obj_list(
 		struct wlan_objmgr_pdev *pdev,
 		enum wlan_objmgr_obj_type obj_type,
 		wlan_objmgr_pdev_op_handler handler,
-		void *arg, uint8_t lock_free_op);
+		void *arg, uint8_t lock_free_op,
+		wlan_objmgr_ref_dbgid dbg_id);
 
 /**
  * wlan_objmgr_trigger_pdev_comp_priv_object_creation() - create
@@ -285,12 +290,12 @@ QDF_STATUS wlan_objmgr_trigger_pdev_comp_priv_object_creation(
 		enum wlan_umac_comp_id id);
 
 /**
- * wlan_objmgr_trigger_pdev_comp_priv_object_deletion() - delete
+ * wlan_objmgr_trigger_pdev_comp_priv_object_deletion() - destroy
  * comp object of pdev
  * @pdev: PDEV object
  * @id: Component id
  *
- * API to delete component private object in run time, this would
+ * API to destroy component private object in run time, this would
  * be used for features which gets disabled in run time
  *
  * Return: SUCCESS on successful deletion
@@ -301,30 +306,66 @@ QDF_STATUS wlan_objmgr_trigger_pdev_comp_priv_object_deletion(
 		enum wlan_umac_comp_id id);
 
 /**
- * wlan_objmgr_find_vdev_by_id_from_pdev() - find vdev using id from pdev
+ * wlan_objmgr_get_vdev_by_id_from_pdev() - find vdev using id from pdev
  * @pdev: PDEV object
  * @vdev_id: vdev id
+ * @dbg_id: id of the caller
  *
  * API to find vdev object pointer by vdev id from pdev's vdev list
  *
  * Return: vdev pointer
  *         NULL on FAILURE
  */
-struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_pdev(
-			struct wlan_objmgr_pdev *pdev, uint8_t vdev_id);
+struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev(
+			struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
+			wlan_objmgr_ref_dbgid dbg_id);
 
 /**
- * wlan_objmgr_find_vdev_by_macaddr_from_pdev() - find vdev using macaddr
+ * wlan_objmgr_get_vdev_by_id_from_pdev_no_state() - find vdev using id from
+ *                                                      pdev
+ * @pdev: PDEV object
+ * @vdev_id: vdev id
+ * @dbg_id: id of the caller
+ *
+ * API to find vdev object pointer by vdev id from pdev's vdev list
+ *
+ * Return: vdev pointer
+ *         NULL on FAILURE
+ */
+struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_no_state(
+			struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
+			wlan_objmgr_ref_dbgid dbg_id);
+
+/**
+ * wlan_objmgr_get_vdev_by_macaddr_from_pdev() - find vdev using macaddr
  * @pdev: PDEV object
  * @macaddr: MAC address
+ * @dbg_id: id of the caller
  *
  * API to find vdev object pointer by vdev mac addr from pdev's vdev list
  *
  * Return: vdev pointer
  *         NULL on FAILURE
  */
-struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_pdev(
-		struct wlan_objmgr_pdev *pdev, uint8_t *macaddr);
+struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev(
+		struct wlan_objmgr_pdev *pdev, uint8_t *macaddr,
+		wlan_objmgr_ref_dbgid dbg_id);
+
+/**
+ * wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state() - find vdev using
+ *                                                           macaddr
+ * @pdev: PDEV object
+ * @macaddr: MAC address
+ * @dbg_id: id of the caller
+ *
+ * API to find vdev object pointer by vdev mac addr from pdev's vdev list
+ *
+ * Return: vdev pointer
+ *         NULL on FAILURE
+ */
+struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state(
+		struct wlan_objmgr_pdev *pdev, uint8_t *macaddr,
+		wlan_objmgr_ref_dbgid dbg_id);
 
 /**
  * wlan_objmgr_pdev_get_comp_private_obj() - get pdev component private object
@@ -601,4 +642,82 @@ static inline uint8_t wlan_pdev_get_max_vdev_count(
 	/* This API is invoked with lock acquired, do not add log prints */
 	return pdev->pdev_objmgr.max_vdev_count;
 }
+
+/**
+ * DOC: Examples to use PDEV ref count APIs
+ *
+ * In all the scenarios, the pair of API should be followed
+ * otherwise it lead to memory leak
+ *
+ *  scenario 1:
+ *
+ *     wlan_objmgr_pdev_obj_create()
+ *     ----
+ *     wlan_objmgr_pdev_obj_delete()
+ *
+ *  scenario 2:
+ *
+ *     wlan_objmgr_pdev_get_ref()
+ *     ----
+ *     the operations which are done on
+ *     pdev object
+ *     ----
+ *     wlan_objmgr_pdev_release_ref()
+ *
+ *  scenario 3:
+ *
+ *     wlan_objmgr_get_pdev_by_id[_no_state]()
+ *     ----
+ *     the operations which are done on
+ *     pdev object
+ *     ----
+ *     wlan_objmgr_pdev_release_ref()
+ *
+ *  scenario 4:
+ *
+ *     wlan_objmgr_get_pdev_by_macaddr[_no_state]()
+ *     ----
+ *     the operations which are done on
+ *     pdev object
+ *     ----
+ *     wlan_objmgr_pdev_release_ref()
+ */
+
+/**
+ * wlan_objmgr_pdev_get_ref() - increment ref count
+ * @pdev: PDEV object
+ * @id:   Object Manager ref debug id
+ *
+ * API to increment ref count of pdev
+ *
+ * Return: void
+ */
+void wlan_objmgr_pdev_get_ref(struct wlan_objmgr_pdev *pdev,
+					wlan_objmgr_ref_dbgid id);
+
+/**
+ * wlan_objmgr_pdev_try_get_ref() - increment ref count, if allowed
+ * @pdev: PDEV object
+ * @id:   Object Manager ref debug id
+ *
+ * API to increment ref count of pdev after checking valid object state
+ *
+ * Return: void
+ */
+QDF_STATUS wlan_objmgr_pdev_try_get_ref(struct wlan_objmgr_pdev *pdev,
+						wlan_objmgr_ref_dbgid id);
+
+/**
+ * wlan_objmgr_pdev_release_ref() - decrement ref count
+ * @pdev: PDEV object
+ * @id:   Object Manager ref debug id
+ *
+ * API to decrement ref count of pdev, if ref count is 1, it initiates the
+ * PDEV deletion
+ *
+ * Return: void
+ */
+void wlan_objmgr_pdev_release_ref(struct wlan_objmgr_pdev *pdev,
+						wlan_objmgr_ref_dbgid id);
+
 #endif /* _WLAN_OBJMGR_PDEV_H_*/

+ 58 - 28
umac/cmn_services/obj_mgr/inc/wlan_objmgr_peer_obj.h

@@ -21,6 +21,7 @@
   */
 #ifndef _WLAN_OBJMGR_PEER_OBJ_H_
 #define _WLAN_OBJMGR_PEER_OBJ_H_
+
 #include <qdf_types.h>
 #include <qdf_atomic.h>
 
@@ -134,8 +135,8 @@ struct wlan_objmgr_peer_mlme {
 
 /**
  * struct wlan_objmgr_peer_objmgr - object manager data of peer
- * @vdev:      VDEV pointer to which it is associated
- * @ref_cnt:  Ref count
+ * @vdev:              VDEV pointer to which it is associated
+ * @ref_cnt:           Ref count
  */
 struct wlan_objmgr_peer_objmgr {
 	struct wlan_objmgr_vdev *vdev;
@@ -203,7 +204,7 @@ struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create(
  * @peer: PEER object
  *
  * Deletes PEER object, removes it from PSOC's, VDEV's peer list
- * Invokes the registered notifiers to delete component objects
+ * Invokes the registered notifiers to destroy component objects
  *
  * Return: SUCCESS/FAILURE
  */
@@ -268,12 +269,12 @@ QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_creation(
 		enum wlan_umac_comp_id id);
 
 /**
- * wlan_objmgr_trigger_peer_comp_priv_object_deletion() - delete
+ * wlan_objmgr_trigger_peer_comp_priv_object_deletion() - destroy
  * peer comp object
  * @peer: PEER object
  * @id: Component id
  *
- * API to delete component private object in run time, this would
+ * API to destroy component private object in run time, this would
  * be used for features which gets disabled in run time
  *
  * Return: SUCCESS on successful deletion
@@ -324,45 +325,74 @@ static inline void wlan_peer_obj_unlock(struct wlan_objmgr_peer *peer)
 {
 	qdf_spin_unlock_bh(&peer->peer_lock);
 }
+
 /**
- * wlan_objmgr_peer_ref_peer() - increment ref count
+ * DOC: Examples to use PEER ref count APIs
+ *
+ * In all the scenarios, the pair of API should be followed
+ * other it lead to memory leak
+ *
+ *  scenario 1:
+ *
+ *     wlan_objmgr_peer_obj_create()
+ *     ----
+ *     wlan_objmgr_peer_obj_delete()
+ *
+ *  scenario 2:
+ *
+ *     wlan_objmgr_peer_get_ref()
+ *     ----
+ *     the operations which are done on
+ *     peer object
+ *     ----
+ *     wlan_objmgr_peer_release_ref()
+ *
+ *  scenario 3:
+ *
+ *     API to retrieve peer (xxx_get_peer_xxx())
+ *     ----
+ *     the operations which are done on
+ *     peer object
+ *     ----
+ *     wlan_objmgr_peer_release_ref()
+ */
+
+/**
+ * wlan_objmgr_peer_get_ref() - increment ref count
  * @peer: PEER object
+ * @id:   Object Manager ref debug id
  *
  * API to increment ref count of peer
  *
  * Return: void
  */
-static inline void wlan_objmgr_peer_ref_peer(struct wlan_objmgr_peer *peer)
-{
-	if (peer == NULL) {
-		qdf_print("%s: peer obj is NULL\n", __func__);
-		return;
-	}
-	/* Increment ref count */
-	qdf_atomic_inc(&peer->peer_objmgr.ref_cnt);
-	return;
-}
+void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer,
+					wlan_objmgr_ref_dbgid id);
+
+/**
+ * wlan_objmgr_peer_try_get_ref() - increment ref count, if allowed
+ * @peer: PEER object
+ * @id:   Object Manager ref debug id
+ *
+ * API to increment ref count of peer, if object state is valid
+ *
+ * Return: void
+ */
+QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer,
+						 wlan_objmgr_ref_dbgid id);
 
 /**
- * wlan_objmgr_peer_unref_peer() - decrement ref count
+ * wlan_objmgr_peer_release_ref() - decrement ref count
  * @peer: PEER object
+ * @id:   Object Manager ref debug id
  *
  * API to decrement ref count of peer, if ref count is 1, it initiates the
  * peer deletion
  *
  * Return: void
  */
-static inline void wlan_objmgr_peer_unref_peer(struct wlan_objmgr_peer *peer)
-{
-	if (peer == NULL) {
-		qdf_print("%s: peer obj is NULL\n", __func__);
-		return;
-	}
-	/* Decrement ref count, free peer, if count becomes 0 */
-	if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt))
-		wlan_objmgr_peer_obj_delete(peer);
-	return;
-}
+void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer,
+						 wlan_objmgr_ref_dbgid id);
 
 /**
  * wlan_psoc_peer_list_peek_head() - get head of psoc peer list

+ 194 - 23
umac/cmn_services/obj_mgr/inc/wlan_objmgr_psoc_obj.h

@@ -192,6 +192,7 @@ struct wlan_objmgr_psoc_nif {
  * @wlan_vdev_id_map[]:   VDEV id map, to allocate free ids
  * @wlan_peer_count:      PEER count
  * @peer_list:            Peer list
+ * @ref_cnt:              Ref count
  */
 struct wlan_objmgr_psoc_objmgr {
 	uint8_t wlan_pdev_count;
@@ -203,6 +204,7 @@ struct wlan_objmgr_psoc_objmgr {
 	uint32_t wlan_vdev_id_map[2];
 	uint16_t wlan_peer_count;
 	struct wlan_peer_list peer_list;
+	qdf_atomic_t ref_cnt;
 };
 
 /**
@@ -282,8 +284,9 @@ struct wlan_objmgr_psoc *wlan_objmgr_psoc_obj_create(uint32_t phy_version,
  * wlan_objmgr_psoc_obj_delete() - psoc object delete
  * @psoc: PSOC object
  *
- * Deletes PSOC object,
- * Invokes the registered notifiers to delete component objects
+ * Logically deletes PSOC object,
+ * Once all the references are released, object manager invokes the registered
+ * notifiers to destroy component objects
  *
  * Return: SUCCESS/FAILURE
  */
@@ -341,6 +344,7 @@ QDF_STATUS wlan_objmgr_psoc_component_obj_detach(
  * @lock_free_op: This gives provision to run this API with out lock protected
  *                 It would be useful, for operations like Obj Delete, where
  *                 lock should not be taken by caller.
+ * @dbg_id: id of the caller
  *
  * API to be used for performing the operations on all PDEV/VDEV/PEER objects
  * of psoc
@@ -355,7 +359,8 @@ QDF_STATUS wlan_objmgr_iterate_obj_list(
 		struct wlan_objmgr_psoc *psoc,
 		enum wlan_objmgr_obj_type obj_type,
 		wlan_objmgr_op_handler handler,
-		void *arg, uint8_t lock_free_op);
+		void *arg, uint8_t lock_free_op,
+		wlan_objmgr_ref_dbgid dbg_id);
 
 /**
  * wlan_objmgr_free_all_objects_per_psoc() - free all psoc objects
@@ -385,12 +390,12 @@ QDF_STATUS wlan_objmgr_trigger_psoc_comp_priv_object_creation(
 		enum wlan_umac_comp_id id);
 
 /**
- * wlan_objmgr_trigger_psoc_comp_priv_object_deletion() - delete
+ * wlan_objmgr_trigger_psoc_comp_priv_object_deletion() - destroy
  * psoc comp object
  * @psoc: PSOC object
  * @id: Component id
  *
- * API to delete component private object in run time, this would
+ * API to destroy component private object in run time, this would
  * be used for features which gets disabled in run time
  *
  * Return: SUCCESS on successful deletion
@@ -401,85 +406,192 @@ QDF_STATUS wlan_objmgr_trigger_psoc_comp_priv_object_deletion(
 		enum wlan_umac_comp_id id);
 
 /**
- * wlan_objmgr_find_peer() - find peer from psoc's peer list
+ * wlan_objmgr_get_peer() - find peer from psoc's peer list
  * @psoc: PSOC object
  * @macaddr: MAC address
+ * @dbg_id: id of the caller
  *
  * API to find peer object pointer by MAC addr
  *
  * Return: peer pointer
  *         NULL on FAILURE
  */
-struct wlan_objmgr_peer *wlan_objmgr_find_peer(
-			struct wlan_objmgr_psoc *psoc, uint8_t *macaddr);
+struct wlan_objmgr_peer *wlan_objmgr_get_peer(
+			struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
+			wlan_objmgr_ref_dbgid dbg_id);
+
+/**
+ * wlan_objmgr_get_peer_no_state() - find peer from psoc's peer list
+ * @psoc: PSOC object
+ * @macaddr: MAC address
+ * @dbg_id: id of the caller
+ *
+ * API to find peer object pointer by MAC addr, ignores the state check
+ *
+ * Return: peer pointer
+ *         NULL on FAILURE
+ */
+struct wlan_objmgr_peer *wlan_objmgr_get_peer_no_state(
+			struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
+			wlan_objmgr_ref_dbgid dbg_id);
 
 /**
- * wlan_objmgr_find_peer_by_mac_n_vdev() - find peer from psoc's peer list
+ * wlan_objmgr_get_peer_by_mac_n_vdev() - find peer from psoc's peer list
  *                                          using mac address and bssid
  * @psoc: PSOC object
  * @macaddr: MAC address
  * @bssid: MAC address of AP its associated
+ * @dbg_id: id of the caller
  *
  * API to find peer object pointer by MAC addr and vdev self mac address
  *
  * Return: peer pointer
  *         NULL on FAILURE
  */
-struct wlan_objmgr_peer *wlan_objmgr_find_peer_by_mac_n_vdev(
+struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev(
+			struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
+			uint8_t *bssid, wlan_objmgr_ref_dbgid dbg_id);
+
+/**
+ * wlan_objmgr_get_peer_by_mac_n_vdev_no_state() - find peer from psoc's peer
+ *                                          list using mac address and bssid
+ * @psoc: PSOC object
+ * @macaddr: MAC address
+ * @bssid: MAC address of AP its associated
+ * @dbg_id: id of the caller
+ *
+ * API to find peer object pointer by MAC addr and vdev self mac address,
+ * ignores the state
+ *
+ * Return: peer pointer
+ *         NULL on FAILURE
+ */
+struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev_no_state(
 			struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
-			uint8_t *bssid);
+			uint8_t *bssid, wlan_objmgr_ref_dbgid dbg_id);
 
 /**
- * wlan_objmgr_find_pdev_by_id() - retrieve pdev by id
+ * wlan_objmgr_get_pdev_by_id() - retrieve pdev by id
  * @psoc: PSOC object
  * @id: pdev id
+ * @dbg_id: id of the caller
  *
  * API to find pdev object pointer by pdev id
  *
  * Return: pdev pointer
  *         NULL on FAILURE
  */
-struct wlan_objmgr_pdev *wlan_objmgr_find_pdev_by_id(
-		struct wlan_objmgr_psoc *psoc, uint8_t id);
+struct wlan_objmgr_pdev *wlan_objmgr_get_pdev_by_id(
+		struct wlan_objmgr_psoc *psoc, uint8_t id,
+		wlan_objmgr_ref_dbgid dbg_id);
 
 /**
- * wlan_objmgr_find_pdev_by_macaddr() - retrieve pdev by macaddr
+ * wlan_objmgr_get_pdev_by_id_no_state() - retrieve pdev by id
+ * @psoc: PSOC object
+ * @id: pdev id
+ * @dbg_id: id of the caller
+ *
+ * API to find pdev object pointer by pdev id, Ignores the state check
+ *
+ * Return: pdev pointer
+ *         NULL on FAILURE
+ */
+struct wlan_objmgr_pdev *wlan_objmgr_get_pdev_by_id_no_state(
+			struct wlan_objmgr_psoc *psoc, uint8_t id,
+			wlan_objmgr_ref_dbgid dbg_id);
+
+/**
+ * wlan_objmgr_get_pdev_by_macaddr() - retrieve pdev by macaddr
  * @psoc: PSOC object
  * @macaddr: MAC address
+ * @dbg_id: id of the caller
  *
  * API to find pdev object pointer by pdev macaddr
  *
  * Return: pdev pointer
  *         NULL on FAILURE
  */
-struct wlan_objmgr_pdev *wlan_objmgr_find_pdev_by_macaddr(
-		struct wlan_objmgr_psoc *psoc, uint8_t *macaddr);
+struct wlan_objmgr_pdev *wlan_objmgr_get_pdev_by_macaddr(
+		struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
+		wlan_objmgr_ref_dbgid dbg_id);
+
+/**
+ * wlan_objmgr_get_pdev_by_macaddr_no_state() - retrieve pdev by macaddr
+ * @psoc: PSOC object
+ * @macaddr: MAC address
+ * @dbg_id: id of the caller
+ *
+ * API to find pdev object pointer by pdev macaddr, ignores the state check
+ *
+ * Return: pdev pointer
+ *         NULL on FAILURE
+ */
+struct wlan_objmgr_pdev *wlan_objmgr_get_pdev_by_macaddr_no_state(
+		struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
+		wlan_objmgr_ref_dbgid dbg_id);
 
 /**
- * wlan_objmgr_find_vdev_by_id_from_psoc() - retrieve vdev by id
+ * wlan_objmgr_get_vdev_by_id_from_psoc() - retrieve vdev by id
  * @psoc: PSOC object
  * @id: vdev id
+ * @dbg_id: id of the caller
  *
  * API to find vdev object pointer by vdev id from psoc
  *
  * Return: vdev pointer
  *         NULL on FAILURE
  */
-struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_psoc(
-			struct wlan_objmgr_psoc *psoc, uint8_t vdev_id);
+struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc(
+			struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
+			wlan_objmgr_ref_dbgid dbg_id);
 
 /**
- * wlan_objmgr_find_vdev_by_macaddr_from_psoc() - retrieve vdev by macaddr
+ * wlan_objmgr_get_vdev_by_id_from_psoc_no_state() - retrieve vdev by id
+ * @psoc: PSOC object
+ * @id: vdev id
+ * @dbg_id: id of the caller
+ *
+ * API to find vdev object pointer by vdev id from psoc, ignores the
+ * state check
+ *
+ * Return: vdev pointer
+ *         NULL on FAILURE
+ */
+struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc_no_state(
+			struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
+			wlan_objmgr_ref_dbgid dbg_id);
+
+/**
+ * wlan_objmgr_get_vdev_by_macaddr_from_psoc() - retrieve vdev by macaddr
  * @psoc: PSOC object
  * @macaddr: macaddr
+ * @dbg_id: id of the caller
  *
  * API to find vdev object pointer by vdev macaddr from psoc
  *
  * Return: vdev pointer
  *         NULL on FAILURE
  */
-struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_psoc(
-		struct wlan_objmgr_psoc *psoc, uint8_t *macaddr);
+struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc(
+		struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
+		wlan_objmgr_ref_dbgid dbg_id);
+
+/**
+ * wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state() - retrieve vdev by
+ *                                                           macaddr
+ * @psoc: PSOC object
+ * @macaddr: macaddr
+ * @dbg_id: id of the caller
+ *
+ * API to find vdev object pointer by vdev macaddr from psoc, ignores the state
+ * check
+ *
+ * Return: vdev pointer
+ *         NULL on FAILURE
+ */
+struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state(
+		struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
+		wlan_objmgr_ref_dbgid dbg_id);
 
 /**
  * wlan_psoc_obj_lock() - Acquire PSOC spinlock
@@ -851,4 +963,63 @@ static inline void *wlan_psoc_get_tgt_if_handle(struct wlan_objmgr_psoc *psoc)
 	return psoc->tgt_if_handle;
 }
 
+/**
+ * DOC: Examples to use PSOC ref count APIs
+ *
+ * In all the scenarios, the pair of API should be followed
+ * other it lead to memory leak
+ *
+ *  scenario 1:
+ *
+ *     wlan_objmgr_psoc_obj_create()
+ *     ----
+ *     wlan_objmgr_psoc_obj_delete()
+ *
+ *  scenario 2:
+ *
+ *     wlan_objmgr_psoc_get_ref()
+ *     ----
+ *     the operations which are done on
+ *     psoc object
+ *     ----
+ *     wlan_objmgr_psoc_release_ref()
+ */
+
+/**
+ * wlan_objmgr_psoc_get_ref() - increment ref count
+ * @psoc: PSOC object
+ * @id:   Object Manager ref debug id
+ *
+ * API to increment ref count of psoc
+ *
+ * Return: void
+ */
+void wlan_objmgr_psoc_get_ref(struct wlan_objmgr_psoc *psoc,
+					wlan_objmgr_ref_dbgid id);
+
+/**
+ * wlan_objmgr_psoc_try_get_ref() - increment ref count, if allowed
+ * @psoc: PSOC object
+ * @id:   Object Manager ref debug id
+ *
+ * API to increment ref count after checking valid object state
+ *
+ * Return: void
+ */
+QDF_STATUS wlan_objmgr_psoc_try_get_ref(struct wlan_objmgr_psoc *psoc,
+						wlan_objmgr_ref_dbgid id);
+
+/**
+ * wlan_objmgr_psoc_release_ref() - decrement ref count
+ * @psoc: PSOC object
+ * @id:   Object Manager ref debug id
+ *
+ * API to decrement ref count of psoc, if ref count is 1, it initiates the
+ * PSOC deletion
+ *
+ * Return: void
+ */
+void wlan_objmgr_psoc_release_ref(struct wlan_objmgr_psoc *psoc,
+						wlan_objmgr_ref_dbgid id);
+
 #endif /* _WLAN_OBJMGR_PSOC_OBJ_H_*/

+ 102 - 13
umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h

@@ -136,7 +136,7 @@
 #define WLAN_VDEV_FEXT_NON_BEACON           0x00400000
 
 /* VDEV OP flags  */
-  /* if the vap deleted by user */
+  /* if the vap destroyed by user */
 #define WLAN_VDEV_OP_DELETE_PROGRESS        0x00000001
  /* set to enable sta-fws fweature */
 #define WLAN_VDEV_OP_STAFWD                 0x00000002
@@ -291,14 +291,15 @@ struct wlan_objmgr_vdev_nif {
 
 /**
  *  struct wlan_objmgr_vdev_objmgr - vdev object manager sub structure
- *  @vdev_id:          VDEV id
- *  @self_peer:        Self PEER
- *  @bss_peer:         BSS PEER
- *  @wlan_peer_list:   PEER list
- *  @wlan_pdev:        PDEV pointer
- *  @wlan_peer_count:  Peer count
- *  @max_peer_count:   Max Peer count
- *  @c_flags:          creation specific flags
+ *  @vdev_id:           VDEV id
+ *  @self_peer:         Self PEER
+ *  @bss_peer:          BSS PEER
+ *  @wlan_peer_list:    PEER list
+ *  @wlan_pdev:         PDEV pointer
+ *  @wlan_peer_count:   Peer count
+ *  @max_peer_count:    Max Peer count
+ *  @c_flags:           creation specific flags
+ *  @ref_cnt:           Ref count
  */
 struct wlan_objmgr_vdev_objmgr {
 	uint8_t vdev_id;
@@ -309,6 +310,7 @@ struct wlan_objmgr_vdev_objmgr {
 	uint16_t wlan_peer_count;
 	uint16_t max_peer_count;
 	uint32_t c_flags;
+	qdf_atomic_t ref_cnt;
 };
 
 /**
@@ -357,8 +359,9 @@ struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create(
  * wlan_objmgr_vdev_obj_delete() - vdev object delete
  * @vdev: vdev object
  *
- * Deletes VDEV object, removes it from PSOC's, PDEV's VDEV list
- * Invokes the registered notifiers to delete component objects
+ * Logically deletes VDEV object,
+ * Once all the references are released, object manager invokes the registered
+ * notifiers to destroy component objects
  *
  * Return: SUCCESS/FAILURE
  */
@@ -411,6 +414,7 @@ QDF_STATUS wlan_objmgr_vdev_component_obj_detach(
  * @handler: the handler will be called for each object of requested type
  *            the handler should be implemented to perform required operation
  * @arg:     agruments passed by caller
+ * @dbg_id: id of the caller
  *
  * API to be used for performing the operations on all PEER objects
  * of vdev
@@ -424,7 +428,7 @@ typedef void (*wlan_objmgr_vdev_op_handler)(struct wlan_objmgr_vdev *vdev,
 QDF_STATUS wlan_objmgr_iterate_peerobj_list(
 		struct wlan_objmgr_vdev *vdev,
 		wlan_objmgr_vdev_op_handler handler,
-		void *arg);
+		void *arg, wlan_objmgr_ref_dbgid dbg_id);
 
 /**
  * wlan_objmgr_trigger_vdev_comp_priv_object_creation() - vdev
@@ -448,7 +452,7 @@ QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_creation(
  * @vdev: VDEV object
  * @id: Component id
  *
- * API to delete component private object in run time, this would
+ * API to destroy component private object in run time, this would
  * be used for features which gets disabled in run time
  *
  * Return: SUCCESS on successful deletion
@@ -1364,4 +1368,89 @@ static inline void *wlan_vdev_get_ospriv(struct wlan_objmgr_vdev *vdev)
 	/* This API is invoked with lock acquired, do not add log prints */
 	return vdev->vdev_nif.osdev;
 }
+
+/**
+ * wlan_vdev_get_peer_count() - get vdev peer count
+ * @vdev: VDEV object
+ *
+ * API to get OS private pointer from VDEV
+ *
+ * Caller need to acquire lock with wlan_vdev_obj_lock()
+ *
+ * Return: peer_count - vdev's peer count
+ */
+static inline uint16_t wlan_vdev_get_peer_count(struct wlan_objmgr_vdev *vdev)
+{
+	/* This API is invoked with lock acquired, do not add log prints */
+	return vdev->vdev_objmgr.wlan_peer_count;
+}
+
+/**
+ * DOC: Examples to use VDEV ref count APIs
+ *
+ * In all the scenarios, the pair of API should be followed
+ * other it lead to memory leak
+ *
+ *  scenario 1:
+ *
+ *     wlan_objmgr_vdev_obj_create()
+ *     ----
+ *     wlan_objmgr_vdev_obj_delete()
+ *
+ *  scenario 2:
+ *
+ *     wlan_objmgr_vdev_get_ref()
+ *     ----
+ *     the operations which are done on
+ *     vdev object
+ *     ----
+ *     wlan_objmgr_vdev_release_ref()
+ *
+ *  scenario 3:
+ *
+ *     API to retrieve vdev (xxx_get_vdev_xxx())
+ *     ----
+ *     the operations which are done on
+ *     vdev object
+ *     ----
+ *     wlan_objmgr_vdev_release_ref()
+ */
+
+/**
+ * wlan_objmgr_vdev_get_ref() - increment ref count
+ * @vdev: VDEV object
+ * @id:   Object Manager ref debug id
+ *
+ * API to increment ref count of vdev
+ *
+ * Return: void
+ */
+void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev,
+				wlan_objmgr_ref_dbgid id);
+
+/**
+ * wlan_objmgr_vdev_try_get_ref() - increment ref count, if allowed
+ * @vdev: VDEV object
+ * @id:   Object Manager ref debug id
+ *
+ * API to increment ref count of vdev after checking valid object state
+ *
+ * Return: void
+ */
+QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev,
+						wlan_objmgr_ref_dbgid id);
+
+/**
+ * wlan_objmgr_vdev_release_ref() - decrement ref count
+ * @vdev: VDEV object
+ * @id:   Object Manager ref debug id
+ *
+ * API to decrement ref count of vdev, if ref count is 1, it initiates the
+ * VDEV deletion
+ *
+ * Return: void
+ */
+void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev,
+						wlan_objmgr_ref_dbgid id);
+
 #endif /* _WLAN_OBJMGR_VDEV_OBJ_H_*/

+ 43 - 43
umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj.c

@@ -64,7 +64,7 @@ EXPORT_SYMBOL(wlan_objmgr_global_obj_init);
 
 QDF_STATUS wlan_objmgr_global_obj_deinit(void)
 {
-	/* If it is already deleted */
+	/* If it is already destroyed */
 	if (g_umac_glb_obj == NULL) {
 		qdf_print("%s: Global object is not allocated\n", __func__);
 		return QDF_STATUS_E_FAILURE;
@@ -138,9 +138,9 @@ QDF_STATUS wlan_objmgr_unregister_psoc_create_handler(
 	return QDF_STATUS_SUCCESS;
 }
 
-QDF_STATUS wlan_objmgr_register_psoc_delete_handler(
+QDF_STATUS wlan_objmgr_register_psoc_destroy_handler(
 		enum wlan_umac_comp_id id,
-		wlan_objmgr_psoc_delete_handler handler,
+		wlan_objmgr_psoc_destroy_handler handler,
 		void *arg)
 {
 	/* If id is not within valid range, return */
@@ -150,23 +150,23 @@ QDF_STATUS wlan_objmgr_register_psoc_delete_handler(
 	}
 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
 	/* If there is a valid entry, return failure */
-	if (g_umac_glb_obj->psoc_delete_handler[id] != NULL) {
+	if (g_umac_glb_obj->psoc_destroy_handler[id] != NULL) {
 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 		qdf_print("%s:callback for comp %d is already registered\n",
 			  __func__, id);
 		return QDF_STATUS_E_FAILURE;
 	}
 	/* Store handler and args in Global object table */
-	g_umac_glb_obj->psoc_delete_handler[id] = handler;
-	g_umac_glb_obj->psoc_delete_handler_arg[id] = arg;
+	g_umac_glb_obj->psoc_destroy_handler[id] = handler;
+	g_umac_glb_obj->psoc_destroy_handler_arg[id] = arg;
 
 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 	return QDF_STATUS_SUCCESS;
 }
 
-QDF_STATUS wlan_objmgr_unregister_psoc_delete_handler(
+QDF_STATUS wlan_objmgr_unregister_psoc_destroy_handler(
 		enum wlan_umac_comp_id id,
-		wlan_objmgr_psoc_delete_handler handler,
+		wlan_objmgr_psoc_destroy_handler handler,
 		void *arg)
 {
 	/* If id is not within valid range, return */
@@ -176,15 +176,15 @@ QDF_STATUS wlan_objmgr_unregister_psoc_delete_handler(
 	}
 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
 	/* If there is an invalid entry, return failure */
-	if (g_umac_glb_obj->psoc_delete_handler[id] != handler) {
+	if (g_umac_glb_obj->psoc_destroy_handler[id] != handler) {
 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 		qdf_print("%s:callback for comp %d is not registered\n",
 			  __func__, id);
 		return QDF_STATUS_E_FAILURE;
 	}
 	/* Reset handlers, and args to NULL */
-	g_umac_glb_obj->psoc_delete_handler[id] = NULL;
-	g_umac_glb_obj->psoc_delete_handler_arg[id] = NULL;
+	g_umac_glb_obj->psoc_destroy_handler[id] = NULL;
+	g_umac_glb_obj->psoc_destroy_handler_arg[id] = NULL;
 
 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 	return QDF_STATUS_SUCCESS;
@@ -295,9 +295,9 @@ QDF_STATUS wlan_objmgr_unregister_pdev_create_handler(
 	return QDF_STATUS_SUCCESS;
 }
 
-QDF_STATUS wlan_objmgr_register_pdev_delete_handler(
+QDF_STATUS wlan_objmgr_register_pdev_destroy_handler(
 		enum wlan_umac_comp_id id,
-		wlan_objmgr_pdev_delete_handler handler,
+		wlan_objmgr_pdev_destroy_handler handler,
 		void *arg)
 {
 	/* If id is not within valid range, return */
@@ -307,23 +307,23 @@ QDF_STATUS wlan_objmgr_register_pdev_delete_handler(
 	}
 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
 	/* If there is a valid entry, return failure */
-	if (g_umac_glb_obj->pdev_delete_handler[id] != NULL) {
+	if (g_umac_glb_obj->pdev_destroy_handler[id] != NULL) {
 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 		qdf_print("%s:callback for comp %d is already registered\n",
 			  __func__, id);
 		return QDF_STATUS_E_FAILURE;
 	}
 	/* Store handler and args in Global object table */
-	g_umac_glb_obj->pdev_delete_handler[id] = handler;
-	g_umac_glb_obj->pdev_delete_handler_arg[id] = arg;
+	g_umac_glb_obj->pdev_destroy_handler[id] = handler;
+	g_umac_glb_obj->pdev_destroy_handler_arg[id] = arg;
 
 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 	return QDF_STATUS_SUCCESS;
 }
 
-QDF_STATUS wlan_objmgr_unregister_pdev_delete_handler(
+QDF_STATUS wlan_objmgr_unregister_pdev_destroy_handler(
 		enum wlan_umac_comp_id id,
-		wlan_objmgr_pdev_delete_handler handler,
+		wlan_objmgr_pdev_destroy_handler handler,
 		void *arg)
 {
 	/* If id is not within valid range, return */
@@ -333,15 +333,15 @@ QDF_STATUS wlan_objmgr_unregister_pdev_delete_handler(
 	}
 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
 	/* If there is an invalid entry, return failure */
-	if (g_umac_glb_obj->pdev_delete_handler[id] != handler) {
+	if (g_umac_glb_obj->pdev_destroy_handler[id] != handler) {
 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 		qdf_print("%s:callback for component %d is not registered\n",
 			  __func__, id);
 		return QDF_STATUS_E_FAILURE;
 	}
 	/* Reset handlers, and args to NULL */
-	g_umac_glb_obj->pdev_delete_handler[id] = NULL;
-	g_umac_glb_obj->pdev_delete_handler_arg[id] = NULL;
+	g_umac_glb_obj->pdev_destroy_handler[id] = NULL;
+	g_umac_glb_obj->pdev_destroy_handler_arg[id] = NULL;
 
 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 	return QDF_STATUS_SUCCESS;
@@ -452,9 +452,9 @@ QDF_STATUS wlan_objmgr_unregister_vdev_create_handler(
 	return QDF_STATUS_SUCCESS;
 }
 
-QDF_STATUS wlan_objmgr_register_vdev_delete_handler(
+QDF_STATUS wlan_objmgr_register_vdev_destroy_handler(
 		enum wlan_umac_comp_id id,
-		wlan_objmgr_vdev_delete_handler handler,
+		wlan_objmgr_vdev_destroy_handler handler,
 		void *arg)
 {
 	/* If id is not within valid range, return */
@@ -464,23 +464,23 @@ QDF_STATUS wlan_objmgr_register_vdev_delete_handler(
 	}
 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
 	/* If there is a valid entry, return failure */
-	if (g_umac_glb_obj->vdev_delete_handler[id] != NULL) {
+	if (g_umac_glb_obj->vdev_destroy_handler[id] != NULL) {
 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 		qdf_print("%s:callback for comp %d is already registered\n",
 			  __func__, id);
 		return QDF_STATUS_E_FAILURE;
 	}
 	/* Store handler and args in Global object table */
-	g_umac_glb_obj->vdev_delete_handler[id] = handler;
-	g_umac_glb_obj->vdev_delete_handler_arg[id] = arg;
+	g_umac_glb_obj->vdev_destroy_handler[id] = handler;
+	g_umac_glb_obj->vdev_destroy_handler_arg[id] = arg;
 
 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 	return QDF_STATUS_SUCCESS;
 }
 
-QDF_STATUS wlan_objmgr_unregister_vdev_delete_handler(
+QDF_STATUS wlan_objmgr_unregister_vdev_destroy_handler(
 		enum wlan_umac_comp_id id,
-		wlan_objmgr_vdev_delete_handler handler,
+		wlan_objmgr_vdev_destroy_handler handler,
 		void *arg)
 {
 	/* If id is not within valid range, return */
@@ -490,15 +490,15 @@ QDF_STATUS wlan_objmgr_unregister_vdev_delete_handler(
 	}
 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
 	/* If there is an invalid entry, return failure */
-	if (g_umac_glb_obj->vdev_delete_handler[id] != handler) {
+	if (g_umac_glb_obj->vdev_destroy_handler[id] != handler) {
 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 		qdf_print("%s:callback for comp %d is not registered\n",
 			  __func__, id);
 		return QDF_STATUS_E_FAILURE;
 	}
 	/* Reset handlers, and args to NULL */
-	g_umac_glb_obj->vdev_delete_handler[id] = NULL;
-	g_umac_glb_obj->vdev_delete_handler_arg[id] = NULL;
+	g_umac_glb_obj->vdev_destroy_handler[id] = NULL;
+	g_umac_glb_obj->vdev_destroy_handler_arg[id] = NULL;
 
 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 	return QDF_STATUS_SUCCESS;
@@ -610,9 +610,9 @@ QDF_STATUS wlan_objmgr_unregister_peer_create_handler(
 	return QDF_STATUS_SUCCESS;
 }
 
-QDF_STATUS wlan_objmgr_register_peer_delete_handler(
+QDF_STATUS wlan_objmgr_register_peer_destroy_handler(
 		enum wlan_umac_comp_id id,
-		wlan_objmgr_peer_delete_handler handler,
+		wlan_objmgr_peer_destroy_handler handler,
 		void *arg)
 {
 	/* If id is not within valid range, return */
@@ -622,23 +622,23 @@ QDF_STATUS wlan_objmgr_register_peer_delete_handler(
 	}
 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
 	/* If there is a valid entry, return failure */
-	if (g_umac_glb_obj->peer_delete_handler[id] != NULL) {
+	if (g_umac_glb_obj->peer_destroy_handler[id] != NULL) {
 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 		qdf_print("%s:callback for comp %d is already registered\n",
 			  __func__, id);
 		return QDF_STATUS_E_FAILURE;
 	}
 	/* Store handler and args in Global object table */
-	g_umac_glb_obj->peer_delete_handler[id] = handler;
-	g_umac_glb_obj->peer_delete_handler_arg[id] = arg;
+	g_umac_glb_obj->peer_destroy_handler[id] = handler;
+	g_umac_glb_obj->peer_destroy_handler_arg[id] = arg;
 
 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 	return QDF_STATUS_SUCCESS;
 }
 
-QDF_STATUS wlan_objmgr_unregister_peer_delete_handler(
+QDF_STATUS wlan_objmgr_unregister_peer_destroy_handler(
 		enum wlan_umac_comp_id id,
-		wlan_objmgr_peer_delete_handler handler,
+		wlan_objmgr_peer_destroy_handler handler,
 		void *arg)
 {
 	/* If id is not within valid range, return */
@@ -648,15 +648,15 @@ QDF_STATUS wlan_objmgr_unregister_peer_delete_handler(
 	}
 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
 	/* If there is an invalid entry, return failure */
-	if (g_umac_glb_obj->peer_delete_handler[id] != handler) {
+	if (g_umac_glb_obj->peer_destroy_handler[id] != handler) {
 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 		qdf_print("%s:callback for comp %d is not registered\n",
 			  __func__, id);
 		return QDF_STATUS_E_FAILURE;
 	}
 	/* Reset handlers, and args to NULL */
-	g_umac_glb_obj->peer_delete_handler[id] = NULL;
-	g_umac_glb_obj->peer_delete_handler_arg[id] = NULL;
+	g_umac_glb_obj->peer_destroy_handler[id] = NULL;
+	g_umac_glb_obj->peer_destroy_handler_arg[id] = NULL;
 
 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 	return QDF_STATUS_SUCCESS;
@@ -754,7 +754,7 @@ QDF_STATUS wlan_objmgr_psoc_object_detach(struct wlan_objmgr_psoc *psoc)
 	return status;
 }
 
-QDF_STATUS wlan_objmgr_global_obj_can_deleted(void)
+QDF_STATUS wlan_objmgr_global_obj_can_destroyed(void)
 {
 	uint8_t index = 0;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
@@ -771,4 +771,4 @@ QDF_STATUS wlan_objmgr_global_obj_can_deleted(void)
 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 	return status;
 }
-EXPORT_SYMBOL(wlan_objmgr_global_obj_can_deleted);
+EXPORT_SYMBOL(wlan_objmgr_global_obj_can_destroyed);

+ 20 - 20
umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj_i.h

@@ -28,26 +28,26 @@
  *                              its optional
  *  @psoc_create_handler[]:     PSOC create handler array
  *  @psoc_create_handler_arg[]: PSOC create handler args array
- *  @psoc_delete_handler[]:     PSOC delete handler array
- *  @psoc_delete_handler_arg[]: PSOC delete handler args array
+ *  @psoc_destroy_handler[]:     PSOC destroy handler array
+ *  @psoc_destroy_handler_arg[]: PSOC destroy handler args array
  *  @psoc_status_handler[]:     PSOC status handler array
  *  @psoc_status_handler_arg[]: PSOC status handler args array
  *  @pdev_create_handler[]:     PDEV create handler array
  *  @pdev_create_handler_arg[]: PDEV create handler args array
- *  @pdev_delete_handler[]:     PDEV delete handler array
- *  @pdev_delete_handler_arg[]: PDEV delete handler args array
+ *  @pdev_destroy_handler[]:     PDEV destroy handler array
+ *  @pdev_destroy_handler_arg[]: PDEV destroy handler args array
  *  @pdev_status_handler[]:     PDEV status handler array
  *  @pdev_status_handler_arg[]: PDEV status handler args array
  *  @vdev_create_handler[]:     VDEV create handler array
  *  @vdev_create_handler_arg[]: VDEV create handler args array
- *  @vdev_delete_handler[]:     VDEV delete handler array
- *  @vdev_delete_handler_arg[]: VDEV delete handler args array
+ *  @vdev_destroy_handler[]:     VDEV destroy handler array
+ *  @vdev_destroy_handler_arg[]: VDEV destroy handler args array
  *  @vdev_status_handler[]:     VDEV status handler array
  *  @vdev_status_handler_arg[]: VDEV status handler args array
  *  @peer_create_handler[]:     PEER create handler array
  *  @peer_create_handler_arg[]: PEER create handler args array
- *  @peer_delete_handler[]:     PEER delete handler array
- *  @peer_delete_handler_arg[]: PEER delete handler args array
+ *  @peer_destroy_handler[]:     PEER destroy handler array
+ *  @peer_destroy_handler_arg[]: PEER destroy handler args array
  *  @peer_status_handler[]:     PEER status handler array
  *  @peer_status_handler_arg[]: PEER status handler args array
  *  @global_lock:               Global lock
@@ -57,36 +57,36 @@ struct wlan_objmgr_global {
 	wlan_objmgr_psoc_create_handler
 		psoc_create_handler[WLAN_UMAC_MAX_COMPONENTS];
 	void *psoc_create_handler_arg[WLAN_UMAC_MAX_COMPONENTS];
-	wlan_objmgr_psoc_delete_handler
-		psoc_delete_handler[WLAN_UMAC_MAX_COMPONENTS];
-	void *psoc_delete_handler_arg[WLAN_UMAC_MAX_COMPONENTS];
+	wlan_objmgr_psoc_destroy_handler
+		psoc_destroy_handler[WLAN_UMAC_MAX_COMPONENTS];
+	void *psoc_destroy_handler_arg[WLAN_UMAC_MAX_COMPONENTS];
 	wlan_objmgr_psoc_status_handler
 		psoc_status_handler[WLAN_UMAC_MAX_COMPONENTS];
 	void *psoc_status_handler_arg[WLAN_UMAC_MAX_COMPONENTS];
 	wlan_objmgr_pdev_create_handler
 		pdev_create_handler[WLAN_UMAC_MAX_COMPONENTS];
 	void *pdev_create_handler_arg[WLAN_UMAC_MAX_COMPONENTS];
-	wlan_objmgr_pdev_delete_handler
-		pdev_delete_handler[WLAN_UMAC_MAX_COMPONENTS];
-	void *pdev_delete_handler_arg[WLAN_UMAC_MAX_COMPONENTS];
+	wlan_objmgr_pdev_destroy_handler
+		pdev_destroy_handler[WLAN_UMAC_MAX_COMPONENTS];
+	void *pdev_destroy_handler_arg[WLAN_UMAC_MAX_COMPONENTS];
 	wlan_objmgr_pdev_status_handler
 		pdev_status_handler[WLAN_UMAC_MAX_COMPONENTS];
 	void *pdev_status_handler_arg[WLAN_UMAC_MAX_COMPONENTS];
 	wlan_objmgr_vdev_create_handler
 		vdev_create_handler[WLAN_UMAC_MAX_COMPONENTS];
 	void *vdev_create_handler_arg[WLAN_UMAC_MAX_COMPONENTS];
-	wlan_objmgr_vdev_delete_handler
-		vdev_delete_handler[WLAN_UMAC_MAX_COMPONENTS];
-	void *vdev_delete_handler_arg[WLAN_UMAC_MAX_COMPONENTS];
+	wlan_objmgr_vdev_destroy_handler
+		vdev_destroy_handler[WLAN_UMAC_MAX_COMPONENTS];
+	void *vdev_destroy_handler_arg[WLAN_UMAC_MAX_COMPONENTS];
 	wlan_objmgr_vdev_status_handler
 		vdev_status_handler[WLAN_UMAC_MAX_COMPONENTS];
 	void *vdev_status_handler_arg[WLAN_UMAC_MAX_COMPONENTS];
 	wlan_objmgr_peer_create_handler
 		peer_create_handler[WLAN_UMAC_MAX_COMPONENTS];
 	void *peer_create_handler_arg[WLAN_UMAC_MAX_COMPONENTS];
-	wlan_objmgr_peer_delete_handler
-		peer_delete_handler[WLAN_UMAC_MAX_COMPONENTS];
-	void *peer_delete_handler_arg[WLAN_UMAC_MAX_COMPONENTS];
+	wlan_objmgr_peer_destroy_handler
+		peer_destroy_handler[WLAN_UMAC_MAX_COMPONENTS];
+	void *peer_destroy_handler_arg[WLAN_UMAC_MAX_COMPONENTS];
 	wlan_objmgr_peer_status_handler
 		peer_status_handler[WLAN_UMAC_MAX_COMPONENTS];
 	void *peer_status_handler_arg[WLAN_UMAC_MAX_COMPONENTS];

+ 240 - 61
umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c

@@ -64,6 +64,20 @@ static QDF_STATUS wlan_objmgr_pdev_object_status(
 	return status;
 }
 
+static QDF_STATUS wlan_objmgr_pdev_obj_free(struct wlan_objmgr_pdev *pdev)
+{
+	/* Detach PDEV from PSOC PDEV's list */
+	if (wlan_objmgr_psoc_pdev_detach(pdev->pdev_objmgr.wlan_psoc, pdev) ==
+						QDF_STATUS_E_FAILURE) {
+		qdf_print("%s: PSOC PDEV detach failed\n",  __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+	qdf_spinlock_destroy(&pdev->pdev_lock);
+	qdf_mem_free(pdev);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 struct wlan_objmgr_pdev *wlan_objmgr_pdev_obj_create(
 			struct wlan_objmgr_psoc *psoc, void *osdev_priv)
 {
@@ -102,7 +116,8 @@ struct wlan_objmgr_pdev *wlan_objmgr_pdev_obj_create(
 	pdev->pdev_objmgr.max_vdev_count = WLAN_UMAC_PDEV_MAX_VDEVS;
 	/* Save HDD/OSIF pointer */
 	pdev->pdev_nif.pdev_ospriv = osdev_priv;
-
+	qdf_atomic_init(&pdev->pdev_objmgr.ref_cnt);
+	wlan_objmgr_pdev_get_ref(pdev, WLAN_OBJMGR_ID);
 	/* Invoke registered create handlers */
 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
 		handler = g_umac_glb_obj->pdev_create_handler[id];
@@ -143,10 +158,10 @@ struct wlan_objmgr_pdev *wlan_objmgr_pdev_obj_create(
 }
 EXPORT_SYMBOL(wlan_objmgr_pdev_obj_create);
 
-QDF_STATUS wlan_objmgr_pdev_obj_delete(struct wlan_objmgr_pdev *pdev)
+static QDF_STATUS wlan_objmgr_pdev_obj_destroy(struct wlan_objmgr_pdev *pdev)
 {
 	uint8_t id;
-	wlan_objmgr_pdev_delete_handler handler;
+	wlan_objmgr_pdev_destroy_handler handler;
 	QDF_STATUS obj_status;
 	void *arg;
 
@@ -155,10 +170,15 @@ QDF_STATUS wlan_objmgr_pdev_obj_delete(struct wlan_objmgr_pdev *pdev)
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	/* Invoke registered delete handlers */
+	if (pdev->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) {
+		qdf_print("%s:pdev object delete is not invoked\n", __func__);
+		WLAN_OBJMGR_BUG(0);
+	}
+
+	/* Invoke registered destroy handlers */
 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
-		handler = g_umac_glb_obj->pdev_delete_handler[id];
-		arg = g_umac_glb_obj->pdev_delete_handler_arg[id];
+		handler = g_umac_glb_obj->pdev_destroy_handler[id];
+		arg = g_umac_glb_obj->pdev_destroy_handler_arg[id];
 		if (handler != NULL)
 			pdev->obj_status[id] = handler(pdev, arg);
 		else
@@ -168,7 +188,7 @@ QDF_STATUS wlan_objmgr_pdev_obj_delete(struct wlan_objmgr_pdev *pdev)
 	obj_status = wlan_objmgr_pdev_object_status(pdev);
 
 	if (obj_status == QDF_STATUS_E_FAILURE) {
-		qdf_print("%s: PDEV component objects delete failed\n",
+		qdf_print("%s: PDEV component objects destroy failed\n",
 			  __func__);
 		/* Ideally should not happen */
 		/* This leads to memleak ??? how to handle */
@@ -179,20 +199,27 @@ QDF_STATUS wlan_objmgr_pdev_obj_delete(struct wlan_objmgr_pdev *pdev)
 	if (obj_status == QDF_STATUS_COMP_ASYNC) {
 		pdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED;
 		return QDF_STATUS_COMP_ASYNC;
-	} else {
-		/* Detach PDEV from PSOC PDEV's list */
-		if (wlan_objmgr_psoc_pdev_detach(pdev->pdev_objmgr.wlan_psoc,
-						 pdev) ==
-						 QDF_STATUS_E_FAILURE) {
-			qdf_print("%s: PSOC PDEV detach failed\n",
-				  __func__);
-			return QDF_STATUS_E_FAILURE;
-		}
-		/* de-init lock */
-		qdf_spinlock_destroy(&pdev->pdev_lock);
-		/* Free the memory */
-		qdf_mem_free(pdev);
 	}
+
+	/* Free PDEV object */
+	return wlan_objmgr_pdev_obj_free(pdev);
+}
+
+QDF_STATUS wlan_objmgr_pdev_obj_delete(struct wlan_objmgr_pdev *pdev)
+{
+	if (pdev == NULL) {
+		qdf_print("%s:pdev is NULL\n", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+	/*
+	 * Update PDEV object state to LOGICALLY DELETED
+	 * It prevents further access of this object
+	 */
+	wlan_pdev_obj_lock(pdev);
+	pdev->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED;
+	wlan_pdev_obj_unlock(pdev);
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_OBJMGR_ID);
+
 	return QDF_STATUS_SUCCESS;
 }
 EXPORT_SYMBOL(wlan_objmgr_pdev_obj_delete);
@@ -228,13 +255,16 @@ QDF_STATUS wlan_objmgr_pdev_component_obj_attach(
 	/* Save component's pointer and status */
 	pdev->pdev_comp_priv_obj[id] = comp_priv_obj;
 	pdev->obj_status[id] = status;
+
 	wlan_pdev_obj_unlock(pdev);
 
 	if (pdev->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED)
 		return QDF_STATUS_SUCCESS;
-	/* If PDEV object status is partially created means, this API is
-	invoked with differnt context, this block should be executed for async
-	components only */
+	/**
+	 * If PDEV object status is partially created means, this API is
+	 * invoked with differnt context, this block should be executed for
+	 * async components only
+	 */
 	/* Derive status */
 	obj_status = wlan_objmgr_pdev_object_status(pdev);
 	/* STATUS_SUCCESS means, object is CREATED */
@@ -281,7 +311,7 @@ QDF_STATUS wlan_objmgr_pdev_component_obj_detach(
 	pdev->obj_status[id] = QDF_STATUS_SUCCESS;
 	wlan_pdev_obj_unlock(pdev);
 
-	/* If PDEV object status is partially deleted means, this API is
+	/* If PDEV object status is partially destroyed means, this API is
 	invoked with differnt context, this block should be executed for async
 	components only */
 	if ((pdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) ||
@@ -318,15 +348,8 @@ QDF_STATUS wlan_objmgr_pdev_component_obj_detach(
 		/* Delete pdev object */
 		if ((obj_status == QDF_STATUS_SUCCESS) &&
 		    (pdev->obj_state == WLAN_OBJ_STATE_DELETED)) {
-			/* Detach pdev object from psoc */
-			if (wlan_objmgr_psoc_pdev_detach(
-				pdev->pdev_objmgr.wlan_psoc, pdev) ==
-						QDF_STATUS_E_FAILURE)
-				return QDF_STATUS_E_FAILURE;
-			/* Destroy spinlock */
-			qdf_spinlock_destroy(&pdev->pdev_lock);
-			/* Free PDEV memory */
-			qdf_mem_free(pdev);
+			/* Free PDEV object */
+			return wlan_objmgr_pdev_obj_free(pdev);
 		}
 	}
 	return QDF_STATUS_SUCCESS;
@@ -338,7 +361,8 @@ QDF_STATUS wlan_objmgr_pdev_component_obj_detach(
 static void wlan_objmgr_pdev_vdev_iterate_peers(struct wlan_objmgr_pdev *pdev,
 				struct wlan_objmgr_vdev *vdev,
 				wlan_objmgr_pdev_op_handler handler,
-				void *arg, uint8_t lock_free_op)
+				void *arg, uint8_t lock_free_op,
+				wlan_objmgr_ref_dbgid dbg_id)
 {
 	qdf_list_t *peer_list = NULL;
 	struct wlan_objmgr_peer *peer = NULL;
@@ -353,17 +377,17 @@ static void wlan_objmgr_pdev_vdev_iterate_peers(struct wlan_objmgr_pdev *pdev,
 	if (peer_list != NULL) {
 		peer = wlan_vdev_peer_list_peek_head(peer_list);
 		while (peer != NULL) {
-			/* Increment ref count, to hold the
-				peer pointer */
-			wlan_objmgr_peer_ref_peer(peer);
 			/* Get next peer pointer */
 			peer_next = wlan_peer_get_next_peer_of_vdev(peer_list,
 								    peer);
-			/* Invoke the handler */
-			handler(pdev, (void *)peer, arg);
-			/* Decrement ref count, this can lead
-				to peer deletion also */
-			wlan_objmgr_peer_unref_peer(peer);
+			/* Increment ref count, to hold the
+				peer pointer */
+			if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
+					QDF_STATUS_SUCCESS) {
+				/* Invoke the handler */
+				handler(pdev, (void *)peer, arg);
+				wlan_objmgr_peer_release_ref(peer, dbg_id);
+			}
 			peer = peer_next;
 		}
 	}
@@ -375,7 +399,8 @@ QDF_STATUS wlan_objmgr_pdev_iterate_obj_list(
 		struct wlan_objmgr_pdev *pdev,
 		enum wlan_objmgr_obj_type obj_type,
 		wlan_objmgr_pdev_op_handler handler,
-		void *arg, uint8_t lock_free_op)
+		void *arg, uint8_t lock_free_op,
+		wlan_objmgr_ref_dbgid dbg_id)
 {
 	struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr;
 	qdf_list_t *vdev_list = NULL;
@@ -394,26 +419,35 @@ QDF_STATUS wlan_objmgr_pdev_iterate_obj_list(
 			VDEV object */
 		vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
 		while (vdev != NULL) {
-				/* TODO increment ref count */
-			/* Get next vdev (handler can be invoked for
-				vdev deletion also */
+			/*
+			 * Get next vdev (handler can be invoked for
+			 * vdev deletion also
+			 */
 			vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list,
 						vdev);
-			handler(pdev, (void *)vdev, arg);
+			if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) ==
+						QDF_STATUS_SUCCESS) {
+				handler(pdev, (void *)vdev, arg);
+				wlan_objmgr_vdev_release_ref(vdev, dbg_id);
+			}
 			vdev = vdev_next;
-				/* TODO decrement ref count */
 		}
 		break;
 	case WLAN_PEER_OP:
 		vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
 		while (vdev != NULL) {
-			/* TODO increment ref count */
-			wlan_objmgr_pdev_vdev_iterate_peers(pdev, vdev, handler,
-							    arg, lock_free_op);
 			/* Get Next VDEV */
 			vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list,
 						vdev);
-			/* TODO decrement ref count */
+			if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) ==
+						QDF_STATUS_SUCCESS) {
+				wlan_objmgr_pdev_vdev_iterate_peers(pdev, vdev,
+								handler, arg,
+								lock_free_op,
+								dbg_id);
+				wlan_objmgr_vdev_release_ref(vdev, dbg_id);
+			}
+			vdev = vdev_next;
 		}
 		break;
 	default:
@@ -471,7 +505,7 @@ QDF_STATUS wlan_objmgr_trigger_pdev_comp_priv_object_deletion(
 		struct wlan_objmgr_pdev *pdev,
 		enum wlan_umac_comp_id id)
 {
-	wlan_objmgr_pdev_delete_handler handler;
+	wlan_objmgr_pdev_destroy_handler handler;
 	void *arg;
 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
 
@@ -488,8 +522,8 @@ QDF_STATUS wlan_objmgr_trigger_pdev_comp_priv_object_deletion(
 	wlan_pdev_obj_unlock(pdev);
 
 	/* Invoke registered create handlers */
-	handler = g_umac_glb_obj->pdev_delete_handler[id];
-	arg = g_umac_glb_obj->pdev_delete_handler_arg[id];
+	handler = g_umac_glb_obj->pdev_destroy_handler[id];
+	arg = g_umac_glb_obj->pdev_destroy_handler_arg[id];
 	if (handler != NULL)
 		pdev->obj_status[id] = handler(pdev, arg);
 	else
@@ -541,6 +575,8 @@ QDF_STATUS wlan_objmgr_pdev_vdev_attach(struct wlan_objmgr_pdev *pdev,
 	}
 	/* Add vdev to pdev's vdev list */
 	wlan_obj_pdev_vdevlist_add_tail(&objmgr->wlan_vdev_list, vdev);
+	/* Increment pdev ref count to make sure it won't be destroyed before */
+	wlan_objmgr_pdev_get_ref(pdev, WLAN_OBJMGR_ID);
 	/* Increment vdev count of pdev */
 	objmgr->wlan_vdev_count++;
 	wlan_pdev_obj_unlock(pdev);
@@ -563,13 +599,15 @@ QDF_STATUS wlan_objmgr_pdev_vdev_detach(struct wlan_objmgr_pdev *pdev,
 	wlan_obj_pdev_vdevlist_remove_vdev(&objmgr->wlan_vdev_list, vdev);
 	/* decrement vdev count */
 	objmgr->wlan_vdev_count--;
-
 	wlan_pdev_obj_unlock(pdev);
+	/* Decrement pdev ref count since vdev is releasing reference */
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_OBJMGR_ID);
 	return QDF_STATUS_SUCCESS;
 }
 
-struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_pdev(
-			struct wlan_objmgr_pdev *pdev, uint8_t vdev_id)
+struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev(
+			struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
+			wlan_objmgr_ref_dbgid dbg_id)
 {
 	struct wlan_objmgr_vdev *vdev;
 	struct wlan_objmgr_vdev *vdev_next;
@@ -586,6 +624,10 @@ struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_pdev(
 	entry of vdev list */
 	while (vdev != NULL) {
 		if (wlan_vdev_get_id(vdev) == vdev_id) {
+			if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) !=
+							QDF_STATUS_SUCCESS)
+				vdev = NULL;
+
 			wlan_pdev_obj_unlock(pdev);
 			return vdev;
 		}
@@ -596,10 +638,82 @@ struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_pdev(
 	wlan_pdev_obj_unlock(pdev);
 	return NULL;
 }
-EXPORT_SYMBOL(wlan_objmgr_find_vdev_by_id_from_pdev);
+EXPORT_SYMBOL(wlan_objmgr_get_vdev_by_id_from_pdev);
 
-struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_pdev(
-		struct wlan_objmgr_pdev *pdev, uint8_t *macaddr)
+struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_no_state(
+			struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
+			wlan_objmgr_ref_dbgid dbg_id)
+{
+	struct wlan_objmgr_vdev *vdev;
+	struct wlan_objmgr_vdev *vdev_next;
+	struct wlan_objmgr_pdev_objmgr *objmgr;
+	qdf_list_t *vdev_list;
+
+	wlan_pdev_obj_lock(pdev);
+
+	objmgr = &pdev->pdev_objmgr;
+	vdev_list = &objmgr->wlan_vdev_list;
+	/* Get first vdev */
+	vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
+	/**
+	 * Iterate through pdev's vdev list, till vdev id matches with
+	 * entry of vdev list
+	 */
+	while (vdev != NULL) {
+		if (wlan_vdev_get_id(vdev) == vdev_id) {
+			wlan_objmgr_vdev_get_ref(vdev, dbg_id);
+			wlan_pdev_obj_unlock(pdev);
+
+			return vdev;
+		}
+		/* get next vdev */
+		vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev);
+		vdev = vdev_next;
+	}
+	wlan_pdev_obj_unlock(pdev);
+
+	return NULL;
+}
+EXPORT_SYMBOL(wlan_objmgr_get_vdev_by_id_from_pdev_no_state);
+
+struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev(
+		struct wlan_objmgr_pdev *pdev, uint8_t *macaddr,
+		wlan_objmgr_ref_dbgid dbg_id)
+{
+	struct wlan_objmgr_vdev *vdev;
+	struct wlan_objmgr_vdev *vdev_next;
+	struct wlan_objmgr_pdev_objmgr *objmgr;
+	qdf_list_t *vdev_list;
+
+	wlan_pdev_obj_lock(pdev);
+	objmgr = &pdev->pdev_objmgr;
+	vdev_list = &objmgr->wlan_vdev_list;
+	/* Get first vdev */
+	vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
+	/* Iterate through pdev's vdev list, till vdev macaddr matches with
+	entry of vdev list */
+	while (vdev != NULL) {
+		if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr)
+					== QDF_STATUS_SUCCESS) {
+			if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) !=
+							QDF_STATUS_SUCCESS)
+				vdev = NULL;
+
+			wlan_pdev_obj_unlock(pdev);
+			return vdev;
+		}
+		/* get next vdev */
+		vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev);
+		vdev = vdev_next;
+	}
+	wlan_pdev_obj_unlock(pdev);
+
+	return NULL;
+}
+
+struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state(
+		struct wlan_objmgr_pdev *pdev, uint8_t *macaddr,
+		wlan_objmgr_ref_dbgid dbg_id)
 {
 	struct wlan_objmgr_vdev *vdev;
 	struct wlan_objmgr_vdev *vdev_next;
@@ -616,7 +730,9 @@ struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_pdev(
 	while (vdev != NULL) {
 		if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr)
 					== QDF_STATUS_SUCCESS) {
+			wlan_objmgr_vdev_get_ref(vdev, dbg_id);
 			wlan_pdev_obj_unlock(pdev);
+
 			return vdev;
 		}
 		/* get next vdev */
@@ -624,6 +740,7 @@ struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_pdev(
 		vdev = vdev_next;
 	}
 	wlan_pdev_obj_unlock(pdev);
+
 	return NULL;
 }
 
@@ -647,6 +764,68 @@ void *wlan_objmgr_pdev_get_comp_private_obj(
 	}
 
 	comp_priv_obj = pdev->pdev_comp_priv_obj[id];
+
 	return comp_priv_obj;
 }
 EXPORT_SYMBOL(wlan_objmgr_pdev_get_comp_private_obj);
+
+void wlan_objmgr_pdev_get_ref(struct wlan_objmgr_pdev *pdev,
+					wlan_objmgr_ref_dbgid id)
+{
+	if (pdev == NULL) {
+		qdf_print("%s: pdev obj is NULL\n", __func__);
+		QDF_ASSERT(0);
+		return;
+	}
+	qdf_atomic_inc(&pdev->pdev_objmgr.ref_cnt);
+
+	return;
+}
+EXPORT_SYMBOL(wlan_objmgr_pdev_get_ref);
+
+QDF_STATUS wlan_objmgr_pdev_try_get_ref(struct wlan_objmgr_pdev *pdev,
+						wlan_objmgr_ref_dbgid id)
+{
+	if (pdev == NULL) {
+		qdf_print("%s: pdev obj is NULL\n", __func__);
+		QDF_ASSERT(0);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	wlan_pdev_obj_lock(pdev);
+	if (pdev->obj_state == WLAN_OBJ_STATE_LOGICALLY_DELETED) {
+		wlan_pdev_obj_unlock(pdev);
+		qdf_print("%s: pdev obj is in Deletion Progress state\n",
+			  __func__);
+		return QDF_STATUS_E_RESOURCES;
+	}
+
+	wlan_objmgr_pdev_get_ref(pdev, id);
+	wlan_pdev_obj_unlock(pdev);
+
+	return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(wlan_objmgr_pdev_try_get_ref);
+
+void wlan_objmgr_pdev_release_ref(struct wlan_objmgr_pdev *pdev,
+						wlan_objmgr_ref_dbgid id)
+{
+	if (pdev == NULL) {
+		qdf_print("%s: pdev obj is NULL\n", __func__);
+		QDF_ASSERT(0);
+		return;
+	}
+
+	if (!qdf_atomic_read(&pdev->pdev_objmgr.ref_cnt)) {
+		qdf_print("%s: pdev ref cnt is 0\n", __func__);
+		WLAN_OBJMGR_BUG(0);
+		return;
+	}
+
+	/* Decrement ref count, free pdev, if ref count == 0 */
+	if (qdf_atomic_dec_and_test(&pdev->pdev_objmgr.ref_cnt))
+		wlan_objmgr_pdev_obj_destroy(pdev);
+
+	return;
+}
+EXPORT_SYMBOL(wlan_objmgr_pdev_release_ref);

+ 146 - 77
umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c

@@ -65,6 +65,47 @@ static QDF_STATUS wlan_objmgr_peer_object_status(
 	return status;
 }
 
+static QDF_STATUS wlan_objmgr_peer_obj_free(struct wlan_objmgr_peer *peer)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_objmgr_vdev *vdev;
+
+	vdev = wlan_peer_get_vdev(peer);
+	if (vdev == NULL) {
+		qdf_print("%s: VDEV is NULL\n", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	/* get PSOC from VDEV, if it is NULL, return */
+	psoc = wlan_vdev_get_psoc(vdev);
+	if (psoc == NULL) {
+		qdf_print("%s: PSOC is NULL\n", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	/* Decrement ref count for BSS peer, so that BSS peer deletes last*/
+	if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_STA) ||
+	    (wlan_peer_get_peer_type(peer) == WLAN_PEER_STA_TEMP))
+		wlan_objmgr_peer_release_ref(wlan_vdev_get_bsspeer(vdev),
+					     WLAN_OBJMGR_ID);
+
+	/* Detach peer from VDEV's peer list */
+	if (wlan_objmgr_vdev_peer_detach(vdev, peer) == QDF_STATUS_E_FAILURE) {
+		qdf_print("%s: Peer VDEV detach failure\n", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+	/* Detach peer from PSOC's peer list */
+	if (wlan_objmgr_psoc_peer_detach(psoc, peer) == QDF_STATUS_E_FAILURE) {
+		qdf_print("%s: Peer PSOC detach failure\n", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+	qdf_spinlock_destroy(&peer->peer_lock);
+	qdf_mem_free(peer);
+
+	return QDF_STATUS_SUCCESS;
+
+}
+
 struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create(
 			struct wlan_objmgr_vdev *vdev,
 			enum wlan_peer_type type,
@@ -102,6 +143,7 @@ struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create(
 	wlan_peer_set_macaddr(peer, macaddr);
 	/* initialize peer state */
 	wlan_peer_mlme_set_state(peer, WLAN_INIT_STATE);
+	qdf_atomic_init(&peer->peer_objmgr.ref_cnt);
 	/* Attach peer to psoc, psoc maintains the node table for the device */
 	if (wlan_objmgr_psoc_peer_attach(psoc, peer) !=
 					QDF_STATUS_SUCCESS) {
@@ -118,11 +160,12 @@ struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create(
 		qdf_mem_free(peer);
 		return NULL;
 	}
-	/* init spinlock */
 	qdf_spinlock_create(&peer->peer_lock);
+	wlan_objmgr_peer_get_ref(peer, WLAN_OBJMGR_ID);
 	/* Increment ref count for BSS peer, so that BSS peer deletes last*/
 	if ((type == WLAN_PEER_STA) || (type == WLAN_PEER_STA_TEMP))
-		wlan_objmgr_peer_ref_peer(wlan_vdev_get_bsspeer(vdev));
+		wlan_objmgr_peer_get_ref(wlan_vdev_get_bsspeer(vdev),
+					 WLAN_OBJMGR_ID);
 	/* TODO init other parameters */
 	/* Invoke registered create handlers */
 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
@@ -159,40 +202,27 @@ struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create(
 	return peer;
 }
 
-QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer)
+static QDF_STATUS wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer)
 {
 	uint8_t id;
-	wlan_objmgr_peer_delete_handler handler;
+	wlan_objmgr_peer_destroy_handler handler;
 	QDF_STATUS obj_status;
 	void *arg;
-	struct wlan_objmgr_psoc *psoc;
-	struct wlan_objmgr_vdev *vdev;
 
 	if (peer == NULL) {
 		qdf_print("%s: PEER is NULL\n", __func__);
 		return QDF_STATUS_E_FAILURE;
 	}
-	/* get VDEV from peer, if it is NULL, return */
-	vdev = wlan_peer_get_vdev(peer);
-	if (vdev == NULL) {
-		qdf_print("%s: VDEV is NULL\n", __func__);
-		return QDF_STATUS_E_FAILURE;
-	}
-	/* get PSOC from VDEV, if it is NULL, return */
-	psoc = wlan_vdev_get_psoc(vdev);
-	if (psoc == NULL) {
-		qdf_print("%s: PSOC is NULL\n", __func__);
-		return QDF_STATUS_E_FAILURE;
+
+	if (peer->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) {
+		qdf_print("%s:peer object delete is not invoked\n", __func__);
+		WLAN_OBJMGR_BUG(0);
 	}
-	/* Decrement ref count for BSS peer, so that BSS peer deletes last*/
-	if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_STA) ||
-	    (wlan_peer_get_peer_type(peer) == WLAN_PEER_STA_TEMP))
-		wlan_objmgr_peer_unref_peer(wlan_vdev_get_bsspeer(vdev));
 
-	/* Invoke registered delete handlers */
+	/* Invoke registered destroy handlers */
 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
-		handler = g_umac_glb_obj->peer_delete_handler[id];
-		arg = g_umac_glb_obj->peer_delete_handler_arg[id];
+		handler = g_umac_glb_obj->peer_destroy_handler[id];
+		arg = g_umac_glb_obj->peer_destroy_handler_arg[id];
 		if (handler != NULL)
 			peer->obj_status[id] = handler(peer, arg);
 		else
@@ -209,27 +239,31 @@ QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer)
 	if (obj_status == QDF_STATUS_COMP_ASYNC) {
 		peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED;
 		return QDF_STATUS_COMP_ASYNC;
-	} else {
-		/* Detach peer from VDEV's peer list */
-		if (wlan_objmgr_vdev_peer_detach(vdev, peer)
-				== QDF_STATUS_E_FAILURE) {
-			qdf_print("%s: Peer VDEV detach failure\n", __func__);
-			return QDF_STATUS_E_FAILURE;
-		}
-		/* Detach peer from PSOC's peer list */
-		if (wlan_objmgr_psoc_peer_detach(psoc, peer)
-					== QDF_STATUS_E_FAILURE) {
-			qdf_print("%s: Peer PSOC detach failure\n", __func__);
-			return QDF_STATUS_E_FAILURE;
-		}
-		/* destroy spinlock */
-		qdf_spinlock_destroy(&peer->peer_lock);
-		/* Free memory */
-		qdf_mem_free(peer);
 	}
-	return QDF_STATUS_SUCCESS;
+
+	/* Free the peer object */
+	return wlan_objmgr_peer_obj_free(peer);
 }
 
+QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer)
+{
+	if (peer == NULL) {
+		qdf_print("%s: PEER is NULL\n", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	/**
+	 * Update VDEV object state to LOGICALLY DELETED
+	 * It prevents further access of this object
+	 */
+	wlan_peer_obj_lock(peer);
+	peer->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED;
+	wlan_peer_obj_unlock(peer);
+	wlan_objmgr_peer_release_ref(peer, WLAN_OBJMGR_ID);
+
+	return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(wlan_objmgr_peer_obj_delete);
 /**
  ** APIs to attach/detach component objects
  */
@@ -295,27 +329,11 @@ QDF_STATUS wlan_objmgr_peer_component_obj_detach(
 		void *comp_priv_obj)
 {
 	QDF_STATUS obj_status;
-	struct wlan_objmgr_psoc *psoc;
-	struct wlan_objmgr_vdev *vdev;
 
 	/* component id is invalid */
 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
 		return QDF_STATUS_MAXCOMP_FAIL;
 
-	/* get VDEV from peer, if it is NULL, return */
-	vdev = wlan_peer_get_vdev(peer);
-	if (vdev == NULL) {
-		qdf_print("%s: VDEV is NULL\n", __func__);
-		return QDF_STATUS_E_FAILURE;
-	}
-
-	/* get PSOC from VDEV, if it is NULL, return */
-	psoc = wlan_vdev_get_psoc(vdev);
-	if (psoc == NULL) {
-		qdf_print("%s: PSOC is NULL\n", __func__);
-		return QDF_STATUS_E_FAILURE;
-	}
-
 	wlan_peer_obj_lock(peer);
 	/* If there is a invalid entry, return failure */
 	if (peer->peer_comp_priv_obj[id] != comp_priv_obj) {
@@ -328,7 +346,7 @@ QDF_STATUS wlan_objmgr_peer_component_obj_detach(
 	peer->obj_status[id] = QDF_STATUS_SUCCESS;
 	wlan_peer_obj_unlock(peer);
 
-	/* If PEER object status is partially deleted means, this API is
+	/* If PEER object status is partially destroyed means, this API is
 	invoked with differnt context, this block should be executed for async
 	components only */
 	if ((peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) ||
@@ -361,22 +379,11 @@ QDF_STATUS wlan_objmgr_peer_component_obj_detach(
 			/* Delete peer object */
 		if ((obj_status == QDF_STATUS_SUCCESS)  &&
 		    (peer->obj_state == WLAN_OBJ_STATE_DELETED)) {
-			/* delete peer from vdev's peer list */
-			if (wlan_objmgr_vdev_peer_detach(vdev, peer) ==
-						QDF_STATUS_E_FAILURE)
-				return QDF_STATUS_E_FAILURE;
-
-			/* delete peer from psoc's peer list */
-			if (wlan_objmgr_psoc_peer_detach(psoc, peer) ==
-						QDF_STATUS_E_FAILURE)
-				return QDF_STATUS_E_FAILURE;
-			/* Destroy spinlock */
-			qdf_spinlock_destroy(&peer->peer_lock);
-			/* free memory */
-			qdf_mem_free(peer);
-			return QDF_STATUS_SUCCESS;
+			/* Free the peer object */
+			return wlan_objmgr_peer_obj_free(peer);
 		}
 	}
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -429,7 +436,7 @@ QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_deletion(
 		struct wlan_objmgr_peer *peer,
 		enum wlan_umac_comp_id id)
 {
-	wlan_objmgr_peer_delete_handler handler;
+	wlan_objmgr_peer_destroy_handler handler;
 	void *arg;
 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
 
@@ -446,9 +453,9 @@ QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_deletion(
 
 	wlan_peer_obj_unlock(peer);
 
-	/* Invoke registered delete handlers */
-	handler = g_umac_glb_obj->peer_delete_handler[id];
-	arg = g_umac_glb_obj->peer_delete_handler_arg[id];
+	/* Invoke registered destroy handlers */
+	handler = g_umac_glb_obj->peer_destroy_handler[id];
+	arg = g_umac_glb_obj->peer_destroy_handler_arg[id];
 	if (handler != NULL)
 		peer->obj_status[id] = handler(peer, arg);
 	else
@@ -487,3 +494,65 @@ void *wlan_objmgr_peer_get_comp_private_obj(
 	return comp_priv_obj;
 }
 EXPORT_SYMBOL(wlan_objmgr_peer_get_comp_private_obj);
+
+void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer,
+					wlan_objmgr_ref_dbgid id)
+{
+	if (peer == NULL) {
+		qdf_print("%s: peer obj is NULL\n", __func__);
+		QDF_ASSERT(0);
+		return;
+	}
+	/* Increment ref count */
+	qdf_atomic_inc(&peer->peer_objmgr.ref_cnt);
+
+	return;
+}
+EXPORT_SYMBOL(wlan_objmgr_peer_get_ref);
+
+QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer,
+						 wlan_objmgr_ref_dbgid id)
+{
+	if (peer == NULL) {
+		qdf_print("%s: peer obj is NULL\n", __func__);
+		QDF_ASSERT(0);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	wlan_peer_obj_lock(peer);
+	if (peer->obj_state == WLAN_OBJ_STATE_LOGICALLY_DELETED) {
+		wlan_peer_obj_unlock(peer);
+		qdf_print("%s: peer obj is in Deletion Progress state\n",
+			  __func__);
+		return QDF_STATUS_E_RESOURCES;
+	}
+
+	wlan_objmgr_peer_get_ref(peer, id);
+	wlan_peer_obj_unlock(peer);
+
+	return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(wlan_objmgr_peer_try_get_ref);
+
+void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer,
+						 wlan_objmgr_ref_dbgid id)
+{
+	if (peer == NULL) {
+		qdf_print("%s: peer obj is NULL\n", __func__);
+		QDF_ASSERT(0);
+		return;
+	}
+
+	if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) {
+		qdf_print("%s: peer ref cnt is 0\n", __func__);
+		WLAN_OBJMGR_BUG(0);
+		return;
+	}
+
+	/* Decrement ref count, free vdev, if ref acount == 0 */
+	if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt))
+		wlan_objmgr_peer_obj_destroy(peer);
+
+	return;
+}
+EXPORT_SYMBOL(wlan_objmgr_peer_release_ref);

+ 405 - 72
umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c

@@ -86,6 +86,20 @@ static void wlan_objmgr_psoc_peer_list_deinit(struct wlan_peer_list *peer_list)
 	for (i = 0; i < WLAN_PEER_HASHSIZE; i++)
 		qdf_list_destroy(&peer_list->peer_hash[i]);
 }
+
+static QDF_STATUS wlan_objmgr_psoc_obj_free(struct wlan_objmgr_psoc *psoc)
+{
+	/* Detach PSOC from global object's psoc list  */
+	if (wlan_objmgr_psoc_object_detach(psoc) == QDF_STATUS_E_FAILURE) {
+		qdf_print("%s: PSOC object detach failed\n", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+	wlan_objmgr_psoc_peer_list_deinit(&psoc->soc_objmgr.peer_list);
+	qdf_spinlock_destroy(&psoc->psoc_lock);
+	qdf_mem_free(psoc);
+
+	return QDF_STATUS_SUCCESS;
+}
 /*
  * wlan_objmgr_psco_create_handler would return following status values
  */
@@ -106,7 +120,6 @@ struct wlan_objmgr_psoc *wlan_objmgr_psoc_obj_create(uint32_t phy_version,
 		qdf_print("%s: PSOC allocation failed\n", __func__);
 		return NULL;
 	}
-	/* Init spinlock */
 	qdf_spinlock_create(&psoc->psoc_lock);
 	/* Initialize with default values */
 	objmgr = &psoc->soc_objmgr;
@@ -114,11 +127,13 @@ struct wlan_objmgr_psoc *wlan_objmgr_psoc_obj_create(uint32_t phy_version,
 	objmgr->wlan_vdev_count = 0;
 	objmgr->max_vdev_count = WLAN_UMAC_PSOC_MAX_VDEVS;
 	objmgr->wlan_peer_count = 0;
+	qdf_atomic_init(&objmgr->ref_cnt);
 	/* set phy version, dev_type in psoc */
 	wlan_psoc_set_nif_phy_version(psoc, phy_version);
 	wlan_psoc_set_dev_type(psoc, dev_type);
 	/* Initialize peer list */
 	wlan_objmgr_psoc_peer_list_init(&objmgr->peer_list);
+	wlan_objmgr_psoc_get_ref(psoc, WLAN_OBJMGR_ID);
 	/* Invoke registered create handlers */
 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
 		handler = g_umac_glb_obj->psoc_create_handler[id];
@@ -167,10 +182,10 @@ struct wlan_objmgr_psoc *wlan_objmgr_psoc_obj_create(uint32_t phy_version,
 }
 EXPORT_SYMBOL(wlan_objmgr_psoc_obj_create);
 
-QDF_STATUS wlan_objmgr_psoc_obj_delete(struct wlan_objmgr_psoc *psoc)
+static QDF_STATUS wlan_objmgr_psoc_obj_destroy(struct wlan_objmgr_psoc *psoc)
 {
 	uint8_t id;
-	wlan_objmgr_psoc_delete_handler handler;
+	wlan_objmgr_psoc_destroy_handler handler;
 	QDF_STATUS obj_status;
 	void *arg;
 
@@ -180,10 +195,15 @@ QDF_STATUS wlan_objmgr_psoc_obj_delete(struct wlan_objmgr_psoc *psoc)
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	if (psoc->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) {
+		qdf_print("%s:psoc object delete is not invoked\n", __func__);
+		WLAN_OBJMGR_BUG(0);
+	}
+
 	/* Invoke registered create handlers */
 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
-		handler = g_umac_glb_obj->psoc_delete_handler[id];
-		arg = g_umac_glb_obj->psoc_delete_handler_arg[id];
+		handler = g_umac_glb_obj->psoc_destroy_handler[id];
+		arg = g_umac_glb_obj->psoc_destroy_handler_arg[id];
 		if (handler != NULL)
 			psoc->obj_status[id] = handler(psoc, arg);
 		else
@@ -203,20 +223,28 @@ QDF_STATUS wlan_objmgr_psoc_obj_delete(struct wlan_objmgr_psoc *psoc)
 	if (obj_status == QDF_STATUS_COMP_ASYNC) {
 		psoc->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED;
 		return QDF_STATUS_COMP_ASYNC;
-	} else {
-		/* Detach PSOC from global object's psoc list  */
-		if (wlan_objmgr_psoc_object_detach(psoc) ==
-					QDF_STATUS_E_FAILURE) {
-			qdf_print("%s: PSOC object detach failed\n", __func__);
-			return QDF_STATUS_E_FAILURE;
-		}
-		wlan_objmgr_psoc_peer_list_deinit(&psoc->soc_objmgr.peer_list);
-		/* Destroy spinlock */
-		qdf_spinlock_destroy(&psoc->psoc_lock);
-		/* Free the memory */
-		qdf_mem_free(psoc);
 	}
 
+	/* Free psoc object */
+	return wlan_objmgr_psoc_obj_free(psoc);
+}
+
+
+QDF_STATUS wlan_objmgr_psoc_obj_delete(struct wlan_objmgr_psoc *psoc)
+{
+	if (psoc == NULL) {
+		qdf_print("%s:psoc is NULL\n", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+	/*
+	 * Update PSOC object state to LOGICALLY DELETED
+	 * It prevents further access of this object
+	 */
+	wlan_psoc_obj_lock(psoc);
+	psoc->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED;
+	wlan_psoc_obj_unlock(psoc);
+	wlan_objmgr_psoc_release_ref(psoc, WLAN_OBJMGR_ID);
+
 	return QDF_STATUS_SUCCESS;
 }
 EXPORT_SYMBOL(wlan_objmgr_psoc_obj_delete);
@@ -248,6 +276,7 @@ QDF_STATUS wlan_objmgr_psoc_component_obj_attach(
 	/* Save component's pointer and status */
 	psoc->soc_comp_priv_obj[id] = comp_priv_obj;
 	psoc->obj_status[id] = status;
+
 	wlan_psoc_obj_unlock(psoc);
 
 	if (psoc->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED)
@@ -345,17 +374,8 @@ QDF_STATUS wlan_objmgr_psoc_component_obj_detach(
 		/* Delete psoc object */
 		if ((obj_status == QDF_STATUS_SUCCESS)  &&
 		    (psoc->obj_state == WLAN_OBJ_STATE_DELETED)) {
-			/* Detach PSOC from global object's psoc list */
-			if (wlan_objmgr_psoc_object_detach(psoc) ==
-						QDF_STATUS_E_FAILURE)
-				return QDF_STATUS_E_FAILURE;
-
-			wlan_objmgr_psoc_peer_list_deinit(
-				&psoc->soc_objmgr.peer_list);
-			/* Destroy spinlock */
-			qdf_spinlock_destroy(&psoc->psoc_lock);
-			/* Free memory */
-			qdf_mem_free(psoc);
+			/* Free psoc object */
+			return wlan_objmgr_psoc_obj_free(psoc);
 		}
 	}
 
@@ -370,13 +390,16 @@ QDF_STATUS wlan_objmgr_iterate_obj_list(
 		struct wlan_objmgr_psoc *psoc,
 		enum wlan_objmgr_obj_type obj_type,
 		wlan_objmgr_op_handler handler,
-		void *arg, uint8_t lock_free_op)
+		void *arg, uint8_t lock_free_op,
+		wlan_objmgr_ref_dbgid dbg_id)
 {
 	uint16_t obj_id;
 	uint8_t i;
 	struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr;
 	struct wlan_peer_list *peer_list;
 	qdf_list_t *obj_list;
+	struct wlan_objmgr_pdev *pdev;
+	struct wlan_objmgr_vdev *vdev;
 	struct wlan_objmgr_peer *peer;
 	struct wlan_objmgr_peer *peer_next;
 
@@ -390,24 +413,26 @@ QDF_STATUS wlan_objmgr_iterate_obj_list(
 	case WLAN_PDEV_OP:
 		/* Iterate through PDEV list, invoke handler for each pdev */
 		for (obj_id = 0; obj_id < WLAN_UMAC_MAX_PDEVS; obj_id++) {
-			if (objmgr->wlan_pdev_list[obj_id] != NULL) {
-				/* TODO increment ref count */
-				handler(psoc,
-					(void *)objmgr->wlan_pdev_list[obj_id],
-					arg);
-				/* TODO decrement ref count */
+			pdev = objmgr->wlan_pdev_list[obj_id];
+			if ((pdev != NULL) &&
+			    (pdev->obj_state !=
+				WLAN_OBJ_STATE_LOGICALLY_DELETED)) {
+				wlan_objmgr_pdev_get_ref(pdev, dbg_id);
+				handler(psoc, (void *)pdev, arg);
+				wlan_objmgr_pdev_release_ref(pdev, dbg_id);
 			}
 		}
 		break;
 	case WLAN_VDEV_OP:
 		/* Iterate through VDEV list, invoke handler for each vdev */
 		for (obj_id = 0; obj_id < WLAN_UMAC_PSOC_MAX_VDEVS; obj_id++) {
-			if (objmgr->wlan_vdev_list[obj_id] != NULL) {
-				/* TODO increment ref count */
-				handler(psoc,
-					(void *)objmgr->wlan_vdev_list[obj_id],
-					arg);
-				/* TODO decrement ref count */
+			vdev = objmgr->wlan_vdev_list[obj_id];
+			if ((vdev != NULL) &&
+			    (vdev->obj_state !=
+				WLAN_OBJ_STATE_LOGICALLY_DELETED)) {
+				wlan_objmgr_vdev_get_ref(vdev, dbg_id);
+				handler(psoc, vdev, arg);
+				wlan_objmgr_vdev_release_ref(vdev, dbg_id);
 			}
 		}
 		break;
@@ -422,16 +447,15 @@ QDF_STATUS wlan_objmgr_iterate_obj_list(
 			obj_list = &peer_list->peer_hash[i];
 			peer = wlan_psoc_peer_list_peek_head(obj_list);
 			while (peer) {
-				/* Increment ref count, to hold the
-					peer pointer */
-				wlan_objmgr_peer_ref_peer(peer);
-				handler(psoc, (void *)peer, arg);
 				/* Get next peer */
 				peer_next = wlan_peer_get_next_peer_of_psoc(
 								obj_list, peer);
-				/* Decrement ref count, this can lead
-					to peer deletion also */
-				wlan_objmgr_peer_unref_peer(peer);
+				if (wlan_objmgr_peer_try_get_ref(peer, dbg_id)
+						== QDF_STATUS_SUCCESS) {
+					handler(psoc, (void *)peer, arg);
+					wlan_objmgr_peer_release_ref(peer,
+								     dbg_id);
+				}
 				peer = peer_next;
 			}
 		}
@@ -477,13 +501,16 @@ QDF_STATUS wlan_objmgr_free_all_objects_per_psoc(
 {
 	/* Free all peers */
 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP,
-				     wlan_objmgr_psoc_peer_delete, NULL, 1);
+				     wlan_objmgr_psoc_peer_delete, NULL, 1,
+				     WLAN_OBJMGR_ID);
 	/* Free all vdevs */
 	wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
-				     wlan_objmgr_psoc_vdev_delete, NULL, 1);
+				     wlan_objmgr_psoc_vdev_delete, NULL, 1,
+				     WLAN_OBJMGR_ID);
 	/* Free all PDEVs */
 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
-				     wlan_objmgr_psoc_pdev_delete, NULL, 1);
+				     wlan_objmgr_psoc_pdev_delete, NULL, 1,
+				     WLAN_OBJMGR_ID);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -535,7 +562,7 @@ QDF_STATUS wlan_objmgr_trigger_psoc_comp_priv_object_deletion(
 		struct wlan_objmgr_psoc *psoc,
 		enum wlan_umac_comp_id id)
 {
-	wlan_objmgr_psoc_delete_handler handler;
+	wlan_objmgr_psoc_destroy_handler handler;
 	void *arg;
 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
 
@@ -551,8 +578,8 @@ QDF_STATUS wlan_objmgr_trigger_psoc_comp_priv_object_deletion(
 	}
 	wlan_psoc_obj_unlock(psoc);
 	/* Invoke registered create handlers */
-	handler = g_umac_glb_obj->psoc_delete_handler[id];
-	arg = g_umac_glb_obj->psoc_delete_handler_arg[id];
+	handler = g_umac_glb_obj->psoc_destroy_handler[id];
+	arg = g_umac_glb_obj->psoc_destroy_handler_arg[id];
 	if (handler != NULL)
 		psoc->obj_status[id] = handler(psoc, arg);
 	else
@@ -600,6 +627,8 @@ QDF_STATUS wlan_objmgr_psoc_pdev_attach(struct wlan_objmgr_psoc *psoc,
 		/* save pdev id */
 		pdev->pdev_objmgr.wlan_pdev_id = id;
 		status = QDF_STATUS_SUCCESS;
+		/* Inrement psoc ref count to block its free before pdev */
+		wlan_objmgr_psoc_get_ref(psoc, WLAN_OBJMGR_ID);
 	}
 	wlan_psoc_obj_unlock(psoc);
 
@@ -625,12 +654,15 @@ QDF_STATUS wlan_objmgr_psoc_pdev_detach(struct wlan_objmgr_psoc *psoc,
 	objmgr->wlan_pdev_count--;
 	pdev->pdev_objmgr.wlan_pdev_id = 0xff;
 	wlan_psoc_obj_unlock(psoc);
+	/* Release ref count of psoc */
+	wlan_objmgr_psoc_release_ref(psoc, WLAN_OBJMGR_ID);
 
 	return QDF_STATUS_SUCCESS;
 }
 
-struct wlan_objmgr_pdev *wlan_objmgr_find_pdev_by_id(
-		struct wlan_objmgr_psoc *psoc, uint8_t id)
+struct wlan_objmgr_pdev *wlan_objmgr_get_pdev_by_id(
+		struct wlan_objmgr_psoc *psoc, uint8_t id,
+		wlan_objmgr_ref_dbgid dbg_id)
 {
 	struct wlan_objmgr_psoc_objmgr *objmgr;
 	struct wlan_objmgr_pdev *pdev = NULL;
@@ -639,11 +671,37 @@ struct wlan_objmgr_pdev *wlan_objmgr_find_pdev_by_id(
 	objmgr = &psoc->soc_objmgr;
 	/* get pdev from pdev list */
 	pdev = objmgr->wlan_pdev_list[id];
+	/* Do not return object, if it is not CREATED state */
+	if (pdev != NULL) {
+		if (wlan_objmgr_pdev_try_get_ref(pdev, dbg_id) !=
+							QDF_STATUS_SUCCESS)
+			pdev = NULL;
+	}
+
 	wlan_psoc_obj_unlock(psoc);
 
 	return pdev;
 }
 
+struct wlan_objmgr_pdev *wlan_objmgr_get_pdev_by_id_no_state(
+		struct wlan_objmgr_psoc *psoc, uint8_t id,
+		wlan_objmgr_ref_dbgid dbg_id)
+{
+	struct wlan_objmgr_psoc_objmgr *objmgr;
+	struct wlan_objmgr_pdev *pdev = NULL;
+
+	wlan_psoc_obj_lock(psoc);
+	objmgr = &psoc->soc_objmgr;
+	/* get pdev from pdev list */
+	pdev = objmgr->wlan_pdev_list[id];
+	/* Do not return object, if it is not CREATED state */
+	if (pdev != NULL)
+		wlan_objmgr_pdev_get_ref(pdev, dbg_id);
+
+	wlan_psoc_obj_unlock(psoc);
+
+	return pdev;
+}
 QDF_STATUS wlan_objmgr_psoc_vdev_attach(struct wlan_objmgr_psoc *psoc,
 					struct wlan_objmgr_vdev *vdev)
 {
@@ -724,8 +782,36 @@ QDF_STATUS wlan_objmgr_psoc_vdev_detach(struct wlan_objmgr_psoc *psoc,
 }
 
 
-struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_psoc(
-			struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
+struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc(
+			struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
+			wlan_objmgr_ref_dbgid dbg_id)
+{
+	struct wlan_objmgr_vdev *vdev;
+
+	/* if PSOC is NULL, return */
+	if (psoc == NULL)
+		return NULL;
+	/* vdev id is invalid */
+	if (vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS)
+		return NULL;
+
+	wlan_psoc_obj_lock(psoc);
+	/* retrieve vdev pointer from vdev list */
+	vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_id];
+	if (vdev != NULL) {
+		if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) !=
+							QDF_STATUS_SUCCESS)
+			vdev = NULL;
+	}
+	wlan_psoc_obj_unlock(psoc);
+
+	return vdev;
+}
+EXPORT_SYMBOL(wlan_objmgr_get_vdev_by_id_from_psoc);
+
+struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc_no_state(
+			struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
+			wlan_objmgr_ref_dbgid dbg_id)
 {
 	struct wlan_objmgr_vdev *vdev;
 
@@ -739,13 +825,53 @@ struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_psoc(
 	wlan_psoc_obj_lock(psoc);
 	/* retrieve vdev pointer from vdev list */
 	vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_id];
+	if (vdev != NULL)
+		wlan_objmgr_vdev_get_ref(vdev, dbg_id);
+
 	wlan_psoc_obj_unlock(psoc);
 
 	return vdev;
 }
+EXPORT_SYMBOL(wlan_objmgr_get_vdev_by_id_from_psoc_no_state);
+
+struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc(
+		struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
+		wlan_objmgr_ref_dbgid dbg_id)
+{
+	struct wlan_objmgr_vdev *vdev;
+	uint8_t id;
+
+	/* if PSOC is NULL, return */
+	if (psoc == NULL)
+		return NULL;
+
+	wlan_psoc_obj_lock(psoc);
+	/* Iterate through PSOC's vdev list */
+	for (id = 0; id < WLAN_UMAC_PSOC_MAX_VDEVS; id++) {
+		vdev = psoc->soc_objmgr.wlan_vdev_list[id];
+		if (vdev == NULL)
+			continue;
+		/* MAC address matches, break */
+		if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr)
+			== QDF_STATUS_SUCCESS) {
+			if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) !=
+							QDF_STATUS_SUCCESS)
+				vdev = NULL;
+
+			wlan_psoc_obj_unlock(psoc);
+
+			return vdev;
+		}
+	}
+	wlan_psoc_obj_unlock(psoc);
+
+	return NULL;
+}
+EXPORT_SYMBOL(wlan_objmgr_get_vdev_by_macaddr_from_psoc);
 
-struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_psoc(
-		struct wlan_objmgr_psoc *psoc, uint8_t *macaddr)
+struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state(
+		struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
+		wlan_objmgr_ref_dbgid dbg_id)
 {
 	struct wlan_objmgr_vdev *vdev;
 	uint8_t id;
@@ -763,7 +889,9 @@ struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_psoc(
 		/* MAC address matches, break */
 		if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr)
 			== QDF_STATUS_SUCCESS) {
+			wlan_objmgr_vdev_get_ref(vdev, dbg_id);
 			wlan_psoc_obj_unlock(psoc);
+
 			return vdev;
 		}
 	}
@@ -771,6 +899,7 @@ struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_psoc(
 
 	return NULL;
 }
+EXPORT_SYMBOL(wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state);
 
 static void wlan_obj_psoc_peerlist_add_tail(qdf_list_t *obj_list,
 				struct wlan_objmgr_peer *obj)
@@ -818,7 +947,8 @@ static QDF_STATUS wlan_peer_bssid_match(struct wlan_objmgr_peer *peer,
  *         NULL on FAILURE
  */
 static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer(
-				qdf_list_t *obj_list, uint8_t *macaddr)
+				qdf_list_t *obj_list, uint8_t *macaddr,
+				wlan_objmgr_ref_dbgid dbg_id)
 {
 	struct wlan_objmgr_peer *peer;
 	struct wlan_objmgr_peer *peer_temp;
@@ -829,8 +959,44 @@ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer(
 		/* For peer, macaddr is key */
 		if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr)
 			== QDF_STATUS_SUCCESS) {
-			/* Increment ref count for access */
-			wlan_objmgr_peer_ref_peer(peer);
+			if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) !=
+							QDF_STATUS_SUCCESS) {
+				/* BSS peer can have multiple peer instances.
+				 * Iterate through the list to return the
+				 * active peer incase of BSS else return NULL.
+				 */
+				if (wlan_peer_get_peer_type(peer) !=
+							WLAN_PEER_AP)
+					return NULL;
+
+			} else {
+				return peer;
+			}
+		}
+		/* Move to next peer */
+		peer_temp = peer;
+		peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp);
+	}
+
+	/* Not found, return NULL */
+	return NULL;
+}
+
+static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_no_state(
+				qdf_list_t *obj_list, uint8_t *macaddr,
+				wlan_objmgr_ref_dbgid dbg_id)
+{
+	struct wlan_objmgr_peer *peer;
+	struct wlan_objmgr_peer *peer_temp;
+
+	/* Iterate through hash list to get the peer */
+	peer = wlan_psoc_peer_list_peek_head(obj_list);
+	while (peer != NULL) {
+		/* For peer, macaddr is key */
+		if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr)
+			== QDF_STATUS_SUCCESS) {
+			wlan_objmgr_peer_get_ref(peer, dbg_id);
+
 			return peer;
 		}
 		/* Move to next peer */
@@ -858,7 +1024,8 @@ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer(
  */
 static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid(
 					qdf_list_t *obj_list, uint8_t *macaddr,
-					uint8_t *bssid)
+					uint8_t *bssid,
+					wlan_objmgr_ref_dbgid dbg_id)
 {
 	struct wlan_objmgr_peer *peer;
 	struct wlan_objmgr_peer *peer_temp;
@@ -876,8 +1043,46 @@ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid(
 			 */
 			if (wlan_peer_bssid_match(peer, bssid) ==
 							QDF_STATUS_SUCCESS) {
-				/* Increment ref count for access */
-				wlan_objmgr_peer_ref_peer(peer);
+				if (wlan_objmgr_peer_try_get_ref(peer, dbg_id)
+							!= QDF_STATUS_SUCCESS)
+					peer = NULL;
+
+				return peer;
+			}
+		}
+		/* Move to next peer */
+		peer_temp = peer;
+		peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp);
+	}
+
+	/* Not found, return NULL */
+	return NULL;
+}
+
+static struct wlan_objmgr_peer
+		*wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid_no_state(
+					qdf_list_t *obj_list, uint8_t *macaddr,
+					uint8_t *bssid,
+					wlan_objmgr_ref_dbgid dbg_id)
+{
+	struct wlan_objmgr_peer *peer;
+	struct wlan_objmgr_peer *peer_temp;
+
+	/* Iterate through hash list to get the peer */
+	peer = wlan_psoc_peer_list_peek_head(obj_list);
+	while (peer != NULL) {
+		/* For peer, macaddr is key */
+		if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr)
+			== QDF_STATUS_SUCCESS) {
+			/*
+			 *  BSSID match is requested by caller, check BSSID
+			 *  (vdev mac == bssid) --  return peer
+			 *  (vdev mac != bssid) --  perform next iteration
+			 */
+			if (wlan_peer_bssid_match(peer, bssid) ==
+							QDF_STATUS_SUCCESS) {
+				wlan_objmgr_peer_get_ref(peer, dbg_id);
+
 				return peer;
 			}
 		}
@@ -958,8 +1163,9 @@ QDF_STATUS wlan_objmgr_psoc_peer_detach(struct wlan_objmgr_psoc *psoc,
 	return QDF_STATUS_SUCCESS;
 }
 
-struct wlan_objmgr_peer *wlan_objmgr_find_peer(
-			struct wlan_objmgr_psoc *psoc, uint8_t *macaddr)
+struct wlan_objmgr_peer *wlan_objmgr_get_peer(
+			struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
+			wlan_objmgr_ref_dbgid dbg_id)
 {
 	struct wlan_objmgr_psoc_objmgr *objmgr;
 	uint8_t hash_index;
@@ -980,16 +1186,48 @@ struct wlan_objmgr_peer *wlan_objmgr_find_peer(
 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
 	/* Iterate through peer list, get peer */
 	peer = wlan_obj_psoc_peerlist_get_peer(
-		&peer_list->peer_hash[hash_index], macaddr);
+		&peer_list->peer_hash[hash_index], macaddr, dbg_id);
 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
 	wlan_psoc_obj_unlock(psoc);
 
 	return peer;
 }
+EXPORT_SYMBOL(wlan_objmgr_get_peer);
 
-struct wlan_objmgr_peer *wlan_objmgr_find_peer_by_mac_n_vdev(
+struct wlan_objmgr_peer *wlan_objmgr_get_peer_no_state(
 			struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
-			uint8_t *bssid)
+			wlan_objmgr_ref_dbgid dbg_id)
+{
+	struct wlan_objmgr_psoc_objmgr *objmgr;
+	uint8_t hash_index;
+	struct wlan_objmgr_peer *peer = NULL;
+	struct wlan_peer_list *peer_list;
+
+	/* psoc lock should be taken before peer list lock */
+	wlan_psoc_obj_lock(psoc);
+	objmgr = &psoc->soc_objmgr;
+	/* List is empty, return NULL */
+	if (objmgr->wlan_peer_count == 0) {
+		wlan_psoc_obj_unlock(psoc);
+		return NULL;
+	}
+	/* reduce the search window, with hash key */
+	hash_index = WLAN_PEER_HASH(macaddr);
+	peer_list = &objmgr->peer_list;
+	qdf_spin_lock_bh(&peer_list->peer_list_lock);
+	/* Iterate through peer list, get peer */
+	peer = wlan_obj_psoc_peerlist_get_peer_no_state(
+		&peer_list->peer_hash[hash_index], macaddr, dbg_id);
+	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
+	wlan_psoc_obj_unlock(psoc);
+
+	return peer;
+}
+EXPORT_SYMBOL(wlan_objmgr_get_peer_no_state);
+
+struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev(
+			struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
+			uint8_t *bssid, wlan_objmgr_ref_dbgid dbg_id)
 {
 	struct wlan_objmgr_psoc_objmgr *objmgr;
 	uint8_t hash_index;
@@ -1010,12 +1248,44 @@ struct wlan_objmgr_peer *wlan_objmgr_find_peer_by_mac_n_vdev(
 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
 	/* Iterate through peer list, get peer */
 	peer = wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid(
-		&peer_list->peer_hash[hash_index], macaddr, bssid);
+		&peer_list->peer_hash[hash_index], macaddr, bssid, dbg_id);
 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
 	wlan_psoc_obj_unlock(psoc);
 
 	return peer;
 }
+EXPORT_SYMBOL(wlan_objmgr_get_peer_by_mac_n_vdev);
+
+struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev_no_state(
+			struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
+			uint8_t *bssid, wlan_objmgr_ref_dbgid dbg_id)
+{
+	struct wlan_objmgr_psoc_objmgr *objmgr;
+	uint8_t hash_index;
+	struct wlan_objmgr_peer *peer = NULL;
+	struct wlan_peer_list *peer_list;
+
+	/* psoc lock should be taken before peer list lock */
+	wlan_psoc_obj_lock(psoc);
+	objmgr = &psoc->soc_objmgr;
+	/* List is empty, return NULL */
+	if (objmgr->wlan_peer_count == 0) {
+		wlan_psoc_obj_unlock(psoc);
+		return NULL;
+	}
+	/* reduce the search window, with hash key */
+	hash_index = WLAN_PEER_HASH(macaddr);
+	peer_list = &objmgr->peer_list;
+	qdf_spin_lock_bh(&peer_list->peer_list_lock);
+	/* Iterate through peer list, get peer */
+	peer = wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid_no_state(
+		&peer_list->peer_hash[hash_index], macaddr, bssid, dbg_id);
+	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
+	wlan_psoc_obj_unlock(psoc);
+
+	return peer;
+}
+EXPORT_SYMBOL(wlan_objmgr_get_peer_by_mac_n_vdev_no_state);
 
 void *wlan_objmgr_psoc_get_comp_private_obj(struct wlan_objmgr_psoc *psoc,
 					enum wlan_umac_comp_id id)
@@ -1040,3 +1310,66 @@ void *wlan_objmgr_psoc_get_comp_private_obj(struct wlan_objmgr_psoc *psoc,
 	return comp_private_obj;
 }
 EXPORT_SYMBOL(wlan_objmgr_psoc_get_comp_private_obj);
+
+void wlan_objmgr_psoc_get_ref(struct wlan_objmgr_psoc *psoc,
+						wlan_objmgr_ref_dbgid id)
+{
+	if (psoc == NULL) {
+		qdf_print("%s: psoc obj is NULL\n", __func__);
+		QDF_ASSERT(0);
+		return;
+	}
+	/* Increment ref count */
+	qdf_atomic_inc(&psoc->soc_objmgr.ref_cnt);
+
+	return;
+}
+EXPORT_SYMBOL(wlan_objmgr_psoc_get_ref);
+
+QDF_STATUS wlan_objmgr_psoc_try_get_ref(struct wlan_objmgr_psoc *psoc,
+						wlan_objmgr_ref_dbgid id)
+{
+	if (psoc == NULL) {
+		qdf_print("%s: psoc obj is NULL\n", __func__);
+		QDF_ASSERT(0);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	wlan_psoc_obj_lock(psoc);
+	if (psoc->obj_state == WLAN_OBJ_STATE_LOGICALLY_DELETED) {
+		wlan_psoc_obj_unlock(psoc);
+		qdf_print("%s: psoc obj is in Deletion Progress staet\n",
+			  __func__);
+		return QDF_STATUS_E_RESOURCES;
+	}
+
+	/* Increment ref count */
+	wlan_objmgr_psoc_get_ref(psoc, id);
+	wlan_psoc_obj_unlock(psoc);
+
+	return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(wlan_objmgr_psoc_try_get_ref);
+
+void wlan_objmgr_psoc_release_ref(struct wlan_objmgr_psoc *psoc,
+						wlan_objmgr_ref_dbgid id)
+{
+	if (psoc == NULL) {
+		qdf_print("%s: psoc obj is NULL\n", __func__);
+		QDF_ASSERT(0);
+		return;
+	}
+
+	if (!qdf_atomic_read(&psoc->soc_objmgr.ref_cnt)) {
+		qdf_print("%s: psoc ref cnt is 0\n", __func__);
+		WLAN_OBJMGR_BUG(0);
+		return;
+	}
+
+	/* Decrement ref count, free psoc, if ref count == 0 */
+	if (qdf_atomic_dec_and_test(&psoc->soc_objmgr.ref_cnt))
+		wlan_objmgr_psoc_obj_destroy(psoc);
+
+	return;
+}
+EXPORT_SYMBOL(wlan_objmgr_psoc_release_ref);

+ 156 - 57
umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c

@@ -67,9 +67,39 @@ static QDF_STATUS wlan_objmgr_vdev_object_status(
 		}
 	}
 	wlan_vdev_obj_unlock(vdev);
+
 	return status;
 }
 
+static QDF_STATUS wlan_objmgr_vdev_obj_free(struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_objmgr_pdev *pdev;
+
+	/* if PDEV is NULL, return */
+	pdev = wlan_vdev_get_pdev(vdev);
+	if (pdev == NULL) {
+		qdf_print("%s:pdev is NULL\n", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	/* Detach VDEV from PDEV VDEV's list */
+	if (wlan_objmgr_pdev_vdev_detach(pdev, vdev) ==
+					QDF_STATUS_E_FAILURE)
+		return QDF_STATUS_E_FAILURE;
+
+	/* Detach VDEV from PSOC VDEV's list */
+	if (wlan_objmgr_psoc_vdev_detach(
+			pdev->pdev_objmgr.wlan_psoc, vdev) ==
+					QDF_STATUS_E_FAILURE)
+		return QDF_STATUS_E_FAILURE;
+
+	qdf_spinlock_destroy(&vdev->vdev_lock);
+	qdf_mem_free(vdev);
+
+	return QDF_STATUS_SUCCESS;
+
+}
+
 struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create(
 			struct wlan_objmgr_pdev *pdev,
 			struct wlan_vdev_create_params *params)
@@ -129,6 +159,8 @@ struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create(
 	vdev->vdev_nif.osdev = params->osifp;
 	/* peer count to 0 */
 	vdev->vdev_objmgr.wlan_peer_count = 0;
+	qdf_atomic_init(&vdev->vdev_objmgr.ref_cnt);
+	wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID);
 	/* Initialize max peer count based on opmode type */
 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE)
 		vdev->vdev_objmgr.max_peer_count = WLAN_UMAC_MAX_STA_PEERS;
@@ -181,30 +213,29 @@ struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create(
 	}
 	return vdev;
 }
+EXPORT_SYMBOL(wlan_objmgr_vdev_obj_create);
 
-QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev)
+static QDF_STATUS wlan_objmgr_vdev_obj_destroy(struct wlan_objmgr_vdev *vdev)
 {
 	uint8_t id;
-	wlan_objmgr_vdev_delete_handler handler;
+	wlan_objmgr_vdev_destroy_handler handler;
 	QDF_STATUS obj_status;
 	void *arg;
-	struct wlan_objmgr_pdev *pdev;
 
 	if (vdev == NULL) {
 		qdf_print("%s:vdev is NULL\n", __func__);
 		return QDF_STATUS_E_FAILURE;
 	}
-	/* if PDEV is NULL, return */
-	pdev = wlan_vdev_get_pdev(vdev);
-	if (pdev == NULL) {
-		qdf_print("%s:pdev is NULL\n", __func__);
-		return QDF_STATUS_E_FAILURE;
+
+	if (vdev->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) {
+		qdf_print("%s:vdev object delete is not invoked\n", __func__);
+		WLAN_OBJMGR_BUG(0);
 	}
 
 	/* Invoke registered create handlers */
 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
-		handler = g_umac_glb_obj->vdev_delete_handler[id];
-		arg = g_umac_glb_obj->vdev_delete_handler_arg[id];
+		handler = g_umac_glb_obj->vdev_destroy_handler[id];
+		arg = g_umac_glb_obj->vdev_destroy_handler_arg[id];
 		if (handler != NULL)
 			vdev->obj_status[id] = handler(vdev, arg);
 		else
@@ -225,25 +256,30 @@ QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev)
 	if (obj_status == QDF_STATUS_COMP_ASYNC) {
 		vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED;
 		return QDF_STATUS_COMP_ASYNC;
-	} else {
-		/* Detach VDEV from PDEV VDEV's list */
-		if (wlan_objmgr_pdev_vdev_detach(pdev, vdev) ==
-						QDF_STATUS_E_FAILURE)
-			return QDF_STATUS_E_FAILURE;
-
-		/* Detach VDEV from PSOC VDEV's list */
-		if (wlan_objmgr_psoc_vdev_detach(
-				pdev->pdev_objmgr.wlan_psoc, vdev) ==
-						QDF_STATUS_E_FAILURE)
-			return QDF_STATUS_E_FAILURE;
-
-		/* de-init lock */
-		qdf_spinlock_destroy(&vdev->vdev_lock);
-		/* Free the memory */
-		qdf_mem_free(vdev);
 	}
+
+	/* Free VDEV object */
+	return wlan_objmgr_vdev_obj_free(vdev);
+}
+
+QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev)
+{
+	if (vdev == NULL) {
+		qdf_print("%s:vdev is NULL\n", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+	/*
+	 * Update VDEV object state to LOGICALLY DELETED
+	 * It prevents further access of this object
+	 */
+	wlan_vdev_obj_lock(vdev);
+	vdev->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED;
+	wlan_vdev_obj_unlock(vdev);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
+
 	return QDF_STATUS_SUCCESS;
 }
+EXPORT_SYMBOL(wlan_objmgr_vdev_obj_delete);
 
 /**
  ** APIs to attach/detach component objects
@@ -273,7 +309,6 @@ QDF_STATUS wlan_objmgr_vdev_component_obj_attach(
 	vdev->vdev_comp_priv_obj[id] = comp_priv_obj;
 	vdev->obj_status[id] = status;
 	wlan_vdev_obj_unlock(vdev);
-
 	if (vdev->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED)
 		return QDF_STATUS_SUCCESS;
 	/*
@@ -329,7 +364,7 @@ QDF_STATUS wlan_objmgr_vdev_component_obj_detach(
 	wlan_vdev_obj_unlock(vdev);
 
 	/**
-	 *If VDEV object status is partially deleted means, this API is
+	 *If VDEV object status is partially destroyed means, this API is
 	 * invoked with differnt context, this block should be executed for
 	 * async components only
 	 */
@@ -370,25 +405,13 @@ QDF_STATUS wlan_objmgr_vdev_component_obj_detach(
 		/* Delete vdev object */
 		if ((obj_status == QDF_STATUS_SUCCESS)  &&
 		    (vdev->obj_state == WLAN_OBJ_STATE_DELETED)) {
-			/* Detach vdev object from psoc */
-			if (wlan_objmgr_pdev_vdev_detach(
-					wlan_vdev_get_pdev(vdev), vdev)
-						== QDF_STATUS_E_FAILURE)
-				return QDF_STATUS_E_FAILURE;
-			/* Detach vdev object from psoc */
-			if (wlan_objmgr_psoc_vdev_detach(
-				wlan_vdev_get_psoc(vdev), vdev) ==
-						QDF_STATUS_E_FAILURE)
-				return QDF_STATUS_E_FAILURE;
-
-			/* Destroy spinlock */
-			qdf_spinlock_destroy(&vdev->vdev_lock);
-			/* Free VDEV memory */
-			qdf_mem_free(vdev);
+			/* Free VDEV object */
+			return wlan_objmgr_vdev_obj_free(vdev);
 		}
 	}
 	return QDF_STATUS_SUCCESS;
 }
+EXPORT_SYMBOL(wlan_objmgr_vdev_component_obj_detach);
 
 /**
  ** APIs to operations on vdev objects
@@ -396,34 +419,43 @@ QDF_STATUS wlan_objmgr_vdev_component_obj_detach(
 QDF_STATUS wlan_objmgr_iterate_peerobj_list(
 		struct wlan_objmgr_vdev *vdev,
 		wlan_objmgr_vdev_op_handler handler,
-		void *arg)
+		void *arg, wlan_objmgr_ref_dbgid dbg_id)
 {
 	qdf_list_t *peer_list = NULL;
 	struct wlan_objmgr_peer *peer = NULL;
-	struct wlan_objmgr_peer *prev_peer = NULL;
+	struct wlan_objmgr_peer *peer_next = NULL;
 
 	if (vdev == NULL) {
 		qdf_print("%s: VDEV NULL\n", __func__);
 		return QDF_STATUS_E_FAILURE;
 	}
-		/* TODO increment ref count */
 	wlan_vdev_obj_lock(vdev);
+
+	if (vdev->obj_state ==
+		WLAN_OBJ_STATE_LOGICALLY_DELETED) {
+		wlan_vdev_obj_unlock(vdev);
+		qdf_print("%s: VDEV is in delete progress\n", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+	wlan_objmgr_vdev_get_ref(vdev, dbg_id);
 	peer_list = &vdev->vdev_objmgr.wlan_peer_list;
 	if (peer_list != NULL) {
 		/* Iterate through VDEV's peer list */
 		peer = wlan_vdev_peer_list_peek_head(peer_list);
 		while (peer != NULL) {
-			wlan_objmgr_peer_ref_peer(peer);
-			/* Invoke handler for operation */
-			handler(vdev, (void *)peer, arg);
-			prev_peer = peer;
-			peer = wlan_peer_get_next_peer_of_vdev(peer_list,
-							       prev_peer);
-			wlan_objmgr_peer_unref_peer(prev_peer);
+			peer_next = wlan_peer_get_next_peer_of_vdev(peer_list,
+							       peer);
+			if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
+					QDF_STATUS_SUCCESS) {
+				/* Invoke handler for operation */
+				handler(vdev, (void *)peer, arg);
+				wlan_objmgr_peer_release_ref(peer, dbg_id);
+			}
+			peer = peer_next;
 		}
 	}
+	wlan_objmgr_vdev_release_ref(vdev, dbg_id);
 	wlan_vdev_obj_unlock(vdev);
-		/* TODO decrement ref count */
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -475,7 +507,7 @@ QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_deletion(
 		struct wlan_objmgr_vdev *vdev,
 		enum wlan_umac_comp_id id)
 {
-	wlan_objmgr_vdev_delete_handler handler;
+	wlan_objmgr_vdev_destroy_handler handler;
 	void *arg;
 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
 
@@ -492,8 +524,8 @@ QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_deletion(
 	wlan_vdev_obj_unlock(vdev);
 
 	/* Invoke registered create handlers */
-	handler = g_umac_glb_obj->vdev_delete_handler[id];
-	arg = g_umac_glb_obj->vdev_delete_handler_arg[id];
+	handler = g_umac_glb_obj->vdev_destroy_handler[id];
+	arg = g_umac_glb_obj->vdev_destroy_handler_arg[id];
 	if (handler != NULL)
 		vdev->obj_status[id] = handler(vdev, arg);
 	else
@@ -565,6 +597,8 @@ QDF_STATUS wlan_objmgr_vdev_peer_attach(struct wlan_objmgr_vdev *vdev,
 		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE)
 			wlan_vdev_set_bsspeer(vdev, peer);
 	}
+	/* Increment vdev ref count to make sure it won't be destroyed before */
+	wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID);
 	wlan_vdev_obj_unlock(vdev);
 	return QDF_STATUS_SUCCESS;
 }
@@ -589,6 +623,8 @@ QDF_STATUS wlan_objmgr_vdev_peer_detach(struct wlan_objmgr_vdev *vdev,
 	/* decrement peer count */
 	objmgr->wlan_peer_count--;
 	wlan_vdev_obj_unlock(vdev);
+	/* decrement vdev ref count after peer released its reference */
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -616,3 +652,66 @@ void *wlan_objmgr_vdev_get_comp_private_obj(
 	return comp_priv_obj;
 }
 EXPORT_SYMBOL(wlan_objmgr_vdev_get_comp_private_obj);
+
+void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev,
+						wlan_objmgr_ref_dbgid id)
+{
+	if (vdev == NULL) {
+		qdf_print("%s: vdev obj is NULL\n", __func__);
+		QDF_ASSERT(0);
+		return;
+	}
+	/* Increment ref count */
+	qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt);
+
+	return;
+}
+EXPORT_SYMBOL(wlan_objmgr_vdev_get_ref);
+
+QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev,
+						wlan_objmgr_ref_dbgid id)
+{
+	if (vdev == NULL) {
+		qdf_print("%s: vdev obj is NULL\n", __func__);
+		QDF_ASSERT(0);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	wlan_vdev_obj_lock(vdev);
+	if (vdev->obj_state == WLAN_OBJ_STATE_LOGICALLY_DELETED) {
+		wlan_vdev_obj_unlock(vdev);
+		qdf_print("%s: vdev obj is in Deletion Progress state\n",
+			  __func__);
+		return QDF_STATUS_E_RESOURCES;
+	}
+
+	/* Increment ref count */
+	wlan_objmgr_vdev_get_ref(vdev, id);
+	wlan_vdev_obj_unlock(vdev);
+
+	return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(wlan_objmgr_vdev_try_get_ref);
+
+void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev,
+						wlan_objmgr_ref_dbgid id)
+{
+	if (vdev == NULL) {
+		qdf_print("%s: vdev obj is NULL\n", __func__);
+		QDF_ASSERT(0);
+		return;
+	}
+
+	if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) {
+		qdf_print("%s: vdev ref cnt is 0\n", __func__);
+		WLAN_OBJMGR_BUG(0);
+		return;
+	}
+
+	/* Decrement ref count, free vdev, if ref count == 0 */
+	if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt))
+		wlan_objmgr_vdev_obj_destroy(vdev);
+
+	return;
+}
+EXPORT_SYMBOL(wlan_objmgr_vdev_release_ref);

+ 5 - 5
umac/cmn_services/serialization/src/wlan_serialization_main.c

@@ -302,7 +302,7 @@ QDF_STATUS wlan_serialization_init(void)
 		goto err_psoc_create;
 	}
 
-	status = wlan_objmgr_register_psoc_delete_handler(
+	status = wlan_objmgr_register_psoc_destroy_handler(
 			WLAN_UMAC_COMP_SERIALIZATION,
 			wlan_serialization_psoc_obj_destroy_notification, NULL);
 	if (status != QDF_STATUS_SUCCESS) {
@@ -318,7 +318,7 @@ QDF_STATUS wlan_serialization_init(void)
 		goto err_pdev_create;
 	}
 
-	status = wlan_objmgr_register_pdev_delete_handler(
+	status = wlan_objmgr_register_pdev_destroy_handler(
 			WLAN_UMAC_COMP_SERIALIZATION,
 			wlan_serialization_pdev_obj_destroy_notification, NULL);
 	if (status != QDF_STATUS_SUCCESS) {
@@ -334,7 +334,7 @@ err_pdev_delete:
 	wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_SERIALIZATION,
 			wlan_serialization_pdev_obj_create_notification, NULL);
 err_pdev_create:
-	wlan_objmgr_unregister_psoc_delete_handler(WLAN_UMAC_COMP_SERIALIZATION,
+	wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_SERIALIZATION,
 			wlan_serialization_psoc_obj_destroy_notification, NULL);
 err_psoc_delete:
 	wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_SERIALIZATION,
@@ -358,7 +358,7 @@ QDF_STATUS wlan_serialization_deinit(void)
 				status);
 		ret_status = QDF_STATUS_E_FAILURE;
 	}
-	status = wlan_objmgr_unregister_psoc_delete_handler(
+	status = wlan_objmgr_unregister_psoc_destroy_handler(
 			WLAN_UMAC_COMP_SERIALIZATION,
 			wlan_serialization_psoc_obj_destroy_notification,
 			NULL);
@@ -378,7 +378,7 @@ QDF_STATUS wlan_serialization_deinit(void)
 		ret_status = QDF_STATUS_E_FAILURE;
 	}
 
-	status = wlan_objmgr_unregister_pdev_delete_handler(
+	status = wlan_objmgr_unregister_pdev_destroy_handler(
 			WLAN_UMAC_COMP_SERIALIZATION,
 			wlan_serialization_pdev_obj_destroy_notification,
 			NULL);