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