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