xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj.c (revision 5c57a8905ee57aab8b10cde048801372f46cc3c0)
1 /*
2  * Copyright (c) 2016-2017 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 "qdf_mem.h"
25 
26 /* Global object, it is declared globally */
27 struct wlan_objmgr_global *g_umac_glb_obj;
28 /* Component Name table */
29 const char *wlan_umac_Component_name[] = {
30 	"MLME",
31 	"SCAN_MGR",
32 	"SCAN_CACHE",
33 	"MGMT_TXRX",
34 	"",
35 };
36 /*
37 ** APIs to Create/Delete Global object APIs
38 */
39 QDF_STATUS wlan_objmgr_global_obj_init(void)
40 {
41 	struct wlan_objmgr_global *umac_global_obj;
42 
43 	/* If it is already created, ignore */
44 	if (g_umac_glb_obj != NULL) {
45 		obj_mgr_err("Global object is already created");
46 		return QDF_STATUS_E_FAILURE;
47 	}
48 
49 	/* Allocation of memory for Global object */
50 	umac_global_obj = (struct wlan_objmgr_global *)qdf_mem_malloc(
51 				sizeof(*umac_global_obj));
52 	if (umac_global_obj == NULL) {
53 		obj_mgr_err("Global object alloc failed due to malloc");
54 		return QDF_STATUS_E_NOMEM;
55 	}
56 	/* Store Global object pointer in Global variable */
57 	g_umac_glb_obj = umac_global_obj;
58 	/* Initialize spinlock */
59 	qdf_spinlock_create(&g_umac_glb_obj->global_lock);
60 
61 	return QDF_STATUS_SUCCESS;
62 }
63 EXPORT_SYMBOL(wlan_objmgr_global_obj_init);
64 
65 QDF_STATUS wlan_objmgr_global_obj_deinit(void)
66 {
67 	/* If it is already destroyed */
68 	if (g_umac_glb_obj == NULL) {
69 		obj_mgr_err("Global object is not allocated");
70 		return QDF_STATUS_E_FAILURE;
71 	}
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 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] != NULL) {
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 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 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] != NULL) {
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 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 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] != NULL) {
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] != NULL) {
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 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 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] != NULL) {
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 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 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] != NULL) {
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] != NULL) {
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 
434 QDF_STATUS wlan_objmgr_unregister_vdev_create_handler(
435 		enum wlan_umac_comp_id id,
436 		wlan_objmgr_vdev_create_handler handler,
437 		void *arg)
438 {
439 	/* If id is not within valid range, return */
440 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
441 		obj_mgr_err("Component %d is out of range", id);
442 		return QDF_STATUS_MAXCOMP_FAIL;
443 	}
444 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
445 	/* If there is an invalid entry, return failure */
446 	if (g_umac_glb_obj->vdev_create_handler[id] != handler) {
447 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
448 		obj_mgr_err("Callback for comp %d is not registered", id);
449 		QDF_ASSERT(0);
450 		return QDF_STATUS_E_FAILURE;
451 	}
452 	/* Reset handlers, and args to NULL */
453 	g_umac_glb_obj->vdev_create_handler[id] = NULL;
454 	g_umac_glb_obj->vdev_create_handler_arg[id] = NULL;
455 
456 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
457 	return QDF_STATUS_SUCCESS;
458 }
459 
460 QDF_STATUS wlan_objmgr_register_vdev_destroy_handler(
461 		enum wlan_umac_comp_id id,
462 		wlan_objmgr_vdev_destroy_handler handler,
463 		void *arg)
464 {
465 	/* If id is not within valid range, return */
466 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
467 		obj_mgr_err("Component %d is out of range", id);
468 		return QDF_STATUS_MAXCOMP_FAIL;
469 	}
470 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
471 	/* If there is a valid entry, return failure */
472 	if (g_umac_glb_obj->vdev_destroy_handler[id] != NULL) {
473 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
474 		obj_mgr_err("Callback for comp %d is already registered", id);
475 		QDF_ASSERT(0);
476 		return QDF_STATUS_E_FAILURE;
477 	}
478 	/* Store handler and args in Global object table */
479 	g_umac_glb_obj->vdev_destroy_handler[id] = handler;
480 	g_umac_glb_obj->vdev_destroy_handler_arg[id] = arg;
481 
482 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
483 	return QDF_STATUS_SUCCESS;
484 }
485 
486 QDF_STATUS wlan_objmgr_unregister_vdev_destroy_handler(
487 		enum wlan_umac_comp_id id,
488 		wlan_objmgr_vdev_destroy_handler handler,
489 		void *arg)
490 {
491 	/* If id is not within valid range, return */
492 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
493 		obj_mgr_err("Component %d is out of range", id);
494 		return QDF_STATUS_MAXCOMP_FAIL;
495 	}
496 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
497 	/* If there is an invalid entry, return failure */
498 	if (g_umac_glb_obj->vdev_destroy_handler[id] != handler) {
499 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
500 		obj_mgr_err("Callback for comp %d is not registered", id);
501 		QDF_ASSERT(0);
502 		return QDF_STATUS_E_FAILURE;
503 	}
504 	/* Reset handlers, and args to NULL */
505 	g_umac_glb_obj->vdev_destroy_handler[id] = NULL;
506 	g_umac_glb_obj->vdev_destroy_handler_arg[id] = NULL;
507 
508 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
509 	return QDF_STATUS_SUCCESS;
510 }
511 
512 QDF_STATUS wlan_objmgr_register_vdev_status_handler(
513 		enum wlan_umac_comp_id id,
514 		wlan_objmgr_vdev_status_handler handler,
515 		void *arg)
516 {
517 	/* If id is not within valid range, return */
518 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
519 		obj_mgr_err("Component %d is out of range", id);
520 		return QDF_STATUS_MAXCOMP_FAIL;
521 	}
522 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
523 	/* If there is a valid entry, return failure */
524 	if (g_umac_glb_obj->vdev_status_handler[id] != NULL) {
525 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
526 		obj_mgr_err("Callback for comp %d is already registered", id);
527 		return QDF_STATUS_E_FAILURE;
528 	}
529 	/* Store handler and args in Global object table */
530 	g_umac_glb_obj->vdev_status_handler[id] = handler;
531 	g_umac_glb_obj->vdev_status_handler_arg[id] = arg;
532 
533 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
534 	return QDF_STATUS_SUCCESS;
535 }
536 
537 QDF_STATUS wlan_objmgr_unregister_vdev_status_handler(
538 		enum wlan_umac_comp_id id,
539 		wlan_objmgr_vdev_status_handler handler,
540 		void *arg)
541 {
542 	/* If id is not within valid range, return */
543 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
544 		obj_mgr_err("Component %d is out of range", id);
545 		return QDF_STATUS_MAXCOMP_FAIL;
546 	}
547 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
548 	/* If there is an invalid entry, return failure */
549 	if (g_umac_glb_obj->vdev_status_handler[id] != handler) {
550 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
551 		obj_mgr_err("Callback for Component %d is not registered", id);
552 		return QDF_STATUS_E_FAILURE;
553 	}
554 	/* Reset handlers, and args to NULL */
555 	g_umac_glb_obj->vdev_status_handler[id] = NULL;
556 	g_umac_glb_obj->vdev_status_handler_arg[id] = NULL;
557 
558 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
559 	return QDF_STATUS_SUCCESS;
560 }
561 
562 
563 QDF_STATUS wlan_objmgr_register_peer_create_handler(
564 		enum wlan_umac_comp_id id,
565 		wlan_objmgr_peer_create_handler handler,
566 		void *arg)
567 {
568 	/* If id is not within valid range, return */
569 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
570 		obj_mgr_err("Component %d is out of range", id);
571 		return QDF_STATUS_MAXCOMP_FAIL;
572 	}
573 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
574 	/* If there is a valid entry, return failure */
575 	if (g_umac_glb_obj->peer_create_handler[id] != NULL) {
576 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
577 		obj_mgr_err("Callback for comp %d is already registered", id);
578 		QDF_ASSERT(0);
579 		return QDF_STATUS_E_FAILURE;
580 	}
581 	/* Store handler and args in Global object table */
582 	g_umac_glb_obj->peer_create_handler[id] = handler;
583 	g_umac_glb_obj->peer_create_handler_arg[id] = arg;
584 
585 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
586 	return QDF_STATUS_SUCCESS;
587 }
588 
589 
590 QDF_STATUS wlan_objmgr_unregister_peer_create_handler(
591 		enum wlan_umac_comp_id id,
592 		wlan_objmgr_peer_create_handler handler,
593 		void *arg)
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 		return QDF_STATUS_MAXCOMP_FAIL;
599 	}
600 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
601 	/* If there is an invalid entry, return failure */
602 	if (g_umac_glb_obj->peer_create_handler[id] != handler) {
603 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
604 		obj_mgr_err("Callback for comp %d is not registered", id);
605 		QDF_ASSERT(0);
606 		return QDF_STATUS_E_FAILURE;
607 	}
608 	/* Reset handlers, and args to NULL */
609 	g_umac_glb_obj->peer_create_handler[id] = NULL;
610 	g_umac_glb_obj->peer_create_handler_arg[id] = NULL;
611 
612 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
613 	return QDF_STATUS_SUCCESS;
614 }
615 
616 QDF_STATUS wlan_objmgr_register_peer_destroy_handler(
617 		enum wlan_umac_comp_id id,
618 		wlan_objmgr_peer_destroy_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_destroy_handler[id] != NULL) {
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_destroy_handler[id] = handler;
636 	g_umac_glb_obj->peer_destroy_handler_arg[id] = arg;
637 
638 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
639 	return QDF_STATUS_SUCCESS;
640 }
641 
642 QDF_STATUS wlan_objmgr_unregister_peer_destroy_handler(
643 		enum wlan_umac_comp_id id,
644 		wlan_objmgr_peer_destroy_handler handler,
645 		void *arg)
646 {
647 	/* If id is not within valid range, return */
648 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
649 		obj_mgr_err("Component %d is out of range", id);
650 		return QDF_STATUS_MAXCOMP_FAIL;
651 	}
652 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
653 	/* If there is an invalid entry, return failure */
654 	if (g_umac_glb_obj->peer_destroy_handler[id] != handler) {
655 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
656 		obj_mgr_err("Callback for comp %d is not registered", id);
657 		QDF_ASSERT(0);
658 		return QDF_STATUS_E_FAILURE;
659 	}
660 	/* Reset handlers, and args to NULL */
661 	g_umac_glb_obj->peer_destroy_handler[id] = NULL;
662 	g_umac_glb_obj->peer_destroy_handler_arg[id] = NULL;
663 
664 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
665 	return QDF_STATUS_SUCCESS;
666 }
667 
668 QDF_STATUS wlan_objmgr_register_peer_status_handler(
669 		enum wlan_umac_comp_id id,
670 		wlan_objmgr_peer_status_handler handler,
671 		void *arg)
672 {
673 	/* If id is not within valid range, return */
674 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
675 		obj_mgr_err("Component %d is out of range", id);
676 		return QDF_STATUS_MAXCOMP_FAIL;
677 	}
678 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
679 	/* If there is a valid entry, return failure */
680 	if (g_umac_glb_obj->peer_status_handler[id] != NULL) {
681 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
682 		obj_mgr_err("Callback for comp %d is already registered", id);
683 		return QDF_STATUS_E_FAILURE;
684 	}
685 	/* Store handler and args in Global object table */
686 	g_umac_glb_obj->peer_status_handler[id] = handler;
687 	g_umac_glb_obj->peer_status_handler_arg[id] = arg;
688 
689 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
690 	return QDF_STATUS_SUCCESS;
691 }
692 
693 QDF_STATUS wlan_objmgr_unregister_peer_status_handler(
694 		enum wlan_umac_comp_id id,
695 		wlan_objmgr_peer_status_handler handler,
696 		void *arg)
697 {
698 	/* If id is not within valid range, return */
699 	if (id >= WLAN_UMAC_MAX_COMPONENTS) {
700 		obj_mgr_err("Component %d is out of range", id);
701 		return QDF_STATUS_MAXCOMP_FAIL;
702 	}
703 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
704 	/* If there is an invalid entry, return failure */
705 	if (g_umac_glb_obj->peer_status_handler[id] != handler) {
706 		qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
707 		obj_mgr_err("Callback for comp %d is not registered", id);
708 		return QDF_STATUS_E_FAILURE;
709 	}
710 	/* Reset handlers, and args to NULL */
711 	g_umac_glb_obj->peer_status_handler[id] = NULL;
712 	g_umac_glb_obj->peer_status_handler_arg[id] = NULL;
713 
714 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
715 	return QDF_STATUS_SUCCESS;
716 }
717 
718 
719 QDF_STATUS wlan_objmgr_psoc_object_attach(struct wlan_objmgr_psoc *psoc)
720 {
721 	uint8_t index = 0;
722 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
723 
724 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
725 	/* Find free slot in PSOC table, store the PSOC */
726 	while (index < WLAN_OBJMGR_MAX_DEVICES) {
727 		if (g_umac_glb_obj->psoc[index] == NULL) {
728 			/* Found free slot, store psoc */
729 			g_umac_glb_obj->psoc[index] = psoc;
730 			status = QDF_STATUS_SUCCESS;
731 			break;
732 		}
733 		index++;
734 	}
735 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
736 	return status;
737 }
738 
739 QDF_STATUS wlan_objmgr_psoc_object_detach(struct wlan_objmgr_psoc *psoc)
740 {
741 	uint8_t index = 0;
742 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
743 
744 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
745 	while (index < WLAN_OBJMGR_MAX_DEVICES) {
746 		if (g_umac_glb_obj->psoc[index] == psoc) {
747 			/* found psoc, store NULL */
748 			g_umac_glb_obj->psoc[index] = NULL;
749 			status = QDF_STATUS_SUCCESS;
750 			break;
751 		}
752 		index++;
753 	}
754 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
755 	return status;
756 }
757 
758 QDF_STATUS wlan_objmgr_global_obj_can_destroyed(void)
759 {
760 	uint8_t index = 0;
761 	QDF_STATUS status = QDF_STATUS_SUCCESS;
762 
763 	qdf_spin_lock_bh(&g_umac_glb_obj->global_lock);
764 	/* Check whether all PSOCs are freed */
765 	while (index < WLAN_OBJMGR_MAX_DEVICES) {
766 		if (g_umac_glb_obj->psoc[index] != NULL) {
767 			status = QDF_STATUS_E_FAILURE;
768 			break;
769 		}
770 		index++;
771 	}
772 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
773 
774 	return status;
775 }
776 EXPORT_SYMBOL(wlan_objmgr_global_obj_can_destroyed);
777 
778 void wlan_objmgr_print_ref_ids(qdf_atomic_t *id)
779 {
780 	uint32_t i;
781 	uint32_t pending_ref;
782 
783 	obj_mgr_info("Pending references of object");
784 	for (i = 0; i < WLAN_REF_ID_MAX; i++) {
785 		pending_ref = qdf_atomic_read(&id[i]);
786 		if (pending_ref)
787 			obj_mgr_info("%s -- %d",
788 				string_from_dbgid(i), pending_ref);
789 	}
790 
791 	return;
792 }
793