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