xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c (revision d0c05845839e5f2ba5a8dcebe0cd3e4cd4e8dfcf)
1 /*
2  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19  /**
20  * DOC: Public APIs to perform operations on Peer object
21  */
22 #include <wlan_objmgr_cmn.h>
23 #include <wlan_objmgr_global_obj.h>
24 #include <wlan_objmgr_psoc_obj.h>
25 #include <wlan_objmgr_pdev_obj.h>
26 #include <wlan_objmgr_vdev_obj.h>
27 #include <wlan_objmgr_peer_obj.h>
28 #include <wlan_objmgr_debug.h>
29 #include <qdf_mem.h>
30 #include <qdf_module.h>
31 #include "wlan_objmgr_global_obj_i.h"
32 #include "wlan_objmgr_psoc_obj_i.h"
33 #include "wlan_objmgr_pdev_obj_i.h"
34 #include "wlan_objmgr_vdev_obj_i.h"
35 
36 
37 /**
38  ** APIs to Create/Delete Peer object APIs
39  */
40 static QDF_STATUS wlan_objmgr_peer_object_status(
41 		struct wlan_objmgr_peer *peer)
42 {
43 	uint8_t id;
44 	QDF_STATUS status = QDF_STATUS_SUCCESS;
45 
46 	wlan_peer_obj_lock(peer);
47 	/* Iterate through all components to derive the object status */
48 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
49 		/* If component disabled, Ignore */
50 		if (peer->obj_status[id] == QDF_STATUS_COMP_DISABLED)
51 			continue;
52 		/* If component operates in Async, status is Partially created,
53 			break */
54 		else if (peer->obj_status[id] == QDF_STATUS_COMP_ASYNC) {
55 			if (!peer->peer_comp_priv_obj[id]) {
56 				status = QDF_STATUS_COMP_ASYNC;
57 				break;
58 			}
59 		/* If component failed to allocate its object, treat it as
60 			failure, complete object need to be cleaned up */
61 		} else if ((peer->obj_status[id] == QDF_STATUS_E_NOMEM) ||
62 			(peer->obj_status[id] == QDF_STATUS_E_FAILURE)) {
63 			obj_mgr_err("Peer comp object(id:%d) alloc fail", id);
64 			status = QDF_STATUS_E_FAILURE;
65 			break;
66 		}
67 	}
68 	wlan_peer_obj_unlock(peer);
69 	return status;
70 }
71 
72 static QDF_STATUS wlan_objmgr_peer_obj_free(struct wlan_objmgr_peer *peer)
73 {
74 	struct wlan_objmgr_psoc *psoc;
75 	struct wlan_objmgr_vdev *vdev;
76 	uint8_t *macaddr;
77 	uint8_t vdev_id;
78 	bool peer_free_notify = true;
79 
80 	if (!peer) {
81 		obj_mgr_err("PEER is NULL");
82 		return QDF_STATUS_E_FAILURE;
83 	}
84 
85 	macaddr = wlan_peer_get_macaddr(peer);
86 
87 	vdev = wlan_peer_get_vdev(peer);
88 	if (!vdev) {
89 		obj_mgr_err(
90 			"VDEV is NULL for peer("QDF_MAC_ADDR_FMT")",
91 				QDF_MAC_ADDR_REF(macaddr));
92 		return QDF_STATUS_E_FAILURE;
93 	}
94 
95 	/* Notify peer free only for non self peer*/
96 	if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer),
97 			 wlan_vdev_mlme_get_macaddr(vdev)) ==
98 				QDF_STATUS_SUCCESS)
99 		peer_free_notify = false;
100 
101 	vdev_id = wlan_vdev_get_id(vdev);
102 
103 	/* get PSOC from VDEV, if it is NULL, return */
104 	psoc = wlan_vdev_get_psoc(vdev);
105 	if (!psoc) {
106 		obj_mgr_err(
107 			"PSOC is NULL for peer("QDF_MAC_ADDR_FMT")",
108 				QDF_MAC_ADDR_REF(macaddr));
109 		return QDF_STATUS_E_FAILURE;
110 	}
111 
112 	/* Decrement ref count for BSS peer, so that BSS peer deletes last*/
113 	if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_STA) ||
114 	    (wlan_peer_get_peer_type(peer) == WLAN_PEER_STA_TEMP) ||
115 	    (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_CLI))
116 		wlan_objmgr_peer_release_ref(wlan_vdev_get_bsspeer(vdev),
117 					     WLAN_OBJMGR_ID);
118 
119 	wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID);
120 
121 	/* Detach peer from VDEV's peer list */
122 	if (wlan_objmgr_vdev_peer_detach(vdev, peer) == QDF_STATUS_E_FAILURE) {
123 		obj_mgr_err(
124 		"Peer("QDF_MAC_ADDR_FMT") VDEV detach fail, vdev id: %d",
125 			QDF_MAC_ADDR_REF(macaddr), vdev_id);
126 		wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
127 		return QDF_STATUS_E_FAILURE;
128 	}
129 	/* Detach peer from PSOC's peer list */
130 	if (wlan_objmgr_psoc_peer_detach(psoc, peer) == QDF_STATUS_E_FAILURE) {
131 		obj_mgr_err(
132 		"Peer("QDF_MAC_ADDR_FMT") PSOC detach failure",
133 			QDF_MAC_ADDR_REF(macaddr));
134 		wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
135 		return QDF_STATUS_E_FAILURE;
136 	}
137 	wlan_objmgr_peer_trace_del_ref_list(peer);
138 	wlan_objmgr_peer_trace_deinit_lock(peer);
139 	qdf_spinlock_destroy(&peer->peer_lock);
140 	qdf_mem_free(peer);
141 	peer = NULL;
142 
143 	if (peer_free_notify)
144 		wlan_objmgr_vdev_peer_freed_notify(vdev);
145 
146 	wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
147 
148 	return QDF_STATUS_SUCCESS;
149 
150 }
151 
152 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
153 static void
154 wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer *peer)
155 {
156 	uint8_t id;
157 
158 	for (id = 0; id < WLAN_REF_ID_MAX; id++)
159 		qdf_atomic_init(&peer->peer_objmgr.ref_id_dbg[id]);
160 }
161 #else
162 static inline void
163 wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer *peer) {}
164 #endif
165 
166 struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create(
167 			struct wlan_objmgr_vdev *vdev,
168 			enum wlan_peer_type type,
169 			uint8_t *macaddr)
170 {
171 	struct wlan_objmgr_peer *peer;
172 	struct wlan_objmgr_psoc *psoc;
173 	wlan_objmgr_peer_create_handler handler;
174 	wlan_objmgr_peer_status_handler stat_handler;
175 	void *arg;
176 	QDF_STATUS obj_status;
177 	uint8_t id;
178 
179 	if (!vdev) {
180 		obj_mgr_err(
181 			"VDEV is NULL for peer ("QDF_MAC_ADDR_FMT")",
182 				QDF_MAC_ADDR_REF(macaddr));
183 		return NULL;
184 	}
185 	/* Get psoc, if psoc is NULL, return */
186 	psoc = wlan_vdev_get_psoc(vdev);
187 	if (!psoc) {
188 		obj_mgr_err(
189 			"PSOC is NULL for peer ("QDF_MAC_ADDR_FMT")",
190 				QDF_MAC_ADDR_REF(macaddr));
191 		return NULL;
192 	}
193 	/* Allocate memory for peer object */
194 	peer = qdf_mem_malloc(sizeof(*peer));
195 	if (!peer)
196 		return NULL;
197 
198 	peer->obj_state = WLAN_OBJ_STATE_ALLOCATED;
199 	qdf_atomic_init(&peer->peer_objmgr.ref_cnt);
200 	wlan_objmgr_peer_init_ref_id_debug(peer);
201 	wlan_objmgr_peer_trace_init_lock(peer);
202 	wlan_objmgr_peer_get_ref(peer, WLAN_OBJMGR_ID);
203 	/* set vdev to peer */
204 	wlan_peer_set_vdev(peer, vdev);
205 	/* set peer type */
206 	wlan_peer_set_peer_type(peer, type);
207 	/* set mac address of peer */
208 	wlan_peer_set_macaddr(peer, macaddr);
209 	/* initialize peer state */
210 	wlan_peer_mlme_set_state(peer, WLAN_INIT_STATE);
211 	wlan_peer_mlme_reset_seq_num(peer);
212 	peer->peer_objmgr.print_cnt = 0;
213 
214 	qdf_spinlock_create(&peer->peer_lock);
215 	/* Attach peer to psoc, psoc maintains the node table for the device */
216 	if (wlan_objmgr_psoc_peer_attach(psoc, peer) !=
217 					QDF_STATUS_SUCCESS) {
218 		obj_mgr_warn(
219 		"Peer("QDF_MAC_ADDR_FMT") PSOC attach failure",
220 				QDF_MAC_ADDR_REF(macaddr));
221 		qdf_spinlock_destroy(&peer->peer_lock);
222 		wlan_objmgr_peer_trace_deinit_lock(peer);
223 		qdf_mem_free(peer);
224 		return NULL;
225 	}
226 	/* Attach peer to vdev peer table */
227 	if (wlan_objmgr_vdev_peer_attach(vdev, peer) !=
228 					QDF_STATUS_SUCCESS) {
229 		obj_mgr_warn(
230 		"Peer("QDF_MAC_ADDR_FMT") VDEV attach failure",
231 				QDF_MAC_ADDR_REF(macaddr));
232 		/* if attach fails, detach from psoc table before free */
233 		wlan_objmgr_psoc_peer_detach(psoc, peer);
234 		qdf_spinlock_destroy(&peer->peer_lock);
235 		wlan_objmgr_peer_trace_deinit_lock(peer);
236 		qdf_mem_free(peer);
237 		return NULL;
238 	}
239 	wlan_peer_set_pdev_id(peer, wlan_objmgr_pdev_get_pdev_id(
240 			wlan_vdev_get_pdev(vdev)));
241 	/* Increment ref count for BSS peer, so that BSS peer deletes last*/
242 	if ((type == WLAN_PEER_STA) || (type == WLAN_PEER_STA_TEMP)
243 				    || (type == WLAN_PEER_P2P_CLI))
244 		wlan_objmgr_peer_get_ref(wlan_vdev_get_bsspeer(vdev),
245 					 WLAN_OBJMGR_ID);
246 	/* TODO init other parameters */
247 	/* Invoke registered create handlers */
248 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
249 		handler = g_umac_glb_obj->peer_create_handler[id];
250 		arg = g_umac_glb_obj->peer_create_handler_arg[id];
251 		if (handler)
252 			peer->obj_status[id] = handler(peer, arg);
253 		else
254 			peer->obj_status[id] = QDF_STATUS_COMP_DISABLED;
255 	}
256 	/* derive the object status */
257 	obj_status = wlan_objmgr_peer_object_status(peer);
258 	/* If SUCCESS, Object is created */
259 	if (obj_status == QDF_STATUS_SUCCESS) {
260 		peer->obj_state = WLAN_OBJ_STATE_CREATED;
261 		for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
262 			stat_handler = g_umac_glb_obj->peer_status_handler[id];
263 			arg = g_umac_glb_obj->peer_status_handler_arg[id];
264 			if (stat_handler)
265 				stat_handler(peer, arg,
266 					     QDF_STATUS_SUCCESS);
267 		}
268 	} else if (obj_status == QDF_STATUS_COMP_ASYNC) {
269 		/* If any component operates in different context, update it
270 		as partially created */
271 		peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
272 	} else if (obj_status == QDF_STATUS_E_FAILURE) {
273 		/* Clean up the peer */
274 		obj_mgr_err(
275 		"Peer("QDF_MAC_ADDR_FMT") comp object alloc fail",
276 				QDF_MAC_ADDR_REF(macaddr));
277 		wlan_objmgr_peer_obj_delete(peer);
278 		return NULL;
279 	}
280 
281 	obj_mgr_debug("Created peer " QDF_MAC_ADDR_FMT " type %d",
282 		      QDF_MAC_ADDR_REF(macaddr), type);
283 
284 	return peer;
285 }
286 
287 static QDF_STATUS
288 __wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer)
289 {
290 	uint8_t id;
291 	wlan_objmgr_peer_destroy_handler handler;
292 	QDF_STATUS obj_status;
293 	void *arg;
294 	uint8_t *macaddr;
295 
296 	if (!peer) {
297 		obj_mgr_err("PEER is NULL");
298 		return QDF_STATUS_E_FAILURE;
299 	}
300 	wlan_objmgr_notify_destroy(peer, WLAN_PEER_OP);
301 
302 	macaddr = wlan_peer_get_macaddr(peer);
303 
304 	obj_mgr_debug("Physically deleting peer " QDF_MAC_ADDR_FMT,
305 		      QDF_MAC_ADDR_REF(macaddr));
306 
307 	if (peer->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) {
308 		obj_mgr_err("PEER object del is not invoked obj_state:%d peer "
309 			    QDF_MAC_ADDR_FMT, peer->obj_state,
310 			    QDF_MAC_ADDR_REF(macaddr));
311 		WLAN_OBJMGR_BUG(0);
312 	}
313 
314 	/* Invoke registered destroy handlers */
315 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
316 		handler = g_umac_glb_obj->peer_destroy_handler[id];
317 		arg = g_umac_glb_obj->peer_destroy_handler_arg[id];
318 		if (handler &&
319 		    (peer->obj_status[id] == QDF_STATUS_SUCCESS ||
320 		     peer->obj_status[id] == QDF_STATUS_COMP_ASYNC))
321 			peer->obj_status[id] = handler(peer, arg);
322 		else
323 			peer->obj_status[id] = QDF_STATUS_COMP_DISABLED;
324 	}
325 	/* Derive the object status */
326 	obj_status = wlan_objmgr_peer_object_status(peer);
327 	if (obj_status == QDF_STATUS_E_FAILURE) {
328 		/* If it status is failure, memory will not be freed */
329 		QDF_BUG(0);
330 		return QDF_STATUS_E_FAILURE;
331 	}
332 	/* few components deletion is in progress */
333 	if (obj_status == QDF_STATUS_COMP_ASYNC) {
334 		peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED;
335 		return QDF_STATUS_COMP_ASYNC;
336 	}
337 
338 	/* Free the peer object */
339 	return wlan_objmgr_peer_obj_free(peer);
340 }
341 
342 #ifdef FEATURE_DELAYED_PEER_OBJ_DESTROY
343 /*
344  * Length of the list used to hold delayed peer obj free.
345  * Must be a multiple of 2.
346  */
347 #define MAX_DELAYED_FREE_PEERS 64
348 
349 /**
350  * wlan_objmgr_peer_obj_free_work() - Peer obj freed in the delayed work
351  * @data: PDEV object
352  *
353  * Peer obj freed in the delayed work
354  *
355  * Return: None
356  */
357 static void wlan_objmgr_peer_obj_free_work(void *data)
358 {
359 	struct wlan_objmgr_pdev *pdev = data;
360 	struct wlan_objmgr_peer *peer;
361 	qdf_list_node_t *node;
362 	uint8_t *macaddr;
363 
364 	if (!pdev) {
365 		obj_mgr_err("pdev is NULL");
366 		return;
367 	}
368 
369 	qdf_spin_lock_bh(&pdev->peer_free_lock);
370 	while (!(qdf_list_empty(&pdev->peer_free_list))) {
371 		qdf_list_remove_front(&pdev->peer_free_list, &node);
372 		qdf_spin_unlock_bh(&pdev->peer_free_lock);
373 
374 		peer = qdf_container_of(node,
375 					struct wlan_objmgr_peer,
376 					free_node);
377 
378 		macaddr = wlan_peer_get_macaddr(peer);
379 		obj_mgr_debug("active_work_cnt %u list size %u peer 0x%pK("
380 			      QDF_MAC_ADDR_FMT ")",
381 			      pdev->active_work_cnt,
382 			      qdf_list_size(&pdev->peer_free_list),
383 			      peer,
384 			      QDF_MAC_ADDR_REF(macaddr));
385 
386 		__wlan_objmgr_peer_obj_destroy(peer);
387 
388 		qdf_spin_lock_bh(&pdev->peer_free_lock);
389 	}
390 
391 	pdev->active_work_cnt--;
392 
393 	qdf_spin_unlock_bh(&pdev->peer_free_lock);
394 }
395 
396 /**
397  * wlan_peer_obj_free_enqueue() - enqueue freed peer into kworker
398  * @peer: PEER object
399  *
400  * Enqueue freed peer into kworker
401  *
402  * Return: None
403  */
404 static QDF_STATUS
405 wlan_peer_obj_free_enqueue(struct wlan_objmgr_peer *peer)
406 {
407 	struct wlan_objmgr_vdev *vdev;
408 	struct wlan_objmgr_pdev *pdev;
409 	uint8_t *macaddr;
410 
411 	if (!peer) {
412 		obj_mgr_err("peer is NULL");
413 		return QDF_STATUS_E_FAILURE;
414 	}
415 
416 	macaddr = wlan_peer_get_macaddr(peer);
417 
418 	vdev = wlan_peer_get_vdev(peer);
419 	if (!vdev) {
420 		obj_mgr_err("VDEV is NULL for peer(" QDF_MAC_ADDR_FMT ")",
421 			    QDF_MAC_ADDR_REF(macaddr));
422 		return QDF_STATUS_E_FAILURE;
423 	}
424 	/* get PDEV from VDEV, if it is NULL, return */
425 	pdev = wlan_vdev_get_pdev(vdev);
426 	if (!pdev) {
427 		obj_mgr_err("PDEV is NULL for peer(" QDF_MAC_ADDR_FMT ")",
428 			    QDF_MAC_ADDR_REF(macaddr));
429 		return QDF_STATUS_E_FAILURE;
430 	}
431 
432 	qdf_spin_lock_bh(&pdev->peer_free_lock);
433 	qdf_list_insert_back(&pdev->peer_free_list, &peer->free_node);
434 	pdev->active_work_cnt++;
435 	qdf_spin_unlock_bh(&pdev->peer_free_lock);
436 
437 	obj_mgr_debug("active_work_cnt %u list size %u peer 0x%pK("
438 		      QDF_MAC_ADDR_FMT ")",
439 		      pdev->active_work_cnt,
440 		      qdf_list_size(&pdev->peer_free_list),
441 		      peer,
442 		      QDF_MAC_ADDR_REF(macaddr));
443 
444 	qdf_sched_work(0, &pdev->peer_obj_free_work);
445 
446 	return QDF_STATUS_SUCCESS;
447 }
448 
449 static QDF_STATUS
450 wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer)
451 {
452 	QDF_STATUS status;
453 
454 	status = wlan_peer_obj_free_enqueue(peer);
455 	if (status != QDF_STATUS_SUCCESS) {
456 		obj_mgr_warn("enqueue failure, call free obj directly");
457 		status = __wlan_objmgr_peer_obj_destroy(peer);
458 	}
459 
460 	return status;
461 }
462 
463 /**
464  * wlan_delayed_peer_obj_free_init() - Init for delayed peer obj freed queue
465  * @data: PDEV object
466  *
467  * Initialize main data structures to process peer obj destroy in a delayed
468  * workqueue.
469  *
470  * Return: QDF_STATUS_SUCCESS on success else a QDF error.
471  */
472 QDF_STATUS wlan_delayed_peer_obj_free_init(void *data)
473 {
474 	struct wlan_objmgr_pdev *pdev = data;
475 
476 	if (!pdev) {
477 		obj_mgr_err("pdev is NULL");
478 		return QDF_STATUS_E_FAILURE;
479 	}
480 
481 	qdf_spinlock_create(&pdev->peer_free_lock);
482 	qdf_create_work(0, &pdev->peer_obj_free_work,
483 			wlan_objmgr_peer_obj_free_work,
484 			(void *)pdev);
485 	pdev->active_work_cnt = 0;
486 
487 	/* Initialize PDEV's peer free list, assign default values */
488 	qdf_list_create(&pdev->peer_free_list, MAX_DELAYED_FREE_PEERS);
489 
490 	obj_mgr_debug("Delayed peer obj free init successfully");
491 
492 	return QDF_STATUS_SUCCESS;
493 }
494 
495 /**
496  * wlan_delayed_peer_obj_free_deinit() - De-Init delayed peer freed processing
497  * @data: PDEV object
498  *
499  * De-initialize main data structures to process peer obj freed in a delayed
500  * workqueue.
501  *
502  * Return: QDF_STATUS_SUCCESS on success else a QDF error.
503  */
504 QDF_STATUS wlan_delayed_peer_obj_free_deinit(void *data)
505 {
506 	struct wlan_objmgr_pdev *pdev = data;
507 
508 	if (!pdev) {
509 		obj_mgr_err("pdev is NULL");
510 		return QDF_STATUS_E_FAILURE;
511 	}
512 
513 	qdf_destroy_work(0, &pdev->peer_obj_free_work);
514 	qdf_spinlock_destroy(&pdev->peer_free_lock);
515 
516 	obj_mgr_debug("Deinit successfully, active_work_cnt=%u",
517 		      pdev->active_work_cnt);
518 
519 	return QDF_STATUS_SUCCESS;
520 }
521 #else
522 static QDF_STATUS
523 wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer)
524 {
525 	return __wlan_objmgr_peer_obj_destroy(peer);
526 }
527 #endif
528 
529 QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer)
530 {
531 	uint8_t print_idx;
532 	uint8_t *macaddr;
533 
534 	if (!peer) {
535 		obj_mgr_err("PEER is NULL");
536 		return QDF_STATUS_E_FAILURE;
537 	}
538 
539 	wlan_peer_obj_lock(peer);
540 	macaddr = wlan_peer_get_macaddr(peer);
541 	wlan_peer_obj_unlock(peer);
542 
543 	obj_mgr_debug("Logically deleting peer " QDF_MAC_ADDR_FMT,
544 		      QDF_MAC_ADDR_REF(macaddr));
545 
546 	print_idx = qdf_get_pidx();
547 	wlan_objmgr_print_peer_ref_ids(peer, QDF_TRACE_LEVEL_DEBUG);
548 	/**
549 	 * Update VDEV object state to LOGICALLY DELETED
550 	 * It prevents further access of this object
551 	 */
552 	wlan_peer_obj_lock(peer);
553 	peer->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED;
554 	wlan_peer_obj_unlock(peer);
555 	wlan_objmgr_notify_log_delete(peer, WLAN_PEER_OP);
556 	wlan_objmgr_peer_release_ref(peer, WLAN_OBJMGR_ID);
557 
558 	return QDF_STATUS_SUCCESS;
559 }
560 qdf_export_symbol(wlan_objmgr_peer_obj_delete);
561 /**
562  ** APIs to attach/detach component objects
563  */
564 QDF_STATUS wlan_objmgr_peer_component_obj_attach(
565 		struct wlan_objmgr_peer *peer,
566 		enum wlan_umac_comp_id id,
567 		void *comp_priv_obj,
568 		QDF_STATUS status)
569 {
570 	wlan_objmgr_peer_status_handler s_hler;
571 	void *arg;
572 	uint8_t i;
573 	QDF_STATUS obj_status;
574 
575 	/* component id is invalid */
576 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
577 		return QDF_STATUS_MAXCOMP_FAIL;
578 
579 	wlan_peer_obj_lock(peer);
580 	/* If there is a valid entry, return failure,
581 	valid object needs to be freed first */
582 	if (peer->peer_comp_priv_obj[id]) {
583 		wlan_peer_obj_unlock(peer);
584 		return QDF_STATUS_E_FAILURE;
585 	}
586 	/* Assign component object private pointer(can be NULL also), status */
587 	peer->peer_comp_priv_obj[id] = comp_priv_obj;
588 	peer->obj_status[id] = status;
589 	wlan_peer_obj_unlock(peer);
590 
591 	if (peer->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED)
592 		return QDF_STATUS_SUCCESS;
593 
594 	/* If PEER object status is partially created means, this API is
595 	invoked with differnt context. this block should be executed for async
596 	components only */
597 	/* Derive status */
598 	obj_status = wlan_objmgr_peer_object_status(peer);
599 	/* STATUS_SUCCESS means, object is CREATED */
600 	if (obj_status == QDF_STATUS_SUCCESS)
601 		peer->obj_state = WLAN_OBJ_STATE_CREATED;
602 	/* update state as CREATION failed, caller has to delete the
603 	PEER object */
604 	else if (obj_status == QDF_STATUS_E_FAILURE)
605 		peer->obj_state = WLAN_OBJ_STATE_CREATION_FAILED;
606 	/* Notify components about the CREATION success/failure */
607 	if ((obj_status == QDF_STATUS_SUCCESS) ||
608 	    (obj_status == QDF_STATUS_E_FAILURE)) {
609 		/* nofity object status */
610 		for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) {
611 			s_hler = g_umac_glb_obj->peer_status_handler[i];
612 			arg = g_umac_glb_obj->peer_status_handler_arg[i];
613 			if (s_hler)
614 				s_hler(peer, arg, obj_status);
615 		}
616 	}
617 	return QDF_STATUS_SUCCESS;
618 }
619 
620 qdf_export_symbol(wlan_objmgr_peer_component_obj_attach);
621 
622 QDF_STATUS wlan_objmgr_peer_component_obj_detach(
623 		struct wlan_objmgr_peer *peer,
624 		enum wlan_umac_comp_id id,
625 		void *comp_priv_obj)
626 {
627 	QDF_STATUS obj_status;
628 
629 	/* component id is invalid */
630 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
631 		return QDF_STATUS_MAXCOMP_FAIL;
632 
633 	wlan_peer_obj_lock(peer);
634 	/* If there is a invalid entry, return failure */
635 	if (peer->peer_comp_priv_obj[id] != comp_priv_obj) {
636 		peer->obj_status[id] = QDF_STATUS_E_FAILURE;
637 		wlan_peer_obj_unlock(peer);
638 		return QDF_STATUS_E_FAILURE;
639 	}
640 	/* Reset the pointer to NULL */
641 	peer->peer_comp_priv_obj[id] = NULL;
642 	peer->obj_status[id] = QDF_STATUS_SUCCESS;
643 	wlan_peer_obj_unlock(peer);
644 
645 	/* If PEER object status is partially destroyed means, this API is
646 	invoked with differnt context, this block should be executed for async
647 	components only */
648 	if ((peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) ||
649 	    (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) {
650 		/* Derive object status */
651 		obj_status = wlan_objmgr_peer_object_status(peer);
652 		if (obj_status == QDF_STATUS_SUCCESS) {
653 			/*Update the status as Deleted, if full object
654 				deletion is in progress */
655 			if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
656 				peer->obj_state = WLAN_OBJ_STATE_DELETED;
657 			/* Move to creation state, since this component
658 			deletion alone requested */
659 			if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
660 				peer->obj_state = WLAN_OBJ_STATE_CREATED;
661 		/* Object status is failure */
662 		} else if (obj_status == QDF_STATUS_E_FAILURE) {
663 			/*Update the status as Deletion failed, if full object
664 				deletion is in progress */
665 			if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
666 				peer->obj_state =
667 					WLAN_OBJ_STATE_DELETION_FAILED;
668 			/* Move to creation state, since this component
669 			deletion alone requested (do not block other
670 			components) */
671 			if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
672 				peer->obj_state = WLAN_OBJ_STATE_CREATED;
673 		}
674 
675 			/* Delete peer object */
676 		if ((obj_status == QDF_STATUS_SUCCESS)  &&
677 		    (peer->obj_state == WLAN_OBJ_STATE_DELETED)) {
678 			/* Free the peer object */
679 			return wlan_objmgr_peer_obj_free(peer);
680 		}
681 	}
682 
683 	return QDF_STATUS_SUCCESS;
684 }
685 
686 qdf_export_symbol(wlan_objmgr_peer_component_obj_detach);
687 
688 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_creation(
689 		struct wlan_objmgr_peer *peer,
690 		enum wlan_umac_comp_id id)
691 {
692 	wlan_objmgr_peer_create_handler handler;
693 	void *arg;
694 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
695 
696 	/* Component id is invalid */
697 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
698 		return QDF_STATUS_MAXCOMP_FAIL;
699 
700 	wlan_peer_obj_lock(peer);
701 	/* If component object is already created, delete old
702 		component object, then invoke creation */
703 	if (peer->peer_comp_priv_obj[id]) {
704 		wlan_peer_obj_unlock(peer);
705 		return QDF_STATUS_E_FAILURE;
706 	}
707 	wlan_peer_obj_unlock(peer);
708 
709 	/* Invoke registered create handlers */
710 	handler = g_umac_glb_obj->peer_create_handler[id];
711 	arg = g_umac_glb_obj->peer_create_handler_arg[id];
712 	if (handler)
713 		peer->obj_status[id] = handler(peer, arg);
714 	else
715 		return QDF_STATUS_E_FAILURE;
716 
717 	/* If object status is created, then only handle this object status */
718 	if (peer->obj_state == WLAN_OBJ_STATE_CREATED) {
719 		/* Derive object status */
720 		obj_status = wlan_objmgr_peer_object_status(peer);
721 		/* Move PDEV object state to Partially created state */
722 		if (obj_status == QDF_STATUS_COMP_ASYNC) {
723 			/*TODO atomic */
724 			peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
725 		}
726 	}
727 
728 	return obj_status;
729 }
730 
731 
732 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_deletion(
733 		struct wlan_objmgr_peer *peer,
734 		enum wlan_umac_comp_id id)
735 {
736 	wlan_objmgr_peer_destroy_handler handler;
737 	void *arg;
738 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
739 
740 	/* component id is invalid */
741 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
742 		return QDF_STATUS_MAXCOMP_FAIL;
743 
744 	wlan_peer_obj_lock(peer);
745 	/* Component object was never created, invalid operation */
746 	if (!peer->peer_comp_priv_obj[id]) {
747 		wlan_peer_obj_unlock(peer);
748 		return QDF_STATUS_E_FAILURE;
749 	}
750 
751 	wlan_peer_obj_unlock(peer);
752 
753 	/* Invoke registered destroy handlers */
754 	handler = g_umac_glb_obj->peer_destroy_handler[id];
755 	arg = g_umac_glb_obj->peer_destroy_handler_arg[id];
756 	if (handler)
757 		peer->obj_status[id] = handler(peer, arg);
758 	else
759 		return QDF_STATUS_E_FAILURE;
760 
761 	/* If object status is created, then only handle this object status */
762 	if (peer->obj_state == WLAN_OBJ_STATE_CREATED) {
763 		obj_status = wlan_objmgr_peer_object_status(peer);
764 			/* move object state to DEL progress */
765 		if (obj_status == QDF_STATUS_COMP_ASYNC)
766 			peer->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS;
767 	}
768 	return obj_status;
769 }
770 
771 void *wlan_objmgr_peer_get_comp_private_obj(
772 		struct wlan_objmgr_peer *peer,
773 		enum wlan_umac_comp_id id)
774 {
775 	void *comp_priv_obj;
776 
777 	/* component id is invalid */
778 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
779 		QDF_BUG(0);
780 		return NULL;
781 	}
782 
783 	if (!peer) {
784 		QDF_BUG(0);
785 		return NULL;
786 	}
787 
788 	comp_priv_obj = peer->peer_comp_priv_obj[id];
789 	return comp_priv_obj;
790 }
791 qdf_export_symbol(wlan_objmgr_peer_get_comp_private_obj);
792 
793 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
794 static inline void
795 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer,
796 				  wlan_objmgr_ref_dbgid id)
797 {
798 	qdf_atomic_inc(&peer->peer_objmgr.ref_id_dbg[id]);
799 }
800 #else
801 static inline void
802 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer,
803 				  wlan_objmgr_ref_dbgid id) {}
804 #endif
805 
806 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
807 static QDF_STATUS
808 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer,
809 				      wlan_objmgr_ref_dbgid id)
810 {
811 	if (!qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id])) {
812 		uint8_t *macaddr;
813 
814 		macaddr = wlan_peer_get_macaddr(peer);
815 		obj_mgr_err(
816 		"peer("QDF_MAC_ADDR_FMT") ref was not taken by %d",
817 			QDF_MAC_ADDR_REF(macaddr), id);
818 		wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg,
819 					  QDF_TRACE_LEVEL_FATAL);
820 		WLAN_OBJMGR_BUG(0);
821 		return QDF_STATUS_E_FAILURE;
822 	}
823 
824 	qdf_atomic_dec(&peer->peer_objmgr.ref_id_dbg[id]);
825 	return QDF_STATUS_SUCCESS;
826 }
827 #else
828 static QDF_STATUS
829 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer,
830 				      wlan_objmgr_ref_dbgid id)
831 {
832 	return QDF_STATUS_SUCCESS;
833 }
834 #endif
835 
836 #ifdef WLAN_OBJMGR_REF_ID_TRACE
837 static inline void
838 wlan_objmgr_peer_ref_trace(struct wlan_objmgr_peer *peer,
839 			   wlan_objmgr_ref_dbgid id,
840 			   const char *func, int line)
841 {
842 	struct wlan_objmgr_trace *trace;
843 
844 	trace = &peer->peer_objmgr.trace;
845 
846 	if (func)
847 		wlan_objmgr_trace_ref(&trace->references[id].head,
848 				      trace, func, line);
849 }
850 
851 static inline void
852 wlan_objmgr_peer_deref_trace(struct wlan_objmgr_peer *peer,
853 			     wlan_objmgr_ref_dbgid id,
854 			     const char *func, int line)
855 {
856 	struct wlan_objmgr_trace *trace;
857 
858 	trace = &peer->peer_objmgr.trace;
859 	if (func)
860 		wlan_objmgr_trace_ref(&trace->dereferences[id].head,
861 				      trace, func, line);
862 }
863 #endif
864 
865 #ifdef WLAN_OBJMGR_REF_ID_TRACE
866 void wlan_objmgr_peer_get_ref_debug(struct wlan_objmgr_peer *peer,
867 				    wlan_objmgr_ref_dbgid id,
868 				    const char *func, int line)
869 {
870 	if (!peer) {
871 		obj_mgr_err("peer obj is NULL for %d", id);
872 		QDF_ASSERT(0);
873 		return;
874 	}
875 	/* Increment ref count */
876 	qdf_atomic_inc(&peer->peer_objmgr.ref_cnt);
877 	wlan_objmgr_peer_get_debug_id_ref(peer, id);
878 
879 	wlan_objmgr_peer_ref_trace(peer, id, func, line);
880 	return;
881 }
882 
883 qdf_export_symbol(wlan_objmgr_peer_get_ref_debug);
884 #else
885 void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer,
886 			      wlan_objmgr_ref_dbgid id)
887 {
888 	if (!peer) {
889 		obj_mgr_err("peer obj is NULL for %d", id);
890 		QDF_ASSERT(0);
891 		return;
892 	}
893 	/* Increment ref count */
894 	qdf_atomic_inc(&peer->peer_objmgr.ref_cnt);
895 	wlan_objmgr_peer_get_debug_id_ref(peer, id);
896 }
897 
898 qdf_export_symbol(wlan_objmgr_peer_get_ref);
899 #endif
900 
901 #ifdef WLAN_OBJMGR_REF_ID_TRACE
902 QDF_STATUS wlan_objmgr_peer_try_get_ref_debug(struct wlan_objmgr_peer *peer,
903 					      wlan_objmgr_ref_dbgid id,
904 					      const char *func, int line)
905 {
906 	if (!peer) {
907 		obj_mgr_err("peer obj is NULL for %d", id);
908 		QDF_ASSERT(0);
909 		return QDF_STATUS_E_FAILURE;
910 	}
911 
912 	wlan_peer_obj_lock(peer);
913 	if (peer->obj_state != WLAN_OBJ_STATE_CREATED) {
914 		wlan_peer_obj_unlock(peer);
915 		if (peer->peer_objmgr.print_cnt++ <=
916 				WLAN_OBJMGR_RATELIMIT_THRESH) {
917 			uint8_t *macaddr;
918 
919 			macaddr = wlan_peer_get_macaddr(peer);
920 			obj_mgr_debug(
921 			"peer(" QDF_MAC_ADDR_FMT ") not in Created st(%d)",
922 			QDF_MAC_ADDR_REF(macaddr),
923 			peer->obj_state);
924 		}
925 		return QDF_STATUS_E_RESOURCES;
926 	}
927 
928 	wlan_objmgr_peer_get_ref_debug(peer, id, func, line);
929 	wlan_peer_obj_unlock(peer);
930 
931 	return QDF_STATUS_SUCCESS;
932 }
933 
934 qdf_export_symbol(wlan_objmgr_peer_try_get_ref_debug);
935 #else
936 QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer,
937 					wlan_objmgr_ref_dbgid id)
938 {
939 	if (!peer) {
940 		obj_mgr_err("peer obj is NULL for %d", id);
941 		QDF_ASSERT(0);
942 		return QDF_STATUS_E_FAILURE;
943 	}
944 
945 	wlan_peer_obj_lock(peer);
946 	if (peer->obj_state != WLAN_OBJ_STATE_CREATED) {
947 		wlan_peer_obj_unlock(peer);
948 		if (peer->peer_objmgr.print_cnt++ <=
949 				WLAN_OBJMGR_RATELIMIT_THRESH) {
950 			uint8_t *macaddr;
951 
952 			macaddr = wlan_peer_get_macaddr(peer);
953 			obj_mgr_debug(
954 			"peer(" QDF_MAC_ADDR_FMT ") not in Created st(%d)",
955 			QDF_MAC_ADDR_REF(macaddr),
956 			peer->obj_state);
957 		}
958 		return QDF_STATUS_E_RESOURCES;
959 	}
960 
961 	wlan_objmgr_peer_get_ref(peer, id);
962 	wlan_peer_obj_unlock(peer);
963 
964 	return QDF_STATUS_SUCCESS;
965 }
966 
967 qdf_export_symbol(wlan_objmgr_peer_try_get_ref);
968 #endif
969 
970 #ifdef WLAN_OBJMGR_REF_ID_TRACE
971 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc_debug(
972 					struct wlan_peer_list *peer_list,
973 					uint8_t hash_index,
974 					struct wlan_objmgr_peer *peer,
975 					wlan_objmgr_ref_dbgid dbg_id,
976 					const char *func, int line)
977 {
978 	struct wlan_objmgr_peer *peer_next = NULL;
979 	qdf_list_node_t *psoc_node = NULL;
980 	qdf_list_node_t *prev_psoc_node = NULL;
981 	qdf_list_t *obj_list;
982 
983 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
984 	obj_list = &peer_list->peer_hash[hash_index];
985 
986 	prev_psoc_node = &peer->psoc_peer;
987 	while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
988 						QDF_STATUS_SUCCESS) {
989 		peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
990 					     psoc_peer);
991 
992 		if (wlan_objmgr_peer_try_get_ref_debug(peer_next, dbg_id,
993 						       func, line) ==
994 				QDF_STATUS_SUCCESS) {
995 			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
996 			return peer_next;
997 		}
998 
999 		prev_psoc_node = psoc_node;
1000 	}
1001 
1002 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1003 
1004 	return NULL;
1005 }
1006 #else
1007 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc(
1008 					struct wlan_peer_list *peer_list,
1009 					uint8_t hash_index,
1010 					struct wlan_objmgr_peer *peer,
1011 					wlan_objmgr_ref_dbgid dbg_id)
1012 {
1013 	struct wlan_objmgr_peer *peer_next = NULL;
1014 	qdf_list_node_t *psoc_node = NULL;
1015 	qdf_list_node_t *prev_psoc_node = NULL;
1016 	qdf_list_t *obj_list;
1017 
1018 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1019 	obj_list = &peer_list->peer_hash[hash_index];
1020 
1021 	prev_psoc_node = &peer->psoc_peer;
1022 	while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
1023 						QDF_STATUS_SUCCESS) {
1024 		peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
1025 					     psoc_peer);
1026 
1027 		if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) ==
1028 				QDF_STATUS_SUCCESS) {
1029 			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1030 			return peer_next;
1031 		}
1032 
1033 		prev_psoc_node = psoc_node;
1034 	}
1035 
1036 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1037 
1038 	return NULL;
1039 }
1040 #endif
1041 
1042 #ifdef WLAN_OBJMGR_REF_ID_TRACE
1043 struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head_debug(
1044 				struct wlan_objmgr_vdev *vdev,
1045 				qdf_list_t *peer_list,
1046 				wlan_objmgr_ref_dbgid dbg_id,
1047 				const char *func, int line)
1048 {
1049 	struct wlan_objmgr_peer *peer;
1050 	qdf_list_node_t *vdev_node = NULL;
1051 	qdf_list_node_t *prev_vdev_node = NULL;
1052 
1053 	wlan_vdev_obj_lock(vdev);
1054 
1055 	if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) {
1056 		wlan_vdev_obj_unlock(vdev);
1057 		return NULL;
1058 	}
1059 
1060 	do {
1061 		peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
1062 					vdev_peer);
1063 
1064 		if (wlan_objmgr_peer_try_get_ref_debug(peer, dbg_id,
1065 						       func, line) ==
1066 				QDF_STATUS_SUCCESS) {
1067 			wlan_vdev_obj_unlock(vdev);
1068 			return peer;
1069 		}
1070 
1071 		prev_vdev_node = vdev_node;
1072 	} while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
1073 							QDF_STATUS_SUCCESS);
1074 
1075 	wlan_vdev_obj_unlock(vdev);
1076 
1077 	return NULL;
1078 }
1079 #else
1080 struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head(
1081 				struct wlan_objmgr_vdev *vdev,
1082 				qdf_list_t *peer_list,
1083 				wlan_objmgr_ref_dbgid dbg_id)
1084 {
1085 	struct wlan_objmgr_peer *peer;
1086 	qdf_list_node_t *vdev_node = NULL;
1087 	qdf_list_node_t *prev_vdev_node = NULL;
1088 
1089 	wlan_vdev_obj_lock(vdev);
1090 
1091 	if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) {
1092 		wlan_vdev_obj_unlock(vdev);
1093 		return NULL;
1094 	}
1095 
1096 	do {
1097 		peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
1098 						vdev_peer);
1099 
1100 		if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
1101 				QDF_STATUS_SUCCESS) {
1102 			wlan_vdev_obj_unlock(vdev);
1103 			return peer;
1104 		}
1105 
1106 		prev_vdev_node = vdev_node;
1107 	} while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
1108 							QDF_STATUS_SUCCESS);
1109 
1110 	wlan_vdev_obj_unlock(vdev);
1111 
1112 	return NULL;
1113 }
1114 #endif
1115 
1116 #ifdef WLAN_OBJMGR_REF_ID_TRACE
1117 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev_debug(
1118 					struct wlan_objmgr_vdev *vdev,
1119 					qdf_list_t *peer_list,
1120 					struct wlan_objmgr_peer *peer,
1121 					wlan_objmgr_ref_dbgid dbg_id,
1122 					const char *func, int line)
1123 {
1124 	struct wlan_objmgr_peer *peer_next;
1125 	qdf_list_node_t *vdev_node = NULL;
1126 	qdf_list_node_t *prev_vdev_node = NULL;
1127 
1128 	if (!peer)
1129 		return NULL;
1130 
1131 	wlan_vdev_obj_lock(vdev);
1132 
1133 	prev_vdev_node = &peer->vdev_peer;
1134 	while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
1135 						QDF_STATUS_SUCCESS) {
1136 		peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
1137 					     vdev_peer);
1138 
1139 		if (wlan_objmgr_peer_try_get_ref_debug(peer_next, dbg_id,
1140 						       func, line) ==
1141 				QDF_STATUS_SUCCESS) {
1142 			wlan_vdev_obj_unlock(vdev);
1143 			return peer_next;
1144 		}
1145 
1146 		prev_vdev_node = vdev_node;
1147 	}
1148 
1149 	wlan_vdev_obj_unlock(vdev);
1150 
1151 	return NULL;
1152 }
1153 #else
1154 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev(
1155 					struct wlan_objmgr_vdev *vdev,
1156 					qdf_list_t *peer_list,
1157 					struct wlan_objmgr_peer *peer,
1158 					wlan_objmgr_ref_dbgid dbg_id)
1159 {
1160 	struct wlan_objmgr_peer *peer_next;
1161 	qdf_list_node_t *vdev_node = NULL;
1162 	qdf_list_node_t *prev_vdev_node = NULL;
1163 
1164 	if (!peer)
1165 		return NULL;
1166 
1167 	wlan_vdev_obj_lock(vdev);
1168 
1169 	prev_vdev_node = &peer->vdev_peer;
1170 	while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
1171 						QDF_STATUS_SUCCESS) {
1172 		peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
1173 					vdev_peer);
1174 
1175 		if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) ==
1176 				QDF_STATUS_SUCCESS) {
1177 			wlan_vdev_obj_unlock(vdev);
1178 			return peer_next;
1179 		}
1180 
1181 		prev_vdev_node = vdev_node;
1182 	}
1183 
1184 	wlan_vdev_obj_unlock(vdev);
1185 
1186 	return NULL;
1187 }
1188 #endif
1189 
1190 #ifdef WLAN_OBJMGR_REF_ID_TRACE
1191 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head_debug(
1192 					struct wlan_peer_list *peer_list,
1193 					uint8_t hash_index,
1194 					wlan_objmgr_ref_dbgid dbg_id,
1195 					const char *func, int line)
1196 {
1197 	struct wlan_objmgr_peer *peer;
1198 	qdf_list_node_t *psoc_node = NULL;
1199 	qdf_list_node_t *prev_psoc_node = NULL;
1200 	qdf_list_t *obj_list;
1201 
1202 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1203 	obj_list = &peer_list->peer_hash[hash_index];
1204 
1205 	if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) {
1206 		qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1207 		return NULL;
1208 	}
1209 
1210 	do {
1211 		peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
1212 					psoc_peer);
1213 		if (wlan_objmgr_peer_try_get_ref_debug(peer, dbg_id,
1214 						       func, line) ==
1215 				QDF_STATUS_SUCCESS) {
1216 			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1217 			return peer;
1218 		}
1219 
1220 		prev_psoc_node = psoc_node;
1221 	} while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
1222 						QDF_STATUS_SUCCESS);
1223 
1224 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1225 	return NULL;
1226 }
1227 #else
1228 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head(
1229 					struct wlan_peer_list *peer_list,
1230 					uint8_t hash_index,
1231 					wlan_objmgr_ref_dbgid dbg_id)
1232 {
1233 	struct wlan_objmgr_peer *peer;
1234 	qdf_list_node_t *psoc_node = NULL;
1235 	qdf_list_node_t *prev_psoc_node = NULL;
1236 	qdf_list_t *obj_list;
1237 
1238 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1239 	obj_list = &peer_list->peer_hash[hash_index];
1240 
1241 	if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) {
1242 		qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1243 		return NULL;
1244 	}
1245 
1246 	do {
1247 		peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
1248 						psoc_peer);
1249 		if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
1250 				QDF_STATUS_SUCCESS) {
1251 			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1252 			return peer;
1253 		}
1254 
1255 		prev_psoc_node = psoc_node;
1256 	} while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
1257 						QDF_STATUS_SUCCESS);
1258 
1259 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1260 	return NULL;
1261 }
1262 #endif
1263 
1264 #ifdef WLAN_OBJMGR_REF_ID_TRACE
1265 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref_debug(
1266 					struct wlan_peer_list *peer_list,
1267 					uint8_t hash_index,
1268 					wlan_objmgr_ref_dbgid dbg_id,
1269 					const char *func, int line)
1270 {
1271 	struct wlan_objmgr_peer *peer;
1272 	qdf_list_t *obj_list;
1273 
1274 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1275 	obj_list = &peer_list->peer_hash[hash_index];
1276 
1277 	peer = wlan_psoc_peer_list_peek_head(obj_list);
1278 
1279 	/* This API is invoked by caller, only when caller need to access the
1280 	 * peer object, though object is not in active state, this API should be
1281 	 * used carefully, where multiple object frees are not triggered
1282 	 */
1283 	if (peer)
1284 		wlan_objmgr_peer_get_ref_debug(peer, dbg_id, func, line);
1285 
1286 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1287 
1288 	return peer;
1289 }
1290 #else
1291 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref(
1292 					struct wlan_peer_list *peer_list,
1293 					uint8_t hash_index,
1294 					wlan_objmgr_ref_dbgid dbg_id)
1295 {
1296 	struct wlan_objmgr_peer *peer;
1297 	qdf_list_t *obj_list;
1298 
1299 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1300 	obj_list = &peer_list->peer_hash[hash_index];
1301 
1302 	peer = wlan_psoc_peer_list_peek_head(obj_list);
1303 
1304 	/* This API is invoked by caller, only when caller need to access the
1305 	 * peer object, though object is not in active state, this API should be
1306 	 * used carefully, where multiple object frees are not triggered
1307 	 */
1308 	if (peer)
1309 		wlan_objmgr_peer_get_ref(peer, dbg_id);
1310 
1311 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1312 
1313 	return peer;
1314 }
1315 #endif
1316 
1317 #ifdef WLAN_OBJMGR_REF_ID_TRACE
1318 struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref_debug(
1319 			struct wlan_peer_list *peer_list, uint8_t hash_index,
1320 			struct wlan_objmgr_peer *peer,
1321 			wlan_objmgr_ref_dbgid dbg_id,
1322 			const char *func, int line)
1323 {
1324 	qdf_list_t *obj_list;
1325 	struct wlan_objmgr_peer *peer_next;
1326 
1327 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1328 	obj_list = &peer_list->peer_hash[hash_index];
1329 
1330 	peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer);
1331 	/* This API is invoked by caller, only when caller need to access the
1332 	 * peer object, though object is not in active state, this API should be
1333 	 * used carefully, where multiple free on object are not triggered
1334 	 */
1335 	if (peer_next)
1336 		wlan_objmgr_peer_get_ref_debug(peer_next, dbg_id, func, line);
1337 
1338 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1339 
1340 	return peer_next;
1341 }
1342 #else
1343 struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref(
1344 			struct wlan_peer_list *peer_list, uint8_t hash_index,
1345 			struct wlan_objmgr_peer *peer,
1346 			wlan_objmgr_ref_dbgid dbg_id)
1347 {
1348 	qdf_list_t *obj_list;
1349 	struct wlan_objmgr_peer *peer_next;
1350 
1351 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1352 	obj_list = &peer_list->peer_hash[hash_index];
1353 
1354 	peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer);
1355 	/* This API is invoked by caller, only when caller need to access the
1356 	 * peer object, though object is not in active state, this API should be
1357 	 * used carefully, where multiple free on object are not triggered
1358 	 */
1359 	if (peer_next)
1360 		wlan_objmgr_peer_get_ref(peer_next, dbg_id);
1361 
1362 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1363 
1364 	return peer_next;
1365 }
1366 #endif
1367 
1368 #ifdef WLAN_OBJMGR_REF_ID_TRACE
1369 void wlan_objmgr_peer_release_ref_debug(struct wlan_objmgr_peer *peer,
1370 					wlan_objmgr_ref_dbgid id,
1371 					const char *func, int line)
1372 {
1373 	QDF_STATUS status;
1374 
1375 	if (!peer) {
1376 		obj_mgr_err("peer obj is NULL for %d", id);
1377 		QDF_ASSERT(0);
1378 		return;
1379 	}
1380 
1381 	if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) {
1382 		uint8_t *macaddr;
1383 
1384 		macaddr = wlan_peer_get_macaddr(peer);
1385 		obj_mgr_err("peer("QDF_MAC_ADDR_FMT") ref cnt is 0",
1386 				QDF_MAC_ADDR_REF(macaddr));
1387 		WLAN_OBJMGR_BUG(0);
1388 		return;
1389 	}
1390 
1391 	status = wlan_objmgr_peer_release_debug_id_ref(peer, id);
1392 	if (QDF_IS_STATUS_ERROR(status))
1393 		return;
1394 
1395 	wlan_objmgr_peer_deref_trace(peer, id, func, line);
1396 	/* Provide synchronization from the access to add peer
1397 	 * to logically deleted peer list.
1398 	 */
1399 	wlan_peer_obj_lock(peer);
1400 	/* Decrement ref count, free peer object, if ref count == 0 */
1401 	if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) {
1402 		wlan_peer_obj_unlock(peer);
1403 		wlan_objmgr_peer_obj_destroy(peer);
1404 	} else {
1405 		wlan_peer_obj_unlock(peer);
1406 	}
1407 
1408 	return;
1409 }
1410 
1411 qdf_export_symbol(wlan_objmgr_peer_release_ref_debug);
1412 #else
1413 void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer,
1414 				  wlan_objmgr_ref_dbgid id)
1415 {
1416 	QDF_STATUS status;
1417 
1418 	if (!peer) {
1419 		obj_mgr_err("peer obj is NULL for %d", id);
1420 		QDF_ASSERT(0);
1421 		return;
1422 	}
1423 
1424 	if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) {
1425 		uint8_t *macaddr;
1426 
1427 		macaddr = wlan_peer_get_macaddr(peer);
1428 		obj_mgr_err("peer("QDF_MAC_ADDR_FMT") ref cnt is 0",
1429 			    QDF_MAC_ADDR_REF(macaddr));
1430 		WLAN_OBJMGR_BUG(0);
1431 		return;
1432 	}
1433 
1434 	status = wlan_objmgr_peer_release_debug_id_ref(peer, id);
1435 	if (QDF_IS_STATUS_ERROR(status))
1436 		return;
1437 
1438 	/* Provide synchronization from the access to add peer
1439 	 * to logically deleted peer list.
1440 	 */
1441 	wlan_peer_obj_lock(peer);
1442 	/* Decrement ref count, free peer object, if ref count == 0 */
1443 	if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) {
1444 		wlan_peer_obj_unlock(peer);
1445 		wlan_objmgr_peer_obj_destroy(peer);
1446 	} else {
1447 		wlan_peer_obj_unlock(peer);
1448 	}
1449 }
1450 
1451 qdf_export_symbol(wlan_objmgr_peer_release_ref);
1452 #endif
1453 
1454 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
1455 void
1456 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer,
1457 			       QDF_TRACE_LEVEL log_level)
1458 {
1459 	wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg, log_level);
1460 }
1461 
1462 uint32_t
1463 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer,
1464 				  enum wlan_umac_comp_id id)
1465 {
1466 	return qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id]);
1467 }
1468 #else
1469 void
1470 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer,
1471 			       QDF_TRACE_LEVEL log_level)
1472 {
1473 	uint32_t pending_ref;
1474 
1475 	pending_ref = qdf_atomic_read(&peer->peer_objmgr.ref_cnt);
1476 	obj_mgr_log_level(log_level, "Pending refs -- %d", pending_ref);
1477 }
1478 
1479 uint32_t
1480 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer,
1481 				  enum wlan_umac_comp_id id)
1482 {
1483 	return 0;
1484 }
1485 #endif
1486 
1487 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE
1488 QDF_STATUS wlan_peer_update_macaddr(struct wlan_objmgr_peer *peer,
1489 				    uint8_t *new_macaddr)
1490 {
1491 	struct wlan_objmgr_psoc *psoc;
1492 	struct wlan_objmgr_vdev *vdev;
1493 	uint8_t *macaddr;
1494 	QDF_STATUS status;
1495 
1496 	if (!peer) {
1497 		obj_mgr_err("PEER is NULL");
1498 		return QDF_STATUS_E_FAILURE;
1499 	}
1500 
1501 	macaddr = wlan_peer_get_macaddr(peer);
1502 
1503 	vdev = wlan_peer_get_vdev(peer);
1504 	if (!vdev) {
1505 		obj_mgr_err("VDEV is NULL for peer(" QDF_MAC_ADDR_FMT ")",
1506 			    QDF_MAC_ADDR_REF(macaddr));
1507 		return QDF_STATUS_E_FAILURE;
1508 	}
1509 
1510 	/* get PSOC from VDEV, if it is NULL, return */
1511 	psoc = wlan_vdev_get_psoc(vdev);
1512 	if (!psoc) {
1513 		obj_mgr_err("PSOC is NULL for peer(" QDF_MAC_ADDR_FMT ")",
1514 			    QDF_MAC_ADDR_REF(macaddr));
1515 		return QDF_STATUS_E_FAILURE;
1516 	}
1517 
1518 	status = wlan_objmgr_psoc_peer_detach(psoc, peer);
1519 	if (QDF_IS_STATUS_ERROR(status)) {
1520 		obj_mgr_err("Failed to detach peer(" QDF_MAC_ADDR_FMT ")",
1521 			    QDF_MAC_ADDR_REF(macaddr));
1522 		return status;
1523 	}
1524 
1525 	wlan_peer_set_macaddr(peer, new_macaddr);
1526 
1527 	status = wlan_objmgr_psoc_peer_attach(psoc, peer);
1528 	if (QDF_IS_STATUS_ERROR(status)) {
1529 		obj_mgr_err("Failed to attach peer(" QDF_MAC_ADDR_FMT ")",
1530 			    QDF_MAC_ADDR_REF(new_macaddr));
1531 		return status;
1532 	}
1533 	return QDF_STATUS_SUCCESS;
1534 }
1535 #endif
1536