xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c (revision 4865edfd190c086bbe2c69aae12a8226f877b91e)
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 	if (!lock_free_op)
415 		wlan_vdev_obj_lock(vdev);
416 	/* Get peer list of the vdev */
417 	peer_list = &vdev->vdev_objmgr.wlan_peer_list;
418 	if (peer_list != NULL) {
419 		peer = wlan_vdev_peer_list_peek_head(peer_list);
420 		while (peer != NULL) {
421 			/* Get next peer pointer */
422 			peer_next = wlan_peer_get_next_peer_of_vdev(peer_list,
423 								    peer);
424 			/* Increment ref count, to hold the
425 				peer pointer */
426 			if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
427 					QDF_STATUS_SUCCESS) {
428 				/* Invoke the handler */
429 				handler(pdev, (void *)peer, arg);
430 				wlan_objmgr_peer_release_ref(peer, dbg_id);
431 			}
432 			peer = peer_next;
433 		}
434 	}
435 	if (!lock_free_op)
436 		wlan_vdev_obj_unlock(vdev);
437 }
438 
439 QDF_STATUS wlan_objmgr_pdev_iterate_obj_list(
440 		struct wlan_objmgr_pdev *pdev,
441 		enum wlan_objmgr_obj_type obj_type,
442 		wlan_objmgr_pdev_op_handler handler,
443 		void *arg, uint8_t lock_free_op,
444 		wlan_objmgr_ref_dbgid dbg_id)
445 {
446 	struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr;
447 	qdf_list_t *vdev_list = NULL;
448 	struct wlan_objmgr_vdev *vdev = NULL;
449 	struct wlan_objmgr_vdev *vdev_next = NULL;
450 
451 	/* If caller requests for lock free opeation, do not acquire
452 		handler will handle the synchronization*/
453 	if (!lock_free_op)
454 		wlan_pdev_obj_lock(pdev);
455 	/* VDEV list */
456 	vdev_list = &objmgr->wlan_vdev_list;
457 	switch (obj_type) {
458 	case WLAN_VDEV_OP:
459 		/* Iterate through all VDEV object, and invoke handler for each
460 			VDEV object */
461 		vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
462 		while (vdev != NULL) {
463 			/*
464 			 * Get next vdev (handler can be invoked for
465 			 * vdev deletion also
466 			 */
467 			vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list,
468 						vdev);
469 			if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) ==
470 						QDF_STATUS_SUCCESS) {
471 				handler(pdev, (void *)vdev, arg);
472 				wlan_objmgr_vdev_release_ref(vdev, dbg_id);
473 			}
474 			vdev = vdev_next;
475 		}
476 		break;
477 	case WLAN_PEER_OP:
478 		vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
479 		while (vdev != NULL) {
480 			/* Get Next VDEV */
481 			vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list,
482 						vdev);
483 			if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) ==
484 						QDF_STATUS_SUCCESS) {
485 				wlan_objmgr_pdev_vdev_iterate_peers(pdev, vdev,
486 								handler, arg,
487 								lock_free_op,
488 								dbg_id);
489 				wlan_objmgr_vdev_release_ref(vdev, dbg_id);
490 			}
491 			vdev = vdev_next;
492 		}
493 		break;
494 	default:
495 		break;
496 	}
497 	if (!lock_free_op)
498 		wlan_pdev_obj_unlock(pdev);
499 
500 	return QDF_STATUS_SUCCESS;
501 }
502 qdf_export_symbol(wlan_objmgr_pdev_iterate_obj_list);
503 
504 QDF_STATUS wlan_objmgr_trigger_pdev_comp_priv_object_creation(
505 		struct wlan_objmgr_pdev *pdev,
506 		enum wlan_umac_comp_id id)
507 {
508 	wlan_objmgr_pdev_create_handler handler;
509 	void *arg;
510 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
511 
512 	/* Component id is invalid */
513 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
514 		return QDF_STATUS_MAXCOMP_FAIL;
515 
516 	wlan_pdev_obj_lock(pdev);
517 	/* If component object is already created, delete old
518 		component object, then invoke creation */
519 	if (pdev->pdev_comp_priv_obj[id] != NULL) {
520 		wlan_pdev_obj_unlock(pdev);
521 		return QDF_STATUS_E_FAILURE;
522 	}
523 	wlan_pdev_obj_unlock(pdev);
524 
525 	/* Invoke registered create handlers */
526 	handler = g_umac_glb_obj->pdev_create_handler[id];
527 	arg = g_umac_glb_obj->pdev_create_handler_arg[id];
528 	if (handler != NULL)
529 		pdev->obj_status[id] = handler(pdev, arg);
530 	else
531 		return QDF_STATUS_E_FAILURE;
532 	/* If object status is created, then only handle this object status */
533 	if (pdev->obj_state == WLAN_OBJ_STATE_CREATED) {
534 		/* Derive object status */
535 		obj_status = wlan_objmgr_pdev_object_status(pdev);
536 		/* Move PDEV object state to Partially created state */
537 		if (obj_status == QDF_STATUS_COMP_ASYNC) {
538 			/*TODO atomic */
539 			pdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
540 		}
541 	}
542 	return obj_status;
543 }
544 
545 QDF_STATUS wlan_objmgr_trigger_pdev_comp_priv_object_deletion(
546 		struct wlan_objmgr_pdev *pdev,
547 		enum wlan_umac_comp_id id)
548 {
549 	wlan_objmgr_pdev_destroy_handler handler;
550 	void *arg;
551 	QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
552 
553 	/* component id is invalid */
554 	if (id >= WLAN_UMAC_MAX_COMPONENTS)
555 		return QDF_STATUS_MAXCOMP_FAIL;
556 
557 	wlan_pdev_obj_lock(pdev);
558 	/* Component object was never created, invalid operation */
559 	if (pdev->pdev_comp_priv_obj[id] == NULL) {
560 		wlan_pdev_obj_unlock(pdev);
561 		return QDF_STATUS_E_FAILURE;
562 	}
563 	wlan_pdev_obj_unlock(pdev);
564 
565 	/* Invoke registered create handlers */
566 	handler = g_umac_glb_obj->pdev_destroy_handler[id];
567 	arg = g_umac_glb_obj->pdev_destroy_handler_arg[id];
568 	if (handler != NULL)
569 		pdev->obj_status[id] = handler(pdev, arg);
570 	else
571 		return QDF_STATUS_E_FAILURE;
572 
573 	/* If object status is created, then only handle this object status */
574 	if (pdev->obj_state == WLAN_OBJ_STATE_CREATED) {
575 		obj_status = wlan_objmgr_pdev_object_status(pdev);
576 		/* move object state to DEL progress */
577 		if (obj_status == QDF_STATUS_COMP_ASYNC)
578 			pdev->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS;
579 	}
580 	return obj_status;
581 }
582 
583 static void wlan_obj_pdev_vdevlist_add_tail(qdf_list_t *obj_list,
584 				struct wlan_objmgr_vdev *obj)
585 {
586 	qdf_list_insert_back(obj_list, &obj->vdev_node);
587 }
588 
589 static QDF_STATUS wlan_obj_pdev_vdevlist_remove_vdev(
590 				qdf_list_t *obj_list,
591 				struct wlan_objmgr_vdev *vdev)
592 {
593 	qdf_list_node_t *vdev_node = NULL;
594 
595 	if (vdev == NULL)
596 		return QDF_STATUS_E_FAILURE;
597 	/* get vdev list node element */
598 	vdev_node = &vdev->vdev_node;
599 	/* list is empty, return failure */
600 	if (qdf_list_remove_node(obj_list, vdev_node) != QDF_STATUS_SUCCESS)
601 		return QDF_STATUS_E_FAILURE;
602 
603 	return QDF_STATUS_SUCCESS;
604 }
605 
606 QDF_STATUS wlan_objmgr_pdev_vdev_attach(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 Max vdev count exceeds, return failure */
613 	if (objmgr->wlan_vdev_count > objmgr->max_vdev_count) {
614 		wlan_pdev_obj_unlock(pdev);
615 		return QDF_STATUS_E_FAILURE;
616 	}
617 	/* Add vdev to pdev's vdev list */
618 	wlan_obj_pdev_vdevlist_add_tail(&objmgr->wlan_vdev_list, vdev);
619 	/* Increment pdev ref count to make sure it won't be destroyed before */
620 	wlan_objmgr_pdev_get_ref(pdev, WLAN_OBJMGR_ID);
621 	/* Increment vdev count of pdev */
622 	objmgr->wlan_vdev_count++;
623 	wlan_pdev_obj_unlock(pdev);
624 
625 	return QDF_STATUS_SUCCESS;
626 }
627 
628 QDF_STATUS wlan_objmgr_pdev_vdev_detach(struct wlan_objmgr_pdev *pdev,
629 				struct wlan_objmgr_vdev *vdev)
630 {
631 	struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr;
632 
633 	wlan_pdev_obj_lock(pdev);
634 	/* if vdev count is 0, return failure */
635 	if (objmgr->wlan_vdev_count == 0) {
636 		wlan_pdev_obj_unlock(pdev);
637 		return QDF_STATUS_E_FAILURE;
638 	}
639 	/* remove vdev from pdev's vdev list */
640 	wlan_obj_pdev_vdevlist_remove_vdev(&objmgr->wlan_vdev_list, vdev);
641 	/* decrement vdev count */
642 	objmgr->wlan_vdev_count--;
643 	wlan_pdev_obj_unlock(pdev);
644 	/* Decrement pdev ref count since vdev is releasing reference */
645 	wlan_objmgr_pdev_release_ref(pdev, WLAN_OBJMGR_ID);
646 	return QDF_STATUS_SUCCESS;
647 }
648 
649 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev(
650 			struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
651 			wlan_objmgr_ref_dbgid dbg_id)
652 {
653 	struct wlan_objmgr_vdev *vdev;
654 	struct wlan_objmgr_vdev *vdev_next;
655 	struct wlan_objmgr_pdev_objmgr *objmgr;
656 	qdf_list_t *vdev_list;
657 
658 	wlan_pdev_obj_lock(pdev);
659 
660 	objmgr = &pdev->pdev_objmgr;
661 	vdev_list = &objmgr->wlan_vdev_list;
662 	/* Get first vdev */
663 	vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
664 	/* Iterate through pdev's vdev list, till vdev id matches with
665 	entry of vdev list */
666 	while (vdev != NULL) {
667 		if (wlan_vdev_get_id(vdev) == vdev_id) {
668 			if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) !=
669 							QDF_STATUS_SUCCESS)
670 				vdev = NULL;
671 
672 			wlan_pdev_obj_unlock(pdev);
673 			return vdev;
674 		}
675 		/* get next vdev */
676 		vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev);
677 		vdev = vdev_next;
678 	}
679 	wlan_pdev_obj_unlock(pdev);
680 	return NULL;
681 }
682 qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_pdev);
683 
684 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_no_state(
685 			struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
686 			wlan_objmgr_ref_dbgid dbg_id)
687 {
688 	struct wlan_objmgr_vdev *vdev;
689 	struct wlan_objmgr_vdev *vdev_next;
690 	struct wlan_objmgr_pdev_objmgr *objmgr;
691 	qdf_list_t *vdev_list;
692 
693 	wlan_pdev_obj_lock(pdev);
694 
695 	objmgr = &pdev->pdev_objmgr;
696 	vdev_list = &objmgr->wlan_vdev_list;
697 	/* Get first vdev */
698 	vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
699 	/**
700 	 * Iterate through pdev's vdev list, till vdev id matches with
701 	 * entry of vdev list
702 	 */
703 	while (vdev != NULL) {
704 		if (wlan_vdev_get_id(vdev) == vdev_id) {
705 			wlan_objmgr_vdev_get_ref(vdev, dbg_id);
706 			wlan_pdev_obj_unlock(pdev);
707 
708 			return vdev;
709 		}
710 		/* get next vdev */
711 		vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev);
712 		vdev = vdev_next;
713 	}
714 	wlan_pdev_obj_unlock(pdev);
715 
716 	return NULL;
717 }
718 qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_pdev_no_state);
719 
720 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev(
721 		struct wlan_objmgr_pdev *pdev, uint8_t *macaddr,
722 		wlan_objmgr_ref_dbgid dbg_id)
723 {
724 	struct wlan_objmgr_vdev *vdev;
725 	struct wlan_objmgr_vdev *vdev_next;
726 	struct wlan_objmgr_pdev_objmgr *objmgr;
727 	qdf_list_t *vdev_list;
728 
729 	wlan_pdev_obj_lock(pdev);
730 	objmgr = &pdev->pdev_objmgr;
731 	vdev_list = &objmgr->wlan_vdev_list;
732 	/* Get first vdev */
733 	vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
734 	/* Iterate through pdev's vdev list, till vdev macaddr matches with
735 	entry of vdev list */
736 	while (vdev != NULL) {
737 		if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr)
738 					== QDF_STATUS_SUCCESS) {
739 			if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) !=
740 							QDF_STATUS_SUCCESS)
741 				vdev = NULL;
742 
743 			wlan_pdev_obj_unlock(pdev);
744 			return vdev;
745 		}
746 		/* get next vdev */
747 		vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev);
748 		vdev = vdev_next;
749 	}
750 	wlan_pdev_obj_unlock(pdev);
751 
752 	return NULL;
753 }
754 
755 struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state(
756 		struct wlan_objmgr_pdev *pdev, uint8_t *macaddr,
757 		wlan_objmgr_ref_dbgid dbg_id)
758 {
759 	struct wlan_objmgr_vdev *vdev;
760 	struct wlan_objmgr_vdev *vdev_next;
761 	struct wlan_objmgr_pdev_objmgr *objmgr;
762 	qdf_list_t *vdev_list;
763 
764 	wlan_pdev_obj_lock(pdev);
765 	objmgr = &pdev->pdev_objmgr;
766 	vdev_list = &objmgr->wlan_vdev_list;
767 	/* Get first vdev */
768 	vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
769 	/* Iterate through pdev's vdev list, till vdev macaddr matches with
770 	entry of vdev list */
771 	while (vdev != NULL) {
772 		if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr)
773 					== QDF_STATUS_SUCCESS) {
774 			wlan_objmgr_vdev_get_ref(vdev, dbg_id);
775 			wlan_pdev_obj_unlock(pdev);
776 
777 			return vdev;
778 		}
779 		/* get next vdev */
780 		vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev);
781 		vdev = vdev_next;
782 	}
783 	wlan_pdev_obj_unlock(pdev);
784 
785 	return NULL;
786 }
787 
788 void *wlan_objmgr_pdev_get_comp_private_obj(
789 		struct wlan_objmgr_pdev *pdev,
790 		enum wlan_umac_comp_id id)
791 {
792 	void *comp_priv_obj;
793 
794 	/* component id is invalid */
795 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
796 		QDF_BUG(0);
797 		return NULL;
798 	}
799 
800 	if (pdev == NULL) {
801 		QDF_BUG(0);
802 		return NULL;
803 	}
804 
805 	comp_priv_obj = pdev->pdev_comp_priv_obj[id];
806 
807 	return comp_priv_obj;
808 }
809 qdf_export_symbol(wlan_objmgr_pdev_get_comp_private_obj);
810 
811 void wlan_objmgr_pdev_get_ref(struct wlan_objmgr_pdev *pdev,
812 					wlan_objmgr_ref_dbgid id)
813 {
814 	if (pdev == NULL) {
815 		obj_mgr_err("pdev obj is NULL");
816 		QDF_ASSERT(0);
817 		return;
818 	}
819 	qdf_atomic_inc(&pdev->pdev_objmgr.ref_cnt);
820 	qdf_atomic_inc(&pdev->pdev_objmgr.ref_id_dbg[id]);
821 
822 	return;
823 }
824 qdf_export_symbol(wlan_objmgr_pdev_get_ref);
825 
826 QDF_STATUS wlan_objmgr_pdev_try_get_ref(struct wlan_objmgr_pdev *pdev,
827 						wlan_objmgr_ref_dbgid id)
828 {
829 	uint8_t pdev_id;
830 
831 	if (pdev == NULL) {
832 		obj_mgr_err("pdev obj is NULL");
833 		QDF_ASSERT(0);
834 		return QDF_STATUS_E_FAILURE;
835 	}
836 
837 	wlan_pdev_obj_lock(pdev);
838 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
839 	if (pdev->obj_state != WLAN_OBJ_STATE_CREATED) {
840 		wlan_pdev_obj_unlock(pdev);
841 		if (pdev->pdev_objmgr.print_cnt++ <=
842 				WLAN_OBJMGR_RATELIMIT_THRESH)
843 			obj_mgr_err(
844 			"[Ref id: %d] pdev [%d] is not in Created(st:%d)",
845 					id, pdev_id, pdev->obj_state);
846 		return QDF_STATUS_E_RESOURCES;
847 	}
848 
849 	wlan_objmgr_pdev_get_ref(pdev, id);
850 	wlan_pdev_obj_unlock(pdev);
851 
852 	return QDF_STATUS_SUCCESS;
853 }
854 qdf_export_symbol(wlan_objmgr_pdev_try_get_ref);
855 
856 void wlan_objmgr_pdev_release_ref(struct wlan_objmgr_pdev *pdev,
857 						wlan_objmgr_ref_dbgid id)
858 {
859 	uint8_t pdev_id;
860 
861 	if (pdev == NULL) {
862 		obj_mgr_err("pdev obj is NULL");
863 		QDF_ASSERT(0);
864 		return;
865 	}
866 
867 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
868 
869 	if (!qdf_atomic_read(&pdev->pdev_objmgr.ref_id_dbg[id])) {
870 		obj_mgr_err("pdev (id:%d)ref cnt was not taken by %d",
871 				pdev_id, id);
872 		wlan_objmgr_print_ref_ids(pdev->pdev_objmgr.ref_id_dbg);
873 		WLAN_OBJMGR_BUG(0);
874 	}
875 
876 	if (!qdf_atomic_read(&pdev->pdev_objmgr.ref_cnt)) {
877 		obj_mgr_err("pdev ref cnt is 0: pdev-id:%d", pdev_id);
878 		WLAN_OBJMGR_BUG(0);
879 		return;
880 	}
881 
882 	qdf_atomic_dec(&pdev->pdev_objmgr.ref_id_dbg[id]);
883 	/* Decrement ref count, free pdev, if ref count == 0 */
884 	if (qdf_atomic_dec_and_test(&pdev->pdev_objmgr.ref_cnt))
885 		wlan_objmgr_pdev_obj_destroy(pdev);
886 
887 	return;
888 }
889 qdf_export_symbol(wlan_objmgr_pdev_release_ref);
890 
891 struct wlan_objmgr_vdev *wlan_objmgr_pdev_get_first_vdev(
892 		struct wlan_objmgr_pdev *pdev,
893 		wlan_objmgr_ref_dbgid dbg_id)
894 {
895 	struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr;
896 	qdf_list_t *vdev_list = NULL;
897 	struct wlan_objmgr_vdev *vdev;
898 	qdf_list_node_t *node = NULL;
899 	qdf_list_node_t *prev_node = NULL;
900 
901 	wlan_pdev_obj_lock(pdev);
902 
903 	/* VDEV list */
904 	vdev_list = &objmgr->wlan_vdev_list;
905 	if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) {
906 		wlan_pdev_obj_unlock(pdev);
907 		return NULL;
908 	}
909 
910 	do {
911 		vdev = qdf_container_of(node, struct wlan_objmgr_vdev,
912 					vdev_node);
913 		if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) ==
914 						QDF_STATUS_SUCCESS) {
915 			wlan_pdev_obj_unlock(pdev);
916 			return vdev;
917 		}
918 
919 		prev_node = node;
920 	} while (qdf_list_peek_next(vdev_list, prev_node, &node) ==
921 						QDF_STATUS_SUCCESS);
922 
923 	wlan_pdev_obj_unlock(pdev);
924 
925 	return NULL;
926 }
927 
928 qdf_export_symbol(wlan_objmgr_pdev_get_first_vdev);
929