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