1 /*
2  * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: wlan_serialization_main.c
22  * This file defines the important functions pertinent to
23  * serialization to initialize and de-initialize the
24  * component.
25  */
26 #include <qdf_status.h>
27 #include <qdf_list.h>
28 #include <wlan_objmgr_cmn.h>
29 #include <wlan_objmgr_global_obj.h>
30 #include <wlan_objmgr_psoc_obj.h>
31 #include "wlan_serialization_main_i.h"
32 #include "wlan_serialization_rules_i.h"
33 #include "wlan_serialization_utils_i.h"
34 
wlan_serialization_psoc_disable(struct wlan_objmgr_psoc * psoc)35 QDF_STATUS wlan_serialization_psoc_disable(struct wlan_objmgr_psoc *psoc)
36 {
37 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
38 	struct wlan_ser_psoc_obj *ser_soc_obj =
39 		wlan_serialization_get_psoc_obj(psoc);
40 
41 	if (!ser_soc_obj) {
42 		ser_err("invalid ser_soc_obj");
43 		goto error;
44 	}
45 
46 	/*
47 	 * purge all serialization command if there are any pending to make
48 	 * sure memory and vdev ref are freed.
49 	 */
50 	wlan_serialization_purge_all_cmd(psoc);
51 	/* clean up all timers before exiting */
52 	status = wlan_serialization_cleanup_all_timers(ser_soc_obj);
53 	if (status != QDF_STATUS_SUCCESS)
54 		ser_err("ser cleaning up all timer failed");
55 
56 	/* Use lock to free to avoid any race where timer is still in use */
57 	wlan_serialization_acquire_lock(&ser_soc_obj->timer_lock);
58 	qdf_mem_free(ser_soc_obj->timers);
59 	ser_soc_obj->timers = NULL;
60 	ser_soc_obj->max_active_cmds = 0;
61 	wlan_serialization_release_lock(&ser_soc_obj->timer_lock);
62 error:
63 	return status;
64 }
65 
wlan_serialization_psoc_enable(struct wlan_objmgr_psoc * psoc)66 QDF_STATUS wlan_serialization_psoc_enable(struct wlan_objmgr_psoc *psoc)
67 {
68 	uint8_t pdev_count;
69 	struct wlan_ser_psoc_obj *ser_soc_obj =
70 		wlan_serialization_get_psoc_obj(psoc);
71 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
72 
73 	if (!ser_soc_obj) {
74 		ser_err("invalid ser_soc_obj");
75 		goto error;
76 	}
77 
78 	pdev_count = wlan_psoc_get_pdev_count(psoc);
79 	ser_soc_obj->max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS +
80 					(pdev_count * WLAN_SER_MAX_VDEVS);
81 
82 	ser_debug("max_active_cmds %d", ser_soc_obj->max_active_cmds);
83 
84 	ser_soc_obj->timers =
85 		qdf_mem_malloc(sizeof(struct wlan_serialization_timer) *
86 				ser_soc_obj->max_active_cmds);
87 	if (!ser_soc_obj->timers) {
88 		status = QDF_STATUS_E_NOMEM;
89 		goto error;
90 	}
91 
92 	status = QDF_STATUS_SUCCESS;
93 
94 error:
95 	return status;
96 }
97 
98 /**
99  * wlan_serialization_psoc_create_handler() - PSOC obj create callback
100  * @psoc: PSOC object
101  * @arg_list: Variable argument list
102  *
103  * This callback is registered with object manager during initialization and
104  * when obj manager gets its turn to create the object, it would notify each
105  * component with the corresponding callback registered to inform the
106  * completion of the creation of the respective object.
107  *
108  * Return: QDF Status
109  */
wlan_serialization_psoc_create_handler(struct wlan_objmgr_psoc * psoc,void * arg_list)110 static QDF_STATUS wlan_serialization_psoc_create_handler(
111 		struct wlan_objmgr_psoc *psoc, void *arg_list)
112 {
113 	struct wlan_ser_psoc_obj *soc_ser_obj;
114 	QDF_STATUS status = QDF_STATUS_E_NOMEM;
115 
116 	soc_ser_obj =
117 		qdf_mem_malloc(sizeof(*soc_ser_obj));
118 	if (!soc_ser_obj)
119 		goto error;
120 
121 	status = wlan_objmgr_psoc_component_obj_attach(
122 					psoc,
123 					WLAN_UMAC_COMP_SERIALIZATION,
124 					soc_ser_obj,
125 					QDF_STATUS_SUCCESS);
126 	if (QDF_IS_STATUS_ERROR(status)) {
127 		qdf_mem_free(soc_ser_obj);
128 		ser_err("Obj attach failed");
129 		goto error;
130 	}
131 	wlan_serialization_create_lock(&soc_ser_obj->timer_lock);
132 	ser_debug("ser psoc obj created");
133 	status = QDF_STATUS_SUCCESS;
134 
135 error:
136 	return status;
137 }
138 
139 /**
140  * wlan_serialization_destroy_cmd_pool() - Destroy the global cmd pool
141  * @pdev_queue: Serialization pdev queue
142  *
143  * Return: None
144  */
wlan_serialization_destroy_cmd_pool(struct wlan_serialization_pdev_queue * pdev_queue)145 static void wlan_serialization_destroy_cmd_pool(
146 		struct wlan_serialization_pdev_queue *pdev_queue)
147 {
148 	qdf_list_node_t *node = NULL;
149 
150 	ser_debug("Destroy cmd pool list %pK, size %d",
151 		  &pdev_queue->cmd_pool_list,
152 		  qdf_list_size(&pdev_queue->cmd_pool_list));
153 	while (!qdf_list_empty(&pdev_queue->cmd_pool_list)) {
154 		qdf_list_remove_front(&pdev_queue->cmd_pool_list,
155 				      &node);
156 		qdf_mem_free(node);
157 	}
158 
159 	qdf_list_destroy(&pdev_queue->cmd_pool_list);
160 
161 }
162 
163 /**
164  * wlan_serialization_create_cmd_pool() - Create the global cmd pool
165  * @pdev_queue: Serialization pdev queue
166  * @cmd_pool_size: Size of the command pool
167  *
168  * Global command pool of memory is created here.
169  * It is safe to allocate memory individually for each command rather than
170  * requesting for a huge chunk of memory at once.
171  *
172  * The individual command nodes allocated above will keep moving between
173  * the active, pending and global pool lists dynamically, but all the
174  * memory will be freed during driver unload only.
175  *
176  * Return: QDF Status
177  */
178 static QDF_STATUS
wlan_serialization_create_cmd_pool(struct wlan_serialization_pdev_queue * pdev_queue,uint16_t cmd_pool_size)179 wlan_serialization_create_cmd_pool(
180 		struct wlan_serialization_pdev_queue *pdev_queue,
181 		uint16_t cmd_pool_size)
182 {
183 	struct wlan_serialization_command_list *cmd_list_ptr;
184 	uint16_t i;
185 	QDF_STATUS status = QDF_STATUS_E_NOMEM;
186 
187 	qdf_list_create(&pdev_queue->cmd_pool_list, cmd_pool_size);
188 
189 	for (i = 0; i < cmd_pool_size; i++) {
190 		cmd_list_ptr = qdf_mem_malloc(sizeof(*cmd_list_ptr));
191 		if (!cmd_list_ptr) {
192 			wlan_serialization_destroy_cmd_pool(pdev_queue);
193 			goto error;
194 		}
195 
196 		qdf_mem_zero(cmd_list_ptr, sizeof(*cmd_list_ptr));
197 		qdf_list_insert_back(
198 				     &pdev_queue->cmd_pool_list,
199 				     &cmd_list_ptr->pdev_node);
200 		cmd_list_ptr->cmd_in_use = 0;
201 	}
202 
203 	ser_debug("Create cmd pool list %pK, size %d",
204 		  &pdev_queue->cmd_pool_list,
205 		  qdf_list_size(&pdev_queue->cmd_pool_list));
206 
207 	status = QDF_STATUS_SUCCESS;
208 
209 error:
210 	return status;
211 }
212 
213 /**
214  * wlan_serialization_pdev_create_handler() - PDEV obj create callback
215  * @pdev: PDEV object
216  * @arg_list: Variable argument list
217  *
218  * This callback is registered with object manager during initialization and
219  * when obj manager gets its turn to create the object, it would notify each
220  * component with the corresponding callback registered to inform the
221  * completion of the creation of the respective object.
222  *
223  * Return: QDF Status
224  */
wlan_serialization_pdev_create_handler(struct wlan_objmgr_pdev * pdev,void * arg_list)225 static QDF_STATUS wlan_serialization_pdev_create_handler(
226 		struct wlan_objmgr_pdev *pdev, void *arg_list)
227 {
228 	struct wlan_ser_pdev_obj *ser_pdev_obj;
229 	struct wlan_serialization_pdev_queue *pdev_queue;
230 	QDF_STATUS status = QDF_STATUS_E_NOMEM;
231 	uint8_t index;
232 	uint8_t free_index;
233 	uint16_t max_active_cmds;
234 	uint16_t max_pending_cmds;
235 	uint16_t cmd_pool_size;
236 
237 	ser_pdev_obj =
238 		qdf_mem_malloc(sizeof(*ser_pdev_obj));
239 	if (!ser_pdev_obj)
240 		goto error;
241 
242 	for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) {
243 		pdev_queue = &ser_pdev_obj->pdev_q[index];
244 
245 		wlan_serialization_create_lock(&pdev_queue->pdev_queue_lock);
246 
247 		switch (index) {
248 		case SER_PDEV_QUEUE_COMP_SCAN:
249 			max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS;
250 			max_pending_cmds = WLAN_SER_MAX_PENDING_SCAN_CMDS;
251 			cmd_pool_size = max_active_cmds + max_pending_cmds;
252 			break;
253 
254 		case SER_PDEV_QUEUE_COMP_NON_SCAN:
255 			max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS;
256 			max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS;
257 			cmd_pool_size = max_active_cmds + max_pending_cmds;
258 			ser_debug("max_active_cmds %d max_pending_cmds %d",
259 				  max_active_cmds, max_pending_cmds);
260 			break;
261 		}
262 		qdf_list_create(&pdev_queue->active_list,
263 				max_active_cmds);
264 		qdf_list_create(&pdev_queue->pending_list,
265 				max_pending_cmds);
266 
267 		status = wlan_serialization_create_cmd_pool(pdev_queue,
268 							    cmd_pool_size);
269 		if (status != QDF_STATUS_SUCCESS) {
270 			ser_err("Create cmd pool failed, status %d", status);
271 			goto error_free;
272 		}
273 
274 		qdf_mem_zero(pdev_queue->vdev_active_cmd_bitmap,
275 			     sizeof(pdev_queue->vdev_active_cmd_bitmap));
276 
277 		pdev_queue->blocking_cmd_active = 0;
278 		pdev_queue->blocking_cmd_waiting = 0;
279 	}
280 
281 	status = wlan_objmgr_pdev_component_obj_attach(
282 			pdev, WLAN_UMAC_COMP_SERIALIZATION,
283 			ser_pdev_obj, QDF_STATUS_SUCCESS);
284 
285 	if (status != QDF_STATUS_SUCCESS) {
286 		ser_err("Pdev obj attach failed, status %d", status);
287 		goto error_free;
288 	}
289 
290 	return QDF_STATUS_SUCCESS;
291 
292 error_free:
293 	for (free_index = 0; free_index <= index; free_index++) {
294 		pdev_queue = &ser_pdev_obj->pdev_q[free_index];
295 
296 		wlan_serialization_destroy_cmd_pool(pdev_queue);
297 		qdf_list_destroy(&pdev_queue->pending_list);
298 		qdf_list_destroy(&pdev_queue->active_list);
299 		wlan_serialization_destroy_lock(&pdev_queue->pdev_queue_lock);
300 	}
301 error:
302 	return status;
303 }
304 
305 /**
306  * wlan_serialization_psoc_destroy_handler() - PSOC obj delete callback
307  * @psoc: PSOC object
308  * @arg_list: Variable argument list
309  *
310  * This callback is registered with object manager during initialization and
311  * when obj manager gets its turn to delete the object, it would notify each
312  * component with the corresponding callback registered to inform the
313  * completion of the deletion of the respective object.
314  *
315  * Return: QDF Status
316  */
317 static QDF_STATUS
wlan_serialization_psoc_destroy_handler(struct wlan_objmgr_psoc * psoc,void * arg_list)318 wlan_serialization_psoc_destroy_handler(struct wlan_objmgr_psoc *psoc,
319 					void *arg_list)
320 {
321 	QDF_STATUS status = QDF_STATUS_E_FAULT;
322 	struct wlan_ser_psoc_obj *ser_soc_obj =
323 		wlan_serialization_get_psoc_obj(psoc);
324 
325 	if (!ser_soc_obj) {
326 		ser_err("invalid ser_soc_obj");
327 		goto error;
328 	}
329 	status = wlan_objmgr_psoc_component_obj_detach(
330 			psoc, WLAN_UMAC_COMP_SERIALIZATION, ser_soc_obj);
331 	if (status != QDF_STATUS_SUCCESS)
332 		ser_err("ser psoc private obj detach failed");
333 
334 	wlan_serialization_destroy_lock(&ser_soc_obj->timer_lock);
335 	ser_debug("ser psoc obj deleted with status %d", status);
336 	qdf_mem_free(ser_soc_obj);
337 
338 error:
339 	return status;
340 }
341 
342 /**
343  * wlan_serialization_pdev_destroy_handler() - PDEV obj delete callback
344  * @pdev: PDEV object
345  * @arg_list: Variable argument list
346  *
347  * This callback is registered with object manager during initialization and
348  * when obj manager gets its turn to delete the object, it would notify each
349  * component with the corresponding callback registered to inform the
350  * completion of the deletion of the respective object.
351  *
352  * Return: QDF Status
353  */
wlan_serialization_pdev_destroy_handler(struct wlan_objmgr_pdev * pdev,void * arg_list)354 static QDF_STATUS wlan_serialization_pdev_destroy_handler(
355 		struct wlan_objmgr_pdev *pdev, void *arg_list)
356 {
357 	QDF_STATUS status;
358 	struct wlan_serialization_pdev_queue *pdev_queue;
359 	struct wlan_ser_pdev_obj *ser_pdev_obj =
360 		wlan_serialization_get_pdev_obj(pdev);
361 	uint8_t index;
362 
363 	if (!ser_pdev_obj) {
364 		ser_err("ser_pdev_obj NULL");
365 		return QDF_STATUS_E_INVAL;
366 	}
367 	status = wlan_objmgr_pdev_component_obj_detach(
368 			pdev, WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj);
369 
370 	for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) {
371 		pdev_queue = &ser_pdev_obj->pdev_q[index];
372 
373 		wlan_serialization_destroy_pdev_list(pdev_queue);
374 		wlan_serialization_destroy_cmd_pool(pdev_queue);
375 
376 		wlan_serialization_destroy_lock(&pdev_queue->pdev_queue_lock);
377 	}
378 	qdf_mem_free(ser_pdev_obj);
379 
380 	return status;
381 }
382 
383 /**
384  * wlan_serialization_vdev_create_handler() - VDEV obj create callback
385  * @vdev: VDEV object
386  * @arg_list: Variable argument list
387  *
388  * This callback is registered with object manager during initialization and
389  * when obj manager gets its turn to create the object, it would notify each
390  * component with the corresponding callback registered to inform the
391  * completion of the creation of the respective object.
392  *
393  * Return: QDF Status
394  */
395 static QDF_STATUS
wlan_serialization_vdev_create_handler(struct wlan_objmgr_vdev * vdev,void * arg_list)396 wlan_serialization_vdev_create_handler(struct wlan_objmgr_vdev *vdev,
397 				       void *arg_list)
398 {
399 	struct wlan_ser_vdev_obj *ser_vdev_obj;
400 	struct wlan_serialization_vdev_queue *vdev_q;
401 	QDF_STATUS status = QDF_STATUS_E_NOMEM;
402 	uint8_t index;
403 	uint8_t max_active_cmds;
404 	uint8_t max_pending_cmds;
405 
406 	ser_vdev_obj = qdf_mem_malloc(sizeof(*ser_vdev_obj));
407 	if (!ser_vdev_obj)
408 		goto error;
409 
410 	for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) {
411 		vdev_q = &ser_vdev_obj->vdev_q[index];
412 
413 		switch (index) {
414 		case SER_VDEV_QUEUE_COMP_NON_SCAN:
415 			max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS /
416 				WLAN_SER_MAX_VDEVS;
417 			if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE ||
418 			    wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_GO_MODE)
419 				max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS_AP;
420 			else
421 				max_pending_cmds =
422 						WLAN_SER_MAX_PENDING_CMDS_STA;
423 
424 			ser_debug("Vdev type %d max_pending_cmds %d",
425 				  wlan_vdev_mlme_get_opmode(vdev),
426 				  max_pending_cmds);
427 			break;
428 		}
429 
430 		qdf_list_create(&vdev_q->active_list,
431 				max_active_cmds);
432 		qdf_list_create(&vdev_q->pending_list,
433 				max_pending_cmds);
434 	}
435 
436 	status = wlan_objmgr_vdev_component_obj_attach(
437 			vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj,
438 			QDF_STATUS_SUCCESS);
439 
440 	if (status != QDF_STATUS_SUCCESS) {
441 		for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) {
442 			vdev_q = &ser_vdev_obj->vdev_q[index];
443 			qdf_list_destroy(&vdev_q->pending_list);
444 			qdf_list_destroy(&vdev_q->active_list);
445 		}
446 		qdf_mem_free(ser_vdev_obj);
447 		ser_err("serialization vdev obj attach failed");
448 	}
449 error:
450 	return status;
451 }
452 
453 /**
454  * wlan_serialization_vdev_destroy_handler() - vdev obj delete callback
455  * @vdev: VDEV object
456  * @arg_list: Variable argument list
457  *
458  * This callback is registered with object manager during initialization and
459  * when obj manager gets its turn to delete the object, it would notify each
460  * component with the corresponding callback registered to inform the
461  * completion of the deletion of the respective object.
462  *
463  * Return: QDF Status
464  */
wlan_serialization_vdev_destroy_handler(struct wlan_objmgr_vdev * vdev,void * arg_list)465 static QDF_STATUS wlan_serialization_vdev_destroy_handler(
466 		struct wlan_objmgr_vdev *vdev, void *arg_list)
467 {
468 	QDF_STATUS status = QDF_STATUS_SUCCESS;
469 	struct wlan_serialization_vdev_queue *vdev_q;
470 	struct wlan_ser_vdev_obj *ser_vdev_obj =
471 		wlan_serialization_get_vdev_obj(vdev);
472 	uint8_t index;
473 
474 	if (!ser_vdev_obj) {
475 		ser_err("ser_vdev_obj NULL");
476 		return QDF_STATUS_E_INVAL;
477 	}
478 
479 	status = wlan_objmgr_vdev_component_obj_detach(
480 			vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj);
481 
482 	/*Clean up serialization timers if any for this vdev*/
483 	wlan_serialization_cleanup_vdev_timers(vdev);
484 
485 	for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) {
486 		vdev_q = &ser_vdev_obj->vdev_q[index];
487 		wlan_serialization_destroy_vdev_list(&vdev_q->pending_list);
488 		wlan_serialization_destroy_vdev_list(&vdev_q->active_list);
489 	}
490 
491 	qdf_mem_free(ser_vdev_obj);
492 
493 	return status;
494 }
495 
wlan_serialization_init(void)496 QDF_STATUS wlan_serialization_init(void)
497 {
498 	QDF_STATUS status = QDF_STATUS_SUCCESS;
499 
500 	status = wlan_objmgr_register_psoc_create_handler(
501 			WLAN_UMAC_COMP_SERIALIZATION,
502 			wlan_serialization_psoc_create_handler, NULL);
503 	if (status != QDF_STATUS_SUCCESS) {
504 		ser_err("Failed to reg soc ser obj create handler");
505 		goto err_psoc_create;
506 	}
507 
508 	status = wlan_objmgr_register_psoc_destroy_handler(
509 			WLAN_UMAC_COMP_SERIALIZATION,
510 			wlan_serialization_psoc_destroy_handler, NULL);
511 	if (status != QDF_STATUS_SUCCESS) {
512 		ser_err("Failed to reg soc ser obj delete handler");
513 		goto err_psoc_delete;
514 	}
515 
516 	status = wlan_objmgr_register_pdev_create_handler(
517 			WLAN_UMAC_COMP_SERIALIZATION,
518 			wlan_serialization_pdev_create_handler, NULL);
519 	if (status != QDF_STATUS_SUCCESS) {
520 		ser_err("Failed to reg pdev ser obj create handler");
521 		goto err_pdev_create;
522 	}
523 
524 	status = wlan_objmgr_register_pdev_destroy_handler(
525 			WLAN_UMAC_COMP_SERIALIZATION,
526 			wlan_serialization_pdev_destroy_handler, NULL);
527 	if (status != QDF_STATUS_SUCCESS) {
528 		ser_err("Failed to reg pdev ser obj delete handler");
529 		goto err_pdev_delete;
530 	}
531 
532 	status = wlan_objmgr_register_vdev_create_handler(
533 			WLAN_UMAC_COMP_SERIALIZATION,
534 			wlan_serialization_vdev_create_handler, NULL);
535 	if (status != QDF_STATUS_SUCCESS) {
536 		ser_err("Failed to reg vdev ser obj create handler");
537 		goto err_vdev_create;
538 	}
539 
540 	status = wlan_objmgr_register_vdev_destroy_handler(
541 			WLAN_UMAC_COMP_SERIALIZATION,
542 			wlan_serialization_vdev_destroy_handler, NULL);
543 	if (status != QDF_STATUS_SUCCESS) {
544 		ser_err("Failed to reg vdev ser obj delete handler");
545 		goto err_vdev_delete;
546 	}
547 
548 	status = QDF_STATUS_SUCCESS;
549 	goto exit;
550 
551 err_vdev_delete:
552 	wlan_objmgr_unregister_vdev_create_handler(
553 			WLAN_UMAC_COMP_SERIALIZATION,
554 			wlan_serialization_vdev_create_handler,
555 			NULL);
556 err_vdev_create:
557 	wlan_objmgr_unregister_pdev_destroy_handler(
558 			WLAN_UMAC_COMP_SERIALIZATION,
559 			wlan_serialization_pdev_destroy_handler,
560 			NULL);
561 err_pdev_delete:
562 	wlan_objmgr_unregister_pdev_create_handler(
563 			WLAN_UMAC_COMP_SERIALIZATION,
564 			wlan_serialization_pdev_create_handler,
565 			NULL);
566 err_pdev_create:
567 	wlan_objmgr_unregister_psoc_destroy_handler(
568 			WLAN_UMAC_COMP_SERIALIZATION,
569 			wlan_serialization_psoc_destroy_handler,
570 			NULL);
571 err_psoc_delete:
572 	wlan_objmgr_unregister_psoc_create_handler(
573 			WLAN_UMAC_COMP_SERIALIZATION,
574 			wlan_serialization_psoc_create_handler,
575 			NULL);
576 err_psoc_create:
577 exit:
578 	return status;
579 }
580 
wlan_serialization_deinit(void)581 QDF_STATUS wlan_serialization_deinit(void)
582 {
583 	QDF_STATUS status;
584 	QDF_STATUS ret_status = QDF_STATUS_SUCCESS;
585 
586 	status = wlan_objmgr_unregister_psoc_create_handler(
587 			WLAN_UMAC_COMP_SERIALIZATION,
588 			wlan_serialization_psoc_create_handler,
589 			NULL);
590 
591 	if (status != QDF_STATUS_SUCCESS) {
592 		ser_err("unreg fail for psoc ser obj create notf:%d", status);
593 		ret_status = QDF_STATUS_E_FAILURE;
594 	}
595 	status = wlan_objmgr_unregister_psoc_destroy_handler(
596 			WLAN_UMAC_COMP_SERIALIZATION,
597 			wlan_serialization_psoc_destroy_handler,
598 			NULL);
599 
600 	if (status != QDF_STATUS_SUCCESS) {
601 		ser_err("unreg fail for psoc ser obj destroy notf:%d", status);
602 		ret_status = QDF_STATUS_E_FAILURE;
603 	}
604 
605 	status = wlan_objmgr_unregister_pdev_create_handler(
606 			WLAN_UMAC_COMP_SERIALIZATION,
607 			wlan_serialization_pdev_create_handler,
608 			NULL);
609 	if (status != QDF_STATUS_SUCCESS) {
610 		ser_err("unreg fail for pdev ser obj create notf:%d", status);
611 		ret_status = QDF_STATUS_E_FAILURE;
612 	}
613 
614 	status = wlan_objmgr_unregister_pdev_destroy_handler(
615 			WLAN_UMAC_COMP_SERIALIZATION,
616 			wlan_serialization_pdev_destroy_handler,
617 			NULL);
618 
619 	if (status != QDF_STATUS_SUCCESS) {
620 		ser_err("unreg fail for pdev ser destroy notf:%d", status);
621 		ret_status = QDF_STATUS_E_FAILURE;
622 	}
623 
624 	ser_debug("deregistered callbacks with obj mgr successfully");
625 
626 	return ret_status;
627 }
628