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