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