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