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