/*
 * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
 *
 * Permission to use, copy, modify, and/or distribute this software for
 * any purpose with or without fee is hereby granted, provided that the
 * above copyright notice and this permission notice appear in all
 * copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */
 /**
  * DOC: Public APIs to perform operations on Global objects
  */

#include <wlan_objmgr_cmn.h>
#include <wlan_objmgr_global_obj.h>
#include <wlan_objmgr_psoc_obj.h>
#include <wlan_objmgr_pdev_obj.h>
#include <wlan_objmgr_vdev_obj.h>
#include <wlan_objmgr_peer_obj.h>
#include <qdf_mem.h>
#include <qdf_types.h>
#include <qdf_module.h>
#include "wlan_objmgr_global_obj_i.h"
#include "wlan_objmgr_psoc_obj_i.h"
#include "wlan_objmgr_pdev_obj_i.h"

/**
 ** APIs to Create/Delete Global object APIs
 */
static QDF_STATUS wlan_objmgr_psoc_object_status(
			struct wlan_objmgr_psoc *psoc)
{
	uint8_t id;
	QDF_STATUS status = QDF_STATUS_SUCCESS;

	wlan_psoc_obj_lock(psoc);
	/* Iterate through all components to derive the object status */
	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
		/* If component disabled, Ignore */
		if (psoc->obj_status[id] == QDF_STATUS_COMP_DISABLED)
			continue;
		/* If component operates in Async, status is Partially created,
		 * break
		 */
		else if (psoc->obj_status[id] == QDF_STATUS_COMP_ASYNC) {
			if (psoc->soc_comp_priv_obj[id] == NULL) {
				status = QDF_STATUS_COMP_ASYNC;
				break;
			}
		/*
		 * If component failed to allocate its object, treat it as
		 * failure, complete object need to be cleaned up
		 */
		} else if ((psoc->obj_status[id] == QDF_STATUS_E_NOMEM) ||
			(psoc->obj_status[id] == QDF_STATUS_E_FAILURE)) {
			status = QDF_STATUS_E_FAILURE;
			break;
		}
	}
	wlan_psoc_obj_unlock(psoc);

	return status;
}

static void wlan_objmgr_psoc_peer_list_init(struct wlan_peer_list *peer_list)
{
	uint8_t i;

	qdf_spinlock_create(&peer_list->peer_list_lock);
	for (i = 0; i < WLAN_PEER_HASHSIZE; i++)
		qdf_list_create(&peer_list->peer_hash[i],
				WLAN_UMAC_PSOC_MAX_PEERS);
}

static void wlan_objmgr_psoc_peer_list_deinit(struct wlan_peer_list *peer_list)
{
	uint8_t i;

	/* deinit the lock */
	qdf_spinlock_destroy(&peer_list->peer_list_lock);
	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) {
		obj_mgr_err("PSOC object detach failed");
		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;
}

struct wlan_objmgr_psoc *wlan_objmgr_psoc_obj_create(uint32_t phy_version,
						WLAN_DEV_TYPE dev_type)
{
	uint8_t id;
	struct wlan_objmgr_psoc *psoc = NULL;
	wlan_objmgr_psoc_create_handler handler;
	wlan_objmgr_psoc_status_handler stat_handler;
	struct wlan_objmgr_psoc_objmgr *objmgr;
	QDF_STATUS obj_status;
	void *arg;

	psoc = qdf_mem_malloc(sizeof(*psoc));
	if (psoc == NULL) {
		obj_mgr_err("PSOC allocation failed");
		return NULL;
	}
	psoc->obj_state = WLAN_OBJ_STATE_ALLOCATED;
	qdf_spinlock_create(&psoc->psoc_lock);
	/* Initialize with default values */
	objmgr = &psoc->soc_objmgr;
	objmgr->wlan_pdev_count = 0;
	objmgr->wlan_vdev_count = 0;
	objmgr->max_vdev_count = WLAN_UMAC_PSOC_MAX_VDEVS;
	objmgr->wlan_peer_count = 0;
	objmgr->max_peer_count = WLAN_UMAC_PSOC_MAX_PEERS;
	qdf_atomic_init(&objmgr->ref_cnt);
	objmgr->print_cnt = 0;
	/* 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];
		arg = g_umac_glb_obj->psoc_create_handler_arg[id];
		if (handler != NULL)
			psoc->obj_status[id] = handler(psoc, arg);
		else
			psoc->obj_status[id] = QDF_STATUS_COMP_DISABLED;
	}
	/* Derive object status */
	obj_status = wlan_objmgr_psoc_object_status(psoc);

	if (obj_status == QDF_STATUS_SUCCESS) {
		/* Object status is SUCCESS, Object is created */
		psoc->obj_state = WLAN_OBJ_STATE_CREATED;
		for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
			stat_handler = g_umac_glb_obj->psoc_status_handler[id];
			arg = g_umac_glb_obj->psoc_status_handler_arg[id];
			if (stat_handler != NULL)
				stat_handler(psoc, arg,
					     QDF_STATUS_SUCCESS);
		}
	} else if (obj_status == QDF_STATUS_COMP_ASYNC) {
		/*
		 * Few components operates in Asynchrous communction
		 * Object state partially created
		 */
		psoc->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
	} else if (obj_status == QDF_STATUS_E_FAILURE) {
		/* Component object failed to be created, clean up the object */
		obj_mgr_err("PSOC component objects allocation failed");
		/* Clean up the psoc */
		wlan_objmgr_psoc_obj_delete(psoc);
		return NULL;
	}

	if (wlan_objmgr_psoc_object_attach(psoc) !=
				QDF_STATUS_SUCCESS) {
		obj_mgr_err("PSOC object attach failed");
		wlan_objmgr_psoc_obj_delete(psoc);
		return NULL;
	}

	obj_mgr_info("Created psoc %d", psoc->soc_objmgr.psoc_id);

	return psoc;
}
qdf_export_symbol(wlan_objmgr_psoc_obj_create);

static QDF_STATUS wlan_objmgr_psoc_obj_destroy(struct wlan_objmgr_psoc *psoc)
{
	uint8_t id;
	wlan_objmgr_psoc_destroy_handler handler;
	QDF_STATUS obj_status;
	void *arg;

	if (psoc == NULL) {
		obj_mgr_err("psoc is NULL");
		return QDF_STATUS_E_FAILURE;
	}
	wlan_objmgr_notify_destroy(psoc, WLAN_PSOC_OP);

	obj_mgr_info("Physically deleting psoc %d", psoc->soc_objmgr.psoc_id);

	if (psoc->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) {
		obj_mgr_err("psoc object delete is not invoked");
		WLAN_OBJMGR_BUG(0);
	}

	/* Invoke registered create handlers */
	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; 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
			psoc->obj_status[id] = QDF_STATUS_COMP_DISABLED;
	}
	/* Derive object status */
	obj_status = wlan_objmgr_psoc_object_status(psoc);

	if (obj_status == QDF_STATUS_E_FAILURE) {
		obj_mgr_err("PSOC component object free failed");
		/* Ideally should not happen
		 * This leads to memleak, BUG_ON to find which component
		 * delete notification failed and fix it.
		 */
		QDF_BUG(0);
		return QDF_STATUS_E_FAILURE;
	}
	/* Deletion is in progress */
	if (obj_status == QDF_STATUS_COMP_ASYNC) {
		psoc->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED;
		return QDF_STATUS_COMP_ASYNC;
	}

	/* Free psoc object */
	return wlan_objmgr_psoc_obj_free(psoc);
}


QDF_STATUS wlan_objmgr_psoc_obj_delete(struct wlan_objmgr_psoc *psoc)
{
	uint8_t print_idx;

	if (psoc == NULL) {
		obj_mgr_err("psoc is NULL");
		return QDF_STATUS_E_FAILURE;
	}

	obj_mgr_info("Logically deleting psoc %d", psoc->soc_objmgr.psoc_id);

	print_idx = qdf_get_pidx();
	if (qdf_print_is_verbose_enabled(print_idx, QDF_MODULE_ID_OBJ_MGR,
		QDF_TRACE_LEVEL_DEBUG)) {
		wlan_objmgr_print_ref_ids(psoc->soc_objmgr.ref_id_dbg);
	}

	/*
	 * 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_notify_log_delete(psoc, WLAN_PSOC_OP);
	wlan_objmgr_psoc_release_ref(psoc, WLAN_OBJMGR_ID);

	return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(wlan_objmgr_psoc_obj_delete);

QDF_STATUS wlan_objmgr_psoc_component_obj_attach(
		struct wlan_objmgr_psoc *psoc,
		enum wlan_umac_comp_id id,
		void *comp_priv_obj,
		QDF_STATUS status)
{
	wlan_objmgr_psoc_status_handler stat_handler;
	void *arg = NULL;
	QDF_STATUS obj_status;
	uint8_t i;

	/* component id is invalid */
	if (id >= WLAN_UMAC_MAX_COMPONENTS)
		return QDF_STATUS_MAXCOMP_FAIL;

	wlan_psoc_obj_lock(psoc);
	/* If there is a valid entry, return failure */
	if (psoc->soc_comp_priv_obj[id] != NULL) {
		wlan_psoc_obj_unlock(psoc);
		return QDF_STATUS_E_FAILURE;
	}
	/* 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)
		return QDF_STATUS_SUCCESS;
	/* If PSOC 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_psoc_object_status(psoc);
	/* STATUS_SUCCESS means, object is CREATED */
	if (obj_status == QDF_STATUS_SUCCESS)
		psoc->obj_state = WLAN_OBJ_STATE_CREATED;
	/* update state as CREATION failed, caller has to delete the
	 * PSOC object
	 */
	else if (obj_status == QDF_STATUS_E_FAILURE)
		psoc->obj_state = WLAN_OBJ_STATE_CREATION_FAILED;

	/* Notify components about the CREATION success/failure */
	if ((obj_status == QDF_STATUS_SUCCESS) ||
	    (obj_status == QDF_STATUS_E_FAILURE)) {
		/* nofity object status */
		for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) {
			stat_handler = g_umac_glb_obj->psoc_status_handler[i];
			arg = g_umac_glb_obj->psoc_status_handler_arg[i];
			if (stat_handler != NULL)
				stat_handler(psoc, arg, obj_status);
		}
	}

	return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(wlan_objmgr_psoc_component_obj_attach);

QDF_STATUS wlan_objmgr_psoc_component_obj_detach(
		struct wlan_objmgr_psoc *psoc,
		enum wlan_umac_comp_id id,
		void *comp_priv_obj)
{
	QDF_STATUS obj_status;

	/* component id is invalid */
	if (id >= WLAN_UMAC_MAX_COMPONENTS)
		return QDF_STATUS_MAXCOMP_FAIL;

	wlan_psoc_obj_lock(psoc);
	/* If there is a valid entry, return failure */
	if (psoc->soc_comp_priv_obj[id] != comp_priv_obj) {
		psoc->obj_status[id] = QDF_STATUS_E_FAILURE;
		wlan_psoc_obj_unlock(psoc);
		return QDF_STATUS_E_FAILURE;
	}
	/* Reset pointers to NULL, update the status*/
	psoc->soc_comp_priv_obj[id] = NULL;
	psoc->obj_status[id] = QDF_STATUS_SUCCESS;
	wlan_psoc_obj_unlock(psoc);

	/* If PSOC object status is partially created means, this API is
	 * invoked with differnt context, this block should be executed for
	 * async components only
	 */
	if ((psoc->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) ||
	    (psoc->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) {
		/* Derive object status */
		obj_status = wlan_objmgr_psoc_object_status(psoc);
		if (obj_status == QDF_STATUS_SUCCESS) {
			/* Update the status as Deleted, if full object
			 * deletion is in progress
			 */
			if (psoc->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
				psoc->obj_state = WLAN_OBJ_STATE_DELETED;

			/* Move to creation state, since this component
			 * deletion alone requested
			 */
			if (psoc->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
				psoc->obj_state = WLAN_OBJ_STATE_CREATED;
		/* Object status is failure */
		} else if (obj_status == QDF_STATUS_E_FAILURE) {
			/* Update the status as Deletion failed, if full object
			 * deletion is in progress
			 */
			if (psoc->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
				psoc->obj_state =
					WLAN_OBJ_STATE_DELETION_FAILED;

			/* Move to creation state, since this component
			 * deletion alone requested (do not block other
			 * components)
			 */
			if (psoc->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
				psoc->obj_state = WLAN_OBJ_STATE_CREATED;
		}

		/* Delete psoc object */
		if ((obj_status == QDF_STATUS_SUCCESS)  &&
		    (psoc->obj_state == WLAN_OBJ_STATE_DELETED)) {
			/* Free psoc object */
			return wlan_objmgr_psoc_obj_free(psoc);
		}
	}

	return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(wlan_objmgr_psoc_component_obj_detach);

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,
		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;
	uint16_t max_vdev_cnt;

	/* If caller requests for lock free opeation, do not acquire,
	 * handler will handle the synchronization
	 */
	if (!lock_free_op)
		wlan_psoc_obj_lock(psoc);

	switch (obj_type) {
	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++) {
			pdev = objmgr->wlan_pdev_list[obj_id];
			if ((pdev != NULL) &&
			    (wlan_objmgr_pdev_try_get_ref(pdev, dbg_id) ==
				QDF_STATUS_SUCCESS)) {
				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 */
		max_vdev_cnt = wlan_psoc_get_max_vdev_count(psoc);
		for (obj_id = 0; obj_id < max_vdev_cnt; obj_id++) {
			vdev = objmgr->wlan_vdev_list[obj_id];
			if ((vdev != NULL) &&
			    (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) ==
				QDF_STATUS_SUCCESS)) {
				handler(psoc, vdev, arg);
				wlan_objmgr_vdev_release_ref(vdev, dbg_id);
			}
		}
		break;
	case WLAN_PEER_OP:
		/* Iterate through PEER list, invoke handler for each peer */
		peer_list = &objmgr->peer_list;
		/* psoc lock should be taken before list lock */
		if (!lock_free_op)
			qdf_spin_lock_bh(&peer_list->peer_list_lock);
		/* Since peer list has sublist, iterate through sublists */
		for (i = 0; i < WLAN_PEER_HASHSIZE; i++) {
			obj_list = &peer_list->peer_hash[i];
			peer = wlan_psoc_peer_list_peek_head(obj_list);
			while (peer) {
				/* Get next peer */
				peer_next = wlan_peer_get_next_peer_of_psoc(
								obj_list, 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;
			}
		}
		if (!lock_free_op)
			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
		break;
	default:
		break;
	}
	if (!lock_free_op)
		wlan_psoc_obj_unlock(psoc);

	return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(wlan_objmgr_iterate_obj_list);

QDF_STATUS wlan_objmgr_iterate_obj_list_all(
		struct wlan_objmgr_psoc *psoc,
		enum wlan_objmgr_obj_type obj_type,
		wlan_objmgr_op_handler handler,
		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;
	uint16_t max_vdev_cnt;

	/* If caller requests for lock free opeation, do not acquire,
	 * handler will handle the synchronization
	 */
	if (!lock_free_op)
		wlan_psoc_obj_lock(psoc);

	switch (obj_type) {
	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++) {
			pdev = objmgr->wlan_pdev_list[obj_id];
			if (pdev != NULL) {
				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 */
		max_vdev_cnt = wlan_psoc_get_max_vdev_count(psoc);
		for (obj_id = 0; obj_id < max_vdev_cnt; obj_id++) {
			vdev = objmgr->wlan_vdev_list[obj_id];
			if (vdev != NULL) {
				wlan_objmgr_vdev_get_ref(vdev, dbg_id);
				handler(psoc, vdev, arg);
				wlan_objmgr_vdev_release_ref(vdev, dbg_id);
			}
		}
		break;
	case WLAN_PEER_OP:
		/* Iterate through PEER list, invoke handler for each peer */
		peer_list = &objmgr->peer_list;
		/* psoc lock should be taken before list lock */
		if (!lock_free_op)
			qdf_spin_lock_bh(&peer_list->peer_list_lock);
		/* Since peer list has sublist, iterate through sublists */
		for (i = 0; i < WLAN_PEER_HASHSIZE; i++) {
			obj_list = &peer_list->peer_hash[i];
			peer = wlan_psoc_peer_list_peek_head(obj_list);
			while (peer) {
				/* Get next peer */
				peer_next = wlan_peer_get_next_peer_of_psoc(
								obj_list, peer);
				wlan_objmgr_peer_get_ref(peer, dbg_id);
				handler(psoc, (void *)peer, arg);
				wlan_objmgr_peer_release_ref(peer, dbg_id);
				peer = peer_next;
			}
		}
		if (!lock_free_op)
			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
		break;
	default:
		break;
	}
	if (!lock_free_op)
		wlan_psoc_obj_unlock(psoc);

	return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(wlan_objmgr_iterate_obj_list_all);

/**
 * wlan_objmgr_iterate_obj_list_all_noref() - iterate through all psoc objects
 *                                            without taking ref
 * @psoc: PSOC object
 * @obj_type: PDEV_OP/VDEV_OP/PEER_OP
 * @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
 *
 * API to be used for performing the operations on all PDEV/VDEV/PEER objects
 * of psoc with lock protected
 *
 * Return: SUCCESS/FAILURE
 */
static QDF_STATUS wlan_objmgr_iterate_obj_list_all_noref(
		struct wlan_objmgr_psoc *psoc,
		enum wlan_objmgr_obj_type obj_type,
		wlan_objmgr_op_handler handler,
		void *arg)
{
	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;
	uint16_t max_vdev_cnt;

	/* If caller requests for lock free opeation, do not acquire,
	 * handler will handle the synchronization
	 */
	wlan_psoc_obj_lock(psoc);

	switch (obj_type) {
	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++) {
			pdev = objmgr->wlan_pdev_list[obj_id];
			if (pdev != NULL)
				handler(psoc, (void *)pdev, arg);
		}
		break;
	case WLAN_VDEV_OP:
		/* Iterate through VDEV list, invoke handler for each vdev */
		max_vdev_cnt = wlan_psoc_get_max_vdev_count(psoc);
		for (obj_id = 0; obj_id < max_vdev_cnt; obj_id++) {
			vdev = objmgr->wlan_vdev_list[obj_id];
			if (vdev != NULL)
				handler(psoc, vdev, arg);
		}
		break;
	case WLAN_PEER_OP:
		/* Iterate through PEER list, invoke handler for each peer */
		peer_list = &objmgr->peer_list;
		/* psoc lock should be taken before list lock */
		qdf_spin_lock_bh(&peer_list->peer_list_lock);
		/* Since peer list has sublist, iterate through sublists */
		for (i = 0; i < WLAN_PEER_HASHSIZE; i++) {
			obj_list = &peer_list->peer_hash[i];
			peer = wlan_psoc_peer_list_peek_head(obj_list);
			while (peer) {
				/* Get next peer */
				peer_next = wlan_peer_get_next_peer_of_psoc(
								obj_list, peer);
				handler(psoc, (void *)peer, arg);
				peer = peer_next;
			}
		}
		qdf_spin_unlock_bh(&peer_list->peer_list_lock);
		break;
	default:
		break;
	}
	wlan_psoc_obj_unlock(psoc);

	return QDF_STATUS_SUCCESS;
}

static void wlan_objmgr_psoc_peer_delete(struct wlan_objmgr_psoc *psoc,
					 void *obj, void *args)
{
	struct wlan_objmgr_peer *peer = (struct wlan_objmgr_peer *)obj;

	wlan_objmgr_peer_obj_delete(peer);
}

static void wlan_objmgr_psoc_vdev_delete(struct wlan_objmgr_psoc *psoc,
					 void *obj, void *args)
{
	struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)obj;

	wlan_objmgr_vdev_obj_delete(vdev);
}

static void wlan_objmgr_psoc_pdev_delete(struct wlan_objmgr_psoc *psoc,
					 void *obj, void *args)
{
	struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj;

	wlan_objmgr_pdev_obj_delete(pdev);
}

QDF_STATUS wlan_objmgr_free_all_objects_per_psoc(
		struct wlan_objmgr_psoc *psoc)
{
	/* Free all peers */
	wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP,
				     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_ID);
	/* Free all PDEVs */
	wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
				     wlan_objmgr_psoc_pdev_delete, NULL, 1,
				     WLAN_OBJMGR_ID);

	return QDF_STATUS_SUCCESS;
}

QDF_STATUS wlan_objmgr_trigger_psoc_comp_priv_object_creation(
		struct wlan_objmgr_psoc *psoc,
		enum wlan_umac_comp_id id)
{
	wlan_objmgr_psoc_create_handler handler;
	void *arg;
	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;

	/* Component id is invalid */
	if (id >= WLAN_UMAC_MAX_COMPONENTS)
		return QDF_STATUS_MAXCOMP_FAIL;

	wlan_psoc_obj_lock(psoc);
	/* If component object is already created, delete old
	 * component object, then invoke creation
	 */
	if (psoc->soc_comp_priv_obj[id] != NULL) {
		wlan_psoc_obj_unlock(psoc);
		return QDF_STATUS_E_FAILURE;
	}
	wlan_psoc_obj_unlock(psoc);
	/* Invoke registered create handlers */
	handler = g_umac_glb_obj->psoc_create_handler[id];
	arg = g_umac_glb_obj->psoc_create_handler_arg[id];
	if (handler != NULL)
		psoc->obj_status[id] = handler(psoc, arg);
	else
		return QDF_STATUS_E_FAILURE;

	/* If object status is created, then only handle this object status */
	if (psoc->obj_state == WLAN_OBJ_STATE_CREATED) {
		/* Derive object status */
		obj_status = wlan_objmgr_psoc_object_status(psoc);
		/* Move PSOC object state to Partially created state */
		if (obj_status == QDF_STATUS_COMP_ASYNC) {
			/*TODO atomic */
			psoc->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
		}
	}

	return obj_status;
}

QDF_STATUS wlan_objmgr_trigger_psoc_comp_priv_object_deletion(
		struct wlan_objmgr_psoc *psoc,
		enum wlan_umac_comp_id id)
{
	wlan_objmgr_psoc_destroy_handler handler;
	void *arg;
	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;

	/* component id is invalid */
	if (id >= WLAN_UMAC_MAX_COMPONENTS)
		return QDF_STATUS_MAXCOMP_FAIL;

	wlan_psoc_obj_lock(psoc);
	/* Component object was never created, invalid operation */
	if (psoc->soc_comp_priv_obj[id] == NULL) {
		wlan_psoc_obj_unlock(psoc);
		return QDF_STATUS_E_FAILURE;
	}
	wlan_psoc_obj_unlock(psoc);
	/* Invoke registered create handlers */
	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
		return QDF_STATUS_E_FAILURE;

	/* If object status is created, then only handle this object status */
	if (psoc->obj_state == WLAN_OBJ_STATE_CREATED) {
		obj_status = wlan_objmgr_psoc_object_status(psoc);
			/* move object state to DEL progress */
		if (obj_status == QDF_STATUS_COMP_ASYNC)
			psoc->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS;
	}

	return obj_status;
}

/* Util APIs */

QDF_STATUS wlan_objmgr_psoc_pdev_attach(struct wlan_objmgr_psoc *psoc,
					struct wlan_objmgr_pdev *pdev)
{
	struct wlan_objmgr_psoc_objmgr *objmgr;
	uint8_t id = 0;
	QDF_STATUS status;

	wlan_psoc_obj_lock(psoc);
	objmgr = &psoc->soc_objmgr;
	/*
	 * Derive pdev id from pdev map
	 * First free pdev id is assigned
	 */
	while ((id < WLAN_UMAC_MAX_PDEVS) &&
			(objmgr->wlan_pdev_id_map & (1<<id)))
		id++;

	if (id == WLAN_UMAC_MAX_PDEVS) {
		status = QDF_STATUS_E_FAILURE;
	} else {
		/* Update the map for reserving the id */
		objmgr->wlan_pdev_id_map |= (1<<id);
		/* store pdev in pdev list */
		objmgr->wlan_pdev_list[id] = pdev;
		/* Increment pdev count */
		objmgr->wlan_pdev_count++;
		/* 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);

	return status;
}

QDF_STATUS wlan_objmgr_psoc_pdev_detach(struct wlan_objmgr_psoc *psoc,
						struct wlan_objmgr_pdev *pdev)
{
	struct wlan_objmgr_psoc_objmgr *objmgr;
	uint8_t id;

	id = pdev->pdev_objmgr.wlan_pdev_id;
	/* If id is invalid, return */
	if (id >= WLAN_UMAC_MAX_PDEVS)
		return QDF_STATUS_E_FAILURE;

	wlan_psoc_obj_lock(psoc);
	objmgr = &psoc->soc_objmgr;
	/* Free pdev id slot */
	objmgr->wlan_pdev_id_map &= ~(1<<id);
	objmgr->wlan_pdev_list[id] = NULL;
	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_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;

	/* If id is invalid, return */
	if (id >= WLAN_UMAC_MAX_PDEVS)
		return 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) {
		if (wlan_objmgr_pdev_try_get_ref(pdev, dbg_id) !=
							QDF_STATUS_SUCCESS)
			pdev = NULL;
	}

	wlan_psoc_obj_unlock(psoc);

	return pdev;
}
qdf_export_symbol(wlan_objmgr_get_pdev_by_id);

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;

	/* If id is invalid, return */
	if (id >= WLAN_UMAC_MAX_PDEVS)
		return 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)
{
	struct wlan_objmgr_psoc_objmgr *objmgr;
	uint8_t id = 0;
	uint8_t map_index = 0;
	uint8_t map_entry_size = 32;
	uint8_t adjust_ix = 0;
	QDF_STATUS status;

	wlan_psoc_obj_lock(psoc);
	objmgr = &psoc->soc_objmgr;
	/* Find first free vdev id */
	while ((id < objmgr->max_vdev_count) &&
		(objmgr->wlan_vdev_id_map[map_index] & (1<<(id - adjust_ix)))) {
		id++;
		/*
		 * The map is two DWORDS(32 bits), so, map_index
		 * adjust_ix derived based on the id value
		 */
		if (id == ((map_index + 1) * map_entry_size)) {
			map_index++;
			adjust_ix = map_index * map_entry_size;
		}
	}
	/* If no free slot, return failure */
	if (id == objmgr->max_vdev_count) {
		status = QDF_STATUS_E_FAILURE;
	} else {
		/* set free vdev id index */
		objmgr->wlan_vdev_id_map[map_index] |= (1<<(id-adjust_ix));
		/* store vdev pointer in vdev list */
		objmgr->wlan_vdev_list[id] = vdev;
		/* increment vdev counter */
		objmgr->wlan_vdev_count++;
		/* save vdev id */
		vdev->vdev_objmgr.vdev_id = id;
		status = QDF_STATUS_SUCCESS;
	}
	wlan_psoc_obj_unlock(psoc);

	return status;
}

QDF_STATUS wlan_objmgr_psoc_vdev_detach(struct wlan_objmgr_psoc *psoc,
					struct wlan_objmgr_vdev *vdev)
{
	struct wlan_objmgr_psoc_objmgr *objmgr;
	uint8_t id = 0;
	uint8_t map_index = 0;
	uint8_t map_entry_size = 32;
	uint8_t adjust_ix = 0;

	id = vdev->vdev_objmgr.vdev_id;
	/* Invalid vdev id */
	if (id >= wlan_psoc_get_max_vdev_count(psoc))
		return QDF_STATUS_E_FAILURE;
	/*
	 * Derive map_index and adjust_ix to find actual DWORD
	 * the id map is present
	 */
	while ((id - adjust_ix) >= map_entry_size) {
		map_index++;
		adjust_ix = map_index * map_entry_size;
	}
	wlan_psoc_obj_lock(psoc);
	objmgr = &psoc->soc_objmgr;
	/* unset bit, to free the slot */
	objmgr->wlan_vdev_id_map[map_index] &= ~(1<<(id-adjust_ix));
	/* reset VDEV pointer to NULL in VDEV list array */
	objmgr->wlan_vdev_list[id] = NULL;
	/* decrement vdev count */
	objmgr->wlan_vdev_count--;
	vdev->vdev_objmgr.vdev_id = 0xff;
	wlan_psoc_obj_unlock(psoc);

	return QDF_STATUS_SUCCESS;
}

struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_opmode_from_psoc(
			struct wlan_objmgr_psoc *psoc,
			enum QDF_OPMODE opmode,
			wlan_objmgr_ref_dbgid dbg_id)
{
	struct wlan_objmgr_vdev *vdev = NULL;
	int vdev_cnt = 0;
	uint16_t max_vdev_cnt;

	/* if PSOC is NULL, return */
	if (psoc == NULL)
		return NULL;

	wlan_psoc_obj_lock(psoc);

	max_vdev_cnt = wlan_psoc_get_max_vdev_count(psoc);
	/* retrieve vdev pointer from vdev list */
	while (vdev_cnt < max_vdev_cnt) {
		vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_cnt];
		vdev_cnt++;
		if (vdev == NULL)
			continue;
		wlan_vdev_obj_lock(vdev);
		if (vdev->vdev_mlme.vdev_opmode == opmode) {
			wlan_vdev_obj_unlock(vdev);
			if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) !=
							QDF_STATUS_SUCCESS) {
				vdev = NULL;
				continue;
			}
			break;
		}
		wlan_vdev_obj_unlock(vdev);
	}
	wlan_psoc_obj_unlock(psoc);

	return vdev;
}

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_psoc_get_max_vdev_count(psoc))
		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;
}
qdf_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;

	/* if PSOC is NULL, return */
	if (psoc == NULL)
		return NULL;
	/* vdev id is invalid */
	if (vdev_id >= wlan_psoc_get_max_vdev_count(psoc))
		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)
		wlan_objmgr_vdev_get_ref(vdev, dbg_id);

	wlan_psoc_obj_unlock(psoc);

	return vdev;
}
qdf_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;
	uint16_t max_vdev_cnt;

	/* if PSOC is NULL, return */
	if (psoc == NULL)
		return NULL;

	wlan_psoc_obj_lock(psoc);
	max_vdev_cnt = wlan_psoc_get_max_vdev_count(psoc);
	/* Iterate through PSOC's vdev list */
	for (id = 0; id < max_vdev_cnt; 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;
}
qdf_export_symbol(wlan_objmgr_get_vdev_by_macaddr_from_psoc);

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;
	uint16_t max_vdev_cnt;

	/* if PSOC is NULL, return */
	if (psoc == NULL)
		return NULL;

	wlan_psoc_obj_lock(psoc);
	max_vdev_cnt = wlan_psoc_get_max_vdev_count(psoc);
	/* Iterate through PSOC's vdev list */
	for (id = 0; id < max_vdev_cnt; 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) {
			wlan_objmgr_vdev_get_ref(vdev, dbg_id);
			wlan_psoc_obj_unlock(psoc);

			return vdev;
		}
	}
	wlan_psoc_obj_unlock(psoc);

	return NULL;
}
qdf_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)
{
	qdf_list_insert_back(obj_list, &obj->psoc_peer);
}

static QDF_STATUS wlan_obj_psoc_peerlist_remove_peer(
				qdf_list_t *obj_list,
				struct wlan_objmgr_peer *peer)
{
	qdf_list_node_t *psoc_node = NULL;

	if (peer == NULL)
		return QDF_STATUS_E_FAILURE;
	/* get vdev list node element */
	psoc_node = &peer->psoc_peer;
	/* list is empty, return failure */
	if (qdf_list_remove_node(obj_list, psoc_node) != QDF_STATUS_SUCCESS)
		return QDF_STATUS_E_FAILURE;

	return QDF_STATUS_SUCCESS;
}

static QDF_STATUS wlan_peer_bssid_match(struct wlan_objmgr_peer *peer,
				     uint8_t *bssid)
{
	struct wlan_objmgr_vdev *vdev = wlan_peer_get_vdev(peer);
	uint8_t *peer_bssid = wlan_vdev_mlme_get_macaddr(vdev);

	if (WLAN_ADDR_EQ(peer_bssid, bssid) == QDF_STATUS_SUCCESS)
		return QDF_STATUS_SUCCESS;
	else
		return QDF_STATUS_E_FAILURE;
}

/**
 * wlan_obj_psoc_peerlist_get_peer_logically_deleted() - get peer
 * from psoc peer list
 * @psoc: PSOC object
 * @macaddr: MAC address
 *
 * API to finds peer object pointer of logically deleted peer
 *
 * Return: peer pointer
 *         NULL on FAILURE
 */
static struct wlan_objmgr_peer *
			wlan_obj_psoc_peerlist_get_peer_logically_deleted(
				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) {
			/* Return peer in logically deleted state */
			if (peer->obj_state ==
					WLAN_OBJ_STATE_LOGICALLY_DELETED) {
				wlan_objmgr_peer_get_ref(peer, dbg_id);

				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;
}

/**
 * wlan_obj_psoc_peerlist_get_peer() - get peer from psoc peer list
 * @psoc: PSOC object
 * @macaddr: MAC address
 *
 * API to finds peer object pointer by MAC addr from hash list
 *
 * Return: peer pointer
 *         NULL on FAILURE
 */
static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer(
				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) {
			if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
							QDF_STATUS_SUCCESS) {
				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 */
		peer_temp = peer;
		peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp);
	}

	/* Not found, return NULL */
	return NULL;
}

/**
 * wlan_obj_psoc_populate_logically_del_peerlist_by_mac_n_bssid() - get peer
 *                                           from psoc peer list using
 *                                           mac and vdev self mac
 * @obj_list: peer object list
 * @macaddr: MAC address
 * @bssid: BSSID address
 * @dbg_id: id of the caller
 *
 * API to finds peer object pointer by MAC addr and BSSID from
 * peer hash list for a node which is in logically deleted state,
 * bssid check is done on matching peer
 *
 * Caller to free the list allocated in this function
 *
 * Return: list of peer pointers
 *         NULL on FAILURE
 */
static qdf_list_t
	*wlan_obj_psoc_populate_logically_del_peerlist_by_mac_n_bssid(
				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;
	struct wlan_logically_del_peer *peer_list = NULL;
	qdf_list_t *logical_del_peer_list = NULL;
	bool lock_released = false;

	logical_del_peer_list = qdf_mem_malloc(sizeof(*logical_del_peer_list));
	if (!logical_del_peer_list) {
		obj_mgr_err("failed to allocate list");
		return NULL;
	}

	qdf_list_create(logical_del_peer_list, WLAN_UMAC_PSOC_MAX_PEERS);

	/* Iterate through hash list to get the peer */
	peer = wlan_psoc_peer_list_peek_head(obj_list);
	while (peer != NULL) {
		wlan_peer_obj_lock(peer);
		/* For peer, macaddr is key */
		if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr)
			== QDF_STATUS_SUCCESS) {
			/*
			 *  if BSSID not NULL,
			 *  then match is requested by caller, check BSSID
			 *  (vdev mac == bssid) --  return peer
			 *  (vdev mac != bssid) --  perform next iteration
			 */
			if ((bssid == NULL) ||
				(wlan_peer_bssid_match(peer, bssid) ==
				 QDF_STATUS_SUCCESS)) {
				/* Return peer in logically deleted state */
				if ((peer->obj_state ==
					WLAN_OBJ_STATE_LOGICALLY_DELETED) &&
				     qdf_atomic_read(
						&peer->peer_objmgr.ref_cnt)) {

					wlan_objmgr_peer_get_ref(peer, dbg_id);
					wlan_peer_obj_unlock(peer);
					lock_released = true;

					peer_list =
					qdf_mem_malloc(
					sizeof(struct wlan_logically_del_peer));
					if (peer_list == NULL) {
						/* Lock is already released */
						obj_mgr_err("Mem alloc failed");
						break;
					}

					peer_list->peer = peer;

					qdf_list_insert_front(
						logical_del_peer_list,
							&peer_list->list);
				}
			}
		}

		if (!lock_released)
			wlan_peer_obj_unlock(peer);

		/* Move to next peer */
		peer_temp = peer;
		peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp);
		lock_released = false;
	}

	/* Not found, return NULL */
	if (qdf_list_empty(logical_del_peer_list)) {
		qdf_mem_free(logical_del_peer_list);
		return NULL;
	} else {
		return logical_del_peer_list;
	}

}

/**
 * wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid() - get peer from psoc peer
 *                                                    list using mac and vdev
 *                                                    self mac
 * @psoc: PSOC object
 * @macaddr: MAC address
 * @bssid: BSSID address
 *
 * API to finds peer object pointer by MAC addr and BSSID from
 * peer hash list, bssid check is done on matching peer
 *
 * Return: peer pointer
 *         NULL on FAILURE
 */
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,
					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) {
				if (wlan_objmgr_peer_try_get_ref(peer, dbg_id)
					== QDF_STATUS_SUCCESS) {
					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;
			}
		}
		/* 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;
}

QDF_STATUS wlan_objmgr_psoc_peer_attach(struct wlan_objmgr_psoc *psoc,
					 struct wlan_objmgr_peer *peer)
{
	struct wlan_objmgr_psoc_objmgr *objmgr;
	uint8_t hash_index;
	struct wlan_peer_list *peer_list;

	wlan_psoc_obj_lock(psoc);
	objmgr = &psoc->soc_objmgr;
	/* Max peer limit is reached, return failure */
	if (objmgr->wlan_peer_count >= wlan_psoc_get_max_peer_count(psoc)) {
		wlan_psoc_obj_unlock(psoc);
		return QDF_STATUS_E_FAILURE;
	}
	/* Derive hash index from mac address */
	hash_index = WLAN_PEER_HASH(peer->macaddr);
	peer_list = &objmgr->peer_list;
	/* psoc lock should be taken before list lock */
	qdf_spin_lock_bh(&peer_list->peer_list_lock);
	/* add peer to hash peer list */
	wlan_obj_psoc_peerlist_add_tail(
			&peer_list->peer_hash[hash_index],
							peer);
	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
	/* Increment peer count */
	objmgr->wlan_peer_count++;
	wlan_psoc_obj_unlock(psoc);

	return QDF_STATUS_SUCCESS;
}

QDF_STATUS wlan_objmgr_psoc_peer_detach(struct wlan_objmgr_psoc *psoc,
						struct wlan_objmgr_peer *peer)
{
	struct wlan_objmgr_psoc_objmgr *objmgr;
	uint8_t hash_index;
	struct wlan_peer_list *peer_list;

	wlan_psoc_obj_lock(psoc);
	objmgr = &psoc->soc_objmgr;
	/* if list is empty, return */
	if (objmgr->wlan_peer_count == 0) {
		wlan_psoc_obj_unlock(psoc);
		return QDF_STATUS_E_FAILURE;
	}
	/* Get hash index, to locate the actual peer list */
	hash_index = WLAN_PEER_HASH(peer->macaddr);
	peer_list = &objmgr->peer_list;
	/* psoc lock should be taken before list lock */
	qdf_spin_lock_bh(&peer_list->peer_list_lock);
	/* removes the peer from peer_list */
	if (wlan_obj_psoc_peerlist_remove_peer(
				&peer_list->peer_hash[hash_index],
						peer) ==
				QDF_STATUS_E_FAILURE) {
		qdf_spin_unlock_bh(&peer_list->peer_list_lock);
		wlan_psoc_obj_unlock(psoc);
		obj_mgr_err("Failed to detach peer");
		return QDF_STATUS_E_FAILURE;
	}
	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
	/* Decrement peer count */
	objmgr->wlan_peer_count--;
	wlan_psoc_obj_unlock(psoc);

	return QDF_STATUS_SUCCESS;
}

struct wlan_objmgr_peer *wlan_objmgr_get_peer_logically_deleted(
			struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
			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_logically_deleted(
		&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;
}

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;
	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(
		&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;
}
qdf_export_symbol(wlan_objmgr_get_peer);

struct wlan_objmgr_peer *wlan_objmgr_get_peer_nolock(
			struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
			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 */
	objmgr = &psoc->soc_objmgr;
	/* List is empty, return NULL */
	if (objmgr->wlan_peer_count == 0)
		return NULL;

	/* reduce the search window, with hash key */
	hash_index = WLAN_PEER_HASH(macaddr);
	peer_list = &objmgr->peer_list;
	/* Iterate through peer list, get peer */
	peer = wlan_obj_psoc_peerlist_get_peer(
		&peer_list->peer_hash[hash_index], macaddr, dbg_id);

	return peer;
}
qdf_export_symbol(wlan_objmgr_get_peer_nolock);


struct wlan_objmgr_peer *wlan_objmgr_get_peer_no_state(
			struct wlan_objmgr_psoc *psoc, uint8_t *macaddr,
			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;
}
qdf_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;
	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(
		&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;
}
qdf_export_symbol(wlan_objmgr_get_peer_by_mac_n_vdev);


/**
 * wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev() - get peer from psoc
 *                                                           peer list using
 *                                                           mac and vdev
 *                                                           self mac
 * @psoc: PSOC object
 * @macaddr: MAC address
 * @bssid: BSSID address. NULL mac means search all.
 * @dbg_id: id of the caller
 *
 * API to finds peer object pointer by MAC addr and BSSID from
 * peer hash list, bssid check is done on matching peer
 *
 * Return: list of peer pointer pointers
 *         NULL on FAILURE
 */

qdf_list_t *wlan_objmgr_populate_logically_deleted_peerlist_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;
	struct wlan_peer_list *peer_list = NULL;
	qdf_list_t *logical_del_peer_list = NULL;

	/* 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 */
	logical_del_peer_list =
		wlan_obj_psoc_populate_logically_del_peerlist_by_mac_n_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 logical_del_peer_list;
}
qdf_export_symbol(wlan_objmgr_populate_logically_deleted_peerlist_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;
}
qdf_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)
{
	void *comp_private_obj;

	/* component id is invalid */
	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
		QDF_BUG(0);
		return NULL;
	}

	if (psoc == NULL) {
		QDF_BUG(0);
		return NULL;
	}

	comp_private_obj = psoc->soc_comp_priv_obj[id];

	return comp_private_obj;
}
qdf_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) {
		obj_mgr_err("psoc obj is NULL for id:%d", id);
		QDF_ASSERT(0);
		return;
	}
	/* Increment ref count */
	qdf_atomic_inc(&psoc->soc_objmgr.ref_cnt);
	qdf_atomic_inc(&psoc->soc_objmgr.ref_id_dbg[id]);
	return;
}
qdf_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) {
		obj_mgr_err("psoc obj is NULL for id:%d", id);
		QDF_ASSERT(0);
		return QDF_STATUS_E_FAILURE;
	}

	wlan_psoc_obj_lock(psoc);
	if (psoc->obj_state != WLAN_OBJ_STATE_CREATED) {
		wlan_psoc_obj_unlock(psoc);
		if (psoc->soc_objmgr.print_cnt++ <=
				WLAN_OBJMGR_RATELIMIT_THRESH)
			obj_mgr_err(
			"[Ref id: %d] psoc is not in Created state(%d)",
					id, psoc->obj_state);

		return QDF_STATUS_E_RESOURCES;
	}

	/* Increment ref count */
	wlan_objmgr_psoc_get_ref(psoc, id);
	wlan_psoc_obj_unlock(psoc);

	return QDF_STATUS_SUCCESS;
}
qdf_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) {
		obj_mgr_err("psoc obj is NULL for id:%d", id);
		QDF_ASSERT(0);
		return;
	}

	if (!qdf_atomic_read(&psoc->soc_objmgr.ref_id_dbg[id])) {
		obj_mgr_err("psoc ref cnt was not taken by %d", id);
		wlan_objmgr_print_ref_ids(psoc->soc_objmgr.ref_id_dbg);
		WLAN_OBJMGR_BUG(0);
	}

	if (!qdf_atomic_read(&psoc->soc_objmgr.ref_cnt)) {
		obj_mgr_err("psoc ref cnt is 0");
		WLAN_OBJMGR_BUG(0);
		return;
	}

	qdf_atomic_dec(&psoc->soc_objmgr.ref_id_dbg[id]);
	/* 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;
}
qdf_export_symbol(wlan_objmgr_psoc_release_ref);

static void wlan_objmgr_psoc_peer_ref_print(struct wlan_objmgr_psoc *psoc,
					 void *obj, void *args)
{
	struct wlan_objmgr_peer *peer = (struct wlan_objmgr_peer *)obj;
	uint8_t *macaddr;

	wlan_peer_obj_lock(peer);
	macaddr = wlan_peer_get_macaddr(peer);
	wlan_peer_obj_unlock(peer);

	obj_mgr_info("Peer MAC is %02x:%02x:%02x:%02x:%02x:%02x",
		  macaddr[0], macaddr[1], macaddr[2], macaddr[3],
		  macaddr[4], macaddr[5]);
	wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg);
}

static void wlan_objmgr_psoc_vdev_ref_print(struct wlan_objmgr_psoc *psoc,
					 void *obj, void *args)
{
	struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)obj;
	uint8_t id;

	wlan_vdev_obj_lock(vdev);
	id = wlan_vdev_get_id(vdev);
	wlan_vdev_obj_unlock(vdev);
	obj_mgr_info("Vdev ID is %d", id);

	wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg);
}

static void wlan_objmgr_psoc_pdev_ref_print(struct wlan_objmgr_psoc *psoc,
					 void *obj, void *args)
{
	struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj;
	uint8_t id;

	wlan_pdev_obj_lock(pdev);
	id = wlan_objmgr_pdev_get_pdev_id(pdev);
	wlan_pdev_obj_unlock(pdev);
	obj_mgr_info("pdev ID is %d", id);

	wlan_objmgr_print_ref_ids(pdev->pdev_objmgr.ref_id_dbg);
}

QDF_STATUS wlan_objmgr_print_ref_all_objects_per_psoc(
		struct wlan_objmgr_psoc *psoc)
{
	obj_mgr_info("Ref counts of PEER");
	wlan_objmgr_iterate_obj_list_all_noref(psoc, WLAN_PEER_OP,
				wlan_objmgr_psoc_peer_ref_print, NULL);
	obj_mgr_info("Ref counts of VDEV");
	wlan_objmgr_iterate_obj_list_all_noref(psoc, WLAN_VDEV_OP,
				wlan_objmgr_psoc_vdev_ref_print, NULL);
	obj_mgr_info("Ref counts of PDEV");
	wlan_objmgr_iterate_obj_list_all_noref(psoc, WLAN_PDEV_OP,
				wlan_objmgr_psoc_pdev_ref_print, NULL);

	obj_mgr_info(" Ref counts of PSOC");
	wlan_objmgr_print_ref_ids(psoc->soc_objmgr.ref_id_dbg);

	return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(wlan_objmgr_print_ref_all_objects_per_psoc);

QDF_STATUS wlan_objmgr_psoc_set_user_config(struct wlan_objmgr_psoc *psoc,
		struct wlan_objmgr_psoc_user_config *user_config_data)
{
	if (user_config_data == NULL) {
		obj_mgr_err("user_config_data is NULL");
		QDF_BUG(0);
		return QDF_STATUS_E_FAILURE;
	}
	wlan_psoc_obj_lock(psoc);
	qdf_mem_copy(&psoc->soc_nif.user_config, user_config_data,
		     sizeof(psoc->soc_nif.user_config));
	wlan_psoc_obj_unlock(psoc);

	return QDF_STATUS_SUCCESS;
}
