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