xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c (revision 19ceffca9d494f2431432fa8123aa187c91cb4fb)
1 /*
2  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021 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_STATUS wlan_objmgr_peer_component_obj_detach(
621 		struct wlan_objmgr_peer *peer,
622 		enum wlan_umac_comp_id id,
623 		void *comp_priv_obj)
624 {
625 	QDF_STATUS obj_status;
626 
627 	/* component id is invalid */
628 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
629 		return QDF_STATUS_MAXCOMP_FAIL;
630 
631 	wlan_peer_obj_lock(peer);
632 	/* If there is a invalid entry, return failure */
633 	if (peer->peer_comp_priv_obj[id] != comp_priv_obj) {
634 		peer->obj_status[id] = QDF_STATUS_E_FAILURE;
635 		wlan_peer_obj_unlock(peer);
636 		return QDF_STATUS_E_FAILURE;
637 	}
638 	/* Reset the pointer to NULL */
639 	peer->peer_comp_priv_obj[id] = NULL;
640 	peer->obj_status[id] = QDF_STATUS_SUCCESS;
641 	wlan_peer_obj_unlock(peer);
642 
643 	/* If PEER object status is partially destroyed means, this API is
644 	invoked with differnt context, this block should be executed for async
645 	components only */
646 	if ((peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) ||
647 	    (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) {
648 		/* Derive object status */
649 		obj_status = wlan_objmgr_peer_object_status(peer);
650 		if (obj_status == QDF_STATUS_SUCCESS) {
651 			/*Update the status as Deleted, if full object
652 				deletion is in progress */
653 			if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
654 				peer->obj_state = WLAN_OBJ_STATE_DELETED;
655 			/* Move to creation state, since this component
656 			deletion alone requested */
657 			if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
658 				peer->obj_state = WLAN_OBJ_STATE_CREATED;
659 		/* Object status is failure */
660 		} else if (obj_status == QDF_STATUS_E_FAILURE) {
661 			/*Update the status as Deletion failed, if full object
662 				deletion is in progress */
663 			if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
664 				peer->obj_state =
665 					WLAN_OBJ_STATE_DELETION_FAILED;
666 			/* Move to creation state, since this component
667 			deletion alone requested (do not block other
668 			components) */
669 			if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
670 				peer->obj_state = WLAN_OBJ_STATE_CREATED;
671 		}
672 
673 			/* Delete peer object */
674 		if ((obj_status == QDF_STATUS_SUCCESS)  &&
675 		    (peer->obj_state == WLAN_OBJ_STATE_DELETED)) {
676 			/* Free the peer object */
677 			return wlan_objmgr_peer_obj_free(peer);
678 		}
679 	}
680 
681 	return QDF_STATUS_SUCCESS;
682 }
683 
684 
685 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_creation(
686 		struct wlan_objmgr_peer *peer,
687 		enum wlan_umac_comp_id id)
688 {
689 	wlan_objmgr_peer_create_handler handler;
690 	void *arg;
691 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
692 
693 	/* Component id is invalid */
694 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
695 		return QDF_STATUS_MAXCOMP_FAIL;
696 
697 	wlan_peer_obj_lock(peer);
698 	/* If component object is already created, delete old
699 		component object, then invoke creation */
700 	if (peer->peer_comp_priv_obj[id]) {
701 		wlan_peer_obj_unlock(peer);
702 		return QDF_STATUS_E_FAILURE;
703 	}
704 	wlan_peer_obj_unlock(peer);
705 
706 	/* Invoke registered create handlers */
707 	handler = g_umac_glb_obj->peer_create_handler[id];
708 	arg = g_umac_glb_obj->peer_create_handler_arg[id];
709 	if (handler)
710 		peer->obj_status[id] = handler(peer, arg);
711 	else
712 		return QDF_STATUS_E_FAILURE;
713 
714 	/* If object status is created, then only handle this object status */
715 	if (peer->obj_state == WLAN_OBJ_STATE_CREATED) {
716 		/* Derive object status */
717 		obj_status = wlan_objmgr_peer_object_status(peer);
718 		/* Move PDEV object state to Partially created state */
719 		if (obj_status == QDF_STATUS_COMP_ASYNC) {
720 			/*TODO atomic */
721 			peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
722 		}
723 	}
724 
725 	return obj_status;
726 }
727 
728 
729 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_deletion(
730 		struct wlan_objmgr_peer *peer,
731 		enum wlan_umac_comp_id id)
732 {
733 	wlan_objmgr_peer_destroy_handler handler;
734 	void *arg;
735 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
736 
737 	/* component id is invalid */
738 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
739 		return QDF_STATUS_MAXCOMP_FAIL;
740 
741 	wlan_peer_obj_lock(peer);
742 	/* Component object was never created, invalid operation */
743 	if (!peer->peer_comp_priv_obj[id]) {
744 		wlan_peer_obj_unlock(peer);
745 		return QDF_STATUS_E_FAILURE;
746 	}
747 
748 	wlan_peer_obj_unlock(peer);
749 
750 	/* Invoke registered destroy handlers */
751 	handler = g_umac_glb_obj->peer_destroy_handler[id];
752 	arg = g_umac_glb_obj->peer_destroy_handler_arg[id];
753 	if (handler)
754 		peer->obj_status[id] = handler(peer, arg);
755 	else
756 		return QDF_STATUS_E_FAILURE;
757 
758 	/* If object status is created, then only handle this object status */
759 	if (peer->obj_state == WLAN_OBJ_STATE_CREATED) {
760 		obj_status = wlan_objmgr_peer_object_status(peer);
761 			/* move object state to DEL progress */
762 		if (obj_status == QDF_STATUS_COMP_ASYNC)
763 			peer->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS;
764 	}
765 	return obj_status;
766 }
767 
768 void *wlan_objmgr_peer_get_comp_private_obj(
769 		struct wlan_objmgr_peer *peer,
770 		enum wlan_umac_comp_id id)
771 {
772 	void *comp_priv_obj;
773 
774 	/* component id is invalid */
775 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
776 		QDF_BUG(0);
777 		return NULL;
778 	}
779 
780 	if (!peer) {
781 		QDF_BUG(0);
782 		return NULL;
783 	}
784 
785 	comp_priv_obj = peer->peer_comp_priv_obj[id];
786 	return comp_priv_obj;
787 }
788 qdf_export_symbol(wlan_objmgr_peer_get_comp_private_obj);
789 
790 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
791 static inline void
792 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer,
793 				  wlan_objmgr_ref_dbgid id)
794 {
795 	qdf_atomic_inc(&peer->peer_objmgr.ref_id_dbg[id]);
796 }
797 #else
798 static inline void
799 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer,
800 				  wlan_objmgr_ref_dbgid id) {}
801 #endif
802 
803 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
804 static QDF_STATUS
805 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer,
806 				      wlan_objmgr_ref_dbgid id)
807 {
808 	if (!qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id])) {
809 		uint8_t *macaddr;
810 
811 		macaddr = wlan_peer_get_macaddr(peer);
812 		obj_mgr_err(
813 		"peer("QDF_MAC_ADDR_FMT") ref was not taken by %d",
814 			QDF_MAC_ADDR_REF(macaddr), id);
815 		wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg,
816 					  QDF_TRACE_LEVEL_FATAL);
817 		WLAN_OBJMGR_BUG(0);
818 		return QDF_STATUS_E_FAILURE;
819 	}
820 
821 	qdf_atomic_dec(&peer->peer_objmgr.ref_id_dbg[id]);
822 	return QDF_STATUS_SUCCESS;
823 }
824 #else
825 static QDF_STATUS
826 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer,
827 				      wlan_objmgr_ref_dbgid id)
828 {
829 	return QDF_STATUS_SUCCESS;
830 }
831 #endif
832 
833 #ifdef WLAN_OBJMGR_REF_ID_TRACE
834 static inline void
835 wlan_objmgr_peer_ref_trace(struct wlan_objmgr_peer *peer,
836 			   wlan_objmgr_ref_dbgid id,
837 			   const char *func, int line)
838 {
839 	struct wlan_objmgr_trace *trace;
840 
841 	trace = &peer->peer_objmgr.trace;
842 
843 	if (func)
844 		wlan_objmgr_trace_ref(&trace->references[id].head,
845 				      trace, func, line);
846 }
847 
848 static inline void
849 wlan_objmgr_peer_deref_trace(struct wlan_objmgr_peer *peer,
850 			     wlan_objmgr_ref_dbgid id,
851 			     const char *func, int line)
852 {
853 	struct wlan_objmgr_trace *trace;
854 
855 	trace = &peer->peer_objmgr.trace;
856 	if (func)
857 		wlan_objmgr_trace_ref(&trace->dereferences[id].head,
858 				      trace, func, line);
859 }
860 #endif
861 
862 #ifdef WLAN_OBJMGR_REF_ID_TRACE
863 void wlan_objmgr_peer_get_ref_debug(struct wlan_objmgr_peer *peer,
864 				    wlan_objmgr_ref_dbgid id,
865 				    const char *func, int line)
866 {
867 	if (!peer) {
868 		obj_mgr_err("peer obj is NULL for %d", id);
869 		QDF_ASSERT(0);
870 		return;
871 	}
872 	/* Increment ref count */
873 	qdf_atomic_inc(&peer->peer_objmgr.ref_cnt);
874 	wlan_objmgr_peer_get_debug_id_ref(peer, id);
875 
876 	wlan_objmgr_peer_ref_trace(peer, id, func, line);
877 	return;
878 }
879 
880 qdf_export_symbol(wlan_objmgr_peer_get_ref_debug);
881 #else
882 void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer,
883 			      wlan_objmgr_ref_dbgid id)
884 {
885 	if (!peer) {
886 		obj_mgr_err("peer obj is NULL for %d", id);
887 		QDF_ASSERT(0);
888 		return;
889 	}
890 	/* Increment ref count */
891 	qdf_atomic_inc(&peer->peer_objmgr.ref_cnt);
892 	wlan_objmgr_peer_get_debug_id_ref(peer, id);
893 }
894 
895 qdf_export_symbol(wlan_objmgr_peer_get_ref);
896 #endif
897 
898 #ifdef WLAN_OBJMGR_REF_ID_TRACE
899 QDF_STATUS wlan_objmgr_peer_try_get_ref_debug(struct wlan_objmgr_peer *peer,
900 					      wlan_objmgr_ref_dbgid id,
901 					      const char *func, int line)
902 {
903 	if (!peer) {
904 		obj_mgr_err("peer obj is NULL for %d", id);
905 		QDF_ASSERT(0);
906 		return QDF_STATUS_E_FAILURE;
907 	}
908 
909 	wlan_peer_obj_lock(peer);
910 	if (peer->obj_state != WLAN_OBJ_STATE_CREATED) {
911 		wlan_peer_obj_unlock(peer);
912 		if (peer->peer_objmgr.print_cnt++ <=
913 				WLAN_OBJMGR_RATELIMIT_THRESH) {
914 			uint8_t *macaddr;
915 
916 			macaddr = wlan_peer_get_macaddr(peer);
917 			obj_mgr_debug(
918 			"peer(" QDF_MAC_ADDR_FMT ") not in Created st(%d)",
919 			QDF_MAC_ADDR_REF(macaddr),
920 			peer->obj_state);
921 		}
922 		return QDF_STATUS_E_RESOURCES;
923 	}
924 
925 	wlan_objmgr_peer_get_ref_debug(peer, id, func, line);
926 	wlan_peer_obj_unlock(peer);
927 
928 	return QDF_STATUS_SUCCESS;
929 }
930 
931 qdf_export_symbol(wlan_objmgr_peer_try_get_ref_debug);
932 #else
933 QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer,
934 					wlan_objmgr_ref_dbgid id)
935 {
936 	if (!peer) {
937 		obj_mgr_err("peer obj is NULL for %d", id);
938 		QDF_ASSERT(0);
939 		return QDF_STATUS_E_FAILURE;
940 	}
941 
942 	wlan_peer_obj_lock(peer);
943 	if (peer->obj_state != WLAN_OBJ_STATE_CREATED) {
944 		wlan_peer_obj_unlock(peer);
945 		if (peer->peer_objmgr.print_cnt++ <=
946 				WLAN_OBJMGR_RATELIMIT_THRESH) {
947 			uint8_t *macaddr;
948 
949 			macaddr = wlan_peer_get_macaddr(peer);
950 			obj_mgr_debug(
951 			"peer(" QDF_MAC_ADDR_FMT ") not in Created st(%d)",
952 			QDF_MAC_ADDR_REF(macaddr),
953 			peer->obj_state);
954 		}
955 		return QDF_STATUS_E_RESOURCES;
956 	}
957 
958 	wlan_objmgr_peer_get_ref(peer, id);
959 	wlan_peer_obj_unlock(peer);
960 
961 	return QDF_STATUS_SUCCESS;
962 }
963 
964 qdf_export_symbol(wlan_objmgr_peer_try_get_ref);
965 #endif
966 
967 #ifdef WLAN_OBJMGR_REF_ID_TRACE
968 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc_debug(
969 					struct wlan_peer_list *peer_list,
970 					uint8_t hash_index,
971 					struct wlan_objmgr_peer *peer,
972 					wlan_objmgr_ref_dbgid dbg_id,
973 					const char *func, int line)
974 {
975 	struct wlan_objmgr_peer *peer_next = NULL;
976 	qdf_list_node_t *psoc_node = NULL;
977 	qdf_list_node_t *prev_psoc_node = NULL;
978 	qdf_list_t *obj_list;
979 
980 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
981 	obj_list = &peer_list->peer_hash[hash_index];
982 
983 	prev_psoc_node = &peer->psoc_peer;
984 	while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
985 						QDF_STATUS_SUCCESS) {
986 		peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
987 					     psoc_peer);
988 
989 		if (wlan_objmgr_peer_try_get_ref_debug(peer_next, dbg_id,
990 						       func, line) ==
991 				QDF_STATUS_SUCCESS) {
992 			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
993 			return peer_next;
994 		}
995 
996 		prev_psoc_node = psoc_node;
997 	}
998 
999 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1000 
1001 	return NULL;
1002 }
1003 #else
1004 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc(
1005 					struct wlan_peer_list *peer_list,
1006 					uint8_t hash_index,
1007 					struct wlan_objmgr_peer *peer,
1008 					wlan_objmgr_ref_dbgid dbg_id)
1009 {
1010 	struct wlan_objmgr_peer *peer_next = NULL;
1011 	qdf_list_node_t *psoc_node = NULL;
1012 	qdf_list_node_t *prev_psoc_node = NULL;
1013 	qdf_list_t *obj_list;
1014 
1015 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1016 	obj_list = &peer_list->peer_hash[hash_index];
1017 
1018 	prev_psoc_node = &peer->psoc_peer;
1019 	while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
1020 						QDF_STATUS_SUCCESS) {
1021 		peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
1022 					     psoc_peer);
1023 
1024 		if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) ==
1025 				QDF_STATUS_SUCCESS) {
1026 			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1027 			return peer_next;
1028 		}
1029 
1030 		prev_psoc_node = psoc_node;
1031 	}
1032 
1033 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1034 
1035 	return NULL;
1036 }
1037 #endif
1038 
1039 #ifdef WLAN_OBJMGR_REF_ID_TRACE
1040 struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head_debug(
1041 				struct wlan_objmgr_vdev *vdev,
1042 				qdf_list_t *peer_list,
1043 				wlan_objmgr_ref_dbgid dbg_id,
1044 				const char *func, int line)
1045 {
1046 	struct wlan_objmgr_peer *peer;
1047 	qdf_list_node_t *vdev_node = NULL;
1048 	qdf_list_node_t *prev_vdev_node = NULL;
1049 
1050 	wlan_vdev_obj_lock(vdev);
1051 
1052 	if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) {
1053 		wlan_vdev_obj_unlock(vdev);
1054 		return NULL;
1055 	}
1056 
1057 	do {
1058 		peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
1059 					vdev_peer);
1060 
1061 		if (wlan_objmgr_peer_try_get_ref_debug(peer, dbg_id,
1062 						       func, line) ==
1063 				QDF_STATUS_SUCCESS) {
1064 			wlan_vdev_obj_unlock(vdev);
1065 			return peer;
1066 		}
1067 
1068 		prev_vdev_node = vdev_node;
1069 	} while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
1070 							QDF_STATUS_SUCCESS);
1071 
1072 	wlan_vdev_obj_unlock(vdev);
1073 
1074 	return NULL;
1075 }
1076 #else
1077 struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head(
1078 				struct wlan_objmgr_vdev *vdev,
1079 				qdf_list_t *peer_list,
1080 				wlan_objmgr_ref_dbgid dbg_id)
1081 {
1082 	struct wlan_objmgr_peer *peer;
1083 	qdf_list_node_t *vdev_node = NULL;
1084 	qdf_list_node_t *prev_vdev_node = NULL;
1085 
1086 	wlan_vdev_obj_lock(vdev);
1087 
1088 	if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) {
1089 		wlan_vdev_obj_unlock(vdev);
1090 		return NULL;
1091 	}
1092 
1093 	do {
1094 		peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
1095 						vdev_peer);
1096 
1097 		if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
1098 				QDF_STATUS_SUCCESS) {
1099 			wlan_vdev_obj_unlock(vdev);
1100 			return peer;
1101 		}
1102 
1103 		prev_vdev_node = vdev_node;
1104 	} while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
1105 							QDF_STATUS_SUCCESS);
1106 
1107 	wlan_vdev_obj_unlock(vdev);
1108 
1109 	return NULL;
1110 }
1111 #endif
1112 
1113 #ifdef WLAN_OBJMGR_REF_ID_TRACE
1114 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev_debug(
1115 					struct wlan_objmgr_vdev *vdev,
1116 					qdf_list_t *peer_list,
1117 					struct wlan_objmgr_peer *peer,
1118 					wlan_objmgr_ref_dbgid dbg_id,
1119 					const char *func, int line)
1120 {
1121 	struct wlan_objmgr_peer *peer_next;
1122 	qdf_list_node_t *vdev_node = NULL;
1123 	qdf_list_node_t *prev_vdev_node = NULL;
1124 
1125 	if (!peer)
1126 		return NULL;
1127 
1128 	wlan_vdev_obj_lock(vdev);
1129 
1130 	prev_vdev_node = &peer->vdev_peer;
1131 	while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
1132 						QDF_STATUS_SUCCESS) {
1133 		peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
1134 					     vdev_peer);
1135 
1136 		if (wlan_objmgr_peer_try_get_ref_debug(peer_next, dbg_id,
1137 						       func, line) ==
1138 				QDF_STATUS_SUCCESS) {
1139 			wlan_vdev_obj_unlock(vdev);
1140 			return peer_next;
1141 		}
1142 
1143 		prev_vdev_node = vdev_node;
1144 	}
1145 
1146 	wlan_vdev_obj_unlock(vdev);
1147 
1148 	return NULL;
1149 }
1150 #else
1151 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev(
1152 					struct wlan_objmgr_vdev *vdev,
1153 					qdf_list_t *peer_list,
1154 					struct wlan_objmgr_peer *peer,
1155 					wlan_objmgr_ref_dbgid dbg_id)
1156 {
1157 	struct wlan_objmgr_peer *peer_next;
1158 	qdf_list_node_t *vdev_node = NULL;
1159 	qdf_list_node_t *prev_vdev_node = NULL;
1160 
1161 	if (!peer)
1162 		return NULL;
1163 
1164 	wlan_vdev_obj_lock(vdev);
1165 
1166 	prev_vdev_node = &peer->vdev_peer;
1167 	while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
1168 						QDF_STATUS_SUCCESS) {
1169 		peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
1170 					vdev_peer);
1171 
1172 		if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) ==
1173 				QDF_STATUS_SUCCESS) {
1174 			wlan_vdev_obj_unlock(vdev);
1175 			return peer_next;
1176 		}
1177 
1178 		prev_vdev_node = vdev_node;
1179 	}
1180 
1181 	wlan_vdev_obj_unlock(vdev);
1182 
1183 	return NULL;
1184 }
1185 #endif
1186 
1187 #ifdef WLAN_OBJMGR_REF_ID_TRACE
1188 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head_debug(
1189 					struct wlan_peer_list *peer_list,
1190 					uint8_t hash_index,
1191 					wlan_objmgr_ref_dbgid dbg_id,
1192 					const char *func, int line)
1193 {
1194 	struct wlan_objmgr_peer *peer;
1195 	qdf_list_node_t *psoc_node = NULL;
1196 	qdf_list_node_t *prev_psoc_node = NULL;
1197 	qdf_list_t *obj_list;
1198 
1199 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1200 	obj_list = &peer_list->peer_hash[hash_index];
1201 
1202 	if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) {
1203 		qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1204 		return NULL;
1205 	}
1206 
1207 	do {
1208 		peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
1209 					psoc_peer);
1210 		if (wlan_objmgr_peer_try_get_ref_debug(peer, dbg_id,
1211 						       func, line) ==
1212 				QDF_STATUS_SUCCESS) {
1213 			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1214 			return peer;
1215 		}
1216 
1217 		prev_psoc_node = psoc_node;
1218 	} while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
1219 						QDF_STATUS_SUCCESS);
1220 
1221 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1222 	return NULL;
1223 }
1224 #else
1225 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head(
1226 					struct wlan_peer_list *peer_list,
1227 					uint8_t hash_index,
1228 					wlan_objmgr_ref_dbgid dbg_id)
1229 {
1230 	struct wlan_objmgr_peer *peer;
1231 	qdf_list_node_t *psoc_node = NULL;
1232 	qdf_list_node_t *prev_psoc_node = NULL;
1233 	qdf_list_t *obj_list;
1234 
1235 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1236 	obj_list = &peer_list->peer_hash[hash_index];
1237 
1238 	if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) {
1239 		qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1240 		return NULL;
1241 	}
1242 
1243 	do {
1244 		peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
1245 						psoc_peer);
1246 		if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
1247 				QDF_STATUS_SUCCESS) {
1248 			qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1249 			return peer;
1250 		}
1251 
1252 		prev_psoc_node = psoc_node;
1253 	} while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
1254 						QDF_STATUS_SUCCESS);
1255 
1256 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1257 	return NULL;
1258 }
1259 #endif
1260 
1261 #ifdef WLAN_OBJMGR_REF_ID_TRACE
1262 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref_debug(
1263 					struct wlan_peer_list *peer_list,
1264 					uint8_t hash_index,
1265 					wlan_objmgr_ref_dbgid dbg_id,
1266 					const char *func, int line)
1267 {
1268 	struct wlan_objmgr_peer *peer;
1269 	qdf_list_t *obj_list;
1270 
1271 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1272 	obj_list = &peer_list->peer_hash[hash_index];
1273 
1274 	peer = wlan_psoc_peer_list_peek_head(obj_list);
1275 
1276 	/* This API is invoked by caller, only when caller need to access the
1277 	 * peer object, though object is not in active state, this API should be
1278 	 * used carefully, where multiple object frees are not triggered
1279 	 */
1280 	if (peer)
1281 		wlan_objmgr_peer_get_ref_debug(peer, dbg_id, func, line);
1282 
1283 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1284 
1285 	return peer;
1286 }
1287 #else
1288 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref(
1289 					struct wlan_peer_list *peer_list,
1290 					uint8_t hash_index,
1291 					wlan_objmgr_ref_dbgid dbg_id)
1292 {
1293 	struct wlan_objmgr_peer *peer;
1294 	qdf_list_t *obj_list;
1295 
1296 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1297 	obj_list = &peer_list->peer_hash[hash_index];
1298 
1299 	peer = wlan_psoc_peer_list_peek_head(obj_list);
1300 
1301 	/* This API is invoked by caller, only when caller need to access the
1302 	 * peer object, though object is not in active state, this API should be
1303 	 * used carefully, where multiple object frees are not triggered
1304 	 */
1305 	if (peer)
1306 		wlan_objmgr_peer_get_ref(peer, dbg_id);
1307 
1308 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1309 
1310 	return peer;
1311 }
1312 #endif
1313 
1314 #ifdef WLAN_OBJMGR_REF_ID_TRACE
1315 struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref_debug(
1316 			struct wlan_peer_list *peer_list, uint8_t hash_index,
1317 			struct wlan_objmgr_peer *peer,
1318 			wlan_objmgr_ref_dbgid dbg_id,
1319 			const char *func, int line)
1320 {
1321 	qdf_list_t *obj_list;
1322 	struct wlan_objmgr_peer *peer_next;
1323 
1324 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1325 	obj_list = &peer_list->peer_hash[hash_index];
1326 
1327 	peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer);
1328 	/* This API is invoked by caller, only when caller need to access the
1329 	 * peer object, though object is not in active state, this API should be
1330 	 * used carefully, where multiple free on object are not triggered
1331 	 */
1332 	if (peer_next)
1333 		wlan_objmgr_peer_get_ref_debug(peer_next, dbg_id, func, line);
1334 
1335 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1336 
1337 	return peer_next;
1338 }
1339 #else
1340 struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref(
1341 			struct wlan_peer_list *peer_list, uint8_t hash_index,
1342 			struct wlan_objmgr_peer *peer,
1343 			wlan_objmgr_ref_dbgid dbg_id)
1344 {
1345 	qdf_list_t *obj_list;
1346 	struct wlan_objmgr_peer *peer_next;
1347 
1348 	qdf_spin_lock_bh(&peer_list->peer_list_lock);
1349 	obj_list = &peer_list->peer_hash[hash_index];
1350 
1351 	peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer);
1352 	/* This API is invoked by caller, only when caller need to access the
1353 	 * peer object, though object is not in active state, this API should be
1354 	 * used carefully, where multiple free on object are not triggered
1355 	 */
1356 	if (peer_next)
1357 		wlan_objmgr_peer_get_ref(peer_next, dbg_id);
1358 
1359 	qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1360 
1361 	return peer_next;
1362 }
1363 #endif
1364 
1365 #ifdef WLAN_OBJMGR_REF_ID_TRACE
1366 void wlan_objmgr_peer_release_ref_debug(struct wlan_objmgr_peer *peer,
1367 					wlan_objmgr_ref_dbgid id,
1368 					const char *func, int line)
1369 {
1370 	QDF_STATUS status;
1371 
1372 	if (!peer) {
1373 		obj_mgr_err("peer obj is NULL for %d", id);
1374 		QDF_ASSERT(0);
1375 		return;
1376 	}
1377 
1378 	if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) {
1379 		uint8_t *macaddr;
1380 
1381 		macaddr = wlan_peer_get_macaddr(peer);
1382 		obj_mgr_err("peer("QDF_MAC_ADDR_FMT") ref cnt is 0",
1383 				QDF_MAC_ADDR_REF(macaddr));
1384 		WLAN_OBJMGR_BUG(0);
1385 		return;
1386 	}
1387 
1388 	status = wlan_objmgr_peer_release_debug_id_ref(peer, id);
1389 	if (QDF_IS_STATUS_ERROR(status))
1390 		return;
1391 
1392 	wlan_objmgr_peer_deref_trace(peer, id, func, line);
1393 	/* Provide synchronization from the access to add peer
1394 	 * to logically deleted peer list.
1395 	 */
1396 	wlan_peer_obj_lock(peer);
1397 	/* Decrement ref count, free peer object, if ref count == 0 */
1398 	if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) {
1399 		wlan_peer_obj_unlock(peer);
1400 		wlan_objmgr_peer_obj_destroy(peer);
1401 	} else {
1402 		wlan_peer_obj_unlock(peer);
1403 	}
1404 
1405 	return;
1406 }
1407 
1408 qdf_export_symbol(wlan_objmgr_peer_release_ref_debug);
1409 #else
1410 void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer,
1411 				  wlan_objmgr_ref_dbgid id)
1412 {
1413 	QDF_STATUS status;
1414 
1415 	if (!peer) {
1416 		obj_mgr_err("peer obj is NULL for %d", id);
1417 		QDF_ASSERT(0);
1418 		return;
1419 	}
1420 
1421 	if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) {
1422 		uint8_t *macaddr;
1423 
1424 		macaddr = wlan_peer_get_macaddr(peer);
1425 		obj_mgr_err("peer("QDF_MAC_ADDR_FMT") ref cnt is 0",
1426 			    QDF_MAC_ADDR_REF(macaddr));
1427 		WLAN_OBJMGR_BUG(0);
1428 		return;
1429 	}
1430 
1431 	status = wlan_objmgr_peer_release_debug_id_ref(peer, id);
1432 	if (QDF_IS_STATUS_ERROR(status))
1433 		return;
1434 
1435 	/* Provide synchronization from the access to add peer
1436 	 * to logically deleted peer list.
1437 	 */
1438 	wlan_peer_obj_lock(peer);
1439 	/* Decrement ref count, free peer object, if ref count == 0 */
1440 	if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) {
1441 		wlan_peer_obj_unlock(peer);
1442 		wlan_objmgr_peer_obj_destroy(peer);
1443 	} else {
1444 		wlan_peer_obj_unlock(peer);
1445 	}
1446 }
1447 
1448 qdf_export_symbol(wlan_objmgr_peer_release_ref);
1449 #endif
1450 
1451 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
1452 void
1453 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer,
1454 			       QDF_TRACE_LEVEL log_level)
1455 {
1456 	wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg, log_level);
1457 }
1458 
1459 uint32_t
1460 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer,
1461 				  enum wlan_umac_comp_id id)
1462 {
1463 	return qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id]);
1464 }
1465 #else
1466 void
1467 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer,
1468 			       QDF_TRACE_LEVEL log_level)
1469 {
1470 	uint32_t pending_ref;
1471 
1472 	pending_ref = qdf_atomic_read(&peer->peer_objmgr.ref_cnt);
1473 	obj_mgr_log_level(log_level, "Pending refs -- %d", pending_ref);
1474 }
1475 
1476 uint32_t
1477 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer,
1478 				  enum wlan_umac_comp_id id)
1479 {
1480 	return 0;
1481 }
1482 #endif
1483 
1484 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE
1485 QDF_STATUS wlan_peer_update_macaddr(struct wlan_objmgr_peer *peer,
1486 				    uint8_t *new_macaddr)
1487 {
1488 	struct wlan_objmgr_psoc *psoc;
1489 	struct wlan_objmgr_vdev *vdev;
1490 	uint8_t *macaddr;
1491 	QDF_STATUS status;
1492 
1493 	if (!peer) {
1494 		obj_mgr_err("PEER is NULL");
1495 		return QDF_STATUS_E_FAILURE;
1496 	}
1497 
1498 	macaddr = wlan_peer_get_macaddr(peer);
1499 
1500 	vdev = wlan_peer_get_vdev(peer);
1501 	if (!vdev) {
1502 		obj_mgr_err("VDEV is NULL for peer(" QDF_MAC_ADDR_FMT ")",
1503 			    QDF_MAC_ADDR_REF(macaddr));
1504 		return QDF_STATUS_E_FAILURE;
1505 	}
1506 
1507 	/* get PSOC from VDEV, if it is NULL, return */
1508 	psoc = wlan_vdev_get_psoc(vdev);
1509 	if (!psoc) {
1510 		obj_mgr_err("PSOC is NULL for peer(" QDF_MAC_ADDR_FMT ")",
1511 			    QDF_MAC_ADDR_REF(macaddr));
1512 		return QDF_STATUS_E_FAILURE;
1513 	}
1514 
1515 	status = wlan_objmgr_psoc_peer_detach(psoc, peer);
1516 	if (QDF_IS_STATUS_ERROR(status)) {
1517 		obj_mgr_err("Failed to detach peer(" QDF_MAC_ADDR_FMT ")",
1518 			    QDF_MAC_ADDR_REF(macaddr));
1519 		return status;
1520 	}
1521 
1522 	wlan_peer_set_macaddr(peer, new_macaddr);
1523 
1524 	status = wlan_objmgr_psoc_peer_attach(psoc, peer);
1525 	if (QDF_IS_STATUS_ERROR(status)) {
1526 		obj_mgr_err("Failed to attach peer(" QDF_MAC_ADDR_FMT ")",
1527 			    QDF_MAC_ADDR_REF(new_macaddr));
1528 		return status;
1529 	}
1530 	return QDF_STATUS_SUCCESS;
1531 }
1532 #endif
1533