xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c (revision 11f5a63a6cbdda84849a730de22f0a71e635d58c)
1 /*
2  * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 
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 <qdf_mem.h>
27 #include <qdf_module.h>
28 #include "wlan_objmgr_global_obj_i.h"
29 #include "wlan_objmgr_psoc_obj_i.h"
30 #include "wlan_objmgr_pdev_obj_i.h"
31 #include "wlan_objmgr_vdev_obj_i.h"
32 
33 /**
34  ** APIs to Create/Delete Global object APIs
35  */
36 
37 static QDF_STATUS wlan_objmgr_vdev_object_status(
38 		struct wlan_objmgr_vdev *vdev)
39 {
40 	uint8_t id;
41 	QDF_STATUS status = QDF_STATUS_SUCCESS;
42 
43 	wlan_vdev_obj_lock(vdev);
44 
45 	/* Iterate through all components to derive the object status */
46 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
47 		/* If component disabled, Ignore */
48 		if (vdev->obj_status[id] == QDF_STATUS_COMP_DISABLED) {
49 			continue;
50 		/*
51 		 * If component operates in Async, status is Partially created,
52 		 * break
53 		 */
54 		} else if (vdev->obj_status[id] == QDF_STATUS_COMP_ASYNC) {
55 			if (!vdev->vdev_comp_priv_obj[id]) {
56 				status = QDF_STATUS_COMP_ASYNC;
57 				break;
58 			}
59 		/*
60 		 * If component failed to allocate its object, treat it as
61 		 * failure, complete object need to be cleaned up
62 		 */
63 		} else if ((vdev->obj_status[id] == QDF_STATUS_E_NOMEM) ||
64 			(vdev->obj_status[id] == QDF_STATUS_E_FAILURE)) {
65 			status = QDF_STATUS_E_FAILURE;
66 			break;
67 		}
68 	}
69 	wlan_vdev_obj_unlock(vdev);
70 
71 	return status;
72 }
73 
74 static QDF_STATUS wlan_objmgr_vdev_obj_free(struct wlan_objmgr_vdev *vdev)
75 {
76 	struct wlan_objmgr_pdev *pdev;
77 	struct wlan_objmgr_psoc *psoc;
78 
79 	if (!vdev) {
80 		obj_mgr_err("vdev is NULL");
81 		return QDF_STATUS_E_FAILURE;
82 	}
83 	/* if PDEV is NULL, return */
84 	pdev = wlan_vdev_get_pdev(vdev);
85 	if (!pdev) {
86 		obj_mgr_err("pdev is NULL for vdev-id: %d",
87 			vdev->vdev_objmgr.vdev_id);
88 		return QDF_STATUS_E_FAILURE;
89 	}
90 	psoc = wlan_pdev_get_psoc(pdev);
91 	if (!psoc) {
92 		obj_mgr_err("psoc is NULL in pdev");
93 		return QDF_STATUS_E_FAILURE;
94 	}
95 
96 	/* Detach VDEV from PDEV VDEV's list */
97 	if (wlan_objmgr_pdev_vdev_detach(pdev, vdev) ==
98 					QDF_STATUS_E_FAILURE)
99 		return QDF_STATUS_E_FAILURE;
100 
101 	/* Detach VDEV from PSOC VDEV's list */
102 	if (wlan_objmgr_psoc_vdev_detach(psoc, vdev) ==
103 					 QDF_STATUS_E_FAILURE)
104 		return QDF_STATUS_E_FAILURE;
105 
106 	qdf_spinlock_destroy(&vdev->vdev_lock);
107 
108 	qdf_mem_free(vdev->vdev_mlme.bss_chan);
109 	qdf_mem_free(vdev->vdev_mlme.des_chan);
110 	qdf_mem_free(vdev->vdev_nif.osdev);
111 	qdf_mem_free(vdev);
112 
113 	return QDF_STATUS_SUCCESS;
114 
115 }
116 
117 struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create(
118 			struct wlan_objmgr_pdev *pdev,
119 			struct wlan_vdev_create_params *params)
120 {
121 	struct wlan_objmgr_vdev *vdev;
122 	struct wlan_objmgr_psoc *psoc;
123 	uint8_t id;
124 	wlan_objmgr_vdev_create_handler handler;
125 	wlan_objmgr_vdev_status_handler stat_handler;
126 	void *arg;
127 	QDF_STATUS obj_status;
128 
129 	if (!pdev) {
130 		obj_mgr_err("pdev is NULL");
131 		return NULL;
132 	}
133 	psoc = wlan_pdev_get_psoc(pdev);
134 	/* PSOC is NULL */
135 	if (!psoc) {
136 		obj_mgr_err("psoc is NULL for pdev-id:%d",
137 			pdev->pdev_objmgr.wlan_pdev_id);
138 		return NULL;
139 	}
140 	/* Allocate vdev object memory */
141 	vdev = qdf_mem_malloc(sizeof(*vdev));
142 	if (!vdev)
143 		return NULL;
144 
145 	vdev->obj_state = WLAN_OBJ_STATE_ALLOCATED;
146 
147 	vdev->vdev_mlme.bss_chan = qdf_mem_malloc(sizeof(struct wlan_channel));
148 	if (!vdev->vdev_mlme.bss_chan) {
149 		qdf_mem_free(vdev);
150 		return NULL;
151 	}
152 
153 	vdev->vdev_mlme.des_chan = qdf_mem_malloc(sizeof(struct wlan_channel));
154 	if (!vdev->vdev_mlme.des_chan) {
155 		qdf_mem_free(vdev->vdev_mlme.bss_chan);
156 		qdf_mem_free(vdev);
157 		return NULL;
158 	}
159 
160 	/* Initialize spinlock */
161 	qdf_spinlock_create(&vdev->vdev_lock);
162 	/* Attach VDEV to PSOC VDEV's list */
163 	if (wlan_objmgr_psoc_vdev_attach(psoc, vdev) !=
164 				QDF_STATUS_SUCCESS) {
165 		obj_mgr_err("psoc vdev attach failed for vdev-id:%d",
166 					vdev->vdev_objmgr.vdev_id);
167 		qdf_mem_free(vdev->vdev_mlme.bss_chan);
168 		qdf_mem_free(vdev->vdev_mlme.des_chan);
169 		qdf_spinlock_destroy(&vdev->vdev_lock);
170 		qdf_mem_free(vdev);
171 		return NULL;
172 	}
173 	/* Store pdev in vdev */
174 	wlan_vdev_set_pdev(vdev, pdev);
175 	/* Attach vdev to PDEV */
176 	if (wlan_objmgr_pdev_vdev_attach(pdev, vdev) !=
177 				QDF_STATUS_SUCCESS) {
178 		obj_mgr_err("pdev vdev attach failed for vdev-id:%d",
179 				vdev->vdev_objmgr.vdev_id);
180 		wlan_objmgr_psoc_vdev_detach(psoc, vdev);
181 		qdf_mem_free(vdev->vdev_mlme.bss_chan);
182 		qdf_mem_free(vdev->vdev_mlme.des_chan);
183 		qdf_spinlock_destroy(&vdev->vdev_lock);
184 		qdf_mem_free(vdev);
185 		return NULL;
186 	}
187 	/* set opmode */
188 	wlan_vdev_mlme_set_opmode(vdev, params->opmode);
189 	/* set MAC address */
190 	wlan_vdev_mlme_set_macaddr(vdev, params->macaddr);
191 	/* set MAT address */
192 	wlan_vdev_mlme_set_mataddr(vdev, params->mataddr);
193 	/* Set create flags */
194 	vdev->vdev_objmgr.c_flags = params->flags;
195 	/* store os-specific pointer */
196 	vdev->vdev_nif.osdev = params->osifp;
197 	/* peer count to 0 */
198 	vdev->vdev_objmgr.wlan_peer_count = 0;
199 	qdf_atomic_init(&vdev->vdev_objmgr.ref_cnt);
200 	vdev->vdev_objmgr.print_cnt = 0;
201 	wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID);
202 	/* Initialize max peer count based on opmode type */
203 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE)
204 		vdev->vdev_objmgr.max_peer_count = WLAN_UMAC_MAX_STA_PEERS;
205 	else
206 		vdev->vdev_objmgr.max_peer_count =
207 				wlan_pdev_get_max_peer_count(pdev);
208 
209 	/* Initialize peer list */
210 	qdf_list_create(&vdev->vdev_objmgr.wlan_peer_list,
211 			vdev->vdev_objmgr.max_peer_count +
212 			WLAN_MAX_PDEV_TEMP_PEERS);
213 	/* TODO init other parameters */
214 
215 	/* Invoke registered create handlers */
216 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
217 		handler = g_umac_glb_obj->vdev_create_handler[id];
218 		arg = g_umac_glb_obj->vdev_create_handler_arg[id];
219 		if (handler)
220 			vdev->obj_status[id] = handler(vdev, arg);
221 		else
222 			vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED;
223 	}
224 
225 	/* Derive object status */
226 	obj_status = wlan_objmgr_vdev_object_status(vdev);
227 
228 	if (obj_status == QDF_STATUS_SUCCESS) {
229 		/* Object status is SUCCESS, Object is created */
230 		vdev->obj_state = WLAN_OBJ_STATE_CREATED;
231 		/* Invoke component registered status handlers */
232 		for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
233 			stat_handler = g_umac_glb_obj->vdev_status_handler[id];
234 			arg = g_umac_glb_obj->vdev_status_handler_arg[id];
235 			if (stat_handler) {
236 				stat_handler(vdev, arg,
237 					     QDF_STATUS_SUCCESS);
238 			}
239 		}
240 	/*
241 	 * Few components operates in Asynchrous communction, Object state
242 	 * partially created
243 	 */
244 	} else if (obj_status == QDF_STATUS_COMP_ASYNC) {
245 		vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
246 	/* Component object failed to be created, clean up the object */
247 	} else if (obj_status == QDF_STATUS_E_FAILURE) {
248 		/* Clean up the psoc */
249 		wlan_objmgr_vdev_obj_delete(vdev);
250 		obj_mgr_err("VDEV comp objects creation failed for vdev-id:%d",
251 			vdev->vdev_objmgr.vdev_id);
252 		/*
253 		 * Set params osifp to NULL as it is freed during vdev obj
254 		 * delete, This prevents caller from performing double free.
255 		 */
256 		params->osifp = NULL;
257 		return NULL;
258 	}
259 
260 	obj_mgr_info("Created vdev %d", vdev->vdev_objmgr.vdev_id);
261 
262 	return vdev;
263 }
264 qdf_export_symbol(wlan_objmgr_vdev_obj_create);
265 
266 static QDF_STATUS wlan_objmgr_vdev_obj_destroy(struct wlan_objmgr_vdev *vdev)
267 {
268 	uint8_t id;
269 	wlan_objmgr_vdev_destroy_handler handler;
270 	QDF_STATUS obj_status;
271 	void *arg;
272 	uint8_t vdev_id;
273 
274 	if (!vdev) {
275 		obj_mgr_err("vdev is NULL");
276 		return QDF_STATUS_E_FAILURE;
277 	}
278 	wlan_objmgr_notify_destroy(vdev, WLAN_VDEV_OP);
279 
280 	vdev_id = wlan_vdev_get_id(vdev);
281 
282 	wlan_print_vdev_info(vdev);
283 	obj_mgr_debug("Physically deleting vdev %d", vdev_id);
284 
285 	if (vdev->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) {
286 		obj_mgr_err("VDEV object delete is not invoked vdevid:%d objstate:%d",
287 			    wlan_vdev_get_id(vdev), vdev->obj_state);
288 		WLAN_OBJMGR_BUG(0);
289 	}
290 
291 	/* Invoke registered destroy handlers */
292 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
293 		handler = g_umac_glb_obj->vdev_destroy_handler[id];
294 		arg = g_umac_glb_obj->vdev_destroy_handler_arg[id];
295 		if (handler &&
296 		    (vdev->obj_status[id] == QDF_STATUS_SUCCESS ||
297 		     vdev->obj_status[id] == QDF_STATUS_COMP_ASYNC))
298 			vdev->obj_status[id] = handler(vdev, arg);
299 		else
300 			vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED;
301 	}
302 	/* Derive object status */
303 	obj_status = wlan_objmgr_vdev_object_status(vdev);
304 
305 	if (obj_status == QDF_STATUS_E_FAILURE) {
306 		obj_mgr_err("VDEV object deletion failed: vdev-id: %d",
307 				vdev_id);
308 		/* Ideally should not happen */
309 		/* This leads to memleak ??? how to handle */
310 		QDF_BUG(0);
311 		return QDF_STATUS_E_FAILURE;
312 	}
313 
314 	/* Deletion is in progress */
315 	if (obj_status == QDF_STATUS_COMP_ASYNC) {
316 		vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED;
317 		return QDF_STATUS_COMP_ASYNC;
318 	}
319 
320 	/* Free VDEV object */
321 	return wlan_objmgr_vdev_obj_free(vdev);
322 }
323 
324 QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev)
325 {
326 	uint8_t print_idx;
327 
328 	if (!vdev) {
329 		obj_mgr_err("vdev is NULL");
330 		return QDF_STATUS_E_FAILURE;
331 	}
332 
333 	obj_mgr_info("Logically deleting vdev %d", vdev->vdev_objmgr.vdev_id);
334 
335 	print_idx = qdf_get_pidx();
336 	wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg,
337 				  QDF_TRACE_LEVEL_DEBUG);
338 	/*
339 	 * Update VDEV object state to LOGICALLY DELETED
340 	 * It prevents further access of this object
341 	 */
342 	wlan_vdev_obj_lock(vdev);
343 	vdev->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED;
344 	wlan_vdev_obj_unlock(vdev);
345 	wlan_objmgr_notify_log_delete(vdev, WLAN_VDEV_OP);
346 	wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
347 
348 	return QDF_STATUS_SUCCESS;
349 }
350 qdf_export_symbol(wlan_objmgr_vdev_obj_delete);
351 
352 /**
353  ** APIs to attach/detach component objects
354  */
355 QDF_STATUS wlan_objmgr_vdev_component_obj_attach(
356 		struct wlan_objmgr_vdev *vdev,
357 		enum wlan_umac_comp_id id,
358 		void *comp_priv_obj,
359 		QDF_STATUS status)
360 {
361 	wlan_objmgr_vdev_status_handler stat_handler;
362 	void *arg;
363 	uint8_t i;
364 	QDF_STATUS obj_status;
365 
366 	/* component id is invalid */
367 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
368 		return QDF_STATUS_MAXCOMP_FAIL;
369 
370 	wlan_vdev_obj_lock(vdev);
371 	/* If there is a valid entry, return failure */
372 	if (vdev->vdev_comp_priv_obj[id]) {
373 		wlan_vdev_obj_unlock(vdev);
374 		return QDF_STATUS_E_FAILURE;
375 	}
376 	/* Save component's pointer and status */
377 	vdev->vdev_comp_priv_obj[id] = comp_priv_obj;
378 	vdev->obj_status[id] = status;
379 	wlan_vdev_obj_unlock(vdev);
380 	if (vdev->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED)
381 		return QDF_STATUS_SUCCESS;
382 	/*
383 	 * If VDEV object status is partially created means, this API is
384 	 * invoked with differnt context, this block should be executed for
385 	 * async components only
386 	 */
387 	/* Derive status */
388 	obj_status = wlan_objmgr_vdev_object_status(vdev);
389 	/* STATUS_SUCCESS means, object is CREATED */
390 	if (obj_status == QDF_STATUS_SUCCESS)
391 		vdev->obj_state = WLAN_OBJ_STATE_CREATED;
392 	/*
393 	 * update state as CREATION failed, caller has to delete the
394 	 * VDEV object
395 	 */
396 	else if (obj_status == QDF_STATUS_E_FAILURE)
397 		vdev->obj_state = WLAN_OBJ_STATE_CREATION_FAILED;
398 	/* Notify components about the CREATION success/failure */
399 	if ((obj_status == QDF_STATUS_SUCCESS) ||
400 	    (obj_status == QDF_STATUS_E_FAILURE)) {
401 		for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) {
402 			stat_handler = g_umac_glb_obj->vdev_status_handler[i];
403 			arg = g_umac_glb_obj->vdev_status_handler_arg[i];
404 			if (stat_handler)
405 				stat_handler(vdev, arg, obj_status);
406 		}
407 	}
408 	return QDF_STATUS_SUCCESS;
409 }
410 qdf_export_symbol(wlan_objmgr_vdev_component_obj_attach);
411 
412 QDF_STATUS wlan_objmgr_vdev_component_obj_detach(
413 		struct wlan_objmgr_vdev *vdev,
414 		enum wlan_umac_comp_id id,
415 		void *comp_priv_obj)
416 {
417 	QDF_STATUS obj_status;
418 
419 	/* component id is invalid */
420 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
421 		return QDF_STATUS_MAXCOMP_FAIL;
422 
423 	wlan_vdev_obj_lock(vdev);
424 	/* If there is a valid entry, return failure */
425 	if (vdev->vdev_comp_priv_obj[id] != comp_priv_obj) {
426 		vdev->obj_status[id] = QDF_STATUS_E_FAILURE;
427 		wlan_vdev_obj_unlock(vdev);
428 		return QDF_STATUS_E_FAILURE;
429 	}
430 	/* Reset pointers to NULL, update the status*/
431 	vdev->vdev_comp_priv_obj[id] = NULL;
432 	vdev->obj_status[id] = QDF_STATUS_SUCCESS;
433 	wlan_vdev_obj_unlock(vdev);
434 
435 	/**
436 	 *If VDEV object status is partially destroyed means, this API is
437 	 * invoked with differnt context, this block should be executed for
438 	 * async components only
439 	 */
440 	if ((vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) ||
441 	    (vdev->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) {
442 		/* Derive object status */
443 		obj_status = wlan_objmgr_vdev_object_status(vdev);
444 		if (obj_status == QDF_STATUS_SUCCESS) {
445 			/*
446 			 * Update the status as Deleted, if full object
447 			 * deletion is in progress
448 			 */
449 			if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
450 				vdev->obj_state = WLAN_OBJ_STATE_DELETED;
451 			/*
452 			 * Move to creation state, since this component
453 			 * deletion alone requested
454 			 */
455 			else if (vdev->obj_state ==
456 					WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
457 				vdev->obj_state = WLAN_OBJ_STATE_CREATED;
458 		/* Object status is failure */
459 		} else if (obj_status == QDF_STATUS_E_FAILURE) {
460 			/*
461 			 * Update the status as Deletion failed, if full object
462 			 * deletion is in progress
463 			 */
464 			if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
465 				vdev->obj_state =
466 					WLAN_OBJ_STATE_DELETION_FAILED;
467 			/* Move to creation state, since this component
468 			deletion alone requested (do not block other
469 			components) */
470 			else if (vdev->obj_state ==
471 					WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
472 				vdev->obj_state = WLAN_OBJ_STATE_CREATED;
473 		}
474 		/* Delete vdev object */
475 		if ((obj_status == QDF_STATUS_SUCCESS)  &&
476 		    (vdev->obj_state == WLAN_OBJ_STATE_DELETED)) {
477 			/* Free VDEV object */
478 			return wlan_objmgr_vdev_obj_free(vdev);
479 		}
480 	}
481 	return QDF_STATUS_SUCCESS;
482 }
483 qdf_export_symbol(wlan_objmgr_vdev_component_obj_detach);
484 
485 /**
486  ** APIs to operations on vdev objects
487  */
488 QDF_STATUS wlan_objmgr_iterate_peerobj_list(
489 		struct wlan_objmgr_vdev *vdev,
490 		wlan_objmgr_vdev_op_handler handler,
491 		void *arg, wlan_objmgr_ref_dbgid dbg_id)
492 {
493 	qdf_list_t *peer_list = NULL;
494 	struct wlan_objmgr_peer *peer = NULL;
495 	struct wlan_objmgr_peer *peer_next = NULL;
496 	uint8_t vdev_id;
497 
498 	if (!vdev) {
499 		obj_mgr_err("VDEV is NULL");
500 		return QDF_STATUS_E_FAILURE;
501 	}
502 	wlan_vdev_obj_lock(vdev);
503 	vdev_id = wlan_vdev_get_id(vdev);
504 
505 	if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) {
506 		wlan_vdev_obj_unlock(vdev);
507 		obj_mgr_err("VDEV is not in create state:%d: vdev-id:%d",
508 			    vdev->obj_state, vdev_id);
509 		return QDF_STATUS_E_FAILURE;
510 	}
511 	wlan_objmgr_vdev_get_ref(vdev, dbg_id);
512 	peer_list = &vdev->vdev_objmgr.wlan_peer_list;
513 	if (peer_list) {
514 		/* Iterate through VDEV's peer list */
515 		peer = wlan_vdev_peer_list_peek_head(peer_list);
516 		while (peer) {
517 			peer_next = wlan_peer_get_next_peer_of_vdev(peer_list,
518 							       peer);
519 			if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
520 					QDF_STATUS_SUCCESS) {
521 				/* Invoke handler for operation */
522 				handler(vdev, (void *)peer, arg);
523 				wlan_objmgr_peer_release_ref(peer, dbg_id);
524 			}
525 			peer = peer_next;
526 		}
527 	}
528 	wlan_objmgr_vdev_release_ref(vdev, dbg_id);
529 	wlan_vdev_obj_unlock(vdev);
530 	return QDF_STATUS_SUCCESS;
531 }
532 
533 /**
534  ** APIs to get a peer with given mac in a vdev
535  */
536 struct wlan_objmgr_peer *
537 wlan_objmgr_vdev_find_peer_by_mac(struct wlan_objmgr_vdev *vdev,
538 				  uint8_t *peer_mac,
539 				  wlan_objmgr_ref_dbgid dbg_id)
540 {
541 	qdf_list_t *peer_list;
542 	struct wlan_objmgr_peer *peer = NULL;
543 	struct wlan_objmgr_peer *peer_next = NULL;
544 	uint8_t vdev_id;
545 
546 	if (!vdev) {
547 		obj_mgr_err("VDEV is NULL");
548 		return NULL;
549 	}
550 	wlan_vdev_obj_lock(vdev);
551 	vdev_id = wlan_vdev_get_id(vdev);
552 
553 	if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) {
554 		wlan_vdev_obj_unlock(vdev);
555 		obj_mgr_err("VDEV is not in create state:%d: vdev-id:%d",
556 			    vdev->obj_state, vdev_id);
557 		return NULL;
558 	}
559 	wlan_objmgr_vdev_get_ref(vdev, dbg_id);
560 	peer_list = &vdev->vdev_objmgr.wlan_peer_list;
561 	/* Iterate through VDEV's peer list */
562 	peer = wlan_vdev_peer_list_peek_head(peer_list);
563 	while (peer) {
564 		peer_next = wlan_peer_get_next_peer_of_vdev(peer_list,
565 							    peer);
566 		if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
567 						 QDF_STATUS_SUCCESS) {
568 			if (!WLAN_ADDR_EQ(peer_mac,
569 					  wlan_peer_get_macaddr(peer))) {
570 				wlan_objmgr_vdev_release_ref(vdev,
571 							     dbg_id);
572 				wlan_vdev_obj_unlock(vdev);
573 				return peer;
574 			}
575 			wlan_objmgr_peer_release_ref(peer, dbg_id);
576 		}
577 		peer = peer_next;
578 	}
579 	wlan_objmgr_vdev_release_ref(vdev, dbg_id);
580 	wlan_vdev_obj_unlock(vdev);
581 	return NULL;
582 }
583 
584 qdf_export_symbol(wlan_objmgr_vdev_find_peer_by_mac);
585 
586 /**
587  * wlan_obj_vdev_populate_logically_del_peerlist() - get peer
588  * from vdev peer list
589  * @obj_list: peer object list
590  * @vdev_obj: vdev object mgr substructure
591  * @dbg_id: id of the caller
592  *
593  * API to finds peer object pointer by vdev from peer hash list for a node
594  * which is in logically deleted state
595  *
596  * Caller to free the list allocated in this function
597  *
598  * Return: list of peer pointers
599  *         NULL on FAILURE
600  */
601 static qdf_list_t *wlan_obj_vdev_populate_logically_del_peerlist(
602 				qdf_list_t *obj_list,
603 				struct wlan_objmgr_vdev_objmgr *vdev_obj,
604 				wlan_objmgr_ref_dbgid dbg_id)
605 {
606 	struct wlan_objmgr_peer *peer;
607 	struct wlan_objmgr_peer *peer_next;
608 	struct wlan_logically_del_peer *peer_list;
609 	qdf_list_t *logical_del_peerlist;
610 	bool lock_released = false;
611 
612 	logical_del_peerlist = qdf_mem_malloc(sizeof(*logical_del_peerlist));
613 	if (!logical_del_peerlist)
614 		return NULL;
615 
616 	qdf_list_create(logical_del_peerlist, vdev_obj->max_peer_count);
617 
618 	peer = wlan_vdev_peer_list_peek_head(obj_list);
619 	while (peer) {
620 		wlan_peer_obj_lock(peer);
621 		peer_next = wlan_peer_get_next_peer_of_vdev(obj_list, peer);
622 		if (peer->obj_state == WLAN_OBJ_STATE_LOGICALLY_DELETED &&
623 		    qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) {
624 			wlan_objmgr_peer_get_ref(peer, dbg_id);
625 			wlan_peer_obj_unlock(peer);
626 			lock_released = true;
627 
628 			peer_list = qdf_mem_malloc(sizeof(*peer_list));
629 			if (!peer_list) {
630 				wlan_objmgr_peer_release_ref(peer, dbg_id);
631 				WLAN_OBJMGR_BUG(0);
632 				break;
633 			}
634 
635 			peer_list->peer = peer;
636 			qdf_list_insert_front(logical_del_peerlist,
637 					      &peer_list->list);
638 		}
639 
640 		if (!lock_released)
641 			wlan_peer_obj_unlock(peer);
642 
643 		peer = peer_next;
644 		lock_released = false;
645 	}
646 
647 	/* Not found, return NULL */
648 	if (qdf_list_empty(logical_del_peerlist)) {
649 		qdf_mem_free(logical_del_peerlist);
650 		return NULL;
651 	}
652 
653 	return logical_del_peerlist;
654 }
655 
656 qdf_list_t *wlan_objmgr_vdev_get_log_del_peer_list(
657 		struct wlan_objmgr_vdev *vdev,
658 		wlan_objmgr_ref_dbgid dbg_id)
659 {
660 	qdf_list_t *peer_list;
661 	qdf_list_t *log_del_peer_list = NULL;
662 
663 	if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) {
664 		obj_mgr_err("Invalid state vdev:%d state:%d",
665 			    wlan_vdev_get_id(vdev), vdev->obj_state);
666 		return NULL;
667 	}
668 
669 	wlan_vdev_obj_lock(vdev);
670 	if (vdev->vdev_objmgr.wlan_peer_count == 0) {
671 		wlan_vdev_obj_unlock(vdev);
672 		return NULL;
673 	}
674 
675 	wlan_objmgr_vdev_get_ref(vdev, dbg_id);
676 	peer_list = &vdev->vdev_objmgr.wlan_peer_list;
677 	if (peer_list) {
678 		log_del_peer_list =
679 			wlan_obj_vdev_populate_logically_del_peerlist(
680 					peer_list, &vdev->vdev_objmgr,
681 					dbg_id);
682 	}
683 
684 	wlan_objmgr_vdev_release_ref(vdev, dbg_id);
685 	wlan_vdev_obj_unlock(vdev);
686 
687 	return log_del_peer_list;
688 }
689 
690 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_creation(
691 		struct wlan_objmgr_vdev *vdev,
692 		enum wlan_umac_comp_id id)
693 {
694 	wlan_objmgr_vdev_create_handler handler;
695 	void *arg;
696 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
697 
698 	/* Component id is invalid */
699 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
700 		return QDF_STATUS_MAXCOMP_FAIL;
701 
702 	wlan_vdev_obj_lock(vdev);
703 	/*
704 	 * If component object is already created, delete old
705 	 * component object, then invoke creation
706 	 */
707 	if (vdev->vdev_comp_priv_obj[id]) {
708 		wlan_vdev_obj_unlock(vdev);
709 		return QDF_STATUS_E_FAILURE;
710 	}
711 	wlan_vdev_obj_unlock(vdev);
712 
713 	/* Invoke registered create handlers */
714 	handler = g_umac_glb_obj->vdev_create_handler[id];
715 	arg = g_umac_glb_obj->vdev_create_handler_arg[id];
716 	if (handler)
717 		vdev->obj_status[id] = handler(vdev, arg);
718 	else
719 		return QDF_STATUS_E_FAILURE;
720 
721 	/* If object status is created, then only handle this object status */
722 	if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) {
723 		/* Derive object status */
724 		obj_status = wlan_objmgr_vdev_object_status(vdev);
725 		/* Move PDEV object state to Partially created state */
726 		if (obj_status == QDF_STATUS_COMP_ASYNC) {
727 			/*TODO atomic */
728 			vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
729 		}
730 	}
731 	return obj_status;
732 }
733 
734 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_deletion(
735 		struct wlan_objmgr_vdev *vdev,
736 		enum wlan_umac_comp_id id)
737 {
738 	wlan_objmgr_vdev_destroy_handler handler;
739 	void *arg;
740 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
741 
742 	/* component id is invalid */
743 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
744 		return QDF_STATUS_MAXCOMP_FAIL;
745 
746 	wlan_vdev_obj_lock(vdev);
747 	/* Component object was never created, invalid operation */
748 	if (!vdev->vdev_comp_priv_obj[id]) {
749 		wlan_vdev_obj_unlock(vdev);
750 		return QDF_STATUS_E_FAILURE;
751 	}
752 	wlan_vdev_obj_unlock(vdev);
753 
754 	/* Invoke registered create handlers */
755 	handler = g_umac_glb_obj->vdev_destroy_handler[id];
756 	arg = g_umac_glb_obj->vdev_destroy_handler_arg[id];
757 	if (handler)
758 		vdev->obj_status[id] = handler(vdev, arg);
759 	else
760 		return QDF_STATUS_E_FAILURE;
761 
762 	/* If object status is created, then only handle this object status */
763 	if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) {
764 		obj_status = wlan_objmgr_vdev_object_status(vdev);
765 		/* move object state to DEL progress */
766 		if (obj_status == QDF_STATUS_COMP_ASYNC)
767 			vdev->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS;
768 	}
769 	return obj_status;
770 }
771 
772 
773 
774 static void wlan_obj_vdev_peerlist_add_tail(qdf_list_t *obj_list,
775 	struct wlan_objmgr_peer *obj)
776 {
777 	qdf_list_insert_back(obj_list, &obj->vdev_peer);
778 }
779 
780 static QDF_STATUS wlan_obj_vdev_peerlist_remove_peer(qdf_list_t *obj_list,
781 					struct wlan_objmgr_peer *peer)
782 {
783 	qdf_list_node_t *vdev_node = NULL;
784 
785 	if (!peer)
786 		return QDF_STATUS_E_FAILURE;
787 	/* get vdev list node element */
788 	vdev_node = &peer->vdev_peer;
789 	/* list is empty, return failure */
790 	if (qdf_list_remove_node(obj_list, vdev_node) != QDF_STATUS_SUCCESS)
791 		return QDF_STATUS_E_FAILURE;
792 
793 	return QDF_STATUS_SUCCESS;
794 }
795 
796 QDF_STATUS wlan_objmgr_vdev_peer_attach(struct wlan_objmgr_vdev *vdev,
797 						struct wlan_objmgr_peer *peer)
798 {
799 	struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr;
800 	struct wlan_objmgr_pdev *pdev;
801 	enum QDF_OPMODE opmode;
802 
803 	wlan_vdev_obj_lock(vdev);
804 	pdev = wlan_vdev_get_pdev(vdev);
805 	/* If Max VDEV peer count exceeds, return failure */
806 	if (peer->peer_mlme.peer_type != WLAN_PEER_STA_TEMP) {
807 		if (objmgr->wlan_peer_count >= objmgr->max_peer_count) {
808 			wlan_vdev_obj_unlock(vdev);
809 			return QDF_STATUS_E_FAILURE;
810 		}
811 	}
812 	wlan_vdev_obj_unlock(vdev);
813 
814 	/* If Max PDEV peer count exceeds, return failure */
815 	wlan_pdev_obj_lock(pdev);
816 	if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) {
817 		if (wlan_pdev_get_temp_peer_count(pdev) >=
818 			WLAN_MAX_PDEV_TEMP_PEERS) {
819 			wlan_pdev_obj_unlock(pdev);
820 			return QDF_STATUS_E_FAILURE;
821 		}
822 	} else {
823 		if (wlan_pdev_get_peer_count(pdev) >=
824 			wlan_pdev_get_max_peer_count(pdev)) {
825 			wlan_pdev_obj_unlock(pdev);
826 			return QDF_STATUS_E_FAILURE;
827 		}
828 	}
829 
830 	if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP)
831 		wlan_pdev_incr_temp_peer_count(wlan_vdev_get_pdev(vdev));
832 	else
833 		wlan_pdev_incr_peer_count(wlan_vdev_get_pdev(vdev));
834 	wlan_pdev_obj_unlock(pdev);
835 
836 	wlan_vdev_obj_lock(vdev);
837 	/* Add peer to vdev's peer list */
838 	wlan_obj_vdev_peerlist_add_tail(&objmgr->wlan_peer_list, peer);
839 	objmgr->wlan_peer_count++;
840 
841 	if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer),
842 			 wlan_vdev_mlme_get_macaddr(vdev)) ==
843 				QDF_STATUS_SUCCESS) {
844 		/*
845 		 * if peer mac address and vdev mac address match, set
846 		 * this peer as self peer
847 		 */
848 		wlan_vdev_set_selfpeer(vdev, peer);
849 		opmode = wlan_vdev_mlme_get_opmode(vdev);
850 		/* For AP mode, self peer and BSS peer are same */
851 		if ((opmode == QDF_SAP_MODE) ||
852 		    (opmode == QDF_P2P_GO_MODE) ||
853 		    (opmode == QDF_NDI_MODE))
854 			wlan_vdev_set_bsspeer(vdev, peer);
855 	}
856 	/* set BSS peer for sta */
857 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE ||
858 	     wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_CLIENT_MODE) &&
859 	    (wlan_peer_get_peer_type(peer) == WLAN_PEER_AP ||
860 	     wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO))
861 		wlan_vdev_set_bsspeer(vdev, peer);
862 
863 	/* Increment vdev ref count to make sure it won't be destroyed before */
864 	wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID);
865 	wlan_vdev_obj_unlock(vdev);
866 	return QDF_STATUS_SUCCESS;
867 }
868 
869 QDF_STATUS wlan_objmgr_vdev_peer_detach(struct wlan_objmgr_vdev *vdev,
870 					struct wlan_objmgr_peer *peer)
871 {
872 	struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr;
873 	struct wlan_objmgr_pdev *pdev;
874 
875 	wlan_vdev_obj_lock(vdev);
876 	/* if peer count is 0, return failure */
877 	if (objmgr->wlan_peer_count == 0) {
878 		wlan_vdev_obj_unlock(vdev);
879 		return QDF_STATUS_E_FAILURE;
880 	}
881 
882 	if (wlan_vdev_get_selfpeer(vdev) == peer) {
883 		/*
884 		 * There might be instances where new node is created
885 		 * before deleting existing node, in which case selfpeer
886 		 * will be pointing to the new node. So set selfpeer to
887 		 * NULL only if vdev->vdev_objmgr.self_peer is pointing
888 		 * to the peer processed for deletion
889 		 */
890 		wlan_vdev_set_selfpeer(vdev, NULL);
891 	}
892 
893 	if (wlan_vdev_get_bsspeer(vdev) == peer) {
894 		/*
895 		 * There might be instances where new node is created
896 		 * before deleting existing node, in which case bsspeer
897 		 * in vdev will be pointing to the new node. So set
898 		 * bsspeer to NULL only if vdev->vdev_objmgr.bss_peer is
899 		 * pointing to the peer processed for deletion
900 		 */
901 		wlan_vdev_set_bsspeer(vdev, NULL);
902 	}
903 
904 	/* remove peer from vdev's peer list */
905 	if (wlan_obj_vdev_peerlist_remove_peer(&objmgr->wlan_peer_list, peer)
906 				== QDF_STATUS_E_FAILURE) {
907 		wlan_vdev_obj_unlock(vdev);
908 		return QDF_STATUS_E_FAILURE;
909 	}
910 	/* decrement peer count */
911 	objmgr->wlan_peer_count--;
912 	/* decrement pdev peer count */
913 	pdev = wlan_vdev_get_pdev(vdev);
914 	wlan_vdev_obj_unlock(vdev);
915 
916 	wlan_pdev_obj_lock(pdev);
917 	if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP)
918 		wlan_pdev_decr_temp_peer_count(pdev);
919 	else
920 		wlan_pdev_decr_peer_count(pdev);
921 	wlan_pdev_obj_unlock(pdev);
922 
923 	/* decrement vdev ref count after peer released its reference */
924 	wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
925 	return QDF_STATUS_SUCCESS;
926 }
927 
928 struct wlan_objmgr_peer *wlan_objmgr_vdev_try_get_bsspeer(
929 					struct wlan_objmgr_vdev *vdev,
930 					wlan_objmgr_ref_dbgid id)
931 {
932 	struct wlan_objmgr_peer *peer;
933 	QDF_STATUS status = QDF_STATUS_E_EMPTY;
934 
935 	if (!vdev)
936 		return NULL;
937 
938 	wlan_vdev_obj_lock(vdev);
939 	peer = wlan_vdev_get_bsspeer(vdev);
940 	if (peer)
941 		status = wlan_objmgr_peer_try_get_ref(peer, id);
942 	wlan_vdev_obj_unlock(vdev);
943 
944 	if (QDF_IS_STATUS_SUCCESS(status))
945 		return peer;
946 
947 	return NULL;
948 }
949 
950 void *wlan_objmgr_vdev_get_comp_private_obj(
951 		struct wlan_objmgr_vdev *vdev,
952 		enum wlan_umac_comp_id id)
953 {
954 	void *comp_priv_obj;
955 
956 	/* component id is invalid */
957 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
958 		QDF_BUG(0);
959 		return NULL;
960 	}
961 
962 	if (!vdev) {
963 		QDF_BUG(0);
964 		return NULL;
965 	}
966 
967 	comp_priv_obj = vdev->vdev_comp_priv_obj[id];
968 
969 	return comp_priv_obj;
970 }
971 qdf_export_symbol(wlan_objmgr_vdev_get_comp_private_obj);
972 
973 void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev,
974 						wlan_objmgr_ref_dbgid id)
975 {
976 	if (!vdev) {
977 		obj_mgr_err("vdev obj is NULL for id:%d", id);
978 		QDF_ASSERT(0);
979 		return;
980 	}
981 	/* Increment ref count */
982 	qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt);
983 	qdf_atomic_inc(&vdev->vdev_objmgr.ref_id_dbg[id]);
984 
985 	return;
986 }
987 qdf_export_symbol(wlan_objmgr_vdev_get_ref);
988 
989 QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev,
990 						wlan_objmgr_ref_dbgid id)
991 {
992 	uint8_t vdev_id;
993 
994 	if (!vdev) {
995 		obj_mgr_err("vdev obj is NULL for id:%d", id);
996 		QDF_ASSERT(0);
997 		return QDF_STATUS_E_FAILURE;
998 	}
999 
1000 	wlan_vdev_obj_lock(vdev);
1001 	vdev_id = wlan_vdev_get_id(vdev);
1002 	if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) {
1003 		wlan_vdev_obj_unlock(vdev);
1004 		if (vdev->vdev_objmgr.print_cnt++ <=
1005 				WLAN_OBJMGR_RATELIMIT_THRESH)
1006 			obj_mgr_err(
1007 			"[Ref id: %d] vdev(%d) is not in Created state(%d)",
1008 				id, vdev_id, vdev->obj_state);
1009 
1010 		return QDF_STATUS_E_RESOURCES;
1011 	}
1012 
1013 	/* Increment ref count */
1014 	wlan_objmgr_vdev_get_ref(vdev, id);
1015 	wlan_vdev_obj_unlock(vdev);
1016 
1017 	return QDF_STATUS_SUCCESS;
1018 }
1019 qdf_export_symbol(wlan_objmgr_vdev_try_get_ref);
1020 
1021 void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev,
1022 						wlan_objmgr_ref_dbgid id)
1023 {
1024 	uint8_t vdev_id;
1025 
1026 	if (!vdev) {
1027 		obj_mgr_err("vdev obj is NULL for id:%d", id);
1028 		QDF_ASSERT(0);
1029 		return;
1030 	}
1031 
1032 	vdev_id = wlan_vdev_get_id(vdev);
1033 
1034 	if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_id_dbg[id])) {
1035 		obj_mgr_alert("vdev (id:%d)ref cnt was not taken by %d",
1036 			      vdev_id, id);
1037 		wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg,
1038 					  QDF_TRACE_LEVEL_FATAL);
1039 		WLAN_OBJMGR_BUG(0);
1040 		return;
1041 	}
1042 
1043 	if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) {
1044 		obj_mgr_alert("vdev ref cnt is 0");
1045 		WLAN_OBJMGR_BUG(0);
1046 		return;
1047 	}
1048 	qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]);
1049 
1050 	/* Decrement ref count, free vdev, if ref count == 0 */
1051 	if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt))
1052 		wlan_objmgr_vdev_obj_destroy(vdev);
1053 
1054 	return;
1055 }
1056 qdf_export_symbol(wlan_objmgr_vdev_release_ref);
1057 
1058 struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head(
1059 			struct wlan_objmgr_pdev *pdev,
1060 			qdf_list_t *vdev_list, wlan_objmgr_ref_dbgid dbg_id)
1061 {
1062 	struct wlan_objmgr_vdev *vdev;
1063 	qdf_list_node_t *node = NULL;
1064 	qdf_list_node_t *prev_node = NULL;
1065 
1066 	wlan_pdev_obj_lock(pdev);
1067 
1068 	if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) {
1069 		wlan_pdev_obj_unlock(pdev);
1070 		return NULL;
1071 	}
1072 
1073 	do {
1074 		vdev = qdf_container_of(node, struct wlan_objmgr_vdev,
1075 								vdev_node);
1076 		if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) ==
1077 						QDF_STATUS_SUCCESS) {
1078 			wlan_pdev_obj_unlock(pdev);
1079 			return vdev;
1080 		}
1081 
1082 		prev_node = node;
1083 	} while (qdf_list_peek_next(vdev_list, prev_node, &node) ==
1084 						QDF_STATUS_SUCCESS);
1085 
1086 	wlan_pdev_obj_unlock(pdev);
1087 
1088 	return NULL;
1089 }
1090 
1091 struct wlan_objmgr_vdev *wlan_pdev_peek_active_first_vdev(
1092 		struct wlan_objmgr_pdev *pdev,
1093 		wlan_objmgr_ref_dbgid dbg_id)
1094 {
1095 	struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr;
1096 	qdf_list_t *vdev_list;
1097 
1098 	/* VDEV list */
1099 	vdev_list = &objmgr->wlan_vdev_list;
1100 
1101 	return wlan_pdev_vdev_list_peek_active_head(pdev, vdev_list,
1102 						    dbg_id);
1103 }
1104 
1105 struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev(
1106 			struct wlan_objmgr_pdev *pdev,
1107 			qdf_list_t *vdev_list,
1108 			struct wlan_objmgr_vdev *vdev,
1109 			wlan_objmgr_ref_dbgid dbg_id)
1110 {
1111 	struct wlan_objmgr_vdev *vdev_next;
1112 	qdf_list_node_t *node = &vdev->vdev_node;
1113 	qdf_list_node_t *prev_node = NULL;
1114 
1115 	if (!node)
1116 		return NULL;
1117 
1118 	wlan_pdev_obj_lock(pdev);
1119 	prev_node = node;
1120 	while (qdf_list_peek_next(vdev_list, prev_node, &node) ==
1121 							QDF_STATUS_SUCCESS) {
1122 		vdev_next = qdf_container_of(node, struct wlan_objmgr_vdev,
1123 								vdev_node);
1124 		if (wlan_objmgr_vdev_try_get_ref(vdev_next, dbg_id) ==
1125 						QDF_STATUS_SUCCESS) {
1126 			wlan_pdev_obj_unlock(pdev);
1127 			return vdev_next;
1128 		}
1129 
1130 		prev_node = node;
1131 	}
1132 	wlan_pdev_obj_unlock(pdev);
1133 
1134 	return NULL;
1135 }
1136 
1137 #ifdef WLAN_OBJMGR_DEBUG
1138 void wlan_print_vdev_info(struct wlan_objmgr_vdev *vdev)
1139 {
1140 	struct wlan_objmgr_vdev_objmgr *vdev_objmgr;
1141 	uint32_t ref_cnt;
1142 
1143 	vdev_objmgr = &vdev->vdev_objmgr;
1144 
1145 	ref_cnt = qdf_atomic_read(&vdev_objmgr->ref_cnt);
1146 
1147 	obj_mgr_debug("vdev: %pK", vdev);
1148 	obj_mgr_debug("vdev_id: %d", vdev_objmgr->vdev_id);
1149 	obj_mgr_debug("print_cnt: %d", vdev_objmgr->print_cnt);
1150 	obj_mgr_debug("wlan_pdev: %pK", vdev_objmgr->wlan_pdev);
1151 	obj_mgr_debug("ref_cnt: %d", ref_cnt);
1152 }
1153 
1154 qdf_export_symbol(wlan_print_vdev_info);
1155 #endif
1156 
1157