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