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