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