xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj.c (revision 2f4b444fb7e689b83a4ab0e7b3b38f0bf4def8e0)
1 /*
2  * Copyright (c) 2016-2021 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 
22 #include "wlan_objmgr_global_obj_i.h"
23 #include <wlan_objmgr_global_obj.h>
24 #include "wlan_objmgr_debug.h"
25 #include "wlan_objmgr_psoc_obj.h"
26 #include "qdf_mem.h"
27 #include <qdf_module.h>
28 
29 /* Global object, it is declared globally */
30 struct wlan_objmgr_global *g_umac_glb_obj;
31 
32 qdf_export_symbol(g_umac_glb_obj);
33 
34 /*
35 ** APIs to Create/Delete Global object APIs
36 */
37 QDF_STATUS wlan_objmgr_global_obj_init(void)
38 {
39 	struct wlan_objmgr_global *umac_global_obj;
40 
41 	/* If it is already created, ignore */
42 	if (g_umac_glb_obj) {
43 		obj_mgr_err("Global object is already created");
44 		return QDF_STATUS_E_FAILURE;
45 	}
46 
47 	/* Allocation of memory for Global object */
48 	umac_global_obj = (struct wlan_objmgr_global *)qdf_mem_malloc(
49 				sizeof(*umac_global_obj));
50 	if (!umac_global_obj)
51 		return QDF_STATUS_E_NOMEM;
52 
53 	/* Store Global object pointer in Global variable */
54 	g_umac_glb_obj = umac_global_obj;
55 	/* Initialize spinlock */
56 	qdf_spinlock_create(&g_umac_glb_obj->global_lock);
57 	wlan_objmgr_debug_info_init();
58 
59 	return QDF_STATUS_SUCCESS;
60 }
61 qdf_export_symbol(wlan_objmgr_global_obj_init);
62 
63 QDF_STATUS wlan_objmgr_global_obj_deinit(void)
64 {
65 	/* If it is already destroyed */
66 	if (!g_umac_glb_obj) {
67 		obj_mgr_err("Global object is not allocated");
68 		return QDF_STATUS_E_FAILURE;
69 	}
70 
71 	wlan_objmgr_debug_info_deinit();
72 
73 	if (QDF_STATUS_SUCCESS == wlan_objmgr_global_obj_can_destroyed()) {
74 		qdf_spinlock_destroy(&g_umac_glb_obj->global_lock);
75 		qdf_mem_free(g_umac_glb_obj);
76 		g_umac_glb_obj = NULL;
77 	} else {
78 		obj_mgr_err("PSOCs are leaked can't free global objmgr ctx");
79 		WLAN_OBJMGR_BUG(0);
80 	}
81 
82 	return QDF_STATUS_SUCCESS;
83 }
84 qdf_export_symbol(wlan_objmgr_global_obj_deinit);
85 
86 /**
87  ** APIs to register/unregister handlers
88  */
89 QDF_STATUS wlan_objmgr_register_psoc_create_handler(
90 		enum wlan_umac_comp_id id,
91 		wlan_objmgr_psoc_create_handler handler,
92 		void *arg)
93 {
94 	/* If id is not within valid range, return */
95 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
96 		obj_mgr_err("Component %d is out of range", id);
97 		return QDF_STATUS_MAXCOMP_FAIL;
98 	}
99 
100 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
101 	/* If there is a valid entry, return failure */
102 	if (g_umac_glb_obj->psoc_create_handler[id]) {
103 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
104 		obj_mgr_err("Callback for comp %d is already registered", id);
105 		QDF_ASSERT(0);
106 		return QDF_STATUS_E_FAILURE;
107 	}
108 	/* Store handler and args in Global object table */
109 	g_umac_glb_obj->psoc_create_handler[id] = handler;
110 	g_umac_glb_obj->psoc_create_handler_arg[id] = arg;
111 
112 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
113 	return QDF_STATUS_SUCCESS;
114 }
115 qdf_export_symbol(wlan_objmgr_register_psoc_create_handler);
116 
117 QDF_STATUS wlan_objmgr_unregister_psoc_create_handler(
118 		enum wlan_umac_comp_id id,
119 		wlan_objmgr_psoc_create_handler handler,
120 		void *arg)
121 {
122 	/* If id is not within valid range, return */
123 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
124 		obj_mgr_err("Component %d is out of range", id);
125 		return QDF_STATUS_MAXCOMP_FAIL;
126 	}
127 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
128 	/* If there is an invalid entry, return failure */
129 	if (g_umac_glb_obj->psoc_create_handler[id] != handler) {
130 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
131 		obj_mgr_err("Callback for comp %d is not registered", id);
132 		QDF_ASSERT(0);
133 		return QDF_STATUS_E_FAILURE;
134 	}
135 	/* Reset handlers, and args to NULL */
136 	g_umac_glb_obj->psoc_create_handler[id] = NULL;
137 	g_umac_glb_obj->psoc_create_handler_arg[id] = NULL;
138 
139 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
140 	return QDF_STATUS_SUCCESS;
141 }
142 qdf_export_symbol(wlan_objmgr_unregister_psoc_create_handler);
143 
144 QDF_STATUS wlan_objmgr_register_psoc_destroy_handler(
145 		enum wlan_umac_comp_id id,
146 		wlan_objmgr_psoc_destroy_handler handler,
147 		void *arg)
148 {
149 	/* If id is not within valid range, return */
150 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
151 		obj_mgr_err("Component %d is out of range", id);
152 		return QDF_STATUS_MAXCOMP_FAIL;
153 	}
154 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
155 	/* If there is a valid entry, return failure */
156 	if (g_umac_glb_obj->psoc_destroy_handler[id]) {
157 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
158 		obj_mgr_err("Callback for comp %d is already registered", id);
159 		QDF_ASSERT(0);
160 		return QDF_STATUS_E_FAILURE;
161 	}
162 	/* Store handler and args in Global object table */
163 	g_umac_glb_obj->psoc_destroy_handler[id] = handler;
164 	g_umac_glb_obj->psoc_destroy_handler_arg[id] = arg;
165 
166 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
167 	return QDF_STATUS_SUCCESS;
168 }
169 qdf_export_symbol(wlan_objmgr_register_psoc_destroy_handler);
170 
171 QDF_STATUS wlan_objmgr_unregister_psoc_destroy_handler(
172 		enum wlan_umac_comp_id id,
173 		wlan_objmgr_psoc_destroy_handler handler,
174 		void *arg)
175 {
176 	/* If id is not within valid range, return */
177 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
178 		obj_mgr_err("Component %d is out of range", id);
179 		return QDF_STATUS_MAXCOMP_FAIL;
180 	}
181 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
182 	/* If there is an invalid entry, return failure */
183 	if (g_umac_glb_obj->psoc_destroy_handler[id] != handler) {
184 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
185 		obj_mgr_err("Callback for comp %d is not registered", id);
186 		QDF_ASSERT(0);
187 		return QDF_STATUS_E_FAILURE;
188 	}
189 	/* Reset handlers, and args to NULL */
190 	g_umac_glb_obj->psoc_destroy_handler[id] = NULL;
191 	g_umac_glb_obj->psoc_destroy_handler_arg[id] = NULL;
192 
193 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
194 	return QDF_STATUS_SUCCESS;
195 }
196 qdf_export_symbol(wlan_objmgr_unregister_psoc_destroy_handler);
197 
198 QDF_STATUS wlan_objmgr_register_psoc_status_handler(
199 		enum wlan_umac_comp_id id,
200 		wlan_objmgr_psoc_status_handler handler,
201 		void *arg)
202 {
203 	/* If id is not within valid range, return */
204 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
205 		obj_mgr_err("Component %d is out of range", id);
206 		return QDF_STATUS_MAXCOMP_FAIL;
207 	}
208 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
209 	/* If there is a valid entry, return failure */
210 	if (g_umac_glb_obj->psoc_status_handler[id]) {
211 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
212 		obj_mgr_err("Callback for comp %d is already registered", id);
213 		return QDF_STATUS_E_FAILURE;
214 	}
215 	/* Store handler and args in Global object table */
216 	g_umac_glb_obj->psoc_status_handler[id] = handler;
217 	g_umac_glb_obj->psoc_status_handler_arg[id] = arg;
218 
219 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
220 	return QDF_STATUS_SUCCESS;
221 }
222 
223 QDF_STATUS wlan_objmgr_unregister_psoc_status_handler(
224 		enum wlan_umac_comp_id id,
225 		wlan_objmgr_psoc_status_handler handler,
226 		void *arg)
227 {
228 	/* If id is not within valid range, return */
229 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
230 		obj_mgr_err("Component %d is out of range", id);
231 		return QDF_STATUS_MAXCOMP_FAIL;
232 	}
233 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
234 	/* If there is an invalid entry, return failure */
235 	if (g_umac_glb_obj->psoc_status_handler[id] != handler) {
236 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
237 		obj_mgr_err("Callback for comp %d is not registered", id);
238 		return QDF_STATUS_E_FAILURE;
239 	}
240 	/* Reset handlers, and args to NULL */
241 	g_umac_glb_obj->psoc_status_handler[id] = NULL;
242 	g_umac_glb_obj->psoc_status_handler_arg[id] = NULL;
243 
244 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
245 	return QDF_STATUS_SUCCESS;
246 }
247 
248 
249 QDF_STATUS wlan_objmgr_register_pdev_create_handler(
250 		enum wlan_umac_comp_id id,
251 		wlan_objmgr_pdev_create_handler handler,
252 		void *arg)
253 {
254 	/* If id is not within valid range, return */
255 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
256 		obj_mgr_err("Component %d is out of range", id);
257 		return QDF_STATUS_MAXCOMP_FAIL;
258 	}
259 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
260 	/* If there is a valid entry, return failure */
261 	if (g_umac_glb_obj->pdev_create_handler[id]) {
262 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
263 		obj_mgr_err("Callback for comp %d is already registered", id);
264 		QDF_ASSERT(0);
265 		return QDF_STATUS_E_FAILURE;
266 	}
267 	/* Store handler and args in Global object table */
268 	g_umac_glb_obj->pdev_create_handler[id] = handler;
269 	g_umac_glb_obj->pdev_create_handler_arg[id] = arg;
270 
271 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
272 	return QDF_STATUS_SUCCESS;
273 }
274 qdf_export_symbol(wlan_objmgr_register_pdev_create_handler);
275 
276 QDF_STATUS wlan_objmgr_unregister_pdev_create_handler(
277 		enum wlan_umac_comp_id id,
278 		wlan_objmgr_pdev_create_handler handler,
279 		void *arg)
280 {
281 	/* If id is not within valid range, return */
282 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
283 		obj_mgr_err("Component %d is out of range", id);
284 		return QDF_STATUS_MAXCOMP_FAIL;
285 	}
286 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
287 	/* If there is an invalid entry, return failure */
288 	if (g_umac_glb_obj->pdev_create_handler[id] != handler) {
289 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
290 		obj_mgr_err("Callback for comp %d is not registered", id);
291 		QDF_ASSERT(0);
292 		return QDF_STATUS_E_FAILURE;
293 	}
294 	/* Reset handlers, and args to NULL */
295 	g_umac_glb_obj->pdev_create_handler[id] = NULL;
296 	g_umac_glb_obj->pdev_create_handler_arg[id] = NULL;
297 
298 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
299 	return QDF_STATUS_SUCCESS;
300 }
301 qdf_export_symbol(wlan_objmgr_unregister_pdev_create_handler);
302 
303 QDF_STATUS wlan_objmgr_register_pdev_destroy_handler(
304 		enum wlan_umac_comp_id id,
305 		wlan_objmgr_pdev_destroy_handler handler,
306 		void *arg)
307 {
308 	/* If id is not within valid range, return */
309 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
310 		obj_mgr_err("Component %d is out of range", id);
311 		return QDF_STATUS_MAXCOMP_FAIL;
312 	}
313 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
314 	/* If there is a valid entry, return failure */
315 	if (g_umac_glb_obj->pdev_destroy_handler[id]) {
316 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
317 		obj_mgr_err("Callback for comp %d is already registered", id);
318 		QDF_ASSERT(0);
319 		return QDF_STATUS_E_FAILURE;
320 	}
321 	/* Store handler and args in Global object table */
322 	g_umac_glb_obj->pdev_destroy_handler[id] = handler;
323 	g_umac_glb_obj->pdev_destroy_handler_arg[id] = arg;
324 
325 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
326 	return QDF_STATUS_SUCCESS;
327 }
328 qdf_export_symbol(wlan_objmgr_register_pdev_destroy_handler);
329 
330 QDF_STATUS wlan_objmgr_unregister_pdev_destroy_handler(
331 		enum wlan_umac_comp_id id,
332 		wlan_objmgr_pdev_destroy_handler handler,
333 		void *arg)
334 {
335 	/* If id is not within valid range, return */
336 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
337 		obj_mgr_err("Component %d is out of range", id);
338 		return QDF_STATUS_MAXCOMP_FAIL;
339 	}
340 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
341 	/* If there is an invalid entry, return failure */
342 	if (g_umac_glb_obj->pdev_destroy_handler[id] != handler) {
343 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
344 		obj_mgr_err("Callback for Component %d is not registered", id);
345 		QDF_ASSERT(0);
346 		return QDF_STATUS_E_FAILURE;
347 	}
348 	/* Reset handlers, and args to NULL */
349 	g_umac_glb_obj->pdev_destroy_handler[id] = NULL;
350 	g_umac_glb_obj->pdev_destroy_handler_arg[id] = NULL;
351 
352 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
353 	return QDF_STATUS_SUCCESS;
354 }
355 qdf_export_symbol(wlan_objmgr_unregister_pdev_destroy_handler);
356 
357 QDF_STATUS wlan_objmgr_register_pdev_status_handler(
358 		enum wlan_umac_comp_id id,
359 		wlan_objmgr_pdev_status_handler handler,
360 		void *arg)
361 {
362 	/* If id is not within valid range, return */
363 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
364 		obj_mgr_err("Component %d is out of range", id);
365 		return QDF_STATUS_MAXCOMP_FAIL;
366 	}
367 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
368 	/* If there is a valid entry, return failure */
369 	if (g_umac_glb_obj->pdev_status_handler[id]) {
370 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
371 		obj_mgr_err("Callback for comp %d is already registered", id);
372 		return QDF_STATUS_E_FAILURE;
373 	}
374 	/* Store handler and args in Global object table */
375 	g_umac_glb_obj->pdev_status_handler[id] = handler;
376 	g_umac_glb_obj->pdev_status_handler_arg[id] = arg;
377 
378 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
379 	return QDF_STATUS_SUCCESS;
380 }
381 
382 QDF_STATUS wlan_objmgr_unregister_pdev_status_handler(
383 		enum wlan_umac_comp_id id,
384 		wlan_objmgr_pdev_status_handler handler,
385 		void *arg)
386 {
387 	/* If id is not within valid range, return */
388 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
389 		obj_mgr_err("Component %d is out of range", id);
390 		return QDF_STATUS_MAXCOMP_FAIL;
391 	}
392 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
393 	/* If there is an invalid entry, return failure */
394 	if (g_umac_glb_obj->pdev_status_handler[id] != handler) {
395 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
396 		obj_mgr_err("Callback for Component %d is not registered", id);
397 		return QDF_STATUS_E_FAILURE;
398 	}
399 	/* Reset handlers, and args to NULL */
400 	g_umac_glb_obj->pdev_status_handler[id] = NULL;
401 	g_umac_glb_obj->pdev_status_handler_arg[id] = NULL;
402 
403 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
404 	return QDF_STATUS_SUCCESS;
405 }
406 
407 
408 QDF_STATUS wlan_objmgr_register_vdev_create_handler(
409 		enum wlan_umac_comp_id id,
410 		wlan_objmgr_vdev_create_handler handler,
411 		void *arg)
412 {
413 	/* If id is not within valid range, return */
414 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
415 		obj_mgr_err("Component %d is out of range", id);
416 		return QDF_STATUS_MAXCOMP_FAIL;
417 	}
418 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
419 	/* If there is a valid entry, return failure */
420 	if (g_umac_glb_obj->vdev_create_handler[id]) {
421 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
422 		obj_mgr_err("Callback for comp %d is already registered", id);
423 		QDF_ASSERT(0);
424 		return QDF_STATUS_E_FAILURE;
425 	}
426 	/* Store handler and args in Global object table */
427 	g_umac_glb_obj->vdev_create_handler[id] = handler;
428 	g_umac_glb_obj->vdev_create_handler_arg[id] = arg;
429 
430 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
431 	return QDF_STATUS_SUCCESS;
432 }
433 qdf_export_symbol(wlan_objmgr_register_vdev_create_handler);
434 
435 QDF_STATUS wlan_objmgr_unregister_vdev_create_handler(
436 		enum wlan_umac_comp_id id,
437 		wlan_objmgr_vdev_create_handler handler,
438 		void *arg)
439 {
440 	/* If id is not within valid range, return */
441 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
442 		obj_mgr_err("Component %d is out of range", id);
443 		return QDF_STATUS_MAXCOMP_FAIL;
444 	}
445 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
446 	/* If there is an invalid entry, return failure */
447 	if (g_umac_glb_obj->vdev_create_handler[id] != handler) {
448 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
449 		obj_mgr_err("Callback for comp %d is not registered", id);
450 		QDF_ASSERT(0);
451 		return QDF_STATUS_E_FAILURE;
452 	}
453 	/* Reset handlers, and args to NULL */
454 	g_umac_glb_obj->vdev_create_handler[id] = NULL;
455 	g_umac_glb_obj->vdev_create_handler_arg[id] = NULL;
456 
457 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
458 	return QDF_STATUS_SUCCESS;
459 }
460 qdf_export_symbol(wlan_objmgr_unregister_vdev_create_handler);
461 
462 QDF_STATUS wlan_objmgr_register_vdev_destroy_handler(
463 		enum wlan_umac_comp_id id,
464 		wlan_objmgr_vdev_destroy_handler handler,
465 		void *arg)
466 {
467 	/* If id is not within valid range, return */
468 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
469 		obj_mgr_err("Component %d is out of range", id);
470 		return QDF_STATUS_MAXCOMP_FAIL;
471 	}
472 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
473 	/* If there is a valid entry, return failure */
474 	if (g_umac_glb_obj->vdev_destroy_handler[id]) {
475 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
476 		obj_mgr_err("Callback for comp %d is already registered", id);
477 		QDF_ASSERT(0);
478 		return QDF_STATUS_E_FAILURE;
479 	}
480 	/* Store handler and args in Global object table */
481 	g_umac_glb_obj->vdev_destroy_handler[id] = handler;
482 	g_umac_glb_obj->vdev_destroy_handler_arg[id] = arg;
483 
484 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
485 	return QDF_STATUS_SUCCESS;
486 }
487 qdf_export_symbol(wlan_objmgr_register_vdev_destroy_handler);
488 
489 QDF_STATUS wlan_objmgr_unregister_vdev_destroy_handler(
490 		enum wlan_umac_comp_id id,
491 		wlan_objmgr_vdev_destroy_handler handler,
492 		void *arg)
493 {
494 	/* If id is not within valid range, return */
495 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
496 		obj_mgr_err("Component %d is out of range", id);
497 		return QDF_STATUS_MAXCOMP_FAIL;
498 	}
499 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
500 	/* If there is an invalid entry, return failure */
501 	if (g_umac_glb_obj->vdev_destroy_handler[id] != handler) {
502 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
503 		obj_mgr_err("Callback for comp %d is not registered", id);
504 		QDF_ASSERT(0);
505 		return QDF_STATUS_E_FAILURE;
506 	}
507 	/* Reset handlers, and args to NULL */
508 	g_umac_glb_obj->vdev_destroy_handler[id] = NULL;
509 	g_umac_glb_obj->vdev_destroy_handler_arg[id] = NULL;
510 
511 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
512 	return QDF_STATUS_SUCCESS;
513 }
514 qdf_export_symbol(wlan_objmgr_unregister_vdev_destroy_handler);
515 
516 QDF_STATUS wlan_objmgr_register_vdev_status_handler(
517 		enum wlan_umac_comp_id id,
518 		wlan_objmgr_vdev_status_handler handler,
519 		void *arg)
520 {
521 	/* If id is not within valid range, return */
522 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
523 		obj_mgr_err("Component %d is out of range", id);
524 		return QDF_STATUS_MAXCOMP_FAIL;
525 	}
526 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
527 	/* If there is a valid entry, return failure */
528 	if (g_umac_glb_obj->vdev_status_handler[id]) {
529 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
530 		obj_mgr_err("Callback for comp %d is already registered", id);
531 		return QDF_STATUS_E_FAILURE;
532 	}
533 	/* Store handler and args in Global object table */
534 	g_umac_glb_obj->vdev_status_handler[id] = handler;
535 	g_umac_glb_obj->vdev_status_handler_arg[id] = arg;
536 
537 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
538 	return QDF_STATUS_SUCCESS;
539 }
540 
541 QDF_STATUS wlan_objmgr_unregister_vdev_status_handler(
542 		enum wlan_umac_comp_id id,
543 		wlan_objmgr_vdev_status_handler handler,
544 		void *arg)
545 {
546 	/* If id is not within valid range, return */
547 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
548 		obj_mgr_err("Component %d is out of range", id);
549 		return QDF_STATUS_MAXCOMP_FAIL;
550 	}
551 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
552 	/* If there is an invalid entry, return failure */
553 	if (g_umac_glb_obj->vdev_status_handler[id] != handler) {
554 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
555 		obj_mgr_err("Callback for Component %d is not registered", id);
556 		return QDF_STATUS_E_FAILURE;
557 	}
558 	/* Reset handlers, and args to NULL */
559 	g_umac_glb_obj->vdev_status_handler[id] = NULL;
560 	g_umac_glb_obj->vdev_status_handler_arg[id] = NULL;
561 
562 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
563 	return QDF_STATUS_SUCCESS;
564 }
565 
566 QDF_STATUS wlan_objmgr_register_vdev_peer_free_notify_handler(
567 		enum wlan_umac_comp_id id,
568 		wlan_objmgr_vdev_peer_free_notify_handler handler)
569 {
570 	/* If id is not within valid range, return */
571 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
572 		obj_mgr_err("Component %d is out of range", id);
573 		WLAN_OBJMGR_BUG(0);
574 		return QDF_STATUS_MAXCOMP_FAIL;
575 	}
576 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
577 	/* If there is a valid entry, return failure */
578 	if (g_umac_glb_obj->vdev_peer_free_notify_handler[id]) {
579 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
580 		obj_mgr_err("Callback for comp %d is already registered", id);
581 		return QDF_STATUS_E_FAILURE;
582 	}
583 	/* Store handler in Global object table */
584 	g_umac_glb_obj->vdev_peer_free_notify_handler[id] = handler;
585 
586 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
587 
588 	return QDF_STATUS_SUCCESS;
589 }
590 
591 QDF_STATUS wlan_objmgr_unregister_vdev_peer_free_notify_handler(
592 		enum wlan_umac_comp_id id,
593 		wlan_objmgr_vdev_peer_free_notify_handler handler)
594 {
595 	/* If id is not within valid range, return */
596 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
597 		obj_mgr_err("Component %d is out of range", id);
598 		WLAN_OBJMGR_BUG(0);
599 		return QDF_STATUS_MAXCOMP_FAIL;
600 	}
601 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
602 	/* If there is an invalid entry, return failure */
603 	if (g_umac_glb_obj->vdev_peer_free_notify_handler[id] != handler) {
604 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
605 		obj_mgr_err("Callback for Component %d is not registered", id);
606 		return QDF_STATUS_E_FAILURE;
607 	}
608 	/* Reset handlers to NULL */
609 	g_umac_glb_obj->vdev_peer_free_notify_handler[id] = NULL;
610 
611 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
612 
613 	return QDF_STATUS_SUCCESS;
614 }
615 
616 QDF_STATUS wlan_objmgr_register_peer_create_handler(
617 		enum wlan_umac_comp_id id,
618 		wlan_objmgr_peer_create_handler handler,
619 		void *arg)
620 {
621 	/* If id is not within valid range, return */
622 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
623 		obj_mgr_err("Component %d is out of range", id);
624 		return QDF_STATUS_MAXCOMP_FAIL;
625 	}
626 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
627 	/* If there is a valid entry, return failure */
628 	if (g_umac_glb_obj->peer_create_handler[id]) {
629 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
630 		obj_mgr_err("Callback for comp %d is already registered", id);
631 		QDF_ASSERT(0);
632 		return QDF_STATUS_E_FAILURE;
633 	}
634 	/* Store handler and args in Global object table */
635 	g_umac_glb_obj->peer_create_handler[id] = handler;
636 	g_umac_glb_obj->peer_create_handler_arg[id] = arg;
637 
638 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
639 	return QDF_STATUS_SUCCESS;
640 }
641 
642 
643 QDF_STATUS wlan_objmgr_unregister_peer_create_handler(
644 		enum wlan_umac_comp_id id,
645 		wlan_objmgr_peer_create_handler handler,
646 		void *arg)
647 {
648 	/* If id is not within valid range, return */
649 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
650 		obj_mgr_err("Component %d is out of range", id);
651 		return QDF_STATUS_MAXCOMP_FAIL;
652 	}
653 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
654 	/* If there is an invalid entry, return failure */
655 	if (g_umac_glb_obj->peer_create_handler[id] != handler) {
656 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
657 		obj_mgr_err("Callback for comp %d is not registered", id);
658 		QDF_ASSERT(0);
659 		return QDF_STATUS_E_FAILURE;
660 	}
661 	/* Reset handlers, and args to NULL */
662 	g_umac_glb_obj->peer_create_handler[id] = NULL;
663 	g_umac_glb_obj->peer_create_handler_arg[id] = NULL;
664 
665 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
666 	return QDF_STATUS_SUCCESS;
667 }
668 
669 QDF_STATUS wlan_objmgr_register_peer_destroy_handler(
670 		enum wlan_umac_comp_id id,
671 		wlan_objmgr_peer_destroy_handler handler,
672 		void *arg)
673 {
674 	/* If id is not within valid range, return */
675 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
676 		obj_mgr_err("Component %d is out of range", id);
677 		return QDF_STATUS_MAXCOMP_FAIL;
678 	}
679 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
680 	/* If there is a valid entry, return failure */
681 	if (g_umac_glb_obj->peer_destroy_handler[id]) {
682 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
683 		obj_mgr_err("Callback for comp %d is already registered", id);
684 		QDF_ASSERT(0);
685 		return QDF_STATUS_E_FAILURE;
686 	}
687 	/* Store handler and args in Global object table */
688 	g_umac_glb_obj->peer_destroy_handler[id] = handler;
689 	g_umac_glb_obj->peer_destroy_handler_arg[id] = arg;
690 
691 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
692 	return QDF_STATUS_SUCCESS;
693 }
694 
695 QDF_STATUS wlan_objmgr_unregister_peer_destroy_handler(
696 		enum wlan_umac_comp_id id,
697 		wlan_objmgr_peer_destroy_handler handler,
698 		void *arg)
699 {
700 	/* If id is not within valid range, return */
701 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
702 		obj_mgr_err("Component %d is out of range", id);
703 		return QDF_STATUS_MAXCOMP_FAIL;
704 	}
705 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
706 	/* If there is an invalid entry, return failure */
707 	if (g_umac_glb_obj->peer_destroy_handler[id] != handler) {
708 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
709 		obj_mgr_err("Callback for comp %d is not registered", id);
710 		QDF_ASSERT(0);
711 		return QDF_STATUS_E_FAILURE;
712 	}
713 	/* Reset handlers, and args to NULL */
714 	g_umac_glb_obj->peer_destroy_handler[id] = NULL;
715 	g_umac_glb_obj->peer_destroy_handler_arg[id] = NULL;
716 
717 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
718 	return QDF_STATUS_SUCCESS;
719 }
720 
721 QDF_STATUS wlan_objmgr_register_peer_status_handler(
722 		enum wlan_umac_comp_id id,
723 		wlan_objmgr_peer_status_handler handler,
724 		void *arg)
725 {
726 	/* If id is not within valid range, return */
727 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
728 		obj_mgr_err("Component %d is out of range", id);
729 		return QDF_STATUS_MAXCOMP_FAIL;
730 	}
731 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
732 	/* If there is a valid entry, return failure */
733 	if (g_umac_glb_obj->peer_status_handler[id]) {
734 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
735 		obj_mgr_err("Callback for comp %d is already registered", id);
736 		return QDF_STATUS_E_FAILURE;
737 	}
738 	/* Store handler and args in Global object table */
739 	g_umac_glb_obj->peer_status_handler[id] = handler;
740 	g_umac_glb_obj->peer_status_handler_arg[id] = arg;
741 
742 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
743 	return QDF_STATUS_SUCCESS;
744 }
745 
746 QDF_STATUS wlan_objmgr_unregister_peer_status_handler(
747 		enum wlan_umac_comp_id id,
748 		wlan_objmgr_peer_status_handler handler,
749 		void *arg)
750 {
751 	/* If id is not within valid range, return */
752 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
753 		obj_mgr_err("Component %d is out of range", id);
754 		return QDF_STATUS_MAXCOMP_FAIL;
755 	}
756 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
757 	/* If there is an invalid entry, return failure */
758 	if (g_umac_glb_obj->peer_status_handler[id] != handler) {
759 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
760 		obj_mgr_err("Callback for comp %d is not registered", id);
761 		return QDF_STATUS_E_FAILURE;
762 	}
763 	/* Reset handlers, and args to NULL */
764 	g_umac_glb_obj->peer_status_handler[id] = NULL;
765 	g_umac_glb_obj->peer_status_handler_arg[id] = NULL;
766 
767 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
768 	return QDF_STATUS_SUCCESS;
769 }
770 
771 QDF_STATUS wlan_objmgr_psoc_object_attach(struct wlan_objmgr_psoc *psoc)
772 {
773 	uint8_t index = 0;
774 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
775 
776 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
777 	/* Find free slot in PSOC table, store the PSOC */
778 	while (index < WLAN_OBJMGR_MAX_DEVICES) {
779 		if (!g_umac_glb_obj->psoc[index]) {
780 			/* Found free slot, store psoc */
781 			g_umac_glb_obj->psoc[index] = psoc;
782 			psoc->soc_objmgr.psoc_id = index;
783 			status = QDF_STATUS_SUCCESS;
784 			break;
785 		}
786 		index++;
787 	}
788 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
789 	return status;
790 }
791 
792 QDF_STATUS wlan_objmgr_psoc_object_detach(struct wlan_objmgr_psoc *psoc)
793 {
794 	uint8_t psoc_id;
795 
796 	psoc_id = psoc->soc_objmgr.psoc_id;
797 	QDF_BUG(psoc_id < WLAN_OBJMGR_MAX_DEVICES);
798 	if (psoc_id >= WLAN_OBJMGR_MAX_DEVICES)
799 		return QDF_STATUS_E_INVAL;
800 
801 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
802 	g_umac_glb_obj->psoc[psoc_id] = NULL;
803 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
804 
805 	return QDF_STATUS_SUCCESS;
806 }
807 
808 QDF_STATUS wlan_objmgr_global_obj_can_destroyed(void)
809 {
810 	uint8_t index = 0;
811 	QDF_STATUS status = QDF_STATUS_SUCCESS;
812 
813 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
814 	/* Check whether all PSOCs are freed */
815 	while (index < WLAN_OBJMGR_MAX_DEVICES) {
816 		if (g_umac_glb_obj->psoc[index]) {
817 			status = QDF_STATUS_E_FAILURE;
818 			break;
819 		}
820 		index++;
821 	}
822 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
823 
824 	return status;
825 }
826 qdf_export_symbol(wlan_objmgr_global_obj_can_destroyed);
827 
828 void wlan_objmgr_print_ref_ids(qdf_atomic_t *id,
829 				QDF_TRACE_LEVEL log_level)
830 {
831 	uint32_t i;
832 	uint32_t pending_ref;
833 
834 	obj_mgr_log_level(log_level, "Pending references of object");
835 	for (i = 0; i < WLAN_REF_ID_MAX; i++) {
836 		pending_ref = qdf_atomic_read(&id[i]);
837 		if (pending_ref)
838 			obj_mgr_log_level(log_level, "%s -- %d",
839 				string_from_dbgid(i), pending_ref);
840 	}
841 
842 	return;
843 }
844 
845 QDF_STATUS wlan_objmgr_iterate_psoc_list(
846 		wlan_objmgr_psoc_handler handler,
847 		void *arg, wlan_objmgr_ref_dbgid dbg_id)
848 {
849 	uint8_t index = 0;
850 
851 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
852 
853 	while (index < WLAN_OBJMGR_MAX_DEVICES) {
854 		if (g_umac_glb_obj->psoc[index]) {
855 			handler((void *)g_umac_glb_obj->psoc[index],
856 				arg, index);
857 		}
858 		index++;
859 	}
860 
861 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
862 
863 	return QDF_STATUS_SUCCESS;
864 }
865 
866 qdf_export_symbol(wlan_objmgr_iterate_psoc_list);
867 
868 #ifdef WLAN_FEATURE_11BE_MLO
869 struct mlo_mgr_context *wlan_objmgr_get_mlo_ctx(void)
870 {
871 	return g_umac_glb_obj->mlo_ctx;
872 }
873 
874 void wlan_objmgr_set_mlo_ctx(struct mlo_mgr_context *ctx)
875 {
876 	g_umac_glb_obj->mlo_ctx = ctx;
877 }
878 #endif
879