xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c (revision 92d87f51612f6c3b2285266215edee8911647c2f)
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_info("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 	if (qdf_print_is_verbose_enabled(print_idx, QDF_MODULE_ID_OBJ_MGR,
336 		QDF_TRACE_LEVEL_DEBUG)) {
337 		wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg);
338 	}
339 
340 	/*
341 	 * Update VDEV object state to LOGICALLY DELETED
342 	 * It prevents further access of this object
343 	 */
344 	wlan_vdev_obj_lock(vdev);
345 	vdev->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED;
346 	wlan_vdev_obj_unlock(vdev);
347 	wlan_objmgr_notify_log_delete(vdev, WLAN_VDEV_OP);
348 	wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
349 
350 	return QDF_STATUS_SUCCESS;
351 }
352 qdf_export_symbol(wlan_objmgr_vdev_obj_delete);
353 
354 /**
355  ** APIs to attach/detach component objects
356  */
357 QDF_STATUS wlan_objmgr_vdev_component_obj_attach(
358 		struct wlan_objmgr_vdev *vdev,
359 		enum wlan_umac_comp_id id,
360 		void *comp_priv_obj,
361 		QDF_STATUS status)
362 {
363 	wlan_objmgr_vdev_status_handler stat_handler;
364 	void *arg;
365 	uint8_t i;
366 	QDF_STATUS obj_status;
367 
368 	/* component id is invalid */
369 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
370 		return QDF_STATUS_MAXCOMP_FAIL;
371 
372 	wlan_vdev_obj_lock(vdev);
373 	/* If there is a valid entry, return failure */
374 	if (vdev->vdev_comp_priv_obj[id] != NULL) {
375 		wlan_vdev_obj_unlock(vdev);
376 		return QDF_STATUS_E_FAILURE;
377 	}
378 	/* Save component's pointer and status */
379 	vdev->vdev_comp_priv_obj[id] = comp_priv_obj;
380 	vdev->obj_status[id] = status;
381 	wlan_vdev_obj_unlock(vdev);
382 	if (vdev->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED)
383 		return QDF_STATUS_SUCCESS;
384 	/*
385 	 * If VDEV object status is partially created means, this API is
386 	 * invoked with differnt context, this block should be executed for
387 	 * async components only
388 	 */
389 	/* Derive status */
390 	obj_status = wlan_objmgr_vdev_object_status(vdev);
391 	/* STATUS_SUCCESS means, object is CREATED */
392 	if (obj_status == QDF_STATUS_SUCCESS)
393 		vdev->obj_state = WLAN_OBJ_STATE_CREATED;
394 	/*
395 	 * update state as CREATION failed, caller has to delete the
396 	 * VDEV object
397 	 */
398 	else if (obj_status == QDF_STATUS_E_FAILURE)
399 		vdev->obj_state = WLAN_OBJ_STATE_CREATION_FAILED;
400 	/* Notify components about the CREATION success/failure */
401 	if ((obj_status == QDF_STATUS_SUCCESS) ||
402 	    (obj_status == QDF_STATUS_E_FAILURE)) {
403 		for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) {
404 			stat_handler = g_umac_glb_obj->vdev_status_handler[i];
405 			arg = g_umac_glb_obj->vdev_status_handler_arg[i];
406 			if (stat_handler != NULL)
407 				stat_handler(vdev, arg, obj_status);
408 		}
409 	}
410 	return QDF_STATUS_SUCCESS;
411 }
412 qdf_export_symbol(wlan_objmgr_vdev_component_obj_attach);
413 
414 QDF_STATUS wlan_objmgr_vdev_component_obj_detach(
415 		struct wlan_objmgr_vdev *vdev,
416 		enum wlan_umac_comp_id id,
417 		void *comp_priv_obj)
418 {
419 	QDF_STATUS obj_status;
420 
421 	/* component id is invalid */
422 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
423 		return QDF_STATUS_MAXCOMP_FAIL;
424 
425 	wlan_vdev_obj_lock(vdev);
426 	/* If there is a valid entry, return failure */
427 	if (vdev->vdev_comp_priv_obj[id] != comp_priv_obj) {
428 		vdev->obj_status[id] = QDF_STATUS_E_FAILURE;
429 		wlan_vdev_obj_unlock(vdev);
430 		return QDF_STATUS_E_FAILURE;
431 	}
432 	/* Reset pointers to NULL, update the status*/
433 	vdev->vdev_comp_priv_obj[id] = NULL;
434 	vdev->obj_status[id] = QDF_STATUS_SUCCESS;
435 	wlan_vdev_obj_unlock(vdev);
436 
437 	/**
438 	 *If VDEV object status is partially destroyed means, this API is
439 	 * invoked with differnt context, this block should be executed for
440 	 * async components only
441 	 */
442 	if ((vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) ||
443 	    (vdev->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) {
444 		/* Derive object status */
445 		obj_status = wlan_objmgr_vdev_object_status(vdev);
446 		if (obj_status == QDF_STATUS_SUCCESS) {
447 			/*
448 			 * Update the status as Deleted, if full object
449 			 * deletion is in progress
450 			 */
451 			if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
452 				vdev->obj_state = WLAN_OBJ_STATE_DELETED;
453 			/*
454 			 * Move to creation state, since this component
455 			 * deletion alone requested
456 			 */
457 			else if (vdev->obj_state ==
458 					WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
459 				vdev->obj_state = WLAN_OBJ_STATE_CREATED;
460 		/* Object status is failure */
461 		} else if (obj_status == QDF_STATUS_E_FAILURE) {
462 			/*
463 			 * Update the status as Deletion failed, if full object
464 			 * deletion is in progress
465 			 */
466 			if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
467 				vdev->obj_state =
468 					WLAN_OBJ_STATE_DELETION_FAILED;
469 			/* Move to creation state, since this component
470 			deletion alone requested (do not block other
471 			components) */
472 			else if (vdev->obj_state ==
473 					WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
474 				vdev->obj_state = WLAN_OBJ_STATE_CREATED;
475 		}
476 		/* Delete vdev object */
477 		if ((obj_status == QDF_STATUS_SUCCESS)  &&
478 		    (vdev->obj_state == WLAN_OBJ_STATE_DELETED)) {
479 			/* Free VDEV object */
480 			return wlan_objmgr_vdev_obj_free(vdev);
481 		}
482 	}
483 	return QDF_STATUS_SUCCESS;
484 }
485 qdf_export_symbol(wlan_objmgr_vdev_component_obj_detach);
486 
487 /**
488  ** APIs to operations on vdev objects
489  */
490 QDF_STATUS wlan_objmgr_iterate_peerobj_list(
491 		struct wlan_objmgr_vdev *vdev,
492 		wlan_objmgr_vdev_op_handler handler,
493 		void *arg, wlan_objmgr_ref_dbgid dbg_id)
494 {
495 	qdf_list_t *peer_list = NULL;
496 	struct wlan_objmgr_peer *peer = NULL;
497 	struct wlan_objmgr_peer *peer_next = NULL;
498 	uint8_t vdev_id;
499 
500 	if (vdev == NULL) {
501 		obj_mgr_err("VDEV is NULL");
502 		return QDF_STATUS_E_FAILURE;
503 	}
504 	wlan_vdev_obj_lock(vdev);
505 	vdev_id = wlan_vdev_get_id(vdev);
506 
507 	if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) {
508 		wlan_vdev_obj_unlock(vdev);
509 		obj_mgr_err("VDEV is not in create state(:%d): vdev-id:%d",
510 				vdev_id, vdev->obj_state);
511 		return QDF_STATUS_E_FAILURE;
512 	}
513 	wlan_objmgr_vdev_get_ref(vdev, dbg_id);
514 	peer_list = &vdev->vdev_objmgr.wlan_peer_list;
515 	if (peer_list != NULL) {
516 		/* Iterate through VDEV's peer list */
517 		peer = wlan_vdev_peer_list_peek_head(peer_list);
518 		while (peer != NULL) {
519 			peer_next = wlan_peer_get_next_peer_of_vdev(peer_list,
520 							       peer);
521 			if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
522 					QDF_STATUS_SUCCESS) {
523 				/* Invoke handler for operation */
524 				handler(vdev, (void *)peer, arg);
525 				wlan_objmgr_peer_release_ref(peer, dbg_id);
526 			}
527 			peer = peer_next;
528 		}
529 	}
530 	wlan_objmgr_vdev_release_ref(vdev, dbg_id);
531 	wlan_vdev_obj_unlock(vdev);
532 	return QDF_STATUS_SUCCESS;
533 }
534 
535 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_creation(
536 		struct wlan_objmgr_vdev *vdev,
537 		enum wlan_umac_comp_id id)
538 {
539 	wlan_objmgr_vdev_create_handler handler;
540 	void *arg;
541 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
542 
543 	/* Component id is invalid */
544 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
545 		return QDF_STATUS_MAXCOMP_FAIL;
546 
547 	wlan_vdev_obj_lock(vdev);
548 	/*
549 	 * If component object is already created, delete old
550 	 * component object, then invoke creation
551 	 */
552 	if (vdev->vdev_comp_priv_obj[id] != NULL) {
553 		wlan_vdev_obj_unlock(vdev);
554 		return QDF_STATUS_E_FAILURE;
555 	}
556 	wlan_vdev_obj_unlock(vdev);
557 
558 	/* Invoke registered create handlers */
559 	handler = g_umac_glb_obj->vdev_create_handler[id];
560 	arg = g_umac_glb_obj->vdev_create_handler_arg[id];
561 	if (handler != NULL)
562 		vdev->obj_status[id] = handler(vdev, arg);
563 	else
564 		return QDF_STATUS_E_FAILURE;
565 
566 	/* If object status is created, then only handle this object status */
567 	if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) {
568 		/* Derive object status */
569 		obj_status = wlan_objmgr_vdev_object_status(vdev);
570 		/* Move PDEV object state to Partially created state */
571 		if (obj_status == QDF_STATUS_COMP_ASYNC) {
572 			/*TODO atomic */
573 			vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
574 		}
575 	}
576 	return obj_status;
577 }
578 
579 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_deletion(
580 		struct wlan_objmgr_vdev *vdev,
581 		enum wlan_umac_comp_id id)
582 {
583 	wlan_objmgr_vdev_destroy_handler handler;
584 	void *arg;
585 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
586 
587 	/* component id is invalid */
588 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
589 		return QDF_STATUS_MAXCOMP_FAIL;
590 
591 	wlan_vdev_obj_lock(vdev);
592 	/* Component object was never created, invalid operation */
593 	if (vdev->vdev_comp_priv_obj[id] == NULL) {
594 		wlan_vdev_obj_unlock(vdev);
595 		return QDF_STATUS_E_FAILURE;
596 	}
597 	wlan_vdev_obj_unlock(vdev);
598 
599 	/* Invoke registered create handlers */
600 	handler = g_umac_glb_obj->vdev_destroy_handler[id];
601 	arg = g_umac_glb_obj->vdev_destroy_handler_arg[id];
602 	if (handler != NULL)
603 		vdev->obj_status[id] = handler(vdev, arg);
604 	else
605 		return QDF_STATUS_E_FAILURE;
606 
607 	/* If object status is created, then only handle this object status */
608 	if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) {
609 		obj_status = wlan_objmgr_vdev_object_status(vdev);
610 		/* move object state to DEL progress */
611 		if (obj_status == QDF_STATUS_COMP_ASYNC)
612 			vdev->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS;
613 	}
614 	return obj_status;
615 }
616 
617 
618 
619 static void wlan_obj_vdev_peerlist_add_tail(qdf_list_t *obj_list,
620 	struct wlan_objmgr_peer *obj)
621 {
622 	qdf_list_insert_back(obj_list, &obj->vdev_peer);
623 }
624 
625 static QDF_STATUS wlan_obj_vdev_peerlist_remove_peer(qdf_list_t *obj_list,
626 					struct wlan_objmgr_peer *peer)
627 {
628 	qdf_list_node_t *vdev_node = NULL;
629 
630 	if (peer == NULL)
631 		return QDF_STATUS_E_FAILURE;
632 	/* get vdev list node element */
633 	vdev_node = &peer->vdev_peer;
634 	/* list is empty, return failure */
635 	if (qdf_list_remove_node(obj_list, vdev_node) != QDF_STATUS_SUCCESS)
636 		return QDF_STATUS_E_FAILURE;
637 
638 	return QDF_STATUS_SUCCESS;
639 }
640 
641 QDF_STATUS wlan_objmgr_vdev_peer_attach(struct wlan_objmgr_vdev *vdev,
642 						struct wlan_objmgr_peer *peer)
643 {
644 	struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr;
645 	struct wlan_objmgr_pdev *pdev;
646 	enum QDF_OPMODE opmode;
647 
648 	wlan_vdev_obj_lock(vdev);
649 	pdev = wlan_vdev_get_pdev(vdev);
650 	/* If Max VDEV peer count exceeds, return failure */
651 	if (peer->peer_mlme.peer_type != WLAN_PEER_STA_TEMP) {
652 		if (objmgr->wlan_peer_count >= objmgr->max_peer_count) {
653 			wlan_vdev_obj_unlock(vdev);
654 			return QDF_STATUS_E_FAILURE;
655 		}
656 	}
657 	wlan_vdev_obj_unlock(vdev);
658 
659 	/* If Max PDEV peer count exceeds, return failure */
660 	wlan_pdev_obj_lock(pdev);
661 	if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) {
662 		if (wlan_pdev_get_temp_peer_count(pdev) >=
663 			WLAN_MAX_PDEV_TEMP_PEERS) {
664 			wlan_pdev_obj_unlock(pdev);
665 			return QDF_STATUS_E_FAILURE;
666 		}
667 	} else {
668 		if (wlan_pdev_get_peer_count(pdev) >=
669 			wlan_pdev_get_max_peer_count(pdev)) {
670 			wlan_pdev_obj_unlock(pdev);
671 			return QDF_STATUS_E_FAILURE;
672 		}
673 	}
674 
675 	if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP)
676 		wlan_pdev_incr_temp_peer_count(wlan_vdev_get_pdev(vdev));
677 	else
678 		wlan_pdev_incr_peer_count(wlan_vdev_get_pdev(vdev));
679 	wlan_pdev_obj_unlock(pdev);
680 
681 	wlan_vdev_obj_lock(vdev);
682 	/* Add peer to vdev's peer list */
683 	wlan_obj_vdev_peerlist_add_tail(&objmgr->wlan_peer_list, peer);
684 	objmgr->wlan_peer_count++;
685 
686 	if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer),
687 			 wlan_vdev_mlme_get_macaddr(vdev)) ==
688 				QDF_STATUS_SUCCESS) {
689 		/*
690 		 * if peer mac address and vdev mac address match, set
691 		 * this peer as self peer
692 		 */
693 		wlan_vdev_set_selfpeer(vdev, peer);
694 		opmode = wlan_vdev_mlme_get_opmode(vdev);
695 		/* For AP mode, self peer and BSS peer are same */
696 		if ((opmode == QDF_SAP_MODE) || (opmode == QDF_P2P_GO_MODE))
697 			wlan_vdev_set_bsspeer(vdev, peer);
698 	}
699 	/* set BSS peer for sta */
700 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_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 		WLAN_OBJMGR_BUG(0);
862 	}
863 
864 	if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) {
865 		obj_mgr_err("vdev ref cnt is 0");
866 		WLAN_OBJMGR_BUG(0);
867 		return;
868 	}
869 	qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]);
870 
871 	/* Decrement ref count, free vdev, if ref count == 0 */
872 	if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt))
873 		wlan_objmgr_vdev_obj_destroy(vdev);
874 
875 	return;
876 }
877 qdf_export_symbol(wlan_objmgr_vdev_release_ref);
878 
879 bool wlan_vdev_is_connected(struct wlan_objmgr_vdev *vdev)
880 {
881 	struct wlan_objmgr_peer *peer;
882 	enum wlan_peer_state peer_state;
883 
884 	wlan_vdev_obj_lock(vdev);
885 	peer = wlan_vdev_get_bsspeer(vdev);
886 	wlan_vdev_obj_unlock(vdev);
887 
888 	if (!peer)
889 		return false;
890 
891 	wlan_peer_obj_lock(peer);
892 	peer_state = wlan_peer_mlme_get_state(peer);
893 	wlan_peer_obj_unlock(peer);
894 
895 	if (peer_state != WLAN_ASSOC_STATE)
896 		return false;
897 
898 	return true;
899 }
900 qdf_export_symbol(wlan_vdev_is_connected);
901 
902 struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head(
903 			struct wlan_objmgr_pdev *pdev,
904 			qdf_list_t *vdev_list, wlan_objmgr_ref_dbgid dbg_id)
905 {
906 	struct wlan_objmgr_vdev *vdev;
907 	qdf_list_node_t *node = NULL;
908 	qdf_list_node_t *prev_node = NULL;
909 
910 	wlan_pdev_obj_lock(pdev);
911 
912 	if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) {
913 		wlan_pdev_obj_unlock(pdev);
914 		return NULL;
915 	}
916 
917 	do {
918 		vdev = qdf_container_of(node, struct wlan_objmgr_vdev,
919 								vdev_node);
920 		if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) ==
921 						QDF_STATUS_SUCCESS) {
922 			wlan_pdev_obj_unlock(pdev);
923 			return vdev;
924 		}
925 
926 		prev_node = node;
927 	} while (qdf_list_peek_next(vdev_list, prev_node, &node) ==
928 						QDF_STATUS_SUCCESS);
929 
930 	wlan_pdev_obj_unlock(pdev);
931 
932 	return NULL;
933 }
934 
935 struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev(
936 			struct wlan_objmgr_pdev *pdev,
937 			qdf_list_t *vdev_list,
938 			struct wlan_objmgr_vdev *vdev,
939 			wlan_objmgr_ref_dbgid dbg_id)
940 {
941 	struct wlan_objmgr_vdev *vdev_next;
942 	qdf_list_node_t *node = &vdev->vdev_node;
943 	qdf_list_node_t *prev_node = NULL;
944 
945 	if (node == NULL)
946 		return NULL;
947 
948 	wlan_pdev_obj_lock(pdev);
949 	prev_node = node;
950 	while (qdf_list_peek_next(vdev_list, prev_node, &node) ==
951 							QDF_STATUS_SUCCESS) {
952 		vdev_next = qdf_container_of(node, struct wlan_objmgr_vdev,
953 								vdev_node);
954 		if (wlan_objmgr_vdev_try_get_ref(vdev_next, dbg_id) ==
955 						QDF_STATUS_SUCCESS) {
956 			wlan_pdev_obj_unlock(pdev);
957 			return vdev_next;
958 		}
959 
960 		prev_node = node;
961 	}
962 	wlan_pdev_obj_unlock(pdev);
963 
964 	return NULL;
965 }
966 
967