xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c (revision 302a1d9701784af5f4797b1a9fe07ae820b51907)
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 != NULL)
297 			vdev->obj_status[id] = handler(vdev, arg);
298 		else
299 			vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED;
300 	}
301 	/* Derive object status */
302 	obj_status = wlan_objmgr_vdev_object_status(vdev);
303 
304 	if (obj_status == QDF_STATUS_E_FAILURE) {
305 		obj_mgr_err("VDEV object deletion failed: vdev-id: %d",
306 				vdev_id);
307 		/* Ideally should not happen */
308 		/* This leads to memleak ??? how to handle */
309 		QDF_BUG(0);
310 		return QDF_STATUS_E_FAILURE;
311 	}
312 
313 	/* Deletion is in progress */
314 	if (obj_status == QDF_STATUS_COMP_ASYNC) {
315 		vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED;
316 		return QDF_STATUS_COMP_ASYNC;
317 	}
318 
319 	/* Free VDEV object */
320 	return wlan_objmgr_vdev_obj_free(vdev);
321 }
322 
323 QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev)
324 {
325 	uint8_t print_idx;
326 
327 	if (vdev == NULL) {
328 		obj_mgr_err("vdev is NULL");
329 		return QDF_STATUS_E_FAILURE;
330 	}
331 
332 	obj_mgr_info("Logically deleting vdev %d", vdev->vdev_objmgr.vdev_id);
333 
334 	print_idx = qdf_get_pidx();
335 	wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg,
336 				  QDF_TRACE_LEVEL_DEBUG);
337 	/*
338 	 * Update VDEV object state to LOGICALLY DELETED
339 	 * It prevents further access of this object
340 	 */
341 	wlan_vdev_obj_lock(vdev);
342 	vdev->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED;
343 	wlan_vdev_obj_unlock(vdev);
344 	wlan_objmgr_notify_log_delete(vdev, WLAN_VDEV_OP);
345 	wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
346 
347 	return QDF_STATUS_SUCCESS;
348 }
349 qdf_export_symbol(wlan_objmgr_vdev_obj_delete);
350 
351 /**
352  ** APIs to attach/detach component objects
353  */
354 QDF_STATUS wlan_objmgr_vdev_component_obj_attach(
355 		struct wlan_objmgr_vdev *vdev,
356 		enum wlan_umac_comp_id id,
357 		void *comp_priv_obj,
358 		QDF_STATUS status)
359 {
360 	wlan_objmgr_vdev_status_handler stat_handler;
361 	void *arg;
362 	uint8_t i;
363 	QDF_STATUS obj_status;
364 
365 	/* component id is invalid */
366 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
367 		return QDF_STATUS_MAXCOMP_FAIL;
368 
369 	wlan_vdev_obj_lock(vdev);
370 	/* If there is a valid entry, return failure */
371 	if (vdev->vdev_comp_priv_obj[id] != NULL) {
372 		wlan_vdev_obj_unlock(vdev);
373 		return QDF_STATUS_E_FAILURE;
374 	}
375 	/* Save component's pointer and status */
376 	vdev->vdev_comp_priv_obj[id] = comp_priv_obj;
377 	vdev->obj_status[id] = status;
378 	wlan_vdev_obj_unlock(vdev);
379 	if (vdev->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED)
380 		return QDF_STATUS_SUCCESS;
381 	/*
382 	 * If VDEV object status is partially created means, this API is
383 	 * invoked with differnt context, this block should be executed for
384 	 * async components only
385 	 */
386 	/* Derive status */
387 	obj_status = wlan_objmgr_vdev_object_status(vdev);
388 	/* STATUS_SUCCESS means, object is CREATED */
389 	if (obj_status == QDF_STATUS_SUCCESS)
390 		vdev->obj_state = WLAN_OBJ_STATE_CREATED;
391 	/*
392 	 * update state as CREATION failed, caller has to delete the
393 	 * VDEV object
394 	 */
395 	else if (obj_status == QDF_STATUS_E_FAILURE)
396 		vdev->obj_state = WLAN_OBJ_STATE_CREATION_FAILED;
397 	/* Notify components about the CREATION success/failure */
398 	if ((obj_status == QDF_STATUS_SUCCESS) ||
399 	    (obj_status == QDF_STATUS_E_FAILURE)) {
400 		for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) {
401 			stat_handler = g_umac_glb_obj->vdev_status_handler[i];
402 			arg = g_umac_glb_obj->vdev_status_handler_arg[i];
403 			if (stat_handler != NULL)
404 				stat_handler(vdev, arg, obj_status);
405 		}
406 	}
407 	return QDF_STATUS_SUCCESS;
408 }
409 qdf_export_symbol(wlan_objmgr_vdev_component_obj_attach);
410 
411 QDF_STATUS wlan_objmgr_vdev_component_obj_detach(
412 		struct wlan_objmgr_vdev *vdev,
413 		enum wlan_umac_comp_id id,
414 		void *comp_priv_obj)
415 {
416 	QDF_STATUS obj_status;
417 
418 	/* component id is invalid */
419 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
420 		return QDF_STATUS_MAXCOMP_FAIL;
421 
422 	wlan_vdev_obj_lock(vdev);
423 	/* If there is a valid entry, return failure */
424 	if (vdev->vdev_comp_priv_obj[id] != comp_priv_obj) {
425 		vdev->obj_status[id] = QDF_STATUS_E_FAILURE;
426 		wlan_vdev_obj_unlock(vdev);
427 		return QDF_STATUS_E_FAILURE;
428 	}
429 	/* Reset pointers to NULL, update the status*/
430 	vdev->vdev_comp_priv_obj[id] = NULL;
431 	vdev->obj_status[id] = QDF_STATUS_SUCCESS;
432 	wlan_vdev_obj_unlock(vdev);
433 
434 	/**
435 	 *If VDEV object status is partially destroyed means, this API is
436 	 * invoked with differnt context, this block should be executed for
437 	 * async components only
438 	 */
439 	if ((vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) ||
440 	    (vdev->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) {
441 		/* Derive object status */
442 		obj_status = wlan_objmgr_vdev_object_status(vdev);
443 		if (obj_status == QDF_STATUS_SUCCESS) {
444 			/*
445 			 * Update the status as Deleted, if full object
446 			 * deletion is in progress
447 			 */
448 			if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
449 				vdev->obj_state = WLAN_OBJ_STATE_DELETED;
450 			/*
451 			 * Move to creation state, since this component
452 			 * deletion alone requested
453 			 */
454 			else if (vdev->obj_state ==
455 					WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
456 				vdev->obj_state = WLAN_OBJ_STATE_CREATED;
457 		/* Object status is failure */
458 		} else if (obj_status == QDF_STATUS_E_FAILURE) {
459 			/*
460 			 * Update the status as Deletion failed, if full object
461 			 * deletion is in progress
462 			 */
463 			if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
464 				vdev->obj_state =
465 					WLAN_OBJ_STATE_DELETION_FAILED;
466 			/* Move to creation state, since this component
467 			deletion alone requested (do not block other
468 			components) */
469 			else if (vdev->obj_state ==
470 					WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
471 				vdev->obj_state = WLAN_OBJ_STATE_CREATED;
472 		}
473 		/* Delete vdev object */
474 		if ((obj_status == QDF_STATUS_SUCCESS)  &&
475 		    (vdev->obj_state == WLAN_OBJ_STATE_DELETED)) {
476 			/* Free VDEV object */
477 			return wlan_objmgr_vdev_obj_free(vdev);
478 		}
479 	}
480 	return QDF_STATUS_SUCCESS;
481 }
482 qdf_export_symbol(wlan_objmgr_vdev_component_obj_detach);
483 
484 /**
485  ** APIs to operations on vdev objects
486  */
487 QDF_STATUS wlan_objmgr_iterate_peerobj_list(
488 		struct wlan_objmgr_vdev *vdev,
489 		wlan_objmgr_vdev_op_handler handler,
490 		void *arg, wlan_objmgr_ref_dbgid dbg_id)
491 {
492 	qdf_list_t *peer_list = NULL;
493 	struct wlan_objmgr_peer *peer = NULL;
494 	struct wlan_objmgr_peer *peer_next = NULL;
495 	uint8_t vdev_id;
496 
497 	if (vdev == NULL) {
498 		obj_mgr_err("VDEV is NULL");
499 		return QDF_STATUS_E_FAILURE;
500 	}
501 	wlan_vdev_obj_lock(vdev);
502 	vdev_id = wlan_vdev_get_id(vdev);
503 
504 	if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) {
505 		wlan_vdev_obj_unlock(vdev);
506 		obj_mgr_err("VDEV is not in create state(:%d): vdev-id:%d",
507 				vdev_id, vdev->obj_state);
508 		return QDF_STATUS_E_FAILURE;
509 	}
510 	wlan_objmgr_vdev_get_ref(vdev, dbg_id);
511 	peer_list = &vdev->vdev_objmgr.wlan_peer_list;
512 	if (peer_list != NULL) {
513 		/* Iterate through VDEV's peer list */
514 		peer = wlan_vdev_peer_list_peek_head(peer_list);
515 		while (peer != NULL) {
516 			peer_next = wlan_peer_get_next_peer_of_vdev(peer_list,
517 							       peer);
518 			if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
519 					QDF_STATUS_SUCCESS) {
520 				/* Invoke handler for operation */
521 				handler(vdev, (void *)peer, arg);
522 				wlan_objmgr_peer_release_ref(peer, dbg_id);
523 			}
524 			peer = peer_next;
525 		}
526 	}
527 	wlan_objmgr_vdev_release_ref(vdev, dbg_id);
528 	wlan_vdev_obj_unlock(vdev);
529 	return QDF_STATUS_SUCCESS;
530 }
531 
532 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_creation(
533 		struct wlan_objmgr_vdev *vdev,
534 		enum wlan_umac_comp_id id)
535 {
536 	wlan_objmgr_vdev_create_handler handler;
537 	void *arg;
538 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
539 
540 	/* Component id is invalid */
541 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
542 		return QDF_STATUS_MAXCOMP_FAIL;
543 
544 	wlan_vdev_obj_lock(vdev);
545 	/*
546 	 * If component object is already created, delete old
547 	 * component object, then invoke creation
548 	 */
549 	if (vdev->vdev_comp_priv_obj[id] != NULL) {
550 		wlan_vdev_obj_unlock(vdev);
551 		return QDF_STATUS_E_FAILURE;
552 	}
553 	wlan_vdev_obj_unlock(vdev);
554 
555 	/* Invoke registered create handlers */
556 	handler = g_umac_glb_obj->vdev_create_handler[id];
557 	arg = g_umac_glb_obj->vdev_create_handler_arg[id];
558 	if (handler != NULL)
559 		vdev->obj_status[id] = handler(vdev, arg);
560 	else
561 		return QDF_STATUS_E_FAILURE;
562 
563 	/* If object status is created, then only handle this object status */
564 	if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) {
565 		/* Derive object status */
566 		obj_status = wlan_objmgr_vdev_object_status(vdev);
567 		/* Move PDEV object state to Partially created state */
568 		if (obj_status == QDF_STATUS_COMP_ASYNC) {
569 			/*TODO atomic */
570 			vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
571 		}
572 	}
573 	return obj_status;
574 }
575 
576 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_deletion(
577 		struct wlan_objmgr_vdev *vdev,
578 		enum wlan_umac_comp_id id)
579 {
580 	wlan_objmgr_vdev_destroy_handler handler;
581 	void *arg;
582 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
583 
584 	/* component id is invalid */
585 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
586 		return QDF_STATUS_MAXCOMP_FAIL;
587 
588 	wlan_vdev_obj_lock(vdev);
589 	/* Component object was never created, invalid operation */
590 	if (vdev->vdev_comp_priv_obj[id] == NULL) {
591 		wlan_vdev_obj_unlock(vdev);
592 		return QDF_STATUS_E_FAILURE;
593 	}
594 	wlan_vdev_obj_unlock(vdev);
595 
596 	/* Invoke registered create handlers */
597 	handler = g_umac_glb_obj->vdev_destroy_handler[id];
598 	arg = g_umac_glb_obj->vdev_destroy_handler_arg[id];
599 	if (handler != NULL)
600 		vdev->obj_status[id] = handler(vdev, arg);
601 	else
602 		return QDF_STATUS_E_FAILURE;
603 
604 	/* If object status is created, then only handle this object status */
605 	if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) {
606 		obj_status = wlan_objmgr_vdev_object_status(vdev);
607 		/* move object state to DEL progress */
608 		if (obj_status == QDF_STATUS_COMP_ASYNC)
609 			vdev->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS;
610 	}
611 	return obj_status;
612 }
613 
614 
615 
616 static void wlan_obj_vdev_peerlist_add_tail(qdf_list_t *obj_list,
617 	struct wlan_objmgr_peer *obj)
618 {
619 	qdf_list_insert_back(obj_list, &obj->vdev_peer);
620 }
621 
622 static QDF_STATUS wlan_obj_vdev_peerlist_remove_peer(qdf_list_t *obj_list,
623 					struct wlan_objmgr_peer *peer)
624 {
625 	qdf_list_node_t *vdev_node = NULL;
626 
627 	if (peer == NULL)
628 		return QDF_STATUS_E_FAILURE;
629 	/* get vdev list node element */
630 	vdev_node = &peer->vdev_peer;
631 	/* list is empty, return failure */
632 	if (qdf_list_remove_node(obj_list, vdev_node) != QDF_STATUS_SUCCESS)
633 		return QDF_STATUS_E_FAILURE;
634 
635 	return QDF_STATUS_SUCCESS;
636 }
637 
638 QDF_STATUS wlan_objmgr_vdev_peer_attach(struct wlan_objmgr_vdev *vdev,
639 						struct wlan_objmgr_peer *peer)
640 {
641 	struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr;
642 	struct wlan_objmgr_pdev *pdev;
643 	enum QDF_OPMODE opmode;
644 
645 	wlan_vdev_obj_lock(vdev);
646 	pdev = wlan_vdev_get_pdev(vdev);
647 	/* If Max VDEV peer count exceeds, return failure */
648 	if (peer->peer_mlme.peer_type != WLAN_PEER_STA_TEMP) {
649 		if (objmgr->wlan_peer_count >= objmgr->max_peer_count) {
650 			wlan_vdev_obj_unlock(vdev);
651 			return QDF_STATUS_E_FAILURE;
652 		}
653 	}
654 	wlan_vdev_obj_unlock(vdev);
655 
656 	/* If Max PDEV peer count exceeds, return failure */
657 	wlan_pdev_obj_lock(pdev);
658 	if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) {
659 		if (wlan_pdev_get_temp_peer_count(pdev) >=
660 			WLAN_MAX_PDEV_TEMP_PEERS) {
661 			wlan_pdev_obj_unlock(pdev);
662 			return QDF_STATUS_E_FAILURE;
663 		}
664 	} else {
665 		if (wlan_pdev_get_peer_count(pdev) >=
666 			wlan_pdev_get_max_peer_count(pdev)) {
667 			wlan_pdev_obj_unlock(pdev);
668 			return QDF_STATUS_E_FAILURE;
669 		}
670 	}
671 
672 	if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP)
673 		wlan_pdev_incr_temp_peer_count(wlan_vdev_get_pdev(vdev));
674 	else
675 		wlan_pdev_incr_peer_count(wlan_vdev_get_pdev(vdev));
676 	wlan_pdev_obj_unlock(pdev);
677 
678 	wlan_vdev_obj_lock(vdev);
679 	/* Add peer to vdev's peer list */
680 	wlan_obj_vdev_peerlist_add_tail(&objmgr->wlan_peer_list, peer);
681 	objmgr->wlan_peer_count++;
682 
683 	if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer),
684 			 wlan_vdev_mlme_get_macaddr(vdev)) ==
685 				QDF_STATUS_SUCCESS) {
686 		/*
687 		 * if peer mac address and vdev mac address match, set
688 		 * this peer as self peer
689 		 */
690 		wlan_vdev_set_selfpeer(vdev, peer);
691 		opmode = wlan_vdev_mlme_get_opmode(vdev);
692 		/* For AP mode, self peer and BSS peer are same */
693 		if ((opmode == QDF_SAP_MODE) || (opmode == QDF_P2P_GO_MODE))
694 			wlan_vdev_set_bsspeer(vdev, peer);
695 	}
696 	/* set BSS peer for sta */
697 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) &&
698 		((wlan_peer_get_peer_type(peer) == WLAN_PEER_AP) ||
699 		 (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO)))
700 		wlan_vdev_set_bsspeer(vdev, peer);
701 
702 	/* Increment vdev ref count to make sure it won't be destroyed before */
703 	wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID);
704 	wlan_vdev_obj_unlock(vdev);
705 	return QDF_STATUS_SUCCESS;
706 }
707 
708 QDF_STATUS wlan_objmgr_vdev_peer_detach(struct wlan_objmgr_vdev *vdev,
709 					struct wlan_objmgr_peer *peer)
710 {
711 	struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr;
712 	struct wlan_objmgr_pdev *pdev;
713 
714 	wlan_vdev_obj_lock(vdev);
715 	/* if peer count is 0, return failure */
716 	if (objmgr->wlan_peer_count == 0) {
717 		wlan_vdev_obj_unlock(vdev);
718 		return QDF_STATUS_E_FAILURE;
719 	}
720 
721 	if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_AP) ||
722 	    (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO)) {
723 		if (wlan_vdev_get_selfpeer(vdev) == peer) {
724 			/*
725 			 * There might be instances where new node is created
726 			 * before deleting existing node, in which case selfpeer
727 			 * will be pointing to the new node. So set selfpeer to
728 			 * NULL only if vdev->vdev_objmgr.self_peer is pointing
729 			 * to the peer processed for deletion
730 			 */
731 			wlan_vdev_set_selfpeer(vdev, NULL);
732 		}
733 
734 		if (wlan_vdev_get_bsspeer(vdev) == peer) {
735 			/*
736 			 * There might be instances where new node is created
737 			 * before deleting existing node, in which case bsspeer
738 			 * in vdev will be pointing to the new node. So set
739 			 * bsspeer to NULL only if vdev->vdev_objmgr.bss_peer is
740 			 * pointing to the peer processed for deletion
741 			 */
742 			wlan_vdev_set_bsspeer(vdev, NULL);
743 		}
744 	}
745 
746 	/* remove peer from vdev's peer list */
747 	if (wlan_obj_vdev_peerlist_remove_peer(&objmgr->wlan_peer_list, peer)
748 				== QDF_STATUS_E_FAILURE) {
749 		wlan_vdev_obj_unlock(vdev);
750 		return QDF_STATUS_E_FAILURE;
751 	}
752 	/* decrement peer count */
753 	objmgr->wlan_peer_count--;
754 	/* decrement pdev peer count */
755 	pdev = wlan_vdev_get_pdev(vdev);
756 	wlan_vdev_obj_unlock(vdev);
757 
758 	wlan_pdev_obj_lock(pdev);
759 	if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP)
760 		wlan_pdev_decr_temp_peer_count(pdev);
761 	else
762 		wlan_pdev_decr_peer_count(pdev);
763 	wlan_pdev_obj_unlock(pdev);
764 
765 	/* decrement vdev ref count after peer released its reference */
766 	wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
767 	return QDF_STATUS_SUCCESS;
768 }
769 
770 void *wlan_objmgr_vdev_get_comp_private_obj(
771 		struct wlan_objmgr_vdev *vdev,
772 		enum wlan_umac_comp_id id)
773 {
774 	void *comp_priv_obj;
775 
776 	/* component id is invalid */
777 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
778 		QDF_BUG(0);
779 		return NULL;
780 	}
781 
782 	if (vdev == NULL) {
783 		QDF_BUG(0);
784 		return NULL;
785 	}
786 
787 	comp_priv_obj = vdev->vdev_comp_priv_obj[id];
788 
789 	return comp_priv_obj;
790 }
791 qdf_export_symbol(wlan_objmgr_vdev_get_comp_private_obj);
792 
793 void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev,
794 						wlan_objmgr_ref_dbgid id)
795 {
796 	if (vdev == NULL) {
797 		obj_mgr_err("vdev obj is NULL for id:%d", id);
798 		QDF_ASSERT(0);
799 		return;
800 	}
801 	/* Increment ref count */
802 	qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt);
803 	qdf_atomic_inc(&vdev->vdev_objmgr.ref_id_dbg[id]);
804 
805 	return;
806 }
807 qdf_export_symbol(wlan_objmgr_vdev_get_ref);
808 
809 QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev,
810 						wlan_objmgr_ref_dbgid id)
811 {
812 	uint8_t vdev_id;
813 
814 	if (vdev == NULL) {
815 		obj_mgr_err("vdev obj is NULL for id:%d", id);
816 		QDF_ASSERT(0);
817 		return QDF_STATUS_E_FAILURE;
818 	}
819 
820 	wlan_vdev_obj_lock(vdev);
821 	vdev_id = wlan_vdev_get_id(vdev);
822 	if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) {
823 		wlan_vdev_obj_unlock(vdev);
824 		if (vdev->vdev_objmgr.print_cnt++ <=
825 				WLAN_OBJMGR_RATELIMIT_THRESH)
826 			obj_mgr_err(
827 			"[Ref id: %d] vdev(%d) is not in Created state(%d)",
828 				id, vdev_id, vdev->obj_state);
829 
830 		return QDF_STATUS_E_RESOURCES;
831 	}
832 
833 	/* Increment ref count */
834 	wlan_objmgr_vdev_get_ref(vdev, id);
835 	wlan_vdev_obj_unlock(vdev);
836 
837 	return QDF_STATUS_SUCCESS;
838 }
839 qdf_export_symbol(wlan_objmgr_vdev_try_get_ref);
840 
841 void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev,
842 						wlan_objmgr_ref_dbgid id)
843 {
844 	uint8_t vdev_id;
845 
846 	if (vdev == NULL) {
847 		obj_mgr_err("vdev obj is NULL for id:%d", id);
848 		QDF_ASSERT(0);
849 		return;
850 	}
851 
852 	vdev_id = wlan_vdev_get_id(vdev);
853 
854 	if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_id_dbg[id])) {
855 		obj_mgr_err("vdev (id:%d)ref cnt was not taken by %d",
856 				vdev_id, id);
857 		wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg,
858 					  QDF_TRACE_LEVEL_FATAL);
859 		WLAN_OBJMGR_BUG(0);
860 	}
861 
862 	if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) {
863 		obj_mgr_err("vdev ref cnt is 0");
864 		WLAN_OBJMGR_BUG(0);
865 		return;
866 	}
867 	qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]);
868 
869 	/* Decrement ref count, free vdev, if ref count == 0 */
870 	if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt))
871 		wlan_objmgr_vdev_obj_destroy(vdev);
872 
873 	return;
874 }
875 qdf_export_symbol(wlan_objmgr_vdev_release_ref);
876 
877 bool wlan_vdev_is_connected(struct wlan_objmgr_vdev *vdev)
878 {
879 	struct wlan_objmgr_peer *peer;
880 	enum wlan_peer_state peer_state;
881 
882 	wlan_vdev_obj_lock(vdev);
883 	peer = wlan_vdev_get_bsspeer(vdev);
884 	wlan_vdev_obj_unlock(vdev);
885 
886 	if (!peer)
887 		return false;
888 
889 	wlan_peer_obj_lock(peer);
890 	peer_state = wlan_peer_mlme_get_state(peer);
891 	wlan_peer_obj_unlock(peer);
892 
893 	if (peer_state != WLAN_ASSOC_STATE)
894 		return false;
895 
896 	return true;
897 }
898 qdf_export_symbol(wlan_vdev_is_connected);
899 
900 struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head(
901 			struct wlan_objmgr_pdev *pdev,
902 			qdf_list_t *vdev_list, wlan_objmgr_ref_dbgid dbg_id)
903 {
904 	struct wlan_objmgr_vdev *vdev;
905 	qdf_list_node_t *node = NULL;
906 	qdf_list_node_t *prev_node = NULL;
907 
908 	wlan_pdev_obj_lock(pdev);
909 
910 	if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) {
911 		wlan_pdev_obj_unlock(pdev);
912 		return NULL;
913 	}
914 
915 	do {
916 		vdev = qdf_container_of(node, struct wlan_objmgr_vdev,
917 								vdev_node);
918 		if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) ==
919 						QDF_STATUS_SUCCESS) {
920 			wlan_pdev_obj_unlock(pdev);
921 			return vdev;
922 		}
923 
924 		prev_node = node;
925 	} while (qdf_list_peek_next(vdev_list, prev_node, &node) ==
926 						QDF_STATUS_SUCCESS);
927 
928 	wlan_pdev_obj_unlock(pdev);
929 
930 	return NULL;
931 }
932 
933 struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev(
934 			struct wlan_objmgr_pdev *pdev,
935 			qdf_list_t *vdev_list,
936 			struct wlan_objmgr_vdev *vdev,
937 			wlan_objmgr_ref_dbgid dbg_id)
938 {
939 	struct wlan_objmgr_vdev *vdev_next;
940 	qdf_list_node_t *node = &vdev->vdev_node;
941 	qdf_list_node_t *prev_node = NULL;
942 
943 	if (node == NULL)
944 		return NULL;
945 
946 	wlan_pdev_obj_lock(pdev);
947 	prev_node = node;
948 	while (qdf_list_peek_next(vdev_list, prev_node, &node) ==
949 							QDF_STATUS_SUCCESS) {
950 		vdev_next = qdf_container_of(node, struct wlan_objmgr_vdev,
951 								vdev_node);
952 		if (wlan_objmgr_vdev_try_get_ref(vdev_next, dbg_id) ==
953 						QDF_STATUS_SUCCESS) {
954 			wlan_pdev_obj_unlock(pdev);
955 			return vdev_next;
956 		}
957 
958 		prev_node = node;
959 	}
960 	wlan_pdev_obj_unlock(pdev);
961 
962 	return NULL;
963 }
964 
965