/*
 * Copyright (c) 2016-2019 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_module.h>
#include "wlan_objmgr_global_obj_i.h"
#include "wlan_objmgr_psoc_obj_i.h"
#include "wlan_objmgr_pdev_obj_i.h"
#include "wlan_objmgr_vdev_obj_i.h"

/**
 ** APIs to Create/Delete Global object APIs
 */

static QDF_STATUS wlan_objmgr_vdev_object_status(
		struct wlan_objmgr_vdev *vdev)
{
	uint8_t id;
	QDF_STATUS status = QDF_STATUS_SUCCESS;

	wlan_vdev_obj_lock(vdev);

	/* Iterate through all components to derive the object status */
	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
		/* If component disabled, Ignore */
		if (vdev->obj_status[id] == QDF_STATUS_COMP_DISABLED) {
			continue;
		/*
		 * If component operates in Async, status is Partially created,
		 * break
		 */
		} else if (vdev->obj_status[id] == QDF_STATUS_COMP_ASYNC) {
			if (!vdev->vdev_comp_priv_obj[id]) {
				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 ((vdev->obj_status[id] == QDF_STATUS_E_NOMEM) ||
			(vdev->obj_status[id] == QDF_STATUS_E_FAILURE)) {
			status = QDF_STATUS_E_FAILURE;
			break;
		}
	}
	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;
	struct wlan_objmgr_psoc *psoc;

	if (!vdev) {
		obj_mgr_err("vdev is NULL");
		return QDF_STATUS_E_FAILURE;
	}
	/* if PDEV is NULL, return */
	pdev = wlan_vdev_get_pdev(vdev);
	if (!pdev) {
		obj_mgr_err("pdev is NULL for vdev-id: %d",
			vdev->vdev_objmgr.vdev_id);
		return QDF_STATUS_E_FAILURE;
	}
	psoc = wlan_pdev_get_psoc(pdev);
	if (!psoc) {
		obj_mgr_err("psoc is NULL in pdev");
		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(psoc, vdev) ==
					 QDF_STATUS_E_FAILURE)
		return QDF_STATUS_E_FAILURE;

	qdf_spinlock_destroy(&vdev->vdev_lock);

	qdf_mem_free(vdev->vdev_mlme.bss_chan);
	qdf_mem_free(vdev->vdev_mlme.des_chan);
	qdf_mem_free(vdev->vdev_nif.osdev);
	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)
{
	struct wlan_objmgr_vdev *vdev;
	struct wlan_objmgr_psoc *psoc;
	uint8_t id;
	wlan_objmgr_vdev_create_handler handler;
	wlan_objmgr_vdev_status_handler stat_handler;
	void *arg;
	QDF_STATUS obj_status;

	if (!pdev) {
		obj_mgr_err("pdev is NULL");
		return NULL;
	}
	psoc = wlan_pdev_get_psoc(pdev);
	/* PSOC is NULL */
	if (!psoc) {
		obj_mgr_err("psoc is NULL for pdev-id:%d",
			pdev->pdev_objmgr.wlan_pdev_id);
		return NULL;
	}
	/* Allocate vdev object memory */
	vdev = qdf_mem_malloc(sizeof(*vdev));
	if (!vdev)
		return NULL;

	vdev->obj_state = WLAN_OBJ_STATE_ALLOCATED;

	vdev->vdev_mlme.bss_chan = qdf_mem_malloc(sizeof(struct wlan_channel));
	if (!vdev->vdev_mlme.bss_chan) {
		qdf_mem_free(vdev);
		return NULL;
	}

	vdev->vdev_mlme.des_chan = qdf_mem_malloc(sizeof(struct wlan_channel));
	if (!vdev->vdev_mlme.des_chan) {
		qdf_mem_free(vdev->vdev_mlme.bss_chan);
		qdf_mem_free(vdev);
		return NULL;
	}

	/* Initialize spinlock */
	qdf_spinlock_create(&vdev->vdev_lock);
	/* Attach VDEV to PSOC VDEV's list */
	if (wlan_objmgr_psoc_vdev_attach(psoc, vdev) !=
				QDF_STATUS_SUCCESS) {
		obj_mgr_err("psoc vdev attach failed for vdev-id:%d",
					vdev->vdev_objmgr.vdev_id);
		qdf_mem_free(vdev->vdev_mlme.bss_chan);
		qdf_mem_free(vdev->vdev_mlme.des_chan);
		qdf_spinlock_destroy(&vdev->vdev_lock);
		qdf_mem_free(vdev);
		return NULL;
	}
	/* Store pdev in vdev */
	wlan_vdev_set_pdev(vdev, pdev);
	/* Attach vdev to PDEV */
	if (wlan_objmgr_pdev_vdev_attach(pdev, vdev) !=
				QDF_STATUS_SUCCESS) {
		obj_mgr_err("pdev vdev attach failed for vdev-id:%d",
				vdev->vdev_objmgr.vdev_id);
		wlan_objmgr_psoc_vdev_detach(psoc, vdev);
		qdf_mem_free(vdev->vdev_mlme.bss_chan);
		qdf_mem_free(vdev->vdev_mlme.des_chan);
		qdf_spinlock_destroy(&vdev->vdev_lock);
		qdf_mem_free(vdev);
		return NULL;
	}
	/* set opmode */
	wlan_vdev_mlme_set_opmode(vdev, params->opmode);
	/* set MAC address */
	wlan_vdev_mlme_set_macaddr(vdev, params->macaddr);
	/* set MAT address */
	wlan_vdev_mlme_set_mataddr(vdev, params->mataddr);
	/* Set create flags */
	vdev->vdev_objmgr.c_flags = params->flags;
	/* store os-specific pointer */
	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);
	vdev->vdev_objmgr.print_cnt = 0;
	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;
	else
		vdev->vdev_objmgr.max_peer_count =
				wlan_pdev_get_max_peer_count(pdev);

	/* Initialize peer list */
	qdf_list_create(&vdev->vdev_objmgr.wlan_peer_list,
			vdev->vdev_objmgr.max_peer_count +
			WLAN_MAX_PDEV_TEMP_PEERS);
	/* TODO init other parameters */

	/* Invoke registered create handlers */
	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
		handler = g_umac_glb_obj->vdev_create_handler[id];
		arg = g_umac_glb_obj->vdev_create_handler_arg[id];
		if (handler)
			vdev->obj_status[id] = handler(vdev, arg);
		else
			vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED;
	}

	/* Derive object status */
	obj_status = wlan_objmgr_vdev_object_status(vdev);

	if (obj_status == QDF_STATUS_SUCCESS) {
		/* Object status is SUCCESS, Object is created */
		vdev->obj_state = WLAN_OBJ_STATE_CREATED;
		/* Invoke component registered status handlers */
		for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
			stat_handler = g_umac_glb_obj->vdev_status_handler[id];
			arg = g_umac_glb_obj->vdev_status_handler_arg[id];
			if (stat_handler) {
				stat_handler(vdev, arg,
					     QDF_STATUS_SUCCESS);
			}
		}
	/*
	 * Few components operates in Asynchrous communction, Object state
	 * partially created
	 */
	} else if (obj_status == QDF_STATUS_COMP_ASYNC) {
		vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
	/* Component object failed to be created, clean up the object */
	} else if (obj_status == QDF_STATUS_E_FAILURE) {
		/* Clean up the psoc */
		wlan_objmgr_vdev_obj_delete(vdev);
		obj_mgr_err("VDEV comp objects creation failed for vdev-id:%d",
			vdev->vdev_objmgr.vdev_id);
		/*
		 * Set params osifp to NULL as it is freed during vdev obj
		 * delete, This prevents caller from performing double free.
		 */
		params->osifp = NULL;
		return NULL;
	}

	obj_mgr_info("Created vdev %d", vdev->vdev_objmgr.vdev_id);

	return vdev;
}
qdf_export_symbol(wlan_objmgr_vdev_obj_create);

static QDF_STATUS wlan_objmgr_vdev_obj_destroy(struct wlan_objmgr_vdev *vdev)
{
	uint8_t id;
	wlan_objmgr_vdev_destroy_handler handler;
	QDF_STATUS obj_status;
	void *arg;
	uint8_t vdev_id;

	if (!vdev) {
		obj_mgr_err("vdev is NULL");
		return QDF_STATUS_E_FAILURE;
	}
	wlan_objmgr_notify_destroy(vdev, WLAN_VDEV_OP);

	vdev_id = wlan_vdev_get_id(vdev);

	wlan_print_vdev_info(vdev);
	obj_mgr_debug("Physically deleting vdev %d", vdev_id);

	if (vdev->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) {
		obj_mgr_err("VDEV object delete is not invoked vdevid:%d objstate:%d",
			    wlan_vdev_get_id(vdev), vdev->obj_state);
		WLAN_OBJMGR_BUG(0);
	}

	/* Invoke registered destroy handlers */
	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
		handler = g_umac_glb_obj->vdev_destroy_handler[id];
		arg = g_umac_glb_obj->vdev_destroy_handler_arg[id];
		if (handler &&
		    (vdev->obj_status[id] == QDF_STATUS_SUCCESS ||
		     vdev->obj_status[id] == QDF_STATUS_COMP_ASYNC))
			vdev->obj_status[id] = handler(vdev, arg);
		else
			vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED;
	}
	/* Derive object status */
	obj_status = wlan_objmgr_vdev_object_status(vdev);

	if (obj_status == QDF_STATUS_E_FAILURE) {
		obj_mgr_err("VDEV object deletion failed: vdev-id: %d",
				vdev_id);
		/* Ideally should not happen */
		/* This leads to memleak ??? how to handle */
		QDF_BUG(0);
		return QDF_STATUS_E_FAILURE;
	}

	/* Deletion is in progress */
	if (obj_status == QDF_STATUS_COMP_ASYNC) {
		vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED;
		return QDF_STATUS_COMP_ASYNC;
	}

	/* Free VDEV object */
	return wlan_objmgr_vdev_obj_free(vdev);
}

QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev)
{
	uint8_t print_idx;

	if (!vdev) {
		obj_mgr_err("vdev is NULL");
		return QDF_STATUS_E_FAILURE;
	}

	obj_mgr_info("Logically deleting vdev %d", vdev->vdev_objmgr.vdev_id);

	print_idx = qdf_get_pidx();
	wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg,
				  QDF_TRACE_LEVEL_DEBUG);
	/*
	 * 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_notify_log_delete(vdev, WLAN_VDEV_OP);
	wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);

	return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(wlan_objmgr_vdev_obj_delete);

/**
 ** APIs to attach/detach component objects
 */
QDF_STATUS wlan_objmgr_vdev_component_obj_attach(
		struct wlan_objmgr_vdev *vdev,
		enum wlan_umac_comp_id id,
		void *comp_priv_obj,
		QDF_STATUS status)
{
	wlan_objmgr_vdev_status_handler stat_handler;
	void *arg;
	uint8_t i;
	QDF_STATUS obj_status;

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

	wlan_vdev_obj_lock(vdev);
	/* If there is a valid entry, return failure */
	if (vdev->vdev_comp_priv_obj[id]) {
		wlan_vdev_obj_unlock(vdev);
		return QDF_STATUS_E_FAILURE;
	}
	/* Save component's pointer and status */
	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;
	/*
	 * If VDEV 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_vdev_object_status(vdev);
	/* STATUS_SUCCESS means, object is CREATED */
	if (obj_status == QDF_STATUS_SUCCESS)
		vdev->obj_state = WLAN_OBJ_STATE_CREATED;
	/*
	 * update state as CREATION failed, caller has to delete the
	 * VDEV object
	 */
	else if (obj_status == QDF_STATUS_E_FAILURE)
		vdev->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)) {
		for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) {
			stat_handler = g_umac_glb_obj->vdev_status_handler[i];
			arg = g_umac_glb_obj->vdev_status_handler_arg[i];
			if (stat_handler)
				stat_handler(vdev, arg, obj_status);
		}
	}
	return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(wlan_objmgr_vdev_component_obj_attach);

QDF_STATUS wlan_objmgr_vdev_component_obj_detach(
		struct wlan_objmgr_vdev *vdev,
		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_vdev_obj_lock(vdev);
	/* If there is a valid entry, return failure */
	if (vdev->vdev_comp_priv_obj[id] != comp_priv_obj) {
		vdev->obj_status[id] = QDF_STATUS_E_FAILURE;
		wlan_vdev_obj_unlock(vdev);
		return QDF_STATUS_E_FAILURE;
	}
	/* Reset pointers to NULL, update the status*/
	vdev->vdev_comp_priv_obj[id] = NULL;
	vdev->obj_status[id] = QDF_STATUS_SUCCESS;
	wlan_vdev_obj_unlock(vdev);

	/**
	 *If VDEV object status is partially destroyed means, this API is
	 * invoked with differnt context, this block should be executed for
	 * async components only
	 */
	if ((vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) ||
	    (vdev->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) {
		/* Derive object status */
		obj_status = wlan_objmgr_vdev_object_status(vdev);
		if (obj_status == QDF_STATUS_SUCCESS) {
			/*
			 * Update the status as Deleted, if full object
			 * deletion is in progress
			 */
			if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
				vdev->obj_state = WLAN_OBJ_STATE_DELETED;
			/*
			 * Move to creation state, since this component
			 * deletion alone requested
			 */
			else if (vdev->obj_state ==
					WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
				vdev->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 (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
				vdev->obj_state =
					WLAN_OBJ_STATE_DELETION_FAILED;
			/* Move to creation state, since this component
			deletion alone requested (do not block other
			components) */
			else if (vdev->obj_state ==
					WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
				vdev->obj_state = WLAN_OBJ_STATE_CREATED;
		}
		/* Delete vdev object */
		if ((obj_status == QDF_STATUS_SUCCESS)  &&
		    (vdev->obj_state == WLAN_OBJ_STATE_DELETED)) {
			/* Free VDEV object */
			return wlan_objmgr_vdev_obj_free(vdev);
		}
	}
	return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(wlan_objmgr_vdev_component_obj_detach);

/**
 ** APIs to operations on vdev objects
 */
QDF_STATUS wlan_objmgr_iterate_peerobj_list(
		struct wlan_objmgr_vdev *vdev,
		wlan_objmgr_vdev_op_handler handler,
		void *arg, wlan_objmgr_ref_dbgid dbg_id)
{
	qdf_list_t *peer_list = NULL;
	struct wlan_objmgr_peer *peer = NULL;
	struct wlan_objmgr_peer *peer_next = NULL;
	uint8_t vdev_id;

	if (!vdev) {
		obj_mgr_err("VDEV is NULL");
		return QDF_STATUS_E_FAILURE;
	}
	wlan_vdev_obj_lock(vdev);
	vdev_id = wlan_vdev_get_id(vdev);

	if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) {
		wlan_vdev_obj_unlock(vdev);
		obj_mgr_err("VDEV is not in create state(:%d): vdev-id:%d",
				vdev_id, vdev->obj_state);
		return QDF_STATUS_E_FAILURE;
	}
	wlan_objmgr_vdev_get_ref(vdev, dbg_id);
	peer_list = &vdev->vdev_objmgr.wlan_peer_list;
	if (peer_list) {
		/* Iterate through VDEV's peer list */
		peer = wlan_vdev_peer_list_peek_head(peer_list);
		while (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);
	return QDF_STATUS_SUCCESS;
}

/**
 * wlan_obj_vdev_populate_logically_del_peerlist() - get peer
 * from vdev peer list
 * @obj_list: peer object list
 * @vdev_obj: vdev object mgr substructure
 * @dbg_id: id of the caller
 *
 * API to finds peer object pointer by vdev from peer hash list for a node
 * which is in logically deleted state
 *
 * Caller to free the list allocated in this function
 *
 * Return: list of peer pointers
 *         NULL on FAILURE
 */
static qdf_list_t *wlan_obj_vdev_populate_logically_del_peerlist(
				qdf_list_t *obj_list,
				struct wlan_objmgr_vdev_objmgr *vdev_obj,
				wlan_objmgr_ref_dbgid dbg_id)
{
	struct wlan_objmgr_peer *peer;
	struct wlan_objmgr_peer *peer_next;
	struct wlan_logically_del_peer *peer_list;
	qdf_list_t *logical_del_peerlist;
	bool lock_released = false;

	logical_del_peerlist = qdf_mem_malloc(sizeof(*logical_del_peerlist));
	if (!logical_del_peerlist)
		return NULL;

	qdf_list_create(logical_del_peerlist, vdev_obj->max_peer_count);

	peer = wlan_vdev_peer_list_peek_head(obj_list);
	while (peer) {
		wlan_peer_obj_lock(peer);
		peer_next = wlan_peer_get_next_peer_of_vdev(obj_list, peer);
		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(*peer_list));
			if (!peer_list) {
				wlan_objmgr_peer_release_ref(peer, dbg_id);
				WLAN_OBJMGR_BUG(0);
				break;
			}

			peer_list->peer = peer;
			qdf_list_insert_front(logical_del_peerlist,
					      &peer_list->list);
		}

		if (!lock_released)
			wlan_peer_obj_unlock(peer);

		peer = peer_next;
		lock_released = false;
	}

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

	return logical_del_peerlist;
}

qdf_list_t *wlan_objmgr_vdev_get_log_del_peer_list(
		struct wlan_objmgr_vdev *vdev,
		wlan_objmgr_ref_dbgid dbg_id)
{
	qdf_list_t *peer_list;
	qdf_list_t *log_del_peer_list = NULL;

	if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) {
		obj_mgr_err("Invalid state vdev:%d state:%d",
			    wlan_vdev_get_id(vdev), vdev->obj_state);
		return NULL;
	}

	wlan_vdev_obj_lock(vdev);
	if (vdev->vdev_objmgr.wlan_peer_count == 0) {
		wlan_vdev_obj_unlock(vdev);
		return NULL;
	}

	wlan_objmgr_vdev_get_ref(vdev, dbg_id);
	peer_list = &vdev->vdev_objmgr.wlan_peer_list;
	if (peer_list) {
		log_del_peer_list =
			wlan_obj_vdev_populate_logically_del_peerlist(
					peer_list, &vdev->vdev_objmgr,
					dbg_id);
	}

	wlan_objmgr_vdev_release_ref(vdev, dbg_id);
	wlan_vdev_obj_unlock(vdev);

	return log_del_peer_list;
}

QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_creation(
		struct wlan_objmgr_vdev *vdev,
		enum wlan_umac_comp_id id)
{
	wlan_objmgr_vdev_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_vdev_obj_lock(vdev);
	/*
	 * If component object is already created, delete old
	 * component object, then invoke creation
	 */
	if (vdev->vdev_comp_priv_obj[id]) {
		wlan_vdev_obj_unlock(vdev);
		return QDF_STATUS_E_FAILURE;
	}
	wlan_vdev_obj_unlock(vdev);

	/* Invoke registered create handlers */
	handler = g_umac_glb_obj->vdev_create_handler[id];
	arg = g_umac_glb_obj->vdev_create_handler_arg[id];
	if (handler)
		vdev->obj_status[id] = handler(vdev, arg);
	else
		return QDF_STATUS_E_FAILURE;

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

QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_deletion(
		struct wlan_objmgr_vdev *vdev,
		enum wlan_umac_comp_id id)
{
	wlan_objmgr_vdev_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_vdev_obj_lock(vdev);
	/* Component object was never created, invalid operation */
	if (!vdev->vdev_comp_priv_obj[id]) {
		wlan_vdev_obj_unlock(vdev);
		return QDF_STATUS_E_FAILURE;
	}
	wlan_vdev_obj_unlock(vdev);

	/* Invoke registered create handlers */
	handler = g_umac_glb_obj->vdev_destroy_handler[id];
	arg = g_umac_glb_obj->vdev_destroy_handler_arg[id];
	if (handler)
		vdev->obj_status[id] = handler(vdev, arg);
	else
		return QDF_STATUS_E_FAILURE;

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



static void wlan_obj_vdev_peerlist_add_tail(qdf_list_t *obj_list,
	struct wlan_objmgr_peer *obj)
{
	qdf_list_insert_back(obj_list, &obj->vdev_peer);
}

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

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

	return QDF_STATUS_SUCCESS;
}

QDF_STATUS wlan_objmgr_vdev_peer_attach(struct wlan_objmgr_vdev *vdev,
						struct wlan_objmgr_peer *peer)
{
	struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr;
	struct wlan_objmgr_pdev *pdev;
	enum QDF_OPMODE opmode;

	wlan_vdev_obj_lock(vdev);
	pdev = wlan_vdev_get_pdev(vdev);
	/* If Max VDEV peer count exceeds, return failure */
	if (peer->peer_mlme.peer_type != WLAN_PEER_STA_TEMP) {
		if (objmgr->wlan_peer_count >= objmgr->max_peer_count) {
			wlan_vdev_obj_unlock(vdev);
			return QDF_STATUS_E_FAILURE;
		}
	}
	wlan_vdev_obj_unlock(vdev);

	/* If Max PDEV peer count exceeds, return failure */
	wlan_pdev_obj_lock(pdev);
	if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) {
		if (wlan_pdev_get_temp_peer_count(pdev) >=
			WLAN_MAX_PDEV_TEMP_PEERS) {
			wlan_pdev_obj_unlock(pdev);
			return QDF_STATUS_E_FAILURE;
		}
	} else {
		if (wlan_pdev_get_peer_count(pdev) >=
			wlan_pdev_get_max_peer_count(pdev)) {
			wlan_pdev_obj_unlock(pdev);
			return QDF_STATUS_E_FAILURE;
		}
	}

	if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP)
		wlan_pdev_incr_temp_peer_count(wlan_vdev_get_pdev(vdev));
	else
		wlan_pdev_incr_peer_count(wlan_vdev_get_pdev(vdev));
	wlan_pdev_obj_unlock(pdev);

	wlan_vdev_obj_lock(vdev);
	/* Add peer to vdev's peer list */
	wlan_obj_vdev_peerlist_add_tail(&objmgr->wlan_peer_list, peer);
	objmgr->wlan_peer_count++;

	if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer),
			 wlan_vdev_mlme_get_macaddr(vdev)) ==
				QDF_STATUS_SUCCESS) {
		/*
		 * if peer mac address and vdev mac address match, set
		 * this peer as self peer
		 */
		wlan_vdev_set_selfpeer(vdev, peer);
		opmode = wlan_vdev_mlme_get_opmode(vdev);
		/* For AP mode, self peer and BSS peer are same */
		if ((opmode == QDF_SAP_MODE) ||
		    (opmode == QDF_P2P_GO_MODE) ||
		    (opmode == QDF_NDI_MODE))
			wlan_vdev_set_bsspeer(vdev, peer);
	}
	/* set BSS peer for sta */
	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE ||
	     wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_CLIENT_MODE) &&
	    (wlan_peer_get_peer_type(peer) == WLAN_PEER_AP ||
	     wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO))
		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;
}

QDF_STATUS wlan_objmgr_vdev_peer_detach(struct wlan_objmgr_vdev *vdev,
					struct wlan_objmgr_peer *peer)
{
	struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr;
	struct wlan_objmgr_pdev *pdev;

	wlan_vdev_obj_lock(vdev);
	/* if peer count is 0, return failure */
	if (objmgr->wlan_peer_count == 0) {
		wlan_vdev_obj_unlock(vdev);
		return QDF_STATUS_E_FAILURE;
	}

	if (wlan_vdev_get_selfpeer(vdev) == peer) {
		/*
		 * There might be instances where new node is created
		 * before deleting existing node, in which case selfpeer
		 * will be pointing to the new node. So set selfpeer to
		 * NULL only if vdev->vdev_objmgr.self_peer is pointing
		 * to the peer processed for deletion
		 */
		wlan_vdev_set_selfpeer(vdev, NULL);
	}

	if (wlan_vdev_get_bsspeer(vdev) == peer) {
		/*
		 * There might be instances where new node is created
		 * before deleting existing node, in which case bsspeer
		 * in vdev will be pointing to the new node. So set
		 * bsspeer to NULL only if vdev->vdev_objmgr.bss_peer is
		 * pointing to the peer processed for deletion
		 */
		wlan_vdev_set_bsspeer(vdev, NULL);
	}

	/* remove peer from vdev's peer list */
	if (wlan_obj_vdev_peerlist_remove_peer(&objmgr->wlan_peer_list, peer)
				== QDF_STATUS_E_FAILURE) {
		wlan_vdev_obj_unlock(vdev);
		return QDF_STATUS_E_FAILURE;
	}
	/* decrement peer count */
	objmgr->wlan_peer_count--;
	/* decrement pdev peer count */
	pdev = wlan_vdev_get_pdev(vdev);
	wlan_vdev_obj_unlock(vdev);

	wlan_pdev_obj_lock(pdev);
	if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP)
		wlan_pdev_decr_temp_peer_count(pdev);
	else
		wlan_pdev_decr_peer_count(pdev);
	wlan_pdev_obj_unlock(pdev);

	/* decrement vdev ref count after peer released its reference */
	wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
	return QDF_STATUS_SUCCESS;
}

struct wlan_objmgr_peer *wlan_objmgr_vdev_try_get_bsspeer(
					struct wlan_objmgr_vdev *vdev,
					wlan_objmgr_ref_dbgid id)
{
	struct wlan_objmgr_peer *peer;
	QDF_STATUS status = QDF_STATUS_E_EMPTY;

	if (!vdev)
		return NULL;

	wlan_vdev_obj_lock(vdev);
	peer = wlan_vdev_get_bsspeer(vdev);
	if (peer)
		status = wlan_objmgr_peer_try_get_ref(peer, id);
	wlan_vdev_obj_unlock(vdev);

	if (QDF_IS_STATUS_SUCCESS(status))
		return peer;

	return NULL;
}

void *wlan_objmgr_vdev_get_comp_private_obj(
		struct wlan_objmgr_vdev *vdev,
		enum wlan_umac_comp_id id)
{
	void *comp_priv_obj;

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

	if (!vdev) {
		QDF_BUG(0);
		return NULL;
	}

	comp_priv_obj = vdev->vdev_comp_priv_obj[id];

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

	return;
}
qdf_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)
{
	uint8_t vdev_id;

	if (!vdev) {
		obj_mgr_err("vdev obj is NULL for id:%d", id);
		QDF_ASSERT(0);
		return QDF_STATUS_E_FAILURE;
	}

	wlan_vdev_obj_lock(vdev);
	vdev_id = wlan_vdev_get_id(vdev);
	if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) {
		wlan_vdev_obj_unlock(vdev);
		if (vdev->vdev_objmgr.print_cnt++ <=
				WLAN_OBJMGR_RATELIMIT_THRESH)
			obj_mgr_err(
			"[Ref id: %d] vdev(%d) is not in Created state(%d)",
				id, vdev_id, vdev->obj_state);

		return QDF_STATUS_E_RESOURCES;
	}

	/* Increment ref count */
	wlan_objmgr_vdev_get_ref(vdev, id);
	wlan_vdev_obj_unlock(vdev);

	return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(wlan_objmgr_vdev_try_get_ref);

void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev,
						wlan_objmgr_ref_dbgid id)
{
	uint8_t vdev_id;

	if (!vdev) {
		obj_mgr_err("vdev obj is NULL for id:%d", id);
		QDF_ASSERT(0);
		return;
	}

	vdev_id = wlan_vdev_get_id(vdev);

	if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_id_dbg[id])) {
		obj_mgr_alert("vdev (id:%d)ref cnt was not taken by %d",
			      vdev_id, id);
		wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg,
					  QDF_TRACE_LEVEL_FATAL);
		WLAN_OBJMGR_BUG(0);
		return;
	}

	if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) {
		obj_mgr_alert("vdev ref cnt is 0");
		WLAN_OBJMGR_BUG(0);
		return;
	}
	qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]);

	/* 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;
}
qdf_export_symbol(wlan_objmgr_vdev_release_ref);

struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head(
			struct wlan_objmgr_pdev *pdev,
			qdf_list_t *vdev_list, wlan_objmgr_ref_dbgid dbg_id)
{
	struct wlan_objmgr_vdev *vdev;
	qdf_list_node_t *node = NULL;
	qdf_list_node_t *prev_node = NULL;

	wlan_pdev_obj_lock(pdev);

	if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) {
		wlan_pdev_obj_unlock(pdev);
		return NULL;
	}

	do {
		vdev = qdf_container_of(node, struct wlan_objmgr_vdev,
								vdev_node);
		if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) ==
						QDF_STATUS_SUCCESS) {
			wlan_pdev_obj_unlock(pdev);
			return vdev;
		}

		prev_node = node;
	} while (qdf_list_peek_next(vdev_list, prev_node, &node) ==
						QDF_STATUS_SUCCESS);

	wlan_pdev_obj_unlock(pdev);

	return NULL;
}

struct wlan_objmgr_vdev *wlan_pdev_peek_active_first_vdev(
		struct wlan_objmgr_pdev *pdev,
		wlan_objmgr_ref_dbgid dbg_id)
{
	struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr;
	qdf_list_t *vdev_list;

	/* VDEV list */
	vdev_list = &objmgr->wlan_vdev_list;

	return wlan_pdev_vdev_list_peek_active_head(pdev, vdev_list,
						    dbg_id);
}

struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev(
			struct wlan_objmgr_pdev *pdev,
			qdf_list_t *vdev_list,
			struct wlan_objmgr_vdev *vdev,
			wlan_objmgr_ref_dbgid dbg_id)
{
	struct wlan_objmgr_vdev *vdev_next;
	qdf_list_node_t *node = &vdev->vdev_node;
	qdf_list_node_t *prev_node = NULL;

	if (!node)
		return NULL;

	wlan_pdev_obj_lock(pdev);
	prev_node = node;
	while (qdf_list_peek_next(vdev_list, prev_node, &node) ==
							QDF_STATUS_SUCCESS) {
		vdev_next = qdf_container_of(node, struct wlan_objmgr_vdev,
								vdev_node);
		if (wlan_objmgr_vdev_try_get_ref(vdev_next, dbg_id) ==
						QDF_STATUS_SUCCESS) {
			wlan_pdev_obj_unlock(pdev);
			return vdev_next;
		}

		prev_node = node;
	}
	wlan_pdev_obj_unlock(pdev);

	return NULL;
}

#ifdef WLAN_OBJMGR_DEBUG
void wlan_print_vdev_info(struct wlan_objmgr_vdev *vdev)
{
	struct wlan_objmgr_vdev_objmgr *vdev_objmgr;
	uint32_t ref_cnt;

	vdev_objmgr = &vdev->vdev_objmgr;

	ref_cnt = qdf_atomic_read(&vdev_objmgr->ref_cnt);

	obj_mgr_debug("vdev: %pK", vdev);
	obj_mgr_debug("vdev_id: %d", vdev_objmgr->vdev_id);
	obj_mgr_debug("print_cnt: %d", vdev_objmgr->print_cnt);
	obj_mgr_debug("wlan_pdev: %pK", vdev_objmgr->wlan_pdev);
	obj_mgr_debug("ref_cnt: %d", ref_cnt);
}

qdf_export_symbol(wlan_print_vdev_info);
#endif

