xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c (revision dd4dc88b837a295134aa9869114a2efee0f4894b)
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]) {
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) {
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) {
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) {
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->vdev_nif.osdev);
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) {
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) {
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)
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)
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) {
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) {
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) {
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]) {
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)
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) {
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) {
508 		/* Iterate through VDEV's peer list */
509 		peer = wlan_vdev_peer_list_peek_head(peer_list);
510 		while (peer) {
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 /**
528  * wlan_obj_vdev_populate_logically_del_peerlist() - get peer
529  * from vdev peer list
530  * @obj_list: peer object list
531  * @vdev_obj: vdev object mgr substructure
532  * @dbg_id: id of the caller
533  *
534  * API to finds peer object pointer by vdev from peer hash list for a node
535  * which is in logically deleted state
536  *
537  * Caller to free the list allocated in this function
538  *
539  * Return: list of peer pointers
540  *         NULL on FAILURE
541  */
542 static qdf_list_t *wlan_obj_vdev_populate_logically_del_peerlist(
543 				qdf_list_t *obj_list,
544 				struct wlan_objmgr_vdev_objmgr *vdev_obj,
545 				wlan_objmgr_ref_dbgid dbg_id)
546 {
547 	struct wlan_objmgr_peer *peer;
548 	struct wlan_objmgr_peer *peer_next;
549 	struct wlan_logically_del_peer *peer_list;
550 	qdf_list_t *logical_del_peerlist;
551 	bool lock_released = false;
552 
553 	logical_del_peerlist = qdf_mem_malloc(sizeof(*logical_del_peerlist));
554 	if (!logical_del_peerlist)
555 		return NULL;
556 
557 	qdf_list_create(logical_del_peerlist, vdev_obj->max_peer_count);
558 
559 	peer = wlan_vdev_peer_list_peek_head(obj_list);
560 	while (peer) {
561 		wlan_peer_obj_lock(peer);
562 		peer_next = wlan_peer_get_next_peer_of_vdev(obj_list, peer);
563 		if (peer->obj_state == WLAN_OBJ_STATE_LOGICALLY_DELETED &&
564 		    qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) {
565 			wlan_objmgr_peer_get_ref(peer, dbg_id);
566 			wlan_peer_obj_unlock(peer);
567 			lock_released = true;
568 
569 			peer_list = qdf_mem_malloc(sizeof(*peer_list));
570 			if (!peer_list) {
571 				wlan_objmgr_peer_release_ref(peer, dbg_id);
572 				WLAN_OBJMGR_BUG(0);
573 				break;
574 			}
575 
576 			peer_list->peer = peer;
577 			qdf_list_insert_front(logical_del_peerlist,
578 					      &peer_list->list);
579 		}
580 
581 		if (!lock_released)
582 			wlan_peer_obj_unlock(peer);
583 
584 		peer = peer_next;
585 		lock_released = false;
586 	}
587 
588 	/* Not found, return NULL */
589 	if (qdf_list_empty(logical_del_peerlist)) {
590 		qdf_mem_free(logical_del_peerlist);
591 		return NULL;
592 	}
593 
594 	return logical_del_peerlist;
595 }
596 
597 qdf_list_t *wlan_objmgr_vdev_get_log_del_peer_list(
598 		struct wlan_objmgr_vdev *vdev,
599 		wlan_objmgr_ref_dbgid dbg_id)
600 {
601 	qdf_list_t *peer_list;
602 	qdf_list_t *log_del_peer_list = NULL;
603 
604 	if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) {
605 		obj_mgr_err("Invalid state vdev:%d state:%d",
606 			    wlan_vdev_get_id(vdev), vdev->obj_state);
607 		return NULL;
608 	}
609 
610 	wlan_vdev_obj_lock(vdev);
611 	if (vdev->vdev_objmgr.wlan_peer_count == 0) {
612 		wlan_vdev_obj_unlock(vdev);
613 		return NULL;
614 	}
615 
616 	wlan_objmgr_vdev_get_ref(vdev, dbg_id);
617 	peer_list = &vdev->vdev_objmgr.wlan_peer_list;
618 	if (peer_list) {
619 		log_del_peer_list =
620 			wlan_obj_vdev_populate_logically_del_peerlist(
621 					peer_list, &vdev->vdev_objmgr,
622 					dbg_id);
623 	}
624 
625 	wlan_objmgr_vdev_release_ref(vdev, dbg_id);
626 	wlan_vdev_obj_unlock(vdev);
627 
628 	return log_del_peer_list;
629 }
630 
631 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_creation(
632 		struct wlan_objmgr_vdev *vdev,
633 		enum wlan_umac_comp_id id)
634 {
635 	wlan_objmgr_vdev_create_handler handler;
636 	void *arg;
637 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
638 
639 	/* Component id is invalid */
640 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
641 		return QDF_STATUS_MAXCOMP_FAIL;
642 
643 	wlan_vdev_obj_lock(vdev);
644 	/*
645 	 * If component object is already created, delete old
646 	 * component object, then invoke creation
647 	 */
648 	if (vdev->vdev_comp_priv_obj[id]) {
649 		wlan_vdev_obj_unlock(vdev);
650 		return QDF_STATUS_E_FAILURE;
651 	}
652 	wlan_vdev_obj_unlock(vdev);
653 
654 	/* Invoke registered create handlers */
655 	handler = g_umac_glb_obj->vdev_create_handler[id];
656 	arg = g_umac_glb_obj->vdev_create_handler_arg[id];
657 	if (handler)
658 		vdev->obj_status[id] = handler(vdev, arg);
659 	else
660 		return QDF_STATUS_E_FAILURE;
661 
662 	/* If object status is created, then only handle this object status */
663 	if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) {
664 		/* Derive object status */
665 		obj_status = wlan_objmgr_vdev_object_status(vdev);
666 		/* Move PDEV object state to Partially created state */
667 		if (obj_status == QDF_STATUS_COMP_ASYNC) {
668 			/*TODO atomic */
669 			vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
670 		}
671 	}
672 	return obj_status;
673 }
674 
675 QDF_STATUS wlan_objmgr_trigger_vdev_comp_priv_object_deletion(
676 		struct wlan_objmgr_vdev *vdev,
677 		enum wlan_umac_comp_id id)
678 {
679 	wlan_objmgr_vdev_destroy_handler handler;
680 	void *arg;
681 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
682 
683 	/* component id is invalid */
684 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
685 		return QDF_STATUS_MAXCOMP_FAIL;
686 
687 	wlan_vdev_obj_lock(vdev);
688 	/* Component object was never created, invalid operation */
689 	if (!vdev->vdev_comp_priv_obj[id]) {
690 		wlan_vdev_obj_unlock(vdev);
691 		return QDF_STATUS_E_FAILURE;
692 	}
693 	wlan_vdev_obj_unlock(vdev);
694 
695 	/* Invoke registered create handlers */
696 	handler = g_umac_glb_obj->vdev_destroy_handler[id];
697 	arg = g_umac_glb_obj->vdev_destroy_handler_arg[id];
698 	if (handler)
699 		vdev->obj_status[id] = handler(vdev, arg);
700 	else
701 		return QDF_STATUS_E_FAILURE;
702 
703 	/* If object status is created, then only handle this object status */
704 	if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) {
705 		obj_status = wlan_objmgr_vdev_object_status(vdev);
706 		/* move object state to DEL progress */
707 		if (obj_status == QDF_STATUS_COMP_ASYNC)
708 			vdev->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS;
709 	}
710 	return obj_status;
711 }
712 
713 
714 
715 static void wlan_obj_vdev_peerlist_add_tail(qdf_list_t *obj_list,
716 	struct wlan_objmgr_peer *obj)
717 {
718 	qdf_list_insert_back(obj_list, &obj->vdev_peer);
719 }
720 
721 static QDF_STATUS wlan_obj_vdev_peerlist_remove_peer(qdf_list_t *obj_list,
722 					struct wlan_objmgr_peer *peer)
723 {
724 	qdf_list_node_t *vdev_node = NULL;
725 
726 	if (!peer)
727 		return QDF_STATUS_E_FAILURE;
728 	/* get vdev list node element */
729 	vdev_node = &peer->vdev_peer;
730 	/* list is empty, return failure */
731 	if (qdf_list_remove_node(obj_list, vdev_node) != QDF_STATUS_SUCCESS)
732 		return QDF_STATUS_E_FAILURE;
733 
734 	return QDF_STATUS_SUCCESS;
735 }
736 
737 QDF_STATUS wlan_objmgr_vdev_peer_attach(struct wlan_objmgr_vdev *vdev,
738 						struct wlan_objmgr_peer *peer)
739 {
740 	struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr;
741 	struct wlan_objmgr_pdev *pdev;
742 	enum QDF_OPMODE opmode;
743 
744 	wlan_vdev_obj_lock(vdev);
745 	pdev = wlan_vdev_get_pdev(vdev);
746 	/* If Max VDEV peer count exceeds, return failure */
747 	if (peer->peer_mlme.peer_type != WLAN_PEER_STA_TEMP) {
748 		if (objmgr->wlan_peer_count >= objmgr->max_peer_count) {
749 			wlan_vdev_obj_unlock(vdev);
750 			return QDF_STATUS_E_FAILURE;
751 		}
752 	}
753 	wlan_vdev_obj_unlock(vdev);
754 
755 	/* If Max PDEV peer count exceeds, return failure */
756 	wlan_pdev_obj_lock(pdev);
757 	if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) {
758 		if (wlan_pdev_get_temp_peer_count(pdev) >=
759 			WLAN_MAX_PDEV_TEMP_PEERS) {
760 			wlan_pdev_obj_unlock(pdev);
761 			return QDF_STATUS_E_FAILURE;
762 		}
763 	} else {
764 		if (wlan_pdev_get_peer_count(pdev) >=
765 			wlan_pdev_get_max_peer_count(pdev)) {
766 			wlan_pdev_obj_unlock(pdev);
767 			return QDF_STATUS_E_FAILURE;
768 		}
769 	}
770 
771 	if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP)
772 		wlan_pdev_incr_temp_peer_count(wlan_vdev_get_pdev(vdev));
773 	else
774 		wlan_pdev_incr_peer_count(wlan_vdev_get_pdev(vdev));
775 	wlan_pdev_obj_unlock(pdev);
776 
777 	wlan_vdev_obj_lock(vdev);
778 	/* Add peer to vdev's peer list */
779 	wlan_obj_vdev_peerlist_add_tail(&objmgr->wlan_peer_list, peer);
780 	objmgr->wlan_peer_count++;
781 
782 	if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer),
783 			 wlan_vdev_mlme_get_macaddr(vdev)) ==
784 				QDF_STATUS_SUCCESS) {
785 		/*
786 		 * if peer mac address and vdev mac address match, set
787 		 * this peer as self peer
788 		 */
789 		wlan_vdev_set_selfpeer(vdev, peer);
790 		opmode = wlan_vdev_mlme_get_opmode(vdev);
791 		/* For AP mode, self peer and BSS peer are same */
792 		if ((opmode == QDF_SAP_MODE) || (opmode == QDF_P2P_GO_MODE))
793 			wlan_vdev_set_bsspeer(vdev, peer);
794 	}
795 	/* set BSS peer for sta */
796 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE ||
797 	     wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_CLIENT_MODE) &&
798 	    (wlan_peer_get_peer_type(peer) == WLAN_PEER_AP ||
799 	     wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO))
800 		wlan_vdev_set_bsspeer(vdev, peer);
801 
802 	/* Increment vdev ref count to make sure it won't be destroyed before */
803 	wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID);
804 	wlan_vdev_obj_unlock(vdev);
805 	return QDF_STATUS_SUCCESS;
806 }
807 
808 QDF_STATUS wlan_objmgr_vdev_peer_detach(struct wlan_objmgr_vdev *vdev,
809 					struct wlan_objmgr_peer *peer)
810 {
811 	struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr;
812 	struct wlan_objmgr_pdev *pdev;
813 
814 	wlan_vdev_obj_lock(vdev);
815 	/* if peer count is 0, return failure */
816 	if (objmgr->wlan_peer_count == 0) {
817 		wlan_vdev_obj_unlock(vdev);
818 		return QDF_STATUS_E_FAILURE;
819 	}
820 
821 	if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_AP) ||
822 	    (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_GO)) {
823 		if (wlan_vdev_get_selfpeer(vdev) == peer) {
824 			/*
825 			 * There might be instances where new node is created
826 			 * before deleting existing node, in which case selfpeer
827 			 * will be pointing to the new node. So set selfpeer to
828 			 * NULL only if vdev->vdev_objmgr.self_peer is pointing
829 			 * to the peer processed for deletion
830 			 */
831 			wlan_vdev_set_selfpeer(vdev, NULL);
832 		}
833 
834 		if (wlan_vdev_get_bsspeer(vdev) == peer) {
835 			/*
836 			 * There might be instances where new node is created
837 			 * before deleting existing node, in which case bsspeer
838 			 * in vdev will be pointing to the new node. So set
839 			 * bsspeer to NULL only if vdev->vdev_objmgr.bss_peer is
840 			 * pointing to the peer processed for deletion
841 			 */
842 			wlan_vdev_set_bsspeer(vdev, NULL);
843 		}
844 	}
845 
846 	/* remove peer from vdev's peer list */
847 	if (wlan_obj_vdev_peerlist_remove_peer(&objmgr->wlan_peer_list, peer)
848 				== QDF_STATUS_E_FAILURE) {
849 		wlan_vdev_obj_unlock(vdev);
850 		return QDF_STATUS_E_FAILURE;
851 	}
852 	/* decrement peer count */
853 	objmgr->wlan_peer_count--;
854 	/* decrement pdev peer count */
855 	pdev = wlan_vdev_get_pdev(vdev);
856 	wlan_vdev_obj_unlock(vdev);
857 
858 	wlan_pdev_obj_lock(pdev);
859 	if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP)
860 		wlan_pdev_decr_temp_peer_count(pdev);
861 	else
862 		wlan_pdev_decr_peer_count(pdev);
863 	wlan_pdev_obj_unlock(pdev);
864 
865 	/* decrement vdev ref count after peer released its reference */
866 	wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
867 	return QDF_STATUS_SUCCESS;
868 }
869 
870 struct wlan_objmgr_peer *wlan_objmgr_vdev_try_get_bsspeer(
871 					struct wlan_objmgr_vdev *vdev,
872 					wlan_objmgr_ref_dbgid id)
873 {
874 	struct wlan_objmgr_peer *peer;
875 	QDF_STATUS status = QDF_STATUS_E_EMPTY;
876 
877 	if (!vdev)
878 		return NULL;
879 
880 	wlan_vdev_obj_lock(vdev);
881 	peer = wlan_vdev_get_bsspeer(vdev);
882 	if (peer)
883 		status = wlan_objmgr_peer_try_get_ref(peer, id);
884 	wlan_vdev_obj_unlock(vdev);
885 
886 	if (QDF_IS_STATUS_SUCCESS(status))
887 		return peer;
888 
889 	return NULL;
890 }
891 
892 void *wlan_objmgr_vdev_get_comp_private_obj(
893 		struct wlan_objmgr_vdev *vdev,
894 		enum wlan_umac_comp_id id)
895 {
896 	void *comp_priv_obj;
897 
898 	/* component id is invalid */
899 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
900 		QDF_BUG(0);
901 		return NULL;
902 	}
903 
904 	if (!vdev) {
905 		QDF_BUG(0);
906 		return NULL;
907 	}
908 
909 	comp_priv_obj = vdev->vdev_comp_priv_obj[id];
910 
911 	return comp_priv_obj;
912 }
913 qdf_export_symbol(wlan_objmgr_vdev_get_comp_private_obj);
914 
915 void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev,
916 						wlan_objmgr_ref_dbgid id)
917 {
918 	if (!vdev) {
919 		obj_mgr_err("vdev obj is NULL for id:%d", id);
920 		QDF_ASSERT(0);
921 		return;
922 	}
923 	/* Increment ref count */
924 	qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt);
925 	qdf_atomic_inc(&vdev->vdev_objmgr.ref_id_dbg[id]);
926 
927 	return;
928 }
929 qdf_export_symbol(wlan_objmgr_vdev_get_ref);
930 
931 QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev,
932 						wlan_objmgr_ref_dbgid id)
933 {
934 	uint8_t vdev_id;
935 
936 	if (!vdev) {
937 		obj_mgr_err("vdev obj is NULL for id:%d", id);
938 		QDF_ASSERT(0);
939 		return QDF_STATUS_E_FAILURE;
940 	}
941 
942 	wlan_vdev_obj_lock(vdev);
943 	vdev_id = wlan_vdev_get_id(vdev);
944 	if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) {
945 		wlan_vdev_obj_unlock(vdev);
946 		if (vdev->vdev_objmgr.print_cnt++ <=
947 				WLAN_OBJMGR_RATELIMIT_THRESH)
948 			obj_mgr_err(
949 			"[Ref id: %d] vdev(%d) is not in Created state(%d)",
950 				id, vdev_id, vdev->obj_state);
951 
952 		return QDF_STATUS_E_RESOURCES;
953 	}
954 
955 	/* Increment ref count */
956 	wlan_objmgr_vdev_get_ref(vdev, id);
957 	wlan_vdev_obj_unlock(vdev);
958 
959 	return QDF_STATUS_SUCCESS;
960 }
961 qdf_export_symbol(wlan_objmgr_vdev_try_get_ref);
962 
963 void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev,
964 						wlan_objmgr_ref_dbgid id)
965 {
966 	uint8_t vdev_id;
967 
968 	if (!vdev) {
969 		obj_mgr_err("vdev obj is NULL for id:%d", id);
970 		QDF_ASSERT(0);
971 		return;
972 	}
973 
974 	vdev_id = wlan_vdev_get_id(vdev);
975 
976 	if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_id_dbg[id])) {
977 		obj_mgr_err("vdev (id:%d)ref cnt was not taken by %d",
978 				vdev_id, id);
979 		wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg,
980 					  QDF_TRACE_LEVEL_FATAL);
981 		WLAN_OBJMGR_BUG(0);
982 		return;
983 	}
984 
985 	if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) {
986 		obj_mgr_err("vdev ref cnt is 0");
987 		WLAN_OBJMGR_BUG(0);
988 		return;
989 	}
990 	qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]);
991 
992 	/* Decrement ref count, free vdev, if ref count == 0 */
993 	if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt))
994 		wlan_objmgr_vdev_obj_destroy(vdev);
995 
996 	return;
997 }
998 qdf_export_symbol(wlan_objmgr_vdev_release_ref);
999 
1000 struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head(
1001 			struct wlan_objmgr_pdev *pdev,
1002 			qdf_list_t *vdev_list, wlan_objmgr_ref_dbgid dbg_id)
1003 {
1004 	struct wlan_objmgr_vdev *vdev;
1005 	qdf_list_node_t *node = NULL;
1006 	qdf_list_node_t *prev_node = NULL;
1007 
1008 	wlan_pdev_obj_lock(pdev);
1009 
1010 	if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) {
1011 		wlan_pdev_obj_unlock(pdev);
1012 		return NULL;
1013 	}
1014 
1015 	do {
1016 		vdev = qdf_container_of(node, struct wlan_objmgr_vdev,
1017 								vdev_node);
1018 		if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) ==
1019 						QDF_STATUS_SUCCESS) {
1020 			wlan_pdev_obj_unlock(pdev);
1021 			return vdev;
1022 		}
1023 
1024 		prev_node = node;
1025 	} while (qdf_list_peek_next(vdev_list, prev_node, &node) ==
1026 						QDF_STATUS_SUCCESS);
1027 
1028 	wlan_pdev_obj_unlock(pdev);
1029 
1030 	return NULL;
1031 }
1032 
1033 struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev(
1034 			struct wlan_objmgr_pdev *pdev,
1035 			qdf_list_t *vdev_list,
1036 			struct wlan_objmgr_vdev *vdev,
1037 			wlan_objmgr_ref_dbgid dbg_id)
1038 {
1039 	struct wlan_objmgr_vdev *vdev_next;
1040 	qdf_list_node_t *node = &vdev->vdev_node;
1041 	qdf_list_node_t *prev_node = NULL;
1042 
1043 	if (!node)
1044 		return NULL;
1045 
1046 	wlan_pdev_obj_lock(pdev);
1047 	prev_node = node;
1048 	while (qdf_list_peek_next(vdev_list, prev_node, &node) ==
1049 							QDF_STATUS_SUCCESS) {
1050 		vdev_next = qdf_container_of(node, struct wlan_objmgr_vdev,
1051 								vdev_node);
1052 		if (wlan_objmgr_vdev_try_get_ref(vdev_next, dbg_id) ==
1053 						QDF_STATUS_SUCCESS) {
1054 			wlan_pdev_obj_unlock(pdev);
1055 			return vdev_next;
1056 		}
1057 
1058 		prev_node = node;
1059 	}
1060 	wlan_pdev_obj_unlock(pdev);
1061 
1062 	return NULL;
1063 }
1064 
1065