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