xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c (revision 6ecd284e5a94a1c96e26d571dd47419ac305990d)
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 	/* TODO init other parameters */
220 
221 	/* Invoke registered create handlers */
222 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
223 		handler = g_umac_glb_obj->vdev_create_handler[id];
224 		arg = g_umac_glb_obj->vdev_create_handler_arg[id];
225 		if (handler != NULL)
226 			vdev->obj_status[id] = handler(vdev, arg);
227 		else
228 			vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED;
229 	}
230 
231 	/* Derive object status */
232 	obj_status = wlan_objmgr_vdev_object_status(vdev);
233 
234 	if (obj_status == QDF_STATUS_SUCCESS) {
235 		/* Object status is SUCCESS, Object is created */
236 		vdev->obj_state = WLAN_OBJ_STATE_CREATED;
237 		/* Invoke component registered status handlers */
238 		for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
239 			stat_handler = g_umac_glb_obj->vdev_status_handler[id];
240 			arg = g_umac_glb_obj->vdev_status_handler_arg[id];
241 			if (stat_handler != NULL) {
242 				stat_handler(vdev, arg,
243 					     QDF_STATUS_SUCCESS);
244 			}
245 		}
246 	/*
247 	 * Few components operates in Asynchrous communction, Object state
248 	 * partially created
249 	 */
250 	} else if (obj_status == QDF_STATUS_COMP_ASYNC) {
251 		vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
252 	/* Component object failed to be created, clean up the object */
253 	} else if (obj_status == QDF_STATUS_E_FAILURE) {
254 		/* Clean up the psoc */
255 		wlan_objmgr_vdev_obj_delete(vdev);
256 		obj_mgr_err("VDEV comp objects creation failed for vdev-id:%d",
257 			vdev->vdev_objmgr.vdev_id);
258 		return NULL;
259 	}
260 
261 	obj_mgr_info("Created vdev %d", vdev->vdev_objmgr.vdev_id);
262 
263 	return vdev;
264 }
265 qdf_export_symbol(wlan_objmgr_vdev_obj_create);
266 
267 static QDF_STATUS wlan_objmgr_vdev_obj_destroy(struct wlan_objmgr_vdev *vdev)
268 {
269 	uint8_t id;
270 	wlan_objmgr_vdev_destroy_handler handler;
271 	QDF_STATUS obj_status;
272 	void *arg;
273 	uint8_t vdev_id;
274 
275 	if (vdev == NULL) {
276 		obj_mgr_err("vdev is NULL");
277 		return QDF_STATUS_E_FAILURE;
278 	}
279 	wlan_objmgr_notify_destroy(vdev, WLAN_VDEV_OP);
280 
281 	vdev_id = wlan_vdev_get_id(vdev);
282 
283 	obj_mgr_info("Physically deleting vdev %d", vdev_id);
284 
285 	if (vdev->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) {
286 		obj_mgr_err("vdev object delete is not invoked: vdev-id:%d",
287 			wlan_vdev_get_id(vdev));
288 		WLAN_OBJMGR_BUG(0);
289 	}
290 
291 	/* Invoke registered destroy handlers */
292 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
293 		handler = g_umac_glb_obj->vdev_destroy_handler[id];
294 		arg = g_umac_glb_obj->vdev_destroy_handler_arg[id];
295 		if (handler != NULL)
296 			vdev->obj_status[id] = handler(vdev, arg);
297 		else
298 			vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED;
299 	}
300 	/* Derive object status */
301 	obj_status = wlan_objmgr_vdev_object_status(vdev);
302 
303 	if (obj_status == QDF_STATUS_E_FAILURE) {
304 		obj_mgr_err("VDEV object deletion failed: vdev-id: %d",
305 				vdev_id);
306 		/* Ideally should not happen */
307 		/* This leads to memleak ??? how to handle */
308 		QDF_BUG(0);
309 		return QDF_STATUS_E_FAILURE;
310 	}
311 
312 	/* Deletion is in progress */
313 	if (obj_status == QDF_STATUS_COMP_ASYNC) {
314 		vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED;
315 		return QDF_STATUS_COMP_ASYNC;
316 	}
317 
318 	/* Free VDEV object */
319 	return wlan_objmgr_vdev_obj_free(vdev);
320 }
321 
322 QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev)
323 {
324 	uint8_t print_idx;
325 
326 	if (vdev == NULL) {
327 		obj_mgr_err("vdev is NULL");
328 		return QDF_STATUS_E_FAILURE;
329 	}
330 
331 	obj_mgr_info("Logically deleting vdev %d", vdev->vdev_objmgr.vdev_id);
332 
333 	print_idx = qdf_get_pidx();
334 	if (qdf_print_is_verbose_enabled(print_idx, QDF_MODULE_ID_OBJ_MGR,
335 		QDF_TRACE_LEVEL_DEBUG)) {
336 		wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg);
337 	}
338 
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 peer count exceeds, return failure */
650 	if (objmgr->wlan_peer_count >= objmgr->max_peer_count) {
651 		wlan_vdev_obj_unlock(vdev);
652 		return QDF_STATUS_E_FAILURE;
653 	}
654 	wlan_vdev_obj_unlock(vdev);
655 
656 	wlan_pdev_obj_lock(pdev);
657 	if (wlan_pdev_get_peer_count(pdev) >=
658 			wlan_pdev_get_max_peer_count(pdev)) {
659 		wlan_pdev_obj_unlock(pdev);
660 		return QDF_STATUS_E_FAILURE;
661 	}
662 
663 	wlan_pdev_incr_peer_count(wlan_vdev_get_pdev(vdev));
664 	wlan_pdev_obj_unlock(pdev);
665 
666 	wlan_vdev_obj_lock(vdev);
667 	/* Add peer to vdev's peer list */
668 	wlan_obj_vdev_peerlist_add_tail(&objmgr->wlan_peer_list, peer);
669 	objmgr->wlan_peer_count++;
670 
671 	if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer),
672 			 wlan_vdev_mlme_get_macaddr(vdev)) ==
673 				QDF_STATUS_SUCCESS) {
674 		/*
675 		 * if peer mac address and vdev mac address match, set
676 		 * this peer as self peer
677 		 */
678 		wlan_vdev_set_selfpeer(vdev, peer);
679 		opmode = wlan_vdev_mlme_get_opmode(vdev);
680 		/* For AP mode, self peer and BSS peer are same */
681 		if ((opmode == QDF_SAP_MODE) || (opmode == QDF_P2P_GO_MODE))
682 			wlan_vdev_set_bsspeer(vdev, peer);
683 	}
684 	/* set BSS peer for sta */
685 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) &&
686 		((wlan_peer_get_peer_type(peer) == WLAN_PEER_AP) ||
687 		 (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO)))
688 		wlan_vdev_set_bsspeer(vdev, peer);
689 
690 	/* Increment vdev ref count to make sure it won't be destroyed before */
691 	wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID);
692 	wlan_vdev_obj_unlock(vdev);
693 	return QDF_STATUS_SUCCESS;
694 }
695 
696 QDF_STATUS wlan_objmgr_vdev_peer_detach(struct wlan_objmgr_vdev *vdev,
697 					struct wlan_objmgr_peer *peer)
698 {
699 	struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr;
700 	struct wlan_objmgr_pdev *pdev;
701 
702 	wlan_vdev_obj_lock(vdev);
703 	/* if peer count is 0, return failure */
704 	if (objmgr->wlan_peer_count == 0) {
705 		wlan_vdev_obj_unlock(vdev);
706 		return QDF_STATUS_E_FAILURE;
707 	}
708 
709 	if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_AP) ||
710 	    (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO)) {
711 		if (wlan_vdev_get_selfpeer(vdev) == peer) {
712 			/*
713 			 * There might be instances where new node is created
714 			 * before deleting existing node, in which case selfpeer
715 			 * will be pointing to the new node. So set selfpeer to
716 			 * NULL only if vdev->vdev_objmgr.self_peer is pointing
717 			 * to the peer processed for deletion
718 			 */
719 			wlan_vdev_set_selfpeer(vdev, NULL);
720 		}
721 
722 		if (wlan_vdev_get_bsspeer(vdev) == peer) {
723 			/*
724 			 * There might be instances where new node is created
725 			 * before deleting existing node, in which case bsspeer
726 			 * in vdev will be pointing to the new node. So set
727 			 * bsspeer to NULL only if vdev->vdev_objmgr.bss_peer is
728 			 * pointing to the peer processed for deletion
729 			 */
730 			wlan_vdev_set_bsspeer(vdev, NULL);
731 		}
732 	}
733 
734 	/* remove peer from vdev's peer list */
735 	if (wlan_obj_vdev_peerlist_remove_peer(&objmgr->wlan_peer_list, peer)
736 				== QDF_STATUS_E_FAILURE) {
737 		wlan_vdev_obj_unlock(vdev);
738 		return QDF_STATUS_E_FAILURE;
739 	}
740 	/* decrement peer count */
741 	objmgr->wlan_peer_count--;
742 	/* decrement pdev peer count */
743 	pdev = wlan_vdev_get_pdev(vdev);
744 	wlan_vdev_obj_unlock(vdev);
745 
746 	wlan_pdev_obj_lock(pdev);
747 	wlan_pdev_decr_peer_count(pdev);
748 	wlan_pdev_obj_unlock(pdev);
749 
750 	/* decrement vdev ref count after peer released its reference */
751 	wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
752 	return QDF_STATUS_SUCCESS;
753 }
754 
755 void *wlan_objmgr_vdev_get_comp_private_obj(
756 		struct wlan_objmgr_vdev *vdev,
757 		enum wlan_umac_comp_id id)
758 {
759 	void *comp_priv_obj;
760 
761 	/* component id is invalid */
762 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
763 		QDF_BUG(0);
764 		return NULL;
765 	}
766 
767 	if (vdev == NULL) {
768 		QDF_BUG(0);
769 		return NULL;
770 	}
771 
772 	comp_priv_obj = vdev->vdev_comp_priv_obj[id];
773 
774 	return comp_priv_obj;
775 }
776 qdf_export_symbol(wlan_objmgr_vdev_get_comp_private_obj);
777 
778 void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev,
779 						wlan_objmgr_ref_dbgid id)
780 {
781 	if (vdev == NULL) {
782 		obj_mgr_err("vdev obj is NULL for id:%d", id);
783 		QDF_ASSERT(0);
784 		return;
785 	}
786 	/* Increment ref count */
787 	qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt);
788 	qdf_atomic_inc(&vdev->vdev_objmgr.ref_id_dbg[id]);
789 
790 	return;
791 }
792 qdf_export_symbol(wlan_objmgr_vdev_get_ref);
793 
794 QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev,
795 						wlan_objmgr_ref_dbgid id)
796 {
797 	uint8_t vdev_id;
798 
799 	if (vdev == NULL) {
800 		obj_mgr_err("vdev obj is NULL for id:%d", id);
801 		QDF_ASSERT(0);
802 		return QDF_STATUS_E_FAILURE;
803 	}
804 
805 	wlan_vdev_obj_lock(vdev);
806 	vdev_id = wlan_vdev_get_id(vdev);
807 	if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) {
808 		wlan_vdev_obj_unlock(vdev);
809 		if (vdev->vdev_objmgr.print_cnt++ <=
810 				WLAN_OBJMGR_RATELIMIT_THRESH)
811 			obj_mgr_err(
812 			"[Ref id: %d] vdev(%d) is not in Created state(%d)",
813 				id, vdev_id, vdev->obj_state);
814 
815 		return QDF_STATUS_E_RESOURCES;
816 	}
817 
818 	/* Increment ref count */
819 	wlan_objmgr_vdev_get_ref(vdev, id);
820 	wlan_vdev_obj_unlock(vdev);
821 
822 	return QDF_STATUS_SUCCESS;
823 }
824 qdf_export_symbol(wlan_objmgr_vdev_try_get_ref);
825 
826 void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev,
827 						wlan_objmgr_ref_dbgid id)
828 {
829 	uint8_t vdev_id;
830 
831 	if (vdev == NULL) {
832 		obj_mgr_err("vdev obj is NULL for id:%d", id);
833 		QDF_ASSERT(0);
834 		return;
835 	}
836 
837 	vdev_id = wlan_vdev_get_id(vdev);
838 
839 	if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_id_dbg[id])) {
840 		obj_mgr_err("vdev (id:%d)ref cnt was not taken by %d",
841 				vdev_id, id);
842 		wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg);
843 		WLAN_OBJMGR_BUG(0);
844 	}
845 
846 	if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) {
847 		obj_mgr_err("vdev ref cnt is 0");
848 		WLAN_OBJMGR_BUG(0);
849 		return;
850 	}
851 	qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]);
852 
853 	/* Decrement ref count, free vdev, if ref count == 0 */
854 	if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt))
855 		wlan_objmgr_vdev_obj_destroy(vdev);
856 
857 	return;
858 }
859 qdf_export_symbol(wlan_objmgr_vdev_release_ref);
860 
861 bool wlan_vdev_is_connected(struct wlan_objmgr_vdev *vdev)
862 {
863 	struct wlan_objmgr_peer *peer;
864 	enum wlan_peer_state peer_state;
865 
866 	wlan_vdev_obj_lock(vdev);
867 	peer = wlan_vdev_get_bsspeer(vdev);
868 	wlan_vdev_obj_unlock(vdev);
869 
870 	if (!peer)
871 		return false;
872 
873 	wlan_peer_obj_lock(peer);
874 	peer_state = wlan_peer_mlme_get_state(peer);
875 	wlan_peer_obj_unlock(peer);
876 
877 	if (peer_state != WLAN_ASSOC_STATE)
878 		return false;
879 
880 	return true;
881 }
882 qdf_export_symbol(wlan_vdev_is_connected);
883