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