xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c (revision 3149adf58a329e17232a4c0e58d460d025edd55a)
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 "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 = (struct wlan_channel *)qdf_mem_malloc(
148 			sizeof(struct wlan_channel));
149 	if (vdev->vdev_mlme.bss_chan == NULL) {
150 		QDF_TRACE(QDF_MODULE_ID_MLME, QDF_TRACE_LEVEL_ERROR,
151 				"%s:bss_chan is NULL", __func__);
152 		qdf_mem_free(vdev);
153 		return NULL;
154 	}
155 
156 	vdev->vdev_mlme.des_chan = (struct wlan_channel *)qdf_mem_malloc(
157 			sizeof(struct wlan_channel));
158 	if (vdev->vdev_mlme.des_chan == NULL) {
159 		QDF_TRACE(QDF_MODULE_ID_MLME, QDF_TRACE_LEVEL_ERROR,
160 				"%s:des_chan is NULL", __func__);
161 		qdf_mem_free(vdev->vdev_mlme.bss_chan);
162 		qdf_mem_free(vdev);
163 		return NULL;
164 	}
165 
166 	/* Initialize spinlock */
167 	qdf_spinlock_create(&vdev->vdev_lock);
168 	/* Attach VDEV to PSOC VDEV's list */
169 	if (wlan_objmgr_psoc_vdev_attach(psoc, vdev) !=
170 				QDF_STATUS_SUCCESS) {
171 		obj_mgr_err("psoc vdev attach failed for vdev-id:%d",
172 					vdev->vdev_objmgr.vdev_id);
173 		qdf_mem_free(vdev->vdev_mlme.bss_chan);
174 		qdf_mem_free(vdev->vdev_mlme.des_chan);
175 		qdf_spinlock_destroy(&vdev->vdev_lock);
176 		qdf_mem_free(vdev);
177 		return NULL;
178 	}
179 	/* Store pdev in vdev */
180 	wlan_vdev_set_pdev(vdev, pdev);
181 	/* Attach vdev to PDEV */
182 	if (wlan_objmgr_pdev_vdev_attach(pdev, vdev) !=
183 				QDF_STATUS_SUCCESS) {
184 		obj_mgr_err("pdev vdev attach failed for vdev-id:%d",
185 				vdev->vdev_objmgr.vdev_id);
186 		wlan_objmgr_psoc_vdev_detach(psoc, vdev);
187 		qdf_mem_free(vdev->vdev_mlme.bss_chan);
188 		qdf_mem_free(vdev->vdev_mlme.des_chan);
189 		qdf_spinlock_destroy(&vdev->vdev_lock);
190 		qdf_mem_free(vdev);
191 		return NULL;
192 	}
193 	/* set opmode */
194 	wlan_vdev_mlme_set_opmode(vdev, params->opmode);
195 	/* set MAC address */
196 	wlan_vdev_mlme_set_macaddr(vdev, params->macaddr);
197 	/* set MAT address */
198 	wlan_vdev_mlme_set_mataddr(vdev, params->mataddr);
199 	/* Set create flags */
200 	vdev->vdev_objmgr.c_flags = params->flags;
201 	/* store os-specific pointer */
202 	vdev->vdev_nif.osdev = params->osifp;
203 	/* peer count to 0 */
204 	vdev->vdev_objmgr.wlan_peer_count = 0;
205 	qdf_atomic_init(&vdev->vdev_objmgr.ref_cnt);
206 	vdev->vdev_objmgr.print_cnt = 0;
207 	wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID);
208 	/* Initialize max peer count based on opmode type */
209 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE)
210 		vdev->vdev_objmgr.max_peer_count = WLAN_UMAC_MAX_STA_PEERS;
211 	else
212 		vdev->vdev_objmgr.max_peer_count =
213 				wlan_pdev_get_max_peer_count(pdev);
214 
215 	/* Initialize peer list */
216 	qdf_list_create(&vdev->vdev_objmgr.wlan_peer_list,
217 			vdev->vdev_objmgr.max_peer_count);
218 	/* TODO init other parameters */
219 
220 	/* Invoke registered create handlers */
221 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
222 		handler = g_umac_glb_obj->vdev_create_handler[id];
223 		arg = g_umac_glb_obj->vdev_create_handler_arg[id];
224 		if (handler != NULL)
225 			vdev->obj_status[id] = handler(vdev, arg);
226 		else
227 			vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED;
228 	}
229 
230 	/* Derive object status */
231 	obj_status = wlan_objmgr_vdev_object_status(vdev);
232 
233 	if (obj_status == QDF_STATUS_SUCCESS) {
234 		/* Object status is SUCCESS, Object is created */
235 		vdev->obj_state = WLAN_OBJ_STATE_CREATED;
236 		/* Invoke component registered status handlers */
237 		for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
238 			stat_handler = g_umac_glb_obj->vdev_status_handler[id];
239 			arg = g_umac_glb_obj->vdev_status_handler_arg[id];
240 			if (stat_handler != NULL) {
241 				stat_handler(vdev, arg,
242 					     QDF_STATUS_SUCCESS);
243 			}
244 		}
245 	/*
246 	 * Few components operates in Asynchrous communction, Object state
247 	 * partially created
248 	 */
249 	} else if (obj_status == QDF_STATUS_COMP_ASYNC) {
250 		vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
251 	/* Component object failed to be created, clean up the object */
252 	} else if (obj_status == QDF_STATUS_E_FAILURE) {
253 		/* Clean up the psoc */
254 		wlan_objmgr_vdev_obj_delete(vdev);
255 		obj_mgr_err("VDEV comp objects creation failed for vdev-id:%d",
256 			vdev->vdev_objmgr.vdev_id);
257 		return NULL;
258 	}
259 
260 	obj_mgr_info("Created vdev %d", vdev->vdev_objmgr.vdev_id);
261 
262 	return vdev;
263 }
264 EXPORT_SYMBOL(wlan_objmgr_vdev_obj_create);
265 
266 static QDF_STATUS wlan_objmgr_vdev_obj_destroy(struct wlan_objmgr_vdev *vdev)
267 {
268 	uint8_t id;
269 	wlan_objmgr_vdev_destroy_handler handler;
270 	QDF_STATUS obj_status;
271 	void *arg;
272 	uint8_t vdev_id;
273 
274 	if (vdev == NULL) {
275 		obj_mgr_err("vdev is NULL");
276 		return QDF_STATUS_E_FAILURE;
277 	}
278 
279 	vdev_id = wlan_vdev_get_id(vdev);
280 
281 	obj_mgr_info("Physically deleting vdev %d", vdev_id);
282 
283 	if (vdev->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) {
284 		obj_mgr_err("vdev object delete is not invoked: vdev-id:%d",
285 			wlan_vdev_get_id(vdev));
286 		WLAN_OBJMGR_BUG(0);
287 	}
288 
289 	/* Invoke registered destroy handlers */
290 	for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
291 		handler = g_umac_glb_obj->vdev_destroy_handler[id];
292 		arg = g_umac_glb_obj->vdev_destroy_handler_arg[id];
293 		if (handler != NULL)
294 			vdev->obj_status[id] = handler(vdev, arg);
295 		else
296 			vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED;
297 	}
298 	/* Derive object status */
299 	obj_status = wlan_objmgr_vdev_object_status(vdev);
300 
301 	if (obj_status == QDF_STATUS_E_FAILURE) {
302 		obj_mgr_err("VDEV object deletion failed: vdev-id: %d",
303 				vdev_id);
304 		/* Ideally should not happen */
305 		/* This leads to memleak ??? how to handle */
306 		QDF_BUG(0);
307 		return QDF_STATUS_E_FAILURE;
308 	}
309 
310 	/* Deletion is in progress */
311 	if (obj_status == QDF_STATUS_COMP_ASYNC) {
312 		vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED;
313 		return QDF_STATUS_COMP_ASYNC;
314 	}
315 
316 	/* Free VDEV object */
317 	return wlan_objmgr_vdev_obj_free(vdev);
318 }
319 
320 QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev)
321 {
322 	uint8_t print_idx;
323 
324 	if (vdev == NULL) {
325 		obj_mgr_err("vdev is NULL");
326 		return QDF_STATUS_E_FAILURE;
327 	}
328 
329 	obj_mgr_info("Logically deleting vdev %d", vdev->vdev_objmgr.vdev_id);
330 
331 	print_idx = qdf_get_pidx();
332 	if (qdf_print_is_verbose_enabled(print_idx, QDF_MODULE_ID_OBJ_MGR,
333 		QDF_TRACE_LEVEL_DEBUG)) {
334 		wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg);
335 	}
336 
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_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
345 
346 	return QDF_STATUS_SUCCESS;
347 }
348 EXPORT_SYMBOL(wlan_objmgr_vdev_obj_delete);
349 
350 /**
351  ** APIs to attach/detach component objects
352  */
353 QDF_STATUS wlan_objmgr_vdev_component_obj_attach(
354 		struct wlan_objmgr_vdev *vdev,
355 		enum wlan_umac_comp_id id,
356 		void *comp_priv_obj,
357 		QDF_STATUS status)
358 {
359 	wlan_objmgr_vdev_status_handler stat_handler;
360 	void *arg;
361 	uint8_t i;
362 	QDF_STATUS obj_status;
363 
364 	/* component id is invalid */
365 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
366 		return QDF_STATUS_MAXCOMP_FAIL;
367 
368 	wlan_vdev_obj_lock(vdev);
369 	/* If there is a valid entry, return failure */
370 	if (vdev->vdev_comp_priv_obj[id] != NULL) {
371 		wlan_vdev_obj_unlock(vdev);
372 		return QDF_STATUS_E_FAILURE;
373 	}
374 	/* Save component's pointer and status */
375 	vdev->vdev_comp_priv_obj[id] = comp_priv_obj;
376 	vdev->obj_status[id] = status;
377 	wlan_vdev_obj_unlock(vdev);
378 	if (vdev->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED)
379 		return QDF_STATUS_SUCCESS;
380 	/*
381 	 * If VDEV object status is partially created means, this API is
382 	 * invoked with differnt context, this block should be executed for
383 	 * async components only
384 	 */
385 	/* Derive status */
386 	obj_status = wlan_objmgr_vdev_object_status(vdev);
387 	/* STATUS_SUCCESS means, object is CREATED */
388 	if (obj_status == QDF_STATUS_SUCCESS)
389 		vdev->obj_state = WLAN_OBJ_STATE_CREATED;
390 	/*
391 	 * update state as CREATION failed, caller has to delete the
392 	 * VDEV object
393 	 */
394 	else if (obj_status == QDF_STATUS_E_FAILURE)
395 		vdev->obj_state = WLAN_OBJ_STATE_CREATION_FAILED;
396 	/* Notify components about the CREATION success/failure */
397 	if ((obj_status == QDF_STATUS_SUCCESS) ||
398 	    (obj_status == QDF_STATUS_E_FAILURE)) {
399 		for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) {
400 			stat_handler = g_umac_glb_obj->vdev_status_handler[i];
401 			arg = g_umac_glb_obj->vdev_status_handler_arg[i];
402 			if (stat_handler != NULL)
403 				stat_handler(vdev, arg, obj_status);
404 		}
405 	}
406 	return QDF_STATUS_SUCCESS;
407 }
408 EXPORT_SYMBOL(wlan_objmgr_vdev_component_obj_attach);
409 
410 QDF_STATUS wlan_objmgr_vdev_component_obj_detach(
411 		struct wlan_objmgr_vdev *vdev,
412 		enum wlan_umac_comp_id id,
413 		void *comp_priv_obj)
414 {
415 	QDF_STATUS obj_status;
416 
417 	/* component id is invalid */
418 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
419 		return QDF_STATUS_MAXCOMP_FAIL;
420 
421 	wlan_vdev_obj_lock(vdev);
422 	/* If there is a valid entry, return failure */
423 	if (vdev->vdev_comp_priv_obj[id] != comp_priv_obj) {
424 		vdev->obj_status[id] = QDF_STATUS_E_FAILURE;
425 		wlan_vdev_obj_unlock(vdev);
426 		return QDF_STATUS_E_FAILURE;
427 	}
428 	/* Reset pointers to NULL, update the status*/
429 	vdev->vdev_comp_priv_obj[id] = NULL;
430 	vdev->obj_status[id] = QDF_STATUS_SUCCESS;
431 	wlan_vdev_obj_unlock(vdev);
432 
433 	/**
434 	 *If VDEV object status is partially destroyed means, this API is
435 	 * invoked with differnt context, this block should be executed for
436 	 * async components only
437 	 */
438 	if ((vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) ||
439 	    (vdev->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) {
440 		/* Derive object status */
441 		obj_status = wlan_objmgr_vdev_object_status(vdev);
442 		if (obj_status == QDF_STATUS_SUCCESS) {
443 			/*
444 			 * Update the status as Deleted, if full object
445 			 * deletion is in progress
446 			 */
447 			if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
448 				vdev->obj_state = WLAN_OBJ_STATE_DELETED;
449 			/*
450 			 * Move to creation state, since this component
451 			 * deletion alone requested
452 			 */
453 			else if (vdev->obj_state ==
454 					WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
455 				vdev->obj_state = WLAN_OBJ_STATE_CREATED;
456 		/* Object status is failure */
457 		} else if (obj_status == QDF_STATUS_E_FAILURE) {
458 			/*
459 			 * Update the status as Deletion failed, if full object
460 			 * deletion is in progress
461 			 */
462 			if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
463 				vdev->obj_state =
464 					WLAN_OBJ_STATE_DELETION_FAILED;
465 			/* Move to creation state, since this component
466 			deletion alone requested (do not block other
467 			components) */
468 			else if (vdev->obj_state ==
469 					WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
470 				vdev->obj_state = WLAN_OBJ_STATE_CREATED;
471 		}
472 		/* Delete vdev object */
473 		if ((obj_status == QDF_STATUS_SUCCESS)  &&
474 		    (vdev->obj_state == WLAN_OBJ_STATE_DELETED)) {
475 			/* Free VDEV object */
476 			return wlan_objmgr_vdev_obj_free(vdev);
477 		}
478 	}
479 	return QDF_STATUS_SUCCESS;
480 }
481 EXPORT_SYMBOL(wlan_objmgr_vdev_component_obj_detach);
482 
483 /**
484  ** APIs to operations on vdev objects
485  */
486 QDF_STATUS wlan_objmgr_iterate_peerobj_list(
487 		struct wlan_objmgr_vdev *vdev,
488 		wlan_objmgr_vdev_op_handler handler,
489 		void *arg, wlan_objmgr_ref_dbgid dbg_id)
490 {
491 	qdf_list_t *peer_list = NULL;
492 	struct wlan_objmgr_peer *peer = NULL;
493 	struct wlan_objmgr_peer *peer_next = NULL;
494 	uint8_t vdev_id;
495 
496 	if (vdev == NULL) {
497 		obj_mgr_err("VDEV is NULL");
498 		return QDF_STATUS_E_FAILURE;
499 	}
500 	wlan_vdev_obj_lock(vdev);
501 	vdev_id = wlan_vdev_get_id(vdev);
502 
503 	if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) {
504 		wlan_vdev_obj_unlock(vdev);
505 		obj_mgr_err("VDEV is not in create state(:%d): vdev-id:%d",
506 				vdev_id, vdev->obj_state);
507 		return QDF_STATUS_E_FAILURE;
508 	}
509 	wlan_objmgr_vdev_get_ref(vdev, dbg_id);
510 	peer_list = &vdev->vdev_objmgr.wlan_peer_list;
511 	if (peer_list != NULL) {
512 		/* Iterate through VDEV's peer list */
513 		peer = wlan_vdev_peer_list_peek_head(peer_list);
514 		while (peer != NULL) {
515 			peer_next = wlan_peer_get_next_peer_of_vdev(peer_list,
516 							       peer);
517 			if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
518 					QDF_STATUS_SUCCESS) {
519 				/* Invoke handler for operation */
520 				handler(vdev, (void *)peer, arg);
521 				wlan_objmgr_peer_release_ref(peer, dbg_id);
522 			}
523 			peer = peer_next;
524 		}
525 	}
526 	wlan_objmgr_vdev_release_ref(vdev, dbg_id);
527 	wlan_vdev_obj_unlock(vdev);
528 	return QDF_STATUS_SUCCESS;
529 }
530 
531 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_creation(
532 		struct wlan_objmgr_vdev *vdev,
533 		enum wlan_umac_comp_id id)
534 {
535 	wlan_objmgr_vdev_create_handler handler;
536 	void *arg;
537 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
538 
539 	/* Component id is invalid */
540 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
541 		return QDF_STATUS_MAXCOMP_FAIL;
542 
543 	wlan_vdev_obj_lock(vdev);
544 	/*
545 	 * If component object is already created, delete old
546 	 * component object, then invoke creation
547 	 */
548 	if (vdev->vdev_comp_priv_obj[id] != NULL) {
549 		wlan_vdev_obj_unlock(vdev);
550 		return QDF_STATUS_E_FAILURE;
551 	}
552 	wlan_vdev_obj_unlock(vdev);
553 
554 	/* Invoke registered create handlers */
555 	handler = g_umac_glb_obj->vdev_create_handler[id];
556 	arg = g_umac_glb_obj->vdev_create_handler_arg[id];
557 	if (handler != NULL)
558 		vdev->obj_status[id] = handler(vdev, arg);
559 	else
560 		return QDF_STATUS_E_FAILURE;
561 
562 	/* If object status is created, then only handle this object status */
563 	if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) {
564 		/* Derive object status */
565 		obj_status = wlan_objmgr_vdev_object_status(vdev);
566 		/* Move PDEV object state to Partially created state */
567 		if (obj_status == QDF_STATUS_COMP_ASYNC) {
568 			/*TODO atomic */
569 			vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
570 		}
571 	}
572 	return obj_status;
573 }
574 
575 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_deletion(
576 		struct wlan_objmgr_vdev *vdev,
577 		enum wlan_umac_comp_id id)
578 {
579 	wlan_objmgr_vdev_destroy_handler handler;
580 	void *arg;
581 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
582 
583 	/* component id is invalid */
584 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
585 		return QDF_STATUS_MAXCOMP_FAIL;
586 
587 	wlan_vdev_obj_lock(vdev);
588 	/* Component object was never created, invalid operation */
589 	if (vdev->vdev_comp_priv_obj[id] == NULL) {
590 		wlan_vdev_obj_unlock(vdev);
591 		return QDF_STATUS_E_FAILURE;
592 	}
593 	wlan_vdev_obj_unlock(vdev);
594 
595 	/* Invoke registered create handlers */
596 	handler = g_umac_glb_obj->vdev_destroy_handler[id];
597 	arg = g_umac_glb_obj->vdev_destroy_handler_arg[id];
598 	if (handler != NULL)
599 		vdev->obj_status[id] = handler(vdev, arg);
600 	else
601 		return QDF_STATUS_E_FAILURE;
602 
603 	/* If object status is created, then only handle this object status */
604 	if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) {
605 		obj_status = wlan_objmgr_vdev_object_status(vdev);
606 		/* move object state to DEL progress */
607 		if (obj_status == QDF_STATUS_COMP_ASYNC)
608 			vdev->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS;
609 	}
610 	return obj_status;
611 }
612 
613 
614 
615 static void wlan_obj_vdev_peerlist_add_tail(qdf_list_t *obj_list,
616 	struct wlan_objmgr_peer *obj)
617 {
618 	qdf_list_insert_back(obj_list, &obj->vdev_peer);
619 }
620 
621 static QDF_STATUS wlan_obj_vdev_peerlist_remove_peer(qdf_list_t *obj_list,
622 					struct wlan_objmgr_peer *peer)
623 {
624 	qdf_list_node_t *vdev_node = NULL;
625 
626 	if (peer == NULL)
627 		return QDF_STATUS_E_FAILURE;
628 	/* get vdev list node element */
629 	vdev_node = &peer->vdev_peer;
630 	/* list is empty, return failure */
631 	if (qdf_list_remove_node(obj_list, vdev_node) != QDF_STATUS_SUCCESS)
632 		return QDF_STATUS_E_FAILURE;
633 
634 	return QDF_STATUS_SUCCESS;
635 }
636 
637 QDF_STATUS wlan_objmgr_vdev_peer_attach(struct wlan_objmgr_vdev *vdev,
638 						struct wlan_objmgr_peer *peer)
639 {
640 	struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr;
641 	struct wlan_objmgr_pdev *pdev;
642 
643 	wlan_vdev_obj_lock(vdev);
644 	pdev = wlan_vdev_get_pdev(vdev);
645 	/* If Max peer count exceeds, return failure */
646 	if ((objmgr->wlan_peer_count >= objmgr->max_peer_count) ||
647 	     (wlan_pdev_get_peer_count(pdev) >=
648 			wlan_pdev_get_max_peer_count(pdev))) {
649 		wlan_vdev_obj_unlock(vdev);
650 		return QDF_STATUS_E_FAILURE;
651 	}
652 	/* Add peer to vdev's peer list */
653 	wlan_obj_vdev_peerlist_add_tail(&objmgr->wlan_peer_list, peer);
654 	objmgr->wlan_peer_count++;
655 	wlan_pdev_incr_peer_count(wlan_vdev_get_pdev(vdev));
656 
657 	if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer),
658 			 wlan_vdev_mlme_get_macaddr(vdev)) ==
659 				QDF_STATUS_SUCCESS) {
660 		/*
661 		 * if peer mac address and vdev mac address match, set
662 		 * this peer as self peer
663 		 */
664 		wlan_vdev_set_selfpeer(vdev, peer);
665 		/* For AP mode, self peer and BSS peer are same */
666 		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
667 			wlan_vdev_set_bsspeer(vdev, peer);
668 	}
669 	/* set BSS peer for sta */
670 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) &&
671 		((wlan_peer_get_peer_type(peer) == WLAN_PEER_AP) ||
672 		 (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO)))
673 		wlan_vdev_set_bsspeer(vdev, peer);
674 
675 	/* Increment vdev ref count to make sure it won't be destroyed before */
676 	wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID);
677 	wlan_vdev_obj_unlock(vdev);
678 	return QDF_STATUS_SUCCESS;
679 }
680 
681 QDF_STATUS wlan_objmgr_vdev_peer_detach(struct wlan_objmgr_vdev *vdev,
682 					struct wlan_objmgr_peer *peer)
683 {
684 	struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr;
685 
686 	wlan_vdev_obj_lock(vdev);
687 	/* if peer count is 0, return failure */
688 	if (objmgr->wlan_peer_count == 0) {
689 		wlan_vdev_obj_unlock(vdev);
690 		return QDF_STATUS_E_FAILURE;
691 	}
692 
693 	if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_AP) ||
694 	    (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO)) {
695 		if (wlan_vdev_get_selfpeer(vdev) == peer) {
696 			/*
697 			 * There might be instances where new node is created
698 			 * before deleting existing node, in which case selfpeer
699 			 * will be pointing to the new node. So set selfpeer to
700 			 * NULL only if vdev->vdev_objmgr.self_peer is pointing
701 			 * to the peer processed for deletion
702 			 */
703 			wlan_vdev_set_selfpeer(vdev, NULL);
704 		}
705 
706 		if (wlan_vdev_get_bsspeer(vdev) == peer) {
707 			/*
708 			 * There might be instances where new node is created
709 			 * before deleting existing node, in which case bsspeer
710 			 * in vdev will be pointing to the new node. So set
711 			 * bsspeer to NULL only if vdev->vdev_objmgr.bss_peer is
712 			 * pointing to the peer processed for deletion
713 			 */
714 			wlan_vdev_set_bsspeer(vdev, NULL);
715 		}
716 	}
717 
718 	/* remove peer from vdev's peer list */
719 	if (wlan_obj_vdev_peerlist_remove_peer(&objmgr->wlan_peer_list, peer)
720 				== QDF_STATUS_E_FAILURE) {
721 		wlan_vdev_obj_unlock(vdev);
722 		return QDF_STATUS_E_FAILURE;
723 	}
724 	/* decrement peer count */
725 	objmgr->wlan_peer_count--;
726 	wlan_pdev_decr_peer_count(wlan_vdev_get_pdev(vdev));
727 	wlan_vdev_obj_unlock(vdev);
728 	/* decrement vdev ref count after peer released its reference */
729 	wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
730 	return QDF_STATUS_SUCCESS;
731 }
732 
733 void *wlan_objmgr_vdev_get_comp_private_obj(
734 		struct wlan_objmgr_vdev *vdev,
735 		enum wlan_umac_comp_id id)
736 {
737 	void *comp_priv_obj;
738 
739 	/* component id is invalid */
740 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
741 		QDF_BUG(0);
742 		return NULL;
743 	}
744 
745 	if (vdev == NULL) {
746 		QDF_BUG(0);
747 		return NULL;
748 	}
749 
750 	comp_priv_obj = vdev->vdev_comp_priv_obj[id];
751 
752 	return comp_priv_obj;
753 }
754 EXPORT_SYMBOL(wlan_objmgr_vdev_get_comp_private_obj);
755 
756 void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev,
757 						wlan_objmgr_ref_dbgid id)
758 {
759 	if (vdev == NULL) {
760 		obj_mgr_err("vdev obj is NULL for id:%d", id);
761 		QDF_ASSERT(0);
762 		return;
763 	}
764 	/* Increment ref count */
765 	qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt);
766 	qdf_atomic_inc(&vdev->vdev_objmgr.ref_id_dbg[id]);
767 
768 	return;
769 }
770 EXPORT_SYMBOL(wlan_objmgr_vdev_get_ref);
771 
772 QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev,
773 						wlan_objmgr_ref_dbgid id)
774 {
775 	uint8_t vdev_id;
776 
777 	if (vdev == NULL) {
778 		obj_mgr_err("vdev obj is NULL for id:%d", id);
779 		QDF_ASSERT(0);
780 		return QDF_STATUS_E_FAILURE;
781 	}
782 
783 	wlan_vdev_obj_lock(vdev);
784 	vdev_id = wlan_vdev_get_id(vdev);
785 	if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) {
786 		wlan_vdev_obj_unlock(vdev);
787 		if (vdev->vdev_objmgr.print_cnt++ <=
788 				WLAN_OBJMGR_RATELIMIT_THRESH)
789 			obj_mgr_err(
790 			"[Ref id: %d] vdev(%d) is not in Created state(%d)",
791 				id, vdev_id, vdev->obj_state);
792 
793 		return QDF_STATUS_E_RESOURCES;
794 	}
795 
796 	/* Increment ref count */
797 	wlan_objmgr_vdev_get_ref(vdev, id);
798 	wlan_vdev_obj_unlock(vdev);
799 
800 	return QDF_STATUS_SUCCESS;
801 }
802 EXPORT_SYMBOL(wlan_objmgr_vdev_try_get_ref);
803 
804 void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev,
805 						wlan_objmgr_ref_dbgid id)
806 {
807 	uint8_t vdev_id;
808 
809 	if (vdev == NULL) {
810 		obj_mgr_err("vdev obj is NULL for id:%d", id);
811 		QDF_ASSERT(0);
812 		return;
813 	}
814 
815 	vdev_id = wlan_vdev_get_id(vdev);
816 
817 	if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_id_dbg[id])) {
818 		obj_mgr_err("vdev (id:%d)ref cnt was not taken by %d",
819 				vdev_id, id);
820 		wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg);
821 		WLAN_OBJMGR_BUG(0);
822 	}
823 
824 	if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) {
825 		obj_mgr_err("vdev ref cnt is 0");
826 		WLAN_OBJMGR_BUG(0);
827 		return;
828 	}
829 	qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]);
830 
831 	/* Decrement ref count, free vdev, if ref count == 0 */
832 	if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt))
833 		wlan_objmgr_vdev_obj_destroy(vdev);
834 
835 	return;
836 }
837 EXPORT_SYMBOL(wlan_objmgr_vdev_release_ref);
838 
839 bool wlan_vdev_is_connected(struct wlan_objmgr_vdev *vdev)
840 {
841 	struct wlan_objmgr_peer *peer;
842 	enum wlan_peer_state peer_state;
843 
844 	wlan_vdev_obj_lock(vdev);
845 	peer = wlan_vdev_get_bsspeer(vdev);
846 	wlan_vdev_obj_unlock(vdev);
847 
848 	if (!peer)
849 		return false;
850 
851 	wlan_peer_obj_lock(peer);
852 	peer_state = wlan_peer_mlme_get_state(peer);
853 	wlan_peer_obj_unlock(peer);
854 
855 	if (peer_state != WLAN_ASSOC_STATE)
856 		return false;
857 
858 	return true;
859 }
860 EXPORT_SYMBOL(wlan_vdev_is_connected);
861